Skip to content

Commit 7f6cd93

Browse files
committed
WARNING: Multiple funcs reviewed!
There were some problems about frameCount vs sampleCount that could cause some breaks. raylib audio structs stores sampleCount = frameCount*channels. Most libraries return framesCount instead of sampleCount. stb_vorbis seems to refer to framesCount as samples. All required functions have been reviewed.
1 parent 72e51cd commit 7f6cd93

File tree

2 files changed

+28
-27
lines changed

2 files changed

+28
-27
lines changed

src/raudio.c

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**********************************************************************************************
22
*
3-
* raudio - A simple and easy-to-use audio library based on miniaudio
3+
* raudio v1.0 - A simple and easy-to-use audio library based on miniaudio
44
*
55
* FEATURES:
66
* - Manage audio device (init/close)
@@ -824,7 +824,7 @@ void ExportWave(Wave wave, const char *fileName)
824824
{
825825
// Export raw sample data (without header)
826826
// NOTE: It's up to the user to track wave parameters
827-
SaveFileData(fileName, wave.data, wave.sampleCount*wave.channels*wave.sampleSize/8);
827+
SaveFileData(fileName, wave.data, wave.sampleCount*wave.sampleSize/8);
828828
success = true;
829829
}
830830

@@ -1007,10 +1007,10 @@ void SetSoundPitch(Sound sound, float pitch)
10071007
// Convert wave data to desired format
10081008
void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels)
10091009
{
1010-
ma_format formatIn = ((wave->sampleSize == 8)? ma_format_u8 : ((wave->sampleSize == 16)? ma_format_s16 : ma_format_f32));
1011-
ma_format formatOut = (( sampleSize == 8)? ma_format_u8 : (( sampleSize == 16)? ma_format_s16 : ma_format_f32));
1010+
ma_format formatIn = ((wave->sampleSize == 8)? ma_format_u8 : ((wave->sampleSize == 16)? ma_format_s16 : ma_format_f32));
1011+
ma_format formatOut = ((sampleSize == 8)? ma_format_u8 : ((sampleSize == 16)? ma_format_s16 : ma_format_f32));
10121012

1013-
ma_uint32 frameCountIn = wave->sampleCount; // Is wave->sampleCount actually the frame count? That terminology needs to change, if so.
1013+
ma_uint32 frameCountIn = wave->sampleCount/wave->channels;
10141014

10151015
ma_uint32 frameCount = (ma_uint32)ma_convert_frames(NULL, 0, formatOut, channels, sampleRate, NULL, frameCountIn, formatIn, wave->channels, wave->sampleRate);
10161016
if (frameCount == 0)
@@ -1028,7 +1028,7 @@ void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels)
10281028
return;
10291029
}
10301030

1031-
wave->sampleCount = frameCount;
1031+
wave->sampleCount = frameCount*channels;
10321032
wave->sampleSize = sampleSize;
10331033
wave->sampleRate = sampleRate;
10341034
wave->channels = channels;
@@ -1041,12 +1041,12 @@ Wave WaveCopy(Wave wave)
10411041
{
10421042
Wave newWave = { 0 };
10431043

1044-
newWave.data = RL_MALLOC(wave.sampleCount*wave.sampleSize/8*wave.channels);
1044+
newWave.data = RL_MALLOC(wave.sampleCount*wave.sampleSize/8);
10451045

10461046
if (newWave.data != NULL)
10471047
{
10481048
// NOTE: Size must be provided in bytes
1049-
memcpy(newWave.data, wave.data, wave.sampleCount*wave.channels*wave.sampleSize/8);
1049+
memcpy(newWave.data, wave.data, wave.sampleCount*wave.sampleSize/8);
10501050

10511051
newWave.sampleCount = wave.sampleCount;
10521052
newWave.sampleRate = wave.sampleRate;
@@ -1066,9 +1066,9 @@ void WaveCrop(Wave *wave, int initSample, int finalSample)
10661066
{
10671067
int sampleCount = finalSample - initSample;
10681068

1069-
void *data = RL_MALLOC(sampleCount*wave->sampleSize/8*wave->channels);
1069+
void *data = RL_MALLOC(sampleCount*wave->sampleSize/8);
10701070

1071-
memcpy(data, (unsigned char *)wave->data + (initSample*wave->channels*wave->sampleSize/8), sampleCount*wave->channels*wave->sampleSize/8);
1071+
memcpy(data, (unsigned char *)wave->data + (initSample*wave->channels*wave->sampleSize/8), sampleCount*wave->sampleSize/8);
10721072

10731073
RL_FREE(wave->data);
10741074
wave->data = data;
@@ -1080,16 +1080,15 @@ void WaveCrop(Wave *wave, int initSample, int finalSample)
10801080
// NOTE: Returned sample values are normalized to range [-1..1]
10811081
float *GetWaveData(Wave wave)
10821082
{
1083-
float *samples = (float *)RL_MALLOC(wave.sampleCount*wave.channels*sizeof(float));
1083+
float *samples = (float *)RL_MALLOC(wave.sampleCount*sizeof(float));
10841084

1085+
// NOTE: sampleCount is the total number of interlaced samples (including channels)
1086+
10851087
for (unsigned int i = 0; i < wave.sampleCount; i++)
10861088
{
1087-
for (unsigned int j = 0; j < wave.channels; j++)
1088-
{
1089-
if (wave.sampleSize == 8) samples[wave.channels*i + j] = (float)(((unsigned char *)wave.data)[wave.channels*i + j] - 127)/256.0f;
1090-
else if (wave.sampleSize == 16) samples[wave.channels*i + j] = (float)((short *)wave.data)[wave.channels*i + j]/32767.0f;
1091-
else if (wave.sampleSize == 32) samples[wave.channels*i + j] = ((float *)wave.data)[wave.channels*i + j];
1092-
}
1089+
if (wave.sampleSize == 8) samples[i] = (float)(((unsigned char *)wave.data)[i] - 127)/256.0f;
1090+
else if (wave.sampleSize == 16) samples[i] = (float)(((short *)wave.data)[i])/32767.0f;
1091+
else if (wave.sampleSize == 32) samples[i] = ((float *)wave.data)[i];
10931092
}
10941093

10951094
return samples;
@@ -1140,6 +1139,8 @@ Music LoadMusicStream(const char *fileName)
11401139

11411140
// OGG bit rate defaults to 16 bit, it's enough for compressed format
11421141
music.stream = InitAudioStream(info.sample_rate, 16, info.channels);
1142+
1143+
// WARNING: It seems this function returns length in frames, not samples, so we multiply by channels
11431144
music.sampleCount = (unsigned int)stb_vorbis_stream_length_in_samples((stb_vorbis *)music.ctxData)*info.channels;
11441145
music.looping = true; // Looping enabled by default
11451146
musicLoaded = true;
@@ -1157,7 +1158,7 @@ Music LoadMusicStream(const char *fileName)
11571158
drflac *ctxFlac = (drflac *)music.ctxData;
11581159

11591160
music.stream = InitAudioStream(ctxFlac->sampleRate, ctxFlac->bitsPerSample, ctxFlac->channels);
1160-
music.sampleCount = (unsigned int)ctxFlac->totalPCMFrameCount;
1161+
music.sampleCount = (unsigned int)ctxFlac->totalPCMFrameCount*ctxFlac->channels;
11611162
music.looping = true; // Looping enabled by default
11621163
musicLoaded = true;
11631164
}
@@ -1196,7 +1197,7 @@ Music LoadMusicStream(const char *fileName)
11961197

11971198
// NOTE: Only stereo is supported for XM
11981199
music.stream = InitAudioStream(48000, 16, 2);
1199-
music.sampleCount = (unsigned int)jar_xm_get_remaining_samples(ctxXm)*2;
1200+
music.sampleCount = (unsigned int)jar_xm_get_remaining_samples(ctxXm)*2; // 2 channels
12001201
music.looping = true; // Looping enabled by default
12011202
jar_xm_reset(ctxXm); // make sure we start at the beginning of the song
12021203
musicLoaded = true;
@@ -1219,7 +1220,7 @@ Music LoadMusicStream(const char *fileName)
12191220

12201221
// NOTE: Only stereo is supported for MOD
12211222
music.stream = InitAudioStream(48000, 16, 2);
1222-
music.sampleCount = (unsigned int)jar_mod_max_samples(ctxMod)*2;
1223+
music.sampleCount = (unsigned int)jar_mod_max_samples(ctxMod)*2; // 2 channels
12231224
music.looping = true; // Looping enabled by default
12241225
musicLoaded = true;
12251226

@@ -1493,7 +1494,7 @@ float GetMusicTimePlayed(Music music)
14931494
{
14941495
//ma_uint32 frameSizeInBytes = ma_get_bytes_per_sample(music.stream.buffer->dsp.formatConverterIn.config.formatIn)*music.stream.buffer->dsp.formatConverterIn.config.channels;
14951496
unsigned int samplesPlayed = music.stream.buffer->totalFramesProcessed*music.stream.channels;
1496-
secondsPlayed = (float)samplesPlayed / (music.stream.sampleRate*music.stream.channels);
1497+
secondsPlayed = (float)samplesPlayed/(music.stream.sampleRate*music.stream.channels);
14971498
}
14981499

14991500
return secondsPlayed;
@@ -1983,10 +1984,10 @@ static Wave LoadOGG(const unsigned char *fileData, unsigned int fileSize)
19831984
float totalSeconds = stb_vorbis_stream_length_in_seconds(oggData);
19841985
if (totalSeconds > 10) TRACELOG(LOG_WARNING, "WAVE: OGG audio length larger than 10 seconds (%f sec.), that's a big file in memory, consider music streaming", totalSeconds);
19851986

1986-
wave.data = (short *)RL_MALLOC(wave.sampleCount*wave.channels*sizeof(short));
1987+
wave.data = (short *)RL_MALLOC(wave.sampleCount*sizeof(short));
19871988

19881989
// NOTE: Returns the number of samples to process (be careful! we ask for number of shorts!)
1989-
stb_vorbis_get_samples_short_interleaved(oggData, info.channels, (short *)wave.data, wave.sampleCount*wave.channels);
1990+
stb_vorbis_get_samples_short_interleaved(oggData, info.channels, (short *)wave.data, wave.sampleCount);
19901991
TRACELOG(LOG_INFO, "WAVE: OGG data loaded successfully (%i Hz, %i bit, %s)", wave.sampleRate, wave.sampleSize, (wave.channels == 1)? "Mono" : "Stereo");
19911992

19921993
stb_vorbis_close(oggData);
@@ -2005,12 +2006,12 @@ static Wave LoadFLAC(const unsigned char *fileData, unsigned int fileSize)
20052006
Wave wave = { 0 };
20062007

20072008
// Decode the entire FLAC file in one go
2008-
unsigned long long int totalSampleCount = 0;
2009-
wave.data = drflac_open_memory_and_read_pcm_frames_s16(fileData, fileSize, &wave.channels, &wave.sampleRate, &totalSampleCount, NULL);
2009+
unsigned long long int totalFrameCount = 0;
2010+
wave.data = drflac_open_memory_and_read_pcm_frames_s16(fileData, fileSize, &wave.channels, &wave.sampleRate, &totalFrameCount, NULL);
20102011

20112012
if (wave.data != NULL)
20122013
{
2013-
wave.sampleCount = (unsigned int)totalSampleCount;
2014+
wave.sampleCount = (unsigned int)totalFrameCount*wave.channels;
20142015
wave.sampleSize = 16;
20152016

20162017
TRACELOG(LOG_INFO, "WAVE: FLAC data loaded successfully (%i Hz, %i bit, %s)", wave.sampleRate, wave.sampleSize, (wave.channels == 1)? "Mono" : "Stereo");

src/raudio.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**********************************************************************************************
22
*
3-
* raudio - A simple and easy-to-use audio library based on miniaudio
3+
* raudio v1.0 - A simple and easy-to-use audio library based on miniaudio
44
*
55
* FEATURES:
66
* - Manage audio device (init/close)

0 commit comments

Comments
 (0)