snd_sequence_struct *snd_decode_ogg(uint8 *buffer,int32 bytes){ int result; int channels; int samplerate; short *out; result=stb_vorbis_decode_memory((unsigned char *)buffer,bytes,&channels,&samplerate,&out); if (result==-1) return NULL; //extern int stb_vorbis_decode_memory(unsigned char *mem, int len, int *channels, int *sample_rate, short **output); // decode an entire file and output the data interleaved into a malloc()ed // buffer stored in *output. The return value is the number of samples // decoded, or -1 if the file could not be opened or was not an ogg vorbis file. // When you're done with it, just free() the pointer returned in *output. //attach to new sequence static int32 seq_handle; seq_handle=list_add(snd_sequences); static snd_sequence_struct *seq; seq=(snd_sequence_struct*)list_get(snd_sequences,seq_handle); memset(seq,0,sizeof(snd_sequence_struct)); seq->references=1; seq->channels=channels; seq->sample_rate=samplerate; seq->bits_per_sample=16; seq->endian=0;//native seq->is_unsigned=0; seq->data=(uint8*)out; seq->data_size=result*2*channels; return seq; }
bool SoundData::loadOgg(const byte * buffer, Uint32 bufferSize) { clear(); short* samples; int channels; int sample_rate; int len; len = stb_vorbis_decode_memory(buffer, (int)bufferSize, &channels, &sample_rate, &samples); if (!samples) { return false; } Uint32 dataSize = Uint32(len * channels * 2); if (!separateChannels((byte*)samples, dataSize, channels, 16)) { free(samples); return false; } free(samples); _channels = channels; _sampleRate = sample_rate; _bitsPerSample = 16; return true; }
const i32 audio_vorbisPlay(MemoryArena_ *arena, AudioManager *audioManager, AudioRenderer *audioRenderer, AudioVorbis *vorbis, i32 numPlays) { if (vorbis == NULL) return -1; i32 result = initRendererForPlayback(arena, audioManager, audioRenderer, vorbis, numPlays); i16 *soundSamples; i32 channels, sampleRate; i32 numSamples = stb_vorbis_decode_memory( vorbis->data, vorbis->size, &channels, &sampleRate, &soundSamples); alBufferData(audioRenderer->bufferId[0], audioRenderer->format, soundSamples, numSamples * vorbis->info.channels * sizeof(i16), vorbis->info.sample_rate); // NOTE(doyle): stb_vorbis specific implementation requires free() // TODO(doyle): Object pool this and use our malloc to avoid dependency in Audio.c free(soundSamples); audioRenderer->audio = vorbis; audioRenderer->isStreaming = FALSE; audioRenderer->state = audiostate_playing; return result; }
S32 PCMAudioManager::loadSound(const char *assetName) { Property *prop = btGetContext()->appProperties->get("debug_sounds"); BOOL32 debugSounds = FALSE; if (prop) { debugSounds = prop->getBoolValue(); } if (isSoundLoaded(assetName)) { return getSoundId(assetName); } int assetSize = 0; unsigned char *fileData = _platform_load_asset(assetName, &assetSize); S32 sndId = -1; if (fileData) { signed short *decoded; int channels, len; unsigned int sampleRate = 0; len = stb_vorbis_decode_memory(fileData, assetSize, &channels, &sampleRate, &decoded); if (debugSounds) { char buf[1024]; sprintf(buf, "Loaded %s: (%i enc bytes) length=%i channels=%i rate=%i", assetName, assetSize, len, channels, sampleRate); logmsg(buf); } sndId = loadSound(decoded, len * channels, sampleRate, channels, assetName); } _platform_free_asset(fileData); return sndId; }
int main(int argc, char **argv) { size_t memlen; unsigned char *mem = stb_fileu("c:/x/theme_03.ogg", &memlen); int chan, samplerate; short *output; int samples = stb_vorbis_decode_memory(mem, memlen, &chan, &samplerate, &output); return 0; }
int main(int argc, char **argv) { size_t memlen; unsigned char *mem = stb_fileu("c:/x/sketch008.ogg", &memlen); int chan, samplerate; short *output; int samples = stb_vorbis_decode_memory(mem, memlen, &chan, &samplerate, &output); stb_filewrite("c:/x/sketch008.raw", output, samples*4); return 0; }
bool Clip::load(FS::IFile& file) { short* output = nullptr; auto res = stb_vorbis_decode_memory( (unsigned char*)file.getBuffer(), (int)file.size(), &m_channels, &m_sample_rate, &output); if (res <= 0) return false; m_data.resize(res * m_channels); copyMemory(&m_data[0], output, res * m_channels * sizeof(m_data[0])); free(output); return true; }
void StbVorbisImporter::doOpenData(Containers::ArrayView<const char> data) { Int numChannels, frequency; Short* decodedData = nullptr; Int samples = stb_vorbis_decode_memory(reinterpret_cast<const UnsignedByte*>(data.data()), data.size(), &numChannels, &frequency, &decodedData); if(samples == -1) { Error() << "Audio::StbVorbisImporter::openData(): the file signature is invalid"; return; } else if (samples == -2) { /* memory allocation failure */ Error() << "Audio::StbVorbisImporter::openData(): out of memory"; return; } Containers::Array<char> tempData{reinterpret_cast<char*>(decodedData), size_t(samples*numChannels*2), [](char* data, size_t) { std::free(data); }}; _frequency = frequency; /* Decide about format */ if(numChannels == 1) _format = Buffer::Format::Mono16; else if(numChannels == 2) _format = Buffer::Format::Stereo16; /** @todo Buffer::Format::*Float32 when extension support is done */ else { Error() << "Audio::StbVorbisImporter::openData(): unsupported channel count" << numChannels << "with" << 16 << "bits per sample"; return; } _data = std::move(tempData); return; }
VorbisFile::VorbisFile(const common::DataPtr& inFile) { data = NULL; int err; stb_vorbis* oggfile = stb_vorbis_open_memory((unsigned char*)inFile->bytes.get(), inFile->size, &err, NULL); if(!oggfile) { EOUT("throwing from here"); lost::common::StringStream os; os << "couldn't open ogg file '"; throw std::runtime_error(os.str().c_str()); } stb_vorbis_info info = stb_vorbis_get_info(oggfile); stb_vorbis_close(oggfile); sampleRate = info.sample_rate; numSamples = stb_vorbis_decode_memory((unsigned char*)(inFile->bytes.get()), inFile->size, &channels, &data); DOUT("decoded to "<<numSamples*2 <<" bytes"); buffer.reset(new al::Buffer); buffer->bufferData((channels == 2) ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16, data, numSamples*2, sampleRate); }
void *loom_asset_soundDeserializer( void *buffer, size_t bufferLen, LoomAssetCleanupCallback *dtor ) { loom_asset_sound_t *sound = (loom_asset_sound_t*)lmAlloc(gAssetAllocator, sizeof(loom_asset_sound_t)); memset(sound, 0, sizeof(loom_asset_sound_t)); unsigned char *charBuff = (unsigned char *)buffer; // Look for magic header in buffer. if(charBuff[0] == 0x4f && charBuff[1] == 0x67 && charBuff[2] == 0x67 && charBuff[3] == 0x53) { // It's an Ogg, assume vorbis and throw it to stb_vorbis. int channels = 0; short *outputBuffer = NULL; int sampleCount = stb_vorbis_decode_memory(charBuff, (int)bufferLen, &channels, &outputBuffer); if(sampleCount < 0) { lmLogError(gSoundAssetGroup, "Failed to decode Ogg Vorbis"); loom_asset_soundDtor(&sound); return NULL; } sound->channels = channels; sound->bytesPerSample = 2; sound->sampleCount = sampleCount; sound->bufferSize = sampleCount * channels * 2; sound->sampleRate = 44100; // TODO: This should be variable // We can skip this if we get clever about allocations in stbv. sound->buffer = lmAlloc(gAssetAllocator, sound->bufferSize); memcpy(sound->buffer, outputBuffer, sound->bufferSize); free(outputBuffer); } else if((charBuff[0] == 0x49 // ID3 && charBuff[1] == 0x44 && charBuff[2] == 0x33) || (charBuff[0] == 0xff // Missing ID3 Tag && charBuff[1] == 0xfb)) { // It's an MP3, y'all! short *outBuffer = (short*)lmAlloc(gAssetAllocator, MP3_MAX_SAMPLES_PER_FRAME * 2); mp3_info_t mp3Info; // Decode once to get total size. size_t totalBytes = 0; size_t bytesRead = 0, bytesLeft = bufferLen; mp3_decoder_t decmp3 = mp3_create(); for(;;) { int bytesDecoded = mp3_decode(decmp3, charBuff + bytesRead, (int)bytesLeft, outBuffer, &mp3Info); bytesRead += bytesDecoded; bytesLeft -= bytesDecoded; totalBytes += mp3Info.audio_bytes; if(bytesDecoded > 0) continue; // Clean up. mp3_done(decmp3); break; } // Great, set up the sound asset. // TODO: Warn about non 44.1khz mp3s. sound->channels = mp3Info.channels; sound->bytesPerSample = 2; sound->sampleCount = (int)totalBytes / sound->bytesPerSample; sound->bufferSize = sound->channels * sound->bytesPerSample * sound->sampleCount; sound->sampleRate = 44100; // TODO: This should be variable sound->buffer = lmAlloc(gAssetAllocator, sound->bufferSize); // Decode again to get real samples. decmp3 = mp3_create(); bytesRead = 0; bytesLeft = bufferLen; int curBufferOffset = 0; for(;;) { int bytesDecoded = mp3_decode(decmp3, charBuff + bytesRead, (int)bytesLeft, outBuffer, &mp3Info); bytesRead += bytesDecoded; bytesLeft -= bytesDecoded; memcpy(((unsigned char*)sound->buffer) + curBufferOffset, outBuffer, mp3Info.audio_bytes); curBufferOffset += mp3Info.audio_bytes; if(bytesDecoded > 0) continue; // Clean up. mp3_done(decmp3); break; } // Awesome, all set! lmFree(gAssetAllocator, outBuffer); } else if(charBuff[0] == 0x52 // 'RIFF' && charBuff[1] == 0x49 && charBuff[2] == 0x46 && charBuff[3] == 0x46) { // We've got a wav file wav_info wav; bool wavLoadSuccess = load_wav(charBuff, bufferLen, NULL, &wav); if (!wavLoadSuccess) { lmLogError(gSoundAssetGroup, "Failed to load wav format info"); loom_asset_soundDtor(sound); return 0; } sound->channels = wav.numChannels; sound->bytesPerSample = wav.sampleSize / 8; // wav sample size is in bits if (sound->bytesPerSample != 1 && sound->bytesPerSample != 2) { lmLogError(gSoundAssetGroup, "Unsupported wav format. Currently only 8-bit or 16-bit PCM are supported"); loom_asset_soundDtor(sound); return 0; } sound->bufferSize = wav.sampleDataSize; sound->sampleCount = sound->bufferSize / sound->bytesPerSample; sound->sampleRate = wav.samplesPerSecond; sound->buffer = lmAlloc(gAssetAllocator, sound->bufferSize); bool dataCopySuccess = load_wav(charBuff, bufferLen, (uint8_t*)sound->buffer, NULL); if (!dataCopySuccess) { lmLogError(gSoundAssetGroup, "Failed to copy wav data"); loom_asset_soundDtor(sound); return 0; } } else { lmLogError(gSoundAssetGroup, "Failed to identify sound buffer by magic number!"); loom_asset_soundDtor(sound); return 0; } *dtor = loom_asset_soundDtor; if(!sound->buffer) { lmLogError(gSoundAssetGroup, "Sound load failed due to this cryptic reason: %s", "(unknown)"); lmFree(gAssetAllocator, sound); return 0; } lmLogDebug(gSoundAssetGroup, "Sound allocation: %d bytes", sound->bufferSize); return sound; }
void *loom_asset_soundDeserializer( void *buffer, size_t bufferLen, LoomAssetCleanupCallback *dtor ) { loom_asset_sound_t *sound = (loom_asset_sound_t*)lmAlloc(gAssetAllocator, sizeof(loom_asset_sound_t)); unsigned char *charBuff = (unsigned char *)buffer; // Look for magic header in buffer. if(charBuff[0] == 0x4f && charBuff[1] == 0x67 && charBuff[2] == 0x67 && charBuff[3] == 0x53) { // It's an Ogg, assume vorbis and throw it to stb_vorbis. int channels = 0; short *outputBuffer = NULL; int sampleCount = stb_vorbis_decode_memory(charBuff, bufferLen, &channels, &outputBuffer); if(sampleCount < 0) { lmLogError(gSoundAssetGroup, "Failed to decode Ogg Vorbis!"); return NULL; } sound->channels = channels; sound->bytesPerSample = 2; sound->sampleCount = sampleCount; sound->bufferSize = sampleCount * channels * 2; // We can skip this if we get clever about allocations in stbv. sound->buffer = lmAlloc(gAssetAllocator, sound->bufferSize); memcpy(sound->buffer, outputBuffer, sound->bufferSize); free(outputBuffer); } else if((charBuff[0] == 0x49 // ID3 && charBuff[1] == 0x44 && charBuff[2] == 0x33) || (charBuff[0] == 0xff // Missing ID3 Tag && charBuff[1] == 0xfb)) { // It's an MP3, y'all! short *outBuffer = (short*)lmAlloc(gAssetAllocator, MP3_MAX_SAMPLES_PER_FRAME * 2); mp3_info_t mp3Info; // Decode once to get total size. int totalBytes = 0; int bytesRead = 0, bytesLeft = bufferLen; mp3_decoder_t decmp3 = mp3_create(); for(;;) { int bytesDecoded = mp3_decode(decmp3, charBuff + bytesRead, bytesLeft, outBuffer, &mp3Info); bytesRead += bytesDecoded; bytesLeft -= bytesDecoded; totalBytes += mp3Info.audio_bytes; if(bytesDecoded > 0) continue; // Clean up. mp3_done(decmp3); break; } // Great, set up the sound asset. // TODO: Warn about non 44.1khz mp3s. sound->channels = mp3Info.channels; sound->bytesPerSample = 2; sound->sampleCount = totalBytes / sound->bytesPerSample; sound->bufferSize = sound->channels * sound->bytesPerSample * sound->sampleCount; sound->buffer = lmAlloc(gAssetAllocator, sound->bufferSize); // Decode again to get real samples. decmp3 = mp3_create(); bytesRead = 0; bytesLeft = bufferLen; int curBufferOffset = 0; for(;;) { int bytesDecoded = mp3_decode(decmp3, charBuff + bytesRead, bytesLeft, outBuffer, &mp3Info); bytesRead += bytesDecoded; bytesLeft -= bytesDecoded; memcpy(((unsigned char*)sound->buffer) + curBufferOffset, outBuffer, mp3Info.audio_bytes); curBufferOffset += mp3Info.audio_bytes; if(bytesDecoded > 0) continue; // Clean up. mp3_done(decmp3); break; } // Awesome, all set! lmFree(gAssetAllocator, outBuffer); } else { lmLogError(gSoundAssetGroup, "Failed to identify sound buffer by magic number!"); return 0; } *dtor = loom_asset_soundDtor; if(!sound->buffer) { lmLogError(gSoundAssetGroup, "Sound load failed due to this cryptic reason: %s", "(unknown)"); lmFree(gAssetAllocator, sound); return 0; } lmLogError(gSoundAssetGroup, "Allocated %d bytes for a sound!", sound->bufferSize); return sound; }