2 * ALURE OpenAL utility library
3 * Copyright (c) 2009-2010 by Chris Robinson.
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to
7 * deal in the Software without restriction, including without limitation the
8 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9 * sell copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
37 static void *dumb_handle;
38 #define MAKE_FUNC(x) static typeof(x)* p##x
39 MAKE_FUNC(dumbfile_open_ex);
40 MAKE_FUNC(dumbfile_close);
41 MAKE_FUNC(dumb_read_mod);
42 MAKE_FUNC(dumb_read_s3m);
43 MAKE_FUNC(dumb_read_xm);
44 MAKE_FUNC(dumb_read_it);
45 MAKE_FUNC(dumb_silence);
46 MAKE_FUNC(duh_sigrenderer_generate_samples);
47 MAKE_FUNC(duh_get_it_sigrenderer);
48 MAKE_FUNC(duh_end_sigrenderer);
49 MAKE_FUNC(unload_duh);
50 MAKE_FUNC(dumb_it_start_at_order);
51 MAKE_FUNC(dumb_it_set_loop_callback);
52 MAKE_FUNC(dumb_it_sr_get_speed);
53 MAKE_FUNC(dumb_it_sr_set_speed);
56 #define dumbfile_open_ex pdumbfile_open_ex
57 #define dumbfile_close pdumbfile_close
58 #define dumb_read_mod pdumb_read_mod
59 #define dumb_read_s3m pdumb_read_s3m
60 #define dumb_read_xm pdumb_read_xm
61 #define dumb_read_it pdumb_read_it
62 #define dumb_silence pdumb_silence
63 #define duh_sigrenderer_generate_samples pduh_sigrenderer_generate_samples
64 #define duh_get_it_sigrenderer pduh_get_it_sigrenderer
65 #define duh_end_sigrenderer pduh_end_sigrenderer
66 #define unload_duh punload_duh
67 #define dumb_it_start_at_order pdumb_it_start_at_order
68 #define dumb_it_set_loop_callback pdumb_it_set_loop_callback
69 #define dumb_it_sr_get_speed pdumb_it_sr_get_speed
70 #define dumb_it_sr_set_speed pdumb_it_sr_set_speed
76 struct dumbStream : public alureStream {
81 DUH_SIGRENDERER *renderer;
82 std::vector<sample_t> sampleBuf;
92 #define DUMB_LIB "libdumb.dll"
93 #elif defined(__APPLE__)
94 #define DUMB_LIB "libdumb.dylib"
96 #define DUMB_LIB "libdumb.so"
99 dumb_handle = OpenLib(DUMB_LIB);
100 if(!dumb_handle) return;
102 LOAD_FUNC(dumb_handle, dumbfile_open_ex);
103 LOAD_FUNC(dumb_handle, dumbfile_close);
104 LOAD_FUNC(dumb_handle, dumb_read_mod);
105 LOAD_FUNC(dumb_handle, dumb_read_s3m);
106 LOAD_FUNC(dumb_handle, dumb_read_xm);
107 LOAD_FUNC(dumb_handle, dumb_read_it);
108 LOAD_FUNC(dumb_handle, dumb_silence);
109 LOAD_FUNC(dumb_handle, duh_sigrenderer_generate_samples);
110 LOAD_FUNC(dumb_handle, duh_get_it_sigrenderer);
111 LOAD_FUNC(dumb_handle, duh_end_sigrenderer);
112 LOAD_FUNC(dumb_handle, unload_duh);
113 LOAD_FUNC(dumb_handle, dumb_it_start_at_order);
114 LOAD_FUNC(dumb_handle, dumb_it_set_loop_callback);
115 LOAD_FUNC(dumb_handle, dumb_it_sr_get_speed);
116 LOAD_FUNC(dumb_handle, dumb_it_sr_set_speed);
121 CloseLib(dumb_handle);
125 static void Init() { }
126 static void Deinit() { }
129 virtual bool IsValid()
130 { return renderer != NULL; }
132 virtual bool GetFormat(ALenum *fmt, ALuint *frequency, ALuint *blockalign)
134 if(format == AL_NONE)
136 format = GetSampleFormat(2, 32, true);
137 if(format == AL_NONE)
138 format = AL_FORMAT_STEREO16;
141 *frequency = samplerate;
142 *blockalign = 2 * ((format==AL_FORMAT_STEREO16) ? sizeof(ALshort) :
147 virtual ALuint GetData(ALubyte *data, ALuint bytes)
151 if(dumb_it_sr_get_speed(duh_get_it_sigrenderer(renderer)) == 0)
154 ALuint sample_count = bytes / ((format==AL_FORMAT_STEREO16) ?
155 sizeof(ALshort) : sizeof(ALfloat));
157 sampleBuf.resize(sample_count);
158 sample_t *samples[] = {
162 dumb_silence(samples[0], sample_count);
163 ret = duh_sigrenderer_generate_samples(renderer, 1.0f, 65536.0f/samplerate, sample_count/2, samples);
165 if(format == AL_FORMAT_STEREO16)
167 for(ALuint i = 0;i < ret;i++)
168 ((ALshort*)data)[i] = clamp(samples[0][i]>>8, -32768, 32767);
172 for(ALuint i = 0;i < ret;i++)
173 ((ALfloat*)data)[i] = samples[0][i] * (1.0/8388607.0);
175 ret *= ((format==AL_FORMAT_STEREO16) ? sizeof(ALshort) : sizeof(ALfloat));
180 virtual bool Rewind()
182 DUH_SIGRENDERER *newrenderer = dumb_it_start_at_order(duh, 2, lastOrder);
185 SetError("Could not start renderer");
188 duh_end_sigrenderer(renderer);
189 renderer = newrenderer;
193 virtual bool SetOrder(ALuint order)
195 DUH_SIGRENDERER *newrenderer = dumb_it_start_at_order(duh, 2, order);
198 SetError("Could not set order");
201 duh_end_sigrenderer(renderer);
202 renderer = newrenderer;
208 dumbStream(std::istream *_fstream)
209 : alureStream(_fstream), dumbFile(NULL), duh(NULL), renderer(NULL),
210 lastOrder(0), format(AL_NONE), samplerate(48000)
212 if(!dumb_handle) return;
214 ALCdevice *device = alcGetContextsDevice(alcGetCurrentContext());
215 if(device) alcGetIntegerv(device, ALC_FREQUENCY, 1, &samplerate);
217 DUH* (*funcs[])(DUMBFILE*) = {
227 vfs.getc = read_char;
231 for(size_t i = 0;funcs[i];i++)
233 dumbFile = dumbfile_open_ex(this, &vfs);
236 duh = funcs[i](dumbFile);
239 renderer = dumb_it_start_at_order(duh, 2, lastOrder);
242 dumb_it_set_loop_callback(duh_get_it_sigrenderer(renderer), loop_cb, this);
250 dumbfile_close(dumbFile);
258 virtual ~dumbStream()
261 duh_end_sigrenderer(renderer);
269 dumbfile_close(dumbFile);
274 // DUMBFILE iostream callbacks
275 static int skip(void *user_data, long offset)
277 std::istream *stream = static_cast<dumbStream*>(user_data)->fstream;
280 if(stream->seekg(offset, std::ios_base::cur))
285 static long read(char *ptr, long size, void *user_data)
287 std::istream *stream = static_cast<dumbStream*>(user_data)->fstream;
290 stream->read(ptr, size);
291 return stream->gcount();
294 static int read_char(void *user_data)
296 std::istream *stream = static_cast<dumbStream*>(user_data)->fstream;
300 stream->read(reinterpret_cast<char*>(&ret), 1);
301 if(stream->gcount() > 0)
306 static int loop_cb(void *user_data)
308 dumbStream *self = static_cast<dumbStream*>(user_data);
309 dumb_it_sr_set_speed(duh_get_it_sigrenderer(self->renderer), 0);
313 // Priority = -1, because mod loading can find false-positives
314 static DecoderDecl<dumbStream,-1> dumbStream_decoder;
315 Decoder &alure_init_dumb(void)
316 { return dumbStream_decoder; }