Просмотр исходного кода

[raudio] Use miniaudio decoder for MP3/WAV/FLAC music streams

pull/5537/head
torph 2 недель назад
Родитель
Сommit
12e18a22ad
Не удалось извлечь подпись
1 измененных файлов: 77 добавлений и 211 удалений
  1. +77
    -211
      src/raudio.c

+ 77
- 211
src/raudio.c Просмотреть файл

@ -323,10 +323,8 @@ typedef enum {
// in charge of reading the different file types
typedef enum {
MUSIC_AUDIO_NONE = 0, // No audio context loaded
MUSIC_AUDIO_WAV, // WAV audio context
MUSIC_AUDIO_DECODER, // Something abstracted by a miniaudio decoder
MUSIC_AUDIO_OGG, // OGG audio context
MUSIC_AUDIO_FLAC, // FLAC audio context
MUSIC_AUDIO_MP3, // MP3 audio context
MUSIC_AUDIO_QOA, // QOA audio context
MUSIC_MODULE_XM, // XM module audio context
MUSIC_MODULE_MOD // MOD module audio context
@ -1323,31 +1321,43 @@ Music LoadMusicStream(const char *fileName)
Music music = { 0 };
bool musicLoaded = false;
if (false) { }
// Whether the input file can be decoded with miniaudio
bool decodable = false;
#if defined(SUPPORT_FILEFORMAT_WAV)
else if (IsFileExtension(fileName, ".wav"))
{
drwav *ctxWav = (drwav *)RL_CALLOC(1, sizeof(drwav));
bool success = drwav_init_file(ctxWav, fileName, NULL);
decodable |= IsFileExtension(fileName, ".wav");
#endif
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()
#if defined(SUPPORT_FILEFORMAT_MP3)
decodable |= IsFileExtension(fileName, ".mp3");
#endif
music.stream = LoadAudioStream(ctxWav->sampleRate, sampleSize, ctxWav->channels);
music.frameCount = (unsigned int)ctxWav->totalPCMFrameCount;
music.looping = true; // Looping enabled by default
musicLoaded = true;
}
else
{
RL_FREE(ctxWav);
#if defined(SUPPORT_FILEFORMAT_FLAC)
decodable |= IsFileExtension(fileName, ".flac");
#endif
if (decodable) {
ma_decoder *ctxDecoder = (ma_decoder *)RL_CALLOC(1, sizeof(ma_decoder));
const ma_uint32 sampleRate = 48000;
const ma_uint32 channels = 2;
ma_decoder_config cfg = ma_decoder_config_init(ma_format_s16, channels, sampleRate);
ma_result ma_res = ma_decoder_init_file(fileName, &cfg, ctxDecoder);
if (ma_res != MA_SUCCESS) {
TRACELOG(LOG_WARNING, "Failed to setup audio decoder!\n");
RL_FREE(ctxDecoder);
return music;
}
music.ctxType = MUSIC_AUDIO_DECODER;
music.ctxData = ctxDecoder;
music.stream = LoadAudioStream(sampleRate, 16, channels);
ma_uint64 frameCount = 0;
ma_decoder_get_length_in_pcm_frames(ctxDecoder, &frameCount);
music.frameCount = frameCount;
music.looping = true;
musicLoaded = true;
}
#endif
#if defined(SUPPORT_FILEFORMAT_OGG)
else if (IsFileExtension(fileName, ".ogg"))
{
@ -1374,27 +1384,6 @@ Music LoadMusicStream(const char *fileName)
}
}
#endif
#if defined(SUPPORT_FILEFORMAT_MP3)
else if (IsFileExtension(fileName, ".mp3"))
{
drmp3 *ctxMp3 = (drmp3 *)RL_CALLOC(1, sizeof(drmp3));
int result = drmp3_init_file(ctxMp3, fileName, NULL);
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"))
{
@ -1414,28 +1403,6 @@ Music LoadMusicStream(const char *fileName)
else{} //No uninit required
}
#endif
#if defined(SUPPORT_FILEFORMAT_FLAC)
else if (IsFileExtension(fileName, ".flac"))
{
drflac *ctxFlac = drflac_open_file(fileName, NULL);
if (ctxFlac != NULL)
{
music.ctxType = MUSIC_AUDIO_FLAC;
music.ctxData = ctxFlac;
int sampleSize = ctxFlac->bitsPerSample;
if (ctxFlac->bitsPerSample == 24) sampleSize = 16; // Forcing conversion to s16 on UpdateMusicStream()
music.stream = LoadAudioStream(ctxFlac->sampleRate, sampleSize, 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)
else if (IsFileExtension(fileName, ".xm"))
{
@ -1515,33 +1482,43 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
Music music = { 0 };
bool musicLoaded = false;
if (false) { }
// Whether the input file can be decoded with miniaudio
bool decodable = false;
#if defined(SUPPORT_FILEFORMAT_WAV)
else if ((strcmp(fileType, ".wav") == 0) || (strcmp(fileType, ".WAV") == 0))
{
drwav *ctxWav = (drwav *)RL_CALLOC(1, sizeof(drwav));
decodable |= (strcmp(fileType, ".wav") == 0) || (strcmp(fileType, ".WAV") == 0);
#endif
#if defined(SUPPORT_FILEFORMAT_MP3)
decodable |= (strcmp(fileType, ".mp3") == 0) || (strcmp(fileType, ".MP3") == 0);
#endif
bool success = drwav_init_memory(ctxWav, (const void *)data, dataSize, NULL);
#if defined(SUPPORT_FILEFORMAT_FLAC)
decodable |= (strcmp(fileType, ".flac") == 0) || (strcmp(fileType, ".FLAC") == 0);
#endif
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()
music.stream = LoadAudioStream(ctxWav->sampleRate, sampleSize, ctxWav->channels);
music.frameCount = (unsigned int)ctxWav->totalPCMFrameCount;
music.looping = true; // Looping enabled by default
musicLoaded = true;
}
else
{
drwav_uninit(ctxWav);
RL_FREE(ctxWav);
if (decodable) {
ma_decoder *ctxDecoder = (ma_decoder *)RL_CALLOC(1, sizeof(ma_decoder));
const ma_uint32 sampleRate = 48000;
const ma_uint32 channels = 2;
ma_decoder_config cfg = ma_decoder_config_init(ma_format_s16, channels, sampleRate);
ma_result ma_res = ma_decoder_init_memory(data, dataSize, &cfg, ctxDecoder);
if (ma_res != MA_SUCCESS) {
TRACELOG(LOG_WARNING, "Failed to setup audio decoder!\n");
RL_FREE(ctxDecoder);
return music;
}
music.ctxType = MUSIC_AUDIO_DECODER;
music.ctxData = ctxDecoder;
music.stream = LoadAudioStream(sampleRate, 16, channels);
ma_uint64 frameCount = 0;
ma_decoder_get_length_in_pcm_frames(ctxDecoder, &frameCount);
music.frameCount = frameCount;
music.looping = true;
musicLoaded = true;
}
#endif
#if defined(SUPPORT_FILEFORMAT_OGG)
else if ((strcmp(fileType, ".ogg") == 0) || (strcmp(fileType, ".OGG") == 0))
{
@ -1568,28 +1545,6 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
}
}
#endif
#if defined(SUPPORT_FILEFORMAT_MP3)
else if ((strcmp(fileType, ".mp3") == 0) || (strcmp(fileType, ".MP3") == 0))
{
drmp3 *ctxMp3 = (drmp3 *)RL_CALLOC(1, sizeof(drmp3));
int success = drmp3_init_memory(ctxMp3, (const void *)data, dataSize, NULL);
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))
{
@ -1613,28 +1568,6 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
else{} //No uninit required
}
#endif
#if defined(SUPPORT_FILEFORMAT_FLAC)
else if ((strcmp(fileType, ".flac") == 0) || (strcmp(fileType, ".FLAC") == 0))
{
drflac *ctxFlac = drflac_open_memory((const void *)data, dataSize, NULL);
if (ctxFlac != NULL)
{
music.ctxType = MUSIC_AUDIO_FLAC;
music.ctxData = ctxFlac;
int sampleSize = ctxFlac->bitsPerSample;
if (ctxFlac->bitsPerSample == 24) sampleSize = 16; // Forcing conversion to s16 on UpdateMusicStream()
music.stream = LoadAudioStream(ctxFlac->sampleRate, sampleSize, 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)
else if ((strcmp(fileType, ".xm") == 0) || (strcmp(fileType, ".XM") == 0))
{
@ -1739,22 +1672,15 @@ void UnloadMusicStream(Music music)
if (music.ctxData != NULL)
{
if (false) { }
#if defined(SUPPORT_FILEFORMAT_WAV)
else if (music.ctxType == MUSIC_AUDIO_WAV) drwav_uninit((drwav *)music.ctxData);
#endif
if (music.ctxType == MUSIC_AUDIO_DECODER) {
ma_decoder_uninit((ma_decoder *)music.ctxData);
}
#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_close((drflac *)music.ctxData); 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
@ -1789,21 +1715,13 @@ void StopMusicStream(Music music)
switch (music.ctxType)
{
#if defined(SUPPORT_FILEFORMAT_WAV)
case MUSIC_AUDIO_WAV: drwav_seek_to_first_pcm_frame((drwav *)music.ctxData); break;
#endif
case MUSIC_AUDIO_DECODER: ma_decoder_seek_to_pcm_frame((ma_decoder *)music.ctxData, 0); break;
#if defined(SUPPORT_FILEFORMAT_OGG)
case MUSIC_AUDIO_OGG: stb_vorbis_seek_start((stb_vorbis *)music.ctxData); break;
#endif
#if defined(SUPPORT_FILEFORMAT_MP3)
case MUSIC_AUDIO_MP3: drmp3_seek_to_start_of_stream((drmp3 *)music.ctxData); break;
#endif
#if defined(SUPPORT_FILEFORMAT_QOA)
case MUSIC_AUDIO_QOA: qoaplay_rewind((qoaplay_desc *)music.ctxData); break;
#endif
#if defined(SUPPORT_FILEFORMAT_FLAC)
case MUSIC_AUDIO_FLAC: drflac__seek_to_first_frame((drflac *)music.ctxData); break;
#endif
#if defined(SUPPORT_FILEFORMAT_XM)
case MUSIC_MODULE_XM: jar_xm_reset((jar_xm_context_t *)music.ctxData); break;
#endif
@ -1824,15 +1742,10 @@ void SeekMusicStream(Music music, float position)
switch (music.ctxType)
{
#if defined(SUPPORT_FILEFORMAT_WAV)
case MUSIC_AUDIO_WAV: drwav_seek_to_pcm_frame((drwav *)music.ctxData, positionInFrames); break;
#endif
case MUSIC_AUDIO_DECODER: ma_decoder_seek_to_pcm_frame((ma_decoder *)music.ctxData, positionInFrames); break;
#if defined(SUPPORT_FILEFORMAT_OGG)
case MUSIC_AUDIO_OGG: stb_vorbis_seek_frame((stb_vorbis *)music.ctxData, positionInFrames); break;
#endif
#if defined(SUPPORT_FILEFORMAT_MP3)
case MUSIC_AUDIO_MP3: drmp3_seek_to_pcm_frame((drmp3 *)music.ctxData, positionInFrames); break;
#endif
#if defined(SUPPORT_FILEFORMAT_QOA)
case MUSIC_AUDIO_QOA:
{
@ -1842,9 +1755,6 @@ void SeekMusicStream(Music music, float position)
// We need to compute QOA frame number and update positionInFrames
positionInFrames = ((qoaplay_desc *)music.ctxData)->sample_position;
} break;
#endif
#if defined(SUPPORT_FILEFORMAT_FLAC)
case MUSIC_AUDIO_FLAC: drflac_seek_to_pcm_frame((drflac *)music.ctxData, positionInFrames); break;
#endif
default: break;
}
@ -1907,33 +1817,15 @@ void UpdateMusicStream(Music music)
switch (music.ctxType)
{
#if defined(SUPPORT_FILEFORMAT_WAV)
case MUSIC_AUDIO_WAV:
case MUSIC_AUDIO_DECODER:
{
if (music.stream.sampleSize == 16)
{
while (true)
{
int frameCountRead = (int)drwav_read_pcm_frames_s16((drwav *)music.ctxData, frameCountStillNeeded, (short *)((char *)AUDIO.System.pcmBuffer + frameCountReadTotal*frameSize));
frameCountReadTotal += frameCountRead;
frameCountStillNeeded -= frameCountRead;
if (frameCountStillNeeded == 0) break;
else drwav_seek_to_first_pcm_frame((drwav *)music.ctxData);
}
}
else if (music.stream.sampleSize == 32)
{
while (true)
{
int frameCountRead = (int)drwav_read_pcm_frames_f32((drwav *)music.ctxData, frameCountStillNeeded, (float *)((char *)AUDIO.System.pcmBuffer + frameCountReadTotal*frameSize));
frameCountReadTotal += frameCountRead;
frameCountStillNeeded -= frameCountRead;
if (frameCountStillNeeded == 0) break;
else drwav_seek_to_first_pcm_frame((drwav *)music.ctxData);
}
}
} break;
#endif
ma_uint64 frameCountRead = 0;
ma_decoder_read_pcm_frames((ma_decoder *)music.ctxData, (short *)((char *)AUDIO.System.pcmBuffer + frameCountReadTotal*frameSize), frameCountStillNeeded, &frameCountRead);
frameCountReadTotal += frameCountRead;
frameCountStillNeeded -= frameCountRead;
if (frameCountStillNeeded == 0) break;
else ma_decoder_seek_to_pcm_frame((ma_decoder *)music.ctxData, 0);
}
#if defined(SUPPORT_FILEFORMAT_OGG)
case MUSIC_AUDIO_OGG:
{
@ -1947,19 +1839,6 @@ void UpdateMusicStream(Music music)
}
} break;
#endif
#if defined(SUPPORT_FILEFORMAT_MP3)
case MUSIC_AUDIO_MP3:
{
while (true)
{
int frameCountRead = (int)drmp3_read_pcm_frames_f32((drmp3 *)music.ctxData, frameCountStillNeeded, (float *)((char *)AUDIO.System.pcmBuffer + frameCountReadTotal*frameSize));
frameCountReadTotal += frameCountRead;
frameCountStillNeeded -= frameCountRead;
if (frameCountStillNeeded == 0) break;
else drmp3_seek_to_start_of_stream((drmp3 *)music.ctxData);
}
} break;
#endif
#if defined(SUPPORT_FILEFORMAT_QOA)
case MUSIC_AUDIO_QOA:
{
@ -1977,19 +1856,6 @@ void UpdateMusicStream(Music music)
*/
} break;
#endif
#if defined(SUPPORT_FILEFORMAT_FLAC)
case MUSIC_AUDIO_FLAC:
{
while (true)
{
int frameCountRead = (int)drflac_read_pcm_frames_s16((drflac *)music.ctxData, frameCountStillNeeded, (short *)((char *)AUDIO.System.pcmBuffer + frameCountReadTotal*frameSize));
frameCountReadTotal += frameCountRead;
frameCountStillNeeded -= frameCountRead;
if (frameCountStillNeeded == 0) break;
else drflac__seek_to_first_frame((drflac *)music.ctxData);
}
} break;
#endif
#if defined(SUPPORT_FILEFORMAT_XM)
case MUSIC_MODULE_XM:
{

Загрузка…
Отмена
Сохранить