mirror of
https://github.com/libretro/RetroArch
synced 2025-01-31 15:32:59 +00:00
Cleanups in audio mixer code
This commit is contained in:
parent
6d50ac7cb7
commit
a833c5f4a6
@ -115,7 +115,7 @@ audio_chunk_t* audio_mix_load_wav_file(const char *path, int sample_rate)
|
||||
int sample_size;
|
||||
int64_t len = 0;
|
||||
void *buf = NULL;
|
||||
audio_chunk_t *chunk = (audio_chunk_t*)calloc(1, sizeof(*chunk));
|
||||
audio_chunk_t *chunk = (audio_chunk_t*)malloc(sizeof(*chunk));
|
||||
|
||||
if (!chunk)
|
||||
return NULL;
|
||||
@ -126,10 +126,26 @@ audio_chunk_t* audio_mix_load_wav_file(const char *path, int sample_rate)
|
||||
goto error;
|
||||
}
|
||||
|
||||
chunk->sample_rate = sample_rate;
|
||||
chunk->buf = buf;
|
||||
chunk->len = len;
|
||||
chunk->rwav = (rwav_t*)malloc(sizeof(rwav_t));
|
||||
chunk->buf = buf;
|
||||
chunk->upsample_buf = NULL;
|
||||
chunk->float_buf = NULL;
|
||||
chunk->float_resample_buf = NULL;
|
||||
chunk->resample_buf = NULL;
|
||||
chunk->len = len;
|
||||
chunk->resample_len = 0;
|
||||
chunk->rwav = (rwav_t*)malloc(sizeof(rwav_t));
|
||||
chunk->sample_rate = sample_rate;
|
||||
chunk->resample = false;
|
||||
chunk->resampler = NULL;
|
||||
chunk->resampler_data = NULL;
|
||||
chunk->ratio = 0.00f;
|
||||
|
||||
chunk->rwav->bitspersample = 0;
|
||||
chunk->rwav->numchannels = 0;
|
||||
chunk->rwav->samplerate = 0;
|
||||
chunk->rwav->numsamples = 0;
|
||||
chunk->rwav->subchunk2size = 0;
|
||||
chunk->rwav->samples = NULL;
|
||||
|
||||
if (rwav_load(chunk->rwav, chunk->buf, chunk->len) == RWAV_ITERATE_ERROR)
|
||||
{
|
||||
@ -139,28 +155,42 @@ audio_chunk_t* audio_mix_load_wav_file(const char *path, int sample_rate)
|
||||
|
||||
/* numsamples does not know or care about
|
||||
* multiple channels, but we need space for 2 */
|
||||
chunk->upsample_buf = (int16_t*)memalign_alloc(128,
|
||||
chunk->upsample_buf = (int16_t*)memalign_alloc(128,
|
||||
chunk->rwav->numsamples * 2 * sizeof(int16_t));
|
||||
|
||||
sample_size = chunk->rwav->bitspersample / 8;
|
||||
sample_size = chunk->rwav->bitspersample / 8;
|
||||
|
||||
if (sample_size == 1)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < chunk->rwav->numsamples; i++)
|
||||
{
|
||||
uint8_t *sample = (
|
||||
(uint8_t*)chunk->rwav->samples) +
|
||||
(i * chunk->rwav->numchannels);
|
||||
if (chunk->rwav->numchannels == 1)
|
||||
{
|
||||
for (i = 0; i < chunk->rwav->numsamples; i++)
|
||||
{
|
||||
uint8_t *sample = (
|
||||
(uint8_t*)chunk->rwav->samples) + i;
|
||||
|
||||
chunk->upsample_buf[i * 2] = (int16_t)((sample[0] - 128) << 8);
|
||||
chunk->upsample_buf[i * 2] =
|
||||
(int16_t)((sample[0] - 128) << 8);
|
||||
chunk->upsample_buf[(i * 2) + 1] =
|
||||
(int16_t)((sample[0] - 128) << 8);
|
||||
}
|
||||
}
|
||||
else if (chunk->rwav->numchannels == 2)
|
||||
{
|
||||
for (i = 0; i < chunk->rwav->numsamples; i++)
|
||||
{
|
||||
uint8_t *sample = (
|
||||
(uint8_t*)chunk->rwav->samples) +
|
||||
(i * 2);
|
||||
|
||||
if (chunk->rwav->numchannels == 1)
|
||||
chunk->upsample_buf[(i * 2) + 1] = (int16_t)((sample[0] - 128) << 8);
|
||||
else if (chunk->rwav->numchannels == 2)
|
||||
chunk->upsample_buf[(i * 2) + 1] = (int16_t)((sample[1] - 128) << 8);
|
||||
}
|
||||
chunk->upsample_buf[i * 2] =
|
||||
(int16_t)((sample[0] - 128) << 8);
|
||||
chunk->upsample_buf[(i * 2) + 1] =
|
||||
(int16_t)((sample[1] - 128) << 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (sample_size == 2)
|
||||
{
|
||||
@ -170,14 +200,16 @@ audio_chunk_t* audio_mix_load_wav_file(const char *path, int sample_rate)
|
||||
|
||||
for (i = 0; i < chunk->rwav->numsamples; i++)
|
||||
{
|
||||
int16_t sample = ((int16_t*)chunk->rwav->samples)[i];
|
||||
int16_t sample = ((int16_t*)
|
||||
chunk->rwav->samples)[i];
|
||||
|
||||
chunk->upsample_buf[i * 2] = sample;
|
||||
chunk->upsample_buf[(i * 2) + 1] = sample;
|
||||
}
|
||||
}
|
||||
else if (chunk->rwav->numchannels == 2)
|
||||
memcpy(chunk->upsample_buf, chunk->rwav->samples, chunk->rwav->subchunk2size);
|
||||
memcpy(chunk->upsample_buf, chunk->rwav->samples,
|
||||
chunk->rwav->subchunk2size);
|
||||
}
|
||||
else if (sample_size != 2)
|
||||
{
|
||||
@ -189,7 +221,7 @@ audio_chunk_t* audio_mix_load_wav_file(const char *path, int sample_rate)
|
||||
if (sample_rate != (int)chunk->rwav->samplerate)
|
||||
{
|
||||
chunk->resample = true;
|
||||
chunk->ratio = (double)sample_rate / chunk->rwav->samplerate;
|
||||
chunk->ratio = (double)sample_rate / chunk->rwav->samplerate;
|
||||
|
||||
retro_resampler_realloc(&chunk->resampler_data,
|
||||
&chunk->resampler,
|
||||
@ -201,12 +233,18 @@ audio_chunk_t* audio_mix_load_wav_file(const char *path, int sample_rate)
|
||||
{
|
||||
struct resampler_data info;
|
||||
|
||||
chunk->float_buf = (float*)memalign_alloc(128, chunk->rwav->numsamples * 2 * chunk->ratio * sizeof(float));
|
||||
chunk->float_buf = (float*)memalign_alloc(128,
|
||||
chunk->rwav->numsamples * 2 *
|
||||
chunk->ratio * sizeof(float));
|
||||
|
||||
/* why is *3 needed instead of just *2? does the sinc driver require more space than we know about? */
|
||||
chunk->float_resample_buf = (float*)memalign_alloc(128, chunk->rwav->numsamples * 3 * chunk->ratio * sizeof(float));
|
||||
/* why is *3 needed instead of just *2? Does the
|
||||
* sinc driver require more space than we know about? */
|
||||
chunk->float_resample_buf = (float*)memalign_alloc(128,
|
||||
chunk->rwav->numsamples * 3 *
|
||||
chunk->ratio * sizeof(float));
|
||||
|
||||
convert_s16_to_float(chunk->float_buf, chunk->upsample_buf, chunk->rwav->numsamples * 2, 1.0);
|
||||
convert_s16_to_float(chunk->float_buf,
|
||||
chunk->upsample_buf, chunk->rwav->numsamples * 2, 1.0);
|
||||
|
||||
info.data_in = (const float*)chunk->float_buf;
|
||||
info.data_out = chunk->float_resample_buf;
|
||||
@ -218,10 +256,13 @@ audio_chunk_t* audio_mix_load_wav_file(const char *path, int sample_rate)
|
||||
|
||||
chunk->resampler->process(chunk->resampler_data, &info);
|
||||
|
||||
/* number of output_frames does not increase with multiple channels, but assume we need space for 2 */
|
||||
chunk->resample_buf = (int16_t*)memalign_alloc(128, info.output_frames * 2 * sizeof(int16_t));
|
||||
/* number of output_frames does not increase with
|
||||
* multiple channels, but assume we need space for 2 */
|
||||
chunk->resample_buf = (int16_t*)memalign_alloc(128,
|
||||
info.output_frames * 2 * sizeof(int16_t));
|
||||
chunk->resample_len = info.output_frames;
|
||||
convert_float_to_s16(chunk->resample_buf, chunk->float_resample_buf, info.output_frames * 2);
|
||||
convert_float_to_s16(chunk->resample_buf,
|
||||
chunk->float_resample_buf, info.output_frames * 2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -258,7 +299,8 @@ size_t audio_mix_get_chunk_num_samples(audio_chunk_t *chunk)
|
||||
*
|
||||
* Returns: A signed 16-bit audio sample.
|
||||
**/
|
||||
int16_t audio_mix_get_chunk_sample(audio_chunk_t *chunk, unsigned channel, size_t index)
|
||||
int16_t audio_mix_get_chunk_sample(audio_chunk_t *chunk,
|
||||
unsigned channel, size_t index)
|
||||
{
|
||||
if (!chunk)
|
||||
return 0;
|
||||
@ -273,10 +315,12 @@ int16_t audio_mix_get_chunk_sample(audio_chunk_t *chunk, unsigned channel, size_
|
||||
|
||||
if (chunk->resample)
|
||||
sample = (uint8_t*)chunk->resample_buf +
|
||||
(sample_size * index * chunk->rwav->numchannels) + (channel * sample_size);
|
||||
(sample_size * index * chunk->rwav->numchannels)
|
||||
+ (channel * sample_size);
|
||||
else
|
||||
sample = (uint8_t*)chunk->upsample_buf +
|
||||
(sample_size * index * chunk->rwav->numchannels) + (channel * sample_size);
|
||||
(sample_size * index * chunk->rwav->numchannels)
|
||||
+ (channel * sample_size);
|
||||
|
||||
sample_out = (int16_t)*sample;
|
||||
|
||||
|
@ -184,10 +184,11 @@ struct audio_mixer_voice
|
||||
} types;
|
||||
};
|
||||
|
||||
/* TODO/FIXME - static globals */
|
||||
static struct audio_mixer_voice s_voices[AUDIO_MIXER_MAX_VOICES] = {{0}};
|
||||
static unsigned s_rate = 0;
|
||||
|
||||
static bool wav2float(const rwav_t* wav, float** pcm, size_t samples_out)
|
||||
static bool wav_to_float(const rwav_t* wav, float** pcm, size_t samples_out)
|
||||
{
|
||||
size_t i;
|
||||
/* Allocate on a 16-byte boundary, and pad to a multiple of 16 bytes */
|
||||
@ -334,7 +335,7 @@ audio_mixer_sound_t* audio_mixer_load_wav(void *buffer, int32_t size)
|
||||
|
||||
samples = wav.numsamples * 2;
|
||||
|
||||
if (!wav2float(&wav, &pcm, samples))
|
||||
if (!wav_to_float(&wav, &pcm, samples))
|
||||
return NULL;
|
||||
|
||||
if (wav.samplerate != s_rate)
|
||||
@ -839,8 +840,8 @@ void audio_mixer_stop(audio_mixer_voice_t* voice)
|
||||
|
||||
if (voice)
|
||||
{
|
||||
stop_cb = voice->stop_cb;
|
||||
sound = voice->sound;
|
||||
stop_cb = voice->stop_cb;
|
||||
sound = voice->sound;
|
||||
|
||||
voice->type = AUDIO_MIXER_TYPE_NONE;
|
||||
|
||||
@ -899,7 +900,7 @@ static void audio_mixer_mix_ogg(float* buffer, size_t num_frames,
|
||||
float volume)
|
||||
{
|
||||
int i;
|
||||
struct resampler_data info = { 0 };
|
||||
struct resampler_data info;
|
||||
float temp_buffer[AUDIO_MIXER_TEMP_BUFFER] = { 0 };
|
||||
unsigned buf_free = (unsigned)(num_frames * 2);
|
||||
unsigned temp_samples = 0;
|
||||
@ -922,14 +923,12 @@ again:
|
||||
stb_vorbis_seek_start(voice->types.ogg.stream);
|
||||
goto again;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (voice->stop_cb)
|
||||
voice->stop_cb(voice->sound, AUDIO_MIXER_SOUND_FINISHED);
|
||||
|
||||
voice->type = AUDIO_MIXER_TYPE_NONE;
|
||||
return;
|
||||
}
|
||||
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;
|
||||
@ -939,11 +938,12 @@ again:
|
||||
info.ratio = voice->types.ogg.ratio;
|
||||
|
||||
if (voice->types.ogg.resampler)
|
||||
{
|
||||
voice->types.ogg.resampler->process(voice->types.ogg.resampler_data, &info);
|
||||
}
|
||||
voice->types.ogg.resampler->process(
|
||||
voice->types.ogg.resampler_data, &info);
|
||||
else
|
||||
memcpy(voice->types.ogg.buffer, temp_buffer, temp_samples * sizeof(float));
|
||||
memcpy(voice->types.ogg.buffer, temp_buffer,
|
||||
temp_samples * sizeof(float));
|
||||
|
||||
voice->types.ogg.position = 0;
|
||||
voice->types.ogg.samples = voice->types.ogg.buf_samples;
|
||||
}
|
||||
@ -958,15 +958,12 @@ again:
|
||||
buf_free -= voice->types.ogg.samples;
|
||||
goto again;
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
for (i = buf_free; i != 0; --i )
|
||||
*buffer++ += *pcm++ * volume;
|
||||
|
||||
voice->types.ogg.position += buf_free;
|
||||
voice->types.ogg.samples -= buf_free;
|
||||
}
|
||||
for (i = buf_free; i != 0; --i )
|
||||
*buffer++ += *pcm++ * volume;
|
||||
|
||||
voice->types.ogg.position += buf_free;
|
||||
voice->types.ogg.samples -= buf_free;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1000,14 +997,12 @@ again:
|
||||
replay_seek( voice->types.mod.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;
|
||||
}
|
||||
if (voice->stop_cb)
|
||||
voice->stop_cb(voice->sound, AUDIO_MIXER_SOUND_FINISHED);
|
||||
|
||||
voice->type = AUDIO_MIXER_TYPE_NONE;
|
||||
return;
|
||||
}
|
||||
|
||||
voice->types.mod.position = 0;
|
||||
@ -1028,20 +1023,17 @@ again:
|
||||
buf_free -= voice->types.mod.samples;
|
||||
goto again;
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
for (i = buf_free; i != 0; --i )
|
||||
{
|
||||
samplei = *pcm++ * volume;
|
||||
samplef = (float)((int)samplei + 32768) / 65535.0f;
|
||||
samplef = samplef * 2.0f - 1.0f;
|
||||
*buffer++ += samplef;
|
||||
}
|
||||
|
||||
voice->types.mod.position += buf_free;
|
||||
voice->types.mod.samples -= buf_free;
|
||||
for (i = buf_free; i != 0; --i )
|
||||
{
|
||||
samplei = *pcm++ * volume;
|
||||
samplef = (float)((int)samplei + 32768) / 65535.0f;
|
||||
samplef = samplef * 2.0f - 1.0f;
|
||||
*buffer++ += samplef;
|
||||
}
|
||||
|
||||
voice->types.mod.position += buf_free;
|
||||
voice->types.mod.samples -= buf_free;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1051,11 +1043,11 @@ static void audio_mixer_mix_flac(float* buffer, size_t num_frames,
|
||||
float volume)
|
||||
{
|
||||
int i;
|
||||
struct resampler_data info = { 0 };
|
||||
struct resampler_data info;
|
||||
float temp_buffer[AUDIO_MIXER_TEMP_BUFFER] = { 0 };
|
||||
unsigned buf_free = (unsigned)(num_frames * 2);
|
||||
unsigned temp_samples = 0;
|
||||
float* pcm = NULL;
|
||||
float *pcm = NULL;
|
||||
|
||||
if (voice->types.flac.position == voice->types.flac.samples)
|
||||
{
|
||||
@ -1071,14 +1063,12 @@ again:
|
||||
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;
|
||||
}
|
||||
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;
|
||||
@ -1088,11 +1078,10 @@ again:
|
||||
info.ratio = voice->types.flac.ratio;
|
||||
|
||||
if (voice->types.flac.resampler)
|
||||
{
|
||||
voice->types.flac.resampler->process(voice->types.flac.resampler_data, &info);
|
||||
}
|
||||
voice->types.flac.resampler->process(
|
||||
voice->types.flac.resampler_data, &info);
|
||||
else
|
||||
memcpy(voice->types.flac.buffer, temp_buffer, temp_samples * sizeof(float));
|
||||
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;
|
||||
}
|
||||
@ -1107,15 +1096,12 @@ again:
|
||||
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;
|
||||
}
|
||||
for (i = buf_free; i != 0; --i )
|
||||
*buffer++ += *pcm++ * volume;
|
||||
|
||||
voice->types.flac.position += buf_free;
|
||||
voice->types.flac.samples -= buf_free;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1125,7 +1111,7 @@ static void audio_mixer_mix_mp3(float* buffer, size_t num_frames,
|
||||
float volume)
|
||||
{
|
||||
int i;
|
||||
struct resampler_data info = { 0 };
|
||||
struct resampler_data info;
|
||||
float temp_buffer[AUDIO_MIXER_TEMP_BUFFER] = { 0 };
|
||||
unsigned buf_free = (unsigned)(num_frames * 2);
|
||||
unsigned temp_samples = 0;
|
||||
@ -1134,7 +1120,9 @@ static void audio_mixer_mix_mp3(float* buffer, size_t num_frames,
|
||||
if (voice->types.mp3.position == voice->types.mp3.samples)
|
||||
{
|
||||
again:
|
||||
temp_samples = (unsigned)drmp3_read_f32(&voice->types.mp3.stream, AUDIO_MIXER_TEMP_BUFFER/2, temp_buffer) * 2;
|
||||
temp_samples = (unsigned)drmp3_read_f32(
|
||||
&voice->types.mp3.stream,
|
||||
AUDIO_MIXER_TEMP_BUFFER / 2, temp_buffer) * 2;
|
||||
|
||||
if (temp_samples == 0)
|
||||
{
|
||||
@ -1146,14 +1134,12 @@ again:
|
||||
drmp3_seek_to_frame(&voice->types.mp3.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;
|
||||
}
|
||||
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;
|
||||
@ -1163,9 +1149,11 @@ again:
|
||||
info.ratio = voice->types.mp3.ratio;
|
||||
|
||||
if (voice->types.mp3.resampler)
|
||||
voice->types.mp3.resampler->process(voice->types.mp3.resampler_data, &info);
|
||||
voice->types.mp3.resampler->process(
|
||||
voice->types.mp3.resampler_data, &info);
|
||||
else
|
||||
memcpy(voice->types.mp3.buffer, temp_buffer, temp_samples * sizeof(float));
|
||||
memcpy(voice->types.mp3.buffer, temp_buffer,
|
||||
temp_samples * sizeof(float));
|
||||
voice->types.mp3.position = 0;
|
||||
voice->types.mp3.samples = voice->types.mp3.buf_samples;
|
||||
}
|
||||
@ -1180,19 +1168,17 @@ again:
|
||||
buf_free -= voice->types.mp3.samples;
|
||||
goto again;
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
for (i = buf_free; i != 0; --i )
|
||||
*buffer++ += *pcm++ * volume;
|
||||
|
||||
voice->types.mp3.position += buf_free;
|
||||
voice->types.mp3.samples -= buf_free;
|
||||
}
|
||||
for (i = buf_free; i != 0; --i )
|
||||
*buffer++ += *pcm++ * volume;
|
||||
|
||||
voice->types.mp3.position += buf_free;
|
||||
voice->types.mp3.samples -= buf_free;
|
||||
}
|
||||
#endif
|
||||
|
||||
void audio_mixer_mix(float* buffer, size_t num_frames, float volume_override, bool override)
|
||||
void audio_mixer_mix(float* buffer, size_t num_frames,
|
||||
float volume_override, bool override)
|
||||
{
|
||||
unsigned i;
|
||||
size_t j = 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user