void audio_output::init(int i) { if (!_initialized) { if (i < 0) { if (!(_device = alcOpenDevice(NULL))) { throw exc(_("No OpenAL device available.")); } } else if (i >= static_cast<int>(_devices.size())) { throw exc(str::asprintf(_("OpenAL device '%s' is not available."), _("unknown"))); } else { if (!(_device = alcOpenDevice(_devices[i].c_str()))) { throw exc(str::asprintf(_("OpenAL device '%s' is not available."), _devices[i].c_str())); } } if (!(_context = alcCreateContext(_device, NULL))) { alcCloseDevice(_device); throw exc(_("No OpenAL context available.")); } alcMakeContextCurrent(_context); set_openal_versions(); _buffers.resize(_num_buffers); alGenBuffers(_num_buffers, &(_buffers[0])); if (alGetError() != AL_NO_ERROR) { alcMakeContextCurrent(NULL); alcDestroyContext(_context); alcCloseDevice(_device); throw exc(_("Cannot create OpenAL buffers.")); } alGenSources(1, &_source); if (alGetError() != AL_NO_ERROR) { alDeleteBuffers(_num_buffers, &(_buffers[0])); alcMakeContextCurrent(NULL); alcDestroyContext(_context); alcCloseDevice(_device); throw exc(_("Cannot create OpenAL source.")); } /* Comment from alffmpeg.c: * "Set parameters so mono sources won't distance attenuate" */ alSourcei(_source, AL_SOURCE_RELATIVE, AL_TRUE); alSourcei(_source, AL_ROLLOFF_FACTOR, 0); if (alGetError() != AL_NO_ERROR) { alDeleteSources(1, &_source); alDeleteBuffers(_num_buffers, &(_buffers[0])); alcMakeContextCurrent(NULL); alcDestroyContext(_context); alcCloseDevice(_device); throw exc(_("Cannot set OpenAL source parameters.")); } _state = 0; _initialized = true; } }
void AudioController::initialize() { #ifndef __ANDROID__ _alcDevice = alcOpenDevice (NULL); if (!_alcDevice) { LOG_ERROR("AudioController::initialize() error. Unable to open OpenAL device.\n"); return; } _alcContext = alcCreateContext(_alcDevice, NULL); ALCenum alcErr = alcGetError(_alcDevice); if (!_alcContext || alcErr != ALC_NO_ERROR) { alcCloseDevice (_alcDevice); LOG_ERROR_VARG("AudioController::initialize() error. Unable to create OpenAL context. Error: %d\n", alcErr); return; } alcMakeContextCurrent(_alcContext); alcErr = alcGetError(_alcDevice); if (alcErr != ALC_NO_ERROR) { LOG_ERROR_VARG("AudioController::initialize() error. Unable to make OpenAL context current. Error: %d\n", alcErr); } #else // Create the engine. SLresult result = slCreateEngine(&_engineObject, 0, NULL, 0, NULL, NULL); if (result != SL_RESULT_SUCCESS) { LOG_ERROR("AudioController::initialize() error. Unable to create OpenSL engine."); return; } // Realize the engine. result = (*_engineObject)->Realize(_engineObject, SL_BOOLEAN_FALSE); if (result != SL_RESULT_SUCCESS) { LOG_ERROR("AudioController::initialize() error. Unable to realize OpenSL engine."); return; } // Get the engine interface in order to create other objects later on. result = (*_engineObject)->GetInterface(_engineObject, SL_IID_ENGINE, &_engineEngine); if (result != SL_RESULT_SUCCESS) { LOG_ERROR("AudioController::initialize() error. Unable to retrieve OpenSL engine interface."); return; } // Create the output mix. result = (*_engineEngine)->CreateOutputMix(_engineEngine, &_outputMixObject, 0, NULL, NULL); if (result != SL_RESULT_SUCCESS) { LOG_ERROR("AudioController::initialize() error. Unable to create OpenSL output mix."); return; } // Realize the output mix. result = (*_outputMixObject)->Realize(_outputMixObject, SL_BOOLEAN_FALSE); if (result != SL_RESULT_SUCCESS) { LOG_ERROR("AudioController::initialize() error. Unable to realize OpenSL output mix."); return; } #endif }
Sound_Renderer_AL::Sound_Renderer_AL() : m_device(0), m_context(0), m_bgm(0), m_bgm_source(0) { #ifndef _MACOSX #ifdef _WINDOWS m_openal32 = LoadLibrary("OpenAL32.dll"); #else m_openal32 = LoadLibrary("libopenal.so"); if(!m_openal32) m_openal32 = LoadLibrary("libopenal.so.1"); #endif if(!m_openal32) { std::cerr << "Loading OpenAL32.dll failed." << std::endl; throw Sound_Init_Failure(); } g_alBufferData = (alBufferData_fcn)GetProcAddress(m_openal32, "alBufferData"); g_alcCloseDevice = (alcCloseDevice_fcn)GetProcAddress(m_openal32, "alcCloseDevice"); g_alcCreateContext = (alcCreateContext_fcn)GetProcAddress(m_openal32, "alcCreateContext"); g_alcDestroyContext = (alcDestroyContext_fcn)GetProcAddress(m_openal32, "alcDestroyContext"); g_alIsExtensionPresent = (alIsExtensionPresent_fcn)GetProcAddress(m_openal32, "alIsExtensionPresent"); g_alcMakeContextCurrent = (alcMakeContextCurrent_fcn)GetProcAddress(m_openal32, "alcMakeContextCurrent"); g_alcOpenDevice = (alcOpenDevice_fcn)GetProcAddress(m_openal32, "alcOpenDevice"); g_alDeleteBuffers = (alDeleteBuffers_fcn)GetProcAddress(m_openal32, "alDeleteBuffers"); g_alDeleteSources = (alDeleteSources_fcn)GetProcAddress(m_openal32, "alDeleteSources"); g_alGenBuffers = (alGenBuffers_fcn)GetProcAddress(m_openal32, "alGenBuffers"); g_alGetError = (alGetError_fcn)GetProcAddress(m_openal32, "alGetError"); g_alGetListenerf = (alGetListenerf_fcn)GetProcAddress(m_openal32, "alGetListenerf"); g_alGetListenerfv = (alGetListenerfv_fcn)GetProcAddress(m_openal32, "alGetListenerfv"); g_alGetSourcef = (alGetSourcef_fcn)GetProcAddress(m_openal32, "alGetSourcef"); g_alGetSourcefv = (alGetSourcefv_fcn)GetProcAddress(m_openal32, "alGetSourcefv"); g_alGetSourcei = (alGetSourcei_fcn)GetProcAddress(m_openal32, "alGetSourcei"); g_alGenSources = (alGenSources_fcn)GetProcAddress(m_openal32, "alGenSources"); g_alListenerf = (alListenerf_fcn)GetProcAddress(m_openal32, "alListenerf"); g_alListenerfv = (alListenerfv_fcn)GetProcAddress(m_openal32, "alListenerfv"); g_alSourcef = (alSourcef_fcn)GetProcAddress(m_openal32, "alSourcef"); g_alSourcefv = (alSourcefv_fcn)GetProcAddress(m_openal32, "alSourcefv"); g_alSourcei = (alSourcei_fcn)GetProcAddress(m_openal32, "alSourcei"); g_alSourcePause = (alSourcePause_fcn)GetProcAddress(m_openal32, "alSourcePause"); g_alSourcePlay = (alSourcePlay_fcn)GetProcAddress(m_openal32, "alSourcePlay"); g_alSourceStop = (alSourceStop_fcn)GetProcAddress(m_openal32, "alSourceStop"); if(!g_alBufferData || !g_alcCloseDevice || !g_alcCreateContext || !g_alcDestroyContext || !g_alIsExtensionPresent || !g_alcMakeContextCurrent || !g_alcOpenDevice || !g_alDeleteBuffers || !g_alDeleteSources || !g_alGenBuffers || !g_alGetError || !g_alGetListenerf || !g_alGetListenerfv || !g_alGetSourcef || !g_alGetSourcefv || !g_alGetSourcei || !g_alGenSources || !g_alListenerf || !g_alListenerfv || !g_alSourcef || !g_alSourcefv || !g_alSourcei || !g_alSourcePause || !g_alSourcePlay || !g_alSourceStop) { std::cerr << "Loading OpenAL32.dll failed." << std::endl; zero_handles(); FreeLibrary(m_openal32); throw Sound_Init_Failure(); } #else g_alBufferData = (alBufferData_fcn)::alBufferData; g_alcCloseDevice = (alcCloseDevice_fcn)::alcCloseDevice; g_alcCreateContext = (alcCreateContext_fcn)::alcCreateContext; g_alcDestroyContext = (alcDestroyContext_fcn)::alcDestroyContext; g_alIsExtensionPresent = (alIsExtensionPresent_fcn)::alIsExtensionPresent; g_alcMakeContextCurrent = (alcMakeContextCurrent_fcn)::alcMakeContextCurrent; g_alcOpenDevice = (alcOpenDevice_fcn)::alcOpenDevice; g_alDeleteBuffers = (alDeleteBuffers_fcn)::alDeleteBuffers; g_alDeleteSources = (alDeleteSources_fcn)::alDeleteSources; g_alGenBuffers = (alGenBuffers_fcn)::alGenBuffers; g_alGetError = (alGetError_fcn)::alGetError; g_alGetListenerf = (alGetListenerf_fcn)::alGetListenerf; g_alGetListenerfv = (alGetListenerfv_fcn)::alGetListenerfv; g_alGetSourcef = (alGetSourcef_fcn)::alGetSourcef; g_alGetSourcefv = (alGetSourcefv_fcn)::alGetSourcefv; g_alGetSourcei = (alGetSourcei_fcn)::alGetSourcei; g_alGenSources = (alGenSources_fcn)::alGenSources; g_alListenerf = (alListenerf_fcn)::alListenerf; g_alListenerfv = (alListenerfv_fcn)::alListenerfv; g_alSourcef = (alSourcef_fcn)::alSourcef; g_alSourcefv = (alSourcefv_fcn)::alSourcefv; g_alSourcei = (alSourcei_fcn)::alSourcei; g_alSourcePause = (alSourcePause_fcn)::alSourcePause; g_alSourcePlay = (alSourcePlay_fcn)::alSourcePlay; g_alSourceStop = (alSourceStop_fcn)::alSourceStop; #endif m_device = alcOpenDevice()(0); if(!m_device) { zero_handles(); #ifndef _MACOSX FreeLibrary(m_openal32); #endif throw Sound_Init_Failure(); } m_context = alcCreateContext()(m_device, 0); if(!m_context) { alcCloseDevice()(m_device); zero_handles(); #ifndef _MACOSX FreeLibrary(m_openal32); #endif throw Sound_Init_Failure(); } if(!alcMakeContextCurrent()(m_context)) { alcDestroyContext()(m_context); alcCloseDevice()(m_device); zero_handles(); #ifndef _MACOSX FreeLibrary(m_openal32); #endif throw Sound_Init_Failure(); } // Check for Vorbis extension functionality; seems to always fail :( alIsExtensionPresent()("AL_EXT_vorbis"); //cerr << "Valid Audio Formats: " << alutGetMIMETypes(ALUT_LOADER_BUFFER) << std::endl; ALfloat listener_position[] = {0.0f, 0.0f, 0.0f}; ALfloat listener_velocity[] = {0.0f, 0.0f, 0.0f}; ALfloat listener_forward_and_up[] = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; alListenerfv()(AL_POSITION, listener_position); alListenerfv()(AL_VELOCITY, listener_velocity); alListenerfv()(AL_ORIENTATION, listener_forward_and_up); }
//* // ======================================================================================================================= // ======================================================================================================================= // bool sound_InitLibrary(void) { int err; const ALfloat listenerVel[3] = { 0.0, 0.0, 0.0 }; const ALfloat listenerOri[6] = { 0.0, 0.0, 1.0, 0.0, 1.0, 0.0 }; char buf[512]; const ALCchar *deviceName; #if 0 // This code is disabled because enumerating devices apparently crashes PulseAudio on Fedora12 /* Get the available devices and print them. * Devices are separated by NUL chars ('\0') and the list of devices is * terminated by two NUL chars. */ deviceName = alcGetString(NULL, ALC_DEVICE_SPECIFIER); while (deviceName != NULL && *deviceName != '\0') { debug(LOG_SOUND, "available OpenAL device(s) are: %s", deviceName); deviceName += strlen(deviceName) + 1; } #endif #ifdef WZ_OS_WIN /* HACK: Select the "software" OpenAL device on Windows because it * provides 256 sound sources (unlike most Creative's default * which provides only 16), causing our lack of source-management * to be significantly less noticeable. */ device = alcOpenDevice("Generic Software"); // If the software device isn't available, fall back to default if (!device) #endif { // Open default device device = alcOpenDevice(nullptr); } if (!device) { debug(LOG_ERROR, "Couldn't open audio device."); return false; } // Print current device name and add it to dump info deviceName = alcGetString(device, ALC_DEVICE_SPECIFIER); debug(LOG_SOUND, "Current audio device: %s", deviceName); ssprintf(buf, "OpenAL Device Name: %s", deviceName); addDumpInfo(buf); context = alcCreateContext(device, nullptr); //NULL was contextAttributes if (!context) { debug(LOG_ERROR, "Couldn't open audio context."); return false; } alcMakeContextCurrent(context); err = sound_GetContextError(device); if (err != ALC_NO_ERROR) { debug(LOG_ERROR, "Couldn't initialize audio context: %s", alcGetString(device, err)); return false; } // Dump Open AL device info (depends on context) // to the crash handler for the dump file and debug log ssprintf(buf, "OpenAL Vendor: %s", alGetString(AL_VENDOR)); addDumpInfo(buf); debug(LOG_SOUND, "%s", buf); ssprintf(buf, "OpenAL Version: %s", alGetString(AL_VERSION)); addDumpInfo(buf); debug(LOG_SOUND, "%s", buf); ssprintf(buf, "OpenAL Renderer: %s", alGetString(AL_RENDERER)); addDumpInfo(buf); debug(LOG_SOUND, "%s", buf); ssprintf(buf, "OpenAL Extensions: %s", alGetString(AL_EXTENSIONS)); addDumpInfo(buf); debug(LOG_SOUND, "%s", buf); openal_initialized = true; // Clear Error Codes alGetError(); alcGetError(device); alListener3f(AL_POSITION, 0.f, 0.f, 0.f); alListenerfv(AL_VELOCITY, listenerVel); alListenerfv(AL_ORIENTATION, listenerOri); alDistanceModel(AL_NONE); sound_GetError(); return true; }
void audioInit() { if (audioDevice) return; audioDevice = alcOpenDevice(NULL); if (!audioDevice) { LOG(("Audio Error: default sound device not present.")); return; } ALCint attributes[] = { ALC_STEREO_SOURCES, 8, 0 }; audioContext = alcCreateContext(audioDevice, attributes); alcMakeContextCurrent(audioContext); if (!_checkALCError()) return audioFinish(); ALfloat v[] = { 0.f, 0.f, -1.f, 0.f, 1.f, 0.f }; alListener3f(AL_POSITION, 0.f, 0.f, 0.f); alListener3f(AL_VELOCITY, 0.f, 0.f, 0.f); alListenerfv(AL_ORIENTATION, v); alDistanceModel(AL_NONE); alGenSources(1, ¬ifySource); alSourcef(notifySource, AL_PITCH, 1.f); alSourcef(notifySource, AL_GAIN, 1.f); alSource3f(notifySource, AL_POSITION, 0, 0, 0); alSource3f(notifySource, AL_VELOCITY, 0, 0, 0); alSourcei(notifySource, AL_LOOPING, 0); alGenBuffers(1, ¬ifyBuffer); if (!_checkALError()) return audioFinish(); QFile notify(st::newMsgSound); if (!notify.open(QIODevice::ReadOnly)) return audioFinish(); QByteArray blob = notify.readAll(); const char *data = blob.constData(); if (blob.size() < 44) return audioFinish(); if (*((const uint32*)(data + 0)) != 0x46464952) return audioFinish(); // ChunkID - "RIFF" if (*((const uint32*)(data + 4)) != uint32(blob.size() - 8)) return audioFinish(); // ChunkSize if (*((const uint32*)(data + 8)) != 0x45564157) return audioFinish(); // Format - "WAVE" if (*((const uint32*)(data + 12)) != 0x20746d66) return audioFinish(); // Subchunk1ID - "fmt " uint32 subchunk1Size = *((const uint32*)(data + 16)), extra = subchunk1Size - 16; if (subchunk1Size < 16 || (extra && extra < 2)) return audioFinish(); if (*((const uint16*)(data + 20)) != 1) return audioFinish(); // AudioFormat - PCM (1) uint16 numChannels = *((const uint16*)(data + 22)); if (numChannels != 1 && numChannels != 2) return audioFinish(); uint32 sampleRate = *((const uint32*)(data + 24)); uint32 byteRate = *((const uint32*)(data + 28)); uint16 blockAlign = *((const uint16*)(data + 32)); uint16 bitsPerSample = *((const uint16*)(data + 34)); if (bitsPerSample % 8) return audioFinish(); uint16 bytesPerSample = bitsPerSample / 8; if (bytesPerSample != 1 && bytesPerSample != 2) return audioFinish(); if (blockAlign != numChannels * bytesPerSample) return audioFinish(); if (byteRate != sampleRate * blockAlign) return audioFinish(); if (extra) { uint16 extraSize = *((const uint16*)(data + 36)); if (uint32(extraSize + 2) != extra) return audioFinish(); if (uint32(blob.size()) < 44 + extra) return audioFinish(); } if (*((const uint32*)(data + extra + 36)) != 0x61746164) return audioFinish(); // Subchunk2ID - "data" uint32 subchunk2Size = *((const uint32*)(data + extra + 40)); if (subchunk2Size % (numChannels * bytesPerSample)) return audioFinish(); uint32 numSamples = subchunk2Size / (numChannels * bytesPerSample); if (uint32(blob.size()) < 44 + extra + subchunk2Size) return audioFinish(); data += 44 + extra; ALenum format = 0; switch (bytesPerSample) { case 1: switch (numChannels) { case 1: format = AL_FORMAT_MONO8; break; case 2: format = AL_FORMAT_STEREO8; break; } break; case 2: switch (numChannels) { case 1: format = AL_FORMAT_MONO16; break; case 2: format = AL_FORMAT_STEREO16; break; } break; } if (!format) return audioFinish(); alBufferData(notifyBuffer, format, data, subchunk2Size, sampleRate); alSourcei(notifySource, AL_BUFFER, notifyBuffer); if (!_checkALError()) return audioFinish(); voicemsgs = new VoiceMessages(); }
//----------------------------------------------------------------------------// 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(); }
int main( int argc, char* argv[] ) { ALCdevice *dev; FILE *fh; struct stat sbuf; void *data; char *fname; int size; int i = 0; dev = alcOpenDevice( NULL ); if( dev == NULL ) { return 1; } /* Initialize ALUT. */ context_id = alcCreateContext( dev, NULL ); if(context_id == NULL) { alcCloseDevice( dev ); return 1; } alcMakeContextCurrent( context_id ); fixup_function_pointers(); init( ); if(argc == 1) { fname = VORBIS_FILE; } else { fname = argv[1]; } if(stat(fname, &sbuf) == -1) { perror(fname); return errno; } size = sbuf.st_size; data = malloc(size); if(data == NULL) { exit(1); } fh = fopen(fname, "rb"); if(fh == NULL) { fprintf(stderr, "Could not open %s\n", fname); free(data); exit(1); } fread(data, size, 1, fh); alutLoadVorbisp = (vorbisLoader *) alGetProcAddress((ALubyte *) VORBIS_FUNC); if(alutLoadVorbisp == NULL) { free(data); fprintf(stderr, "Could not GetProc %s\n", (ALubyte *) VORBIS_FUNC); exit(-4); } if(alutLoadVorbisp(vorbbuf, data, size) != AL_TRUE) { fprintf(stderr, "alutLoadVorbis failed\n"); exit(-2); } free(data); alSourcePlay( vorbsource ); while(SourceIsPlaying(vorbsource) == AL_TRUE) { sleep(1); } cleanup(); alcCloseDevice( dev ); return 0; }
int main() { ALCdevice* device = alcOpenDevice(NULL); ALCcontext* context = alcCreateContext(device, NULL); alcMakeContextCurrent(context); 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); ALuint buffers[1]; alGenBuffers(1, buffers); FILE* source = fopen("audio.wav", "rb"); 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); ALuint sources[1]; alGenSources(1, sources); 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); emscripten_async_call(playSource, reinterpret_cast<void*>(sources[0]), 700); return 0; }
bool OpenAL::OpenDevice() { // Initialisation of the module s_device = alcOpenDevice(s_deviceName.IsEmpty() ? nullptr : s_deviceName.GetConstBuffer()); // We choose the default device if (!s_device) { NazaraError("Failed to open default device"); return false; } // One context is enough s_context = alcCreateContext(s_device, nullptr); if (!s_context) { NazaraError("Failed to create context"); return false; } if (!alcMakeContextCurrent(s_context)) { NazaraError("Failed to activate context"); return false; } s_rendererName = reinterpret_cast<const char*>(alGetString(AL_RENDERER)); s_vendorName = reinterpret_cast<const char*>(alGetString(AL_VENDOR)); const ALchar* version = alGetString(AL_VERSION); if (version) { unsigned int major = version[0] - '0'; unsigned int minor = version[2] - '0'; if (major != 0 && major <= 9) { if (minor > 9) { NazaraWarning("Unable to retrieve OpenAL minor version (using 0)"); minor = 0; } s_version = major*100 + minor*10; NazaraDebug("OpenAL version: " + String::Number(major) + '.' + String::Number(minor)); } else { NazaraDebug("Unable to retrieve OpenAL major version"); s_version = 0; } } else { NazaraDebug("Unable to retrieve OpenAL version"); s_version = 0; } // We complete the formats table AudioFormat[AudioFormat_Mono] = AL_FORMAT_MONO16; AudioFormat[AudioFormat_Stereo] = AL_FORMAT_STEREO16; // "The presence of an enum value does not guarantee the applicability of an extension to the current context." if (alIsExtensionPresent("AL_EXT_MCFORMATS")) { AudioFormat[AudioFormat_Quad] = alGetEnumValue("AL_FORMAT_QUAD16"); AudioFormat[AudioFormat_5_1] = alGetEnumValue("AL_FORMAT_51CHN16"); AudioFormat[AudioFormat_6_1] = alGetEnumValue("AL_FORMAT_61CHN16"); AudioFormat[AudioFormat_7_1] = alGetEnumValue("AL_FORMAT_71CHN16"); } else if (alIsExtensionPresent("AL_LOKI_quadriphonic")) AudioFormat[AudioFormat_Quad] = alGetEnumValue("AL_FORMAT_QUAD16_LOKI"); return true; }
void SYS_InitSound() { #ifdef SYS_SOUNDDEBUG soundsLoaded = 0; soundsFree = SIZEOFWAVEPOOL; soundLog = fopen( soundLogFileName, "w" ); fprintf(soundLog, "SYS_InitSound() - OpenAL SKU - %d sounds in pool\n", soundsFree); if (alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT") == AL_TRUE) { const char* devicesStr = alcGetString(0, ALC_DEVICE_SPECIFIER); const char* defaultDeviceStr = alcGetString(0, ALC_DEFAULT_DEVICE_SPECIFIER); fprintf(soundLog, "OpenAL default device = %s\n", defaultDeviceStr); fprintf(soundLog, "All devices:\n"); const char* p = devicesStr; while( *p ) { fprintf(soundLog, "%s\n", p); p += (strlen(p) + 1); } } #endif // open device ALCdevice* device = alcOpenDevice(0); if ( !device ) { SYS_Error("Error opening OpenAL device\n"); return; } #ifdef SYS_SOUNDDEBUG const char* extStr = alcGetString(device, ALC_EXTENSIONS); fprintf(soundLog, "OpenAL extentions : %s\n", extStr); #endif alGetError(); // clear error code // create context ALCcontext* context = alcCreateContext(device,0); alcMakeContextCurrent(context); CheckForErrors(); // use linear distance model & disable doppler. alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED); alDopplerFactor(0.0f); // init wave pools memset(wavePool, 0, sizeof(struct SYS_Wave) * SIZEOFWAVEPOOL); freeList = wavePool; usedList = 0; for ( int i = 0; i < SIZEOFWAVEPOOL; ++i ) { freeList[i].prev = (i == 0) ? 0 : &wavePool[i-1]; freeList[i].next = (i == SIZEOFWAVEPOOL-1) ? 0 : &wavePool[i+1]; } // init source pool memset(sourcePool, 0, sizeof(ALuint) * SIZEOFSOURCEPOOL); CheckForErrors(); int error = mpg123_init(); if (error != MPG123_OK) { printf("Error mpg123_init() : %s\n", mpg123_plain_strerror(error)); } }
bool fsLowLevelAPI::openSoundDevice(u8 channel_num, u16 sample_rate, u16 snd_mix_buf_msec, SoundMixFunction snd_mix_func) { fprintf(stderr,"channel_num %d sample_rate %d snd_mix_buf_mse %d \n",channel_num, sample_rate, snd_mix_buf_msec); if (isSoundDeviceOpen()) { closeSoundDevice(); } pthread_mutex_init(&s_snd_mix_mutex, NULL); s_snd_mix_func = snd_mix_func; m_pAudioDevice = alcOpenDevice(NULL); if (m_pAudioDevice) { m_pAlcContext = alcCreateContext(m_pAudioDevice, NULL); alcMakeContextCurrent(m_pAlcContext); } ALenum err = alGetError(); if (err != AL_NO_ERROR) { return false; } alGenSources(1, &m_AudioSource); alGenBuffers(BUFFER_COUNT, m_AudioBuffers); s_channel_num = channel_num; s_sample_rate = sample_rate; s_snd_mix_buf_msec = snd_mix_buf_msec; s_snd_mix_buf_sample_num = sample_rate * snd_mix_buf_msec / 1000; s_bits_per_sample = 16; if (s_channel_num != 1 && s_channel_num != 2) { return false; } switch (s_bits_per_sample){ case 8: m_AudioFormat = (channel_num == 1) ? AL_FORMAT_MONO8 : AL_FORMAT_STEREO8; break; case 16: m_AudioFormat = (channel_num == 1) ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16; break; default: return 0; } // m_AudioFormat = AL_FORMAT_STEREO16; s_snd_mix_buf_size = 2 * s_channel_num * s_snd_mix_buf_sample_num; /*for (s32 i = 0; i < 2; i++) { s_snd_mix_buf[i] = ckMalloc(s_snd_mix_buf_size); ckMemMgr::memset(s_snd_mix_buf[i], 0, s_snd_mix_buf_size); }*/ buf = fsMalloc(s_snd_mix_buf_size); s_snd_mix_buf = fsMalloc(s_snd_mix_buf_size*2); //alGenBuffers(BUFFER_COUNT, m_AudioBuffers); //alGenSources(1, &m_AudioSource); //alSourcePlay(m_AudioSource); s_is_playing = true; if (pthread_create(&s_snd_play_thread, NULL, soundPlayThread, NULL) != 0) { s_is_playing = false; closeSoundDevice(); return false; } // if (pthread_create(&s_snd_play_thread, NULL, soundPlayThread, NULL) != 0) // { // s_is_playing = false; // closeSoundDevice(); // return false; // } // s_is_snd_dev_open = true; return true; }
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 }
// 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; }
int main( int argc, char* argv[] ) { ALCdevice *dev; time_t shouldend; int attrlist[] = { ALC_FREQUENCY, DEFFREQ, ALC_INVALID }; char *musicitr = musicstr; ALfloat pitch = 1.0; int beats; char note; int i; dev = alcOpenDevice( NULL ); if( dev == NULL ) { return 1; } cc = alcCreateContext( dev, attrlist); if(cc == NULL) { alcCloseDevice( dev ); return 1; } alcMakeContextCurrent( cc ); fixup_function_pointers(); if(argc == 1) { init(WAVEFILE); } else { init(argv[1]); } while(*musicitr) { alSourceStop( chords[0] ); alSourceStop( chords[1] ); alSourceStop( chords[2] ); while(*musicitr == ' ') { musicitr++; } for(i = 0; i < 3; i++) { switch(*musicitr) { case 'c': pitch = 0.500010; break; case 'd': pitch = 0.561223; break; case 'e': pitch = 0.629967; break; case 'f': pitch = 0.667425; break; case 'g': pitch = 0.749164; break; case 'a': pitch = 0.840898; break; case 'b': pitch = 0.943870; break; case 'C': pitch = 1.0; break; case 'D': pitch = 1.122465; break; case 'E': pitch = 1.259933; break; case 'F': pitch = 1.339704; break; case 'G': pitch = 1.498309; break; case 'A': pitch = 1.681796; break; case 'B': pitch = 1.897754; break; default: fprintf(stderr, "unknown note %d\n", *musicitr); break; } note = *musicitr; musicitr++; /* skip note */ fprintf(stderr, "chord[%d] = %c\n", i, note); alSourcef(chords[i], AL_PITCH, pitch); } alSourcePlayv(3, chords); while(*musicitr == ' ') { musicitr++; } beats = (int) *musicitr - '0'; musicitr++; fprintf(stderr, "beats %d\n", beats); micro_sleep(beats / 4.0 * 1000000); } alcDestroyContext( cc ); alcCloseDevice( dev ); cleanup(); return 0; }
int main( int argc, char* argv[] ) { ALCdevice *dev; int attrlist[] = { ALC_FREQUENCY, 44100, ALC_INVALID }; time_t shouldend; time_t start; int i; ALboolean done = AL_FALSE; dev = alcOpenDevice( NULL ); if( dev == NULL ) { return 1; } /* Initialize ALUT. */ for(i = 0; i < NUMCONTEXTS; i++) { context_ids[i] = alcCreateContext( dev, attrlist ); if(context_ids[i] == NULL) { return 1; } } fixup_function_pointers(); talBombOnError(); if(argc == 1) { init("sample.wav"); } else { init(argv[1]); } start = time(NULL); for(i = 0; i < NUMCONTEXTS; i++) { alcMakeContextCurrent(context_ids[i]); alSourcePlay( moving_sources[i] ); sleep(1); } #if 0 while(done == AL_FALSE) { iterate(); shouldend = time(NULL); if((shouldend - start) > 10) { for(i = 0; i < NUMCONTEXTS; i++) { alcMakeContextCurrent(context_ids[i]); alSourceStop(moving_sources[i]); } } done = AL_TRUE; for(i = 0; i < NUMCONTEXTS; i++) { alcMakeContextCurrent(context_ids[i]); done = done && !SourceIsPlaying( moving_sources[i] ); } } #else for(i = 0; i < 10; i++) { fprintf(stderr, "i = %d\n", i); sleep(1); } #endif cleanup(); return 0; }
OpenalSoundInterface::OpenalSoundInterface(float sampling_rate, int n_channels): SoundInterface (sampling_rate, n_channels) { car_src = NULL; ALfloat far_away[] = { 0.0f, 0.0f, 1000.0f }; ALfloat zeroes[] = { 0.0f, 0.0f, 0.0f }; ALfloat front[] = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f }; dev = alcOpenDevice( NULL ); if( dev == NULL ) { throw ("Could not open device"); } // Last zero is termination of the array, I think the current official beat SDK ignores that. // ALCint attr[] = { ALC_MONO_SOURCES, 1024, ALC_STEREO_SOURCES, 0, 0}; cc = alcCreateContext( dev, NULL); if(cc == NULL) { alcCloseDevice( dev ); throw ("Could not create context."); } alcMakeContextCurrent( cc ); alcGetError(dev); alGetError(); // Figure out the number of possible sources, watch out for an API update, perhaps // one can get that easier later with al(c)GetInteger (I'm sure that there is no way to // query this now) or even request a number with the context. const int MAX_SOURCES = 1024; int sources; ALuint sourcelist[MAX_SOURCES]; for (sources = 0; sources < MAX_SOURCES; sources++) { alGenSources(1, &sourcelist[sources]); if (alGetError() != AL_NO_ERROR) { break; } } int clear; for (clear = 0; clear < sources; clear++) { if (alIsSource(sourcelist[clear])) { alDeleteSources(1, &sourcelist[clear]); if (alGetError() != AL_NO_ERROR) { printf("Error in probing OpenAL sources.\n"); } } else { printf("Error in probing OpenAL sources.\n"); } } OSI_MAX_SOURCES = sources; OSI_MAX_STATIC_SOURCES = MAX(0, OSI_MAX_SOURCES - OSI_MIN_DYNAMIC_SOURCES); // Figure out the number of buffers. int buffers; ALuint bufferlist[MAX_SOURCES]; for (buffers = 0; buffers < MAX_SOURCES; buffers++) { alGenBuffers(1, &bufferlist[buffers]); if (alGetError() != AL_NO_ERROR) { break; } } for (clear = 0; clear < buffers; clear++) { if (alIsBuffer(bufferlist[clear])) { alDeleteBuffers(1, &bufferlist[clear]); if (alGetError() != AL_NO_ERROR) { printf("Error in probing OpenAL buffers.\n"); } } else { printf("Error in probing OpenAL buffers.\n"); } } OSI_MAX_BUFFERS = buffers; printf("OpenAL backend info:\n Vendor: %s\n Renderer: %s\n Version: %s\n", alGetString(AL_VENDOR), alGetString(AL_RENDERER), alGetString(AL_VERSION)); printf(" Available sources: %d%s\n", OSI_MAX_SOURCES, (sources >= MAX_SOURCES) ? " or more" : ""); printf(" Available buffers: %d%s\n", OSI_MAX_BUFFERS, (buffers >= MAX_SOURCES) ? " or more" : ""); alDistanceModel ( AL_INVERSE_DISTANCE ); int error = alGetError(); if (error != AL_NO_ERROR) { printf("OpenAL Error: %d alDistanceModel\n", error); } alDopplerFactor (1.0f); //alSpeedOfSound (SPEED_OF_SOUND); // not defined in linux yet. alDopplerVelocity (SPEED_OF_SOUND); error = alGetError(); if (error != AL_NO_ERROR) { printf("OpenAL Error: %d alDopplerX\n", error); } alListenerfv(AL_POSITION, far_away ); alListenerfv(AL_VELOCITY, zeroes ); alListenerfv(AL_ORIENTATION, front ); error = alGetError(); if (error != AL_NO_ERROR) { printf("OpenAL Error: %d alListenerfv\n", error); } engpri = NULL; global_gain = 1.0f; // initialise mappings grass.schar = &CarSoundData::grass; grass_skid.schar = &CarSoundData::grass_skid; road.schar = &CarSoundData::road; metal_skid.schar = &CarSoundData::drag_collision; backfire_loop.schar = &CarSoundData::engine_backfire; turbo.schar = &CarSoundData::turbo; axle.schar = &CarSoundData::axle; n_static_sources_in_use = 0; }
void audio_thread(void *args){ ToxAV *av = args; const char *device_list, *output_device = NULL; void *audio_device = NULL; _Bool call[MAX_CALLS] = {0}, preview = 0; _Bool groups_audio[MAX_NUM_GROUPS] = {0}; int perframe = (UTOX_DEFAULT_FRAME_A * UTOX_DEFAULT_SAMPLE_RATE_A) / 1000; uint8_t buf[perframe * 2 * UTOX_DEFAULT_AUDIO_CHANNELS]; //, dest[perframe * 2 * UTOX_DEFAULT_AUDIO_CHANNELS]; memset(buf, 0, sizeof(buf)); uint8_t audio_count = 0; _Bool record_on = 0; #ifdef AUDIO_FILTERING debug("Audio Filtering"); #ifdef ALC_LOOPBACK_CAPTURE_SAMPLES debug(" and Echo cancellation"); #endif debug(" enabled in this build\n"); #endif debug("frame size: %u\n", perframe); device_list = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER); if (device_list) { audio_device = (void*)device_list; debug("uTox audio input device list:\n"); while(*device_list) { debug("\t%s\n", device_list); postmessage(AUDIO_IN_DEVICE, UI_STRING_ID_INVALID, 0, (void*)device_list); device_list += strlen(device_list) + 1; } } postmessage(AUDIO_IN_DEVICE, STR_AUDIO_IN_NONE, 0, NULL); audio_detect(); if (alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT")) { device_list = alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER); } else { device_list = alcGetString(NULL, ALC_DEVICE_SPECIFIER); } if(device_list) { output_device = device_list; debug("uTox audio output device list:\n"); while(*device_list) { debug("\t%s\n", device_list); postmessage(AUDIO_OUT_DEVICE, 0, 0, (void*)device_list); device_list += strlen(device_list) + 1; } } device_out = alcOpenDevice(output_device); if(!device_out) { debug("alcOpenDevice() failed\n"); return; } int attrlist[] = { ALC_FREQUENCY, UTOX_DEFAULT_SAMPLE_RATE_A, ALC_INVALID }; context = alcCreateContext(device_out, attrlist); if(!alcMakeContextCurrent(context)) { debug("alcMakeContextCurrent() failed\n"); alcCloseDevice(device_out); return; } alGenSources(countof(source), source); static ALuint ringSrc[MAX_CALLS]; alGenSources(MAX_CALLS, ringSrc); /* Create buffer to store samples */ ALuint RingBuffer; alGenBuffers(1, &RingBuffer); { float frequency1 = 441.f; float frequency2 = 882.f; int seconds = 4; unsigned sample_rate = 22050; size_t buf_size = seconds * sample_rate * 2; //16 bit (2 bytes per sample) int16_t *samples = malloc(buf_size * sizeof(int16_t)); if (!samples) return; /*Generate an electronic ringer sound that quickly alternates between two frequencies*/ int index = 0; for(index = 0; index < buf_size; ++index) { if ((index / (sample_rate)) % 4 < 2 ) {//4 second ring cycle, first 2 secondsring, the rest(2 seconds) is silence if((index / 1000) % 2 == 1) { samples[index] = 5000 * sin((2.0 * 3.1415926 * frequency1) / sample_rate * index); //5000=amplitude(volume level). It can be from zero to 32700 } else { samples[index] = 5000 * sin((2.0 * 3.1415926 * frequency2) / sample_rate * index); } } else { samples[index] = 0; } } alBufferData(RingBuffer, AL_FORMAT_MONO16, samples, buf_size, sample_rate); free(samples); } { unsigned int i; for (i = 0; i < MAX_CALLS; ++i) { alSourcei(ringSrc[i], AL_LOOPING, AL_TRUE); alSourcei(ringSrc[i], AL_BUFFER, RingBuffer); } } Filter_Audio *f_a = NULL; audio_thread_init = 1; int16_t *preview_buffer = NULL; unsigned int preview_buffer_index = 0; #define PREVIEW_BUFFER_SIZE (UTOX_DEFAULT_SAMPLE_RATE_A / 2) while(1) { if(audio_thread_msg) { TOX_MSG *m = &audio_msg; if(!m->msg) { break; } switch(m->msg) { case AUDIO_SET_INPUT: { audio_device = m->data; if(record_on) { alccapturestop(device_in); alccaptureclose(device_in); } if(audio_count) { device_in = alcopencapture(audio_device); if(!device_in) { record_on = 0; } else { alccapturestart(device_in); record_on = 1; } } debug("set audio in\n"); break; } case AUDIO_SET_OUTPUT: { output_device = m->data; ALCdevice *device = alcOpenDevice(output_device); if(!device) { debug("alcOpenDevice() failed\n"); break; } ALCcontext *con = alcCreateContext(device, NULL); if(!alcMakeContextCurrent(con)) { debug("alcMakeContextCurrent() failed\n"); alcCloseDevice(device); break; } alcDestroyContext(context); alcCloseDevice(device_out); context = con; device_out = device; alGenSources(countof(source), source); alGenSources(MAX_CALLS, ringSrc); Tox *tox = toxav_get_tox(av); uint32_t num_chats = tox_count_chatlist(tox); if (num_chats != 0) { int32_t chats[num_chats]; uint32_t max = tox_get_chatlist(tox, chats, num_chats); unsigned int i; for (i = 0; i < max; ++i) { if (tox_group_get_type(tox, chats[i]) == TOX_GROUPCHAT_TYPE_AV) { GROUPCHAT *g = &group[chats[i]]; alGenSources(g->peers, g->source); } } } debug("set audio out\n"); break; } case AUDIO_PREVIEW_START: { preview = 1; audio_count++; preview_buffer = calloc(PREVIEW_BUFFER_SIZE, 2); preview_buffer_index = 0; if(!record_on) { device_in = alcopencapture(audio_device); if(device_in) { alccapturestart(device_in); record_on = 1; debug("Starting Audio Preview\n"); } } break; } case AUDIO_START: { audio_count++; if(!record_on) { device_in = alcopencapture(audio_device); if(device_in) { alccapturestart(device_in); record_on = 1; debug("Listening to audio\n"); yieldcpu(20); } } break; } case GROUP_AUDIO_CALL_START: { break; // TODO, new groups API audio_count++; groups_audio[m->param1] = 1; if(!record_on) { device_in = alcopencapture(audio_device); if(device_in) { alccapturestart(device_in); record_on = 1; debug("Starting Audio GroupCall\n"); } } break; } case AUDIO_PREVIEW_END: { preview = 0; audio_count--; free(preview_buffer); preview_buffer = NULL; if(!audio_count && record_on) { alccapturestop(device_in); alccaptureclose(device_in); record_on = 0; debug("Audio Preview Stopped\n"); } break; } case AUDIO_END: { if(!call[m->param1]) { break; } call[m->param1] = 0; audio_count--; if(!audio_count && record_on) { alccapturestop(device_in); alccaptureclose(device_in); record_on = 0; debug("stop\n"); } break; } case GROUP_AUDIO_CALL_END: { break; // TODO, new groups API if(!groups_audio[m->param1]) { break; } audio_count--; groups_audio[m->param1] = 0; if(!audio_count && record_on) { alccapturestop(device_in); alccaptureclose(device_in); record_on = 0; debug("stop\n"); } break; } case AUDIO_PLAY_RINGTONE: { if(!audible_notifications_enabled) { break; } alSourcePlay(ringSrc[m->param1]); break; } case AUDIO_STOP_RINGTONE: { ALint state; alGetSourcei(ringSrc[m->param1], AL_SOURCE_STATE, &state); if(state == AL_PLAYING) { alSourceStop(ringSrc[m->param1]); } break; } } audio_thread_msg = 0; } // TODO move this code to filter_audio.c #ifdef AUDIO_FILTERING if (!f_a && audio_filtering_enabled) { f_a = new_filter_audio(UTOX_DEFAULT_SAMPLE_RATE_A); if (!f_a) { audio_filtering_enabled = 0; debug("filter audio failed\n"); } else { debug("filter audio on\n"); } } else if (f_a && !audio_filtering_enabled) { kill_filter_audio(f_a); f_a = NULL; debug("filter audio off\n"); } #else if (audio_filtering_enabled) { audio_filtering_enabled = 0; } #endif _Bool sleep = 1; if(record_on) { ALint samples; _Bool frame = 0; /* If we have a device_in we're on linux so we can just call OpenAL, otherwise we're on something else so * we'll need to call audio_frame() to add to the buffer for us. */ if (device_in == (void*)1) { frame = audio_frame((void*)buf); if (frame) { /* We have an audio frame to use, continue without sleeping. */ sleep = 0; } } else { alcGetIntegerv(device_in, ALC_CAPTURE_SAMPLES, sizeof(samples), &samples); if(samples >= perframe) { alcCaptureSamples(device_in, buf, perframe); frame = 1; if (samples >= perframe * 2) { sleep = 0; } } } #ifdef AUDIO_FILTERING #ifdef ALC_LOOPBACK_CAPTURE_SAMPLES if (f_a && audio_filtering_enabled) { alcGetIntegerv(device_out, ALC_LOOPBACK_CAPTURE_SAMPLES, sizeof(samples), &samples); if(samples >= perframe) { int16_t buffer[perframe]; alcCaptureSamplesLoopback(device_out, buffer, perframe); pass_audio_output(f_a, buffer, perframe); set_echo_delay_ms(f_a, UTOX_DEFAULT_FRAME_A); if (samples >= perframe * 2) { sleep = 0; } } } #endif #endif if (frame) { _Bool voice = 1; #ifdef AUDIO_FILTERING if (f_a) { int ret = filter_audio(f_a, (int16_t*)buf, perframe); if (ret == -1) { debug("filter audio error\n"); } if (ret == 0) { voice = 0; } } #endif /* If push to talk, we don't have to do anything */ if (!check_ptt_key()) { voice = 0; //PTT is up, send nothing. } if (preview) { if (preview_buffer_index + perframe > PREVIEW_BUFFER_SIZE) { preview_buffer_index = 0; } sourceplaybuffer(0, preview_buffer + preview_buffer_index, perframe, UTOX_DEFAULT_AUDIO_CHANNELS, UTOX_DEFAULT_SAMPLE_RATE_A); if (voice) { memcpy(preview_buffer + preview_buffer_index, buf, perframe * sizeof(int16_t)); } else { memset(preview_buffer + preview_buffer_index, 0, perframe * sizeof(int16_t)); } preview_buffer_index += perframe; } if (voice) { int i, active_call_count = 0; for(i = 0; i < UTOX_MAX_NUM_FRIENDS; i++) { if( UTOX_SEND_AUDIO(i) ) { active_call_count++; TOXAV_ERR_SEND_FRAME error = 0; toxav_audio_send_frame(av, friend[i].number, (const int16_t *)buf, perframe, UTOX_DEFAULT_AUDIO_CHANNELS, UTOX_DEFAULT_SAMPLE_RATE_A, &error); if (error) { debug("toxav_send_audio error friend == %i, error == %i\n", i, error); } else { // debug("Send a frame to friend %i\n",i); if (i >= UTOX_MAX_CALLS) { debug("We're calling more peers than allowed by UTOX_MAX_CALLS, This is a bug\n"); break; } } } } // TODO REMOVED until new groups api can be implemented. /*Tox *tox = toxav_get_tox(av); uint32_t num_chats = tox_count_chatlist(tox); if (num_chats != 0) { int32_t chats[num_chats]; uint32_t max = tox_get_chatlist(tox, chats, num_chats); for (i = 0; i < max; ++i) { if (groups_audio[chats[i]]) { toxav_group_send_audio(tox, chats[i], (int16_t *)buf, perframe, UTOX_DEFAULT_AUDIO_CHANNELS, UTOX_DEFAULT_SAMPLE_RATE_A); } } }*/ } } } if (sleep) { yieldcpu(5); } } utox_filter_audio_kill(f_a); //missing some cleanup ? alDeleteSources(MAX_CALLS, ringSrc); alDeleteSources(countof(source), source); alDeleteBuffers(1, &RingBuffer); if(device_in) { if(record_on) { alcCaptureStop(device_in); } alcCaptureCloseDevice(device_in); } alcMakeContextCurrent(NULL); alcDestroyContext(context); alcCloseDevice(device_out); audio_thread_msg = 0; audio_thread_init = 0; debug("UTOX AUDIO:\tClean thread exit!\n"); }
int main(int argc, char *argv[]) { SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0"); // SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0"); /* initialize SDL first */ if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) { showInitError(std::string("Error initializing SDL: ") + SDL_GetError()); return 0; } if (!EventThread::allocUserEvents()) { showInitError("Error allocating SDL user events"); return 0; } #ifndef WORKDIR_CURRENT /* set working directory */ char *dataDir = SDL_GetBasePath(); if (dataDir) { int result = chdir(dataDir); (void)result; SDL_free(dataDir); } #endif /* now we load the config */ Config conf; conf.read(argc, argv); if (!conf.gameFolder.empty()) if (chdir(conf.gameFolder.c_str()) != 0) { showInitError(std::string("Unable to switch into gameFolder ") + conf.gameFolder); return 0; } conf.readGameINI(); if (conf.windowTitle.empty()) conf.windowTitle = conf.game.title; assert(conf.rgssVersion >= 1 && conf.rgssVersion <= 3); printRgssVersion(conf.rgssVersion); int imgFlags = IMG_INIT_PNG | IMG_INIT_JPG; if (IMG_Init(imgFlags) != imgFlags) { showInitError(std::string("Error initializing SDL_image: ") + SDL_GetError()); SDL_Quit(); return 0; } if (TTF_Init() < 0) { showInitError(std::string("Error initializing SDL_ttf: ") + SDL_GetError()); IMG_Quit(); SDL_Quit(); return 0; } if (Sound_Init() == 0) { showInitError(std::string("Error initializing SDL_sound: ") + Sound_GetError()); TTF_Quit(); IMG_Quit(); SDL_Quit(); return 0; } SDL_Window *win; Uint32 winFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_INPUT_FOCUS; if (conf.winResizable) winFlags |= SDL_WINDOW_RESIZABLE; if (conf.fullscreen) winFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP; win = SDL_CreateWindow(conf.windowTitle.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, conf.defScreenW, conf.defScreenH, winFlags); if (!win) { showInitError(std::string("Error creating window: ") + SDL_GetError()); return 0; } /* OSX and Windows have their own native ways of * dealing with icons; don't interfere with them */ #ifdef __LINUX__ setupWindowIcon(conf, win); #else (void) setupWindowIcon; #endif ALCdevice *alcDev = alcOpenDevice(0); if (!alcDev) { showInitError("Error opening OpenAL device"); SDL_DestroyWindow(win); TTF_Quit(); IMG_Quit(); SDL_Quit(); return 0; } SDL_DisplayMode mode; SDL_GetDisplayMode(0, 0, &mode); /* Can't sync to display refresh rate if its value is unknown */ if (!mode.refresh_rate) conf.syncToRefreshrate = false; EventThread eventThread; RGSSThreadData rtData(&eventThread, argv[0], win, alcDev, mode.refresh_rate, conf); int winW, winH; SDL_GetWindowSize(win, &winW, &winH); rtData.windowSizeMsg.post(Vec2i(winW, winH)); /* Load and post key bindings */ rtData.bindingUpdateMsg.post(loadBindings(conf)); /* Start RGSS thread */ SDL_Thread *rgssThread = SDL_CreateThread(rgssThreadFun, "rgss", &rtData); /* Start event processing */ eventThread.process(rtData); /* Request RGSS thread to stop */ rtData.rqTerm.set(); /* Wait for RGSS thread response */ for (int i = 0; i < 1000; ++i) { /* We can stop waiting when the request was ack'd */ if (rtData.rqTermAck) { Debug() << "RGSS thread ack'd request after" << i*10 << "ms"; break; } /* Give RGSS thread some time to respond */ SDL_Delay(10); } /* If RGSS thread ack'd request, wait for it to shutdown, * otherwise abandon hope and just end the process as is. */ if (rtData.rqTermAck) SDL_WaitThread(rgssThread, 0); else SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, conf.windowTitle.c_str(), "The RGSS script seems to be stuck and mkxp will now force quit", win); if (!rtData.rgssErrorMsg.empty()) { Debug() << rtData.rgssErrorMsg; SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, conf.windowTitle.c_str(), rtData.rgssErrorMsg.c_str(), win); } /* Clean up any remainin events */ eventThread.cleanup(); Debug() << "Shutting down."; alcCloseDevice(alcDev); SDL_DestroyWindow(win); Sound_Quit(); TTF_Quit(); IMG_Quit(); SDL_Quit(); return 0; }
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; }
void *decode_audio_thread(void *arg) { INFO("Started decode audio thread!"); av_session_t *_phone = arg; _phone->running_decaud = 1; //int recved_size; //uint8_t dest [RTP_PAYLOAD_SIZE]; int frame_size = AUDIO_FRAME_SIZE; //int data_size; ALCdevice *dev; ALCcontext *ctx; ALuint source, *buffers; dev = alcOpenDevice(NULL); ctx = alcCreateContext(dev, NULL); alcMakeContextCurrent(ctx); int openal_buffers = 5; buffers = calloc(sizeof(ALuint) * openal_buffers, 1); alGenBuffers(openal_buffers, buffers); alGenSources((ALuint)1, &source); alSourcei(source, AL_LOOPING, AL_FALSE); ALuint buffer; ALint ready; uint16_t zeros[frame_size]; memset(zeros, 0, frame_size); int16_t PCM[frame_size]; int i; for (i = 0; i < openal_buffers; ++i) { alBufferData(buffers[i], AL_FORMAT_MONO16, zeros, frame_size, 48000); } alSourceQueueBuffers(source, openal_buffers, buffers); alSourcePlay(source); if (alGetError() != AL_NO_ERROR) { fprintf(stderr, "Error starting audio\n"); goto ending; } int dec_frame_len = 0; while (_phone->running_decaud) { alGetSourcei(source, AL_BUFFERS_PROCESSED, &ready); if (ready <= 0) continue; dec_frame_len = toxav_recv_audio(_phone->av, frame_size, PCM); /* Play the packet */ if (dec_frame_len > 0) { alSourceUnqueueBuffers(source, 1, &buffer); alBufferData(buffer, AL_FORMAT_MONO16, PCM, dec_frame_len * 2 * 1, 48000); int error = alGetError(); if (error != AL_NO_ERROR) { fprintf(stderr, "Error setting buffer %d\n", error); break; } alSourceQueueBuffers(source, 1, &buffer); if (alGetError() != AL_NO_ERROR) { fprintf(stderr, "Error: could not buffer audio\n"); break; } alGetSourcei(source, AL_SOURCE_STATE, &ready); if (ready != AL_PLAYING) alSourcePlay(source); } usleep(1000); } ending: /* clean up codecs */ //pthread_mutex_lock(&cs->ctrl_mutex); /* alDeleteSources(1, &source); alDeleteBuffers(openal_buffers, buffers); alcMakeContextCurrent(NULL); alcDestroyContext(ctx); alcCloseDevice(dev); */ //pthread_mutex_unlock(&cs->ctrl_mutex); _phone->running_decaud = -1; pthread_exit ( NULL ); }
void Audio_Init(void) { device = alcOpenDevice(NULL); context = alcCreateContext(device, NULL); alcMakeContextCurrent(context); }
// TODO: generate buffers separately DeviceError open_device(DeviceType type, int32_t selection, uint32_t* device_idx) { if (size[type] <= selection || selection < 0) return de_InvalidSelection; lock; uint32_t i; for (i = 0; i < MAX_DEVICES && running[type][i] != NULL; i ++); if (i == MAX_DEVICES) { unlock; return de_AllDevicesBusy; } else *device_idx = i; Device* device = running[type][*device_idx] = calloc(1, sizeof(Device));; device->selection = selection; for (i = 0; i < *device_idx; i ++) { /* Check if any previous has the same selection */ if ( running[type][i]->selection == selection ) { device->dhndl = running[type][i]->dhndl; if (type == output) { device->ctx = running[type][i]->ctx; memcpy(device->buffers, running[type][i]->buffers, sizeof(running[type][i]->buffers)); device->source = running[type][i]->source; } device->ref_count++; pthread_mutex_init(device->mutex, NULL); unlock; return de_None; } } if (type == input) { device->dhndl = alcCaptureOpenDevice(devices_names[type][selection], av_DefaultSettings.audio_sample_rate, AL_FORMAT_MONO16, frame_size * 2); device->VAD_treshold = VAD_THRESHOLD_DEFAULT; } else { device->dhndl = alcOpenDevice(devices_names[type][selection]); if ( !device->dhndl ) { free(device); running[type][*device_idx] = NULL; unlock; return de_FailedStart; } device->ctx = alcCreateContext(device->dhndl, NULL); alcMakeContextCurrent(device->ctx); alGenBuffers(openal_bufs, device->buffers); alGenSources((uint32_t)1, &device->source); alSourcei(device->source, AL_LOOPING, AL_FALSE); uint16_t zeros[frame_size]; memset(zeros, 0, frame_size*2); for ( i =0; i < openal_bufs; ++i) { alBufferData(device->buffers[i], AL_FORMAT_MONO16, zeros, frame_size*2, sample_rate); } alSourceQueueBuffers(device->source, openal_bufs, device->buffers); alSourcePlay(device->source); } if (alcGetError(device->dhndl) != AL_NO_ERROR) { free(device); running[type][*device_idx] = NULL; unlock; return de_FailedStart; } if (type == input) { alcCaptureStart(device->dhndl); thread_paused = _False; } pthread_mutex_init(device->mutex, NULL); unlock; return de_None; }
int main(int, char**) { // Setup SDL if (SDL_Init(SDL_INIT_EVERYTHING) != 0) return -1; // Setup window SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); SDL_DisplayMode current; SDL_GetCurrentDisplayMode(0, ¤t); SDL_Window *sdl_window = SDL_CreateWindow("testbed", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE); SDL_GLContext glcontext = SDL_GL_CreateContext(sdl_window); // Setup ImGui binding ImGui_ImplSdl_Init(sdl_window); // OpenAL: Open and initialize a device with default settings // and set current context, making the program ready to call OpenAL functions. ALCdevice* alc_device = NULL; ALCcontext* alc_ctx = NULL; const char* alc_device_spec = NULL; const char* alc_ext = NULL; const char* al_vendor = NULL; const char* al_renderer = NULL; const char* al_version = NULL; const char* al_ext = NULL; { alc_device = alcOpenDevice(NULL); if(!alc_device) { ERR("Could not open a device!\n"); return 1; } alc_ctx = alcCreateContext(alc_device, NULL); if(alc_ctx == NULL || alcMakeContextCurrent(alc_ctx) == ALC_FALSE) { if(alc_ctx != NULL) alcDestroyContext(alc_ctx); alcCloseDevice(alc_device); ERR("Could not set a context!\n"); return 1; } alc_device_spec = alcGetString(alc_device, ALC_DEVICE_SPECIFIER); alc_ext = alcGetString(alc_device, ALC_EXTENSIONS); //alcGetIntegerv(alc_device, ALC_MAJOR_VERSION, 1, &alc_major); //alcGetIntegerv(alc_device, ALC_MINOR_VERSION, 1, &alc_minor); al_vendor = alGetString(AL_VENDOR); al_renderer = alGetString(AL_RENDERER); al_version = alGetString(AL_VERSION); al_ext = alGetString(AL_EXTENSIONS); } // Load resource SResources Resources; { bool ok = LoadResources(Resources); if (!ok) { ERR("Could not load all program resource.\n"); return 1; } } // openal sources SMgrState MgrState; SEmitter* SpatialEmit; SEmitter* AmbiantLoop; { Mgr_Init(MgrState); SpatialEmit = &MgrState.Emitters[0]; AmbiantLoop = &MgrState.Emitters[1]; alSourcei(SpatialEmit->Source, AL_BUFFER, Resources.albuf_monoloop); alSourcei(SpatialEmit->Source, AL_LOOPING, AL_TRUE); alSourcei(SpatialEmit->Source, AL_DIRECT_CHANNELS_SOFT, AL_FALSE); SpatialEmit->active = false; SpatialEmit->dB = 0.f; SpatialEmit->pos[0] = .5f; SpatialEmit->pos[1] = .75f; SpatialEmit->pos[2] = -3; SpatialEmit->radius = 0.01f; alSourcei(AmbiantLoop->Source, AL_BUFFER, Resources.albuf_stereoloop); alSourcei(AmbiantLoop->Source, AL_LOOPING, AL_TRUE); alSourcei(AmbiantLoop->Source, AL_DIRECT_CHANNELS_SOFT, AL_TRUE); AmbiantLoop->active = false; AmbiantLoop->dB = -9.f; } // Main loop bool done = false; while (!done) { SDL_Event event; while (SDL_PollEvent(&event)) { ImGui_ImplSdl_ProcessEvent(&event); if (event.type == SDL_QUIT) done = true; } uint CurTimeMs = SDL_GetTicks(); int ActiveSources = Mgr_Update(MgrState); ImGui_ImplSdl_NewFrame(sdl_window); ImGui::SetNextWindowPos(ImVec2(10, 10)); ImGui::SetNextWindowSize(ImVec2(500, 700)); ImGui::Begin("main", NULL, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoMove); // top bar. { if (ImGui::Button("Quit")) break; ImGui::SameLine(); static bool ShowImguiHelp = false; ImGui::Checkbox("show imgui help", &ShowImguiHelp); if (ShowImguiHelp) ImGui::ShowTestWindow(); // documentation shortcut } ImGui::Spacing(); // ----------------- // Openal info: if (ImGui::CollapsingHeader("OpenAL info")) { ImGui::Columns(2, "OpenAL_info"); ImGui::Text("device"); ImGui::NextColumn(); ImGui::TextWrapped(alc_device_spec); ImGui::NextColumn(); ImGui::Text("vendor"); ImGui::NextColumn(); ImGui::TextWrapped(al_vendor); ImGui::NextColumn(); ImGui::Text("renderer"); ImGui::NextColumn(); ImGui::TextWrapped(al_renderer); ImGui::NextColumn(); ImGui::Text("version"); ImGui::NextColumn(); ImGui::TextWrapped(al_version); ImGui::NextColumn(); ImGui::Separator(); ImGui::Text("ALC extensions"); ImGui::NextColumn(); ImGui::TextWrapped(alc_ext); ImGui::NextColumn(); ImGui::Separator(); ImGui::Text("AL extensions"); ImGui::NextColumn(); ImGui::TextWrapped(al_ext); ImGui::NextColumn(); ImGui::Columns(1); } ImGui::Spacing(); // ----------------- // basic test if (ImGui::CollapsingHeader("Basic", NULL, true, true)) { static float mono_gaindB = -3.f; static float stereo_gaindB = -3.f; if (ImGui::Button("Play mono")) { Mgr_Play(MgrState, Resources.albuf_mono, mono_gaindB); } ImGui::SameLine(); ImGui::SliderFloat("##vol1", &mono_gaindB, -60, 6, "%.1fdB"); if (ImGui::Button("Play stereo")) { Mgr_Play(MgrState, Resources.albuf_stereo, stereo_gaindB); } ImGui::SameLine(); ImGui::SliderFloat("##vol2", &stereo_gaindB, -60, 6, "%.1fdB"); } ImGui::Spacing(); // ----------------- // Direct if (ImGui::CollapsingHeader("Direct", NULL, true, true)) { ImGui::Checkbox("Ambiance", &AmbiantLoop->active); ImGui::SameLine(); ImGui::SliderFloat("##vol0", &AmbiantLoop->dB, -60, 6, "%.1fdB"); } ImGui::Spacing(); // ----------------- // Spatialized if (ImGui::CollapsingHeader("Spatialized", NULL, true, true)) { ImGui::Checkbox("Mosquito", &SpatialEmit->active); ImGui::SameLine(); ImGui::SliderFloat("##vol4", &SpatialEmit->dB, -60, 6, "%.1fdB"); ImGui::SliderFloat("radius", &SpatialEmit->radius, 0, 5); static uint PrevTime = 0; static float PrevPos[3]; static bool automove = false; ImGui::Checkbox("Auto move", &automove); if (automove) { struct SLocal { static void anim(float t, float v[3]) { float w = (t*2*PI); v[0] = 5*sinf(w*2+1) + 3*sinf(w*6+2) + 2*sinf(w*6+3) + 1*sinf(w*9+4); v[1] = 5*sinf(w*3+5) + 3*sinf(w*4+6) + 2*sinf(w*7+7) + 1*sinf(w*8+8); v[2] = 5*sinf(w*4+9) + 3*sinf(w*5+1) + 2*sinf(w*8+2) + 1*sinf(w*7+3); } }; float t = (CurTimeMs % 60000) / 60000.f; SLocal::anim(t, SpatialEmit->pos); } ImGui::InputFloat3("pos", SpatialEmit->pos); ImGui::InputFloat3("vel", SpatialEmit->vel); ImGuiPointOnMap("top", &SpatialEmit->pos[0], &SpatialEmit->pos[2], SpatialEmit->radius, 10, 0.25f); ImGui::SameLine(); ImGuiPointOnMap("front", &SpatialEmit->pos[0], &SpatialEmit->pos[1], SpatialEmit->radius, 10, 0.25f); if (PrevTime != 0 && CurTimeMs > PrevTime) { float dt = 0.001f*(CurTimeMs-PrevTime); float k = 1.f; SpatialEmit->vel[0] = k * ((SpatialEmit->pos[0] - PrevPos[0]) / dt); SpatialEmit->vel[1] = k * ((SpatialEmit->pos[1] - PrevPos[1]) / dt); SpatialEmit->vel[2] = k * ((SpatialEmit->pos[2] - PrevPos[2]) / dt); } PrevTime = CurTimeMs; memcpy(PrevPos, SpatialEmit->pos, sizeof(PrevPos)); } ImGui::Spacing(); // ----------------- // basic test if (ImGui::CollapsingHeader("Tests", NULL, true, true)) { static const float Front[3] = {0,0,-1}; if (ImGui::Button("stereo base")) { Mgr_Play(MgrState, Resources.albuf_stereo, -3, false); } ImGui::SameLine(); if (ImGui::Button("stereo direct")) { Mgr_Play(MgrState, Resources.albuf_stereo, -3, true); } if (ImGui::Button("mono base")) { Mgr_Play(MgrState, Resources.albuf_mono, -3, false); } ImGui::SameLine(); if (ImGui::Button("mono direct")) { Mgr_Play(MgrState, Resources.albuf_mono, -3, true); } ImGui::SameLine(); if (ImGui::Button("mono 3d narrow")) { Mgr_Play(MgrState, Resources.albuf_mono, -3, Front, 0.01f); } ImGui::SameLine(); if (ImGui::Button("mono 3d wide")) { Mgr_Play(MgrState, Resources.albuf_mono, -3, Front, 1.f); } ImGui::SameLine(); if (ImGui::Button("mono 3d omni")) { Mgr_Play(MgrState, Resources.albuf_mono, -3, Front, 10.f); } } ImGui::Spacing(); // ----------------- // status { ImGui::Separator(); ImGui::Text("Active Sources: %d / %d\n", ActiveSources, MGR_MAX_SOURCES); ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } ImGui::End(); // Rendering ImVec4 clear_color = ImColor(114, 144, 154); glViewport(0, 0, (int)ImGui::GetIO().DisplaySize.x, (int)ImGui::GetIO().DisplaySize.y); glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w); glClear(GL_COLOR_BUFFER_BIT); ImGui::Render(); SDL_GL_SwapWindow(sdl_window); } Mgr_Destroy(MgrState); FreeResources(Resources); // OpenAL: cleanup { alcMakeContextCurrent(NULL); alcDestroyContext(alc_ctx); alcCloseDevice(alc_device); } // Cleanup ImGui_ImplSdl_Shutdown(); SDL_GL_DeleteContext(glcontext); SDL_DestroyWindow(sdl_window); SDL_Quit(); return 0; }
// TODO: generate buffers separately DeviceError open_device(DeviceType type, int32_t selection, uint32_t* device_idx, uint32_t sample_rate, uint32_t frame_duration, uint8_t channels) { if (size[type] <= selection || selection < 0) return de_InvalidSelection; if (channels != 1 && channels != 2) return de_UnsupportedMode; lock; const uint32_t frame_size = (sample_rate * frame_duration / 1000); uint32_t i; for (i = 0; i < MAX_DEVICES && running[type][i] != NULL; ++i); if (i == MAX_DEVICES) { unlock; return de_AllDevicesBusy; } else *device_idx = i; for (i = 0; i < MAX_DEVICES; i ++) { /* Check if any device has the same selection */ if ( running[type][i] && running[type][i]->selection == selection ) { // printf("a%d-%d:%p ", selection, i, running[type][i]->dhndl); running[type][*device_idx] = running[type][i]; running[type][i]->ref_count ++; unlock; return de_None; } } Device* device = running[type][*device_idx] = calloc(1, sizeof(Device)); device->selection = selection; device->sample_rate = sample_rate; device->frame_duration = frame_duration; device->sound_mode = channels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16; if (pthread_mutex_init(device->mutex, NULL) != 0) { free(device); unlock; return de_InternalError; } if (type == input) { device->dhndl = alcCaptureOpenDevice(devices_names[type][selection], sample_rate, device->sound_mode, frame_size * 2); #ifdef AUDIO device->VAD_treshold = user_settings->VAD_treshold; #endif } else { device->dhndl = alcOpenDevice(devices_names[type][selection]); if ( !device->dhndl ) { free(device); running[type][*device_idx] = NULL; unlock; return de_FailedStart; } device->ctx = alcCreateContext(device->dhndl, NULL); alcMakeContextCurrent(device->ctx); alGenBuffers(OPENAL_BUFS, device->buffers); alGenSources((uint32_t)1, &device->source); alSourcei(device->source, AL_LOOPING, AL_FALSE); uint16_t zeros[frame_size]; memset(zeros, 0, frame_size*2); for ( i = 0; i < OPENAL_BUFS; ++i ) { alBufferData(device->buffers[i], device->sound_mode, zeros, frame_size*2, sample_rate); } alSourceQueueBuffers(device->source, OPENAL_BUFS, device->buffers); alSourcePlay(device->source); } if (alcGetError(device->dhndl) != AL_NO_ERROR) { free(device); running[type][*device_idx] = NULL; unlock; return de_FailedStart; } if (type == input) { alcCaptureStart(device->dhndl); thread_paused = false; } unlock; return de_None; }
Sound::SoundManager::SoundManager() : m_pDevice(alcOpenDevice(nullptr)) { if(!m_pDevice) LogError() << "Could not open audio device"; //m_Enumeration = alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT"); ALCenum error; error = alGetError(); if (error != AL_NO_ERROR) LogError() << error; m_pContext = alcCreateContext(m_pDevice, NULL); if (!alcMakeContextCurrent(m_pContext)) LogError() << "Could not make current context"; ALfloat listenerOri[] = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f }; alListener3f(AL_POSITION, 0, 0, 1.0f); error = alGetError(); if (error != AL_NO_ERROR) LogError() << error; alListener3f(AL_VELOCITY, 0, 0, 0); error = alGetError(); if (error != AL_NO_ERROR) LogError() << error; alListenerfv(AL_ORIENTATION, listenerOri); error = alGetError(); if (error != AL_NO_ERROR) LogError() << error; ALuint source; alGenSources((ALuint)1, &source); error = alGetError(); if (error != AL_NO_ERROR) LogError() << error; alSourcef(source, AL_PITCH, 1); error = alGetError(); if (error != AL_NO_ERROR) LogError() << error; alSourcef(source, AL_GAIN, 1); error = alGetError(); if (error != AL_NO_ERROR) LogError() << error; alSource3f(source, AL_POSITION, 0, 0, 0); error = alGetError(); if (error != AL_NO_ERROR) LogError() << error; alSource3f(source, AL_VELOCITY, 0, 0, 0); error = alGetError(); if (error != AL_NO_ERROR) LogError() << error; alSourcei(source, AL_LOOPING, AL_FALSE); error = alGetError(); if (error != AL_NO_ERROR) LogError() << error; ALuint buffer; alGenBuffers((ALuint)1, &buffer); error = alGetError(); if (error != AL_NO_ERROR) LogError() << error; ALsizei size, freq; ALenum format; ALvoid *data; ALboolean loop = AL_FALSE; alutLoadWAVFile(reinterpret_cast<ALbyte *>(const_cast<char *>("test.wav")), &format, &data, &size, &freq, &loop); error = alGetError(); if (error != AL_NO_ERROR) LogError() << error; alBufferData(buffer, format, data, size, freq); alSourcei(source, AL_BUFFER, buffer);alSourcePlay(source); alSourcePlay(source); error = alGetError(); if (error != AL_NO_ERROR) LogError() << error; ALint source_state; alGetSourcei(source, AL_SOURCE_STATE, &source_state); LogInfo() << "Play sound..."; while (source_state == AL_PLAYING) { alGetSourcei(source, AL_SOURCE_STATE, &source_state); error = alGetError(); if (error != AL_NO_ERROR) LogError() << error; LogInfo() << "Play sound..."; } // cleanup context alDeleteSources(1, &source); alDeleteBuffers(1, &buffer); m_pDevice = alcGetContextsDevice(m_pContext); alcMakeContextCurrent(NULL); alcDestroyContext(m_pContext); }
// virtual bool LLAudioEngine_OpenAL::init(const S32 num_channels, void* userdata) { mWindGen = NULL; LLAudioEngine::init(num_channels, userdata); if (!alutInit(NULL, NULL)) { llwarns << "LLAudioEngine_OpenAL::init() ALUT initialization failed: " << alutGetErrorString (alutGetError ()) << llendl; return false; } // check for extensions const ALCchar* device_list(NULL); const ALCchar* device_default(NULL); if (alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT") == AL_TRUE) { device_default = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER); device_list = alcGetString(NULL, ALC_DEVICE_SPECIFIER); llinfos << "Results for ALC_ENUMERATION_EXT:\n" << ll_safe_string(device_list) << llendl; } // initialize device ALCdevice* mDevice = alcOpenDevice(NULL); if (mDevice == NULL) { llinfos << "Could not find a default device, trying to open default manually: " << ll_safe_string(device_default) << llendl; mDevice = alcOpenDevice(device_default); if (mDevice == NULL) { const ALCchar* device_list_walk = device_list; do { mDevice = alcOpenDevice(device_list_walk); if (mDevice != NULL) { break; } else { device_list_walk += strlen(device_list_walk)+1; } } while (device_list_walk[0] != '\0'); if (mDevice == NULL) { llinfos << "OpenAL could not find an installed audio device. Aborting" << llendl; ALCenum error = alcGetError(mDevice); if (error != ALC_NO_ERROR) { llinfos << "ALC error: " << ll_safe_string(alcGetString(mDevice, error)) << llendl; } return false; } } } // create context ALCcontext* mContext = alcCreateContext(mDevice, NULL); if (mContext != NULL) { if (!alcMakeContextCurrent(mContext)) { ALenum error = alGetError(); if (error != AL_NO_ERROR) { llinfos << "ALC error: " << convertALErrorToString(error) << ". Could not set current context!" << llendl; } alcDestroyContext(mContext); return false; } } else { llinfos << "ALC error: could not create context from device!" << llendl; alcCloseDevice(mDevice); return false; } llinfos << "LLAudioEngine_OpenAL::init() OpenAL successfully initialized" << llendl; llinfos << "ALC default device: " << ll_safe_string(alcGetString(mDevice, ALC_DEFAULT_DEVICE_SPECIFIER)) << llendl; llinfos << "OpenAL version: " << ll_safe_string(alGetString(AL_VERSION)) << llendl; llinfos << "OpenAL vendor: " << ll_safe_string(alGetString(AL_VENDOR)) << llendl; llinfos << "OpenAL renderer: " << ll_safe_string(alGetString(AL_RENDERER)) << llendl; ALint major = alutGetMajorVersion(); ALint minor = alutGetMinorVersion(); llinfos << "ALUT version: " << major << "." << minor << llendl; alcGetIntegerv(mDevice, ALC_MAJOR_VERSION, 1, &major); alcGetIntegerv(mDevice, ALC_MINOR_VERSION, 1, &minor); llinfos << "ALC version: " << major << "." << minor << llendl; return true; }
/** * @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; }
bool AudioEngine::SingletonInitialize() { if(!AUDIO_ENABLE) 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() << std::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 << std::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 << std::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() << std::endl; return false; } // Create an OpenAL context _context = alcCreateContext(_device, NULL); if(CheckALCError() || _context == NULL) { PRINT_ERROR << "failed to create an OpenAL context: " << CreateALCErrorString() << std::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" << std::endl; return false; } return true; } // bool AudioEngine::SingletonInitialize()
/* ======================== idSoundHardware_OpenAL::Init ======================== */ void idSoundHardware_OpenAL::Init() { cmdSystem->AddCommand( "listDevices", listDevices_f, 0, "Lists the connected sound devices", NULL ); common->Printf( "Setup OpenAL device and context... " ); openalDevice = alcOpenDevice( NULL ); if( openalDevice == NULL ) { common->FatalError( "idSoundHardware_OpenAL::Init: alcOpenDevice() failed\n" ); return; } openalContext = alcCreateContext( openalDevice, NULL ); if( alcMakeContextCurrent( openalContext ) == 0 ) { common->FatalError( "idSoundHardware_OpenAL::Init: alcMakeContextCurrent( %p) failed\n", openalContext ); return; } common->Printf( "Done.\n" ); common->Printf( "OpenAL vendor: %s\n", alGetString( AL_VENDOR ) ); common->Printf( "OpenAL renderer: %s\n", alGetString( AL_RENDERER ) ); common->Printf( "OpenAL version: %s\n", alGetString( AL_VERSION ) ); common->Printf( "OpenAL extensions: %s\n", alGetString( AL_EXTENSIONS ) ); //pMasterVoice->SetVolume( DBtoLinear( s_volume_dB.GetFloat() ) ); //outputChannels = deviceDetails.OutputFormat.Format.nChannels; //channelMask = deviceDetails.OutputFormat.dwChannelMask; //idSoundVoice::InitSurround( outputChannels, channelMask ); // --------------------- // Create VU Meter Effect // --------------------- /* IUnknown* vuMeter = NULL; XAudio2CreateVolumeMeter( &vuMeter, 0 ); XAUDIO2_EFFECT_DESCRIPTOR descriptor; descriptor.InitialState = true; descriptor.OutputChannels = outputChannels; descriptor.pEffect = vuMeter; XAUDIO2_EFFECT_CHAIN chain; chain.EffectCount = 1; chain.pEffectDescriptors = &descriptor; pMasterVoice->SetEffectChain( &chain ); vuMeter->Release(); */ // --------------------- // Create VU Meter Graph // --------------------- /* vuMeterRMS = console->CreateGraph( outputChannels ); vuMeterPeak = console->CreateGraph( outputChannels ); vuMeterRMS->Enable( false ); vuMeterPeak->Enable( false ); memset( vuMeterPeakTimes, 0, sizeof( vuMeterPeakTimes ) ); vuMeterPeak->SetFillMode( idDebugGraph::GRAPH_LINE ); vuMeterPeak->SetBackgroundColor( idVec4( 0.0f, 0.0f, 0.0f, 0.0f ) ); vuMeterRMS->AddGridLine( 0.500f, idVec4( 0.5f, 0.5f, 0.5f, 1.0f ) ); vuMeterRMS->AddGridLine( 0.250f, idVec4( 0.5f, 0.5f, 0.5f, 1.0f ) ); vuMeterRMS->AddGridLine( 0.125f, idVec4( 0.5f, 0.5f, 0.5f, 1.0f ) ); const char* channelNames[] = { "L", "R", "C", "S", "Lb", "Rb", "Lf", "Rf", "Cb", "Ls", "Rs" }; for( int i = 0, ci = 0; ci < sizeof( channelNames ) / sizeof( channelNames[0] ); ci++ ) { if( ( channelMask & BIT( ci ) ) == 0 ) { continue; } vuMeterRMS->SetLabel( i, channelNames[ ci ] ); i++; } */ // OpenAL doesn't really impose a maximum number of sources voices.SetNum( voices.Max() ); freeVoices.SetNum( voices.Max() ); zombieVoices.SetNum( 0 ); for( int i = 0; i < voices.Num(); i++ ) { freeVoices[i] = &voices[i]; } }
int main(int argc, char **argv) { ALboolean enumeration; const ALCchar *devices; const ALCchar *defaultDeviceName = argv[1]; int ret; #ifdef LIBAUDIO WaveInfo *wave; #endif char *bufferData; ALCdevice *device; ALvoid *data; ALCcontext *context; ALsizei size, freq; ALenum format; ALuint buffer, source; ALfloat listenerOri[] = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f }; ALboolean loop = AL_FALSE; ALCenum error; ALint source_state; enumeration = alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT"); if (enumeration == AL_FALSE) fprintf(stderr, "enumeration extension not available\n"); list_audio_devices(alcGetString(NULL, ALC_DEVICE_SPECIFIER)); if (!defaultDeviceName) defaultDeviceName = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER); device = alcOpenDevice(defaultDeviceName); if (!device) { fprintf(stderr, "unable to open default device\n"); return -1; } fprintf(stdout, "Device: %s\n", alcGetString(device, ALC_DEVICE_SPECIFIER)); alGetError(); context = alcCreateContext(device, NULL); if (!alcMakeContextCurrent(context)) { fprintf(stderr, "failed to make default context\n"); return -1; } TEST_ERROR("make default context"); /* set orientation */ alListener3f(AL_POSITION, 0, 0, 1.0f); TEST_ERROR("listener position"); alListener3f(AL_VELOCITY, 0, 0, 0); TEST_ERROR("listener velocity"); alListenerfv(AL_ORIENTATION, listenerOri); TEST_ERROR("listener orientation"); alGenSources((ALuint)1, &source); TEST_ERROR("source generation"); alSourcef(source, AL_PITCH, 1); TEST_ERROR("source pitch"); alSourcef(source, AL_GAIN, 1); TEST_ERROR("source gain"); alSource3f(source, AL_POSITION, 0, 0, 0); TEST_ERROR("source position"); alSource3f(source, AL_VELOCITY, 0, 0, 0); TEST_ERROR("source velocity"); alSourcei(source, AL_LOOPING, AL_FALSE); TEST_ERROR("source looping"); alGenBuffers(1, &buffer); TEST_ERROR("buffer generation"); #ifdef LIBAUDIO /* load data */ wave = WaveOpenFileForReading("test.wav"); if (!wave) { fprintf(stderr, "failed to read wave file\n"); return -1; } ret = WaveSeekFile(0, wave); if (ret) { fprintf(stderr, "failed to seek wave file\n"); return -1; } bufferData = malloc(wave->dataSize); if (!bufferData) { perror("malloc"); return -1; } ret = WaveReadFile(bufferData, wave->dataSize, wave); if (ret != wave->dataSize) { fprintf(stderr, "short read: %d, want: %d\n", ret, wave->dataSize); return -1; } alBufferData(buffer, to_al_format(wave->channels, wave->bitsPerSample), bufferData, wave->dataSize, wave->sampleRate); TEST_ERROR("failed to load buffer data"); #else alutLoadWAVFile("test.wav", &format, &data, &size, &freq, &loop); TEST_ERROR("loading wav file"); alBufferData(buffer, format, data, size, freq); TEST_ERROR("buffer copy"); #endif alSourcei(source, AL_BUFFER, buffer); TEST_ERROR("buffer binding"); alSourcePlay(source); TEST_ERROR("source playing"); alGetSourcei(source, AL_SOURCE_STATE, &source_state); TEST_ERROR("source state get"); while (source_state == AL_PLAYING) { alGetSourcei(source, AL_SOURCE_STATE, &source_state); TEST_ERROR("source state get"); } /* exit context */ alDeleteSources(1, &source); alDeleteBuffers(1, &buffer); device = alcGetContextsDevice(context); alcMakeContextCurrent(NULL); alcDestroyContext(context); alcCloseDevice(device); return 0; }