twn_audio.c: only apply volume scaling on mixing of different streams

This commit is contained in:
veclavtalica 2025-01-26 11:08:13 +03:00
parent 6a029b7e79
commit bf3eb50b55

View File

@ -356,7 +356,8 @@ TWN_API void audio_parameter(const char *channel, const char *param, float value
static void audio_mixin_streams(const AudioChannel *channel, static void audio_mixin_streams(const AudioChannel *channel,
uint8_t *restrict a, uint8_t *restrict a,
uint8_t *restrict b, uint8_t *restrict b,
size_t frames) size_t frames,
bool last)
{ {
float *const sa = (float *)(void *)a; float *const sa = (float *)(void *)a;
float *const sb = (float *)(void *)b; float *const sb = (float *)(void *)b;
@ -364,14 +365,22 @@ static void audio_mixin_streams(const AudioChannel *channel,
const float left_panning = fminf(fabsf(channel->panning - 1.0f), 1.0f); const float left_panning = fminf(fabsf(channel->panning - 1.0f), 1.0f);
const float right_panning = fminf(fabsf(channel->panning + 1.0f), 1.0f); const float right_panning = fminf(fabsf(channel->panning + 1.0f), 1.0f);
for (size_t s = 0; s < frames; ++s) { if (last) {
/* left channel */ for (size_t s = 0; s < frames; ++s) {
sa[s * 2 + 0] += (float)(sb[s * 2 + 0] * channel->volume * left_panning); /* left channel */
sa[s * 2 + 0] *= 1 / (float)M_2_SQRTPI; sa[s * 2 + 0] += (float)(sb[s * 2 + 0] * channel->volume * left_panning);
/* right channel */
/* right channel */ sa[s * 2 + 1] += (float)(sb[s * 2 + 1] * channel->volume * right_panning);
sa[s * 2 + 1] += (float)(sb[s * 2 + 1] * channel->volume * right_panning); }
sa[s * 2 + 1] *= 1 / (float)M_2_SQRTPI; } else {
for (size_t s = 0; s < frames; ++s) {
/* left channel */
sa[s * 2 + 0] += (float)(sb[s * 2 + 0] * channel->volume * left_panning);
sa[s * 2 + 0] *= 1 / (float)M_2_SQRTPI;
/* right channel */
sa[s * 2 + 1] += (float)(sb[s * 2 + 1] * channel->volume * right_panning);
sa[s * 2 + 1] *= 1 / (float)M_2_SQRTPI;
}
} }
} }
@ -379,7 +388,7 @@ static void audio_mixin_streams(const AudioChannel *channel,
/* remember: frame consists of sample * channel_count */ /* remember: frame consists of sample * channel_count */
static void audio_sample_and_mixin_channel(AudioChannel *channel, static void audio_sample_and_mixin_channel(AudioChannel *channel,
uint8_t *stream, uint8_t *stream,
int len) int len, bool last)
{ {
static uint8_t buffer[16384]; /* TODO: better make it a growable scratch instead, which will simplify things */ static uint8_t buffer[16384]; /* TODO: better make it a growable scratch instead, which will simplify things */
const size_t float_buffer_frames = sizeof (buffer) / sizeof (float) / 2; const size_t float_buffer_frames = sizeof (buffer) / sizeof (float) / 2;
@ -414,7 +423,8 @@ static void audio_sample_and_mixin_channel(AudioChannel *channel,
/* panning and mixing */ /* panning and mixing */
audio_mixin_streams(channel, audio_mixin_streams(channel,
&stream[i * sizeof(float) * 2], buffer, &stream[i * sizeof(float) * 2], buffer,
samples_per_channel); samples_per_channel,
last);
i += samples_per_channel; i += samples_per_channel;
} }
@ -431,7 +441,8 @@ static void audio_sample_and_mixin_channel(AudioChannel *channel,
audio_mixin_streams(channel, audio_mixin_streams(channel,
&stream[i * sizeof(float) * 2], &stream[i * sizeof(float) * 2],
&((uint8_t *)channel->context.wav.samples)[channel->context.wav.position * sizeof (float) * 2], &((uint8_t *)channel->context.wav.samples)[channel->context.wav.position * sizeof (float) * 2],
limit); limit,
last);
channel->context.wav.position += limit; channel->context.wav.position += limit;
@ -477,7 +488,8 @@ static void audio_sample_and_mixin_channel(AudioChannel *channel,
audio_mixin_streams(channel, audio_mixin_streams(channel,
&stream[i * sizeof(float) * 2], &stream[i * sizeof(float) * 2],
buffer, buffer,
samples_per_channel); samples_per_channel,
last);
i += samples_per_channel; i += samples_per_channel;
} }
@ -509,19 +521,25 @@ void audio_callback(void *userdata, uint8_t *stream, int len) {
/* prepare for mixing */ /* prepare for mixing */
SDL_memset(stream, 0, len); SDL_memset(stream, 0, len);
for (int i = 0; i < shlen(ctx.audio_channels); ++i) { size_t const audio_channels_len = shlen(ctx.audio_channels);
for (size_t i = 0; i < audio_channels_len; ++i) {
sanity_check_channel(&ctx.audio_channels[i].value); sanity_check_channel(&ctx.audio_channels[i].value);
audio_sample_and_mixin_channel(&ctx.audio_channels[i].value, stream, len); audio_sample_and_mixin_channel(&ctx.audio_channels[i].value,
stream, len,
i == audio_channels_len - 1);
} }
for (int i = 0; i < arrlen(ctx.unnamed_audio_channels); ++i) { size_t const unnamed_audio_channels_len = shlen(ctx.unnamed_audio_channels);
for (size_t i = 0; i < unnamed_audio_channels_len; ++i) {
sanity_check_channel(&ctx.unnamed_audio_channels[i]); sanity_check_channel(&ctx.unnamed_audio_channels[i]);
audio_sample_and_mixin_channel(&ctx.unnamed_audio_channels[i], stream, len); audio_sample_and_mixin_channel(&ctx.unnamed_audio_channels[i],
stream, len,
i == unnamed_audio_channels_len - 1);
} }
/* ditch finished unnamed */ /* ditch finished unnamed */
int i = 0; size_t i = 0;
while (i < arrlen(ctx.unnamed_audio_channels)) { while (i < unnamed_audio_channels_len) {
if (ctx.unnamed_audio_channels[i].finished) { if (ctx.unnamed_audio_channels[i].finished) {
free_audio_channel(ctx.unnamed_audio_channels[i]); free_audio_channel(ctx.unnamed_audio_channels[i]);
arrdelswap(ctx.unnamed_audio_channels, i); arrdelswap(ctx.unnamed_audio_channels, i);