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 #define DUMB_LIB "libdumb.dll"
38 #elif defined(__APPLE__)
39 #define DUMB_LIB "libdumb.dylib"
41 #define DUMB_LIB "libdumb.so"
44 static void *dumb_handle
;
45 #define MAKE_FUNC(x) static typeof(x)* p##x
46 MAKE_FUNC(dumbfile_open_ex
);
47 MAKE_FUNC(dumbfile_close
);
48 MAKE_FUNC(dumb_read_mod
);
49 MAKE_FUNC(dumb_read_s3m
);
50 MAKE_FUNC(dumb_read_xm
);
51 MAKE_FUNC(dumb_read_it
);
52 MAKE_FUNC(dumb_silence
);
53 MAKE_FUNC(duh_sigrenderer_generate_samples
);
54 MAKE_FUNC(duh_get_it_sigrenderer
);
55 MAKE_FUNC(duh_end_sigrenderer
);
56 MAKE_FUNC(unload_duh
);
57 MAKE_FUNC(dumb_it_start_at_order
);
58 MAKE_FUNC(dumb_it_set_loop_callback
);
59 MAKE_FUNC(dumb_it_sr_get_speed
);
60 MAKE_FUNC(dumb_it_sr_set_speed
);
64 struct dumbStream
: public alureStream
{
69 DUH_SIGRENDERER
*renderer
;
70 std::vector
<sample_t
> sampleBuf
;
78 dumb_handle
= OpenLib(DUMB_LIB
);
79 if(!dumb_handle
) return;
81 LOAD_FUNC(dumb_handle
, dumbfile_open_ex
);
82 LOAD_FUNC(dumb_handle
, dumbfile_close
);
83 LOAD_FUNC(dumb_handle
, dumb_read_mod
);
84 LOAD_FUNC(dumb_handle
, dumb_read_s3m
);
85 LOAD_FUNC(dumb_handle
, dumb_read_xm
);
86 LOAD_FUNC(dumb_handle
, dumb_read_it
);
87 LOAD_FUNC(dumb_handle
, dumb_silence
);
88 LOAD_FUNC(dumb_handle
, duh_sigrenderer_generate_samples
);
89 LOAD_FUNC(dumb_handle
, duh_get_it_sigrenderer
);
90 LOAD_FUNC(dumb_handle
, duh_end_sigrenderer
);
91 LOAD_FUNC(dumb_handle
, unload_duh
);
92 LOAD_FUNC(dumb_handle
, dumb_it_start_at_order
);
93 LOAD_FUNC(dumb_handle
, dumb_it_set_loop_callback
);
94 LOAD_FUNC(dumb_handle
, dumb_it_sr_get_speed
);
95 LOAD_FUNC(dumb_handle
, dumb_it_sr_set_speed
);
100 CloseLib(dumb_handle
);
104 virtual bool IsValid()
105 { return renderer
!= NULL
; }
107 virtual bool GetFormat(ALenum
*fmt
, ALuint
*frequency
, ALuint
*blockalign
)
109 if(format
== AL_NONE
)
111 format
= GetSampleFormat(2, 32, true);
112 if(format
== AL_NONE
)
113 format
= AL_FORMAT_STEREO16
;
116 *frequency
= samplerate
;
117 *blockalign
= 2 * ((format
==AL_FORMAT_STEREO16
) ? sizeof(ALshort
) :
122 virtual ALuint
GetData(ALubyte
*data
, ALuint bytes
)
126 if(pdumb_it_sr_get_speed(pduh_get_it_sigrenderer(renderer
)) == 0)
129 ALuint sample_count
= bytes
/ ((format
==AL_FORMAT_STEREO16
) ?
130 sizeof(ALshort
) : sizeof(ALfloat
));
132 sampleBuf
.resize(sample_count
);
133 sample_t
*samples
[] = {
137 pdumb_silence(samples
[0], sample_count
);
138 ret
= pduh_sigrenderer_generate_samples(renderer
, 1.0f
, 65536.0f
/samplerate
, sample_count
/2, samples
);
140 if(format
== AL_FORMAT_STEREO16
)
142 for(ALuint i
= 0;i
< ret
;i
++)
143 ((ALshort
*)data
)[i
] = clamp(samples
[0][i
]>>8, -32768, 32767);
147 for(ALuint i
= 0;i
< ret
;i
++)
148 ((ALfloat
*)data
)[i
] = samples
[0][i
] * (1.0/8388607.0);
150 ret
*= ((format
==AL_FORMAT_STEREO16
) ? sizeof(ALshort
) : sizeof(ALfloat
));
155 virtual bool Rewind()
157 DUH_SIGRENDERER
*newrenderer
= pdumb_it_start_at_order(duh
, 2, lastOrder
);
160 SetError("Could not start renderer");
163 pduh_end_sigrenderer(renderer
);
164 renderer
= newrenderer
;
168 virtual bool SetOrder(ALuint order
)
170 DUH_SIGRENDERER
*newrenderer
= pdumb_it_start_at_order(duh
, 2, order
);
173 SetError("Could not set order");
176 pduh_end_sigrenderer(renderer
);
177 renderer
= newrenderer
;
183 dumbStream(std::istream
*_fstream
)
184 : alureStream(_fstream
), dumbFile(NULL
), duh(NULL
), renderer(NULL
),
185 lastOrder(0), format(AL_NONE
), samplerate(48000)
187 if(!dumb_handle
) return;
189 ALCdevice
*device
= alcGetContextsDevice(alcGetCurrentContext());
191 alcGetIntegerv(device
, ALC_FREQUENCY
, 1, &samplerate
);
193 DUH
* (*funcs
[])(DUMBFILE
*) = {
203 vfs
.getc
= read_char
;
207 for(size_t i
= 0;funcs
[i
];i
++)
209 dumbFile
= pdumbfile_open_ex(this, &vfs
);
212 duh
= funcs
[i
](dumbFile
);
215 renderer
= pdumb_it_start_at_order(duh
, 2, lastOrder
);
218 pdumb_it_set_loop_callback(pduh_get_it_sigrenderer(renderer
), loop_cb
, this);
226 pdumbfile_close(dumbFile
);
234 virtual ~dumbStream()
237 pduh_end_sigrenderer(renderer
);
245 pdumbfile_close(dumbFile
);
250 // DUMBFILE iostream callbacks
251 static int skip(void *user_data
, long offset
)
253 std::istream
*stream
= static_cast<dumbStream
*>(user_data
)->fstream
;
256 if(stream
->seekg(offset
, std::ios_base::cur
))
261 static long read(char *ptr
, long size
, void *user_data
)
263 std::istream
*stream
= static_cast<dumbStream
*>(user_data
)->fstream
;
266 stream
->read(ptr
, size
);
267 return stream
->gcount();
270 static int read_char(void *user_data
)
272 std::istream
*stream
= static_cast<dumbStream
*>(user_data
)->fstream
;
276 stream
->read(reinterpret_cast<char*>(&ret
), 1);
277 if(stream
->gcount() > 0)
282 static int loop_cb(void *user_data
)
284 dumbStream
*self
= static_cast<dumbStream
*>(user_data
);
285 pdumb_it_sr_set_speed(pduh_get_it_sigrenderer(self
->renderer
), 0);
289 // Priority = -1, because mod loading can find false-positives
290 static DecoderDecl
<dumbStream
,-1> dumbStream_decoder
;
291 Decoder
&alure_init_dumb(void)
292 { return dumbStream_decoder
; }