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 /* WAV samples converted to float */
332 float* pcm = NULL;
333 size_t samples = 0;
334 /* Result */
335 audio_mixer_sound_t* sound = NULL;
336 enum rwav_state rwav_ret = rwav_load(&wav, buffer, size);
337
338 if (rwav_ret != RWAV_ITERATE_DONE)
339 return NULL;
340
341 samples = wav.numsamples * 2;
342
343 if (!wav_to_float(&wav, &pcm, samples))
344 return NULL;
345
346 if (wav.samplerate != s_rate)
347 {
348 float* resampled = NULL;
349
350 if (!one_shot_resample(pcm, samples,
351 wav.samplerate, &resampled, &samples))
352 return NULL;
353
354 memalign_free((void*)pcm);
355 pcm = resampled;
356 }
357
358 sound = (audio_mixer_sound_t*)calloc(1, sizeof(*sound));
359
360 if (!sound)
361 {
362 memalign_free((void*)pcm);
363 return NULL;
364 }
365
366 sound->type = AUDIO_MIXER_TYPE_WAV;
367 sound->types.wav.frames = (unsigned)(samples / 2);
368 sound->types.wav.pcm = pcm;
369
370 rwav_free(&wav);
371
372 return sound;
373 #else
374 return NULL;
375 #endif
376 }
377
audio_mixer_load_ogg(void * buffer,int32_t size)378 audio_mixer_sound_t* audio_mixer_load_ogg(void *buffer, int32_t size)
379 {
380 #ifdef HAVE_STB_VORBIS
381 audio_mixer_sound_t* sound = (audio_mixer_sound_t*)calloc(1, sizeof(*sound));
382
383 if (!sound)
384 return NULL;
385
386 sound->type = AUDIO_MIXER_TYPE_OGG;
387 sound->types.ogg.size = size;
388 sound->types.ogg.data = buffer;
389
390 return sound;
391 #else
392 return NULL;
393 #endif
394 }
395
audio_mixer_load_flac(void * buffer,int32_t size)396 audio_mixer_sound_t* audio_mixer_load_flac(void *buffer, int32_t size)
397 {
398 #ifdef HAVE_DR_FLAC
399 audio_mixer_sound_t* sound = (audio_mixer_sound_t*)calloc(1, sizeof(*sound));
400
401 if (!sound)
402 return NULL;
403
404 sound->type = AUDIO_MIXER_TYPE_FLAC;
405 sound->types.flac.size = size;
406 sound->types.flac.data = buffer;
407
408 return sound;
409 #else
410 return NULL;
411 #endif
412 }
413
audio_mixer_load_mp3(void * buffer,int32_t size)414 audio_mixer_sound_t* audio_mixer_load_mp3(void *buffer, int32_t size)
415 {
416 #ifdef HAVE_DR_MP3
417 audio_mixer_sound_t* sound = (audio_mixer_sound_t*)calloc(1, sizeof(*sound));
418
419 if (!sound)
420 return NULL;
421
422 sound->type = AUDIO_MIXER_TYPE_MP3;
423 sound->types.mp3.size = size;
424 sound->types.mp3.data = buffer;
425
426 return sound;
427 #else
428 return NULL;
429 #endif
430 }
431
audio_mixer_load_mod(void * buffer,int32_t size)432 audio_mixer_sound_t* audio_mixer_load_mod(void *buffer, int32_t size)
433 {
434 #ifdef HAVE_IBXM
435 audio_mixer_sound_t* sound = (audio_mixer_sound_t*)calloc(1, sizeof(*sound));
436
437 if (!sound)
438 return NULL;
439
440 sound->type = AUDIO_MIXER_TYPE_MOD;
441 sound->types.mod.size = size;
442 sound->types.mod.data = buffer;
443
444 return sound;
445 #else
446 return NULL;
447 #endif
448 }
449
audio_mixer_destroy(audio_mixer_sound_t * sound)450 void audio_mixer_destroy(audio_mixer_sound_t* sound)
451 {
452 void *handle = NULL;
453 if (!sound)
454 return;
455
456 switch (sound->type)
457 {
458 case AUDIO_MIXER_TYPE_WAV:
459 handle = (void*)sound->types.wav.pcm;
460 if (handle)
461 memalign_free(handle);
462 break;
463 case AUDIO_MIXER_TYPE_OGG:
464 #ifdef HAVE_STB_VORBIS
465 handle = (void*)sound->types.ogg.data;
466 if (handle)
467 free(handle);
468 #endif
469 break;
470 case AUDIO_MIXER_TYPE_MOD:
471 #ifdef HAVE_IBXM
472 handle = (void*)sound->types.mod.data;
473 if (handle)
474 free(handle);
475 #endif
476 break;
477 case AUDIO_MIXER_TYPE_FLAC:
478 #ifdef HAVE_DR_FLAC
479 handle = (void*)sound->types.flac.data;
480 if (handle)
481 free(handle);
482 #endif
483 break;
484 case AUDIO_MIXER_TYPE_MP3:
485 #ifdef HAVE_DR_MP3
486 handle = (void*)sound->types.mp3.data;
487 if (handle)
488 free(handle);
489 #endif
490 break;
491 case AUDIO_MIXER_TYPE_NONE:
492 break;
493 }
494
495 free(sound);
496 }
497
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)498 static bool audio_mixer_play_wav(audio_mixer_sound_t* sound,
499 audio_mixer_voice_t* voice, bool repeat, float volume,
500 audio_mixer_stop_cb_t stop_cb)
501 {
502 voice->types.wav.position = 0;
503 return true;
504 }
505
506 #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)507 static bool audio_mixer_play_ogg(
508 audio_mixer_sound_t* sound,
509 audio_mixer_voice_t* voice,
510 bool repeat, float volume,
511 audio_mixer_stop_cb_t stop_cb)
512 {
513 stb_vorbis_info info;
514 int res = 0;
515 float ratio = 1.0f;
516 unsigned samples = 0;
517 void *ogg_buffer = NULL;
518 void *resampler_data = NULL;
519 const retro_resampler_t* resamp = NULL;
520 stb_vorbis *stb_vorbis = stb_vorbis_open_memory(
521 (const unsigned char*)sound->types.ogg.data,
522 sound->types.ogg.size, &res, NULL);
523
524 if (!stb_vorbis)
525 return false;
526
527 info = stb_vorbis_get_info(stb_vorbis);
528
529 if (info.sample_rate != s_rate)
530 {
531 ratio = (double)s_rate / (double)info.sample_rate;
532
533 if (!retro_resampler_realloc(&resampler_data,
534 &resamp, NULL, RESAMPLER_QUALITY_DONTCARE,
535 ratio))
536 goto error;
537 }
538
539 samples = (unsigned)(AUDIO_MIXER_TEMP_BUFFER * ratio);
540 ogg_buffer = (float*)memalign_alloc(16,
541 ((samples + 15) & ~15) * sizeof(float));
542
543 if (!ogg_buffer)
544 {
545 if (resamp && resampler_data)
546 resamp->free(resampler_data);
547 goto error;
548 }
549
550 /* "system" menu sounds may reuse the same voice without freeing anything first, so do that here if needed */
551 if (voice->types.ogg.stream)
552 stb_vorbis_close(voice->types.ogg.stream);
553 if (voice->types.ogg.resampler && voice->types.ogg.resampler_data)
554 voice->types.ogg.resampler->free(voice->types.ogg.resampler_data);
555 if (voice->types.ogg.buffer)
556 memalign_free(voice->types.ogg.buffer);
557
558 voice->types.ogg.resampler = resamp;
559 voice->types.ogg.resampler_data = resampler_data;
560 voice->types.ogg.buffer = (float*)ogg_buffer;
561 voice->types.ogg.buf_samples = samples;
562 voice->types.ogg.ratio = ratio;
563 voice->types.ogg.stream = stb_vorbis;
564 voice->types.ogg.position = 0;
565 voice->types.ogg.samples = 0;
566
567 return true;
568
569 error:
570 stb_vorbis_close(stb_vorbis);
571 return false;
572 }
573 #endif
574
575 #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)576 static bool audio_mixer_play_mod(
577 audio_mixer_sound_t* sound,
578 audio_mixer_voice_t* voice,
579 bool repeat, float volume,
580 audio_mixer_stop_cb_t stop_cb)
581 {
582 struct data data;
583 char message[64];
584 int buf_samples = 0;
585 int samples = 0;
586 void *mod_buffer = NULL;
587 struct module* module = NULL;
588 struct replay* replay = NULL;
589
590 data.buffer = (char*)sound->types.mod.data;
591 data.length = sound->types.mod.size;
592 module = module_load(&data, message);
593
594 if (!module)
595 {
596 printf("audio_mixer_play_mod module_load() failed with error: %s\n", message);
597 goto error;
598 }
599
600 if (voice->types.mod.module)
601 dispose_module(voice->types.mod.module);
602
603 voice->types.mod.module = module;
604
605 replay = new_replay(module, s_rate, 1);
606
607 if (!replay)
608 {
609 printf("audio_mixer_play_mod new_replay() failed\n");
610 goto error;
611 }
612
613 buf_samples = calculate_mix_buf_len(s_rate);
614 mod_buffer = memalign_alloc(16, ((buf_samples + 15) & ~15) * sizeof(int));
615
616 if (!mod_buffer)
617 {
618 printf("audio_mixer_play_mod cannot allocate mod_buffer !\n");
619 goto error;
620 }
621
622 samples = replay_calculate_duration(replay);
623
624 if (!samples)
625 {
626 printf("audio_mixer_play_mod cannot retrieve duration !\n");
627 goto error;
628 }
629
630 /* FIXME: stopping and then starting a mod stream will crash here in dispose_replay (ASAN says struct replay is misaligned?) */
631 if (voice->types.mod.stream)
632 dispose_replay(voice->types.mod.stream);
633 if (voice->types.mod.buffer)
634 memalign_free(voice->types.mod.buffer);
635
636 voice->types.mod.buffer = (int*)mod_buffer;
637 voice->types.mod.buf_samples = buf_samples;
638 voice->types.mod.stream = replay;
639 voice->types.mod.position = 0;
640 voice->types.mod.samples = 0; /* samples; */
641
642 return true;
643
644 error:
645 if (mod_buffer)
646 memalign_free(mod_buffer);
647 if (module)
648 dispose_module(module);
649 return false;
650
651 }
652 #endif
653
654 #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)655 static bool audio_mixer_play_flac(
656 audio_mixer_sound_t* sound,
657 audio_mixer_voice_t* voice,
658 bool repeat, float volume,
659 audio_mixer_stop_cb_t stop_cb)
660 {
661 float ratio = 1.0f;
662 unsigned samples = 0;
663 void *flac_buffer = NULL;
664 void *resampler_data = NULL;
665 const retro_resampler_t* resamp = NULL;
666 drflac *dr_flac = drflac_open_memory((const unsigned char*)sound->types.flac.data,sound->types.flac.size);
667
668 if (!dr_flac)
669 return false;
670 if (dr_flac->sampleRate != s_rate)
671 {
672 ratio = (double)s_rate / (double)(dr_flac->sampleRate);
673
674 if (!retro_resampler_realloc(&resampler_data,
675 &resamp, NULL, RESAMPLER_QUALITY_DONTCARE,
676 ratio))
677 goto error;
678 }
679
680 samples = (unsigned)(AUDIO_MIXER_TEMP_BUFFER * ratio);
681 flac_buffer = (float*)memalign_alloc(16,
682 ((samples + 15) & ~15) * sizeof(float));
683
684 if (!flac_buffer)
685 {
686 if (resamp && resamp->free)
687 resamp->free(resampler_data);
688 goto error;
689 }
690
691 if (voice->types.flac.stream)
692 drflac_close(voice->types.flac.stream);
693 if (voice->types.flac.resampler && voice->types.flac.resampler_data)
694 voice->types.flac.resampler->free(voice->types.flac.resampler_data);
695 if (voice->types.flac.buffer)
696 memalign_free(voice->types.flac.buffer);
697
698 voice->types.flac.resampler = resamp;
699 voice->types.flac.resampler_data = resampler_data;
700 voice->types.flac.buffer = (float*)flac_buffer;
701 voice->types.flac.buf_samples = samples;
702 voice->types.flac.ratio = ratio;
703 voice->types.flac.stream = dr_flac;
704 voice->types.flac.position = 0;
705 voice->types.flac.samples = 0;
706
707 return true;
708
709 error:
710 drflac_close(dr_flac);
711 return false;
712 }
713 #endif
714
715 #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)716 static bool audio_mixer_play_mp3(
717 audio_mixer_sound_t* sound,
718 audio_mixer_voice_t* voice,
719 bool repeat, float volume,
720 audio_mixer_stop_cb_t stop_cb)
721 {
722 float ratio = 1.0f;
723 unsigned samples = 0;
724 void *mp3_buffer = NULL;
725 void *resampler_data = NULL;
726 const retro_resampler_t* resamp = NULL;
727 bool res;
728
729 if (voice->types.mp3.stream.pData)
730 {
731 drmp3_uninit(&voice->types.mp3.stream);
732 memset(&voice->types.mp3.stream, 0, sizeof(voice->types.mp3.stream));
733 }
734
735 res = drmp3_init_memory(&voice->types.mp3.stream, (const unsigned char*)sound->types.mp3.data, sound->types.mp3.size, NULL);
736
737 if (!res)
738 return false;
739
740 if (voice->types.mp3.stream.sampleRate != s_rate)
741 {
742 ratio = (double)s_rate / (double)(voice->types.mp3.stream.sampleRate);
743
744 if (!retro_resampler_realloc(&resampler_data,
745 &resamp, NULL, RESAMPLER_QUALITY_DONTCARE,
746 ratio))
747 goto error;
748 }
749
750 samples = (unsigned)(AUDIO_MIXER_TEMP_BUFFER * ratio);
751 mp3_buffer = (float*)memalign_alloc(16,
752 ((samples + 15) & ~15) * sizeof(float));
753
754 if (!mp3_buffer)
755 {
756 if (resamp && resampler_data)
757 resamp->free(resampler_data);
758 goto error;
759 }
760
761 /* "system" menu sounds may reuse the same voice without freeing anything first, so do that here if needed */
762 if (voice->types.mp3.resampler && voice->types.mp3.resampler_data)
763 voice->types.mp3.resampler->free(voice->types.mp3.resampler_data);
764 if (voice->types.mp3.buffer)
765 memalign_free(voice->types.mp3.buffer);
766
767 voice->types.mp3.resampler = resamp;
768 voice->types.mp3.resampler_data = resampler_data;
769 voice->types.mp3.buffer = (float*)mp3_buffer;
770 voice->types.mp3.buf_samples = samples;
771 voice->types.mp3.ratio = ratio;
772 voice->types.mp3.position = 0;
773 voice->types.mp3.samples = 0;
774
775 return true;
776
777 error:
778 drmp3_uninit(&voice->types.mp3.stream);
779 return false;
780 }
781 #endif
782
audio_mixer_play(audio_mixer_sound_t * sound,bool repeat,float volume,audio_mixer_stop_cb_t stop_cb)783 audio_mixer_voice_t* audio_mixer_play(audio_mixer_sound_t* sound, bool repeat,
784 float volume, audio_mixer_stop_cb_t stop_cb)
785 {
786 unsigned i;
787 bool res = false;
788 audio_mixer_voice_t* voice = s_voices;
789
790 if (!sound)
791 return NULL;
792
793 for (i = 0; i < AUDIO_MIXER_MAX_VOICES; i++, voice++)
794 {
795 if (voice->type != AUDIO_MIXER_TYPE_NONE)
796 continue;
797
798 switch (sound->type)
799 {
800 case AUDIO_MIXER_TYPE_WAV:
801 res = audio_mixer_play_wav(sound, voice, repeat, volume, stop_cb);
802 break;
803 case AUDIO_MIXER_TYPE_OGG:
804 #ifdef HAVE_STB_VORBIS
805 res = audio_mixer_play_ogg(sound, voice, repeat, volume, stop_cb);
806 #endif
807 break;
808 case AUDIO_MIXER_TYPE_MOD:
809 #ifdef HAVE_IBXM
810 res = audio_mixer_play_mod(sound, voice, repeat, volume, stop_cb);
811 #endif
812 break;
813 case AUDIO_MIXER_TYPE_FLAC:
814 #ifdef HAVE_DR_FLAC
815 res = audio_mixer_play_flac(sound, voice, repeat, volume, stop_cb);
816 #endif
817 break;
818 case AUDIO_MIXER_TYPE_MP3:
819 #ifdef HAVE_DR_MP3
820 res = audio_mixer_play_mp3(sound, voice, repeat, volume, stop_cb);
821 #endif
822 break;
823 case AUDIO_MIXER_TYPE_NONE:
824 break;
825 }
826
827 break;
828 }
829
830 if (res)
831 {
832 voice->type = sound->type;
833 voice->repeat = repeat;
834 voice->volume = volume;
835 voice->sound = sound;
836 voice->stop_cb = stop_cb;
837 }
838 else
839 voice = NULL;
840
841 return voice;
842 }
843
audio_mixer_stop(audio_mixer_voice_t * voice)844 void audio_mixer_stop(audio_mixer_voice_t* voice)
845 {
846 audio_mixer_stop_cb_t stop_cb = NULL;
847 audio_mixer_sound_t* sound = NULL;
848
849 if (voice)
850 {
851 stop_cb = voice->stop_cb;
852 sound = voice->sound;
853
854 voice->type = AUDIO_MIXER_TYPE_NONE;
855
856 if (stop_cb)
857 stop_cb(sound, AUDIO_MIXER_SOUND_STOPPED);
858 }
859 }
860
audio_mixer_mix_wav(float * buffer,size_t num_frames,audio_mixer_voice_t * voice,float volume)861 static void audio_mixer_mix_wav(float* buffer, size_t num_frames,
862 audio_mixer_voice_t* voice,
863 float volume)
864 {
865 int i;
866 unsigned buf_free = (unsigned)(num_frames * 2);
867 const audio_mixer_sound_t* sound = voice->sound;
868 unsigned pcm_available = sound->types.wav.frames
869 * 2 - voice->types.wav.position;
870 const float* pcm = sound->types.wav.pcm +
871 voice->types.wav.position;
872
873 again:
874 if (pcm_available < buf_free)
875 {
876 for (i = pcm_available; i != 0; i--)
877 *buffer++ += *pcm++ * volume;
878
879 if (voice->repeat)
880 {
881 if (voice->stop_cb)
882 voice->stop_cb(voice->sound, AUDIO_MIXER_SOUND_REPEATED);
883
884 buf_free -= pcm_available;
885 pcm_available = sound->types.wav.frames * 2;
886 pcm = sound->types.wav.pcm;
887 voice->types.wav.position = 0;
888 goto again;
889 }
890
891 if (voice->stop_cb)
892 voice->stop_cb(voice->sound, AUDIO_MIXER_SOUND_FINISHED);
893
894 voice->type = AUDIO_MIXER_TYPE_NONE;
895 }
896 else
897 {
898 for (i = buf_free; i != 0; i--)
899 *buffer++ += *pcm++ * volume;
900
901 voice->types.wav.position += buf_free;
902 }
903 }
904
905 #ifdef HAVE_STB_VORBIS
audio_mixer_mix_ogg(float * buffer,size_t num_frames,audio_mixer_voice_t * voice,float volume)906 static void audio_mixer_mix_ogg(float* buffer, size_t num_frames,
907 audio_mixer_voice_t* voice,
908 float volume)
909 {
910 int i;
911 float* temp_buffer = NULL;
912 unsigned buf_free = (unsigned)(num_frames * 2);
913 unsigned temp_samples = 0;
914 float* pcm = NULL;
915
916 if (voice->types.ogg.position == voice->types.ogg.samples)
917 {
918 again:
919 if (temp_buffer == NULL)
920 temp_buffer = (float*)malloc(AUDIO_MIXER_TEMP_BUFFER * sizeof(float));
921
922 temp_samples = stb_vorbis_get_samples_float_interleaved(
923 voice->types.ogg.stream, 2, temp_buffer,
924 AUDIO_MIXER_TEMP_BUFFER) * 2;
925
926 if (temp_samples == 0)
927 {
928 if (voice->repeat)
929 {
930 if (voice->stop_cb)
931 voice->stop_cb(voice->sound, AUDIO_MIXER_SOUND_REPEATED);
932
933 stb_vorbis_seek_start(voice->types.ogg.stream);
934 goto again;
935 }
936
937 if (voice->stop_cb)
938 voice->stop_cb(voice->sound, AUDIO_MIXER_SOUND_FINISHED);
939
940 voice->type = AUDIO_MIXER_TYPE_NONE;
941 goto cleanup;
942 }
943
944 if (voice->types.ogg.resampler)
945 {
946 struct resampler_data info;
947 info.data_in = temp_buffer;
948 info.data_out = voice->types.ogg.buffer;
949 info.input_frames = temp_samples / 2;
950 info.output_frames = 0;
951 info.ratio = voice->types.ogg.ratio;
952
953 voice->types.ogg.resampler->process(
954 voice->types.ogg.resampler_data, &info);
955 }
956 else
957 memcpy(voice->types.ogg.buffer, temp_buffer,
958 temp_samples * sizeof(float));
959
960 voice->types.ogg.position = 0;
961 voice->types.ogg.samples = voice->types.ogg.buf_samples;
962 }
963
964 pcm = voice->types.ogg.buffer + voice->types.ogg.position;
965
966 if (voice->types.ogg.samples < buf_free)
967 {
968 for (i = voice->types.ogg.samples; i != 0; i--)
969 *buffer++ += *pcm++ * volume;
970
971 buf_free -= voice->types.ogg.samples;
972 goto again;
973 }
974
975 for (i = buf_free; i != 0; --i )
976 *buffer++ += *pcm++ * volume;
977
978 voice->types.ogg.position += buf_free;
979 voice->types.ogg.samples -= buf_free;
980
981 cleanup:
982 if (temp_buffer != NULL)
983 free(temp_buffer);
984 }
985 #endif
986
987 #ifdef HAVE_IBXM
audio_mixer_mix_mod(float * buffer,size_t num_frames,audio_mixer_voice_t * voice,float volume)988 static void audio_mixer_mix_mod(float* buffer, size_t num_frames,
989 audio_mixer_voice_t* voice,
990 float volume)
991 {
992 int i;
993 float samplef = 0.0f;
994 int samplei = 0;
995 unsigned temp_samples = 0;
996 unsigned buf_free = (unsigned)(num_frames * 2);
997 int* pcm = NULL;
998
999 if (voice->types.mod.position == voice->types.mod.samples)
1000 {
1001 again:
1002 temp_samples = replay_get_audio(
1003 voice->types.mod.stream, voice->types.mod.buffer );
1004
1005 temp_samples *= 2; /* stereo */
1006
1007 if (temp_samples == 0)
1008 {
1009 if (voice->repeat)
1010 {
1011 if (voice->stop_cb)
1012 voice->stop_cb(voice->sound, AUDIO_MIXER_SOUND_REPEATED);
1013
1014 replay_seek( voice->types.mod.stream, 0);
1015 goto again;
1016 }
1017
1018 if (voice->stop_cb)
1019 voice->stop_cb(voice->sound, AUDIO_MIXER_SOUND_FINISHED);
1020
1021 voice->type = AUDIO_MIXER_TYPE_NONE;
1022 return;
1023 }
1024
1025 voice->types.mod.position = 0;
1026 voice->types.mod.samples = temp_samples;
1027 }
1028 pcm = voice->types.mod.buffer + voice->types.mod.position;
1029
1030 if (voice->types.mod.samples < buf_free)
1031 {
1032 for (i = voice->types.mod.samples; i != 0; i--)
1033 {
1034 samplei = *pcm++ * volume;
1035 samplef = (float)((int)samplei + 32768) / 65535.0f;
1036 samplef = samplef * 2.0f - 1.0f;
1037 *buffer++ += samplef;
1038 }
1039
1040 buf_free -= voice->types.mod.samples;
1041 goto again;
1042 }
1043
1044 for (i = buf_free; i != 0; --i )
1045 {
1046 samplei = *pcm++ * volume;
1047 samplef = (float)((int)samplei + 32768) / 65535.0f;
1048 samplef = samplef * 2.0f - 1.0f;
1049 *buffer++ += samplef;
1050 }
1051
1052 voice->types.mod.position += buf_free;
1053 voice->types.mod.samples -= buf_free;
1054 }
1055 #endif
1056
1057 #ifdef HAVE_DR_FLAC
audio_mixer_mix_flac(float * buffer,size_t num_frames,audio_mixer_voice_t * voice,float volume)1058 static void audio_mixer_mix_flac(float* buffer, size_t num_frames,
1059 audio_mixer_voice_t* voice,
1060 float volume)
1061 {
1062 int i;
1063 struct resampler_data info;
1064 float temp_buffer[AUDIO_MIXER_TEMP_BUFFER] = { 0 };
1065 unsigned buf_free = (unsigned)(num_frames * 2);
1066 unsigned temp_samples = 0;
1067 float *pcm = NULL;
1068
1069 if (voice->types.flac.position == voice->types.flac.samples)
1070 {
1071 again:
1072 temp_samples = (unsigned)drflac_read_f32( voice->types.flac.stream, AUDIO_MIXER_TEMP_BUFFER, temp_buffer);
1073 if (temp_samples == 0)
1074 {
1075 if (voice->repeat)
1076 {
1077 if (voice->stop_cb)
1078 voice->stop_cb(voice->sound, AUDIO_MIXER_SOUND_REPEATED);
1079
1080 drflac_seek_to_sample(voice->types.flac.stream,0);
1081 goto again;
1082 }
1083
1084 if (voice->stop_cb)
1085 voice->stop_cb(voice->sound, AUDIO_MIXER_SOUND_FINISHED);
1086
1087 voice->type = AUDIO_MIXER_TYPE_NONE;
1088 return;
1089 }
1090
1091 info.data_in = temp_buffer;
1092 info.data_out = voice->types.flac.buffer;
1093 info.input_frames = temp_samples / 2;
1094 info.output_frames = 0;
1095 info.ratio = voice->types.flac.ratio;
1096
1097 if (voice->types.flac.resampler)
1098 voice->types.flac.resampler->process(
1099 voice->types.flac.resampler_data, &info);
1100 else
1101 memcpy(voice->types.flac.buffer, temp_buffer, temp_samples * sizeof(float));
1102 voice->types.flac.position = 0;
1103 voice->types.flac.samples = voice->types.flac.buf_samples;
1104 }
1105
1106 pcm = voice->types.flac.buffer + voice->types.flac.position;
1107
1108 if (voice->types.flac.samples < buf_free)
1109 {
1110 for (i = voice->types.flac.samples; i != 0; i--)
1111 *buffer++ += *pcm++ * volume;
1112
1113 buf_free -= voice->types.flac.samples;
1114 goto again;
1115 }
1116
1117 for (i = buf_free; i != 0; --i )
1118 *buffer++ += *pcm++ * volume;
1119
1120 voice->types.flac.position += buf_free;
1121 voice->types.flac.samples -= buf_free;
1122 }
1123 #endif
1124
1125 #ifdef HAVE_DR_MP3
audio_mixer_mix_mp3(float * buffer,size_t num_frames,audio_mixer_voice_t * voice,float volume)1126 static void audio_mixer_mix_mp3(float* buffer, size_t num_frames,
1127 audio_mixer_voice_t* voice,
1128 float volume)
1129 {
1130 int i;
1131 struct resampler_data info;
1132 float temp_buffer[AUDIO_MIXER_TEMP_BUFFER] = { 0 };
1133 unsigned buf_free = (unsigned)(num_frames * 2);
1134 unsigned temp_samples = 0;
1135 float* pcm = NULL;
1136
1137 if (voice->types.mp3.position == voice->types.mp3.samples)
1138 {
1139 again:
1140 temp_samples = (unsigned)drmp3_read_f32(
1141 &voice->types.mp3.stream,
1142 AUDIO_MIXER_TEMP_BUFFER / 2, temp_buffer) * 2;
1143
1144 if (temp_samples == 0)
1145 {
1146 if (voice->repeat)
1147 {
1148 if (voice->stop_cb)
1149 voice->stop_cb(voice->sound, AUDIO_MIXER_SOUND_REPEATED);
1150
1151 drmp3_seek_to_frame(&voice->types.mp3.stream,0);
1152 goto again;
1153 }
1154
1155 if (voice->stop_cb)
1156 voice->stop_cb(voice->sound, AUDIO_MIXER_SOUND_FINISHED);
1157
1158 voice->type = AUDIO_MIXER_TYPE_NONE;
1159 return;
1160 }
1161
1162 info.data_in = temp_buffer;
1163 info.data_out = voice->types.mp3.buffer;
1164 info.input_frames = temp_samples / 2;
1165 info.output_frames = 0;
1166 info.ratio = voice->types.mp3.ratio;
1167
1168 if (voice->types.mp3.resampler)
1169 voice->types.mp3.resampler->process(
1170 voice->types.mp3.resampler_data, &info);
1171 else
1172 memcpy(voice->types.mp3.buffer, temp_buffer,
1173 temp_samples * sizeof(float));
1174 voice->types.mp3.position = 0;
1175 voice->types.mp3.samples = voice->types.mp3.buf_samples;
1176 }
1177
1178 pcm = voice->types.mp3.buffer + voice->types.mp3.position;
1179
1180 if (voice->types.mp3.samples < buf_free)
1181 {
1182 for (i = voice->types.mp3.samples; i != 0; i--)
1183 *buffer++ += *pcm++ * volume;
1184
1185 buf_free -= voice->types.mp3.samples;
1186 goto again;
1187 }
1188
1189 for (i = buf_free; i != 0; --i )
1190 *buffer++ += *pcm++ * volume;
1191
1192 voice->types.mp3.position += buf_free;
1193 voice->types.mp3.samples -= buf_free;
1194 }
1195 #endif
1196
audio_mixer_mix(float * buffer,size_t num_frames,float volume_override,bool override)1197 void audio_mixer_mix(float* buffer, size_t num_frames,
1198 float volume_override, bool override)
1199 {
1200 unsigned i;
1201 size_t j = 0;
1202 float* sample = NULL;
1203 audio_mixer_voice_t* voice = s_voices;
1204
1205 for (i = 0; i < AUDIO_MIXER_MAX_VOICES; i++, voice++)
1206 {
1207 float volume = (override) ? volume_override : voice->volume;
1208
1209 switch (voice->type)
1210 {
1211 case AUDIO_MIXER_TYPE_WAV:
1212 audio_mixer_mix_wav(buffer, num_frames, voice, volume);
1213 break;
1214 case AUDIO_MIXER_TYPE_OGG:
1215 #ifdef HAVE_STB_VORBIS
1216 audio_mixer_mix_ogg(buffer, num_frames, voice, volume);
1217 #endif
1218 break;
1219 case AUDIO_MIXER_TYPE_MOD:
1220 #ifdef HAVE_IBXM
1221 audio_mixer_mix_mod(buffer, num_frames, voice, volume);
1222 #endif
1223 break;
1224 case AUDIO_MIXER_TYPE_FLAC:
1225 #ifdef HAVE_DR_FLAC
1226 audio_mixer_mix_flac(buffer, num_frames, voice, volume);
1227 #endif
1228 break;
1229 case AUDIO_MIXER_TYPE_MP3:
1230 #ifdef HAVE_DR_MP3
1231 audio_mixer_mix_mp3(buffer, num_frames, voice, volume);
1232 #endif
1233 break;
1234 case AUDIO_MIXER_TYPE_NONE:
1235 break;
1236 }
1237 }
1238
1239 for (j = 0, sample = buffer; j < num_frames * 2; j++, sample++)
1240 {
1241 if (*sample < -1.0f)
1242 *sample = -1.0f;
1243 else if (*sample > 1.0f)
1244 *sample = 1.0f;
1245 }
1246 }
1247
audio_mixer_voice_get_volume(audio_mixer_voice_t * voice)1248 float audio_mixer_voice_get_volume(audio_mixer_voice_t *voice)
1249 {
1250 if (!voice)
1251 return 0.0f;
1252
1253 return voice->volume;
1254 }
1255
audio_mixer_voice_set_volume(audio_mixer_voice_t * voice,float val)1256 void audio_mixer_voice_set_volume(audio_mixer_voice_t *voice, float val)
1257 {
1258 if (!voice)
1259 return;
1260
1261 voice->volume = val;
1262 }
1263