1use std::collections::HashMap;
2use std::collections::VecDeque;
3use crate::{AudioFormat, ChannelProperties};
4
5#[derive(Debug)]
6pub enum AudioErrorType {
7 InvalidBuffer,
8 InvalidChannel,
9 NoChannels
10}
11
12#[derive(Debug)]
13pub struct AudioError<'a> {
14 pub error_type: AudioErrorType,
15 pub description: &'a str
16}
17
18impl<'a> AudioError<'a> {
19 pub fn new(error_type: AudioErrorType) -> Self {
20 let description = match error_type {
21 AudioErrorType::InvalidBuffer => "An invalid buffer was provided.",
22 AudioErrorType::InvalidChannel => "An invalid channel was provided.",
23 AudioErrorType::NoChannels => "No available channels.",
24 };
25
26 Self {
27 error_type,
28 description
29 }
30 }
31}
32
33struct Buffer {
34 has_data: bool,
35
36 data: Vec<u8>,
37 format: AudioFormat,
38}
39
40struct Channel {
41 buffer: i32,
42 playing: bool,
43 chunk: u64,
44 position: f64,
45 sample_rate: i32,
46 speed: f64,
47
48 properties: ChannelProperties,
49 queued: VecDeque<i32>
50}
51
52pub struct AudioSystem {
53 pub format: AudioFormat,
54
55 buffers: HashMap<i32, Buffer>,
56 channels: Vec<Channel>,
57 current_handle: i32,
58 current_sample: u8,
59
60 callback: Option<fn(u16, i32)>
61}
62
63impl AudioSystem {
64 pub fn new(format: Option<AudioFormat>, channels: u16) -> AudioSystem {
65 let i_fmt = if format.is_none() {
66 AudioFormat {
67 channels: 2,
68 sample_rate: 48000,
69 bits_per_sample: 16
70 }
71 } else { format.unwrap() };
72
73 let mut v_channels = Vec::with_capacity(channels as usize);
74 for _ in 0..channels {
75 v_channels.push(Channel {
76 buffer: -1,
77 playing: false,
78 chunk: 0,
79 position: 0.0,
80 sample_rate: 0,
81 speed: 0.0,
82 properties: ChannelProperties::default(),
83 queued: VecDeque::new()
84 });
85 }
86
87 AudioSystem { format: i_fmt, buffers: HashMap::new(), channels: v_channels, current_handle: 0, current_sample: 0, callback: None }
88 }
89
90 pub fn create_buffer(&mut self) -> i32 {
91 let buffer = Buffer { has_data: false, data: Vec::new(), format: AudioFormat { channels: 0, sample_rate: 0, bits_per_sample: 0 } };
92 self.buffers.insert(self.current_handle, buffer);
93
94 let p_buffer = self.current_handle;
95 self.current_handle += 1;
96
97 p_buffer
98 }
99
100 pub fn delete_buffer(&mut self, buffer: i32) -> Result<(), AudioError> {
101 for channel in self.channels.iter_mut() {
102 if channel.buffer == buffer {
103 channel.playing = false;
104 }
105 }
106
107 self.buffers.remove(&buffer).ok_or(AudioError::new(AudioErrorType::InvalidBuffer))?;
108
109 Ok(())
110 }
111
112 pub fn update_buffer(&mut self, buffer: i32, data: &[u8], format: AudioFormat) -> Result<(), AudioError> {
113
114 let mut i_buffer = self.buffers.get_mut(&buffer).ok_or(AudioError::new(AudioErrorType::InvalidBuffer))?;
115
116 i_buffer.data = data.to_vec();
117 i_buffer.format = format;
118 i_buffer.has_data = true;
119
120 Ok(())
121 }
122
123 pub fn play_buffer(&mut self, buffer: i32, channel: u16, properties: ChannelProperties) -> Result<(), AudioError> {
124 let i_buffer = self.buffers.get(&buffer).ok_or(AudioError::new(AudioErrorType::InvalidBuffer))?;
125 let i_channel = self.channels.get_mut(channel as usize).ok_or(AudioError::new(AudioErrorType::InvalidChannel))?;
126
127 i_channel.queued.clear();
128
129 i_channel.chunk = 0;
130 i_channel.position = 0.0;
131 i_channel.properties = properties;
132 i_channel.sample_rate = i_buffer.format.sample_rate;
133 i_channel.speed = i_buffer.format.sample_rate as f64 / self.format.sample_rate as f64;
134 i_channel.speed *= i_channel.properties.speed;
135 i_channel.buffer = buffer;
136 i_channel.playing = true;
137
138 Ok(())
139 }
140
141 pub fn set_channel_properties(&mut self, channel: u16, properties: ChannelProperties) -> Result<(), AudioError> {
142 let mut channel = &mut self.channels.get_mut(channel as usize).ok_or(AudioError::new(AudioErrorType::InvalidChannel))?;
143 channel.properties = properties;
144 channel.speed = self.buffers.get(&channel.buffer).ok_or(AudioError::new(AudioErrorType::InvalidBuffer))?.format.sample_rate as f64 / self.format.sample_rate as f64;
145 channel.speed *= channel.properties.speed;
146
147 Ok(())
148 }
149
150 pub fn play(&mut self, channel: u16) -> Result<(), AudioError> {
151 let mut channel = &mut self.channels.get_mut(channel as usize).ok_or(AudioError::new(AudioErrorType::InvalidChannel))?;
152 channel.playing = true;
153
154 Ok(())
155 }
156
157 pub fn pause(&mut self, channel: u16) -> Result<(), AudioError> {
158 let mut channel = &mut self.channels.get_mut(channel as usize).ok_or(AudioError::new(AudioErrorType::InvalidChannel))?;
159 channel.playing = false;
160
161 Ok(())
162 }
163
164 pub fn stop(&mut self, channel: u16) -> Result<(), AudioError> {
165 let mut channel = &mut self.channels.get_mut(channel as usize).ok_or(AudioError::new(AudioErrorType::InvalidChannel))?;
166 channel.playing = false;
167 channel.position = 0.0;
168 channel.chunk = 0;
169 channel.queued.clear();
170
171 Ok(())
172 }
173
174 pub fn set_buffer_finished_callback(&mut self, callback: fn(u16, i32)) {
175 self.callback = Some(callback);
176 }
177
178 pub fn queue_buffer(&mut self, buffer: i32, channel: u16) -> Result<(), AudioError> {
179 let channel = &mut self.channels.get_mut(channel as usize).ok_or(AudioError::new(AudioErrorType::InvalidChannel))?;
180 if !self.buffers.contains_key(&buffer) {
181 return Err(AudioError::new(AudioErrorType::InvalidBuffer));
182 }
183 channel.queued.push_back(buffer);
184
185 Ok(())
186 }
187
188 pub fn advance(&mut self) -> i16 {
189 let mut result: i32 = 0;
190
191 let mut current_channel = 0;
192 for channel in self.channels.iter_mut() {
193 if !channel.playing {
194 continue;
195 }
196
197 const CHUNK_SIZE: f64 = 48000.0;
198
199 let mut buffer = &self.buffers[&channel.buffer];
200 let format = &buffer.format;
201 let properties = &channel.properties;
202 let fmt_channels = format.channels;
203 let fmt_bps = format.bits_per_sample;
204 let mut data = &buffer.data;
205
206 let alignment = (fmt_bps / 8) as usize;
207
208 let pos_f64 = channel.position + channel.chunk as f64 * CHUNK_SIZE as f64;
209 let pos = pos_f64 as usize;
210
211 let mut get_pos = pos * alignment * fmt_channels as usize;
212 get_pos += self.current_sample as usize * alignment * (fmt_channels - 1) as usize;
213 get_pos -= get_pos % alignment;
214
215 let next_pos = if channel.speed < 1.0 { pos + channel.properties.interpolation_type as usize } else { pos };
216
217 let mut get_next_pos = next_pos * alignment * fmt_channels as usize;
218 get_next_pos += self.current_sample as usize * alignment * (fmt_channels - 1) as usize;
219 get_next_pos -= get_next_pos % alignment;
220
221 if get_next_pos >= data.len() {
222 if properties.looping {
223 channel.chunk = 0;
224 let amount = channel.position - CHUNK_SIZE;
225 channel.position = if amount > 0.0 { amount } else { 0.0 };
226 if get_pos == get_next_pos {
227 get_pos = 0;
228 }
229
230 get_next_pos = 0;
231
232 } else if channel.queued.len() > 0 {
233 if let Some(cb) = self.callback {
234 cb(current_channel, channel.buffer)
235 };
236
237 channel.buffer = channel.queued.pop_front().unwrap();
238 buffer = &self.buffers[&channel.buffer];
239 data = &buffer.data;
240
241 channel.chunk = 0;
242 let amount = channel.position - CHUNK_SIZE;
243 channel.position = if amount > 0.0 { amount } else { 0.0 };
244
245 if get_pos == get_next_pos {
246 get_pos = 0;
247 }
248
249 get_next_pos = 0;
250 } else {
251 if let Some(cb) = self.callback {
252 cb(current_channel, channel.buffer)
253 };
254 channel.playing = false;
255 channel.chunk = 0;
256 channel.position = 0.0;
257 continue;
258 }
259 }
260
261 if data.len() == 0 {
262 continue;
263 }
264
265 let pan = f64::clamp(if self.current_sample == 0 { (1.0 - channel.properties.panning) * 2.0 } else { 1.0 - ((0.5 - channel.properties.panning)) * 2.0 }, 0.0, 1.0);
266
267 let mut value = Self::get_sample(data, get_pos, fmt_bps);
268 let value_next = Self::get_sample(data, get_next_pos, fmt_bps);
269
270 value = Self::lerp(value, value_next, pos_f64 - pos as f64);
271 value *= channel.properties.volume * pan;
272
273 result += value as i32;
274
275 if self.current_sample == 0 {
276 channel.position += channel.speed;
277 }
278
279 if channel.position >= CHUNK_SIZE {
280 channel.chunk += 1;
281 channel.position = channel.position - CHUNK_SIZE;
282 }
283
284 current_channel += 1;
285 }
286
287 self.current_sample += 1;
288 self.current_sample = self.current_sample % 2;
289
290 let result = i32::clamp(result, i16::MIN as i32, i16::MAX as i32) as i16;
291
292 result
293 }
294
295 pub fn num_channels(&self) -> u16 {
296 self.channels.len() as u16
297 }
298
299 pub fn is_playing(&self, channel: u16) -> bool {
300 if let Some(channel) = self.channels.get(channel as usize) {
301 channel.playing
302 } else {
303 false
304 }
305 }
306
307 pub fn get_available_channel(&self) -> Result<u16, AudioError> {
308 for (i, channel) in self.channels.iter().enumerate() {
309 if !channel.playing {
310 return Ok(i as u16);
311 }
312 }
313
314 Err(AudioError::new(AudioErrorType::NoChannels))
315 }
316
317 #[inline(always)]
318 fn get_sample(data: &[u8], pos: usize, fmt_bps: u8) -> f64 {
319 match fmt_bps {
320 16 => (data[pos] as i16 | ((data[pos + 1] as i16) << 8) as i16) as f64,
321 8 => ((((data[pos] as i32) << 8) as i32) - i16::MAX as i32) as f64,
322 _ => panic!("Invalid bits per sample.")
323 }
324 }
325
326 #[inline(always)]
327 fn lerp(value: f64, next: f64, amount: f64) -> f64 {
328 amount * (next - value) + value
329 }
330}