#ifndef POMME_NO_MP3 #include "PommeSound.h" #include #include #define MINIMP3_IMPLEMENTATION #include "SoundFormats/minimp3.h" #define MINIMP3_IO_SIZE (128*1024) // io buffer size for streaming functions, must be greater than MINIMP3_BUF_SIZE #define MINIMP3_BUF_SIZE (16*1024) // buffer which can hold minimum 10 consecutive mp3 frames (~16KB) worst case SndListHandle Pomme::Sound::LoadMP3AsResource(std::istream& stream) { mp3dec_t context = {}; mp3dec_init(&context); mp3dec_frame_info_t frameInfo; std::vector fileBuf; std::vector songPCM; std::vector tempPCM(MINIMP3_MAX_SAMPLES_PER_FRAME); int totalSamples = 0; while (true) { // Refill buffer if (fileBuf.size() < MINIMP3_BUF_SIZE) { if (stream.eof()) { // bail break; } auto oldSize = fileBuf.size(); auto toRead = MINIMP3_BUF_SIZE - oldSize; fileBuf.resize(MINIMP3_BUF_SIZE); stream.read((char*) (fileBuf.data() + oldSize), (int) toRead); auto didRead = stream.gcount(); fileBuf.resize(oldSize + didRead); } int numDecodedSamples = mp3dec_decode_frame(&context, fileBuf.data(), (int) fileBuf.size(), tempPCM.data(), &frameInfo); if (numDecodedSamples > 0) { size_t minCapacity = songPCM.size() + (numDecodedSamples * frameInfo.channels); if (songPCM.capacity() < minCapacity) { songPCM.reserve(2 * minCapacity); } songPCM.insert(songPCM.end(), tempPCM.begin(), tempPCM.begin() + (numDecodedSamples * frameInfo.channels)); totalSamples += numDecodedSamples; } fileBuf.erase(fileBuf.begin(), fileBuf.begin() + frameInfo.frame_bytes); } Pomme::Sound::SampledSoundInfo info = {}; info.compressionType = 'swot'; info.bigEndian = false; info.isCompressed = false; info.baseNote = 60; // Middle C info.codecBitDepth = 8 * sizeof(mp3d_sample_t); info.sampleRate = frameInfo.hz; info.nChannels = frameInfo.channels; info.nPackets = totalSamples; info.decompressedLength = totalSamples * info.nChannels * sizeof(mp3d_sample_t); info.compressedLength = info.decompressedLength; info.dataStart = (char*) songPCM.data(); return info.MakeStandaloneResource(); } #endif // POMME_NO_MP3