Mercurial > fife-parpg
diff engine/core/loaders/native/audio_loaders/sounddecoder_ogg.cpp @ 0:4a0efb7baf70
* Datasets becomes the new trunk and retires after that :-)
author | mvbarracuda@33b003aa-7bff-0310-803a-e67f0ece8222 |
---|---|
date | Sun, 29 Jun 2008 18:44:17 +0000 |
parents | |
children | 90005975cdbb |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/engine/core/loaders/native/audio_loaders/sounddecoder_ogg.cpp Sun Jun 29 18:44:17 2008 +0000 @@ -0,0 +1,134 @@ +/*************************************************************************** + * Copyright (C) 2005-2008 by the FIFE team * + * http://www.fifengine.de * + * This file is part of FIFE. * + * * + * FIFE is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +// Standard C++ library includes + +// Platform specific includes + +// 3rd party library includes + +// FIFE includes +// These includes are split up in two parts, separated by one empty line +// First block: files included from the FIFE root src directory +// Second block: files included from the same folder +#include "util/log/logger.h" +#include "util/base/exception.h" + +#include "sounddecoder_ogg.h" + +namespace FIFE { + static Logger _log(LM_AUDIO); + + /* OggVorbis Callback functions + */ + namespace OGG_cb { + static size_t read(void *ptr, size_t size, size_t nmemb, void *datasource) { + RawData* rdp = reinterpret_cast<RawData*>(datasource); + size_t restlen = rdp->getDataLength()-rdp->getCurrentIndex(); + size_t len = (restlen<=size*nmemb)?restlen:size*nmemb; + if (len) { + rdp->readInto(reinterpret_cast<uint8_t *>(ptr), len); + } + return len; + } + + static int seek(void *datasource, ogg_int64_t offset, int whence) { + RawData* rdp = reinterpret_cast<RawData*>(datasource); + switch (whence) { + case SEEK_SET: + (*rdp).setIndex(offset); + return 0; + case SEEK_CUR: + (*rdp).moveIndex(offset); + return 0; + case SEEK_END: + (*rdp).setIndex( (*rdp).getDataLength() -1 + offset); + return 0; + } + return -1; + } + + static int close(void *datasource) { return 0; } + + static long tell(void *datasource) { + RawData* rdp = reinterpret_cast<RawData*>(datasource); + return (*rdp).getCurrentIndex(); + } + } + + SoundDecoderOgg::SoundDecoderOgg(RawData* rdp) : m_file(rdp) { + + ov_callbacks ocb = { + OGG_cb::read, OGG_cb::seek, OGG_cb::close, OGG_cb::tell + }; + + if (0 > ov_open_callbacks(m_file.get(), &m_ovf, 0, 0, ocb)) { + throw InvalidFormat("Error opening OggVorbis file"); + } + + + vorbis_info *vi = ov_info(&m_ovf, -1); + if (!vi) { + throw InvalidFormat("Error fetching OggVorbis info"); + } + + if (!ov_seekable(&m_ovf)) { + throw InvalidFormat("OggVorbis file has to be seekable"); + } + + m_isstereo = vi->channels == 2; + m_samplerate = vi->rate; + m_is8bit = false; + m_declength = (m_isstereo ? 2 : 1) * 2 * ov_pcm_total(&m_ovf, -1); + m_datasize = 0; + m_data = NULL; + } + + bool SoundDecoderOgg::decode(unsigned long length) { + int stream = 0; + int ret = 0; + + // release buffer and allocate new memory + releaseBuffer(); + m_data = new char[length]; + + // decode the stream + m_datasize = 0; + do { + ret = ov_read(&m_ovf, m_data + m_datasize, + length-m_datasize, 0, 2, 1, &stream); + if (ret > 0) { + m_datasize += ret; + } + + } while (length-m_datasize > 0 && ret > 0); + + return m_datasize == 0; + } + + bool SoundDecoderOgg::setCursor(unsigned long pos) { + + if (ov_pcm_seek(&m_ovf, pos / ((m_isstereo ? 2 : 1) * 2)) == 0) { + return true; + } + return false; + } +}