mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-12 09:06:55 -04:00
WIP on adding speed/rate argument when playing sounds instead
This commit is contained in:
parent
6e433e5585
commit
97fcc429bf
103
src/Audio.c
103
src/Audio.c
@ -54,8 +54,8 @@ static void AudioWarn(cc_result res, const char* action) {
|
||||
Logger_Warn(res, action, Audio_DescribeError);
|
||||
}
|
||||
static void AudioBase_Clear(struct AudioContext* ctx);
|
||||
static void* AudioBase_AdjustSound(struct AudioContext* ctx, struct Sound* snd, int volume);
|
||||
static cc_result AudioBase_PlaySound(struct AudioContext* ctx, struct Sound* snd, void* data);
|
||||
static cc_bool AudioBase_AdjustSound(struct AudioContext* ctx, struct AudioData* data);
|
||||
static cc_result AudioBase_PlaySound(struct AudioContext* ctx, struct AudioData* data);
|
||||
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
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 */
|
||||
return true;
|
||||
}
|
||||
|
||||
cc_result Audio_PlaySound(struct AudioContext* ctx, struct Sound* snd, int volume) {
|
||||
void* data = AudioBase_AdjustSound(ctx, snd, volume);
|
||||
if (data) return AudioBase_PlaySound(ctx, snd, data);
|
||||
cc_result Audio_PlayData(struct AudioContext* ctx, struct Sound* snd, int volume) {
|
||||
cc_book ok = AudioBase_AdjustSound(ctx, snd, volume);
|
||||
if (ok) return AudioBase_PlaySound(ctx, snd, data);
|
||||
return ERR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
@ -477,15 +477,21 @@ cc_result Audio_Poll(struct AudioContext* ctx, int* inUse) {
|
||||
|
||||
*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);
|
||||
}
|
||||
|
||||
cc_result Audio_PlaySound(struct AudioContext* ctx, struct Sound* snd, int volume) {
|
||||
void* data = AudioBase_AdjustSound(ctx, snd, volume);
|
||||
if (data) return AudioBase_PlaySound(ctx, snd, data);
|
||||
return ERR_OUT_OF_MEMORY;
|
||||
cc_result Audio_PlayData(struct AudioContext* ctx, struct AudioData* data) {
|
||||
cc_bool ok = AudioBase_AdjustSound(ctx, data);
|
||||
if (!ok) 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) {
|
||||
@ -684,9 +690,9 @@ cc_bool Audio_FastPlay(struct AudioContext* ctx, int channels, int sampleRate) {
|
||||
return !ctx->channels || (ctx->channels == channels && ctx->sampleRate == sampleRate);
|
||||
}
|
||||
|
||||
cc_result Audio_PlaySound(struct AudioContext* ctx, struct Sound* snd, int volume) {
|
||||
void* data = AudioBase_AdjustSound(ctx, snd, volume);
|
||||
if (data) return AudioBase_PlaySound(ctx, snd, data);
|
||||
cc_result Audio_PlayData(struct AudioContext* ctx, struct Sound* snd, int volume) {
|
||||
cc_bool ok = AudioBase_AdjustSound(ctx, snd, volume);
|
||||
if (ok) return AudioBase_PlaySound(ctx, snd, data);
|
||||
return ERR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
@ -756,12 +762,12 @@ cc_result Audio_Poll(struct AudioContext* ctx, int* inUse) {
|
||||
*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 */
|
||||
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)
|
||||
ctx->contextID = interop_AudioCreate();
|
||||
return interop_AudioPlay(ctx->contextID, snd, volume);
|
||||
@ -792,34 +798,35 @@ static void AudioBase_Clear(struct AudioContext* ctx) {
|
||||
ctx->_tmpSize = 0;
|
||||
}
|
||||
|
||||
static void* AudioBase_AdjustSound(struct AudioContext* ctx, struct Sound* snd, int volume) {
|
||||
void* data;
|
||||
if (volume >= 100) return snd->data;
|
||||
static cc_bool AudioBase_AdjustSound(struct AudioContext* ctx, struct AudioData* data) {
|
||||
void* audio;
|
||||
if (data->volume >= 100) return true;
|
||||
|
||||
/* 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 */
|
||||
if (ctx->_tmpData) {
|
||||
data = Mem_TryRealloc(ctx->_tmpData, snd->size, 1);
|
||||
audio = Mem_TryRealloc(ctx->_tmpData, data->size, 1);
|
||||
} else {
|
||||
data = Mem_TryAlloc(snd->size, 1);
|
||||
audio = Mem_TryAlloc(data->size, 1);
|
||||
}
|
||||
|
||||
if (!data) return NULL;
|
||||
ctx->_tmpData = data;
|
||||
ctx->_tmpSize = snd->size;
|
||||
if (!data) return false;
|
||||
ctx->_tmpData = audio;
|
||||
ctx->_tmpSize = data->size;
|
||||
}
|
||||
|
||||
data = ctx->_tmpData;
|
||||
Mem_Copy(data, snd->data, snd->size);
|
||||
ApplyVolume((cc_int16*)data, snd->size / 2, volume);
|
||||
return data;
|
||||
audio = ctx->_tmpData;
|
||||
Mem_Copy(audio, data->data, data->size);
|
||||
ApplyVolume((cc_int16*)audio, data->size / 2, data->volume);
|
||||
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;
|
||||
if ((res = Audio_SetFormat(ctx, snd->channels, snd->sampleRate))) return res;
|
||||
if ((res = Audio_QueueData(ctx, data, snd->size))) return res;
|
||||
if ((res = Audio_SetFormat(ctx, data->channels, data->sampleRate))) return res;
|
||||
if ((res = Audio_QueueData(ctx, data->data, data->size))) return res;
|
||||
if ((res = Audio_Play(ctx))) return res;
|
||||
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) {
|
||||
const struct Sound* snd_;
|
||||
struct Sound snd;
|
||||
struct AudioData data;
|
||||
const struct Sound* snd;
|
||||
struct AudioContext* ctx;
|
||||
int inUse, i, volume;
|
||||
int inUse, i;
|
||||
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;
|
||||
|
||||
snd = *snd_;
|
||||
volume = Audio_SoundsVolume;
|
||||
data.data = snd->data;
|
||||
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/Grass#Sounds */
|
||||
if (board == &digBoard) {
|
||||
if (type == SOUND_METAL) snd.sampleRate = (snd.sampleRate * 6) / 5;
|
||||
else snd.sampleRate = (snd.sampleRate * 4) / 5;
|
||||
if (type == SOUND_METAL) data.rate = 120;
|
||||
else data.rate = 80;
|
||||
} else {
|
||||
volume /= 2;
|
||||
if (type == SOUND_METAL) snd.sampleRate = (snd.sampleRate * 7) / 5;
|
||||
data.volume /= 2;
|
||||
if (type == SOUND_METAL) data.rate = 140;
|
||||
}
|
||||
|
||||
/* 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 (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);
|
||||
return;
|
||||
}
|
||||
@ -1025,7 +1036,7 @@ static void Sounds_Play(cc_uint8 type, struct Soundboard* board) {
|
||||
if (res) { Sounds_Fail(res); return; }
|
||||
if (inUse > 0) continue;
|
||||
|
||||
res = Audio_PlaySound(ctx, &snd, volume);
|
||||
res = Audio_PlayData(ctx, &data);
|
||||
if (res) Sounds_Fail(res);
|
||||
return;
|
||||
}
|
||||
|
16
src/Audio.h
16
src/Audio.h
@ -12,6 +12,13 @@ struct Sound {
|
||||
int channels, sampleRate;
|
||||
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. */
|
||||
/* 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) */
|
||||
cc_result Audio_Poll(struct AudioContext* ctx, int* inUse);
|
||||
|
||||
/* Plays the given audio data at the given volume */
|
||||
cc_result Audio_PlaySound(struct AudioContext* ctx, struct Sound* snd, int volume);
|
||||
/* Whether the given audio context can play audio data in the given format, */
|
||||
/* without recreating the underlying audio device */
|
||||
cc_bool Audio_FastPlay(struct AudioContext* ctx, int channels, int sampleRate);
|
||||
/* 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. */
|
||||
cc_bool Audio_DescribeError(cc_result res, cc_string* dst);
|
||||
#endif
|
||||
|
@ -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,
|
||||
};
|
||||
static PackedCol checkbox_palette[] = {
|
||||
static const PackedCol checkbox_palette[] = {
|
||||
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(197, 196, 197, 255), PackedCol_Make( 57, 57, 57, 255),
|
||||
|
Loading…
x
Reference in New Issue
Block a user