Add one-shot audio playback (i.e. buffer all data)
This commit is contained in:
parent
1900de6a92
commit
b5db6e0e2b
115
src/Audio.c
115
src/Audio.c
@ -130,7 +130,7 @@ INTERNAL i32 rendererAcquire(MemoryArena *arena, AudioManager *audioManager,
|
||||
"rendererAcquire(): Renderer has not been released before "
|
||||
"acquiring, force release by stopping stream");
|
||||
#endif
|
||||
audio_streamStopVorbis(arena, audioManager, audioRenderer);
|
||||
audio_stopVorbis(arena, audioManager, audioRenderer);
|
||||
}
|
||||
|
||||
// TODO(doyle): Super bad linear O(n) search for every audio-enabled entity
|
||||
@ -209,8 +209,11 @@ INTERNAL const i32 rendererRelease(MemoryArena *arena, AudioManager *audioManage
|
||||
audioRenderer->bufferId[i] = 0;
|
||||
}
|
||||
|
||||
stb_vorbis_close(audioRenderer->audio->file);
|
||||
PLATFORM_MEM_FREE(arena, audioRenderer->audio, sizeof(AudioVorbis));
|
||||
if (audioRenderer->isStreaming)
|
||||
{
|
||||
stb_vorbis_close(audioRenderer->audio->file);
|
||||
PLATFORM_MEM_FREE(arena, audioRenderer->audio, sizeof(AudioVorbis));
|
||||
}
|
||||
|
||||
audioRenderer->audio = NULL;
|
||||
audioRenderer->numPlays = 0;
|
||||
@ -223,10 +226,10 @@ INTERNAL const i32 rendererRelease(MemoryArena *arena, AudioManager *audioManage
|
||||
return result;
|
||||
}
|
||||
|
||||
#define AUDIO_CHUNK_SIZE_ 65536
|
||||
const i32 audio_streamPlayVorbis(MemoryArena *arena, AudioManager *audioManager,
|
||||
AudioRenderer *audioRenderer,
|
||||
AudioVorbis *vorbis, i32 numPlays)
|
||||
INTERNAL i32 initRendererForPlayback(MemoryArena *arena,
|
||||
AudioManager *audioManager,
|
||||
AudioRenderer *audioRenderer,
|
||||
AudioVorbis *vorbis, i32 numPlays)
|
||||
{
|
||||
#ifdef DENGINE_DEBUG
|
||||
ASSERT(audioManager && audioRenderer && vorbis);
|
||||
@ -255,6 +258,39 @@ const i32 audio_streamPlayVorbis(MemoryArena *arena, AudioManager *audioManager,
|
||||
#endif
|
||||
}
|
||||
|
||||
audioRenderer->numPlays = numPlays;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const i32 audio_playVorbis(MemoryArena *arena, AudioManager *audioManager,
|
||||
AudioRenderer *audioRenderer, AudioVorbis *vorbis,
|
||||
i32 numPlays)
|
||||
{
|
||||
i32 result = initRendererForPlayback(arena, audioManager, audioRenderer,
|
||||
vorbis, numPlays);
|
||||
|
||||
i16 *soundSamples;
|
||||
i32 channels, sampleRate;
|
||||
i32 numSamples = stb_vorbis_decode_memory(
|
||||
vorbis->data, vorbis->size, &channels, &sampleRate, &soundSamples);
|
||||
alBufferData(audioRenderer->bufferId[0], audioRenderer->format,
|
||||
soundSamples, numSamples * vorbis->info.channels * sizeof(i16),
|
||||
vorbis->info.sample_rate);
|
||||
|
||||
audioRenderer->audio = vorbis;
|
||||
audioRenderer->isStreaming = FALSE;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const i32 audio_streamPlayVorbis(MemoryArena *arena, AudioManager *audioManager,
|
||||
AudioRenderer *audioRenderer,
|
||||
AudioVorbis *vorbis, i32 numPlays)
|
||||
{
|
||||
|
||||
i32 result = initRendererForPlayback(arena, audioManager, audioRenderer,
|
||||
vorbis, numPlays);
|
||||
// NOTE(doyle): We make a copy of the audio vorbis file using all the same
|
||||
// data except the file pointer. If the same sound is playing twice
|
||||
// simultaneously, we need unique file pointers into the data to track song
|
||||
@ -272,14 +308,14 @@ const i32 audio_streamPlayVorbis(MemoryArena *arena, AudioManager *audioManager,
|
||||
copyAudio->file =
|
||||
stb_vorbis_open_memory(copyAudio->data, copyAudio->size, &error, NULL);
|
||||
|
||||
audioRenderer->audio = copyAudio;
|
||||
audioRenderer->numPlays = numPlays;
|
||||
audioRenderer->audio = copyAudio;
|
||||
audioRenderer->isStreaming = TRUE;
|
||||
|
||||
return 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
const i32 audio_streamStopVorbis(MemoryArena *arena, AudioManager *audioManager,
|
||||
AudioRenderer *audioRenderer)
|
||||
const i32 audio_stopVorbis(MemoryArena *arena, AudioManager *audioManager,
|
||||
AudioRenderer *audioRenderer)
|
||||
{
|
||||
i32 result = 0;
|
||||
u32 alSourceId = getSourceId(audioManager, audioRenderer);
|
||||
@ -291,15 +327,22 @@ const i32 audio_streamStopVorbis(MemoryArena *arena, AudioManager *audioManager,
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG("audio_streamStopVorbis(): Tried to stop invalid source");
|
||||
#ifdef DENGINE_DEBUG
|
||||
if (audioRenderer->audio)
|
||||
{
|
||||
DEBUG_LOG(
|
||||
"audio_streamStopVorbis(): Tried to stop invalid source, but "
|
||||
"renderer has valid audio ptr");
|
||||
}
|
||||
#endif
|
||||
result = -1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const i32 audio_streamPauseVorbis(AudioManager *audioManager,
|
||||
AudioRenderer *audioRenderer)
|
||||
const i32 audio_pauseVorbis(AudioManager *audioManager,
|
||||
AudioRenderer *audioRenderer)
|
||||
{
|
||||
i32 result = 0;
|
||||
u32 alSourceId = getSourceId(audioManager, audioRenderer);
|
||||
@ -316,8 +359,8 @@ const i32 audio_streamPauseVorbis(AudioManager *audioManager,
|
||||
return result;
|
||||
}
|
||||
|
||||
const i32 audio_streamResumeVorbis(AudioManager *audioManager,
|
||||
AudioRenderer *audioRenderer)
|
||||
const i32 audio_resumeVorbis(AudioManager *audioManager,
|
||||
AudioRenderer *audioRenderer)
|
||||
{
|
||||
i32 result = 0;
|
||||
u32 alSourceId = getSourceId(audioManager, audioRenderer);
|
||||
@ -328,13 +371,16 @@ const i32 audio_streamResumeVorbis(AudioManager *audioManager,
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG("audio_streamResumeVorbis(): Tried to resume invalid source");
|
||||
#ifdef DENGINE_DEBUG
|
||||
DEBUG_LOG("audio_resumeVorbis(): Tried to resume invalid source")
|
||||
#endif
|
||||
result = -1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#define AUDIO_CHUNK_SIZE_ 65536
|
||||
const i32 audio_updateAndPlay(MemoryArena *arena, AudioManager *audioManager,
|
||||
AudioRenderer *audioRenderer)
|
||||
{
|
||||
@ -388,22 +434,31 @@ const i32 audio_updateAndPlay(MemoryArena *arena, AudioManager *audioManager,
|
||||
}
|
||||
}
|
||||
|
||||
stb_vorbis_seek_start(audio->file);
|
||||
for (i32 i = 0; i < ARRAY_COUNT(audioRenderer->bufferId); i++)
|
||||
if (audioRenderer->isStreaming)
|
||||
{
|
||||
i16 audioChunk[AUDIO_CHUNK_SIZE_] = {0};
|
||||
stb_vorbis_get_samples_short_interleaved(
|
||||
audio->file, audio->info.channels, audioChunk,
|
||||
AUDIO_CHUNK_SIZE_);
|
||||
stb_vorbis_seek_start(audio->file);
|
||||
for (i32 i = 0; i < ARRAY_COUNT(audioRenderer->bufferId); i++)
|
||||
{
|
||||
i16 audioChunk[AUDIO_CHUNK_SIZE_] = {0};
|
||||
stb_vorbis_get_samples_short_interleaved(
|
||||
audio->file, audio->info.channels, audioChunk,
|
||||
AUDIO_CHUNK_SIZE_);
|
||||
|
||||
alBufferData(audioRenderer->bufferId[i], audioRenderer->format,
|
||||
audioChunk, AUDIO_CHUNK_SIZE_ * sizeof(i16),
|
||||
audio->info.sample_rate);
|
||||
AL_CHECK_ERROR();
|
||||
alBufferData(audioRenderer->bufferId[i], audioRenderer->format,
|
||||
audioChunk, AUDIO_CHUNK_SIZE_ * sizeof(i16),
|
||||
audio->info.sample_rate);
|
||||
AL_CHECK_ERROR();
|
||||
}
|
||||
|
||||
alSourceQueueBuffers(alSourceId,
|
||||
ARRAY_COUNT(audioRenderer->bufferId),
|
||||
audioRenderer->bufferId);
|
||||
}
|
||||
else
|
||||
{
|
||||
alSourceQueueBuffers(alSourceId, 1, audioRenderer->bufferId);
|
||||
}
|
||||
|
||||
alSourceQueueBuffers(alSourceId, ARRAY_COUNT(audioRenderer->bufferId),
|
||||
audioRenderer->bufferId);
|
||||
AL_CHECK_ERROR();
|
||||
alSourcePlay(alSourceId);
|
||||
AL_CHECK_ERROR();
|
||||
|
@ -13,6 +13,7 @@ enum State
|
||||
|
||||
enum EventType
|
||||
{
|
||||
eventtype_null = 0,
|
||||
eventtype_start_attack,
|
||||
eventtype_end_attack,
|
||||
eventtype_start_anim,
|
||||
@ -1035,10 +1036,10 @@ void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt)
|
||||
if (!event.data) continue;
|
||||
|
||||
Entity *entity = (CAST(Entity *) event.data);
|
||||
audio_streamPlayVorbis(
|
||||
audio_playVorbis(
|
||||
arena, audioManager, entity->audioRenderer,
|
||||
asset_getVorbis(assetManager, audiolist_tackle), 1);
|
||||
break;
|
||||
break;
|
||||
}
|
||||
// NOTE(doyle): We delete dead entities at the end of the update
|
||||
// loop incase a later indexed entity deletes an earlier indexed
|
||||
@ -1049,8 +1050,8 @@ void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt)
|
||||
if (!event.data) continue;
|
||||
|
||||
Entity *entity = (CAST(Entity *) event.data);
|
||||
audio_streamStopVorbis(&state->arena, audioManager,
|
||||
entity->audioRenderer);
|
||||
audio_stopVorbis(&state->arena, audioManager,
|
||||
entity->audioRenderer);
|
||||
entity_clearData(&state->arena, world, entity);
|
||||
numDeadEntities++;
|
||||
break;
|
||||
|
@ -29,23 +29,28 @@ typedef struct AudioManager
|
||||
typedef struct AudioRenderer
|
||||
{
|
||||
i32 sourceIndex;
|
||||
ALuint bufferId[4];
|
||||
ALuint bufferId[3];
|
||||
|
||||
AudioVorbis *audio;
|
||||
ALuint format;
|
||||
i32 numPlays;
|
||||
|
||||
b32 isStreaming;
|
||||
} AudioRenderer;
|
||||
|
||||
|
||||
const i32 audio_init(AudioManager *audioManager);
|
||||
const i32 audio_playVorbis(MemoryArena *arena, AudioManager *audioManager,
|
||||
AudioRenderer *audioRenderer, AudioVorbis *vorbis,
|
||||
i32 numPlays);
|
||||
const i32 audio_streamPlayVorbis(MemoryArena *arena, AudioManager *audioManager,
|
||||
AudioRenderer *audioRenderer,
|
||||
AudioVorbis *vorbis, i32 numPlays);
|
||||
const i32 audio_streamStopVorbis(MemoryArena *arena, AudioManager *audioManager,
|
||||
const i32 audio_stopVorbis(MemoryArena *arena, AudioManager *audioManager,
|
||||
AudioRenderer *audioRenderer);
|
||||
const i32 audio_streamPauseVorbis(AudioManager *audioManager,
|
||||
const i32 audio_pauseVorbis(AudioManager *audioManager,
|
||||
AudioRenderer *audioRenderer);
|
||||
const i32 audio_streamResumeVorbis(AudioManager *audioManager,
|
||||
const i32 audio_resumeVorbis(AudioManager *audioManager,
|
||||
AudioRenderer *audioRenderer);
|
||||
const i32 audio_updateAndPlay(MemoryArena *arena, AudioManager *audioManager,
|
||||
AudioRenderer *audioRenderer);
|
||||
|
@ -9,9 +9,6 @@
|
||||
#include "Dengine/MemoryArena.h"
|
||||
#include "Dengine/Renderer.h"
|
||||
|
||||
/* Forward Declaration */
|
||||
typedef struct MemoryArena MemoryArena;
|
||||
|
||||
#define NUM_KEYS 1024
|
||||
#define METERS_TO_PIXEL 240
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user