Skip to main content

ace_player/decoder/
audio.rs

1//! Pure-Rust audio decode via symphonia.
2use anyhow::Result;
3use tokio::sync::mpsc::Sender;
4
5pub type AudioFrame = Vec<f32>;
6
7/// Decode audio stream and send frames to channel.
8pub async fn decode_stream(source: String, tx: Sender<AudioFrame>) -> Result<()> {
9    use symphonia::core::audio::SampleBuffer;
10    use symphonia::core::codecs::DecoderOptions;
11    use symphonia::core::formats::FormatOptions;
12    use symphonia::core::io::MediaSourceStream;
13    use symphonia::core::meta::MetadataOptions;
14    use symphonia::core::probe::Hint;
15
16    let path = std::path::Path::new(&source);
17    let file = std::fs::File::open(path)?;
18    let mss = MediaSourceStream::new(Box::new(file), Default::default());
19
20    let hint = Hint::new();
21    let probed = symphonia::default::get_probe().format(
22        &hint,
23        mss,
24        &FormatOptions::default(),
25        &MetadataOptions::default(),
26    )?;
27
28    let mut format = probed.format;
29    let track = format
30        .tracks()
31        .iter()
32        .find(|t| t.codec_params.codec != symphonia::core::codecs::CODEC_TYPE_NULL)
33        .ok_or_else(|| anyhow::anyhow!("No audio track found"))?;
34
35    let mut decoder = symphonia::default::get_codecs()
36        .make(&track.codec_params, &DecoderOptions::default())?;
37
38    let track_id = track.id;
39
40    loop {
41        let packet = match format.next_packet() {
42            Ok(p) => p,
43            Err(_) => break,
44        };
45
46        if packet.track_id() != track_id {
47            continue;
48        }
49
50        let decoded = decoder.decode(&packet)?;
51        let spec = *decoded.spec();
52        let mut buf = SampleBuffer::<f32>::new(decoded.capacity() as u64, spec);
53        buf.copy_interleaved_ref(decoded);
54
55        if tx.send(buf.samples().to_vec()).await.is_err() {
56            break;
57        }
58    }
59
60    Ok(())
61}