Audio looping fix (#2579)
* WAVs looping fix. But broke other formats looping * Fix audio looping issue * Follow raylib formatting * Cast void* to char* to make MSVC compiler happy Co-authored-by: Ray <raysan5@gmail.com>
This commit is contained in:
parent
b6f87023ad
commit
0ef3e4c4d5
1 changed files with 53 additions and 50 deletions
103
src/raudio.c
103
src/raudio.c
|
@ -1725,7 +1725,8 @@ void UpdateMusicStream(Music music)
|
||||||
unsigned int subBufferSizeInFrames = music.stream.buffer->sizeInFrames/2;
|
unsigned int subBufferSizeInFrames = music.stream.buffer->sizeInFrames/2;
|
||||||
|
|
||||||
// On first call of this function we lazily pre-allocated a temp buffer to read audio files/memory data in
|
// 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;
|
int frameSize = music.stream.channels*music.stream.sampleSize/8;
|
||||||
|
unsigned int pcmSize = subBufferSizeInFrames*frameSize;
|
||||||
if (AUDIO.System.pcmBufferSize < pcmSize)
|
if (AUDIO.System.pcmBufferSize < pcmSize)
|
||||||
{
|
{
|
||||||
RL_FREE(AUDIO.System.pcmBuffer);
|
RL_FREE(AUDIO.System.pcmBuffer);
|
||||||
|
@ -1733,74 +1734,85 @@ void UpdateMusicStream(Music music)
|
||||||
AUDIO.System.pcmBufferSize = pcmSize;
|
AUDIO.System.pcmBufferSize = pcmSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int framesLeft = music.frameCount - music.stream.buffer->framesProcessed; // Frames left to be processed
|
int framesLeft = music.frameCount - music.stream.buffer->framesProcessed; // Frames left to be processed
|
||||||
unsigned int framesToStream = 0; // Total frames to be streamed
|
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
|
|
||||||
|
|
||||||
// Check both sub-buffers to check if they require refilling
|
// Check both sub-buffers to check if they require refilling
|
||||||
for (int i = 0; i < 2; i++)
|
for (int i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
if ((music.stream.buffer != NULL) && !music.stream.buffer->isSubBufferProcessed[i]) continue; // No refilling required, move to next sub-buffer
|
if ((music.stream.buffer != NULL) && !music.stream.buffer->isSubBufferProcessed[i]) continue; // No refilling required, move to next sub-buffer
|
||||||
|
|
||||||
if (framesLeft >= subBufferSizeInFrames) framesToStream = subBufferSizeInFrames;
|
if ((framesLeft >= subBufferSizeInFrames) || music.looping) framesToStream = subBufferSizeInFrames;
|
||||||
else
|
else framesToStream = framesLeft;
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
int frameCountStillNeeded = framesToStream;
|
||||||
|
int frameCountRedTotal = 0;
|
||||||
switch (music.ctxType)
|
switch (music.ctxType)
|
||||||
{
|
{
|
||||||
#if defined(SUPPORT_FILEFORMAT_WAV)
|
#if defined(SUPPORT_FILEFORMAT_WAV)
|
||||||
case MUSIC_AUDIO_WAV:
|
case MUSIC_AUDIO_WAV:
|
||||||
{
|
{
|
||||||
// NOTE: Returns the number of samples to process (not required)
|
if (music.stream.sampleSize == 16)
|
||||||
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);
|
while (true)
|
||||||
|
{
|
||||||
if (music.stream.sampleSize == 16) drwav_read_pcm_frames_s16((drwav *)music.ctxData, framesLoopingExtra, (short *)AUDIO.System.pcmBuffer + framesToStream*music.stream.channels);
|
int frameCountRed = drwav_read_pcm_frames_s16((drwav *)music.ctxData, frameCountStillNeeded, (short *)((char *)AUDIO.System.pcmBuffer + frameCountRedTotal*frameSize));
|
||||||
else if (music.stream.sampleSize == 32) drwav_read_pcm_frames_f32((drwav *)music.ctxData, framesLoopingExtra, (float *)AUDIO.System.pcmBuffer + framesToStream*music.stream.channels);
|
frameCountRedTotal += frameCountRed;
|
||||||
|
frameCountStillNeeded -= frameCountRed;
|
||||||
framesToStream += framesLoopingExtra;
|
if (frameCountStillNeeded == 0) break;
|
||||||
|
else drwav_seek_to_pcm_frame((drwav *)music.ctxData, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (music.stream.sampleSize == 32)
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
int frameCountRed = drwav_read_pcm_frames_f32((drwav *)music.ctxData, frameCountStillNeeded, (float *)((char *)AUDIO.System.pcmBuffer + frameCountRedTotal*frameSize));
|
||||||
|
frameCountRedTotal += frameCountRed;
|
||||||
|
frameCountStillNeeded -= frameCountRed;
|
||||||
|
if (frameCountStillNeeded == 0) break;
|
||||||
|
else drwav_seek_to_pcm_frame((drwav *)music.ctxData, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
#endif
|
#endif
|
||||||
#if defined(SUPPORT_FILEFORMAT_OGG)
|
#if defined(SUPPORT_FILEFORMAT_OGG)
|
||||||
case MUSIC_AUDIO_OGG:
|
case MUSIC_AUDIO_OGG:
|
||||||
{
|
{
|
||||||
// NOTE: Returns the number of samples to process (be careful! we ask for number of shorts!)
|
while (true)
|
||||||
stb_vorbis_get_samples_short_interleaved((stb_vorbis *)music.ctxData, music.stream.channels, (short *)AUDIO.System.pcmBuffer, framesToStream*music.stream.channels);
|
{
|
||||||
|
int frameCountRed = stb_vorbis_get_samples_short_interleaved((stb_vorbis *)music.ctxData, music.stream.channels, (short *)((char *)AUDIO.System.pcmBuffer + frameCountRedTotal*frameSize), frameCountStillNeeded*music.stream.channels);
|
||||||
// stb_vorbis_seek_start((stb_vorbis *)music.ctxData);
|
frameCountRedTotal += frameCountRed;
|
||||||
|
frameCountStillNeeded -= frameCountRed;
|
||||||
|
if (frameCountStillNeeded == 0) break;
|
||||||
|
else stb_vorbis_seek_start((stb_vorbis *)music.ctxData);
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
#endif
|
#endif
|
||||||
#if defined(SUPPORT_FILEFORMAT_FLAC)
|
#if defined(SUPPORT_FILEFORMAT_FLAC)
|
||||||
case MUSIC_AUDIO_FLAC:
|
case MUSIC_AUDIO_FLAC:
|
||||||
{
|
{
|
||||||
// NOTE: Returns the number of samples to process (not required)
|
while (true)
|
||||||
drflac_read_pcm_frames_s16((drflac *)music.ctxData, frameCountToStream*music.stream.channels, (short *)AUDIO.System.pcm);
|
{
|
||||||
|
int frameCountRed = drflac_read_pcm_frames_s16((drflac *)music.ctxData, frameCountStillNeeded, (short *)((char *)AUDIO.System.pcmBuffer + frameCountRedTotal*frameSize));
|
||||||
// drflac_seek_to_pcm_frame((drflac *)music.ctxData, 0);
|
frameCountRedTotal += frameCountRed;
|
||||||
|
frameCountStillNeeded -= frameCountRed;
|
||||||
|
if (frameCountStillNeeded == 0) break;
|
||||||
|
else drflac_seek_to_pcm_frame((drflac *)music.ctxData, 0);
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
#endif
|
#endif
|
||||||
#if defined(SUPPORT_FILEFORMAT_MP3)
|
#if defined(SUPPORT_FILEFORMAT_MP3)
|
||||||
case MUSIC_AUDIO_MP3:
|
case MUSIC_AUDIO_MP3:
|
||||||
{
|
{
|
||||||
drmp3_read_pcm_frames_f32((drmp3 *)music.ctxData, framesToStream, (float *)AUDIO.System.pcmBuffer);
|
while (true)
|
||||||
|
{
|
||||||
//drmp3_seek_to_pcm_frame((drmp3 *)music.ctxData, 0);
|
int frameCountRed = drmp3_read_pcm_frames_f32((drmp3 *)music.ctxData, frameCountStillNeeded, (float *)((char *)AUDIO.System.pcmBuffer + frameCountRedTotal*frameSize));
|
||||||
|
frameCountRedTotal += frameCountRed;
|
||||||
|
frameCountStillNeeded -= frameCountRed;
|
||||||
|
if (frameCountStillNeeded == 0) break;
|
||||||
|
else drmp3_seek_to_pcm_frame((drmp3 *)music.ctxData, 0);
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
#endif
|
#endif
|
||||||
#if defined(SUPPORT_FILEFORMAT_XM)
|
#if defined(SUPPORT_FILEFORMAT_XM)
|
||||||
|
@ -1841,16 +1853,7 @@ void UpdateMusicStream(Music music)
|
||||||
// Reset audio stream for looping
|
// Reset audio stream for looping
|
||||||
if (streamEnding)
|
if (streamEnding)
|
||||||
{
|
{
|
||||||
if (music.looping)
|
if (!music.looping) StopMusicStream(music);
|
||||||
{
|
|
||||||
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
|
else
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue