mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-14 10:05:44 -04:00
Try to simplify audio backend code a bit
This commit is contained in:
parent
e22be93ab3
commit
b2fdf80be1
@ -351,7 +351,7 @@ static cc_result Music_PlayOgg(struct Stream* source) {
|
||||
|
||||
channels = vorbis.channels;
|
||||
sampleRate = vorbis.sampleRate;
|
||||
if ((res = Audio_SetFormat(&music_ctx, channels, sampleRate))) goto cleanup;
|
||||
if ((res = Audio_SetFormat(&music_ctx, channels, sampleRate, 100))) goto cleanup;
|
||||
|
||||
/* largest possible vorbis frame decodes to blocksize1 * channels samples, */
|
||||
/* so can end up decoding slightly over a second of audio */
|
||||
|
@ -51,7 +51,7 @@ cc_result Audio_Init(struct AudioContext* ctx, int buffers);
|
||||
void Audio_Close(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, int channels, int sampleRate);
|
||||
cc_result Audio_SetFormat(struct AudioContext* ctx, int channels, int sampleRate, int playbackRate);
|
||||
/* Sets the volume audio data is played at */
|
||||
void Audio_SetVolume(struct AudioContext* ctx, int volume);
|
||||
/* Queues the given audio chunk for playing. */
|
||||
@ -66,8 +66,6 @@ cc_result Audio_Play(struct AudioContext* ctx);
|
||||
cc_result Audio_Poll(struct AudioContext* ctx, int* inUse);
|
||||
cc_result Audio_Pause(struct AudioContext* ctx); /* Only implemented with OpenSL ES backend */
|
||||
|
||||
/* Plays the given audio data */
|
||||
cc_result Audio_PlayData(struct AudioContext* ctx, struct AudioData* data);
|
||||
/* Whether the given audio data can be played without recreating the underlying audio device */
|
||||
cc_bool Audio_FastPlay(struct AudioContext* ctx, struct AudioData* data);
|
||||
/* Outputs more detailed information about errors with audio. */
|
||||
|
@ -12,12 +12,12 @@ void Audio_Warn(cc_result res, const char* action) {
|
||||
|
||||
/* Common/Base methods */
|
||||
static void AudioBase_Clear(struct AudioContext* ctx);
|
||||
static cc_bool AudioBase_AdjustSound(struct AudioContext* ctx, struct AudioData* data);
|
||||
static cc_bool AudioBase_AdjustSound(struct AudioContext* ctx, void* data, cc_uint32 size);
|
||||
static void AudioBase_AllocChunks(int size, void** chunks, int numChunks);
|
||||
static void AudioBase_FreeChunks(void** chunks, int numChunks);
|
||||
|
||||
/* achieve higher speed by playing samples at higher sample rate */
|
||||
#define Audio_AdjustSampleRate(data) ((data->sampleRate * data->rate) / 100)
|
||||
#define Audio_AdjustSampleRate(sampleRate, playbackRate) ((sampleRate * playbackRate) / 100)
|
||||
|
||||
#if defined CC_BUILD_OPENAL
|
||||
/*########################################################################################################################*
|
||||
@ -205,8 +205,8 @@ void Audio_Close(struct AudioContext* ctx) {
|
||||
ctx->count = 0;
|
||||
}
|
||||
|
||||
cc_result Audio_SetFormat(struct AudioContext* ctx, int channels, int sampleRate) {
|
||||
ctx->sampleRate = sampleRate;
|
||||
cc_result Audio_SetFormat(struct AudioContext* ctx, int channels, int sampleRate, int playbackRate) {
|
||||
ctx->sampleRate = Audio_AdjustSampleRate(sampleRate, playbackRate);
|
||||
|
||||
if (channels == 1) {
|
||||
ctx->format = AL_FORMAT_MONO16;
|
||||
@ -269,16 +269,6 @@ cc_bool Audio_FastPlay(struct AudioContext* ctx, struct AudioData* data) {
|
||||
return true;
|
||||
}
|
||||
|
||||
cc_result Audio_PlayData(struct AudioContext* ctx, struct AudioData* data) {
|
||||
cc_result res;
|
||||
data->sampleRate = Audio_AdjustSampleRate(data);
|
||||
|
||||
if ((res = Audio_SetFormat(ctx, data->channels, data->sampleRate))) return res;
|
||||
if ((res = Audio_QueueChunk(ctx, data->data, data->size))) return res;
|
||||
if ((res = Audio_Play(ctx))) return res;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char* GetError(cc_result res) {
|
||||
switch (res) {
|
||||
case AL_ERR_INIT_CONTEXT: return "Failed to init OpenAL context";
|
||||
@ -408,11 +398,12 @@ void Audio_Close(struct AudioContext* ctx) {
|
||||
AudioBase_Clear(ctx);
|
||||
}
|
||||
|
||||
cc_result Audio_SetFormat(struct AudioContext* ctx, int channels, int sampleRate) {
|
||||
cc_result Audio_SetFormat(struct AudioContext* ctx, int channels, int sampleRate, int playbackRate) {
|
||||
WAVEFORMATEX fmt;
|
||||
cc_result res;
|
||||
int sampleSize;
|
||||
|
||||
sampleRate = Audio_AdjustSampleRate(sampleRate, playbackRate);
|
||||
if (ctx->channels == channels && ctx->sampleRate == sampleRate) return 0;
|
||||
ctx->channels = channels;
|
||||
ctx->sampleRate = sampleRate;
|
||||
@ -443,13 +434,16 @@ cc_result Audio_QueueChunk(struct AudioContext* ctx, void* chunk, cc_uint32 data
|
||||
WAVEHDR* hdr;
|
||||
int i;
|
||||
|
||||
cc_bool ok = AudioBase_AdjustSound(ctx, chunk, dataSize);
|
||||
if (!ok) return ERR_OUT_OF_MEMORY;
|
||||
|
||||
for (i = 0; i < ctx->count; i++) {
|
||||
hdr = &ctx->headers[i];
|
||||
if (!(hdr->dwFlags & WHDR_DONE)) continue;
|
||||
|
||||
Mem_Set(hdr, 0, sizeof(WAVEHDR));
|
||||
hdr->lpData = (LPSTR)chunk;
|
||||
hdr->dwBufferLength = dataSize;
|
||||
hdr->lpData = (LPSTR)ctx->_tmpData;
|
||||
hdr->dwBufferLength = ctx->_tmpSize;
|
||||
hdr->dwLoops = 1;
|
||||
|
||||
if ((res = waveOutPrepareHeader(ctx->handle, hdr, sizeof(WAVEHDR)))) return res;
|
||||
@ -483,21 +477,10 @@ cc_result Audio_Poll(struct AudioContext* ctx, int* inUse) {
|
||||
|
||||
cc_bool Audio_FastPlay(struct AudioContext* ctx, struct AudioData* data) {
|
||||
int channels = data->channels;
|
||||
int sampleRate = Audio_AdjustSampleRate(data);
|
||||
int sampleRate = Audio_AdjustSampleRate(data->sampleRate, data->rate);
|
||||
return !ctx->channels || (ctx->channels == channels && ctx->sampleRate == sampleRate);
|
||||
}
|
||||
|
||||
cc_result Audio_PlayData(struct AudioContext* ctx, struct AudioData* data) {
|
||||
cc_bool ok = AudioBase_AdjustSound(ctx, data);
|
||||
cc_result res;
|
||||
if (!ok) return ERR_OUT_OF_MEMORY;
|
||||
data->sampleRate = Audio_AdjustSampleRate(data);
|
||||
|
||||
if ((res = Audio_SetFormat(ctx, data->channels, data->sampleRate))) return res;
|
||||
if ((res = Audio_QueueChunk(ctx, data->data, data->size))) return res;
|
||||
return 0;
|
||||
}
|
||||
|
||||
cc_bool Audio_DescribeError(cc_result res, cc_string* dst) {
|
||||
char buffer[NATIVE_STR_LEN] = { 0 };
|
||||
waveOutGetErrorTextA(res, buffer, NATIVE_STR_LEN);
|
||||
@ -634,7 +617,7 @@ void Audio_Close(struct AudioContext* ctx) {
|
||||
ctx->sampleRate = 0;
|
||||
}
|
||||
|
||||
cc_result Audio_SetFormat(struct AudioContext* ctx, int channels, int sampleRate) {
|
||||
cc_result Audio_SetFormat(struct AudioContext* ctx, int channels, int sampleRate, int playbackRate) {
|
||||
SLDataLocator_AndroidSimpleBufferQueue input;
|
||||
SLDataLocator_OutputMix output;
|
||||
SLObjectItf playerObject;
|
||||
@ -645,6 +628,9 @@ cc_result Audio_SetFormat(struct AudioContext* ctx, int channels, int sampleRate
|
||||
SLDataSink dst;
|
||||
cc_result res;
|
||||
|
||||
/* rate is in milli, so 1000 = normal rate */
|
||||
if ((res = (*ctx->playerRate)->SetRate(ctx->playerRate, playbackRate * 10))) return res;
|
||||
|
||||
if (ctx->channels == channels && ctx->sampleRate == sampleRate) return 0;
|
||||
ctx->channels = channels;
|
||||
ctx->sampleRate = sampleRate;
|
||||
@ -721,18 +707,6 @@ cc_bool Audio_FastPlay(struct AudioContext* ctx, struct AudioData* data) {
|
||||
return !ctx->channels || (ctx->channels == data->channels && ctx->sampleRate == data->sampleRate);
|
||||
}
|
||||
|
||||
cc_result Audio_PlayData(struct AudioContext* ctx, struct AudioData* data) {
|
||||
cc_result res;
|
||||
|
||||
if ((res = Audio_SetFormat(ctx, data->channels, data->sampleRate))) return res;
|
||||
/* rate is in milli, so 1000 = normal rate */
|
||||
if ((res = (*ctx->playerRate)->SetRate(ctx->playerRate, data->rate * 10))) return res;
|
||||
|
||||
if ((res = Audio_QueueChunk(ctx, data->data, data->size))) return res;
|
||||
if ((res = Audio_Play(ctx))) return res;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char* GetError(cc_result res) {
|
||||
switch (res) {
|
||||
case SL_RESULT_PRECONDITIONS_VIOLATED: return "Preconditions violated";
|
||||
@ -820,10 +794,11 @@ void Audio_Close(struct AudioContext* ctx) {
|
||||
ctx->count = 0;
|
||||
}
|
||||
|
||||
cc_result Audio_SetFormat(struct AudioContext* ctx, int channels, int sampleRate) {
|
||||
cc_result Audio_SetFormat(struct AudioContext* ctx, int channels, int sampleRate, int playbackRate) {
|
||||
ctx->stereo = (channels == 2);
|
||||
int fmt = ctx->stereo ? NDSP_FORMAT_STEREO_PCM16 : NDSP_FORMAT_MONO_PCM16;
|
||||
|
||||
|
||||
sampleRate = Audio_AdjustSampleRate(sampleRate, playbackRate);
|
||||
ndspChnSetFormat(ctx->chanID, fmt);
|
||||
ndspChnSetRate(ctx->chanID, sampleRate);
|
||||
return 0;
|
||||
@ -890,15 +865,6 @@ cc_bool Audio_FastPlay(struct AudioContext* ctx, struct AudioData* data) {
|
||||
return true;
|
||||
}
|
||||
|
||||
cc_result Audio_PlayData(struct AudioContext* ctx, struct AudioData* data) {
|
||||
data->sampleRate = Audio_AdjustSampleRate(data);
|
||||
cc_result res;
|
||||
|
||||
if ((res = Audio_SetFormat(ctx, data->channels, data->sampleRate))) return res;
|
||||
if ((res = Audio_QueueChunk(ctx, data->data, data->size))) return res;
|
||||
return 0;
|
||||
}
|
||||
|
||||
cc_bool Audio_DescribeError(cc_result res, cc_string* dst) {
|
||||
return false;
|
||||
}
|
||||
@ -1008,7 +974,8 @@ void Audio_Close(struct AudioContext* ctx) {
|
||||
ctx->count = 0;
|
||||
}
|
||||
|
||||
cc_result Audio_SetFormat(struct AudioContext* ctx, int channels, int sampleRate) {
|
||||
cc_result Audio_SetFormat(struct AudioContext* ctx, int channels, int sampleRate, int playbackRate) {
|
||||
sampleRate = Audio_AdjustSampleRate(sampleRate, playbackRate);
|
||||
ctx->channels = channels;
|
||||
ctx->sampleRate = sampleRate;
|
||||
|
||||
@ -1020,8 +987,7 @@ cc_result Audio_SetFormat(struct AudioContext* ctx, int channels, int sampleRate
|
||||
// mono
|
||||
audrvVoiceSetMixFactor(&drv, ctx->chanID, 1.0f, 0, 0);
|
||||
audrvVoiceSetMixFactor(&drv, ctx->chanID, 1.0f, 0, 1);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// stereo
|
||||
audrvVoiceSetMixFactor(&drv, ctx->chanID, 1.0f, 0, 0);
|
||||
audrvVoiceSetMixFactor(&drv, ctx->chanID, 0.0f, 0, 1);
|
||||
@ -1099,17 +1065,6 @@ cc_bool Audio_FastPlay(struct AudioContext* ctx, struct AudioData* data) {
|
||||
return true;
|
||||
}
|
||||
|
||||
cc_result Audio_PlayData(struct AudioContext* ctx, struct AudioData* data) {
|
||||
data->sampleRate = Audio_AdjustSampleRate(data);
|
||||
cc_result res;
|
||||
|
||||
if ((res = Audio_SetFormat(ctx, data->channels, data->sampleRate))) return res;
|
||||
if ((res = Audio_QueueChunk(ctx, data->data, data->size))) return res;
|
||||
|
||||
if ((res = Audio_Play(ctx))) return res;
|
||||
return 0;
|
||||
}
|
||||
|
||||
cc_bool Audio_DescribeError(cc_result res, cc_string* dst) {
|
||||
return false;
|
||||
}
|
||||
@ -1229,7 +1184,8 @@ void Audio_Close(struct AudioContext* ctx) {
|
||||
ctx->count = 0;
|
||||
}
|
||||
|
||||
cc_result Audio_SetFormat(struct AudioContext* ctx, int channels, int sampleRate) {
|
||||
cc_result Audio_SetFormat(struct AudioContext* ctx, int channels, int sampleRate, int playbackRate) {
|
||||
sampleRate = Audio_AdjustSampleRate(sampleRate, playbackRate);
|
||||
ctx->channels = channels;
|
||||
ctx->sampleRate = sampleRate;
|
||||
return 0;
|
||||
@ -1279,16 +1235,6 @@ cc_bool Audio_FastPlay(struct AudioContext* ctx, struct AudioData* data) {
|
||||
return true;
|
||||
}
|
||||
|
||||
cc_result Audio_PlayData(struct AudioContext* ctx, struct AudioData* data) {
|
||||
data->sampleRate = Audio_AdjustSampleRate(data);
|
||||
cc_result res;
|
||||
|
||||
if ((res = Audio_SetFormat(ctx, data->channels, data->sampleRate))) return res;
|
||||
if ((res = Audio_QueueChunk(ctx, data->data, data->size))) return res;
|
||||
if ((res = Audio_Play(ctx))) return res;
|
||||
return 0;
|
||||
}
|
||||
|
||||
cc_bool Audio_DescribeError(cc_result res, cc_string* dst) {
|
||||
return false;
|
||||
}
|
||||
@ -1310,7 +1256,7 @@ void Audio_FreeChunks(void** chunks, int numChunks) {
|
||||
/*########################################################################################################################*
|
||||
*-----------------------------------------------------WebAudio backend----------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
struct AudioContext { int contextID, count; };
|
||||
struct AudioContext { int contextID, count, rate; void* data; };
|
||||
#define AUDIO_COMMON_ALLOC
|
||||
|
||||
extern int interop_InitAudio(void);
|
||||
@ -1333,6 +1279,8 @@ void AudioBackend_Free(void) { }
|
||||
cc_result Audio_Init(struct AudioContext* ctx, int buffers) {
|
||||
ctx->count = buffers;
|
||||
ctx->contextID = interop_AudioCreate();
|
||||
ctx->data = NULL;
|
||||
ctx->rate = 100;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1342,8 +1290,8 @@ void Audio_Close(struct AudioContext* ctx) {
|
||||
ctx->count = 0;
|
||||
}
|
||||
|
||||
cc_result Audio_SetFormat(struct AudioContext* ctx, int channels, int sampleRate) {
|
||||
return ERR_NOT_SUPPORTED;
|
||||
cc_result Audio_SetFormat(struct AudioContext* ctx, int channels, int sampleRate, int playbackRate) {
|
||||
ctx->rate = playbackRate; return 0;
|
||||
}
|
||||
|
||||
void Audio_SetVolume(struct AudioContext* ctx, int volume) {
|
||||
@ -1351,10 +1299,12 @@ void Audio_SetVolume(struct AudioContext* ctx, int volume) {
|
||||
}
|
||||
|
||||
cc_result Audio_QueueChunk(struct AudioContext* ctx, void* chunk, cc_uint32 size) {
|
||||
return ERR_NOT_SUPPORTED;
|
||||
ctx->data = chunk; return 0;
|
||||
}
|
||||
|
||||
cc_result Audio_Play(struct AudioContext* ctx) { return ERR_NOT_SUPPORTED; }
|
||||
cc_result Audio_Play(struct AudioContext* ctx) {
|
||||
return interop_AudioPlay(ctx->contextID, ctx->data, ctx->rate);
|
||||
}
|
||||
|
||||
cc_result Audio_Poll(struct AudioContext* ctx, int* inUse) {
|
||||
return interop_AudioPoll(ctx->contextID, inUse);
|
||||
@ -1365,10 +1315,6 @@ cc_bool Audio_FastPlay(struct AudioContext* ctx, struct AudioData* data) {
|
||||
return true;
|
||||
}
|
||||
|
||||
cc_result Audio_PlayData(struct AudioContext* ctx, struct AudioData* data) {
|
||||
return interop_AudioPlay(ctx->contextID, data->data, data->rate);
|
||||
}
|
||||
|
||||
cc_bool Audio_DescribeError(cc_result res, cc_string* dst) {
|
||||
char buffer[NATIVE_STR_LEN];
|
||||
int len = interop_AudioDescribe(res, buffer, NATIVE_STR_LEN);
|
||||
@ -1400,12 +1346,26 @@ cc_result Audio_Init(struct AudioContext* ctx, int buffers) {
|
||||
|
||||
void Audio_Close(struct AudioContext* ctx) { }
|
||||
|
||||
cc_bool Audio_FastPlay(struct AudioContext* ctx, struct AudioData* data) { return true; }
|
||||
|
||||
cc_result Audio_PlayData(struct AudioContext* ctx, struct AudioData* data) {
|
||||
cc_result Audio_SetFormat(struct AudioContext* ctx, int channels, int sampleRate, int playbackRate) {
|
||||
return ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
void Audio_SetVolume(struct AudioContext* ctx, int volume) { }
|
||||
|
||||
cc_result Audio_QueueChunk(struct AudioContext* ctx, void* chunk, cc_uint32 size) {
|
||||
return ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
cc_result Audio_Play(struct AudioContext* ctx) {
|
||||
return ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
cc_result Audio_Poll(struct AudioContext* ctx, int* inUse) {
|
||||
return ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
cc_bool Audio_FastPlay(struct AudioContext* ctx, struct AudioData* data) { return false; }
|
||||
|
||||
cc_bool Audio_DescribeError(cc_result res, cc_string* dst) { return false; }
|
||||
#endif
|
||||
|
||||
@ -1444,9 +1404,13 @@ static void AudioBase_Clear(struct AudioContext* ctx) {
|
||||
ctx->_tmpSize = 0;
|
||||
}
|
||||
|
||||
static cc_bool AudioBase_AdjustSound(struct AudioContext* ctx, struct AudioData* data) {
|
||||
static cc_bool AudioBase_AdjustSound(struct AudioContext* ctx, void* data, cc_uint32 size) {
|
||||
void* audio;
|
||||
if (ctx->volume >= 100) return true;
|
||||
if (ctx->volume >= 100) {
|
||||
ctx->_tmpData = data;
|
||||
ctx->_tmpSize = size;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* copy to temp buffer to apply volume */
|
||||
if (ctx->_tmpSize < data->size) {
|
||||
@ -1496,8 +1460,13 @@ static struct AudioContext context_pool[POOL_MAX_CONTEXTS];
|
||||
|
||||
#ifndef CC_BUILD_NOSOUNDS
|
||||
static cc_result PlayAudio(struct AudioContext* ctx, struct AudioData* data) {
|
||||
cc_result res;
|
||||
Audio_SetVolume(ctx, data->volume);
|
||||
return Audio_PlayData(ctx, data);
|
||||
|
||||
if ((res = Audio_SetFormat(ctx, data->channels, data->sampleRate, data->rate))) return res;
|
||||
if ((res = Audio_QueueChunk(ctx, data->data, data->size))) return res;
|
||||
if ((res = Audio_Play(ctx))) return res;
|
||||
return 0;
|
||||
}
|
||||
|
||||
cc_result AudioPool_Play(struct AudioData* data) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user