]> git.tdb.fi Git - libs/al.git/commitdiff
Split Sound into SoundDecoder and Waveform parts
authorMikko Rasa <tdb@tdb.fi>
Tue, 20 Nov 2012 14:48:04 +0000 (16:48 +0200)
committerMikko Rasa <tdb@tdb.fi>
Tue, 20 Nov 2012 14:48:04 +0000 (16:48 +0200)
12 files changed:
source/buffer.cpp
source/buffer.h
source/jukebox.cpp
source/jukebox.h
source/sound.cpp [deleted file]
source/sound.h [deleted file]
source/sounddecoder.cpp [new file with mode: 0644]
source/sounddecoder.h [new file with mode: 0644]
source/streamer.cpp
source/streamer.h
source/waveform.cpp [new file with mode: 0644]
source/waveform.h [new file with mode: 0644]

index 1d7510e0a527f8dc165b4dcb2e85ac48e52a190a..5aef1b4555081963d12da637ee5dfd199a75718a 100644 (file)
@@ -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
index d84e46a021d4f0eaedb070cdf4c73cce3ec71541..38ca36d6047f3417bd0b5a5b01292b7b126e4f5a 100644 (file)
@@ -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 &);
 };
 
index d2a997d4cfffcf35f61f7e020183665b837f1492..02a33cdfee3e1d55e56eed59b647b7fe630131a0 100644 (file)
@@ -2,7 +2,7 @@
 #include <cstdlib>
 #include <stdexcept>
 #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();
 }
 
index 13672953b9325861ce62ec2971a69fe95be1f3ed..fe17f2e4a58f456338eff200046f577e80f61498 100644 (file)
@@ -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<std::string> tracks;
        std::list<std::string>::iterator current_track;
        bool shuffle;
diff --git a/source/sound.cpp b/source/sound.cpp
deleted file mode 100644 (file)
index fe2de5e..0000000
+++ /dev/null
@@ -1,195 +0,0 @@
-#include <cstring>
-#include <stdexcept>
-#include "sound.h"
-
-using namespace std;
-
-namespace {
-
-struct MemorySource
-{
-       const void *data;
-       unsigned length;
-       unsigned pos;
-
-       MemorySource(const void *d, unsigned l): data(d), length(l), pos(0) { }
-};
-
-size_t memory_read(void *ptr, size_t size, size_t nmemb, void *src)
-{
-       MemorySource &memsrc = *reinterpret_cast<MemorySource *>(src);
-       unsigned len = min<unsigned>(size*nmemb, memsrc.length-memsrc.pos);
-       memcpy(ptr, reinterpret_cast<const char *>(memsrc.data)+memsrc.pos, len);
-       memsrc.pos += len;
-
-       return len/size;
-}
-
-int memory_seek(void *src, ogg_int64_t offset, int whence)
-{
-       MemorySource &memsrc = *reinterpret_cast<MemorySource *>(src);
-       if(whence==SEEK_SET)
-               memsrc.pos = offset;
-       else if(whence==SEEK_CUR)
-               memsrc.pos += offset;
-       else if(whence==SEEK_END)
-               memsrc.pos = memsrc.length-offset;
-       memsrc.pos = min(memsrc.pos, memsrc.length);
-
-       return memsrc.pos;
-}
-
-int memory_close(void *src)
-{
-       delete reinterpret_cast<MemorySource *>(src);
-       return 0;
-}
-
-long memory_tell(void *src)
-{
-       MemorySource &memsrc = *reinterpret_cast<MemorySource *>(src);
-       return memsrc.pos;
-}
-
-ov_callbacks memory_callbacks=
-{
-       &memory_read,
-       &memory_seek,
-       &memory_close,
-       &memory_tell
-};
-
-} // namespace
-
-namespace Msp {
-namespace AL {
-
-Sound::Sound():
-       data(0),
-       eof_flag(false)
-{
-       ovfile.datasource = 0;
-}
-
-Sound::~Sound()
-{
-       delete[] data;
-       if(ovfile.datasource)
-               ov_clear(&ovfile);
-}
-
-void Sound::open_file(const string &fn)
-{
-       if(ovfile.datasource)
-               throw logic_error("Sound has already been opened");
-       if(ov_fopen(const_cast<char *>(fn.c_str()), &ovfile)<0)
-               throw runtime_error("Could not open ogg vorbis file "+fn);
-
-       open_common();
-}
-
-void Sound::open_memory(const void *d, unsigned len)
-{
-       if(ovfile.datasource)
-               throw logic_error("Sound has already been opened");
-
-       MemorySource *src = new MemorySource(d, len);
-       if(ov_open_callbacks(src, &ovfile, 0, 0, memory_callbacks)<0)
-       {
-               delete src;
-               throw runtime_error("Could not open ogg vorbis memory block");
-       }
-
-       open_common();
-}
-
-void Sound::open_common()
-{
-       delete data;
-       data = 0;
-
-       vorbis_info *info = ov_info(&ovfile, -1);
-       freq = info->rate;
-       switch(info->channels)
-       {
-       case 1: format = MONO16; break;
-       case 2: format = STEREO16; break;
-       default: throw runtime_error("Unsupported number of channels");
-       }
-}
-
-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()
-{
-       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)
-{
-       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, &section);
-               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");
-}
-
-const char *Sound::get_data() const
-{
-       if(!data)
-               throw logic_error("Data has not been loaded");
-       return data;
-}
-
-} // namespace AL
-} // namespace Msp
diff --git a/source/sound.h b/source/sound.h
deleted file mode 100644 (file)
index 60bdf45..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-#ifndef MSP_AL_SOUND_H_
-#define MSP_AL_SOUND_H_
-
-#include <string>
-#include <vorbis/vorbisfile.h>
-#include "format.h"
-
-namespace Msp {
-namespace AL {
-
-/**
-This class facilitates loading sound files.  Currently only Ogg Vorbis is
-supported.
-*/
-class Sound
-{
-private:
-       OggVorbis_File ovfile;
-       unsigned freq;
-       unsigned size;
-       char *data;
-       Format format;
-       unsigned read_pos;
-       bool eof_flag;
-
-public:
-       Sound();
-       ~Sound();
-
-       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);
-       bool eof() const { return eof_flag; }
-
-       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
-} // namespace Msp
-
-#endif
diff --git a/source/sounddecoder.cpp b/source/sounddecoder.cpp
new file mode 100644 (file)
index 0000000..d4d1767
--- /dev/null
@@ -0,0 +1,142 @@
+#include <cstring>
+#include <stdexcept>
+#include "sounddecoder.h"
+
+using namespace std;
+
+namespace {
+
+struct MemorySource
+{
+       const void *data;
+       unsigned length;
+       unsigned pos;
+
+       MemorySource(const void *d, unsigned l): data(d), length(l), pos(0) { }
+};
+
+size_t memory_read(void *ptr, size_t size, size_t nmemb, void *src)
+{
+       MemorySource &memsrc = *reinterpret_cast<MemorySource *>(src);
+       unsigned len = min<unsigned>(size*nmemb, memsrc.length-memsrc.pos);
+       memcpy(ptr, reinterpret_cast<const char *>(memsrc.data)+memsrc.pos, len);
+       memsrc.pos += len;
+
+       return len/size;
+}
+
+int memory_seek(void *src, ogg_int64_t offset, int whence)
+{
+       MemorySource &memsrc = *reinterpret_cast<MemorySource *>(src);
+       if(whence==SEEK_SET)
+               memsrc.pos = offset;
+       else if(whence==SEEK_CUR)
+               memsrc.pos += offset;
+       else if(whence==SEEK_END)
+               memsrc.pos = memsrc.length-offset;
+       memsrc.pos = min(memsrc.pos, memsrc.length);
+
+       return memsrc.pos;
+}
+
+int memory_close(void *src)
+{
+       delete reinterpret_cast<MemorySource *>(src);
+       return 0;
+}
+
+long memory_tell(void *src)
+{
+       MemorySource &memsrc = *reinterpret_cast<MemorySource *>(src);
+       return memsrc.pos;
+}
+
+ov_callbacks memory_callbacks=
+{
+       &memory_read,
+       &memory_seek,
+       &memory_close,
+       &memory_tell
+};
+
+} // namespace
+
+namespace Msp {
+namespace AL {
+
+SoundDecoder::SoundDecoder():
+       eof_flag(false)
+{
+       ovfile.datasource = 0;
+}
+
+SoundDecoder::~SoundDecoder()
+{
+       if(ovfile.datasource)
+               ov_clear(&ovfile);
+}
+
+void SoundDecoder::open_file(const string &fn)
+{
+       if(ovfile.datasource)
+               throw logic_error("Sound has already been opened");
+       if(ov_fopen(const_cast<char *>(fn.c_str()), &ovfile)<0)
+               throw runtime_error("Could not open ogg vorbis file "+fn);
+
+       open_common();
+}
+
+void SoundDecoder::open_memory(const void *d, unsigned len)
+{
+       if(ovfile.datasource)
+               throw logic_error("Sound has already been opened");
+
+       MemorySource *src = new MemorySource(d, len);
+       if(ov_open_callbacks(src, &ovfile, 0, 0, memory_callbacks)<0)
+       {
+               delete src;
+               throw runtime_error("Could not open ogg vorbis memory block");
+       }
+
+       open_common();
+}
+
+void SoundDecoder::open_common()
+{
+       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;
+       case 2: format = STEREO16; break;
+       default: throw runtime_error("Unsupported number of channels");
+       }
+}
+
+void SoundDecoder::close()
+{
+       if(ovfile.datasource)
+               ov_clear(&ovfile);
+}
+
+void SoundDecoder::rewind()
+{
+       ov_pcm_seek(&ovfile, 0);
+}
+
+unsigned SoundDecoder::read(char *buf, unsigned len)
+{
+       int section = 0;
+       int res = ov_read(&ovfile, buf, len, 0, 2, 1, &section);
+       if(res<0)
+               throw runtime_error("Error reading ogg vorbis file");
+       else if(res==0)
+               eof_flag = true;
+       return res;
+}
+
+} // namespace AL
+} // namespace Msp
diff --git a/source/sounddecoder.h b/source/sounddecoder.h
new file mode 100644 (file)
index 0000000..ad56646
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef MSP_AL_SOUND_H_
+#define MSP_AL_SOUND_H_
+
+#include <string>
+#include <vorbis/vorbisfile.h>
+#include "format.h"
+
+namespace Msp {
+namespace AL {
+
+/**
+This class facilitates loading sound files.  Currently only Ogg Vorbis is
+supported.
+*/
+class SoundDecoder
+{
+private:
+       OggVorbis_File ovfile;
+       unsigned freq;
+       unsigned size;
+       Format format;
+       bool eof_flag;
+
+public:
+       SoundDecoder();
+       ~SoundDecoder();
+
+       void open_file(const std::string &);
+       void open_memory(const void *, unsigned);
+private:
+       void open_common();
+public:
+       void close();
+       void rewind();
+       unsigned read(char *, unsigned);
+       bool eof() const { return eof_flag; }
+
+       Format get_format() const { return format; }
+       unsigned get_frequency() const { return freq; }
+       unsigned get_size() const { return size; }
+};
+
+} // namespace AL
+} // namespace Msp
+
+#endif
index b90a9d1c73ab3f78b50384c805348ff40b960699..bca08a2f06ea02c6ff357e90e42ba40ded4c02a7 100644 (file)
@@ -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<char> data(chunk_size);
@@ -60,7 +60,7 @@ void Streamer::tick()
                unsigned pos = 0;
                while(pos<chunk_size)
                {
-                       unsigned len = snd->read(&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
index 7843e9e8a0497e265bda373c55a557e99fa2f4a0..192ede9d68ebc1a8d245b1a559a727c052b91f38 100644 (file)
@@ -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<Buffer *> 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 (file)
index 0000000..36978c6
--- /dev/null
@@ -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 (file)
index 0000000..c1f0a2d
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef MSP_AL_WAVEFORM_H_
+#define MSP_AL_WAVEFORM_H_
+
+#include <string>
+#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