summaryrefslogtreecommitdiffhomepage
path: root/src/audio.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/audio.c')
-rw-r--r--src/audio.c113
1 files changed, 74 insertions, 39 deletions
diff --git a/src/audio.c b/src/audio.c
index adbe4f4f..659ead0f 100644
--- a/src/audio.c
+++ b/src/audio.c
@@ -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: 8bit PCM, 16bit 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: 8bit PCM, 16bit 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 32bit 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, (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, 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 \ No newline at end of file
+#endif