1use crate::bindings::{
4 OPUS_APPLICATION_AUDIO, OPUS_APPLICATION_RESTRICTED_LOWDELAY, OPUS_APPLICATION_VOIP, OPUS_AUTO,
5 OPUS_BANDWIDTH_FULLBAND, OPUS_BANDWIDTH_MEDIUMBAND, OPUS_BANDWIDTH_NARROWBAND,
6 OPUS_BANDWIDTH_SUPERWIDEBAND, OPUS_BANDWIDTH_WIDEBAND, OPUS_BITRATE_MAX, OPUS_FRAMESIZE_2_5_MS,
7 OPUS_FRAMESIZE_5_MS, OPUS_FRAMESIZE_10_MS, OPUS_FRAMESIZE_20_MS, OPUS_FRAMESIZE_40_MS,
8 OPUS_FRAMESIZE_60_MS, OPUS_FRAMESIZE_80_MS, OPUS_FRAMESIZE_100_MS, OPUS_FRAMESIZE_120_MS,
9 OPUS_FRAMESIZE_ARG, OPUS_SIGNAL_MUSIC, OPUS_SIGNAL_VOICE,
10};
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
14pub enum Application {
15 #[default]
17 Voip = OPUS_APPLICATION_VOIP as isize,
18 Audio = OPUS_APPLICATION_AUDIO as isize,
20 RestrictedLowDelay = OPUS_APPLICATION_RESTRICTED_LOWDELAY as isize,
22}
23
24#[derive(Debug, Clone, Copy, PartialEq, Eq)]
26pub enum Channels {
27 Mono = 1,
29 Stereo = 2,
31}
32
33impl Channels {
34 #[must_use]
36 pub const fn as_usize(self) -> usize {
37 self as usize
38 }
39
40 #[must_use]
42 pub const fn as_i32(self) -> i32 {
43 self as i32
44 }
45}
46
47#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
49pub enum SampleRate {
50 Hz8000 = 8000,
52 Hz12000 = 12000,
54 Hz16000 = 16000,
56 Hz24000 = 24000,
58 #[default]
60 Hz48000 = 48000,
61}
62
63impl SampleRate {
64 #[must_use]
66 pub const fn as_i32(self) -> i32 {
67 self as i32
68 }
69
70 #[must_use]
72 pub const fn is_valid(self) -> bool {
73 matches!(
74 self,
75 Self::Hz8000 | Self::Hz12000 | Self::Hz16000 | Self::Hz24000 | Self::Hz48000
76 )
77 }
78}
79
80#[derive(Debug, Clone, Copy, PartialEq, Eq)]
82pub enum Bandwidth {
83 Narrowband = OPUS_BANDWIDTH_NARROWBAND as isize,
85 Mediumband = OPUS_BANDWIDTH_MEDIUMBAND as isize,
87 Wideband = OPUS_BANDWIDTH_WIDEBAND as isize,
89 SuperWideband = OPUS_BANDWIDTH_SUPERWIDEBAND as isize,
91 Fullband = OPUS_BANDWIDTH_FULLBAND as isize,
93}
94
95#[derive(Debug, Clone, Copy, PartialEq, Eq)]
97pub enum FrameSize {
98 Ms2_5 = 25,
100 Ms5 = 50,
102 Ms10 = 100,
104 Ms20 = 200,
106 Ms40 = 400,
108 Ms60 = 600,
110}
111
112impl FrameSize {
113 #[must_use]
115 pub const fn samples(self, sample_rate: SampleRate) -> usize {
116 (self as usize * (sample_rate as usize)) / 10_000
118 }
119}
120
121#[derive(Debug, Clone, Copy, PartialEq, Eq)]
123pub enum Signal {
124 Auto = OPUS_AUTO as isize,
126 Voice = OPUS_SIGNAL_VOICE as isize,
128 Music = OPUS_SIGNAL_MUSIC as isize,
130}
131
132#[derive(Debug, Clone, Copy, PartialEq, Eq)]
134pub enum ExpertFrameDuration {
135 Auto = OPUS_FRAMESIZE_ARG as isize,
137 Ms2_5 = OPUS_FRAMESIZE_2_5_MS as isize,
139 Ms5 = OPUS_FRAMESIZE_5_MS as isize,
141 Ms10 = OPUS_FRAMESIZE_10_MS as isize,
143 Ms20 = OPUS_FRAMESIZE_20_MS as isize,
145 Ms40 = OPUS_FRAMESIZE_40_MS as isize,
147 Ms60 = OPUS_FRAMESIZE_60_MS as isize,
149 Ms80 = OPUS_FRAMESIZE_80_MS as isize,
151 Ms100 = OPUS_FRAMESIZE_100_MS as isize,
153 Ms120 = OPUS_FRAMESIZE_120_MS as isize,
155}
156
157#[derive(Debug, Clone, Copy, PartialEq, Eq)]
159pub struct Complexity(u32);
160
161impl Complexity {
162 #[must_use]
164 pub const fn try_new(complexity: u32) -> Option<Self> {
165 if complexity <= 10 {
166 Some(Self(complexity))
167 } else {
168 None
169 }
170 }
171
172 #[must_use]
177 pub const fn new(complexity: u32) -> Self {
178 assert!(complexity <= 10, "Complexity must be between 0 and 10");
179 Self(complexity)
180 }
181
182 #[must_use]
184 pub const fn value(self) -> u32 {
185 self.0
186 }
187}
188
189impl Default for Complexity {
190 fn default() -> Self {
191 Self::new(10)
192 }
193}
194
195#[derive(Debug, Clone, Copy, PartialEq, Eq)]
197pub enum Bitrate {
198 Auto,
200 Max,
202 Custom(i32),
204}
205
206impl Bitrate {
207 #[must_use]
209 pub const fn value(self) -> i32 {
210 match self {
211 Self::Auto => OPUS_AUTO,
212 Self::Max => OPUS_BITRATE_MAX,
213 Self::Custom(bps) => bps,
214 }
215 }
216}
217
218#[cfg(test)]
219mod tests {
220 use super::*;
221
222 #[test]
223 fn frame_size_samples_are_correct() {
224 assert_eq!(FrameSize::Ms20.samples(SampleRate::Hz48000), 960);
225 assert_eq!(FrameSize::Ms5.samples(SampleRate::Hz16000), 80);
226 assert_eq!(FrameSize::Ms2_5.samples(SampleRate::Hz8000), 20);
227 }
228
229 #[test]
230 fn complexity_checked_constructor_rejects_out_of_range_values() {
231 assert_eq!(Complexity::try_new(0), Some(Complexity::new(0)));
232 assert_eq!(Complexity::try_new(10), Some(Complexity::new(10)));
233 assert_eq!(Complexity::try_new(11), None);
234 }
235}