void audiomanager::initsound() { if(!audio) { conoutf("audio is disabled"); return; } nosound = true; device = NULL; context = NULL; // list available devices if(alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT")) { const ALCchar *devices = alcGetString(NULL, ALC_DEVICE_SPECIFIER); if(devices) { string d; copystring(d, "Audio devices: "); // null separated device string for(const ALchar *c = devices; *c; c += strlen(c)+1) { if(c!=devices) concatstring(d, ", "); concatstring(d, c); } conoutf("%s", d); } } // open device const char *devicename = getalias("openaldevice"); device = alcOpenDevice(devicename && devicename[0] ? devicename : NULL); if(device) { context = alcCreateContext(device, NULL); if(context) { alcMakeContextCurrent(context); alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED); // backend infos conoutf("Sound: %s / %s (%s)", alcGetString(device, ALC_DEVICE_SPECIFIER), alGetString(AL_RENDERER), alGetString(AL_VENDOR)); conoutf("Driver: %s", alGetString(AL_VERSION)); // allocate OpenAL resources sourcescheduler::instance().init(16); // let the stream get the first source from the scheduler gamemusic = new oggstream(); if(!gamemusic->valid) DELETEP(gamemusic); setmusicvol(musicvol); nosound = false; } } if(nosound) { ALERR; if(context) alcDestroyContext(context); if(device) alcCloseDevice(device); conoutf("sound initialization failed!"); } }
/** * @brief Initializes the output with echo cancelling enabled * @return true on success, false otherwise * Creates a loopback device and a proxy source on the main output device. * If this function returns true only the proxy source should be used for * audio output. */ bool OpenAL2::initOutputEchoCancel() { // check for the needed extensions for echo cancelation if (alcIsExtensionPresent(alOutDev, "ALC_SOFT_loopback") != AL_TRUE) { qDebug() << "Device doesn't support loopback"; return false; } if (alIsExtensionPresent("AL_SOFT_source_latency") != AL_TRUE) { qDebug() << "Device doesn't support source latency"; return false; } if (!loadOpenALExtensions(alOutDev)) { qDebug() << "Couldn't load needed OpenAL extensions"; return false; } // source for proxy output alGenSources(1, &alProxySource); checkAlError(); // configuration for the loopback device ALCint attrs[] = {ALC_FORMAT_CHANNELS_SOFT, ALC_MONO_SOFT, ALC_FORMAT_TYPE_SOFT, ALC_SHORT_SOFT, ALC_FREQUENCY, IAudioControl::AUDIO_SAMPLE_RATE, 0}; // End of List alProxyDev = alcLoopbackOpenDeviceSOFT(nullptr); checkAlcError(alProxyDev); if (!alProxyDev) { qDebug() << "Couldn't create proxy device"; alDeleteSources(1, &alProxySource); // cleanup source return false; } if (!alcIsRenderFormatSupportedSOFT(alProxyDev, attrs[5], attrs[1], attrs[3])) { qDebug() << "Unsupported format for loopback"; alcCloseDevice(alProxyDev); // cleanup loopback dev alDeleteSources(1, &alProxySource); // cleanup source return false; } alProxyContext = alcCreateContext(alProxyDev, attrs); checkAlcError(alProxyDev); if (!alProxyContext) { qDebug() << "Couldn't create proxy context"; alcCloseDevice(alProxyDev); // cleanup loopback dev alDeleteSources(1, &alProxySource); // cleanup source return false; } if (!alcMakeContextCurrent(alProxyContext)) { qDebug() << "Cannot activate proxy context"; alcDestroyContext(alProxyContext); alcCloseDevice(alProxyDev); // cleanup loopback dev alDeleteSources(1, &alProxySource); // cleanup source return false; } qDebug() << "Echo cancelation enabled"; return true; }