1use std::{convert::TryInto, mem::{size_of, transmute}, cell::RefCell, sync::{Weak, RwLock}, sync::Arc, io::{Read, Seek}};
2
3use byteorder::{LittleEndian, ReadBytesExt};
4
5use crate::{audio::{VOICE_COUNT, AudioSample, get_voice_state, queue_stop_voice, get_time, queue_start_voice, queue_set_voice_param_f, AudioVoiceParam, queue_set_voice_param_i}, math::{Vector3, Quaternion}, io::FileStream};
6
7#[derive(Clone, Copy)]
8pub enum AttenuationType {
9 None,
10 InverseDistance,
11 Linear,
12 ExponentialDistance,
13}
14
15#[derive(Clone, Copy)]
16struct SoundVoice {
17 slot: i32,
18 priority: u8,
19 _is_playing: bool,
20 id: u32,
21 play_time: f64,
22}
23
24pub struct SoundEmitter {
25 pub is_valid: bool,
26 pub priority: u8,
27 pub looping: bool,
28 pub reverb: bool,
29 pub is_3d: bool,
30 pub atten_type: AttenuationType,
31 pub atten_min_dist: f32,
32 pub atten_max_dist: f32,
33 pub atten_rolloff: f32,
34 pub position: Vector3,
35 pub volume: f32,
36 pub pitch: f32,
37 pub pan: f32,
38 sample: Arc<AudioSample>,
39 id: u32,
40 voice: Option<i32>,
41}
42
43struct WavHeader {
44 riff: [u8;4],
45 _overall_size: u32,
46 wave: [u8;4],
47}
48
49impl WavHeader {
50 pub fn read(fs: &mut FileStream) -> WavHeader {
51 let mut riff: [u8;4] = [0;4];
52 fs.read_exact(&mut riff).expect("Failed reading header");
53 let overall_size = fs.read_u32::<LittleEndian>().expect("Failed reading header");
54 let mut wave: [u8;4] = [0;4];
55 fs.read_exact(&mut wave).expect("Failed reading header");
56
57 return WavHeader { riff: riff, _overall_size: overall_size, wave: wave };
58 }
59}
60
61struct WavHeaderFormat {
62 fmt_chunk_marker: [u8;4],
63 length_of_fmt: u32,
64 format_type: u16,
65 channels: u16,
66 samplerate: u32,
67 _byterate: u32,
68 block_align: u16,
69 bits_per_sample: u16,
70}
71
72impl WavHeaderFormat {
73 pub fn read(fs: &mut FileStream) -> WavHeaderFormat {
74 let mut fmt_chunk_marker: [u8;4] = [0;4];
75 fs.read_exact(&mut fmt_chunk_marker).expect("Failed reading header");
76 let length_of_fmt = fs.read_u32::<LittleEndian>().expect("Failed reading header");
77 let format_type = fs.read_u16::<LittleEndian>().expect("Failed reading header");
78 let channels = fs.read_u16::<LittleEndian>().expect("Failed reading header");
79 let samplerate = fs.read_u32::<LittleEndian>().expect("Failed reading header");
80 let byterate = fs.read_u32::<LittleEndian>().expect("Failed reading header");
81 let block_align = fs.read_u16::<LittleEndian>().expect("Failed reading header");
82 let bits_per_sample = fs.read_u16::<LittleEndian>().expect("Failed reading header");
83
84 return WavHeaderFormat {
85 fmt_chunk_marker: fmt_chunk_marker,
86 length_of_fmt: length_of_fmt,
87 format_type: format_type,
88 channels: channels,
89 samplerate: samplerate,
90 _byterate: byterate,
91 block_align: block_align,
92 bits_per_sample: bits_per_sample,
93 };
94 }
95}
96
97struct WavChunkHeader {
98 id: [u8;4],
99 chunk_size: u32,
100}
101
102impl WavChunkHeader {
103 pub fn read(fs: &mut FileStream) -> WavChunkHeader {
104 let mut id: [u8;4] = [0;4];
105 fs.read_exact(&mut id).expect("Failed reading header");
106 let chunk_size = fs.read_u32::<LittleEndian>().expect("Failed reading header");
107
108 return WavChunkHeader {
109 id: id,
110 chunk_size: chunk_size
111 };
112 }
113}
114
115pub struct SoundDriver {
116 max_voices: usize,
117 voices: [SoundVoice;VOICE_COUNT],
118 emitters: Vec<Arc<RwLock<SoundEmitter>>>,
119 listener_position: Vector3,
120 listener_orientation: Quaternion,
121 search_offset: usize,
122}
123
124impl SoundDriver {
125 pub fn new(max_voices: usize) -> SoundDriver {
127 assert!(max_voices <= VOICE_COUNT, "Cannot init sound driver with more than {} voices", VOICE_COUNT);
128
129 let mut driver = SoundDriver {
130 max_voices: max_voices,
131 voices: [
132 SoundVoice {
133 slot: 0,
134 priority: 255,
135 _is_playing: false,
136 id: 0,
137 play_time: 0.0
138 }; VOICE_COUNT
139 ],
140 emitters: Vec::new(),
141 listener_position: Vector3::zero(),
142 listener_orientation: Quaternion::identity(),
143 search_offset: 0,
144 };
145
146 for i in 0..VOICE_COUNT {
147 driver.voices[i].slot = i.try_into().unwrap();
148 }
149
150 return driver;
151 }
152
153 fn allocate_voice(voices: &mut [SoundVoice], search_offset: &mut usize, max_voice: usize, priority: u8) -> Option<usize> {
154 let mut ret: Option<usize> = None;
159
160 for i in 0..max_voice {
161 let idx = (i + *search_offset) % max_voice;
162 let voice = &voices[idx];
163
164 if !voice._is_playing && !get_voice_state(voice.slot) {
165 ret = Some(idx);
166 break;
167 } else {
168 match ret {
169 Some(r) => {
170 let rv = &voices[r];
171 if voice.play_time < rv.play_time && voice.priority >= priority {
172 ret = Some(idx);
173 }
174 },
175 None => {
176 ret = Some(idx);
177 }
178 };
179 }
180 }
181
182 *search_offset = (*search_offset + 1) % max_voice;
183
184 match ret {
185 Some(r) => {
186 let rv = &mut voices[r];
187 rv.priority = priority;
188 },
189 None => {
190 }
191 }
192
193 return ret;
194 }
195
196 fn assign_hw_voice(listener_position: &Vector3, listener_orientation: &Quaternion, voices: &mut [SoundVoice], search_offset: &mut usize, max_voice: usize, emitter: &mut SoundEmitter) {
197 let voice = SoundDriver::allocate_voice(voices, search_offset, max_voice, emitter.priority);
198
199 if voice.is_some() {
200 let idx = voice.unwrap();
201 let t = get_time();
202 voices[idx].play_time = t;
203 voices[idx].id += 1;
204 emitter.voice = Some(idx.try_into().unwrap());
205 emitter.id = voices[idx].id;
206
207 SoundDriver::update_voice(listener_position, listener_orientation, &voices[idx], emitter);
208 queue_start_voice(idx.try_into().unwrap(), t);
209 }
210 }
211
212 fn calc_3d(listener_position: &Vector3, listener_orientation: &Quaternion, position: &Vector3, atten_type: AttenuationType, atten_min_dist: f32, atten_max_dist: f32, atten_rolloff: f32) -> (f32, f32) {
213 let dist = Vector3::distance(position, listener_position).clamp(atten_min_dist, atten_max_dist);
215 let gain = match atten_type {
216 AttenuationType::Linear => {
217 1.0 - atten_rolloff * (dist - atten_min_dist) / (atten_max_dist - atten_min_dist)
218 }
219 AttenuationType::InverseDistance => {
220 atten_min_dist / (atten_min_dist + atten_rolloff * (dist - atten_min_dist))
221 }
222 AttenuationType::ExponentialDistance => {
223 (dist / atten_min_dist).powf(-atten_rolloff)
224 }
225 AttenuationType::None => {
226 1.0
227 }
228 };
229
230 let mut local_pos = *position - *listener_position;
232 let mut rot = *listener_orientation;
233 rot.invert();
234 local_pos = rot * local_pos;
235 local_pos.normalize();
236
237 let pan = local_pos.x;
238
239 return (gain, pan);
240 }
241
242 fn update_voice(listener_position: &Vector3, listener_orientation: &Quaternion, voice: &SoundVoice, emitter: &mut SoundEmitter) {
243 if emitter.id == voice.id {
244 let t = get_time();
245 let mut gain = emitter.volume;
246 let mut pan = emitter.pan;
247
248 if emitter.is_3d {
249 let (gain3d, pan3d) = SoundDriver::calc_3d(listener_position, listener_orientation, &emitter.position,
250 emitter.atten_type, emitter.atten_min_dist, emitter.atten_max_dist, emitter.atten_rolloff);
251
252 gain *= gain3d;
253 pan = pan3d;
254 }
255
256 let voice_slot = TryInto::<i32>::try_into(voice.slot).unwrap();
257 queue_set_voice_param_i(voice_slot, AudioVoiceParam::SampleData, emitter.sample.handle, t);
258 queue_set_voice_param_i(voice_slot, AudioVoiceParam::Samplerate, emitter.sample.samplerate, t);
259 queue_set_voice_param_i(voice_slot, AudioVoiceParam::LoopEnabled, if emitter.looping { 1 } else { 0 }, t);
260 queue_set_voice_param_i(voice_slot, AudioVoiceParam::LoopStart, 0, t);
261 queue_set_voice_param_i(voice_slot, AudioVoiceParam::LoopEnd, 0, t);
262 queue_set_voice_param_i(voice_slot, AudioVoiceParam::Reverb, if emitter.reverb { 1 } else { 0 }, t);
263 queue_set_voice_param_f(voice_slot, AudioVoiceParam::Volume, gain, t);
264 queue_set_voice_param_f(voice_slot, AudioVoiceParam::Detune, 0.0, t);
265 queue_set_voice_param_f(voice_slot, AudioVoiceParam::Pitch, emitter.pitch, t);
266 queue_set_voice_param_f(voice_slot, AudioVoiceParam::Pan, pan, t);
267 queue_set_voice_param_f(voice_slot, AudioVoiceParam::FadeInDuration, 0.0, t);
268 queue_set_voice_param_f(voice_slot, AudioVoiceParam::FadeOutDuration, 0.0, t);
269 } else {
270 emitter.voice = None;
272 }
273 }
274
275 pub fn update(&mut self) {
277 let emitters = self.emitters.as_mut_slice();
278 for emitter_rc in emitters {
279 let voice = {
280 emitter_rc.read().unwrap().voice
281 };
282 {
283 let mut emref = emitter_rc.write().unwrap();
284 match voice {
285 Some(v) => {
286 SoundDriver::update_voice(&self.listener_position, &self.listener_orientation, &self.voices[TryInto::<usize>::try_into(v).unwrap()], &mut emref);
287 },
288 None => {
289 if emref.looping {
290 SoundDriver::assign_hw_voice(&self.listener_position, &self.listener_orientation, &mut self.voices, &mut self.search_offset, self.max_voices, &mut emref);
291 }
292 }
293 }
294 }
295 {
296 let mut emref = emitter_rc.write().unwrap();
297 if !emref.looping && (!voice.is_some() || !get_voice_state(voice.unwrap().try_into().unwrap())) {
299 emref.is_valid = false;
300 }
301 }
302 }
303
304 self.emitters.retain(|x| {
306 x.read().unwrap().is_valid
307 });
308 }
309
310 pub fn set_listener(&mut self, position: Vector3, orientation: Quaternion) {
312 self.listener_position = position;
313 self.listener_orientation = orientation;
314 }
315
316 pub fn play(&mut self, priority: u8, sample: &Arc<AudioSample>, looping: bool, reverb: bool, volume: f32, pitch: f32, pan: f32) -> Weak<RwLock<SoundEmitter>> {
318 let mut emitter = SoundEmitter {
319 is_valid: true,
320 priority: priority,
321 looping: looping,
322 reverb: reverb,
323 is_3d: false,
324 atten_type: AttenuationType::None,
325 atten_min_dist: 0.0,
326 atten_max_dist: 0.0,
327 atten_rolloff: 0.0,
328 position: Vector3::zero(),
329 volume: volume,
330 pitch: pitch,
331 pan: pan,
332 sample: sample.clone(),
333 id: 0,
334 voice: None
335 };
336 SoundDriver::assign_hw_voice(&self.listener_position, &self.listener_orientation, &mut self.voices, &mut self.search_offset, self.max_voices, &mut emitter);
337
338 let rc = Arc::new(RwLock::new(emitter));
339 let wr = Arc::downgrade(&rc);
340 self.emitters.push(rc);
341
342 return wr;
343 }
344
345 pub fn play_3d(&mut self, priority: u8, sample: &Arc<AudioSample>, looping: bool, reverb: bool, volume: f32, pitch: f32,
347 position: Vector3, atten_type: AttenuationType, atten_min_dist: f32, atten_max_dist: f32, atten_rolloff: f32) -> Weak<RwLock<SoundEmitter>> {
348 let mut emitter = SoundEmitter {
349 is_valid: true,
350 priority: priority,
351 looping: looping,
352 reverb: reverb,
353 is_3d: true,
354 atten_type: atten_type,
355 atten_min_dist: atten_min_dist,
356 atten_max_dist: atten_max_dist,
357 atten_rolloff: atten_rolloff,
358 position: position,
359 volume: volume,
360 pitch: pitch,
361 pan: 0.0,
362 sample: sample.clone(),
363 id: 0,
364 voice: None
365 };
366 SoundDriver::assign_hw_voice(&self.listener_position, &self.listener_orientation, &mut self.voices, &mut self.search_offset, self.max_voices, &mut emitter);
367
368 let rc = Arc::new(RwLock::new(emitter));
369 let wr = Arc::downgrade(&rc);
370 self.emitters.push(rc);
371
372 return wr;
373 }
374
375 pub fn stop(&mut self, emitter_ref: Weak<RefCell<SoundEmitter>>) {
377 let rc = emitter_ref.upgrade();
378 if !rc.is_some() {
379 return;
380 }
381
382 let em = rc.unwrap();
383 let mut emitter = em.borrow_mut();
384
385 if !emitter.is_valid { return; }
386
387 if emitter.voice.is_some() {
388 let voiceid = TryInto::<usize>::try_into(emitter.voice.unwrap()).unwrap();
389 let voice: &mut SoundVoice = &mut self.voices[voiceid];
390 if voice.id == emitter.id {
391 voice.priority = 255;
392 queue_stop_voice(voice.slot.try_into().unwrap(), 0.0);
393 }
394 }
395
396 emitter.is_valid = false;
397 }
398}
399
400pub fn load_wav(file: &mut FileStream) -> Result<AudioSample,()> {
402 let header = WavHeader::read(file);
403
404 let riff = match std::str::from_utf8(&header.riff) {
406 Ok(v) => { v },
407 Err(_) => { return Err(()); }
408 };
409
410 if riff != "RIFF" {
411 return Err(());
412 }
413
414 let wave = match std::str::from_utf8(&header.wave) {
416 Ok(v) => { v },
417 Err(_) => { return Err(()); }
418 };
419
420 if wave != "WAVE" {
421 return Err(());
422 }
423
424 let fmt_header = WavHeaderFormat::read(file);
425
426 let fmt_str = match std::str::from_utf8(&fmt_header.fmt_chunk_marker) {
429 Ok(v) => { v },
430 Err(_) => { return Err(()); }
431 };
432
433 if fmt_str != "fmt " {
434 return Err(());
435 }
436
437 if fmt_header.channels != 1 {
438 return Err(());
439 }
440
441 let fmt_header_size: usize = fmt_header.length_of_fmt.try_into().unwrap();
443 let header_size: usize = size_of::<WavHeader>() + fmt_header_size + 8;
444
445 match file.seek(std::io::SeekFrom::Start(header_size.try_into().unwrap())) {
446 Ok(_) => { },
447 Err(_) => { return Err(()); }
448 }
449
450 let mut data_found = false;
451 let mut chunk_header: WavChunkHeader = WavChunkHeader { id: [0;4], chunk_size: 0 };
452
453 while !file.end_of_file() {
454 chunk_header = WavChunkHeader::read(file);
455
456 let chunk_id = match std::str::from_utf8(&chunk_header.id) {
457 Ok(v) => { v },
458 Err(_) => { return Err(()); }
459 };
460
461 if chunk_id == "data" {
462 data_found = true;
463 break;
464 } else {
465 if file.seek(std::io::SeekFrom::Current(chunk_header.chunk_size.try_into().unwrap())).is_err() {
467 return Err(());
468 }
469 }
470 }
471
472 if !data_found {
473 return Err(());
474 }
475
476 if fmt_header.format_type == 1 && fmt_header.bits_per_sample == 8 {
477 let mut pcm8: Vec<u8> = vec![0;chunk_header.chunk_size.try_into().unwrap()];
479 match file.read(pcm8.as_mut_slice()) {
480 Ok(_) => {},
481 Err(_) => { return Err(()); }
482 };
483
484 for i in 0..pcm8.len() {
486 pcm8[i] = pcm8[i].wrapping_sub(128);
487 }
488
489 let sample_handle = unsafe { AudioSample::create_s8(transmute(pcm8.as_slice()),
490 fmt_header.samplerate.try_into().unwrap())? };
491
492 return Ok(sample_handle);
493 } else if fmt_header.format_type == 1 && fmt_header.bits_per_sample == 16 {
494 let mut pcm16: Vec<u8> = vec![0, chunk_header.chunk_size.try_into().unwrap()];
496 match file.read(pcm16.as_mut_slice()) {
497 Ok(_) => {},
498 Err(_) => { return Err(()); }
499 };
500
501 let sample_handle = unsafe { AudioSample::create_s16(transmute(pcm16.as_slice()),
502 fmt_header.samplerate.try_into().unwrap())? };
503
504 return Ok(sample_handle);
505 } else if fmt_header.format_type == 0x11 {
506 let mut adpcm: Vec<u8> = vec![0, chunk_header.chunk_size.try_into().unwrap()];
508 match file.read(adpcm.as_mut_slice()) {
509 Ok(_) => {},
510 Err(_) => { return Err(()); }
511 }
512
513 let sample_handle = AudioSample::create_adpcm(adpcm.as_slice(),
514 fmt_header.block_align.try_into().unwrap(),
515 fmt_header.samplerate.try_into().unwrap())?;
516
517 return Ok(sample_handle);
518 }
519
520 return Err(());
521}