// // Copyright (c) 2008-2017 the Urho3D project. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // #include "../Precompiled.h" #include "../Audio/OggVorbisSoundStream.h" #include "../Audio/Sound.h" #include #include "../DebugNew.h" namespace Atomic { OggVorbisSoundStream::OggVorbisSoundStream(const Sound* sound) { assert(sound && sound->IsCompressed()); SetFormat(sound->GetIntFrequency(), sound->IsSixteenBit(), sound->IsStereo()); // If the sound is looped, the stream will automatically rewind at end SetStopAtEnd(!sound->IsLooped()); // Initialize decoder data_ = sound->GetData(); dataSize_ = sound->GetDataSize(); int error; decoder_ = stb_vorbis_open_memory((unsigned char*)data_.Get(), dataSize_, &error, 0); } OggVorbisSoundStream::~OggVorbisSoundStream() { // Close decoder if (decoder_) { stb_vorbis* vorbis = static_cast(decoder_); stb_vorbis_close(vorbis); decoder_ = 0; } } unsigned OggVorbisSoundStream::GetData(signed char* dest, unsigned numBytes) { if (!decoder_) return 0; stb_vorbis* vorbis = static_cast(decoder_); unsigned channels = stereo_ ? 2 : 1; unsigned outSamples = (unsigned)stb_vorbis_get_samples_short_interleaved(vorbis, channels, (short*)dest, numBytes >> 1); unsigned outBytes = (outSamples * channels) << 1; // Rewind and retry if is looping and produced less output than should have if (outBytes < numBytes && !stopAtEnd_) { numBytes -= outBytes; stb_vorbis_seek_start(vorbis); outSamples = (unsigned)stb_vorbis_get_samples_short_interleaved(vorbis, channels, (short*)(dest + outBytes), numBytes >> 1); outBytes += (outSamples * channels) << 1; } return outBytes; } }