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

View File

@ -34,6 +34,8 @@
#include <boolean.h>
#include <retro_common_api.h>
#include <audio/audio_resampler.h>
RETRO_BEGIN_DECLS
enum audio_mixer_type
@ -60,7 +62,8 @@ void audio_mixer_init(unsigned rate);
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_mod(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);
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);

View File

@ -24937,8 +24937,10 @@ static void audio_driver_deinit_resampler(struct rarch_state *p_rarch)
{
if (p_rarch->audio_driver_resampler && 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_data = NULL;
p_rarch->audio_driver_resampler = 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 =
(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(
&p_rarch->audio_driver_resampler_data,
&p_rarch->audio_driver_resampler,
settings->arrays.audio_resampler,
audio_driver_get_resampler_quality(settings),
p_rarch->audio_driver_resampler_ident,
p_rarch->audio_driver_resampler_quality,
p_rarch->audio_source_ratio_original))
{
RARCH_ERR("Failed to initialize resampler \"%s\".\n",
settings->arrays.audio_resampler);
p_rarch->audio_driver_resampler_ident);
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:
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;
case AUDIO_MIXER_SLOT_SELECTION_AUTOMATIC:
default:
@ -25954,7 +25973,9 @@ bool audio_driver_mixer_add_stream(audio_mixer_stream_params_t *params)
switch (params->type)
{
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
* free()'d when sound playback is complete (it is
* 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:
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;
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;
case AUDIO_STREAM_STATE_PLAYING_SEQUENTIAL:
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;
default:
break;
@ -26043,7 +26070,9 @@ static void audio_driver_mixer_play_stream_internal(
p_rarch->audio_mixer_streams[i].voice =
audio_mixer_play(p_rarch->audio_mixer_streams[i].handle,
(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;
break;
case AUDIO_STREAM_STATE_PLAYING:

View File

@ -1713,6 +1713,7 @@ struct rarch_state
#ifdef HAVE_OVERLAY
enum overlay_visibility *overlay_visibility;
#endif
enum resampler_quality audio_driver_resampler_quality;
#ifdef HAVE_MENU
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_savestate_dir[PATH_MAX_LENGTH];
char dir_savestate[PATH_MAX_LENGTH];
char audio_driver_resampler_ident[64];
#ifdef HAVE_GFX_WIDGETS
bool widgets_active;