void play_sound_p(Sound *snd) { if(tconfig.intval[NO_AUDIO] || snd->lastplayframe == global.frames) return; snd->lastplayframe = global.frames; ALuint i,res = -1; ALint play; for(i = 0; i < SNDSRC_COUNT; i++) { alGetSourcei(resources.sndsrc[i],AL_SOURCE_STATE,&play); if(play != AL_PLAYING) { res = i; break; } } if(res != -1) { alSourcei(resources.sndsrc[res],AL_BUFFER, snd->alsnd); alSourcePlay(resources.sndsrc[res]); } else { warnx("play_sound_p():\n!- not enough sources"); } }
nzSoundStatus NzSoundEmitter::GetInternalStatus() const { ALint state; alGetSourcei(m_source, AL_SOURCE_STATE, &state); switch (state) { case AL_INITIAL: case AL_STOPPED: return nzSoundStatus_Stopped; case AL_PAUSED: return nzSoundStatus_Paused; case AL_PLAYING: return nzSoundStatus_Playing; default: NazaraInternalError("Source state unrecognized"); } return nzSoundStatus_Stopped; }
void OpenALChannel::stop() { if (mUseStream) { if (mStream) { mStream->release(); delete mStream; mStream = 0; mWasPlaying = false; } } else { ALint state; alGetSourcei(mSourceID, AL_SOURCE_STATE, &state); if (state == AL_PLAYING) { alSourceStop(mSourceID); } } }
//* // ======================================================================================================================= // ======================================================================================================================= // BOOL sound_SampleIsFinished( AUDIO_SAMPLE *psSample ) { #ifndef WZ_NOSOUND //~~~~~~~~~~ ALenum state; //~~~~~~~~~~ alGetSourcei( psSample->iSample, AL_SOURCE_STATE, &state ); sound_GetError(); // check for an error and clear the error state for later on in this function if (state == AL_PLAYING || state == AL_PAUSED) { return false; } if (psSample->iSample != (ALuint)AL_INVALID) { alDeleteSources(1, &(psSample->iSample)); sound_GetError(); psSample->iSample = AL_INVALID; } #endif return true; }
void cSoundSourceStream::Step(){ int processed = 0; if(RemainingBytes() == 0 && IsPlaying() && !IsPaused()){ // sound is finished Stop(); } else if(IsPlaying() && RemainingBytes() > 0){ // read the number of played buffers alGetSourcei(miId, AL_BUFFERS_PROCESSED, &processed); CheckOpenAl(); // and refill them while(processed--){ ALuint buffer; alSourceUnqueueBuffers(miId, 1, &buffer); CheckOpenAl(); StreamBuffer(buffer); alSourceQueueBuffers(miId, 1, &buffer); CheckOpenAl(); //printf("#### source step remaining=%i playing=%d paused=%d\n",mpStream->RemainingBytes(),IsPlaying(),IsPaused()); } } }
private_audio::AudioSource *AudioEngine::_AcquireAudioSource() { // (1) Find and return the first source that does not have an owner for(std::vector<AudioSource *>::iterator i = _audio_sources.begin(); i != _audio_sources.end(); ++i) { if((*i)->owner == NULL) { return *i; } } // (2) If all sources are owned, find one that is in the initial or stopped state and change its ownership for(std::vector<AudioSource *>::iterator i = _audio_sources.begin(); i != _audio_sources.end(); ++i) { ALint state; alGetSourcei((*i)->source, AL_SOURCE_STATE, &state); if(state == AL_INITIAL || state == AL_STOPPED) { (*i)->owner->_source = NULL; (*i)->Reset(); // this call sets the source owner pointer to NULL return *i; } } // (3) Return NULL in the (extremely rare) case that all sources are owned and actively playing or paused return NULL; }
//================================================================================================= void Sounds::play() { if (!file) return; ALint state; alGetSourcei( source, AL_SOURCE_STATE, &state ); if (state == AL_PLAYING) return; if (state != AL_PAUSED && flag & STREAM) { file->read( buffer, BUFFER_SIZE ); alBufferData( buffers[0], format, buffer, BUFFER_SIZE, file->freq ); file->read( buffer, BUFFER_SIZE ); alBufferData( buffers[1], format, buffer, BUFFER_SIZE, file->freq ); alSourceQueueBuffers( source, 2, buffers ); ALApp::addStream( this ); } alSourcePlay( source ); }
/* Function: alureGetSourceOffset * * Gets the sample offset of the specified source. For sources started with * <alurePlaySourceStream>, this will be the total samples played. The offset * will loop back to 0 when the stream rewinds for any specified loopcount. For * non-streamed sources, the function will behave as if retrieving the * AL_SAMPLE_OFFSET source value. * * Returns: * (alureUInt)-1 on error. * * See Also: * <alurePlaySourceStream> */ ALURE_API alureUInt64 ALURE_APIENTRY alureGetSourceOffset(ALuint source) { if(alGetError() != AL_NO_ERROR) { SetError("Existing OpenAL error"); return (alureUInt64)-1; } EnterCriticalSection(&cs_StreamPlay); ALint pos; if((alGetSourcei(source, AL_SAMPLE_OFFSET, &pos),alGetError()) != AL_NO_ERROR) { LeaveCriticalSection(&cs_StreamPlay); SetError("Error retrieving source offset"); return (alureUInt64)-1; } alureUInt64 retval = static_cast<ALuint>(pos); std::list<AsyncPlayEntry>::iterator i = AsyncPlayList.begin(), end = AsyncPlayList.end(); while(i != end) { if(i->source == source) { retval += i->base_time; if(i->max_time) retval %= i->max_time; break; } i++; } LeaveCriticalSection(&cs_StreamPlay); return retval; }
void hdW32SoundVoiceDevice::UpdateVoice() { if ( voice_ ) { ALint processed; ALint queued; alGetSourceiv( voice_, AL_BUFFERS_PROCESSED, &processed ); HEART_CHECK_OPENAL_ERRORS(); alGetSourceiv( voice_, AL_BUFFERS_QUEUED, &queued ); HEART_CHECK_OPENAL_ERRORS(); if ( processed > 0 ) { ALuint proBufs[BUFFER_COUNT]; alSourceUnqueueBuffers( voice_, processed, proBufs ); HEART_CHECK_OPENAL_ERRORS(); } ALint playing; alGetSourcei( voice_, AL_SOURCE_STATE, &playing ); HEART_CHECK_OPENAL_ERRORS(); if ( queued && playing != AL_PLAYING && playing != AL_PAUSED ) { alSourcePlay( voice_ ); } if ( queued == 0 && sourceComplete_ == hTrue ) { info_.callback_( this, VOICE_STOPPED ); } if ( queued < BUFFER_COUNT && sourceComplete_ != hTrue ) { info_.callback_( this, NEED_MORE_PCM_DATA ); } } }
void FSoundManager::Update( F32 fDTime ) { FSoundIterator iIt = lSoundList.Begin(); for( ;iIt != lSoundList.End(); ) { ALint iSourceState; I32 iInd = iIt->GetSourceInd(); alGetSourcei( lpSources[iInd].iSourceID, AL_SOURCE_STATE, &iSourceState ); if( LogOpenAL() ) NSLog( @"SourceID %d Index %ld", lpSources[iInd].iSourceID, iInd ); if( (iSourceState == AL_PLAYING) || (iSourceState == AL_PAUSED) ) { iIt++; continue; } delete *iIt; iIt = lSoundList.Erase( iIt ); } /* for( I32 i = 0;i < iMaxSources;i++ ) { ALint iSourceState; if( !lpSources[i].bBusy ) continue; alGetSourcei( lpSources[i].iSourceID, AL_SOURCE_STATE, &iSourceState ); LogOpenAL(); if( (iSourceState == AL_PLAYING) || (iSourceState == AL_PAUSED) ) continue; StopSound( lpSources[i].lpSoundObj ); LogOpenAL(); }*/ }
bool CStreamItem::IdleTask() { AL_CHECK HandleFade(); AL_CHECK int proc_state; alGetSourceiv(m_ALSource, AL_SOURCE_STATE, &proc_state); AL_CHECK if (proc_state == AL_STOPPED) { if (m_LastPlay) return (proc_state != AL_STOPPED); } else { COggData* tmp = (COggData*)m_SoundData; if (! tmp->IsFileFinished()) { int num_processed; alGetSourcei(m_ALSource, AL_BUFFERS_PROCESSED, &num_processed); AL_CHECK if (num_processed > 0) { ALuint* al_buf = new ALuint[num_processed]; alSourceUnqueueBuffers(m_ALSource, num_processed, al_buf); AL_CHECK int didWrite = tmp->FetchDataIntoBuffer(num_processed, al_buf); alSourceQueueBuffers(m_ALSource, didWrite, al_buf); AL_CHECK delete[] al_buf; } } else if (GetLooping())
bool SoundSource::_updateSound(Ogre::Real ElapsedTime) { _update(); if(mActive) { alSource3f(mSource, AL_POSITION, mDerivedPosition.x, mDerivedPosition.y, mDerivedPosition.z); alSource3f(mSource, AL_DIRECTION, mDerivedDirection.x, mDerivedDirection.y, mDerivedDirection.z); mBuffer->update(mSource, ElapsedTime); alGetSourcei(mSource, AL_SOURCE_STATE, &mState); SoundSystem::checkError(__FUNCTION__); updateDistanceAttenuation(); updateEffectiveGain(); } else { switch(mState) { case AL_PLAYING: //if not looping and duration has passed stop if (mTimer->getPosition() > mBuffer->getDuration() && ! mLoop) { mTimer->stop(); mState = AL_STOPPED; } break; case AL_STOPPED: case AL_INITIAL: case AL_PAUSED: //NOOP; break; } } return true; }
int EOSAudioDevice::getAvailableSource() { int state = -1; for(unsigned int handle=0; handle<sourcesHandle.size(); handle++) { alGetSourcei(sourcesHandle[handle], AL_SOURCE_STATE, &state); checkErrors("getAvailableSource[source status query]"); if(state == AL_STOPPED || state == AL_INITIAL) { resetSource(sourcesHandle[handle]); return sourcesHandle[handle]; } } // reset error status int alError = alGetError(); _skippedSounds++; //checkErrors("GetAvailableSource()"); //LOGERROR("[eos.audio] getAvailableSource() -> No available sources."); return SOURCE_NONE; }
void ActiveSound::clear() { if(mActive) { if(!mData.mBuffer->isOgg()) { ALint state; alGetSourcei(mSource,AL_SOURCE_STATE,&state); alSourceStop(mSource); alSourcei(mSource,AL_BUFFER,AL_NONE); mActive = false; } else { mActive = false; mOgg->release(); } if (alGetError() != AL_NO_ERROR) { //add log message here } } }
int SoundManager::_getSource(bool reserved) { // Find a unused source ALint state; //LOOP - Search in container for( unsigned int i=0; i < mSources.size(); i++) { //If - Not reserved if (!mSources[i].reserved) { // Check if it is being used alGetSourcei(mSources[i].source,AL_SOURCE_STATE, &state); if (state != AL_PLAYING && state != AL_PAUSED) { mSources[i].reserved = reserved; return i; } } }//LOOP //All sources are used return -1; }
void CBufferItem::ReleaseOpenALBuffer() { if ( m_ALSource == 0 ) return; int num_processed; AL_CHECK; alGetSourcei(m_ALSource, AL_BUFFERS_PROCESSED, &num_processed); AL_CHECK; if (num_processed > 0) { ALuint* al_buf = new ALuint[num_processed]; alSourceUnqueueBuffers(m_ALSource, num_processed, al_buf); AL_CHECK; delete[] al_buf; } alSourcei(m_ALSource, AL_BUFFER, 0); ((CSoundManager*)g_SoundManager)->ReleaseALSource(m_ALSource); AL_CHECK; m_ALSource = 0; }
DWORD WINAPI stream_run(void * data) { SoundThread * me = (SoundThread *) data; while(me->running) { if(me->sound) { Sound * sound = me->sound; ALuint uiSource; ALint iState = AL_PLAYING; ALuint uiBuffers[1]; alGenBuffers(1, uiBuffers); alGenSources(1, &uiSource); alBufferData(uiBuffers[0], sound->format, sound->data, sound->size, sound->freq); assert(AL_NO_ERROR == alGetError()); alSourceQueueBuffers(uiSource, 1, &uiBuffers[0]); alSourcef(uiSource, AL_GAIN, sound->volume); alSourcePlay(uiSource); while(iState == AL_PLAYING) { Sleep(16); alGetSourcei(uiSource, AL_SOURCE_STATE, &iState); } alSourceStop(uiSource); alSourcei(uiSource, AL_BUFFER, 0); alDeleteSources(1, &uiSource); alDeleteBuffers(1, uiBuffers); me->occupied = false; me->sound = 0; } if(me->running) SuspendThread(me->handle); } return 0; }
void playSound() { char * sound [] = {"scale-a6.wav", "scale-c6.wav", "scale-c7.wav" , "scale-d6.wav", "scale-e6.wav", "scale-f6.wav", "scale-g6.wav", "scale-h6.wav"}; int index = rand() % 8; ALuint buffer, source; ALuint state; // Initialize the environment alutInit(0, NULL); // Capture errors alGetError(); // Load pcm data into buffer buffer = alutCreateBufferFromFile(sound[index]); // Create sound source (use buffer to fill source) alGenSources(1, &source); alSourcei(source, AL_BUFFER, buffer); // Play alSourcePlay(source); // Wait for the song to complete do { alGetSourcei(source, AL_SOURCE_STATE, &state); } while (state == AL_PLAYING); // Clean up sources and buffers alDeleteSources(1, &source); alDeleteBuffers(1, &buffer); // Exit everything alutExit(); }
/** * @brief Play a 44100Hz mono 16bit PCM sound */ void OpenAL::playMono16Sound(const QByteArray& data) { QMutexLocker locker(&audioLock); if (!autoInitOutput()) return; if (!alMainBuffer) alGenBuffers(1, &alMainBuffer); ALint state; alGetSourcei(alMainSource, AL_SOURCE_STATE, &state); if (state == AL_PLAYING) { alSourceStop(alMainSource); alSourcei(alMainSource, AL_BUFFER, AL_NONE); } alBufferData(alMainBuffer, AL_FORMAT_MONO16, data.constData(), data.size(), 44100); alSourcei(alMainSource, AL_BUFFER, static_cast<ALint>(alMainBuffer)); alSourcePlay(alMainSource); int durationMs = data.size() * 1000 / 2 / 44100; playMono16Timer.start(durationMs + 50); }
static void slider_changed(GtkRange *progressbar, struct arguments *argument) { if(fabs(gtk_adjustment_get_value(argument->adjust) - g_timer_elapsed(argument->elapsed, NULL) - argument->offset) > 0.005f) { argument->offset = gtk_adjustment_get_value(argument->adjust); alSourcei(source, AL_BUFFER, 0); alDeleteSources(1, &source); ALenum format; ALuint buffer; alSourcei(source, AL_BUFFER, 0); g_timer_start(argument->elapsed); alGenBuffers(1, &buffer); alGenSources(1, &source); format = AL_FORMAT_STEREO16; alBufferData(buffer, format, current_sample_array + channels * (int) ((gdouble) (nb_bytes_per_sample * sample_rate) * (gdouble) gtk_adjustment_get_value(argument->adjust)), (nSamples - (int) ( (gdouble) gtk_adjustment_get_value(argument->adjust) * (gdouble) sample_rate )) * sizeof(ALint), sample_rate); alSourcei(source, AL_BUFFER, buffer); alGetSourcei(source, AL_SOURCE_STATE, &status); alSourcePlay(source); g_source_remove(argument->tag); if(argument->continue_count != 0) { argument->tag = g_timeout_add_seconds(current_song.duration - (int)gtk_adjustment_get_value(argument->adjust), endless, argument); } argument->bartag = g_timeout_add_seconds(1, timer_progressbar, argument); } }
static void unqueue_old_buffers(int stream) { audio_stream *s = g_streams[stream]; ALint old_buffers = 0; g_mutex_lock(s->mutex); // locking here because unqueue_old_buffers can be run called from // both the video thread and the emulation thread (consider changing this, // perhaps even have a separate thread for periodically unqueuing). alGetSourcei(s->source, AL_BUFFERS_PROCESSED, &old_buffers); check_al_error("alGetSourcei (AL_BUFFERS_PROCESSED)"); if (old_buffers > 0) { ALuint buffers[MAX_BUFFERS]; old_buffers = MIN(old_buffers, MAX_BUFFERS); alSourceUnqueueBuffers(s->source, old_buffers, buffers); if (check_al_error("alSourceUnqueueBuffers") != AL_NO_ERROR) { fs_log("while trying to unqueue %d buffers\n"); } for (int i = 0; i < old_buffers; i++) { g_queue_push_tail(s->queue, GUINT_TO_POINTER(buffers[i])); } s->buffers_queued -= old_buffers; } g_mutex_unlock(s->mutex); }
// 缓冲区复位以便于从头播放 ///////////////////////////////////////////////////////////////////////////////// void OALMusicBuffer::DoReset() { ALint queued_; alGetSourcei(source_, AL_BUFFERS_QUEUED, &queued_); if (queued_ > 0) { std::vector<ALuint> cur_queue(queued_); alSourceUnqueueBuffers(source_, queued_, &cur_queue[0]); } ALenum const format(Convert(format_)); std::vector<uint8_t> data(READSIZE); dataSource_->Reset(); ALsizei non_empty_buf = 0; // 每个缓冲区中装1 / PreSecond秒的数据 for (auto const & buf : bufferQueue_) { data.resize(dataSource_->Read(&data[0], data.size())); if (data.empty()) { break; } else { ++ non_empty_buf; alBufferData(buf, format, &data[0], static_cast<ALuint>(data.size()), static_cast<ALuint>(freq_)); } } alSourceQueueBuffers(source_, non_empty_buf, &bufferQueue_[0]); alSourceRewindv(1, &source_); }
//----------------------------------------------------------- //ofxAA vector<float>& ofSoundPlayerExtended::getCurrentBufferForChannel(int _size, int channel){ if(int(currentBuffer.size()) != _size) { currentBuffer.resize(_size); } currentBuffer.assign(currentBuffer.size(),0); int nCh = channel; //channels number starting from 0 if (nCh >= channels){ nCh = channels - 1;//limit to file nChannels ofLog(OF_LOG_WARNING,"ofSoundPlayerExtended: channel requested exceeds file channels"); } int pos; for(int k = 0; k < int(sources.size())/channels; ++k) { alGetSourcei(sources[k*channels],AL_SAMPLE_OFFSET,&pos); //for(int i = 0; i < channels; ++i) //avoid channels sumup int i = nCh; //use only specified channel { for(int j = 0; j < _size; ++j) { if(pos+j<(int)buffer.size()) { currentBuffer[j] += float(buffer[(pos+j)*channels+i])/65534.0f; } else { currentBuffer[j] = 0; } } } } return currentBuffer; }
void dll_al_GetSourcei(ALuint source, ALenum param, ALint *value) { alGetSourcei(source, param, value); }
//----------------------------------------------------------------------------- void MusicStream::_update(float deltatime) { if (mMusic != 0) { ALenum srcState; int processed; size_t buffers[2]; // Updates fading switch (mFade) { case MF_FADE_IN: mFadeVolume += mFadeSpd*deltatime; if (mFadeVolume >= 1.0f) { // Stop fading mFadeVolume = 1.0f; mFade = MF_NO_FADE; mAudioMan->_fadeEnded(MF_FADE_IN); } break; case MF_FADE_OUT: mFadeVolume -= mFadeSpd*deltatime; if (mFadeVolume <= 0.0f) { // Stop fading mFadeVolume = 0.0f; mFade = MF_NO_FADE; mAudioMan->_fadeEnded(MF_FADE_OUT); switch (mState) { case MSS_PAUSING: alSourcePause(mMusicSrc); mAudioMan->_alErrorCheck("MusicStream::_update()", "Failed pausing music source"); break; case MSS_STOPPING: alSourceStop(mMusicSrc); mAudioMan->_alErrorCheck("MusicStream::_update()", "Failed stopping music source"); break; default: break; } } break; default: break; } // Sets source volume alSourcef(mMusicSrc,AL_GAIN,mFadeVolume * mMaxVolume * mAudioMan->getMasterMusicVolume()); mAudioMan->_alErrorCheck("MusicStream::_update()", "Failed setting music source volume"); // Refills processed buffer with more data from the stream alGetSourcei(mMusicSrc,AL_BUFFERS_PROCESSED,&processed); mAudioMan->_alErrorCheck("MusicStream::_update()", "Failed getting number of processed buffers from music source"); alSourceUnqueueBuffers(mMusicSrc,processed,buffers); mAudioMan->_alErrorCheck("MusicStream::_update()", "Failed unqueuing processed buffers from music source"); for (int i = 0;i < processed;++i) { if (mState == MSS_ENDED) { mAudioMan->_streamEnded(); break; } // Gets more data from OGG/Vorbis stream and queue it back pullStream(buffers[i]); alSourceQueueBuffers(mMusicSrc,1,&buffers[i]); mAudioMan->_alErrorCheck("MusicStream::_update()", "Failed queueing audio buffer in music source"); } // Makes sure the music doesn't stuck stopped // It may happen when you drag the window for too long alGetSourcei(mMusicSrc,AL_SOURCE_STATE,&srcState); mAudioMan->_alErrorCheck("MusicStream::_update()", "Failed getting music source state"); if (srcState == AL_STOPPED) { if (mState != MSS_ENDED) { alSourcePlay(mMusicSrc); mAudioMan->_alErrorCheck("MusicStream::_update()", "Failed playing music source"); } } } _getCurrentPos(); }
void Sound::Impl::PlaySound(const boost::filesystem::path& path, bool is_ui_sound/* = false*/) { if (!m_initialized || !GetOptionsDB().Get<bool>("UI.sound.enabled") || (is_ui_sound && UISoundsTemporarilyDisabled())) return; std::string filename = PathString(path); ALuint current_buffer; ALenum source_state; ALsizei ogg_freq; FILE *file = nullptr; int m_i; bool found_buffer = false; bool found_source = false; #ifdef FREEORION_WIN32 ov_callbacks callbacks = { (size_t (*)(void *, size_t, size_t, void *)) fread, (int (*)(void *, ogg_int64_t, int)) _fseek64_wrap, (int (*)(void *)) fclose, (long (*)(void *)) ftell }; #endif if (alcGetCurrentContext()) { /* First check if the sound data of the file we want to play is already buffered somewhere */ std::map<std::string, ALuint>::iterator it = m_buffers.find(filename); if (it != m_buffers.end()) { current_buffer = it->second; found_buffer = true; } else { if ((file = fopen(filename.c_str(), "rb")) != nullptr) { // make sure we CAN open it OggVorbis_File ogg_file; vorbis_info *vorbis_info; ALenum ogg_format; #ifdef FREEORION_WIN32 if (!(ov_test_callbacks(file, &ogg_file, nullptr, 0, callbacks))) // check if it's a proper ogg #else if (!(ov_test(file, &ogg_file, nullptr, 0))) // check if it's a proper ogg #endif { ov_test_open(&ogg_file); // it is, now fully open the file /* now we need to take some info we will need later */ vorbis_info = ov_info(&ogg_file, -1); if (vorbis_info->channels == 1) ogg_format = AL_FORMAT_MONO16; else ogg_format = AL_FORMAT_STEREO16; ogg_freq = vorbis_info->rate; ogg_int64_t byte_size = ov_pcm_total(&ogg_file, -1) * vorbis_info->channels * 2; if (byte_size <= 1024 * 1024 * 1024) { /* fill up the buffers and queue them up for the first time */ ALuint sound_handle; alGenBuffers(1, &sound_handle); int loop = 0; RefillBuffer(&ogg_file, ogg_format, ogg_freq, sound_handle, byte_size, loop); current_buffer = sound_handle; found_buffer = true; m_buffers.insert(std::make_pair(filename, sound_handle)); } else { ErrorLogger() << "PlaySound: unable to open file " << filename.c_str() << " too big to buffer. Aborting\n"; } ov_clear(&ogg_file); } else { ErrorLogger() << "PlaySound: unable to open file " << filename.c_str() << " possibly not a .ogg vorbis file. Aborting\n"; } } } if (found_buffer) { /* Now that we have the buffer, we need to find a source to send it to */ for (m_i = 1; m_i < NUM_SOURCES; ++m_i) { // as we're playing sounds we start at 1. 0 is reserved for music alGetSourcei(m_sources[m_i], AL_SOURCE_STATE, &source_state); if ((source_state != AL_PLAYING) && (source_state != AL_PAUSED)) { found_source = true; alSourcei(m_sources[m_i], AL_BUFFER, current_buffer); alSourcePlay(m_sources[m_i]); break; // so that the sound won't block all the sources } } if (!found_source) ErrorLogger() << "PlaySound: Could not find aviable source - playback aborted\n"; } source_state = alGetError(); if (source_state != AL_NONE) ErrorLogger() << "PlaySound: OpenAL ERROR: " << alGetString(source_state); /* it's important to check for errors, as some functions won't work properly if * they're called when there is a unchecked previous error. */ } }
//---------------------------------------------------------------------------------- // //---------------------------------------------------------------------------------- bool SoundVoice::CheckPlaying() { ALint state = 0; alGetSourcei(m_source, AL_SOURCE_STATE, &state); return state == AL_PLAYING || state == AL_PAUSED; }
void SoundChannel::QueueBuffers() { // See that we do have waiting sounds and they're ready to play if (!pending_sounds_.size()) return; if ((*pending_sounds_.begin())->GetHandle() == 0) return; // Create source now if did not exist already if (!CreateSource()) { state_ = Foundation::SoundServiceInterface::Stopped; pending_sounds_.clear(); return; } bool queued = false; // Buffer pending sounds, move them to playing vector while (pending_sounds_.size()) { SoundPtr sound = *pending_sounds_.begin(); ALuint buffer = sound->GetHandle(); // If no valid handle yet, cannot play this one, break out if (!buffer) return; alGetError(); alSourceQueueBuffers(handle_, 1, &buffer); ALenum error = alGetError(); if (error != AL_NONE) { // If queuing fails, we may have changed sound format. Stop, flush queue & retry alSourceStop(handle_); alSourcei(handle_, AL_BUFFER, 0); alSourceQueueBuffers(handle_, 1, &buffer); ALenum error = alGetError(); if (error != AL_NONE) OpenALAudioModule::LogError("Could not queue OpenAL sound buffer: " + ToString<int>(error)); else { playing_sounds_.push_back(sound); queued = true; } } else { playing_sounds_.push_back(sound); queued = true; } pending_sounds_.pop_front(); } // If at least one sound queued, start playback if not already playing if (queued) { ALint playing; alGetSourcei(handle_, AL_SOURCE_STATE, &playing); if (playing != AL_PLAYING) alSourcePlay(handle_); state_ = Foundation::SoundServiceInterface::Playing; } }
static gint gst_openal_sink_write (GstAudioSink * audiosink, gpointer data, guint length) { GstOpenALSink *sink = GST_OPENAL_SINK (audiosink); ALint processed, queued, state; ALCcontext *old; gulong rest_us; g_assert (length == sink->buffer_length); old = pushContext (sink->default_context); rest_us = (guint64) (sink->buffer_length / sink->bytes_per_sample) * G_USEC_PER_SEC / sink->rate / sink->channels; do { alGetSourcei (sink->default_source, AL_SOURCE_STATE, &state); alGetSourcei (sink->default_source, AL_BUFFERS_QUEUED, &queued); alGetSourcei (sink->default_source, AL_BUFFERS_PROCESSED, &processed); if (checkALError () != AL_NO_ERROR) { GST_ELEMENT_ERROR (sink, RESOURCE, WRITE, (NULL), ("Source state error detected")); length = 0; goto out_nolock; } if (processed > 0 || queued < sink->buffer_count) break; if (state != AL_PLAYING) alSourcePlay (sink->default_source); g_usleep (rest_us); } while (1); GST_OPENAL_SINK_LOCK (sink); if (sink->write_reset != AL_FALSE) { sink->write_reset = AL_FALSE; length = 0; goto out; } queued -= processed; while (processed-- > 0) { ALuint bid; alSourceUnqueueBuffers (sink->default_source, 1, &bid); } if (state == AL_STOPPED) { /* "Restore" from underruns (not actually needed, but it keeps delay * calculations correct while rebuffering) */ alSourceRewind (sink->default_source); } alBufferData (sink->buffers[sink->buffer_idx], sink->format, data, sink->buffer_length, sink->rate); alSourceQueueBuffers (sink->default_source, 1, &sink->buffers[sink->buffer_idx]); sink->buffer_idx = (sink->buffer_idx + 1) % sink->buffer_count; queued++; if (state != AL_PLAYING && queued == sink->buffer_count) alSourcePlay (sink->default_source); if (checkALError () != AL_NO_ERROR) { GST_ELEMENT_ERROR (sink, RESOURCE, WRITE, (NULL), ("Source queue error detected")); goto out; } out: GST_OPENAL_SINK_UNLOCK (sink); out_nolock: popContext (old, sink->default_context); return length; }
// Creates and initializes an audio context. int ai_context_create(struct cen64_ai_context *context) { uint8_t buf[8]; unsigned i; context->cur_frequency = 31985; if ((context->dev = alcOpenDevice(NULL)) == NULL) { printf("Failed to open the OpenAL device.\n"); return 1; } if ((context->ctx = alcCreateContext(context->dev, NULL)) == NULL) { printf("Failed to create an OpenAL context.\n"); alcCloseDevice(context->dev); return 1; } alcMakeContextCurrent(context->ctx); // Context/device is setup, create some buffers and a source. alGenBuffers(sizeof(context->buffers) / sizeof(*context->buffers), context->buffers); if (alGetError() != AL_NO_ERROR) { alcMakeContextCurrent(NULL); alcDestroyContext(context->ctx); alcCloseDevice(context->dev); } alGenSources(1, &context->source); if (alGetError() != AL_NO_ERROR) { alDeleteBuffers(sizeof(context->buffers) / sizeof(*context->buffers), context->buffers); alcMakeContextCurrent(NULL); alcDestroyContext(context->ctx); alcCloseDevice(context->dev); } // Queue/prime buffers, clear them to prevent pops. // Playing a little test also allows us to verify // that we (probably) won't get weird OpenAL errors // later on if things work now. memset(buf, 0x0, sizeof(buf)); for (i = 0; i < sizeof(context->buffers) / sizeof(*context->buffers); i++) alBufferData(context->buffers[i], AL_FORMAT_STEREO16, buf, sizeof(buf), context->cur_frequency); alSourceQueueBuffers(context->source, sizeof(context->buffers) / sizeof(*context->buffers), context->buffers); alSourcePlay(context->source); if (alGetError() != AL_NO_ERROR) { ai_context_destroy(context); return 1; } // Now wait for them to drain. while (1) { ALint val; alGetSourcei(context->source, AL_BUFFERS_PROCESSED, &val); if (val == (sizeof(context->buffers) / sizeof(*context->buffers))) break; } if (alGetError() != AL_NO_ERROR) { ai_context_destroy(context); return 1; } context->unqueued_buffers = 0; return 0; }