diff options
| author | salmonik <raisersoft@proton.me> | 2026-05-18 21:46:26 +0200 |
|---|---|---|
| committer | salmonik <raisersoft@proton.me> | 2026-05-18 21:46:26 +0200 |
| commit | 6cceb3cbfacb6f4416e49321a9b63b4ce7a9f036 (patch) | |
| tree | 9d883ada0e6cfb4fd533635885dfb4459f200128 /src/audio.rs | |
| parent | first public release. (diff) | |
| download | rsplayer-6cceb3cbfacb6f4416e49321a9b63b4ce7a9f036.tar.gz rsplayer-6cceb3cbfacb6f4416e49321a9b63b4ce7a9f036.zip | |
fix for new symphony API and less debug info in release
Diffstat (limited to '')
| -rw-r--r-- | src/audio.rs | 97 |
1 files changed, 53 insertions, 44 deletions
diff --git a/src/audio.rs b/src/audio.rs index 62afd93..62d13ff 100644 --- a/src/audio.rs +++ b/src/audio.rs | |||
| @@ -101,7 +101,7 @@ impl AudioEngine { | |||
| 101 | 101 | ||
| 102 | struct AudioData { | 102 | struct AudioData { |
| 103 | format: Box<dyn symphonia::core::formats::FormatReader>, | 103 | format: Box<dyn symphonia::core::formats::FormatReader>, |
| 104 | decoder: Box<dyn symphonia::core::codecs::Decoder>, | 104 | decoder: Box<dyn symphonia::core::codecs::audio::AudioDecoder>, |
| 105 | sample_rate: u32, | 105 | sample_rate: u32, |
| 106 | channels: u16, | 106 | channels: u16, |
| 107 | sample_buffer: Vec<f32>, | 107 | sample_buffer: Vec<f32>, |
| @@ -165,10 +165,10 @@ fn audio_thread( | |||
| 165 | 165 | ||
| 166 | let device_sample_rate = config.sample_rate(); | 166 | let device_sample_rate = config.sample_rate(); |
| 167 | let channels = config.channels(); | 167 | let channels = config.channels(); |
| 168 | eprintln!( | 168 | crate::debug_eprintln(format_args!( |
| 169 | "Default output: {} Hz, {} channels", | 169 | "Default output: {} Hz, {} channels", |
| 170 | device_sample_rate, channels | 170 | device_sample_rate, channels |
| 171 | ); | 171 | )); |
| 172 | 172 | ||
| 173 | let mut current_stream: Option<cpal::Stream> = None; | 173 | let mut current_stream: Option<cpal::Stream> = None; |
| 174 | let audio_data: Arc<Mutex<Option<AudioData>>> = Arc::new(Mutex::new(None)); | 174 | let audio_data: Arc<Mutex<Option<AudioData>>> = Arc::new(Mutex::new(None)); |
| @@ -186,13 +186,16 @@ fn audio_thread( | |||
| 186 | 186 | ||
| 187 | match open_audio_file(&path) { | 187 | match open_audio_file(&path) { |
| 188 | Ok(mut data) => { | 188 | Ok(mut data) => { |
| 189 | eprintln!("File: {} Hz, {} channels", data.sample_rate, data.channels); | 189 | crate::debug_eprintln(format_args!( |
| 190 | "File: {} Hz, {} channels", | ||
| 191 | data.sample_rate, data.channels | ||
| 192 | )); | ||
| 190 | 193 | ||
| 191 | if data.sample_rate != device_sample_rate { | 194 | if data.sample_rate != device_sample_rate { |
| 192 | eprintln!( | 195 | crate::debug_eprintln(format_args!( |
| 193 | "Resampling from {} Hz to {} Hz", | 196 | "Resampling from {} Hz to {} Hz", |
| 194 | data.sample_rate, device_sample_rate | 197 | data.sample_rate, device_sample_rate |
| 195 | ); | 198 | )); |
| 196 | data.resample_ratio = | 199 | data.resample_ratio = |
| 197 | Some(device_sample_rate as f64 / data.sample_rate as f64); | 200 | Some(device_sample_rate as f64 / data.sample_rate as f64); |
| 198 | } | 201 | } |
| @@ -201,28 +204,23 @@ fn audio_thread( | |||
| 201 | let channels = data.channels as usize; | 204 | let channels = data.channels as usize; |
| 202 | for _ in 0..100 { | 205 | for _ in 0..100 { |
| 203 | match data.format.next_packet() { | 206 | match data.format.next_packet() { |
| 204 | Ok(packet) => match data.decoder.decode(&packet) { | 207 | Ok(Some(packet)) => match data.decoder.decode(&packet) { |
| 205 | Ok(decoded) => { | 208 | Ok(decoded) => { |
| 206 | let spec = *decoded.spec(); | 209 | let num_samples = decoded.samples_interleaved(); |
| 207 | let mut sample_buf = symphonia::core::audio::SampleBuffer::< | 210 | let mut samples = vec![0.0f32; num_samples]; |
| 208 | f32, | 211 | decoded.copy_to_slice_interleaved(&mut samples); |
| 209 | >::new( | ||
| 210 | decoded.capacity() as u64, spec | ||
| 211 | ); | ||
| 212 | sample_buf.copy_interleaved_ref(decoded); | ||
| 213 | let samples = sample_buf.samples(); | ||
| 214 | 212 | ||
| 215 | let resampled = if let Some(ratio) = data.resample_ratio { | 213 | let resampled = if let Some(ratio) = data.resample_ratio { |
| 216 | resample_linear(samples, ratio, channels) | 214 | resample_linear(&samples, ratio, channels) |
| 217 | } else { | 215 | } else { |
| 218 | samples.to_vec() | 216 | samples |
| 219 | }; | 217 | }; |
| 220 | 218 | ||
| 221 | data.sample_buffer.extend(resampled); | 219 | data.sample_buffer.extend(resampled); |
| 222 | } | 220 | } |
| 223 | Err(_) => break, | 221 | Err(_) => break, |
| 224 | }, | 222 | }, |
| 225 | Err(_) => break, | 223 | _ => break, |
| 226 | } | 224 | } |
| 227 | } | 225 | } |
| 228 | data.buffer_pos = 0; | 226 | data.buffer_pos = 0; |
| @@ -274,29 +272,26 @@ fn audio_thread( | |||
| 274 | 272 | ||
| 275 | // Decode more data | 273 | // Decode more data |
| 276 | match state.format.next_packet() { | 274 | match state.format.next_packet() { |
| 277 | Ok(packet) => { | 275 | Ok(Some(packet)) => { |
| 278 | match state.decoder.decode(&packet) { | 276 | match state.decoder.decode(&packet) { |
| 279 | Ok(decoded) => { | 277 | Ok(decoded) => { |
| 280 | let spec = *decoded.spec(); | 278 | let num_samples = |
| 281 | let mut sample_buf = | 279 | decoded.samples_interleaved(); |
| 282 | symphonia::core::audio::SampleBuffer::< | 280 | let mut samples = |
| 283 | f32, | 281 | vec![0.0f32; num_samples]; |
| 284 | >::new( | 282 | decoded.copy_to_slice_interleaved( |
| 285 | decoded.capacity() as u64, spec | 283 | &mut samples, |
| 286 | ); | 284 | ); |
| 287 | sample_buf | ||
| 288 | .copy_interleaved_ref(decoded); | ||
| 289 | let samples = sample_buf.samples(); | ||
| 290 | 285 | ||
| 291 | // Resample if needed | 286 | // Resample if needed |
| 292 | let resampled = if let Some(ratio) = | 287 | let resampled = if let Some(ratio) = |
| 293 | state.resample_ratio | 288 | state.resample_ratio |
| 294 | { | 289 | { |
| 295 | resample_linear( | 290 | resample_linear( |
| 296 | samples, ratio, channels, | 291 | &samples, ratio, channels, |
| 297 | ) | 292 | ) |
| 298 | } else { | 293 | } else { |
| 299 | samples.to_vec() | 294 | samples |
| 300 | }; | 295 | }; |
| 301 | 296 | ||
| 302 | // Copy what we can to output | 297 | // Copy what we can to output |
| @@ -323,7 +318,7 @@ fn audio_thread( | |||
| 323 | Err(_) => break, | 318 | Err(_) => break, |
| 324 | } | 319 | } |
| 325 | } | 320 | } |
| 326 | Err(_) => break, | 321 | _ => break, |
| 327 | } | 322 | } |
| 328 | } | 323 | } |
| 329 | 324 | ||
| @@ -419,36 +414,50 @@ fn audio_thread( | |||
| 419 | } | 414 | } |
| 420 | 415 | ||
| 421 | fn open_audio_file(path: &PathBuf) -> Result<AudioData, Box<dyn std::error::Error>> { | 416 | fn open_audio_file(path: &PathBuf) -> Result<AudioData, Box<dyn std::error::Error>> { |
| 422 | use symphonia::core::audio::Channels; | 417 | use symphonia::core::audio::layouts::CHANNEL_LAYOUT_STEREO; |
| 418 | use symphonia::core::codecs::audio::AudioDecoderOptions; | ||
| 419 | use symphonia::core::formats::probe::Hint; | ||
| 423 | use symphonia::core::io::MediaSourceStream; | 420 | use symphonia::core::io::MediaSourceStream; |
| 424 | 421 | ||
| 425 | let file = std::fs::File::open(path)?; | 422 | let file = std::fs::File::open(path)?; |
| 426 | let mss = MediaSourceStream::new(Box::new(file), Default::default()); | 423 | let mss = MediaSourceStream::new(Box::new(file), Default::default()); |
| 427 | 424 | ||
| 428 | let hint = symphonia::core::probe::Hint::new(); | 425 | let hint = Hint::new(); |
| 429 | let probed = symphonia::default::get_probe().format( | 426 | let format = symphonia::default::get_probe().probe( |
| 430 | &hint, | 427 | &hint, |
| 431 | mss, | 428 | mss, |
| 432 | &Default::default(), | 429 | Default::default(), |
| 433 | &Default::default(), | 430 | Default::default(), |
| 434 | )?; | 431 | )?; |
| 435 | 432 | ||
| 436 | let format = probed.format; | ||
| 437 | let track = format | 433 | let track = format |
| 438 | .tracks() | 434 | .tracks() |
| 439 | .iter() | 435 | .iter() |
| 440 | .find(|t| t.codec_params.sample_rate.is_some()) | 436 | .find(|t| { |
| 437 | t.codec_params | ||
| 438 | .as_ref() | ||
| 439 | .and_then(|p| p.audio()) | ||
| 440 | .and_then(|a| a.sample_rate) | ||
| 441 | .is_some() | ||
| 442 | }) | ||
| 441 | .ok_or("No suitable track found")?; | 443 | .ok_or("No suitable track found")?; |
| 442 | 444 | ||
| 443 | let sample_rate = track.codec_params.sample_rate.unwrap_or(44100); | 445 | let codec_params = track |
| 444 | let channels = track | ||
| 445 | .codec_params | 446 | .codec_params |
| 447 | .as_ref() | ||
| 448 | .ok_or("No codec parameters")? | ||
| 449 | .audio() | ||
| 450 | .ok_or("Not an audio track")?; | ||
| 451 | |||
| 452 | let sample_rate = codec_params.sample_rate.unwrap_or(44100); | ||
| 453 | let channels = codec_params | ||
| 446 | .channels | 454 | .channels |
| 447 | .unwrap_or(Channels::FRONT_LEFT | Channels::FRONT_RIGHT) | 455 | .clone() |
| 456 | .unwrap_or(CHANNEL_LAYOUT_STEREO) | ||
| 448 | .count() as u16; | 457 | .count() as u16; |
| 449 | 458 | ||
| 450 | let decoder = | 459 | let decoder = symphonia::default::get_codecs() |
| 451 | symphonia::default::get_codecs().make(&track.codec_params, &Default::default())?; | 460 | .make_audio_decoder(codec_params, &AudioDecoderOptions::default())?; |
| 452 | 461 | ||
| 453 | Ok(AudioData { | 462 | Ok(AudioData { |
| 454 | format, | 463 | format, |
