openalbridge/openalbridge.c
changeset 3353 a767dd3786b5
parent 3352 ac5d14a35482
child 3354 cb5d13ff4aae
equal deleted inserted replaced
3352:ac5d14a35482 3353:a767dd3786b5
     1 /*
       
     2  * OpenAL Bridge - a simple portable library for OpenAL interface
       
     3  * Copyright (c) 2009 Vittorio Giovara <vittorio.giovara@gmail.com>
       
     4  *
       
     5  * This program is free software; you can redistribute it and/or modify
       
     6  * it under the terms of the GNU Lesser General Public License as published by
       
     7  * the Free Software Foundation; version 2 of the License
       
     8  *
       
     9  * This program is distributed in the hope that it will be useful,
       
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    12  * GNU Lesser General Public License for more details.
       
    13  *
       
    14  * You should have received a copy of the GNU Lesser General Public License
       
    15  * along with this program; if not, write to the Free Software
       
    16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
       
    17  */
       
    18 
       
    19 #include "openalbridge.h"
       
    20 
       
    21 
       
    22 #ifdef __CPLUSPLUS
       
    23 extern "C" {
       
    24 #endif 
       
    25         
       
    26         /*Sources are points emitting sound*/
       
    27         ALuint *Sources;
       
    28         /*Buffers hold sound data*/
       
    29         ALuint *Buffers;
       
    30         /*index for Sources and Buffers*/
       
    31         ALuint globalindex, globalsize, increment;
       
    32         
       
    33         ALboolean openalReady = AL_FALSE;
       
    34         
       
    35         ALboolean openal_close (void) {
       
    36                 /*Stop all sounds, deallocate all memory and close OpenAL */
       
    37                 ALCcontext *context;
       
    38                 ALCdevice  *device;
       
    39                 
       
    40                 if (openalReady == AL_FALSE) {
       
    41                         errno = EPERM;
       
    42                         err_ret("(%s) WARN - OpenAL not initialized", prog);
       
    43                         return AL_FALSE;
       
    44                 }
       
    45                 
       
    46                 alSourceStopv	(globalsize, Sources);
       
    47                 alDeleteSources (globalsize, Sources);
       
    48                 alDeleteBuffers (globalsize, Buffers);
       
    49                 
       
    50                 free(Sources);
       
    51                 free(Buffers);
       
    52                 
       
    53                 context = alcGetCurrentContext();
       
    54                 device  = alcGetContextsDevice(context);
       
    55                 
       
    56                 alcMakeContextCurrent(NULL);
       
    57                 alcDestroyContext(context);
       
    58                 alcCloseDevice(device);
       
    59                 
       
    60                 openalReady = AL_FALSE;
       
    61                 
       
    62                 return AL_TRUE;
       
    63         }
       
    64         
       
    65         ALboolean openal_ready(void) {
       
    66                 return openalReady;
       
    67         }
       
    68         
       
    69         ALboolean openal_init(char* programname, ALboolean usehardware, uint32_t memorysize) {	
       
    70                 /*Initialize an OpenAL contex and allocate memory space for data and buffers*/
       
    71                 ALCcontext *context;
       
    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)
       
    91                         device = alcOpenDevice(NULL);
       
    92                 else
       
    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;
       
   342 #else
       
   343                 HANDLE Thread;
       
   344                 DWORD threadID;
       
   345 #endif
       
   346                 fade_t *fade;
       
   347                 
       
   348                 if (openalReady == AL_FALSE) {
       
   349                         errno = EPERM;                
       
   350                         err_ret("(%s) WARN - OpenAL not initialized", prog);
       
   351                         return AL_FALSE;
       
   352                 }
       
   353                 
       
   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
       
   371                                 break;
       
   372                         case FADE_OUT:
       
   373 #ifndef _WIN32
       
   374                                 pthread_create(&thread, NULL, helper_fadeout, (void*) fade);
       
   375 #else
       
   376                                 Thread = _beginthread(&helper_fadeout, 0, (void*) fade);
       
   377 #endif	
       
   378                                 break;
       
   379                         default:
       
   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
       
   497 }
       
   498 #endif