2008-05-18 18:40:53 -07:00
|
|
|
/*
|
|
|
|
* openal-info: Display information about ALC and AL.
|
|
|
|
*
|
|
|
|
* Idea based on glxinfo for OpenGL.
|
|
|
|
* Initial OpenAL version by Erik Hofman <erik@ehofman.com>.
|
|
|
|
* Further hacked by Sven Panne <sven.panne@aedion.de>.
|
2008-05-18 18:44:17 -07:00
|
|
|
* More work (clean up) by Chris Robinson <chris.kcat@gmail.com>.
|
2008-05-18 18:40:53 -07:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#if HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
#include "AL/alc.h"
|
|
|
|
#include "AL/al.h"
|
|
|
|
#include "AL/alext.h"
|
|
|
|
|
2008-09-12 18:05:23 -07:00
|
|
|
#ifndef ALC_EXT_EFX
|
|
|
|
#define AL_FILTER_TYPE 0x8001
|
|
|
|
#define AL_EFFECT_TYPE 0x8001
|
|
|
|
#define AL_FILTER_NULL 0x0000
|
|
|
|
#define AL_FILTER_LOWPASS 0x0001
|
|
|
|
#define AL_FILTER_HIGHPASS 0x0002
|
|
|
|
#define AL_FILTER_BANDPASS 0x0003
|
|
|
|
#define AL_EFFECT_NULL 0x0000
|
|
|
|
#define AL_EFFECT_EAXREVERB 0x8000
|
|
|
|
#define AL_EFFECT_REVERB 0x0001
|
|
|
|
#define AL_EFFECT_CHORUS 0x0002
|
|
|
|
#define AL_EFFECT_DISTORTION 0x0003
|
|
|
|
#define AL_EFFECT_ECHO 0x0004
|
|
|
|
#define AL_EFFECT_FLANGER 0x0005
|
|
|
|
#define AL_EFFECT_FREQUENCY_SHIFTER 0x0006
|
|
|
|
#define AL_EFFECT_VOCAL_MORPHER 0x0007
|
|
|
|
#define AL_EFFECT_PITCH_SHIFTER 0x0008
|
|
|
|
#define AL_EFFECT_RING_MODULATOR 0x0009
|
|
|
|
#define AL_EFFECT_AUTOWAH 0x000A
|
|
|
|
#define AL_EFFECT_COMPRESSOR 0x000B
|
|
|
|
#define AL_EFFECT_EQUALIZER 0x000C
|
|
|
|
#define ALC_EFX_MAJOR_VERSION 0x20001
|
|
|
|
#define ALC_EFX_MINOR_VERSION 0x20002
|
|
|
|
#define ALC_MAX_AUXILIARY_SENDS 0x20003
|
|
|
|
#endif
|
|
|
|
ALvoid AL_APIENTRY (*p_alGenFilters)(ALsizei,ALuint*);
|
|
|
|
ALvoid AL_APIENTRY (*p_alDeleteFilters)(ALsizei,ALuint*);
|
|
|
|
ALvoid AL_APIENTRY (*p_alFilteri)(ALuint,ALenum,ALint);
|
|
|
|
ALvoid AL_APIENTRY (*p_alGenEffects)(ALsizei,ALuint*);
|
|
|
|
ALvoid AL_APIENTRY (*p_alDeleteEffects)(ALsizei,ALuint*);
|
|
|
|
ALvoid AL_APIENTRY (*p_alEffecti)(ALuint,ALenum,ALint);
|
2008-05-18 18:40:53 -07:00
|
|
|
|
|
|
|
static const int indentation = 4;
|
|
|
|
static const int maxmimumWidth = 79;
|
|
|
|
|
|
|
|
static void printChar(int c, int *width)
|
|
|
|
{
|
|
|
|
putchar(c);
|
|
|
|
*width = ((c == '\n') ? 0 : ((*width) + 1));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void indent(int *width)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for(i = 0; i < indentation; i++)
|
|
|
|
printChar(' ', width);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void printExtensions(const char *header, char separator, const char *extensions)
|
|
|
|
{
|
|
|
|
int width = 0, start = 0, end = 0;
|
|
|
|
|
|
|
|
printf("%s:\n", header);
|
|
|
|
if(extensions == NULL || extensions[0] == '\0')
|
|
|
|
return;
|
|
|
|
|
|
|
|
indent(&width);
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
if(extensions[end] == separator || extensions[end] == '\0')
|
|
|
|
{
|
|
|
|
if(width + end - start + 2 > maxmimumWidth)
|
|
|
|
{
|
|
|
|
printChar('\n', &width);
|
|
|
|
indent(&width);
|
|
|
|
}
|
|
|
|
while(start < end)
|
|
|
|
{
|
|
|
|
printChar(extensions[start], &width);
|
|
|
|
start++;
|
|
|
|
}
|
|
|
|
if(extensions[end] == '\0')
|
|
|
|
break;
|
|
|
|
start++;
|
|
|
|
end++;
|
|
|
|
if(extensions[end] == '\0')
|
|
|
|
break;
|
|
|
|
printChar(',', &width);
|
|
|
|
printChar(' ', &width);
|
|
|
|
}
|
|
|
|
end++;
|
|
|
|
}
|
|
|
|
printChar('\n', &width);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void die(const char *kind, const char *description)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "%s error %s occured\n", kind, description);
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void checkForErrors(void)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
ALCdevice *device = alcGetContextsDevice(alcGetCurrentContext());
|
|
|
|
ALCenum error = alcGetError(device);
|
|
|
|
if(error != ALC_NO_ERROR)
|
|
|
|
die("ALC", (const char*)alcGetString(device, error));
|
|
|
|
}
|
|
|
|
{
|
|
|
|
ALenum error = alGetError();
|
|
|
|
if(error != AL_NO_ERROR)
|
|
|
|
die("AL", (const char*)alGetString(error));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void printDevices(ALCenum which, const char *kind)
|
|
|
|
{
|
|
|
|
const char *s = alcGetString(NULL, which);
|
|
|
|
checkForErrors();
|
|
|
|
|
|
|
|
printf("Available %sdevices:\n", kind);
|
|
|
|
while(*s != '\0')
|
|
|
|
{
|
|
|
|
printf(" %s\n", s);
|
|
|
|
while(*s++ != '\0')
|
|
|
|
;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void printALCInfo (void)
|
|
|
|
{
|
|
|
|
ALCint major, minor;
|
|
|
|
ALCdevice *device;
|
|
|
|
|
|
|
|
if(alcIsExtensionPresent(NULL, (const ALCchar*)"ALC_ENUMERATION_EXT") == AL_TRUE)
|
|
|
|
{
|
|
|
|
if(alcIsExtensionPresent(NULL, (const ALCchar*)"ALC_ENUMERATE_ALL_EXT") == AL_TRUE)
|
|
|
|
printDevices(ALC_ALL_DEVICES_SPECIFIER, "playback ");
|
|
|
|
else
|
|
|
|
printDevices(ALC_DEVICE_SPECIFIER, "playback ");
|
|
|
|
printDevices(ALC_CAPTURE_DEVICE_SPECIFIER, "capture ");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
printf("No device enumeration available\n");
|
|
|
|
|
|
|
|
device = alcGetContextsDevice(alcGetCurrentContext());
|
|
|
|
checkForErrors();
|
|
|
|
|
|
|
|
printf("Default device: %s\n",
|
|
|
|
alcGetString(device, ALC_DEFAULT_DEVICE_SPECIFIER));
|
|
|
|
|
|
|
|
printf("Default capture device: %s\n",
|
|
|
|
alcGetString(device, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER));
|
|
|
|
|
|
|
|
alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &major);
|
|
|
|
alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &minor);
|
|
|
|
checkForErrors();
|
|
|
|
printf("ALC version: %d.%d\n", (int)major, (int)minor);
|
|
|
|
|
|
|
|
printExtensions("ALC extensions", ' ',
|
|
|
|
alcGetString(device, ALC_EXTENSIONS));
|
|
|
|
checkForErrors();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void printALInfo(void)
|
|
|
|
{
|
|
|
|
printf("OpenAL vendor string: %s\n", alGetString(AL_VENDOR));
|
|
|
|
printf("OpenAL renderer string: %s\n", alGetString(AL_RENDERER));
|
|
|
|
printf("OpenAL version string: %s\n", alGetString(AL_VERSION));
|
|
|
|
printExtensions("OpenAL extensions", ' ', alGetString(AL_EXTENSIONS));
|
|
|
|
checkForErrors();
|
|
|
|
}
|
|
|
|
|
2008-09-12 18:05:23 -07:00
|
|
|
static void printEFXInfo(void)
|
|
|
|
{
|
|
|
|
ALCint major, minor, sends;
|
|
|
|
ALCdevice *device;
|
|
|
|
ALuint obj;
|
|
|
|
int i;
|
|
|
|
const struct {
|
|
|
|
ALenum type;
|
|
|
|
const char *name;
|
|
|
|
} effects[] = {
|
|
|
|
{ AL_EFFECT_EAXREVERB, "EAX Reverb" },
|
|
|
|
{ AL_EFFECT_REVERB, "Standard Reverb" },
|
|
|
|
{ AL_EFFECT_CHORUS, "Chorus" },
|
|
|
|
{ AL_EFFECT_DISTORTION, "Distortion" },
|
|
|
|
{ AL_EFFECT_ECHO, "Echo" },
|
|
|
|
{ AL_EFFECT_FLANGER, "Flanger" },
|
|
|
|
{ AL_EFFECT_FREQUENCY_SHIFTER, "Frequency Shifter" },
|
|
|
|
{ AL_EFFECT_VOCAL_MORPHER, "Vocal Morpher" },
|
|
|
|
{ AL_EFFECT_PITCH_SHIFTER, "Pitch Shifter" },
|
|
|
|
{ AL_EFFECT_RING_MODULATOR, "Ring Modulator" },
|
|
|
|
{ AL_EFFECT_AUTOWAH, "Autowah" },
|
|
|
|
{ AL_EFFECT_COMPRESSOR, "Compressor" },
|
|
|
|
{ AL_EFFECT_EQUALIZER, "Equalizer" },
|
|
|
|
{ AL_EFFECT_NULL, NULL }
|
|
|
|
};
|
|
|
|
const struct {
|
|
|
|
ALenum type;
|
|
|
|
const char *name;
|
|
|
|
} filters[] = {
|
|
|
|
{ AL_FILTER_LOWPASS, "Low-pass" },
|
|
|
|
{ AL_FILTER_HIGHPASS, "High-pass" },
|
|
|
|
{ AL_FILTER_BANDPASS, "Band-pass" },
|
|
|
|
{ AL_FILTER_NULL, NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
device = alcGetContextsDevice(alcGetCurrentContext());
|
|
|
|
|
|
|
|
if(alcIsExtensionPresent(device, (const ALCchar*)"ALC_EXT_EFX") == AL_FALSE)
|
|
|
|
{
|
|
|
|
printf("EFX not available\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
alcGetIntegerv(device, ALC_EFX_MAJOR_VERSION, 1, &major);
|
|
|
|
alcGetIntegerv(device, ALC_EFX_MINOR_VERSION, 1, &minor);
|
|
|
|
checkForErrors();
|
|
|
|
printf("EFX version: %d.%d\n", (int)major, (int)minor);
|
|
|
|
|
|
|
|
alcGetIntegerv(device, ALC_MAX_AUXILIARY_SENDS, 1, &sends);
|
|
|
|
checkForErrors();
|
|
|
|
printf("Max auxiliary sends: %d\n", (int)sends);
|
|
|
|
|
|
|
|
p_alGenFilters = alGetProcAddress("alGenFilters");
|
|
|
|
p_alDeleteFilters = alGetProcAddress("alDeleteFilters");
|
|
|
|
p_alFilteri = alGetProcAddress("alFilteri");
|
|
|
|
p_alGenEffects = alGetProcAddress("alGenEffects");
|
|
|
|
p_alDeleteEffects = alGetProcAddress("alDeleteEffects");
|
|
|
|
p_alEffecti = alGetProcAddress("alEffecti");
|
|
|
|
checkForErrors();
|
|
|
|
if(!p_alGenEffects || !p_alDeleteEffects || !p_alEffecti ||
|
|
|
|
!p_alGenFilters || !p_alDeleteFilters || !p_alFilteri)
|
|
|
|
{
|
|
|
|
printf("Missing EFX functions!\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
p_alGenFilters(1, &obj);
|
|
|
|
checkForErrors();
|
|
|
|
printf("Available filters:\n");
|
|
|
|
for(i = 0;filters[i].type != AL_FILTER_NULL;i++)
|
|
|
|
{
|
|
|
|
p_alFilteri(obj, AL_FILTER_TYPE, filters[i].type);
|
|
|
|
if(alGetError() == AL_NO_ERROR)
|
|
|
|
printf(" %s\n", filters[i].name);
|
|
|
|
}
|
|
|
|
p_alDeleteFilters(1, &obj);
|
|
|
|
checkForErrors();
|
|
|
|
|
|
|
|
p_alGenEffects(1, &obj);
|
|
|
|
checkForErrors();
|
|
|
|
printf("Available effects:\n");
|
|
|
|
for(i = 0;effects[i].type != AL_EFFECT_NULL;i++)
|
|
|
|
{
|
|
|
|
p_alEffecti(obj, AL_EFFECT_TYPE, effects[i].type);
|
|
|
|
if(alGetError() == AL_NO_ERROR)
|
|
|
|
printf(" %s\n", effects[i].name);
|
|
|
|
}
|
|
|
|
p_alDeleteEffects(1, &obj);
|
|
|
|
checkForErrors();
|
|
|
|
}
|
|
|
|
|
2008-05-18 18:40:53 -07:00
|
|
|
int main()
|
|
|
|
{
|
|
|
|
ALCdevice *device = alcOpenDevice(NULL);
|
|
|
|
ALCcontext *context = alcCreateContext(device, NULL);
|
|
|
|
alcMakeContextCurrent(context);
|
|
|
|
checkForErrors();
|
|
|
|
|
|
|
|
printALCInfo();
|
|
|
|
printALInfo();
|
2008-09-12 18:05:23 -07:00
|
|
|
printEFXInfo();
|
2008-05-18 18:40:53 -07:00
|
|
|
checkForErrors();
|
|
|
|
|
|
|
|
alcMakeContextCurrent(NULL);
|
|
|
|
alcDestroyContext(context);
|
|
|
|
alcCloseDevice(device);
|
|
|
|
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
}
|