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