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 source;
ALuint buffers[AUDIO_MAX_BUFFERS]; ALuint buffers[AUDIO_MAX_BUFFERS];
ALuint freeIDs[AUDIO_MAX_BUFFERS]; ALuint freeIDs[AUDIO_MAX_BUFFERS];
struct AudioFormat format; int count, free, channels, sampleRate;
int count, free;
ALenum dataFormat; ALenum dataFormat;
}; };
static void* audio_device; static void* audio_device;
@ -218,9 +217,9 @@ static ALenum GetALFormat(int channels) {
Logger_Abort("Unsupported audio format"); return 0; 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; ALenum i, err;
ctx->dataFormat = GetALFormat(format->channels); ctx->dataFormat = GetALFormat(ctx->channels);
if (!ctx->source) { if (!ctx->source) {
_alGenSources(1, &ctx->source); _alGenSources(1, &ctx->source);
@ -337,8 +336,7 @@ WINMMAPI MMRESULT WINAPI waveOutReset(HWAVEOUT hwo);
struct AudioContext { struct AudioContext {
HWAVEOUT handle; HWAVEOUT handle;
WAVEHDR headers[AUDIO_MAX_BUFFERS]; WAVEHDR headers[AUDIO_MAX_BUFFERS];
struct AudioFormat format; int count, channels, sampleRate;
int count;
}; };
static cc_bool AudioBackend_Init(void) { return true; } static cc_bool AudioBackend_Init(void) { return true; }
static void AudioBackend_Free(void) { } static void AudioBackend_Free(void) { }
@ -360,16 +358,16 @@ static cc_result AudioBackend_Reset(struct AudioContext* ctx) {
return res; return res;
} }
static cc_result AudioBackend_SetFormat(struct AudioContext* ctx, struct AudioFormat* format) { static cc_result AudioBackend_UpdateFormat(struct AudioContext* ctx) {
WAVEFORMATEX fmt; WAVEFORMATEX fmt;
cc_result res; 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; if ((res = AudioBackend_Reset(ctx))) return res;
fmt.wFormatTag = WAVE_FORMAT_PCM; fmt.wFormatTag = WAVE_FORMAT_PCM;
fmt.nChannels = format->channels; fmt.nChannels = ctx->channels;
fmt.nSamplesPerSec = format->sampleRate; fmt.nSamplesPerSec = ctx->sampleRate;
fmt.nAvgBytesPerSec = format->sampleRate * sampleSize; fmt.nAvgBytesPerSec = ctx->sampleRate * sampleSize;
fmt.nBlockAlign = sampleSize; fmt.nBlockAlign = sampleSize;
fmt.wBitsPerSample = 16; fmt.wBitsPerSample = 16;
fmt.cbSize = 0; fmt.cbSize = 0;
@ -432,8 +430,7 @@ static SLEngineItf slEngineEngine;
static SLObjectItf slOutputObject; static SLObjectItf slOutputObject;
struct AudioContext { struct AudioContext {
struct AudioFormat format; int count, channels, sampleRate;
int count;
SLObjectItf bqPlayerObject; SLObjectItf bqPlayerObject;
SLPlayItf bqPlayerPlayer; SLPlayItf bqPlayerPlayer;
SLBufferQueueItf bqPlayerQueue; SLBufferQueueItf bqPlayerQueue;
@ -521,7 +518,7 @@ static void AudioBackend_Reset(struct AudioContext* ctx) {
ctx->bqPlayerQueue = NULL; 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_AndroidSimpleBufferQueue input;
SLDataLocator_OutputMix output; SLDataLocator_OutputMix output;
SLObjectItf bqPlayerObject; SLObjectItf bqPlayerObject;
@ -534,8 +531,8 @@ static cc_result AudioBackend_SetFormat(struct AudioContext* ctx, struct AudioFo
AudioBackend_Reset(ctx); AudioBackend_Reset(ctx);
fmt.formatType = SL_DATAFORMAT_PCM; fmt.formatType = SL_DATAFORMAT_PCM;
fmt.numChannels = format->channels; fmt.numChannels = ctx->channels;
fmt.samplesPerSec = format->sampleRate * 1000; fmt.samplesPerSec = ctx->sampleRate * 1000;
fmt.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16; fmt.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16;
fmt.containerSize = SL_PCMSAMPLEFORMAT_FIXED_16; fmt.containerSize = SL_PCMSAMPLEFORMAT_FIXED_16;
fmt.channelMask = 0; fmt.channelMask = 0;
@ -598,14 +595,15 @@ cc_result Audio_Poll(struct AudioContext* ctx, int* inUse) {
/*########################################################################################################################* /*########################################################################################################################*
*---------------------------------------------------Common backend code---------------------------------------------------* *---------------------------------------------------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) { cc_result Audio_SetFormat(struct AudioContext* ctx, int channels, int sampleRate) {
struct AudioFormat* cur = &ctx->format; if (ctx->channels == channels && ctx->sampleRate == sampleRate) return 0;
if (AudioFormat_Eq(cur, format)) return 0;
ctx->format = *format;
return AudioBackend_SetFormat(ctx, format); ctx->channels = channels;
ctx->sampleRate = sampleRate;
return AudioBackend_UpdateFormat(ctx);
} }
void Audio_Close(struct AudioContext* ctx) { void Audio_Close(struct AudioContext* ctx) {
@ -613,9 +611,9 @@ void Audio_Close(struct AudioContext* ctx) {
AudioBackend_Stop(ctx); AudioBackend_Stop(ctx);
Audio_Poll(ctx, &inUse); /* unqueue buffers */ Audio_Poll(ctx, &inUse); /* unqueue buffers */
ctx->count = 0; ctx->count = 0;
ctx->format.channels = 0; ctx->channels = 0;
ctx->format.sampleRate = 0; ctx->sampleRate = 0;
AudioBackend_Reset(ctx); AudioBackend_Reset(ctx);
} }
@ -624,7 +622,7 @@ void Audio_Close(struct AudioContext* ctx) {
*------------------------------------------------------Soundboard---------------------------------------------------------* *------------------------------------------------------Soundboard---------------------------------------------------------*
*#########################################################################################################################*/ *#########################################################################################################################*/
struct Sound { struct Sound {
struct AudioFormat format; int channels, sampleRate;
cc_uint8* data; cc_uint32 size; 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 ((res = Stream_Read(stream, tmp, sizeof(tmp)))) return res;
if (Stream_GetU16_LE(tmp + 0) != 1) return WAV_ERR_DATA_TYPE; if (Stream_GetU16_LE(tmp + 0) != 1) return WAV_ERR_DATA_TYPE;
snd->format.channels = Stream_GetU16_LE(tmp + 2); snd->channels = Stream_GetU16_LE(tmp + 2);
snd->format.sampleRate = Stream_GetU32_LE(tmp + 4); snd->sampleRate = Stream_GetU32_LE(tmp + 4);
/* tmp[8] (6) alignment data and stuff */ /* tmp[8] (6) alignment data and stuff */
bitsPerSample = Stream_GetU16_LE(tmp + 14); 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; struct SoundGroup* group;
int idx; int idx;
@ -783,7 +781,7 @@ CC_NOINLINE static void Sounds_Fail(cc_result res) {
Audio_SetSounds(0); 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* data = snd->data;
void* tmp; void* tmp;
cc_result res; 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); 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_QueueData(&output->ctx, data, snd->size))) { Sounds_Fail(res); return; }
if ((res = Audio_Play(&output->ctx))) { Sounds_Fail(res); return; } if ((res = Audio_Play(&output->ctx))) { Sounds_Fail(res); return; }
} }
static void Sounds_Play(cc_uint8 type, struct Soundboard* board) { static void Sounds_Play(cc_uint8 type, struct Soundboard* board) {
struct Sound* snd; const struct Sound* snd_;
struct AudioFormat fmt; struct Sound snd;
struct SoundOutput* outputs; struct SoundOutput* outputs;
struct SoundOutput* output; struct SoundOutput* output;
struct AudioFormat* l; int chans, freq;
int inUse, i, volume;
int inUse;
int i, volume;
cc_result res; cc_result res;
if (type == SOUND_NONE || !Audio_SoundsVolume) return; if (type == SOUND_NONE || !Audio_SoundsVolume) return;
snd = Soundboard_PickRandom(board, type); snd_ = Soundboard_PickRandom(board, type);
if (!snd) return; if (!snd_) return;
if (!AudioBackend_Init()) { if (!AudioBackend_Init()) {
AudioBackend_Free(); AudioBackend_Free();
@ -835,16 +831,16 @@ static void Sounds_Play(cc_uint8 type, struct Soundboard* board) {
return; return;
} }
fmt = snd->format; snd = *snd_;
volume = Audio_SoundsVolume; volume = Audio_SoundsVolume;
outputs = fmt.channels == 1 ? monoOutputs : stereoOutputs; outputs = snd.channels == 1 ? monoOutputs : stereoOutputs;
if (board == &digBoard) { if (board == &digBoard) {
if (type == SOUND_METAL) fmt.sampleRate = (fmt.sampleRate * 6) / 5; if (type == SOUND_METAL) snd.sampleRate = (snd.sampleRate * 6) / 5;
else fmt.sampleRate = (fmt.sampleRate * 4) / 5; else snd.sampleRate = (snd.sampleRate * 4) / 5;
} else { } else {
volume /= 2; 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 */ /* 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 (res) { Sounds_Fail(res); return; }
if (inUse > 0) continue; if (inUse > 0) continue;
} }
l = Audio_GetFormat(&output->ctx); chans = Audio_GetChannels(&output->ctx);
if (!l->channels || AudioFormat_Eq(l, &fmt)) { freq = Audio_GetSampleRate(&output->ctx);
Sounds_PlayRaw(output, snd, &fmt, volume); return; 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 (res) { Sounds_Fail(res); return; }
if (inUse > 0) continue; 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) { static cc_result Music_PlayOgg(struct Stream* source) {
struct OggState ogg; struct OggState ogg;
struct VorbisState vorbis = { 0 }; struct VorbisState vorbis = { 0 };
struct AudioFormat fmt; int channels, sampleRate;
int chunkSize, samplesPerSecond; int chunkSize, samplesPerSecond;
cc_int16* data = NULL; cc_int16* data = NULL;
@ -962,14 +959,14 @@ static cc_result Music_PlayOgg(struct Stream* source) {
vorbis.source = &ogg; vorbis.source = &ogg;
if ((res = Vorbis_DecodeHeaders(&vorbis))) goto cleanup; if ((res = Vorbis_DecodeHeaders(&vorbis))) goto cleanup;
fmt.channels = vorbis.channels; channels = vorbis.channels;
fmt.sampleRate = vorbis.sampleRate; sampleRate = vorbis.sampleRate;
if ((res = Audio_SetFormat(&music_ctx, &fmt))) goto cleanup; if ((res = Audio_SetFormat(&music_ctx, channels, sampleRate))) goto cleanup;
/* largest possible vorbis frame decodes to blocksize1 * channels samples, */ /* largest possible vorbis frame decodes to blocksize1 * channels samples, */
/* so can end up decoding slightly over a second of audio */ /* so can end up decoding slightly over a second of audio */
chunkSize = fmt.channels * (fmt.sampleRate + vorbis.blockSizes[1]); chunkSize = channels * (sampleRate + vorbis.blockSizes[1]);
samplesPerSecond = fmt.channels * fmt.sampleRate; samplesPerSecond = channels * sampleRate;
cur = 0; cur = 0;
data = (cc_int16*)Mem_TryAlloc(chunkSize * AUDIO_MAX_BUFFERS, 2); 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_SetSounds(int volume);
void Audio_PlayDigSound(cc_uint8 type); void Audio_PlayDigSound(cc_uint8 type);
void Audio_PlayStepSound(cc_uint8 type); void Audio_PlayStepSound(cc_uint8 type);
#define AUDIO_MAX_BUFFERS 4 #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. */ /* Initialises an audio context. */
void Audio_Init(struct AudioContext* ctx, int buffers); void Audio_Init(struct AudioContext* ctx, int buffers);
/* Stops any playing audio and then frees the audio context. */ /* Stops any playing audio and then frees the audio context. */
void Audio_Close(struct AudioContext* ctx); void Audio_Close(struct AudioContext* ctx);
/* Returns the format audio is played in. */ /* Returns number of channels of the format audio is played in. */
struct AudioFormat* Audio_GetFormat(struct AudioContext* ctx); 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. */ /* Sets the format of the audio data to be played. */
/* NOTE: Changing the format can be expensive, depending on the backend. */ /* 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. */ /* Queues the given audio data for playing. */
/* NOTE: You MUST ensure Audio_Poll indicates a buffer is free before calling this. */ /* 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 */ /* NOTE: Some backends directly read from the data - therefore you MUST NOT modify it */