simple_decoder 0.1.2

The ULTIMATE lightest audio decoding in Rust: Symphonia + Rubato under the hood.
Documentation
use crate::SimpleDecoderError;
use crate::decoders::AudioDecoder;
use crate::types::{AudioFormat, AudioTrack};
use opus::{Channels, Decoder};
use std::io::Cursor;
use symphonia::core::codecs::CODEC_TYPE_OPUS;
use symphonia::core::errors::Error;
use symphonia::core::formats::FormatOptions;
use symphonia::core::io::MediaSourceStream;
use symphonia::core::meta::MetadataOptions;
use symphonia::core::probe::Hint;

pub struct OGGOpusDecoder;

impl AudioDecoder for OGGOpusDecoder {
    fn new() -> Self {
        Self
    }

    fn decode(&self, data: &[u8]) -> std::result::Result<AudioTrack, SimpleDecoderError> {
        let mss = MediaSourceStream::new(Box::new(Cursor::new(data.to_vec())), Default::default());
        let mut hint = Hint::new();
        hint.with_extension("opus");

        let mut probed = symphonia::default::get_probe()
            .format(
                &hint,
                mss,
                &FormatOptions::default(),
                &MetadataOptions::default(),
            )
            .map_err(SimpleDecoderError::DecoderError)?;

        let track = probed
            .format
            .tracks()
            .iter()
            .find(|t| t.codec_params.codec == CODEC_TYPE_OPUS)
            .ok_or(Error::DecodeError("No track found"))
            .map_err(SimpleDecoderError::DecoderError)?;

        let codec_params = &track.codec_params;
        let sample_rate = codec_params
            .sample_rate
            .ok_or(Error::DecodeError("No sample rate found"))
            .map_err(SimpleDecoderError::DecoderError)? as u64;
        let channels = codec_params
            .channels
            .ok_or(Error::DecodeError("No channels found"))
            .map_err(SimpleDecoderError::DecoderError)?
            .count() as u16;
        let track_id = track.id;

        let decoder_channel = match channels {
            1 => Ok(Channels::Mono),
            2 => Ok(Channels::Stereo),
            _ => Err(Error::DecodeError("Unsupported channels count")),
        }
        .map_err(SimpleDecoderError::DecoderError)?;

        let mut decoder = Decoder::new(sample_rate as u32, decoder_channel).map_err(|_| {
            SimpleDecoderError::ResampleError("Unable to create opus decoder".to_string())
        })?;

        let mut pcm: Vec<f32> = vec![];

        loop {
            let packet = match probed.format.next_packet() {
                Ok(packet) => packet,
                Err(Error::IoError(_)) => break,
                Err(e) => return Err(SimpleDecoderError::DecoderError(e)),
            };

            if packet.track_id() != track_id {
                continue;
            };

            let mut output_buff = vec![0.0f32; 5760 * channels as usize];

            let decoded_samples = decoder
                .decode_float(&packet.data, &mut output_buff, false)
                .map_err(|_| {
                    SimpleDecoderError::ResampleError("Unable to decode data".to_string())
                })?;

            pcm.extend_from_slice(&output_buff[..decoded_samples * channels as usize]);
        }

        Ok(AudioTrack {
            format: AudioFormat::OGGOpus,
            channels,
            sample_rate,
            pcm,
        })
    }
}