Eliminate AudioFormat struct

This commit is contained in:
UnknownShadow200 2021-08-07 21:03:08 +10:00
parent 4bd2e4f49f
commit 8c5864621d
2 changed files with 57 additions and 62 deletions

View File

@ -110,8 +110,7 @@ struct AudioContext {
ALuint source;
ALuint buffers[AUDIO_MAX_BUFFERS];
ALuint freeIDs[AUDIO_MAX_BUFFERS];
struct AudioFormat format;
int count, free;
int count, free, channels, sampleRate;
ALenum dataFormat;
};
static void* audio_device;
@ -218,9 +217,9 @@ static ALenum GetALFormat(int channels) {
Logger_Abort("Unsupported audio format"); return 0;
}
static cc_result AudioBackend_SetFormat(struct AudioContext* ctx, struct AudioFormat* format) {
static cc_result AudioBackend_UpdateFormat(struct AudioContext* ctx) {
ALenum i, err;
ctx->dataFormat = GetALFormat(format->channels);
ctx->dataFormat = GetALFormat(ctx->channels);
if (!ctx->source) {
_alGenSources(1, &ctx->source);
@ -337,8 +336,7 @@ WINMMAPI MMRESULT WINAPI waveOutReset(HWAVEOUT hwo);
struct AudioContext {
HWAVEOUT handle;
WAVEHDR headers[AUDIO_MAX_BUFFERS];
struct AudioFormat format;
int count;
int count, channels, sampleRate;
};
static cc_bool AudioBackend_Init(void) { return true; }
static void AudioBackend_Free(void) { }
@ -360,16 +358,16 @@ static cc_result AudioBackend_Reset(struct AudioContext* ctx) {
return res;
}
static cc_result AudioBackend_SetFormat(struct AudioContext* ctx, struct AudioFormat* format) {
static cc_result AudioBackend_UpdateFormat(struct AudioContext* ctx) {
WAVEFORMATEX fmt;
cc_result res;
int sampleSize = format->channels * 2; /* 16 bits per sample / 8 */
int sampleSize = ctx->channels * 2; /* 16 bits per sample / 8 */
if ((res = AudioBackend_Reset(ctx))) return res;
fmt.wFormatTag = WAVE_FORMAT_PCM;
fmt.nChannels = format->channels;
fmt.nSamplesPerSec = format->sampleRate;
fmt.nAvgBytesPerSec = format->sampleRate * sampleSize;
fmt.nChannels = ctx->channels;
fmt.nSamplesPerSec = ctx->sampleRate;
fmt.nAvgBytesPerSec = ctx->sampleRate * sampleSize;
fmt.nBlockAlign = sampleSize;
fmt.wBitsPerSample = 16;
fmt.cbSize = 0;
@ -432,8 +430,7 @@ static SLEngineItf slEngineEngine;
static SLObjectItf slOutputObject;
struct AudioContext {
struct AudioFormat format;
int count;
int count, channels, sampleRate;
SLObjectItf bqPlayerObject;
SLPlayItf bqPlayerPlayer;
SLBufferQueueItf bqPlayerQueue;
@ -521,7 +518,7 @@ static void AudioBackend_Reset(struct AudioContext* ctx) {
ctx->bqPlayerQueue = NULL;
}
static cc_result AudioBackend_SetFormat(struct AudioContext* ctx, struct AudioFormat* format) {
static cc_result AudioBackend_UpdateFormat(struct AudioContext* ctx) {
SLDataLocator_AndroidSimpleBufferQueue input;
SLDataLocator_OutputMix output;
SLObjectItf bqPlayerObject;
@ -534,8 +531,8 @@ static cc_result AudioBackend_SetFormat(struct AudioContext* ctx, struct AudioFo
AudioBackend_Reset(ctx);
fmt.formatType = SL_DATAFORMAT_PCM;
fmt.numChannels = format->channels;
fmt.samplesPerSec = format->sampleRate * 1000;
fmt.numChannels = ctx->channels;
fmt.samplesPerSec = ctx->sampleRate * 1000;
fmt.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16;
fmt.containerSize = SL_PCMSAMPLEFORMAT_FIXED_16;
fmt.channelMask = 0;
@ -598,14 +595,15 @@ cc_result Audio_Poll(struct AudioContext* ctx, int* inUse) {
/*########################################################################################################################*
*---------------------------------------------------Common backend code---------------------------------------------------*
*#########################################################################################################################*/
struct AudioFormat* Audio_GetFormat(struct AudioContext* ctx) { return &ctx->format; }
int Audio_GetChannels(struct AudioContext* ctx) { return ctx->channels; }
int Audio_GetSampleRate(struct AudioContext* ctx) { return ctx->sampleRate; }
cc_result Audio_SetFormat(struct AudioContext* ctx, struct AudioFormat* format) {
struct AudioFormat* cur = &ctx->format;
if (AudioFormat_Eq(cur, format)) return 0;
ctx->format = *format;
cc_result Audio_SetFormat(struct AudioContext* ctx, int channels, int sampleRate) {
if (ctx->channels == channels && ctx->sampleRate == sampleRate) return 0;
return AudioBackend_SetFormat(ctx, format);
ctx->channels = channels;
ctx->sampleRate = sampleRate;
return AudioBackend_UpdateFormat(ctx);
}
void Audio_Close(struct AudioContext* ctx) {
@ -613,9 +611,9 @@ void Audio_Close(struct AudioContext* ctx) {
AudioBackend_Stop(ctx);
Audio_Poll(ctx, &inUse); /* unqueue buffers */
ctx->count = 0;
ctx->format.channels = 0;
ctx->format.sampleRate = 0;
ctx->count = 0;
ctx->channels = 0;
ctx->sampleRate = 0;
AudioBackend_Reset(ctx);
}
@ -624,7 +622,7 @@ void Audio_Close(struct AudioContext* ctx) {
*------------------------------------------------------Soundboard---------------------------------------------------------*
*#########################################################################################################################*/
struct Sound {
struct AudioFormat format;
int channels, sampleRate;
cc_uint8* data; cc_uint32 size;
};
@ -664,8 +662,8 @@ static cc_result Sound_ReadWaveData(struct Stream* stream, struct Sound* snd) {
if ((res = Stream_Read(stream, tmp, sizeof(tmp)))) return res;
if (Stream_GetU16_LE(tmp + 0) != 1) return WAV_ERR_DATA_TYPE;
snd->format.channels = Stream_GetU16_LE(tmp + 2);
snd->format.sampleRate = Stream_GetU32_LE(tmp + 4);
snd->channels = Stream_GetU16_LE(tmp + 2);
snd->sampleRate = Stream_GetU32_LE(tmp + 4);
/* tmp[8] (6) alignment data and stuff */
bitsPerSample = Stream_GetU16_LE(tmp + 14);
@ -752,7 +750,7 @@ static void Soundboard_Init(struct Soundboard* board, const cc_string* boardName
}
}
static struct Sound* Soundboard_PickRandom(struct Soundboard* board, cc_uint8 type) {
static const struct Sound* Soundboard_PickRandom(struct Soundboard* board, cc_uint8 type) {
struct SoundGroup* group;
int idx;
@ -783,7 +781,7 @@ CC_NOINLINE static void Sounds_Fail(cc_result res) {
Audio_SetSounds(0);
}
static void Sounds_PlayRaw(struct SoundOutput* output, struct Sound* snd, struct AudioFormat* fmt, int volume) {
static void Sounds_PlayRaw(struct SoundOutput* output, struct Sound* snd, int volume) {
void* data = snd->data;
void* tmp;
cc_result res;
@ -809,25 +807,23 @@ static void Sounds_PlayRaw(struct SoundOutput* output, struct Sound* snd, struct
Volume_Mix16((cc_int16*)data, snd->size / 2, volume);
}
if ((res = Audio_SetFormat(&output->ctx, fmt))) { Sounds_Fail(res); return; }
if ((res = Audio_SetFormat(&output->ctx, snd->channels, snd->sampleRate))) { Sounds_Fail(res); return; }
if ((res = Audio_QueueData(&output->ctx, data, snd->size))) { Sounds_Fail(res); return; }
if ((res = Audio_Play(&output->ctx))) { Sounds_Fail(res); return; }
}
static void Sounds_Play(cc_uint8 type, struct Soundboard* board) {
struct Sound* snd;
struct AudioFormat fmt;
const struct Sound* snd_;
struct Sound snd;
struct SoundOutput* outputs;
struct SoundOutput* output;
struct AudioFormat* l;
int inUse;
int i, volume;
int chans, freq;
int inUse, i, volume;
cc_result res;
if (type == SOUND_NONE || !Audio_SoundsVolume) return;
snd = Soundboard_PickRandom(board, type);
if (!snd) return;
snd_ = Soundboard_PickRandom(board, type);
if (!snd_) return;
if (!AudioBackend_Init()) {
AudioBackend_Free();
@ -835,16 +831,16 @@ static void Sounds_Play(cc_uint8 type, struct Soundboard* board) {
return;
}
fmt = snd->format;
snd = *snd_;
volume = Audio_SoundsVolume;
outputs = fmt.channels == 1 ? monoOutputs : stereoOutputs;
outputs = snd.channels == 1 ? monoOutputs : stereoOutputs;
if (board == &digBoard) {
if (type == SOUND_METAL) fmt.sampleRate = (fmt.sampleRate * 6) / 5;
else fmt.sampleRate = (fmt.sampleRate * 4) / 5;
if (type == SOUND_METAL) snd.sampleRate = (snd.sampleRate * 6) / 5;
else snd.sampleRate = (snd.sampleRate * 4) / 5;
} else {
volume /= 2;
if (type == SOUND_METAL) fmt.sampleRate = (fmt.sampleRate * 7) / 5;
if (type == SOUND_METAL) snd.sampleRate = (snd.sampleRate * 7) / 5;
}
/* Try to play on fresh device, or device with same data format */
@ -858,10 +854,11 @@ static void Sounds_Play(cc_uint8 type, struct Soundboard* board) {
if (res) { Sounds_Fail(res); return; }
if (inUse > 0) continue;
}
l = Audio_GetFormat(&output->ctx);
if (!l->channels || AudioFormat_Eq(l, &fmt)) {
Sounds_PlayRaw(output, snd, &fmt, volume); return;
chans = Audio_GetChannels(&output->ctx);
freq = Audio_GetSampleRate(&output->ctx);
if (!chans || (chans == snd.channels && freq == snd.sampleRate)) {
Sounds_PlayRaw(output, &snd, volume); return;
}
}
@ -873,7 +870,7 @@ static void Sounds_Play(cc_uint8 type, struct Soundboard* board) {
if (res) { Sounds_Fail(res); return; }
if (inUse > 0) continue;
Sounds_PlayRaw(output, snd, &fmt, volume); return;
Sounds_PlayRaw(output, &snd, volume); return;
}
}
@ -951,7 +948,7 @@ static cc_result Music_Buffer(cc_int16* data, int maxSamples, struct VorbisState
static cc_result Music_PlayOgg(struct Stream* source) {
struct OggState ogg;
struct VorbisState vorbis = { 0 };
struct AudioFormat fmt;
int channels, sampleRate;
int chunkSize, samplesPerSecond;
cc_int16* data = NULL;
@ -962,14 +959,14 @@ static cc_result Music_PlayOgg(struct Stream* source) {
vorbis.source = &ogg;
if ((res = Vorbis_DecodeHeaders(&vorbis))) goto cleanup;
fmt.channels = vorbis.channels;
fmt.sampleRate = vorbis.sampleRate;
if ((res = Audio_SetFormat(&music_ctx, &fmt))) goto cleanup;
channels = vorbis.channels;
sampleRate = vorbis.sampleRate;
if ((res = Audio_SetFormat(&music_ctx, channels, sampleRate))) goto cleanup;
/* largest possible vorbis frame decodes to blocksize1 * channels samples, */
/* so can end up decoding slightly over a second of audio */
chunkSize = fmt.channels * (fmt.sampleRate + vorbis.blockSizes[1]);
samplesPerSecond = fmt.channels * fmt.sampleRate;
chunkSize = channels * (sampleRate + vorbis.blockSizes[1]);
samplesPerSecond = channels * sampleRate;
cur = 0;
data = (cc_int16*)Mem_TryAlloc(chunkSize * AUDIO_MAX_BUFFERS, 2);

View File

@ -19,21 +19,19 @@ void Audio_SetMusic(int volume);
void Audio_SetSounds(int volume);
void Audio_PlayDigSound(cc_uint8 type);
void Audio_PlayStepSound(cc_uint8 type);
#define AUDIO_MAX_BUFFERS 4
/* Information about a source of audio. */
struct AudioFormat { int channels, sampleRate; };
#define AudioFormat_Eq(a, b) ((a)->channels == (b)->channels && (a)->sampleRate == (b)->sampleRate)
/* Initialises an audio context. */
void Audio_Init(struct AudioContext* ctx, int buffers);
/* Stops any playing audio and then frees the audio context. */
void Audio_Close(struct AudioContext* ctx);
/* Returns the format audio is played in. */
struct AudioFormat* Audio_GetFormat(struct AudioContext* ctx);
/* Returns number of channels of the format audio is played in. */
int Audio_GetChannels(struct AudioContext* ctx);
/* Returns number of channels of the format audio is played in. */
int Audio_GetSampeRate(struct AudioContext* ctx);
/* Sets the format of the audio data to be played. */
/* NOTE: Changing the format can be expensive, depending on the backend. */
cc_result Audio_SetFormat(struct AudioContext* ctx, struct AudioFormat* format);
cc_result Audio_SetFormat(struct AudioContext* ctx, int channels, int sampleRate);
/* Queues the given audio data for playing. */
/* NOTE: You MUST ensure Audio_Poll indicates a buffer is free before calling this. */
/* NOTE: Some backends directly read from the data - therefore you MUST NOT modify it */