Skip to main content

lavende_core/audio/
codec.rs

1pub mod opus_decoder {
2    use crate::audio::constants::MAX_OPUS_FRAME_SIZE;
3    use audiopus::{
4        Channels, MutSignals, SampleRate, coder::Decoder as OpusDecoder, packet::Packet,
5    };
6    use symphonia::core::{
7        audio::{AsAudioBufferRef, AudioBuffer, AudioBufferRef, Layout, Signal, SignalSpec},
8        codecs::{
9            CODEC_TYPE_OPUS, CodecDescriptor, CodecParameters, Decoder, DecoderOptions,
10            FinalizeResult,
11        },
12        errors::{Error, Result},
13        formats::Packet as SymphPacket,
14        units::Duration,
15    };
16    pub struct OpusCodecDecoder {
17        params: CodecParameters,
18        channels: usize,
19        decoder: OpusDecoder,
20        buf: AudioBuffer<i16>,
21        pcm: Vec<i16>,
22    }
23    unsafe impl Sync for OpusCodecDecoder {}
24    #[inline]
25    fn opus_channels(n: usize) -> Channels {
26        if n == 1 {
27            Channels::Mono
28        } else {
29            Channels::Stereo
30        }
31    }
32    #[inline]
33    fn opus_layout(n: usize) -> Layout {
34        if n == 1 { Layout::Mono } else { Layout::Stereo }
35    }
36    impl Decoder for OpusCodecDecoder {
37        fn try_new(params: &CodecParameters, _options: &DecoderOptions) -> Result<Self> {
38            if params.codec != CODEC_TYPE_OPUS {
39                return Err(Error::Unsupported("not an opus stream"));
40            }
41            let sample_rate = params.sample_rate.unwrap_or(48000);
42            let channels = params.channels.map(|c| c.count()).unwrap_or(2).clamp(1, 2);
43            let opus_rate = match sample_rate {
44                8000 => SampleRate::Hz8000,
45                12000 => SampleRate::Hz12000,
46                16000 => SampleRate::Hz16000,
47                24000 => SampleRate::Hz24000,
48                _ => SampleRate::Hz48000,
49            };
50            let decoder = OpusDecoder::new(opus_rate, opus_channels(channels))
51                .map_err(|e| Error::IoError(std::io::Error::other(e)))?;
52            let spec = SignalSpec::new_with_layout(sample_rate, opus_layout(channels));
53            let buf = AudioBuffer::<i16>::new(MAX_OPUS_FRAME_SIZE as Duration, spec);
54            let pcm = vec![0i16; MAX_OPUS_FRAME_SIZE * channels];
55            Ok(Self {
56                params: params.clone(),
57                channels,
58                decoder,
59                buf,
60                pcm,
61            })
62        }
63        fn supported_codecs() -> &'static [CodecDescriptor] {
64            &[CodecDescriptor {
65                codec: CODEC_TYPE_OPUS,
66                short_name: "opus",
67                long_name: "Opus (via audiopus)",
68                inst_func: |params, opts| Ok(Box::new(OpusCodecDecoder::try_new(params, opts)?)),
69            }]
70        }
71        fn reset(&mut self) {
72            match OpusDecoder::new(SampleRate::Hz48000, opus_channels(self.channels)) {
73                Ok(dec) => self.decoder = dec,
74                Err(e) => tracing::warn!("opus decoder reset failed: {e}"),
75            }
76        }
77        fn codec_params(&self) -> &CodecParameters {
78            &self.params
79        }
80        fn decode(&mut self, packet: &SymphPacket) -> Result<AudioBufferRef<'_>> {
81            let n = self
82                .decoder
83                .decode(
84                    Packet::try_from(packet.data.as_ref()).ok(),
85                    MutSignals::try_from(self.pcm.as_mut_slice())
86                        .map_err(|e| Error::IoError(std::io::Error::other(e)))?,
87                    false,
88                )
89                .map_err(|e| Error::IoError(std::io::Error::other(e)))?;
90            self.buf.clear();
91            self.buf.render_reserved(Some(n));
92            let ch = self.channels;
93            if ch == 1 {
94                let plane = self.buf.chan_mut(0);
95                plane.copy_from_slice(&self.pcm[..n]);
96            } else {
97                let left = self.buf.chan_mut(0);
98                for (i, chunk) in self.pcm[..n * 2].chunks_exact(2).enumerate() {
99                    left[i] = chunk[0];
100                }
101                let right = self.buf.chan_mut(1);
102                for (i, chunk) in self.pcm[..n * 2].chunks_exact(2).enumerate() {
103                    right[i] = chunk[1];
104                }
105            }
106            Ok(self.buf.as_audio_buffer_ref())
107        }
108        fn finalize(&mut self) -> FinalizeResult {
109            FinalizeResult::default()
110        }
111        fn last_decoded(&self) -> AudioBufferRef<'_> {
112            self.buf.as_audio_buffer_ref()
113        }
114    }
115}
116pub mod opus_encoder {
117    use audiopus::{Application, Channels, SampleRate, coder::Encoder as OpusEncoder};
118    pub struct OpusCodecEncoder {
119        encoder: OpusEncoder,
120    }
121    impl OpusCodecEncoder {
122        pub fn new(quality: u8) -> Result<Self, audiopus::Error> {
123            let mut encoder =
124                OpusEncoder::new(SampleRate::Hz48000, Channels::Stereo, Application::Audio)?;
125            encoder.set_complexity(quality)?;
126            Ok(Self { encoder })
127        }
128        pub fn encode(&mut self, pcm: &[i16], out: &mut [u8]) -> Result<usize, audiopus::Error> {
129            self.encoder.encode(pcm, out)
130        }
131    }
132}
133pub use opus_decoder::OpusCodecDecoder;
134use symphonia::core::codecs::CodecRegistry;
135pub fn register_codecs(registry: &mut CodecRegistry) {
136    registry.register_all::<OpusCodecDecoder>();
137}