CVoid COpenALSoundSource::SetConeOuterVol( CFloat gain ) { alSourcef( m_soundSource, AL_CONE_OUTER_GAIN, gain ); }
CVoid COpenALSoundSource::SetConeAngle( CFloat inner, CFloat outer ) { alSourcef( m_soundSource, AL_CONE_INNER_ANGLE, inner ); alSourcef( m_soundSource, AL_CONE_OUTER_ANGLE, outer ); }
CVoid COpenALSoundSource::SetVolume( CFloat vol ) { alSourcef( m_soundSource, AL_GAIN, vol ); }
CVoid COpenALSoundSource::SetVolume( CFloat vol, CFloat min, CFloat max ) { alSourcef( m_soundSource, AL_MIN_GAIN, min ); alSourcef( m_soundSource, AL_MAX_GAIN, max ); alSourcef( m_soundSource, AL_GAIN, vol ); }
CVoid COpenALSoundSource::SetMaxDistance( CFloat distance ) { alSourcef( m_soundSource, AL_MAX_DISTANCE, distance ); }
CVoid COpenALSoundSource::SetReferenceDistance( CFloat distance ) { alSourcef( m_soundSource, AL_REFERENCE_DISTANCE, distance ); }
CVoid COpenALSoundSource::SetPitch( CFloat pitch ) { alSourcef( m_soundSource, AL_PITCH, pitch ); }
CVoid COpenALSoundSource::SetRolloff( CFloat rolloff ) { alSourcef( m_soundSource, AL_ROLLOFF_FACTOR, rolloff ); }
void cargarSonido (void) { ALsizei tamanyo; Uint8 *datos; ALfloat velocity[3]= { 0.0, 0.0, 0.0 }; ALfloat pitch = 1.0, gain = 1.0; SDL_AudioSpec wav_spec; // reservar memoria para los sonidos son = (sonidos *) malloc (sizeof (sonidos)); // generar el buffer del rayo alGenBuffers (1, &son->bufferRayo); // cargar el sonido de un fichero SDL_LoadWAV ("blaster02.wav", &wav_spec, &datos, &tamanyo); alBufferData (son->bufferRayo, AL_FORMAT_STEREO8, datos, tamanyo, wav_spec.freq); SDL_FreeWAV (datos); // generar la fuente del rayo alGenSources (1, &son->fuenteRayo); // inicializar los valores de la fuente alSourcef (son->fuenteRayo, AL_PITCH, pitch); alSourcef (son->fuenteRayo, AL_GAIN, gain); alSourcefv (son->fuenteRayo, AL_VELOCITY, velocity); alSourcei (son->fuenteRayo, AL_BUFFER, son->bufferRayo); alSourcei (son->fuenteRayo, AL_LOOPING, AL_FALSE); // generar el buffer de ganas alGenBuffers (1, &son->bufferGanas); // cargar el sonido de un fichero SDL_LoadWAV ("chewie04.wav", &wav_spec, &datos, &tamanyo); alBufferData (son->bufferGanas, AL_FORMAT_STEREO8, datos, tamanyo, wav_spec.freq); SDL_FreeWAV (datos); // generar la fuente de ganas alGenSources (1, &son->fuenteGanas); // inicializar los valores de la fuente alSourcef (son->fuenteGanas, AL_PITCH, pitch); alSourcef (son->fuenteGanas, AL_GAIN, gain); alSourcefv (son->fuenteGanas, AL_VELOCITY, velocity); alSourcei (son->fuenteGanas, AL_BUFFER, son->bufferGanas); alSourcei (son->fuenteGanas, AL_LOOPING, AL_FALSE); // generar el buffer de pierdes alGenBuffers (1, &son->bufferPierdes); // cargar el sonido de un fichero SDL_LoadWAV ("chewie03.wav", &wav_spec, &datos, &tamanyo); alBufferData (son->bufferPierdes, AL_FORMAT_STEREO8, datos, tamanyo, wav_spec.freq); SDL_FreeWAV (datos); // generar la fuente de pierdes alGenSources (1, &son->fuentePierdes); // inicializar los valores de la fuente alSourcef (son->fuentePierdes, AL_PITCH, pitch); alSourcef (son->fuentePierdes, AL_GAIN, gain); alSourcefv (son->fuentePierdes, AL_VELOCITY, velocity); alSourcei (son->fuentePierdes, AL_BUFFER, son->bufferPierdes); alSourcei (son->fuentePierdes, AL_LOOPING, AL_FALSE); // generar el buffer de acierto alGenBuffers (1, &son->bufferAcierto); // cargar el sonido de un fichero SDL_LoadWAV ("expl02.wav", &wav_spec, &datos, &tamanyo); alBufferData (son->bufferAcierto, AL_FORMAT_STEREO8, datos, tamanyo, wav_spec.freq); SDL_FreeWAV (datos); // generar la fuente del acierto alGenSources (1, &son->fuenteAcierto); // inicializar los valores de la fuente alSourcef (son->fuenteAcierto, AL_PITCH, pitch); alSourcef (son->fuenteAcierto, AL_GAIN, gain); alSourcefv (son->fuenteAcierto, AL_VELOCITY, velocity); alSourcei (son->fuenteAcierto, AL_BUFFER, son->bufferAcierto); alSourcei (son->fuenteAcierto, AL_LOOPING, AL_FALSE); // generar el buffer de indy alGenBuffers (1, &son->bufferIndy); // cargar el sonido de un fichero SDL_LoadWAV ("indy.wav", &wav_spec, &datos, &tamanyo); alBufferData (son->bufferIndy, AL_FORMAT_STEREO8, datos, tamanyo, wav_spec.freq); SDL_FreeWAV (datos); // generar la fuente de indy alGenSources (1, &son->fuenteIndy); // inicializar los valores de la fuente alSourcef (son->fuenteIndy, AL_PITCH, pitch); alSourcef (son->fuenteIndy, AL_GAIN, gain); alSourcefv (son->fuenteIndy, AL_VELOCITY, velocity); alSourcei (son->fuenteIndy, AL_BUFFER, son->bufferIndy); alSourcei (son->fuenteIndy, AL_LOOPING, AL_FALSE); // generar el buffer de rebote 1 alGenBuffers (1, &son->bufferRebote1); // cargar el sonido de un fichero SDL_LoadWAV ("bounce1.wav", &wav_spec, &datos, &tamanyo); alBufferData (son->bufferRebote1, AL_FORMAT_STEREO8, datos, tamanyo, wav_spec.freq); SDL_FreeWAV (datos); // generar la fuente de rebote 1 alGenSources (1, &son->fuenteRebote1); // inicializar los valores de la fuente alSourcef (son->fuenteRebote1, AL_PITCH, pitch); alSourcef (son->fuenteRebote1, AL_GAIN, gain); alSourcefv (son->fuenteRebote1, AL_VELOCITY, velocity); alSourcei (son->fuenteRebote1, AL_BUFFER, son->bufferRebote1); alSourcei (son->fuenteRebote1, AL_LOOPING, AL_FALSE); // generar el buffer de rebote 2 alGenBuffers (1, &son->bufferRebote2); // cargar el sonido de un fichero SDL_LoadWAV ("bounce2.wav", &wav_spec, &datos, &tamanyo); alBufferData (son->bufferRebote2, AL_FORMAT_STEREO8, datos, tamanyo, wav_spec.freq); SDL_FreeWAV (datos); // generar la fuente de rebote 2 alGenSources (1, &son->fuenteRebote2); // inicializar los valores de la fuente alSourcef (son->fuenteRebote2, AL_PITCH, pitch); alSourcef (son->fuenteRebote2, AL_GAIN, gain); alSourcefv (son->fuenteRebote2, AL_VELOCITY, velocity); alSourcei (son->fuenteRebote2, AL_BUFFER, son->bufferRebote2); alSourcei (son->fuenteRebote2, AL_LOOPING, AL_FALSE); // inicializar los valores del oyente alListenerfv (AL_VELOCITY, velocity); }
void Sound::SetPlayingOffset(float timeOffset) { ALCheck(alSourcef(mySource, AL_SEC_OFFSET, timeOffset)); }
void C4MusicFileOgg::SetVolume(int iLevel) { volume = ((float) iLevel) / 100.0f; if (channel) alSourcef(channel, AL_GAIN, volume); }
void setf(ALenum key, float val) { alSourcef(name_, key, val); check_error("alSourcef (source::setf)"); }
void SonicDog::alertObstacles( const CoordinateVect &obstacles, bool diff ) { int size = obstacles.size(); // checkError( "alGenSources", AL ); pthread_mutex_lock( &q_lock_ ); if ( play_q_.size() > 0 ) { pthread_mutex_unlock( &q_lock_ ); return; } for ( int i = 0; i < size; i++ ) { SoundSrc *src = new SoundSrc; src->once = true; src->x = obstacles[i].first; src->z = obstacles[i].second; src->pause = 1.5; alGetError(); alGenSources( 1, &(src->source) ); checkError( "alGenSources", AL ); alutGetError(); if ( diff ) { // src->buffer = alutCreateBufferWaveform( ALUT_WAVEFORM_IMPULSE, i*100.0f+200.0f, 0.0f, 0.5f ); src->buffer = alutCreateBufferFromFile( "./ding.wav" ); alSourcef( src->source, AL_PITCH, .2*i+1 ); } else { // src->buffer = alutCreateBufferWaveform( ALUT_WAVEFORM_IMPULSE, 400.0f, 0.0f, 0.5f ); src->buffer = alutCreateBufferFromFile( "./ding.wav" ); alSourcef( src->source, AL_PITCH, 1 ); } if ( src->buffer == AL_NONE ) { checkError( "alutCreateBufferWaveform", ALUT ); } bool front = true; if ( regions_ ) { // move the location of the source in the OpenAL world to one of our discrete zones ALfloat pos[] = { 0.0, 0.0, 0.0 }; front = placeInRegion( src->x, src->z, pos ); alSourcefv( src->source, AL_POSITION, pos ); } else if ( cutoff_ ) { ALfloat pos[] = { 0.0, 0.0, 0.0 }; front = placeInCutoff( src->x, src->z, pos ); alSourcefv( src->source, AL_POSITION, pos ); } else { alSource3f( src->source, AL_POSITION, src->x, 0.0f, src->z ); } alSourcef( src->source, AL_GAIN, 10.0f ); alSource3f( src->source, AL_VELOCITY, 0.0f, 0.0f, 0.0f ); alSourcei( src->source, AL_LOOPING, AL_FALSE ); alSourcei( src->source, AL_BUFFER, src->buffer ); if ( front ) { play_q_.push( src ); } else if ( !front_only_ ) { play_q_.push( src ); } else { alDeleteSources( 1, &(src->source) ); alDeleteBuffers( 1, &(src->buffer) ); delete src; } } pthread_mutex_unlock( &q_lock_ ); pthread_cond_broadcast( &empty_q_lock_ ); }
void ALAudio::BGM_Pitch(int pitch) { SET_CONTEXT(ctx_); alSourcef(bgm_src_->get(), AL_PITCH, pitch * 0.01f); }
void SonicDog::startPlaying() { // find out if the client wants the sound to play bool can_play, once, removed; removed = false; pthread_mutex_lock( &play_lock_ ); can_play = playing_; pthread_mutex_unlock( &play_lock_ ); while ( can_play ) { pthread_mutex_lock( &q_lock_ ); while ( play_q_.size() == 0 && !exit_ ) { pthread_cond_wait( &empty_q_lock_, &q_lock_ ); } // check that we can keep playing after being woken up if ( exit_ ) { pthread_mutex_unlock( &q_lock_ ); pthread_exit( 0 ); } // there's stuff in the queue so pop off a source SoundSrc *src = play_q_.front(); play_q_.pop(); pthread_mutex_unlock( &q_lock_ ); once = src->once; do { // play the sound at least once if ( once ) pthread_mutex_lock( &turns_lock_ ); alSourcePlay( src->source ); alutSleep( src->pause ); if ( once ) pthread_mutex_unlock( &turns_lock_ ); if ( !once ) alSourcef( src->source, AL_PITCH, calculatePitch( src->source ) ); // check that we can keep playing pthread_mutex_lock( &play_lock_ ); can_play = playing_; pthread_mutex_unlock( &play_lock_ ); if ( !once ) { bool paused; // check if we're paused pthread_mutex_lock( &pause_lock_ ); BoolMap::iterator p = paused_.find( src->id ); assert( p != paused_.end() ); paused = p->second; while ( paused ) { pthread_cond_wait( &pause_cond_lock_, &pause_lock_ ); BoolMap::iterator p = paused_.find( src->id ); assert( p != paused_.end() ); paused = p->second; } pthread_mutex_unlock( &pause_lock_ ); // check if we've been removed pthread_mutex_lock( &remove_lock_ ); BoolMap::iterator cont = removed_.find( src->id ); if ( cont != removed_.end() ) { removed = cont->second; } pthread_mutex_unlock( &remove_lock_ ); } } while ( can_play && !once && !removed ); // remove this source if wasn't meant to be played only once if ( !src->once ) { // remove this source from the source map if it's in there pthread_mutex_lock( &sources_lock_ ); SoundMap::iterator itr = sources_.find( src->id ); if ( itr != sources_.end() ) { sources_.erase( itr ); } pthread_mutex_unlock( &sources_lock_ ); } // we're done with the source so clean it up alDeleteSources( 1, &(src->source) ); alDeleteBuffers( 1, &(src->buffer) ); delete src; } // we've been stopped, so exit the thread pthread_exit( 0 ); }
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); }
void set_volume(ALfloat const vol) { SET_CONTEXT(ctx_); volume_ = vol; alSourcef(src_, AL_GAIN, vol); }
void SetMusicVolume(float mvol) { alSourcef(musicSource, AL_GAIN, mvol); }
void SFXOpenAL::setRolloff(float rolloff) { alSourcef (m_sound_source, AL_ROLLOFF_FACTOR, rolloff); }
/** * @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; }
void LLAudioEngine_OpenAL::updateWind(LLVector3 wind_vec, F32 camera_altitude) { LLVector3 wind_pos; F64 pitch; F64 center_freq; ALenum error; if (!mEnableWind) return; if (!mWindBuf) return; if (mWindUpdateTimer.checkExpirationAndReset(LL_WIND_UPDATE_INTERVAL)) { // wind comes in as Linden coordinate (+X = forward, +Y = left, +Z = up) // need to convert this to the conventional orientation DS3D and OpenAL use // where +X = right, +Y = up, +Z = backwards wind_vec.setVec(-wind_vec.mV[1], wind_vec.mV[2], -wind_vec.mV[0]); pitch = 1.0 + mapWindVecToPitch(wind_vec); center_freq = 80.0 * pow(pitch,2.5*(mapWindVecToGain(wind_vec)+1.0)); mWindGen->mTargetFreq = (F32)center_freq; mWindGen->mTargetGain = (F32)mapWindVecToGain(wind_vec) * mMaxWindGain; mWindGen->mTargetPanGainR = (F32)mapWindVecToPan(wind_vec); alSourcei(mWindSource, AL_LOOPING, AL_FALSE); alSource3f(mWindSource, AL_POSITION, 0.0, 0.0, 0.0); alSource3f(mWindSource, AL_VELOCITY, 0.0, 0.0, 0.0); alSourcef(mWindSource, AL_ROLLOFF_FACTOR, 0.0); alSourcei(mWindSource, AL_SOURCE_RELATIVE, AL_TRUE); } // ok lets make a wind buffer now ALint processed, queued, unprocessed; alGetSourcei(mWindSource, AL_BUFFERS_PROCESSED, &processed); alGetSourcei(mWindSource, AL_BUFFERS_QUEUED, &queued); unprocessed = queued - processed; // ensure that there are always at least 3x as many filled buffers // queued as we managed to empty since last time. mNumEmptyWindALBuffers = llmin(mNumEmptyWindALBuffers + processed * 3 - unprocessed, MAX_NUM_WIND_BUFFERS-unprocessed); mNumEmptyWindALBuffers = llmax(mNumEmptyWindALBuffers, 0); //llinfos << "mNumEmptyWindALBuffers: " << mNumEmptyWindALBuffers <<" (" << unprocessed << ":" << processed << ")" << llendl; while (processed--) // unqueue old buffers { ALuint buffer; ALenum error; alGetError(); /* clear error */ alSourceUnqueueBuffers(mWindSource, 1, &buffer); error = alGetError(); if (error != AL_NO_ERROR) { llwarns << "LLAudioEngine_OpenAL::updateWind() error swapping (unqueuing) buffers" << llendl; } else { alDeleteBuffers(1, &buffer); } } unprocessed += mNumEmptyWindALBuffers; while (mNumEmptyWindALBuffers > 0) // fill+queue new buffers { ALuint buffer; alGetError(); /* clear error */ alGenBuffers(1,&buffer); if ((error=alGetError()) != AL_NO_ERROR) { llwarns << "LLAudioEngine_OpenAL::updateWind() Error creating wind buffer: " << convertALErrorToString(error) << llendl; break; } alBufferData(buffer, AL_FORMAT_STEREO16, mWindGen->windGenerate(mWindBuf, mWindBufSamples), mWindBufBytes, mWindBufFreq); error = alGetError(); if (error != AL_NO_ERROR) { llwarns << "LLAudioEngine_OpenAL::updateWind() error swapping (bufferdata) buffers" << llendl; } alSourceQueueBuffers(mWindSource, 1, &buffer); error = alGetError(); if (error != AL_NO_ERROR) { llwarns << "LLAudioEngine_OpenAL::updateWind() error swapping (queuing) buffers" << llendl; } --mNumEmptyWindALBuffers; } ALint playing; alGetSourcei(mWindSource, AL_SOURCE_STATE, &playing); if (playing != AL_PLAYING) { alSourcePlay(mWindSource); lldebugs << "Wind had stopped - probably ran out of buffers - restarting: " << (unprocessed+mNumEmptyWindALBuffers) << " now queued." << llendl; } }
/** * @brief Creates a sound environment. */ int sound_al_env( SoundEnv_t env, double param ) { int i; ALuint s; ALfloat f; soundLock(); switch (env) { case SOUND_ENV_NORMAL: /* Set global parameters. */ alSpeedOfSound( 3433. ); if (al_info.efx == AL_TRUE) { /* Disconnect the effect. */ nalAuxiliaryEffectSloti( efx_directSlot, AL_EFFECTSLOT_EFFECT, AL_EFFECT_NULL ); /* Set per-source parameters. */ for (i=0; i<source_ntotal; i++) { s = source_total[i]; alSourcef( s, AL_AIR_ABSORPTION_FACTOR, 0. ); } } break; case SOUND_ENV_NEBULA: f = param / 1000.; /* Set global parameters. */ alSpeedOfSound( 3433./(1. + f*2.) ); if (al_info.efx == AL_TRUE) { if (al_info.efx_reverb == AL_TRUE) { /* Tweak the reverb. */ nalEffectf( efx_reverb, AL_REVERB_DECAY_TIME, 10. ); nalEffectf( efx_reverb, AL_REVERB_DECAY_HFRATIO, 0.5 ); /* Connect the effect. */ nalAuxiliaryEffectSloti( efx_directSlot, AL_EFFECTSLOT_EFFECT, efx_reverb ); } /* Set per-source parameters. */ for (i=0; i<source_ntotal; i++) { s = source_total[i]; /* Value is from 0. (normal) to 10.. * It represents the attenuation per meter. In this case it decreases by * 0.05*AB_FACTOR dB/meter where AB_FACTOR is the air absoprtion factor. * In our case each pixel represents 5 meters. */ alSourcef( s, AL_AIR_ABSORPTION_FACTOR, 3.*f ); } } break; } /* Check for errors. */ al_checkErr(); soundUnlock(); return 0; }
/** * @brief Plays a sound in a group. */ int sound_al_playGroup( int group, alSound *s, int once ) { int i, j; alGroup_t *g; ALint state; double v; for (i=0; i<al_ngroups; i++) { /* Find group. */ if (al_groups[i].id != group) continue; g = &al_groups[i]; g->state = VOICE_PLAYING; soundLock(); for (j=0; j<g->nsources; j++) { alGetSourcei( g->sources[j], AL_SOURCE_STATE, &state ); /* No free ones, just smash the last one. */ if (j == g->nsources-1) { if (state != AL_STOPPED) alSourceStop( g->sources[j] ); } /* Ignore playing/paused. */ else if ((state == AL_PLAYING) || (state == AL_PAUSED)) continue; /* Attach buffer. */ alSourcei( g->sources[j], AL_BUFFER, s->u.al.buf ); /* Do not do positional sound. */ alSourcei( g->sources[j], AL_SOURCE_RELATIVE, AL_TRUE ); /* See if should loop. */ alSourcei( g->sources[j], AL_LOOPING, (once) ? AL_FALSE : AL_TRUE ); /* Set volume. */ v = svolume * g->volume; if (g->speed) v *= svolume_speed; alSourcef( g->sources[j], AL_GAIN, v ); /* Start playing. */ alSourcePlay( g->sources[j] ); /* Check for errors. */ al_checkErr(); soundUnlock(); return 0; } soundUnlock(); WARN(_("Group '%d' has no free sounds."), group ); /* Group matched but not found. */ break; } if (i>=al_ngroups) WARN(_("Group '%d' not found."), group); return -1; }
void OpenALStream::SoundLoop() { Common::SetCurrentThreadName("Audio thread - openal"); bool surround_capable = SConfig::GetInstance().bDPL2Decoder; bool float32_capable = false; bool fixed32_capable = false; #if defined(__APPLE__) surround_capable = false; #endif u32 ulFrequency = m_mixer->GetSampleRate(); numBuffers = SConfig::GetInstance().iLatency + 2; // OpenAL requires a minimum of two buffers memset(uiBuffers, 0, numBuffers * sizeof(ALuint)); uiSource = 0; if (alIsExtensionPresent("AL_EXT_float32")) float32_capable = true; // As there is no extension to check for 32-bit fixed point support // and we know that only a X-Fi with hardware OpenAL supports it, // we just check if one is being used. if (strstr(alGetString(AL_RENDERER), "X-Fi")) fixed32_capable = true; // Clear error state before querying or else we get false positives. ALenum err = alGetError(); // Generate some AL Buffers for streaming alGenBuffers(numBuffers, (ALuint*)uiBuffers); err = CheckALError("generating buffers"); // Generate a Source to playback the Buffers alGenSources(1, &uiSource); err = CheckALError("generating sources"); // Set the default sound volume as saved in the config file. alSourcef(uiSource, AL_GAIN, fVolume); // TODO: Error handling // ALenum err = alGetError(); unsigned int nextBuffer = 0; unsigned int numBuffersQueued = 0; ALint iState = 0; soundTouch.setChannels(2); soundTouch.setSampleRate(ulFrequency); soundTouch.setTempo(1.0); soundTouch.setSetting(SETTING_USE_QUICKSEEK, 0); soundTouch.setSetting(SETTING_USE_AA_FILTER, 0); soundTouch.setSetting(SETTING_SEQUENCE_MS, 1); soundTouch.setSetting(SETTING_SEEKWINDOW_MS, 28); soundTouch.setSetting(SETTING_OVERLAP_MS, 12); while (m_run_thread.IsSet()) { // Block until we have a free buffer int numBuffersProcessed; alGetSourcei(uiSource, AL_BUFFERS_PROCESSED, &numBuffersProcessed); if (numBuffers == numBuffersQueued && !numBuffersProcessed) { soundSyncEvent.Wait(); continue; } // Remove the Buffer from the Queue. if (numBuffersProcessed) { ALuint unqueuedBufferIds[OAL_MAX_BUFFERS]; alSourceUnqueueBuffers(uiSource, numBuffersProcessed, unqueuedBufferIds); err = CheckALError("unqueuing buffers"); numBuffersQueued -= numBuffersProcessed; } // num_samples_to_render in this update - depends on SystemTimers::AUDIO_DMA_PERIOD. const u32 stereo_16_bit_size = 4; const u32 dma_length = 32; const u64 ais_samples_per_second = 48000 * stereo_16_bit_size; u64 audio_dma_period = SystemTimers::GetTicksPerSecond() / (AudioInterface::GetAIDSampleRate() * stereo_16_bit_size / dma_length); u64 num_samples_to_render = (audio_dma_period * ais_samples_per_second) / SystemTimers::GetTicksPerSecond(); unsigned int numSamples = (unsigned int)num_samples_to_render; unsigned int minSamples = surround_capable ? 240 : 0; // DPL2 accepts 240 samples minimum (FWRDURATION) numSamples = (numSamples > OAL_MAX_SAMPLES) ? OAL_MAX_SAMPLES : numSamples; numSamples = m_mixer->Mix(realtimeBuffer, numSamples, false); // Convert the samples from short to float float dest[OAL_MAX_SAMPLES * STEREO_CHANNELS]; for (u32 i = 0; i < numSamples * STEREO_CHANNELS; ++i) dest[i] = (float)realtimeBuffer[i] / (1 << 15); soundTouch.putSamples(dest, numSamples); double rate = (double)m_mixer->GetCurrentSpeed(); if (rate <= 0) { Core::RequestRefreshInfo(); rate = (double)m_mixer->GetCurrentSpeed(); } // Place a lower limit of 10% speed. When a game boots up, there will be // many silence samples. These do not need to be timestretched. if (rate > 0.10) { soundTouch.setTempo(rate); if (rate > 10) { soundTouch.clear(); } } unsigned int nSamples = soundTouch.receiveSamples(sampleBuffer, OAL_MAX_SAMPLES * numBuffers); if (nSamples <= minSamples) continue; if (surround_capable) { float dpl2[OAL_MAX_SAMPLES * OAL_MAX_BUFFERS * SURROUND_CHANNELS]; DPL2Decode(sampleBuffer, nSamples, dpl2); // zero-out the subwoofer channel - DPL2Decode generates a pretty // good 5.0 but not a good 5.1 output. Sadly there is not a 5.0 // AL_FORMAT_50CHN32 to make this super-explicit. // DPL2Decode output: LEFTFRONT, RIGHTFRONT, CENTREFRONT, (sub), LEFTREAR, RIGHTREAR for (u32 i = 0; i < nSamples; ++i) { dpl2[i * SURROUND_CHANNELS + 3 /*sub/lfe*/] = 0.0f; } if (float32_capable) { alBufferData(uiBuffers[nextBuffer], AL_FORMAT_51CHN32, dpl2, nSamples * FRAME_SURROUND_FLOAT, ulFrequency); } else if (fixed32_capable) { int surround_int32[OAL_MAX_SAMPLES * SURROUND_CHANNELS * OAL_MAX_BUFFERS]; for (u32 i = 0; i < nSamples * SURROUND_CHANNELS; ++i) { // For some reason the ffdshow's DPL2 decoder outputs samples bigger than 1. // Most are close to 2.5 and some go up to 8. Hard clamping here, we need to // fix the decoder or implement a limiter. dpl2[i] = dpl2[i] * (INT64_C(1) << 31); if (dpl2[i] > INT_MAX) surround_int32[i] = INT_MAX; else if (dpl2[i] < INT_MIN) surround_int32[i] = INT_MIN; else surround_int32[i] = (int)dpl2[i]; } alBufferData(uiBuffers[nextBuffer], AL_FORMAT_51CHN32, surround_int32, nSamples * FRAME_SURROUND_INT32, ulFrequency); } else { short surround_short[OAL_MAX_SAMPLES * SURROUND_CHANNELS * OAL_MAX_BUFFERS]; for (u32 i = 0; i < nSamples * SURROUND_CHANNELS; ++i) { dpl2[i] = dpl2[i] * (1 << 15); if (dpl2[i] > SHRT_MAX) surround_short[i] = SHRT_MAX; else if (dpl2[i] < SHRT_MIN) surround_short[i] = SHRT_MIN; else surround_short[i] = (int)dpl2[i]; } alBufferData(uiBuffers[nextBuffer], AL_FORMAT_51CHN16, surround_short, nSamples * FRAME_SURROUND_SHORT, ulFrequency); } err = CheckALError("buffering data"); if (err == AL_INVALID_ENUM) { // 5.1 is not supported by the host, fallback to stereo WARN_LOG(AUDIO, "Unable to set 5.1 surround mode. Updating OpenAL Soft might fix this issue."); surround_capable = false; } } else { if (float32_capable) { alBufferData(uiBuffers[nextBuffer], AL_FORMAT_STEREO_FLOAT32, sampleBuffer, nSamples * FRAME_STEREO_FLOAT, ulFrequency); err = CheckALError("buffering float32 data"); if (err == AL_INVALID_ENUM) { float32_capable = false; } } else if (fixed32_capable) { // Clamping is not necessary here, samples are always between (-1,1) int stereo_int32[OAL_MAX_SAMPLES * STEREO_CHANNELS * OAL_MAX_BUFFERS]; for (u32 i = 0; i < nSamples * STEREO_CHANNELS; ++i) stereo_int32[i] = (int)((float)sampleBuffer[i] * (INT64_C(1) << 31)); alBufferData(uiBuffers[nextBuffer], AL_FORMAT_STEREO32, stereo_int32, nSamples * FRAME_STEREO_INT32, ulFrequency); } else { // Convert the samples from float to short short stereo[OAL_MAX_SAMPLES * STEREO_CHANNELS * OAL_MAX_BUFFERS]; for (u32 i = 0; i < nSamples * STEREO_CHANNELS; ++i) stereo[i] = (short)((float)sampleBuffer[i] * (1 << 15)); alBufferData(uiBuffers[nextBuffer], AL_FORMAT_STEREO16, stereo, nSamples * FRAME_STEREO_SHORT, ulFrequency); } } alSourceQueueBuffers(uiSource, 1, &uiBuffers[nextBuffer]); err = CheckALError("queuing buffers"); numBuffersQueued++; nextBuffer = (nextBuffer + 1) % numBuffers; alGetSourcei(uiSource, AL_SOURCE_STATE, &iState); if (iState != AL_PLAYING) { // Buffer underrun occurred, resume playback alSourcePlay(uiSource); err = CheckALError("occurred resuming playback"); } } }
/* * ALboolean LoadALData() * * This function will load our sample data from the disk using the alut * utility and send the data into OpenAL as a buffer. A source is then * also created to play that buffer. */ int LoadSoundBuffers() { int theerror=0; // Variables to load into. if (total_loaded_buffers==0) { fprintf(stderr,"No Sounds to load!\n"); return 0; } ALenum format; ALsizei size; ALvoid* data; ALsizei freq; ALboolean loop; // Load wav data into buffers. alGenBuffers(total_loaded_buffers, Buffers); if(alGetError() != AL_NO_ERROR) { fprintf(stderr,"Error Generating Buffers!\n"); return 0; } for (unsigned int i=0; i<total_loaded_buffers; i++) { alutLoadWAVFile((ALbyte *)filenames[i], &format, &data, &size, &freq, &loop); theerror=alGetError(); if(theerror != AL_NO_ERROR) { fprintf(stderr,"Error (%u) loading Wav sound Buffer %u %s\n",theerror,i,filenames[i]); } alBufferData(Buffers[i], format, data, size, freq); theerror=alGetError(); if(theerror != AL_NO_ERROR) { fprintf(stderr,"Error (%u) loading Wav sound Buffer %u %s\n",theerror,i,filenames[i]); } alutUnloadWAV(format, data, size, freq); theerror=alGetError(); if(theerror != AL_NO_ERROR) { fprintf(stderr,"Error (%u) loading Wav sound Buffer %u %s\n",theerror,i,filenames[i]); } free(filenames[i]); /* Release memory for filename */ } // Bind buffers into audio sources. alGenSources(NUM_SOURCES, Sources); theerror=alGetError(); if(theerror != AL_NO_ERROR) { fprintf(stderr,"Error Generating Sources (%u)!\n",theerror); return 0; } for (unsigned int i=0; i<total_loaded_buffers; i++) { /*alGenSources( 1, &Sources[i] ); theerror=alGetError(); if(theerror != AL_NO_ERROR) { cout<<"Error Generating Sources ("<<theerror<<")!\n"; return false; } */ alSourcei (Sources[i], AL_BUFFER, Buffers[i] ); alSourcef (Sources[i], AL_PITCH, 1.0f ); alSourcef (Sources[i], AL_GAIN, 1.0f ); alSourcefv(Sources[i], AL_POSITION, SourcesPos[i]); alSourcefv(Sources[i], AL_VELOCITY, SourcesVel[i]); alSourcei (Sources[i], AL_LOOPING, AL_FALSE ); } // Bind buffers into audio sources. // Do another error check and return. if(alGetError() != AL_NO_ERROR) return 0; SetListenerValues(); return 1; }
void AudioWorld::initializeMusic() { std::string datPath = "/_work/data/Scripts/_compiled/MUSIC.DAT"; std::string datFile = Utils::getCaseSensitivePath(datPath, m_Engine.getEngineArgs().gameBaseDirectory); if (!Utils::fileExists(datFile)) { LogError() << "Failed to find MUSIC.DAT at: " << datFile; return; } m_MusicVM = new Daedalus::DaedalusVM(datFile); Daedalus::registerGothicEngineClasses(*m_MusicVM); m_MusicVM->getDATFile().iterateSymbolsOfClass("C_MUSICTHEME", [&](size_t i, Daedalus::PARSymbol& s) { Daedalus::GameState::MusicThemeHandle h = m_MusicVM->getGameState().createMusicTheme(); Daedalus::GEngineClasses::C_MusicTheme& mt = m_MusicVM->getGameState().getMusicTheme(h); m_MusicVM->initializeInstance(ZMemory::toBigHandle(h), i, Daedalus::IC_MusicTheme); m_musicThemeSegments[s.name] = mt.file; }); // DirectMusic initialization std::string baseDir = m_Engine.getEngineArgs().gameBaseDirectory; std::string musicPath = Utils::getCaseSensitivePath("/_work/data/Music", baseDir); try { const auto sfFactory = DirectMusic::DlsPlayer::createFactory(); m_musicContext = std::make_unique<DirectMusic::PlayingContext>(44100, 2, sfFactory); auto loader = [musicPath, baseDir](const std::string& name) { const auto search = Utils::lowered(Utils::stripFilePath(name)); for (const auto& file : Utils::getFilesInDirectory(musicPath)) { const auto lowercaseName = Utils::lowered(Utils::stripFilePath(file)); if (lowercaseName == search) { return Utils::readBinaryFileContents(file); } } return std::vector<std::uint8_t>(); }; m_musicContext->provideLoader(loader); for (const auto& segment : Utils::getFilesInDirectory(musicPath, "sgt")) { const auto lowercaseName = Utils::lowered(Utils::stripFilePath(segment)); const auto segm = m_musicContext->loadSegment(segment); LogInfo() << "Loading " + segment; m_Segments[lowercaseName] = m_musicContext->prepareSegment(*segm); } LogInfo() << "All segments loaded."; alGenBuffers(RE_NUM_MUSIC_BUFFERS, m_musicBuffers); alGenSources(1, &m_musicSource); // Set the default volume alSourcef(m_musicSource, AL_GAIN, 1); // Set the default position of the sound alSource3f(m_musicSource, AL_POSITION, 0, 0, 0); m_musicRenderThread = std::thread(&AudioWorld::musicRenderFunction, this); } catch (const std::exception& exc) { LogError() << "Couldn't initialize music system: " << exc.what(); } }
size_t SonicDog::addObject( float x, float z, obj_t type ) { // instantiate the source and buffer for this sound source SoundSrc *src = new SoundSrc; src->id = object_id_; src->once = false; src->x = x; src->z = z; src->pause = 1.5; alGetError(); alGenSources( 1, &(src->source) ); checkError( "alGenSources", AL ); switch ( type ) { case BEAC: { // src->buffer = alutCreateBufferWaveform( ALUT_WAVEFORM_WHITENOISE, 500.0f, 0.0f, 0.5f ); alutGetError(); src->buffer = alutCreateBufferFromFile( "./beeps.wav" ); checkError( "alutCreateBufferFromFile", ALUT ); alSourcef( src->source, AL_GAIN, 10.0f ); break; } case OBS: { alutGetError(); src->buffer = alutCreateBufferWaveform( ALUT_WAVEFORM_SQUARE, object_id_*100.0f + 100.0f, 0.0f, 0.7f ); checkError( "alutCreateBufferWaveform", ALUT ); alSourcef( src->source, AL_GAIN, 0.1f ); break; } default: break; } alSourcef( src->source, AL_PITCH, 1 ); alSource3f( src->source, AL_VELOCITY, 0.0f, 0.0f, 0.0f ); alSourcei( src->source, AL_LOOPING, AL_FALSE ); alSourcei( src->source, AL_BUFFER, src->buffer ); if ( regions_ ) { // move the location of the source in the OpenAL world to one of our discrete zones ALfloat pos[] = { 0.0, 0.0, 0.0 }; placeInRegion( x, z, pos ); alSourcefv( src->source, AL_POSITION, pos ); } else if ( cutoff_ ) { ALfloat pos[] = { 0.0, 0.0, 0.0 }; placeInCutoff( x, z, pos ); alSourcefv( src->source, AL_POSITION, pos ); } else { alSource3f( src->source, AL_POSITION, x, 0.0f, z ); } // insert the src into our map pthread_mutex_lock( &sources_lock_ ); sources_.insert( SoundMap::value_type( src->id, src ) ); pthread_mutex_unlock( &sources_lock_ ); // insert an entry for this source to our removed map pthread_mutex_lock( &remove_lock_ ); removed_.insert( BoolMap::value_type( src->id, false ) ); pthread_mutex_unlock( &remove_lock_ ); // insert an entry for this source to our paused map pthread_mutex_lock( &pause_lock_ ); paused_.insert( BoolMap::value_type( src->id, false ) ); pthread_mutex_unlock( &pause_lock_ ); // alSourcePlay( src->source ); // then insert it into the play queue pthread_mutex_lock( &q_lock_ ); play_q_.push( src ); pthread_mutex_unlock( &q_lock_ ); // alert the threads that a new object has been added pthread_cond_broadcast( &empty_q_lock_ ); // increment the id counter object_id_++; return src->id; }
static void setBackgroundVolume(float volume) { alSourcef(s_backgroundSource, AL_GAIN, volume); }
void AudioDevice::al_setSourcePitch(AudioSource* source, float pitch) { alSourcef(source->m_ID, AL_PITCH, pitch); }
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; }