15 * along with this program; if not, write to the Free Software |
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 |
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA |
17 */ |
17 */ |
18 |
18 |
19 #include "openalbridge.h" |
19 #include "openalbridge.h" |
20 #include "wrappers.h" |
20 |
21 #include "alc.h" |
|
22 #include "loaders.h" |
|
23 #include "endianness.h" |
|
24 |
21 |
25 #ifdef __CPLUSPLUS |
22 #ifdef __CPLUSPLUS |
26 extern "C" { |
23 extern "C" { |
27 #endif |
24 #endif |
28 |
25 |
34 ALuint globalindex, globalsize, increment; |
31 ALuint globalindex, globalsize, increment; |
35 |
32 |
36 ALboolean openalReady = AL_FALSE; |
33 ALboolean openalReady = AL_FALSE; |
37 |
34 |
38 ALboolean openal_close (void) { |
35 ALboolean openal_close (void) { |
39 /*Stop all sounds, deallocate all memory and close OpenAL */ |
36 /*Stop all sounds, deallocate all memory and close OpenAL */ |
40 ALCcontext *context; |
37 ALCcontext *context; |
41 ALCdevice *device; |
38 ALCdevice *device; |
42 |
39 |
43 if(openalReady == AL_FALSE) { |
40 if (openalReady == AL_FALSE) { |
44 fprintf(stderr, "ERROR: OpenAL not initialized\n"); |
41 errno = EPERM; |
45 return AL_FALSE; |
42 err_ret("(%s) WARN - OpenAL not initialized", prog); |
46 } |
43 return AL_FALSE; |
47 |
44 } |
|
45 |
48 alSourceStopv (globalsize, Sources); |
46 alSourceStopv (globalsize, Sources); |
49 alDeleteSources (globalsize, Sources); |
47 alDeleteSources (globalsize, Sources); |
50 alDeleteBuffers (globalsize, Buffers); |
48 alDeleteBuffers (globalsize, Buffers); |
51 |
49 |
52 free(Sources); |
50 free(Sources); |
66 |
64 |
67 ALboolean openal_ready(void) { |
65 ALboolean openal_ready(void) { |
68 return openalReady; |
66 return openalReady; |
69 } |
67 } |
70 |
68 |
71 ALboolean openal_init(uint32_t usehardware, uint32_t memorysize) { |
69 ALboolean openal_init(char* programname, ALboolean usehardware, uint32_t memorysize) { |
72 /*Initialize an OpenAL contex and allocate memory space for data and buffers*/ |
70 /*Initialize an OpenAL contex and allocate memory space for data and buffers*/ |
73 ALCcontext *context; |
71 ALCcontext *context; |
74 ALCdevice *device; |
72 ALCdevice *device; |
75 const ALCchar *default_device; |
73 const ALCchar *default_device; |
76 |
74 |
|
75 prog = programname; |
|
76 |
|
77 |
77 /*Position of the listener*/ |
78 /*Position of the listener*/ |
78 ALfloat ListenerPos[] = { 0.0, 0.0, 0.0 }; |
79 ALfloat ListenerPos[] = { 0.0, 0.0, 0.0 }; |
79 /*Velocity of the listener*/ |
80 /*Velocity of the listener*/ |
80 ALfloat ListenerVel[] = { 0.0, 0.0, 0.0 }; |
81 ALfloat ListenerVel[] = { 0.0, 0.0, 0.0 }; |
81 /*Orientation of the listener. (first 3 elements are "at", second 3 are "up")*/ |
82 /*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 ALfloat ListenerOri[] = { 0.0, 0.0, -1.0, 0.0, 1.0, 0.0 }; |
83 |
84 |
84 if(openalReady == AL_TRUE) { |
85 if (openalReady == AL_TRUE) { |
85 fprintf(stderr, "ERROR 'openal_init()': OpenAL already initialized\n"); |
86 errno = EPERM; |
86 return AL_FALSE; |
87 err_ret("(%s) WARN - OpenAL already initialized", prog); |
87 } |
88 return AL_FALSE; |
88 |
89 } |
89 if(usehardware) |
90 |
90 { |
91 if (usehardware) |
91 if ((device = alcOpenDevice(NULL)) == NULL) { |
92 device = alcOpenDevice(NULL); |
92 fprintf(stderr, "ERROR 'openal_init()': Failed to open sound device\n"); |
93 else |
93 return AL_FALSE; |
94 device = alcOpenDevice("Generic Software"); |
94 } |
95 |
95 } |
96 if (device == NULL) { |
96 else |
97 errno = ENODEV; |
97 { |
98 err_ret("(%s) WARN - Failed to open sound device", prog); |
98 if ((device = alcOpenDevice("Generic Software")) == NULL) { |
99 return AL_FALSE; |
99 fprintf(stderr, "ERROR 'openal_init()': Failed to open sound device\n"); |
100 } |
100 return AL_FALSE; |
101 err_msg("(%s) INFO - output device: %s", prog, alcGetString(device, ALC_DEVICE_SPECIFIER)); |
101 } |
102 |
102 } |
103 context = alcCreateContext(device, NULL); |
103 fprintf(stderr, "Using default device: %s\n", alcGetString(device, ALC_DEVICE_SPECIFIER)); |
104 alcMakeContextCurrent(context); |
104 |
105 alcProcessContext(context); |
105 context = alcCreateContext(device, NULL); |
106 |
106 alcMakeContextCurrent(context); |
107 if (AlGetError("(%s) WARN - Failed to create a new contex") != AL_TRUE) |
107 alcProcessContext(context); |
|
108 |
|
109 if (AlGetError("ERROR %d in 'openal_init()': Creating a new contex\n") != AL_TRUE) |
|
110 return AL_FALSE; |
108 return AL_FALSE; |
111 |
109 |
112 /*allocate memory space for buffers and sources*/ |
110 /*allocate memory space for buffers and sources*/ |
113 if (memorysize == 0) |
111 if (memorysize == 0) |
114 globalsize = 50; |
112 globalsize = 50; |
123 alListenerf (AL_GAIN, 1.0f ); |
121 alListenerf (AL_GAIN, 1.0f ); |
124 alListenerfv(AL_POSITION, ListenerPos); |
122 alListenerfv(AL_POSITION, ListenerPos); |
125 alListenerfv(AL_VELOCITY, ListenerVel); |
123 alListenerfv(AL_VELOCITY, ListenerVel); |
126 alListenerfv(AL_ORIENTATION, ListenerOri); |
124 alListenerfv(AL_ORIENTATION, ListenerOri); |
127 |
125 |
128 if (AlGetError("ERROR %d: Setting Listener properties\n") != AL_TRUE) |
126 if (AlGetError("(%s) WARN - Failed to set Listener properties") != AL_TRUE) |
129 return AL_FALSE; |
127 return AL_FALSE; |
130 |
128 |
131 openalReady = AL_TRUE; |
129 openalReady = AL_TRUE; |
132 |
130 |
133 alGetError(); /* clear any AL errors beforehand */ |
131 alGetError(); /* clear any AL errors beforehand */ |
139 /*expands allocated memory when loading more sound files than expected*/ |
137 /*expands allocated memory when loading more sound files than expected*/ |
140 int oldsize = globalsize; |
138 int oldsize = globalsize; |
141 globalsize += increment; |
139 globalsize += increment; |
142 |
140 |
143 #ifdef DEBUG |
141 #ifdef DEBUG |
144 fprintf(stderr, "OpenALBridge: Realloc in process from %d to %d\n", oldsize, globalsize); |
142 err_msg("(%s) INFO - Realloc in process from %d to %d\n", prog, oldsize, globalsize); |
145 #endif |
143 #endif |
146 |
144 |
147 Buffers = (ALuint*) Realloc(Buffers, sizeof(ALuint)*globalsize); |
145 Buffers = (ALuint*) Realloc(Buffers, sizeof(ALuint)*globalsize); |
148 Sources = (ALuint*) Realloc(Sources, sizeof(ALuint)*globalsize); |
146 Sources = (ALuint*) Realloc(Sources, sizeof(ALuint)*globalsize); |
149 |
147 |
160 char *data; |
158 char *data; |
161 uint32_t fileformat; |
159 uint32_t fileformat; |
162 ALenum error; |
160 ALenum error; |
163 FILE *fp; |
161 FILE *fp; |
164 |
162 |
165 if(openalReady == AL_FALSE) { |
163 if (openalReady == AL_FALSE) { |
166 fprintf(stderr, "ERROR 'openal_loadfile()': OpenAL not initialized\n"); |
164 errno = EPERM; |
167 return AL_FALSE; |
165 err_ret("(%s) WARN - OpenAL not initialized", prog); |
168 } |
166 return AL_FALSE; |
|
167 } |
169 |
168 |
170 /*when the buffers are all used, we can expand memory to accept new files*/ |
169 /*when the buffers are all used, we can expand memory to accept new files*/ |
171 if (globalindex == globalsize) |
170 if (globalindex == globalsize) |
172 helper_realloc(); |
171 helper_realloc(); |
173 |
172 |
174 /*detect the file format, as written in the first 4 bytes of the header*/ |
173 /*detect the file format, as written in the first 4 bytes of the header*/ |
175 fp = Fopen (filename, "rb"); |
174 fp = Fopen (filename, "rb"); |
|
175 |
176 if (fp == NULL) |
176 if (fp == NULL) |
177 return -1; |
177 return -1; |
|
178 |
178 error = fread (&fileformat, sizeof(uint32_t), 1, fp); |
179 error = fread (&fileformat, sizeof(uint32_t), 1, fp); |
179 fclose (fp); |
180 fclose (fp); |
180 |
181 |
181 if (error < 0) { |
182 if (error < 0) { |
182 fprintf(stderr, "ERROR 'openal_loadfile()': file %s is too short \n", filename); |
183 errno = EIO; |
183 return -2; |
184 err_ret("(%s) ERROR - file %s is too short", prog, filename); |
|
185 return -2; |
184 } |
186 } |
185 |
187 |
186 /*prepare the buffer to receive data*/ |
188 /*prepare the buffer to receive data*/ |
187 alGenBuffers(1, &Buffers[globalindex]); |
189 alGenBuffers(1, &Buffers[globalindex]); |
188 |
190 |
189 if (AlGetError("ERROR %d in 'openal_loadfile()': Allocating memory for buffers\n") != AL_TRUE) |
191 if (AlGetError("(%s) ERROR - allocating memory for buffers") != AL_TRUE) |
190 return -3; |
192 return -3; |
191 |
193 |
192 /*prepare the source to emit sound*/ |
194 /*prepare the source to emit sound*/ |
193 alGenSources(1, &Sources[globalindex]); |
195 alGenSources(1, &Sources[globalindex]); |
194 |
196 |
195 if (AlGetError("ERROR %d in 'openal_loadfile()': Allocating memory for sources\n") != AL_TRUE) |
197 if (AlGetError("(%s) ERROR - allocating memory for sources") != AL_TRUE) |
196 return -4; |
198 return -4; |
197 |
199 |
198 |
200 |
199 switch (ENDIAN_BIG_32(fileformat)) { |
201 switch (ENDIAN_BIG_32(fileformat)) { |
200 case OGG_FILE_FORMAT: |
202 case OGG_FILE_FORMAT: |
202 break; |
204 break; |
203 case WAV_FILE_FORMAT: |
205 case WAV_FILE_FORMAT: |
204 error = load_wavpcm (filename, &format, &data, &bitsize, &freq); |
206 error = load_wavpcm (filename, &format, &data, &bitsize, &freq); |
205 break; |
207 break; |
206 default: |
208 default: |
207 fprintf(stderr, "ERROR 'openal_loadfile()': File format (%08X) not supported!\n", ENDIAN_BIG_32(fileformat)); |
209 errno = EINVAL; |
|
210 err_ret ("(%s) ERROR - File format (%08X) not supported", prog, ENDIAN_BIG_32(fileformat)); |
208 return -5; |
211 return -5; |
209 break; |
212 break; |
210 } |
213 } |
211 |
214 |
212 |
215 |
213 /*copy pcm data in one buffer*/ |
216 /*copy pcm data in one buffer*/ |
214 alBufferData(Buffers[globalindex], format, data, bitsize, freq); |
217 alBufferData(Buffers[globalindex], format, data, bitsize, freq); |
215 free(data); /*deallocate data to save memory*/ |
218 free(data); /*deallocate data to save memory*/ |
216 |
219 |
217 if (AlGetError("ERROR %d in 'openal_loadfile()': Writing data to buffer\n") != AL_TRUE) |
220 if (AlGetError("(%s) ERROR - writing data to buffers") != AL_TRUE) |
218 return -6; |
221 return -6; |
219 |
222 |
220 /*set source properties that it will use when it's in playback*/ |
223 /*set source properties that it will use when it's in playback*/ |
221 alSourcei (Sources[globalindex], AL_BUFFER, Buffers[globalindex] ); |
224 alSourcei (Sources[globalindex], AL_BUFFER, Buffers[globalindex] ); |
222 alSourcef (Sources[globalindex], AL_PITCH, 1.0f ); |
225 alSourcef (Sources[globalindex], AL_PITCH, 1.0f ); |
223 alSourcef (Sources[globalindex], AL_GAIN, 1.0f ); |
226 alSourcef (Sources[globalindex], AL_GAIN, 1.0f ); |
224 alSourcefv(Sources[globalindex], AL_POSITION, SourcePos ); |
227 alSourcefv(Sources[globalindex], AL_POSITION, SourcePos ); |
225 alSourcefv(Sources[globalindex], AL_VELOCITY, SourceVel ); |
228 alSourcefv(Sources[globalindex], AL_VELOCITY, SourceVel ); |
226 alSourcei (Sources[globalindex], AL_LOOPING, 0 ); |
229 alSourcei (Sources[globalindex], AL_LOOPING, 0 ); |
227 |
230 |
228 if (AlGetError("ERROR %d in 'openal_loadfile()': Setting source properties\n") != AL_TRUE) |
231 if (AlGetError("(%s) ERROR - setting Source properties") != AL_TRUE) |
229 return -7; |
232 return -7; |
230 |
233 |
231 alGetError(); /* clear any AL errors beforehand */ |
234 alGetError(); /* clear any AL errors beforehand */ |
232 |
235 |
233 /*returns the index of the source you just loaded, increments it and exits*/ |
236 /*returns the index of the source you just loaded, increments it and exits*/ |
237 |
240 |
238 ALboolean openal_toggleloop (uint32_t index){ |
241 ALboolean openal_toggleloop (uint32_t index){ |
239 /*Set or unset looping mode*/ |
242 /*Set or unset looping mode*/ |
240 ALint loop; |
243 ALint loop; |
241 |
244 |
242 if(openalReady == AL_FALSE) { |
245 if (openalReady == AL_FALSE) { |
243 fprintf(stderr, "ERROR 'openal_toggleloop()': OpenAL not initialized\n"); |
246 errno = EPERM; |
244 return AL_FALSE; |
247 err_ret("(%s) WARN - OpenAL not initialized", prog); |
245 } |
248 return AL_FALSE; |
|
249 } |
246 |
250 |
247 if (index >= globalsize) { |
251 if (index >= globalsize) { |
248 fprintf(stderr, "ERROR 'openal_toggleloop()': index out of bounds (got %d, max %d)\n", index, globalindex); |
252 errno = EINVAL; |
249 return AL_FALSE; |
253 err_ret("(%s) ERROR - index out of bounds (got %d, max %d)", prog, index, globalindex); |
|
254 return AL_FALSE; |
250 } |
255 } |
251 |
256 |
252 alGetSourcei (Sources[index], AL_LOOPING, &loop); |
257 alGetSourcei (Sources[index], AL_LOOPING, &loop); |
253 alSourcei (Sources[index], AL_LOOPING, !((uint8_t) loop) & 0x00000001); |
258 alSourcei (Sources[index], AL_LOOPING, !((uint8_t) loop) & 0x00000001); |
254 if (AlGetError("ERROR %d in 'openal_toggleloop()': Getting or setting loop property\n") != AL_TRUE) |
259 if (AlGetError("(%s) ERROR - getting or setting loop property") != AL_TRUE) |
255 return AL_FALSE; |
260 return AL_FALSE; |
256 |
261 |
257 alGetError(); /* clear any AL errors beforehand */ |
262 alGetError(); /* clear any AL errors beforehand */ |
258 |
263 |
259 return AL_TRUE; |
264 return AL_TRUE; |
260 } |
265 } |
261 |
266 |
262 |
267 |
263 ALboolean openal_setvolume (uint32_t index, uint8_t percentage) { |
268 ALboolean openal_setvolume (uint32_t index, uint8_t percentage) { |
264 if(openalReady == AL_FALSE) { |
269 if (openalReady == AL_FALSE) { |
265 fprintf(stderr, "ERROR 'openal_setvolume()': OpenAL not initialized\n"); |
270 errno = EPERM; |
266 return AL_FALSE; |
271 err_ret("(%s) WARN - OpenAL not initialized", prog); |
267 } |
272 return AL_FALSE; |
|
273 } |
268 |
274 |
269 /*Set volume for sound number index*/ |
275 /*Set volume for sound number index*/ |
270 if (index >= globalindex) { |
276 if (index >= globalindex) { |
271 fprintf(stderr, "ERROR 'openal_setvolume()': index out of bounds (got %d, max %d)\n", index, globalindex); |
277 fprintf(stderr, "ERROR 'openal_setvolume()': index out of bounds (got %d, max %d)\n", index, globalindex); |
272 return AL_FALSE; |
278 return AL_FALSE; |
283 return AL_TRUE; |
289 return AL_TRUE; |
284 } |
290 } |
285 |
291 |
286 |
292 |
287 ALboolean openal_setglobalvolume (uint8_t percentage) { |
293 ALboolean openal_setglobalvolume (uint8_t percentage) { |
288 if(openalReady == AL_FALSE) { |
294 if (openalReady == AL_FALSE) { |
289 fprintf(stderr, "ERROR 'openal_setglobalvolume()': OpenAL not initialized\n"); |
295 errno = EPERM; |
290 return AL_FALSE; |
296 err_ret("(%s) WARN - OpenAL not initialized", prog); |
291 } |
297 return AL_FALSE; |
|
298 } |
292 |
299 |
293 /*Set volume for all sounds*/ |
300 /*Set volume for all sounds*/ |
294 if (percentage > 100) |
301 if (percentage > 100) |
295 percentage = 100; |
302 percentage = 100; |
296 alListenerf (AL_GAIN, (float) percentage/100.0f); |
303 alListenerf (AL_GAIN, (float) percentage/100.0f); |
394 return openal_fade(index, quantity, FADE_IN); |
403 return openal_fade(index, quantity, FADE_IN); |
395 } |
404 } |
396 |
405 |
397 |
406 |
398 ALboolean openal_setposition (uint32_t index, float x, float y, float z) { |
407 ALboolean openal_setposition (uint32_t index, float x, float y, float z) { |
399 if(openalReady == AL_FALSE) { |
408 if (openalReady == AL_FALSE) { |
400 fprintf(stderr, "ERROR 'openal_setposition()': OpenAL not initialized\n"); |
409 errno = EPERM; |
401 return AL_FALSE; |
410 err_ret("(%s) WARN - OpenAL not initialized", prog); |
402 } |
411 return AL_FALSE; |
|
412 } |
403 |
413 |
404 if (index >= globalindex) { |
414 if (index >= globalindex) { |
405 fprintf(stderr, "ERROR 'openal_setposition()': index out of bounds (got %d, max %d)\n", index, globalindex); |
415 fprintf(stderr, "ERROR 'openal_setposition()': index out of bounds (got %d, max %d)\n", index, globalindex); |
406 return AL_FALSE; |
416 return AL_FALSE; |
407 } |
417 } |
413 return AL_TRUE; |
423 return AL_TRUE; |
414 } |
424 } |
415 |
425 |
416 |
426 |
417 ALboolean openal_playsound (uint32_t index){ |
427 ALboolean openal_playsound (uint32_t index){ |
418 if(openalReady == AL_FALSE) { |
428 if (openalReady == AL_FALSE) { |
419 fprintf(stderr, "ERROR 'openal_playsound()': OpenAL not initialized\n"); |
429 errno = EPERM; |
420 return AL_FALSE; |
430 err_ret("(%s) WARN - OpenAL not initialized", prog); |
421 } |
431 return AL_FALSE; |
|
432 } |
422 |
433 |
423 /*Play sound number index*/ |
434 /*Play sound number index*/ |
424 if (index >= globalindex) { |
435 if (index >= globalindex) { |
425 fprintf(stderr, "ERROR 'openal_playsound()': index out of bounds (got %d, max %d)\n", index, globalindex); |
436 fprintf(stderr, "ERROR 'openal_playsound()': index out of bounds (got %d, max %d)\n", index, globalindex); |
426 return AL_FALSE; |
437 return AL_FALSE; |
434 return AL_TRUE; |
445 return AL_TRUE; |
435 } |
446 } |
436 |
447 |
437 |
448 |
438 ALboolean openal_pausesound(uint32_t index){ |
449 ALboolean openal_pausesound(uint32_t index){ |
439 if(openalReady == AL_FALSE) { |
450 if (openalReady == AL_FALSE) { |
440 fprintf(stderr, "ERROR 'openal_pausesound()': OpenAL not initialized\n"); |
451 errno = EPERM; |
441 return AL_FALSE; |
452 err_ret("(%s) WARN - OpenAL not initialized", prog); |
442 } |
453 return AL_FALSE; |
|
454 } |
443 |
455 |
444 /*Pause sound number index*/ |
456 /*Pause sound number index*/ |
445 if (index >= globalindex) { |
457 if (index >= globalindex) { |
446 fprintf(stderr, "ERROR 'openal_pausesound()': index out of bounds (got %d, max %d)\n", index, globalindex); |
458 fprintf(stderr, "ERROR 'openal_pausesound()': index out of bounds (got %d, max %d)\n", index, globalindex); |
447 return AL_FALSE; |
459 return AL_FALSE; |
453 return AL_TRUE; |
465 return AL_TRUE; |
454 } |
466 } |
455 |
467 |
456 |
468 |
457 ALboolean openal_stopsound(uint32_t index){ |
469 ALboolean openal_stopsound(uint32_t index){ |
458 if(openalReady == AL_FALSE) { |
470 if (openalReady == AL_FALSE) { |
459 fprintf(stderr, "ERROR 'openal_stopsound()': OpenAL not initialized\n"); |
471 errno = EPERM; |
460 return AL_FALSE; |
472 err_ret("(%s) WARN - OpenAL not initialized", prog); |
461 } |
473 return AL_FALSE; |
|
474 } |
462 |
475 |
463 /*Stop sound number index*/ |
476 /*Stop sound number index*/ |
464 if (index >= globalindex) { |
477 if (index >= globalindex) { |
465 fprintf(stderr, "ERROR 'openal_stopsound()': index out of bounds (got %d, max %d)\n", index, globalindex); |
478 fprintf(stderr, "ERROR 'openal_stopsound()': index out of bounds (got %d, max %d)\n", index, globalindex); |
466 return AL_FALSE; |
479 return AL_FALSE; |