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