Add audio-streaming and loop support
This commit is contained in:
parent
6b2e759257
commit
99a700ca13
@ -149,7 +149,11 @@ int main()
|
|||||||
*******************
|
*******************
|
||||||
*/
|
*/
|
||||||
alGetError();
|
alGetError();
|
||||||
// TODO(doyle): Read this http://www.gamedev.net/page/resources/_/technical/game-programming/basic-openal-sound-manager-for-your-project-r3791
|
// TODO(doyle): Read this
|
||||||
|
// http://www.gamedev.net/page/resources/_/technical/game-programming/basic-openal-sound-manager-for-your-project-r3791
|
||||||
|
// https://gist.github.com/Oddity007/965399
|
||||||
|
// https://jogamp.org/joal-demos/www/devmaster/lesson8.html
|
||||||
|
// http://basic-converter.proboards.com/thread/818/play-files-using-vorbis-openal
|
||||||
ALCdevice *deviceAL = alcOpenDevice(NULL);
|
ALCdevice *deviceAL = alcOpenDevice(NULL);
|
||||||
if (!deviceAL)
|
if (!deviceAL)
|
||||||
{
|
{
|
||||||
@ -168,32 +172,33 @@ int main()
|
|||||||
|
|
||||||
/* Open audio file */
|
/* Open audio file */
|
||||||
PlatformFileRead fileRead = {0};
|
PlatformFileRead fileRead = {0};
|
||||||
|
#if 0
|
||||||
platform_readFileToBuffer(&worldTraveller.arena,
|
platform_readFileToBuffer(&worldTraveller.arena,
|
||||||
"data/audio/Yuki Kajiura - Swordland.ogg",
|
"data/audio/Yuki Kajiura - Swordland.ogg",
|
||||||
&fileRead);
|
&fileRead);
|
||||||
|
#else
|
||||||
|
platform_readFileToBuffer(&worldTraveller.arena,
|
||||||
|
"data/audio/Nobuo Uematsu - Battle 1.ogg",
|
||||||
|
&fileRead);
|
||||||
|
#endif
|
||||||
|
|
||||||
i32 channels, sampleRate, numSamples;
|
i32 error;
|
||||||
ALshort *vorbisData = NULL;
|
stb_vorbis *vorbisFile = stb_vorbis_open_memory(fileRead.buffer, fileRead.size,
|
||||||
numSamples = stb_vorbis_decode_memory(fileRead.buffer, fileRead.size,
|
&error, NULL);
|
||||||
&channels, &sampleRate, &vorbisData);
|
stb_vorbis_info vorbisInfo = stb_vorbis_get_info(vorbisFile);
|
||||||
|
|
||||||
platform_closeFileRead(&worldTraveller.arena, &fileRead);
|
//platform_closeFileRead(&worldTraveller.arena, &fileRead);
|
||||||
|
|
||||||
/* Number of concurrent audio files */
|
/* Generate number of concurrent audio file listeners */
|
||||||
ALuint audioSourceId;
|
ALuint audioSourceId;
|
||||||
alGenSources(1, &audioSourceId);
|
alGenSources(1, &audioSourceId);
|
||||||
AL_CHECK_ERROR();
|
AL_CHECK_ERROR();
|
||||||
|
|
||||||
/* Audio data buffers */
|
/* Generate audio data buffers */
|
||||||
ALuint audioBufferId;
|
ALuint audioBufferId[4];
|
||||||
alGenBuffers(1, &audioBufferId);
|
alGenBuffers(ARRAY_COUNT(audioBufferId), audioBufferId);
|
||||||
AL_CHECK_ERROR();
|
AL_CHECK_ERROR();
|
||||||
|
|
||||||
alBufferData(audioBufferId, AL_FORMAT_STEREO16, vorbisData,
|
|
||||||
numSamples * channels * sizeof(i16), sampleRate);
|
|
||||||
|
|
||||||
alSourceQueueBuffers(audioSourceId, 1, &audioBufferId);
|
|
||||||
alSourcePlay(audioSourceId);
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
ALuint audioFormat = AL_FORMAT_MONO16;
|
ALuint audioFormat = AL_FORMAT_MONO16;
|
||||||
@ -239,6 +244,64 @@ int main()
|
|||||||
f32 endTime = CAST(f32)glfwGetTime();
|
f32 endTime = CAST(f32)glfwGetTime();
|
||||||
secondsElapsed = endTime - startTime;
|
secondsElapsed = endTime - startTime;
|
||||||
|
|
||||||
|
#define AUDIO_CHUNK_SIZE 65536
|
||||||
|
ALint audioState;
|
||||||
|
alGetSourcei(audioSourceId, AL_SOURCE_STATE, &audioState);
|
||||||
|
if (audioState == AL_STOPPED || audioState == AL_INITIAL)
|
||||||
|
{
|
||||||
|
// TODO(doyle): This fixes clicking when reusing old buffers
|
||||||
|
if (audioState == AL_STOPPED)
|
||||||
|
{
|
||||||
|
alDeleteBuffers(ARRAY_COUNT(audioBufferId), audioBufferId);
|
||||||
|
alGenBuffers(ARRAY_COUNT(audioBufferId), audioBufferId);
|
||||||
|
}
|
||||||
|
|
||||||
|
stb_vorbis_seek_start(vorbisFile);
|
||||||
|
for (i32 i = 0; i < ARRAY_COUNT(audioBufferId); i++)
|
||||||
|
{
|
||||||
|
i16 audioChunk[AUDIO_CHUNK_SIZE] = {0};
|
||||||
|
stb_vorbis_get_samples_short_interleaved(
|
||||||
|
vorbisFile, vorbisInfo.channels, audioChunk,
|
||||||
|
AUDIO_CHUNK_SIZE);
|
||||||
|
|
||||||
|
alBufferData(audioBufferId[i], AL_FORMAT_STEREO16, audioChunk,
|
||||||
|
AUDIO_CHUNK_SIZE * sizeof(i16),
|
||||||
|
vorbisInfo.sample_rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
alSourceQueueBuffers(audioSourceId, ARRAY_COUNT(audioBufferId),
|
||||||
|
audioBufferId);
|
||||||
|
alSourcePlay(audioSourceId);
|
||||||
|
}
|
||||||
|
else if (audioState == AL_PLAYING)
|
||||||
|
{
|
||||||
|
ALint numProcessedBuffers;
|
||||||
|
alGetSourcei(audioSourceId, AL_BUFFERS_PROCESSED,
|
||||||
|
&numProcessedBuffers);
|
||||||
|
if (numProcessedBuffers > 0)
|
||||||
|
{
|
||||||
|
ALint numBuffersToUnqueue = 1;
|
||||||
|
ALuint emptyBufferId;
|
||||||
|
alSourceUnqueueBuffers(audioSourceId, numBuffersToUnqueue,
|
||||||
|
&emptyBufferId);
|
||||||
|
|
||||||
|
i16 audioChunk[AUDIO_CHUNK_SIZE] = {0};
|
||||||
|
i32 sampleCount = stb_vorbis_get_samples_short_interleaved(
|
||||||
|
vorbisFile, vorbisInfo.channels, audioChunk,
|
||||||
|
AUDIO_CHUNK_SIZE);
|
||||||
|
|
||||||
|
/* There are still samples to play */
|
||||||
|
if (sampleCount > 0)
|
||||||
|
{
|
||||||
|
DEBUG_LOG("Buffering new audio data");
|
||||||
|
alBufferData(emptyBufferId, AL_FORMAT_STEREO16, audioChunk,
|
||||||
|
sampleCount * vorbisInfo.channels *
|
||||||
|
sizeof(i16),
|
||||||
|
vorbisInfo.sample_rate);
|
||||||
|
alSourceQueueBuffers(audioSourceId, 1, &emptyBufferId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
#if 0
|
#if 0
|
||||||
// TODO(doyle): Busy waiting, should sleep
|
// TODO(doyle): Busy waiting, should sleep
|
||||||
while (secondsElapsed < targetSecondsPerFrame)
|
while (secondsElapsed < targetSecondsPerFrame)
|
||||||
|
Loading…
Reference in New Issue
Block a user