alBufferData(id, fmt, dt, size, freq);
}
+void Buffer::data(const Sound &snd)
+{
+ data(snd.get_format(), snd.get_data(), snd.get_size(), snd.get_frequency());
+}
+
void Buffer::load_data(const string &fn)
{
Sound sound;
- sound.load(fn);
+ sound.load_file(fn);
+
+ data(sound);
+}
+
+
+Buffer::Loader::Loader(Buffer &b):
+ buf(b)
+{
+ add("sound_data", &Loader::sound_data);
+}
+
+void Buffer::Loader::sound_data(const string &data)
+{
+ Sound sound;
+ sound.load_memory(data.data(), data.size());
- data(sound.get_format(), sound.get_data(), sound.get_size(), sound.get_frequency());
+ buf.data(sound);
}
} // namespace AL
using namespace std;
-namespace Msp {
-namespace AL {
+namespace {
-Sound::Sound():
- data(0),
- eof_flag(false)
+struct MemorySource
{
- ovfile.datasource=0;
+ 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(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;
+}
+
+void memory_close(void *src)
+{
+ delete reinterpret_cast<MemorySource *>(src);
+}
+
+long memory_tell(void *src)
+{
+ MemorySource &memsrc=*reinterpret_cast<MemorySource *>(src);
+ return memsrc.pos;
}
-Sound::Sound(const std::string &fn):
+ov_callbacks memory_callbacks=
+{
+ &memory_read,
+ &memory_seek,
+ 0,
+ &memory_tell
+};
+
+} // namespace
+
+namespace Msp {
+namespace AL {
+
+Sound::Sound():
data(0),
eof_flag(false)
{
ovfile.datasource=0;
- open(fn);
}
Sound::~Sound()
{
- delete data;
+ delete[] data;
if(ovfile.datasource)
ov_clear(&ovfile);
}
-void Sound::open(const string &fn)
+void Sound::open_file(const string &fn)
{
if(ovfile.datasource)
throw InvalidState("Sound has already been opened");
if(ov_fopen(const_cast<char *>(fn.c_str()), &ovfile)<0)
throw Exception("Could not open ogg vorbis file "+fn);
- delete data;
- data=0;
+ open_common();
+}
- vorbis_info *info=ov_info(&ovfile, -1);
- freq=info->rate;
- switch(info->channels)
+void Sound::open_memory(const void *d, unsigned len)
+{
+ if(ovfile.datasource)
+ throw InvalidState("Sound has already been opened");
+
+ MemorySource *src=new MemorySource(d, len);
+ if(ov_open_callbacks(src, &ovfile, 0, 0, memory_callbacks)<0)
{
- case 1: format=MONO16; break;
- case 2: format=STEREO16; break;
- default: throw Exception("Unsupported number of channels");
+ delete src;
+ throw Exception("Could not open ogg vorbis memory block");
}
+
+ open_common();
}
void Sound::load_data()
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(const string &fn)
+void Sound::load_memory(const void *d, unsigned len)
{
- open(fn);
+ open_memory(d, len);
load_data();
close();
}
return data;
}
+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 Exception("Unsupported number of channels");
+ }
+}
+
} // namespace AL
} // namespace Msp
public:
Sound();
- Sound(const std::string &);
~Sound();
- void open(const std::string &);
+ void open_file(const std::string &);
+ void open_memory(const void *, unsigned);
void load_data();
- void load(const std::string &);
+ void load_file(const std::string &);
+ void load_memory(const void *, unsigned);
void close();
void rewind();
unsigned read(char *, unsigned);
unsigned get_frequency() const { return freq; }
unsigned get_size() const { return size; }
const char *get_data() const;
+private:
+ void open_common();
};
} // namespace AL