From f4c9c890ab80a3e6de37ba245244d0e69d9c542c Mon Sep 17 00:00:00 2001 From: Nathan Perry Date: Sun, 17 Feb 2019 21:26:36 -0500 Subject: try using opus --- src/audio/play_queue.rs | 26 +++++++++++++++++++--- src/commands/meme.rs | 57 ++++++++++++++++++++++++++++++++++++++----------- src/main.rs | 3 ++- 3 files changed, 69 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/audio/play_queue.rs b/src/audio/play_queue.rs index 119b8c5..0ddcb93 100644 --- a/src/audio/play_queue.rs +++ b/src/audio/play_queue.rs @@ -7,7 +7,10 @@ use std::{ }; use either::{Left, Right}; -use flate2::bufread::DeflateDecoder; +use opus::{ + Channels, + Decoder as OpusDecoder, +}; use serenity::{ prelude::*, voice, @@ -59,6 +62,7 @@ impl PlayQueue { thread::spawn(move || { let queue_lck = Arc::clone(&queue); let voice_manager = voice_manager; + let mut opus_dec = OpusDecoder::new(48000, Channels::Stereo).unwrap(); loop { thread::sleep(Duration::from_millis(250)); @@ -107,8 +111,24 @@ impl PlayQueue { } } }, - Right(ref vec) => { - voice::pcm(true, DeflateDecoder::new(Cursor::new(vec.clone()))) + Right(ref v) => { + let mut out = Vec::new(); + + let mut acc: usize = 0; + while acc < v.len() { + dbg!(acc); + let mut wr = vec![0i16; 960]; + match opus_dec.decode(&v[acc..], &mut wr, true) { + Ok(len) => acc += len, + + Err(e) => { + info!("decoding opus packet: {}", e); + break; + }, + } + } + + voice::pcm(true, Cursor::new(out)) } }; diff --git a/src/commands/meme.rs b/src/commands/meme.rs index 160a652..e4fbde8 100644 --- a/src/commands/meme.rs +++ b/src/commands/meme.rs @@ -3,13 +3,19 @@ use std::{ sync::RwLock, }; +use byteorder::{ + ByteOrder, + NativeEndian, +}; use diesel::PgConnection; use failure::Error; -use flate2::{ - bufread::DeflateEncoder, - Compression, -}; use lazy_static::lazy_static; +use opus::{ + Application, + Bitrate, + Channels, + Encoder as OpusEncoder, +}; use rand::{Rng, thread_rng}; use serenity::{ builder::CreateMessage, @@ -26,7 +32,6 @@ use crate::{ audio::{ CtxExt, ffmpeg_dl, - Opus, parse_times, Pcm, PlayArgs, @@ -155,10 +160,7 @@ pub fn addaudiomeme(_: &mut Context, msg: &Message, mut args: Args) -> Result<() let (start, end) = parse_times(opts); let youtube_url = ytdl_url(audio_link.as_str())?; - let mut audio_reader = DeflateEncoder::new( - BufReader::new(ffmpeg_dl::(&youtube_url, start, end, None)?), - Compression::best(), - ); + let mut audio_reader = BufReader::new(ffmpeg_dl::(&youtube_url, start, end, None)?); let text = match args.multiple_quoted::() { Ok(text) => text.join(" "), @@ -177,15 +179,44 @@ pub fn addaudiomeme(_: &mut Context, msg: &Message, mut args: Args) -> Result<() }) .ok(); - let mut audio_data = Vec::new(); - let bytes = audio_reader.read_to_end(&mut audio_data)?; + let i16_data: Vec = { + let mut audio_data = Vec::new(); + let bytes = audio_reader.read_to_end(&mut audio_data)?; + + let mut i16_data = Vec::with_capacity(bytes / 2); + i16_data.resize(bytes / 2, 0); + + NativeEndian::read_i16_into(&audio_data, &mut i16_data); + + i16_data + }; + + let mut enc = OpusEncoder::new(48000, Channels::Stereo, Application::Audio)?; + enc.set_vbr(false)?; + enc.set_bitrate(Bitrate::Bits(96 * 1024))?; + + let mut out = Vec::new(); + for elem in i16_data.chunks(960) { + let elem = if elem.len() == 960 { + elem + } else if elem.len() > 480 { + &elem[..480] + } else if elem.len() > 240 { + &elem[..240] + } else { + continue + }; + + let mut encoded = enc.encode_vec(elem, 1200)?; + out.append(&mut encoded); + } - if bytes == 0 { + if out.len() == 0 { debug!("read 0 bytes from audio reader"); return send(msg.channel_id, "🔇🔇🔇🔕🔕🔕🔕🔕🔇🔕🔕🔇🔕🔕📣📢📣📢📣", msg.tts); } - let audio_id = Audio::create(&conn, audio_data, msg.author.id.0)?; + let audio_id = Audio::create(&conn, out, msg.author.id.0)?; NewMeme { title, diff --git a/src/main.rs b/src/main.rs index 5162015..3a5aeac 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ #![feature(impl_trait_in_bindings)] +extern crate byteorder; extern crate chrono; #[cfg(feature = "diesel")] #[macro_use] extern crate diesel; @@ -8,10 +9,10 @@ extern crate dotenv; extern crate either; #[macro_use] extern crate failure; extern crate fern; -extern crate flate2; #[cfg_attr(test, macro_use)] extern crate itertools; #[macro_use] extern crate lazy_static; #[macro_use] extern crate log; +extern crate opus; extern crate rand; extern crate regex; extern crate serde_json; -- cgit v1.3.1