Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/openal-0.0.8/src/al_main.c @ 17

Last change on this file since 17 was 17, checked in by landauf, 16 years ago

added openal

File size: 15.5 KB
Line 
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 */
58extern ThreadID mixthread;
59
60/*
61 * pcm buffers that filters act on
62 */
63_alDecodeScratch f_buffers;
64
65/*
66 * Our extension functions
67 */
68static 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 */
93ALboolean _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 */
161void _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
214void _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
229int _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 */
248ALenum _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 */
289ALushort _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 */
315ALubyte _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 */
343ALenum _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 */
386void _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
420void _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 */
501int _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 */
551ALuint _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 */
570ALenum _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 */
595void _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
605void _alMicroSleep(unsigned int n) {
606        TimeDelay(UNIT_MICROHZ, n / 1000000, n % 1000000);
607
608        return;
609}
610
611#elif defined(__sgi)
612
613void _alMicroSleep(unsigned int n) {
614        usleep (n);
615        return;
616}
617
618#else
619
620/* sleep for n microseconds */
621void _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 */
640ALfloat _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 */
649ALboolean _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 */
673ALboolean _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 */
690ALboolean _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 */
713ALboolean _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 */
735ALbyte _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 */
762ALuint _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 */
778ALboolean _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 */
792ALuint
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}
Note: See TracBrowser for help on using the repository browser.