misc/libopenalbridge/openalbridge.c
changeset 3529 0e968ba12a84
parent 3514 59dbd31e9953
child 3697 d5b30d6373fc
equal deleted inserted replaced
3516:a8c673657b79 3529:0e968ba12a84
    32 al_sound_t *the_sounds;
    32 al_sound_t *the_sounds;
    33 ALint cache_pointer;
    33 ALint cache_pointer;
    34 
    34 
    35 // Initialize an OpenAL contex and allocate memory space for data and buffers
    35 // Initialize an OpenAL contex and allocate memory space for data and buffers
    36 // It can be called twice to increase the cache size
    36 // It can be called twice to increase the cache size
    37 int openal_init (int memorysize) {
    37 int openal_init (void) {
    38     ALCcontext *context;
    38     ALCcontext *context;
    39     ALCdevice *device;
    39     ALCdevice *device;
    40     int i;
    40     int i;
    41         
    41         
    42     // reuse old context and resize the existing 
    42     // reuse old context and resize the existing 
    43     if (openal_ready() == AL_TRUE) {
    43     if (openal_ready() == AL_TRUE) {
    44         cache_size += memorysize;
    44         fprintf(stderr,"(Bridge Info) - already initialized\n");
    45         fprintf(stderr,"(Bridge Info) - already initialized, resizing cache to %d\n", cache_size);
       
    46         the_sounds = (al_sound_t *)Realloc (the_sounds, sizeof(al_sound_t) * cache_size);
       
    47         for (i = cache_size - memorysize; i < cache_size; i++) {
       
    48             the_sounds[i].filename = NULL;
       
    49             the_sounds[i].buffer = -1;
       
    50             the_sounds[i].source_index = -1;
       
    51             the_sounds[i].stats = 0;
       
    52         }
       
    53         instances_number++;
    45         instances_number++;
    54         return AL_TRUE;
    46         return AL_TRUE;
    55     }
    47     }
    56     
    48     
    57     cache_pointer = 0;
    49     cache_pointer = 0;
    58     instances_number++;
    50     instances_number++;
    59     
    51     
    60     // set the memory dimentsion and the increment width when reallocating
    52     // initial memory size
    61     if (memorysize <= 0)
    53     cache_size = 50;
    62         cache_size = 50;
    54     
    63     else
       
    64         cache_size = memorysize;
       
    65 
       
    66     // open hardware device if present
    55     // open hardware device if present
    67     device = alcOpenDevice(NULL);
    56     device = alcOpenDevice(NULL);
    68     sources_number = 16;
    57     sources_number = 16;
    69     if (device == NULL) {
    58     if (device == NULL) {
    70         fprintf(stderr,"(Bridge Warning) - failed to open sound device, using software renderer\n");
    59         fprintf(stderr,"(Bridge Warning) - failed to open sound device, using software renderer\n");
   108         fprintf(stderr,"(Bridge ERROR) - Failed to set Listener properties\n");
    97         fprintf(stderr,"(Bridge ERROR) - Failed to set Listener properties\n");
   109         return -3;
    98         return -3;
   110     }
    99     }
   111 
   100 
   112     the_sounds = (al_sound_t *)Malloc (sizeof(al_sound_t) * cache_size);
   101     the_sounds = (al_sound_t *)Malloc (sizeof(al_sound_t) * cache_size);
   113     for (i = 0; i < cache_size; i++) {
   102     for (i = 0; i < cache_size; i++)
   114         the_sounds[i].filename = NULL;
   103         the_sounds[i] = new_sound_el();
   115         the_sounds[i].buffer = -1;
       
   116         the_sounds[i].source_index = -1;
       
   117         the_sounds[i].stats = 0;
       
   118     }
       
   119 
   104 
   120     alGetError();
   105     alGetError();
   121     return AL_TRUE;
   106     return AL_TRUE;
   122 }
   107 }
   123 
   108 
   133         return;
   118         return;
   134     }
   119     }
   135 
   120 
   136     instances_number--;
   121     instances_number--;
   137     if (instances_number > 0) {
   122     if (instances_number > 0) {
       
   123         // release memory only when last session ends
   138         return;
   124         return;
   139     }
   125     }
   140     
   126     
   141     //TODO: free other stuff also
   127     for (i = 0; i < cache_size; i++) {
   142     for (i = 0; i < cache_size; i++)
   128         openal_unloadfile(i);
   143         alDeleteBuffers (1, &the_sounds[i].buffer);
   129     }
   144     free(the_sounds);
   130     free(the_sounds);
   145 
   131 
   146     alSourceStopv	(sources_number, Sources);
   132     alSourceStopv (sources_number, Sources);
   147     alDeleteSources (sources_number, Sources);
   133     alDeleteSources (sources_number, Sources);
   148 
   134 
   149     free(Sources);
   135     free(Sources);
   150 
   136 
   151     context = alcGetCurrentContext();
   137     context = alcGetCurrentContext();
   172 // Open a file, load into memory and allocate the Source buffer for playing
   158 // Open a file, load into memory and allocate the Source buffer for playing
   173 int openal_loadfile (const char *filename){
   159 int openal_loadfile (const char *filename){
   174     ALenum format, error;
   160     ALenum format, error;
   175     ALsizei bitsize, freq;
   161     ALsizei bitsize, freq;
   176     uint32_t fileformat;
   162     uint32_t fileformat;
   177     al_sound_t soundData;
   163     al_sound_t sound_data;
   178     int len, i;
   164     int len, i, index = -1;
   179     char *data;
   165     char *data;
   180     FILE *fp;
   166     FILE *fp;
   181     
   167     
   182     if (openal_ready() == AL_FALSE) {
   168     if (openal_ready() == AL_FALSE) {
   183         fprintf(stderr,"(Bridge Warning) - not initialized\n");
   169         fprintf(stderr,"(Bridge Warning) - not initialized\n");
   191 #ifdef DEBUG
   177 #ifdef DEBUG
   192             fprintf(stderr,"(Bridge Debug) - sound %d is already loaded\n", i);
   178             fprintf(stderr,"(Bridge Debug) - sound %d is already loaded\n", i);
   193 #endif
   179 #endif
   194             return i;
   180             return i;
   195         }
   181         }
   196     }
   182         // if we don't have memory available search for a free element
   197 
   183         if (cache_pointer >= cache_size)
   198     if (cache_pointer >= cache_size) {
   184             if (the_sounds[i].is_used == AL_FALSE)
   199         fprintf(stderr,"(Bridge ERROR) - Cache size limit reached; consider allocating more space\n", filename);
   185                 index = i; 
   200         return -2;
   186     }
   201     }
   187 
       
   188     if (index == -1 && cache_pointer >= cache_size) {
       
   189         fprintf(stderr,"(Bridge Info) - No free spots found; doubling cache size\n", filename);
       
   190         cache_size *= 2;
       
   191         the_sounds = (al_sound_t *)Realloc (the_sounds, sizeof(al_sound_t) * cache_size);
       
   192         for (i = cache_size - 50; i < cache_size; i++) 
       
   193             the_sounds[i] = new_sound_el();
       
   194     } else 
       
   195         index = ++cache_pointer;
       
   196     
   202     
   197     
   203     // detect the file format, as written in the first 4 bytes of the header
   198     // detect the file format, as written in the first 4 bytes of the header
   204     fp = Fopen (filename, "rb");
   199     fp = Fopen (filename, "rb");
   205 
       
   206     if (fp == NULL) {
   200     if (fp == NULL) {
   207         fprintf(stderr,"(Bridge ERROR) - File %s not loaded\n", filename);
   201         fprintf(stderr,"(Bridge ERROR) - File %s not loaded\n", filename);
   208         return -3;
   202         return -3;
   209     }
   203     }
   210 
   204 
   211     error = fread (&fileformat, sizeof(uint32_t), 1, fp);
   205     error = fread (&fileformat, sizeof(uint32_t), 1, fp);
   212     fclose (fp);
   206     fclose (fp);
   213 
       
   214     if (error < 0) {
   207     if (error < 0) {
   215         fprintf(stderr,"(Bridge ERROR) - File %s is too short\n", filename);
   208         fprintf(stderr,"(Bridge ERROR) - File %s is too short\n", filename);
   216         return -4;
   209         return -4;
   217     }
   210     }
   218 
   211 
   229             break;
   222             break;
   230     }
   223     }
   231 
   224 
   232     if (error != 0) {
   225     if (error != 0) {
   233         fprintf(stderr,"(Bridge ERROR) - error loading file %s\n", filename);
   226         fprintf(stderr,"(Bridge ERROR) - error loading file %s\n", filename);
       
   227         if(data)
       
   228             free(data);
       
   229         return -6;
       
   230     }
       
   231 
       
   232     // alGenBuffers happens here
       
   233     sound_data = init_sound_el(filename);
       
   234     
       
   235     if (AL_NO_ERROR != alGetError()) {
       
   236         fprintf(stderr,"(Bridge ERROR) - Failed to allocate memory for buffer %d\n", index);
   234         free(data);
   237         free(data);
   235         return -6;
       
   236     }
       
   237 
       
   238     alGenBuffers(1, &soundData.buffer);
       
   239     soundData.filename = filename;
       
   240     soundData.source_index = -1;
       
   241     soundData.stats = 0;
       
   242     
       
   243     if (AL_NO_ERROR != alGetError()) {
       
   244         fprintf(stderr,"(Bridge ERROR) - Failed to allocate memory for buffers\n");
       
   245         return -5;
   238         return -5;
   246     }
   239     }
   247     
   240     
   248     // copy pcm data in one buffer and free it
   241     // copy pcm data in one buffer and free it
   249     alBufferData(soundData.buffer, format, data, bitsize, freq);
   242     alBufferData(sound_data.buffer, format, data, bitsize, freq);
   250     free(data);
   243     free(data);
   251 
   244 
   252     if (AL_NO_ERROR != alGetError()) {
   245     if (AL_NO_ERROR != alGetError()) {
   253         fprintf(stderr,"(Bridge ERROR) - Failed to write data to buffers\n");
   246         fprintf(stderr,"(Bridge ERROR) - Failed to write data to buffer %d\n", index);
   254         return -8;
   247         return -8;
   255     }
   248     }
   256     
   249     
   257     // clear any AL errors beforehand
   250     // clear any AL errors beforehand
   258     alGetError();
   251     alGetError();
   259 
   252 
   260     fprintf(stderr,"(Bridge Info) - successfully loaded %s\n", filename);
   253     fprintf(stderr,"(Bridge Info) - successfully loaded %s\n", filename);
   261 
   254 
   262     // returns the index of the source you just loaded, increments it and exits
   255     // returns the index of the source you just loaded, increments it and exits
   263     the_sounds[cache_pointer] = soundData;
   256     the_sounds[index] = sound_data;
   264     return cache_pointer++;
   257     return index;
   265 }
   258 }
       
   259 
       
   260 
       
   261 void openal_unloadfile (uint32_t index) {
       
   262     ALint state;
       
   263 
       
   264     if (openal_ready() == AL_TRUE && index < cache_size && the_sounds[index].is_used == AL_TRUE) {
       
   265         alGetSourcei (Sources[the_sounds[index].source_index], AL_SOURCE_STATE, &state);
       
   266         if (state == AL_PLAYING || state == AL_PAUSED)
       
   267             openal_stopsound(index);
       
   268         
       
   269         // free memory and 
       
   270         alDeleteBuffers (1, &the_sounds[index].buffer);
       
   271         the_sounds[index] = new_sound_el();
       
   272     }
       
   273 }