Mercurial > audio-send
comparison utils/openal-info.c @ 0:f9476ff7637e
initial forking of open-al to create multiple listeners
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Tue, 25 Oct 2011 13:02:31 -0700 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:f9476ff7637e |
---|---|
1 /* | |
2 * OpenAL Info Utility | |
3 * | |
4 * Copyright (c) 2010 by Chris Robinson <chris.kcat@gmail.com> | |
5 * | |
6 * Permission is hereby granted, free of charge, to any person obtaining a copy | |
7 * of this software and associated documentation files (the "Software"), to deal | |
8 * in the Software without restriction, including without limitation the rights | |
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
10 * copies of the Software, and to permit persons to whom the Software is | |
11 * furnished to do so, subject to the following conditions: | |
12 * | |
13 * The above copyright notice and this permission notice shall be included in | |
14 * all copies or substantial portions of the Software. | |
15 * | |
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
22 * THE SOFTWARE. | |
23 */ | |
24 | |
25 #include <stdio.h> | |
26 #include <string.h> | |
27 | |
28 #include "AL/alc.h" | |
29 #include "AL/al.h" | |
30 #include "AL/alext.h" | |
31 | |
32 #ifndef ALC_ENUMERATE_ALL_EXT | |
33 #define ALC_DEFAULT_ALL_DEVICES_SPECIFIER 0x1012 | |
34 #define ALC_ALL_DEVICES_SPECIFIER 0x1013 | |
35 #endif | |
36 | |
37 #ifndef ALC_EXT_EFX | |
38 #define ALC_EFX_MAJOR_VERSION 0x20001 | |
39 #define ALC_EFX_MINOR_VERSION 0x20002 | |
40 #define ALC_MAX_AUXILIARY_SENDS 0x20003 | |
41 #define AL_FILTER_TYPE 0x8001 | |
42 #define AL_FILTER_NULL 0x0000 | |
43 #define AL_FILTER_LOWPASS 0x0001 | |
44 #define AL_FILTER_HIGHPASS 0x0002 | |
45 #define AL_FILTER_BANDPASS 0x0003 | |
46 #define AL_EFFECT_TYPE 0x8001 | |
47 #define AL_EFFECT_NULL 0x0000 | |
48 #define AL_EFFECT_EAXREVERB 0x8000 | |
49 #define AL_EFFECT_REVERB 0x0001 | |
50 #define AL_EFFECT_CHORUS 0x0002 | |
51 #define AL_EFFECT_DISTORTION 0x0003 | |
52 #define AL_EFFECT_ECHO 0x0004 | |
53 #define AL_EFFECT_FLANGER 0x0005 | |
54 #define AL_EFFECT_FREQUENCY_SHIFTER 0x0006 | |
55 #define AL_EFFECT_VOCAL_MORPHER 0x0007 | |
56 #define AL_EFFECT_PITCH_SHIFTER 0x0008 | |
57 #define AL_EFFECT_RING_MODULATOR 0x0009 | |
58 #define AL_EFFECT_AUTOWAH 0x000A | |
59 #define AL_EFFECT_COMPRESSOR 0x000B | |
60 #define AL_EFFECT_EQUALIZER 0x000C | |
61 typedef void (AL_APIENTRY *LPALGENFILTERS)(ALsizei, ALuint*); | |
62 typedef void (AL_APIENTRY *LPALDELETEFILTERS)(ALsizei, ALuint*); | |
63 typedef void (AL_APIENTRY *LPALFILTERI)(ALuint, ALenum, ALint); | |
64 typedef void (AL_APIENTRY *LPALGENEFFECTS)(ALsizei, ALuint*); | |
65 typedef void (AL_APIENTRY *LPALDELETEEFFECTS)(ALsizei, ALuint*); | |
66 typedef void (AL_APIENTRY *LPALEFFECTI)(ALuint, ALenum, ALint); | |
67 #endif | |
68 static LPALGENFILTERS palGenFilters; | |
69 static LPALDELETEFILTERS palDeleteFilters; | |
70 static LPALFILTERI palFilteri; | |
71 static LPALGENEFFECTS palGenEffects; | |
72 static LPALDELETEEFFECTS palDeleteEffects; | |
73 static LPALEFFECTI palEffecti; | |
74 | |
75 #ifndef ALC_EXT_DEDICATED | |
76 #define AL_EFFECT_DEDICATED_DIALOGUE 0x9001 | |
77 #define AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT 0x9000 | |
78 #endif | |
79 | |
80 | |
81 #define MAX_WIDTH 80 | |
82 | |
83 static void printList(const char *list, char separator) | |
84 { | |
85 size_t col = MAX_WIDTH, len; | |
86 const char *indent = " "; | |
87 const char *next; | |
88 | |
89 if(!list || *list == '\0') | |
90 { | |
91 fprintf(stdout, "\n%s!!! none !!!\n", indent); | |
92 return; | |
93 } | |
94 | |
95 do { | |
96 next = strchr(list, separator); | |
97 if(next) | |
98 { | |
99 len = next-list; | |
100 do { | |
101 next++; | |
102 } while(*next == separator); | |
103 } | |
104 else | |
105 len = strlen(list); | |
106 | |
107 if(len + col + 2 >= MAX_WIDTH) | |
108 { | |
109 fprintf(stdout, "\n%s", indent); | |
110 col = strlen(indent); | |
111 } | |
112 else | |
113 { | |
114 fputc(' ', stdout); | |
115 col++; | |
116 } | |
117 | |
118 len = fwrite(list, 1, len, stdout); | |
119 col += len; | |
120 | |
121 if(!next || *next == '\0') | |
122 break; | |
123 fputc(',', stdout); | |
124 col++; | |
125 | |
126 list = next; | |
127 } while(1); | |
128 fputc('\n', stdout); | |
129 } | |
130 | |
131 static void printDeviceList(const char *list) | |
132 { | |
133 if(!list || *list == '\0') | |
134 printf(" !!! none !!!\n"); | |
135 else do { | |
136 printf(" %s\n", list); | |
137 list += strlen(list) + 1; | |
138 } while(*list != '\0'); | |
139 } | |
140 | |
141 | |
142 static ALenum checkALErrors(int linenum) | |
143 { | |
144 ALenum err = alGetError(); | |
145 if(err != AL_NO_ERROR) | |
146 printf("OpenAL Error: %s (0x%x), @ %d\n", alGetString(err), err, linenum); | |
147 return err; | |
148 } | |
149 #define checkALErrors() checkALErrors(__LINE__) | |
150 | |
151 static ALCenum checkALCErrors(ALCdevice *device, int linenum) | |
152 { | |
153 ALCenum err = alcGetError(device); | |
154 if(err != ALC_NO_ERROR) | |
155 printf("ALC Error: %s (0x%x), @ %d\n", alcGetString(device, err), err, linenum); | |
156 return err; | |
157 } | |
158 #define checkALCErrors(x) checkALCErrors((x),__LINE__) | |
159 | |
160 | |
161 static void printALCInfo(ALCdevice *device) | |
162 { | |
163 ALCint major, minor; | |
164 | |
165 alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &major); | |
166 alcGetIntegerv(device, ALC_MINOR_VERSION, 1, &minor); | |
167 if(checkALCErrors(device) == ALC_NO_ERROR) | |
168 printf("ALC version: %d.%d\n", major, minor); | |
169 if(device) | |
170 { | |
171 printf("ALC extensions:"); | |
172 printList(alcGetString(device, ALC_EXTENSIONS), ' '); | |
173 checkALCErrors(device); | |
174 } | |
175 } | |
176 | |
177 static void printALInfo(void) | |
178 { | |
179 printf("OpenAL vendor string: %s\n", alGetString(AL_VENDOR)); | |
180 printf("OpenAL renderer string: %s\n", alGetString(AL_RENDERER)); | |
181 printf("OpenAL version string: %s\n", alGetString(AL_VERSION)); | |
182 printf("OpenAL extensions:"); | |
183 printList(alGetString(AL_EXTENSIONS), ' '); | |
184 checkALErrors(); | |
185 } | |
186 | |
187 static void printEFXInfo(ALCdevice *device) | |
188 { | |
189 ALCint major, minor, sends; | |
190 ALuint obj; | |
191 int i; | |
192 const ALenum filters[] = { | |
193 AL_FILTER_LOWPASS, AL_FILTER_HIGHPASS, AL_FILTER_BANDPASS, | |
194 AL_FILTER_NULL | |
195 }; | |
196 char filterNames[] = "Low-pass,High-pass,Band-pass,"; | |
197 const ALenum effects[] = { | |
198 AL_EFFECT_EAXREVERB, AL_EFFECT_REVERB, AL_EFFECT_CHORUS, | |
199 AL_EFFECT_DISTORTION, AL_EFFECT_ECHO, AL_EFFECT_FLANGER, | |
200 AL_EFFECT_FREQUENCY_SHIFTER, AL_EFFECT_VOCAL_MORPHER, | |
201 AL_EFFECT_PITCH_SHIFTER, AL_EFFECT_RING_MODULATOR, AL_EFFECT_AUTOWAH, | |
202 AL_EFFECT_COMPRESSOR, AL_EFFECT_EQUALIZER, AL_EFFECT_NULL | |
203 }; | |
204 const ALenum dedeffects[] = { | |
205 AL_EFFECT_DEDICATED_DIALOGUE, | |
206 AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT, AL_EFFECT_NULL | |
207 }; | |
208 char effectNames[] = "EAX Reverb,Reverb,Chorus,Distortion,Echo,Flanger," | |
209 "Frequency Shifter,Vocal Morpher,Pitch Shifter," | |
210 "Ring Modulator,Autowah,Compressor,Equalizer," | |
211 "Dedicated Dialog,Dedicated LFE,"; | |
212 char *current; | |
213 | |
214 if(alcIsExtensionPresent(device, "ALC_EXT_EFX") == AL_FALSE) | |
215 { | |
216 printf("EFX not available\n"); | |
217 return; | |
218 } | |
219 | |
220 alcGetIntegerv(device, ALC_EFX_MAJOR_VERSION, 1, &major); | |
221 alcGetIntegerv(device, ALC_EFX_MINOR_VERSION, 1, &minor); | |
222 if(checkALCErrors(device) == ALC_NO_ERROR) | |
223 printf("EFX version: %d.%d\n", major, minor); | |
224 alcGetIntegerv(device, ALC_MAX_AUXILIARY_SENDS, 1, &sends); | |
225 if(checkALCErrors(device) == ALC_NO_ERROR) | |
226 printf("Max auxiliary sends: %d\n", sends); | |
227 | |
228 palGenFilters = alGetProcAddress("alGenFilters"); | |
229 palDeleteFilters = alGetProcAddress("alDeleteFilters"); | |
230 palFilteri = alGetProcAddress("alFilteri"); | |
231 palGenEffects = alGetProcAddress("alGenEffects"); | |
232 palDeleteEffects = alGetProcAddress("alDeleteEffects"); | |
233 palEffecti = alGetProcAddress("alEffecti"); | |
234 if(checkALErrors() != AL_NO_ERROR || | |
235 !palGenFilters || !palDeleteFilters || !palFilteri || | |
236 !palGenEffects || !palDeleteEffects || !palEffecti) | |
237 { | |
238 printf("!!! Missing EFX functions !!!\n"); | |
239 return; | |
240 } | |
241 | |
242 palGenFilters(1, &obj); | |
243 if(checkALErrors() == AL_NO_ERROR) | |
244 { | |
245 current = filterNames; | |
246 for(i = 0;filters[i] != AL_FILTER_NULL;i++) | |
247 { | |
248 char *next = strchr(current, ','); | |
249 | |
250 palFilteri(obj, AL_FILTER_TYPE, filters[i]); | |
251 if(alGetError() == AL_NO_ERROR) | |
252 current = next+1; | |
253 else | |
254 memmove(current, next+1, strlen(next)); | |
255 } | |
256 palDeleteFilters(1, &obj); | |
257 checkALErrors(); | |
258 | |
259 printf("Supported filters:"); | |
260 printList(filterNames, ','); | |
261 } | |
262 | |
263 palGenEffects(1, &obj); | |
264 if(checkALErrors() == AL_NO_ERROR) | |
265 { | |
266 current = effectNames; | |
267 for(i = 0;effects[i] != AL_EFFECT_NULL;i++) | |
268 { | |
269 char *next = strchr(current, ','); | |
270 | |
271 palEffecti(obj, AL_EFFECT_TYPE, effects[i]); | |
272 if(alGetError() == AL_NO_ERROR) | |
273 current = next+1; | |
274 else | |
275 memmove(current, next+1, strlen(next)); | |
276 } | |
277 if(alcIsExtensionPresent(device, "ALC_EXT_DEDICATED")) | |
278 { | |
279 for(i = 0;dedeffects[i] != AL_EFFECT_NULL;i++) | |
280 { | |
281 char *next = strchr(current, ','); | |
282 | |
283 palEffecti(obj, AL_EFFECT_TYPE, dedeffects[i]); | |
284 if(alGetError() == AL_NO_ERROR) | |
285 current = next+1; | |
286 else | |
287 memmove(current, next+1, strlen(next)); | |
288 } | |
289 } | |
290 else | |
291 { | |
292 for(i = 0;dedeffects[i] != AL_EFFECT_NULL;i++) | |
293 { | |
294 char *next = strchr(current, ','); | |
295 memmove(current, next+1, strlen(next)); | |
296 } | |
297 } | |
298 palDeleteEffects(1, &obj); | |
299 checkALErrors(); | |
300 | |
301 printf("Supported effects:"); | |
302 printList(effectNames, ','); | |
303 } | |
304 } | |
305 | |
306 int main(int argc, char *argv[]) | |
307 { | |
308 ALCdevice *device; | |
309 ALCcontext *context; | |
310 | |
311 if(argc > 1 && (strcmp(argv[1], "--help") == 0 || | |
312 strcmp(argv[1], "-h") == 0)) | |
313 { | |
314 printf("Usage: %s [playback device]\n", argv[0]); | |
315 return 0; | |
316 } | |
317 | |
318 printf("Available playback devices:\n"); | |
319 if(alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT") != AL_FALSE) | |
320 printDeviceList(alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER)); | |
321 else | |
322 printDeviceList(alcGetString(NULL, ALC_DEVICE_SPECIFIER)); | |
323 printf("Available capture devices:\n"); | |
324 printDeviceList(alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER)); | |
325 | |
326 if(alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT") != AL_FALSE) | |
327 printf("Default playback device: %s\n", | |
328 alcGetString(NULL, ALC_DEFAULT_ALL_DEVICES_SPECIFIER)); | |
329 else | |
330 printf("Default playback device: %s\n", | |
331 alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER)); | |
332 printf("Default capture device: %s\n", | |
333 alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER)); | |
334 | |
335 printALCInfo(NULL); | |
336 | |
337 device = alcOpenDevice((argc>1) ? argv[1] : NULL); | |
338 if(!device) | |
339 { | |
340 printf("\n!!! Failed to open %s !!!\n\n", ((argc>1) ? argv[1] : "default device")); | |
341 return 1; | |
342 } | |
343 | |
344 printf("\n** Info for device \"%s\" **\n", alcGetString(device, ALC_DEVICE_SPECIFIER)); | |
345 printALCInfo(device); | |
346 | |
347 context = alcCreateContext(device, NULL); | |
348 if(!context || alcMakeContextCurrent(context) == ALC_FALSE) | |
349 { | |
350 if(context) | |
351 alcDestroyContext(context); | |
352 alcCloseDevice(device); | |
353 printf("\n!!! Failed to set a context !!!\n\n"); | |
354 return 1; | |
355 } | |
356 | |
357 printALInfo(); | |
358 printEFXInfo(device); | |
359 | |
360 alcMakeContextCurrent(NULL); | |
361 alcDestroyContext(context); | |
362 alcCloseDevice(device); | |
363 | |
364 return 0; | |
365 } |