mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-14 01:55:19 -04:00
Eliminate AudioFormat struct
This commit is contained in:
parent
4bd2e4f49f
commit
8c5864621d
107
src/Audio.c
107
src/Audio.c
@ -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);
|
||||||
|
12
src/Audio.h
12
src/Audio.h
@ -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 */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user