misc/libopenalbridge/openalbridge.c
changeset 3529 0e968ba12a84
parent 3514 59dbd31e9953
child 3697 d5b30d6373fc
--- a/misc/libopenalbridge/openalbridge.c	Fri Jun 18 14:45:05 2010 +0200
+++ b/misc/libopenalbridge/openalbridge.c	Mon Jun 21 16:08:24 2010 +0200
@@ -34,22 +34,14 @@
 
 // Initialize an OpenAL contex and allocate memory space for data and buffers
 // It can be called twice to increase the cache size
-int openal_init (int memorysize) {
+int openal_init (void) {
     ALCcontext *context;
     ALCdevice *device;
     int i;
         
     // reuse old context and resize the existing 
     if (openal_ready() == AL_TRUE) {
-        cache_size += memorysize;
-        fprintf(stderr,"(Bridge Info) - already initialized, resizing cache to %d\n", cache_size);
-        the_sounds = (al_sound_t *)Realloc (the_sounds, sizeof(al_sound_t) * cache_size);
-        for (i = cache_size - memorysize; i < cache_size; i++) {
-            the_sounds[i].filename = NULL;
-            the_sounds[i].buffer = -1;
-            the_sounds[i].source_index = -1;
-            the_sounds[i].stats = 0;
-        }
+        fprintf(stderr,"(Bridge Info) - already initialized\n");
         instances_number++;
         return AL_TRUE;
     }
@@ -57,12 +49,9 @@
     cache_pointer = 0;
     instances_number++;
     
-    // set the memory dimentsion and the increment width when reallocating
-    if (memorysize <= 0)
-        cache_size = 50;
-    else
-        cache_size = memorysize;
-
+    // initial memory size
+    cache_size = 50;
+    
     // open hardware device if present
     device = alcOpenDevice(NULL);
     sources_number = 16;
@@ -110,12 +99,8 @@
     }
 
     the_sounds = (al_sound_t *)Malloc (sizeof(al_sound_t) * cache_size);
-    for (i = 0; i < cache_size; i++) {
-        the_sounds[i].filename = NULL;
-        the_sounds[i].buffer = -1;
-        the_sounds[i].source_index = -1;
-        the_sounds[i].stats = 0;
-    }
+    for (i = 0; i < cache_size; i++)
+        the_sounds[i] = new_sound_el();
 
     alGetError();
     return AL_TRUE;
@@ -135,15 +120,16 @@
 
     instances_number--;
     if (instances_number > 0) {
+        // release memory only when last session ends
         return;
     }
     
-    //TODO: free other stuff also
-    for (i = 0; i < cache_size; i++)
-        alDeleteBuffers (1, &the_sounds[i].buffer);
+    for (i = 0; i < cache_size; i++) {
+        openal_unloadfile(i);
+    }
     free(the_sounds);
 
-    alSourceStopv	(sources_number, Sources);
+    alSourceStopv (sources_number, Sources);
     alDeleteSources (sources_number, Sources);
 
     free(Sources);
@@ -174,8 +160,8 @@
     ALenum format, error;
     ALsizei bitsize, freq;
     uint32_t fileformat;
-    al_sound_t soundData;
-    int len, i;
+    al_sound_t sound_data;
+    int len, i, index = -1;
     char *data;
     FILE *fp;
     
@@ -193,16 +179,24 @@
 #endif
             return i;
         }
+        // if we don't have memory available search for a free element
+        if (cache_pointer >= cache_size)
+            if (the_sounds[i].is_used == AL_FALSE)
+                index = i; 
     }
 
-    if (cache_pointer >= cache_size) {
-        fprintf(stderr,"(Bridge ERROR) - Cache size limit reached; consider allocating more space\n", filename);
-        return -2;
-    }
+    if (index == -1 && cache_pointer >= cache_size) {
+        fprintf(stderr,"(Bridge Info) - No free spots found; doubling cache size\n", filename);
+        cache_size *= 2;
+        the_sounds = (al_sound_t *)Realloc (the_sounds, sizeof(al_sound_t) * cache_size);
+        for (i = cache_size - 50; i < cache_size; i++) 
+            the_sounds[i] = new_sound_el();
+    } else 
+        index = ++cache_pointer;
+    
     
     // detect the file format, as written in the first 4 bytes of the header
     fp = Fopen (filename, "rb");
-
     if (fp == NULL) {
         fprintf(stderr,"(Bridge ERROR) - File %s not loaded\n", filename);
         return -3;
@@ -210,7 +204,6 @@
 
     error = fread (&fileformat, sizeof(uint32_t), 1, fp);
     fclose (fp);
-
     if (error < 0) {
         fprintf(stderr,"(Bridge ERROR) - File %s is too short\n", filename);
         return -4;
@@ -231,26 +224,26 @@
 
     if (error != 0) {
         fprintf(stderr,"(Bridge ERROR) - error loading file %s\n", filename);
-        free(data);
+        if(data)
+            free(data);
         return -6;
     }
 
-    alGenBuffers(1, &soundData.buffer);
-    soundData.filename = filename;
-    soundData.source_index = -1;
-    soundData.stats = 0;
+    // alGenBuffers happens here
+    sound_data = init_sound_el(filename);
     
     if (AL_NO_ERROR != alGetError()) {
-        fprintf(stderr,"(Bridge ERROR) - Failed to allocate memory for buffers\n");
+        fprintf(stderr,"(Bridge ERROR) - Failed to allocate memory for buffer %d\n", index);
+        free(data);
         return -5;
     }
     
     // copy pcm data in one buffer and free it
-    alBufferData(soundData.buffer, format, data, bitsize, freq);
+    alBufferData(sound_data.buffer, format, data, bitsize, freq);
     free(data);
 
     if (AL_NO_ERROR != alGetError()) {
-        fprintf(stderr,"(Bridge ERROR) - Failed to write data to buffers\n");
+        fprintf(stderr,"(Bridge ERROR) - Failed to write data to buffer %d\n", index);
         return -8;
     }
     
@@ -260,6 +253,21 @@
     fprintf(stderr,"(Bridge Info) - successfully loaded %s\n", filename);
 
     // returns the index of the source you just loaded, increments it and exits
-    the_sounds[cache_pointer] = soundData;
-    return cache_pointer++;
+    the_sounds[index] = sound_data;
+    return index;
 }
+
+
+void openal_unloadfile (uint32_t index) {
+    ALint state;
+
+    if (openal_ready() == AL_TRUE && index < cache_size && the_sounds[index].is_used == AL_TRUE) {
+        alGetSourcei (Sources[the_sounds[index].source_index], AL_SOURCE_STATE, &state);
+        if (state == AL_PLAYING || state == AL_PAUSED)
+            openal_stopsound(index);
+        
+        // free memory and 
+        alDeleteBuffers (1, &the_sounds[index].buffer);
+        the_sounds[index] = new_sound_el();
+    }
+}
\ No newline at end of file