1use core::{error::Error, fmt, num::NonZeroU32};
2
3pub const MAX_CHANNELS: usize = 64;
4
5#[repr(transparent)]
9#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
10#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
11#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
12pub struct ChannelCount(u32);
13
14impl ChannelCount {
15 pub const ZERO: Self = Self(0);
16 pub const MONO: Self = Self(1);
17 pub const STEREO: Self = Self(2);
18 pub const MAX: Self = Self(MAX_CHANNELS as u32);
19
20 #[inline]
24 pub const fn new(count: u32) -> Option<Self> {
25 if count <= 64 { Some(Self(count)) } else { None }
26 }
27
28 #[inline]
29 pub const fn get(&self) -> u32 {
30 assert!(self.0 <= 64);
31
32 self.0
33 }
34}
35
36impl From<usize> for ChannelCount {
37 fn from(value: usize) -> Self {
38 Self::new(value as u32).unwrap()
39 }
40}
41
42impl From<ChannelCount> for u32 {
43 fn from(value: ChannelCount) -> Self {
44 value.get()
45 }
46}
47
48impl From<ChannelCount> for usize {
49 fn from(value: ChannelCount) -> Self {
50 value.get() as usize
51 }
52}
53
54#[repr(transparent)]
58#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
59#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
60#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
61pub struct NonZeroChannelCount(NonZeroU32);
62
63impl NonZeroChannelCount {
64 pub const MONO: Self = Self(NonZeroU32::new(1).unwrap());
65 pub const STEREO: Self = Self(NonZeroU32::new(2).unwrap());
66 pub const MAX: Self = Self(NonZeroU32::new(64).unwrap());
67
68 #[inline]
72 pub const fn new(count: u32) -> Option<Self> {
73 if count > 0 && count <= 64 {
74 Some(Self(NonZeroU32::new(count).unwrap()))
75 } else {
76 None
77 }
78 }
79
80 #[inline]
81 pub const fn get(&self) -> ChannelCount {
82 assert!(self.0.get() > 0 && self.0.get() <= 64);
83
84 ChannelCount(self.0.get())
85 }
86}
87
88impl Default for NonZeroChannelCount {
89 fn default() -> Self {
90 Self::STEREO
91 }
92}
93
94impl From<usize> for NonZeroChannelCount {
95 fn from(value: usize) -> Self {
96 Self::new(value as u32).unwrap()
97 }
98}
99
100impl From<NonZeroChannelCount> for NonZeroU32 {
101 fn from(value: NonZeroChannelCount) -> Self {
102 NonZeroU32::new(value.get().get()).unwrap()
103 }
104}
105
106impl From<NonZeroChannelCount> for usize {
107 fn from(value: NonZeroChannelCount) -> Self {
108 value.get().get() as usize
109 }
110}
111
112#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
114#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
115#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
116pub struct ChannelConfig {
117 pub num_inputs: ChannelCount,
118 pub num_outputs: ChannelCount,
119}
120
121impl ChannelConfig {
122 pub fn new(num_inputs: impl Into<ChannelCount>, num_outputs: impl Into<ChannelCount>) -> Self {
123 Self {
124 num_inputs: num_inputs.into(),
125 num_outputs: num_outputs.into(),
126 }
127 }
128
129 pub fn verify(
130 &self,
131 min_num_inputs: ChannelCount,
132 max_num_inputs: ChannelCount,
133 min_num_outputs: ChannelCount,
134 max_num_outputs: ChannelCount,
135 equal_num_ins_outs: bool,
136 ) -> Result<(), ChannelConfigError> {
137 if self.num_inputs.get() < min_num_inputs.get()
138 || self.num_inputs.get() > max_num_inputs.get()
139 {
140 Err(ChannelConfigError::InvalidNumInputs {
141 min: min_num_inputs,
142 max: max_num_inputs,
143 got: self.num_inputs,
144 })
145 } else if self.num_outputs.get() < min_num_outputs.get()
146 || self.num_outputs.get() > max_num_outputs.get()
147 {
148 Err(ChannelConfigError::InvalidNumOutputs {
149 min: min_num_outputs,
150 max: max_num_outputs,
151 got: self.num_outputs,
152 })
153 } else if equal_num_ins_outs && self.num_inputs.get() != self.num_outputs.get() {
154 Err(ChannelConfigError::NumInOutNotEqual {
155 got_in: self.num_inputs,
156 got_out: self.num_outputs,
157 })
158 } else {
159 Ok(())
160 }
161 }
162
163 pub fn is_empty(&self) -> bool {
164 self.num_inputs == ChannelCount::ZERO && self.num_outputs == ChannelCount::ZERO
165 }
166}
167
168impl From<(usize, usize)> for ChannelConfig {
169 fn from(value: (usize, usize)) -> Self {
170 Self::new(value.0, value.1)
171 }
172}
173
174#[derive(Debug, Clone, Copy, PartialEq, Eq)]
176pub enum ChannelConfigError {
177 InvalidNumInputs {
178 min: ChannelCount,
179 max: ChannelCount,
180 got: ChannelCount,
181 },
182 InvalidNumOutputs {
183 min: ChannelCount,
184 max: ChannelCount,
185 got: ChannelCount,
186 },
187 NumInOutNotEqual {
188 got_in: ChannelCount,
189 got_out: ChannelCount,
190 },
191}
192
193impl Error for ChannelConfigError {}
194
195impl fmt::Display for ChannelConfigError {
196 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
197 match self {
198 Self::InvalidNumInputs { min, max, got } => {
199 write!(
200 f,
201 "Invalid number of input channels on audio node | got: {}, min: {}, max: {}",
202 got.get(),
203 min.get(),
204 max.get()
205 )
206 }
207 Self::InvalidNumOutputs { min, max, got } => {
208 write!(
209 f,
210 "Invalid number of output channels on audio node | got: {}, min: {}, max: {}",
211 got.get(),
212 min.get(),
213 max.get()
214 )
215 }
216 Self::NumInOutNotEqual { got_in, got_out } => {
217 write!(
218 f,
219 "Number of input channels does not equal number of output channels | in: {}, out: {}",
220 got_in.get(),
221 got_out.get()
222 )
223 }
224 }
225 }
226}