|
|
@ -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) |
|
|
|
{ |
|
|
|