WIP on adding speed/rate argument when playing sounds instead

This commit is contained in:
UnknownShadow200 2021-08-22 09:31:46 +10:00
parent 6e433e5585
commit 97fcc429bf
3 changed files with 69 additions and 52 deletions

View File

@ -54,8 +54,8 @@ static void AudioWarn(cc_result res, const char* action) {
Logger_Warn(res, action, Audio_DescribeError); Logger_Warn(res, action, Audio_DescribeError);
} }
static void AudioBase_Clear(struct AudioContext* ctx); static void AudioBase_Clear(struct AudioContext* ctx);
static void* AudioBase_AdjustSound(struct AudioContext* ctx, struct Sound* snd, int volume); static cc_bool AudioBase_AdjustSound(struct AudioContext* ctx, struct AudioData* data);
static cc_result AudioBase_PlaySound(struct AudioContext* ctx, struct Sound* snd, void* data); static cc_result AudioBase_PlaySound(struct AudioContext* ctx, struct AudioData* data);
#if defined CC_BUILD_OPENAL #if defined CC_BUILD_OPENAL
@ -289,14 +289,14 @@ cc_result Audio_Poll(struct AudioContext* ctx, int* inUse) {
*inUse = ctx->count - ctx->free; return 0; *inUse = ctx->count - ctx->free; return 0;
} }
cc_bool Audio_FastPlay(struct AudioContext* ctx, int channels, int sampleRate) { cc_bool Audio_FastPlay(struct AudioContext* ctx, struct AudioData* data) {
/* Channels/Sample rate is per buffer, not a per source property */ /* Channels/Sample rate is per buffer, not a per source property */
return true; return true;
} }
cc_result Audio_PlaySound(struct AudioContext* ctx, struct Sound* snd, int volume) { cc_result Audio_PlayData(struct AudioContext* ctx, struct Sound* snd, int volume) {
void* data = AudioBase_AdjustSound(ctx, snd, volume); cc_book ok = AudioBase_AdjustSound(ctx, snd, volume);
if (data) return AudioBase_PlaySound(ctx, snd, data); if (ok) return AudioBase_PlaySound(ctx, snd, data);
return ERR_OUT_OF_MEMORY; return ERR_OUT_OF_MEMORY;
} }
@ -477,15 +477,21 @@ cc_result Audio_Poll(struct AudioContext* ctx, int* inUse) {
*inUse = count; return res; *inUse = count; return res;
} }
/* achieve higher speed by playing samples at higher sample rate */
#define Audio_AdjustSampleRate(data) ((data->sampleRate * data->rate) / 100)
cc_bool Audio_FastPlay(struct AudioContext* ctx, int channels, int sampleRate) { cc_bool Audio_FastPlay(struct AudioContext* ctx, struct AudioData* data) {
int channels = data->channels;
int sampleRate = Audio_AdjustSampleRate(data);
return !ctx->channels || (ctx->channels == channels && ctx->sampleRate == sampleRate); return !ctx->channels || (ctx->channels == channels && ctx->sampleRate == sampleRate);
} }
cc_result Audio_PlaySound(struct AudioContext* ctx, struct Sound* snd, int volume) { cc_result Audio_PlayData(struct AudioContext* ctx, struct AudioData* data) {
void* data = AudioBase_AdjustSound(ctx, snd, volume); cc_bool ok = AudioBase_AdjustSound(ctx, data);
if (data) return AudioBase_PlaySound(ctx, snd, data); if (!ok) return ERR_OUT_OF_MEMORY;
return ERR_OUT_OF_MEMORY;
data->sampleRate = Audio_AdjustSampleRate(data);
return AudioBase_PlaySound(ctx, data);
} }
cc_bool Audio_DescribeError(cc_result res, cc_string* dst) { cc_bool Audio_DescribeError(cc_result res, cc_string* dst) {
@ -684,9 +690,9 @@ cc_bool Audio_FastPlay(struct AudioContext* ctx, int channels, int sampleRate) {
return !ctx->channels || (ctx->channels == channels && ctx->sampleRate == sampleRate); return !ctx->channels || (ctx->channels == channels && ctx->sampleRate == sampleRate);
} }
cc_result Audio_PlaySound(struct AudioContext* ctx, struct Sound* snd, int volume) { cc_result Audio_PlayData(struct AudioContext* ctx, struct Sound* snd, int volume) {
void* data = AudioBase_AdjustSound(ctx, snd, volume); cc_bool ok = AudioBase_AdjustSound(ctx, snd, volume);
if (data) return AudioBase_PlaySound(ctx, snd, data); if (ok) return AudioBase_PlaySound(ctx, snd, data);
return ERR_OUT_OF_MEMORY; return ERR_OUT_OF_MEMORY;
} }
@ -756,12 +762,12 @@ cc_result Audio_Poll(struct AudioContext* ctx, int* inUse) {
*inUse = 0; return 0; *inUse = 0; return 0;
} }
cc_bool Audio_FastPlay(struct AudioContext* ctx, int channels, int sampleRate) { cc_bool Audio_FastPlay(struct AudioContext* ctx, struct AudioData* data) {
/* Channels/Sample rate is per buffer, not a per source property */ /* Channels/Sample rate is per buffer, not a per source property */
return true; return true;
} }
cc_result Audio_PlaySound(struct AudioContext* ctx, struct Sound* snd, int volume) { cc_result Audio_PlayData(struct AudioContext* ctx, struct Sound* snd, int volume) {
if (!ctx->contextID) if (!ctx->contextID)
ctx->contextID = interop_AudioCreate(); ctx->contextID = interop_AudioCreate();
return interop_AudioPlay(ctx->contextID, snd, volume); return interop_AudioPlay(ctx->contextID, snd, volume);
@ -792,34 +798,35 @@ static void AudioBase_Clear(struct AudioContext* ctx) {
ctx->_tmpSize = 0; ctx->_tmpSize = 0;
} }
static void* AudioBase_AdjustSound(struct AudioContext* ctx, struct Sound* snd, int volume) { static cc_bool AudioBase_AdjustSound(struct AudioContext* ctx, struct AudioData* data) {
void* data; void* audio;
if (volume >= 100) return snd->data; if (data->volume >= 100) return true;
/* copy to temp buffer to apply volume */ /* copy to temp buffer to apply volume */
if (ctx->_tmpSize < snd->size) { if (ctx->_tmpSize < data->size) {
/* TODO: check if we can realloc NULL without a problem */ /* TODO: check if we can realloc NULL without a problem */
if (ctx->_tmpData) { if (ctx->_tmpData) {
data = Mem_TryRealloc(ctx->_tmpData, snd->size, 1); audio = Mem_TryRealloc(ctx->_tmpData, data->size, 1);
} else { } else {
data = Mem_TryAlloc(snd->size, 1); audio = Mem_TryAlloc(data->size, 1);
} }
if (!data) return NULL; if (!data) return false;
ctx->_tmpData = data; ctx->_tmpData = audio;
ctx->_tmpSize = snd->size; ctx->_tmpSize = data->size;
} }
data = ctx->_tmpData; audio = ctx->_tmpData;
Mem_Copy(data, snd->data, snd->size); Mem_Copy(audio, data->data, data->size);
ApplyVolume((cc_int16*)data, snd->size / 2, volume); ApplyVolume((cc_int16*)audio, data->size / 2, data->volume);
return data; data->data = audio;
return true;
} }
static cc_result AudioBase_PlaySound(struct AudioContext* ctx, struct Sound* snd, void* data) { static cc_result AudioBase_PlaySound(struct AudioContext* ctx, struct AudioData* data) {
cc_result res; cc_result res;
if ((res = Audio_SetFormat(ctx, snd->channels, snd->sampleRate))) return res; if ((res = Audio_SetFormat(ctx, data->channels, data->sampleRate))) return res;
if ((res = Audio_QueueData(ctx, data, snd->size))) return res; if ((res = Audio_QueueData(ctx, data->data, data->size))) return res;
if ((res = Audio_Play(ctx))) return res; if ((res = Audio_Play(ctx))) return res;
return 0; return 0;
} }
@ -980,27 +987,31 @@ CC_NOINLINE static void Sounds_Fail(cc_result res) {
} }
static void Sounds_Play(cc_uint8 type, struct Soundboard* board) { static void Sounds_Play(cc_uint8 type, struct Soundboard* board) {
const struct Sound* snd_; struct AudioData data;
struct Sound snd; const struct Sound* snd;
struct AudioContext* ctx; struct AudioContext* ctx;
int inUse, i, volume; int inUse, i;
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;
snd = *snd_; data.data = snd->data;
volume = Audio_SoundsVolume; data.size = snd->size;
data.channels = snd->channels;
data.sampleRate = snd->sampleRate;
data.rate = 100;
data.volume = Audio_SoundsVolume;
/* https://minecraft.fandom.com/wiki/Block_of_Gold#Sounds */ /* https://minecraft.fandom.com/wiki/Block_of_Gold#Sounds */
/* https://minecraft.fandom.com/wiki/Grass#Sounds */ /* https://minecraft.fandom.com/wiki/Grass#Sounds */
if (board == &digBoard) { if (board == &digBoard) {
if (type == SOUND_METAL) snd.sampleRate = (snd.sampleRate * 6) / 5; if (type == SOUND_METAL) data.rate = 120;
else snd.sampleRate = (snd.sampleRate * 4) / 5; else data.rate = 80;
} else { } else {
volume /= 2; data.volume /= 2;
if (type == SOUND_METAL) snd.sampleRate = (snd.sampleRate * 7) / 5; if (type == SOUND_METAL) data.rate = 140;
} }
/* Try to play on a context that doesn't need to be recreated */ /* Try to play on a context that doesn't need to be recreated */
@ -1010,9 +1021,9 @@ 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;
if (!Audio_FastPlay(ctx, snd.channels, snd.sampleRate)) continue; if (!Audio_FastPlay(ctx, &data)) continue;
res = Audio_PlaySound(ctx, &snd, volume); res = Audio_PlayData(ctx, &data);
if (res) Sounds_Fail(res); if (res) Sounds_Fail(res);
return; return;
} }
@ -1025,7 +1036,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;
res = Audio_PlaySound(ctx, &snd, volume); res = Audio_PlayData(ctx, &data);
if (res) Sounds_Fail(res); if (res) Sounds_Fail(res);
return; return;
} }

View File

@ -12,6 +12,13 @@ struct Sound {
int channels, sampleRate; int channels, sampleRate;
void* data; cc_uint32 size; void* data; cc_uint32 size;
}; };
struct AudioData {
void* data; cc_uint32 size; /* the raw 16 bit integer samples */
int channels;
int sampleRate; /* frequency / sample rate */
int volume; /* volume data played at (100 = normal volume) */
int rate; /* speed/pitch played at (100 = normal speed) */
};
/* Volume sounds are played at, from 0-100. */ /* Volume sounds are played at, from 0-100. */
/* NOTE: Use Audio_SetSounds, don't change this directly. */ /* NOTE: Use Audio_SetSounds, don't change this directly. */
@ -44,11 +51,10 @@ cc_result Audio_Play(struct AudioContext* ctx);
/* (e.g. if inUse is 0, no audio buffers are being played or queued) */ /* (e.g. if inUse is 0, no audio buffers are being played or queued) */
cc_result Audio_Poll(struct AudioContext* ctx, int* inUse); cc_result Audio_Poll(struct AudioContext* ctx, int* inUse);
/* Plays the given audio data at the given volume */ /* Plays the given audio data */
cc_result Audio_PlaySound(struct AudioContext* ctx, struct Sound* snd, int volume); cc_result Audio_PlayData(struct AudioContext* ctx, struct AudioData* data);
/* Whether the given audio context can play audio data in the given format, */ /* Whether the given audio data can be played without recreating the underlying audio device */
/* without recreating the underlying audio device */ cc_bool Audio_FastPlay(struct AudioContext* ctx, struct AudioData* data);
cc_bool Audio_FastPlay(struct AudioContext* ctx, int channels, int sampleRate);
/* Outputs more detailed information about errors with audio. */ /* Outputs more detailed information about errors with audio. */
cc_bool Audio_DescribeError(cc_result res, cc_string* dst); cc_bool Audio_DescribeError(cc_result res, cc_string* dst);
#endif #endif

View File

@ -206,7 +206,7 @@ static const cc_uint8 checkbox_indices[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
}; };
static PackedCol checkbox_palette[] = { static const PackedCol checkbox_palette[] = {
PackedCol_Make( 0, 0, 0, 0), PackedCol_Make(144, 144, 144, 255), PackedCol_Make( 0, 0, 0, 0), PackedCol_Make(144, 144, 144, 255),
PackedCol_Make( 61, 61, 61, 255), PackedCol_Make( 94, 94, 94, 255), PackedCol_Make( 61, 61, 61, 255), PackedCol_Make( 94, 94, 94, 255),
PackedCol_Make(197, 196, 197, 255), PackedCol_Make( 57, 57, 57, 255), PackedCol_Make(197, 196, 197, 255), PackedCol_Make( 57, 57, 57, 255),