denoize 0.16.0

Pure-Rust audio denoiser with classical DSP and optional RNNoise
Documentation
use super::DecodedPcm;
use opus::{Channels, Decoder};
use std::path::Path;

pub fn decode_ogg_opus(path: &Path) -> Result<DecodedPcm, String> {
    let file = std::fs::File::open(path).map_err(|e| format!("Opus open: {e}"))?;
    let mut packets = ogg::PacketReader::new(std::io::BufReader::new(file));
    let head = packets
        .read_packet()
        .map_err(|e| format!("Ogg read: {e}"))?
        .ok_or("missing OpusHead")?;
    if head.data.len() < 19 || &head.data[..8] != b"OpusHead" {
        return Err("Ogg stream is not Opus".into());
    }
    let count = head.data[9] as usize;
    if !(1..=2).contains(&count) {
        return Err("only mono/stereo Opus is supported".into());
    }
    let pre_skip = u16::from_le_bytes([head.data[10], head.data[11]]) as usize;
    let channels = if count == 1 {
        Channels::Mono
    } else {
        Channels::Stereo
    };
    let mut decoder = Decoder::new(48_000, channels).map_err(|e| format!("Opus decoder: {e}"))?;
    let _tags = packets
        .read_packet()
        .map_err(|e| format!("Ogg tags: {e}"))?;
    let mut decoded = Vec::<f32>::new();
    let mut final_granule = 0_u64;
    let mut buffer = vec![0.0f32; 5_760 * count];
    while let Some(packet) = packets
        .read_packet()
        .map_err(|e| format!("Ogg read: {e}"))?
    {
        final_granule = final_granule.max(packet.absgp_page());
        let frames = decoder
            .decode_float(&packet.data, &mut buffer, false)
            .map_err(|e| format!("Opus decode: {e}"))?;
        decoded.extend_from_slice(&buffer[..frames * count]);
    }
    let skip = (pre_skip * count).min(decoded.len());
    let wanted = final_granule.saturating_sub(pre_skip as u64) as usize * count;
    let end = (skip + wanted).min(decoded.len());
    let mut output = vec![Vec::new(); count];
    for (index, sample) in decoded[skip..end].iter().enumerate() {
        output[index % count].push(*sample as f64);
    }
    Ok(DecodedPcm {
        sample_rate: 48_000,
        channels: output,
        channel_mask: crate::channel_layout::ChannelLayout::from_channel_count(count).mask(),
    })
}