@ -3,32 +3,50 @@
* raylib . audio
*
* This module provides basic functionality to work with audio :
* Manage audio device ( init / close )
* Load and Unload audio files ( WAV , OGG , FLAC , XM , MOD )
* Play / Stop / Pause / Resume loaded audio
* Manage mixing channels
* Manage raw audio context
* Manage audio device ( init / close )
* Load and Unload audio files ( WAV , OGG , FLAC , XM , MOD )
* Play / Stop / Pause / Resume loaded audio
* Manage mixing channels
* Manage raw audio context
*
* External libs :
* NOTES :
*
* Only up to two channels supported : MONO and STEREO ( for additional channels , use AL_EXT_MCFORMATS )
* Only the following sample sizes supported : 8 bit PCM , 16 bit PCM , 32 - bit float PCM ( using AL_EXT_FLOAT32 )
*
* CONFIGURATION :
*
* # define AUDIO_STANDALONE
* If defined , the module can be used as standalone library ( independently of raylib ) .
* Required types and functions are defined in the same module .
*
* # define SUPPORT_FILEFORMAT_WAV / SUPPORT_LOAD_WAV / ENABLE_LOAD_WAV
* # define SUPPORT_FILEFORMAT_OGG
* # define SUPPORT_FILEFORMAT_XM
* # define SUPPORT_FILEFORMAT_MOD
* # define SUPPORT_FILEFORMAT_FLAC
* Selected desired fileformats to be supported for loading . Some of those formats are
* supported by default , to remove support , just comment unrequired # define in this module
*
* # define SUPPORT_RAW_AUDIO_BUFFERS
*
* DEPENDENCIES :
* OpenAL Soft - Audio device management ( http : / / kcat . strangesoft . net / openal . html )
* stb_vorbis - OGG audio files loading ( http : / / www . nothings . org / stb_vorbis / )
* jar_xm - XM module file loading
* jar_mod - MOD audio file loading
* dr_flac - FLAC audio file loading
*
* Module Configuration Flags :
* AUDIO_STANDALONE - Use this module as standalone library ( independently of raylib )
*
* Some design decisions :
* Support only up to two channels : MONO and STEREO ( for additional channels , AL_EXT_MCFORMATS )
* Support only the following sample sizes : 8 bit PCM , 16 bit PCM , 32 - bit float PCM ( using AL_EXT_FLOAT32 )
* CONTRIBUTORS :
*
* Many thanks to Joshua Reisenauer ( github : @ kd7tck ) for the following additions :
* XM audio module support ( jar_xm )
* MOD audio module support ( jar_mod )
* Mixing channels support
* Raw audio context support
* XM audio module support ( jar_xm )
* MOD audio module support ( jar_mod )
* Mixing channels support
* Raw audio context support
*
*
* LICENSE : zlib / libpng
*
* Copyright ( c ) 2014 - 2016 Ramon Santamaria ( @ raysan5 )
*
@ -59,9 +77,14 @@
# include "utils.h" // Required for: fopen() Android mapping, TraceLog()
# endif
# include "AL/al.h" // OpenAL basic header
# include "AL/alc.h" // OpenAL context header (like OpenGL, OpenAL requires a context to work)
/ / # include " AL/alext.h " / / OpenAL extensions header , required for AL_EXT_FLOAT32 and AL_EXT_MCFORMATS
# ifdef __APPLE__
# include "OpenAL/al.h" // OpenAL basic header
# include "OpenAL/alc.h" // OpenAL context header (like OpenGL, OpenAL requires a context to work)
# else
# include "AL/al.h" // OpenAL basic header
# include "AL/alc.h" // OpenAL context header (like OpenGL, OpenAL requires a context to work)
/ / # include " AL/alext.h " / / OpenAL extensions header , required for AL_EXT_FLOAT32 and AL_EXT_MCFORMATS
# endif
/ / OpenAL extension : AL_EXT_FLOAT32 - Support for 32 bit float samples
/ / OpenAL extension : AL_EXT_MCFORMATS - Support for multi - channel formats ( Quad , 5.1 , 6.1 , 7.1 )
@ -241,11 +264,11 @@ Wave LoadWave(const char *fileName)
else if ( strcmp ( GetExtension ( fileName ) , " flac " ) = = 0 ) wave = LoadFLAC ( fileName ) ;
else if ( strcmp ( GetExtension ( fileName ) , " rres " ) = = 0 )
{
RRESData rres = LoadResource ( fileName ) ;
RRES rres = LoadResource ( fileName, 0 ) ;
/ / NOTE : Parameters for RRES_WAVE type are : sampleCount , sampleRate , sampleSize , channels
/ / NOTE : Parameters for RRES_TYPE_ WAVE are : sampleCount , sampleRate , sampleSize , channels
if ( rres . type = = RRES_WAVE ) wave = LoadWaveEx ( rres . data , rres . param1 , rres . param2 , rres . param3 , rres . param4 ) ;
if ( rres [ 0 ] .type = = RRES_TYPE _WAVE ) wave = LoadWaveEx ( rres [ 0 ] .data , rres [ 0 ] .param1 , rres [ 0 ] .param2 , rres [ 0 ] .param3 , rres[ 0 ] . param4 ) ;
else TraceLog ( WARNING , " [%s] Resource file does not contain wave data " , fileName ) ;
UnloadResource ( rres ) ;
@ -374,7 +397,7 @@ void UnloadSound(Sound sound)
/ / Update sound buffer with new data
/ / NOTE : data must match sound . format
void UpdateSound ( Sound sound , const void * data , int numSamples )
void UpdateSound ( Sound sound , const void * data , int samplesCount )
{
ALint sampleRate , sampleSize , channels ;
alGetBufferi ( sound . buffer , AL_FREQUENCY , & sampleRate ) ;
@ -385,7 +408,7 @@ void UpdateSound(Sound sound, const void *data, int numSamples)
TraceLog ( DEBUG , " UpdateSound() : AL_BITS: %i " , sampleSize ) ;
TraceLog ( DEBUG , " UpdateSound() : AL_CHANNELS: %i " , channels ) ;
unsigned int dataSize = numSamples * channels * sampleSize / 8 ; / / Size of data in bytes
unsigned int dataSize = samplesCount * channels * sampleSize / 8 ; / / Size of data in bytes
alSourceStop ( sound . source ) ; / / Stop sound
alSourcei ( sound . source , AL_BUFFER , 0 ) ; / / Unbind buffer from sound to update
@ -581,7 +604,7 @@ void WaveCrop(Wave *wave, int initSample, int finalSample)
void * data = malloc ( sampleCount * wave - > channels * wave - > sampleSize / 8 ) ;
memcpy ( data , wave - > data + ( initSample * wave - > channels * wave - > sampleSize / 8 ) , sampleCount * wave - > channels * wave - > sampleSize / 8 ) ;
memcpy ( data , p">( unsigned char * ) wave - > data + ( initSample * wave - > channels * wave - > sampleSize / 8 ) , sampleCount * wave - > channels * wave - > sampleSize / 8 ) ;
free ( wave - > data ) ;
wave - > data = data ;
@ -739,7 +762,18 @@ void ResumeMusicStream(Music music)
void StopMusicStream ( Music music )
{
alSourceStop ( music - > stream . source ) ;
/ / Clear stream buffers
void * pcm = calloc ( AUDIO_BUFFER_SIZE * music - > stream . sampleSize / 8 * music - > stream . channels , 1 ) ;
for ( int i = 0 ; i < MAX_STREAM_BUFFERS ; i + + )
{
alBufferData ( music - > stream . buffers [ i ] , music - > stream . format , pcm , AUDIO_BUFFER_SIZE * music - > stream . sampleSize / 8 * music - > stream . channels , music - > stream . sampleRate ) ;
}
free ( pcm ) ;
/ / Restart music context
switch ( music - > ctxType )
{
case MUSIC_AUDIO_OGG : stb_vorbis_seek_start ( music - > ctxOgg ) ; break ;
@ -752,6 +786,7 @@ void StopMusicStream(Music music)
}
/ / Update ( re - fill ) music buffers if data already processed
/ / TODO : Make sure buffers are ready for update . . . check music state
void UpdateMusicStream ( Music music )
{
ALenum state ;
@ -768,13 +803,13 @@ void UpdateMusicStream(Music music)
void * pcm = calloc ( AUDIO_BUFFER_SIZE * music - > stream . channels * music - > stream . sampleSize / 8 , 1 ) ;
int numBuffersToProcess = processed ;
int numSamples = 0 ; / / Total size of data steamed in L + R samples for xm floats ,
/ / individual L or R for ogg shorts
int samplesCount = 0 ; / / Total size of data steamed in L + R samples for xm floats ,
/ / individual L or R for ogg shorts
for ( int i = 0 ; i < numBuffersToProcess ; i + + )
{
if ( music - > samplesLeft > = AUDIO_BUFFER_SIZE ) numSamples = AUDIO_BUFFER_SIZE ;
else numSamples = music - > samplesLeft ;
if ( music - > samplesLeft > = AUDIO_BUFFER_SIZE ) samplesCount = AUDIO_BUFFER_SIZE ;
else samplesCount = music - > samplesLeft ;
/ / TODO : Really don ' t like ctxType thingy . . .
switch ( music - > ctxType )
@ -782,22 +817,22 @@ void UpdateMusicStream(Music music)
case MUSIC_AUDIO_OGG :
{
/ / NOTE : Returns the number of samples to process ( be careful ! we ask for number of shorts ! )
int numSamplesOgg = stb_vorbis_get_samples_short_interleaved ( music - > ctxOgg , music - > stream . channels , ( short * ) pcm , numSamples * music - > stream . channels ) ;
int numSamplesOgg = stb_vorbis_get_samples_short_interleaved ( music - > ctxOgg , music - > stream . channels , ( short * ) pcm , samplesCount * music - > stream . channels ) ;
} break ;
case MUSIC_AUDIO_FLAC :
{
/ / NOTE : Returns the number of samples to process
unsigned int numSamplesFlac = ( unsigned int ) drflac_read_s16 ( music - > ctxFlac , numSamples * music - > stream . channels , ( short * ) pcm ) ;
unsigned int numSamplesFlac = ( unsigned int ) drflac_read_s16 ( music - > ctxFlac , samplesCount * music - > stream . channels , ( short * ) pcm ) ;
} break ;
case MUSIC_MODULE_XM : jar_xm_generate_samples_16bit ( music - > ctxXm , pcm , numSamples ) ; break ;
case MUSIC_MODULE_MOD : jar_mod_fillbuffer ( & music - > ctxMod , pcm , numSamples , 0 ) ; break ;
case MUSIC_MODULE_XM : jar_xm_generate_samples_16bit ( music - > ctxXm , pcm , samplesCount ) ; break ;
case MUSIC_MODULE_MOD : jar_mod_fillbuffer ( & music - > ctxMod , pcm , samplesCount , 0 ) ; break ;
default : break ;
}
UpdateAudioStream ( music - > stream , pcm , numSamples ) ;
music - > samplesLeft - = numSamples ;
UpdateAudioStream ( music - > stream , pcm , samplesCount ) ;
music - > samplesLeft - = samplesCount ;
if ( music - > samplesLeft < = 0 )
{
@ -976,7 +1011,7 @@ void CloseAudioStream(AudioStream stream)
/ / Update audio stream buffers with data
/ / NOTE : Only updates one buffer per call
void UpdateAudioStream ( AudioStream stream , const void * data , int numSamples )
void UpdateAudioStream ( AudioStream stream , const void * data , int samplesCount )
{
ALuint buffer = 0 ;
alSourceUnqueueBuffers ( stream . source , 1 , & buffer ) ;
@ -984,7 +1019,7 @@ void UpdateAudioStream(AudioStream stream, const void *data, int numSamples)
/ / Check if any buffer was available for unqueue
if ( alGetError ( ) ! = AL_INVALID_VALUE )
{
alBufferData ( buffer , stream . format , data , numSamples * stream . channels * stream . sampleSize / 8 , stream . sampleRate ) ;
alBufferData ( buffer , stream . format , data , samplesCount * stream . channels * stream . sampleSize / 8 , stream . sampleRate ) ;
alSourceQueueBuffers ( stream . source , 1 , & buffer ) ;
}
}
@ -1113,7 +1148,7 @@ static Wave LoadWAV(const char *fileName)
wave . data = malloc ( wavData . subChunkSize ) ;
/ / Read in the sound data into the soundData variable
fread ( wave . data , mi">1 , wavData . subChunkSize , wavFile ) ;
fread ( wave . data , wavData . subChunkSize, 1 , wavFile ) ;
/ / Store wave parameters
wave . sampleRate = wavFormat . sampleRate ;
@ -1251,4 +1286,4 @@ void TraceLog(int msgType, const char *text, ...)
if ( msgType = = ERROR ) exit ( 1 ) ; / / If ERROR message , exit program
}
# endif
# endif