summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRay <[email protected]>2022-07-11 21:19:21 +0200
committerRay <[email protected]>2022-07-11 21:19:21 +0200
commit3ebfee5dbc1d0de5555105f4989954cd4547bafd (patch)
treeac02b93aec81194a111077245f48bda393594c99
parent0379b94b7ab0532873a477b1ac43ff60cb7ff5b0 (diff)
downloadraylib-3ebfee5dbc1d0de5555105f4989954cd4547bafd.tar.gz
raylib-3ebfee5dbc1d0de5555105f4989954cd4547bafd.zip
REVIEWED: `UpdateMusicStream()` #2228
Trying to implement proper looping, independently of frame rate.
-rw-r--r--src/raudio.c94
1 files changed, 64 insertions, 30 deletions
diff --git a/src/raudio.c b/src/raudio.c
index 2b05d654..43fa382d 100644
--- a/src/raudio.c
+++ b/src/raudio.c
@@ -1724,28 +1724,34 @@ void UpdateMusicStream(Music music)
bool streamEnding = false;
unsigned int subBufferSizeInFrames = music.stream.buffer->sizeInFrames/2;
- // NOTE: Using dynamic allocation because it could require more than 16KB
+ // On first call of this function we lazily pre-allocated a temp buffer to read audio files/memory data in
unsigned int pcmSize = subBufferSizeInFrames*music.stream.channels*music.stream.sampleSize/8;
- if (AUDIO.System.pcmCapacity < pcmSize)
+ if (AUDIO.System.pcmBufferSize < pcmSize)
{
- RL_FREE(AUDIO.System.pcm);
- AUDIO.System.pcm = RL_CALLOC(1, pcmSize);
- AUDIO.System.pcmCapacity = pcmSize;
+ RL_FREE(AUDIO.System.pcmBuffer);
+ AUDIO.System.pcmBuffer = RL_CALLOC(1, pcmSize);
+ AUDIO.System.pcmBufferSize = pcmSize;
}
- int frameCountToStream = 0; // Total size of data in frames to be streamed
-
- // TODO: Get the framesLeft using framesProcessed... but first, get total frames processed correctly...
- //ma_uint32 frameSizeInBytes = ma_get_bytes_per_sample(music.stream.buffer->dsp.formatConverterIn.config.formatIn)*music.stream.buffer->dsp.formatConverterIn.config.channels;
- unsigned int framesLeft = music.frameCount - music.stream.buffer->framesProcessed;
+ int framesLeft = music.frameCount - music.stream.buffer->framesProcessed; // Frames left to be processed
+ int framesToStream = 0; // Total frames to be streamed
+ unsigned int framesLoopingExtra = 0; // In case music requires to loop, we could need to add more frames from beginning to fill buffer
- while (IsAudioStreamProcessed(music.stream))
+ // Check both sub-buffers to check if they require refilling
+ for (int i = 0; i < 2; i++)
{
- // WARNING: If audio needs to loop but the frames left are less than the actual size of buffer to fill,
- // the buffer is only partially filled and no refill is done until next frame call, generating a silence
- // TODO: Possible solution: In case of music loop, fill frames left + frames from start to fill the buffer to process
- if (framesLeft >= subBufferSizeInFrames) frameCountToStream = subBufferSizeInFrames;
- else frameCountToStream = framesLeft;
+ if ((music.stream.buffer != NULL) && !music.stream.buffer->isSubBufferProcessed[i]) continue; // No refilling required, move to next sub-buffer
+
+ if (framesLeft >= subBufferSizeInFrames) framesToStream = subBufferSizeInFrames;
+ else
+ {
+ framesToStream = framesLeft;
+
+ // WARNING: If audio needs to loop but the frames left are less than the actual size of buffer to fill,
+ // the buffer is only partially filled and no refill is done until next frame call, generating a silence
+ // SOLUTION: In case of music loop, fill frames left + frames from start to fill the buffer to process
+ if (music.looping) framesLoopingExtra = subBufferSizeInFrames - framesLeft;
+ }
switch (music.ctxType)
{
@@ -1753,8 +1759,18 @@ void UpdateMusicStream(Music music)
case MUSIC_AUDIO_WAV:
{
// NOTE: Returns the number of samples to process (not required)
- if (music.stream.sampleSize == 16) drwav_read_pcm_frames_s16((drwav *)music.ctxData, frameCountToStream, (short *)AUDIO.System.pcm);
- else if (music.stream.sampleSize == 32) drwav_read_pcm_frames_f32((drwav *)music.ctxData, frameCountToStream, (float *)AUDIO.System.pcm);
+ if (music.stream.sampleSize == 16) drwav_read_pcm_frames_s16((drwav *)music.ctxData, framesToStream, (short *)AUDIO.System.pcmBuffer);
+ else if (music.stream.sampleSize == 32) drwav_read_pcm_frames_f32((drwav *)music.ctxData, framesToStream, (float *)AUDIO.System.pcmBuffer);
+
+ if (framesLoopingExtra > 0)
+ {
+ drwav_seek_to_pcm_frame((drwav *)music.ctxData, 0);
+
+ if (music.stream.sampleSize == 16) drwav_read_pcm_frames_s16((drwav *)music.ctxData, framesLoopingExtra, (short *)AUDIO.System.pcmBuffer + framesToStream*music.stream.channels);
+ else if (music.stream.sampleSize == 32) drwav_read_pcm_frames_f32((drwav *)music.ctxData, framesLoopingExtra, (float *)AUDIO.System.pcmBuffer + framesToStream*music.stream.channels);
+
+ framesToStream += framesLoopingExtra;
+ }
} break;
#endif
@@ -1762,7 +1778,9 @@ void UpdateMusicStream(Music music)
case MUSIC_AUDIO_OGG:
{
// NOTE: Returns the number of samples to process (be careful! we ask for number of shorts!)
- stb_vorbis_get_samples_short_interleaved((stb_vorbis *)music.ctxData, music.stream.channels, (short *)AUDIO.System.pcm, frameCountToStream*music.stream.channels);
+ stb_vorbis_get_samples_short_interleaved((stb_vorbis *)music.ctxData, music.stream.channels, (short *)AUDIO.System.pcmBuffer, framesToStream*music.stream.channels);
+
+ // stb_vorbis_seek_start((stb_vorbis *)music.ctxData);
} break;
#endif
@@ -1772,12 +1790,16 @@ void UpdateMusicStream(Music music)
// NOTE: Returns the number of samples to process (not required)
drflac_read_pcm_frames_s16((drflac *)music.ctxData, frameCountToStream*music.stream.channels, (short *)AUDIO.System.pcm);
+ // drflac_seek_to_pcm_frame((drflac *)music.ctxData, 0);
+
} break;
#endif
#if defined(SUPPORT_FILEFORMAT_MP3)
case MUSIC_AUDIO_MP3:
{
- drmp3_read_pcm_frames_f32((drmp3 *)music.ctxData, frameCountToStream, (float *)AUDIO.System.pcm);
+ drmp3_read_pcm_frames_f32((drmp3 *)music.ctxData, framesToStream, (float *)AUDIO.System.pcmBuffer);
+
+ //drmp3_seek_to_pcm_frame((drmp3 *)music.ctxData, 0);
} break;
#endif
@@ -1785,9 +1807,11 @@ void UpdateMusicStream(Music music)
case MUSIC_MODULE_XM:
{
// NOTE: Internally we consider 2 channels generation, so sampleCount/2
- if (AUDIO_DEVICE_FORMAT == ma_format_f32) jar_xm_generate_samples((jar_xm_context_t *)music.ctxData, (float *)AUDIO.System.pcm, frameCountToStream);
- else if (AUDIO_DEVICE_FORMAT == ma_format_s16) jar_xm_generate_samples_16bit((jar_xm_context_t *)music.ctxData, (short *)AUDIO.System.pcm, frameCountToStream);
- else if (AUDIO_DEVICE_FORMAT == ma_format_u8) jar_xm_generate_samples_8bit((jar_xm_context_t *)music.ctxData, (char *)AUDIO.System.pcm, frameCountToStream);
+ if (AUDIO_DEVICE_FORMAT == ma_format_f32) jar_xm_generate_samples((jar_xm_context_t *)music.ctxData, (float *)AUDIO.System.pcmBuffer, framesToStream);
+ else if (AUDIO_DEVICE_FORMAT == ma_format_s16) jar_xm_generate_samples_16bit((jar_xm_context_t *)music.ctxData, (short *)AUDIO.System.pcmBuffer, framesToStream);
+ else if (AUDIO_DEVICE_FORMAT == ma_format_u8) jar_xm_generate_samples_8bit((jar_xm_context_t *)music.ctxData, (char *)AUDIO.System.pcmBuffer, framesToStream);
+
+ //jar_xm_reset((jar_xm_context_t *)music.ctxData);
} break;
#endif
@@ -1795,18 +1819,20 @@ void UpdateMusicStream(Music music)
case MUSIC_MODULE_MOD:
{
// NOTE: 3rd parameter (nbsample) specify the number of stereo 16bits samples you want, so sampleCount/2
- jar_mod_fillbuffer((jar_mod_context_t *)music.ctxData, (short *)AUDIO.System.pcm, frameCountToStream, 0);
+ jar_mod_fillbuffer((jar_mod_context_t *)music.ctxData, (short *)AUDIO.System.pcmBuffer, framesToStream, 0);
+
+ //jar_mod_seek_start((jar_mod_context_t *)music.ctxData);
+
} break;
#endif
default: break;
}
- UpdateAudioStream(music.stream, AUDIO.System.pcm, frameCountToStream);
+ UpdateAudioStream(music.stream, AUDIO.System.pcmBuffer, framesToStream);
- framesLeft -= frameCountToStream;
-
- if (framesLeft <= 0)
+ if (framesLeft <= subBufferSizeInFrames)
{
+ // Streaming is ending, we filled latest frames from input
streamEnding = true;
break;
}
@@ -1815,8 +1841,16 @@ void UpdateMusicStream(Music music)
// Reset audio stream for looping
if (streamEnding)
{
- StopMusicStream(music); // Stop music (and reset)
- if (music.looping) PlayMusicStream(music); // Play again
+ if (music.looping)
+ {
+ PlayMusicStream(music); // Play again
+
+ // Set cursor offset to extra frames filled previously
+ music.stream.buffer->frameCursorPos = framesLoopingExtra;
+
+ // TODO: It's not working properly... :(
+ }
+ else StopMusicStream(music); // Stop music (and reset)
}
else
{