3 This file is part of libmspal
4 Copyright © 2008-2009 Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
9 #include <msp/core/except.h>
22 MemorySource(const void *d, unsigned l): data(d), length(l), pos(0) { }
25 size_t memory_read(void *ptr, size_t size, size_t nmemb, void *src)
27 MemorySource &memsrc=*reinterpret_cast<MemorySource *>(src);
28 unsigned len=min(size*nmemb, memsrc.length-memsrc.pos);
29 memcpy(ptr, reinterpret_cast<const char *>(memsrc.data)+memsrc.pos, len);
35 int memory_seek(void *src, ogg_int64_t offset, int whence)
37 MemorySource &memsrc=*reinterpret_cast<MemorySource *>(src);
40 else if(whence==SEEK_CUR)
42 else if(whence==SEEK_END)
43 memsrc.pos=memsrc.length-offset;
44 memsrc.pos=min(memsrc.pos, memsrc.length);
49 int memory_close(void *src)
51 delete reinterpret_cast<MemorySource *>(src);
55 long memory_tell(void *src)
57 MemorySource &memsrc=*reinterpret_cast<MemorySource *>(src);
61 ov_callbacks memory_callbacks=
88 void Sound::open_file(const string &fn)
91 throw InvalidState("Sound has already been opened");
92 if(ov_fopen(const_cast<char *>(fn.c_str()), &ovfile)<0)
93 throw Exception("Could not open ogg vorbis file "+fn);
98 void Sound::open_memory(const void *d, unsigned len)
100 if(ovfile.datasource)
101 throw InvalidState("Sound has already been opened");
103 MemorySource *src=new MemorySource(d, len);
104 if(ov_open_callbacks(src, &ovfile, 0, 0, memory_callbacks)<0)
107 throw Exception("Could not open ogg vorbis memory block");
113 void Sound::load_data()
116 throw InvalidState("Data has already been loaded");
118 size=ov_pcm_total(&ovfile, 0)*4;
119 char *dptr=new char[size];
121 while(unsigned len=read(dptr+pos, size-pos))
128 void Sound::load_file(const std::string &fn)
135 void Sound::load_memory(const void *d, unsigned len)
144 if(ovfile.datasource)
153 ov_pcm_seek(&ovfile, 0);
156 unsigned Sound::read(char *buf, unsigned len)
160 len=min(len, size-read_pos);
161 memcpy(buf, data+read_pos, len);
165 else if(ovfile.datasource)
168 int res=ov_read(&ovfile, buf, len, 0, 2, 1, §ion);
170 throw Exception("Error reading ogg vorbis file");
176 throw InvalidState("No data available");
179 const char *Sound::get_data() const
182 throw InvalidState("Data has not been loaded");
186 void Sound::open_common()
191 vorbis_info *info=ov_info(&ovfile, -1);
193 switch(info->channels)
195 case 1: format=MONO16; break;
196 case 2: format=STEREO16; break;
197 default: throw Exception("Unsupported number of channels");