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 } |