/* MUS_MOD can't be auto-detected. If no other format was detected, MOD is * assumed and MUS_MOD will be returned, meaning that the format might not * actually be MOD-based. * * Returns MUS_NONE in case of errors. */ Mix_MusicType detect_music_type(SDL_RWops *rw) { Uint8 magic[5]; Uint8 moremagic[9]; int start = SDL_RWtell(rw); if (SDL_RWread(rw, magic, 1, 4) != 4 || SDL_RWread(rw, moremagic, 1, 8) != 8 ) { printf("Couldn't read from RWops\n"); return MUS_NONE; } SDL_RWseek(rw, start, RW_SEEK_SET); magic[4]='\0'; moremagic[8] = '\0'; /* WAVE files have the magic four bytes "RIFF" AIFF files have the magic 12 bytes "FORM" XXXX "AIFF" */ if (((strcmp((char *)magic, "RIFF") == 0) && (strcmp((char *)(moremagic+4), "WAVE") == 0)) || (strcmp((char *)magic, "FORM") == 0)) { printf("Detected WAV from RW\n"); return MUS_WAV; } /* Ogg Vorbis files have the magic four bytes "OggS" */ if (strcmp((char *)magic, "OggS") == 0) { printf("Detected OGG from RW\n"); return MUS_OGG; } /* FLAC files have the magic four bytes "fLaC" */ if (strcmp((char *)magic, "fLaC") == 0) { printf("Detected FLAC from RW\n"); return MUS_FLAC; } /* MIDI files have the magic four bytes "MThd" */ if (strcmp((char *)magic, "MThd") == 0) { printf("Detected MIDI from RW\n"); return MUS_MID; } if (detect_mp3(magic)) { printf("Detected MP3 from RW\n"); return MUS_MP3; } /* Assume MOD format. * * Apparently there is no way to check if the file is really a MOD, * or there are too many formats supported by MikMod/ModPlug, or * MikMod/ModPlug does this check by itself. */ return MUS_MOD; }
/* Load a wave file */ Mix_Chunk *Mix_LoadWAV_RW(SDL_RWops *src, int freesrc) { Uint32 magic; Mix_Chunk *chunk; SDL_AudioSpec wavespec, *loaded; SDL_AudioCVT wavecvt; int samplesize; /* rcg06012001 Make sure src is valid */ if ( ! src ) { SDL_SetError("Mix_LoadWAV_RW with NULL src"); return(NULL); } /* Make sure audio has been opened */ if ( ! audio_opened ) { SDL_SetError("Audio device hasn't been opened"); if ( freesrc ) { SDL_RWclose(src); } return(NULL); } /* Allocate the chunk memory */ chunk = (Mix_Chunk *)SDL_malloc(sizeof(Mix_Chunk)); if ( chunk == NULL ) { SDL_SetError("Out of memory"); if ( freesrc ) { SDL_RWclose(src); } return(NULL); } /* Find out what kind of audio file this is */ magic = SDL_ReadLE32(src); /* Seek backwards for compatibility with older loaders */ SDL_RWseek(src, -(int)sizeof(Uint32), RW_SEEK_CUR); switch (magic) { case WAVE: case RIFF: loaded = SDL_LoadWAV_RW(src, freesrc, &wavespec, (Uint8 **)&chunk->abuf, &chunk->alen); break; case FORM: loaded = Mix_LoadAIFF_RW(src, freesrc, &wavespec, (Uint8 **)&chunk->abuf, &chunk->alen); break; #ifdef OGG_MUSIC case OGGS: loaded = Mix_LoadOGG_RW(src, freesrc, &wavespec, (Uint8 **)&chunk->abuf, &chunk->alen); break; #endif #ifdef FLAC_MUSIC case FLAC: loaded = Mix_LoadFLAC_RW(src, freesrc, &wavespec, (Uint8 **)&chunk->abuf, &chunk->alen); break; #endif case CREA: loaded = Mix_LoadVOC_RW(src, freesrc, &wavespec, (Uint8 **)&chunk->abuf, &chunk->alen); break; default: #if defined(MP3_MUSIC) || defined(MP3_MAD_MUSIC) if (detect_mp3((Uint8*)&magic)) { /* note: send a copy of the mixer spec */ wavespec = mixer; loaded = Mix_LoadMP3_RW(src, freesrc, &wavespec, (Uint8 **)&chunk->abuf, &chunk->alen); break; } #endif SDL_SetError("Unrecognized sound file type"); if ( freesrc ) { SDL_RWclose(src); } loaded = NULL; break; } if ( !loaded ) { /* The individual loaders have closed src if needed */ SDL_free(chunk); return(NULL); } #if 0 PrintFormat("Audio device", &mixer); PrintFormat("-- Wave file", &wavespec); #endif /* Build the audio converter and create conversion buffers */ if ( wavespec.format != mixer.format || wavespec.channels != mixer.channels || wavespec.freq != mixer.freq ) { if ( SDL_BuildAudioCVT(&wavecvt, wavespec.format, wavespec.channels, wavespec.freq, mixer.format, mixer.channels, mixer.freq) < 0 ) { SDL_free(chunk->abuf); SDL_free(chunk); return(NULL); } samplesize = ((wavespec.format & 0xFF)/8)*wavespec.channels; wavecvt.len = chunk->alen & ~(samplesize-1); wavecvt.buf = (Uint8 *)SDL_calloc(1, wavecvt.len*wavecvt.len_mult); if ( wavecvt.buf == NULL ) { SDL_SetError("Out of memory"); SDL_free(chunk->abuf); SDL_free(chunk); return(NULL); } SDL_memcpy(wavecvt.buf, chunk->abuf, chunk->alen); SDL_free(chunk->abuf); /* Run the audio converter */ if ( SDL_ConvertAudio(&wavecvt) < 0 ) { SDL_free(wavecvt.buf); SDL_free(chunk); return(NULL); } chunk->abuf = wavecvt.buf; chunk->alen = wavecvt.len_cvt; } chunk->allocated = 1; chunk->volume = MIX_MAX_VOLUME; return(chunk); }
static int lua_Mix_Load(State & state){ Stack * stack = state.stack; if (stack->is<LUA_TSTRING>(1)){ AudioSpec * interfaceAS = state.getInterface<AudioSpec>("LuaSDL_AudioSpec"); SDL_AudioSpec * inputSpec = interfaceAS->get(2); if (inputSpec){ const std::string filename = stack->toLString(1); SDL_RWops * src = SDL_RWFromFile(filename.c_str(), "rb"); if (!src){ state.error("Couldn't open audio file: %s\n", filename.c_str()); } Uint32 magic; SDL_AudioSpec wavespec, *audiospec = nullptr; Uint8 *abuf = nullptr; Uint32 alen; /* note: send a copy of the mixer spec */ wavespec = *inputSpec; /* Find out what kind of audio file this is */ magic = SDL_ReadLE32(src); /* Seek backwards for compatibility with older loaders */ SDL_RWseek(src, -(int)sizeof(Uint32), RW_SEEK_CUR); switch (magic) { case WAVE: case RIFF: audiospec = SDL_LoadWAV_RW(src, 0, &wavespec, (Uint8 **)&abuf, &alen); break; case FORM: audiospec = Mix_LoadAIFF_RW(src, 0, &wavespec, (Uint8 **)&abuf, &alen); break; case OGGS: audiospec = Mix_LoadOGG_RW(src, 0, &wavespec, (Uint8 **)&abuf, &alen); break; case FLAC: audiospec = Mix_LoadFLAC_RW(src, 0, &wavespec, (Uint8 **)&abuf, &alen); break; case CREA: audiospec = Mix_LoadVOC_RW(src, 0, &wavespec, (Uint8 **)&abuf, &alen); break; default: if (detect_mp3((Uint8*)&magic)) { audiospec = Mix_LoadMP3_RW(src, 0, &wavespec, (Uint8 **)&abuf, &alen); break; } break; } SDL_RWclose(src); if (audiospec) { stack->pushLString(std::string(reinterpret_cast<char*>(abuf), alen)); interfaceAS->push(audiospec, true); return 2; } else{ state.error("Unreckonized audio file\n"); } } } return 0; }