FIFE 2008.0
|
00001 /*************************************************************************** 00002 * Copyright (C) 2005-2008 by the FIFE team * 00003 * http://www.fifengine.de * 00004 * This file is part of FIFE. * 00005 * * 00006 * FIFE is free software; you can redistribute it and/or * 00007 * modify it under the terms of the GNU Lesser General Public * 00008 * License as published by the Free Software Foundation; either * 00009 * version 2.1 of the License, or (at your option) any later version. * 00010 * * 00011 * This library is distributed in the hope that it will be useful, * 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 00014 * Lesser General Public License for more details. * 00015 * * 00016 * You should have received a copy of the GNU Lesser General Public * 00017 * License along with this library; if not, write to the * 00018 * Free Software Foundation, Inc., * 00019 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * 00020 ***************************************************************************/ 00021 00022 // Standard C++ library includes 00023 00024 // Platform specific includes 00025 00026 // 3rd party library includes 00027 00028 // FIFE includes 00029 // These includes are split up in two parts, separated by one empty line 00030 // First block: files included from the FIFE root src directory 00031 // Second block: files included from the same folder 00032 #include "util/log/logger.h" 00033 #include "util/base/exception.h" 00034 00035 #include "sounddecoder_ogg.h" 00036 00037 namespace FIFE { 00038 static Logger _log(LM_AUDIO); 00039 00040 /* OggVorbis Callback functions 00041 */ 00042 namespace OGG_cb { 00043 static size_t read(void *ptr, size_t size, size_t nmemb, void *datasource) { 00044 RawData* rdp = reinterpret_cast<RawData*>(datasource); 00045 size_t restlen = rdp->getDataLength()-rdp->getCurrentIndex(); 00046 size_t len = (restlen<=size*nmemb)?restlen:size*nmemb; 00047 if (len) { 00048 rdp->readInto(reinterpret_cast<uint8_t *>(ptr), len); 00049 } 00050 return len; 00051 } 00052 00053 static int seek(void *datasource, ogg_int64_t offset, int whence) { 00054 RawData* rdp = reinterpret_cast<RawData*>(datasource); 00055 switch (whence) { 00056 case SEEK_SET: 00057 (*rdp).setIndex(offset); 00058 return 0; 00059 case SEEK_CUR: 00060 (*rdp).moveIndex(offset); 00061 return 0; 00062 case SEEK_END: 00063 (*rdp).setIndex( (*rdp).getDataLength() -1 + offset); 00064 return 0; 00065 } 00066 return -1; 00067 } 00068 00069 static int close(void *datasource) { return 0; } 00070 00071 static long tell(void *datasource) { 00072 RawData* rdp = reinterpret_cast<RawData*>(datasource); 00073 return (*rdp).getCurrentIndex(); 00074 } 00075 } 00076 00077 SoundDecoderOgg::SoundDecoderOgg(RawData* rdp) : m_file(rdp) { 00078 00079 ov_callbacks ocb = { 00080 OGG_cb::read, OGG_cb::seek, OGG_cb::close, OGG_cb::tell 00081 }; 00082 00083 if (0 > ov_open_callbacks(m_file.get(), &m_ovf, 0, 0, ocb)) { 00084 throw InvalidFormat("Error opening OggVorbis file"); 00085 } 00086 00087 00088 vorbis_info *vi = ov_info(&m_ovf, -1); 00089 if (!vi) { 00090 throw InvalidFormat("Error fetching OggVorbis info"); 00091 } 00092 00093 if (!ov_seekable(&m_ovf)) { 00094 throw InvalidFormat("OggVorbis file has to be seekable"); 00095 } 00096 00097 m_isstereo = vi->channels == 2; 00098 m_samplerate = vi->rate; 00099 m_is8bit = false; 00100 m_declength = (m_isstereo ? 2 : 1) * 2 * ov_pcm_total(&m_ovf, -1); 00101 m_datasize = 0; 00102 m_data = NULL; 00103 } 00104 00105 bool SoundDecoderOgg::decode(unsigned long length) { 00106 int stream = 0; 00107 int ret = 0; 00108 00109 // release buffer and allocate new memory 00110 releaseBuffer(); 00111 m_data = new char[length]; 00112 00113 // decode the stream 00114 m_datasize = 0; 00115 do { 00116 ret = ov_read(&m_ovf, m_data + m_datasize, 00117 length-m_datasize, 0, 2, 1, &stream); 00118 if (ret > 0) { 00119 m_datasize += ret; 00120 } 00121 00122 } while (length-m_datasize > 0 && ret > 0); 00123 00124 return m_datasize == 0; 00125 } 00126 00127 bool SoundDecoderOgg::setCursor(unsigned long pos) { 00128 00129 if (ov_pcm_seek(&m_ovf, pos / ((m_isstereo ? 2 : 1) * 2)) == 0) { 00130 return true; 00131 } 00132 return false; 00133 } 00134 }