mirror of
https://github.com/libretro/RetroArch
synced 2025-01-30 21:32:45 +00:00
Fix menu sounds (audio mixing) when using the 'sinc' resampler with quality lower than 'normal'
This commit is contained in:
parent
9ea6f15c1d
commit
547f04b894
@ -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)
|
||||||
|
@ -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:
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
45
retroarch.c
45
retroarch.c
@ -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:
|
||||||
|
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user