perf: Playing audio is instant now.

This commit is contained in:
Ahmet Kaan GÜMÜŞ 2024-08-16 04:43:16 +03:00
parent 204b912025
commit 151e51eeef
5 changed files with 43 additions and 36 deletions

2
.gitignore vendored
View file

@ -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

View file

@ -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,

View file

@ -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,

View file

@ -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 {

View file

@ -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);