Code refractoring of music model to be more friendly-user (issue #144)

This commit is contained in:
Bil152
2016-07-29 21:35:57 +02:00
parent a422e39492
commit 8f7cb6fb19
3 changed files with 269 additions and 211 deletions

View File

@@ -145,7 +145,8 @@ typedef enum {
ERROR_UNABLE_TO_OPEN_RRES_FILE = 2048, ERROR_UNABLE_TO_OPEN_RRES_FILE = 2048,
ERROR_INVALID_RRES_FILE = 4096, ERROR_INVALID_RRES_FILE = 4096,
ERROR_INVALID_RRES_RESOURCE = 8192, ERROR_INVALID_RRES_RESOURCE = 8192,
ERROR_UNINITIALIZED_CHANNELS = 16384 ERROR_UNINITIALIZED_CHANNELS = 16384,
ERROR_UNINTIALIZED_MUSIC_BUFFER = 32768
} AudioError; } AudioError;
#if defined(AUDIO_STANDALONE) #if defined(AUDIO_STANDALONE)
@@ -217,7 +218,7 @@ void CloseAudioDevice(void)
{ {
for (int index = 0; index < MAX_MUSIC_STREAMS; index++) for (int index = 0; index < MAX_MUSIC_STREAMS; index++)
{ {
if (musicStreams[index].mixc) StopMusicStream(index); // Stop music streaming and close current stream if (musicStreams[index].mixc) StopMusicStreamEx(index); // Stop music streaming and close current stream
} }
ALCdevice *device; ALCdevice *device;
@@ -528,7 +529,7 @@ Sound LoadSound(char *fileName)
// Attach sound buffer to source // Attach sound buffer to source
alSourcei(source, AL_BUFFER, buffer); alSourcei(source, AL_BUFFER, buffer);
TraceLog(INFO, "[SND ID %i][BUFR ID %i] Sound file loaded successfully (SampleRate: %i, BitRate: %i, Channels: %i)", source, buffer, wave.sampleRate, wave.bitsPerSample, wave.channels); TraceLog(INFO, "[%s] Sound file loaded successfully (SampleRate: %i, BitRate: %i, Channels: %i)", fileName, wave.sampleRate, wave.bitsPerSample, wave.channels);
// Unallocate WAV data // Unallocate WAV data
UnloadWave(wave); UnloadWave(wave);
@@ -759,7 +760,7 @@ void UnloadSound(Sound sound)
alDeleteSources(1, &sound.source); alDeleteSources(1, &sound.source);
alDeleteBuffers(1, &sound.buffer); alDeleteBuffers(1, &sound.buffer);
TraceLog(INFO, "[SND ID %i][BUFR ID %i] Unloaded sound data from RAM", sound.source, sound.buffer); TraceLog(INFO, "Unloaded sound data");
} }
// Play a sound // Play a sound
@@ -823,116 +824,137 @@ void SetSoundPitch(Sound sound, float pitch)
// Module Functions Definition - Music loading and stream playing (.OGG) // Module Functions Definition - Music loading and stream playing (.OGG)
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
MusicBuffer LoadMusicBufferStream(char *fileName, int index)
{
MusicBuffer buffer = { 0 };
if(index > MAX_MUSIC_STREAMS)
{
TraceLog("[%s] index is greater than MAX_MUSIC_STREAMS", ERROR);
return; // error
}
buffer.fileName = fileName;
buffer.index = index;
if (musicStreams[buffer.index].stream || musicStreams[buffer.index].xmctx) return; // error
return buffer;
}
// Start music playing (open stream) // Start music playing (open stream)
// returns 0 on success or error code // returns 0 on success or error code
int PlayMusicStream(int index, char *fileName) int PlayMusicStream(MusicBuffer musicBuffer)
{ {
if(musicBuffer.fileName == 0)
{
return ERROR_UNINTIALIZED_MUSIC_BUFFER;
}
int mixIndex; int mixIndex;
if (musicStreams[index].stream || musicStreams[index].xmctx) return ERROR_UNINITIALIZED_CHANNELS; // error
for (mixIndex = 0; mixIndex < MAX_MIX_CHANNELS; mixIndex++) // find empty mix channel slot for (mixIndex = 0; mixIndex < MAX_MIX_CHANNELS; mixIndex++) // find empty mix channel slot
{ {
if (mixChannels[mixIndex] == NULL) break; if (mixChannels[mixIndex] == NULL) break;
else if (mixIndex == (MAX_MIX_CHANNELS - 1)) return ERROR_OUT_OF_MIX_CHANNELS; // error else if (mixIndex == (MAX_MIX_CHANNELS - 1)) return ERROR_OUT_OF_MIX_CHANNELS; // error
} }
if (strcmp(GetExtension(fileName), "ogg") == 0) if (strcmp(GetExtension(musicBuffer.fileName),"ogg") == 0)
{ {
// Open audio stream // Open audio stream
musicStreams[index].stream = stb_vorbis_open_filename(fileName, NULL, NULL); musicStreams[musicBuffer.index].stream = stb_vorbis_open_filename(musicBuffer.fileName, NULL, NULL);
if (musicStreams[index].stream == NULL) if (musicStreams[musicBuffer.index].stream == NULL)
{ {
TraceLog(WARNING, "[%s] OGG audio file could not be opened", fileName); TraceLog(WARNING, "[%s] OGG audio file could not be opened", musicBuffer.fileName);
return ERROR_LOADING_OGG; // error return ERROR_LOADING_OGG; // error
} }
else else
{ {
// Get file info // Get file info
stb_vorbis_info info = stb_vorbis_get_info(musicStreams[index].stream); stb_vorbis_info info = stb_vorbis_get_info(musicStreams[musicBuffer.index].stream);
TraceLog(DEBUG, "[%s] Ogg sample rate: %i", fileName, info.sample_rate); TraceLog(INFO, "[%s] Ogg sample rate: %i", musicBuffer.fileName, info.sample_rate);
TraceLog(DEBUG, "[%s] Ogg channels: %i", fileName, info.channels); TraceLog(INFO, "[%s] Ogg channels: %i", musicBuffer.fileName, info.channels);
TraceLog(DEBUG, "[%s] Temp memory required: %i", fileName, info.temp_memory_required); TraceLog(DEBUG, "[%s] Temp memory required: %i", musicBuffer.fileName, info.temp_memory_required);
musicStreams[index].loop = true; // We loop by default musicStreams[musicBuffer.index].loop = true; // We loop by default
musicStreams[index].enabled = true; musicStreams[musicBuffer.index].enabled = true;
musicStreams[index].totalSamplesLeft = (unsigned int)stb_vorbis_stream_length_in_samples(musicStreams[index].stream) * info.channels;
musicStreams[index].totalLengthSeconds = stb_vorbis_stream_length_in_seconds(musicStreams[index].stream); musicStreams[musicBuffer.index].totalSamplesLeft = (unsigned int)stb_vorbis_stream_length_in_samples(musicStreams[musicBuffer.index].stream) * info.channels;
musicStreams[musicBuffer.index].totalLengthSeconds = stb_vorbis_stream_length_in_seconds(musicStreams[musicBuffer.index].stream);
if (info.channels == 2) if (info.channels == 2)
{ {
musicStreams[index].mixc = InitMixChannel(info.sample_rate, mixIndex, 2, false); musicStreams[musicBuffer.index].mixc = InitMixChannel(info.sample_rate, mixIndex, 2, false);
musicStreams[index].mixc->playing = true; musicStreams[musicBuffer.index].mixc->playing = true;
} }
else else
{ {
musicStreams[index].mixc = InitMixChannel(info.sample_rate, mixIndex, 1, false); musicStreams[musicBuffer.index].mixc = InitMixChannel(info.sample_rate, mixIndex, 1, false);
musicStreams[index].mixc->playing = true; musicStreams[musicBuffer.index].mixc->playing = true;
} }
if (!musicStreams[index].mixc) return ERROR_LOADING_OGG; // error if (!musicStreams[musicBuffer.index].mixc) return ERROR_LOADING_OGG; // error
} }
} }
else if (strcmp(GetExtension(fileName), "xm") == 0) else if (strcmp(GetExtension(musicBuffer.fileName),"xm") == 0)
{ {
// only stereo is supported for xm // only stereo is supported for xm
if (!jar_xm_create_context_from_file(&musicStreams[index].xmctx, 48000, fileName)) if (!jar_xm_create_context_from_file(&musicStreams[musicBuffer.index].xmctx, 48000, musicBuffer.fileName))
{ {
musicStreams[index].chipTune = true; musicStreams[musicBuffer.index].chipTune = true;
musicStreams[index].loop = true; musicStreams[musicBuffer.index].loop = true;
jar_xm_set_max_loop_count(musicStreams[index].xmctx, 0); // infinite number of loops jar_xm_set_max_loop_count(musicStreams[musicBuffer.index].xmctx, 0); // infinite number of loops
musicStreams[index].totalSamplesLeft = (unsigned int)jar_xm_get_remaining_samples(musicStreams[index].xmctx); musicStreams[musicBuffer.index].totalSamplesLeft = (unsigned int)jar_xm_get_remaining_samples(musicStreams[musicBuffer.index].xmctx);
musicStreams[index].totalLengthSeconds = ((float)musicStreams[index].totalSamplesLeft)/48000.0f; musicStreams[musicBuffer.index].totalLengthSeconds = ((float)musicStreams[musicBuffer.index].totalSamplesLeft)/48000.0f;
musicStreams[index].enabled = true; musicStreams[musicBuffer.index].enabled = true;
TraceLog(INFO, "[%s] XM number of samples: %i", fileName, musicStreams[index].totalSamplesLeft); TraceLog(INFO, "[%s] XM number of samples: %i", musicBuffer.fileName, musicStreams[musicBuffer.index].totalSamplesLeft);
TraceLog(INFO, "[%s] XM track length: %11.6f sec", fileName, musicStreams[index].totalLengthSeconds); TraceLog(INFO, "[%s] XM track length: %11.6f sec", musicBuffer.fileName, musicStreams[musicBuffer.index].totalLengthSeconds);
musicStreams[index].mixc = InitMixChannel(48000, mixIndex, 2, true); musicStreams[musicBuffer.index].mixc = InitMixChannel(48000, mixIndex, 2, true);
if (!musicStreams[index].mixc) return ERROR_XM_CONTEXT_CREATION; // error if (!musicStreams[musicBuffer.index].mixc) return ERROR_XM_CONTEXT_CREATION; // error
musicStreams[index].mixc->playing = true; musicStreams[musicBuffer.index].mixc->playing = true;
} }
else else
{ {
TraceLog(WARNING, "[%s] XM file could not be opened", fileName); TraceLog(WARNING, "[%s] XM file could not be opened", musicBuffer.fileName);
return ERROR_LOADING_XM; // error return ERROR_LOADING_XM; // error
} }
} }
else if (strcmp(GetExtension(fileName), "mod") == 0) else if (strcmp(GetExtension(musicBuffer.fileName),"mod") == 0)
{ {
jar_mod_init(&musicStreams[index].modctx); jar_mod_init(&musicStreams[musicBuffer.index].modctx);
if (jar_mod_load_file(&musicStreams[index].modctx, fileName)) if (jar_mod_load_file(&musicStreams[musicBuffer.index].modctx, musicBuffer.fileName))
{ {
musicStreams[index].chipTune = true; musicStreams[musicBuffer.index].chipTune = true;
musicStreams[index].loop = true; musicStreams[musicBuffer.index].loop = true;
musicStreams[index].totalSamplesLeft = (unsigned int)jar_mod_max_samples(&musicStreams[index].modctx); musicStreams[musicBuffer.index].totalSamplesLeft = (unsigned int)jar_mod_max_samples(&musicStreams[musicBuffer.index].modctx);
musicStreams[index].totalLengthSeconds = ((float)musicStreams[index].totalSamplesLeft)/48000.0f; musicStreams[musicBuffer.index].totalLengthSeconds = ((float)musicStreams[musicBuffer.index].totalSamplesLeft)/48000.0f;
musicStreams[index].enabled = true; musicStreams[musicBuffer.index].enabled = true;
TraceLog(INFO, "[%s] MOD number of samples: %i", fileName, musicStreams[index].totalSamplesLeft); TraceLog(INFO, "[%s] MOD number of samples: %i", musicBuffer.fileName, musicStreams[musicBuffer.index].totalSamplesLeft);
TraceLog(INFO, "[%s] MOD track length: %11.6f sec", fileName, musicStreams[index].totalLengthSeconds); TraceLog(INFO, "[%s] MOD track length: %11.6f sec", musicBuffer.fileName, musicStreams[musicBuffer.index].totalLengthSeconds);
musicStreams[index].mixc = InitMixChannel(48000, mixIndex, 2, false); musicStreams[musicBuffer.index].mixc = InitMixChannel(48000, mixIndex, 2, false);
if (!musicStreams[index].mixc) return ERROR_MOD_CONTEXT_CREATION; // error if (!musicStreams[musicBuffer.index].mixc) return ERROR_MOD_CONTEXT_CREATION; // error
musicStreams[index].mixc->playing = true; musicStreams[musicBuffer.index].mixc->playing = true;
} }
else else
{ {
TraceLog(WARNING, "[%s] MOD file could not be opened", fileName); TraceLog(WARNING, "[%s] MOD file could not be opened", musicBuffer.fileName);
return ERROR_LOADING_MOD; // error return ERROR_LOADING_MOD; // error
} }
} }
else else
{ {
TraceLog(WARNING, "[%s] Music extension not recognized, it can't be loaded", fileName); TraceLog(WARNING, "[%s] Music extension not recognized, it can't be loaded", musicBuffer.fileName);
return ERROR_EXTENSION_NOT_RECOGNIZED; // error return ERROR_EXTENSION_NOT_RECOGNIZED; // error
} }
@@ -940,7 +962,30 @@ int PlayMusicStream(int index, char *fileName)
} }
// Stop music playing for individual music index of musicStreams array (close stream) // Stop music playing for individual music index of musicStreams array (close stream)
void StopMusicStream(int index) void StopMusicStream(MusicBuffer musicBuffer)
{
if (musicBuffer.index < MAX_MUSIC_STREAMS && musicStreams[musicBuffer.index].mixc)
{
CloseMixChannel(musicStreams[musicBuffer.index].mixc);
if (musicStreams[musicBuffer.index].xmctx)
jar_xm_free_context(musicStreams[musicBuffer.index].xmctx);
else if (musicStreams[musicBuffer.index].modctx.mod_loaded)
jar_mod_unload(&musicStreams[musicBuffer.index].modctx);
else
stb_vorbis_close(musicStreams[musicBuffer.index].stream);
musicStreams[musicBuffer.index].enabled = false;
if (musicStreams[musicBuffer.index].stream || musicStreams[musicBuffer.index].xmctx)
{
musicStreams[musicBuffer.index].stream = NULL;
musicStreams[musicBuffer.index].xmctx = NULL;
}
}
}
void StopMusicStreamEx(int index)
{ {
if (index < MAX_MUSIC_STREAMS && musicStreams[index].mixc) if (index < MAX_MUSIC_STREAMS && musicStreams[index].mixc)
{ {
@@ -964,46 +1009,46 @@ void StopMusicStream(int index)
} }
// Update (re-fill) music buffers if data already processed // Update (re-fill) music buffers if data already processed
void UpdateMusicStream(int index) void UpdateMusicStream(MusicBuffer musicBuffer)
{ {
ALenum state; ALenum state;
bool active = true; bool active = true;
ALint processed = 0; ALint processed = 0;
// Determine if music stream is ready to be written // Determine if music stream is ready to be written
alGetSourcei(musicStreams[index].mixc->alSource, AL_BUFFERS_PROCESSED, &processed); alGetSourcei(musicStreams[musicBuffer.index].mixc->alSource, AL_BUFFERS_PROCESSED, &processed);
if (musicStreams[index].mixc->playing && (index < MAX_MUSIC_STREAMS) && musicStreams[index].enabled && musicStreams[index].mixc && (processed > 0)) if (musicStreams[musicBuffer.index].mixc->playing && (musicBuffer.index < MAX_MUSIC_STREAMS) && musicStreams[musicBuffer.index].enabled && musicStreams[musicBuffer.index].mixc && (processed > 0))
{ {
active = BufferMusicStream(index, processed); active = BufferMusicStream(musicBuffer.index, processed);
if (!active && musicStreams[index].loop) if (!active && musicStreams[musicBuffer.index].loop)
{ {
if (musicStreams[index].chipTune) if (musicStreams[musicBuffer.index].chipTune)
{ {
if(musicStreams[index].modctx.mod_loaded) jar_mod_seek_start(&musicStreams[index].modctx); if(musicStreams[musicBuffer.index].modctx.mod_loaded) jar_mod_seek_start(&musicStreams[musicBuffer.index].modctx);
musicStreams[index].totalSamplesLeft = musicStreams[index].totalLengthSeconds*48000.0f; musicStreams[musicBuffer.index].totalSamplesLeft = musicStreams[musicBuffer.index].totalLengthSeconds*48000.0f;
} }
else else
{ {
stb_vorbis_seek_start(musicStreams[index].stream); stb_vorbis_seek_start(musicStreams[musicBuffer.index].stream);
musicStreams[index].totalSamplesLeft = stb_vorbis_stream_length_in_samples(musicStreams[index].stream)*musicStreams[index].mixc->channels; musicStreams[musicBuffer.index].totalSamplesLeft = stb_vorbis_stream_length_in_samples(musicStreams[musicBuffer.index].stream)*musicStreams[musicBuffer.index].mixc->channels;
} }
// Determine if music stream is ready to be written // Determine if music stream is ready to be written
alGetSourcei(musicStreams[index].mixc->alSource, AL_BUFFERS_PROCESSED, &processed); alGetSourcei(musicStreams[musicBuffer.index].mixc->alSource, AL_BUFFERS_PROCESSED, &processed);
active = BufferMusicStream(index, processed); active = BufferMusicStream(musicBuffer.index, processed);
} }
if (alGetError() != AL_NO_ERROR) TraceLog(WARNING, "Error buffering data..."); if (alGetError() != AL_NO_ERROR) TraceLog(WARNING, "Error buffering data...");
alGetSourcei(musicStreams[index].mixc->alSource, AL_SOURCE_STATE, &state); alGetSourcei(musicStreams[musicBuffer.index].mixc->alSource, AL_SOURCE_STATE, &state);
if (state != AL_PLAYING && active) alSourcePlay(musicStreams[index].mixc->alSource); if (state != AL_PLAYING && active) alSourcePlay(musicStreams[musicBuffer.index].mixc->alSource);
if (!active) StopMusicStream(index); if (!active) StopMusicStream(musicBuffer);
} }
} }
@@ -1023,45 +1068,45 @@ int GetMusicStreamCount(void)
} }
// Pause music playing // Pause music playing
void PauseMusicStream(int index) void PauseMusicStream(MusicBuffer musicBuffer)
{ {
// Pause music stream if music available! // Pause music stream if music available!
if (index < MAX_MUSIC_STREAMS && musicStreams[index].mixc && musicStreams[index].enabled) if (musicBuffer.index < MAX_MUSIC_STREAMS && musicStreams[musicBuffer.index].mixc && musicStreams[musicBuffer.index].enabled)
{ {
TraceLog(INFO, "Pausing music stream"); TraceLog(INFO, "Pausing music stream");
alSourcePause(musicStreams[index].mixc->alSource); alSourcePause(musicStreams[musicBuffer.index].mixc->alSource);
musicStreams[index].mixc->playing = false; musicStreams[musicBuffer.index].mixc->playing = false;
} }
} }
// Resume music playing // Resume music playing
void ResumeMusicStream(int index) void ResumeMusicStream(MusicBuffer musicBuffer)
{ {
// Resume music playing... if music available! // Resume music playing... if music available!
ALenum state; ALenum state;
if (index < MAX_MUSIC_STREAMS && musicStreams[index].mixc) if (musicBuffer.index < MAX_MUSIC_STREAMS && musicStreams[musicBuffer.index].mixc)
{ {
alGetSourcei(musicStreams[index].mixc->alSource, AL_SOURCE_STATE, &state); alGetSourcei(musicStreams[musicBuffer.index].mixc->alSource, AL_SOURCE_STATE, &state);
if (state == AL_PAUSED) if (state == AL_PAUSED)
{ {
TraceLog(INFO, "Resuming music stream"); TraceLog(INFO, "Resuming music stream");
alSourcePlay(musicStreams[index].mixc->alSource); alSourcePlay(musicStreams[musicBuffer.index].mixc->alSource);
musicStreams[index].mixc->playing = true; musicStreams[musicBuffer.index].mixc->playing = true;
} }
} }
} }
// Check if any music is playing // Check if any music is playing
bool IsMusicPlaying(int index) bool IsMusicPlaying(MusicBuffer musicBuffer)
{ {
bool playing = false; bool playing = false;
ALint state; ALint state;
if (index < MAX_MUSIC_STREAMS && musicStreams[index].mixc) if (musicBuffer.index < MAX_MUSIC_STREAMS && musicStreams[musicBuffer.index].mixc)
{ {
alGetSourcei(musicStreams[index].mixc->alSource, AL_SOURCE_STATE, &state); alGetSourcei(musicStreams[musicBuffer.index].mixc->alSource, AL_SOURCE_STATE, &state);
if (state == AL_PLAYING) playing = true; if (state == AL_PLAYING) playing = true;
} }
@@ -1070,57 +1115,57 @@ bool IsMusicPlaying(int index)
} }
// Set volume for music // Set volume for music
void SetMusicVolume(int index, float volume) void SetMusicVolume(MusicBuffer musicBuffer, float volume)
{ {
if (index < MAX_MUSIC_STREAMS && musicStreams[index].mixc) if (musicBuffer.index < MAX_MUSIC_STREAMS && musicStreams[musicBuffer.index].mixc)
{ {
alSourcef(musicStreams[index].mixc->alSource, AL_GAIN, volume); alSourcef(musicStreams[musicBuffer.index].mixc->alSource, AL_GAIN, volume);
} }
} }
// Set pitch for music // Set pitch for music
void SetMusicPitch(int index, float pitch) void SetMusicPitch(MusicBuffer musicBuffer, float pitch)
{ {
if (index < MAX_MUSIC_STREAMS && musicStreams[index].mixc) if (musicBuffer.index < MAX_MUSIC_STREAMS && musicStreams[musicBuffer.index].mixc)
{ {
alSourcef(musicStreams[index].mixc->alSource, AL_PITCH, pitch); alSourcef(musicStreams[musicBuffer.index].mixc->alSource, AL_PITCH, pitch);
} }
} }
// Get music time length (in seconds) // Get music time length (in seconds)
float GetMusicTimeLength(int index) float GetMusicTimeLength(MusicBuffer musicBuffer)
{ {
float totalSeconds; float totalSeconds;
if (musicStreams[index].chipTune) totalSeconds = (float)musicStreams[index].totalLengthSeconds; if (musicStreams[musicBuffer.index].chipTune) totalSeconds = (float)musicStreams[musicBuffer.index].totalLengthSeconds;
else totalSeconds = stb_vorbis_stream_length_in_seconds(musicStreams[index].stream); else totalSeconds = stb_vorbis_stream_length_in_seconds(musicStreams[musicBuffer.index].stream);
return totalSeconds; return totalSeconds;
} }
// Get current music time played (in seconds) // Get current music time played (in seconds)
float GetMusicTimePlayed(int index) float GetMusicTimePlayed(MusicBuffer musicBuffer)
{ {
float secondsPlayed = 0.0f; float secondsPlayed = 0.0f;
if (index < MAX_MUSIC_STREAMS && musicStreams[index].mixc) if (musicBuffer.index < MAX_MUSIC_STREAMS && musicStreams[musicBuffer.index].mixc)
{ {
if (musicStreams[index].chipTune && musicStreams[index].xmctx) if (musicStreams[musicBuffer.index].chipTune && musicStreams[musicBuffer.index].xmctx)
{ {
uint64_t samples; uint64_t samples;
jar_xm_get_position(musicStreams[index].xmctx, NULL, NULL, NULL, &samples); jar_xm_get_position(musicStreams[musicBuffer.index].xmctx, NULL, NULL, NULL, &samples);
secondsPlayed = (float)samples/(48000.0f*musicStreams[index].mixc->channels); // Not sure if this is the correct value secondsPlayed = (float)samples/(48000.0f*musicStreams[musicBuffer.index].mixc->channels); // Not sure if this is the correct value
} }
else if(musicStreams[index].chipTune && musicStreams[index].modctx.mod_loaded) else if(musicStreams[musicBuffer.index].chipTune && musicStreams[musicBuffer.index].modctx.mod_loaded)
{ {
long numsamp = jar_mod_current_samples(&musicStreams[index].modctx); long numsamp = jar_mod_current_samples(&musicStreams[musicBuffer.index].modctx);
secondsPlayed = (float)numsamp/(48000.0f); secondsPlayed = (float)numsamp/(48000.0f);
} }
else else
{ {
int totalSamples = stb_vorbis_stream_length_in_samples(musicStreams[index].stream)*musicStreams[index].mixc->channels; int totalSamples = stb_vorbis_stream_length_in_samples(musicStreams[musicBuffer.index].stream)*musicStreams[musicBuffer.index].mixc->channels;
int samplesPlayed = totalSamples - musicStreams[index].totalSamplesLeft; int samplesPlayed = totalSamples - musicStreams[musicBuffer.index].totalSamplesLeft;
secondsPlayed = (float)samplesPlayed/(musicStreams[index].mixc->sampleRate*musicStreams[index].mixc->channels); secondsPlayed = (float)samplesPlayed/(musicStreams[musicBuffer.index].mixc->sampleRate*musicStreams[musicBuffer.index].mixc->channels);
} }
} }
@@ -1368,7 +1413,7 @@ static void UnloadWave(Wave wave)
{ {
free(wave.data); free(wave.data);
TraceLog(INFO, "Unloaded wave data from RAM"); TraceLog(INFO, "Unloaded wave data");
} }
// Some required functions for audio standalone module version // Some required functions for audio standalone module version

View File

@@ -75,6 +75,11 @@ typedef struct Wave {
short channels; short channels;
} Wave; } Wave;
typedef struct MusicBuffer {
char *fileName;
int index; // index in musicStreams
} MusicBuffer;
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { // Prevents name mangling of functions extern "C" { // Prevents name mangling of functions
#endif #endif
@@ -102,16 +107,17 @@ bool IsSoundPlaying(Sound sound); // Check if a so
void SetSoundVolume(Sound sound, float volume); // Set volume for a sound (1.0 is max level) void SetSoundVolume(Sound sound, float volume); // Set volume for a sound (1.0 is max level)
void SetSoundPitch(Sound sound, float pitch); // Set pitch for a sound (1.0 is base level) void SetSoundPitch(Sound sound, float pitch); // Set pitch for a sound (1.0 is base level)
int PlayMusicStream(int index, char *fileName); // Start music playing (open stream) MusicBuffer LoadMusicBufferStream(char *fileName, int index);
void UpdateMusicStream(int index); // Updates buffers for music streaming int PlayMusicStream(MusicBuffer buffer); // Start music playing (open stream)
void StopMusicStream(int index); // Stop music playing (close stream) void UpdateMusicStream(MusicBuffer buffer); // Updates buffers for music streaming
void PauseMusicStream(int index); // Pause music playing void StopMusicStream(MusicBuffer buffer); // Stop music playing (close stream)
void ResumeMusicStream(int index); // Resume playing paused music void PauseMusicStream(MusicBuffer buffer); // Pause music playing
bool IsMusicPlaying(int index); // Check if music is playing void ResumeMusicStream(MusicBuffer buffer); // Resume playing paused music
void SetMusicVolume(int index, float volume); // Set volume for music (1.0 is max level) bool IsMusicPlaying(MusicBuffer buffer); // Check if music is playing
void SetMusicPitch(int index, float pitch); // Set pitch for a music (1.0 is base level) void SetMusicVolume(MusicBuffer buffer float volume); // Set volume for music (1.0 is max level)
float GetMusicTimeLength(int index); // Get music time length (in seconds) void SetMusicPitch(MusicBuffer buffer, float pitch); // Set pitch for a music (1.0 is base level)
float GetMusicTimePlayed(int index); // Get current music time played (in seconds) float GetMusicTimeLength(MusicBuffer buffer); // Get music time length (in seconds)
float GetMusicTimePlayed(MusicBuffer buffer); // Get current music time played (in seconds)
int GetMusicStreamCount(void); // Get number of streams loaded int GetMusicStreamCount(void); // Get number of streams loaded
int InitRawMixChannel(int sampleRate, int channels, bool floatingPoint); // Initialize raw audio mix channel for audio buffering int InitRawMixChannel(int sampleRate, int channels, bool floatingPoint); // Initialize raw audio mix channel for audio buffering

View File

@@ -478,6 +478,11 @@ typedef struct Wave {
short channels; short channels;
} Wave; } Wave;
typedef struct MusicBuffer {
char *fileName;
int index; // index in musicStreams
} MusicBuffer;
// Texture formats // Texture formats
// NOTE: Support depends on OpenGL version and platform // NOTE: Support depends on OpenGL version and platform
typedef enum { typedef enum {
@@ -815,6 +820,7 @@ Model LoadModelFromRES(const char *rresName, int resId); // Load a 3d mod
Model LoadHeightmap(Image heightmap, Vector3 size); // Load a heightmap image as a 3d model Model LoadHeightmap(Image heightmap, Vector3 size); // Load a heightmap image as a 3d model
Model LoadCubicmap(Image cubicmap); // Load a map image as a 3d model (cubes based) Model LoadCubicmap(Image cubicmap); // Load a map image as a 3d model (cubes based)
void UnloadModel(Model model); // Unload 3d model from memory void UnloadModel(Model model); // Unload 3d model from memory
Mesh GenMeshCube(float width, float height, float depth);
Material LoadMaterial(const char *fileName); // Load material data (from file) Material LoadMaterial(const char *fileName); // Load material data (from file)
Material LoadDefaultMaterial(void); // Load default material (uses default models shader) Material LoadDefaultMaterial(void); // Load default material (uses default models shader)
@@ -896,16 +902,17 @@ bool IsSoundPlaying(Sound sound); // Check if a so
void SetSoundVolume(Sound sound, float volume); // Set volume for a sound (1.0 is max level) void SetSoundVolume(Sound sound, float volume); // Set volume for a sound (1.0 is max level)
void SetSoundPitch(Sound sound, float pitch); // Set pitch for a sound (1.0 is base level) void SetSoundPitch(Sound sound, float pitch); // Set pitch for a sound (1.0 is base level)
int PlayMusicStream(int index, char *fileName); // Start music playing (open stream) MusicBuffer LoadMusicBufferStream(char *fileName, int index);
void UpdateMusicStream(int index); // Updates buffers for music streaming int PlayMusicStream(MusicBuffer buffer); // Start music playing (open stream)
void StopMusicStream(int index); // Stop music playing (close stream) void UpdateMusicStream(MusicBuffer buffer); // Updates buffers for music streaming
void PauseMusicStream(int index); // Pause music playing void StopMusicStream(MusicBuffer buffer); // Stop music playing (close stream)
void ResumeMusicStream(int index); // Resume playing paused music void PauseMusicStream(MusicBuffer buffer); // Pause music playing
bool IsMusicPlaying(int index); // Check if music is playing void ResumeMusicStream(MusicBuffer buffer); // Resume playing paused music
void SetMusicVolume(int index, float volume); // Set volume for music (1.0 is max level) bool IsMusicPlaying(MusicBuffer buffer); // Check if music is playing
void SetMusicPitch(int index, float pitch); // Set pitch for a music (1.0 is base level) void SetMusicVolume(MusicBuffer buffer, float volume); // Set volume for music (1.0 is max level)
float GetMusicTimeLength(int index); // Get current music time length (in seconds) void SetMusicPitch(MusicBuffer buffer, float pitch); // Set pitch for a music (1.0 is base level)
float GetMusicTimePlayed(int index); // Get current music time played (in seconds) float GetMusicTimeLength(MusicBuffer buffer); // Get music time length (in seconds)
float GetMusicTimePlayed(MusicBuffer buffer); // Get current music time played (in seconds)
int GetMusicStreamCount(void); // Get number of streams loaded int GetMusicStreamCount(void); // Get number of streams loaded
#ifdef __cplusplus #ifdef __cplusplus