|
@ -42,6 +42,9 @@ |
|
|
#include <string.h> // Required for strcmp() |
|
|
#include <string.h> // Required for strcmp() |
|
|
#include <stdio.h> // Used for .WAV loading |
|
|
#include <stdio.h> // Used for .WAV loading |
|
|
|
|
|
|
|
|
|
|
|
#define JAR_XM_IMPLEMENTATION |
|
|
|
|
|
#include "jar_xm.h" // For playing .xm files |
|
|
|
|
|
|
|
|
#if defined(AUDIO_STANDALONE) |
|
|
#if defined(AUDIO_STANDALONE) |
|
|
#include <stdarg.h> // Used for functions with variable number of parameters (TraceLog()) |
|
|
#include <stdarg.h> // Used for functions with variable number of parameters (TraceLog()) |
|
|
#else |
|
|
#else |
|
@ -73,6 +76,7 @@ |
|
|
// NOTE: Anything longer than ~10 seconds should be streamed... |
|
|
// NOTE: Anything longer than ~10 seconds should be streamed... |
|
|
typedef struct Music { |
|
|
typedef struct Music { |
|
|
stb_vorbis *stream; |
|
|
stb_vorbis *stream; |
|
|
|
|
|
jar_xm_context_t *chipctx; // Stores jar_xm context |
|
|
|
|
|
|
|
|
ALuint buffers[MUSIC_STREAM_BUFFERS]; |
|
|
ALuint buffers[MUSIC_STREAM_BUFFERS]; |
|
|
ALuint source; |
|
|
ALuint source; |
|
@ -82,7 +86,7 @@ typedef struct Music { |
|
|
int sampleRate; |
|
|
int sampleRate; |
|
|
int totalSamplesLeft; |
|
|
int totalSamplesLeft; |
|
|
bool loop; |
|
|
bool loop; |
|
|
|
|
|
|
|
|
|
|
|
bool chipTune; // True if chiptune is loaded |
|
|
} Music; |
|
|
} Music; |
|
|
|
|
|
|
|
|
#if defined(AUDIO_STANDALONE) |
|
|
#if defined(AUDIO_STANDALONE) |
|
@ -564,6 +568,22 @@ void PlayMusicStream(char *fileName) |
|
|
currentMusic.totalSamplesLeft = stb_vorbis_stream_length_in_samples(currentMusic.stream) * currentMusic.channels; |
|
|
currentMusic.totalSamplesLeft = stb_vorbis_stream_length_in_samples(currentMusic.stream) * currentMusic.channels; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
else if (strcmp(GetExtension(fileName),"xm") == 0) |
|
|
|
|
|
{ |
|
|
|
|
|
currentMusic.chipTune = true; |
|
|
|
|
|
currentMusic.channels = 2; |
|
|
|
|
|
currentMusic.sampleRate = 48000; |
|
|
|
|
|
currentMusic.loop = true; |
|
|
|
|
|
|
|
|
|
|
|
// only stereo/float is supported for xm |
|
|
|
|
|
if(info.channels == 2 && !jar_xm_create_context_from_file(¤tMusic.chipctx, currentMusic.sampleRate, fileName)) |
|
|
|
|
|
{ |
|
|
|
|
|
currentMusic.format = AL_FORMAT_STEREO_FLOAT32; |
|
|
|
|
|
jar_xm_set_max_loop_count(currentMusic.chipctx, 0); //infinite number of loops |
|
|
|
|
|
//currentMusic.totalSamplesLeft = ; // Unsure of how to calculate this |
|
|
|
|
|
musicEnabled = true; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
else TraceLog(WARNING, "[%s] Music extension not recognized, it can't be loaded", fileName); |
|
|
else TraceLog(WARNING, "[%s] Music extension not recognized, it can't be loaded", fileName); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -573,13 +593,18 @@ void StopMusicStream(void) |
|
|
if (musicEnabled) |
|
|
if (musicEnabled) |
|
|
{ |
|
|
{ |
|
|
alSourceStop(currentMusic.source); |
|
|
alSourceStop(currentMusic.source); |
|
|
|
|
|
|
|
|
EmptyMusicStream(); // Empty music buffers |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
EmptyMusicStream(); // Empty music buffers |
|
|
alDeleteSources(1, ¤tMusic.source); |
|
|
alDeleteSources(1, ¤tMusic.source); |
|
|
alDeleteBuffers(2, currentMusic.buffers); |
|
|
alDeleteBuffers(2, currentMusic.buffers); |
|
|
|
|
|
|
|
|
stb_vorbis_close(currentMusic.stream); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (currentMusic.chipTune) |
|
|
|
|
|
{ |
|
|
|
|
|
jar_xm_free_context(currentMusic.chipctx); |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
stb_vorbis_close(currentMusic.stream); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
musicEnabled = false; |
|
|
musicEnabled = false; |
|
@ -633,7 +658,15 @@ void SetMusicVolume(float volume) |
|
|
// Get current music time length (in seconds) |
|
|
// Get current music time length (in seconds) |
|
|
float GetMusicTimeLength(void) |
|
|
float GetMusicTimeLength(void) |
|
|
{ |
|
|
{ |
|
|
float totalSeconds = stb_vorbis_stream_length_in_seconds(currentMusic.stream); |
|
|
|
|
|
|
|
|
float totalSeconds; |
|
|
|
|
|
if (currentMusic.chipTune) |
|
|
|
|
|
{ |
|
|
|
|
|
//totalSeconds = (float)samples; // Need to figure out how toget this |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
totalSeconds = stb_vorbis_stream_length_in_seconds(currentMusic.stream); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
return totalSeconds; |
|
|
return totalSeconds; |
|
|
} |
|
|
} |
|
@ -641,11 +674,20 @@ float GetMusicTimeLength(void) |
|
|
// Get current music time played (in seconds) |
|
|
// Get current music time played (in seconds) |
|
|
float GetMusicTimePlayed(void) |
|
|
float GetMusicTimePlayed(void) |
|
|
{ |
|
|
{ |
|
|
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); |
|
|
|
|
|
|
|
|
float secondsPlayed; |
|
|
|
|
|
if (currentMusic.chipTune) |
|
|
|
|
|
{ |
|
|
|
|
|
uint64_t samples; |
|
|
|
|
|
jar_xm_get_position(currentMusic.chipctx, NULL, NULL, NULL, &samples); // Unsure if this is the desired value |
|
|
|
|
|
secondsPlayed = (float)samples / (currentMusic.sampleRate * currentMusic.channels); |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
int totalSamples = stb_vorbis_stream_length_in_samples(currentMusic.stream) * currentMusic.channels; |
|
|
|
|
|
int samplesPlayed = totalSamples - currentMusic.totalSamplesLeft; |
|
|
|
|
|
secondsPlayed = (float)samplesPlayed / (currentMusic.sampleRate * currentMusic.channels); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return secondsPlayed; |
|
|
return secondsPlayed; |
|
|
} |
|
|
} |
|
@ -668,7 +710,15 @@ static bool BufferMusicStream(ALuint buffer) |
|
|
{ |
|
|
{ |
|
|
while (size < MUSIC_BUFFER_SIZE) |
|
|
while (size < MUSIC_BUFFER_SIZE) |
|
|
{ |
|
|
{ |
|
|
streamedBytes = stb_vorbis_get_samples_short_interleaved(currentMusic.stream, currentMusic.channels, pcm + size, MUSIC_BUFFER_SIZE - size); |
|
|
|
|
|
|
|
|
if (currentMusic.chipTune) |
|
|
|
|
|
{ |
|
|
|
|
|
jar_xm_generate_samples(currentMusic.chipctx, pcm + size, (MUSIC_BUFFER_SIZE - size) / 2); |
|
|
|
|
|
streamedBytes = (MUSIC_BUFFER_SIZE - size)/2; // There is no end of stream for xmfiles, once the end is reached zeros are generated for non looped chiptunes. |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
streamedBytes = stb_vorbis_get_samples_short_interleaved(currentMusic.stream, currentMusic.channels, pcm + size, MUSIC_BUFFER_SIZE - size); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (streamedBytes > 0) size += (streamedBytes*currentMusic.channels); |
|
|
if (streamedBytes > 0) size += (streamedBytes*currentMusic.channels); |
|
|
else break; |
|
|
else break; |
|
|