1 | /* -*- mode: C; tab-width:8; c-basic-offset:8 -*- |
---|
2 | * vi:set ts=8: |
---|
3 | * |
---|
4 | * al_main.c |
---|
5 | * |
---|
6 | * stuff that doesn't fit anywhere else. Also, global initialization/ |
---|
7 | * finitization. |
---|
8 | * |
---|
9 | */ |
---|
10 | #include "al_siteconfig.h" |
---|
11 | |
---|
12 | #include <AL/al.h> |
---|
13 | #include <AL/alc.h> |
---|
14 | #include <AL/alext.h> |
---|
15 | #include <math.h> |
---|
16 | #include <fcntl.h> |
---|
17 | #include <signal.h> |
---|
18 | #include <stddef.h> |
---|
19 | #include <stdlib.h> |
---|
20 | #include <string.h> |
---|
21 | #include <sys/stat.h> |
---|
22 | #include <sys/time.h> |
---|
23 | #include <sys/types.h> |
---|
24 | #include <unistd.h> |
---|
25 | |
---|
26 | #include "al_debug.h" |
---|
27 | #include "al_types.h" |
---|
28 | #include "al_main.h" |
---|
29 | #include "al_buffer.h" |
---|
30 | #include "al_source.h" |
---|
31 | #include "al_mixer.h" |
---|
32 | #include "al_ext.h" |
---|
33 | #include "al_config.h" |
---|
34 | #include "al_vector.h" |
---|
35 | #include "alc/alc_context.h" |
---|
36 | |
---|
37 | #include "al_threadlib.h" |
---|
38 | |
---|
39 | #include "audioconvert/audioconvert.h" |
---|
40 | |
---|
41 | /* standard extensions |
---|
42 | * |
---|
43 | * To avoid having these built in (ie, using the plugin arch), don't |
---|
44 | * include these headers and move the files from EXT_OBJS to EXT_DLL_OBJS. |
---|
45 | */ |
---|
46 | #include "extensions/al_ext_loki.h" |
---|
47 | #include "extensions/al_ext_mp3.h" |
---|
48 | #include "extensions/al_ext_vorbis.h" |
---|
49 | #include "extensions/al_ext_capture.h" |
---|
50 | |
---|
51 | #ifndef M_PI |
---|
52 | #define M_PI 3.14159265358979323846 /* pi */ |
---|
53 | #endif /* M_PI */ |
---|
54 | |
---|
55 | /* |
---|
56 | * mixer thread's ID, if it needs one |
---|
57 | */ |
---|
58 | extern ThreadID mixthread; |
---|
59 | |
---|
60 | /* |
---|
61 | * pcm buffers that filters act on |
---|
62 | */ |
---|
63 | _alDecodeScratch f_buffers; |
---|
64 | |
---|
65 | /* |
---|
66 | * Our extension functions |
---|
67 | */ |
---|
68 | static AL_extension exts[] = { |
---|
69 | #ifdef BUILTIN_EXT_LOKI |
---|
70 | BUILTIN_EXT_LOKI, |
---|
71 | #endif /* BUILDIN_EXT_LOKI */ |
---|
72 | #ifdef BUILTIN_EXT_MP3 |
---|
73 | BUILTIN_EXT_MP3, |
---|
74 | #endif /* BUILDIN_EXT_MP3 */ |
---|
75 | #ifdef BUILTIN_EXT_VORBIS |
---|
76 | BUILTIN_EXT_VORBIS, |
---|
77 | #endif /* BUILDIN_EXT_VORBIS */ |
---|
78 | #ifdef BUILTIN_EXT_CAPTURE |
---|
79 | BUILTIN_EXT_CAPTURE, |
---|
80 | #endif |
---|
81 | { NULL, NULL } |
---|
82 | }; |
---|
83 | |
---|
84 | /* |
---|
85 | * _alInit( void ) |
---|
86 | * |
---|
87 | * _alInit is called when the "first" context is created. If all |
---|
88 | * contexts are deleted, and then one is created, it is called again. |
---|
89 | * |
---|
90 | * Returns AL_TRUE unless some weird sort of memory allocation problem occurs, |
---|
91 | * in which case AL_FALSE is returned. |
---|
92 | */ |
---|
93 | ALboolean _alInit( void ) { |
---|
94 | ALboolean err; |
---|
95 | ALuint i; |
---|
96 | |
---|
97 | for(i = 0; i < _ALC_MAX_CHANNELS; i++) { |
---|
98 | f_buffers.data[i] = NULL; |
---|
99 | } |
---|
100 | |
---|
101 | f_buffers.len = 0; |
---|
102 | |
---|
103 | /* buffer initializations */ |
---|
104 | err = _alInitBuffers(); |
---|
105 | if(err == AL_FALSE) { |
---|
106 | return AL_FALSE; |
---|
107 | } |
---|
108 | |
---|
109 | /* extension initilizations */ |
---|
110 | err = _alInitExtensions(); |
---|
111 | if(err == AL_FALSE) { |
---|
112 | _alDestroyBuffers(); |
---|
113 | |
---|
114 | return AL_FALSE; |
---|
115 | } |
---|
116 | |
---|
117 | #ifdef BUILTIN_EXT_LOKI |
---|
118 | /* FIXME: dynamic-ify this */ |
---|
119 | /* register extension groups */ |
---|
120 | _alRegisterExtensionGroup( (const ALubyte*) "ALC_LOKI_audio_channel" ); |
---|
121 | _alRegisterExtensionGroup( (const ALubyte*) "AL_LOKI_buffer_data_callback" ); |
---|
122 | _alRegisterExtensionGroup( (const ALubyte*) "AL_LOKI_IMA_ADPCM_format" ); |
---|
123 | _alRegisterExtensionGroup( (const ALubyte*) "AL_LOKI_WAVE_format" ); |
---|
124 | _alRegisterExtensionGroup( (const ALubyte*) "AL_LOKI_play_position" ); |
---|
125 | _alRegisterExtensionGroup( (const ALubyte*) "AL_LOKI_quadriphonic" ); |
---|
126 | |
---|
127 | #ifdef ENABLE_EXTENSION_AL_EXT_MP3 |
---|
128 | _alRegisterExtensionGroup( (const ALubyte*) "AL_EXT_MP3" ); |
---|
129 | #endif /* ENABLE_EXTENSION_AL_EXT_MP3 */ |
---|
130 | |
---|
131 | #ifdef ENABLE_EXTENSION_AL_EXT_VORBIS |
---|
132 | _alRegisterExtensionGroup( (const ALubyte*) "AL_EXT_vorbis" ); |
---|
133 | #endif /* ENABLE_EXTENSION_AL_EXT_VORBIS */ |
---|
134 | |
---|
135 | #endif /* BUILTIN_EXT_LOKI */ |
---|
136 | |
---|
137 | _alRegisterExtensionGroup( (const ALubyte*) "AL_EXT_capture" ); |
---|
138 | _alRegisterExtensionGroup( (const ALubyte*) "ALC_EXT_capture" ); |
---|
139 | |
---|
140 | for(i = 0; exts[i].addr != NULL; i++) { |
---|
141 | _alRegisterExtension(exts[i].name, exts[i].addr); |
---|
142 | } |
---|
143 | |
---|
144 | /* do builtin extensions initialization */ |
---|
145 | BUILTIN_EXT_LOKI_INIT; |
---|
146 | BUILTIN_EXT_CAPTURE_INIT; |
---|
147 | BUILTIN_EXT_MP3_INIT; |
---|
148 | BUILTIN_EXT_VORBIS_INIT; |
---|
149 | |
---|
150 | return AL_TRUE; |
---|
151 | } |
---|
152 | |
---|
153 | /* |
---|
154 | * _alExit( void ) |
---|
155 | * |
---|
156 | * Finalizes things when the last context is deleted. |
---|
157 | * |
---|
158 | * FIXME: we can probably clean a lot of this up now that we have |
---|
159 | * alc{Open,Close}Device. |
---|
160 | */ |
---|
161 | void _alExit( void ) { |
---|
162 | int i; |
---|
163 | |
---|
164 | #ifndef NO_THREADING |
---|
165 | /* we could be sync, so we check mixthread for a valid ID */ |
---|
166 | if(mixthread != NULL) { |
---|
167 | time_for_mixer_to_die = AL_TRUE; |
---|
168 | |
---|
169 | _alWaitThread( mixthread ); |
---|
170 | |
---|
171 | while( time_for_mixer_to_die == AL_TRUE ) { |
---|
172 | _alMicroSleep(100000); |
---|
173 | } |
---|
174 | } |
---|
175 | #endif /* NO_THREADING */ |
---|
176 | |
---|
177 | for(i = 0; i < _ALC_MAX_CHANNELS; i++) { |
---|
178 | if(f_buffers.data[i] != NULL) { |
---|
179 | free( f_buffers.data[i] ); |
---|
180 | f_buffers.data[i] = NULL; |
---|
181 | } |
---|
182 | } |
---|
183 | |
---|
184 | f_buffers.len = 0; |
---|
185 | |
---|
186 | _alDestroyConfig(); |
---|
187 | |
---|
188 | _alDestroyExtensions(); |
---|
189 | _alDestroyExtensionGroups( ); |
---|
190 | _alDestroyMixer(); |
---|
191 | _alDestroyFilters(); |
---|
192 | |
---|
193 | _alcDestroyAll(); |
---|
194 | |
---|
195 | _alDestroyBuffers(); /* buffers after mixer and alc destroy */ |
---|
196 | |
---|
197 | /* do builtin extensions destruction */ |
---|
198 | BUILTIN_EXT_LOKI_FINI; |
---|
199 | BUILTIN_EXT_CAPTURE_FINI; |
---|
200 | BUILTIN_EXT_MP3_FINI; |
---|
201 | BUILTIN_EXT_VORBIS_FINI; |
---|
202 | |
---|
203 | return; |
---|
204 | } |
---|
205 | |
---|
206 | /* |
---|
207 | * _alStub( const char *str ) |
---|
208 | * |
---|
209 | * If DEBUG_STUB is defined, _alStub prints out a warning message. If not, no |
---|
210 | * action is taken. |
---|
211 | * |
---|
212 | */ |
---|
213 | #ifdef DEBUG_STUB |
---|
214 | void _alStub( const char *str ) { |
---|
215 | fprintf(stderr, "%s stub function\n", str); |
---|
216 | |
---|
217 | return; |
---|
218 | } |
---|
219 | #endif |
---|
220 | |
---|
221 | /* |
---|
222 | * _alLockPrintf( const char *str, const char *fn, int line ); |
---|
223 | * |
---|
224 | * _alLockPrintf is used for debugging purposes. If DEBUG_LOCK is defined, |
---|
225 | * calls to _alLockPrintf generate a print to stderr. If not, these calls are |
---|
226 | * optimized away. |
---|
227 | */ |
---|
228 | #ifdef DEBUG_LOCK |
---|
229 | int _alLockPrintf( const char *msg, const char *fn, int ln ) { |
---|
230 | static char threadstr[2048]; |
---|
231 | char blanks[] = " "; |
---|
232 | int maxlen = 18 - (strlen(fn) + log10(ln)); |
---|
233 | |
---|
234 | blanks[maxlen] = '\0'; |
---|
235 | |
---|
236 | snprintf(threadstr, sizeof(threadstr), "%s[%u]", blanks, _alSelfThread()); |
---|
237 | |
---|
238 | return _alDebug(ALD_LOCK, fn, ln, "%s %s", threadstr, msg); |
---|
239 | } |
---|
240 | #endif |
---|
241 | |
---|
242 | /* |
---|
243 | * _al_AC2ALFMT( ALuint acformat, ALuint channels ) |
---|
244 | * |
---|
245 | * Returns the openal format equivilant to the audioconvert format acformat, |
---|
246 | * with the number of channels specified by channels. |
---|
247 | */ |
---|
248 | ALenum _al_AC2ALFMT( ALuint acformat, ALuint channels ) { |
---|
249 | switch( acformat ) { |
---|
250 | case AUDIO_U8: |
---|
251 | if(channels == 4) { |
---|
252 | return AL_FORMAT_QUAD8_LOKI; |
---|
253 | } |
---|
254 | if(channels == 2) { |
---|
255 | return AL_FORMAT_STEREO8; |
---|
256 | } |
---|
257 | if(channels == 1) { |
---|
258 | return AL_FORMAT_MONO8; |
---|
259 | } |
---|
260 | break; |
---|
261 | case AUDIO_S16LSB: |
---|
262 | case AUDIO_S16MSB: |
---|
263 | if(channels == 4) { |
---|
264 | return AL_FORMAT_QUAD16_LOKI; |
---|
265 | } |
---|
266 | if(channels == 2) { |
---|
267 | return AL_FORMAT_STEREO16; |
---|
268 | } |
---|
269 | if(channels == 1) { |
---|
270 | return AL_FORMAT_MONO16; |
---|
271 | } |
---|
272 | break; |
---|
273 | } |
---|
274 | |
---|
275 | #ifdef DEBUG_CONVERT |
---|
276 | fprintf( stderr, "AC2ALFMT: wtf? format = 0x%x\n", acformat ); |
---|
277 | #endif |
---|
278 | |
---|
279 | return -1; |
---|
280 | } |
---|
281 | |
---|
282 | /* |
---|
283 | * _al_AL2ACFMT( ALenum alfmt ) |
---|
284 | * |
---|
285 | * Returns the equivilant (sort of) audioconvert format specified by alfmt. |
---|
286 | * audioconvert formats do not have channel information, so this should be |
---|
287 | * combined with _alGetChannelsFromFormat. |
---|
288 | */ |
---|
289 | ALushort _al_AL2ACFMT( ALenum alformat ) { |
---|
290 | switch( alformat ) { |
---|
291 | case AL_FORMAT_QUAD8_LOKI: |
---|
292 | case AL_FORMAT_STEREO8: |
---|
293 | case AL_FORMAT_MONO8: |
---|
294 | return AUDIO_U8; |
---|
295 | case AL_FORMAT_QUAD16_LOKI: |
---|
296 | case AL_FORMAT_STEREO16: |
---|
297 | case AL_FORMAT_MONO16: |
---|
298 | return AUDIO_S16; |
---|
299 | default: |
---|
300 | break; |
---|
301 | } |
---|
302 | |
---|
303 | #ifdef DEBUG_CONVERT |
---|
304 | fprintf(stderr, "AL2ACFMT: wtf? format = 0x%x\n", alformat); |
---|
305 | #endif |
---|
306 | |
---|
307 | return 0; |
---|
308 | } |
---|
309 | |
---|
310 | /* |
---|
311 | * _alGetChannelsFromFormat(fmt) |
---|
312 | * |
---|
313 | * evaluates to the number of channels in an openal format. |
---|
314 | */ |
---|
315 | ALubyte _alGetChannelsFromFormat(ALenum alformat) |
---|
316 | { |
---|
317 | switch( alformat ) { |
---|
318 | case AL_FORMAT_MONO8: |
---|
319 | case AL_FORMAT_MONO16: |
---|
320 | return 1; |
---|
321 | case AL_FORMAT_STEREO8: |
---|
322 | case AL_FORMAT_STEREO16: |
---|
323 | return 2; |
---|
324 | case AL_FORMAT_QUAD8_LOKI: |
---|
325 | case AL_FORMAT_QUAD16_LOKI: |
---|
326 | return 4; |
---|
327 | default: |
---|
328 | break; |
---|
329 | } |
---|
330 | |
---|
331 | #ifdef DEBUG_CONVERT |
---|
332 | fprintf(stderr, "ALCHANNELS: wtf? format = 0x%x\n", alformat); |
---|
333 | #endif |
---|
334 | return 0; |
---|
335 | } |
---|
336 | |
---|
337 | /* |
---|
338 | * _al_formatscale( ALenum format, ALuint new_channel_num ) |
---|
339 | * |
---|
340 | * Returns the openal format that is identical to format, but with sufficient |
---|
341 | * channel width to accomedate new_channel_num channels. |
---|
342 | */ |
---|
343 | ALenum _al_formatscale(ALenum format, ALuint new_channel_num) { |
---|
344 | int fmt_bits = _alGetBitsFromFormat(format); |
---|
345 | |
---|
346 | switch(new_channel_num) { |
---|
347 | case 1: |
---|
348 | switch(fmt_bits) { |
---|
349 | case 8: return AL_FORMAT_MONO8; break; |
---|
350 | case 16: return AL_FORMAT_MONO16; break; |
---|
351 | default: return -1; |
---|
352 | } |
---|
353 | break; |
---|
354 | case 2: |
---|
355 | switch(fmt_bits) { |
---|
356 | case 8: return AL_FORMAT_STEREO8; break; |
---|
357 | case 16: return AL_FORMAT_STEREO16; break; |
---|
358 | default: return -1; |
---|
359 | } |
---|
360 | break; |
---|
361 | case 4: |
---|
362 | switch(fmt_bits) { |
---|
363 | case 8: return AL_FORMAT_QUAD8_LOKI; break; |
---|
364 | case 16: return AL_FORMAT_QUAD16_LOKI; break; |
---|
365 | default: return -1; |
---|
366 | } |
---|
367 | break; |
---|
368 | default: |
---|
369 | #ifdef DEBUG_CONVERT |
---|
370 | fprintf(stderr, |
---|
371 | "No support for %d channel AL format, sorry\n", |
---|
372 | new_channel_num); |
---|
373 | #endif /* DEBUG_CONVERT */ |
---|
374 | break; |
---|
375 | } |
---|
376 | |
---|
377 | return -1; |
---|
378 | } |
---|
379 | |
---|
380 | /* |
---|
381 | * _alBuffersAppend( void **dsts, void **srcs, int len, int offset, int nc ) |
---|
382 | * |
---|
383 | * Copies srcs[0..nc-1][0..(len/2)-1] to |
---|
384 | * dsts[0..nc-1][offset/2..((offset + len)/2)-1]. |
---|
385 | */ |
---|
386 | void _alBuffersAppend(void **dsts, void **srcs, int len, int offset, int nc) { |
---|
387 | char *dstp; |
---|
388 | char *srcp; |
---|
389 | int i; |
---|
390 | int k; |
---|
391 | |
---|
392 | for(i = 0; i < nc; i++) { |
---|
393 | dstp = dsts[i]; |
---|
394 | srcp = srcs[i]; |
---|
395 | |
---|
396 | dstp += offset; |
---|
397 | |
---|
398 | for(k = 0; k < len; k++) { |
---|
399 | dstp[k] = srcp[k]; |
---|
400 | } |
---|
401 | } |
---|
402 | |
---|
403 | return; |
---|
404 | } |
---|
405 | |
---|
406 | /* |
---|
407 | * _alRotatePointAboutAxis( const ALfloat angle, ALfloat *point, |
---|
408 | * const ALfloat *axis ) |
---|
409 | * |
---|
410 | * Rotates point angle radians about axis. |
---|
411 | * |
---|
412 | * angle - in radians |
---|
413 | * point - x/y/z |
---|
414 | * axis - x/y/z (unit vector) |
---|
415 | * |
---|
416 | * FIXME: check my math |
---|
417 | * FIXME: needs to check args |
---|
418 | */ |
---|
419 | #if 0 |
---|
420 | void _alRotatePointAboutAxis( const ALfloat angle, ALfloat *point, |
---|
421 | const ALfloat *axis ) { |
---|
422 | ALmatrix *m; |
---|
423 | ALmatrix *pm; |
---|
424 | ALmatrix *rm; |
---|
425 | |
---|
426 | float s; |
---|
427 | float c; |
---|
428 | float t; |
---|
429 | |
---|
430 | float x = axis[0]; |
---|
431 | float y = axis[1]; |
---|
432 | float z = axis[2]; |
---|
433 | int i; |
---|
434 | |
---|
435 | if(angle == 0.0) { |
---|
436 | /* FIXME: use epsilon? */ |
---|
437 | return; |
---|
438 | } |
---|
439 | |
---|
440 | s = sin( angle ); |
---|
441 | c = cos( angle ); |
---|
442 | t = 1.0 - c; |
---|
443 | |
---|
444 | m = _alMatrixAlloc(3, 3); |
---|
445 | pm = _alMatrixAlloc(1, 3); |
---|
446 | rm = _alMatrixAlloc(1, 3); |
---|
447 | |
---|
448 | #if 1 |
---|
449 | m->data[0][0] = t * x * x + c; |
---|
450 | m->data[0][1] = t * x * y - s * z; |
---|
451 | m->data[0][2] = t * x * z + s * y; |
---|
452 | |
---|
453 | m->data[1][0] = t * x * y + s * z; |
---|
454 | m->data[1][1] = t * y * y + c; |
---|
455 | m->data[1][2] = t * y * z - s * x; |
---|
456 | |
---|
457 | m->data[2][0] = t * x * z - s * y; |
---|
458 | m->data[2][1] = t * y * z + s * x; |
---|
459 | m->data[2][2] = t * z * z + c; |
---|
460 | #else |
---|
461 | m->data[0][0] = t * x * x + c; |
---|
462 | m->data[1][0] = t * x * y - s * z; |
---|
463 | m->data[2][0] = t * x * z + s * y; |
---|
464 | |
---|
465 | m->data[0][1] = t * x * y + s * z; |
---|
466 | m->data[1][1] = t * y * y + c; |
---|
467 | m->data[2][1] = t * y * z - s * x; |
---|
468 | |
---|
469 | m->data[0][2] = t * x * z - s * y; |
---|
470 | m->data[1][2] = t * y * z + s * x; |
---|
471 | m->data[2][2] = t * z * z + c; |
---|
472 | #endif |
---|
473 | |
---|
474 | for(i = 0; i < 3; i++) { |
---|
475 | pm->data[0][i] = point[i]; |
---|
476 | rm->data[0][i] = 0; |
---|
477 | } |
---|
478 | |
---|
479 | /* |
---|
480 | * rm = pm * m |
---|
481 | */ |
---|
482 | _alMatrixMul(rm, pm, m); |
---|
483 | |
---|
484 | for(i = 0; i < 3; i++) { |
---|
485 | point[i] = rm->data[0][i]; |
---|
486 | } |
---|
487 | |
---|
488 | _alMatrixFree(m); |
---|
489 | _alMatrixFree(pm); |
---|
490 | _alMatrixFree(rm); |
---|
491 | |
---|
492 | return; |
---|
493 | } |
---|
494 | #endif |
---|
495 | |
---|
496 | /* |
---|
497 | * _alSlurp( const char *fname, void **buffer ) |
---|
498 | * |
---|
499 | * slurp file named by fname to into *buffer, mallocing memory. |
---|
500 | */ |
---|
501 | int _alSlurp(const char *fname, void **buffer) { |
---|
502 | struct stat buf; |
---|
503 | FILE *fh; |
---|
504 | size_t len; |
---|
505 | |
---|
506 | if((fname == NULL) || (buffer == NULL)) { |
---|
507 | return -1; |
---|
508 | } |
---|
509 | |
---|
510 | if(stat(fname, &buf) == -1) { |
---|
511 | /* couldn't stat file */ |
---|
512 | return -1; |
---|
513 | } |
---|
514 | |
---|
515 | len = buf.st_size; |
---|
516 | if(len <= 0) { |
---|
517 | return -1; |
---|
518 | } |
---|
519 | |
---|
520 | fh = fopen(fname, "rb"); |
---|
521 | if(fh == NULL) { |
---|
522 | /* couldn't open file */ |
---|
523 | return -1; |
---|
524 | } |
---|
525 | |
---|
526 | *buffer = malloc(len); |
---|
527 | if(*buffer == NULL) { |
---|
528 | return -1; |
---|
529 | } |
---|
530 | |
---|
531 | if(fread(*buffer, len, 1, fh) < 1) { |
---|
532 | free(*buffer); |
---|
533 | |
---|
534 | return -1; |
---|
535 | } |
---|
536 | |
---|
537 | fclose( fh ); |
---|
538 | |
---|
539 | return len; |
---|
540 | } |
---|
541 | |
---|
542 | /* |
---|
543 | * _al_PCMRatioify( ALuint ffreq, ALuint tfreq, |
---|
544 | * ALenum ffmt, ALenum tfmt, |
---|
545 | * ALuint samples ) |
---|
546 | * |
---|
547 | * Returns the number of byte necessary to contain samples worth of data, if |
---|
548 | * the data undergoes a conversion from ffreq to tfreq in the sampling-rate |
---|
549 | * and from ffmt to tfmt in terms of format. |
---|
550 | */ |
---|
551 | ALuint _al_PCMRatioify( ALuint ffreq, ALuint tfreq, |
---|
552 | ALenum ffmt, ALenum tfmt, |
---|
553 | ALuint samples ) { |
---|
554 | ALuint ret = samples; |
---|
555 | |
---|
556 | ret *= ((float) tfreq / (float) ffreq); |
---|
557 | |
---|
558 | ret *= (_alGetBitsFromFormat( ffmt ) / 8 ); |
---|
559 | ret /= (_alGetBitsFromFormat( tfmt ) / 8 ); |
---|
560 | |
---|
561 | return ret; |
---|
562 | } |
---|
563 | |
---|
564 | /* |
---|
565 | * _al_AL2FMT( ALuint channels, ALuint bits ) |
---|
566 | * |
---|
567 | * Returns the openal format that has the number of channels channels and the |
---|
568 | * bit depth bits. |
---|
569 | */ |
---|
570 | ALenum _al_AL2FMT(ALuint channels, ALuint bits) { |
---|
571 | switch(channels) { |
---|
572 | case 1: |
---|
573 | if(bits == 8) return AL_FORMAT_MONO8; |
---|
574 | if(bits == 16) return AL_FORMAT_MONO16; |
---|
575 | break; |
---|
576 | case 2: |
---|
577 | if(bits == 8) return AL_FORMAT_STEREO8; |
---|
578 | if(bits == 16) return AL_FORMAT_STEREO16; |
---|
579 | break; |
---|
580 | case 4: |
---|
581 | if(bits == 8) return AL_FORMAT_QUAD8_LOKI; |
---|
582 | if(bits == 16) return AL_FORMAT_QUAD16_LOKI; |
---|
583 | break; |
---|
584 | } |
---|
585 | |
---|
586 | return -1; |
---|
587 | } |
---|
588 | |
---|
589 | #ifdef _WIN32 |
---|
590 | /* sleep for n microseconds |
---|
591 | * |
---|
592 | * Well, not really. For Windows, we divide |
---|
593 | * by 10 and sleep for milliseconds |
---|
594 | */ |
---|
595 | void _alMicroSleep(unsigned int n) { |
---|
596 | Sleep(n / 1000); |
---|
597 | |
---|
598 | return; |
---|
599 | } |
---|
600 | |
---|
601 | #elif defined(__MORPHOS__) |
---|
602 | |
---|
603 | #include <clib/amiga_protos.h> |
---|
604 | |
---|
605 | void _alMicroSleep(unsigned int n) { |
---|
606 | TimeDelay(UNIT_MICROHZ, n / 1000000, n % 1000000); |
---|
607 | |
---|
608 | return; |
---|
609 | } |
---|
610 | |
---|
611 | #elif defined(__sgi) |
---|
612 | |
---|
613 | void _alMicroSleep(unsigned int n) { |
---|
614 | usleep (n); |
---|
615 | return; |
---|
616 | } |
---|
617 | |
---|
618 | #else |
---|
619 | |
---|
620 | /* sleep for n microseconds */ |
---|
621 | void _alMicroSleep(unsigned int n) { |
---|
622 | struct timeval tv; |
---|
623 | |
---|
624 | tv.tv_sec = 0; |
---|
625 | tv.tv_usec = n; |
---|
626 | |
---|
627 | select(0, NULL, NULL, NULL, &tv); |
---|
628 | |
---|
629 | return; |
---|
630 | } |
---|
631 | |
---|
632 | #endif /* _WIN32 */ |
---|
633 | |
---|
634 | /* |
---|
635 | * _alDegreeToRadian( ALfloat degree ) |
---|
636 | * |
---|
637 | * Returns radian equilvilant of degree. |
---|
638 | * |
---|
639 | */ |
---|
640 | ALfloat _alDegreeToRadian( ALfloat degree ) { |
---|
641 | return degree * (M_PI / 180.0f); |
---|
642 | } |
---|
643 | |
---|
644 | /* |
---|
645 | * _alCheckRangef( ALfloat val, ALfloat min, ALfloat max ) |
---|
646 | * |
---|
647 | * Returns AL_TRUE if val is between min and max, inclusive. |
---|
648 | */ |
---|
649 | ALboolean _alCheckRangef(ALfloat val, ALfloat min, ALfloat max) { |
---|
650 | ALboolean retval = AL_TRUE; |
---|
651 | |
---|
652 | #ifdef DEBUG |
---|
653 | if( _alIsFinite(val) == 0 ) { |
---|
654 | retval = AL_FALSE; |
---|
655 | } |
---|
656 | #endif |
---|
657 | |
---|
658 | if(val < min) { |
---|
659 | retval = AL_FALSE; |
---|
660 | } |
---|
661 | if(val > max) { |
---|
662 | retval = AL_FALSE; |
---|
663 | } |
---|
664 | |
---|
665 | return retval; |
---|
666 | } |
---|
667 | |
---|
668 | /* |
---|
669 | * _alCheckRangeb( ALfloat val ) |
---|
670 | * |
---|
671 | * Returns AL_TRUE if val is either AL_TRUE or AL_FALSE. |
---|
672 | */ |
---|
673 | ALboolean _alCheckRangeb(ALboolean b) { |
---|
674 | switch(b) { |
---|
675 | case AL_TRUE: |
---|
676 | case AL_FALSE: |
---|
677 | return AL_TRUE; |
---|
678 | default: |
---|
679 | break; |
---|
680 | } |
---|
681 | |
---|
682 | return AL_FALSE; |
---|
683 | } |
---|
684 | |
---|
685 | /* |
---|
686 | * ALboolean _alIsZeroVector( const ALfloat *fv1 ) |
---|
687 | * |
---|
688 | * Returns true if fv1 == { 0.0f, 0.0f, 0.0f } |
---|
689 | */ |
---|
690 | ALboolean _alIsZeroVector(const ALfloat *fv) |
---|
691 | { |
---|
692 | if(fv[0] != 0.0f) { |
---|
693 | return AL_FALSE; |
---|
694 | } |
---|
695 | |
---|
696 | if(fv[1] != 0.0f) { |
---|
697 | return AL_FALSE; |
---|
698 | } |
---|
699 | |
---|
700 | if(fv[2] != 0.0f) { |
---|
701 | return AL_FALSE; |
---|
702 | } |
---|
703 | |
---|
704 | return AL_TRUE; |
---|
705 | } |
---|
706 | |
---|
707 | /* |
---|
708 | * _al_RAWFORMAT( ALenum format ) |
---|
709 | * |
---|
710 | * Returns AL_TRUE if format is an openal format specifying raw pcm data, |
---|
711 | * AL_FALSE otherwise. |
---|
712 | */ |
---|
713 | ALboolean _al_RAWFORMAT(ALenum format) |
---|
714 | { |
---|
715 | switch(format) { |
---|
716 | case AL_FORMAT_MONO16: |
---|
717 | case AL_FORMAT_MONO8: |
---|
718 | case AL_FORMAT_STEREO16: |
---|
719 | case AL_FORMAT_STEREO8: |
---|
720 | case AL_FORMAT_QUAD16_LOKI: |
---|
721 | case AL_FORMAT_QUAD8_LOKI: |
---|
722 | return AL_TRUE; |
---|
723 | default: |
---|
724 | break; |
---|
725 | } |
---|
726 | |
---|
727 | return AL_FALSE; |
---|
728 | } |
---|
729 | |
---|
730 | /* |
---|
731 | * _alGetBitsFromFormat( ALenum format ) |
---|
732 | * |
---|
733 | * Returns the number of bits per sample for the given format. |
---|
734 | */ |
---|
735 | ALbyte _alGetBitsFromFormat(ALenum format) |
---|
736 | { |
---|
737 | switch(format) { |
---|
738 | case AL_FORMAT_MONO16: |
---|
739 | case AL_FORMAT_STEREO16: |
---|
740 | case AL_FORMAT_QUAD16_LOKI: |
---|
741 | case AL_FORMAT_IMA_ADPCM_MONO16_EXT: |
---|
742 | case AL_FORMAT_IMA_ADPCM_STEREO16_EXT: |
---|
743 | return 16; |
---|
744 | break; |
---|
745 | case AL_FORMAT_MONO8: |
---|
746 | case AL_FORMAT_STEREO8: |
---|
747 | case AL_FORMAT_QUAD8_LOKI: |
---|
748 | return 8; |
---|
749 | break; |
---|
750 | } |
---|
751 | |
---|
752 | assert(0); |
---|
753 | |
---|
754 | return -1; |
---|
755 | } |
---|
756 | |
---|
757 | /* |
---|
758 | * _alSmallestPowerOfTwo( ALuint num ) |
---|
759 | * |
---|
760 | * Returns smallest power of two large that meets or exceeds num. |
---|
761 | */ |
---|
762 | ALuint _alSmallestPowerOfTwo( ALuint num ) |
---|
763 | { |
---|
764 | ALuint retval = 1; |
---|
765 | |
---|
766 | while( retval < num ) { |
---|
767 | retval <<= 1; |
---|
768 | } |
---|
769 | |
---|
770 | return retval; |
---|
771 | } |
---|
772 | |
---|
773 | /* |
---|
774 | * _alIsFinite( ALfloat v ) |
---|
775 | * |
---|
776 | * Returns AL_TRUE if v is a finite, non NaN value, AL_FALSE otherwise. |
---|
777 | */ |
---|
778 | ALboolean _alIsFinite( ALfloat v ) |
---|
779 | { |
---|
780 | /* skip infinite test for now */ |
---|
781 | if(v == v) { |
---|
782 | return AL_TRUE; |
---|
783 | } |
---|
784 | |
---|
785 | return AL_FALSE; |
---|
786 | } |
---|
787 | |
---|
788 | |
---|
789 | /* |
---|
790 | * Returns smallest power of two that meets or exceeds num. |
---|
791 | */ |
---|
792 | ALuint |
---|
793 | _alSpot( ALuint num ) |
---|
794 | { |
---|
795 | ALuint retval = 0; |
---|
796 | num >>= 1; |
---|
797 | while(num) { |
---|
798 | retval++; |
---|
799 | num >>= 1; |
---|
800 | } |
---|
801 | return retval; |
---|
802 | } |
---|