Update C sources and examples
This commit is contained in:
parent
3b28d17b95
commit
8f1ad11c49
100 changed files with 2081 additions and 1686 deletions
169
raylib/audio.c
169
raylib/audio.c
|
@ -1,26 +1,22 @@
|
|||
/**********************************************************************************************
|
||||
*
|
||||
* raylib.audio
|
||||
* raylib.audio - Basic funtionality to work with 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
|
||||
*
|
||||
* 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)
|
||||
* FEATURES:
|
||||
* - Manage audio device (init/close)
|
||||
* - Load and unload audio files
|
||||
* - Format wave data (sample rate, size, channels)
|
||||
* - Play/Stop/Pause/Resume loaded audio
|
||||
* - Manage mixing channels
|
||||
* - Manage raw audio context
|
||||
*
|
||||
* CONFIGURATION:
|
||||
*
|
||||
* #define AUDIO_STANDALONE
|
||||
* If defined, the module can be used as standalone library (independently of raylib).
|
||||
* Define to use the module 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_WAV
|
||||
* #define SUPPORT_FILEFORMAT_OGG
|
||||
* #define SUPPORT_FILEFORMAT_XM
|
||||
* #define SUPPORT_FILEFORMAT_MOD
|
||||
|
@ -28,7 +24,9 @@
|
|||
* 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
|
||||
* LIMITATIONS:
|
||||
* 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)
|
||||
*
|
||||
* DEPENDENCIES:
|
||||
* OpenAL Soft - Audio device management (http://kcat.strangesoft.net/openal.html)
|
||||
|
@ -38,17 +36,16 @@
|
|||
* dr_flac - FLAC audio file loading
|
||||
*
|
||||
* 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
|
||||
* Joshua Reisenauer (github: @kd7tck):
|
||||
* - 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)
|
||||
* Copyright (c) 2014-2017 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* This software is provided "as-is", without any express or implied warranty. In no event
|
||||
* will the authors be held liable for any damages arising from the use of this software.
|
||||
|
@ -67,14 +64,19 @@
|
|||
*
|
||||
**********************************************************************************************/
|
||||
|
||||
//#define AUDIO_STANDALONE // NOTE: To use the audio module as standalone lib, just uncomment this line
|
||||
// Default configuration flags (supported features)
|
||||
//-------------------------------------------------
|
||||
#define SUPPORT_FILEFORMAT_WAV
|
||||
#define SUPPORT_FILEFORMAT_OGG
|
||||
#define SUPPORT_FILEFORMAT_XM
|
||||
//-------------------------------------------------
|
||||
|
||||
#if defined(AUDIO_STANDALONE)
|
||||
#include "audio.h"
|
||||
#include <stdarg.h> // Required for: va_list, va_start(), vfprintf(), va_end()
|
||||
#else
|
||||
#include "raylib.h"
|
||||
#include "utils.h" // Required for: fopen() Android mapping, TraceLog()
|
||||
#include "utils.h" // Required for: fopen() Android mapping
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
@ -93,18 +95,26 @@
|
|||
#include <string.h> // Required for: strcmp(), strncmp()
|
||||
#include <stdio.h> // Required for: FILE, fopen(), fclose(), fread()
|
||||
|
||||
//#define STB_VORBIS_HEADER_ONLY
|
||||
#include "external/stb_vorbis.h" // OGG loading functions
|
||||
#if defined(SUPPORT_FILEFORMAT_OGG)
|
||||
//#define STB_VORBIS_HEADER_ONLY
|
||||
#include "external/stb_vorbis.h" // OGG loading functions
|
||||
#endif
|
||||
|
||||
#define JAR_XM_IMPLEMENTATION
|
||||
#include "external/jar_xm.h" // XM loading functions
|
||||
#if defined(SUPPORT_FILEFORMAT_XM)
|
||||
#define JAR_XM_IMPLEMENTATION
|
||||
#include "external/jar_xm.h" // XM loading functions
|
||||
#endif
|
||||
|
||||
#define JAR_MOD_IMPLEMENTATION
|
||||
#include "external/jar_mod.h" // MOD loading functions
|
||||
#if defined(SUPPORT_FILEFORMAT_MOD)
|
||||
#define JAR_MOD_IMPLEMENTATION
|
||||
#include "external/jar_mod.h" // MOD loading functions
|
||||
#endif
|
||||
|
||||
#define DR_FLAC_IMPLEMENTATION
|
||||
#define DR_FLAC_NO_WIN32_IO
|
||||
#include "external/dr_flac.h" // FLAC loading functions
|
||||
#if defined(SUPPORT_FILEFORMAT_FLAC)
|
||||
#define DR_FLAC_IMPLEMENTATION
|
||||
#define DR_FLAC_NO_WIN32_IO
|
||||
#include "external/dr_flac.h" // FLAC loading functions
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#undef bool
|
||||
|
@ -139,10 +149,18 @@ typedef enum { MUSIC_AUDIO_OGG = 0, MUSIC_AUDIO_FLAC, MUSIC_MODULE_XM, MUSIC_MOD
|
|||
// Music type (file streaming from memory)
|
||||
typedef struct MusicData {
|
||||
MusicContextType ctxType; // Type of music context (OGG, XM, MOD)
|
||||
#if defined(SUPPORT_FILEFORMAT_OGG)
|
||||
stb_vorbis *ctxOgg; // OGG audio context
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_FLAC)
|
||||
drflac *ctxFlac; // FLAC audio context
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_XM)
|
||||
jar_xm_context_t *ctxXm; // XM chiptune context
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_MOD)
|
||||
jar_mod_context_t ctxMod; // MOD chiptune context
|
||||
#endif
|
||||
|
||||
AudioStream stream; // Audio stream (double buffering)
|
||||
|
||||
|
@ -163,13 +181,19 @@ typedef enum { INFO = 0, ERROR, WARNING, DEBUG, OTHER } TraceLogType;
|
|||
//----------------------------------------------------------------------------------
|
||||
// Module specific Functions Declaration
|
||||
//----------------------------------------------------------------------------------
|
||||
#if defined(SUPPORT_FILEFORMAT_WAV)
|
||||
static Wave LoadWAV(const char *fileName); // Load WAV file
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_OGG)
|
||||
static Wave LoadOGG(const char *fileName); // Load OGG file
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_FLAC)
|
||||
static Wave LoadFLAC(const char *fileName); // Load FLAC file
|
||||
#endif
|
||||
|
||||
#if defined(AUDIO_STANDALONE)
|
||||
const char *GetExtension(const char *fileName); // Get the extension for a filename
|
||||
void TraceLog(int msgType, const char *text, ...); // Outputs a trace log message (INFO, ERROR, WARNING)
|
||||
bool IsFileExtension(const char *fileName, const char *ext); // Check file extension
|
||||
void TraceLog(int msgType, const char *text, ...); // Outputs trace log message (INFO, ERROR, WARNING)
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
|
@ -259,10 +283,15 @@ Wave LoadWave(const char *fileName)
|
|||
{
|
||||
Wave wave = { 0 };
|
||||
|
||||
if (strcmp(GetExtension(fileName), "wav") == 0) wave = LoadWAV(fileName);
|
||||
else if (strcmp(GetExtension(fileName), "ogg") == 0) wave = LoadOGG(fileName);
|
||||
else if (strcmp(GetExtension(fileName), "flac") == 0) wave = LoadFLAC(fileName);
|
||||
else if (strcmp(GetExtension(fileName),"rres") == 0)
|
||||
if (IsFileExtension(fileName, ".wav")) wave = LoadWAV(fileName);
|
||||
#if defined(SUPPORT_FILEFORMAT_OGG)
|
||||
else if (IsFileExtension(fileName, ".ogg")) wave = LoadOGG(fileName);
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_FLAC)
|
||||
else if (IsFileExtension(fileName, ".flac")) wave = LoadFLAC(fileName);
|
||||
#endif
|
||||
#if !defined(AUDIO_STANDALONE)
|
||||
else if (IsFileExtension(fileName, ".rres"))
|
||||
{
|
||||
RRES rres = LoadResource(fileName, 0);
|
||||
|
||||
|
@ -273,7 +302,8 @@ Wave LoadWave(const char *fileName)
|
|||
|
||||
UnloadResource(rres);
|
||||
}
|
||||
else TraceLog(WARNING, "[%s] File extension not recognized, it can't be loaded", fileName);
|
||||
#endif
|
||||
else TraceLog(WARNING, "[%s] Audio fileformat not supported, it can't be loaded", fileName);
|
||||
|
||||
return wave;
|
||||
}
|
||||
|
@ -640,7 +670,7 @@ Music LoadMusicStream(const char *fileName)
|
|||
{
|
||||
Music music = (MusicData *)malloc(sizeof(MusicData));
|
||||
|
||||
if (strcmp(GetExtension(fileName), "ogg") == 0)
|
||||
if (IsFileExtension(fileName, ".ogg"))
|
||||
{
|
||||
// Open ogg audio stream
|
||||
music->ctxOgg = stb_vorbis_open_filename(fileName, NULL, NULL);
|
||||
|
@ -663,7 +693,8 @@ Music LoadMusicStream(const char *fileName)
|
|||
TraceLog(DEBUG, "[%s] OGG memory required: %i", fileName, info.temp_memory_required);
|
||||
}
|
||||
}
|
||||
else if (strcmp(GetExtension(fileName), "flac") == 0)
|
||||
#if defined(SUPPORT_FILEFORMAT_FLAC)
|
||||
else if (IsFileExtension(fileName, ".flac"))
|
||||
{
|
||||
music->ctxFlac = drflac_open_file(fileName);
|
||||
|
||||
|
@ -682,7 +713,9 @@ Music LoadMusicStream(const char *fileName)
|
|||
TraceLog(DEBUG, "[%s] FLAC channels: %i", fileName, music->ctxFlac->channels);
|
||||
}
|
||||
}
|
||||
else if (strcmp(GetExtension(fileName), "xm") == 0)
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_XM)
|
||||
else if (IsFileExtension(fileName, ".xm"))
|
||||
{
|
||||
int result = jar_xm_create_context_from_file(&music->ctxXm, 48000, fileName);
|
||||
|
||||
|
@ -702,7 +735,9 @@ Music LoadMusicStream(const char *fileName)
|
|||
}
|
||||
else TraceLog(WARNING, "[%s] XM file could not be opened", fileName);
|
||||
}
|
||||
else if (strcmp(GetExtension(fileName), "mod") == 0)
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_MOD)
|
||||
else if (IsFileExtension(fileName, ".mod"))
|
||||
{
|
||||
jar_mod_init(&music->ctxMod);
|
||||
|
||||
|
@ -719,7 +754,8 @@ Music LoadMusicStream(const char *fileName)
|
|||
}
|
||||
else TraceLog(WARNING, "[%s] MOD file could not be opened", fileName);
|
||||
}
|
||||
else TraceLog(WARNING, "[%s] Music extension not recognized, it can't be loaded", fileName);
|
||||
#endif
|
||||
else TraceLog(WARNING, "[%s] Audio fileformat not supported, it can't be loaded", fileName);
|
||||
|
||||
return music;
|
||||
}
|
||||
|
@ -730,9 +766,15 @@ void UnloadMusicStream(Music music)
|
|||
CloseAudioStream(music->stream);
|
||||
|
||||
if (music->ctxType == MUSIC_AUDIO_OGG) stb_vorbis_close(music->ctxOgg);
|
||||
#if defined(SUPPORT_FILEFORMAT_FLAC)
|
||||
else if (music->ctxType == MUSIC_AUDIO_FLAC) drflac_free(music->ctxFlac);
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_XM)
|
||||
else if (music->ctxType == MUSIC_MODULE_XM) jar_xm_free_context(music->ctxXm);
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_MOD)
|
||||
else if (music->ctxType == MUSIC_MODULE_MOD) jar_mod_unload(&music->ctxMod);
|
||||
#endif
|
||||
|
||||
free(music);
|
||||
}
|
||||
|
@ -777,8 +819,15 @@ void StopMusicStream(Music music)
|
|||
switch (music->ctxType)
|
||||
{
|
||||
case MUSIC_AUDIO_OGG: stb_vorbis_seek_start(music->ctxOgg); break;
|
||||
#if defined(SUPPORT_FILEFORMAT_FLAC)
|
||||
case MUSIC_MODULE_FLAC: /* TODO: Restart FLAC context */ break;
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_XM)
|
||||
case MUSIC_MODULE_XM: /* TODO: Restart XM context */ break;
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_MOD)
|
||||
case MUSIC_MODULE_MOD: jar_mod_seek_start(&music->ctxMod); break;
|
||||
#endif
|
||||
default: break;
|
||||
}
|
||||
|
||||
|
@ -820,14 +869,20 @@ void UpdateMusicStream(Music music)
|
|||
int numSamplesOgg = stb_vorbis_get_samples_short_interleaved(music->ctxOgg, music->stream.channels, (short *)pcm, samplesCount*music->stream.channels);
|
||||
|
||||
} break;
|
||||
#if defined(SUPPORT_FILEFORMAT_FLAC)
|
||||
case MUSIC_AUDIO_FLAC:
|
||||
{
|
||||
// NOTE: Returns the number of samples to process
|
||||
unsigned int numSamplesFlac = (unsigned int)drflac_read_s16(music->ctxFlac, samplesCount*music->stream.channels, (short *)pcm);
|
||||
|
||||
} break;
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_XM)
|
||||
case MUSIC_MODULE_XM: jar_xm_generate_samples_16bit(music->ctxXm, pcm, samplesCount); break;
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_MOD)
|
||||
case MUSIC_MODULE_MOD: jar_mod_fillbuffer(&music->ctxMod, pcm, samplesCount, 0); break;
|
||||
#endif
|
||||
default: break;
|
||||
}
|
||||
|
||||
|
@ -1066,6 +1121,7 @@ void StopAudioStream(AudioStream stream)
|
|||
// Module specific Functions Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
#if defined(SUPPORT_FILEFORMAT_WAV)
|
||||
// Load WAV file into Wave structure
|
||||
static Wave LoadWAV(const char *fileName)
|
||||
{
|
||||
|
@ -1182,7 +1238,9 @@ static Wave LoadWAV(const char *fileName)
|
|||
|
||||
return wave;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(SUPPORT_FILEFORMAT_OGG)
|
||||
// Load OGG file into Wave structure
|
||||
// NOTE: Using stb_vorbis library
|
||||
static Wave LoadOGG(const char *fileName)
|
||||
|
@ -1206,7 +1264,7 @@ static Wave LoadOGG(const char *fileName)
|
|||
wave.sampleCount = (int)stb_vorbis_stream_length_in_samples(oggFile);
|
||||
|
||||
float totalSeconds = stb_vorbis_stream_length_in_seconds(oggFile);
|
||||
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);
|
||||
if (totalSeconds > 10) TraceLog(WARNING, "[%s] Ogg audio length is larger than 10 seconds (%f), that's a big file in memory, consider music streaming", fileName, totalSeconds);
|
||||
|
||||
wave.data = (short *)malloc(wave.sampleCount*wave.channels*sizeof(short));
|
||||
|
||||
|
@ -1222,7 +1280,9 @@ static Wave LoadOGG(const char *fileName)
|
|||
|
||||
return wave;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(SUPPORT_FILEFORMAT_FLAC)
|
||||
// Load FLAC file into Wave structure
|
||||
// NOTE: Using dr_flac library
|
||||
static Wave LoadFLAC(const char *fileName)
|
||||
|
@ -1244,15 +1304,22 @@ static Wave LoadFLAC(const char *fileName)
|
|||
|
||||
return wave;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Some required functions for audio standalone module version
|
||||
#if defined(AUDIO_STANDALONE)
|
||||
// Get the extension for a filename
|
||||
const char *GetExtension(const char *fileName)
|
||||
// Check file extension
|
||||
bool IsFileExtension(const char *fileName, const char *ext)
|
||||
{
|
||||
const char *dot = strrchr(fileName, '.');
|
||||
if (!dot || dot == fileName) return "";
|
||||
return (dot + 1);
|
||||
bool result = false;
|
||||
const char *fileExt;
|
||||
|
||||
if ((fileExt = strrchr(fileName, '.')) != NULL)
|
||||
{
|
||||
if (strcmp(fileExt, ext) == 0) result = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Outputs a trace log message (INFO, ERROR, WARNING)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue