twn_audio: rework interface

This commit is contained in:
2024-10-07 15:21:44 +03:00
parent cc1e64531c
commit ae8cc5f50b
5 changed files with 96 additions and 94 deletions

View File

@ -54,15 +54,6 @@ static int64_t get_audio_data(const char *path, unsigned char **data) {
}
void audio_play(const char *path, const char *channel) {
const AudioChannelItem *pair = shgetp_null(ctx.audio_channels, channel);
if (!pair)
audio_play_ex(path, channel, audio_get_default_args());
else
audio_play_ex(path, channel, pair->value.args);
}
static AudioFileType infer_audio_file_type(const char *path) {
size_t path_len = SDL_strlen(path);
@ -163,18 +154,25 @@ static void repeat_audio(AudioChannel *channel) {
}
void audio_play_ex(const char *path, const char *channel, PlayAudioArgs args) {
void audio_play(const char *path,
const char *channel,
bool repeat,
float volume,
float panning)
{
AudioChannelItem *pair = shgetp_null(ctx.audio_channels, channel);
/* create a channel if it doesn't exist */
if (!pair) {
AudioFileType file_type = infer_audio_file_type(path);
AudioChannel new_channel = {
.args = args,
.file_type = file_type,
.context = init_audio_context(path, file_type),
.path = path,
.name = channel,
.repeat = repeat,
.volume = volume,
.panning = panning,
};
shput(ctx.audio_channels, channel, new_channel);
pair = shgetp_null(ctx.audio_channels, channel);
@ -188,22 +186,40 @@ void audio_play_ex(const char *path, const char *channel, PlayAudioArgs args) {
}
PlayAudioArgs *audio_get_args(const char *channel) {
TWN_API void audio_set(const char *channel, AudioParam param, float value) {
AudioChannelItem *pair = shgetp_null(ctx.audio_channels, channel);
if (!pair)
return NULL;
if (!pair) {
log_warn("No channel by the name of %s to set a parameter for", channel);
return;
}
return &pair->value.args;
}
PlayAudioArgs audio_get_default_args(void) {
return (PlayAudioArgs){
.repeat = false,
.crossfade = false,
.volume = 1.0f,
.panning = 0.0f,
};
switch (param) {
case AUDIO_PARAM_REPEAT:
pair->value.repeat = (bool)value;
break;
case AUDIO_PARAM_VOLUME:
if (value > 1.0f) {
log_warn("Out of range volume for channel %s set", channel);
value = 1.0f;
}
if (value < 0.0f) {
log_warn("Out of range volume for channel %s set", channel);
value = 0.0f;
}
pair->value.volume = value;
break;
case AUDIO_PARAM_PANNING:
if (value > 1.0f) {
log_warn("Out of range panning for channel %s set", channel);
value = 1.0f;
}
if (value < -1.0f) {
log_warn("Out of range panning for channel %s set", channel);
value = -1.0f;
}
pair->value.panning = value;
break;
}
}
@ -216,15 +232,15 @@ static void audio_mixin_streams(const AudioChannel *channel,
float *const sa = (float *)a;
float *const sb = (float *)b;
const float left_panning = fminf(fabsf(channel->args.panning - 1.0f), 1.0f);
const float right_panning = fminf(fabsf(channel->args.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);
for (size_t s = 0; s < frames; s += 2) {
/* left channel */
sa[s] += (float)(sb[s] * channel->args.volume * left_panning);
sa[s] += (float)(sb[s] * channel->volume * left_panning);
/* right channel */
sa[s + 1] += (float)(sb[s + 1] * channel->args.volume * right_panning);
sa[s + 1] += (float)(sb[s + 1] * channel->volume * right_panning);
}
}
@ -253,7 +269,7 @@ static void audio_sample_and_mixin_channel(const AudioChannel *channel,
/* handle end of file */
if (samples_per_channel == 0) {
if (channel->args.repeat) {
if (channel->repeat) {
/* seek to start and try sampling some more */
stb_vorbis_seek_start(channel->context.vorbis.handle);
continue;
@ -284,7 +300,7 @@ static void audio_sample_and_mixin_channel(const AudioChannel *channel,
/* handle end of file */
if (samples_per_channel == 0) {
if (channel->args.repeat) {
if (channel->repeat) {
/* seek to start and try sampling some more */
xm_restart(channel->context.xm.handle);
continue;
@ -313,10 +329,10 @@ static void audio_sample_and_mixin_channel(const AudioChannel *channel,
static void sanity_check_channel(const AudioChannel *channel) {
if (channel->args.volume < 0.0f || channel->args.volume > 1.0f)
if (channel->volume < 0.0f || channel->volume > 1.0f)
log_warn("Volume argument is out of range for channel (%s)", channel->name);
if (channel->args.panning < -1.0f || channel->args.panning > 1.0f)
if (channel->panning < -1.0f || channel->panning > 1.0f)
log_warn("Panning argument is out of range for channel (%s)", channel->name);
}
@ -332,3 +348,11 @@ void audio_callback(void *userdata, uint8_t *stream, int len) {
audio_sample_and_mixin_channel(&ctx.audio_channels[i].value, stream, len);
}
}
TWN_API void audio_play_args(PlayAudioArgs args) {
const char *channel = m_or(args, channel, NULL);
const bool repeat = m_or(args, repeat, false);
const float volume = m_or(args, volume, 1.0f);
const float panning = m_or(args, panning, 0.0f);
audio_play(args.path, channel, repeat, volume, panning);
}

View File

@ -36,11 +36,13 @@ union AudioContext {
typedef struct AudioChannel {
PlayAudioArgs args;
AudioFileType file_type;
union AudioContext context; /* interpreted by `file_type` value */
const char *path;
const char *name;
bool repeat;
float volume;
float panning;
} AudioChannel;