openalbridge/openalbridge.c
changeset 2326 0ddf641fddee
parent 2261 57e99c908e7c
child 2392 a55dbef5cf31
equal deleted inserted replaced
2325:b07e87f6430f 2326:0ddf641fddee
       
     1 /*
       
     2  * OpenAL Bridge - a simple portable library for OpenAL interface
       
     3  * Copyright (c) 2009 Vittorio Giovara <vittorio.giovara@gmail.com>
       
     4  *
       
     5  * This program is free software; you can redistribute it and/or modify
       
     6  * it under the terms of the GNU Lesser General Public License as published by
       
     7  * the Free Software Foundation; version 2 of the License
       
     8  *
       
     9  * This program is distributed in the hope that it will be useful,
       
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    12  * GNU Lesser General Public License for more details.
       
    13  *
       
    14  * You should have received a copy of the GNU Lesser General Public License
       
    15  * along with this program; if not, write to the Free Software
       
    16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
       
    17  */
       
    18 
       
    19 #include "openalbridge.h"
       
    20 #include "wrappers.h"
       
    21 #include "alc.h"
       
    22 #include "loaders.h"
       
    23 #include "endianness.h"
       
    24 
       
    25 #ifdef __CPLUSPLUS
       
    26 extern "C" {
       
    27 #endif 
       
    28     
       
    29     /*Sources are points emitting sound*/
       
    30     ALuint *Sources;
       
    31     /*Buffers hold sound data*/
       
    32     ALuint *Buffers;
       
    33     /*index for Sources and Buffers*/
       
    34     ALuint globalindex, globalsize, increment;
       
    35     
       
    36     ALboolean openalReady = AL_FALSE;
       
    37     
       
    38     ALboolean openal_close (void) {
       
    39         /*Stop all sounds, deallocate all memory and close OpenAL */
       
    40         ALCcontext *context;
       
    41         ALCdevice  *device;
       
    42         
       
    43         if(openalReady == AL_FALSE) {
       
    44             fprintf(stderr, "ERROR: OpenAL not initialized\n");
       
    45             return AL_FALSE;
       
    46         }
       
    47         
       
    48         alSourceStopv	(globalsize, Sources);
       
    49         alDeleteSources (globalsize, Sources);
       
    50         alDeleteBuffers (globalsize, Buffers);
       
    51         
       
    52         free(Sources);
       
    53         free(Buffers);
       
    54         
       
    55         context = alcGetCurrentContext();
       
    56         device  = alcGetContextsDevice(context);
       
    57         
       
    58         alcMakeContextCurrent(NULL);
       
    59         alcDestroyContext(context);
       
    60         alcCloseDevice(device);
       
    61         
       
    62         openalReady = AL_FALSE;
       
    63         
       
    64         return AL_TRUE;
       
    65     }
       
    66     
       
    67     ALboolean openal_ready(void) {
       
    68         return openalReady;
       
    69     }
       
    70     
       
    71     ALboolean openal_init(uint32_t memorysize) {	
       
    72         /*Initialize an OpenAL contex and allocate memory space for data and buffers*/
       
    73         ALCcontext *context;
       
    74         ALCdevice *device;
       
    75         const ALCchar *default_device;
       
    76         
       
    77         /*Position of the listener*/
       
    78         ALfloat ListenerPos[] = { 0.0, 0.0, 0.0 };
       
    79         /*Velocity of the listener*/
       
    80         ALfloat ListenerVel[] = { 0.0, 0.0, 0.0 };
       
    81         /*Orientation of the listener. (first 3 elements are "at", second 3 are "up")*/
       
    82         ALfloat ListenerOri[] = { 0.0, 0.0, -1.0,  0.0, 1.0, 0.0 };
       
    83         
       
    84         if(openalReady == AL_TRUE) {
       
    85             fprintf(stderr, "ERROR: OpenAL already initialized\n");
       
    86             return AL_FALSE;
       
    87         }
       
    88         
       
    89         default_device = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
       
    90         fprintf(stderr, "Using default device: %s\n", default_device);
       
    91         
       
    92         if ((device = alcOpenDevice(default_device)) == NULL) {
       
    93             fprintf(stderr, "ERROR: Failed to open sound device\n");
       
    94             return AL_FALSE;
       
    95         }
       
    96         
       
    97         context = alcCreateContext(device, NULL);
       
    98         alcMakeContextCurrent(context);
       
    99         alcProcessContext(context);
       
   100         
       
   101         if (AlGetError("ERROR %d: Creating a new contex\n") != AL_TRUE)
       
   102             return AL_FALSE;
       
   103         
       
   104         /*allocate memory space for buffers and sources*/
       
   105 	if (memorysize == 0)
       
   106 	    globalsize = 50;
       
   107 	else
       
   108 	    globalsize = memorysize;
       
   109         increment  = globalsize;
       
   110         Buffers = (ALuint*) Malloc(sizeof(ALuint)*globalsize);
       
   111         Sources = (ALuint*) Malloc(sizeof(ALuint)*globalsize);
       
   112         
       
   113         /*set the listener gain, position (on xyz axes), velocity (one value for each axe) and orientation*/
       
   114         alListenerf (AL_GAIN,        1.0f       );
       
   115         alListenerfv(AL_POSITION,    ListenerPos);
       
   116         alListenerfv(AL_VELOCITY,    ListenerVel);
       
   117         alListenerfv(AL_ORIENTATION, ListenerOri);
       
   118         
       
   119         if (AlGetError("ERROR %d: Setting Listener properties\n") != AL_TRUE)
       
   120             return AL_FALSE;
       
   121         
       
   122         openalReady = AL_TRUE;
       
   123         
       
   124         alGetError();  /* clear any AL errors beforehand */
       
   125         return AL_TRUE;
       
   126     }
       
   127     
       
   128     
       
   129     ALboolean helper_realloc (void) {
       
   130         /*expands allocated memory when loading more sound files than expected*/
       
   131         int oldsize = globalsize;
       
   132         globalsize += increment;
       
   133 
       
   134 #ifdef DEBUG
       
   135         fprintf(stderr, "OpenAL: Realloc in process from %d to %d\n", oldsize, globalsize);
       
   136 #endif
       
   137         
       
   138         Buffers = (ALuint*) Realloc(Buffers, sizeof(ALuint)*globalsize);
       
   139         Sources = (ALuint*) Realloc(Sources, sizeof(ALuint)*globalsize);
       
   140         
       
   141         return AL_TRUE;
       
   142     }
       
   143     
       
   144     
       
   145     ALint openal_loadfile (const char *filename){
       
   146         /*Open a file, load into memory and allocate the Source buffer for playing*/
       
   147         ALfloat SourcePos[] = { 0.0, 0.0, 0.0 }; /*Position of the source sound*/
       
   148         ALfloat SourceVel[] = { 0.0, 0.0, 0.0 }; /*Velocity of the source sound*/
       
   149         ALenum format;
       
   150         ALsizei bitsize, freq;
       
   151         char *data;
       
   152         uint32_t fileformat;
       
   153         ALenum error;
       
   154         FILE *fp;
       
   155         
       
   156         if(openalReady == AL_FALSE) {
       
   157             fprintf(stderr, "ERROR: OpenAL not initialized\n");
       
   158             return AL_FALSE;
       
   159         }
       
   160         
       
   161         /*when the buffers are all used, we can expand memory to accept new files*/
       
   162         if (globalindex == globalsize)
       
   163             helper_realloc();
       
   164         
       
   165         /*detect the file format, as written in the first 4 bytes of the header*/
       
   166         fp = Fopen (filename, "rb");
       
   167         if (fp == NULL)
       
   168             return -1;
       
   169         error = fread (&fileformat, sizeof(uint32_t), 1, fp);
       
   170         fclose (fp);
       
   171         
       
   172         if (error < 0) {
       
   173             fprintf(stderr, "ERROR: file %s is too short \n", filename);
       
   174             return -2;
       
   175         }
       
   176         
       
   177         /*prepare the buffer to receive data*/
       
   178         alGenBuffers(1, &Buffers[globalindex]);
       
   179         
       
   180         if (AlGetError("ERROR %d: Allocating memory for buffers\n") != AL_TRUE)
       
   181             return -3;
       
   182         
       
   183         /*prepare the source to emit sound*/
       
   184         alGenSources(1, &Sources[globalindex]);
       
   185         
       
   186         if (AlGetError("ERROR %d: Allocating memory for sources\n") != AL_TRUE)
       
   187             return -4;
       
   188         
       
   189         
       
   190         if (fileformat == 0x5367674F) /*check if ogg*/
       
   191             error = load_oggvorbis (filename, &format, &data, &bitsize, &freq);
       
   192         else {
       
   193             if (fileformat == 0x46464952) /*check if wav*/
       
   194                 error = load_wavpcm (filename, &format, &data, &bitsize, &freq);
       
   195             else {
       
   196                 fprintf(stderr, "ERROR: File format (%08X) not supported!\n", invert_endianness(fileformat));
       
   197                 return -5;
       
   198             }
       
   199         }
       
   200         
       
   201         /*copy pcm data in one buffer*/
       
   202         alBufferData(Buffers[globalindex], format, data, bitsize, freq);
       
   203         free(data);		/*deallocate data to save memory*/
       
   204         
       
   205         if (AlGetError("ERROR %d: Writing data to buffer\n") != AL_TRUE)
       
   206             return -6;
       
   207         
       
   208         /*set source properties that it will use when it's in playback*/
       
   209         alSourcei (Sources[globalindex], AL_BUFFER,   Buffers[globalindex]  );
       
   210         alSourcef (Sources[globalindex], AL_PITCH,    1.0f                  );
       
   211         alSourcef (Sources[globalindex], AL_GAIN,     1.0f                  );
       
   212         alSourcefv(Sources[globalindex], AL_POSITION, SourcePos             );
       
   213         alSourcefv(Sources[globalindex], AL_VELOCITY, SourceVel             );
       
   214         alSourcei (Sources[globalindex], AL_LOOPING,  0                     );
       
   215         
       
   216         if (AlGetError("ERROR %d: Setting source properties\n") != AL_TRUE)
       
   217             return -7;
       
   218         
       
   219         alGetError();  /* clear any AL errors beforehand */
       
   220         
       
   221         /*returns the index of the source you just loaded, increments it and exits*/
       
   222         return globalindex++;
       
   223     }
       
   224     
       
   225     
       
   226     ALboolean openal_toggleloop (uint32_t index){
       
   227         /*Set or unset looping mode*/
       
   228         ALint loop;
       
   229         
       
   230         if(openalReady == AL_FALSE) {
       
   231             fprintf(stderr, "ERROR: OpenAL not initialized\n");
       
   232             return AL_FALSE;
       
   233         }
       
   234         
       
   235         if (index >= globalsize) {
       
   236             fprintf(stderr, "ERROR: index out of bounds (got %d, max %d)\n", index, globalindex);
       
   237             return AL_FALSE;
       
   238         }
       
   239         
       
   240         alGetSourcei (Sources[index], AL_LOOPING, &loop);
       
   241         alSourcei (Sources[index], AL_LOOPING, !((uint8_t) loop) & 0x00000001);
       
   242         if (AlGetError("ERROR %d: Getting or setting loop property\n") != AL_TRUE)
       
   243             return AL_FALSE;
       
   244         
       
   245         alGetError();  /* clear any AL errors beforehand */
       
   246         
       
   247         return AL_TRUE;
       
   248     }
       
   249     
       
   250     
       
   251     ALboolean openal_setvolume (uint32_t index, uint8_t percentage) {
       
   252         if(openalReady == AL_FALSE) {
       
   253             fprintf(stderr, "ERROR: OpenAL not initialized\n");
       
   254             return AL_FALSE;
       
   255         }
       
   256         
       
   257         /*Set volume for sound number index*/
       
   258         if (index >= globalindex) {
       
   259             fprintf(stderr, "ERROR: index out of bounds (got %d, max %d)\n", index, globalindex);
       
   260             return AL_FALSE;
       
   261         }
       
   262         
       
   263         if (percentage > 100)
       
   264             percentage = 100;
       
   265         alSourcef (Sources[index], AL_GAIN, (float) percentage/100.0f);
       
   266         if (AlGetError2("ERROR %d: setting volume for sound %d\n", index) != AL_TRUE)
       
   267             return AL_FALSE;
       
   268         
       
   269         alGetError();  /* clear any AL errors beforehand */
       
   270         
       
   271         return AL_TRUE;
       
   272     }
       
   273     
       
   274     
       
   275     ALboolean openal_setglobalvolume (uint8_t percentage) {
       
   276         if(openalReady == AL_FALSE) {
       
   277             fprintf(stderr, "ERROR: OpenAL not initialized\n");
       
   278             return AL_FALSE;
       
   279         }
       
   280         
       
   281         /*Set volume for all sounds*/		
       
   282         if (percentage > 100)
       
   283             percentage = 100;
       
   284         alListenerf (AL_GAIN, (float) percentage/100.0f);
       
   285         if (AlGetError("ERROR %d: Setting global volume\n") != AL_TRUE)
       
   286             return AL_FALSE;
       
   287         
       
   288         alGetError();  /* clear any AL errors beforehand */
       
   289         
       
   290         return AL_TRUE;
       
   291     }
       
   292     
       
   293     
       
   294     ALboolean openal_togglemute () {
       
   295         /*Mute or unmute sound*/
       
   296         ALfloat mute;
       
   297         
       
   298         if(openalReady == AL_FALSE) {
       
   299             fprintf(stderr, "ERROR: OpenAL not initialized\n");
       
   300             return AL_FALSE;
       
   301         }
       
   302         
       
   303         alGetListenerf (AL_GAIN, &mute);
       
   304         if (mute > 0) 
       
   305             mute = 0;
       
   306         else
       
   307             mute = 1.0;
       
   308         alListenerf (AL_GAIN, mute);
       
   309         if (AlGetError("ERROR %d: Setting mute property\n") != AL_TRUE)
       
   310             return AL_FALSE;
       
   311         
       
   312         alGetError();  /* clear any AL errors beforehand */
       
   313         
       
   314         return AL_TRUE;
       
   315     }
       
   316     
       
   317     
       
   318     ALboolean openal_fade (uint32_t index, uint16_t quantity, ALboolean direction) {
       
   319         /*Fade in or out by calling a helper thread*/
       
   320 #ifndef _WIN32
       
   321         pthread_t thread;
       
   322 #else
       
   323         HANDLE Thread;
       
   324         DWORD threadID;
       
   325 #endif
       
   326         fade_t *fade;
       
   327         
       
   328         if(openalReady == AL_FALSE) {
       
   329             fprintf(stderr, "ERROR: OpenAL not initialized\n");
       
   330             return AL_FALSE;
       
   331         }
       
   332         
       
   333         fade = (fade_t*) Malloc(sizeof(fade_t));
       
   334         fade->index = index;
       
   335         fade->quantity = quantity;
       
   336         
       
   337         if (index >= globalindex) {
       
   338             fprintf(stderr, "ERROR: index out of bounds (got %d, max %d)\n", index, globalindex);
       
   339             return AL_FALSE;
       
   340         }
       
   341         
       
   342         if (direction == FADE_IN)
       
   343 #ifndef _WIN32
       
   344             pthread_create(&thread, NULL, helper_fadein, (void*) fade);
       
   345 #else
       
   346         Thread = _beginthread(&helper_fadein, 0, (void*) fade);
       
   347 #endif
       
   348         else {
       
   349             if (direction == FADE_OUT)
       
   350 #ifndef _WIN32
       
   351                 pthread_create(&thread, NULL, helper_fadeout, (void*) fade);
       
   352 #else
       
   353             Thread = _beginthread(&helper_fadeout, 0, (void*) fade);
       
   354 #endif	
       
   355             else {
       
   356                 fprintf(stderr, "ERROR: unknown direction for fade (%d)\n", direction);
       
   357                 free(fade);
       
   358                 return AL_FALSE;
       
   359             }
       
   360         }
       
   361         
       
   362 #ifndef _WIN32
       
   363         pthread_detach(thread);
       
   364 #endif
       
   365         
       
   366         alGetError();  /* clear any AL errors beforehand */
       
   367         
       
   368         return AL_TRUE;
       
   369     }
       
   370     
       
   371     
       
   372     ALboolean openal_fadeout (uint32_t index, uint16_t quantity) {
       
   373         /*wrapper for fadeout*/
       
   374         return openal_fade(index, quantity, FADE_OUT);
       
   375     }
       
   376     
       
   377     
       
   378     ALboolean openal_fadein (uint32_t index, uint16_t quantity) {
       
   379         /*wrapper for fadein*/
       
   380         return openal_fade(index, quantity, FADE_IN);
       
   381     }
       
   382     
       
   383     
       
   384     ALboolean openal_setposition (uint32_t index, float x, float y, float z) {
       
   385         if(openalReady == AL_FALSE) {
       
   386             fprintf(stderr, "ERROR: OpenAL not initialized\n");
       
   387             return AL_FALSE;
       
   388         }
       
   389         if (index >= globalindex) {
       
   390             fprintf(stderr, "ERROR: index out of bounds (got %d, max %d)\n", index, globalindex);
       
   391             return AL_FALSE;
       
   392         }
       
   393         
       
   394         alSource3f(Sources[index], AL_POSITION, x, y, z);
       
   395         if (AlGetError2("ERROR %d: setting position for sound %d\n", index) != AL_TRUE)
       
   396             return AL_FALSE;
       
   397         
       
   398         return AL_TRUE;
       
   399     }
       
   400     
       
   401     
       
   402     ALboolean openal_playsound (uint32_t index){
       
   403         if(openalReady == AL_FALSE) {
       
   404             fprintf(stderr, "ERROR: OpenAL not initialized\n");
       
   405             return AL_FALSE;
       
   406         }
       
   407         
       
   408         /*Play sound number index*/
       
   409         if (index >= globalindex) {
       
   410             fprintf(stderr, "ERROR: index out of bounds (got %d, max %d)\n", index, globalindex);
       
   411             return AL_FALSE;
       
   412         }
       
   413         alSourcePlay(Sources[index]);
       
   414         if (AlGetError2("ERROR %d: Playing sound %d\n", index) != AL_TRUE)
       
   415             return AL_FALSE;
       
   416         
       
   417         alGetError();  /* clear any AL errors beforehand */
       
   418         
       
   419         return AL_TRUE;
       
   420     }
       
   421     
       
   422     
       
   423     ALboolean openal_pausesound(uint32_t index){
       
   424         if(openalReady == AL_FALSE) {
       
   425             fprintf(stderr, "ERROR: OpenAL not initialized\n");
       
   426             return AL_FALSE;
       
   427         }
       
   428         
       
   429         /*Pause sound number index*/
       
   430         if (index >= globalindex) {
       
   431             fprintf(stderr, "ERROR: index out of bounds (got %d, max %d)\n", index, globalindex);
       
   432             return AL_FALSE;
       
   433         }
       
   434         alSourcePause(Sources[index]);
       
   435         if (AlGetError2("ERROR %d: Pausing sound %d\n", index) != AL_TRUE)
       
   436             return AL_FALSE;
       
   437         
       
   438         return AL_TRUE;
       
   439     }
       
   440     
       
   441     
       
   442     ALboolean openal_stopsound(uint32_t index){
       
   443         if(openalReady == AL_FALSE) {
       
   444             fprintf(stderr, "ERROR: OpenAL not initialized\n");
       
   445             return AL_FALSE;
       
   446         }
       
   447         
       
   448         /*Stop sound number index*/
       
   449         if (index >= globalindex) {
       
   450             fprintf(stderr, "ERROR: index out of bounds (got %d, max %d)\n", index, globalindex);
       
   451             return AL_FALSE;
       
   452         }
       
   453         alSourceStop(Sources[index]);
       
   454         if (AlGetError2("ERROR %d: Stopping sound %d\n", index) != AL_TRUE)
       
   455             return AL_FALSE;
       
   456         
       
   457         alGetError();  /* clear any AL errors beforehand */
       
   458         
       
   459         return AL_TRUE;
       
   460     }
       
   461     
       
   462 #ifdef __CPLUSPLUS
       
   463 }
       
   464 #endif