openalbridge/openalwrap.c
changeset 2326 0ddf641fddee
parent 2325 b07e87f6430f
child 2327 4832b77ec958
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 "openalwrap.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         globalsize = memorysize;
       
   106         increment  = memorysize;
       
   107         Buffers = (ALuint*) Malloc(sizeof(ALuint)*globalsize);
       
   108         Sources = (ALuint*) Malloc(sizeof(ALuint)*globalsize);
       
   109         
       
   110         /*set the listener gain, position (on xyz axes), velocity (one value for each axe) and orientation*/
       
   111         alListenerf (AL_GAIN,        1.0f       );
       
   112         alListenerfv(AL_POSITION,    ListenerPos);
       
   113         alListenerfv(AL_VELOCITY,    ListenerVel);
       
   114         alListenerfv(AL_ORIENTATION, ListenerOri);
       
   115         
       
   116         if (AlGetError("ERROR %d: Setting Listener properties\n") != AL_TRUE)
       
   117             return AL_FALSE;
       
   118         
       
   119         openalReady = AL_TRUE;
       
   120         
       
   121         alGetError();  /* clear any AL errors beforehand */
       
   122         return AL_TRUE;
       
   123     }
       
   124     
       
   125     
       
   126     ALboolean helper_realloc (void) {
       
   127         /*expands allocated memory when loading more sound files than expected*/
       
   128         int oldsize = globalsize;
       
   129         globalsize += increment;
       
   130 
       
   131 #ifdef DEBUG
       
   132         fprintf(stderr, "OpenAL: Realloc in process from %d to %d\n", oldsize, globalsize);
       
   133 #endif
       
   134         
       
   135         Buffers = (ALuint*) Realloc(Buffers, sizeof(ALuint)*globalsize);
       
   136         Sources = (ALuint*) Realloc(Sources, sizeof(ALuint)*globalsize);
       
   137         
       
   138         return AL_TRUE;
       
   139     }
       
   140     
       
   141     
       
   142     ALint openal_loadfile (const char *filename){
       
   143         /*Open a file, load into memory and allocate the Source buffer for playing*/
       
   144         ALfloat SourcePos[] = { 0.0, 0.0, 0.0 }; /*Position of the source sound*/
       
   145         ALfloat SourceVel[] = { 0.0, 0.0, 0.0 }; /*Velocity of the source sound*/
       
   146         ALenum format;
       
   147         ALsizei bitsize, freq;
       
   148         char *data;
       
   149         uint32_t fileformat;
       
   150         ALenum error;
       
   151         FILE *fp;
       
   152         
       
   153         if(openalReady == AL_FALSE) {
       
   154             fprintf(stderr, "ERROR: OpenAL not initialized\n");
       
   155             return AL_FALSE;
       
   156         }
       
   157         
       
   158         /*when the buffers are all used, we can expand memory to accept new files*/
       
   159         if (globalindex == globalsize)
       
   160             helper_realloc();
       
   161         
       
   162         /*detect the file format, as written in the first 4 bytes of the header*/
       
   163         fp = Fopen (filename, "rb");
       
   164         if (fp == NULL)
       
   165             return -1;
       
   166         error = fread (&fileformat, sizeof(uint32_t), 1, fp);
       
   167         fclose (fp);
       
   168         
       
   169         if (error < 0) {
       
   170             fprintf(stderr, "ERROR: file %s is too short \n", filename);
       
   171             return -2;
       
   172         }
       
   173         
       
   174         /*prepare the buffer to receive data*/
       
   175         alGenBuffers(1, &Buffers[globalindex]);
       
   176         
       
   177         if (AlGetError("ERROR %d: Allocating memory for buffers\n") != AL_TRUE)
       
   178             return -3;
       
   179         
       
   180         /*prepare the source to emit sound*/
       
   181         alGenSources(1, &Sources[globalindex]);
       
   182         
       
   183         if (AlGetError("ERROR %d: Allocating memory for sources\n") != AL_TRUE)
       
   184             return -4;
       
   185         
       
   186         
       
   187         if (fileformat == 0x5367674F) /*check if ogg*/
       
   188             error = load_oggvorbis (filename, &format, &data, &bitsize, &freq);
       
   189         else {
       
   190             if (fileformat == 0x46464952) /*check if wav*/
       
   191                 error = load_wavpcm (filename, &format, &data, &bitsize, &freq);
       
   192             else {
       
   193                 fprintf(stderr, "ERROR: File format (%08X) not supported!\n", invert_endianness(fileformat));
       
   194                 return -5;
       
   195             }
       
   196         }
       
   197         
       
   198         /*copy pcm data in one buffer*/
       
   199         alBufferData(Buffers[globalindex], format, data, bitsize, freq);
       
   200         free(data);		/*deallocate data to save memory*/
       
   201         
       
   202         if (AlGetError("ERROR %d: Writing data to buffer\n") != AL_TRUE)
       
   203             return -6;
       
   204         
       
   205         /*set source properties that it will use when it's in playback*/
       
   206         alSourcei (Sources[globalindex], AL_BUFFER,   Buffers[globalindex]  );
       
   207         alSourcef (Sources[globalindex], AL_PITCH,    1.0f                  );
       
   208         alSourcef (Sources[globalindex], AL_GAIN,     1.0f                  );
       
   209         alSourcefv(Sources[globalindex], AL_POSITION, SourcePos             );
       
   210         alSourcefv(Sources[globalindex], AL_VELOCITY, SourceVel             );
       
   211         alSourcei (Sources[globalindex], AL_LOOPING,  0                     );
       
   212         
       
   213         if (AlGetError("ERROR %d: Setting source properties\n") != AL_TRUE)
       
   214             return -7;
       
   215         
       
   216         alGetError();  /* clear any AL errors beforehand */
       
   217         
       
   218         /*returns the index of the source you just loaded, increments it and exits*/
       
   219         return globalindex++;
       
   220     }
       
   221     
       
   222     
       
   223     ALboolean openal_toggleloop (uint32_t index){
       
   224         /*Set or unset looping mode*/
       
   225         ALint loop;
       
   226         
       
   227         if(openalReady == AL_FALSE) {
       
   228             fprintf(stderr, "ERROR: OpenAL not initialized\n");
       
   229             return AL_FALSE;
       
   230         }
       
   231         
       
   232         if (index >= globalsize) {
       
   233             fprintf(stderr, "ERROR: index out of bounds (got %d, max %d)\n", index, globalindex);
       
   234             return AL_FALSE;
       
   235         }
       
   236         
       
   237         alGetSourcei (Sources[index], AL_LOOPING, &loop);
       
   238         alSourcei (Sources[index], AL_LOOPING, !((uint8_t) loop) & 0x00000001);
       
   239         if (AlGetError("ERROR %d: Getting or setting loop property\n") != AL_TRUE)
       
   240             return AL_FALSE;
       
   241         
       
   242         alGetError();  /* clear any AL errors beforehand */
       
   243         
       
   244         return AL_TRUE;
       
   245     }
       
   246     
       
   247     
       
   248     ALboolean openal_setvolume (uint32_t index, uint8_t percentage) {
       
   249         if(openalReady == AL_FALSE) {
       
   250             fprintf(stderr, "ERROR: OpenAL not initialized\n");
       
   251             return AL_FALSE;
       
   252         }
       
   253         
       
   254         /*Set volume for sound number index*/
       
   255         if (index >= globalindex) {
       
   256             fprintf(stderr, "ERROR: index out of bounds (got %d, max %d)\n", index, globalindex);
       
   257             return AL_FALSE;
       
   258         }
       
   259         
       
   260         if (percentage > 100)
       
   261             percentage = 100;
       
   262         alSourcef (Sources[index], AL_GAIN, (float) percentage/100.0f);
       
   263         if (AlGetError2("ERROR %d: setting volume for sound %d\n", index) != AL_TRUE)
       
   264             return AL_FALSE;
       
   265         
       
   266         alGetError();  /* clear any AL errors beforehand */
       
   267         
       
   268         return AL_TRUE;
       
   269     }
       
   270     
       
   271     
       
   272     ALboolean openal_setglobalvolume (uint8_t percentage) {
       
   273         if(openalReady == AL_FALSE) {
       
   274             fprintf(stderr, "ERROR: OpenAL not initialized\n");
       
   275             return AL_FALSE;
       
   276         }
       
   277         
       
   278         /*Set volume for all sounds*/		
       
   279         if (percentage > 100)
       
   280             percentage = 100;
       
   281         alListenerf (AL_GAIN, (float) percentage/100.0f);
       
   282         if (AlGetError("ERROR %d: Setting global volume\n") != AL_TRUE)
       
   283             return AL_FALSE;
       
   284         
       
   285         alGetError();  /* clear any AL errors beforehand */
       
   286         
       
   287         return AL_TRUE;
       
   288     }
       
   289     
       
   290     
       
   291     ALboolean openal_togglemute () {
       
   292         /*Mute or unmute sound*/
       
   293         ALfloat mute;
       
   294         
       
   295         if(openalReady == AL_FALSE) {
       
   296             fprintf(stderr, "ERROR: OpenAL not initialized\n");
       
   297             return AL_FALSE;
       
   298         }
       
   299         
       
   300         alGetListenerf (AL_GAIN, &mute);
       
   301         if (mute > 0) 
       
   302             mute = 0;
       
   303         else
       
   304             mute = 1.0;
       
   305         alListenerf (AL_GAIN, mute);
       
   306         if (AlGetError("ERROR %d: Setting mute property\n") != AL_TRUE)
       
   307             return AL_FALSE;
       
   308         
       
   309         alGetError();  /* clear any AL errors beforehand */
       
   310         
       
   311         return AL_TRUE;
       
   312     }
       
   313     
       
   314     
       
   315     ALboolean openal_fade (uint32_t index, uint16_t quantity, ALboolean direction) {
       
   316         /*Fade in or out by calling a helper thread*/
       
   317 #ifndef _WIN32
       
   318         pthread_t thread;
       
   319 #else
       
   320         HANDLE Thread;
       
   321         DWORD threadID;
       
   322 #endif
       
   323         fade_t *fade;
       
   324         
       
   325         if(openalReady == AL_FALSE) {
       
   326             fprintf(stderr, "ERROR: OpenAL not initialized\n");
       
   327             return AL_FALSE;
       
   328         }
       
   329         
       
   330         fade = (fade_t*) Malloc(sizeof(fade_t));
       
   331         fade->index = index;
       
   332         fade->quantity = quantity;
       
   333         
       
   334         if (index >= globalindex) {
       
   335             fprintf(stderr, "ERROR: index out of bounds (got %d, max %d)\n", index, globalindex);
       
   336             return AL_FALSE;
       
   337         }
       
   338         
       
   339         if (direction == FADE_IN)
       
   340 #ifndef _WIN32
       
   341             pthread_create(&thread, NULL, helper_fadein, (void*) fade);
       
   342 #else
       
   343         Thread = _beginthread(&helper_fadein, 0, (void*) fade);
       
   344 #endif
       
   345         else {
       
   346             if (direction == FADE_OUT)
       
   347 #ifndef _WIN32
       
   348                 pthread_create(&thread, NULL, helper_fadeout, (void*) fade);
       
   349 #else
       
   350             Thread = _beginthread(&helper_fadeout, 0, (void*) fade);
       
   351 #endif	
       
   352             else {
       
   353                 fprintf(stderr, "ERROR: unknown direction for fade (%d)\n", direction);
       
   354                 free(fade);
       
   355                 return AL_FALSE;
       
   356             }
       
   357         }
       
   358         
       
   359 #ifndef _WIN32
       
   360         pthread_detach(thread);
       
   361 #endif
       
   362         
       
   363         alGetError();  /* clear any AL errors beforehand */
       
   364         
       
   365         return AL_TRUE;
       
   366     }
       
   367     
       
   368     
       
   369     ALboolean openal_fadeout (uint32_t index, uint16_t quantity) {
       
   370         /*wrapper for fadeout*/
       
   371         return openal_fade(index, quantity, FADE_OUT);
       
   372     }
       
   373     
       
   374     
       
   375     ALboolean openal_fadein (uint32_t index, uint16_t quantity) {
       
   376         /*wrapper for fadein*/
       
   377         return openal_fade(index, quantity, FADE_IN);
       
   378     }
       
   379     
       
   380     
       
   381     ALboolean openal_setposition (uint32_t index, float x, float y, float z) {
       
   382         if(openalReady == AL_FALSE) {
       
   383             fprintf(stderr, "ERROR: OpenAL not initialized\n");
       
   384             return AL_FALSE;
       
   385         }
       
   386         if (index >= globalindex) {
       
   387             fprintf(stderr, "ERROR: index out of bounds (got %d, max %d)\n", index, globalindex);
       
   388             return AL_FALSE;
       
   389         }
       
   390         
       
   391         alSource3f(Sources[index], AL_POSITION, x, y, z);
       
   392         if (AlGetError2("ERROR %d: setting position for sound %d\n", index) != AL_TRUE)
       
   393             return AL_FALSE;
       
   394         
       
   395         return AL_TRUE;
       
   396     }
       
   397     
       
   398     
       
   399     ALboolean openal_playsound (uint32_t index){
       
   400         if(openalReady == AL_FALSE) {
       
   401             fprintf(stderr, "ERROR: OpenAL not initialized\n");
       
   402             return AL_FALSE;
       
   403         }
       
   404         
       
   405         /*Play sound number index*/
       
   406         if (index >= globalindex) {
       
   407             fprintf(stderr, "ERROR: index out of bounds (got %d, max %d)\n", index, globalindex);
       
   408             return AL_FALSE;
       
   409         }
       
   410         alSourcePlay(Sources[index]);
       
   411         if (AlGetError2("ERROR %d: Playing sound %d\n", index) != AL_TRUE)
       
   412             return AL_FALSE;
       
   413         
       
   414         alGetError();  /* clear any AL errors beforehand */
       
   415         
       
   416         return AL_TRUE;
       
   417     }
       
   418     
       
   419     
       
   420     ALboolean openal_pausesound(uint32_t index){
       
   421         if(openalReady == AL_FALSE) {
       
   422             fprintf(stderr, "ERROR: OpenAL not initialized\n");
       
   423             return AL_FALSE;
       
   424         }
       
   425         
       
   426         /*Pause sound number index*/
       
   427         if (index >= globalindex) {
       
   428             fprintf(stderr, "ERROR: index out of bounds (got %d, max %d)\n", index, globalindex);
       
   429             return AL_FALSE;
       
   430         }
       
   431         alSourcePause(Sources[index]);
       
   432         if (AlGetError2("ERROR %d: Pausing sound %d\n", index) != AL_TRUE)
       
   433             return AL_FALSE;
       
   434         
       
   435         return AL_TRUE;
       
   436     }
       
   437     
       
   438     
       
   439     ALboolean openal_stopsound(uint32_t index){
       
   440         if(openalReady == AL_FALSE) {
       
   441             fprintf(stderr, "ERROR: OpenAL not initialized\n");
       
   442             return AL_FALSE;
       
   443         }
       
   444         
       
   445         /*Stop sound number index*/
       
   446         if (index >= globalindex) {
       
   447             fprintf(stderr, "ERROR: index out of bounds (got %d, max %d)\n", index, globalindex);
       
   448             return AL_FALSE;
       
   449         }
       
   450         alSourceStop(Sources[index]);
       
   451         if (AlGetError2("ERROR %d: Stopping sound %d\n", index) != AL_TRUE)
       
   452             return AL_FALSE;
       
   453         
       
   454         alGetError();  /* clear any AL errors beforehand */
       
   455         
       
   456         return AL_TRUE;
       
   457     }
       
   458     
       
   459 #ifdef __CPLUSPLUS
       
   460 }
       
   461 #endif