1 /* Copyright (C) 2010-2020 The RetroArch team
2 *
3 * ---------------------------------------------------------------------------------------
4 * The following license statement only applies to this file (audio_mixer.c).
5 * ---------------------------------------------------------------------------------------
6 *
7 * Permission is hereby granted, free of charge,
8 * to any person obtaining a copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation the rights to
10 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
11 * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
16 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include "../../config.h"
25 #endif
26
27 #include <audio/audio_mixer.h>
28 #include <audio/audio_resampler.h>
29
30 #ifdef HAVE_RWAV
31 #include <formats/rwav.h>
32 #endif
33 #include <memalign.h>
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <math.h>
39
40 #ifdef HAVE_STB_VORBIS
41 #define STB_VORBIS_NO_PUSHDATA_API
42 #define STB_VORBIS_NO_STDIO
43 #define STB_VORBIS_NO_CRT
44
45 #include <stb/stb_vorbis.h>
46 #endif
47
48 #ifdef HAVE_DR_FLAC
49 #define DR_FLAC_IMPLEMENTATION
50 #include <dr/dr_flac.h>
51 #endif
52
53 #ifdef HAVE_DR_MP3
54 #define DR_MP3_IMPLEMENTATION
55 #include <retro_assert.h>
56 #define DRMP3_ASSERT(expression) retro_assert(expression)
57 #include <dr/dr_mp3.h>
58 #endif
59
60 #ifdef HAVE_IBXM
61 #include <ibxm/ibxm.h>
62 #endif
63
64 #define AUDIO_MIXER_MAX_VOICES 8
65 #define AUDIO_MIXER_TEMP_BUFFER 8192
66
67 struct audio_mixer_sound
68 {
69 enum audio_mixer_type type;
70
71 union
72 {
73 struct
74 {
75 /* wav */
76 const float* pcm;
77 unsigned frames;
78 } wav;
79
80 #ifdef HAVE_STB_VORBIS
81 struct
82 {
83 /* ogg */
84 const void* data;
85 unsigned size;
86 } ogg;
87 #endif
88
89 #ifdef HAVE_DR_FLAC
90 struct
91 {
92 /* flac */
93 const void* data;
94 unsigned size;
95 } flac;
96 #endif
97
98 #ifdef HAVE_DR_MP3
99 struct
100 {
101 /* mp */
102 const void* data;
103 unsigned size;
104 } mp3;
105 #endif
106
107 #ifdef HAVE_IBXM
108 struct
109 {
110 /* mod/s3m/xm */
111 const void* data;
112 unsigned size;
113 } mod;
114 #endif
115 } types;
116 };
117
118 struct audio_mixer_voice
119 {
120 union
121 {
122 struct
123 {
124 unsigned position;
125 } wav;
126
127 #ifdef HAVE_STB_VORBIS
128 struct
129 {
130 stb_vorbis *stream;
131 void *resampler_data;
132 const retro_resampler_t *resampler;
133 float *buffer;
134 unsigned position;
135 unsigned samples;
136 unsigned buf_samples;
137 float ratio;
138 } ogg;
139 #endif
140
141 #ifdef HAVE_DR_FLAC
142 struct
143 {
144 float* buffer;
145 drflac *stream;
146 void *resampler_data;
147 const retro_resampler_t *resampler;
148 unsigned position;
149 unsigned samples;
150 unsigned buf_samples;
151 float ratio;
152 } flac;
153 #endif
154
155 #ifdef HAVE_DR_MP3
156 struct
157 {
158 drmp3 stream;
159 void *resampler_data;
160 const retro_resampler_t *resampler;
161 float* buffer;
162 unsigned position;
163 unsigned samples;
164 unsigned buf_samples;
165 float ratio;
166 } mp3;
167 #endif
168
169 #ifdef HAVE_IBXM
170 struct
171 {
172 int* buffer;
173 struct replay* stream;
174 struct module* module;
175 unsigned position;
176 unsigned samples;
177 unsigned buf_samples;
178 } mod;
179 #endif
180 } types;
181 audio_mixer_sound_t *sound;
182 audio_mixer_stop_cb_t stop_cb;
183 unsigned type;
184 float volume;
185 bool repeat;
186
187 };
188
189 /* TODO/FIXME - static globals */
190 static struct audio_mixer_voice s_voices[AUDIO_MIXER_MAX_VOICES] = {0};
191 static unsigned s_rate = 0;
192
193 #ifdef HAVE_RWAV
wav_to_float(const rwav_t * wav,float ** pcm,size_t samples_out)194 static bool wav_to_float(const rwav_t* wav, float** pcm, size_t samples_out)
195 {
196 size_t i;
197 /* Allocate on a 16-byte boundary, and pad to a multiple of 16 bytes */
198 float *f = (float*)memalign_alloc(16,
199 ((samples_out + 15) & ~15) * sizeof(float));
200
201 if (!f)
202 return false;
203
204 *pcm = f;
205
206 if (wav->bitspersample == 8)
207 {
208 float sample = 0.0f;
209 const uint8_t *u8 = (const uint8_t*)wav->samples;
210
211 if (wav->numchannels == 1)
212 {
213 for (i = wav->numsamples; i != 0; i--)
214 {
215 sample = (float)*u8++ / 255.0f;
216 sample = sample * 2.0f - 1.0f;
217 *f++ = sample;
218 *f++ = sample;
219 }
220 }
221 else if (wav->numchannels == 2)
222 {
223 for (i = wav->numsamples; i != 0; i--)
224 {
225 sample = (float)*u8++ / 255.0f;
226 sample = sample * 2.0f - 1.0f;
227 *f++ = sample;
228 sample = (float)*u8++ / 255.0f;
229 sample = sample * 2.0f - 1.0f;
230 *f++ = sample;
231 }
232 }
233 }
234 else
235 {
236 /* TODO/FIXME note to leiradel - can we use audio/conversion/s16_to_float
237 * functions here? */
238
239 float sample = 0.0f;
240 const int16_t *s16 = (const int16_t*)wav->samples;
241
242 if (wav->numchannels == 1)
243 {
244 for (i = wav->numsamples; i != 0; i--)
245 {
246 sample = (float)((int)*s16++ + 32768) / 65535.0f;
247 sample = sample * 2.0f - 1.0f;
248 *f++ = sample;
249 *f++ = sample;
250 }
251 }
252 else if (wav->numchannels == 2)
253 {
254 for (i = wav->numsamples; i != 0; i--)
255 {
256 sample = (float)((int)*s16++ + 32768) / 65535.0f;
257 sample = sample * 2.0f - 1.0f;
258 *f++ = sample;
259 sample = (float)((int)*s16++ + 32768) / 65535.0f;
260 sample = sample * 2.0f - 1.0f;
261 *f++ = sample;
262 }
263 }
264 }
265
266 return true;
267 }
268
one_shot_resample(const float * in,size_t samples_in,unsigned rate,float ** out,size_t * samples_out)269 static bool one_shot_resample(const float* in, size_t samples_in,
270 unsigned rate, float** out, size_t* samples_out)
271 {
272 struct resampler_data info;
273 void* data = NULL;
274 const retro_resampler_t* resampler = NULL;
275 float ratio = (double)s_rate / (double)rate;
276
277 if (!retro_resampler_realloc(&data, &resampler, NULL,
278 RESAMPLER_QUALITY_DONTCARE, ratio))
279 return false;
280
281 /*
282 * Allocate on a 16-byte boundary, and pad to a multiple of 16 bytes. We
283 * add four more samples in the formula below just as safeguard, because
284 * resampler->process sometimes reports more output samples than the
285 * formula below calculates. Ideally, audio resamplers should have a
286 * function to return the number of samples they will output given a
287 * count of input samples.
288 */
289 *samples_out = samples_in * ratio + 4;
290 *out = (float*)memalign_alloc(16,
291 ((*samples_out + 15) & ~15) * sizeof(float));
292
293 if (*out == NULL)
294 return false;
295
296 info.data_in = in;
297 info.data_out = *out;
298 info.input_frames = samples_in / 2;
299 info.output_frames = 0;
300 info.ratio = ratio;
301
302 resampler->process(data, &info);
303 resampler->free(data);
304 return true;
305 }
306 #endif
307
audio_mixer_init(unsigned rate)308 void audio_mixer_init(unsigned rate)
309 {
310 unsigned i;
311
312 s_rate = rate;
313
314 for (i = 0; i < AUDIO_MIXER_MAX_VOICES; i++)
315 s_voices[i].type = AUDIO_MIXER_TYPE_NONE;
316 }
317
audio_mixer_done(void)318 void audio_mixer_done(void)
319 {
320 unsigned i;
321
322 for (i = 0; i < AUDIO_MIXER_MAX_VOICES; i++)
323 s_voices[i].type = AUDIO_MIXER_TYPE_NONE;
324 }
325
audio_mixer_load_wav(void * buffer,int32_t size)326 audio_mixer_sound_t* audio_mixer_load_wav(void *buffer, int32_t size)
327 {
328 #ifdef HAVE_RWAV
329 /* WAV data */
330 rwav_t wav;
331 enum rwav_state rwav_ret;
332 /* WAV samples converted to float */
333 float* pcm = NULL;
334 size_t samples = 0;
335 /* Result */
336 audio_mixer_sound_t* sound = NULL;
337
338 wav.bitspersample = 0;
339 wav.numchannels = 0;
340 wav.samplerate = 0;
341 wav.numsamples = 0;
342 wav.subchunk2size = 0;
343 wav.samples = NULL;
344
345 if ((rwav_ret = rwav_load(&wav, buffer, size)) != RWAV_ITERATE_DONE)
346 return NULL;
347
348 samples = wav.numsamples * 2;
349
350 if (!wav_to_float(&wav, &pcm, samples))
351 return NULL;
352
353 if (wav.samplerate != s_rate)
354 {
355 float* resampled = NULL;
356
357 if (!one_shot_resample(pcm, samples,
358 wav.samplerate, &resampled, &samples))
359 return NULL;
360
361 memalign_free((void*)pcm);
362 pcm = resampled;
363 }
364
365 sound = (audio_mixer_sound_t*)calloc(1, sizeof(*sound));
366
367 if (!sound)
368 {
369 memalign_free((void*)pcm);
370 return NULL;
371 }
372
373 sound->type = AUDIO_MIXER_TYPE_WAV;
374 sound->types.wav.frames = (unsigned)(samples / 2);
375 sound->types.wav.pcm = pcm;
376
377 rwav_free(&wav);
378
379 return sound;
380 #else
381 return NULL;
382 #endif
383 }
384
audio_mixer_load_ogg(void * buffer,int32_t size)385 audio_mixer_sound_t* audio_mixer_load_ogg(void *buffer, int32_t size)
386 {
387 #ifdef HAVE_STB_VORBIS
388 audio_mixer_sound_t* sound = (audio_mixer_sound_t*)calloc(1, sizeof(*sound));
389
390 if (!sound)
391 return NULL;
392
393 sound->type = AUDIO_MIXER_TYPE_OGG;
394 sound->types.ogg.size = size;
395 sound->types.ogg.data = buffer;
396
397 return sound;
398 #else
399 return NULL;
400 #endif
401 }
402
audio_mixer_load_flac(void * buffer,int32_t size)403 audio_mixer_sound_t* audio_mixer_load_flac(void *buffer, int32_t size)
404 {
405 #ifdef HAVE_DR_FLAC
406 audio_mixer_sound_t* sound = (audio_mixer_sound_t*)calloc(1, sizeof(*sound));
407
408 if (!sound)
409 return NULL;
410
411 sound->type = AUDIO_MIXER_TYPE_FLAC;
412 sound->types.flac.size = size;
413 sound->types.flac.data = buffer;
414
415 return sound;
416 #else
417 return NULL;
418 #endif
419 }
420
audio_mixer_load_mp3(void * buffer,int32_t size)421 audio_mixer_sound_t* audio_mixer_load_mp3(void *buffer, int32_t size)
422 {
423 #ifdef HAVE_DR_MP3
424 audio_mixer_sound_t* sound = (audio_mixer_sound_t*)calloc(1, sizeof(*sound));
425
426 if (!sound)
427 return NULL;
428
429 sound->type = AUDIO_MIXER_TYPE_MP3;
430 sound->types.mp3.size = size;
431 sound->types.mp3.data = buffer;
432
433 return sound;
434 #else
435 return NULL;
436 #endif
437 }
438
audio_mixer_load_mod(void * buffer,int32_t size)439 audio_mixer_sound_t* audio_mixer_load_mod(void *buffer, int32_t size)
440 {
441 #ifdef HAVE_IBXM
442 audio_mixer_sound_t* sound = (audio_mixer_sound_t*)calloc(1, sizeof(*sound));
443
444 if (!sound)
445 return NULL;
446
447 sound->type = AUDIO_MIXER_TYPE_MOD;
448 sound->types.mod.size = size;
449 sound->types.mod.data = buffer;
450
451 return sound;
452 #else
453 return NULL;
454 #endif
455 }
456
audio_mixer_destroy(audio_mixer_sound_t * sound)457 void audio_mixer_destroy(audio_mixer_sound_t* sound)
458 {
459 void *handle = NULL;
460 if (!sound)
461 return;
462
463 switch (sound->type)
464 {
465 case AUDIO_MIXER_TYPE_WAV:
466 handle = (void*)sound->types.wav.pcm;
467 if (handle)
468 memalign_free(handle);
469 break;
470 case AUDIO_MIXER_TYPE_OGG:
471 #ifdef HAVE_STB_VORBIS
472 handle = (void*)sound->types.ogg.data;
473 if (handle)
474 free(handle);
475 #endif
476 break;
477 case AUDIO_MIXER_TYPE_MOD:
478 #ifdef HAVE_IBXM
479 handle = (void*)sound->types.mod.data;
480 if (handle)
481 free(handle);
482 #endif
483 break;
484 case AUDIO_MIXER_TYPE_FLAC:
485 #ifdef HAVE_DR_FLAC
486 handle = (void*)sound->types.flac.data;
487 if (handle)
488 free(handle);
489 #endif
490 break;
491 case AUDIO_MIXER_TYPE_MP3:
492 #ifdef HAVE_DR_MP3
493 handle = (void*)sound->types.mp3.data;
494 if (handle)
495 free(handle);
496 #endif
497 break;
498 case AUDIO_MIXER_TYPE_NONE:
499 break;
500 }
501
502 free(sound);
503 }
504
audio_mixer_play_wav(audio_mixer_sound_t * sound,audio_mixer_voice_t * voice,bool repeat,float volume,audio_mixer_stop_cb_t stop_cb)505 static bool audio_mixer_play_wav(audio_mixer_sound_t* sound,
506 audio_mixer_voice_t* voice, bool repeat, float volume,
507 audio_mixer_stop_cb_t stop_cb)
508 {
509 voice->types.wav.position = 0;
510 return true;
511 }
512
513 #ifdef HAVE_STB_VORBIS
audio_mixer_play_ogg(audio_mixer_sound_t * sound,audio_mixer_voice_t * voice,bool repeat,float volume,audio_mixer_stop_cb_t stop_cb)514 static bool audio_mixer_play_ogg(
515 audio_mixer_sound_t* sound,
516 audio_mixer_voice_t* voice,
517 bool repeat, float volume,
518 audio_mixer_stop_cb_t stop_cb)
519 {
520 stb_vorbis_info info;
521 int res = 0;
522 float ratio = 1.0f;
523 unsigned samples = 0;
524 void *ogg_buffer = NULL;
525 void *resampler_data = NULL;
526 const retro_resampler_t* resamp = NULL;
527 stb_vorbis *stb_vorbis = stb_vorbis_open_memory(
528 (const unsigned char*)sound->types.ogg.data,
529 sound->types.ogg.size, &res, NULL);
530
531 if (!stb_vorbis)
532 return false;
533
534 info = stb_vorbis_get_info(stb_vorbis);
535
536 if (info.sample_rate != s_rate)
537 {
538 ratio = (double)s_rate / (double)info.sample_rate;
539
540 if (!retro_resampler_realloc(&resampler_data,
541 &resamp, NULL, RESAMPLER_QUALITY_DONTCARE,
542 ratio))
543 goto error;
544 }
545
546 samples = (unsigned)(AUDIO_MIXER_TEMP_BUFFER * ratio);
547 ogg_buffer = (float*)memalign_alloc(16,
548 ((samples + 15) & ~15) * sizeof(float));
549
550 if (!ogg_buffer)
551 {
552 if (resamp && resampler_data)
553 resamp->free(resampler_data);
554 goto error;
555 }
556
557 /* "system" menu sounds may reuse the same voice without freeing anything first, so do that here if needed */
558 if (voice->types.ogg.stream)
559 stb_vorbis_close(voice->types.ogg.stream);
560 if (voice->types.ogg.resampler && voice->types.ogg.resampler_data)
561 voice->types.ogg.resampler->free(voice->types.ogg.resampler_data);
562 if (voice->types.ogg.buffer)
563 memalign_free(voice->types.ogg.buffer);
564
565 voice->types.ogg.resampler = resamp;
566 voice->types.ogg.resampler_data = resampler_data;
567 voice->types.ogg.buffer = (float*)ogg_buffer;
568 voice->types.ogg.buf_samples = samples;
569 voice->types.ogg.ratio = ratio;
570 voice->types.ogg.stream = stb_vorbis;
571 voice->types.ogg.position = 0;
572 voice->types.ogg.samples = 0;
573
574 return true;
575
576 error:
577 stb_vorbis_close(stb_vorbis);
578 return false;
579 }
580 #endif
581
582 #ifdef HAVE_IBXM
audio_mixer_play_mod(audio_mixer_sound_t * sound,audio_mixer_voice_t * voice,bool repeat,float volume,audio_mixer_stop_cb_t stop_cb)583 static bool audio_mixer_play_mod(
584 audio_mixer_sound_t* sound,
585 audio_mixer_voice_t* voice,
586 bool repeat, float volume,
587 audio_mixer_stop_cb_t stop_cb)
588 {
589 struct data data;
590 char message[64];
591 int buf_samples = 0;
592 int samples = 0;
593 void *mod_buffer = NULL;
594 struct module* module = NULL;
595 struct replay* replay = NULL;
596
597 data.buffer = (char*)sound->types.mod.data;
598 data.length = sound->types.mod.size;
599 module = module_load(&data, message);
600
601 if (!module)
602 {
603 printf("audio_mixer_play_mod module_load() failed with error: %s\n", message);
604 goto error;
605 }
606
607 if (voice->types.mod.module)
608 dispose_module(voice->types.mod.module);
609
610 voice->types.mod.module = module;
611
612 replay = new_replay(module, s_rate, 1);
613
614 if (!replay)
615 {
616 printf("audio_mixer_play_mod new_replay() failed\n");
617 goto error;
618 }
619
620 buf_samples = calculate_mix_buf_len(s_rate);
621 mod_buffer = memalign_alloc(16, ((buf_samples + 15) & ~15) * sizeof(int));
622
623 if (!mod_buffer)
624 {
625 printf("audio_mixer_play_mod cannot allocate mod_buffer !\n");
626 goto error;
627 }
628
629 samples = replay_calculate_duration(replay);
630
631 if (!samples)
632 {
633 printf("audio_mixer_play_mod cannot retrieve duration !\n");
634 goto error;
635 }
636
637 /* FIXME: stopping and then starting a mod stream will crash here in dispose_replay (ASAN says struct replay is misaligned?) */
638 if (voice->types.mod.stream)
639 dispose_replay(voice->types.mod.stream);
640 if (voice->types.mod.buffer)
641 memalign_free(voice->types.mod.buffer);
642
643 voice->types.mod.buffer = (int*)mod_buffer;
644 voice->types.mod.buf_samples = buf_samples;
645 voice->types.mod.stream = replay;
646 voice->types.mod.position = 0;
647 voice->types.mod.samples = 0; /* samples; */
648
649 return true;
650
651 error:
652 if (mod_buffer)
653 memalign_free(mod_buffer);
654 if (module)
655 dispose_module(module);
656 return false;
657
658 }
659 #endif
660
661 #ifdef HAVE_DR_FLAC
audio_mixer_play_flac(audio_mixer_sound_t * sound,audio_mixer_voice_t * voice,bool repeat,float volume,audio_mixer_stop_cb_t stop_cb)662 static bool audio_mixer_play_flac(
663 audio_mixer_sound_t* sound,
664 audio_mixer_voice_t* voice,
665 bool repeat, float volume,
666 audio_mixer_stop_cb_t stop_cb)
667 {
668 float ratio = 1.0f;
669 unsigned samples = 0;
670 void *flac_buffer = NULL;
671 void *resampler_data = NULL;
672 const retro_resampler_t* resamp = NULL;
673 drflac *dr_flac = drflac_open_memory((const unsigned char*)sound->types.flac.data,sound->types.flac.size);
674
675 if (!dr_flac)
676 return false;
677 if (dr_flac->sampleRate != s_rate)
678 {
679 ratio = (double)s_rate / (double)(dr_flac->sampleRate);
680
681 if (!retro_resampler_realloc(&resampler_data,
682 &resamp, NULL, RESAMPLER_QUALITY_DONTCARE,
683 ratio))
684 goto error;
685 }
686
687 samples = (unsigned)(AUDIO_MIXER_TEMP_BUFFER * ratio);
688 flac_buffer = (float*)memalign_alloc(16,
689 ((samples + 15) & ~15) * sizeof(float));
690
691 if (!flac_buffer)
692 {
693 if (resamp && resamp->free)
694 resamp->free(resampler_data);
695 goto error;
696 }
697
698 if (voice->types.flac.stream)
699 drflac_close(voice->types.flac.stream);
700 if (voice->types.flac.resampler && voice->types.flac.resampler_data)
701 voice->types.flac.resampler->free(voice->types.flac.resampler_data);
702 if (voice->types.flac.buffer)
703 memalign_free(voice->types.flac.buffer);
704
705 voice->types.flac.resampler = resamp;
706 voice->types.flac.resampler_data = resampler_data;
707 voice->types.flac.buffer = (float*)flac_buffer;
708 voice->types.flac.buf_samples = samples;
709 voice->types.flac.ratio = ratio;
710 voice->types.flac.stream = dr_flac;
711 voice->types.flac.position = 0;
712 voice->types.flac.samples = 0;
713
714 return true;
715
716 error:
717 drflac_close(dr_flac);
718 return false;
719 }
720 #endif
721
722 #ifdef HAVE_DR_MP3
audio_mixer_play_mp3(audio_mixer_sound_t * sound,audio_mixer_voice_t * voice,bool repeat,float volume,audio_mixer_stop_cb_t stop_cb)723 static bool audio_mixer_play_mp3(
724 audio_mixer_sound_t* sound,
725 audio_mixer_voice_t* voice,
726 bool repeat, float volume,
727 audio_mixer_stop_cb_t stop_cb)
728 {
729 float ratio = 1.0f;
730 unsigned samples = 0;
731 void *mp3_buffer = NULL;
732 void *resampler_data = NULL;
733 const retro_resampler_t* resamp = NULL;
734 bool res;
735
736 if (voice->types.mp3.stream.pData)
737 {
738 drmp3_uninit(&voice->types.mp3.stream);
739 memset(&voice->types.mp3.stream, 0, sizeof(voice->types.mp3.stream));
740 }
741
742 res = drmp3_init_memory(&voice->types.mp3.stream, (const unsigned char*)sound->types.mp3.data, sound->types.mp3.size, NULL);
743
744 if (!res)
745 return false;
746
747 if (voice->types.mp3.stream.sampleRate != s_rate)
748 {
749 ratio = (double)s_rate / (double)(voice->types.mp3.stream.sampleRate);
750
751 if (!retro_resampler_realloc(&resampler_data,
752 &resamp, NULL, RESAMPLER_QUALITY_DONTCARE,
753 ratio))
754 goto error;
755 }
756
757 samples = (unsigned)(AUDIO_MIXER_TEMP_BUFFER * ratio);
758 mp3_buffer = (float*)memalign_alloc(16,
759 ((samples + 15) & ~15) * sizeof(float));
760
761 if (!mp3_buffer)
762 {
763 if (resamp && resampler_data)
764 resamp->free(resampler_data);
765 goto error;
766 }
767
768 /* "system" menu sounds may reuse the same voice without freeing anything first, so do that here if needed */
769 if (voice->types.mp3.resampler && voice->types.mp3.resampler_data)
770 voice->types.mp3.resampler->free(voice->types.mp3.resampler_data);
771 if (voice->types.mp3.buffer)
772 memalign_free(voice->types.mp3.buffer);
773
774 voice->types.mp3.resampler = resamp;
775 voice->types.mp3.resampler_data = resampler_data;
776 voice->types.mp3.buffer = (float*)mp3_buffer;
777 voice->types.mp3.buf_samples = samples;
778 voice->types.mp3.ratio = ratio;
779 voice->types.mp3.position = 0;
780 voice->types.mp3.samples = 0;
781
782 return true;
783
784 error:
785 drmp3_uninit(&voice->types.mp3.stream);
786 return false;
787 }
788 #endif
789
audio_mixer_play(audio_mixer_sound_t * sound,bool repeat,float volume,audio_mixer_stop_cb_t stop_cb)790 audio_mixer_voice_t* audio_mixer_play(audio_mixer_sound_t* sound, bool repeat,
791 float volume, audio_mixer_stop_cb_t stop_cb)
792 {
793 unsigned i;
794 bool res = false;
795 audio_mixer_voice_t* voice = s_voices;
796
797 if (!sound)
798 return NULL;
799
800 for (i = 0; i < AUDIO_MIXER_MAX_VOICES; i++, voice++)
801 {
802 if (voice->type != AUDIO_MIXER_TYPE_NONE)
803 continue;
804
805 switch (sound->type)
806 {
807 case AUDIO_MIXER_TYPE_WAV:
808 res = audio_mixer_play_wav(sound, voice, repeat, volume, stop_cb);
809 break;
810 case AUDIO_MIXER_TYPE_OGG:
811 #ifdef HAVE_STB_VORBIS
812 res = audio_mixer_play_ogg(sound, voice, repeat, volume, stop_cb);
813 #endif
814 break;
815 case AUDIO_MIXER_TYPE_MOD:
816 #ifdef HAVE_IBXM
817 res = audio_mixer_play_mod(sound, voice, repeat, volume, stop_cb);
818 #endif
819 break;
820 case AUDIO_MIXER_TYPE_FLAC:
821 #ifdef HAVE_DR_FLAC
822 res = audio_mixer_play_flac(sound, voice, repeat, volume, stop_cb);
823 #endif
824 break;
825 case AUDIO_MIXER_TYPE_MP3:
826 #ifdef HAVE_DR_MP3
827 res = audio_mixer_play_mp3(sound, voice, repeat, volume, stop_cb);
828 #endif
829 break;
830 case AUDIO_MIXER_TYPE_NONE:
831 break;
832 }
833
834 break;
835 }
836
837 if (res)
838 {
839 voice->type = sound->type;
840 voice->repeat = repeat;
841 voice->volume = volume;
842 voice->sound = sound;
843 voice->stop_cb = stop_cb;
844 }
845 else
846 voice = NULL;
847
848 return voice;
849 }
850
audio_mixer_stop(audio_mixer_voice_t * voice)851 void audio_mixer_stop(audio_mixer_voice_t* voice)
852 {
853 audio_mixer_stop_cb_t stop_cb = NULL;
854 audio_mixer_sound_t* sound = NULL;
855
856 if (voice)
857 {
858 stop_cb = voice->stop_cb;
859 sound = voice->sound;
860
861 voice->type = AUDIO_MIXER_TYPE_NONE;
862
863 if (stop_cb)
864 stop_cb(sound, AUDIO_MIXER_SOUND_STOPPED);
865 }
866 }
867
audio_mixer_mix_wav(float * buffer,size_t num_frames,audio_mixer_voice_t * voice,float volume)868 static void audio_mixer_mix_wav(float* buffer, size_t num_frames,
869 audio_mixer_voice_t* voice,
870 float volume)
871 {
872 int i;
873 unsigned buf_free = (unsigned)(num_frames * 2);
874 const audio_mixer_sound_t* sound = voice->sound;
875 unsigned pcm_available = sound->types.wav.frames
876 * 2 - voice->types.wav.position;
877 const float* pcm = sound->types.wav.pcm +
878 voice->types.wav.position;
879
880 again:
881 if (pcm_available < buf_free)
882 {
883 for (i = pcm_available; i != 0; i--)
884 *buffer++ += *pcm++ * volume;
885
886 if (voice->repeat)
887 {
888 if (voice->stop_cb)
889 voice->stop_cb(voice->sound, AUDIO_MIXER_SOUND_REPEATED);
890
891 buf_free -= pcm_available;
892 pcm_available = sound->types.wav.frames * 2;
893 pcm = sound->types.wav.pcm;
894 voice->types.wav.position = 0;
895 goto again;
896 }
897
898 if (voice->stop_cb)
899 voice->stop_cb(voice->sound, AUDIO_MIXER_SOUND_FINISHED);
900
901 voice->type = AUDIO_MIXER_TYPE_NONE;
902 }
903 else
904 {
905 for (i = buf_free; i != 0; i--)
906 *buffer++ += *pcm++ * volume;
907
908 voice->types.wav.position += buf_free;
909 }
910 }
911
912 #ifdef HAVE_STB_VORBIS
audio_mixer_mix_ogg(float * buffer,size_t num_frames,audio_mixer_voice_t * voice,float volume)913 static void audio_mixer_mix_ogg(float* buffer, size_t num_frames,
914 audio_mixer_voice_t* voice,
915 float volume)
916 {
917 int i;
918 float* temp_buffer = NULL;
919 unsigned buf_free = (unsigned)(num_frames * 2);
920 unsigned temp_samples = 0;
921 float* pcm = NULL;
922
923 if (voice->types.ogg.position == voice->types.ogg.samples)
924 {
925 again:
926 if (temp_buffer == NULL)
927 temp_buffer = (float*)malloc(AUDIO_MIXER_TEMP_BUFFER * sizeof(float));
928
929 temp_samples = stb_vorbis_get_samples_float_interleaved(
930 voice->types.ogg.stream, 2, temp_buffer,
931 AUDIO_MIXER_TEMP_BUFFER) * 2;
932
933 if (temp_samples == 0)
934 {
935 if (voice->repeat)
936 {
937 if (voice->stop_cb)
938 voice->stop_cb(voice->sound, AUDIO_MIXER_SOUND_REPEATED);
939
940 stb_vorbis_seek_start(voice->types.ogg.stream);
941 goto again;
942 }
943
944 if (voice->stop_cb)
945 voice->stop_cb(voice->sound, AUDIO_MIXER_SOUND_FINISHED);
946
947 voice->type = AUDIO_MIXER_TYPE_NONE;
948 goto cleanup;
949 }
950
951 if (voice->types.ogg.resampler)
952 {
953 struct resampler_data info;
954 info.data_in = temp_buffer;
955 info.data_out = voice->types.ogg.buffer;
956 info.input_frames = temp_samples / 2;
957 info.output_frames = 0;
958 info.ratio = voice->types.ogg.ratio;
959
960 voice->types.ogg.resampler->process(
961 voice->types.ogg.resampler_data, &info);
962 }
963 else
964 memcpy(voice->types.ogg.buffer, temp_buffer,
965 temp_samples * sizeof(float));
966
967 voice->types.ogg.position = 0;
968 voice->types.ogg.samples = voice->types.ogg.buf_samples;
969 }
970
971 pcm = voice->types.ogg.buffer + voice->types.ogg.position;
972
973 if (voice->types.ogg.samples < buf_free)
974 {
975 for (i = voice->types.ogg.samples; i != 0; i--)
976 *buffer++ += *pcm++ * volume;
977
978 buf_free -= voice->types.ogg.samples;
979 goto again;
980 }
981
982 for (i = buf_free; i != 0; --i )
983 *buffer++ += *pcm++ * volume;
984
985 voice->types.ogg.position += buf_free;
986 voice->types.ogg.samples -= buf_free;
987
988 cleanup:
989 if (temp_buffer != NULL)
990 free(temp_buffer);
991 }
992 #endif
993
994 #ifdef HAVE_IBXM
audio_mixer_mix_mod(float * buffer,size_t num_frames,audio_mixer_voice_t * voice,float volume)995 static void audio_mixer_mix_mod(float* buffer, size_t num_frames,
996 audio_mixer_voice_t* voice,
997 float volume)
998 {
999 int i;
1000 float samplef = 0.0f;
1001 unsigned temp_samples = 0;
1002 unsigned buf_free = (unsigned)(num_frames * 2);
1003 int* pcm = NULL;
1004
1005 if (voice->types.mod.samples == 0)
1006 {
1007 again:
1008 temp_samples = replay_get_audio(
1009 voice->types.mod.stream, voice->types.mod.buffer, 0 ) * 2;
1010
1011 if (temp_samples == 0)
1012 {
1013 if (voice->repeat)
1014 {
1015 if (voice->stop_cb)
1016 voice->stop_cb(voice->sound, AUDIO_MIXER_SOUND_REPEATED);
1017
1018 replay_seek( voice->types.mod.stream, 0);
1019 goto again;
1020 }
1021
1022 if (voice->stop_cb)
1023 voice->stop_cb(voice->sound, AUDIO_MIXER_SOUND_FINISHED);
1024
1025 voice->type = AUDIO_MIXER_TYPE_NONE;
1026 return;
1027 }
1028
1029 voice->types.mod.position = 0;
1030 voice->types.mod.samples = temp_samples;
1031 }
1032 pcm = voice->types.mod.buffer + voice->types.mod.position;
1033
1034 if (voice->types.mod.samples < buf_free)
1035 {
1036 for (i = voice->types.mod.samples; i != 0; i--)
1037 {
1038 samplef = ((float)(*pcm++) + 32768.0f) / 65535.0f;
1039 samplef = samplef * 2.0f - 1.0f;
1040 *buffer++ += samplef * volume;
1041 }
1042
1043 buf_free -= voice->types.mod.samples;
1044 goto again;
1045 }
1046
1047 for (i = buf_free; i != 0; --i )
1048 {
1049 samplef = ((float)(*pcm++) + 32768.0f) / 65535.0f;
1050 samplef = samplef * 2.0f - 1.0f;
1051 *buffer++ += samplef * volume;
1052 }
1053
1054 voice->types.mod.position += buf_free;
1055 voice->types.mod.samples -= buf_free;
1056 }
1057 #endif
1058
1059 #ifdef HAVE_DR_FLAC
audio_mixer_mix_flac(float * buffer,size_t num_frames,audio_mixer_voice_t * voice,float volume)1060 static void audio_mixer_mix_flac(float* buffer, size_t num_frames,
1061 audio_mixer_voice_t* voice,
1062 float volume)
1063 {
1064 int i;
1065 struct resampler_data info;
1066 float temp_buffer[AUDIO_MIXER_TEMP_BUFFER] = { 0 };
1067 unsigned buf_free = (unsigned)(num_frames * 2);
1068 unsigned temp_samples = 0;
1069 float *pcm = NULL;
1070
1071 if (voice->types.flac.position == voice->types.flac.samples)
1072 {
1073 again:
1074 temp_samples = (unsigned)drflac_read_f32( voice->types.flac.stream, AUDIO_MIXER_TEMP_BUFFER, temp_buffer);
1075 if (temp_samples == 0)
1076 {
1077 if (voice->repeat)
1078 {
1079 if (voice->stop_cb)
1080 voice->stop_cb(voice->sound, AUDIO_MIXER_SOUND_REPEATED);
1081
1082 drflac_seek_to_sample(voice->types.flac.stream,0);
1083 goto again;
1084 }
1085
1086 if (voice->stop_cb)
1087 voice->stop_cb(voice->sound, AUDIO_MIXER_SOUND_FINISHED);
1088
1089 voice->type = AUDIO_MIXER_TYPE_NONE;
1090 return;
1091 }
1092
1093 info.data_in = temp_buffer;
1094 info.data_out = voice->types.flac.buffer;
1095 info.input_frames = temp_samples / 2;
1096 info.output_frames = 0;
1097 info.ratio = voice->types.flac.ratio;
1098
1099 if (voice->types.flac.resampler)
1100 voice->types.flac.resampler->process(
1101 voice->types.flac.resampler_data, &info);
1102 else
1103 memcpy(voice->types.flac.buffer, temp_buffer, temp_samples * sizeof(float));
1104 voice->types.flac.position = 0;
1105 voice->types.flac.samples = voice->types.flac.buf_samples;
1106 }
1107
1108 pcm = voice->types.flac.buffer + voice->types.flac.position;
1109
1110 if (voice->types.flac.samples < buf_free)
1111 {
1112 for (i = voice->types.flac.samples; i != 0; i--)
1113 *buffer++ += *pcm++ * volume;
1114
1115 buf_free -= voice->types.flac.samples;
1116 goto again;
1117 }
1118
1119 for (i = buf_free; i != 0; --i )
1120 *buffer++ += *pcm++ * volume;
1121
1122 voice->types.flac.position += buf_free;
1123 voice->types.flac.samples -= buf_free;
1124 }
1125 #endif
1126
1127 #ifdef HAVE_DR_MP3
audio_mixer_mix_mp3(float * buffer,size_t num_frames,audio_mixer_voice_t * voice,float volume)1128 static void audio_mixer_mix_mp3(float* buffer, size_t num_frames,
1129 audio_mixer_voice_t* voice,
1130 float volume)
1131 {
1132 int i;
1133 struct resampler_data info;
1134 float temp_buffer[AUDIO_MIXER_TEMP_BUFFER] = { 0 };
1135 unsigned buf_free = (unsigned)(num_frames * 2);
1136 unsigned temp_samples = 0;
1137 float* pcm = NULL;
1138
1139 if (voice->types.mp3.position == voice->types.mp3.samples)
1140 {
1141 again:
1142 temp_samples = (unsigned)drmp3_read_f32(
1143 &voice->types.mp3.stream,
1144 AUDIO_MIXER_TEMP_BUFFER / 2, temp_buffer) * 2;
1145
1146 if (temp_samples == 0)
1147 {
1148 if (voice->repeat)
1149 {
1150 if (voice->stop_cb)
1151 voice->stop_cb(voice->sound, AUDIO_MIXER_SOUND_REPEATED);
1152
1153 drmp3_seek_to_frame(&voice->types.mp3.stream,0);
1154 goto again;
1155 }
1156
1157 if (voice->stop_cb)
1158 voice->stop_cb(voice->sound, AUDIO_MIXER_SOUND_FINISHED);
1159
1160 voice->type = AUDIO_MIXER_TYPE_NONE;
1161 return;
1162 }
1163
1164 info.data_in = temp_buffer;
1165 info.data_out = voice->types.mp3.buffer;
1166 info.input_frames = temp_samples / 2;
1167 info.output_frames = 0;
1168 info.ratio = voice->types.mp3.ratio;
1169
1170 if (voice->types.mp3.resampler)
1171 voice->types.mp3.resampler->process(
1172 voice->types.mp3.resampler_data, &info);
1173 else
1174 memcpy(voice->types.mp3.buffer, temp_buffer,
1175 temp_samples * sizeof(float));
1176 voice->types.mp3.position = 0;
1177 voice->types.mp3.samples = voice->types.mp3.buf_samples;
1178 }
1179
1180 pcm = voice->types.mp3.buffer + voice->types.mp3.position;
1181
1182 if (voice->types.mp3.samples < buf_free)
1183 {
1184 for (i = voice->types.mp3.samples; i != 0; i--)
1185 *buffer++ += *pcm++ * volume;
1186
1187 buf_free -= voice->types.mp3.samples;
1188 goto again;
1189 }
1190
1191 for (i = buf_free; i != 0; --i )
1192 *buffer++ += *pcm++ * volume;
1193
1194 voice->types.mp3.position += buf_free;
1195 voice->types.mp3.samples -= buf_free;
1196 }
1197 #endif
1198
audio_mixer_mix(float * buffer,size_t num_frames,float volume_override,bool override)1199 void audio_mixer_mix(float* buffer, size_t num_frames,
1200 float volume_override, bool override)
1201 {
1202 unsigned i;
1203 size_t j = 0;
1204 float* sample = NULL;
1205 audio_mixer_voice_t* voice = s_voices;
1206
1207 for (i = 0; i < AUDIO_MIXER_MAX_VOICES; i++, voice++)
1208 {
1209 float volume = (override) ? volume_override : voice->volume;
1210
1211 switch (voice->type)
1212 {
1213 case AUDIO_MIXER_TYPE_WAV:
1214 audio_mixer_mix_wav(buffer, num_frames, voice, volume);
1215 break;
1216 case AUDIO_MIXER_TYPE_OGG:
1217 #ifdef HAVE_STB_VORBIS
1218 audio_mixer_mix_ogg(buffer, num_frames, voice, volume);
1219 #endif
1220 break;
1221 case AUDIO_MIXER_TYPE_MOD:
1222 #ifdef HAVE_IBXM
1223 audio_mixer_mix_mod(buffer, num_frames, voice, volume);
1224 #endif
1225 break;
1226 case AUDIO_MIXER_TYPE_FLAC:
1227 #ifdef HAVE_DR_FLAC
1228 audio_mixer_mix_flac(buffer, num_frames, voice, volume);
1229 #endif
1230 break;
1231 case AUDIO_MIXER_TYPE_MP3:
1232 #ifdef HAVE_DR_MP3
1233 audio_mixer_mix_mp3(buffer, num_frames, voice, volume);
1234 #endif
1235 break;
1236 case AUDIO_MIXER_TYPE_NONE:
1237 break;
1238 }
1239 }
1240
1241 for (j = 0, sample = buffer; j < num_frames * 2; j++, sample++)
1242 {
1243 if (*sample < -1.0f)
1244 *sample = -1.0f;
1245 else if (*sample > 1.0f)
1246 *sample = 1.0f;
1247 }
1248 }
1249
audio_mixer_voice_get_volume(audio_mixer_voice_t * voice)1250 float audio_mixer_voice_get_volume(audio_mixer_voice_t *voice)
1251 {
1252 if (!voice)
1253 return 0.0f;
1254
1255 return voice->volume;
1256 }
1257
audio_mixer_voice_set_volume(audio_mixer_voice_t * voice,float val)1258 void audio_mixer_voice_set_volume(audio_mixer_voice_t *voice, float val)
1259 {
1260 if (!voice)
1261 return;
1262
1263 voice->volume = val;
1264 }
1265