mirror of
https://github.com/CTCaer/RetroArch.git
synced 2024-12-15 06:50:32 +00:00
Update libretro-common
This commit is contained in:
parent
b693d76ebb
commit
1f2ef858ab
@ -47,12 +47,17 @@
|
||||
#include <stb/stb_vorbis.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DR_FLAC
|
||||
#define DR_FLAC_IMPLEMENTATION
|
||||
#include <dr/dr_flac.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_IBXM
|
||||
#include <ibxm/ibxm.h>
|
||||
#endif
|
||||
|
||||
#define AUDIO_MIXER_MAX_VOICES 8
|
||||
#define AUDIO_MIXER_TEMP_OGG_BUFFER 8192
|
||||
#define AUDIO_MIXER_TEMP_BUFFER 8192
|
||||
|
||||
struct audio_mixer_sound
|
||||
{
|
||||
@ -75,6 +80,15 @@ struct audio_mixer_sound
|
||||
const void* data;
|
||||
} ogg;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DR_FLAC
|
||||
struct
|
||||
{
|
||||
/* flac */
|
||||
unsigned size;
|
||||
const void* data;
|
||||
} flac;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_IBXM
|
||||
struct
|
||||
@ -116,6 +130,20 @@ struct audio_mixer_voice
|
||||
} ogg;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DR_FLAC
|
||||
struct
|
||||
{
|
||||
unsigned position;
|
||||
unsigned samples;
|
||||
unsigned buf_samples;
|
||||
float* buffer;
|
||||
float ratio;
|
||||
drflac *stream;
|
||||
void *resampler_data;
|
||||
const retro_resampler_t *resampler;
|
||||
} flac;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_IBXM
|
||||
struct
|
||||
{
|
||||
@ -343,6 +371,25 @@ audio_mixer_sound_t* audio_mixer_load_ogg(void *buffer, int32_t size)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
audio_mixer_sound_t* audio_mixer_load_flac(void *buffer, int32_t size)
|
||||
{
|
||||
#ifdef HAVE_DR_FLAC
|
||||
audio_mixer_sound_t* sound = (audio_mixer_sound_t*)calloc(1, sizeof(*sound));
|
||||
|
||||
if (!sound)
|
||||
return NULL;
|
||||
|
||||
sound->type = AUDIO_MIXER_TYPE_FLAC;
|
||||
sound->types.flac.size = size;
|
||||
sound->types.flac.data = buffer;
|
||||
|
||||
return sound;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
audio_mixer_sound_t* audio_mixer_load_mod(void *buffer, int32_t size)
|
||||
{
|
||||
#ifdef HAVE_IBXM
|
||||
@ -386,6 +433,13 @@ void audio_mixer_destroy(audio_mixer_sound_t* sound)
|
||||
handle = (void*)sound->types.mod.data;
|
||||
if (handle)
|
||||
free(handle);
|
||||
#endif
|
||||
break;
|
||||
case AUDIO_MIXER_TYPE_FLAC:
|
||||
#ifdef HAVE_DR_FLAC
|
||||
handle = (void*)sound->types.flac.data;
|
||||
if (handle)
|
||||
free(handle);
|
||||
#endif
|
||||
break;
|
||||
case AUDIO_MIXER_TYPE_NONE:
|
||||
@ -436,7 +490,7 @@ static bool audio_mixer_play_ogg(
|
||||
goto error;
|
||||
}
|
||||
|
||||
samples = (unsigned)(AUDIO_MIXER_TEMP_OGG_BUFFER * ratio);
|
||||
samples = (unsigned)(AUDIO_MIXER_TEMP_BUFFER * ratio);
|
||||
ogg_buffer = (float*)memalign_alloc(16,
|
||||
((samples + 15) & ~15) * sizeof(float));
|
||||
|
||||
@ -531,6 +585,61 @@ error:
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAV_DR_FLAC
|
||||
static bool audio_mixer_play_flac(
|
||||
audio_mixer_sound_t* sound,
|
||||
audio_mixer_voice_t* voice,
|
||||
bool repeat, float volume,
|
||||
audio_mixer_stop_cb_t stop_cb)
|
||||
{
|
||||
int res = 0;
|
||||
float ratio = 1.0f;
|
||||
unsigned samples = 0;
|
||||
void *flac_buffer = NULL;
|
||||
void *resampler_data = NULL;
|
||||
const retro_resampler_t* resamp = NULL;
|
||||
drflac *dr_flac = drflac_open_memory((const unsigned char*)sound->types.flac.data,sound->types.flac.size);
|
||||
|
||||
|
||||
if (!dr_flac)
|
||||
return false;
|
||||
if (dr_flac->sampleRate != s_rate)
|
||||
{
|
||||
ratio = (double)s_rate / (double)(dr_flac->sampleRate);
|
||||
|
||||
if (!retro_resampler_realloc(&resampler_data,
|
||||
&resamp, NULL, RESAMPLER_QUALITY_DONTCARE,
|
||||
ratio))
|
||||
goto error;
|
||||
}
|
||||
|
||||
samples = (unsigned)(AUDIO_MIXER_TEMP_BUFFER * ratio);
|
||||
flac_buffer = (float*)memalign_alloc(16,
|
||||
((samples + 15) & ~15) * sizeof(float));
|
||||
|
||||
if (!flac_buffer)
|
||||
{
|
||||
resamp->free(resampler_data);
|
||||
goto error;
|
||||
}
|
||||
|
||||
voice->types.flac.resampler = resamp;
|
||||
voice->types.flac.resampler_data = resampler_data;
|
||||
voice->types.flac.buffer = (float*)flac_buffer;
|
||||
voice->types.flac.buf_samples = samples;
|
||||
voice->types.flac.ratio = ratio;
|
||||
voice->types.flac.stream = dr_flac;
|
||||
voice->types.flac.position = 0;
|
||||
voice->types.flac.samples = 0;
|
||||
|
||||
return true;
|
||||
|
||||
error:
|
||||
drflac_close(dr_flac);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
audio_mixer_voice_t* audio_mixer_play(audio_mixer_sound_t* sound, bool repeat,
|
||||
float volume, audio_mixer_stop_cb_t stop_cb)
|
||||
{
|
||||
@ -563,6 +672,11 @@ audio_mixer_voice_t* audio_mixer_play(audio_mixer_sound_t* sound, bool repeat,
|
||||
case AUDIO_MIXER_TYPE_MOD:
|
||||
#ifdef HAVE_IBXM
|
||||
res = audio_mixer_play_mod(sound, voice, repeat, volume, stop_cb);
|
||||
#endif
|
||||
break;
|
||||
case AUDIO_MIXER_TYPE_FLAC:
|
||||
#ifdef HAVE_DR_FLAC
|
||||
res = audio_mixer_play_flac(sound, voice, repeat, volume, stop_cb);
|
||||
#endif
|
||||
break;
|
||||
case AUDIO_MIXER_TYPE_NONE:
|
||||
@ -666,7 +780,7 @@ static void audio_mixer_mix_ogg(float* buffer, size_t num_frames,
|
||||
{
|
||||
int i;
|
||||
struct resampler_data info = { 0 };
|
||||
float temp_buffer[AUDIO_MIXER_TEMP_OGG_BUFFER] = { 0 };
|
||||
float temp_buffer[AUDIO_MIXER_TEMP_BUFFER] = { 0 };
|
||||
unsigned buf_free = (unsigned)(num_frames * 2);
|
||||
unsigned temp_samples = 0;
|
||||
float* pcm = NULL;
|
||||
@ -676,7 +790,7 @@ static void audio_mixer_mix_ogg(float* buffer, size_t num_frames,
|
||||
again:
|
||||
temp_samples = stb_vorbis_get_samples_float_interleaved(
|
||||
voice->types.ogg.stream, 2, temp_buffer,
|
||||
AUDIO_MIXER_TEMP_OGG_BUFFER) * 2;
|
||||
AUDIO_MIXER_TEMP_BUFFER) * 2;
|
||||
|
||||
if (temp_samples == 0)
|
||||
{
|
||||
@ -809,6 +923,78 @@ again:
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DR_FLAC
|
||||
static void audio_mixer_mix_flac(float* buffer, size_t num_frames,
|
||||
audio_mixer_voice_t* voice,
|
||||
float volume)
|
||||
{
|
||||
int i;
|
||||
struct resampler_data info = { 0 };
|
||||
float temp_buffer[AUDIO_MIXER_TEMP_BUFFER] = { 0 };
|
||||
unsigned buf_free = (unsigned)(num_frames * 2);
|
||||
unsigned temp_samples = 0;
|
||||
float* pcm = NULL;
|
||||
|
||||
if (voice->types.flac.position == voice->types.flac.samples)
|
||||
{
|
||||
again:
|
||||
temp_samples = drflac_read_f32( voice->types.flac.stream, AUDIO_MIXER_TEMP_BUFFER, temp_buffer);
|
||||
if (temp_samples == 0)
|
||||
{
|
||||
if (voice->repeat)
|
||||
{
|
||||
if (voice->stop_cb)
|
||||
voice->stop_cb(voice->sound, AUDIO_MIXER_SOUND_REPEATED);
|
||||
|
||||
drflac_seek_to_sample(voice->types.flac.stream,0);
|
||||
goto again;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (voice->stop_cb)
|
||||
voice->stop_cb(voice->sound, AUDIO_MIXER_SOUND_FINISHED);
|
||||
|
||||
voice->type = AUDIO_MIXER_TYPE_NONE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
info.data_in = temp_buffer;
|
||||
info.data_out = voice->types.flac.buffer;
|
||||
info.input_frames = temp_samples / 2;
|
||||
info.output_frames = 0;
|
||||
info.ratio = voice->types.flac.ratio;
|
||||
|
||||
if (voice->types.flac.resampler)
|
||||
voice->types.ogg.resampler->process(voice->types.flac.resampler_data, &info);
|
||||
else
|
||||
memcpy(voice->types.flac.buffer, temp_buffer, temp_samples * sizeof(float));
|
||||
voice->types.flac.position = 0;
|
||||
voice->types.flac.samples = voice->types.flac.buf_samples;
|
||||
}
|
||||
|
||||
pcm = voice->types.flac.buffer + voice->types.flac.position;
|
||||
|
||||
if (voice->types.flac.samples < buf_free)
|
||||
{
|
||||
for (i = voice->types.flac.samples; i != 0; i--)
|
||||
*buffer++ += *pcm++ * volume;
|
||||
|
||||
buf_free -= voice->types.flac.samples;
|
||||
goto again;
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
for (i = buf_free; i != 0; --i )
|
||||
*buffer++ += *pcm++ * volume;
|
||||
|
||||
voice->types.flac.position += buf_free;
|
||||
voice->types.flac.samples -= buf_free;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void audio_mixer_mix(float* buffer, size_t num_frames, float volume_override, bool override)
|
||||
{
|
||||
unsigned i;
|
||||
@ -837,6 +1023,11 @@ void audio_mixer_mix(float* buffer, size_t num_frames, float volume_override, bo
|
||||
case AUDIO_MIXER_TYPE_MOD:
|
||||
#ifdef HAVE_IBXM
|
||||
audio_mixer_mix_mod(buffer, num_frames, voice, volume);
|
||||
#endif
|
||||
break;
|
||||
case AUDIO_MIXER_TYPE_FLAC:
|
||||
#ifdef HAVE_DR_FLAC
|
||||
audio_mixer_mix_flac(buffer, num_frames, voice, volume);
|
||||
#endif
|
||||
break;
|
||||
case AUDIO_MIXER_TYPE_NONE:
|
||||
|
@ -392,7 +392,7 @@ char *path_remove_extension(char *path)
|
||||
return NULL;
|
||||
if (*last)
|
||||
*last = '\0';
|
||||
return last;
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -41,7 +41,8 @@ enum audio_mixer_type
|
||||
AUDIO_MIXER_TYPE_NONE = 0,
|
||||
AUDIO_MIXER_TYPE_WAV,
|
||||
AUDIO_MIXER_TYPE_OGG,
|
||||
AUDIO_MIXER_TYPE_MOD
|
||||
AUDIO_MIXER_TYPE_MOD,
|
||||
AUDIO_MIXER_TYPE_FLAC
|
||||
};
|
||||
|
||||
typedef struct audio_mixer_sound audio_mixer_sound_t;
|
||||
@ -61,6 +62,7 @@ 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_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);
|
||||
|
||||
void audio_mixer_destroy(audio_mixer_sound_t* sound);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user