diff --git a/src/config.h b/src/config.h index 71908b0c0..ce943901d 100644 --- a/src/config.h +++ b/src/config.h @@ -187,7 +187,7 @@ #define SUPPORT_FILEFORMAT_WAV 1 #define SUPPORT_FILEFORMAT_OGG 1 #define SUPPORT_FILEFORMAT_XM 1 -//#define SUPPORT_FILEFORMAT_MOD 1 +#define SUPPORT_FILEFORMAT_MOD 1 #define SUPPORT_FILEFORMAT_MP3 1 //#define SUPPORT_FILEFORMAT_FLAC 1 diff --git a/src/raudio.c b/src/raudio.c index 6a122720d..0a0474e1a 100644 --- a/src/raudio.c +++ b/src/raudio.c @@ -1297,6 +1297,103 @@ Music LoadMusicStream(const char *fileName) return music; } +// extension including period ".mod" +Music LoadMusicStreamFromMemory(const char *fileType, unsigned char* data, int dataSize) +{ + Music music = { 0 }; + bool musicLoaded = false; + + char fileExtLower[16] = { 0 }; + strcpy(fileExtLower, TextToLower(fileType)); + + if (false) { } +#if defined(SUPPORT_FILEFORMAT_XM) + if (TextIsEqual(fileExtLower, ".xm")) + { + jar_xm_context_t *ctxXm = NULL; + int result = jar_xm_create_context_safe(&ctxXm, data, dataSize, 48000); + if (result == 0) // XM AUDIO.System.context created successfully + { + music.ctxType = MUSIC_MODULE_XM; + jar_xm_set_max_loop_count(ctxXm, 0); // Set infinite number of loops + + // NOTE: Only stereo is supported for XM + music.stream = InitAudioStream(48000, 16, 2); + music.sampleCount = (unsigned int)jar_xm_get_remaining_samples(ctxXm)*2; // 2 channels + 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; + } + } +#endif +#if defined(SUPPORT_FILEFORMAT_MOD) + else if (TextIsEqual(fileExtLower, ".mod")) + { + jar_mod_context_t *ctxMod = RL_MALLOC(sizeof(jar_mod_context_t)); + int result = 0; + + jar_mod_init(ctxMod); + + // copy data to allocated memory for default UnloadMusicStream + unsigned char *newData = RL_MALLOC(dataSize); + int it = dataSize / sizeof(unsigned char); + for (int i = 0; i < it; i++){ + newData[i] = data[i]; + } + + // Memory loaded version for jar_mod_load_file() + if (dataSize && dataSize < 32*1024*1024) + { + ctxMod->modfilesize = dataSize; + ctxMod->modfile = newData; + if(jar_mod_load(ctxMod, (void*)ctxMod->modfile, dataSize)) result = dataSize; + } + + if (result > 0) + { + music.ctxType = MUSIC_MODULE_MOD; + + // NOTE: Only stereo is supported for MOD + music.stream = InitAudioStream(48000, 16, 2); + music.sampleCount = (unsigned int)jar_mod_max_samples(ctxMod)*2; // 2 channels + music.looping = true; // Looping enabled by default + musicLoaded = true; + + music.ctxData = ctxMod; + musicLoaded = true; + } + } +#endif + else TRACELOG(LOG_WARNING, "STREAM: [%s] Fileformat not supported", fileType); + + if (!musicLoaded) + { + if (false) { } + #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; + TRACELOG(LOG_WARNING, "FILEIO: [%s] Music memory could not be opened", fileType); + } + else + { + // Show some music stream info + TRACELOG(LOG_INFO, "FILEIO: [%s] Music memory successfully loaded:", fileType); + TRACELOG(LOG_INFO, " > Total samples: %i", music.sampleCount); + TRACELOG(LOG_INFO, " > Sample rate: %i Hz", music.stream.sampleRate); + TRACELOG(LOG_INFO, " > Sample size: %i bits", music.stream.sampleSize); + TRACELOG(LOG_INFO, " > Channels: %i (%s)", music.stream.channels, (music.stream.channels == 1)? "Mono" : (music.stream.channels == 2)? "Stereo" : "Multi"); + } + + return music; +} + // Unload music stream void UnloadMusicStream(Music music) { diff --git a/src/raudio.h b/src/raudio.h index 8178deec8..cf8b767a0 100644 --- a/src/raudio.h +++ b/src/raudio.h @@ -164,6 +164,7 @@ float *GetWaveData(Wave wave); // Get samples d // Music management functions Music LoadMusicStream(const char *fileName); // Load music stream from file +Music LoadMusicStreamFromMemory(const char *fileType, unsigned char* data, int dataSize); // Load module music from data void UnloadMusicStream(Music music); // Unload music stream void PlayMusicStream(Music music); // Start music playing void UpdateMusicStream(Music music); // Updates buffers for music streaming diff --git a/src/raylib.h b/src/raylib.h index 15df914b0..2bd62ae19 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1495,6 +1495,7 @@ RLAPI void UnloadWaveSamples(float *samples); // Unload // Music management functions RLAPI Music LoadMusicStream(const char *fileName); // Load music stream from file +RLAPI Music LoadMusicStreamFromMemory(const char *fileType, unsigned char* data, int dataSize); // Load module music from data RLAPI void UnloadMusicStream(Music music); // Unload music stream RLAPI void PlayMusicStream(Music music); // Start music playing RLAPI void UpdateMusicStream(Music music); // Updates buffers for music streaming