twn_audio: settle down on float32 2-channel sampling only, format enums to style used elsewhere
This commit is contained in:
parent
57fe5e8946
commit
a0ea657eb9
@ -16,7 +16,6 @@
|
||||
#define KEYBIND_SLOTS_DEFAULT 3
|
||||
|
||||
#define AUDIO_FREQUENCY 48000
|
||||
#define AUDIO_N_CHANNELS 2
|
||||
|
||||
#define TEXT_FONT_TEXTURE_SIZE_DEFAULT 2048
|
||||
#define TEXT_FONT_OVERSAMPLING_DEFAULT 4
|
||||
|
@ -14,11 +14,9 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
/* TODO: default to float sampling format? */
|
||||
|
||||
static const char *audio_exts[audio_file_type_count] = {
|
||||
".ogg", /* audio_file_type_ogg */
|
||||
".xm", /* audio_file_type_xm */
|
||||
static const char *audio_exts[AUDIO_FILE_TYPE_COUNT] = {
|
||||
".ogg", /* AUDIO_FILE_TYPE_OGG */
|
||||
".xm", /* AUDIO_FILE_TYPE_XM */
|
||||
};
|
||||
|
||||
|
||||
@ -68,7 +66,7 @@ void audio_play(const char *path, const char *channel) {
|
||||
static AudioFileType infer_audio_file_type(const char *path) {
|
||||
size_t path_len = SDL_strlen(path);
|
||||
|
||||
for (int i = 0; i < audio_file_type_count; ++i) {
|
||||
for (int i = 0; i < AUDIO_FILE_TYPE_COUNT; ++i) {
|
||||
size_t ext_length = SDL_strlen(audio_exts[i]);
|
||||
if (path_len <= ext_length)
|
||||
continue;
|
||||
@ -77,7 +75,7 @@ static AudioFileType infer_audio_file_type(const char *path) {
|
||||
return (AudioFileType)i;
|
||||
}
|
||||
|
||||
return audio_file_type_unknown;
|
||||
return AUDIO_FILE_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
@ -85,7 +83,7 @@ static AudioFileType infer_audio_file_type(const char *path) {
|
||||
/* or should we expect things to simply fail? */
|
||||
static union AudioContext init_audio_context(const char *path, AudioFileType type) {
|
||||
switch (type) {
|
||||
case audio_file_type_ogg: {
|
||||
case AUDIO_FILE_TYPE_OGG: {
|
||||
unsigned char *data;
|
||||
int64_t len = get_audio_data(path, &data);
|
||||
if (len == -1) {
|
||||
@ -112,7 +110,7 @@ static union AudioContext init_audio_context(const char *path, AudioFileType typ
|
||||
};
|
||||
}
|
||||
|
||||
case audio_file_type_xm: {
|
||||
case AUDIO_FILE_TYPE_XM: {
|
||||
unsigned char *data;
|
||||
int64_t len = get_audio_data(path, &data);
|
||||
if (len == -1) {
|
||||
@ -148,12 +146,12 @@ static union AudioContext init_audio_context(const char *path, AudioFileType typ
|
||||
|
||||
static void repeat_audio(AudioChannel *channel) {
|
||||
switch (channel->file_type) {
|
||||
case audio_file_type_ogg: {
|
||||
case AUDIO_FILE_TYPE_OGG: {
|
||||
stb_vorbis_seek_start(channel->context.vorbis.handle);
|
||||
break;
|
||||
}
|
||||
|
||||
case audio_file_type_xm: {
|
||||
case AUDIO_FILE_TYPE_XM: {
|
||||
xm_restart(channel->context.xm.handle);
|
||||
break;
|
||||
}
|
||||
@ -209,30 +207,25 @@ PlayAudioArgs audio_get_default_args(void) {
|
||||
}
|
||||
|
||||
|
||||
/* this assumes int16_t based streams */
|
||||
/* this assumes float based streams */
|
||||
static void audio_mixin_streams(const AudioChannel *channel,
|
||||
uint8_t *restrict a,
|
||||
uint8_t *restrict b,
|
||||
size_t frames)
|
||||
{
|
||||
int16_t *const sa = (int16_t *)a;
|
||||
int16_t *const sb = (int16_t *)b;
|
||||
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);
|
||||
|
||||
#if AUDIO_N_CHANNELS == 2
|
||||
|
||||
for (size_t s = 0; s < frames; s += 2) {
|
||||
/* left channel */
|
||||
sa[s] += (int16_t)(sb[s] * channel->args.volume * left_panning);
|
||||
sa[s] += (float)(sb[s] * channel->args.volume * left_panning);
|
||||
|
||||
/* right channel */
|
||||
sa[s + 1] += (int16_t)(sb[s + 1] * channel->args.volume * right_panning);
|
||||
sa[s + 1] += (float)(sb[s + 1] * channel->args.volume * right_panning);
|
||||
}
|
||||
#else
|
||||
#error "Unimplemented channel count"
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -242,21 +235,20 @@ static void audio_sample_and_mixin_channel(const AudioChannel *channel,
|
||||
int len)
|
||||
{
|
||||
static uint8_t buffer[16384];
|
||||
const int int16_buffer_frames = sizeof (buffer) / sizeof (int16_t);
|
||||
const int float_buffer_frames = sizeof (buffer) / sizeof (float);
|
||||
const int stream_frames = len / (int)(sizeof (int16_t));
|
||||
const int stream_frames = len / (int)(sizeof (float));
|
||||
|
||||
switch (channel->file_type) {
|
||||
case audio_file_type_ogg: {
|
||||
case AUDIO_FILE_TYPE_OGG: {
|
||||
/* feed stream for needed conversions */
|
||||
for (int i = 0; i < stream_frames; ) {
|
||||
const int n_frames = (stream_frames - i) > int16_buffer_frames ?
|
||||
int16_buffer_frames : stream_frames - i;
|
||||
const int n_frames = (stream_frames - i) > float_buffer_frames ?
|
||||
float_buffer_frames : stream_frames - i;
|
||||
|
||||
const int samples_per_channel = stb_vorbis_get_samples_short_interleaved(
|
||||
const int samples_per_channel = stb_vorbis_get_samples_float_interleaved(
|
||||
channel->context.vorbis.handle,
|
||||
channel->context.vorbis.channel_count,
|
||||
(int16_t *)buffer,
|
||||
(float *)buffer,
|
||||
n_frames);
|
||||
|
||||
/* handle end of file */
|
||||
@ -272,7 +264,7 @@ static void audio_sample_and_mixin_channel(const AudioChannel *channel,
|
||||
|
||||
/* panning and mixing */
|
||||
audio_mixin_streams(channel,
|
||||
&stream[i * sizeof(int16_t)], buffer,
|
||||
&stream[i * sizeof(float)], buffer,
|
||||
samples_per_channel * 2);
|
||||
|
||||
i += samples_per_channel * 2;
|
||||
@ -281,7 +273,7 @@ static void audio_sample_and_mixin_channel(const AudioChannel *channel,
|
||||
break;
|
||||
}
|
||||
|
||||
case audio_file_type_xm: {
|
||||
case AUDIO_FILE_TYPE_XM: {
|
||||
for (int i = 0; i < stream_frames; ) {
|
||||
const int n_frames = (stream_frames - i) > float_buffer_frames ?
|
||||
float_buffer_frames : stream_frames - i;
|
||||
@ -301,13 +293,9 @@ static void audio_sample_and_mixin_channel(const AudioChannel *channel,
|
||||
break;
|
||||
}
|
||||
|
||||
/* convert floats to int16_t */
|
||||
for (int p = 0; p < samples_per_channel * 2; ++p)
|
||||
((int16_t *)buffer)[p] = (int16_t)(((float *)buffer)[p] * (float)INT16_MAX);
|
||||
|
||||
/* panning and mixing */
|
||||
audio_mixin_streams(channel,
|
||||
&stream[i * sizeof(int16_t)],
|
||||
&stream[i * sizeof(float)],
|
||||
buffer,
|
||||
samples_per_channel * 2);
|
||||
|
||||
|
@ -14,10 +14,10 @@
|
||||
|
||||
|
||||
typedef enum AudioFileType {
|
||||
audio_file_type_ogg,
|
||||
audio_file_type_xm,
|
||||
audio_file_type_count,
|
||||
audio_file_type_unknown,
|
||||
AUDIO_FILE_TYPE_OGG,
|
||||
AUDIO_FILE_TYPE_XM,
|
||||
AUDIO_FILE_TYPE_COUNT,
|
||||
AUDIO_FILE_TYPE_UNKNOWN,
|
||||
} AudioFileType;
|
||||
|
||||
|
||||
|
@ -383,14 +383,16 @@ static bool initialize(void) {
|
||||
SDL_zero(request);
|
||||
|
||||
request.freq = AUDIO_FREQUENCY;
|
||||
request.format = AUDIO_S16;
|
||||
request.channels = AUDIO_N_CHANNELS;
|
||||
request.format = AUDIO_F32;
|
||||
request.channels = 2;
|
||||
request.callback = audio_callback;
|
||||
/* TODO: check for errors */
|
||||
ctx.audio_device = SDL_OpenAudioDevice(NULL, 0, &request, &got, 0);
|
||||
ctx.audio_stream_format = got.format;
|
||||
ctx.audio_stream_frequency = got.freq;
|
||||
ctx.audio_stream_channel_count = got.channels;
|
||||
SDL_assert_always(got.format == AUDIO_F32);
|
||||
SDL_assert_always(got.channels == 2);
|
||||
|
||||
SDL_PauseAudioDevice(ctx.audio_device, 0);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user