perf: ⚡ Playing audio is instant now.
This commit is contained in:
parent
204b912025
commit
151e51eeef
5 changed files with 43 additions and 36 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -5,7 +5,7 @@ target/
|
|||
.vscode/
|
||||
dist/
|
||||
certificates/
|
||||
audios/
|
||||
audio/
|
||||
|
||||
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
|
||||
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use std::{
|
||||
cmp::max,
|
||||
fs::File,
|
||||
path::Path,
|
||||
process::exit,
|
||||
|
@ -18,13 +17,9 @@ use crate::{
|
|||
gui_components::{button_with_centered_text, text_centered},
|
||||
gui_utils::{self, change_audio_volume, change_microphone_volume},
|
||||
utils::get_config,
|
||||
Config, BUFFER_LENGTH,
|
||||
Config, AUDIO_BUFFER_SIZE, AUDIO_PATH, AUDIO_SCROLLABLE_BUTTON_SIZE, BUFFER_LENGTH,
|
||||
};
|
||||
|
||||
const AUDIOS_PATH: &str = "audios";
|
||||
|
||||
const AUDIO_SCROLLABLE_BUTTON_SIZE: u16 = 35;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Player {
|
||||
Play,
|
||||
|
@ -46,6 +41,7 @@ struct AudioMiscellaneous {
|
|||
playing_file_name: String,
|
||||
files: Option<Vec<String>>,
|
||||
decoded_to_playing_sender: Option<Sender<f32>>,
|
||||
should_decode_now_sender: Option<Sender<bool>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -161,7 +157,8 @@ impl Streamer {
|
|||
selected_file_name: String::new(),
|
||||
playing_file_name: String::new(),
|
||||
files: None,
|
||||
decoded_to_playing_sender: None,
|
||||
decoded_to_playing_sender: Some(channel(AUDIO_BUFFER_SIZE).0),
|
||||
should_decode_now_sender: Some(channel(1).0),
|
||||
},
|
||||
gui_status: GUIStatus {
|
||||
are_we_connect: Condition::Passive,
|
||||
|
@ -206,7 +203,8 @@ impl Streamer {
|
|||
selected_file_name: String::new(),
|
||||
playing_file_name: String::new(),
|
||||
files: None,
|
||||
decoded_to_playing_sender: None,
|
||||
decoded_to_playing_sender: Some(channel(AUDIO_BUFFER_SIZE).0),
|
||||
should_decode_now_sender: Some(channel(1).0),
|
||||
},
|
||||
gui_status: GUIStatus {
|
||||
are_we_connect: Condition::Passive,
|
||||
|
@ -359,7 +357,7 @@ impl Streamer {
|
|||
self.gui_status.are_we_play_audio = Condition::Loading;
|
||||
let path = format!(
|
||||
"{}/{}",
|
||||
AUDIOS_PATH, self.audio_miscellaneous.selected_file_name
|
||||
AUDIO_PATH, self.audio_miscellaneous.selected_file_name
|
||||
);
|
||||
match File::open(path) {
|
||||
Ok(file) => {
|
||||
|
@ -372,21 +370,7 @@ impl Streamer {
|
|||
return Task::none();
|
||||
}
|
||||
}
|
||||
self.audio_miscellaneous.decoded_to_playing_sender = Some(
|
||||
channel(max(
|
||||
self.audio_miscellaneous
|
||||
.file
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.metadata()
|
||||
.unwrap()
|
||||
.len() as usize
|
||||
* 10,
|
||||
1,
|
||||
))
|
||||
.0,
|
||||
);
|
||||
|
||||
self.audio_miscellaneous.should_decode_now_sender = Some(channel(1).0);
|
||||
let audio_stream_sender = self.data_channel.audio_stream_sender.clone();
|
||||
let playing_to_base_sender =
|
||||
self.communication_channel.playing_to_base_sender.clone();
|
||||
|
@ -428,12 +412,17 @@ impl Streamer {
|
|||
.unwrap();
|
||||
|
||||
let audio_volume = self.gui_status.audio_volume.value.clone();
|
||||
|
||||
let should_decode_now_sender = self
|
||||
.audio_miscellaneous
|
||||
.should_decode_now_sender
|
||||
.clone()
|
||||
.unwrap();
|
||||
let playing_command = Task::perform(
|
||||
async move {
|
||||
gui_utils::start_playing(
|
||||
audio_stream_sender,
|
||||
decoded_to_playing_sender_for_playing,
|
||||
should_decode_now_sender,
|
||||
file,
|
||||
playing_to_base_sender,
|
||||
base_to_playing_receiver,
|
||||
|
@ -525,7 +514,7 @@ impl Streamer {
|
|||
)
|
||||
}
|
||||
Event::ChooseAudio(chosen_audio) => {
|
||||
let path = format!("{}/{}", AUDIOS_PATH, chosen_audio);
|
||||
let path = format!("{}/{}", AUDIO_PATH, chosen_audio);
|
||||
match File::open(path) {
|
||||
Ok(file) => {
|
||||
self.audio_miscellaneous.file = Some(file);
|
||||
|
@ -566,21 +555,21 @@ impl Streamer {
|
|||
Event::IcedEvent(iced_event) => match iced_event {
|
||||
iced::Event::Keyboard(_) => Task::perform(
|
||||
async move {
|
||||
let files = gui_utils::list_files(Path::new(AUDIOS_PATH)).await;
|
||||
let files = gui_utils::list_files(Path::new(AUDIO_PATH)).await;
|
||||
Event::ListFiles(files)
|
||||
},
|
||||
Message::Event,
|
||||
),
|
||||
iced::Event::Mouse(_) => Task::perform(
|
||||
async move {
|
||||
let files = gui_utils::list_files(Path::new(AUDIOS_PATH)).await;
|
||||
let files = gui_utils::list_files(Path::new(AUDIO_PATH)).await;
|
||||
Event::ListFiles(files)
|
||||
},
|
||||
Message::Event,
|
||||
),
|
||||
iced::Event::Touch(_) => Task::perform(
|
||||
async move {
|
||||
let files = gui_utils::list_files(Path::new(AUDIOS_PATH)).await;
|
||||
let files = gui_utils::list_files(Path::new(AUDIO_PATH)).await;
|
||||
Event::ListFiles(files)
|
||||
},
|
||||
Message::Event,
|
||||
|
@ -591,7 +580,7 @@ impl Streamer {
|
|||
self.exit();
|
||||
}
|
||||
async move {
|
||||
let files = gui_utils::list_files(Path::new(AUDIOS_PATH)).await;
|
||||
let files = gui_utils::list_files(Path::new(AUDIO_PATH)).await;
|
||||
Event::ListFiles(files)
|
||||
}
|
||||
},
|
||||
|
@ -872,7 +861,7 @@ impl Streamer {
|
|||
pub fn list_files() -> Task<Message> {
|
||||
Task::perform(
|
||||
async move {
|
||||
let files = gui_utils::list_files(Path::new(AUDIOS_PATH)).await;
|
||||
let files = gui_utils::list_files(Path::new(AUDIO_PATH)).await;
|
||||
Event::ListFiles(files)
|
||||
},
|
||||
Message::Event,
|
||||
|
|
|
@ -172,6 +172,7 @@ pub async fn stop_recording(
|
|||
pub async fn start_playing(
|
||||
audio_stream_sender: Sender<f32>,
|
||||
decoded_to_playing_sender: Sender<f32>,
|
||||
should_decode_now_sender: Sender<bool>,
|
||||
file: File,
|
||||
playing_to_base_sender: Sender<Player>,
|
||||
base_to_playing_receiver: Receiver<Player>,
|
||||
|
@ -182,6 +183,7 @@ pub async fn start_playing(
|
|||
audio_stream_sender,
|
||||
file,
|
||||
decoded_to_playing_sender,
|
||||
should_decode_now_sender,
|
||||
playing_to_base_sender,
|
||||
base_to_playing_receiver,
|
||||
audio_volume,
|
||||
|
|
|
@ -7,6 +7,9 @@ pub mod streaming;
|
|||
pub mod utils;
|
||||
|
||||
pub const BUFFER_LENGTH: usize = 1000000;
|
||||
pub const AUDIO_PATH: &str = "audio";
|
||||
pub const AUDIO_BUFFER_SIZE: usize = 1048576;
|
||||
pub const AUDIO_SCROLLABLE_BUTTON_SIZE: u16 = 35;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Config {
|
||||
|
|
|
@ -27,6 +27,7 @@ pub async fn play(
|
|||
audio_stream_sender: Sender<f32>,
|
||||
file: File,
|
||||
decoded_to_playing_sender: Sender<f32>,
|
||||
should_decode_now_sender: Sender<bool>,
|
||||
playing_to_base_sender: Sender<Player>,
|
||||
mut base_to_playing_receiver: Receiver<Player>,
|
||||
audio_volume: Arc<Mutex<f32>>,
|
||||
|
@ -39,16 +40,29 @@ pub async fn play(
|
|||
let output_device_sample_rate = output_device_config.sample_rate.0;
|
||||
|
||||
let mut decoded_to_playing_receiver = decoded_to_playing_sender.subscribe();
|
||||
let should_decode_now_receiver = should_decode_now_sender.subscribe();
|
||||
let audio_process_task = tokio::spawn(process_audio(
|
||||
output_device_sample_rate,
|
||||
file,
|
||||
decoded_to_playing_sender,
|
||||
should_decode_now_receiver,
|
||||
));
|
||||
while decoded_to_playing_receiver.is_empty() {
|
||||
tokio::time::sleep(Duration::from_millis(10)).await;
|
||||
}
|
||||
|
||||
let output_data_fn = move |data: &mut [f32], _: &cpal::OutputCallbackInfo| {
|
||||
for sample in data {
|
||||
if should_decode_now_sender.receiver_count() > 0 {
|
||||
if should_decode_now_sender.len() == 0 {
|
||||
if crate::AUDIO_BUFFER_SIZE / 2 > decoded_to_playing_receiver.len() {
|
||||
if let Err(err_val) = should_decode_now_sender.send(true) {
|
||||
eprintln!("Error: Decode Order | {}", err_val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if decoded_to_playing_receiver.len() > 0 {
|
||||
let single = match decoded_to_playing_receiver.blocking_recv() {
|
||||
Ok(single) => single * *audio_volume.lock().unwrap(),
|
||||
|
@ -165,7 +179,8 @@ fn resample_audio(
|
|||
async fn process_audio(
|
||||
output_device_sample_rate: u32,
|
||||
file: File,
|
||||
decoded_to_playing_sender: tokio::sync::broadcast::Sender<f32>,
|
||||
decoded_to_playing_sender: Sender<f32>,
|
||||
mut should_decode_now_receiver: Receiver<bool>,
|
||||
) {
|
||||
let media_source_stream = MediaSourceStream::new(Box::new(file), Default::default());
|
||||
|
||||
|
@ -220,7 +235,6 @@ async fn process_audio(
|
|||
),
|
||||
None => return,
|
||||
};
|
||||
|
||||
let mut resampler = SincFixedIn::<f64>::new(
|
||||
output_device_sample_rate as f64 / audio_sample_rate as f64,
|
||||
2.0,
|
||||
|
@ -238,7 +252,7 @@ async fn process_audio(
|
|||
let _ = decoded_to_playing_sender.send(*single_right as f32);
|
||||
}
|
||||
|
||||
loop {
|
||||
while let Ok(true) = should_decode_now_receiver.recv().await {
|
||||
let (mut audio_decoded_left, mut audio_decoded_right) = (vec![], vec![]);
|
||||
|
||||
match decode_audio(&mut format, track_id, &mut decoder) {
|
||||
|
@ -253,7 +267,6 @@ async fn process_audio(
|
|||
}
|
||||
None => break,
|
||||
};
|
||||
|
||||
let (audio_resampled_left, audio_resampled_right) =
|
||||
resample_audio(audio_decoded_left, audio_decoded_right, &mut resampler);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue