From 9cf42f6d0fcde91c25f5ffe0027cd186223421aa Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 17 Mar 2012 02:51:46 -0700 Subject: [PATCH] Flesh out the sound decoder a bit more --- apps/openmw/mwsound/ffmpeg_decoder.cpp | 15 ++++ apps/openmw/mwsound/ffmpeg_decoder.hpp | 3 + apps/openmw/mwsound/mpgsnd_decoder.cpp | 95 +++++++++++++++++++++++++- apps/openmw/mwsound/mpgsnd_decoder.hpp | 9 +++ apps/openmw/mwsound/sound_decoder.hpp | 11 +++ 5 files changed, 132 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwsound/ffmpeg_decoder.cpp b/apps/openmw/mwsound/ffmpeg_decoder.cpp index 8bd6b3f8e..d3715d5fe 100644 --- a/apps/openmw/mwsound/ffmpeg_decoder.cpp +++ b/apps/openmw/mwsound/ffmpeg_decoder.cpp @@ -6,8 +6,12 @@ namespace MWSound { +static void fail(const std::string &msg) +{ throw std::runtime_error("FFmpeg exception: "+msg); } + bool FFmpeg_Decoder::Open(const std::string &fname) { + fail("Not currently working"); return false; } @@ -15,6 +19,17 @@ void FFmpeg_Decoder::Close() { } +void FFmpeg_Decoder::GetInfo(int *samplerate, ChannelConfig *chans, SampleType *type) +{ + fail("Not currently working"); +} + +size_t FFmpeg_Decoder::Read(char *buffer, size_t bytes) +{ + fail("Not currently working"); + return 0; +} + FFmpeg_Decoder::FFmpeg_Decoder() { diff --git a/apps/openmw/mwsound/ffmpeg_decoder.hpp b/apps/openmw/mwsound/ffmpeg_decoder.hpp index 2b7363f26..6ff93904a 100644 --- a/apps/openmw/mwsound/ffmpeg_decoder.hpp +++ b/apps/openmw/mwsound/ffmpeg_decoder.hpp @@ -19,6 +19,9 @@ namespace MWSound virtual bool Open(const std::string &fname); virtual void Close(); + virtual void GetInfo(int *samplerate, ChannelConfig *chans, SampleType *type); + virtual size_t Read(char *buffer, size_t bytes); + FFmpeg_Decoder(); virtual ~FFmpeg_Decoder(); diff --git a/apps/openmw/mwsound/mpgsnd_decoder.cpp b/apps/openmw/mwsound/mpgsnd_decoder.cpp index 6ca46381d..4ba48f607 100644 --- a/apps/openmw/mwsound/mpgsnd_decoder.cpp +++ b/apps/openmw/mwsound/mpgsnd_decoder.cpp @@ -1,22 +1,115 @@ #ifdef OPENMW_USE_MPG123 +#include +#include + #include "mpgsnd_decoder.hpp" +static void fail(const std::string &msg) +{ throw std::runtime_error("MpgSnd exception: "+msg); } + namespace MWSound { bool MpgSnd_Decoder::Open(const std::string &fname) { + Close(); + + SF_INFO info; + sndFile = sf_open(fname.c_str(), SFM_READ, &info); + if(sndFile) + { + if(info.channels == 1) + chanConfig = MonoChannels; + else if(info.channels == 1) + chanConfig = MonoChannels; + else + { + sf_close(sndFile); + sndFile = NULL; + fail("Unsupported channel count in "+fname); + } + sampleRate = info.samplerate; + return true; + } + + mpgFile = mpg123_new(NULL, NULL); + if(mpgFile && mpg123_open(mpgFile, fname.c_str()) == MPG123_OK) + { + try + { + int encoding, channels; + long rate; + if(mpg123_getformat(mpgFile, &rate, &channels, &encoding) != MPG123_OK) + fail("Failed to get audio format"); + if(encoding != MPG123_ENC_SIGNED_16) + fail("Unsupported encoding in "+fname); + if(channels != 1 && channels != 2) + fail("Unsupported channel count in "+fname); + chanConfig = ((channels==2)?StereoChannels:MonoChannels); + sampleRate = rate; + return true; + } + catch(std::exception &e) + { + mpg123_close(mpgFile); + mpg123_delete(mpgFile); + throw; + } + mpg123_close(mpgFile); + } + if(mpgFile) + mpg123_delete(mpgFile); + mpgFile = NULL; + + fail("Unsupported file type: "+fname); return false; } void MpgSnd_Decoder::Close() { + if(sndFile) + sf_close(sndFile); + sndFile = NULL; + + if(mpgFile) + { + mpg123_close(mpgFile); + mpg123_delete(mpgFile); + mpgFile = NULL; + } } +void MpgSnd_Decoder::GetInfo(int *samplerate, ChannelConfig *chans, SampleType *type) +{ + if(!sndFile && !mpgFile) + fail("No open file"); -MpgSnd_Decoder::MpgSnd_Decoder() + *samplerate = sampleRate; + *chans = chanConfig; + *type = Int16Sample; +} + +size_t MpgSnd_Decoder::Read(char *buffer, size_t bytes) +{ + size_t got = 0; + + if(sndFile) + { + got = sf_read_short(sndFile, (short*)buffer, bytes/2)*2; + } + else if(mpgFile) + { + int err; + err = mpg123_read(mpgFile, (unsigned char*)buffer, bytes, &got); + if(err != MPG123_OK && err != MPG123_DONE) + fail("Failed to read from file"); + } + return got; +} + +MpgSnd_Decoder::MpgSnd_Decoder() : sndFile(NULL), mpgFile(NULL) { static bool initdone = false; if(!initdone) diff --git a/apps/openmw/mwsound/mpgsnd_decoder.hpp b/apps/openmw/mwsound/mpgsnd_decoder.hpp index ffa9037a7..641d891a3 100644 --- a/apps/openmw/mwsound/mpgsnd_decoder.hpp +++ b/apps/openmw/mwsound/mpgsnd_decoder.hpp @@ -13,9 +13,18 @@ namespace MWSound { class MpgSnd_Decoder : public Sound_Decoder { + SNDFILE *sndFile; + mpg123_handle *mpgFile; + + ChannelConfig chanConfig; + int sampleRate; + virtual bool Open(const std::string &fname); virtual void Close(); + virtual void GetInfo(int *samplerate, ChannelConfig *chans, SampleType *type); + virtual size_t Read(char *buffer, size_t bytes); + MpgSnd_Decoder(); virtual ~MpgSnd_Decoder(); diff --git a/apps/openmw/mwsound/sound_decoder.hpp b/apps/openmw/mwsound/sound_decoder.hpp index 0d7e3d9f8..fd8f4ac51 100644 --- a/apps/openmw/mwsound/sound_decoder.hpp +++ b/apps/openmw/mwsound/sound_decoder.hpp @@ -6,9 +6,20 @@ namespace MWSound class Sound_Decoder { public: + enum SampleType { + UInt8Sample, + Int16Sample + }; + enum ChannelConfig { + MonoChannels, + StereoChannels + }; virtual bool Open(const std::string &fname) = 0; virtual void Close() = 0; + virtual void GetInfo(int *samplerate, ChannelConfig *chans, SampleType *type) = 0; + virtual size_t Read(char *buffer, size_t bytes) = 0; + virtual ~Sound_Decoder() { } friend class OpenAL_Output;