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