@@ -117,7 +117,7 @@ struct audio_mixer_sound
117117
118118struct audio_mixer_voice
119119{
120- union
120+ struct
121121 {
122122 struct
123123 {
@@ -183,13 +183,14 @@ struct audio_mixer_voice
183183 unsigned type ;
184184 float volume ;
185185 bool repeat ;
186-
187186};
188187
189188/* TODO/FIXME - static globals */
190189static struct audio_mixer_voice s_voices [AUDIO_MIXER_MAX_VOICES ] = {0 };
191190static unsigned s_rate = 0 ;
192191
192+ static void audio_mixer_release (audio_mixer_voice_t * voice );
193+
193194#ifdef HAVE_RWAV
194195static bool wav_to_float (const rwav_t * wav , float * * pcm , size_t samples_out )
195196{
@@ -319,7 +320,7 @@ void audio_mixer_done(void)
319320 unsigned i ;
320321
321322 for (i = 0 ; i < AUDIO_MIXER_MAX_VOICES ; i ++ )
322- s_voices [i ]. type = AUDIO_MIXER_TYPE_NONE ;
323+ audio_mixer_release ( & s_voices [i ]) ;
323324}
324325
325326audio_mixer_sound_t * audio_mixer_load_wav (void * buffer , int32_t size ,
@@ -562,14 +563,6 @@ static bool audio_mixer_play_ogg(
562563 goto error ;
563564 }
564565
565- /* "system" menu sounds may reuse the same voice without freeing anything first, so do that here if needed */
566- if (voice -> types .ogg .stream )
567- stb_vorbis_close (voice -> types .ogg .stream );
568- if (voice -> types .ogg .resampler && voice -> types .ogg .resampler_data )
569- voice -> types .ogg .resampler -> free (voice -> types .ogg .resampler_data );
570- if (voice -> types .ogg .buffer )
571- memalign_free (voice -> types .ogg .buffer );
572-
573566 voice -> types .ogg .resampler = resamp ;
574567 voice -> types .ogg .resampler_data = resampler_data ;
575568 voice -> types .ogg .buffer = (float * )ogg_buffer ;
@@ -585,6 +578,17 @@ static bool audio_mixer_play_ogg(
585578 stb_vorbis_close (stb_vorbis );
586579 return false;
587580}
581+
582+ static void audio_mixer_release_ogg (audio_mixer_voice_t * voice )
583+ {
584+ if (voice -> types .ogg .stream )
585+ stb_vorbis_close (voice -> types .ogg .stream );
586+ if (voice -> types .ogg .resampler && voice -> types .ogg .resampler_data )
587+ voice -> types .ogg .resampler -> free (voice -> types .ogg .resampler_data );
588+ if (voice -> types .ogg .buffer )
589+ memalign_free (voice -> types .ogg .buffer );
590+ }
591+
588592#endif
589593
590594#ifdef HAVE_IBXM
@@ -642,12 +646,6 @@ static bool audio_mixer_play_mod(
642646 goto error ;
643647 }
644648
645- /* FIXME: stopping and then starting a mod stream will crash here in dispose_replay (ASAN says struct replay is misaligned?) */
646- if (voice -> types .mod .stream )
647- dispose_replay (voice -> types .mod .stream );
648- if (voice -> types .mod .buffer )
649- memalign_free (voice -> types .mod .buffer );
650-
651649 voice -> types .mod .buffer = (int * )mod_buffer ;
652650 voice -> types .mod .buf_samples = buf_samples ;
653651 voice -> types .mod .stream = replay ;
@@ -664,6 +662,14 @@ static bool audio_mixer_play_mod(
664662 return false;
665663
666664}
665+
666+ static void audio_mixer_release_mod (audio_mixer_voice_t * voice )
667+ {
668+ if (voice -> types .mod .stream )
669+ dispose_replay (voice -> types .mod .stream );
670+ if (voice -> types .mod .buffer )
671+ memalign_free (voice -> types .mod .buffer );
672+ }
667673#endif
668674
669675#ifdef HAVE_DR_FLAC
@@ -711,13 +717,6 @@ static bool audio_mixer_play_flac(
711717 goto error ;
712718 }
713719
714- if (voice -> types .flac .stream )
715- drflac_close (voice -> types .flac .stream );
716- if (voice -> types .flac .resampler && voice -> types .flac .resampler_data )
717- voice -> types .flac .resampler -> free (voice -> types .flac .resampler_data );
718- if (voice -> types .flac .buffer )
719- memalign_free (voice -> types .flac .buffer );
720-
721720 voice -> types .flac .resampler = resamp ;
722721 voice -> types .flac .resampler_data = resampler_data ;
723722 voice -> types .flac .buffer = (float * )flac_buffer ;
@@ -733,6 +732,16 @@ static bool audio_mixer_play_flac(
733732 drflac_close (dr_flac );
734733 return false;
735734}
735+
736+ static void audio_mixer_release_flac (audio_mixer_voice_t * voice )
737+ {
738+ if (voice -> types .flac .stream )
739+ drflac_close (voice -> types .flac .stream );
740+ if (voice -> types .flac .resampler && voice -> types .flac .resampler_data )
741+ voice -> types .flac .resampler -> free (voice -> types .flac .resampler_data );
742+ if (voice -> types .flac .buffer )
743+ memalign_free (voice -> types .flac .buffer );
744+ }
736745#endif
737746
738747#ifdef HAVE_DR_MP3
@@ -751,12 +760,6 @@ static bool audio_mixer_play_mp3(
751760 const retro_resampler_t * resamp = NULL ;
752761 bool res ;
753762
754- if (voice -> types .mp3 .stream .pData )
755- {
756- drmp3_uninit (& voice -> types .mp3 .stream );
757- memset (& voice -> types .mp3 .stream , 0 , sizeof (voice -> types .mp3 .stream ));
758- }
759-
760763 res = drmp3_init_memory (& voice -> types .mp3 .stream , (const unsigned char * )sound -> types .mp3 .data , sound -> types .mp3 .size , NULL );
761764
762765 if (!res )
@@ -789,12 +792,6 @@ static bool audio_mixer_play_mp3(
789792 goto error ;
790793 }
791794
792- /* "system" menu sounds may reuse the same voice without freeing anything first, so do that here if needed */
793- if (voice -> types .mp3 .resampler && voice -> types .mp3 .resampler_data )
794- voice -> types .mp3 .resampler -> free (voice -> types .mp3 .resampler_data );
795- if (voice -> types .mp3 .buffer )
796- memalign_free (voice -> types .mp3 .buffer );
797-
798795 voice -> types .mp3 .resampler = resamp ;
799796 voice -> types .mp3 .resampler_data = resampler_data ;
800797 voice -> types .mp3 .buffer = (float * )mp3_buffer ;
@@ -809,6 +806,17 @@ static bool audio_mixer_play_mp3(
809806 drmp3_uninit (& voice -> types .mp3 .stream );
810807 return false;
811808}
809+
810+ static void audio_mixer_release_mp3 (audio_mixer_voice_t * voice )
811+ {
812+ if (voice -> types .mp3 .resampler && voice -> types .mp3 .resampler_data )
813+ voice -> types .mp3 .resampler -> free (voice -> types .mp3 .resampler_data );
814+ if (voice -> types .mp3 .buffer )
815+ memalign_free (voice -> types .mp3 .buffer );
816+ if (voice -> types .mp3 .stream .pData )
817+ drmp3_uninit (& voice -> types .mp3 .stream );
818+ }
819+
812820#endif
813821
814822audio_mixer_voice_t * audio_mixer_play (audio_mixer_sound_t * sound ,
@@ -829,6 +837,9 @@ audio_mixer_voice_t* audio_mixer_play(audio_mixer_sound_t* sound,
829837 if (voice -> type != AUDIO_MIXER_TYPE_NONE )
830838 continue ;
831839
840+ /* claim the voice, also helps with cleanup on error */
841+ voice -> type = sound -> type ;
842+
832843 switch (sound -> type )
833844 {
834845 case AUDIO_MIXER_TYPE_WAV :
@@ -866,18 +877,55 @@ audio_mixer_voice_t* audio_mixer_play(audio_mixer_sound_t* sound,
866877
867878 if (res )
868879 {
869- voice -> type = sound -> type ;
870880 voice -> repeat = repeat ;
871881 voice -> volume = volume ;
872882 voice -> sound = sound ;
873883 voice -> stop_cb = stop_cb ;
874884 }
875885 else
886+ {
887+ audio_mixer_release (voice );
876888 voice = NULL ;
889+ }
877890
878891 return voice ;
879892}
880893
894+ static void audio_mixer_release (audio_mixer_voice_t * voice )
895+ {
896+ if (!voice )
897+ return ;
898+
899+ switch (voice -> type )
900+ {
901+ #ifdef HAVE_STB_VORBIS
902+ case AUDIO_MIXER_TYPE_OGG :
903+ audio_mixer_release_ogg (voice );
904+ break ;
905+ #endif
906+ #ifdef HAVE_IBXM
907+ case AUDIO_MIXER_TYPE_MOD :
908+ audio_mixer_release_mod (voice );
909+ break ;
910+ #endif
911+ #ifdef HAVE_DR_FLAC
912+ case AUDIO_MIXER_TYPE_FLAC :
913+ audio_mixer_release_flac (voice );
914+ break ;
915+ #endif
916+ #ifdef HAVE_DR_MP3
917+ case AUDIO_MIXER_TYPE_MP3 :
918+ audio_mixer_release_mp3 (voice );
919+ break ;
920+ #endif
921+ default :
922+ break ;
923+ }
924+
925+ memset (& voice -> types , 0 , sizeof (voice -> types ));
926+ voice -> type = AUDIO_MIXER_TYPE_NONE ;
927+ }
928+
881929void audio_mixer_stop (audio_mixer_voice_t * voice )
882930{
883931 audio_mixer_stop_cb_t stop_cb = NULL ;
@@ -888,7 +936,7 @@ void audio_mixer_stop(audio_mixer_voice_t* voice)
888936 stop_cb = voice -> stop_cb ;
889937 sound = voice -> sound ;
890938
891- voice -> type = AUDIO_MIXER_TYPE_NONE ;
939+ audio_mixer_release ( voice ) ;
892940
893941 if (stop_cb )
894942 stop_cb (sound , AUDIO_MIXER_SOUND_STOPPED );
@@ -928,7 +976,7 @@ static void audio_mixer_mix_wav(float* buffer, size_t num_frames,
928976 if (voice -> stop_cb )
929977 voice -> stop_cb (voice -> sound , AUDIO_MIXER_SOUND_FINISHED );
930978
931- voice -> type = AUDIO_MIXER_TYPE_NONE ;
979+ audio_mixer_release ( voice ) ;
932980 }
933981 else
934982 {
@@ -974,7 +1022,7 @@ static void audio_mixer_mix_ogg(float* buffer, size_t num_frames,
9741022 if (voice -> stop_cb )
9751023 voice -> stop_cb (voice -> sound , AUDIO_MIXER_SOUND_FINISHED );
9761024
977- voice -> type = AUDIO_MIXER_TYPE_NONE ;
1025+ audio_mixer_release ( voice ) ;
9781026 goto cleanup ;
9791027 }
9801028
@@ -1052,7 +1100,7 @@ static void audio_mixer_mix_mod(float* buffer, size_t num_frames,
10521100 if (voice -> stop_cb )
10531101 voice -> stop_cb (voice -> sound , AUDIO_MIXER_SOUND_FINISHED );
10541102
1055- voice -> type = AUDIO_MIXER_TYPE_NONE ;
1103+ audio_mixer_release ( voice ) ;
10561104 return ;
10571105 }
10581106
@@ -1116,7 +1164,7 @@ static void audio_mixer_mix_flac(float* buffer, size_t num_frames,
11161164 if (voice -> stop_cb )
11171165 voice -> stop_cb (voice -> sound , AUDIO_MIXER_SOUND_FINISHED );
11181166
1119- voice -> type = AUDIO_MIXER_TYPE_NONE ;
1167+ audio_mixer_release ( voice ) ;
11201168 return ;
11211169 }
11221170
@@ -1187,7 +1235,7 @@ static void audio_mixer_mix_mp3(float* buffer, size_t num_frames,
11871235 if (voice -> stop_cb )
11881236 voice -> stop_cb (voice -> sound , AUDIO_MIXER_SOUND_FINISHED );
11891237
1190- voice -> type = AUDIO_MIXER_TYPE_NONE ;
1238+ audio_mixer_release ( voice ) ;
11911239 return ;
11921240 }
11931241
0 commit comments