int main(int argc, char *argv[]) { if(alcIsExtensionPresent(NULL, "ALC_SOFT_loopback") == ALC_FALSE) { fputs("Your OpenAL implementation doesn't support the " "\"ALC_SOFT_loopback\" extension, required for this test. " "Sorry.\n", stderr); exit(EXIT_FAILURE); } ALCint alc_major, alc_minor; alcGetIntegerv(NULL, ALC_MAJOR_VERSION, 1, &alc_major); alcGetIntegerv(NULL, ALC_MINOR_VERSION, 1, &alc_minor); if(alc_major<1 || (alc_major==1 && alc_minor<1)) fputs("Warning : ALC_SOFT_loopback has been written against " "the OpenAL 1.1 specification.\n", stderr); #define HELPER(X) X = alcGetProcAddress(NULL, #X) HELPER(alcLoopbackOpenDeviceSOFT); HELPER(alcIsRenderFormatSupportedSOFT); HELPER(alcRenderSamplesSOFT); #undef HELPER #define HELPER(X) X = alcGetEnumValue(NULL, #X) HELPER(ALC_BYTE_SOFT); HELPER(ALC_UNSIGNED_BYTE_SOFT); HELPER(ALC_SHORT_SOFT); HELPER(ALC_UNSIGNED_SHORT_SOFT); HELPER(ALC_INT_SOFT); HELPER(ALC_UNSIGNED_INT_SOFT); HELPER(ALC_FLOAT_SOFT); HELPER(ALC_MONO_SOFT); HELPER(ALC_STEREO_SOFT); HELPER(ALC_QUAD_SOFT); HELPER(ALC_5POINT1_SOFT); HELPER(ALC_6POINT1_SOFT); HELPER(ALC_7POINT1_SOFT); HELPER(ALC_FORMAT_CHANNELS_SOFT); HELPER(ALC_FORMAT_TYPE_SOFT); #undef HELPER ALCdevice *loopback_device = alcLoopbackOpenDeviceSOFT(NULL); if(!loopback_device) { fputs("Could not open loopback device.\n", stderr); exit(EXIT_FAILURE); } if(alcIsRenderFormatSupportedSOFT(loopback_device, 22050, ALC_STEREO_SOFT, ALC_SHORT_SOFT) == ALC_FALSE) { fputs("The loopback device does not support the " "required render format.\n", stderr); alcCloseDevice(loopback_device); exit(EXIT_FAILURE); } ALCint attrlist[11] = { ALC_MONO_SOURCES, 0, ALC_STEREO_SOURCES, 255, ALC_FREQUENCY, 22050, ALC_FORMAT_CHANNELS_SOFT, ALC_STEREO_SOFT, ALC_FORMAT_TYPE_SOFT, ALC_SHORT_SOFT, 0 }; ALCcontext *ctx = alcCreateContext(loopback_device, attrlist); alcMakeContextCurrent(ctx); alGetError(); /* Clear the error state */ if(argc<=1) { fprintf(stderr, "Usage : %s <small_oggfile>\n", argv[0]); alcCloseDevice(loopback_device); exit(EXIT_FAILURE); } SF_INFO sndinfo; SNDFILE *snd = sf_open(argv[1], SFM_READ, &sndinfo); if(!snd) { fprintf(stderr, "Failed to open \"%s\" : %s\n", argv[1], sf_strerror(snd)); alcCloseDevice(loopback_device); exit(EXIT_FAILURE); } if(sndinfo.channels != 2) { fprintf(stderr, "The source sound file has %d channels " "(exactly 2 are required).\n", sndinfo.channels); alcCloseDevice(loopback_device); exit(EXIT_FAILURE); } short *data = malloc(sndinfo.frames*2*sizeof(short)); printf("Reading from '%s'...\n", argv[1]); sf_readf_short(snd, data, sndinfo.frames); sf_close(snd); ALuint audio_buffer; alGenBuffers(1, &audio_buffer); alBufferData(audio_buffer, AL_FORMAT_STEREO16, data, sndinfo.frames*2*sizeof(short), sndinfo.samplerate); free(data); ALuint audio_source; alGenSources(1, &audio_source); alSourcei(audio_source, AL_BUFFER, audio_buffer); unsigned num_frames = sndinfo.frames; ALCshort *rendered_samples = malloc(num_frames*2*sizeof(ALCshort)); sndinfo.samplerate = 22050; sndinfo.channels = 2; sndinfo.format = SF_FORMAT_OGG | SF_FORMAT_VORBIS | SF_ENDIAN_FILE; snd = sf_open("rendered.ogg", SFM_WRITE, &sndinfo); alSourcePlay(audio_source); puts("Rendering frames..."); unsigned chunk_size = 4096, off; for(off=0 ; off<(num_frames-chunk_size)*2 ; off+=2*chunk_size) alcRenderSamplesSOFT(loopback_device, rendered_samples+off, chunk_size); puts("Writing to 'rendered.ogg'..."); sf_write_short(snd, rendered_samples, off-s); sf_close(snd); free(rendered_samples); alDeleteSources(1, &audio_source); alDeleteBuffers(1, &audio_buffer); alcCloseDevice(loopback_device); alcMakeContextCurrent(NULL); alcDestroyContext(ctx); exit(EXIT_SUCCESS); }
bool cOAL_Device::Init( cOAL_Init_Params& acParams ) { DEF_FUNC_NAME(cOAL_Device::Init); FUNC_USES_ALC; FUNC_USES_AL; LogMsg("",eOAL_LogVerbose_Low, eOAL_LogMsg_Command, "Initializing device: %s...\n", (acParams.msDeviceName == "")? "\"preferred\"":acParams.msDeviceName.c_str() ); LogMsg("",eOAL_LogVerbose_High, eOAL_LogMsg_Info, "Configuring streaming options:\n"); cOAL_Stream::SetBufferSize(acParams.mlStreamingBufferSize); LogMsg("",eOAL_LogVerbose_High, eOAL_LogMsg_Info, "\tSetting buffer size to %d bytes\n",cOAL_Stream::GetBufferSize()); cOAL_Stream::SetBufferCount(acParams.mlStreamingBufferCount); LogMsg("",eOAL_LogVerbose_High, eOAL_LogMsg_Info, "\tSetting queue length to %d buffers\n",cOAL_Stream::GetBufferCount()); LogMsg("",eOAL_LogVerbose_Low, eOAL_LogMsg_Info, "Attempting to open device...\n" ); // Open the device, if fails return false if(acParams.msDeviceName.empty()) mpDevice = alcOpenDevice(NULL); else mpDevice = alcOpenDevice( acParams.msDeviceName.c_str() ); if(mpDevice == NULL) { LogMsg("",eOAL_LogVerbose_Low, eOAL_LogMsg_Error, "Error opening device\n" ); return false; } LogMsg("",eOAL_LogVerbose_Low, eOAL_LogMsg_Info, "Success.\n" ); // Get ALC extensions ( ie EFX ) LogMsg("",eOAL_LogVerbose_Low, eOAL_LogMsg_Info, "Checking present ALC extensions\n" ); for (int i = 0; i < NUM_ALC_EXTENSIONS; ++i) { mvbExtensions[i] = RUN_ALC_FUNC((alcIsExtensionPresent(mpDevice,sExtensionNames[i].c_str()) == ALC_TRUE)); if (mvbExtensions[i]) { LogMsg("",eOAL_LogVerbose_High, eOAL_LogMsg_Info, "\t%s\n",sExtensionNames[i].c_str() ); } } ALCint lAttrList[] = { ALC_FREQUENCY, acParams.mlOutputFreq, #ifdef __APPLE__ #else ALC_MONO_SOURCES, acParams.mbVoiceManagement ? 256 : acParams.mlMinMonoSourcesHint, ALC_STEREO_SOURCES, acParams.mbVoiceManagement ? 0 : acParams.mlMinStereoSourcesHint, #endif ALC_MAX_AUXILIARY_SENDS, acParams.mlNumSendsHint, 0, }; LogMsg("",eOAL_LogVerbose_Low, eOAL_LogMsg_Info, "Creating context\n"); // Create and set a context mpContext = RUN_ALC_FUNC(alcCreateContext ( mpDevice, lAttrList )); RUN_ALC_FUNC(alcMakeContextCurrent ( mpContext )); if (ALC_ERROR_OCCURED) { LogMsg("",eOAL_LogVerbose_Low, eOAL_LogMsg_Error, "Error creating context\n"); return false; } ///////////////////////////////////////////////// //Retrieve device info, such as extensions LogMsg("",eOAL_LogVerbose_Low, eOAL_LogMsg_Info, "Checking present AL extensions\n" ); for (int i = NUM_ALC_EXTENSIONS; i < NUM_EXTENSIONS; ++i) { mvbExtensions[i] = RUN_AL_FUNC((alIsExtensionPresent(sExtensionNames[i].c_str()) == AL_TRUE)); if (mvbExtensions[i]) LogMsg("",eOAL_LogVerbose_High, eOAL_LogMsg_Info, "\t%s\n",sExtensionNames[i].c_str() ); } LogMsg("",eOAL_LogVerbose_Low, eOAL_LogMsg_Info, "Retrieving Output Devices\n"); vector<string> llDevices = GetOutputDevices(); vector<string>::iterator it; for (it = llDevices.begin(); it != llDevices.end(); ++it) { LogMsg("",eOAL_LogVerbose_Low, eOAL_LogMsg_Info, "\t%s\n", (*it).c_str()); } LogMsg("",eOAL_LogVerbose_Low, eOAL_LogMsg_Info, "Retrieving info\n" ); // Get device name msDeviceName = RUN_ALC_FUNC(alcGetString(mpDevice, ALC_DEVICE_SPECIFIER)); // Get vendor name (just fancy stuff,not very useful) msVendorName = RUN_ALC_FUNC(alGetString( AL_VENDOR )); //Get renderer info msRenderer = RUN_ALC_FUNC(alGetString ( AL_RENDERER )); // Get the OpenAL impl. version RUN_ALC_FUNC(alcGetIntegerv ( mpDevice, ALC_MAJOR_VERSION, sizeof(ALCint), &mlMajorVersion )); RUN_ALC_FUNC(alcGetIntegerv ( mpDevice, ALC_MINOR_VERSION, sizeof(ALCint), &mlMinorVersion )); RUN_ALC_FUNC(alcGetIntegerv ( mpDevice, ALC_MAX_AUXILIARY_SENDS, sizeof(ALCint), &mlEFXSends)); LogMsg("",eOAL_LogVerbose_High, eOAL_LogMsg_Info, "Device name: %s\n", msDeviceName.c_str() ); LogMsg("",eOAL_LogVerbose_High, eOAL_LogMsg_Info, "OpenAL version: %d.%d\n", mlMajorVersion, mlMinorVersion ); // Check device version if ( (mlMajorVersion < acParams.mlMajorVersionReq) || ((mlMajorVersion == acParams.mlMajorVersionReq) && (mlMinorVersion < acParams.mlMinorVersionReq)) ) { LogMsg("",eOAL_LogVerbose_None, eOAL_LogMsg_Error, "Version required: %d.%d\n",acParams.mlMajorVersionReq,acParams.mlMinorVersionReq); return false; } // If alSourceNumHint == -1, create as many sources as possible if (acParams.mlNumSourcesHint == -1) acParams.mlNumSourcesHint = 4096; ///////////////////////////////////////////////// //Start EFX if requested if (acParams.mbUseEFX && IsExtensionAvailable (OAL_ALC_EXT_EFX)) { LogMsg("",eOAL_LogVerbose_Low, eOAL_LogMsg_Info, "Starting EFX on request\n" ); mpEFXManager = new cOAL_EFXManager; mbEFXActive = mpEFXManager->Initialize( acParams.mlNumSlotsHint, mlEFXSends, acParams.mbUseThread, acParams.mlSlotUpdateFreq ); if (!mbEFXActive) { mpEFXManager->Destroy(); delete mpEFXManager; } } LogMsg("",eOAL_LogVerbose_Low, eOAL_LogMsg_Info, "Creating Source Manager\n" ); //Create The source manager mpSourceManager = new cOAL_SourceManager; if ( mpSourceManager->Initialize( acParams.mbVoiceManagement, acParams.mlNumSourcesHint, acParams.mbUseThread, acParams.mlUpdateFreq, mlEFXSends ) == false) { LogMsg("",eOAL_LogVerbose_None, eOAL_LogMsg_Error, "Error creating Source Manager\n"); return false; } return true; }
static void printEFXInfo(ALCdevice *device) { ALCint major, minor, sends; static const ALchar filters[][32] = { "AL_FILTER_LOWPASS", "AL_FILTER_HIGHPASS", "AL_FILTER_BANDPASS", "" }; char filterNames[] = "Low-pass,High-pass,Band-pass,"; static const ALchar effects[][32] = { "AL_EFFECT_EAXREVERB", "AL_EFFECT_REVERB", "AL_EFFECT_CHORUS", "AL_EFFECT_DISTORTION", "AL_EFFECT_ECHO", "AL_EFFECT_FLANGER", "AL_EFFECT_FREQUENCY_SHIFTER", "AL_EFFECT_VOCAL_MORPHER", "AL_EFFECT_PITCH_SHIFTER", "AL_EFFECT_RING_MODULATOR", "AL_EFFECT_AUTOWAH", "AL_EFFECT_COMPRESSOR", "AL_EFFECT_EQUALIZER", "" }; static const ALchar dedeffects[][64] = { "AL_EFFECT_DEDICATED_DIALOGUE", "AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT", "" }; char effectNames[] = "EAX Reverb,Reverb,Chorus,Distortion,Echo,Flanger," "Frequency Shifter,Vocal Morpher,Pitch Shifter," "Ring Modulator,Autowah,Compressor,Equalizer," "Dedicated Dialog,Dedicated LFE,"; char *current; int i; if(alcIsExtensionPresent(device, "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); if(checkALCErrors(device) == ALC_NO_ERROR) printf("EFX version: %d.%d\n", major, minor); alcGetIntegerv(device, ALC_MAX_AUXILIARY_SENDS, 1, &sends); if(checkALCErrors(device) == ALC_NO_ERROR) printf("Max auxiliary sends: %d\n", sends); current = filterNames; for(i = 0;filters[i][0];i++) { char *next = strchr(current, ','); ALenum val; val = alGetEnumValue(filters[i]); if(alGetError() != AL_NO_ERROR || val == 0 || val == -1) memmove(current, next+1, strlen(next)); else current = next+1; } printf("Supported filters:"); printList(filterNames, ','); current = effectNames; for(i = 0;effects[i][0];i++) { char *next = strchr(current, ','); ALenum val; val = alGetEnumValue(effects[i]); if(alGetError() != AL_NO_ERROR || val == 0 || val == -1) memmove(current, next+1, strlen(next)); else current = next+1; } if(alcIsExtensionPresent(device, "ALC_EXT_DEDICATED")) { for(i = 0;dedeffects[i][0];i++) { char *next = strchr(current, ','); ALenum val; val = alGetEnumValue(dedeffects[i]); if(alGetError() != AL_NO_ERROR || val == 0 || val == -1) memmove(current, next+1, strlen(next)); else current = next+1; } } else { for(i = 0;dedeffects[i][0];i++) { char *next = strchr(current, ','); memmove(current, next+1, strlen(next)); } } printf("Supported effects:"); printList(effectNames, ','); }
void plVoiceRecorder::Update(double time) { if(!fRecording) return; int EncoderFrameSize = plSpeex::GetInstance()->GetFrameSize(); if(EncoderFrameSize == -1) return; ALCdevice *captureDevice = plgAudioSys::GetCaptureDevice(); if(!captureDevice) return; unsigned minSamples = EncoderFrameSize * 10; ALCint samples; alcGetIntegerv(captureDevice, ALC_CAPTURE_SAMPLES, sizeof(samples), &samples ); if (samples > 0) { if (samples >= minSamples) { int numFrames = (int)(samples / EncoderFrameSize); // the number of frames that have been captured int totalSamples = numFrames * EncoderFrameSize; // cap uncompressed data if(totalSamples > MAX_DATA_SIZE) totalSamples = MAX_DATA_SIZE; // convert to correct units: short *buffer = new short[totalSamples]; alcCaptureSamples(captureDevice, buffer, totalSamples); if (!CompressionEnabled()) { plNetMsgVoice pMsg; pMsg.SetNetProtocol(kNetProtocolCli2Game); pMsg.SetVoiceData((char *)buffer, totalSamples * sizeof(short)); // set frame size here; pMsg.SetPlayerID(plNetClientApp::GetInstance()->GetPlayerID()); //if (false) //plNetClientApp::GetInstance()->GetFlagsBit(plNetClientApp::kEchoVoice)) // pMsg.SetBit(plNetMessage::kEchoBackToSender); plNetClientApp::GetInstance()->SendMsg(&pMsg); } else // use the speex voice compression lib { uint8_t *packet = new uint8_t[totalSamples]; // packet to send encoded data in int packedLength = 0; // the size of the packet that will be sent hsRAMStream ram; // ram stream to hold output data from speex uint8_t numFrames = totalSamples / EncoderFrameSize; // number of frames to be encoded // encode the data using speex plSpeex::GetInstance()->Encode(buffer, numFrames, &packedLength, &ram); if (packedLength) { // extract data from ram stream into packet ram.Rewind(); ram.Read(packedLength, packet); plNetMsgVoice pMsg; pMsg.SetNetProtocol(kNetProtocolCli2Game); pMsg.SetVoiceData((char *)packet, packedLength); pMsg.SetPlayerID(plNetClientApp::GetInstance()->GetPlayerID()); pMsg.SetFlag(VOICE_ENCODED); // Set encoded flag pMsg.SetNumFrames(numFrames); if (plNetClientApp::GetInstance()->GetFlagsBit(plNetClientApp::kEchoVoice)) pMsg.SetBit(plNetMessage::kEchoBackToSender); plNetClientApp::GetInstance()->SendMsg(&pMsg); } delete[] packet; } delete[] buffer; } else if(!fMikeOpen) { short *buffer = new short[samples]; // the mike has since closed, and there isn't enough data to meet our minimum, so throw this data out alcCaptureSamples(captureDevice, buffer, samples); delete[] buffer; } } }
bool COALExtProvider::Create(ALCdevice* device, ALCcontext*& context) { ALint attribs[4] = { 0 }; bool efx = false; //Try to load effect extension if(ExtPresent(device, ALC_EXT_EFX_NAME)) { attribs[0] = ALC_MAX_AUXILIARY_SENDS; attribs[1] = 4; context = alcCreateContext(device, attribs); efx = true; CON(MSG_INFO, _W(" Device supports Effect Extension")); } else { CON(MSG_INFO, _W(" Device doesn't support Effect Extension")); context = alcCreateContext(device, NULL); } if(context == NULL) return false; alcMakeContextCurrent(context); alcGetIntegerv(device, ALC_MAX_AUXILIARY_SENDS, 1, &m_maxAux); CON(MSG_INFO, _W(" Device supports %d Aux Sends per Source"), m_maxAux); if(efx) { alGenEffects = (LPALGENEFFECTS)alGetProcAddress("alGenEffects"); alDeleteEffects = (LPALDELETEEFFECTS )alGetProcAddress("alDeleteEffects"); alIsEffect = (LPALISEFFECT )alGetProcAddress("alIsEffect"); alEffecti = (LPALEFFECTI)alGetProcAddress("alEffecti"); alEffectiv = (LPALEFFECTIV)alGetProcAddress("alEffectiv"); alEffectf = (LPALEFFECTF)alGetProcAddress("alEffectf"); alEffectfv = (LPALEFFECTFV)alGetProcAddress("alEffectfv"); alGetEffecti = (LPALGETEFFECTI)alGetProcAddress("alGetEffecti"); alGetEffectiv = (LPALGETEFFECTIV)alGetProcAddress("alGetEffectiv"); alGetEffectf = (LPALGETEFFECTF)alGetProcAddress("alGetEffectf"); alGetEffectfv = (LPALGETEFFECTFV)alGetProcAddress("alGetEffectfv"); alGenFilters = (LPALGENFILTERS)alGetProcAddress("alGenFilters"); alDeleteFilters = (LPALDELETEFILTERS)alGetProcAddress("alDeleteFilters"); alIsFilter = (LPALISFILTER)alGetProcAddress("alIsFilter"); alFilteri = (LPALFILTERI)alGetProcAddress("alFilteri"); alFilteriv = (LPALFILTERIV)alGetProcAddress("alFilteriv"); alFilterf = (LPALFILTERF)alGetProcAddress("alFilterf"); alFilterfv = (LPALFILTERFV)alGetProcAddress("alFilterfv"); alGetFilteri = (LPALGETFILTERI )alGetProcAddress("alGetFilteri"); alGetFilteriv= (LPALGETFILTERIV )alGetProcAddress("alGetFilteriv"); alGetFilterf = (LPALGETFILTERF )alGetProcAddress("alGetFilterf"); alGetFilterfv= (LPALGETFILTERFV )alGetProcAddress("alGetFilterfv"); alGenAuxiliaryEffectSlots = (LPALGENAUXILIARYEFFECTSLOTS)alGetProcAddress("alGenAuxiliaryEffectSlots"); alDeleteAuxiliaryEffectSlots = (LPALDELETEAUXILIARYEFFECTSLOTS)alGetProcAddress("alDeleteAuxiliaryEffectSlots"); alIsAuxiliaryEffectSlot = (LPALISAUXILIARYEFFECTSLOT)alGetProcAddress("alIsAuxiliaryEffectSlot"); alAuxiliaryEffectSloti = (LPALAUXILIARYEFFECTSLOTI)alGetProcAddress("alAuxiliaryEffectSloti"); alAuxiliaryEffectSlotiv = (LPALAUXILIARYEFFECTSLOTIV)alGetProcAddress("alAuxiliaryEffectSlotiv"); alAuxiliaryEffectSlotf = (LPALAUXILIARYEFFECTSLOTF)alGetProcAddress("alAuxiliaryEffectSlotf"); alAuxiliaryEffectSlotfv = (LPALAUXILIARYEFFECTSLOTFV)alGetProcAddress("alAuxiliaryEffectSlotfv"); alGetAuxiliaryEffectSloti = (LPALGETAUXILIARYEFFECTSLOTI)alGetProcAddress("alGetAuxiliaryEffectSloti"); alGetAuxiliaryEffectSlotiv = (LPALGETAUXILIARYEFFECTSLOTIV)alGetProcAddress("alGetAuxiliaryEffectSlotiv"); alGetAuxiliaryEffectSlotf = (LPALGETAUXILIARYEFFECTSLOTF)alGetProcAddress("alGetAuxiliaryEffectSlotf"); alGetAuxiliaryEffectSlotfv = (LPALGETAUXILIARYEFFECTSLOTFV)alGetProcAddress("alGetAuxiliaryEffectSlotfv"); if(!(alGenEffects && alDeleteEffects && alIsEffect && alEffecti && alEffectiv && alEffectf && alEffectfv && alGetEffecti && alGetEffectiv && alGetEffectf && alGetEffectfv && alGenFilters && alDeleteFilters && alIsFilter && alFilteri && alFilteriv && alFilterf && alFilterfv && alGetFilteri && alGetFilteriv && alGetFilterf && alGetFilterfv && alGenAuxiliaryEffectSlots && alDeleteAuxiliaryEffectSlots && alIsAuxiliaryEffectSlot && alAuxiliaryEffectSloti && alAuxiliaryEffectSlotiv && alAuxiliaryEffectSlotf && alAuxiliaryEffectSlotfv && alGetAuxiliaryEffectSloti && alGetAuxiliaryEffectSlotiv && alGetAuxiliaryEffectSlotf && alGetAuxiliaryEffectSlotfv)) { CON(MSG_INFO, _W(" Can't load EFX functions!")); efx = false; } } m_initialized = efx; return efx; }
void Audio::init() { #ifdef WIN32 EFXEAXREVERBPROPERTIES efxReverb; int attrib[] = {ALC_MAX_AUXILIARY_SENDS, 4}; int sends; ALenum al_err; #endif debugf("Using default audio device: %s\n", alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER)); device = alcOpenDevice(NULL); if (device == NULL) { debugf("No sound device/driver has been found.\n"); return; } #ifdef WIN32 context = alcCreateContext(device, attrib); #else context = alcCreateContext(device, NULL); #endif if (context == NULL) { debugf("alcCreateContext failed.\n"); } if ( alcMakeContextCurrent(context) == ALC_FALSE ) { ALCenum error = alcGetError(device); switch (error) { case ALC_NO_ERROR: debugf("alcMakeContextCurrent failed: No error.\n"); break; case ALC_INVALID_DEVICE: debugf("alcMakeContextCurrent failed: Invalid device.\n"); break; case ALC_INVALID_CONTEXT: debugf("alcMakeContextCurrent failed: Invalid context.\n"); break; case ALC_INVALID_ENUM: debugf("alcMakeContextCurrent failed: Invalid enum.\n"); break; case ALC_INVALID_VALUE: debugf("alcMakeContextCurrent failed: Invalid value.\n"); break; case ALC_OUT_OF_MEMORY: debugf("alcMakeContextCurrent failed: Out of memory.\n"); break; } return; } #ifdef WIN32 alcGetIntegerv(device, ALC_MAX_AUXILIARY_SENDS, 1, &sends); debugf("%d sends per audio source\n", sends); #endif alListenerf(AL_REFERENCE_DISTANCE, 100.0f); //gain = (distance / AL_REFERENCE_DISTANCE) ^ (-AL_ROLLOFF_FACTOR alDistanceModel(AL_EXPONENT_DISTANCE); alListenerf(AL_ROLLOFF_FACTOR, 0.000001f); // alListenerf(AL_MAX_DISTANCE, 10000.0f); alDopplerFactor(1.0f); // alDopplerVelocity(8.0f); // alSpeedOfSound(343.3f * UNITS_TO_METERS); #ifdef WIN32 alListenerf(AL_METERS_PER_UNIT, 0.3f); ALFWIsEFXSupported(); alGenAuxiliaryEffectSlots(1, &slot); al_err = alGetError(); if (al_err != AL_NO_ERROR) { debugf("Unable to generate slot: %s\n", GetALErrorString(al_err)); return; } alGenEffects(1, &effect); al_err = alGetError(); if (al_err != AL_NO_ERROR) { debugf("Unable to generate effect: %s\n", GetALErrorString(al_err)); return; } alEffecti(effect, AL_EFFECT_TYPE, AL_EFFECT_EAXREVERB); al_err = alGetError(); if (al_err != AL_NO_ERROR) { debugf("Unable to set effect: %s\n", GetALErrorString(al_err)); return; } ConvertReverbParameters(&eaxBathroom, &efxReverb); SetEFXEAXReverbProperties(&efxReverb, effect); // alEffectf(effect, AL_REVERB_GAIN, 1.0f); // alEffectf(effect, AL_REVERB_DECAY_TIME, 20.0f); // alEffectf(effect, AL_REVERB_DENSITY, 0.25f); alGenFilters(1, &filter); al_err = alGetError(); if (al_err != AL_NO_ERROR) { debugf("Unable to generate filter: %s\n", GetALErrorString(al_err)); return; } alFilteri(filter, AL_FILTER_TYPE, AL_FILTER_LOWPASS); alFilterf(filter, AL_LOWPASS_GAIN, 0.5f); alFilterf(filter, AL_LOWPASS_GAINHF, 0.5f); #endif }
/* * iComponent interface */ bool csSndSysRendererOpenAL::Initialize (iObjectRegistry *obj_reg) { if (!libopenal_is_present) { Report (CS_REPORTER_SEVERITY_WARNING, "OpenAL is not available (libopenal is missing)"); return false; } // Save the object registry for later use m_ObjectRegistry = obj_reg; Report (CS_REPORTER_SEVERITY_DEBUG, "Initializing OpenAL sound system"); // Read the config file m_Config.AddConfig (obj_reg, "/config/sound.cfg"); // Get a list of OpenAL devices: // The spec says it's an ALCchar, but my headers include no such type. // The format is a series of strings separatrd by nulls, teminated by a // double null. Report (CS_REPORTER_SEVERITY_DEBUG, "Retrieving available devices."); const ALCchar *devices = alcGetString (0, ALC_DEVICE_SPECIFIER); // Loop while there is no second null while (*devices != 0) { Report (CS_REPORTER_SEVERITY_DEBUG, "Available OpenAL device: %s", devices); // Seek until the null while (*devices != 0) devices++; // Skip the null devices++; } // Report the default device. Report (CS_REPORTER_SEVERITY_DEBUG, "Default OpenAL device: %s", alcGetString (0, ALC_DEFAULT_DEVICE_SPECIFIER)); // Check if a specific device is specified const ALCchar *device = m_Config->GetStr ("SndSys.OpenALDevice", 0); if (device == 0) { // The config did not contain a device to use Report (CS_REPORTER_SEVERITY_DEBUG, "No device specified"); } else { // Attempt to open the spcified device m_Device = alcOpenDevice (device); if (m_Device == 0) { // Failed to open the device Report (CS_REPORTER_SEVERITY_WARNING, "Unable to open device %s", device); } } // If we still don't have a device, try the default: if (m_Device == 0) { Report (CS_REPORTER_SEVERITY_DEBUG, "Falling back on default device"); m_Device = alcOpenDevice (0); if (m_Device == 0) { // Even that failed, give up. Report (CS_REPORTER_SEVERITY_ERROR, "Unable to open device"); return false; } } // Check some OpenAL context attributes/capabilities // http://opensource.creative.com/pipermail/openal/2006-February/009337.html ALCenum err; ALCint attrSize = 0; ALCint *attributes; ALCint *data; alcGetIntegerv(m_Device, ALC_ATTRIBUTES_SIZE, sizeof(ALCint), &attrSize); err = alcGetError (m_Device); if (err == ALC_NO_ERROR) { attributes = (ALCint *)cs_malloc(attrSize * sizeof(ALCint)); alcGetIntegerv(m_Device, ALC_ALL_ATTRIBUTES, attrSize, attributes); err = alcGetError (m_Device); if (err == ALC_NO_ERROR) { data = attributes; while (data < attributes + attrSize) { switch (*data) { case ALC_FREQUENCY: data += 1; Report (CS_REPORTER_SEVERITY_DEBUG, "OpenAL context frequency: %d Hz", *data); break; case ALC_REFRESH: data += 1; Report (CS_REPORTER_SEVERITY_DEBUG, "OpenAL context refresh: %d Hz", *data); break; case ALC_SYNC: data += 1; Report (CS_REPORTER_SEVERITY_DEBUG, "OpenAL context uses %s (%sthreaded) context", *data ? "synchronous": "asynchronous", *data ? "non " : ""); break; case ALC_MONO_SOURCES: data += 1; Report (CS_REPORTER_SEVERITY_DEBUG, "OpenAL context should support %d mono sources", *data); break; case ALC_STEREO_SOURCES: data += 1; Report (CS_REPORTER_SEVERITY_DEBUG, "OpenAL context should support %d stereo sources", *data); break; default: break; } data += 1; } } else Report (CS_REPORTER_SEVERITY_DEBUG, "Can't retrieve attributes: OpenAL error %s", ALCErrors.StringForIdent (err)); cs_free(attributes); } else Report (CS_REPORTER_SEVERITY_DEBUG, "Can't retrieve attributes size: OpenAL error %s", ALCErrors.StringForIdent (err)); // Configure sound sources SndSysSourceOpenAL2D::Configure( m_Config ); // Register for event callbacks. csRef<iEventQueue> q (csQueryRegistry<iEventQueue> (m_ObjectRegistry)); evSystemOpen = csevSystemOpen(m_ObjectRegistry); evSystemClose = csevSystemClose(m_ObjectRegistry); evFrame = csevFrame(m_ObjectRegistry); if (q != 0) { csEventID subEvents[] = { evSystemOpen, evSystemClose, evFrame, CS_EVENTLIST_END }; q->RegisterListener(this, subEvents); } return true; }
int main(int argc, char *argv[]) { ALCcontext *default_context = 0, *custom_context = 0; ALCdevice *dev; int attrlist[] = { ALC_FREQUENCY, 44100, ALC_SYNC, AL_TRUE, 0 }; dev = alcOpenDevice( (const ALubyte *) "'((sampling-rate 44100))" ); if( dev == NULL ) { return 1; } /* Initialize ALUT. */ default_context = alcCreateContext(dev, NULL); if(default_context == NULL) { alcCloseDevice( dev ); return 1; } free(malloc(4)); alcMakeContextCurrent(default_context); { ALint NumFlags = 0; ALint *Flags = 0; int i; printf("default context\n"); alcGetIntegerv(dev, ALC_ATTRIBUTES_SIZE, sizeof NumFlags, &NumFlags ); printf("NumFlags %d\n", NumFlags); if(NumFlags) { Flags = malloc(sizeof NumFlags * sizeof *Flags); assert(Flags); alcGetIntegerv(dev, ALC_ALL_ATTRIBUTES, sizeof NumFlags * sizeof *Flags, Flags ); } for(i = 0; i < NumFlags-1; i += 2) { printf("key 0x%x : value %d\n", Flags[i], Flags[i+1]); } /* must be 0 terminated */ assert(Flags[NumFlags-1] == 0); } custom_context = alcCreateContext(dev, attrlist); if(custom_context == NULL) { alcCloseDevice( dev ); return 1; } alcMakeContextCurrent(custom_context); { ALint NumFlags = 0; ALint *Flags = 0; int i; printf("custom context\n"); alcGetIntegerv(dev, ALC_ATTRIBUTES_SIZE, sizeof NumFlags, &NumFlags ); printf("NumFlags %d\n", NumFlags); if(NumFlags) { Flags = malloc(sizeof NumFlags * sizeof *Flags); assert(Flags); alcGetIntegerv(dev, ALC_ALL_ATTRIBUTES, sizeof NumFlags * sizeof *Flags, Flags ); } for(i = 0; i < NumFlags-1; i += 2) { printf("key 0x%x : value %d\n", Flags[i], Flags[i+1]); } /* must be 0 terminated */ assert(Flags[NumFlags-1] == 0); } fixup_function_pointers(); alcDestroyContext(default_context); alcDestroyContext(custom_context); return 0; }
bool AudioEngine::SingletonInitialize() { if (AUDIO_ENABLE == false) return true; const ALCchar* best_device = 0; // Will store the name of the 'best' device for audio playback ALCint highest_version = 0; // The highest version number found CheckALError(); // Clears errors CheckALCError(); // Clears errors // Find the highest-version device available, if the extension for device enumeration is present if (alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT") == AL_TRUE) { const ALCchar* device_list = 0; device_list = alcGetString(0, ALC_DEVICE_SPECIFIER); // Get list of all devices (terminated with two '0') if (CheckALCError() == true) { IF_PRINT_WARNING(AUDIO_DEBUG) << "failed to retrieve the list of available audio devices: " << CreateALCErrorString() << endl; } while (*device_list != 0) { // Check all the detected devices ALCint major_v = 0, minor_v = 0; // Open a temporary device for reading in its version number ALCdevice* temp_device = alcOpenDevice(device_list); if (CheckALCError() || temp_device == NULL) { // If we couldn't open the device, just move on to the next IF_PRINT_WARNING(AUDIO_DEBUG) << "couldn't open device for version checking: " << device_list << endl; device_list += strlen(device_list) + 1; continue; } // Create a temporary context for the device ALCcontext *temp_context = alcCreateContext(temp_device, 0); if (CheckALCError() || temp_context == NULL) { // If we couldn't create the context, move on to the next device IF_PRINT_WARNING(AUDIO_DEBUG) << "couldn't create a temporary context for device: " << device_list << endl; alcCloseDevice(temp_device); device_list += strlen(device_list) + 1; continue; } // Retrieve the version number for the device alcMakeContextCurrent(temp_context); alcGetIntegerv(temp_device, ALC_MAJOR_VERSION, sizeof(ALCint), &major_v); alcGetIntegerv(temp_device, ALC_MINOR_VERSION, sizeof(ALCint), &minor_v); alcMakeContextCurrent(0); // Disable the temporary context alcDestroyContext(temp_context); // Destroy the temporary context alcCloseDevice(temp_device); // Close the temporary device // Check if a higher version device was found if (highest_version < (major_v * 10 + minor_v)) { highest_version = (major_v * 10 + minor_v); best_device = device_list; } device_list += strlen(device_list) + 1; // Go to the next device name in the list } // while (*device_name != 0) } // if (alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT") == AL_TRUE) // Open the 'best' device we found above. If no devices were previously found, // it will try opening the default device (= 0) _device = alcOpenDevice(best_device); if (CheckALCError() || _device == NULL) { PRINT_ERROR << "failed to open an OpenAL audio device: " << CreateALCErrorString() << endl; return false; } // Create an OpenAL context _context = alcCreateContext(_device, NULL); if (CheckALCError() || _context == NULL) { PRINT_ERROR << "failed to create an OpenAL context: " << CreateALCErrorString()<< endl; alcCloseDevice(_device); return false; } alcMakeContextCurrent(_context); CheckALError(); // Clear errors CheckALCError(); // Clear errors // Create as many sources as possible (we fix an upper bound of MAX_DEFAULT_AUDIO_SOURCES) ALuint source; for (uint16 i = 0; i < _max_sources; i++) { alGenSources(1, &source); if (CheckALError() == true) { _max_sources = i; _max_cache_size = i / 4; break; } _audio_sources.push_back(new private_audio::AudioSource(source)); } if (_max_sources == 0) { PRINT_ERROR << "failed to create at least one OpenAL audio source" << endl; return false; } return true; } // bool AudioEngine::SingletonInitialize()
//////////////////////////////////////////////////////////// /// Point d'entr�e du programme /// /// \return Code d'erreur de l'application /// //////////////////////////////////////////////////////////// int main_capture() { int time_left = 0; // Initialisation d'OpenAL avec le device par d�faut if (!InitOpenAL_capture(NULL)) return EXIT_FAILURE; // Initialisation de la capture if (!InitCapture(NULL)) return EXIT_FAILURE; // Lancement de la capture alcCaptureStart(CaptureDevice); // On va stocker les �chantillons captur�s dans un tableau d'entiers sign�s 16 bits std::vector<ALshort> Samples; // ...Et c'est parti pour 5 secondes de capture time_t Start = time(NULL); while ((time_left = time(NULL) - Start) <= 5) // si x passe � 1, on stop la capture { std::cout << "\rSpeech capture in progress... " << std::fixed << std::setprecision(2) << 5-time_left << " sec left"; // On r�cup�re le nombre d'�chantillons disponibles ALCint SamplesAvailable; alcGetIntegerv(CaptureDevice, ALC_CAPTURE_SAMPLES, 1, &SamplesAvailable); // On lit les �chantillons et on les ajoute au tableau if (SamplesAvailable > 0) { std::size_t Start = Samples.size(); Samples.resize(Start + SamplesAvailable); alcCaptureSamples(CaptureDevice, &Samples[Start], SamplesAvailable); } } // On stoppe la capture alcCaptureStop(CaptureDevice); // On n'oublie pas les �ventuels �chantillons qu'il reste � r�cup�rer ALCint SamplesAvailable; alcGetIntegerv(CaptureDevice, ALC_CAPTURE_SAMPLES, 1, &SamplesAvailable); if (SamplesAvailable > 0) { std::size_t Start = Samples.size(); Samples.resize(Start + SamplesAvailable); alcCaptureSamples(CaptureDevice, &Samples[Start], SamplesAvailable); } std::cout << "\rSpeech capture complete " << std::endl; // On sauvegarde les �chantillons captur�s dans un fichier SaveSound("vocal.wav", Samples); // Fermeture de la capture ShutdownCapture(); // Fermeture d'OpenAL ShutdownOpenAL_capture(); return EXIT_SUCCESS; }
// initializes hardware device from perferred/default/enumerated list bool openal_init_device(SCP_string *playback, SCP_string *capture) { if ( !Playback_device.empty() ) { if (playback) { *playback = Playback_device; } if (capture) { *capture = Capture_device; } return true; } if (playback) { playback->erase(); } if (capture) { capture->erase(); } // initialize default setup first, for version check... ALCdevice *device = alcOpenDevice(NULL); if (device == NULL) { return false; } ALCcontext *context = alcCreateContext(device, NULL); if (context == NULL) { alcCloseDevice(device); return false; } alcMakeContextCurrent(context); // version check (for 1.0 or 1.1) ALCint AL_minor_version = 0; alcGetIntegerv(NULL, ALC_MINOR_VERSION, sizeof(ALCint), &AL_minor_version); if (AL_minor_version < 1) { #ifdef _WIN32 MessageBox(NULL, "OpenAL 1.1 or newer is required for proper operation. Please upgrade your OpenAL drivers, which\nare available at http://www.openal.org/downloads.html, and try running the game again.", NULL, MB_OK); #else printf("OpenAL 1.1 or newer is required for proper operation.\n"); printf("Please upgrade to a newer version if on OS X or switch\n"); printf("to OpenAL-Soft on Linux.\n"); #endif alcMakeContextCurrent(NULL); alcDestroyContext(context); alcCloseDevice(device); return false; } alcGetError(device); // close default device alcMakeContextCurrent(NULL); alcDestroyContext(context); alcCloseDevice(device); // go through and find out what devices we actually want to use ... find_playback_device(); find_capture_device(); if ( Playback_device.empty() ) { return false; } #ifndef NDEBUG if ( !PlaybackDevices.empty() ) { nprintf(("OpenAL", " Available Playback Devices:\n")); for (size_t idx = 0; idx < PlaybackDevices.size(); idx++) { nprintf(("OpenAL", " %s", PlaybackDevices[idx].device_name.c_str())); if (PlaybackDevices[idx].type == OAL_DEVICE_USER) { nprintf(("OpenAL", " *preferred*\n")); } else if (PlaybackDevices[idx].type == OAL_DEVICE_DEFAULT) { nprintf(("OpenAL", " *default*\n")); } else { nprintf(("OpenAL", "\n")); } } } if ( !CaptureDevices.empty() ) { if ( !PlaybackDevices.empty() ) { nprintf(("OpenAL", "\n")); } nprintf(("OpenAL", " Available Capture Devices:\n")); for (size_t idx = 0; idx < CaptureDevices.size(); idx++) { nprintf(("OpenAL", " %s", CaptureDevices[idx].device_name.c_str())); if (CaptureDevices[idx].type == OAL_DEVICE_USER) { nprintf(("OpenAL", " *preferred*\n")); } else if (CaptureDevices[idx].type == OAL_DEVICE_DEFAULT) { nprintf(("OpenAL", " *default*\n")); } else { nprintf(("OpenAL", "\n")); } } nprintf(("OpenAL", "\n")); } #endif // cleanup PlaybackDevices.clear(); CaptureDevices.clear(); if (playback) { *playback = Playback_device; } if (capture) { *capture = Capture_device; } return true; }
IKeOpenALAudioDevice::IKeOpenALAudioDevice( KeAudioDeviceDesc* audiodevice_desc ): device(NULL), context(NULL) { ALint attributes[4] = {0}; ALenum error = 0; initialized = No; /* Create the default OpenAL device */ device = alcOpenDevice( NULL ); if( !device ) { DISPDBG_R( KE_ERROR, "Error initializing OpenAL audio device!" ); } #if defined(__APPLE__) && defined(__MOBILE_OS__) /* Not available for iOS afaik */ #else /* Does the user want to initialize EFX? */ if( audiodevice_desc->aux_sends != 0 ) { /* Verify the EFX extension is supported */ /* If not, uninitialize and exit */ if( !alcIsExtensionPresent( device, "ALC_EXT_EFX" ) ) { DISPDBG( 1, "ALC_EXT_EFX extension is not present!\n" ); alcCloseDevice( device ); return; } /* Set EFX attributes */ attributes[0] = ALC_MAX_AUXILIARY_SENDS; attributes[1] = audiodevice_desc->aux_sends; /* TODO: More? */ } #endif /* Create an OpenAL context */ context = alcCreateContext( device, audiodevice_desc->aux_sends == 0 ? NULL : attributes ); OALC_DISPDBG( KE_ERROR, "Error initializing OpenAL context!" ); if( !context ) { alcCloseDevice( device ); return; } /* Set the newly created OpenAL context */ ALboolean res = alcMakeContextCurrent( context ); if( !res ) { OALC_DISPDBG( KE_ERROR, "An error occured setting OpenAL context!" ); alcDestroyContext( context ); alcCloseDevice( device ); return; } /* So far, so good, right? */ error = alGetError(); #if defined(__APPLE__) && defined(__MOBILE_OS__) /* Not available for iOS afaik */ #else /* Verify that we get the desired number of auxiliry sends */ if( audiodevice_desc->aux_sends != 0 ) { int sends = 0; alcGetIntegerv( device, ALC_MAX_AUXILIARY_SENDS, 1, &sends ); if( sends != audiodevice_desc->aux_sends ) DISPDBG( 1, "Requested " << audiodevice_desc->aux_sends << " max auxiliary sends, got " << sends << "instead...\n" ); else DISPDBG( 1, "Max auxiliary sends: " << sends << "\n" ); } #endif const ALCchar* extensions = alcGetString( device, ALC_EXTENSIONS ); int extension_count = 0; std::vector<ALCchar> ext; ext.push_back('\t'); ext.push_back('\t'); /* Count extensions */ for( int i = 0; i < strlen( extensions )+1; i++ ) { if( extensions[i] == ' ' || extensions[i] == '\0' ) { extension_count++; ext.push_back('\n'); ext.push_back('\t'); ext.push_back('\t'); } else ext.push_back(extensions[i]); } ext.push_back('\n\0'); /* Print OpenAL driver/implementation details */ DISPDBG( 1, "\n\tOpenAL Vendor: " << alGetString( AL_VENDOR ) << "\n\tOpenAL Version: " << alGetString( AL_VERSION ) << "\n\tOpenAL Renderer: " << alGetString( AL_RENDERER ) << "\n" ); /* Print extensions */ std::stringstream sstr; sstr << extension_count; std::string ext_str = "\n\tOpenAL Extensions (" + sstr.str() + "):\n"; ext_str += ext.data(); DISPDBG( KE_DBGLVL(0), ext_str ); initialized = Yes; }
int main() { ALCdevice *pDevice; ALCcontext *pContext; ALCdevice *pCaptureDevice; const ALCchar *szDefaultCaptureDevice; ALint iSamplesAvailable; FILE *pFile; ALchar Buffer[BUFFERSIZE]; WAVEHEADER sWaveHeader; ALint iDataSize = 0; ALint iSize; // NOTE : This code does NOT setup the Wave Device's Audio Mixer to select a recording input // or a recording level. // Initialize Framework ALFWInit(); ALFWprintf("Capture Application\n"); if (!ALFWInitOpenAL()) { ALFWprintf("Failed to initialize OpenAL\n"); ALFWShutdown(); return 0; } // Check for Capture Extension support pContext = alcGetCurrentContext(); pDevice = alcGetContextsDevice(pContext); if (alcIsExtensionPresent(pDevice, "ALC_EXT_CAPTURE") == AL_FALSE) { ALFWprintf("Failed to detect Capture Extension\n"); ALFWShutdownOpenAL(); ALFWShutdown(); return 0; } // Get list of available Capture Devices const ALchar *pDeviceList = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER); if (pDeviceList) { ALFWprintf("\nAvailable Capture Devices are:-\n"); while (*pDeviceList) { ALFWprintf("%s\n", pDeviceList); pDeviceList += strlen(pDeviceList) + 1; } } // Get the name of the 'default' capture device szDefaultCaptureDevice = alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER); ALFWprintf("\nDefault Capture Device is '%s'\n\n", szDefaultCaptureDevice); // Open the default Capture device to record a 22050Hz 16bit Mono Stream using an internal buffer // of BUFFERSIZE Samples (== BUFFERSIZE * 2 bytes) pCaptureDevice = alcCaptureOpenDevice(szDefaultCaptureDevice, 22050, AL_FORMAT_MONO16, BUFFERSIZE); if (pCaptureDevice) { ALFWprintf("Opened '%s' Capture Device\n\n", alcGetString(pCaptureDevice, ALC_CAPTURE_DEVICE_SPECIFIER)); // Create / open a file for the captured data pFile = fopen(OUTPUT_WAVE_FILE, "wb"); // Prepare a WAVE file header for the captured data sprintf(sWaveHeader.szRIFF, "RIFF"); sWaveHeader.lRIFFSize = 0; sprintf(sWaveHeader.szWave, "WAVE"); sprintf(sWaveHeader.szFmt, "fmt "); sWaveHeader.lFmtSize = sizeof(WAVEFORMATEX); sWaveHeader.wfex.nChannels = 1; sWaveHeader.wfex.wBitsPerSample = 16; sWaveHeader.wfex.wFormatTag = WAVE_FORMAT_PCM; sWaveHeader.wfex.nSamplesPerSec = 22050; sWaveHeader.wfex.nBlockAlign = sWaveHeader.wfex.nChannels * sWaveHeader.wfex.wBitsPerSample / 8; sWaveHeader.wfex.nAvgBytesPerSec = sWaveHeader.wfex.nSamplesPerSec * sWaveHeader.wfex.nBlockAlign; sWaveHeader.wfex.cbSize = 0; sprintf(sWaveHeader.szData, "data"); sWaveHeader.lDataSize = 0; fwrite(&sWaveHeader, sizeof(WAVEHEADER), 1, pFile); // Start audio capture alcCaptureStart(pCaptureDevice); // Record for two seconds or until a key is pressed DWORD dwStartTime = timeGetTime(); while (!ALFWKeyPress() && (timeGetTime() <= (dwStartTime + 2000))) { // Release some CPU time ... Sleep(1); // Find out how many samples have been captured alcGetIntegerv(pCaptureDevice, ALC_CAPTURE_SAMPLES, 1, &iSamplesAvailable); ALFWprintf("Samples available : %d\r", iSamplesAvailable); // When we have enough data to fill our BUFFERSIZE byte buffer, grab the samples if (iSamplesAvailable > (BUFFERSIZE / sWaveHeader.wfex.nBlockAlign)) { // Consume Samples alcCaptureSamples(pCaptureDevice, Buffer, BUFFERSIZE / sWaveHeader.wfex.nBlockAlign); // Write the audio data to a file fwrite(Buffer, BUFFERSIZE, 1, pFile); // Record total amount of data recorded iDataSize += BUFFERSIZE; } } // Stop capture alcCaptureStop(pCaptureDevice); // Check if any Samples haven't been consumed yet alcGetIntegerv(pCaptureDevice, ALC_CAPTURE_SAMPLES, 1, &iSamplesAvailable); while (iSamplesAvailable) { if (iSamplesAvailable > (BUFFERSIZE / sWaveHeader.wfex.nBlockAlign)) { alcCaptureSamples(pCaptureDevice, Buffer, BUFFERSIZE / sWaveHeader.wfex.nBlockAlign); fwrite(Buffer, BUFFERSIZE, 1, pFile); iSamplesAvailable -= (BUFFERSIZE / sWaveHeader.wfex.nBlockAlign); iDataSize += BUFFERSIZE; } else { alcCaptureSamples(pCaptureDevice, Buffer, iSamplesAvailable); fwrite(Buffer, iSamplesAvailable * sWaveHeader.wfex.nBlockAlign, 1, pFile); iDataSize += iSamplesAvailable * sWaveHeader.wfex.nBlockAlign; iSamplesAvailable = 0; } } // Fill in Size information in Wave Header fseek(pFile, 4, SEEK_SET); iSize = iDataSize + sizeof(WAVEHEADER) - 8; fwrite(&iSize, 4, 1, pFile); fseek(pFile, 42, SEEK_SET); fwrite(&iDataSize, 4, 1, pFile); fclose(pFile); ALFWprintf("\nSaved captured audio data to '%s'\n", OUTPUT_WAVE_FILE); // Close the Capture Device alcCaptureCloseDevice(pCaptureDevice); } // Close down OpenAL ALFWShutdownOpenAL(); // Close down the Framework ALFWShutdown(); return 0; }
int main() { int major, minor; alcGetIntegerv(NULL, ALC_MAJOR_VERSION, 1, &major); alcGetIntegerv(NULL, ALC_MAJOR_VERSION, 1, &minor); assert(major == 1); printf("ALC version: %i.%i\n", major, minor); printf("Default device: %s\n", alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER)); ALCdevice* device = alcOpenDevice(NULL); ALCcontext* context = alcCreateContext(device, NULL); alcMakeContextCurrent(context); assert(alGetString(AL_VERSION)); printf("OpenAL version: %s\n", alGetString(AL_VERSION)); printf("OpenAL vendor: %s\n", alGetString(AL_VENDOR)); printf("OpenAL renderer: %s\n", alGetString(AL_RENDERER)); ALfloat listenerPos[] = {0.0, 0.0, 0.0}; ALfloat listenerVel[] = {0.0, 0.0, 0.0}; ALfloat listenerOri[] = {0.0, 0.0, -1.0, 0.0, 1.0, 0.0}; alListenerfv(AL_POSITION, listenerPos); alListenerfv(AL_VELOCITY, listenerVel); alListenerfv(AL_ORIENTATION, listenerOri); // check getting and setting global gain ALfloat volume; alGetListenerf(AL_GAIN, &volume); assert(volume == 1.0); alListenerf(AL_GAIN, 0.0); alGetListenerf(AL_GAIN, &volume); assert(volume == 0.0); alListenerf(AL_GAIN, 1.0); // reset gain to default ALuint buffers[1]; alGenBuffers(1, buffers); #ifdef __EMSCRIPTEN__ FILE* source = fopen("audio.wav", "rb"); #else FILE* source = fopen("sounds/audio.wav", "rb"); #endif fseek(source, 0, SEEK_END); int size = ftell(source); fseek(source, 0, SEEK_SET); unsigned char* buffer = (unsigned char*) malloc(size); fread(buffer, size, 1, source); unsigned offset = 12; // ignore the RIFF header offset += 8; // ignore the fmt header offset += 2; // ignore the format type unsigned channels = buffer[offset + 1] << 8; channels |= buffer[offset]; offset += 2; printf("Channels: %u\n", channels); unsigned frequency = buffer[offset + 3] << 24; frequency |= buffer[offset + 2] << 16; frequency |= buffer[offset + 1] << 8; frequency |= buffer[offset]; offset += 4; printf("Frequency: %u\n", frequency); offset += 6; // ignore block size and bps unsigned bits = buffer[offset + 1] << 8; bits |= buffer[offset]; offset += 2; printf("Bits: %u\n", bits); ALenum format = 0; if(bits == 8) { if(channels == 1) format = AL_FORMAT_MONO8; else if(channels == 2) format = AL_FORMAT_STEREO8; } else if(bits == 16) { if(channels == 1) format = AL_FORMAT_MONO16; else if(channels == 2) format = AL_FORMAT_STEREO16; } offset += 8; // ignore the data chunk printf("Start offset: %d\n", offset); alBufferData(buffers[0], format, &buffer[offset], size - offset, frequency); ALint val; alGetBufferi(buffers[0], AL_FREQUENCY, &val); assert(val == frequency); alGetBufferi(buffers[0], AL_SIZE, &val); assert(val == size - offset); alGetBufferi(buffers[0], AL_BITS, &val); assert(val == bits); alGetBufferi(buffers[0], AL_CHANNELS, &val); assert(val == channels); ALuint sources[1]; alGenSources(1, sources); assert(alIsSource(sources[0])); alSourcei(sources[0], AL_BUFFER, buffers[0]); ALint state; alGetSourcei(sources[0], AL_SOURCE_STATE, &state); assert(state == AL_INITIAL); alSourcePlay(sources[0]); alGetSourcei(sources[0], AL_SOURCE_STATE, &state); assert(state == AL_PLAYING); #ifdef __EMSCRIPTEN__ emscripten_async_call(playSource, reinterpret_cast<void*>(sources[0]), 700); #else usleep(700000); playSource(reinterpret_cast<void*>(sources[0])); #endif return 0; }
CEFX::CEFX(ALCdevice* device) :enabled(false) ,supported(false) ,sfxProperties(NULL) ,sfxSlot(0) ,sfxReverb(0) ,sfxFilter(0) ,updates(0) ,maxSlots(0) ,maxSlotsPerSource(0) { SetAirAbsorptionFactor(configHandler->GetFloat("snd_airAbsorption")); bool hasExtension = alcIsExtensionPresent(device, "ALC_EXT_EFX"); if(hasExtension && alGenEffects && alDeleteEffects) supported = true; //! set default preset eaxPresets["default"] = eaxPresets[default_preset]; //! always allocate this sfxProperties = new EAXSfxProps(); *sfxProperties = eaxPresets[default_preset]; if (!supported) { if(!hasExtension) { LOG(" EFX Supported: no"); } else { LOG(" EFX is supported but software does not seem to work properly"); } return; } //! clear log alGetError() ; //! Check Available Effects { static const ALuint effects[] = { AL_EFFECT_REVERB, AL_EFFECT_EAXREVERB, AL_EFFECT_CHORUS, AL_EFFECT_DISTORTION, AL_EFFECT_ECHO, AL_EFFECT_FLANGER, AL_EFFECT_FREQUENCY_SHIFTER, AL_EFFECT_VOCAL_MORPHER, AL_EFFECT_PITCH_SHIFTER, AL_EFFECT_RING_MODULATOR, AL_EFFECT_AUTOWAH, AL_EFFECT_COMPRESSOR, AL_EFFECT_EQUALIZER }; ALuint alFx; alGenEffects(1, &alFx); if (alGetError() == AL_NO_ERROR) { for(size_t i = 0; i < sizeof(effects)/sizeof(effects[0]); i++) { const ALuint fx = effects[i]; alEffecti(alFx, AL_EFFECT_TYPE, fx); effectsSupported[fx] = (alGetError() == AL_NO_ERROR); } } alDeleteEffects(1, &alFx); } //! Check Available Filters { static const ALuint filters[] = { AL_FILTER_LOWPASS, AL_FILTER_HIGHPASS, AL_FILTER_BANDPASS }; ALuint alFilter; alGenFilters(1, &alFilter); if (alGetError() == AL_NO_ERROR) { for(size_t i = 0; i < sizeof(filters)/sizeof(filters[0]); i++) { const ALuint filter = filters[i]; alFilteri(alFilter, AL_FILTER_TYPE, filter); filtersSupported[filter] = (alGetError() == AL_NO_ERROR); } } alDeleteFilters(1, &alFilter); } //! Check Max Available EffectSlots { int n; ALuint alFXSlots[128]; for (n = 0; n < 128; n++) { alGenAuxiliaryEffectSlots(1, &alFXSlots[n]); if (alGetError() != AL_NO_ERROR) break; } maxSlots = n; alDeleteAuxiliaryEffectSlots(n, alFXSlots); } //! Check Max AUX FX SLOTS Per Sound Source alcGetIntegerv(device, ALC_MAX_AUXILIARY_SENDS, 1, (ALCint*)&maxSlotsPerSource); //! Check requirements if (!effectsSupported[AL_EFFECT_EAXREVERB] || !filtersSupported[AL_FILTER_LOWPASS] || (maxSlots<1) || (maxSlotsPerSource<1) ) { if (enabled) { LOG_L(L_WARNING, " EFX Supported: no"); } supported = false; return; } //! Create our global sfx enviroment alGenAuxiliaryEffectSlots(1, &sfxSlot); alGenEffects(1, &sfxReverb); alEffecti(sfxReverb, AL_EFFECT_TYPE, AL_EFFECT_EAXREVERB); alGenFilters(1, &sfxFilter); alFilteri(sfxFilter, AL_FILTER_TYPE, AL_FILTER_LOWPASS); if (!alIsAuxiliaryEffectSlot(sfxSlot) || !alIsEffect(sfxReverb) || !alIsFilter(sfxFilter)) { LOG_L(L_ERROR, " Initializing EFX failed!"); alDeleteFilters(1, &sfxFilter); alDeleteEffects(1, &sfxReverb); alDeleteAuxiliaryEffectSlots(1, &sfxSlot); supported = false; return; } //! Load defaults CommitEffects(); if (!CheckError(" EFX")) { LOG_L(L_ERROR, " Initializing EFX failed!"); alAuxiliaryEffectSloti(sfxSlot, AL_EFFECTSLOT_EFFECT, AL_EFFECT_NULL); alDeleteFilters(1, &sfxFilter); alDeleteEffects(1, &sfxReverb); alDeleteAuxiliaryEffectSlots(1, &sfxSlot); supported = false; return; } //! User may disable it (performance reasons?) enabled = configHandler->GetBool("UseEFX"); LOG(" EFX Enabled: %s", (enabled ? "yes" : "no")); if (enabled) { LOG_L(L_DEBUG, " EFX MaxSlots: %i", maxSlots); LOG_L(L_DEBUG, " EFX MaxSlotsPerSource: %i", maxSlotsPerSource); } configHandler->NotifyOnChange(this); }
/** * @brief Initializes the sound subsystem. * * @return 0 on success. */ int sound_al_init (void) { int ret; ALuint s; ALint freq; ALint attribs[4] = { 0, 0, 0, 0 }; /* Default values. */ ret = 0; /* we'll need a mutex */ sound_lock = SDL_CreateMutex(); soundLock(); /* opening the default device */ al_device = alcOpenDevice(NULL); if (al_device == NULL) { WARN("Unable to open default sound device"); ret = -1; goto snderr_dev; } /* Query EFX extension. */ if (conf.al_efx) { al_info.efx = alcIsExtensionPresent( al_device, "ALC_EXT_EFX" ); if (al_info.efx == AL_TRUE) { attribs[0] = ALC_MAX_AUXILIARY_SENDS; attribs[1] = 4; } } else al_info.efx = AL_FALSE; /* Create the OpenAL context */ al_context = alcCreateContext( al_device, attribs ); if (al_context == NULL) { WARN("Unable to create OpenAL context"); ret = -2; goto snderr_ctx; } /* Clear the errors */ alGetError(); /* Set active context */ if (alcMakeContextCurrent( al_context )==AL_FALSE) { WARN("Failure to set default context"); ret = -4; goto snderr_act; } /* Get context information. */ alcGetIntegerv( al_device, ALC_FREQUENCY, sizeof(freq), &freq ); /* Try to enable EFX. */ if (al_info.efx == AL_TRUE) al_enableEFX(); else { al_info.efx_reverb = AL_FALSE; al_info.efx_echo = AL_FALSE; } /* Allocate source for music. */ alGenSources( 1, &music_source ); /* Check for errors. */ al_checkErr(); /* Start allocating the sources - music has already taken his */ source_nstack = 0; source_mstack = 0; while (source_nstack < conf.snd_voices) { if (source_mstack < source_nstack+1) { /* allocate more memory */ if (source_mstack == 0) source_mstack = conf.snd_voices; else source_mstack *= 2; source_stack = realloc( source_stack, sizeof(ALuint) * source_mstack ); } alGenSources( 1, &s ); source_stack[source_nstack] = s; /* How OpenAL distance model works: * * Clamped: * gain = distance_function( CLAMP( AL_REFERENCE_DISTANCE, AL_MAX_DISTANCE, distance ) ); * * Distance functions: * AL_REFERENCE_DISTANCE * * Inverse = ------------------------------------------------------------------------------ * AL_REFERENCE_DISTANCE + AL_ROLLOFF_FACTOR ( distance - AL_REFERENCE_DISTANCE ) * * 1 - AL_ROLLOFF_FACTOR ( distance - AL_REFERENCE_DISTANCE ) * * Linear = ---------------------------------------------------------- * AL_MAX_DISTANCE - AL_REFERENCE_DISTANCE * * / distance \ -AL_ROLLOFF_FACTOR * * Exponential = | --------------------- | * \ AL_REFERENCE_DISTANCE / * * * Some values: * * model falloff reference 100 1000 5000 10000 * linear 1 500 1.000 0.947 0.526 0.000 * inverse 1 500 1.000 0.500 0.100 0.050 * exponent 1 500 1.000 0.500 0.100 0.050 * inverse 0.5 500 1.000 0.667 0.182 0.095 * exponent 0.5 500 1.000 0.707 0.316 0.223 * inverse 2 500 1.000 0.333 0.052 0.026 * exponent 2 500 1.000 0.250 0.010 0.003 */ alSourcef( s, AL_REFERENCE_DISTANCE, 500. ); /* Close distance to clamp at (doesn't get louder). */ alSourcef( s, AL_MAX_DISTANCE, 25000. ); /* Max distance to clamp at (doesn't get quieter). */ alSourcef( s, AL_ROLLOFF_FACTOR, 1. ); /* Determines how it drops off. */ /* Set the filter. */ if (al_info.efx == AL_TRUE) alSource3i( s, AL_AUXILIARY_SEND_FILTER, efx_directSlot, 0, AL_FILTER_NULL ); /* Check for error. */ if (alGetError() == AL_NO_ERROR) source_nstack++; else break; } /* Reduce ram usage. */ source_mstack = source_nstack; source_stack = realloc( source_stack, sizeof(ALuint) * source_mstack ); /* Copy allocated sources to total stack. */ source_ntotal = source_mstack; source_total = malloc( sizeof(ALuint) * source_mstack ); memcpy( source_total, source_stack, sizeof(ALuint) * source_mstack ); /* Copy allocated sources to all stack. */ source_nall = source_mstack; source_all = malloc( sizeof(ALuint) * source_mstack ); memcpy( source_all, source_stack, sizeof(ALuint) * source_mstack ); /* Set up how sound works. */ alDistanceModel( AL_INVERSE_DISTANCE_CLAMPED ); /* Clamping is fundamental so it doesn't sound like crap. */ alDopplerFactor( 1. ); sound_al_env( SOUND_ENV_NORMAL, 0. ); /* Check for errors. */ al_checkErr(); /* we can unlock now */ soundUnlock(); /* debug magic */ DEBUG("OpenAL started: %d Hz", freq); DEBUG("Renderer: %s", alGetString(AL_RENDERER)); if (al_info.efx == AL_FALSE) DEBUG("Version: %s without EFX", alGetString(AL_VERSION)); else DEBUG("Version: %s with EFX %d.%d", alGetString(AL_VERSION), al_info.efx_major, al_info.efx_minor); DEBUG(); return ret; /* * error handling */ snderr_act: alcDestroyContext( al_context ); snderr_ctx: al_context = NULL; alcCloseDevice( al_device ); snderr_dev: al_device = NULL; soundUnlock(); SDL_DestroyMutex( sound_lock ); sound_lock = NULL; return ret; }
// Initialize digitized wav driver // // return : <int> 1 - initialized successfully // 0 - init fail // int OpenALAudio::init_wav() { ALCint size; std::vector<ALCint> attributes; assert(!this->wav_init_flag); this->wav_res.init(DIR_RES"A_WAVE2.RES", 0, 0); this->al_device = alcOpenDevice(NULL); if (this->al_device == NULL) { ERR("alcOpenDevice failed\n"); goto err; } attributes.push_back(0); this->al_context = alcCreateContext(this->al_device, &attributes[0]); if (this->al_context == NULL) { ERR("alcCreateContext failed: 0x%x\n", alcGetError(this->al_device)); goto err; } if (!alcMakeContextCurrent(this->al_context)) { ERR("alcMakeContextCurrent failed: 0x%x\n", alcGetError(this->al_device)); goto err; } attributes.clear(); alcGetIntegerv(this->al_device, ALC_ATTRIBUTES_SIZE, 1, &size); attributes.resize(size); alcGetIntegerv(this->al_device, ALC_ALL_ATTRIBUTES, attributes.size(), &attributes[0]); this->max_sources = 16; /* default, in case OpenAL doesn't tell us */ for (int n = 0;; n += 2) { if (attributes[n] == 0) break; switch (attributes[n]) { case ALC_MONO_SOURCES: MSG("ALC_MONO_SOURCES: %i\n", attributes[n + 1]); this->max_sources = attributes[n + 1]; break; case ALC_STEREO_SOURCES: MSG("ALC_STEREO_SOURCES: %i\n", attributes[n + 1]); attributes[n + 1]; break; } } this->wav_init_flag = true; return 1; err: this->deinit_wav(); return 0; }
/** * @brief Enables the OpenAL EFX extension. * * @return 0 on success. */ static int al_enableEFX (void) { /* Get general information. */ alcGetIntegerv( al_device, ALC_MAX_AUXILIARY_SENDS, 1, &al_info.efx_auxSends ); alcGetIntegerv( al_device, ALC_EFX_MAJOR_VERSION, 1, &al_info.efx_major ); alcGetIntegerv( al_device, ALC_EFX_MINOR_VERSION, 1, &al_info.efx_minor ); /* Get function pointers. */ nalGenAuxiliaryEffectSlots = alGetProcAddress( "alGenAuxiliaryEffectSlots" ); nalDeleteAuxiliaryEffectSlots = alGetProcAddress( "alDeleteAuxiliaryEffectSlots" ); nalIsAuxiliaryEffectSlot = alGetProcAddress( "alIsAuxiliaryEffectSlot" ); nalAuxiliaryEffectSloti = alGetProcAddress( "alAuxiliaryEffectSloti" ); nalAuxiliaryEffectSlotiv = alGetProcAddress( "alAuxiliaryEffectSlotiv" ); nalAuxiliaryEffectSlotf = alGetProcAddress( "alAuxiliaryEffectSlotf" ); nalAuxiliaryEffectSlotfv = alGetProcAddress( "alAuxiliaryEffectSlotfv" ); nalGetAuxiliaryEffectSloti = alGetProcAddress( "alGetAuxiliaryEffectSloti" ); nalGetAuxiliaryEffectSlotiv = alGetProcAddress( "alGetAuxiliaryEffectSlotiv" ); nalGetAuxiliaryEffectSlotf = alGetProcAddress( "alGetAuxiliaryEffectSlotf" ); nalGetAuxiliaryEffectSlotfv = alGetProcAddress( "alGetAuxiliaryEffectSlotfv" ); nalGenFilters = alGetProcAddress( "alGenFilters" ); nalDeleteFilters = alGetProcAddress( "alDeleteFilters" ); nalFilteri = alGetProcAddress( "alFilteri" ); nalFilteriv = alGetProcAddress( "alFilteriv" ); nalFilterf = alGetProcAddress( "alFilterf" ); nalFilterfv = alGetProcAddress( "alFilterfv" ); nalGenEffects = alGetProcAddress( "alGenEffects" ); nalDeleteEffects = alGetProcAddress( "alDeleteEffects" ); nalEffecti = alGetProcAddress( "alEffecti" ); nalEffectiv = alGetProcAddress( "alEffectiv" ); nalEffectf = alGetProcAddress( "alEffectf" ); nalEffectfv = alGetProcAddress( "alEffectfv" ); if (!nalGenAuxiliaryEffectSlots || !nalDeleteAuxiliaryEffectSlots || !nalIsAuxiliaryEffectSlot || !nalAuxiliaryEffectSloti || !nalAuxiliaryEffectSlotiv || !nalAuxiliaryEffectSlotf || !nalAuxiliaryEffectSlotfv || !nalGetAuxiliaryEffectSloti || !nalGetAuxiliaryEffectSlotiv || !nalGetAuxiliaryEffectSlotf || !nalGetAuxiliaryEffectSlotfv || !nalGenFilters || !nalDeleteFilters || !nalFilteri || !nalFilteriv || !nalFilterf || !nalFilterfv || !nalGenEffects || !nalDeleteEffects || !nalEffecti || !nalEffectiv || !nalEffectf || !nalEffectfv) { DEBUG("OpenAL EFX functions not found, disabling EFX."); al_info.efx = AL_FALSE; return -1; } /* Create auxiliary slot. */ nalGenAuxiliaryEffectSlots( 1, &efx_directSlot ); /* Create reverb effect. */ nalGenEffects( 1, &efx_reverb ); nalEffecti( efx_reverb, AL_EFFECT_TYPE, AL_EFFECT_REVERB ); if(alGetError() != AL_NO_ERROR) { DEBUG("OpenAL Reverb not found, disabling."); al_info.efx_reverb = AL_FALSE; nalDeleteEffects( 1, &efx_reverb ); } else { al_info.efx_reverb = AL_TRUE; /* Set Reverb parameters. */ /*nalEffectf( efx_reverb, AL_REVERB_DECAY_TIME, 15. );*/ } /* Create echo effect. */ nalGenEffects( 1, &efx_echo ); nalEffecti( efx_echo, AL_EFFECT_TYPE, AL_EFFECT_ECHO ); if(alGetError() != AL_NO_ERROR) { DEBUG("OpenAL Echo not found, disabling."); al_info.efx_echo = AL_FALSE; nalDeleteEffects( 1, &efx_echo ); } else { al_info.efx_echo = AL_TRUE; /* Set Echo parameters. */ nalEffectf( efx_echo, AL_ECHO_DELAY, 0.207 ); } /* Set up the listener. */ alListenerf( AL_METERS_PER_UNIT, 5. ); /* Check for errors. */ al_checkErr(); return 0; }
//----------------------------------------------------------------------------// SoundDevices::SoundDevices() { ALDEVICEINFO ALDeviceInfo; char *devices; int index; const char *defaultDeviceName; const char *actualDeviceName; // DeviceInfo vector stores, for each enumerated device, it's device name, selection status, spec version #, and extension support vDeviceInfo.empty(); vDeviceInfo.reserve(10); defaultDeviceIndex = 0; // grab function pointers for 1.0-API functions, and if successful proceed to enumerate all devices if (alcIsExtensionPresent(nullptr, "ALC_ENUMERATION_EXT")) { devices = (char *)alcGetString(nullptr, ALC_DEVICE_SPECIFIER); defaultDeviceName = (char *)alcGetString(nullptr, ALC_DEFAULT_DEVICE_SPECIFIER); index = 0; // go through device list (each device terminated with a single nullptr, list terminated with double nullptr) while (devices != nullptr) { if (strcmp(defaultDeviceName, devices) == 0) { defaultDeviceIndex = index; } ALCdevice *device = alcOpenDevice(devices); if (device) { ALCcontext *context = alcCreateContext(device, nullptr); if (context) { alcMakeContextCurrent(context); // if new actual device name isn't already in the list, then add it... actualDeviceName = alcGetString(device, ALC_DEVICE_SPECIFIER); bool bNewName = (getDeviceIndex(actualDeviceName) < 0); if ((bNewName) && (actualDeviceName != nullptr) && (strlen(actualDeviceName) > 0)) { memset(&ALDeviceInfo, 0, sizeof(ALDEVICEINFO)); ALDeviceInfo.bSelected = true; ALDeviceInfo.strDeviceName = actualDeviceName; alcGetIntegerv(device, ALC_MAJOR_VERSION, sizeof(int), &ALDeviceInfo.iMajorVersion); alcGetIntegerv(device, ALC_MINOR_VERSION, sizeof(int), &ALDeviceInfo.iMinorVersion); ALDeviceInfo.pvstrExtensions = new std::vector<Ogre::String>; // Check for ALC Extensions if (alcIsExtensionPresent(device, "ALC_EXT_CAPTURE") == AL_TRUE) ALDeviceInfo.pvstrExtensions->push_back("ALC_EXT_CAPTURE"); if (alcIsExtensionPresent(device, "ALC_EXT_EFX") == AL_TRUE) ALDeviceInfo.pvstrExtensions->push_back("ALC_EXT_EFX"); // Check for AL Extensions if (alIsExtensionPresent("AL_EXT_OFFSET") == AL_TRUE) ALDeviceInfo.pvstrExtensions->push_back("AL_EXT_OFFSET"); if (alIsExtensionPresent("AL_EXT_LINEAR_DISTANCE") == AL_TRUE) ALDeviceInfo.pvstrExtensions->push_back("AL_EXT_LINEAR_DISTANCE"); if (alIsExtensionPresent("AL_EXT_EXPONENT_DISTANCE") == AL_TRUE) ALDeviceInfo.pvstrExtensions->push_back("AL_EXT_EXPONENT_DISTANCE"); if (alIsExtensionPresent("EAX2.0") == AL_TRUE) ALDeviceInfo.pvstrExtensions->push_back("EAX2.0"); if (alIsExtensionPresent("EAX3.0") == AL_TRUE) ALDeviceInfo.pvstrExtensions->push_back("EAX3.0"); if (alIsExtensionPresent("EAX4.0") == AL_TRUE) ALDeviceInfo.pvstrExtensions->push_back("EAX4.0"); if (alIsExtensionPresent("EAX5.0") == AL_TRUE) ALDeviceInfo.pvstrExtensions->push_back("EAX5.0"); if (alIsExtensionPresent("EAX-RAM") == AL_TRUE) ALDeviceInfo.pvstrExtensions->push_back("EAX-RAM"); // Get Source Count ALDeviceInfo.uiSourceCount = getMaxNumSources(); vDeviceInfo.push_back(ALDeviceInfo); } alcMakeContextCurrent(nullptr); alcDestroyContext(context); } alcCloseDevice(device); } devices += strlen(devices) + 1; index += 1; } } resetFilters(); }
// initializes hardware device from perferred/default/enumerated list bool openal_init_device(SCP_string *playback, SCP_string *capture) { if ( !Playback_device.empty() ) { if (playback) { *playback = Playback_device; } if (capture) { *capture = Capture_device; } return true; } if (playback) { playback->erase(); } if (capture) { capture->erase(); } // initialize default setup first, for version check... ALCdevice *device = alcOpenDevice(NULL); if (device == NULL) { return false; } ALCcontext *context = alcCreateContext(device, NULL); if (context == NULL) { alcCloseDevice(device); return false; } alcMakeContextCurrent(context); // version check (for 1.0 or 1.1) ALCint AL_minor_version = 0; alcGetIntegerv(NULL, ALC_MINOR_VERSION, sizeof(ALCint), &AL_minor_version); if (AL_minor_version < 1) { os::dialogs::Message(os::dialogs::MESSAGEBOX_ERROR, "OpenAL 1.1 or newer is required for proper operation. On Linux and Windows OpenAL Soft is recommended. If you are on Mac OS X you need to upgrade your OS."); alcMakeContextCurrent(NULL); alcDestroyContext(context); alcCloseDevice(device); return false; } alcGetError(device); // close default device alcMakeContextCurrent(NULL); alcDestroyContext(context); alcCloseDevice(device); // go through and find out what devices we actually want to use ... find_playback_device(); find_capture_device(); if ( Playback_device.empty() ) { return false; } #ifndef NDEBUG if ( !PlaybackDevices.empty() ) { nprintf(("OpenAL", " Available Playback Devices:\n")); for (size_t idx = 0; idx < PlaybackDevices.size(); idx++) { nprintf(("OpenAL", " %s", PlaybackDevices[idx].device_name.c_str())); if (PlaybackDevices[idx].type == OAL_DEVICE_USER) { nprintf(("OpenAL", " *preferred*\n")); } else if (PlaybackDevices[idx].type == OAL_DEVICE_DEFAULT) { nprintf(("OpenAL", " *default*\n")); } else { nprintf(("OpenAL", "\n")); } } } if ( !CaptureDevices.empty() ) { if ( !PlaybackDevices.empty() ) { nprintf(("OpenAL", "\n")); } nprintf(("OpenAL", " Available Capture Devices:\n")); for (size_t idx = 0; idx < CaptureDevices.size(); idx++) { nprintf(("OpenAL", " %s", CaptureDevices[idx].device_name.c_str())); if (CaptureDevices[idx].type == OAL_DEVICE_USER) { nprintf(("OpenAL", " *preferred*\n")); } else if (CaptureDevices[idx].type == OAL_DEVICE_DEFAULT) { nprintf(("OpenAL", " *default*\n")); } else { nprintf(("OpenAL", "\n")); } } nprintf(("OpenAL", "\n")); } #endif // cleanup PlaybackDevices.clear(); CaptureDevices.clear(); if (playback) { *playback = Playback_device; } if (capture) { *capture = Capture_device; } return true; }