Fix menu sounds (audio mixing) when using the 'sinc' resampler with quality lower than 'normal'

This commit is contained in:
jdgleaver 2021-09-01 14:36:06 +01:00
parent 9ea6f15c1d
commit 547f04b894
6 changed files with 84 additions and 30 deletions

View File

@ -114,7 +114,8 @@ void audio_mix_free_chunk(audio_chunk_t *chunk)
free(chunk); free(chunk);
} }
audio_chunk_t* audio_mix_load_wav_file(const char *path, int sample_rate) audio_chunk_t* audio_mix_load_wav_file(const char *path, int sample_rate,
const char *resampler_ident, enum resampler_quality quality)
{ {
#ifdef HAVE_RWAV #ifdef HAVE_RWAV
int sample_size; int sample_size;
@ -233,8 +234,8 @@ audio_chunk_t* audio_mix_load_wav_file(const char *path, int sample_rate)
retro_resampler_realloc(&chunk->resampler_data, retro_resampler_realloc(&chunk->resampler_data,
&chunk->resampler, &chunk->resampler,
NULL, resampler_ident,
RESAMPLER_QUALITY_DONTCARE, quality,
chunk->ratio); chunk->ratio);
if (chunk->resampler && chunk->resampler_data) if (chunk->resampler && chunk->resampler_data)

View File

@ -267,15 +267,16 @@ static bool wav_to_float(const rwav_t* wav, float** pcm, size_t samples_out)
} }
static bool one_shot_resample(const float* in, size_t samples_in, static bool one_shot_resample(const float* in, size_t samples_in,
unsigned rate, float** out, size_t* samples_out) unsigned rate, const char *resampler_ident, enum resampler_quality quality,
float** out, size_t* samples_out)
{ {
struct resampler_data info; struct resampler_data info;
void* data = NULL; void* data = NULL;
const retro_resampler_t* resampler = NULL; const retro_resampler_t* resampler = NULL;
float ratio = (double)s_rate / (double)rate; float ratio = (double)s_rate / (double)rate;
if (!retro_resampler_realloc(&data, &resampler, NULL, if (!retro_resampler_realloc(&data, &resampler,
RESAMPLER_QUALITY_DONTCARE, ratio)) resampler_ident, quality, ratio))
return false; return false;
/* /*
@ -323,7 +324,8 @@ void audio_mixer_done(void)
s_voices[i].type = AUDIO_MIXER_TYPE_NONE; s_voices[i].type = AUDIO_MIXER_TYPE_NONE;
} }
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,
const char *resampler_ident, enum resampler_quality quality)
{ {
#ifdef HAVE_RWAV #ifdef HAVE_RWAV
/* WAV data */ /* WAV data */
@ -353,8 +355,9 @@ audio_mixer_sound_t* audio_mixer_load_wav(void *buffer, int32_t size)
{ {
float* resampled = NULL; float* resampled = NULL;
if (!one_shot_resample(pcm, samples, if (!one_shot_resample(pcm, samples, wav.samplerate,
wav.samplerate, &resampled, &samples)) resampler_ident, quality,
&resampled, &samples))
return NULL; return NULL;
memalign_free((void*)pcm); memalign_free((void*)pcm);
@ -514,6 +517,8 @@ static bool audio_mixer_play_ogg(
audio_mixer_sound_t* sound, audio_mixer_sound_t* sound,
audio_mixer_voice_t* voice, audio_mixer_voice_t* voice,
bool repeat, float volume, bool repeat, float volume,
const char *resampler_ident,
enum resampler_quality quality,
audio_mixer_stop_cb_t stop_cb) audio_mixer_stop_cb_t stop_cb)
{ {
stb_vorbis_info info; stb_vorbis_info info;
@ -537,7 +542,7 @@ static bool audio_mixer_play_ogg(
ratio = (double)s_rate / (double)info.sample_rate; ratio = (double)s_rate / (double)info.sample_rate;
if (!retro_resampler_realloc(&resampler_data, if (!retro_resampler_realloc(&resampler_data,
&resamp, NULL, RESAMPLER_QUALITY_DONTCARE, &resamp, resampler_ident, quality,
ratio)) ratio))
goto error; goto error;
} }
@ -662,6 +667,8 @@ static bool audio_mixer_play_flac(
audio_mixer_sound_t* sound, audio_mixer_sound_t* sound,
audio_mixer_voice_t* voice, audio_mixer_voice_t* voice,
bool repeat, float volume, bool repeat, float volume,
const char *resampler_ident,
enum resampler_quality quality,
audio_mixer_stop_cb_t stop_cb) audio_mixer_stop_cb_t stop_cb)
{ {
float ratio = 1.0f; float ratio = 1.0f;
@ -678,7 +685,7 @@ static bool audio_mixer_play_flac(
ratio = (double)s_rate / (double)(dr_flac->sampleRate); ratio = (double)s_rate / (double)(dr_flac->sampleRate);
if (!retro_resampler_realloc(&resampler_data, if (!retro_resampler_realloc(&resampler_data,
&resamp, NULL, RESAMPLER_QUALITY_DONTCARE, &resamp, resampler_ident, quality,
ratio)) ratio))
goto error; goto error;
} }
@ -723,6 +730,8 @@ static bool audio_mixer_play_mp3(
audio_mixer_sound_t* sound, audio_mixer_sound_t* sound,
audio_mixer_voice_t* voice, audio_mixer_voice_t* voice,
bool repeat, float volume, bool repeat, float volume,
const char *resampler_ident,
enum resampler_quality quality,
audio_mixer_stop_cb_t stop_cb) audio_mixer_stop_cb_t stop_cb)
{ {
float ratio = 1.0f; float ratio = 1.0f;
@ -748,7 +757,7 @@ static bool audio_mixer_play_mp3(
ratio = (double)s_rate / (double)(voice->types.mp3.stream.sampleRate); ratio = (double)s_rate / (double)(voice->types.mp3.stream.sampleRate);
if (!retro_resampler_realloc(&resampler_data, if (!retro_resampler_realloc(&resampler_data,
&resamp, NULL, RESAMPLER_QUALITY_DONTCARE, &resamp, resampler_ident, quality,
ratio)) ratio))
goto error; goto error;
} }
@ -786,8 +795,11 @@ error:
} }
#endif #endif
audio_mixer_voice_t* audio_mixer_play(audio_mixer_sound_t* sound, bool repeat, audio_mixer_voice_t* audio_mixer_play(audio_mixer_sound_t* sound,
float volume, audio_mixer_stop_cb_t stop_cb) bool repeat, float volume,
const char *resampler_ident,
enum resampler_quality quality,
audio_mixer_stop_cb_t stop_cb)
{ {
unsigned i; unsigned i;
bool res = false; bool res = false;
@ -808,7 +820,8 @@ audio_mixer_voice_t* audio_mixer_play(audio_mixer_sound_t* sound, bool repeat,
break; break;
case AUDIO_MIXER_TYPE_OGG: case AUDIO_MIXER_TYPE_OGG:
#ifdef HAVE_STB_VORBIS #ifdef HAVE_STB_VORBIS
res = audio_mixer_play_ogg(sound, voice, repeat, volume, stop_cb); res = audio_mixer_play_ogg(sound, voice, repeat, volume,
resampler_ident, quality, stop_cb);
#endif #endif
break; break;
case AUDIO_MIXER_TYPE_MOD: case AUDIO_MIXER_TYPE_MOD:
@ -818,12 +831,14 @@ audio_mixer_voice_t* audio_mixer_play(audio_mixer_sound_t* sound, bool repeat,
break; break;
case AUDIO_MIXER_TYPE_FLAC: case AUDIO_MIXER_TYPE_FLAC:
#ifdef HAVE_DR_FLAC #ifdef HAVE_DR_FLAC
res = audio_mixer_play_flac(sound, voice, repeat, volume, stop_cb); res = audio_mixer_play_flac(sound, voice, repeat, volume,
resampler_ident, quality, stop_cb);
#endif #endif
break; break;
case AUDIO_MIXER_TYPE_MP3: case AUDIO_MIXER_TYPE_MP3:
#ifdef HAVE_DR_MP3 #ifdef HAVE_DR_MP3
res = audio_mixer_play_mp3(sound, voice, repeat, volume, stop_cb); res = audio_mixer_play_mp3(sound, voice, repeat, volume,
resampler_ident, quality, stop_cb);
#endif #endif
break; break;
case AUDIO_MIXER_TYPE_NONE: case AUDIO_MIXER_TYPE_NONE:

View File

@ -68,7 +68,8 @@ void audio_mix_volume_C(float *dst, const float *src, float vol, size_t samples)
void audio_mix_free_chunk(audio_chunk_t *chunk); void audio_mix_free_chunk(audio_chunk_t *chunk);
audio_chunk_t* audio_mix_load_wav_file(const char *path, int sample_rate); audio_chunk_t* audio_mix_load_wav_file(const char *path, int sample_rate,
const char *resampler_ident, enum resampler_quality quality);
size_t audio_mix_get_chunk_num_samples(audio_chunk_t *chunk); size_t audio_mix_get_chunk_num_samples(audio_chunk_t *chunk);

View File

@ -34,6 +34,8 @@
#include <boolean.h> #include <boolean.h>
#include <retro_common_api.h> #include <retro_common_api.h>
#include <audio/audio_resampler.h>
RETRO_BEGIN_DECLS RETRO_BEGIN_DECLS
enum audio_mixer_type enum audio_mixer_type
@ -60,7 +62,8 @@ void audio_mixer_init(unsigned rate);
void audio_mixer_done(void); void audio_mixer_done(void);
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,
const char *resampler_ident, enum resampler_quality quality);
audio_mixer_sound_t* audio_mixer_load_ogg(void *buffer, int32_t size); audio_mixer_sound_t* audio_mixer_load_ogg(void *buffer, int32_t size);
audio_mixer_sound_t* audio_mixer_load_mod(void *buffer, int32_t size); audio_mixer_sound_t* audio_mixer_load_mod(void *buffer, int32_t size);
audio_mixer_sound_t* audio_mixer_load_flac(void *buffer, int32_t size); audio_mixer_sound_t* audio_mixer_load_flac(void *buffer, int32_t size);
@ -69,7 +72,10 @@ audio_mixer_sound_t* audio_mixer_load_mp3(void *buffer, int32_t size);
void audio_mixer_destroy(audio_mixer_sound_t* sound); void audio_mixer_destroy(audio_mixer_sound_t* sound);
audio_mixer_voice_t* audio_mixer_play(audio_mixer_sound_t* sound, audio_mixer_voice_t* audio_mixer_play(audio_mixer_sound_t* sound,
bool repeat, float volume, audio_mixer_stop_cb_t stop_cb); bool repeat, float volume,
const char *resampler_ident,
enum resampler_quality quality,
audio_mixer_stop_cb_t stop_cb);
void audio_mixer_stop(audio_mixer_voice_t* voice); void audio_mixer_stop(audio_mixer_voice_t* voice);

View File

@ -24939,6 +24939,8 @@ static void audio_driver_deinit_resampler(struct rarch_state *p_rarch)
p_rarch->audio_driver_resampler->free(p_rarch->audio_driver_resampler_data); p_rarch->audio_driver_resampler->free(p_rarch->audio_driver_resampler_data);
p_rarch->audio_driver_resampler = NULL; p_rarch->audio_driver_resampler = NULL;
p_rarch->audio_driver_resampler_data = NULL; p_rarch->audio_driver_resampler_data = NULL;
p_rarch->audio_driver_resampler_ident[0] = '\0';
p_rarch->audio_driver_resampler_quality = RESAMPLER_QUALITY_DONTCARE;
} }
@ -25195,15 +25197,25 @@ static bool audio_driver_init_internal(
p_rarch->audio_source_ratio_current = p_rarch->audio_source_ratio_current =
(double)settings->uints.audio_output_sample_rate / p_rarch->audio_driver_input; (double)settings->uints.audio_output_sample_rate / p_rarch->audio_driver_input;
if (!string_is_empty(settings->arrays.audio_resampler))
strlcpy(p_rarch->audio_driver_resampler_ident,
settings->arrays.audio_resampler,
sizeof(p_rarch->audio_driver_resampler_ident));
else
p_rarch->audio_driver_resampler_ident[0] = '\0';
p_rarch->audio_driver_resampler_quality =
audio_driver_get_resampler_quality(settings);
if (!retro_resampler_realloc( if (!retro_resampler_realloc(
&p_rarch->audio_driver_resampler_data, &p_rarch->audio_driver_resampler_data,
&p_rarch->audio_driver_resampler, &p_rarch->audio_driver_resampler,
settings->arrays.audio_resampler, p_rarch->audio_driver_resampler_ident,
audio_driver_get_resampler_quality(settings), p_rarch->audio_driver_resampler_quality,
p_rarch->audio_source_ratio_original)) p_rarch->audio_source_ratio_original))
{ {
RARCH_ERR("Failed to initialize resampler \"%s\".\n", RARCH_ERR("Failed to initialize resampler \"%s\".\n",
settings->arrays.audio_resampler); p_rarch->audio_driver_resampler_ident);
p_rarch->audio_driver_active = false; p_rarch->audio_driver_active = false;
} }
@ -25932,6 +25944,13 @@ bool audio_driver_mixer_add_stream(audio_mixer_stream_params_t *params)
{ {
case AUDIO_MIXER_SLOT_SELECTION_MANUAL: case AUDIO_MIXER_SLOT_SELECTION_MANUAL:
free_slot = params->slot_selection_idx; free_slot = params->slot_selection_idx;
/* If we are using a manually specified
* slot, must free any existing stream
* before assigning the new one */
audio_driver_mixer_stop_stream(free_slot);
audio_driver_mixer_remove_stream(free_slot);
break; break;
case AUDIO_MIXER_SLOT_SELECTION_AUTOMATIC: case AUDIO_MIXER_SLOT_SELECTION_AUTOMATIC:
default: default:
@ -25954,7 +25973,9 @@ bool audio_driver_mixer_add_stream(audio_mixer_stream_params_t *params)
switch (params->type) switch (params->type)
{ {
case AUDIO_MIXER_TYPE_WAV: case AUDIO_MIXER_TYPE_WAV:
handle = audio_mixer_load_wav(buf, (int32_t)params->bufsize); handle = audio_mixer_load_wav(buf, (int32_t)params->bufsize,
p_rarch->audio_driver_resampler_ident,
p_rarch->audio_driver_resampler_quality);
/* WAV is a special case - input buffer is not /* WAV is a special case - input buffer is not
* free()'d when sound playback is complete (it is * free()'d when sound playback is complete (it is
* converted to a PCM buffer, which is free()'d instead), * converted to a PCM buffer, which is free()'d instead),
@ -25992,14 +26013,20 @@ bool audio_driver_mixer_add_stream(audio_mixer_stream_params_t *params)
{ {
case AUDIO_STREAM_STATE_PLAYING_LOOPED: case AUDIO_STREAM_STATE_PLAYING_LOOPED:
looped = true; looped = true;
voice = audio_mixer_play(handle, looped, params->volume, stop_cb); voice = audio_mixer_play(handle, looped, params->volume,
p_rarch->audio_driver_resampler_ident,
p_rarch->audio_driver_resampler_quality, stop_cb);
break; break;
case AUDIO_STREAM_STATE_PLAYING: case AUDIO_STREAM_STATE_PLAYING:
voice = audio_mixer_play(handle, looped, params->volume, stop_cb); voice = audio_mixer_play(handle, looped, params->volume,
p_rarch->audio_driver_resampler_ident,
p_rarch->audio_driver_resampler_quality, stop_cb);
break; break;
case AUDIO_STREAM_STATE_PLAYING_SEQUENTIAL: case AUDIO_STREAM_STATE_PLAYING_SEQUENTIAL:
stop_cb = audio_mixer_play_stop_sequential_cb; stop_cb = audio_mixer_play_stop_sequential_cb;
voice = audio_mixer_play(handle, looped, params->volume, stop_cb); voice = audio_mixer_play(handle, looped, params->volume,
p_rarch->audio_driver_resampler_ident,
p_rarch->audio_driver_resampler_quality, stop_cb);
break; break;
default: default:
break; break;
@ -26043,7 +26070,9 @@ static void audio_driver_mixer_play_stream_internal(
p_rarch->audio_mixer_streams[i].voice = p_rarch->audio_mixer_streams[i].voice =
audio_mixer_play(p_rarch->audio_mixer_streams[i].handle, audio_mixer_play(p_rarch->audio_mixer_streams[i].handle,
(type == AUDIO_STREAM_STATE_PLAYING_LOOPED) ? true : false, (type == AUDIO_STREAM_STATE_PLAYING_LOOPED) ? true : false,
1.0f, p_rarch->audio_mixer_streams[i].stop_cb); 1.0f, p_rarch->audio_driver_resampler_ident,
p_rarch->audio_driver_resampler_quality,
p_rarch->audio_mixer_streams[i].stop_cb);
p_rarch->audio_mixer_streams[i].state = (enum audio_mixer_state)type; p_rarch->audio_mixer_streams[i].state = (enum audio_mixer_state)type;
break; break;
case AUDIO_STREAM_STATE_PLAYING: case AUDIO_STREAM_STATE_PLAYING:

View File

@ -1713,6 +1713,7 @@ struct rarch_state
#ifdef HAVE_OVERLAY #ifdef HAVE_OVERLAY
enum overlay_visibility *overlay_visibility; enum overlay_visibility *overlay_visibility;
#endif #endif
enum resampler_quality audio_driver_resampler_quality;
#ifdef HAVE_MENU #ifdef HAVE_MENU
menu_input_pointer_hw_state_t menu_input_pointer_hw_state; menu_input_pointer_hw_state_t menu_input_pointer_hw_state;
@ -1775,6 +1776,7 @@ struct rarch_state
char current_savefile_dir[PATH_MAX_LENGTH]; char current_savefile_dir[PATH_MAX_LENGTH];
char current_savestate_dir[PATH_MAX_LENGTH]; char current_savestate_dir[PATH_MAX_LENGTH];
char dir_savestate[PATH_MAX_LENGTH]; char dir_savestate[PATH_MAX_LENGTH];
char audio_driver_resampler_ident[64];
#ifdef HAVE_GFX_WIDGETS #ifdef HAVE_GFX_WIDGETS
bool widgets_active; bool widgets_active;