From: Tom <rtp...@us...> - 2010-04-26 23:09:59
|
gemrb: Infinity Engine emulator The branch master has been updated via c57ac09f34b08213b1629eba3d5d5c6b0bb15a78 (commit) via d2b6b668f0326cee3770de2f7be8dd22631fae3d (commit) via 80979b41a59388876bbdcfa27c959b30587e165b (commit) via 1669ac8b2431ceb99148d4f5bf86c047bf57edb6 (commit) via a7c1d826c87d2b323fef8a9e2620de7ad9703c0d (commit) via 7700e87e55bb53c1b0fea81900737b42c77ca40c (commit) via 896991b2db9e0abaddd5784a6ab0fc04fb647ab5 (commit) via 657ccd80926aa001e64fff6e27cf8bb4e68ef7e0 (commit) Summary of changes: configure.in | 13 +- gemrb/core/Audio.h | 3 +- gemrb/core/GameData.cpp | 1 - gemrb/core/Interface.cpp | 11 +- gemrb/core/ResourceManager.cpp | 11 +- gemrb/core/SaveGameIterator.cpp | 29 +- gemrb/core/SoundMgr.cpp | 1 + gemrb/core/SoundMgr.h | 36 ++- gemrb/core/VFS.cpp | 181 +++++----- gemrb/core/VFS.h | 27 +- gemrb/core/Variables.cpp | 1 - gemrb/plugins/ACMImporter/ACMImporter.cpp | 97 ----- gemrb/plugins/ACMImporter/CMakeLists.txt | 5 - gemrb/plugins/ACMImporter/Makefile.am | 3 - gemrb/plugins/ACMImporter/readers.cpp | 385 -------------------- gemrb/plugins/ACMImporter/readers.h | 253 ------------- gemrb/plugins/ACMReader/ACMReader.cpp | 120 ++++++ .../ACMImporter.h => ACMReader/ACMReader.h} | 74 +++-- gemrb/plugins/ACMReader/CMakeLists.txt | 3 + gemrb/plugins/ACMReader/Makefile.am | 3 + .../plugins/{ACMImporter => ACMReader}/decoder.cpp | 0 gemrb/plugins/{ACMImporter => ACMReader}/decoder.h | 0 gemrb/plugins/{ACMImporter => ACMReader}/general.h | 0 .../{ACMImporter => ACMReader}/unpacker.cpp | 18 +- .../plugins/{ACMImporter => ACMReader}/unpacker.h | 0 gemrb/plugins/AREImporter/AREImporter.cpp | 1 - gemrb/plugins/CMakeLists.txt | 4 +- .../DirectoryImporter/DirectoryImporter.cpp | 11 +- .../plugins/DirectoryImporter/DirectoryImporter.h | 3 - gemrb/plugins/GUIScript/GUIScript.cpp | 8 +- gemrb/plugins/KEYImporter/KEYImporter.cpp | 44 +-- gemrb/plugins/MUSImporter/MUSImporter.cpp | 51 ++-- gemrb/plugins/MUSImporter/MUSImporter.h | 2 + gemrb/plugins/Makefile.am | 4 +- gemrb/plugins/NullSound/NullSound.cpp | 4 +- gemrb/plugins/NullSound/NullSound.h | 2 +- gemrb/plugins/OGGReader/CMakeLists.txt | 7 + gemrb/plugins/OGGReader/Makefile.am | 6 + gemrb/plugins/OGGReader/OGGReader.cpp | 129 +++++++ .../PNGImporter.h => OGGReader/OGGReader.h} | 44 ++- gemrb/plugins/OpenALAudio/OpenALAudio.cpp | 43 +-- gemrb/plugins/OpenALAudio/OpenALAudio.h | 2 +- gemrb/plugins/TLKImporter/TlkOverride.cpp | 10 +- gemrb/plugins/WAVReader/CMakeLists.txt | 3 + gemrb/plugins/WAVReader/Makefile.am | 3 + gemrb/plugins/WAVReader/WAVReader.cpp | 193 ++++++++++ .../ACMImporter.h => WAVReader/WAVReader.h} | 57 ++-- 47 files changed, 812 insertions(+), 1094 deletions(-) delete mode 100644 gemrb/plugins/ACMImporter/ACMImporter.cpp delete mode 100644 gemrb/plugins/ACMImporter/CMakeLists.txt delete mode 100644 gemrb/plugins/ACMImporter/Makefile.am delete mode 100644 gemrb/plugins/ACMImporter/readers.cpp delete mode 100644 gemrb/plugins/ACMImporter/readers.h create mode 100644 gemrb/plugins/ACMReader/ACMReader.cpp copy gemrb/plugins/{ACMImporter/ACMImporter.h => ACMReader/ACMReader.h} (51%) create mode 100644 gemrb/plugins/ACMReader/CMakeLists.txt create mode 100644 gemrb/plugins/ACMReader/Makefile.am rename gemrb/plugins/{ACMImporter => ACMReader}/decoder.cpp (100%) rename gemrb/plugins/{ACMImporter => ACMReader}/decoder.h (100%) rename gemrb/plugins/{ACMImporter => ACMReader}/general.h (100%) rename gemrb/plugins/{ACMImporter => ACMReader}/unpacker.cpp (98%) rename gemrb/plugins/{ACMImporter => ACMReader}/unpacker.h (100%) create mode 100644 gemrb/plugins/OGGReader/CMakeLists.txt create mode 100644 gemrb/plugins/OGGReader/Makefile.am create mode 100644 gemrb/plugins/OGGReader/OGGReader.cpp copy gemrb/plugins/{PNGImporter/PNGImporter.h => OGGReader/OGGReader.h} (65%) create mode 100644 gemrb/plugins/WAVReader/CMakeLists.txt create mode 100644 gemrb/plugins/WAVReader/Makefile.am create mode 100644 gemrb/plugins/WAVReader/WAVReader.cpp rename gemrb/plugins/{ACMImporter/ACMImporter.h => WAVReader/WAVReader.h} (58%) from d74803e98ff664df058646bab7518290ed1379e4 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- http://gemrb.git.sourceforge.net/git/gitweb.cgi?p=gemrb/gemrb;a=commitdiff;h=c57ac09f34b08213b1629eba3d5d5c6b0bb15a78 commit c57ac09f34b08213b1629eba3d5d5c6b0bb15a78 Merge: d74803e d2b6b66 Author: Tom Prince <tom...@ua...> Date: Mon Apr 26 18:42:15 2010 -0400 Merge branch 'sound' diff --cc gemrb/core/ResourceManager.cpp index f39c1c1,f70b35d..c4e19c1 --- a/gemrb/core/ResourceManager.cpp +++ b/gemrb/core/ResourceManager.cpp @@@ -53,9 -51,9 +52,9 @@@ bool ResourceManager::AddSource(char *p static void PrintPossibleFiles(const char* ResRef, const TypeID *type) { - const std::vector<ResourceDesc>& types = core->GetPluginMgr()->GetResourceDesc(type); + const std::vector<ResourceDesc>& types = PluginMgr::Get()->GetResourceDesc(type); for (size_t j = 0; j < types.size(); j++) { - printf("%.8s%s ", ResRef, types[j].GetExt()); + printf("%s%s ", ResRef, types[j].GetExt()); } } diff --cc gemrb/core/SoundMgr.cpp index 94dc659,0026300..2172155 --- a/gemrb/core/SoundMgr.cpp +++ b/gemrb/core/SoundMgr.cpp @@@ -20,9 -20,10 +20,10 @@@ #include "SoundMgr.h" -const TypeID SoundMgr::ID = {}; +const TypeID SoundMgr::ID = { "SoundMgr" }; SoundMgr::SoundMgr(void) + : samples( 0 ), channels( 0 ), samplerate( 0 ) { } http://gemrb.git.sourceforge.net/git/gitweb.cgi?p=gemrb/gemrb;a=commitdiff;h=d2b6b668f0326cee3770de2f7be8dd22631fae3d commit d2b6b668f0326cee3770de2f7be8dd22631fae3d Author: Tom Prince <tom...@ua...> Date: Tue Apr 20 20:26:47 2010 -0400 Resource support for sound. Signed-off-by: Tom Prince <tom...@ua...> diff --git a/configure.in b/configure.in index 01352a0..37cd023 100644 --- a/configure.in +++ b/configure.in @@ -167,9 +167,12 @@ AM_CHECK_PYTHON_LIBS([], [AC_MSG_ERROR([ ])]) -AC_CHECK_LIB(vorbisfile, ov_info, - AC_DEFINE( HAS_VORBIS_SUPPORT, 1, [Handling of .ogg soundfiles]) - LIBS="$LIBS -lvorbis -lvorbisfile",, -lvorbis ) +AC_CHECK_HEADER([vorbis/vorbisfile.h], + [AC_CHECK_LIB(vorbisfile, ov_info, + [AC_DEFINE( HAS_VORBIS_SUPPORT, 1, [Handling of .ogg soundfiles]) + vorbis_ok=yes],[vorbis_ok=no], -lvorbis )], + [vorbis_ok=no]) +AM_CONDITIONAL([VORBIS], [test x$vorbis_ok = xyes]) dnl FIXME: check for libpng properly, using libpng(12)-config AC_CHECK_HEADER(png.h,,AC_MSG_ERROR([*** libpng not found!])) @@ -232,7 +235,9 @@ gemrb/GUIScripts/pst/Makefile gemrb/GUIScripts/test1/Makefile gemrb/plugins/Makefile gemrb/plugins/2DAImporter/Makefile -gemrb/plugins/ACMImporter/Makefile +gemrb/plugins/ACMReader/Makefile +gemrb/plugins/OGGReader/Makefile +gemrb/plugins/WAVReader/Makefile gemrb/plugins/AREImporter/Makefile gemrb/plugins/BAMImporter/Makefile gemrb/plugins/BIFImporter/Makefile diff --git a/gemrb/core/SoundMgr.cpp b/gemrb/core/SoundMgr.cpp index 82e7f83..0026300 100644 --- a/gemrb/core/SoundMgr.cpp +++ b/gemrb/core/SoundMgr.cpp @@ -23,6 +23,7 @@ const TypeID SoundMgr::ID = {}; SoundMgr::SoundMgr(void) + : samples( 0 ), channels( 0 ), samplerate( 0 ) { } diff --git a/gemrb/core/SoundMgr.h b/gemrb/core/SoundMgr.h index 3a5a223..7d47681 100644 --- a/gemrb/core/SoundMgr.h +++ b/gemrb/core/SoundMgr.h @@ -22,23 +22,43 @@ #define SOUNDMGR_H #include "ie_types.h" -#include "Plugin.h" +#include "Resource.h" #include "DataStream.h" -class GEM_EXPORT SoundMgr : public Plugin { +/** + * Base Class for sound plugins + */ +class GEM_EXPORT SoundMgr : public Resource { public: static const TypeID ID; public: SoundMgr(void); virtual ~SoundMgr(void); virtual bool Open(DataStream* stream, bool autofree = true ) = 0 ; - virtual int get_length() = 0 ; - virtual int get_channels() = 0 ; - virtual int get_samplerate() = 0 ; + /** + * Read up to cnt samples into memory + * + * @param[out] memory Array to hold samples read. + * @param[in] cnt number of samples to read. + * @returns Number of samples read. + */ virtual int read_samples( short* memory, int cnt ) = 0 ; - virtual void rewind(void) = 0 ; - + int get_channels() + { + return channels; + } + int get_samplerate() + { + return samplerate; + } + int get_length() + { + return samples; + } // returns the total samples count +protected: + int samples; // total count of sound samples + int channels; + int samplerate; }; - #endif diff --git a/gemrb/plugins/ACMImporter/ACMImporter.cpp b/gemrb/plugins/ACMImporter/ACMImporter.cpp deleted file mode 100644 index c482211..0000000 --- a/gemrb/plugins/ACMImporter/ACMImporter.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* GemRB - Infinity Engine Emulator - * Copyright (C) 2003-2004 The GemRB Project - * - * This program 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 Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * - */ - -#include "ACMImporter.h" - -ACMImp::ACMImp() -{ - SoundReader = 0; -} - -bool ACMImp::Open(DataStream* stream, bool autofree) -{ - delete SoundReader; - SoundReader = 0; - - if (!stream) { - return false; - } - char Signature[4]; - ieDword SignatureDword; - stream->Read( Signature, 4 ); - stream->Seek( 0, GEM_STREAM_START ); - stream->ReadDword( &SignatureDword ); - stream->Seek( 0, GEM_STREAM_START ); -#ifdef HAS_VORBIS_SUPPORT - if(strnicmp(Signature, "oggs", 4) == 0) { - SoundReader = CreateSoundReader(stream, SND_READER_OGG, stream->Size(), autofree) ; - } //ogg -#endif - if(strnicmp(Signature, "RIFF", 4) == 0) { - SoundReader = CreateSoundReader(stream, SND_READER_WAV, stream->Size(), autofree) ; - } //wav - if (SignatureDword == IP_ACM_SIG) { - SoundReader = CreateSoundReader(stream, SND_READER_ACM, stream->Size(), autofree) ; - } //acm - if (memcmp( Signature, "WAVC", 4 ) == 0) { - SoundReader = CreateSoundReader(stream, SND_READER_ACM, stream->Size(), autofree) ; - } //wavc - - if (SoundReader) - return true ; - - return false; -} - -ACMImp::~ACMImp() -{ - delete SoundReader ; -} - -int ACMImp::get_channels() -{ - return SoundReader->get_channels() ; -} - -int ACMImp::get_length() -{ - return SoundReader->get_length() ; -} - -int ACMImp::get_samplerate() -{ - return SoundReader->get_samplerate() ; -} - -int ACMImp::read_samples(short* memory, int cnt) -{ - return SoundReader->read_samples(memory, cnt) ; -} - -void ACMImp::rewind() -{ - SoundReader->rewind() ; -} - -#include "plugindef.h" - -GEMRB_PLUGIN(0x1AE768FE, "ACM File Importer") -PLUGIN_CLASS(IE_WAV_CLASS_ID, ACMImp) -END_PLUGIN() diff --git a/gemrb/plugins/ACMImporter/CMakeLists.txt b/gemrb/plugins/ACMImporter/CMakeLists.txt deleted file mode 100644 index 04dd9fa..0000000 --- a/gemrb/plugins/ACMImporter/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -FILE( GLOB ACMImporter_files *.cpp ) - -ADD_GEMRB_PLUGIN (ACMImporter ${ACMImporter_files}) - -TARGET_LINK_LIBRARIES(ACMImporter ${VORBIS_LIBRARY}) diff --git a/gemrb/plugins/ACMImporter/Makefile.am b/gemrb/plugins/ACMImporter/Makefile.am deleted file mode 100644 index 5e41086..0000000 --- a/gemrb/plugins/ACMImporter/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ -plugin_LTLIBRARIES = ACMImporter.la -ACMImporter_la_LDFLAGS = -module -avoid-version -shared -ACMImporter_la_SOURCES = unpacker.cpp readers.cpp decoder.cpp ACMImporter.cpp ACMImporter.h decoder.h general.h readers.h unpacker.h diff --git a/gemrb/plugins/ACMImporter/readers.cpp b/gemrb/plugins/ACMImporter/readers.cpp deleted file mode 100644 index 54d954a..0000000 --- a/gemrb/plugins/ACMImporter/readers.cpp +++ /dev/null @@ -1,385 +0,0 @@ -/* GemRB - Infinity Engine Emulator - * Copyright (C) 2003 The GemRB Project - * - * This program 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 Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * - */ - -//#include "stdafx.h" -// Classes for sound files. -// Supported formats: PCM-RAW, PCM-WAV (both 8 and 16 bits), -// Ogg Vorbis and Interplay's ACM. - -#include <stdio.h> -#include "Interface.h" -#include "readers.h" -#include "general.h" - -#ifdef HAS_VORBIS_SUPPORT -static size_t ovfd_read(void *ptr, size_t size, size_t nmemb, void *datasource) -{ - DataStream *vb = (DataStream *) datasource; - int bytesToRead = size * nmemb; - - int remains = vb->Remains(); - if(remains<=0) { - /* no more reading, we're at the end */ - return 0; - } - if(bytesToRead > remains ) { - bytesToRead = remains; - } - vb->Read(ptr, bytesToRead); - return bytesToRead; -} - -static int ovfd_seek(void *datasource, ogg_int64_t offset, int whence) { - DataStream *vb = (DataStream *) datasource; - switch(whence) { - case SEEK_SET: - if(vb->Seek(offset, GEM_STREAM_START)<0) - return -1; - break; - case SEEK_CUR: - if(vb->Seek(offset, GEM_CURRENT_POS)<0) - return -1; - break; - case SEEK_END: - if(vb->Seek(vb->Size()+offset, GEM_STREAM_START)<0) - return -1; - break; - default: - return -1; - } - return vb->GetPos(); -} - -static int ovfd_close(void * /*datasource*/) { - return 0; -} - -static long ovfd_tell(void *datasource) { - DataStream *vb = (DataStream *) datasource; - return (long) vb->GetPos(); -} - -int COGGReader::init_reader() -{ - vorbis_info *info; - int res; - ov_callbacks cbstruct = { - ovfd_read, ovfd_seek, ovfd_close, ovfd_tell - }; - - res=ov_open_callbacks(stream, &OggStream, NULL, 0, cbstruct); - if(res<0) { - printMessage("Sound","Couldn't initialize vorbis!\n", LIGHT_RED); - return 0; - } - info = ov_info(&OggStream, -1); - channels = info->channels; - samplerate = info->rate; - samples_left = ( samples = ov_pcm_total(&OggStream, -1) ); - return 1; -} - -void fix_endian(ieWord &dest); - -int COGGReader::read_samples(short* buffer, int count) -{ - int whatisthis; - - if(samples_left<count) { - count=samples_left; - } - int samples_got=0; - int samples_need=count; - while(samples_need) { - int rd=ov_read(&OggStream, (char *)buffer, samples_need<<1, 0, 2, 1, &whatisthis); - if(rd==OV_HOLE) { - continue; - } - if(rd<=0) { - break; - } - rd>>=1; - buffer+=rd; - samples_got+=rd; - samples_need-=rd; - } - samples_left-=samples_got; - if (stream->IsEndianSwitch()) { - for (size_t i = 0; i < (size_t)samples_got; i++) { - fix_endian(((ieWord *)buffer-samples_got)[i]); - } - } - - return samples_got; -} - -#endif - -int CACMReader::init_reader() -{ - ACM_Header hdr; - char tmp[4]; - - stream->Read( tmp, sizeof( tmp ) ); - if (!memcmp( tmp, "WAVC", 4 )) { - stream->Seek( 24, GEM_CURRENT_POS ); - } else { - stream->Seek( -4, GEM_CURRENT_POS ); - } - //stream->Read( &hdr, sizeof( ACM_Header ) ); - //maybe this'll work on a PPC - - stream->ReadDword( &hdr.signature ); - stream->ReadDword( &hdr.samples ); - stream->ReadWord( &hdr.channels ); - stream->ReadWord( &hdr.rate ); - ieWord tmpword; - stream->ReadWord( &tmpword ); - //subblocks = (int) (tmpword&0xfff); - //levels = (int) (tmpword>>12); - subblocks = (int) (tmpword>>4); - levels = (int) (tmpword&15); - - if (hdr.signature != IP_ACM_SIG) { - return 0; - } - samples_left = ( samples = hdr.samples ); - channels = hdr.channels; - samplerate = hdr.rate; - //levels = hdr.levels; - //subblocks = hdr.subblocks; - - block_size = ( 1 << levels ) * subblocks; - //using malloc for simple arrays (supposed to be faster) - block = (int *) malloc(sizeof(int)*block_size); - if (!block) { - return 0; - } - unpacker = new CValueUnpacker( levels, subblocks, stream ); - if (!unpacker || !unpacker->init_unpacker()) { - return 0; - } - decoder = new CSubbandDecoder( levels ); - if (!decoder || !decoder->init_decoder()) { - return 0; - } - return 1; -} -int CACMReader::make_new_samples() -{ - if (!unpacker->get_one_block( block )) { - return 0; - } - - decoder->decode_data( block, subblocks ); - values = block; - samples_ready = ( block_size > samples_left ) ? samples_left : block_size; - samples_left -= samples_ready; - - return 1; -} - -int CACMReader::read_samples(short* buffer, int count) -{ - int res = 0; - while (res < count) { - if (samples_ready == 0) { - if (samples_left == 0) - break; - if (!make_new_samples()) - break; - } - *buffer = ( short ) ( ( *values ) >> levels ); - values++; - buffer++; - res += 1; - samples_ready--; - } - return res; -} - -CSoundReader* CreateSoundReader(DataStream* stream, int type, int samples, - bool autoFree) -{ - CSoundReader* res = NULL; - - switch (type) { -#ifdef HAS_VORBIS_SUPPORT - case SND_READER_OGG: - res = new COGGReader( stream, autoFree ); - break; -#endif - case SND_READER_ACM: - res = new CACMReader( stream, autoFree ); - break; - case SND_READER_WAV: - res = new CWavPCMReader( stream, samples, autoFree ); - break; - default: - if (autoFree) delete stream; - break; - } - if (res) { - if (!res->init_reader()) { - delete res; - res = NULL; - } - } - return res; -} - -int CRawPCMReader::init_reader() -{ - if (samples < 0) { - samples = stream->Size(); - stream->Seek( 0, GEM_STREAM_START ); - if (is16bit) { - samples >>= 1; // each sample has 16 bit - } - } - samples_left = samples; - return 1; -} - -inline void fix_endian(ieDword &dest) -{ - unsigned char tmp; - tmp=((unsigned char *) &dest)[0]; - ((unsigned char *) &dest)[0]=((unsigned char *) &dest)[3]; - ((unsigned char *) &dest)[3]=tmp; - tmp=((unsigned char *) &dest)[1]; - ((unsigned char *) &dest)[1]=((unsigned char *) &dest)[2]; - ((unsigned char *) &dest)[2]=tmp; - -} - -inline void fix_endian(ieWord &dest) -{ - unsigned char tmp; - tmp=((unsigned char *) &dest)[0]; - ((unsigned char *) &dest)[0]=((unsigned char *) &dest)[1]; - ((unsigned char *) &dest)[1]=tmp; -} - - -int CRawPCMReader::read_samples(short* buffer, int count) -{ - if (count > samples_left) { - count = samples_left; - } - int res = 0; - if (count) { - res = stream->Read( buffer, count * ( ( is16bit ? 2 : 1 ) ) ); - } - if (!is16bit) { - char* alt_buff = ( char* ) buffer; - int i = res; - while(i--) { - alt_buff[( i << 1 ) + 1] = ( char ) ( alt_buff[i] - 0x80 ); - alt_buff[i << 1] = 0; - } - } - if(is16bit) { - res >>= 1; - if (stream->IsEndianSwitch()) { - for (size_t i = 0; i < (size_t)count; i++) { - fix_endian(((ieWord *)buffer)[i]); - } - } - } - samples_left -= res; - return res; -} - -int CWavPCMReader::init_reader() -{ - int res = CRawPCMReader::init_reader(); if (!res) { - return res; - } - - cWAVEFORMATEX fmt; - RIFF_CHUNK r_hdr, fmt_hdr, data_hdr; - unsigned int wave; - memset( &fmt, 0, sizeof( fmt ) ); - - //stream->Read( &r_hdr, sizeof( r_hdr ) ); - //don't swap this - stream->Read(&r_hdr.fourcc, 4); - stream->ReadDword(&r_hdr.length); - //don't swap this - stream->Read( &wave, 4 ); - if (r_hdr.fourcc != *( unsigned int * ) RIFF_4cc || - wave != *( unsigned int * ) WAVE_4cc) { - return 0; - } - - //stream->Read( &fmt_hdr, sizeof( fmt_hdr ) ); - //don't swap this - stream->Read(&fmt_hdr.fourcc,4); - stream->ReadDword(&fmt_hdr.length); - if (fmt_hdr.fourcc != *( unsigned int * ) fmt_4cc || - fmt_hdr.length > sizeof( cWAVEFORMATEX )) { - return 0; - } - memset(&fmt,0,sizeof(fmt) ); - stream->Read( &fmt, fmt_hdr.length ); - //hmm, we should swap fmt bytes if we are on a mac - //but we don't know exactly how much of the structure we'll read - //so we have to swap the bytes after reading them - if (stream->IsEndianSwitch()) { - fix_endian(fmt.wFormatTag); - fix_endian(fmt.nChannels); - fix_endian(fmt.nSamplesPerSec); - fix_endian(fmt.wBitsPerSample); - //we don't use these fields, so who cares - //fix_endian(fmt.nAvgBytesPerSec); - //fix_endian(fmt.nBlockAlign); - //fix_endian(fmt.cbSize); - } - if (fmt.wFormatTag != 1) { - return 0; - } - is16bit = ( fmt.wBitsPerSample == 16 ); - - //stream->Read( &data_hdr, sizeof( data_hdr ) ); - //don't swap this - stream->Read(&data_hdr.fourcc,4); - stream->ReadDword(&data_hdr.length); - - if (data_hdr.fourcc == *( unsigned int * ) fact_4cc) { - stream->Seek( data_hdr.length, GEM_CURRENT_POS ); - //stream->Read( &data_hdr, sizeof( data_hdr ) ); - stream->ReadDword(&data_hdr.fourcc); - stream->ReadDword(&data_hdr.length); - } - if (data_hdr.fourcc != *( unsigned int * ) data_4cc) { - return 0; - } - - samples = data_hdr.length; - if (is16bit) { - samples >>= 1; - } - samples_left = samples; - channels = fmt.nChannels; - samplerate = fmt.nSamplesPerSec; - return 1; -} - diff --git a/gemrb/plugins/ACMImporter/readers.h b/gemrb/plugins/ACMImporter/readers.h deleted file mode 100644 index 7f156c4..0000000 --- a/gemrb/plugins/ACMImporter/readers.h +++ /dev/null @@ -1,253 +0,0 @@ -/* GemRB - Infinity Engine Emulator - * Copyright (C) 2003 The GemRB Project - * - * This program 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 Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * - */ - -#ifndef _ACM_LAB_SOUND_READER_H -#define _ACM_LAB_SOUND_READER_H - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include "unpacker.h" -#include "decoder.h" -#include "general.h" -#include "DataStream.h" - -#ifdef HAS_VORBIS_SUPPORT -#include <vorbis/vorbisfile.h> -#endif - -#define INIT_NO_ERROR_MSG 0 -#define INIT_NEED_ERROR_MSG 1 - -// Abstract Sound Reader class -class CSoundReader { -protected: - int samples; // total count of sound samples - // one sample consists of - // channels * (is16bit ? 2 : 1) bytes - int channels; - int samplerate; - int samples_left; // count of unread samples - int is16bit; // 1 - if 16 bit file, 0 - otherwise - DataStream* stream; - bool autoFree; - -public: - CSoundReader(DataStream* stream, bool autoFree = true) - - : samples( 0 ), channels( 0 ), samples_left( 0 ), is16bit( 1 ) - { - this->stream = stream; - this->autoFree = autoFree; - } - - virtual ~CSoundReader() - { - if (stream && autoFree) { - delete( stream ); - } - } - - int get_channels() - { - return channels; - } - int get_samplerate() - { - return samplerate; - } - virtual int init_reader() = 0; // initializes the sound reader - - int get_length() - { - return samples; - } // returns the total samples count - int get_samples_left() - { - return samples_left; - } - int get_bits() - { - return ( is16bit ) ? 16 : 8; - } - - virtual const char* get_file_type() = 0; - - virtual int read_samples(short* buffer, int count) = 0; // returns actual count of read samples -// virtual short read_one_sample(); // returns next sound sample - void rewind() - { - stream->Seek(0, GEM_STREAM_START ); - init_reader() ; - } -}; - -// RAW file reader -class CRawPCMReader : public CSoundReader { -public: - CRawPCMReader(DataStream* stream, int bits, int len, bool autoFree = true)//int fhandle, int bits, int len) - - : CSoundReader( stream, autoFree ) - { - is16bit = ( bits == 16 ); - samples = len; - } - - virtual int init_reader(); - virtual int read_samples(short* buffer, int count); - virtual const char* get_file_type() - { - return ( is16bit ? "RAW16" : "RAW8" ); - } -}; - -// WAV files -class CWavPCMReader : public CRawPCMReader { -public: - CWavPCMReader(DataStream* stream, int len, bool autoFree = true) - : CRawPCMReader( stream, 16, len, autoFree ) - { - } - virtual int init_reader(); - virtual const char* get_file_type() - { - return "WAV"; - } -}; - -#ifdef HAS_VORBIS_SUPPORT -class COGGReader : public CSoundReader { -private: - OggVorbis_File OggStream; -public: - COGGReader(DataStream* stream, bool autoFree = true) - : CSoundReader( stream, autoFree) - { - memset(&OggStream, 0, sizeof(OggStream) ); - } - virtual ~COGGReader() - { - ov_clear(&OggStream); - } - virtual int init_reader(); - virtual const char* get_file_type() - { - return "OGG"; - } - virtual int read_samples(short* buffer, int count); -}; -#endif //HAS_VORBIS_SUPPORT - -// IP's ACM files -class CACMReader : public CSoundReader { -private: - int levels, subblocks; - int block_size; - int* block, * values; - int samples_ready; - CValueUnpacker* unpacker; // ACM-stream unpacker - CSubbandDecoder* decoder; // IP's subband decoder - - int make_new_samples(); -public: - CACMReader(DataStream* stream, bool autoFree = true) - - : CSoundReader( stream, autoFree ), block( NULL ), values( NULL ), - samples_ready( 0 ), unpacker( NULL ), decoder( NULL ) - { - } - virtual ~CACMReader() - { - if (block) { - free(block); - } - if (unpacker) { - delete unpacker; - } - if (decoder) { - delete decoder; - } - } - - virtual int init_reader(); - virtual const char* get_file_type() - { - return "ACM"; - } - virtual int read_samples(short* buffer, int count); - - int get_levels() - { - return levels; - } - int get_subblocks() - { - return subblocks; - } -}; - - -// WAVEFORMATEX structure (from MS SDK) -struct cWAVEFORMATEX { - unsigned short wFormatTag; /* format type */ - unsigned short nChannels; /* number of channels (i.e. mono, stereo...) */ - unsigned int nSamplesPerSec; /* sample rate */ - unsigned int nAvgBytesPerSec; /* for buffer estimation */ - unsigned short nBlockAlign; /* block size of data */ - unsigned short wBitsPerSample; /* number of bits per sample of mono data */ - unsigned short cbSize; /* the count in bytes of the size of */ - /* extra information (after cbSize) */ -}; - -struct RIFF_CHUNK { - unsigned int fourcc; - unsigned int length; -}; - -const unsigned char RIFF_4cc[] = { - 'R', 'I', 'F', 'F' -}; -const unsigned char WAVE_4cc[] = { - 'W', 'A', 'V', 'E' -}; -const unsigned char fmt_4cc[] = { - 'f', 'm', 't', ' ' -}; -const unsigned char fact_4cc[] = { - 'f', 'a', 'c', 't' -}; -const unsigned char data_4cc[] = { - 'd', 'a', 't', 'a' -}; - - -// File open routine. -CSoundReader* CreateSoundReader(DataStream* stream, int open_mode, - int samples, bool autoFree = true); - -// Open modes: -#define SND_READER_AUTO 0 -#define SND_READER_RAW8 1 -#define SND_READER_RAW16 2 -#define SND_READER_WAV 3 -#define SND_READER_ACM 4 -#define SND_READER_OGG 5 - -#endif diff --git a/gemrb/plugins/ACMReader/ACMReader.cpp b/gemrb/plugins/ACMReader/ACMReader.cpp new file mode 100644 index 0000000..dd98ac6 --- /dev/null +++ b/gemrb/plugins/ACMReader/ACMReader.cpp @@ -0,0 +1,120 @@ +/* GemRB - Infinity Engine Emulator + * Copyright (C) 2003 The GemRB Project + * + * This program 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 Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "ACMReader.h" +#include "general.h" + +bool ACMReader::Open(DataStream* stream, bool autoFree) +{ + if (!Resource::Open(stream, autoFree)) + return false; + Close(); + + ACM_Header hdr; + + char Signature[4]; + ieDword SignatureDword; + stream->Read( Signature, 4 ); + stream->Seek( 0, GEM_STREAM_START ); + stream->ReadDword( &SignatureDword ); + if (!memcmp( Signature, "WAVC", 4 )) { + str->Seek( 28, GEM_STREAM_START ); + } else if (SignatureDword == IP_ACM_SIG) { + stream->Seek( 0, GEM_STREAM_START ); + } else { + return false; + } + + //str->Read( &hdr, sizeof( ACM_Header ) ); + //maybe this'll work on a PPC + + str->ReadDword( &hdr.signature ); + str->ReadDword( &hdr.samples ); + str->ReadWord( &hdr.channels ); + str->ReadWord( &hdr.rate ); + ieWord tmpword; + str->ReadWord( &tmpword ); + //subblocks = (int) (tmpword&0xfff); + //levels = (int) (tmpword>>12); + subblocks = (int) (tmpword>>4); + levels = (int) (tmpword&15); + + if (hdr.signature != IP_ACM_SIG) { + return false; + } + samples_left = ( samples = hdr.samples ); + channels = hdr.channels; + samplerate = hdr.rate; + //levels = hdr.levels; + //subblocks = hdr.subblocks; + + block_size = ( 1 << levels ) * subblocks; + //using malloc for simple arrays (supposed to be faster) + block = (int *) malloc(sizeof(int)*block_size); + if (!block) { + return false; + } + unpacker = new CValueUnpacker( levels, subblocks, str ); + if (!unpacker || !unpacker->init_unpacker()) { + return false; + } + decoder = new CSubbandDecoder( levels ); + if (!decoder || !decoder->init_decoder()) { + return false; + } + return true; +} +int ACMReader::make_new_samples() +{ + if (!unpacker->get_one_block( block )) { + return 0; + } + + decoder->decode_data( block, subblocks ); + values = block; + samples_ready = ( block_size > samples_left ) ? samples_left : block_size; + samples_left -= samples_ready; + + return 1; +} + +int ACMReader::read_samples(short* buffer, int count) +{ + int res = 0; + while (res < count) { + if (samples_ready == 0) { + if (samples_left == 0) + break; + if (!make_new_samples()) + break; + } + *buffer = ( short ) ( ( *values ) >> levels ); + values++; + buffer++; + res += 1; + samples_ready--; + } + return res; +} + +#include "plugindef.h" + +GEMRB_PLUGIN(0x10373EE, "ACM File Importer") +PLUGIN_IE_RESOURCE(ACMReader, ".acm", (ieWord)IE_ACM_CLASS_ID) +PLUGIN_IE_RESOURCE(ACMReader, ".wav", (ieWord)IE_WAV_CLASS_ID) +END_PLUGIN() diff --git a/gemrb/plugins/ACMImporter/ACMImporter.h b/gemrb/plugins/ACMReader/ACMReader.h similarity index 51% copy from gemrb/plugins/ACMImporter/ACMImporter.h copy to gemrb/plugins/ACMReader/ACMReader.h index 963521b..730d69b 100644 --- a/gemrb/plugins/ACMImporter/ACMImporter.h +++ b/gemrb/plugins/ACMReader/ACMReader.h @@ -14,46 +14,62 @@ * 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 Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * */ -#ifndef ACMIMP_H -#define ACMIMP_H +#ifndef ACMREADER_H +#define ACMREADER_H #include <stdio.h> #include <string.h> #include <stdlib.h> -#include "readers.h" +#include "unpacker.h" +#include "decoder.h" +#include "general.h" #include "DataStream.h" #include "SoundMgr.h" -#ifdef HAS_VORBIS_SUPPORT -#include <vorbis/vorbisfile.h> -#endif - -#define INIT_NO_ERROR_MSG 0 -#define INIT_NEED_ERROR_MSG 1 - -// Abstract Sound Reader class -class ACMImp : public SoundMgr { +// IP's ACM files +class ACMReader : public SoundMgr { private: - CSoundReader* SoundReader ; + int samples_left; // count of unread samples + int levels, subblocks; + int block_size; + int* block, * values; + int samples_ready; + CValueUnpacker* unpacker; // ACM-stream unpacker + CSubbandDecoder* decoder; // IP's subband decoder + int make_new_samples(); public: - ACMImp() ; - ~ACMImp() ; - void release() - { - delete this ; - } - bool Open(DataStream* stream, bool autofree ); - int get_length() ; - int get_channels() ; - int get_samplerate() ; - int read_samples(short* memory, int cnt) ; - void rewind(void) ; -}; + ACMReader() + : samples_left( 0 ), block( NULL ), values( NULL ), + samples_ready( 0 ), unpacker( NULL ), decoder( NULL ) + { + } + virtual ~ACMReader() + { + Close(); + } + void Close() + { + if (block) { + free(block); + } + if (unpacker) { + delete unpacker; + } + if (decoder) { + delete decoder; + } + } -#endif //ACMIMP_H + bool Open(DataStream* stream, bool autoFree = true); + virtual int read_samples(short* buffer, int count); +public: + void release() + { + delete this; + } +}; +#endif diff --git a/gemrb/plugins/ACMReader/CMakeLists.txt b/gemrb/plugins/ACMReader/CMakeLists.txt new file mode 100644 index 0000000..04683d3 --- /dev/null +++ b/gemrb/plugins/ACMReader/CMakeLists.txt @@ -0,0 +1,3 @@ +FILE( GLOB ACMReader_files *.cpp ) + +ADD_GEMRB_PLUGIN (ACMReader ${ACMReader_files}) diff --git a/gemrb/plugins/ACMReader/Makefile.am b/gemrb/plugins/ACMReader/Makefile.am new file mode 100644 index 0000000..bda9589 --- /dev/null +++ b/gemrb/plugins/ACMReader/Makefile.am @@ -0,0 +1,3 @@ +plugin_LTLIBRARIES = ACMReader.la +ACMReader_la_LDFLAGS = -module -avoid-version -shared +ACMReader_la_SOURCES = ACMReader.cpp ACMReader.h decoder.cpp decoder.h unpacker.cpp unpacker.h general.h diff --git a/gemrb/plugins/ACMImporter/decoder.cpp b/gemrb/plugins/ACMReader/decoder.cpp similarity index 100% rename from gemrb/plugins/ACMImporter/decoder.cpp rename to gemrb/plugins/ACMReader/decoder.cpp diff --git a/gemrb/plugins/ACMImporter/decoder.h b/gemrb/plugins/ACMReader/decoder.h similarity index 100% rename from gemrb/plugins/ACMImporter/decoder.h rename to gemrb/plugins/ACMReader/decoder.h diff --git a/gemrb/plugins/ACMImporter/general.h b/gemrb/plugins/ACMReader/general.h similarity index 100% rename from gemrb/plugins/ACMImporter/general.h rename to gemrb/plugins/ACMReader/general.h diff --git a/gemrb/plugins/ACMImporter/unpacker.cpp b/gemrb/plugins/ACMReader/unpacker.cpp similarity index 98% rename from gemrb/plugins/ACMImporter/unpacker.cpp rename to gemrb/plugins/ACMReader/unpacker.cpp index b7863a8..9e94528 100644 --- a/gemrb/plugins/ACMImporter/unpacker.cpp +++ b/gemrb/plugins/ACMReader/unpacker.cpp @@ -48,7 +48,7 @@ short Table2[125] = { // 000 001 002 003 004 010 011 012 013 014 ... // 100 101 102 103 104 ... // 200 ... -// ... +// ... unsigned char Table3[121] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x20, 0x21, @@ -178,7 +178,7 @@ int CValueUnpacker::k1_3bits(int pass, int /*ind*/) avail_bits--; next_bits >>= 1; block_ptr[i * sb_size + pass] = 0; if (( ++i ) == subblocks) - break; + break; block_ptr[i * sb_size + pass] = 0; } else if (( next_bits & 2 ) == 0) { avail_bits -= 2; @@ -251,7 +251,7 @@ int CValueUnpacker::k2_4bits(int pass, int /*ind*/) avail_bits--; next_bits >>= 1; block_ptr[i * sb_size + pass] = 0; if (( ++i ) == subblocks) - break; + break; block_ptr[i * sb_size + pass] = 0; } else if (( next_bits & 2 ) == 0) { avail_bits -= 2; @@ -323,7 +323,7 @@ int CValueUnpacker::k3_5bits(int pass, int /*ind*/) avail_bits--; next_bits >>= 1; block_ptr[i * sb_size + pass] = 0; if (( ++i ) == subblocks) - break; + break; block_ptr[i * sb_size + pass] = 0; } else if (( next_bits & 2 ) == 0) { avail_bits -= 2; @@ -331,10 +331,10 @@ int CValueUnpacker::k3_5bits(int pass, int /*ind*/) block_ptr[i * sb_size + pass] = 0; } else if (( next_bits & 4 ) == 0) { block_ptr[i * sb_size + pass] = ( next_bits & 8 ) ? - buff_middle[1] : - buff_middle[-1]; - avail_bits -= 4; - next_bits >>= 4; + buff_middle[1] : + buff_middle[-1]; + avail_bits -= 4; + next_bits >>= 4; } else { avail_bits -= 5; int val = ( next_bits & 0x18 ) >> 3; @@ -385,7 +385,7 @@ int CValueUnpacker::k4_5bits(int pass, int /*ind*/) avail_bits--; next_bits >>= 1; block_ptr[i * sb_size + pass] = 0; if (( ++i ) == subblocks) - break; + break; block_ptr[i * sb_size + pass] = 0; } else if (( next_bits & 2 ) == 0) { avail_bits -= 2; diff --git a/gemrb/plugins/ACMImporter/unpacker.h b/gemrb/plugins/ACMReader/unpacker.h similarity index 100% rename from gemrb/plugins/ACMImporter/unpacker.h rename to gemrb/plugins/ACMReader/unpacker.h diff --git a/gemrb/plugins/CMakeLists.txt b/gemrb/plugins/CMakeLists.txt index 9bbdf13..10569f8 100644 --- a/gemrb/plugins/CMakeLists.txt +++ b/gemrb/plugins/CMakeLists.txt @@ -1,5 +1,7 @@ ADD_SUBDIRECTORY( 2DAImporter ) -ADD_SUBDIRECTORY( ACMImporter ) +ADD_SUBDIRECTORY( ACMReader ) +ADD_SUBDIRECTORY( WAVReader ) +ADD_SUBDIRECTORY( OGGReader ) ADD_SUBDIRECTORY( AREImporter ) ADD_SUBDIRECTORY( BAMImporter ) ADD_SUBDIRECTORY( BIFImporter ) diff --git a/gemrb/plugins/DirectoryImporter/DirectoryImporter.cpp b/gemrb/plugins/DirectoryImporter/DirectoryImporter.cpp index b37774f..78ddd99 100644 --- a/gemrb/plugins/DirectoryImporter/DirectoryImporter.cpp +++ b/gemrb/plugins/DirectoryImporter/DirectoryImporter.cpp @@ -14,9 +14,6 @@ * 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 Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $Id$ - * */ #include "win32def.h" diff --git a/gemrb/plugins/DirectoryImporter/DirectoryImporter.h b/gemrb/plugins/DirectoryImporter/DirectoryImporter.h index eda45b0..52dddb2 100644 --- a/gemrb/plugins/DirectoryImporter/DirectoryImporter.h +++ b/gemrb/plugins/DirectoryImporter/DirectoryImporter.h @@ -14,9 +14,6 @@ * 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 Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $Id$ - * */ #ifndef KEYIMP_H diff --git a/gemrb/plugins/MUSImporter/MUSImporter.cpp b/gemrb/plugins/MUSImporter/MUSImporter.cpp index f48b268..577d2a5 100644 --- a/gemrb/plugins/MUSImporter/MUSImporter.cpp +++ b/gemrb/plugins/MUSImporter/MUSImporter.cpp @@ -260,9 +260,9 @@ void MUSImporter::PlayNext() PLnext = -1; else PLnext = PLpos + 1; - if ((unsigned int) PLnext >= playlist.size() ) { - PLnext = 0; - } + if ((unsigned int) PLnext >= playlist.size() ) { + PLnext = 0; + } } } else { Playing = false; @@ -290,19 +290,13 @@ void MUSImporter::PlayMusic(char* name) strncpy(FName, name, _MAX_PATH); } - DataStream *stream = manager.GetResource(FName, IE_ACM_CLASS_ID); - SoundMgr* sound = (SoundMgr*) core->GetInterface(IE_WAV_CLASS_ID); - if (!sound->Open(stream)) { - sound->release(); - printMessage("MUSImporter", "",WHITE); - printf( "Cannot open %s...", FName ); - printStatus("NOT FOUND", YELLOW ); - core->GetAudioDrv()->Stop(); - } else { + if (SoundMgr* sound = (SoundMgr*) manager.GetResource(FName, &SoundMgr::ID)) { int soundID = core->GetAudioDrv()->CreateStream( sound ); if (soundID == -1) { core->GetAudioDrv()->Stop(); } + } else { + core->GetAudioDrv()->Stop(); } printf( "Playing: %s\n", FName ); } diff --git a/gemrb/plugins/Makefile.am b/gemrb/plugins/Makefile.am index f1f21aa..22207c0 100644 --- a/gemrb/plugins/Makefile.am +++ b/gemrb/plugins/Makefile.am @@ -4,7 +4,9 @@ SUBDIRS = \ OpenALAudio \ ZLibManager \ 2DAImporter \ - ACMImporter \ + ACMReader \ + OGGReader \ + WAVReader \ NullSound \ AREImporter \ BAMImporter \ diff --git a/gemrb/plugins/OGGReader/CMakeLists.txt b/gemrb/plugins/OGGReader/CMakeLists.txt new file mode 100644 index 0000000..e7da2f9 --- /dev/null +++ b/gemrb/plugins/OGGReader/CMakeLists.txt @@ -0,0 +1,7 @@ +IF (VORBIS_LIBRARY) + FILE( GLOB OGGReader_files *.cpp ) + + ADD_GEMRB_PLUGIN (OGGReader ${OGGReader_files}) + + TARGET_LINK_LIBRARIES(OGGReader ${VORBIS_LIBRARY}) +ENDIF (VORBIS_LIBRARY) diff --git a/gemrb/plugins/OGGReader/Makefile.am b/gemrb/plugins/OGGReader/Makefile.am new file mode 100644 index 0000000..7a1e7eb --- /dev/null +++ b/gemrb/plugins/OGGReader/Makefile.am @@ -0,0 +1,6 @@ +if VORBIS +plugin_LTLIBRARIES = OGGReader.la +OGGReader_la_LDFLAGS = -module -avoid-version -shared +OGGReader_la_LIBADD = -lvorbisfile -lvorbis +OGGReader_la_SOURCES = OGGReader.cpp OGGReader.h +endif diff --git a/gemrb/plugins/OGGReader/OGGReader.cpp b/gemrb/plugins/OGGReader/OGGReader.cpp new file mode 100644 index 0000000..ed42d1c --- /dev/null +++ b/gemrb/plugins/OGGReader/OGGReader.cpp @@ -0,0 +1,129 @@ +/* GemRB - Infinity Engine Emulator + * Copyright (C) 2003 The GemRB Project + * + * This program 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 Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "OGGReader.h" + +static size_t ovfd_read(void *ptr, size_t size, size_t nmemb, void *datasource) +{ + DataStream *vb = (DataStream *) datasource; + int bytesToRead = size * nmemb; + + int remains = vb->Remains(); + if(remains<=0) { + /* no more reading, we're at the end */ + return 0; + } + if(bytesToRead > remains ) { + bytesToRead = remains; + } + vb->Read(ptr, bytesToRead); + return bytesToRead; +} + +static int ovfd_seek(void *datasource, ogg_int64_t offset, int whence) { + DataStream *vb = (DataStream *) datasource; + switch(whence) { + case SEEK_SET: + if(vb->Seek(offset, GEM_STREAM_START)<0) + return -1; + break; + case SEEK_CUR: + if(vb->Seek(offset, GEM_CURRENT_POS)<0) + return -1; + break; + case SEEK_END: + if(vb->Seek(vb->Size()+offset, GEM_STREAM_START)<0) + return -1; + break; + default: + return -1; + } + return vb->GetPos(); +} + +static int ovfd_close(void * /*datasource*/) { + return 0; +} + +static long ovfd_tell(void *datasource) { + DataStream *vb = (DataStream *) datasource; + return (long) vb->GetPos(); +} + +bool OGGReader::Open(DataStream* stream, bool autoFree) +{ + if (!Resource::Open(stream, autoFree)) + return false; + Close(); + + char Signature[4]; + stream->Read( Signature, 4 ); + stream->Seek( 0, GEM_STREAM_START ); + if(strnicmp(Signature, "oggs", 4) != 0) + return false; + + vorbis_info *info; + int res; + ov_callbacks cbstruct = { + ovfd_read, ovfd_seek, ovfd_close, ovfd_tell + }; + + res=ov_open_callbacks(str, &OggStream, NULL, 0, cbstruct); + if(res<0) { + printMessage("Sound","Couldn't initialize vorbis!\n", LIGHT_RED); + return false; + } + info = ov_info(&OggStream, -1); + channels = info->channels; + samplerate = info->rate; + samples_left = ( samples = ov_pcm_total(&OggStream, -1) ); + return true; +} + +int OGGReader::read_samples(short* buffer, int count) +{ + int whatisthis; + + if(samples_left<count) { + count=samples_left; + } + int samples_got=0; + int samples_need=count; + while(samples_need) { + int rd=ov_read(&OggStream, (char *)buffer, samples_need<<1, str->IsEndianSwitch(), 2, 1, &whatisthis); + if(rd==OV_HOLE) { + continue; + } + if(rd<=0) { + break; + } + rd>>=1; + buffer+=rd; + samples_got+=rd; + samples_need-=rd; + } + samples_left-=samples_got; + + return samples_got; +} + +#include "plugindef.h" + +GEMRB_PLUGIN(0x18C310C3, "OGG File Importer") +PLUGIN_RESOURCE(OGGReader, ".ogg") +END_PLUGIN() diff --git a/gemrb/plugins/ACMImporter/ACMImporter.h b/gemrb/plugins/OGGReader/OGGReader.h similarity index 64% copy from gemrb/plugins/ACMImporter/ACMImporter.h copy to gemrb/plugins/OGGReader/OGGReader.h index 963521b..7b052c7 100644 --- a/gemrb/plugins/ACMImporter/ACMImporter.h +++ b/gemrb/plugins/OGGReader/OGGReader.h @@ -14,46 +14,44 @@ * 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 Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * */ -#ifndef ACMIMP_H -#define ACMIMP_H +#ifndef ACMREADER_H +#define ACMREADER_H #include <stdio.h> #include <string.h> #include <stdlib.h> -#include "readers.h" #include "DataStream.h" #include "SoundMgr.h" -#ifdef HAS_VORBIS_SUPPORT #include <vorbis/vorbisfile.h> -#endif - -#define INIT_NO_ERROR_MSG 0 -#define INIT_NEED_ERROR_MSG 1 -// Abstract Sound Reader class -class ACMImp : public SoundMgr { +class OGGReader : public SoundMgr { private: - CSoundReader* SoundReader ; - + OggVorbis_File OggStream; + int samples_left; // count of unread samples +public: + OGGReader() + : samples_left( 0 ) + { + memset(&OggStream, 0, sizeof(OggStream) ); + } + virtual ~OGGReader() + { + Close(); + } + void Close() + { + ov_clear(&OggStream); + } + bool Open(DataStream* stream, bool autoFree = true); + int read_samples(short* buffer, int count); public: - ACMImp() ; - ~ACMImp() ; - void release() - { - delete this ; - } - bool Open(DataStream* stream, bool autofree ); - int get_length() ; - int get_channels() ; - int get_samplerate() ; - int read_samples(short* memory, int cnt) ; - void rewind(void) ; + void release(void) + { + delete this; + } }; -#endif //ACMIMP_H - +#endif diff --git a/gemrb/plugins/OpenALAudio/OpenALAudio.cpp b/gemrb/plugins/OpenALAudio/OpenALAudio.cpp index c4f76d9..f44651d 100644 --- a/gemrb/plugins/OpenALAudio/OpenALAudio.cpp +++ b/gemrb/plugins/OpenALAudio/OpenALAudio.cpp @@ -231,22 +231,15 @@ ALuint OpenALAudioDriver::loadSound(const char *ResRef, unsigned int &time_lengt time_length = e->Length; return e->Buffer; } - //no cache entry... - DataStream* stream = gamedata->GetResource(ResRef, IE_WAV_CLASS_ID); - if (!stream) - stream = gamedata->GetResource(ResRef, IE_OGG_CLASS_ID); - if (!stream) - return 0; + //no cache entry... alGenBuffers(1, &Buffer); if (checkALError("Unable to create sound buffer", "ERROR")) { - delete stream; return 0; } - SoundMgr* acm = (SoundMgr*) core->GetInterface(IE_WAV_CLASS_ID); - if (!acm->Open(stream)) { - acm->release(); + SoundMgr* acm = (SoundMgr*) gamedata->GetResource(ResRef, &SoundMgr::ID); + if (!acm) { alDeleteBuffers( 1, &Buffer ); return 0; } diff --git a/gemrb/plugins/WAVReader/CMakeLists.txt b/gemrb/plugins/WAVReader/CMakeLists.txt new file mode 100644 index 0000000..89df945 --- /dev/null +++ b/gemrb/plugins/WAVReader/CMakeLists.txt @@ -0,0 +1,3 @@ +FILE( GLOB WAVReader_files *.cpp ) + +ADD_GEMRB_PLUGIN (WAVReader ${WAVReader_files}) diff --git a/gemrb/plugins/WAVReader/Makefile.am b/gemrb/plugins/WAVReader/Makefile.am new file mode 100644 index 0000000..768fb1e --- /dev/null +++ b/gemrb/plugins/WAVReader/Makefile.am @@ -0,0 +1,3 @@ +plugin_LTLIBRARIES = WAVReader.la +WAVReader_la_LDFLAGS = -module -avoid-version -shared +WAVReader_la_SOURCES = WAVReader.cpp WAVReader.h diff --git a/gemrb/plugins/WAVReader/WAVReader.cpp b/gemrb/plugins/WAVReader/WAVReader.cpp new file mode 100644 index 0000000..e2e7dbc --- /dev/null +++ b/gemrb/plugins/WAVReader/WAVReader.cpp @@ -0,0 +1,193 @@ +/* GemRB - Infinity Engine Emulator + * Copyright (C) 2003 The GemRB Project + * + * This program 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 Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "WAVReader.h" +#include <utility> + +// WAVEFORMATEX structure (from MS SDK) +struct cWAVEFORMATEX { + unsigned short wFormatTag; /* format type */ + unsigned short nChannels; /* number of channels (i.e. mono, stereo...) */ + unsigned int nSamplesPerSec; /* sample rate */ + unsigned int nAvgBytesPerSec; /* for buffer estimation */ + unsigned short nBlockAlign; /* block size of data */ + unsigned short wBitsPerSample; /* number of bits per sample of mono data */ + unsigned short cbSize; /* the count in bytes of the size of */ + /* extra information (after cbSize) */ +}; + +struct RIFF_CHUNK { + unsigned int fourcc; + unsigned int length; +}; + +const unsigned char RIFF_4cc[] = { + 'R', 'I', 'F', 'F' +}; +const unsigned char WAVE_4cc[] = { + 'W', 'A', 'V', 'E' +}; +const unsigned char fmt_4cc[] = { + 'f', 'm', 't', ' ' +}; +const unsigned char fact_4cc[] = { + 'f', 'a', 'c', 't' +}; +const unsigned char data_4cc[] = { + 'd', 'a', 't', 'a' +}; + +bool RawPCMReader::Open(DataStream* stream, bool autoFree) +{ + if (!Resource::Open(stream, autoFree)) + return false; + + samples = str->Size(); + str->Seek( 0, GEM_STREAM_START ); + if (is16bit) { + samples >>= 1; // each sample has 16 bit + } + samples_left = samples; + return 1; +} + +inline void fix_endian(ieDword &dest) +{ + std::swap(((unsigned char *) &dest)[0],((unsigned char *) &dest)[3]); + std::swap(((unsigned char *) &dest)[1],((unsigned char *) &dest)[2]); +} + +inline void fix_endian(ieWord &dest) +{ + std::swap(((unsigned char *) &dest)[0],((unsigned char *) &dest)[1]); +} + +int RawPCMReader::read_samples(short* buffer, int count) +{ + if (count > samples_left) { + count = samples_left; + } + int res = 0; + if (count) { + res = str->Read( buffer, count * ( ( is16bit ? 2 : 1 ) ) ); + } + if (!is16bit) { + char* alt_buff = ( char* ) buffer; + int i = res; + while(i--) { + alt_buff[( i << 1 ) + 1] = ( char ) ( alt_buff[i] - 0x80 ); + alt_buff[i << 1] = 0; + } + } + if(is16bit) { + res >>= 1; + if (str->IsEndianSwitch()) { + for (size_t i = 0; i < (size_t)count; i++) { + fix_endian(((ieWord *)buffer)[i]); + } + } + } + samples_left -= res; + return res; +} + +bool WavPCMReader::Open(DataStream* stream, bool autoFree) +{ + if (!RawPCMReader::Open(stream, autoFree)) + return false; + + char Signature[4]; + stream->Read( Signature, 4 ); + stream->Seek( 0, GEM_STREAM_START ); + if(strnicmp(Signature, "RIFF", 4) != 0) + return false; + + cWAVEFORMATEX fmt; + RIFF_CHUNK r_hdr, fmt_hdr, data_hdr; + unsigned int wave; + memset( &fmt, 0, sizeof( fmt ) ); + + //str->Read( &r_hdr, sizeof( r_hdr ) ); + //don't swap this + str->Read(&r_hdr.fourcc, 4); + str->ReadDword(&r_hdr.length); + //don't swap this + str->Read( &wave, 4 ); + if (r_hdr.fourcc != *( unsigned int * ) RIFF_4cc || + wave != *( unsigned int * ) WAVE_4cc) { + return false; + } + + //str->Read( &fmt_hdr, sizeof( fmt_hdr ) ); + //don't swap this + str->Read(&fmt_hdr.fourcc,4); + str->ReadDword(&fmt_hdr.length); + if (fmt_hdr.fourcc != *( unsigned int * ) fmt_4cc || + fmt_hdr.length > sizeof( cWAVEFORMATEX )) { + return false; + } + memset(&fmt,0,sizeof(fmt) ); + str->Read( &fmt, fmt_hdr.length ); + //hmm, we should swap fmt bytes if we are on a mac + //but we don't know exactly how much of the structure we'll read + //so we have to swap the bytes after reading them + if (str->IsEndianSwitch()) { + fix_endian(fmt.wFormatTag); + fix_endian(fmt.nChannels); + fix_endian(fmt.nSamplesPerSec); + fix_endian(fmt.wBitsPerSample); + //we don't use these fields, so who cares + //fix_endian(fmt.nAvgBytesPerSec); + //fix_endian(fmt.nBlockAlign); + //fix_endian(fmt.cbSize); + } + if (fmt.wFormatTag != 1) { + return false; + } + is16bit = ( fmt.wBitsPerSample == 16 ); + + //str->Read( &data_hdr, sizeof( data_hdr ) ); + //don't swap this + str->Read(&data_hdr.fourcc,4); + str->ReadDword(&data_hdr.length); + + if (data_hdr.fourcc == *( unsigned int * ) fact_4cc) { + str->Seek( data_hdr.length, GEM_CURRENT_POS ); + //str->Read( &data_hdr, sizeof( data_hdr ) ); + str->ReadDword(&data_hdr.fourcc); + str->ReadDword(&data_hdr.length); + } + if (data_hdr.fourcc != *( unsigned int * ) data_4cc) { + return false; + } + + samples = data_hdr.length; + if (is16bit) { + samples >>= 1; + } + samples_left = samples; + channels = fmt.nChannels; + samplerate = fmt.nSamplesPerSec; + return true; +} + +#include "plugindef.h" + +GEMRB_PLUGIN(0x11BB1288, "WAV File Importer") +PLUGIN_IE_RESOURCE(WavPCMReader, ".wav", (ieWord)IE_WAV_CLASS_ID) +END_PLUGIN() diff --git a/gemrb/plugins/ACMImporter/ACMImporter.h b/gemrb/plugins/WAVReader/WAVReader.h similarity index 58% rename from gemrb/plugins/ACMImporter/ACMImporter.h rename to gemrb/plugins/WAVReader/WAVReader.h index 963521b..480b110 100644 --- a/gemrb/plugins/ACMImporter/ACMImporter.h +++ b/gemrb/plugins/WAVReader/WAVReader.h @@ -18,42 +18,45 @@ * */ -#ifndef ACMIMP_H -#define ACMIMP_H +#ifndef WAVREADER_H +#define WAVREADER_H #include <stdio.h> #include <string.h> #include <stdlib.h> -#include "readers.h" #include "DataStream.h" #include "SoundMgr.h" -#ifdef HAS_VORBIS_SUPPORT -#include <vorbis/vorbisfile.h> -#endif - -#define INIT_NO_ERROR_MSG 0 -#define INIT_NEED_ERROR_MSG 1 - -// Abstract Sound Reader class -class ACMImp : public SoundMgr { -private: - CSoundReader* SoundReader ; +// RAW file reader +class RawPCMReader : public SoundMgr { +protected: + // one sample consists of + // channels * (is16bit ? 2 : 1) bytes + int samples_left; // count of unread samples + int is16bit; // 1 - if 16 bit file, 0 - otherwise +public: + RawPCMReader(int bits) + : is16bit( bits == 16 ) + { + } + bool Open(DataStream* stream, bool autoFree = true); + virtual int read_samples(short* buffer, int count); public: - ACMImp() ; - ~ACMImp() ; - void release() - { - delete this ; - } - bool Open(DataStream* stream, bool autofree ); - int get_length() ; - int get_channels() ; - int get_samplerate() ; - int read_samples(short* memory, int cnt) ; - void rewind(void) ; + void release(void) + { + delete this; + } }; -#endif //ACMIMP_H +// WAV files +class WavPCMReader : public RawPCMReader { +public: + WavPCMReader() + : RawPCMReader( 16 ) + { + } + bool Open(DataStream* stream, bool autoFree = true); +}; +#endif http://gemrb.git.sourceforge.net/git/gitweb.cgi?p=gemrb/gemrb;a=commitdiff;h=80979b41a59388876bbdcfa27c959b30587e165b commit 80979b41a59388876bbdcfa27c959b30587e165b Author: Tom Prince <tom...@ua...> Date: Tue Apr 20 19:19:24 2010 -0400 ResourceManager: Don't assume that resource names are limited to 8 characters. Using resource manger for sounds, we pass in pathnames, rather than filenames, so they can be longer than 8 characters. diff --git a/gemrb/core/ResourceManager.cpp b/gemrb/core/ResourceManager.cpp index 3d23450..f70b35d 100644 --- a/gemrb/core/ResourceManager.cpp +++ b/gemrb/core/ResourceManager.cpp @@ -53,7 +53,7 @@ static void PrintPossibleFiles(const char* ResRef, const TypeID *type) { const std::vector<ResourceDesc>& types = core->GetPluginMgr()->GetResourceDesc(type); for (size_t j = 0; j < types.size(); j++) { - printf("%.8s%s ", ResRef, types[j].GetExt()); + printf("%s%s ", ResRef, types[j].GetExt()); } } @@ -69,7 +69,7 @@ bool ResourceManager::Exists(const char *ResRef, SClass_ID type, bool silent) } if (!silent) { printMessage( "ResourceManager", "Searching for ", WHITE ); - printf( "%.8s%s...", ResRef, core->TypeExt( type ) ); + printf( "%s%s...", ResRef, core->TypeExt( type ) ); printStatus( "NOT FOUND", YELLOW ); } return false; @@ -90,7 +90,7 @@ bool ResourceManager::Exists(const char *ResRef, const TypeID *type, bool silent } if (!silent) { printMessage( "ResourceManager", "Searching for ", WHITE ); - printf( "%.8s... ", ResRef ); + printf( "%s... ", ResRef ); printf("Tried "); PrintPossibleFiles(ResRef,type); printStatus( "NOT FOUND", YELLOW ); @@ -104,7 +104,7 @@ DataStream* ResourceManager::GetResource(const char* ResRef, SClass_ID type, boo return false; if (!silent) { printMessage( "ResourceManager", "Searching for ", WHITE ); - printf( "%.8s%s...", ResRef, core->TypeExt( type ) ); + printf( "%s%s...", ResRef, core->TypeExt( type ) ); } for (size_t i = 0; i < searchPath.size(); i++) { DataStream *ds = searchPath[i]->GetResource(ResRef, type); @@ -136,7 +136,7 @@ Resource* ResourceManager::GetResource(const char* ResRef, const TypeID *type, b Resource *res = types[j].Create(str); if (res) { if (!silent) { - printf( "%.8s%s...", ResRef, types[j].GetExt() ); + printf( "%s%s...", ResRef, types[j].GetExt() ); printStatus( searchPath[i]->GetDescription(), GREEN ); } return res; http://gemrb.git.sourceforge.net/git/gitweb.cgi?p=gemrb/gemrb;a=commitdiff;h=1669ac8b2431ceb99148d4f5bf86c047bf57edb6 commit 1669ac8b2431ceb99148d4f5bf86c047bf57edb6 Author: Tom Prince <tom...@ua...> Date: Thu Mar 25 23:49:32 2010 -0400 MUSImporter: Switch to using DirectoryImporter, rather than opening files directly. This is in preparation for turning SoundMgr into a Resource. Signed-off-by: Tom Prince <tom...@ua...> diff --git a/gemrb/core/Audio.h b/gemrb/core/Audio.h index 909aa0c..7db71a7 100644 --- a/gemrb/core/Audio.h +++ b/gemrb/core/Audio.h @@ -30,6 +30,7 @@ #define GEM_SND_VOL_MUSIC 1 #define GEM_SND_VOL_AMBIENTS 2 +class SoundMgr; class AmbientMgr; class GEM_EXPORT Audio : public Plugin { @@ -45,7 +46,7 @@ public: virtual void ResetMusics() = 0; virtual bool Play() = 0; virtual bool Stop() = 0; - virtual int StreamFile(const char* fileName ) = 0; + virtual int CreateStream(SoundMgr*) = 0; virtual void UpdateListenerPos(int XPos, int YPos ) = 0; virtual void GetListenerPos(int &XPos, int &YPos ) = 0; virtual bool ReleaseStream(int stream, bool HardStop=false ) = 0; diff --git a/gemrb/plugins/MUSImporter/MUSImporter.cpp b/gemrb/plugins/MUSImporter/MUSImporter.cpp index 4872a23..f48b268 100644 --- a/gemrb/plugins/MUSImporter/MUSImporter.cpp +++ b/gemrb/plugins/MUSImporter/MUSImporter.cpp @@ -22,6 +22,7 @@ #include "MUSImporter.h" #include "Interface.h" #include "... [truncated message content] |