diff options
| author | raysan5 <raysan5@gmail.com> | 2014-04-19 16:36:49 +0200 |
|---|---|---|
| committer | raysan5 <raysan5@gmail.com> | 2014-04-19 16:36:49 +0200 |
| commit | f06a15ac8b3fe92d101ae795225fbf56fa670dba (patch) | |
| tree | cdfba90ee24fd078a15c89d8753ee3e11d8e229b /src/audio.c | |
| parent | 650a8f7f159d3ce2addb1b0fdb31c3f460005391 (diff) | |
| download | raylib-f06a15ac8b3fe92d101ae795225fbf56fa670dba.tar.gz raylib-f06a15ac8b3fe92d101ae795225fbf56fa670dba.zip | |
raylib 1.1
View CHANGELOG for a detailed list of changes
Diffstat (limited to 'src/audio.c')
| -rw-r--r-- | src/audio.c | 630 |
1 files changed, 346 insertions, 284 deletions
diff --git a/src/audio.c b/src/audio.c index 35874b59..c32b9f6e 100644 --- a/src/audio.c +++ b/src/audio.c @@ -6,7 +6,7 @@ * * Uses external lib: * OpenAL - Audio device management lib -* TODO: stb_vorbis - Ogg audio files loading +* stb_vorbis - Ogg audio files loading * * Copyright (c) 2013 Ramon Santamaria (Ray San - raysan@raysanweb.com) * @@ -32,50 +32,45 @@ #include <AL/al.h> // OpenAL basic header #include <AL/alc.h> // OpenAL context header (like OpenGL, OpenAL requires a context to work) -#include <stdlib.h> // To use exit() function +#include <stdlib.h> // Declares malloc() and free() for memory management +#include <string.h> // Required for strcmp() #include <stdio.h> // Used for .WAV loading #include "utils.h" // rRES data decompression utility function -//#include "stb_vorbis.h" // OGG loading functions +#include "stb_vorbis.h" // OGG loading functions //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- -// Nop... +#define MUSIC_STREAM_BUFFERS 2 +#define MUSIC_BUFFER_SIZE 4096*8 //4096*32 //---------------------------------------------------------------------------------- // Types and Structures Definition //---------------------------------------------------------------------------------- -// Sound source type (all file loaded in memory) -/* -struct Sound { - unsigned int source; - unsigned int buffer; -}; - -// Music type (file streamming from memory) -// NOTE: Anything longer than ~10 seconds should be Music... -struct Music { - stb_vorbis* stream; - stb_vorbis_info info; - - ALuint id; - ALuint buffers[2]; + +// Music type (file streaming from memory) +// NOTE: Anything longer than ~10 seconds should be streamed... +typedef struct Music { + stb_vorbis *stream; + + ALuint buffers[MUSIC_STREAM_BUFFERS]; ALuint source; ALenum format; - int bufferSize; + int channels; + int sampleRate; int totalSamplesLeft; bool loop; -}; -*/ + +} Music; // Wave file data typedef struct Wave { - unsigned char *data; // Buffer data pointer + void *data; // Buffer data pointer + unsigned int dataSize; // Data size in bytes unsigned int sampleRate; - unsigned int dataSize; short bitsPerSample; short channels; } Wave; @@ -83,22 +78,23 @@ typedef struct Wave { //---------------------------------------------------------------------------------- // Global Variables Definition //---------------------------------------------------------------------------------- -static bool musicIsPlaying; -static Music *currentMusic; +bool musicEnabled = false; +static Music currentMusic; // Current music loaded + // NOTE: Only one music file playing at a time //---------------------------------------------------------------------------------- // Module specific Functions Declaration //---------------------------------------------------------------------------------- -static Wave LoadWAV(char *fileName); -static void UnloadWAV(Wave wave); -//static Ogg LoadOGG(char *fileName); -static bool MusicStream(Music music, ALuint buffer); +static Wave LoadWAV(const char *fileName); +static Wave LoadOGG(char *fileName); +static void UnloadWave(Wave wave); -extern bool MusicStreamUpdate(); -extern void PlayCurrentMusic(); +static bool BufferMusicStream(ALuint buffer); // Fill music buffers with data +static void EmptyMusicStream(); // Empty music buffers +extern void UpdateMusicStream(); // Updates buffers (refill) for music streaming //---------------------------------------------------------------------------------- -// Module Functions Definition - Window and OpenGL Context Functions +// Module Functions Definition - Audio Device initialization and Closing //---------------------------------------------------------------------------------- // Initialize audio device and context @@ -126,13 +122,13 @@ void InitAudioDevice() alListener3f(AL_POSITION, 0, 0, 0); alListener3f(AL_VELOCITY, 0, 0, 0); alListener3f(AL_ORIENTATION, 0, 0, -1); - - musicIsPlaying = false; } // Close the audio device for the current context, and destroys the context void CloseAudioDevice() { + StopMusicStream(); // Stop music streaming and close current stream + ALCdevice *device; ALCcontext *context = alcGetCurrentContext(); @@ -145,60 +141,70 @@ void CloseAudioDevice() alcCloseDevice(device); } +//---------------------------------------------------------------------------------- +// Module Functions Definition - Sounds loading and playing (.WAV) +//---------------------------------------------------------------------------------- + // Load sound to memory Sound LoadSound(char *fileName) { Sound sound; + Wave wave; // NOTE: The entire file is loaded to memory to play it all at once (no-streaming) - // WAV file loading - // NOTE: Buffer space is allocated inside LoadWAV, Wave must be freed - Wave wave = LoadWAV(fileName); - - ALenum format = 0; - // The OpenAL format is worked out by looking at the number of channels and the bits per sample - if (wave.channels == 1) - { - if (wave.bitsPerSample == 8 ) format = AL_FORMAT_MONO8; - else if (wave.bitsPerSample == 16) format = AL_FORMAT_MONO16; - } - else if (wave.channels == 2) - { - if (wave.bitsPerSample == 8 ) format = AL_FORMAT_STEREO8; - else if (wave.bitsPerSample == 16) format = AL_FORMAT_STEREO16; - } - + // Audio file loading + // NOTE: Buffer space is allocated inside function, Wave must be freed - // Create an audio source - ALuint source; - alGenSources(1, &source); // Generate pointer to audio source - - alSourcef(source, AL_PITCH, 1); - alSourcef(source, AL_GAIN, 1); - alSource3f(source, AL_POSITION, 0, 0, 0); - alSource3f(source, AL_VELOCITY, 0, 0, 0); - alSourcei(source, AL_LOOPING, AL_FALSE); + if (strcmp(GetExtension(fileName),"wav") == 0) wave = LoadWAV(fileName); + else if (strcmp(GetExtension(fileName),"ogg") == 0) wave = LoadOGG(fileName); + else TraceLog(WARNING, "[%s] Sound extension not recognized, it can't be loaded", fileName); - // Convert loaded data to OpenAL buffer - //---------------------------------------- - ALuint buffer; - alGenBuffers(1, &buffer); // Generate pointer to buffer + if (wave.data != NULL) + { + ALenum format = 0; + // The OpenAL format is worked out by looking at the number of channels and the bits per sample + if (wave.channels == 1) + { + if (wave.bitsPerSample == 8 ) format = AL_FORMAT_MONO8; + else if (wave.bitsPerSample == 16) format = AL_FORMAT_MONO16; + } + else if (wave.channels == 2) + { + if (wave.bitsPerSample == 8 ) format = AL_FORMAT_STEREO8; + else if (wave.bitsPerSample == 16) format = AL_FORMAT_STEREO16; + } + + // Create an audio source + ALuint source; + alGenSources(1, &source); // Generate pointer to audio source + + alSourcef(source, AL_PITCH, 1); + alSourcef(source, AL_GAIN, 1); + alSource3f(source, AL_POSITION, 0, 0, 0); + alSource3f(source, AL_VELOCITY, 0, 0, 0); + alSourcei(source, AL_LOOPING, AL_FALSE); + + // Convert loaded data to OpenAL buffer + //---------------------------------------- + ALuint buffer; + alGenBuffers(1, &buffer); // Generate pointer to buffer - // Upload sound data to buffer - alBufferData(buffer, format, (void*)wave.data, wave.dataSize, wave.sampleRate); + // Upload sound data to buffer + alBufferData(buffer, format, wave.data, wave.dataSize, wave.sampleRate); - // Attach sound buffer to source - alSourcei(source, AL_BUFFER, buffer); - - // Unallocate WAV data - UnloadWAV(wave); - - TraceLog(INFO, "[%s] Sound file loaded successfully", fileName); - TraceLog(INFO, "[%s] Sample rate: %i - Channels: %i", fileName, wave.sampleRate, wave.channels); - - sound.source = source; - sound.buffer = buffer; + // Attach sound buffer to source + alSourcei(source, AL_BUFFER, buffer); + + // Unallocate WAV data + UnloadWave(wave); + + TraceLog(INFO, "[%s] Sound file loaded successfully", fileName); + TraceLog(INFO, "[%s] Sample rate: %i - Channels: %i", fileName, wave.sampleRate, wave.channels); + + sound.source = source; + sound.buffer = buffer; + } return sound; } @@ -314,7 +320,7 @@ Sound LoadSoundFromRES(const char *rresName, int resId) alSourcei(source, AL_BUFFER, buffer); // Unallocate WAV data - UnloadWAV(wave); + UnloadWave(wave); TraceLog(INFO, "[%s] Sound loaded successfully from resource, sample rate: %i", rresName, (int)sampleRate); @@ -381,22 +387,6 @@ void PlaySound(Sound sound) //alGetSourcef(sound.source, AL_SEC_OFFSET, &result); // AL_SAMPLE_OFFSET } -// Play a sound with extended options -// TODO: This function should be reviewed... -void PlaySoundEx(Sound sound, float timePosition, bool loop) -{ - // TODO: Review - - // Change the current position (e.g. skip some part of the sound) - // NOTE: Only work when the entire file is in a single buffer - //alSourcei(sound.source, AL_BYTE_OFFSET, int(position * sampleRate)); - - alSourcePlay(sound.source); // Play the sound - - if (loop) alSourcei(sound.source, AL_LOOPING, AL_TRUE); - else alSourcei(sound.source, AL_LOOPING, AL_FALSE); -} - // Pause a sound void PauseSound(Sound sound) { @@ -421,30 +411,250 @@ bool SoundIsPlaying(Sound sound) return playing; } +// Set volume for a sound +void SetSoundVolume(Sound sound, float volume) +{ + alSourcef(sound.source, AL_GAIN, volume); +} + +// Set pitch for a sound +void SetSoundPitch(Sound sound, float pitch) +{ + alSourcef(sound.source, AL_PITCH, pitch); +} + +//---------------------------------------------------------------------------------- +// Module Functions Definition - Music loading and stream playing (.OGG) +//---------------------------------------------------------------------------------- + +// Start music playing (open stream) +void PlayMusicStream(char *fileName) +{ + if (strcmp(GetExtension(fileName),"ogg") == 0) + { + // Stop current music, clean buffers, unload current stream + StopMusicStream(); + + // Open audio stream + currentMusic.stream = stb_vorbis_open_filename(fileName, NULL, NULL); + + if (currentMusic.stream == NULL) TraceLog(WARNING, "[%s] Could not open ogg audio file", fileName); + else + { + // Get file info + stb_vorbis_info info = stb_vorbis_get_info(currentMusic.stream); + + currentMusic.channels = info.channels; + currentMusic.sampleRate = info.sample_rate; + + TraceLog(INFO, "[%s] Ogg sample rate: %i", fileName, info.sample_rate); + TraceLog(INFO, "[%s] Ogg channels: %i", fileName, info.channels); + TraceLog(INFO, "[%s] Temp memory required: %i", fileName, info.temp_memory_required); + + if (info.channels == 2) currentMusic.format = AL_FORMAT_STEREO16; + else currentMusic.format = AL_FORMAT_MONO16; + + currentMusic.loop = true; // We loop by default + musicEnabled = true; + + // Create an audio source + alGenSources(1, ¤tMusic.source); // Generate pointer to audio source + + alSourcef(currentMusic.source, AL_PITCH, 1); + alSourcef(currentMusic.source, AL_GAIN, 1); + alSource3f(currentMusic.source, AL_POSITION, 0, 0, 0); + alSource3f(currentMusic.source, AL_VELOCITY, 0, 0, 0); + //alSourcei(currentMusic.source, AL_LOOPING, AL_TRUE); // ERROR: Buffers do not queue! + + // Generate two OpenAL buffers + alGenBuffers(2, currentMusic.buffers); + + // Fill buffers with music... + BufferMusicStream(currentMusic.buffers[0]); + BufferMusicStream(currentMusic.buffers[1]); + + // Queue buffers and start playing + alSourceQueueBuffers(currentMusic.source, 2, currentMusic.buffers); + alSourcePlay(currentMusic.source); + + // NOTE: Regularly, we must check if a buffer has been processed and refill it: MusicStreamUpdate() + + currentMusic.totalSamplesLeft = stb_vorbis_stream_length_in_samples(currentMusic.stream) * currentMusic.channels; + } + } + else TraceLog(WARNING, "[%s] Music extension not recognized, it can't be loaded", fileName); +} + +// Stop music playing (close stream) +void StopMusicStream() +{ + if (musicEnabled) + { + alSourceStop(currentMusic.source); + + EmptyMusicStream(); // Empty music buffers + + alDeleteSources(1, ¤tMusic.source); + alDeleteBuffers(2, currentMusic.buffers); + + stb_vorbis_close(currentMusic.stream); + } + + musicEnabled = false; +} + +// Pause music playing +void PauseMusicStream() +{ + // TODO: Record music is paused or check if music available! + alSourcePause(currentMusic.source); +} + // Check if music is playing -bool MusicIsPlaying(Music music) +bool MusicIsPlaying() { ALenum state; - alGetSourcei(music.source, AL_SOURCE_STATE, &state); + alGetSourcei(currentMusic.source, AL_SOURCE_STATE, &state); return (state == AL_PLAYING); } -// Set volume for a sound -void SetVolume(Sound sound, float volume) +// Set volume for music +void SetMusicVolume(float volume) { - alSourcef(sound.source, AL_GAIN, volume); + alSourcef(currentMusic.source, AL_GAIN, volume); } -// Set pitch for a sound -void SetPitch(Sound sound, float pitch) +// Get current music time length (in seconds) +float GetMusicTimeLength() { - alSourcef(sound.source, AL_PITCH, pitch); + float totalSeconds = stb_vorbis_stream_length_in_seconds(currentMusic.stream); + + return totalSeconds; +} + +// Get current music time played (in seconds) +float GetMusicTimePlayed() +{ + int totalSamples = stb_vorbis_stream_length_in_samples(currentMusic.stream) * currentMusic.channels; + + int samplesPlayed = totalSamples - currentMusic.totalSamplesLeft; + + float secondsPlayed = (float)samplesPlayed / (currentMusic.sampleRate * currentMusic.channels); + + return secondsPlayed; +} + +//---------------------------------------------------------------------------------- +// Module specific Functions Definition +//---------------------------------------------------------------------------------- + +// Fill music buffers with new data from music stream +static bool BufferMusicStream(ALuint buffer) +{ + short pcm[MUSIC_BUFFER_SIZE]; + + int size = 0; // Total size of data steamed (in bytes) + int streamedBytes = 0; // Bytes of data obtained in one samples get + + bool active = true; // We can get more data from stream (not finished) + + if (musicEnabled) + { + while (size < MUSIC_BUFFER_SIZE) + { + streamedBytes = stb_vorbis_get_samples_short_interleaved(currentMusic.stream, currentMusic.channels, pcm + size, MUSIC_BUFFER_SIZE - size); + + if (streamedBytes > 0) size += (streamedBytes*currentMusic.channels); + else break; + } + + TraceLog(DEBUG, "Streaming music data to buffer. Bytes streamed: %i", size); + } + + if (size > 0) + { + alBufferData(buffer, currentMusic.format, pcm, size*sizeof(short), currentMusic.sampleRate); + + currentMusic.totalSamplesLeft -= size; + } + else + { + active = false; + TraceLog(WARNING, "No more data obtained from stream"); + } + + return active; +} + +// Empty music buffers +static void EmptyMusicStream() +{ + ALuint buffer = 0; + int queued = 0; + + alGetSourcei(currentMusic.source, AL_BUFFERS_QUEUED, &queued); + + while(queued > 0) + { + alSourceUnqueueBuffers(currentMusic.source, 1, &buffer); + + queued--; + } +} + +// Update (re-fill) music buffers if data already processed +extern void UpdateMusicStream() +{ + ALuint buffer = 0; + ALint processed = 0; + bool active = true; + + if (musicEnabled) + { + // Get the number of already processed buffers (if any) + alGetSourcei(currentMusic.source, AL_BUFFERS_PROCESSED, &processed); + + while (processed > 0) + { + // Recover processed buffer for refill + alSourceUnqueueBuffers(currentMusic.source, 1, &buffer); + + // Refill buffer + active = BufferMusicStream(buffer); + + // If no more data to stream, restart music (if loop) + if ((!active) && (currentMusic.loop)) + { + if (currentMusic.loop) + { + stb_vorbis_seek_start(currentMusic.stream); + currentMusic.totalSamplesLeft = stb_vorbis_stream_length_in_samples(currentMusic.stream) * currentMusic.channels; + + active = BufferMusicStream(buffer); + } + } + + // Add refilled buffer to queue again... don't let the music stop! + alSourceQueueBuffers(currentMusic.source, 1, &buffer); + + if(alGetError() != AL_NO_ERROR) TraceLog(WARNING, "Ogg playing, error buffering data..."); + + processed--; + } + + ALenum state; + alGetSourcei(currentMusic.source, AL_SOURCE_STATE, &state); + + if ((state != AL_PLAYING) && active) alSourcePlay(currentMusic.source); + + if (!active) StopMusicStream(); + } } // Load WAV file into Wave structure -static Wave LoadWAV(char *fileName) +static Wave LoadWAV(const char *fileName) { // Basic WAV headers structs typedef struct { @@ -543,199 +753,51 @@ static Wave LoadWAV(char *fileName) return wave; } -// Unload WAV file data -static void UnloadWAV(Wave wave) +// Load OGG file into Wave structure +static Wave LoadOGG(char *fileName) { - free(wave.data); -} - -// TODO: Ogg data loading -Music LoadMusic(char *fileName) -{ - Music music; + Wave wave; - // Open audio stream - music.stream = stb_vorbis_open_filename(fileName, NULL, NULL); + stb_vorbis *oggFile = stb_vorbis_open_filename(fileName, NULL, NULL); + stb_vorbis_info info = stb_vorbis_get_info(oggFile); - if (music.stream == NULL) TraceLog(WARNING, "Could not open ogg audio file"); - else - { - // Get file info - music.info = stb_vorbis_get_info(music.stream); - - printf("Ogg sample rate: %i\n", music.info.sample_rate); - printf("Ogg channels: %i\n", music.info.channels); - printf("Temp memory required: %i\n", music.info.temp_memory_required); - - if (music.info.channels == 2) music.format = AL_FORMAT_STEREO16; - else music.format = AL_FORMAT_MONO16; - - music.bufferSize = 4096*8; - music.loop = true; // We loop by default - - // Create an audio source - alGenSources(1, &music.source); // Generate pointer to audio source - - alSourcef(music.source, AL_PITCH, 1); - alSourcef(music.source, AL_GAIN, 1); - alSource3f(music.source, AL_POSITION, 0, 0, 0); - alSource3f(music.source, AL_VELOCITY, 0, 0, 0); - alSourcei(music.source, AL_LOOPING, AL_TRUE); // We loop by default - - // Convert loaded data to OpenAL buffers - alGenBuffers(2, music.buffers); - /* - if (!MusicStream(music, music.buffers[0])) exit(1); - if (!MusicStream(music, music.buffers[1])) exit(1); - - alSourceQueueBuffers(music.source, 2, music.buffers); - - PlayMusic(music); - */ - music.totalSamplesLeft = stb_vorbis_stream_length_in_samples(music.stream) * music.info.channels; - - currentMusic = &music; - } + wave.sampleRate = info.sample_rate; + wave.bitsPerSample = 16; + wave.channels = info.channels; - return music; -} + TraceLog(DEBUG, "[%s] Ogg sample rate: %i", fileName, info.sample_rate); + TraceLog(DEBUG, "[%s] Ogg channels: %i", fileName, info.channels); -void UnloadMusic(Music music) -{ - StopMusic(music); - - alDeleteSources(1, &music.source); - alDeleteBuffers(2, music.buffers); + int totalSamplesLength = (stb_vorbis_stream_length_in_samples(oggFile) * info.channels); - stb_vorbis_close(music.stream); -} - -void PlayMusic(Music music) -{ - //if (MusicIsPlaying(music)) return true; - - if (!MusicStream(music, music.buffers[0])) TraceLog(WARNING, "MusicStream returned 0"); - if (!MusicStream(music, music.buffers[1])) TraceLog(WARNING, "MusicStream returned 0"); + wave.dataSize = totalSamplesLength*sizeof(short); // Size must be in bytes - alSourceQueueBuffers(music.source, 2, music.buffers); - alSourcePlay(music.source); - - TraceLog(INFO, "Playing music"); -} - -extern void PlayCurrentMusic() -{ - if (!MusicStream(*currentMusic, currentMusic->buffers[0])) TraceLog(WARNING, "MusicStream returned 0"); - if (!MusicStream(*currentMusic, currentMusic->buffers[1])) TraceLog(WARNING, "MusicStream returned 0"); + TraceLog(DEBUG, "[%s] Samples length: %i", fileName, totalSamplesLength); - alSourceQueueBuffers(currentMusic->source, 2, currentMusic->buffers); - alSourcePlay(currentMusic->source); -} - -// Stop reproducing music -void StopMusic(Music music) -{ - alSourceStop(music.source); + float totalSeconds = stb_vorbis_stream_length_in_seconds(oggFile); - musicIsPlaying = false; -} - -static bool MusicStream(Music music, ALuint buffer) -{ - //Uncomment this to avoid VLAs - //#define BUFFER_SIZE 4096*32 - #ifndef BUFFER_SIZE//VLAs ftw - #define BUFFER_SIZE (music.bufferSize) - #endif - ALshort pcm[BUFFER_SIZE]; - - int size = 0; - int result = 0; - - while (size < BUFFER_SIZE) - { - result = stb_vorbis_get_samples_short_interleaved(music.stream, music.info.channels, pcm+size, BUFFER_SIZE-size); - - if (result > 0) size += (result*music.info.channels); - else break; - } - - if (size == 0) return false; - - alBufferData(buffer, music.format, pcm, size*sizeof(ALshort), music.info.sample_rate); + TraceLog(DEBUG, "[%s] Total seconds: %f", fileName, totalSeconds); - music.totalSamplesLeft -= size; - - #undef BUFFER_SIZE - - return true; -} -/* -extern bool MusicStreamUpdate() -{ - ALint processed = 0; - - alGetSourcei(currentMusic->source, AL_BUFFERS_PROCESSED, &processed); - - while (processed--) - { - ALuint buffer = 0; - - alSourceUnqueueBuffers(currentMusic->source, 1, &buffer); - - if (!MusicStream(*currentMusic, buffer)) - { - bool shouldExit = true; - - if (currentMusic->loop) - { - stb_vorbis_seek_start(currentMusic->stream); - currentMusic->totalSamplesLeft = stb_vorbis_stream_length_in_samples(currentMusic->stream) * currentMusic->info.channels; - - shouldExit = !MusicStream(*currentMusic, buffer); - } - - if (shouldExit) return false; - } - - alSourceQueueBuffers(currentMusic->source, 1, &buffer); - } - - return true; -} -*/ -extern bool MusicStreamUpdate() -{ - int processed; - bool active = true; - - alGetSourcei(currentMusic->source, AL_BUFFERS_PROCESSED, &processed); + if (totalSeconds > 10) TraceLog(WARNING, "[%s] Ogg audio lenght is larger than 10 seconds (%f), that's a big file in memory, consider music streaming", fileName, totalSeconds); - printf("Data processed: %i\n", processed); - - while (processed--) - { - ALuint buffer = 0; - - alSourceUnqueueBuffers(currentMusic->source, 1, &buffer); + int totalSamples = totalSeconds*info.sample_rate*info.channels; + + TraceLog(DEBUG, "[%s] Total samples calculated: %i", fileName, totalSamples); + + //short *data + wave.data = malloc(sizeof(short)*totalSamplesLength); - active = MusicStream(*currentMusic, buffer); - - alSourceQueueBuffers(currentMusic->source, 1, &buffer); - } - - return active; + int samplesObtained = stb_vorbis_get_samples_short_interleaved(oggFile, info.channels, wave.data, totalSamplesLength); + + TraceLog(DEBUG, "[%s] Samples obtained: %i", fileName, samplesObtained); + + stb_vorbis_close(oggFile); + + return wave; } -void MusicStreamEmpty() +// Unload Wave data +static void UnloadWave(Wave wave) { - int queued; - - alGetSourcei(currentMusic->source, AL_BUFFERS_QUEUED, &queued); - - while(queued--) - { - ALuint buffer; - alSourceUnqueueBuffers(currentMusic->source, 1, &buffer); - } + free(wave.data); }
\ No newline at end of file |
