-
Hi, I'm trying to listen mp3 music that symphonia decode. Actually I did it. Since code is a bit longer here is the logic: Decode with symphonia and store into ring buffer, then play with cpal. But problem is audio is playing I think twice as much as speed then normal. How can I make it normal ? 2024-05-02.16-10-06.mp4let file = File::open("music.mp3").unwrap();
//Buffer limit can be detected automatically
let (mut producer, mut receiver) = HeapRb::<f32>::new(BUFFER_LENGTH*100).split();
let media_source_stream = MediaSourceStream::new(Box::new(file), Default::default());
let hint = Hint::new();
let metadata_options = MetadataOptions::default();
let format_options = FormatOptions::default();
let probed = symphonia::default::get_probe()
.format(
&hint,
media_source_stream,
&format_options,
&metadata_options,
)
.unwrap();
let mut format = probed.format;
let track = format
.tracks()
.iter()
.find(|t| t.codec_params.codec != CODEC_TYPE_NULL)
.unwrap();
DecoderOptions::default();
let decoder_options = DecoderOptions::default();
let mut decoder = symphonia::default::get_codecs()
.make(&track.codec_params, &decoder_options)
.unwrap();
let track_id = track.id;
loop {
let packet = match format.next_packet() {
Ok(packet) => packet,
Err(err_val) => {
eprintln!("Error: Packaging Audio File | {}", err_val);
break;
}
};
while !format.metadata().is_latest() {
format.metadata().pop();
}
if packet.track_id() != track_id {
continue;
}
let _ = playing_to_base_sender.send(true);
match decoder.decode(&packet) {
Ok(decoded) => match decoded {
AudioBufferRef::F32(buf) => {
println!("Size = {:#?}", buf.capacity());
for &sample in buf.chan(0) {
match producer.push(sample) {
Ok(_) => {
//println!("{}", sample);
}
Err(_) => {
println!("E");
}
}
}
}
_ => {}
},
Err(_) => {
//eprintln!("Error: Sample Decode | {}", err_val);
println!("End ?");
}
}
}
let host = cpal::default_host();
let output_device = host.default_output_device().unwrap();
let config: cpal::StreamConfig = output_device.default_output_config().unwrap().into();
let output_data_fn = move |data:&mut [f32], _: &cpal::OutputCallbackInfo| {
for sample in data {
let mini_packet = receiver.pop().unwrap();
*sample = mini_packet;
}
};
let output_stream = output_device.build_output_stream(&config, output_data_fn, err_fn, None).unwrap();
output_stream.play().unwrap();
std::thread::sleep(Duration::from_secs(10000000));
output_stream.pause().unwrap();
drop(output_stream);
}
fn err_fn(err: cpal::StreamError) {
eprintln!("Something Happened: {}", err);
} |
Beta Was this translation helpful? Give feedback.
Answered by
Tahinli
May 2, 2024
Replies: 1 comment
-
Okay solved, main problem was I only play one channel. second problem is sample rate difference, I used rubato to make sample rate equal as my output device. I hardcoded some values as you can see, you can change them, it's just concept code. use std::{fs::File, time::Duration};
use cpal::{traits::{DeviceTrait, HostTrait, StreamTrait}, FromSample};
use ringbuf::HeapRb;
use rubato::{Resampler, SincFixedIn, SincInterpolationParameters, SincInterpolationType, WindowFunction};
use symphonia::core::{
audio::{AudioBufferRef, SampleBuffer, Signal},
codecs::{DecoderOptions, CODEC_TYPE_NULL},
formats::FormatOptions,
io::MediaSourceStream,
meta::MetadataOptions,
probe::Hint,
};
use tokio::sync::broadcast::{Receiver, Sender};
use crate::BUFFER_LENGTH;
pub async fn play() {
let file = File::open("music.mp3").unwrap();
let mut counter = 0;
//Buffer limit can be detected automatically
let (mut producer, mut receiver) = HeapRb::<f32>::new(BUFFER_LENGTH*100).split();
let mut audio_decoded_left = vec![];
let mut audio_decoded_right = vec![];
let media_source_stream = MediaSourceStream::new(Box::new(file), Default::default());
let hint = Hint::new();
let metadata_options = MetadataOptions::default();
let format_options = FormatOptions::default();
let probed = symphonia::default::get_probe()
.format(
&hint,
media_source_stream,
&format_options,
&metadata_options,
)
.unwrap();
let mut format = probed.format;
let track = format
.tracks()
.iter()
.find(|t| t.codec_params.codec != CODEC_TYPE_NULL)
.unwrap();
DecoderOptions::default();
let decoder_options = DecoderOptions::default();
let mut decoder = symphonia::default::get_codecs()
.make(&track.codec_params, &decoder_options)
.unwrap();
let track_id = track.id;
loop {
let packet = match format.next_packet() {
Ok(packet) => packet,
Err(err_val) => {
eprintln!("Error: Packaging Audio File | {}", err_val);
break;
}
};
while !format.metadata().is_latest() {
format.metadata().pop();
}
if packet.track_id() != track_id {
continue;
}
match decoder.decode(&packet) {
Ok(decoded) => match decoded {
AudioBufferRef::F32(buf) => {
counter += 1;
println!("Size = {:#?}", buf.capacity());
for (left, right) in buf.chan(0).iter().zip(buf.chan(1).iter()) {
audio_decoded_left.push(*left as f64);
audio_decoded_right.push(*right as f64);
}
}
_ => {}
},
Err(_) => {
//eprintln!("Error: Sample Decode | {}", err_val);
println!("End ?");
}
}
}
let params = SincInterpolationParameters {
sinc_len: 256,
f_cutoff: 0.95,
interpolation: SincInterpolationType::Linear,
oversampling_factor: 256,
window: WindowFunction::BlackmanHarris2,
};
let mut resampler = SincFixedIn::<f64>::new(
44100 as f64 / 48000 as f64,
2.0,
params,
audio_decoded_left.len(),
2,
).unwrap();
let audio_decoded_channes_combined = vec![audio_decoded_left, audio_decoded_right];
let audio_resampled = resampler.process(&audio_decoded_channes_combined, None).unwrap();
let mut audio_resampled_left = vec![];
let mut audio_resampled_right = vec![];
for sample in &audio_resampled[0] {
audio_resampled_left.push(*sample);
}
for sample in &audio_resampled[1] {
audio_resampled_right.push(*sample);
}
audio_resampled_left.reverse();
audio_resampled_right.reverse();
for _ in 0..audio_resampled_left.clone().len() {
producer.push(audio_resampled_left.pop().unwrap() as f32).unwrap();
producer.push(audio_resampled_right.pop().unwrap() as f32).unwrap();
}
let host = cpal::default_host();
let output_device = host.default_output_device().unwrap();
let config: cpal::StreamConfig = output_device.default_output_config().unwrap().into();
println!("{:#?}", config.sample_rate);
let output_data_fn = move |data:&mut [f32], _: &cpal::OutputCallbackInfo| {
for sample in data {
let mini_packet = match receiver.pop() {
Some(single) => {
single
},
None => 0.0,
};
if audio_stream_sender.receiver_count() > 0 {
let _= audio_stream_sender.send(mini_packet);
}
*sample = mini_packet;
}
};
let output_stream = output_device.build_output_stream(&config, output_data_fn, err_fn, None).unwrap();
output_stream.play().unwrap();
std::thread::sleep(Duration::from_secs(10000000));
output_stream.pause().unwrap();
drop(output_stream);
}
fn err_fn(err: cpal::StreamError) {
eprintln!("Something Happened: {}", err);
} |
Beta Was this translation helpful? Give feedback.
0 replies
Answer selected by
Tahinli
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Okay solved, main problem was I only play one channel. second problem is sample rate difference, I used rubato to make sample rate equal as my output device. I hardcoded some values as you can see, you can change them, it's just concept code.