Browse Source

Fixes for loading Music (#3966)

* Fixes for loading Music

Fix for #3889
Fixes for QOA crashes.
Memory leak FIX on unsuccessful .wav loading.

* Added comments
veins1 1 year ago
parent
commit
1aa3559155
1 changed files with 95 additions and 96 deletions
  1. 95 96
      src/raudio.c

+ 95 - 96
src/raudio.c

@@ -1334,11 +1334,10 @@ Music LoadMusicStream(const char *fileName)
         drwav *ctxWav = RL_CALLOC(1, sizeof(drwav));
         bool success = drwav_init_file(ctxWav, fileName, NULL);
 
-        music.ctxType = MUSIC_AUDIO_WAV;
-        music.ctxData = ctxWav;
-
         if (success)
         {
+            music.ctxType = MUSIC_AUDIO_WAV;
+            music.ctxData = ctxWav;
             int sampleSize = ctxWav->bitsPerSample;
             if (ctxWav->bitsPerSample == 24) sampleSize = 16;   // Forcing conversion to s16 on UpdateMusicStream()
 
@@ -1347,17 +1346,23 @@ Music LoadMusicStream(const char *fileName)
             music.looping = true;   // Looping enabled by default
             musicLoaded = true;
         }
+        else
+        {
+            drwav_uninit(ctxWav);
+            RL_FREE(ctxWav);
+        }
     }
 #endif
 #if defined(SUPPORT_FILEFORMAT_OGG)
     else if (IsFileExtension(fileName, ".ogg"))
     {
         // Open ogg audio stream
-        music.ctxType = MUSIC_AUDIO_OGG;
-        music.ctxData = stb_vorbis_open_filename(fileName, NULL, NULL);
+        stb_vorbis *ctxOgg = stb_vorbis_open_filename(fileName, NULL, NULL);
 
-        if (music.ctxData != NULL)
+        if (ctxOgg != NULL)
         {
+            music.ctxType = MUSIC_AUDIO_OGG;
+            music.ctxData = ctxOgg;
             stb_vorbis_info info = stb_vorbis_get_info((stb_vorbis *)music.ctxData);  // Get Ogg file info
 
             // OGG bit rate defaults to 16 bit, it's enough for compressed format
@@ -1368,6 +1373,10 @@ Music LoadMusicStream(const char *fileName)
             music.looping = true;   // Looping enabled by default
             musicLoaded = true;
         }
+        else
+        {
+            stb_vorbis_close(ctxOgg);
+        }
     }
 #endif
 #if defined(SUPPORT_FILEFORMAT_MP3)
@@ -1376,27 +1385,30 @@ Music LoadMusicStream(const char *fileName)
         drmp3 *ctxMp3 = RL_CALLOC(1, sizeof(drmp3));
         int result = drmp3_init_file(ctxMp3, fileName, NULL);
 
-        music.ctxType = MUSIC_AUDIO_MP3;
-        music.ctxData = ctxMp3;
-
         if (result > 0)
         {
+            music.ctxType = MUSIC_AUDIO_MP3;
+            music.ctxData = ctxMp3;
             music.stream = LoadAudioStream(ctxMp3->sampleRate, 32, ctxMp3->channels);
             music.frameCount = (unsigned int)drmp3_get_pcm_frame_count(ctxMp3);
             music.looping = true;   // Looping enabled by default
             musicLoaded = true;
         }
+        else
+        {
+            RL_FREE(ctxMp3);
+        }
     }
 #endif
 #if defined(SUPPORT_FILEFORMAT_QOA)
     else if (IsFileExtension(fileName, ".qoa"))
     {
         qoaplay_desc *ctxQoa = qoaplay_open(fileName);
-        music.ctxType = MUSIC_AUDIO_QOA;
-        music.ctxData = ctxQoa;
 
-        if (ctxQoa->file != NULL)
+        if (ctxQoa != NULL)
         {
+            music.ctxType = MUSIC_AUDIO_QOA;
+            music.ctxData = ctxQoa;
             // NOTE: We are loading samples are 32bit float normalized data, so,
             // we configure the output audio stream to also use float 32bit
             music.stream = LoadAudioStream(ctxQoa->info.samplerate, 32, ctxQoa->info.channels);
@@ -1404,23 +1416,27 @@ Music LoadMusicStream(const char *fileName)
             music.looping = true;   // Looping enabled by default
             musicLoaded = true;
         }
+        else{} //No uninit required
     }
 #endif
 #if defined(SUPPORT_FILEFORMAT_FLAC)
     else if (IsFileExtension(fileName, ".flac"))
     {
-        music.ctxType = MUSIC_AUDIO_FLAC;
-        music.ctxData = drflac_open_file(fileName, NULL);
+        drflac *ctxFlac = drflac_open_file(fileName, NULL);
 
-        if (music.ctxData != NULL)
+        if (ctxFlac != NULL)
         {
-            drflac *ctxFlac = (drflac *)music.ctxData;
-
+            music.ctxType = MUSIC_AUDIO_FLAC;
+            music.ctxData = ctxFlac;
             music.stream = LoadAudioStream(ctxFlac->sampleRate, ctxFlac->bitsPerSample, ctxFlac->channels);
             music.frameCount = (unsigned int)ctxFlac->totalPCMFrameCount;
             music.looping = true;   // Looping enabled by default
             musicLoaded = true;
         }
+        else
+        {
+            drflac_free(ctxFlac, NULL);
+        }
     }
 #endif
 #if defined(SUPPORT_FILEFORMAT_XM)
@@ -1429,11 +1445,10 @@ Music LoadMusicStream(const char *fileName)
         jar_xm_context_t *ctxXm = NULL;
         int result = jar_xm_create_context_from_file(&ctxXm, AUDIO.System.device.sampleRate, fileName);
 
-        music.ctxType = MUSIC_MODULE_XM;
-        music.ctxData = ctxXm;
-
         if (result == 0)    // XM AUDIO.System.context created successfully
         {
+            music.ctxType = MUSIC_MODULE_XM;
+            music.ctxData = ctxXm;
             jar_xm_set_max_loop_count(ctxXm, 0);    // Set infinite number of loops
 
             unsigned int bits = 32;
@@ -1447,6 +1462,10 @@ Music LoadMusicStream(const char *fileName)
             jar_xm_reset(ctxXm);    // Make sure we start at the beginning of the song
             musicLoaded = true;
         }
+        else 
+        {
+            jar_xm_free_context(ctxXm);
+        }
     }
 #endif
 #if defined(SUPPORT_FILEFORMAT_MOD)
@@ -1456,48 +1475,27 @@ Music LoadMusicStream(const char *fileName)
         jar_mod_init(ctxMod);
         int result = jar_mod_load_file(ctxMod, fileName);
 
-        music.ctxType = MUSIC_MODULE_MOD;
-        music.ctxData = ctxMod;
-
         if (result > 0)
         {
+            music.ctxType = MUSIC_MODULE_MOD;
+            music.ctxData = ctxMod;
             // NOTE: Only stereo is supported for MOD
             music.stream = LoadAudioStream(AUDIO.System.device.sampleRate, 16, AUDIO_DEVICE_CHANNELS);
             music.frameCount = (unsigned int)jar_mod_max_samples(ctxMod);    // NOTE: Always 2 channels (stereo)
             music.looping = true;   // Looping enabled by default
             musicLoaded = true;
         }
+        else
+        {
+            jar_mod_unload(ctxMod);
+            RL_FREE(ctxMod);
+        }
     }
 #endif
     else TRACELOG(LOG_WARNING, "STREAM: [%s] File format not supported", fileName);
 
     if (!musicLoaded)
     {
-        if (false) { }
-    #if defined(SUPPORT_FILEFORMAT_WAV)
-        else if (music.ctxType == MUSIC_AUDIO_WAV) drwav_uninit((drwav *)music.ctxData);
-    #endif
-    #if defined(SUPPORT_FILEFORMAT_OGG)
-        else if (music.ctxType == MUSIC_AUDIO_OGG) stb_vorbis_close((stb_vorbis *)music.ctxData);
-    #endif
-    #if defined(SUPPORT_FILEFORMAT_MP3)
-        else if (music.ctxType == MUSIC_AUDIO_MP3) { drmp3_uninit((drmp3 *)music.ctxData); RL_FREE(music.ctxData); }
-    #endif
-    #if defined(SUPPORT_FILEFORMAT_QOA)
-        else if (music.ctxType == MUSIC_AUDIO_QOA) qoaplay_close((qoaplay_desc *)music.ctxData);
-    #endif
-    #if defined(SUPPORT_FILEFORMAT_FLAC)
-        else if (music.ctxType == MUSIC_AUDIO_FLAC) drflac_free((drflac *)music.ctxData, NULL);
-    #endif
-    #if defined(SUPPORT_FILEFORMAT_XM)
-        else if (music.ctxType == MUSIC_MODULE_XM) jar_xm_free_context((jar_xm_context_t *)music.ctxData);
-    #endif
-    #if defined(SUPPORT_FILEFORMAT_MOD)
-        else if (music.ctxType == MUSIC_MODULE_MOD) { jar_mod_unload((jar_mod_context_t *)music.ctxData); RL_FREE(music.ctxData); }
-    #endif
-
-        music.ctxData = NULL;
-        music.ctxType = MUSIC_AUDIO_NONE;
         TRACELOG(LOG_WARNING, "FILEIO: [%s] Music file could not be opened", fileName);
     }
     else
@@ -1528,11 +1526,10 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
 
         bool success = drwav_init_memory(ctxWav, (const void *)data, dataSize, NULL);
 
-        music.ctxType = MUSIC_AUDIO_WAV;
-        music.ctxData = ctxWav;
-
         if (success)
         {
+            music.ctxType = MUSIC_AUDIO_WAV;
+            music.ctxData = ctxWav;
             int sampleSize = ctxWav->bitsPerSample;
             if (ctxWav->bitsPerSample == 24) sampleSize = 16;   // Forcing conversion to s16 on UpdateMusicStream()
 
@@ -1541,18 +1538,22 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
             music.looping = true;   // Looping enabled by default
             musicLoaded = true;
         }
+        else {
+            drwav_uninit(ctxWav);
+            RL_FREE(ctxWav);
+        }
     }
 #endif
 #if defined(SUPPORT_FILEFORMAT_OGG)
     else if ((strcmp(fileType, ".ogg") == 0) || (strcmp(fileType, ".OGG") == 0))
     {
         // Open ogg audio stream
-        music.ctxType = MUSIC_AUDIO_OGG;
-        //music.ctxData = stb_vorbis_open_filename(fileName, NULL, NULL);
-        music.ctxData = stb_vorbis_open_memory((const unsigned char *)data, dataSize, NULL, NULL);
+        stb_vorbis* ctxOgg = stb_vorbis_open_memory((const unsigned char*)data, dataSize, NULL, NULL);
 
-        if (music.ctxData != NULL)
+        if (ctxOgg != NULL)
         {
+            music.ctxType = MUSIC_AUDIO_OGG;
+            music.ctxData = ctxOgg;
             stb_vorbis_info info = stb_vorbis_get_info((stb_vorbis *)music.ctxData);  // Get Ogg file info
 
             // OGG bit rate defaults to 16 bit, it's enough for compressed format
@@ -1563,6 +1564,10 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
             music.looping = true;   // Looping enabled by default
             musicLoaded = true;
         }
+        else 
+        {
+            stb_vorbis_close(ctxOgg);
+        }
     }
 #endif
 #if defined(SUPPORT_FILEFORMAT_MP3)
@@ -1571,27 +1576,35 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
         drmp3 *ctxMp3 = RL_CALLOC(1, sizeof(drmp3));
         int success = drmp3_init_memory(ctxMp3, (const void*)data, dataSize, NULL);
 
-        music.ctxType = MUSIC_AUDIO_MP3;
-        music.ctxData = ctxMp3;
-
         if (success)
         {
+            music.ctxType = MUSIC_AUDIO_MP3;
+            music.ctxData = ctxMp3;
             music.stream = LoadAudioStream(ctxMp3->sampleRate, 32, ctxMp3->channels);
             music.frameCount = (unsigned int)drmp3_get_pcm_frame_count(ctxMp3);
             music.looping = true;   // Looping enabled by default
             musicLoaded = true;
         }
+        else
+        {
+            drmp3_uninit(ctxMp3);
+            RL_FREE(ctxMp3);
+        }
     }
 #endif
 #if defined(SUPPORT_FILEFORMAT_QOA)
     else if ((strcmp(fileType, ".qoa") == 0) || (strcmp(fileType, ".QOA") == 0))
     {
-        qoaplay_desc *ctxQoa = qoaplay_open_memory(data, dataSize);
-        music.ctxType = MUSIC_AUDIO_QOA;
-        music.ctxData = ctxQoa;
+        qoaplay_desc *ctxQoa = NULL;
+        if ((data != NULL) && (dataSize > 0))
+        {
+            ctxQoa = qoaplay_open_memory(data, dataSize);
+        }
 
-        if ((ctxQoa->file_data != NULL) && (ctxQoa->file_data_size != 0))
+        if (ctxQoa != NULL)
         {
+            music.ctxType = MUSIC_AUDIO_QOA;
+            music.ctxData = ctxQoa;
             // NOTE: We are loading samples are 32bit float normalized data, so,
             // we configure the output audio stream to also use float 32bit
             music.stream = LoadAudioStream(ctxQoa->info.samplerate, 32, ctxQoa->info.channels);
@@ -1599,23 +1612,27 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
             music.looping = true;   // Looping enabled by default
             musicLoaded = true;
         }
+        else{} //No uninit required
     }
 #endif
 #if defined(SUPPORT_FILEFORMAT_FLAC)
     else if ((strcmp(fileType, ".flac") == 0) || (strcmp(fileType, ".FLAC") == 0))
     {
-        music.ctxType = MUSIC_AUDIO_FLAC;
-        music.ctxData = drflac_open_memory((const void*)data, dataSize, NULL);
+        drflac *ctxFlac = drflac_open_memory((const void*)data, dataSize, NULL);
 
-        if (music.ctxData != NULL)
+        if (ctxFlac != NULL)
         {
-            drflac *ctxFlac = (drflac *)music.ctxData;
-
+            music.ctxType = MUSIC_AUDIO_FLAC;
+            music.ctxData = ctxFlac;
             music.stream = LoadAudioStream(ctxFlac->sampleRate, ctxFlac->bitsPerSample, ctxFlac->channels);
             music.frameCount = (unsigned int)ctxFlac->totalPCMFrameCount;
             music.looping = true;   // Looping enabled by default
             musicLoaded = true;
         }
+        else
+        {
+            drflac_free(ctxFlac, NULL);
+        }
     }
 #endif
 #if defined(SUPPORT_FILEFORMAT_XM)
@@ -1626,6 +1643,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
         if (result == 0)    // XM AUDIO.System.context created successfully
         {
             music.ctxType = MUSIC_MODULE_XM;
+            music.ctxData = ctxXm;
             jar_xm_set_max_loop_count(ctxXm, 0);    // Set infinite number of loops
 
             unsigned int bits = 32;
@@ -1638,9 +1656,12 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
             music.looping = true;   // Looping enabled by default
             jar_xm_reset(ctxXm);    // Make sure we start at the beginning of the song
 
-            music.ctxData = ctxXm;
             musicLoaded = true;
         }
+        else
+        {
+            jar_xm_free_context(ctxXm);
+        }
     }
 #endif
 #if defined(SUPPORT_FILEFORMAT_MOD)
@@ -1667,15 +1688,18 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
         if (result > 0)
         {
             music.ctxType = MUSIC_MODULE_MOD;
+            music.ctxData = ctxMod;
 
             // NOTE: Only stereo is supported for MOD
             music.stream = LoadAudioStream(AUDIO.System.device.sampleRate, 16, 2);
             music.frameCount = (unsigned int)jar_mod_max_samples(ctxMod);    // NOTE: Always 2 channels (stereo)
             music.looping = true;   // Looping enabled by default
             musicLoaded = true;
-
-            music.ctxData = ctxMod;
-            musicLoaded = true;
+        }
+        else
+        {
+            jar_mod_unload(ctxMod);
+            RL_FREE(ctxMod);
         }
     }
 #endif
@@ -1683,31 +1707,6 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
 
     if (!musicLoaded)
     {
-        if (false) { }
-#if defined(SUPPORT_FILEFORMAT_WAV)
-        else if (music.ctxType == MUSIC_AUDIO_WAV) drwav_uninit((drwav *)music.ctxData);
-#endif
-#if defined(SUPPORT_FILEFORMAT_OGG)
-        else if (music.ctxType == MUSIC_AUDIO_OGG) stb_vorbis_close((stb_vorbis *)music.ctxData);
-#endif
-#if defined(SUPPORT_FILEFORMAT_MP3)
-        else if (music.ctxType == MUSIC_AUDIO_MP3) { drmp3_uninit((drmp3 *)music.ctxData); RL_FREE(music.ctxData); }
-#endif
-#if defined(SUPPORT_FILEFORMAT_QOA)
-        else if (music.ctxType == MUSIC_AUDIO_QOA) qoaplay_close((qoaplay_desc *)music.ctxData);
-#endif
-#if defined(SUPPORT_FILEFORMAT_FLAC)
-        else if (music.ctxType == MUSIC_AUDIO_FLAC) drflac_free((drflac *)music.ctxData, NULL);
-#endif
-#if defined(SUPPORT_FILEFORMAT_XM)
-        else if (music.ctxType == MUSIC_MODULE_XM) jar_xm_free_context((jar_xm_context_t *)music.ctxData);
-#endif
-#if defined(SUPPORT_FILEFORMAT_MOD)
-        else if (music.ctxType == MUSIC_MODULE_MOD) { jar_mod_unload((jar_mod_context_t *)music.ctxData); RL_FREE(music.ctxData); }
-#endif
-
-        music.ctxData = NULL;
-        music.ctxType = MUSIC_AUDIO_NONE;
         TRACELOG(LOG_WARNING, "FILEIO: Music data could not be loaded");
     }
     else