Add one-shot audio playback (i.e. buffer all data)

This commit is contained in:
Doyle Thai 2016-08-04 00:32:13 +10:00
parent 1900de6a92
commit b5db6e0e2b
4 changed files with 99 additions and 41 deletions

View File

@ -130,7 +130,7 @@ INTERNAL i32 rendererAcquire(MemoryArena *arena, AudioManager *audioManager,
"rendererAcquire(): Renderer has not been released before " "rendererAcquire(): Renderer has not been released before "
"acquiring, force release by stopping stream"); "acquiring, force release by stopping stream");
#endif #endif
audio_streamStopVorbis(arena, audioManager, audioRenderer); audio_stopVorbis(arena, audioManager, audioRenderer);
} }
// TODO(doyle): Super bad linear O(n) search for every audio-enabled entity // 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; audioRenderer->bufferId[i] = 0;
} }
if (audioRenderer->isStreaming)
{
stb_vorbis_close(audioRenderer->audio->file); stb_vorbis_close(audioRenderer->audio->file);
PLATFORM_MEM_FREE(arena, audioRenderer->audio, sizeof(AudioVorbis)); PLATFORM_MEM_FREE(arena, audioRenderer->audio, sizeof(AudioVorbis));
}
audioRenderer->audio = NULL; audioRenderer->audio = NULL;
audioRenderer->numPlays = 0; audioRenderer->numPlays = 0;
@ -223,8 +226,8 @@ INTERNAL const i32 rendererRelease(MemoryArena *arena, AudioManager *audioManage
return result; return result;
} }
#define AUDIO_CHUNK_SIZE_ 65536 INTERNAL i32 initRendererForPlayback(MemoryArena *arena,
const i32 audio_streamPlayVorbis(MemoryArena *arena, AudioManager *audioManager, AudioManager *audioManager,
AudioRenderer *audioRenderer, AudioRenderer *audioRenderer,
AudioVorbis *vorbis, i32 numPlays) AudioVorbis *vorbis, i32 numPlays)
{ {
@ -255,6 +258,39 @@ const i32 audio_streamPlayVorbis(MemoryArena *arena, AudioManager *audioManager,
#endif #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 // 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 // data except the file pointer. If the same sound is playing twice
// simultaneously, we need unique file pointers into the data to track song // simultaneously, we need unique file pointers into the data to track song
@ -273,12 +309,12 @@ const i32 audio_streamPlayVorbis(MemoryArena *arena, AudioManager *audioManager,
stb_vorbis_open_memory(copyAudio->data, copyAudio->size, &error, NULL); stb_vorbis_open_memory(copyAudio->data, copyAudio->size, &error, NULL);
audioRenderer->audio = copyAudio; audioRenderer->audio = copyAudio;
audioRenderer->numPlays = numPlays; audioRenderer->isStreaming = TRUE;
return 0; return result;
} }
const i32 audio_streamStopVorbis(MemoryArena *arena, AudioManager *audioManager, const i32 audio_stopVorbis(MemoryArena *arena, AudioManager *audioManager,
AudioRenderer *audioRenderer) AudioRenderer *audioRenderer)
{ {
i32 result = 0; i32 result = 0;
@ -291,14 +327,21 @@ const i32 audio_streamStopVorbis(MemoryArena *arena, AudioManager *audioManager,
} }
else 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; result = -1;
} }
return result; return result;
} }
const i32 audio_streamPauseVorbis(AudioManager *audioManager, const i32 audio_pauseVorbis(AudioManager *audioManager,
AudioRenderer *audioRenderer) AudioRenderer *audioRenderer)
{ {
i32 result = 0; i32 result = 0;
@ -316,7 +359,7 @@ const i32 audio_streamPauseVorbis(AudioManager *audioManager,
return result; return result;
} }
const i32 audio_streamResumeVorbis(AudioManager *audioManager, const i32 audio_resumeVorbis(AudioManager *audioManager,
AudioRenderer *audioRenderer) AudioRenderer *audioRenderer)
{ {
i32 result = 0; i32 result = 0;
@ -328,13 +371,16 @@ const i32 audio_streamResumeVorbis(AudioManager *audioManager,
} }
else 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; result = -1;
} }
return result; return result;
} }
#define AUDIO_CHUNK_SIZE_ 65536
const i32 audio_updateAndPlay(MemoryArena *arena, AudioManager *audioManager, const i32 audio_updateAndPlay(MemoryArena *arena, AudioManager *audioManager,
AudioRenderer *audioRenderer) AudioRenderer *audioRenderer)
{ {
@ -388,6 +434,8 @@ const i32 audio_updateAndPlay(MemoryArena *arena, AudioManager *audioManager,
} }
} }
if (audioRenderer->isStreaming)
{
stb_vorbis_seek_start(audio->file); stb_vorbis_seek_start(audio->file);
for (i32 i = 0; i < ARRAY_COUNT(audioRenderer->bufferId); i++) for (i32 i = 0; i < ARRAY_COUNT(audioRenderer->bufferId); i++)
{ {
@ -402,8 +450,15 @@ const i32 audio_updateAndPlay(MemoryArena *arena, AudioManager *audioManager,
AL_CHECK_ERROR(); AL_CHECK_ERROR();
} }
alSourceQueueBuffers(alSourceId, ARRAY_COUNT(audioRenderer->bufferId), alSourceQueueBuffers(alSourceId,
ARRAY_COUNT(audioRenderer->bufferId),
audioRenderer->bufferId); audioRenderer->bufferId);
}
else
{
alSourceQueueBuffers(alSourceId, 1, audioRenderer->bufferId);
}
AL_CHECK_ERROR(); AL_CHECK_ERROR();
alSourcePlay(alSourceId); alSourcePlay(alSourceId);
AL_CHECK_ERROR(); AL_CHECK_ERROR();

View File

@ -13,6 +13,7 @@ enum State
enum EventType enum EventType
{ {
eventtype_null = 0,
eventtype_start_attack, eventtype_start_attack,
eventtype_end_attack, eventtype_end_attack,
eventtype_start_anim, eventtype_start_anim,
@ -1035,7 +1036,7 @@ void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt)
if (!event.data) continue; if (!event.data) continue;
Entity *entity = (CAST(Entity *) event.data); Entity *entity = (CAST(Entity *) event.data);
audio_streamPlayVorbis( audio_playVorbis(
arena, audioManager, entity->audioRenderer, arena, audioManager, entity->audioRenderer,
asset_getVorbis(assetManager, audiolist_tackle), 1); asset_getVorbis(assetManager, audiolist_tackle), 1);
break; break;
@ -1049,7 +1050,7 @@ void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt)
if (!event.data) continue; if (!event.data) continue;
Entity *entity = (CAST(Entity *) event.data); Entity *entity = (CAST(Entity *) event.data);
audio_streamStopVorbis(&state->arena, audioManager, audio_stopVorbis(&state->arena, audioManager,
entity->audioRenderer); entity->audioRenderer);
entity_clearData(&state->arena, world, entity); entity_clearData(&state->arena, world, entity);
numDeadEntities++; numDeadEntities++;

View File

@ -29,23 +29,28 @@ typedef struct AudioManager
typedef struct AudioRenderer typedef struct AudioRenderer
{ {
i32 sourceIndex; i32 sourceIndex;
ALuint bufferId[4]; ALuint bufferId[3];
AudioVorbis *audio; AudioVorbis *audio;
ALuint format; ALuint format;
i32 numPlays; i32 numPlays;
b32 isStreaming;
} AudioRenderer; } AudioRenderer;
const i32 audio_init(AudioManager *audioManager); 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, const i32 audio_streamPlayVorbis(MemoryArena *arena, AudioManager *audioManager,
AudioRenderer *audioRenderer, AudioRenderer *audioRenderer,
AudioVorbis *vorbis, i32 numPlays); AudioVorbis *vorbis, i32 numPlays);
const i32 audio_streamStopVorbis(MemoryArena *arena, AudioManager *audioManager, const i32 audio_stopVorbis(MemoryArena *arena, AudioManager *audioManager,
AudioRenderer *audioRenderer); AudioRenderer *audioRenderer);
const i32 audio_streamPauseVorbis(AudioManager *audioManager, const i32 audio_pauseVorbis(AudioManager *audioManager,
AudioRenderer *audioRenderer); AudioRenderer *audioRenderer);
const i32 audio_streamResumeVorbis(AudioManager *audioManager, const i32 audio_resumeVorbis(AudioManager *audioManager,
AudioRenderer *audioRenderer); AudioRenderer *audioRenderer);
const i32 audio_updateAndPlay(MemoryArena *arena, AudioManager *audioManager, const i32 audio_updateAndPlay(MemoryArena *arena, AudioManager *audioManager,
AudioRenderer *audioRenderer); AudioRenderer *audioRenderer);

View File

@ -9,9 +9,6 @@
#include "Dengine/MemoryArena.h" #include "Dengine/MemoryArena.h"
#include "Dengine/Renderer.h" #include "Dengine/Renderer.h"
/* Forward Declaration */
typedef struct MemoryArena MemoryArena;
#define NUM_KEYS 1024 #define NUM_KEYS 1024
#define METERS_TO_PIXEL 240 #define METERS_TO_PIXEL 240