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