4 * Copyright (c) 2010 by Chris Robinson <chris.kcat@gmail.com>
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:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
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
34 #ifndef ALC_ENUMERATE_ALL_EXT
35 #define ALC_DEFAULT_ALL_DEVICES_SPECIFIER 0x1012
36 #define ALC_ALL_DEVICES_SPECIFIER 0x1013
40 #define ALC_EFX_MAJOR_VERSION 0x20001
41 #define ALC_EFX_MINOR_VERSION 0x20002
42 #define ALC_MAX_AUXILIARY_SENDS 0x20003
43 #define AL_FILTER_TYPE 0x8001
44 #define AL_FILTER_NULL 0x0000
45 #define AL_FILTER_LOWPASS 0x0001
46 #define AL_FILTER_HIGHPASS 0x0002
47 #define AL_FILTER_BANDPASS 0x0003
48 #define AL_EFFECT_TYPE 0x8001
49 #define AL_EFFECT_NULL 0x0000
50 #define AL_EFFECT_EAXREVERB 0x8000
51 #define AL_EFFECT_REVERB 0x0001
52 #define AL_EFFECT_CHORUS 0x0002
53 #define AL_EFFECT_DISTORTION 0x0003
54 #define AL_EFFECT_ECHO 0x0004
55 #define AL_EFFECT_FLANGER 0x0005
56 #define AL_EFFECT_FREQUENCY_SHIFTER 0x0006
57 #define AL_EFFECT_VOCAL_MORPHER 0x0007
58 #define AL_EFFECT_PITCH_SHIFTER 0x0008
59 #define AL_EFFECT_RING_MODULATOR 0x0009
60 #define AL_EFFECT_AUTOWAH 0x000A
61 #define AL_EFFECT_COMPRESSOR 0x000B
62 #define AL_EFFECT_EQUALIZER 0x000C
63 typedef void (AL_APIENTRY
*LPALGENFILTERS
)(ALsizei
, ALuint
*);
64 typedef void (AL_APIENTRY
*LPALDELETEFILTERS
)(ALsizei
, ALuint
*);
65 typedef void (AL_APIENTRY
*LPALFILTERI
)(ALuint
, ALenum
, ALint
);
66 typedef void (AL_APIENTRY
*LPALGENEFFECTS
)(ALsizei
, ALuint
*);
67 typedef void (AL_APIENTRY
*LPALDELETEEFFECTS
)(ALsizei
, ALuint
*);
68 typedef void (AL_APIENTRY
*LPALEFFECTI
)(ALuint
, ALenum
, ALint
);
70 static LPALGENFILTERS palGenFilters
;
71 static LPALDELETEFILTERS palDeleteFilters
;
72 static LPALFILTERI palFilteri
;
73 static LPALGENEFFECTS palGenEffects
;
74 static LPALDELETEEFFECTS palDeleteEffects
;
75 static LPALEFFECTI palEffecti
;
80 static void printList(const char *list
, char separator
)
82 size_t col
= MAX_WIDTH
, len
;
83 const char *indent
= " ";
86 if(!list
|| *list
== '\0')
88 fprintf(stdout
, "\n%s!!! none !!!\n", indent
);
93 next
= strchr(list
, separator
);
99 } while(*next
== separator
);
104 if(len
+ col
+ 2 >= MAX_WIDTH
)
106 fprintf(stdout
, "\n%s", indent
);
107 col
= strlen(indent
);
115 len
= fwrite(list
, 1, len
, stdout
);
118 if(!next
|| *next
== '\0')
128 static void printDeviceList(const char *list
)
130 if(!list
|| *list
== '\0')
131 printf(" !!! none !!!\n");
133 printf(" %s\n", list
);
134 list
+= strlen(list
) + 1;
135 } while(*list
!= '\0');
139 static ALenum
checkALErrors(int linenum
)
141 ALenum err
= alGetError();
142 if(err
!= AL_NO_ERROR
)
143 printf("OpenAL Error: %s (0x%x), @ %d\n", alGetString(err
), err
, linenum
);
146 #define checkALErrors() checkALErrors(__LINE__)
148 static ALCenum
checkALCErrors(ALCdevice
*device
, int linenum
)
150 ALCenum err
= alcGetError(device
);
151 if(err
!= ALC_NO_ERROR
)
152 printf("ALC Error: %s (0x%x), @ %d\n", alcGetString(device
, err
), err
, linenum
);
155 #define checkALCErrors(x) checkALCErrors((x),__LINE__)
158 static void printALCInfo(ALCdevice
*device
)
162 alcGetIntegerv(device
, ALC_MAJOR_VERSION
, 1, &major
);
163 alcGetIntegerv(device
, ALC_MINOR_VERSION
, 1, &minor
);
164 if(checkALCErrors(device
) == ALC_NO_ERROR
)
165 printf("ALC version: %d.%d\n", major
, minor
);
168 printf("ALC extensions:");
169 printList(alcGetString(device
, ALC_EXTENSIONS
), ' ');
170 checkALCErrors(device
);
174 static void printALInfo(void)
176 printf("OpenAL vendor string: %s\n", alGetString(AL_VENDOR
));
177 printf("OpenAL renderer string: %s\n", alGetString(AL_RENDERER
));
178 printf("OpenAL version string: %s\n", alGetString(AL_VERSION
));
179 printf("OpenAL extensions:");
180 printList(alGetString(AL_EXTENSIONS
), ' ');
184 static void printEFXInfo(ALCdevice
*device
)
186 ALCint major
, minor
, sends
;
189 const ALenum filters
[] = {
190 AL_FILTER_LOWPASS
, AL_FILTER_HIGHPASS
, AL_FILTER_BANDPASS
,
193 char filterNames
[] = "Low-pass,High-pass,Band-pass,";
194 const ALenum effects
[] = {
195 AL_EFFECT_EAXREVERB
, AL_EFFECT_REVERB
, AL_EFFECT_CHORUS
,
196 AL_EFFECT_DISTORTION
, AL_EFFECT_ECHO
, AL_EFFECT_FLANGER
,
197 AL_EFFECT_FREQUENCY_SHIFTER
, AL_EFFECT_VOCAL_MORPHER
,
198 AL_EFFECT_PITCH_SHIFTER
, AL_EFFECT_RING_MODULATOR
, AL_EFFECT_AUTOWAH
,
199 AL_EFFECT_COMPRESSOR
, AL_EFFECT_EQUALIZER
, AL_EFFECT_NULL
201 char effectNames
[] = "EAX Reverb,Reverb,Chorus,Distortion,Echo,Flanger,"
202 "Frequency Shifter,Vocal Morpher,Pitch Shifter,"
203 "Ring Modulator,Autowah,Compressor,Equalizer,";
206 if(alcIsExtensionPresent(device
, "ALC_EXT_EFX") == AL_FALSE
)
208 printf("EFX not available\n");
212 alcGetIntegerv(device
, ALC_EFX_MAJOR_VERSION
, 1, &major
);
213 alcGetIntegerv(device
, ALC_EFX_MINOR_VERSION
, 1, &minor
);
214 if(checkALCErrors(device
) == ALC_NO_ERROR
)
215 printf("EFX version: %d.%d\n", major
, minor
);
216 alcGetIntegerv(device
, ALC_MAX_AUXILIARY_SENDS
, 1, &sends
);
217 if(checkALCErrors(device
) == ALC_NO_ERROR
)
218 printf("Max auxiliary sends: %d\n", sends
);
220 palGenFilters
= alGetProcAddress("alGenFilters");
221 palDeleteFilters
= alGetProcAddress("alDeleteFilters");
222 palFilteri
= alGetProcAddress("alFilteri");
223 palGenEffects
= alGetProcAddress("alGenEffects");
224 palDeleteEffects
= alGetProcAddress("alDeleteEffects");
225 palEffecti
= alGetProcAddress("alEffecti");
226 if(checkALErrors() != AL_NO_ERROR
||
227 !palGenFilters
|| !palDeleteFilters
|| !palFilteri
||
228 !palGenEffects
|| !palDeleteEffects
|| !palEffecti
)
230 printf("!!! Missing EFX functions !!!\n");
234 palGenFilters(1, &obj
);
235 if(checkALErrors() == AL_NO_ERROR
)
237 current
= filterNames
;
238 for(i
= 0;filters
[i
] != AL_FILTER_NULL
;i
++)
240 char *next
= strchr(current
, ',');
242 palFilteri(obj
, AL_FILTER_TYPE
, filters
[i
]);
243 if(alGetError() == AL_NO_ERROR
)
246 memmove(current
, next
+1, strlen(next
));
248 palDeleteFilters(1, &obj
);
251 printf("Supported filters:");
252 printList(filterNames
, ',');
255 palGenEffects(1, &obj
);
256 if(checkALErrors() == AL_NO_ERROR
)
258 current
= effectNames
;
259 for(i
= 0;effects
[i
] != AL_EFFECT_NULL
;i
++)
261 char *next
= strchr(current
, ',');
263 palEffecti(obj
, AL_EFFECT_TYPE
, effects
[i
]);
264 if(alGetError() == AL_NO_ERROR
)
267 memmove(current
, next
+1, strlen(next
));
269 palDeleteEffects(1, &obj
);
272 printf("Supported effects:");
273 printList(effectNames
, ',');
277 int main(int argc
, char *argv
[])
282 if(argc
> 1 && (strcmp(argv
[1], "--help") == 0 ||
283 strcmp(argv
[1], "-h") == 0))
285 printf("Usage: %s [playback device]\n", argv
[0]);
289 printf("Available playback devices:\n");
290 if(alcIsExtensionPresent(NULL
, "ALC_ENUMERATE_ALL_EXT") != AL_FALSE
)
291 printDeviceList(alcGetString(NULL
, ALC_ALL_DEVICES_SPECIFIER
));
293 printDeviceList(alcGetString(NULL
, ALC_DEVICE_SPECIFIER
));
294 printf("Available capture devices:\n");
295 printDeviceList(alcGetString(NULL
, ALC_CAPTURE_DEVICE_SPECIFIER
));
297 printf("Default playback device: %s\n",
298 alcGetString(NULL
, ALC_DEFAULT_DEVICE_SPECIFIER
));
299 printf("Default capture device: %s\n",
300 alcGetString(NULL
, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
));
304 device
= alcOpenDevice((argc
>1) ? argv
[1] : NULL
);
307 printf("\n!!! Failed to open %s !!!\n\n", ((argc
>1) ? argv
[1] : "default device"));
311 printf("\n** Info for device \"%s\" **\n", alcGetString(device
, ALC_DEVICE_SPECIFIER
));
312 printALCInfo(device
);
314 context
= alcCreateContext(device
, NULL
);
315 if(!context
|| alcMakeContextCurrent(context
) == ALC_FALSE
)
318 alcDestroyContext(context
);
319 alcCloseDevice(device
);
320 printf("\n!!! Failed to set a context !!!\n\n");
325 printEFXInfo(device
);
327 alcMakeContextCurrent(NULL
);
328 alcDestroyContext(context
);
329 alcCloseDevice(device
);