Cleanups in audio mixer code

This commit is contained in:
twinaphex 2020-06-28 23:24:00 +02:00
parent 6d50ac7cb7
commit a833c5f4a6
2 changed files with 145 additions and 115 deletions

View File

@ -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;

View File

@ -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;