Merge remote-tracking branch 'refs/remotes/libretro/master' into wiiu_controller_patcher

This commit is contained in:
Maschell 2017-05-19 22:24:22 +02:00
commit 58543a43ff
13 changed files with 412 additions and 306 deletions

View File

@ -106,7 +106,7 @@ static const audio_driver_t *audio_drivers[] = {
&audio_rwebaudio,
#endif
#if defined(PSP) || defined(VITA)
&audio_psp,
&audio_psp,
#endif
#ifdef _3DS
&audio_ctr_csnd,
@ -122,38 +122,43 @@ static size_t audio_driver_chunk_block_size = 0;
static size_t audio_driver_rewind_ptr = 0;
static size_t audio_driver_rewind_size = 0;
static int16_t *audio_driver_rewind_buf = NULL;
static float *audio_driver_input_data = NULL;
static int16_t *audio_driver_rewind_buf = NULL;
static int16_t *audio_driver_output_samples_conv_buf = NULL;
static unsigned audio_driver_free_samples_buf[AUDIO_BUFFER_FREE_SAMPLES_COUNT];
static uint64_t audio_driver_free_samples_count = 0;
static float *audio_driver_output_samples_buf = NULL;
static int16_t *audio_driver_output_samples_conv_buf = NULL;
static float audio_driver_volume_gain = 0.0f;
static size_t audio_driver_buffer_size = 0;
static size_t audio_driver_data_ptr = 0;
static bool audio_driver_control = false;
static bool audio_driver_control = false;
static bool audio_driver_mute_enable = false;
static bool audio_driver_use_float = false;
static bool audio_driver_active = false;
static bool audio_driver_data_own = false;
static bool audio_mixer_active = false;
static float audio_driver_rate_control_delta = 0.0f;
static float audio_driver_input = 0.0f;
static float audio_driver_volume_gain = 0.0f;
static float *audio_driver_input_data = NULL;
static float *audio_driver_output_samples_buf = NULL;
static double audio_source_ratio_original = 0.0f;
static double audio_source_ratio_current = 0.0f;
static struct retro_audio_callback audio_callback = {0};
static retro_dsp_filter_t *audio_driver_dsp = NULL;
static struct string_list *audio_driver_devices_list = NULL;
static const retro_resampler_t *audio_driver_resampler = NULL;
static void *audio_driver_resampler_data = NULL;
static const audio_driver_t *current_audio = NULL;
static void *audio_driver_context_audio_data = NULL;
static bool audio_driver_use_float = false;
static bool audio_driver_active = false;
static bool audio_driver_data_own = false;
/**
* compute_audio_buffer_statistics:
*
@ -464,6 +469,8 @@ static bool audio_driver_init_internal(bool audio_cb_inited)
audio_driver_free_samples_count = 0;
audio_mixer_init(settings->uints.audio_out_rate);
/* Threaded driver is initially stopped. */
if (
audio_driver_active
@ -513,7 +520,6 @@ static bool audio_driver_flush(const int16_t *data, size_t samples)
bool is_slowmotion = false;
const void *output_data = NULL;
unsigned output_frames = 0;
settings_t *settings = config_get_ptr();
src_data.data_in = NULL;
src_data.data_out = NULL;
@ -527,7 +533,7 @@ static bool audio_driver_flush(const int16_t *data, size_t samples)
runloop_get_status(&is_paused, &is_idle, &is_slowmotion,
&is_perfcnt_enable);
if (is_paused || settings->bools.audio_mute_enable)
if (is_paused || audio_driver_mute_enable)
return true;
if (!audio_driver_active || !audio_driver_input_data)
return false;
@ -555,8 +561,8 @@ static bool audio_driver_flush(const int16_t *data, size_t samples)
if (dsp_data.output)
{
src_data.data_in = dsp_data.output;
src_data.input_frames = dsp_data.output_frames;
src_data.data_in = dsp_data.output;
src_data.input_frames = dsp_data.output_frames;
}
}
@ -572,14 +578,15 @@ static bool audio_driver_flush(const int16_t *data, size_t samples)
(int)current_audio->write_avail(audio_driver_context_audio_data);
int delta_mid = avail - half_size;
double direction = (double)delta_mid / half_size;
double adjust = 1.0 + settings->floats.audio_rate_control_delta * direction;
double adjust = 1.0 + audio_driver_rate_control_delta * direction;
#if 0
RARCH_LOG_OUTPUT("[Audio]: Audio buffer is %u%% full\n",
(unsigned)(100 - (avail * 100) / audio_driver_buffer_size));
#endif
audio_driver_free_samples_buf[write_idx] = avail;
audio_driver_free_samples_buf
[write_idx] = avail;
audio_source_ratio_current =
audio_source_ratio_original * adjust;
@ -590,25 +597,31 @@ static bool audio_driver_flush(const int16_t *data, size_t samples)
#endif
}
src_data.ratio = audio_source_ratio_current;
src_data.ratio = audio_source_ratio_current;
if (is_slowmotion)
src_data.ratio *= settings->floats.slowmotion_ratio;
{
settings_t *settings = config_get_ptr();
src_data.ratio *= settings->floats.slowmotion_ratio;
}
audio_driver_resampler->process(audio_driver_resampler_data, &src_data);
output_data = audio_driver_output_samples_buf;
output_frames = (unsigned)src_data.output_frames;
if (audio_mixer_active)
audio_mixer_mix(audio_driver_output_samples_buf, src_data.output_frames);
output_data = audio_driver_output_samples_buf;
output_frames = (unsigned)src_data.output_frames;
if (audio_driver_use_float)
output_frames *= sizeof(float);
output_frames *= sizeof(float);
else
{
convert_float_to_s16(audio_driver_output_samples_conv_buf,
(const float*)output_data, output_frames * 2);
output_data = audio_driver_output_samples_conv_buf;
output_frames *= sizeof(int16_t);
output_data = audio_driver_output_samples_conv_buf;
output_frames *= sizeof(int16_t);
}
if (current_audio->write(audio_driver_context_audio_data,
@ -754,6 +767,7 @@ void audio_driver_monitor_adjust_system_rates(void)
const struct retro_system_timing *info = NULL;
struct retro_system_av_info *av_info = video_viewport_get_system_av_info();
float video_refresh_rate = settings->floats.video_refresh_rate;
float max_timing_skew = settings->floats.audio_max_timing_skew;
if (av_info)
info = (const struct retro_system_timing*)&av_info->timing;
@ -764,7 +778,7 @@ void audio_driver_monitor_adjust_system_rates(void)
timing_skew = fabs(1.0f - info->fps / video_refresh_rate);
audio_driver_input = info->sample_rate;
if (timing_skew <= settings->floats.audio_max_timing_skew)
if (timing_skew <= max_timing_skew)
audio_driver_input *= (video_refresh_rate / info->fps);
RARCH_LOG("[Audio]: Set audio input rate to: %.2f Hz.\n",
@ -872,6 +886,7 @@ bool audio_driver_get_devices_list(void **data)
bool audio_driver_deinit(void)
{
audio_mixer_done();
audio_driver_free_devices_list();
if (!audio_driver_deinit_internal())
return false;
@ -937,14 +952,13 @@ bool audio_driver_has_callback(void)
bool audio_driver_toggle_mute(void)
{
settings_t *settings = config_get_ptr();
bool new_mute_state = !settings->bools.audio_mute_enable;
bool new_mute_state = !audio_driver_mute_enable;
if (!audio_driver_context_audio_data)
return false;
if (!audio_driver_active)
return false;
configuration_set_bool(settings,
settings->bools.audio_mute_enable, new_mute_state);
audio_driver_mute_enable = new_mute_state;
if (new_mute_state)
command_event(CMD_EVENT_AUDIO_STOP, NULL);
@ -1038,3 +1052,44 @@ void audio_driver_destroy(void)
audio_driver_data_own = false;
current_audio = NULL;
}
void audio_set_float(enum audio_action action, float val)
{
switch (action)
{
case AUDIO_ACTION_RATE_CONTROL_DELTA:
audio_driver_rate_control_delta = val;
break;
case AUDIO_ACTION_NONE:
default:
break;
}
}
float *audio_get_float_ptr(enum audio_action action)
{
switch (action)
{
case AUDIO_ACTION_RATE_CONTROL_DELTA:
return &audio_driver_rate_control_delta;
case AUDIO_ACTION_NONE:
default:
break;
}
return NULL;
}
bool *audio_get_bool_ptr(enum audio_action action)
{
switch (action)
{
case AUDIO_ACTION_MUTE_ENABLE:
return &audio_driver_mute_enable;
case AUDIO_ACTION_NONE:
default:
break;
}
return NULL;
}

View File

@ -33,6 +33,13 @@ RETRO_BEGIN_DECLS
#define AUDIO_MAX_RATIO 16
enum audio_action
{
AUDIO_ACTION_NONE = 0,
AUDIO_ACTION_RATE_CONTROL_DELTA,
AUDIO_ACTION_MUTE_ENABLE
};
typedef struct audio_driver
{
/* Creates and initializes handle to audio driver.
@ -209,6 +216,12 @@ void audio_driver_unset_callback(void);
void audio_driver_frame_is_reverse(void);
void audio_set_float(enum audio_action action, float val);
float *audio_get_float_ptr(enum audio_action action);
bool *audio_get_bool_ptr(enum audio_action action);
bool audio_driver_deinit(void);
bool audio_driver_init(void);

View File

@ -1,8 +1,17 @@
diff --git a/audio/audio_driver.c b/audio/audio_driver.c
index 10dcbc5b3..203e89d0a 100644
index 10dcbc5b3..0d2bb4d85 100644
--- a/audio/audio_driver.c
+++ b/audio/audio_driver.c
@@ -597,6 +597,8 @@ static bool audio_driver_flush(const int16_t *data, size_t samples)
@@ -464,6 +464,8 @@ static bool audio_driver_init_internal(bool audio_cb_inited)
audio_driver_free_samples_count = 0;
+ audio_mixer_init(48000);
+
/* Threaded driver is initially stopped. */
if (
audio_driver_active
@@ -597,6 +599,8 @@ static bool audio_driver_flush(const int16_t *data, size_t samples)
audio_driver_resampler->process(audio_driver_resampler_data, &src_data);
@ -21,7 +30,7 @@ index 0e3a8dc44..4f79b2ed7 100644
if (runloop_cmd_triggered(trigger_input, RARCH_RESET))
+ {
command_event(CMD_EVENT_RESET, NULL);
+ audio_mixer_load_wav("/home/squarepusher/piano2.wav");
+ audio_mixer_load_ogg("/home/squarepusher/SumertimeBlues.ogg");
+ }
cheat_manager_state_checks(

View File

@ -2060,7 +2060,8 @@ bool command_event(enum event_command cmd, void *data)
case CMD_EVENT_AUDIO_MUTE_TOGGLE:
{
settings_t *settings = config_get_ptr();
const char *msg = !settings->bools.audio_mute_enable ?
bool audio_mute_enable = *(audio_get_bool_ptr(AUDIO_ACTION_MUTE_ENABLE));
const char *msg = !audio_mute_enable ?
msg_hash_to_str(MSG_AUDIO_MUTED):
msg_hash_to_str(MSG_AUDIO_UNMUTED);

View File

@ -1152,7 +1152,7 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings,
SETTING_BOOL("keyboard_gamepad_enable", &settings->bools.input_keyboard_gamepad_enable, true, true, false);
SETTING_BOOL("core_set_supports_no_game_enable", &settings->bools.set_supports_no_game_enable, true, true, false);
SETTING_BOOL("audio_enable", &settings->bools.audio_enable, true, audio_enable, false);
SETTING_BOOL("audio_mute_enable", &settings->bools.audio_mute_enable, true, false, false);
SETTING_BOOL("audio_mute_enable", audio_get_bool_ptr(AUDIO_ACTION_MUTE_ENABLE), true, false, false);
SETTING_BOOL("location_allow", &settings->bools.location_allow, true, false, false);
SETTING_BOOL("video_font_enable", &settings->bools.video_font_enable, true, font_enable, false);
SETTING_BOOL("core_updater_auto_extract_archive", &settings->bools.network_buildbot_auto_extract_archive, true, true, false);
@ -1266,7 +1266,7 @@ static struct config_float_setting *populate_settings_float(settings_t *settings
SETTING_FLOAT("video_aspect_ratio", &settings->floats.video_aspect_ratio, true, aspect_ratio, false);
SETTING_FLOAT("video_scale", &settings->floats.video_scale, false, 0.0f, false);
SETTING_FLOAT("video_refresh_rate", &settings->floats.video_refresh_rate, true, refresh_rate, false);
SETTING_FLOAT("audio_rate_control_delta", &settings->floats.audio_rate_control_delta, true, rate_control_delta, false);
SETTING_FLOAT("audio_rate_control_delta", audio_get_float_ptr(AUDIO_ACTION_RATE_CONTROL_DELTA), true, rate_control_delta, false);
SETTING_FLOAT("audio_max_timing_skew", &settings->floats.audio_max_timing_skew, true, max_timing_skew, false);
SETTING_FLOAT("audio_volume", &settings->floats.audio_volume, true, audio_volume, false);
#ifdef HAVE_OVERLAY

View File

@ -74,7 +74,6 @@ typedef struct settings
/* Audio */
bool audio_enable;
bool audio_mute_enable;
bool audio_sync;
bool audio_rate_control;
#ifdef HAVE_WASAPI
@ -229,7 +228,6 @@ typedef struct settings
float menu_footer_opacity;
float menu_header_opacity;
float audio_rate_control_delta;
float audio_max_timing_skew;
float audio_volume; /* dB scale. */

View File

@ -46,13 +46,16 @@
#define AUDIO_MIXER_MAX_VOICES 8
#define AUDIO_MIXER_TEMP_OGG_BUFFER 8192
#define AUDIO_MIXER_TYPE_NONE 0
#define AUDIO_MIXER_TYPE_WAV 1
#define AUDIO_MIXER_TYPE_OGG 2
struct audio_mixer_sound_t
enum audio_mixer_type
{
unsigned type;
AUDIO_MIXER_TYPE_NONE = 0,
AUDIO_MIXER_TYPE_WAV,
AUDIO_MIXER_TYPE_OGG
};
struct audio_mixer_sound
{
enum audio_mixer_type type;
union
{
@ -74,12 +77,12 @@ struct audio_mixer_sound_t
} types;
};
struct audio_mixer_voice_t
struct audio_mixer_voice
{
unsigned type;
bool repeat;
unsigned type;
float volume;
audio_mixer_sound_t* sound;
audio_mixer_sound_t *sound;
audio_mixer_stop_cb_t stop_cb;
union
@ -96,44 +99,39 @@ struct audio_mixer_voice_t
/* ogg */
unsigned position;
unsigned samples;
stb_vorbis* stream;
float* buffer;
unsigned buf_samples;
void* resampler_data;
float* buffer;
float ratio;
const retro_resampler_t* resampler;
stb_vorbis *stream;
void *resampler_data;
const retro_resampler_t *resampler;
} ogg;
#endif
} types;
};
static audio_mixer_voice_t s_voices[AUDIO_MIXER_MAX_VOICES];
static unsigned s_rate = 0;
static struct audio_mixer_voice s_voices[AUDIO_MIXER_MAX_VOICES];
static unsigned s_rate = 0;
static bool wav2float(const rwav_t* wav, float** pcm, size_t* samples_out)
static bool wav2float(const rwav_t* wav, float** pcm, size_t samples_out)
{
size_t i;
float sample = 0.0f;
const uint8_t* u8 = NULL;
const int16_t* s16 = NULL;
float* f = NULL;
/* Allocate on a 16-byte boundary, and pad to a multiple of 16 bytes */
*samples_out = wav->numsamples * 2;
f = (float*)memalign_alloc(16,
((*samples_out + 15) & ~15) * sizeof(float));
float *f = (float*)memalign_alloc(16,
((samples_out + 15) & ~15) * sizeof(float));
if (!f)
return false;
*pcm = f;
if (wav->numchannels == 1)
if (wav->bitspersample == 8)
{
if (wav->bitspersample == 8)
float sample = 0.0f;
const uint8_t *u8 = (const uint8_t*)wav->samples;
if (wav->numchannels == 1)
{
u8 = (const uint8_t*)wav->samples;
for (i = wav->numsamples; i != 0; i--)
{
sample = (float)*u8++ / 255.0f;
@ -142,10 +140,29 @@ static bool wav2float(const rwav_t* wav, float** pcm, size_t* samples_out)
*f++ = sample;
}
}
else
else if (wav->numchannels == 2)
{
for (i = wav->numsamples; i != 0; i--)
{
sample = (float)*u8++ / 255.0f;
sample = sample * 2.0f - 1.0f;
*f++ = sample;
sample = (float)*u8++ / 255.0f;
sample = sample * 2.0f - 1.0f;
*f++ = sample;
}
}
}
else
{
/* TODO/FIXME note to leiradel - can we use audio/conversion/s16_to_float
* functions here? */
float sample = 0.0f;
const int16_t *s16 = (const int16_t*)wav->samples;
if (wav->numchannels == 1)
{
s16 = (const int16_t*)wav->samples;
for (i = wav->numsamples; i != 0; i--)
{
sample = (float)((int)*s16++ + 32768) / 65535.0f;
@ -154,27 +171,8 @@ static bool wav2float(const rwav_t* wav, float** pcm, size_t* samples_out)
*f++ = sample;
}
}
}
else if (wav->numchannels == 2)
{
if (wav->bitspersample == 8)
else if (wav->numchannels == 2)
{
u8 = (const uint8_t*)wav->samples;
for (i = wav->numsamples; i != 0; i--)
{
sample = (float)*u8++ / 255.0f;
sample = sample * 2.0f - 1.0f;
*f++ = sample;
sample = (float)*u8++ / 255.0f;
sample = sample * 2.0f - 1.0f;
*f++ = sample;
}
}
else
{
s16 = (const int16_t*)wav->samples;
for (i = wav->numsamples; i != 0; i--)
{
sample = (float)((int)*s16++ + 32768) / 65535.0f;
@ -186,7 +184,7 @@ static bool wav2float(const rwav_t* wav, float** pcm, size_t* samples_out)
}
}
}
return true;
}
@ -254,27 +252,29 @@ audio_mixer_sound_t* audio_mixer_load_wav(const char* path)
ssize_t size = 0;
/* WAV samples converted to float */
float* pcm = NULL;
float* resampled = NULL;
size_t samples = 0;
/* Result */
audio_mixer_sound_t* sound = NULL;
enum rwav_state rwav_ret = RWAV_ITERATE_ERROR;
if (filestream_read_file(path, &buffer, &size) == 0)
return NULL;
if (rwav_load(&wav, buffer, size) != RWAV_ITERATE_DONE)
{
free(buffer);
return NULL;
}
rwav_ret = rwav_load(&wav, buffer, size);
free(buffer);
if (rwav_ret != RWAV_ITERATE_DONE)
return NULL;
if (!wav2float(&wav, &pcm, &samples))
samples = wav.numsamples * 2;
if (!wav2float(&wav, &pcm, samples))
return NULL;
if (wav.samplerate != s_rate)
{
float* resampled = NULL;
if (!one_shot_resample(pcm, samples,
wav.samplerate, &resampled, &samples))
return NULL;
@ -296,6 +296,7 @@ audio_mixer_sound_t* audio_mixer_load_wav(const char* path)
sound->types.wav.pcm = pcm;
rwav_free(&wav);
return sound;
}
@ -329,6 +330,9 @@ audio_mixer_sound_t* audio_mixer_load_ogg(const char* path)
void audio_mixer_destroy(audio_mixer_sound_t* sound)
{
if (!sound)
return;
switch (sound->type)
{
case AUDIO_MIXER_TYPE_WAV:
@ -339,6 +343,8 @@ void audio_mixer_destroy(audio_mixer_sound_t* sound)
memalign_free((void*)sound->types.ogg.data);
#endif
break;
case AUDIO_MIXER_TYPE_NONE:
break;
}
free(sound);
@ -348,11 +354,6 @@ static bool audio_mixer_play_wav(audio_mixer_sound_t* sound,
audio_mixer_voice_t* voice, bool repeat, float volume,
audio_mixer_stop_cb_t stop_cb)
{
voice->type = AUDIO_MIXER_TYPE_WAV;
voice->repeat = repeat;
voice->volume = volume;
voice->sound = sound;
voice->stop_cb = stop_cb;
voice->types.wav.position = 0;
return true;
@ -366,58 +367,59 @@ static bool audio_mixer_play_ogg(
audio_mixer_stop_cb_t stop_cb)
{
stb_vorbis_info info;
int res = 0;
float ratio = 0.0f;
unsigned samples = 0;
voice->repeat = repeat;
voice->volume = volume;
voice->sound = sound;
voice->stop_cb = stop_cb;
voice->types.ogg.stream = stb_vorbis_open_memory(
int res = 0;
float ratio = 0.0f;
unsigned samples = 0;
void *ogg_buffer = NULL;
void *resampler_data = NULL;
const retro_resampler_t* resamp = NULL;
stb_vorbis *stb_vorbis = stb_vorbis_open_memory(
(const unsigned char*)sound->types.ogg.data,
sound->types.ogg.size, &res, NULL);
if (!voice->types.ogg.stream)
if (!stb_vorbis)
return false;
info = stb_vorbis_get_info(voice->types.ogg.stream);
info = stb_vorbis_get_info(stb_vorbis);
/* Only stereo supported for now */
if (info.channels != 2)
{
stb_vorbis_close(voice->types.ogg.stream);
return false;
}
goto error;
if (info.sample_rate != s_rate)
{
voice->types.ogg.ratio = ratio = (double)s_rate / (double)info.sample_rate;
ratio = (double)s_rate / (double)info.sample_rate;
if (!retro_resampler_realloc(&voice->types.ogg.resampler_data,
&voice->types.ogg.resampler, NULL, ratio))
{
stb_vorbis_close(voice->types.ogg.stream);
return false;
}
if (!retro_resampler_realloc(&resampler_data,
&resamp, NULL, ratio))
goto error;
}
samples =
voice->types.ogg.buf_samples = (unsigned)(AUDIO_MIXER_TEMP_OGG_BUFFER * ratio);
voice->types.ogg.buffer = (float*)memalign_alloc(16,
samples = (unsigned)(AUDIO_MIXER_TEMP_OGG_BUFFER * ratio);
ogg_buffer = (float*)memalign_alloc(16,
((samples + 15) & ~15) * sizeof(float));
if (!voice->types.ogg.buffer)
if (!ogg_buffer)
{
voice->types.ogg.resampler->free(voice->types.ogg.resampler_data);
stb_vorbis_close(voice->types.ogg.stream);
return false;
resamp->free(resampler_data);
goto error;
}
voice->type = AUDIO_MIXER_TYPE_OGG;
voice->types.ogg.position = voice->types.ogg.samples = 0;
voice->types.ogg.resampler = resamp;
voice->types.ogg.resampler_data = resampler_data;
voice->types.ogg.buffer = ogg_buffer;
voice->types.ogg.buf_samples = samples;
voice->types.ogg.ratio = ratio;
voice->types.ogg.stream = stb_vorbis;
voice->types.ogg.position = 0;
voice->types.ogg.samples = 0;
voice->type = AUDIO_MIXER_TYPE_OGG;
return true;
error:
stb_vorbis_close(stb_vorbis);
return false;
}
#endif
@ -427,30 +429,42 @@ audio_mixer_voice_t* audio_mixer_play(audio_mixer_sound_t* sound, bool repeat,
unsigned i;
bool res = false;
audio_mixer_voice_t* voice = s_voices;
if (!sound)
return NULL;
for (i = 0; i < AUDIO_MIXER_MAX_VOICES; i++, voice++)
{
if (voice->type == AUDIO_MIXER_TYPE_NONE)
if (voice->type != AUDIO_MIXER_TYPE_NONE)
continue;
switch (sound->type)
{
switch (sound->type)
{
case AUDIO_MIXER_TYPE_WAV:
res = audio_mixer_play_wav(sound, voice, repeat, volume, stop_cb);
break;
case AUDIO_MIXER_TYPE_OGG:
case AUDIO_MIXER_TYPE_WAV:
res = audio_mixer_play_wav(sound, voice, repeat, volume, stop_cb);
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, stop_cb);
#endif
break;
}
break;
break;
case AUDIO_MIXER_TYPE_NONE:
break;
}
break;
}
if (res)
return voice;
return NULL;
if (!res)
return NULL;
voice->type = sound->type;
voice->repeat = repeat;
voice->volume = volume;
voice->sound = sound;
voice->stop_cb = stop_cb;
return voice;
}
void audio_mixer_stop(audio_mixer_voice_t* voice)
@ -459,15 +473,17 @@ void audio_mixer_stop(audio_mixer_voice_t* voice)
voice->stop_cb(voice, AUDIO_MIXER_SOUND_STOPPED);
}
static void mix_wav(float* buffer, size_t num_frames, audio_mixer_voice_t* voice)
static void audio_mixer_mix_wav(float* buffer, size_t num_frames,
audio_mixer_voice_t* voice,
float volume)
{
int i;
unsigned buf_free = (unsigned)(num_frames * 2);
const audio_mixer_sound_t* sound = voice->sound;
unsigned pcm_available = sound->types.wav.frames
* 2 - voice->types.wav.position;
const float* pcm = sound->types.wav.pcm + voice->types.wav.position;
float volume = voice->volume;
const float* pcm = sound->types.wav.pcm +
voice->types.wav.position;
again:
if (pcm_available < buf_free)
@ -502,18 +518,16 @@ again:
}
#ifdef HAVE_STB_VORBIS
static void mix_ogg(float* buffer, size_t num_frames, audio_mixer_voice_t* voice)
static void audio_mixer_mix_ogg(float* buffer, size_t num_frames,
audio_mixer_voice_t* voice,
float volume)
{
int i;
float temp_buffer[AUDIO_MIXER_TEMP_OGG_BUFFER];
struct resampler_data info;
float temp_buffer[AUDIO_MIXER_TEMP_OGG_BUFFER];
unsigned buf_free = num_frames * 2;
unsigned temp_samples = 0;
float volume = voice->volume;
float* pcm = NULL;
#if 0
const audio_mixer_sound_t* sound = voice->sound;
#endif
if (voice->types.ogg.position == voice->types.ogg.samples)
{
@ -584,12 +598,21 @@ void audio_mixer_mix(float* buffer, size_t num_frames)
for (i = 0; i < AUDIO_MIXER_MAX_VOICES; i++, voice++)
{
if (voice->type == AUDIO_MIXER_TYPE_WAV)
mix_wav(buffer, num_frames, voice);
float volume = voice->volume;
switch (voice->type)
{
case AUDIO_MIXER_TYPE_WAV:
audio_mixer_mix_wav(buffer, num_frames, voice, volume);
break;
case AUDIO_MIXER_TYPE_OGG:
#ifdef HAVE_STB_VORBIS
else if (voice->type == AUDIO_MIXER_TYPE_OGG)
mix_ogg(buffer, num_frames, voice);
audio_mixer_mix_ogg(buffer, num_frames, voice, volume);
#endif
break;
case AUDIO_MIXER_TYPE_NONE:
break;
}
}
for (j = 0, sample = buffer; j < num_frames; j++, sample++)

View File

@ -522,31 +522,31 @@ bool file_archive_extract_file(
bool ret = true;
struct string_list *list = string_split(valid_exts, "|");
userdata.archive_path[0] = '\0';
userdata.first_extracted_file_path = NULL;
userdata.extracted_file_path = NULL;
userdata.extraction_directory = extraction_directory;
userdata.archive_path_size = archive_path_size;
userdata.ext = list;
userdata.list = NULL;
userdata.found_file = false;
userdata.list_only = false;
userdata.context = NULL;
userdata.archive_name[0] = '\0';
userdata.crc = 0;
userdata.dec = NULL;
userdata.decomp_state.opt_file = NULL;
userdata.decomp_state.needle = NULL;
userdata.decomp_state.size = 0;
userdata.decomp_state.found = NULL;
if (!list)
{
ret = false;
goto end;
}
userdata.archive_path[0] = '\0';
userdata.first_extracted_file_path = NULL;
userdata.extracted_file_path = NULL;
userdata.extraction_directory = extraction_directory;
userdata.archive_path_size = archive_path_size;
userdata.ext = list;
userdata.list = NULL;
userdata.found_file = false;
userdata.list_only = false;
userdata.context = NULL;
userdata.archive_name[0] = '\0';
userdata.crc = 0;
userdata.dec = NULL;
userdata.decomp_state.opt_file = NULL;
userdata.decomp_state.needle = NULL;
userdata.decomp_state.size = 0;
userdata.decomp_state.found = NULL;
if (!file_archive_walk(archive_path, valid_exts,
file_archive_extract_cb, &userdata))
{

View File

@ -37,128 +37,143 @@ enum
ITER_COPY_SAMPLES_16
};
struct rwav_iterator
{
rwav_t *out;
const uint8_t *data;
size_t size;
size_t i, j;
int step;
};
void rwav_init(rwav_iterator_t* iter, rwav_t* out, const void* buf, size_t size)
{
iter->out = out;
iter->data = (const uint8_t*)buf;
iter->size = size;
iter->step = ITER_BEGIN;
iter->out = out;
iter->data = (const uint8_t*)buf;
iter->size = size;
iter->step = ITER_BEGIN;
out->samples = NULL;
}
int rwav_iterate(rwav_iterator_t *iter)
{
rwav_t *rwav = iter->out;
const uint8_t *data = iter->data;
uint16_t *u16;
void *samples;
size_t s;
uint16_t *u16 = NULL;
void *samples = NULL;
rwav_t *rwav = iter->out;
const uint8_t *data = iter->data;
switch (iter->step)
{
case ITER_BEGIN:
if (iter->size < 44)
return RWAV_ITERATE_ERROR; /* buffer is smaller than an empty wave file */
if (data[0] != 'R' || data[1] != 'I' || data[2] != 'F' || data[3] != 'F')
return RWAV_ITERATE_ERROR;
if (data[8] != 'W' || data[9] != 'A' || data[10] != 'V' || data[11] != 'E')
return RWAV_ITERATE_ERROR;
case ITER_BEGIN:
if (iter->size < 44)
return RWAV_ITERATE_ERROR; /* buffer is smaller than an empty wave file */
if (data[12] != 'f' || data[13] != 'm' || data[14] != 't' || data[15] != ' ')
return RWAV_ITERATE_ERROR; /* we don't support non-PCM or compressed data */
if (data[16] != 16 || data[17] != 0 || data[18] != 0 || data[19] != 0)
return RWAV_ITERATE_ERROR;
if (data[20] != 1 || data[21] != 0)
return RWAV_ITERATE_ERROR; /* we don't support non-PCM or compressed data */
if (data[0] != 'R' || data[1] != 'I' || data[2] != 'F' || data[3] != 'F')
return RWAV_ITERATE_ERROR;
if (data[36] != 'd' || data[37] != 'a' || data[38] != 't' || data[39] != 'a')
return RWAV_ITERATE_ERROR;
rwav->bitspersample = data[34] | data[35] << 8;
if (rwav->bitspersample != 8 && rwav->bitspersample != 16)
return RWAV_ITERATE_ERROR; /* we only support 8 and 16 bps */
rwav->subchunk2size = data[40] | data[41] << 8 | data[42] << 16 | data[43] << 24;
if (rwav->subchunk2size > iter->size - 44)
return RWAV_ITERATE_ERROR; /* too few bytes in buffer */
if (data[8] != 'W' || data[9] != 'A' || data[10] != 'V' || data[11] != 'E')
return RWAV_ITERATE_ERROR;
samples = malloc(rwav->subchunk2size);
if (samples == NULL)
return RWAV_ITERATE_ERROR;
rwav->numchannels = data[22] | data[23] << 8;
rwav->numsamples = rwav->subchunk2size * 8 / rwav->bitspersample / rwav->numchannels;
rwav->samplerate = data[24] | data[25] << 8 | data[26] << 16 | data[27] << 24;
rwav->samples = samples;
iter->step = ITER_COPY_SAMPLES;
return RWAV_ITERATE_MORE;
case ITER_COPY_SAMPLES:
iter->i = 0;
if (rwav->bitspersample == 8)
{
iter->step = ITER_COPY_SAMPLES_8;
case ITER_COPY_SAMPLES_8:
s = rwav->subchunk2size - iter->i;
if (s > RWAV_ITERATE_BUF_SIZE)
s = RWAV_ITERATE_BUF_SIZE;
memcpy((void*)((uint8_t*)rwav->samples + iter->i), (void *)(iter->data + 44 + iter->i), s);
iter->i += s;
return iter->i < rwav->subchunk2size ? RWAV_ITERATE_MORE : RWAV_ITERATE_DONE;
}
else
{
iter->step = ITER_COPY_SAMPLES_16;
iter->j = 0;
case ITER_COPY_SAMPLES_16:
s = rwav->subchunk2size - iter->i;
if (s > RWAV_ITERATE_BUF_SIZE)
s = RWAV_ITERATE_BUF_SIZE;
u16 = (uint16_t *)rwav->samples;
while (s != 0)
if (data[12] != 'f' || data[13] != 'm' || data[14] != 't' || data[15] != ' ')
return RWAV_ITERATE_ERROR; /* we don't support non-PCM or compressed data */
if (data[16] != 16 || data[17] != 0 || data[18] != 0 || data[19] != 0)
return RWAV_ITERATE_ERROR;
if (data[20] != 1 || data[21] != 0)
return RWAV_ITERATE_ERROR; /* we don't support non-PCM or compressed data */
if (data[36] != 'd' || data[37] != 'a' || data[38] != 't' || data[39] != 'a')
return RWAV_ITERATE_ERROR;
rwav->bitspersample = data[34] | data[35] << 8;
if (rwav->bitspersample != 8 && rwav->bitspersample != 16)
return RWAV_ITERATE_ERROR; /* we only support 8 and 16 bps */
rwav->subchunk2size = data[40] | data[41] << 8 | data[42] << 16 | data[43] << 24;
if (rwav->subchunk2size > iter->size - 44)
return RWAV_ITERATE_ERROR; /* too few bytes in buffer */
samples = malloc(rwav->subchunk2size);
if (samples == NULL)
return RWAV_ITERATE_ERROR;
rwav->numchannels = data[22] | data[23] << 8;
rwav->numsamples = rwav->subchunk2size * 8 / rwav->bitspersample / rwav->numchannels;
rwav->samplerate = data[24] | data[25] << 8 | data[26] << 16 | data[27] << 24;
rwav->samples = samples;
iter->step = ITER_COPY_SAMPLES;
return RWAV_ITERATE_MORE;
case ITER_COPY_SAMPLES:
iter->i = 0;
if (rwav->bitspersample == 8)
{
u16[iter->j++] = iter->data[44 + iter->i] | iter->data[45 + iter->i] << 8;
iter->i += 2;
s -= 2;
iter->step = ITER_COPY_SAMPLES_8;
/* TODO/FIXME - what is going on here? */
case ITER_COPY_SAMPLES_8:
s = rwav->subchunk2size - iter->i;
if (s > RWAV_ITERATE_BUF_SIZE)
s = RWAV_ITERATE_BUF_SIZE;
memcpy((void*)((uint8_t*)rwav->samples + iter->i), (void *)(iter->data + 44 + iter->i), s);
iter->i += s;
}
else
{
iter->step = ITER_COPY_SAMPLES_16;
iter->j = 0;
/* TODO/FIXME - what is going on here? */
case ITER_COPY_SAMPLES_16:
s = rwav->subchunk2size - iter->i;
if (s > RWAV_ITERATE_BUF_SIZE)
s = RWAV_ITERATE_BUF_SIZE;
u16 = (uint16_t *)rwav->samples;
while (s != 0)
{
u16[iter->j++] = iter->data[44 + iter->i] | iter->data[45 + iter->i] << 8;
iter->i += 2;
s -= 2;
}
}
return iter->i < rwav->subchunk2size ? RWAV_ITERATE_MORE : RWAV_ITERATE_DONE;
}
}
return RWAV_ITERATE_ERROR;
}
int rwav_load(rwav_t* out, const void* buf, size_t size)
enum rwav_state rwav_load(rwav_t* out, const void* buf, size_t size)
{
int res;
rwav_iterator_t iter = {0};
enum rwav_state res;
rwav_iterator_t iter;
iter.out = NULL;
iter.data = NULL;
iter.size = 0;
iter.i = 0;
iter.j = 0;
iter.step = 0;
rwav_init(&iter, out, buf, size);
do
{
res = rwav_iterate(&iter);
}while (res == RWAV_ITERATE_MORE);
return res;
}

View File

@ -31,8 +31,8 @@
RETRO_BEGIN_DECLS
typedef struct audio_mixer_sound_t audio_mixer_sound_t;
typedef struct audio_mixer_voice_t audio_mixer_voice_t;
typedef struct audio_mixer_sound audio_mixer_sound_t;
typedef struct audio_mixer_voice audio_mixer_voice_t;
typedef void (*audio_mixer_stop_cb_t)(audio_mixer_voice_t* voice, unsigned reason);
@ -42,6 +42,7 @@ typedef void (*audio_mixer_stop_cb_t)(audio_mixer_voice_t* voice, unsigned reaso
#define AUDIO_MIXER_SOUND_REPEATED 2
void audio_mixer_init(unsigned rate);
void audio_mixer_done(void);
audio_mixer_sound_t* audio_mixer_load_wav(const char* path);
@ -49,8 +50,10 @@ audio_mixer_sound_t* audio_mixer_load_ogg(const char* path);
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);
void audio_mixer_stop(audio_mixer_voice_t* voice);
audio_mixer_voice_t* audio_mixer_play(audio_mixer_sound_t* sound,
bool repeat, float volume, audio_mixer_stop_cb_t stop_cb);
void audio_mixer_stop(audio_mixer_voice_t* voice);
void audio_mixer_mix(float* buffer, size_t num_frames);

View File

@ -47,28 +47,17 @@ typedef struct
/* PCM data */
const void* samples;
}
rwav_t;
} rwav_t;
enum
enum rwav_state
{
RWAV_ITERATE_ERROR = -1,
RWAV_ITERATE_MORE = 0,
RWAV_ITERATE_DONE = 1,
RWAV_ITERATE_ERROR = -1,
RWAV_ITERATE_MORE = 0,
RWAV_ITERATE_DONE = 1,
RWAV_ITERATE_BUF_SIZE = 4096
};
typedef struct
{
/* internal data, don't touch */
rwav_t *out;
const uint8_t *data;
size_t size;
size_t i, j;
int step;
}
rwav_iterator_t;
typedef struct rwav_iterator rwav_iterator_t;
/**
* Initializes the iterator to fill the out structure with data parsed from buf.
@ -86,7 +75,7 @@ int rwav_iterate(rwav_iterator_t *iter);
/**
* Loads the entire data in one go.
*/
int rwav_load(rwav_t* out, const void* buf, size_t size);
enum rwav_state rwav_load(rwav_t* out, const void* buf, size_t size);
/**
* Frees parsed wave data.

View File

@ -225,7 +225,7 @@ RFILE *filestream_open(const char *path, unsigned mode, ssize_t len)
stream->fd = sceIoOpen(path, flags, mode_int);
#else
#if defined(HAVE_BUFFERED_IO)
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0 && mode_str)
{
stream->fp = fopen(path, mode_str);
if (!stream->fp)

View File

@ -1478,16 +1478,16 @@ void general_read_handler(void *data)
switch (setting->enum_idx)
{
case MENU_ENUM_LABEL_AUDIO_RATE_CONTROL_DELTA:
*setting->value.target.fraction = settings->floats.audio_rate_control_delta;
*setting->value.target.fraction = *(audio_get_float_ptr(AUDIO_ACTION_RATE_CONTROL_DELTA));
if (*setting->value.target.fraction < 0.0005)
{
configuration_set_bool(settings, settings->bools.audio_rate_control, false);
settings->floats.audio_rate_control_delta = 0.0;
audio_set_float(AUDIO_ACTION_RATE_CONTROL_DELTA, 0.0f);
}
else
{
configuration_set_bool(settings, settings->bools.audio_rate_control, true);
settings->floats.audio_rate_control_delta = *setting->value.target.fraction;
audio_set_float(AUDIO_ACTION_RATE_CONTROL_DELTA, *setting->value.target.fraction);
}
break;
case MENU_ENUM_LABEL_AUDIO_MAX_TIMING_SKEW:
@ -1600,12 +1600,12 @@ void general_write_handler(void *data)
if (*setting->value.target.fraction < 0.0005)
{
configuration_set_bool(settings, settings->bools.audio_rate_control, false);
settings->floats.audio_rate_control_delta = 0.0;
audio_set_float(AUDIO_ACTION_RATE_CONTROL_DELTA, 0.0f);
}
else
{
configuration_set_bool(settings, settings->bools.audio_rate_control, true);
settings->floats.audio_rate_control_delta = *setting->value.target.fraction;
audio_set_float(AUDIO_ACTION_RATE_CONTROL_DELTA, *setting->value.target.fraction);
}
break;
case MENU_ENUM_LABEL_VIDEO_REFRESH_RATE_AUTO:
@ -3761,7 +3761,7 @@ static bool setting_append_list(
CONFIG_BOOL(
list, list_info,
&settings->bools.audio_mute_enable,
audio_get_bool_ptr(AUDIO_ACTION_MUTE_ENABLE),
MENU_ENUM_LABEL_AUDIO_MUTE,
MENU_ENUM_LABEL_VALUE_AUDIO_MUTE,
false,
@ -3853,7 +3853,7 @@ static bool setting_append_list(
CONFIG_FLOAT(
list, list_info,
&settings->floats.audio_rate_control_delta,
audio_get_float_ptr(AUDIO_ACTION_RATE_CONTROL_DELTA),
MENU_ENUM_LABEL_AUDIO_RATE_CONTROL_DELTA,
MENU_ENUM_LABEL_VALUE_AUDIO_RATE_CONTROL_DELTA,
rate_control_delta,