misc/openalbridge/openalbridge.c
changeset 3353 a767dd3786b5
child 3356 3ae3fccb439e
equal deleted inserted replaced
3352:ac5d14a35482 3353:a767dd3786b5
       
     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 "globals.h"
       
    21 #include "wrappers.h"
       
    22 #include "alc.h"
       
    23 #include "loaders.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             errno = EPERM;
       
    45             err_ret("(%s) WARN - OpenAL not initialized", prog);
       
    46             return AL_FALSE;
       
    47         }
       
    48         
       
    49         alSourceStopv	(globalsize, Sources);
       
    50         alDeleteSources (globalsize, Sources);
       
    51         alDeleteBuffers (globalsize, Buffers);
       
    52         
       
    53         free(Sources);
       
    54         free(Buffers);
       
    55         
       
    56         context = alcGetCurrentContext();
       
    57         device  = alcGetContextsDevice(context);
       
    58         
       
    59         alcMakeContextCurrent(NULL);
       
    60         alcDestroyContext(context);
       
    61         alcCloseDevice(device);
       
    62         
       
    63         openalReady = AL_FALSE;
       
    64         
       
    65         err_msg("(%s) INFO - OpenAL closed", prog);
       
    66         
       
    67         return AL_TRUE;
       
    68     }
       
    69     
       
    70     ALboolean openal_ready(void) {
       
    71         return openalReady;
       
    72     }
       
    73     
       
    74     ALboolean openal_init(char* programname, ALboolean usehardware, uint32_t memorysize) {	
       
    75         /*Initialize an OpenAL contex and allocate memory space for data and buffers*/
       
    76         ALCcontext *context;
       
    77         ALCdevice *device;
       
    78         const ALCchar *default_device;
       
    79         
       
    80         prog = programname;
       
    81         
       
    82         /*Position of the listener*/
       
    83         ALfloat ListenerPos[] = { 0.0, 0.0, 0.0 };
       
    84         /*Velocity of the listener*/
       
    85         ALfloat ListenerVel[] = { 0.0, 0.0, 0.0 };
       
    86         /*Orientation of the listener. (first 3 elements are "at", second 3 are "up")*/
       
    87         ALfloat ListenerOri[] = { 0.0, 0.0, -1.0,  0.0, 1.0, 0.0 };
       
    88         
       
    89         if (openalReady == AL_TRUE) {
       
    90             errno = EPERM;                
       
    91             err_ret("(%s) WARN - OpenAL already initialized", prog);
       
    92             return AL_FALSE;
       
    93         }
       
    94         
       
    95         if (usehardware == AL_TRUE) {
       
    96              default_device = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
       
    97             device = alcOpenDevice(default_device);
       
    98         } else
       
    99             device = alcOpenDevice("Generic Software");
       
   100         
       
   101         if (device == NULL) {
       
   102             errno = ENODEV;                
       
   103             err_ret("(%s) WARN - Failed to open sound device", prog);
       
   104             return AL_FALSE;
       
   105         }
       
   106         err_msg("(%s) INFO - Output device: %s", prog, alcGetString(device, ALC_DEVICE_SPECIFIER));
       
   107         
       
   108         context = alcCreateContext(device, NULL);
       
   109         alcMakeContextCurrent(context);
       
   110         alcProcessContext(context);
       
   111         
       
   112         if (AlGetError("(%s) WARN - Failed to create a new contex") != AL_TRUE)
       
   113             return AL_FALSE;
       
   114         
       
   115         /*allocate memory space for buffers and sources*/
       
   116         if (memorysize == 0)
       
   117             globalsize = 50;
       
   118         else
       
   119             globalsize = memorysize;
       
   120         increment  = globalsize;
       
   121         
       
   122         Buffers = (ALuint*) Malloc(sizeof(ALuint)*globalsize);
       
   123         Sources = (ALuint*) Malloc(sizeof(ALuint)*globalsize);
       
   124         
       
   125         /*set the listener gain, position (on xyz axes), velocity (one value for each axe) and orientation*/
       
   126         alListenerf (AL_GAIN,        1.0f       );
       
   127         alListenerfv(AL_POSITION,    ListenerPos);
       
   128         alListenerfv(AL_VELOCITY,    ListenerVel);
       
   129         alListenerfv(AL_ORIENTATION, ListenerOri);
       
   130         
       
   131         if (AlGetError("(%s) WARN - Failed to set Listener properties") != AL_TRUE)
       
   132             return AL_FALSE;
       
   133         
       
   134         openalReady = AL_TRUE;
       
   135         
       
   136         alGetError();  /* clear any AL errors beforehand */
       
   137         return AL_TRUE;
       
   138     }
       
   139     
       
   140     
       
   141     ALboolean helper_realloc (void) {
       
   142         /*expands allocated memory when loading more sound files than expected*/
       
   143         int oldsize = globalsize;
       
   144         globalsize += increment;
       
   145         
       
   146         err_msg("(%s) INFO - Realloc in process from %d to %d\n", prog, oldsize, globalsize);
       
   147         
       
   148         Buffers = (ALuint*) Realloc(Buffers, sizeof(ALuint)*globalsize);
       
   149         Sources = (ALuint*) Realloc(Sources, sizeof(ALuint)*globalsize);
       
   150         
       
   151         return AL_TRUE;
       
   152     }
       
   153     
       
   154     
       
   155     ALint openal_loadfile (const char *filename){
       
   156         /*Open a file, load into memory and allocate the Source buffer for playing*/
       
   157         ALfloat SourcePos[] = { 0.0, 0.0, 0.0 }; /*Position of the source sound*/
       
   158         ALfloat SourceVel[] = { 0.0, 0.0, 0.0 }; /*Velocity of the source sound*/
       
   159         ALenum format;
       
   160         ALsizei bitsize, freq;
       
   161         char *data;
       
   162         uint32_t fileformat;
       
   163         ALenum error;
       
   164         FILE *fp;
       
   165         
       
   166         if (openalReady == AL_FALSE) {
       
   167             errno = EPERM;                
       
   168             err_ret("(%s) WARN - OpenAL not initialized", prog);
       
   169             return AL_FALSE;
       
   170         }
       
   171         
       
   172         /*when the buffers are all used, we can expand memory to accept new files*/
       
   173         if (globalindex == globalsize)
       
   174             helper_realloc();
       
   175         
       
   176         /*detect the file format, as written in the first 4 bytes of the header*/
       
   177         fp = Fopen (filename, "rb");
       
   178         
       
   179         if (fp == NULL)
       
   180             return -1;
       
   181         
       
   182         error = fread (&fileformat, sizeof(uint32_t), 1, fp);
       
   183         fclose (fp);
       
   184         
       
   185         if (error < 0) {
       
   186             errno = EIO;
       
   187             err_ret("(%s) ERROR - File %s is too short", prog, filename);
       
   188             return -2;
       
   189         }
       
   190         
       
   191         /*prepare the buffer to receive data*/
       
   192         alGenBuffers(1, &Buffers[globalindex]);
       
   193         
       
   194         if (AlGetError("(%s) ERROR - Failed to allocate memory for buffers") != AL_TRUE)
       
   195             return -3;
       
   196         
       
   197         /*prepare the source to emit sound*/
       
   198         alGenSources(1, &Sources[globalindex]);
       
   199         
       
   200         if (AlGetError("(%s) ERROR - Failed to allocate memory for sources") != AL_TRUE)
       
   201             return -4;
       
   202         
       
   203         
       
   204         switch (ENDIAN_BIG_32(fileformat)) {
       
   205             case OGG_FILE_FORMAT:
       
   206                 error = load_oggvorbis (filename, &format, &data, &bitsize, &freq);
       
   207                 break;
       
   208             case WAV_FILE_FORMAT:
       
   209                 error = load_wavpcm (filename, &format, &data, &bitsize, &freq);
       
   210                 break;
       
   211             default:
       
   212                 errno = EINVAL;
       
   213                 err_ret ("(%s) ERROR - File format (%08X) not supported", prog, ENDIAN_BIG_32(fileformat));
       
   214                 return -5;
       
   215                 break;
       
   216         }
       
   217         
       
   218         
       
   219         /*copy pcm data in one buffer*/
       
   220         alBufferData(Buffers[globalindex], format, data, bitsize, freq);
       
   221         free(data);		/*deallocate data to save memory*/
       
   222         
       
   223         if (AlGetError("(%s) ERROR - Failed to write data to buffers") != AL_TRUE)
       
   224             return -6;
       
   225         
       
   226         /*set source properties that it will use when it's in playback*/
       
   227         alSourcei (Sources[globalindex], AL_BUFFER,   Buffers[globalindex]  );
       
   228         alSourcef (Sources[globalindex], AL_PITCH,    1.0f                  );
       
   229         alSourcef (Sources[globalindex], AL_GAIN,     1.0f                  );
       
   230         alSourcefv(Sources[globalindex], AL_POSITION, SourcePos             );
       
   231         alSourcefv(Sources[globalindex], AL_VELOCITY, SourceVel             );
       
   232         alSourcei (Sources[globalindex], AL_LOOPING,  0                     );
       
   233         
       
   234         if (AlGetError("(%s) ERROR - Failed to set Source properties") != AL_TRUE)
       
   235             return -7;
       
   236         
       
   237         alGetError();  /* clear any AL errors beforehand */
       
   238         
       
   239         /*returns the index of the source you just loaded, increments it and exits*/
       
   240         return globalindex++;
       
   241     }
       
   242     
       
   243     
       
   244     ALboolean openal_toggleloop (uint32_t index){
       
   245         /*Set or unset looping mode*/
       
   246         ALint loop;
       
   247         
       
   248         if (openalReady == AL_FALSE) {
       
   249             errno = EPERM;                
       
   250             err_ret("(%s) WARN - OpenAL not initialized", prog);
       
   251             return AL_FALSE;
       
   252         }
       
   253         
       
   254         if (index >= globalsize) {
       
   255             errno = EINVAL;
       
   256             err_ret("(%s) ERROR - Index out of bounds (got %d, max %d)", prog, index, globalindex);
       
   257             return AL_FALSE;
       
   258         }
       
   259         
       
   260         alGetSourcei (Sources[index], AL_LOOPING, &loop);
       
   261         alSourcei (Sources[index], AL_LOOPING, !((uint8_t) loop) & 0x00000001);
       
   262         if (AlGetError("(%s) ERROR - Failed to get or set loop property") != AL_TRUE)
       
   263             return AL_FALSE;
       
   264         
       
   265         alGetError();  /* clear any AL errors beforehand */
       
   266         
       
   267         return AL_TRUE;
       
   268     }
       
   269     
       
   270     
       
   271     ALboolean openal_setvolume (uint32_t index, uint8_t percentage) {
       
   272         if (openalReady == AL_FALSE) {
       
   273             errno = EPERM;                
       
   274             err_ret("(%s) WARN - OpenAL not initialized", prog);
       
   275             return AL_FALSE;
       
   276         }
       
   277         
       
   278         /*Set volume for sound number index*/
       
   279         if (index >= globalsize) {
       
   280             errno = EINVAL;
       
   281             err_ret("(%s) ERROR - Index out of bounds (got %d, max %d)", prog, index, globalindex);
       
   282             return AL_FALSE;
       
   283         }
       
   284         
       
   285         if (percentage > 100)
       
   286             percentage = 100;
       
   287         alSourcef (Sources[index], AL_GAIN, (float) percentage/100.0f);
       
   288         if (AlGetError2("(%s) ERROR -  Failed to set volume for sound %d\n", index) != AL_TRUE)
       
   289             return AL_FALSE;
       
   290         
       
   291         alGetError();  /* clear any AL errors beforehand */
       
   292         
       
   293         return AL_TRUE;
       
   294     }
       
   295     
       
   296     
       
   297     ALboolean openal_setglobalvolume (uint8_t percentage) {
       
   298         if (openalReady == AL_FALSE) {
       
   299             errno = EPERM;                
       
   300             err_ret("(%s) WARN - OpenAL not initialized", prog);
       
   301             return AL_FALSE;
       
   302         }
       
   303         
       
   304         /*Set volume for all sounds*/		
       
   305         if (percentage > 100)
       
   306             percentage = 100;
       
   307         alListenerf (AL_GAIN, (float) percentage/100.0f);
       
   308         if (AlGetError("(%s) ERROR -  Failed to set global volume") != AL_TRUE)
       
   309             return AL_FALSE;
       
   310         
       
   311         alGetError();  /* clear any AL errors beforehand */
       
   312         
       
   313         return AL_TRUE;
       
   314     }
       
   315     
       
   316     
       
   317     ALboolean openal_togglemute () {
       
   318         /*Mute or unmute sound*/
       
   319         ALfloat mute;
       
   320         
       
   321         if (openalReady == AL_FALSE) {
       
   322             errno = EPERM;                
       
   323             err_ret("(%s) WARN - OpenAL not initialized", prog);
       
   324             return AL_FALSE;
       
   325         }
       
   326         
       
   327         alGetListenerf (AL_GAIN, &mute);
       
   328         if (mute > 0) 
       
   329             mute = 0;
       
   330         else
       
   331             mute = 1.0;
       
   332         alListenerf (AL_GAIN, mute);
       
   333         if (AlGetError("(%s) ERROR -  Failed to set mute property") != AL_TRUE)
       
   334             return AL_FALSE;
       
   335         
       
   336         alGetError();  /* clear any AL errors beforehand */
       
   337         
       
   338         return AL_TRUE;
       
   339     }
       
   340     
       
   341     
       
   342     ALboolean openal_fade (uint32_t index, uint16_t quantity, ALboolean direction) {
       
   343         /*Fade in or out by calling a helper thread*/
       
   344 #ifndef _WIN32
       
   345         pthread_t thread;
       
   346 #else
       
   347         HANDLE Thread;
       
   348         DWORD threadID;
       
   349 #endif
       
   350         fade_t *fade;
       
   351         
       
   352         if (openalReady == AL_FALSE) {
       
   353             errno = EPERM;                
       
   354             err_ret("(%s) WARN - OpenAL not initialized", prog);
       
   355             return AL_FALSE;
       
   356         }
       
   357         
       
   358         fade = (fade_t*) Malloc(sizeof(fade_t));
       
   359         fade->index = index;
       
   360         fade->quantity = quantity;
       
   361         
       
   362         if (index >= globalsize) {
       
   363             errno = EINVAL;
       
   364             err_ret("(%s) ERROR - Index out of bounds (got %d, max %d)", prog, index, globalindex);
       
   365             return AL_FALSE;
       
   366         }
       
   367         
       
   368         switch (direction) {
       
   369             case FADE_IN:
       
   370 #ifndef _WIN32
       
   371                 pthread_create(&thread, NULL, helper_fadein, (void*) fade);
       
   372 #else
       
   373                 Thread = _beginthread(&helper_fadein, 0, (void*) fade);
       
   374 #endif
       
   375                 break;
       
   376             case FADE_OUT:
       
   377 #ifndef _WIN32
       
   378                 pthread_create(&thread, NULL, helper_fadeout, (void*) fade);
       
   379 #else
       
   380                 Thread = _beginthread(&helper_fadeout, 0, (void*) fade);
       
   381 #endif	
       
   382                 break;
       
   383             default:
       
   384                 errno = EINVAL;
       
   385                 err_ret("(%s) ERROR - Unknown direction for fading", prog, index, globalindex);
       
   386                 free(fade);
       
   387                 return AL_FALSE;
       
   388                 break;
       
   389         }
       
   390         
       
   391 #ifndef _WIN32
       
   392         pthread_detach(thread);
       
   393 #endif
       
   394         
       
   395         alGetError();  /* clear any AL errors beforehand */
       
   396         
       
   397         return AL_TRUE;
       
   398     }
       
   399     
       
   400     
       
   401     ALboolean openal_fadeout (uint32_t index, uint16_t quantity) {
       
   402         /*wrapper for fadeout*/
       
   403         return openal_fade(index, quantity, FADE_OUT);
       
   404     }
       
   405     
       
   406     
       
   407     ALboolean openal_fadein (uint32_t index, uint16_t quantity) {
       
   408         /*wrapper for fadein*/
       
   409         return openal_fade(index, quantity, FADE_IN);
       
   410     }
       
   411     
       
   412     
       
   413     ALboolean openal_setposition (uint32_t index, float x, float y, float z) {
       
   414         if (openalReady == AL_FALSE) {
       
   415             errno = EPERM;                
       
   416             err_ret("(%s) WARN - OpenAL not initialized", prog);
       
   417             return AL_FALSE;
       
   418         }
       
   419         
       
   420         if (index >= globalsize) {
       
   421             errno = EINVAL;
       
   422             err_ret("(%s) ERROR - Index out of bounds (got %d, max %d)", prog, index, globalindex);
       
   423             return AL_FALSE;
       
   424         }
       
   425         
       
   426         alSource3f(Sources[index], AL_POSITION, x, y, z);
       
   427         if (AlGetError2("(%s) ERROR - Failed to set position for sound %d)", index) != AL_TRUE)
       
   428             return AL_FALSE;
       
   429         
       
   430         return AL_TRUE;
       
   431     }
       
   432     
       
   433     
       
   434     ALboolean openal_playsound (uint32_t index){
       
   435         if (openalReady == AL_FALSE) {
       
   436             errno = EPERM;                
       
   437             err_ret("(%s) WARN - OpenAL not initialized", prog);
       
   438             return AL_FALSE;
       
   439         }
       
   440         
       
   441         /*Play sound number index*/
       
   442         if (index >= globalsize) {
       
   443             errno = EINVAL;
       
   444             err_ret("(%s) ERROR - Index out of bounds (got %d, max %d)", prog, index, globalindex);
       
   445             return AL_FALSE;
       
   446         }
       
   447         alSourcePlay(Sources[index]);
       
   448         if (AlGetError2("(%s) ERROR - Failed to play sound %d)", index) != AL_TRUE)
       
   449             return AL_FALSE;
       
   450         
       
   451         alGetError();  /* clear any AL errors beforehand */
       
   452         
       
   453         return AL_TRUE;
       
   454     }
       
   455     
       
   456     
       
   457     ALboolean openal_pausesound(uint32_t index){
       
   458         if (openalReady == AL_FALSE) {
       
   459             errno = EPERM;                
       
   460             err_ret("(%s) WARN - OpenAL not initialized", prog);
       
   461             return AL_FALSE;
       
   462         }
       
   463         
       
   464         /*Pause sound number index*/
       
   465         if (index >= globalsize) {
       
   466             errno = EINVAL;
       
   467             err_ret("(%s) ERROR - Index out of bounds (got %d, max %d)", prog, index, globalindex);
       
   468             return AL_FALSE;
       
   469         }
       
   470         alSourcePause(Sources[index]);
       
   471         if (AlGetError2("(%s) ERROR - Failed to pause sound %d)", index) != AL_TRUE)
       
   472             return AL_FALSE;
       
   473         
       
   474         return AL_TRUE;
       
   475     }
       
   476     
       
   477     
       
   478     ALboolean openal_stopsound(uint32_t index){
       
   479         if (openalReady == AL_FALSE) {
       
   480             errno = EPERM;                
       
   481             err_ret("(%s) WARN - OpenAL not initialized", prog);
       
   482             return AL_FALSE;
       
   483         }
       
   484         
       
   485         /*Stop sound number index*/
       
   486         if (index >= globalsize) {
       
   487             errno = EINVAL;
       
   488             err_ret("(%s) ERROR - Index out of bounds (got %d, max %d)", prog, index, globalindex);
       
   489             return AL_FALSE;
       
   490         }
       
   491         alSourceStop(Sources[index]);
       
   492         if (AlGetError2("(%s) ERROR - Failed to stop sound %d)", index) != AL_TRUE)
       
   493             return AL_FALSE;
       
   494         
       
   495         alGetError();  /* clear any AL errors beforehand */
       
   496         
       
   497         return AL_TRUE;
       
   498     }
       
   499     
       
   500     
       
   501     ALboolean openal_freesound(uint32_t index){
       
   502         if (openalReady == AL_FALSE) {
       
   503             errno = EPERM;                
       
   504             err_ret("(%s) WARN - OpenAL not initialized", prog);
       
   505             return AL_FALSE;
       
   506         }
       
   507         
       
   508         /*Stop sound number index*/
       
   509         if (index >= globalsize) {
       
   510             errno = EINVAL;
       
   511             err_ret("(%s) ERROR - Index out of bounds (got %d, max %d)", prog, index, globalindex);
       
   512             return AL_FALSE;
       
   513         }
       
   514         globalindex--;
       
   515         
       
   516         alGetError();  /* clear any AL errors beforehand */
       
   517         
       
   518         return AL_TRUE;
       
   519     }
       
   520     
       
   521 #ifdef __CPLUSPLUS
       
   522 }
       
   523 #endif