mirror of
https://github.com/libretro/RetroArch
synced 2025-01-30 12:32:52 +00:00
free audio voices properly
This commit is contained in:
parent
08c1c05f82
commit
f63c11ebaf
@ -183,13 +183,14 @@ struct audio_mixer_voice
|
|||||||
unsigned type;
|
unsigned type;
|
||||||
float volume;
|
float volume;
|
||||||
bool repeat;
|
bool repeat;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* TODO/FIXME - static globals */
|
/* TODO/FIXME - static globals */
|
||||||
static struct audio_mixer_voice s_voices[AUDIO_MIXER_MAX_VOICES] = {0};
|
static struct audio_mixer_voice s_voices[AUDIO_MIXER_MAX_VOICES] = {0};
|
||||||
static unsigned s_rate = 0;
|
static unsigned s_rate = 0;
|
||||||
|
|
||||||
|
static void audio_mixer_release(audio_mixer_voice_t* voice);
|
||||||
|
|
||||||
#ifdef HAVE_RWAV
|
#ifdef HAVE_RWAV
|
||||||
static bool wav_to_float(const rwav_t* wav, float** pcm, size_t samples_out)
|
static bool wav_to_float(const rwav_t* wav, float** pcm, size_t samples_out)
|
||||||
{
|
{
|
||||||
@ -319,7 +320,7 @@ void audio_mixer_done(void)
|
|||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
for (i = 0; i < AUDIO_MIXER_MAX_VOICES; i++)
|
for (i = 0; i < AUDIO_MIXER_MAX_VOICES; i++)
|
||||||
s_voices[i].type = AUDIO_MIXER_TYPE_NONE;
|
audio_mixer_release(&s_voices[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
audio_mixer_sound_t* audio_mixer_load_wav(void *buffer, int32_t size,
|
audio_mixer_sound_t* audio_mixer_load_wav(void *buffer, int32_t size,
|
||||||
@ -562,14 +563,6 @@ static bool audio_mixer_play_ogg(
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* "system" menu sounds may reuse the same voice without freeing anything first, so do that here if needed */
|
|
||||||
if (voice->types.ogg.stream)
|
|
||||||
stb_vorbis_close(voice->types.ogg.stream);
|
|
||||||
if (voice->types.ogg.resampler && voice->types.ogg.resampler_data)
|
|
||||||
voice->types.ogg.resampler->free(voice->types.ogg.resampler_data);
|
|
||||||
if (voice->types.ogg.buffer)
|
|
||||||
memalign_free(voice->types.ogg.buffer);
|
|
||||||
|
|
||||||
voice->types.ogg.resampler = resamp;
|
voice->types.ogg.resampler = resamp;
|
||||||
voice->types.ogg.resampler_data = resampler_data;
|
voice->types.ogg.resampler_data = resampler_data;
|
||||||
voice->types.ogg.buffer = (float*)ogg_buffer;
|
voice->types.ogg.buffer = (float*)ogg_buffer;
|
||||||
@ -585,6 +578,17 @@ error:
|
|||||||
stb_vorbis_close(stb_vorbis);
|
stb_vorbis_close(stb_vorbis);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void audio_mixer_release_ogg(audio_mixer_voice_t* voice)
|
||||||
|
{
|
||||||
|
if (voice->types.ogg.stream)
|
||||||
|
stb_vorbis_close(voice->types.ogg.stream);
|
||||||
|
if (voice->types.ogg.resampler && voice->types.ogg.resampler_data)
|
||||||
|
voice->types.ogg.resampler->free(voice->types.ogg.resampler_data);
|
||||||
|
if (voice->types.ogg.buffer)
|
||||||
|
memalign_free(voice->types.ogg.buffer);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_IBXM
|
#ifdef HAVE_IBXM
|
||||||
@ -642,12 +646,6 @@ static bool audio_mixer_play_mod(
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: stopping and then starting a mod stream will crash here in dispose_replay (ASAN says struct replay is misaligned?) */
|
|
||||||
if (voice->types.mod.stream)
|
|
||||||
dispose_replay(voice->types.mod.stream);
|
|
||||||
if (voice->types.mod.buffer)
|
|
||||||
memalign_free(voice->types.mod.buffer);
|
|
||||||
|
|
||||||
voice->types.mod.buffer = (int*)mod_buffer;
|
voice->types.mod.buffer = (int*)mod_buffer;
|
||||||
voice->types.mod.buf_samples = buf_samples;
|
voice->types.mod.buf_samples = buf_samples;
|
||||||
voice->types.mod.stream = replay;
|
voice->types.mod.stream = replay;
|
||||||
@ -664,6 +662,14 @@ error:
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void audio_mixer_release_mod(audio_mixer_voice_t* voice)
|
||||||
|
{
|
||||||
|
if (voice->types.mod.stream)
|
||||||
|
dispose_replay(voice->types.mod.stream);
|
||||||
|
if (voice->types.mod.buffer)
|
||||||
|
memalign_free(voice->types.mod.buffer);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_DR_FLAC
|
#ifdef HAVE_DR_FLAC
|
||||||
@ -711,13 +717,6 @@ static bool audio_mixer_play_flac(
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (voice->types.flac.stream)
|
|
||||||
drflac_close(voice->types.flac.stream);
|
|
||||||
if (voice->types.flac.resampler && voice->types.flac.resampler_data)
|
|
||||||
voice->types.flac.resampler->free(voice->types.flac.resampler_data);
|
|
||||||
if (voice->types.flac.buffer)
|
|
||||||
memalign_free(voice->types.flac.buffer);
|
|
||||||
|
|
||||||
voice->types.flac.resampler = resamp;
|
voice->types.flac.resampler = resamp;
|
||||||
voice->types.flac.resampler_data = resampler_data;
|
voice->types.flac.resampler_data = resampler_data;
|
||||||
voice->types.flac.buffer = (float*)flac_buffer;
|
voice->types.flac.buffer = (float*)flac_buffer;
|
||||||
@ -733,6 +732,16 @@ error:
|
|||||||
drflac_close(dr_flac);
|
drflac_close(dr_flac);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void audio_mixer_release_flac(audio_mixer_voice_t* voice)
|
||||||
|
{
|
||||||
|
if (voice->types.flac.stream)
|
||||||
|
drflac_close(voice->types.flac.stream);
|
||||||
|
if (voice->types.flac.resampler && voice->types.flac.resampler_data)
|
||||||
|
voice->types.flac.resampler->free(voice->types.flac.resampler_data);
|
||||||
|
if (voice->types.flac.buffer)
|
||||||
|
memalign_free(voice->types.flac.buffer);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_DR_MP3
|
#ifdef HAVE_DR_MP3
|
||||||
@ -751,12 +760,6 @@ static bool audio_mixer_play_mp3(
|
|||||||
const retro_resampler_t* resamp = NULL;
|
const retro_resampler_t* resamp = NULL;
|
||||||
bool res;
|
bool res;
|
||||||
|
|
||||||
if (voice->types.mp3.stream.pData)
|
|
||||||
{
|
|
||||||
drmp3_uninit(&voice->types.mp3.stream);
|
|
||||||
memset(&voice->types.mp3.stream, 0, sizeof(voice->types.mp3.stream));
|
|
||||||
}
|
|
||||||
|
|
||||||
res = drmp3_init_memory(&voice->types.mp3.stream, (const unsigned char*)sound->types.mp3.data, sound->types.mp3.size, NULL);
|
res = drmp3_init_memory(&voice->types.mp3.stream, (const unsigned char*)sound->types.mp3.data, sound->types.mp3.size, NULL);
|
||||||
|
|
||||||
if (!res)
|
if (!res)
|
||||||
@ -789,12 +792,6 @@ static bool audio_mixer_play_mp3(
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* "system" menu sounds may reuse the same voice without freeing anything first, so do that here if needed */
|
|
||||||
if (voice->types.mp3.resampler && voice->types.mp3.resampler_data)
|
|
||||||
voice->types.mp3.resampler->free(voice->types.mp3.resampler_data);
|
|
||||||
if (voice->types.mp3.buffer)
|
|
||||||
memalign_free(voice->types.mp3.buffer);
|
|
||||||
|
|
||||||
voice->types.mp3.resampler = resamp;
|
voice->types.mp3.resampler = resamp;
|
||||||
voice->types.mp3.resampler_data = resampler_data;
|
voice->types.mp3.resampler_data = resampler_data;
|
||||||
voice->types.mp3.buffer = (float*)mp3_buffer;
|
voice->types.mp3.buffer = (float*)mp3_buffer;
|
||||||
@ -809,6 +806,17 @@ error:
|
|||||||
drmp3_uninit(&voice->types.mp3.stream);
|
drmp3_uninit(&voice->types.mp3.stream);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void audio_mixer_release_mp3(audio_mixer_voice_t* voice)
|
||||||
|
{
|
||||||
|
if (voice->types.mp3.resampler && voice->types.mp3.resampler_data)
|
||||||
|
voice->types.mp3.resampler->free(voice->types.mp3.resampler_data);
|
||||||
|
if (voice->types.mp3.buffer)
|
||||||
|
memalign_free(voice->types.mp3.buffer);
|
||||||
|
if (voice->types.mp3.stream.pData)
|
||||||
|
drmp3_uninit(&voice->types.mp3.stream);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
audio_mixer_voice_t* audio_mixer_play(audio_mixer_sound_t* sound,
|
audio_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,
|
|||||||
if (voice->type != AUDIO_MIXER_TYPE_NONE)
|
if (voice->type != AUDIO_MIXER_TYPE_NONE)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
/* claim the voice, also helps with cleanup on error */
|
||||||
|
voice->type = sound->type;
|
||||||
|
|
||||||
switch (sound->type)
|
switch (sound->type)
|
||||||
{
|
{
|
||||||
case AUDIO_MIXER_TYPE_WAV:
|
case AUDIO_MIXER_TYPE_WAV:
|
||||||
@ -866,18 +877,55 @@ audio_mixer_voice_t* audio_mixer_play(audio_mixer_sound_t* sound,
|
|||||||
|
|
||||||
if (res)
|
if (res)
|
||||||
{
|
{
|
||||||
voice->type = sound->type;
|
|
||||||
voice->repeat = repeat;
|
voice->repeat = repeat;
|
||||||
voice->volume = volume;
|
voice->volume = volume;
|
||||||
voice->sound = sound;
|
voice->sound = sound;
|
||||||
voice->stop_cb = stop_cb;
|
voice->stop_cb = stop_cb;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
audio_mixer_release(voice);
|
||||||
voice = NULL;
|
voice = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return voice;
|
return voice;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void audio_mixer_release(audio_mixer_voice_t* voice)
|
||||||
|
{
|
||||||
|
if (!voice)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (voice->type)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_STB_VORBIS
|
||||||
|
case AUDIO_MIXER_TYPE_OGG:
|
||||||
|
audio_mixer_release_ogg(voice);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_IBXM
|
||||||
|
case AUDIO_MIXER_TYPE_MOD:
|
||||||
|
audio_mixer_release_mod(voice);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_DR_FLAC
|
||||||
|
case AUDIO_MIXER_TYPE_FLAC:
|
||||||
|
audio_mixer_release_flac(voice);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_DR_MP3
|
||||||
|
case AUDIO_MIXER_TYPE_MP3:
|
||||||
|
audio_mixer_release_mp3(voice);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&voice->types, 0, sizeof(voice->types));
|
||||||
|
voice->type = AUDIO_MIXER_TYPE_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
void audio_mixer_stop(audio_mixer_voice_t* voice)
|
void audio_mixer_stop(audio_mixer_voice_t* voice)
|
||||||
{
|
{
|
||||||
audio_mixer_stop_cb_t stop_cb = NULL;
|
audio_mixer_stop_cb_t stop_cb = NULL;
|
||||||
@ -888,7 +936,7 @@ void audio_mixer_stop(audio_mixer_voice_t* voice)
|
|||||||
stop_cb = voice->stop_cb;
|
stop_cb = voice->stop_cb;
|
||||||
sound = voice->sound;
|
sound = voice->sound;
|
||||||
|
|
||||||
voice->type = AUDIO_MIXER_TYPE_NONE;
|
audio_mixer_release(voice);
|
||||||
|
|
||||||
if (stop_cb)
|
if (stop_cb)
|
||||||
stop_cb(sound, AUDIO_MIXER_SOUND_STOPPED);
|
stop_cb(sound, AUDIO_MIXER_SOUND_STOPPED);
|
||||||
@ -928,7 +976,7 @@ again:
|
|||||||
if (voice->stop_cb)
|
if (voice->stop_cb)
|
||||||
voice->stop_cb(voice->sound, AUDIO_MIXER_SOUND_FINISHED);
|
voice->stop_cb(voice->sound, AUDIO_MIXER_SOUND_FINISHED);
|
||||||
|
|
||||||
voice->type = AUDIO_MIXER_TYPE_NONE;
|
audio_mixer_release(voice);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -974,7 +1022,7 @@ again:
|
|||||||
if (voice->stop_cb)
|
if (voice->stop_cb)
|
||||||
voice->stop_cb(voice->sound, AUDIO_MIXER_SOUND_FINISHED);
|
voice->stop_cb(voice->sound, AUDIO_MIXER_SOUND_FINISHED);
|
||||||
|
|
||||||
voice->type = AUDIO_MIXER_TYPE_NONE;
|
audio_mixer_release(voice);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1052,7 +1100,7 @@ again:
|
|||||||
if (voice->stop_cb)
|
if (voice->stop_cb)
|
||||||
voice->stop_cb(voice->sound, AUDIO_MIXER_SOUND_FINISHED);
|
voice->stop_cb(voice->sound, AUDIO_MIXER_SOUND_FINISHED);
|
||||||
|
|
||||||
voice->type = AUDIO_MIXER_TYPE_NONE;
|
audio_mixer_release(voice);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1116,7 +1164,7 @@ again:
|
|||||||
if (voice->stop_cb)
|
if (voice->stop_cb)
|
||||||
voice->stop_cb(voice->sound, AUDIO_MIXER_SOUND_FINISHED);
|
voice->stop_cb(voice->sound, AUDIO_MIXER_SOUND_FINISHED);
|
||||||
|
|
||||||
voice->type = AUDIO_MIXER_TYPE_NONE;
|
audio_mixer_release(voice);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1187,7 +1235,7 @@ again:
|
|||||||
if (voice->stop_cb)
|
if (voice->stop_cb)
|
||||||
voice->stop_cb(voice->sound, AUDIO_MIXER_SOUND_FINISHED);
|
voice->stop_cb(voice->sound, AUDIO_MIXER_SOUND_FINISHED);
|
||||||
|
|
||||||
voice->type = AUDIO_MIXER_TYPE_NONE;
|
audio_mixer_release(voice);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user