From 6cc0f1735a00e8f9eb80ff0c9468fb67205f6d20 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Tue, 20 Nov 2012 16:48:04 +0200 Subject: [PATCH] Split Sound into SoundDecoder and Waveform parts --- source/buffer.cpp | 18 ++--- source/buffer.h | 4 +- source/jukebox.cpp | 20 +++--- source/jukebox.h | 4 +- source/{sound.cpp => sounddecoder.cpp} | 93 ++++++-------------------- source/{sound.h => sounddecoder.h} | 12 +--- source/streamer.cpp | 22 +++--- source/streamer.h | 12 ++-- source/waveform.cpp | 50 ++++++++++++++ source/waveform.h | 37 ++++++++++ 10 files changed, 150 insertions(+), 122 deletions(-) rename source/{sound.cpp => sounddecoder.cpp} (61%) rename source/{sound.h => sounddecoder.h} (79%) create mode 100644 source/waveform.cpp create mode 100644 source/waveform.h diff --git a/source/buffer.cpp b/source/buffer.cpp index 1d7510e..5aef1b4 100644 --- a/source/buffer.cpp +++ b/source/buffer.cpp @@ -1,5 +1,5 @@ #include "buffer.h" -#include "sound.h" +#include "waveform.h" using namespace std; @@ -21,17 +21,17 @@ void Buffer::data(Format fmt, const void *dt, sizei size, sizei freq) alBufferData(id, fmt, dt, size, freq); } -void Buffer::data(const Sound &snd) +void Buffer::data(const Waveform &wave) { - data(snd.get_format(), snd.get_data(), snd.get_size(), snd.get_frequency()); + data(wave.get_format(), wave.get_data(), wave.get_size(), wave.get_frequency()); } void Buffer::load_data(const string &fn) { - Sound sound; - sound.load_file(fn); + Waveform wave; + wave.load_file(fn); - data(sound); + data(wave); } @@ -43,10 +43,10 @@ Buffer::Loader::Loader(Buffer &b): void Buffer::Loader::sound_data(const string &data) { - Sound sound; - sound.load_memory(data.data(), data.size()); + Waveform wave; + wave.load_memory(data.data(), data.size()); - buf.data(sound); + buf.data(wave); } } // namespace AL diff --git a/source/buffer.h b/source/buffer.h index d84e46a..38ca36d 100644 --- a/source/buffer.h +++ b/source/buffer.h @@ -10,7 +10,7 @@ namespace Msp { namespace AL { -class Sound; +class Waveform; /** Buffers are used to store audio data and feed it into a Source. @@ -38,7 +38,7 @@ public: uint get_id() const { return id; } void data(Format, const void *, sizei, sizei); - void data(const Sound &); + void data(const Waveform &); void load_data(const std::string &); }; diff --git a/source/jukebox.cpp b/source/jukebox.cpp index d2a997d..02a33cd 100644 --- a/source/jukebox.cpp +++ b/source/jukebox.cpp @@ -2,7 +2,7 @@ #include #include #include "jukebox.h" -#include "sound.h" +#include "sounddecoder.h" using namespace std; @@ -11,7 +11,7 @@ namespace AL { Jukebox::Jukebox(): streamer(source), - sound(0), + decoder(0), current_track(tracks.end()), shuffle(false) { } @@ -19,7 +19,7 @@ Jukebox::Jukebox(): Jukebox::~Jukebox() { streamer.stop(); - delete sound; + delete decoder; } void Jukebox::add_track(const string &trk) @@ -67,12 +67,12 @@ void Jukebox::set_shuffle(bool s) void Jukebox::play() { - if(tracks.empty() || sound) + if(tracks.empty() || decoder) return; - sound = new AL::Sound; - sound->open_file(*current_track); - streamer.play(*sound); + decoder = new AL::SoundDecoder; + decoder->open_file(*current_track); + streamer.play(*decoder); } void Jukebox::next() @@ -123,14 +123,14 @@ void Jukebox::previous() void Jukebox::stop() { streamer.stop(); - delete sound; - sound = 0; + delete decoder; + decoder = 0; } void Jukebox::tick() { streamer.tick(); - if(sound && sound->eof()) + if(decoder && decoder->eof()) next(); } diff --git a/source/jukebox.h b/source/jukebox.h index 1367295..fe17f2e 100644 --- a/source/jukebox.h +++ b/source/jukebox.h @@ -10,7 +10,7 @@ namespace Msp { namespace AL { -class Sound; +class SoundDecoder; class Jukebox { @@ -20,7 +20,7 @@ public: private: Source source; Streamer streamer; - Sound *sound; + SoundDecoder *decoder; std::list tracks; std::list::iterator current_track; bool shuffle; diff --git a/source/sound.cpp b/source/sounddecoder.cpp similarity index 61% rename from source/sound.cpp rename to source/sounddecoder.cpp index fe2de5e..d4d1767 100644 --- a/source/sound.cpp +++ b/source/sounddecoder.cpp @@ -1,6 +1,6 @@ #include #include -#include "sound.h" +#include "sounddecoder.h" using namespace std; @@ -64,21 +64,19 @@ ov_callbacks memory_callbacks= namespace Msp { namespace AL { -Sound::Sound(): - data(0), +SoundDecoder::SoundDecoder(): eof_flag(false) { ovfile.datasource = 0; } -Sound::~Sound() +SoundDecoder::~SoundDecoder() { - delete[] data; if(ovfile.datasource) ov_clear(&ovfile); } -void Sound::open_file(const string &fn) +void SoundDecoder::open_file(const string &fn) { if(ovfile.datasource) throw logic_error("Sound has already been opened"); @@ -88,7 +86,7 @@ void Sound::open_file(const string &fn) open_common(); } -void Sound::open_memory(const void *d, unsigned len) +void SoundDecoder::open_memory(const void *d, unsigned len) { if(ovfile.datasource) throw logic_error("Sound has already been opened"); @@ -103,13 +101,13 @@ void Sound::open_memory(const void *d, unsigned len) open_common(); } -void Sound::open_common() +void SoundDecoder::open_common() { - delete data; - data = 0; - vorbis_info *info = ov_info(&ovfile, -1); freq = info->rate; + + size = ov_pcm_total(&ovfile, 0)*info->channels*2; + switch(info->channels) { case 1: format = MONO16; break; @@ -118,77 +116,26 @@ void Sound::open_common() } } -void Sound::load_data() -{ - if(data) - throw logic_error("Data has already been loaded"); - - size = ov_pcm_total(&ovfile, 0)*4; - char *dptr = new char[size]; - unsigned pos = 0; - while(unsigned len = read(dptr+pos, size-pos)) - pos += len; - data = dptr; - size = pos; - read_pos = 0; -} - -void Sound::load_file(const std::string &fn) -{ - open_file(fn); - load_data(); - close(); -} - -void Sound::load_memory(const void *d, unsigned len) -{ - open_memory(d, len); - load_data(); - close(); -} - -void Sound::close() +void SoundDecoder::close() { if(ovfile.datasource) ov_clear(&ovfile); } -void Sound::rewind() -{ - if(data) - read_pos = 0; - else - ov_pcm_seek(&ovfile, 0); -} - -unsigned Sound::read(char *buf, unsigned len) +void SoundDecoder::rewind() { - if(data) - { - len = min(len, size-read_pos); - memcpy(buf, data+read_pos, len); - read_pos += len; - return len; - } - else if(ovfile.datasource) - { - int section = 0; - int res = ov_read(&ovfile, buf, len, 0, 2, 1, §ion); - if(res<0) - throw runtime_error("Error reading ogg vorbis file"); - else if(res==0) - eof_flag = true; - return res; - } - else - throw logic_error("No data available"); + ov_pcm_seek(&ovfile, 0); } -const char *Sound::get_data() const +unsigned SoundDecoder::read(char *buf, unsigned len) { - if(!data) - throw logic_error("Data has not been loaded"); - return data; + int section = 0; + int res = ov_read(&ovfile, buf, len, 0, 2, 1, §ion); + if(res<0) + throw runtime_error("Error reading ogg vorbis file"); + else if(res==0) + eof_flag = true; + return res; } } // namespace AL diff --git a/source/sound.h b/source/sounddecoder.h similarity index 79% rename from source/sound.h rename to source/sounddecoder.h index 60bdf45..ad56646 100644 --- a/source/sound.h +++ b/source/sounddecoder.h @@ -12,29 +12,24 @@ namespace AL { This class facilitates loading sound files. Currently only Ogg Vorbis is supported. */ -class Sound +class SoundDecoder { private: OggVorbis_File ovfile; unsigned freq; unsigned size; - char *data; Format format; - unsigned read_pos; bool eof_flag; public: - Sound(); - ~Sound(); + SoundDecoder(); + ~SoundDecoder(); void open_file(const std::string &); void open_memory(const void *, unsigned); private: void open_common(); public: - void load_data(); - void load_file(const std::string &); - void load_memory(const void *, unsigned); void close(); void rewind(); unsigned read(char *, unsigned); @@ -43,7 +38,6 @@ public: Format get_format() const { return format; } unsigned get_frequency() const { return freq; } unsigned get_size() const { return size; } - const char *get_data() const; }; } // namespace AL diff --git a/source/streamer.cpp b/source/streamer.cpp index b90a9d1..bca08a2 100644 --- a/source/streamer.cpp +++ b/source/streamer.cpp @@ -1,5 +1,5 @@ #include "buffer.h" -#include "sound.h" +#include "sounddecoder.h" #include "streamer.h" using namespace std; @@ -9,7 +9,7 @@ namespace AL { Streamer::Streamer(Source &s): src(s), - snd(0) + decoder(0) { } Streamer::~Streamer() @@ -20,16 +20,16 @@ Streamer::~Streamer() delete *i; } -void Streamer::play(Sound &s) +void Streamer::play(SoundDecoder &s) { - snd = &s; + decoder = &s; tick(); src.play(); } void Streamer::stop() { - snd = 0; + decoder = 0; src.stop(); } @@ -45,13 +45,13 @@ void Streamer::tick() } } - if(!snd) + if(!decoder) return; if(src.get_state()!=PLAYING && src.get_state()!=PAUSED) src.play(); - unsigned freq = snd->get_frequency(); + unsigned freq = decoder->get_frequency(); unsigned chunk_size = freq&~0xF; unsigned queued = src.get_buffers_queued(); vector data(chunk_size); @@ -60,7 +60,7 @@ void Streamer::tick() unsigned pos = 0; while(posread(&data[0]+pos, chunk_size-pos); + unsigned len = decoder->read(&data[0]+pos, chunk_size-pos); if(len==0) break; pos += len; @@ -69,14 +69,14 @@ void Streamer::tick() if(pos) { Buffer *buf = new Buffer; - buf->data(snd->get_format(), &data[0], pos, freq); + buf->data(decoder->get_format(), &data[0], pos, freq); src.queue_buffer(*buf); buffers.push_back(buf); } } - if(snd->eof()) - snd = 0; + if(decoder->eof()) + decoder = 0; } } // namespace AL diff --git a/source/streamer.h b/source/streamer.h index 7843e9e..192ede9 100644 --- a/source/streamer.h +++ b/source/streamer.h @@ -7,26 +7,26 @@ namespace Msp { namespace AL { -class Sound; +class SoundDecoder; class Buffer; /** -A streamer transfers data from a Sound to a Source. It is permanently attached -to the same Source, but can play multiple Sounds during its lifetime. A single -Sound can only be played by one Streamer at a time. +A streamer transfers data from a SoundDecoder to a Source. It is permanently +attached to the same Source, but can read from multiple decoders during its +lifetime. */ class Streamer { private: Source &src; - Sound *snd; + SoundDecoder *decoder; std::list buffers; public: Streamer(Source &); ~Streamer(); - void play(Sound &); + void play(SoundDecoder &); void stop(); void tick(); }; diff --git a/source/waveform.cpp b/source/waveform.cpp new file mode 100644 index 0000000..36978c6 --- /dev/null +++ b/source/waveform.cpp @@ -0,0 +1,50 @@ +#include "sounddecoder.h" +#include "waveform.h" + +using namespace std; + +namespace Msp { +namespace AL { + +Waveform::Waveform(): + format(MONO8), + freq(0), + size(0), + data(0) +{ } + +Waveform::~Waveform() +{ + delete[] data; +} + +void Waveform::load_file(const string &fn) +{ + SoundDecoder decoder; + decoder.open_file(fn); + load(decoder); +} + +void Waveform::load_memory(const void *d, unsigned len) +{ + SoundDecoder decoder; + decoder.open_memory(d, len); + load(decoder); +} + +void Waveform::load(SoundDecoder &decoder) +{ + delete[] data; + + format = decoder.get_format(); + freq = decoder.get_frequency(); + size = decoder.get_size(); + data = new char[size]; + unsigned pos = 0; + while(unsigned len = decoder.read(data+pos, size-pos)) + pos += len; + size = pos; +} + +} // namespace AL +} // namespace Msp diff --git a/source/waveform.h b/source/waveform.h new file mode 100644 index 0000000..c1f0a2d --- /dev/null +++ b/source/waveform.h @@ -0,0 +1,37 @@ +#ifndef MSP_AL_WAVEFORM_H_ +#define MSP_AL_WAVEFORM_H_ + +#include +#include "format.h" + +namespace Msp { +namespace AL { + +class SoundDecoder; + +class Waveform +{ +private: + Format format; + unsigned freq; + unsigned size; + char *data; + +public: + Waveform(); + ~Waveform(); + + void load_file(const std::string &); + void load_memory(const void *, unsigned); + void load(SoundDecoder &); + + Format get_format() const { return format; } + unsigned get_frequency() const { return freq; } + unsigned get_size() const { return size; } + const char *get_data() const { return data; } +}; + +} // namespace AL +} // namespace Msp + +#endif -- 2.45.2