twn_audio.c: only apply volume scaling on mixing of different streams
This commit is contained in:
parent
6a029b7e79
commit
bf3eb50b55
@ -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,22 +365,30 @@ 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);
|
||||||
|
|
||||||
|
if (last) {
|
||||||
|
for (size_t s = 0; s < frames; ++s) {
|
||||||
|
/* left channel */
|
||||||
|
sa[s * 2 + 0] += (float)(sb[s * 2 + 0] * channel->volume * left_panning);
|
||||||
|
/* right channel */
|
||||||
|
sa[s * 2 + 1] += (float)(sb[s * 2 + 1] * channel->volume * right_panning);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
for (size_t s = 0; s < frames; ++s) {
|
for (size_t s = 0; s < frames; ++s) {
|
||||||
/* left channel */
|
/* left channel */
|
||||||
sa[s * 2 + 0] += (float)(sb[s * 2 + 0] * channel->volume * left_panning);
|
sa[s * 2 + 0] += (float)(sb[s * 2 + 0] * channel->volume * left_panning);
|
||||||
sa[s * 2 + 0] *= 1 / (float)M_2_SQRTPI;
|
sa[s * 2 + 0] *= 1 / (float)M_2_SQRTPI;
|
||||||
|
|
||||||
/* 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;
|
sa[s * 2 + 1] *= 1 / (float)M_2_SQRTPI;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* 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);
|
||||||
|
Loading…
Reference in New Issue
Block a user