bool SoundStream::fillQueue() { // Fill and enqueue all the available buffers bool requestStop = false; for (int i = 0; (i < BufferCount) && !requestStop; ++i) { if (fillAndPushBuffer(i)) requestStop = true; } return requestStop; }
bool SoundStream::fillQueue() { // Fill and enqueue all the available buffers bool requestStop = false; for (int i = 0; (i < BufferCount) && !requestStop; ++i) { // Since no sound has been loaded yet, we can't schedule loop seeks preemptively, // So if we start on EOF or Loop End, we let fillAndPushBuffer() adjust the sample count if (fillAndPushBuffer(i, (i == 0))) requestStop = true; } return requestStop; }
bool SoundStream::fillAndPushBuffer(unsigned int bufferNum) { bool requestStop = false; // Acquire audio data Chunk data = {NULL, 0}; if (!onGetData(data)) { // Mark the buffer as the last one (so that we know when to reset the playing position) m_endBuffers[bufferNum] = true; // Check if the stream must loop or stop if (m_loop) { // Return to the beginning of the stream source onSeek(Time::Zero); // If we previously had no data, try to fill the buffer once again if (!data.samples || (data.sampleCount == 0)) { return fillAndPushBuffer(bufferNum); } } else { // Not looping: request stop requestStop = true; } } // Fill the buffer if some data was returned if (data.samples && data.sampleCount) { unsigned int buffer = m_buffers[bufferNum]; // Fill the buffer ALsizei size = static_cast<ALsizei>(data.sampleCount) * sizeof(Int16); alCheck(alBufferData(buffer, m_format, data.samples, size, m_sampleRate)); // Push it into the sound queue alCheck(alSourceQueueBuffers(m_source, 1, &buffer)); } return requestStop; }
void SoundStream::streamData() { // Create the buffers alCheck(alGenBuffers(BufferCount, m_buffers)); for (int i = 0; i < BufferCount; ++i) m_endBuffers[i] = false; // Fill the queue bool requestStop = fillQueue(); // Play the sound alCheck(alSourcePlay(m_source)); while (m_isStreaming) { // The stream has been interrupted! if (SoundSource::getStatus() == Stopped) { if (!requestStop) { // Just continue alCheck(alSourcePlay(m_source)); } else { // End streaming m_isStreaming = false; } } // Get the number of buffers that have been processed (ie. ready for reuse) ALint nbProcessed = 0; alCheck(alGetSourcei(m_source, AL_BUFFERS_PROCESSED, &nbProcessed)); while (nbProcessed--) { // Pop the first unused buffer from the queue ALuint buffer; alCheck(alSourceUnqueueBuffers(m_source, 1, &buffer)); // Find its number unsigned int bufferNum = 0; for (int i = 0; i < BufferCount; ++i) if (m_buffers[i] == buffer) { bufferNum = i; break; } // Retrieve its size and add it to the samples count if (m_endBuffers[bufferNum]) { // This was the last buffer: reset the sample count m_samplesProcessed = 0; m_endBuffers[bufferNum] = false; } else { ALint size, bits; alCheck(alGetBufferi(buffer, AL_SIZE, &size)); alCheck(alGetBufferi(buffer, AL_BITS, &bits)); m_samplesProcessed += size / (bits / 8); } // Fill it and push it back into the playing queue if (!requestStop) { if (fillAndPushBuffer(bufferNum)) requestStop = true; } } // Leave some time for the other threads if the stream is still playing if (SoundSource::getStatus() != Stopped) sleep(milliseconds(10)); } // Stop the playback alCheck(alSourceStop(m_source)); // Unqueue any buffer left in the queue clearQueue(); // Delete the buffers alCheck(alSourcei(m_source, AL_BUFFER, 0)); alCheck(alDeleteBuffers(BufferCount, m_buffers)); }
void SoundStream::streamData() { bool requestStop = false; { Lock lock(m_threadMutex); // Check if the thread was launched Stopped if (m_threadStartState == Stopped) { m_isStreaming = false; return; } } // Create the buffers alCheck(alGenBuffers(BufferCount, m_buffers)); for (int i = 0; i < BufferCount; ++i) m_endBuffers[i] = false; // Fill the queue requestStop = fillQueue(); // Play the sound alCheck(alSourcePlay(m_source)); { Lock lock(m_threadMutex); // Check if the thread was launched Paused if (m_threadStartState == Paused) alCheck(alSourcePause(m_source)); } for (;;) { { Lock lock(m_threadMutex); if (!m_isStreaming) break; } // The stream has been interrupted! if (SoundSource::getStatus() == Stopped) { if (!requestStop) { // Just continue alCheck(alSourcePlay(m_source)); } else { // End streaming Lock lock(m_threadMutex); m_isStreaming = false; } } // Get the number of buffers that have been processed (i.e. ready for reuse) ALint nbProcessed = 0; alCheck(alGetSourcei(m_source, AL_BUFFERS_PROCESSED, &nbProcessed)); while (nbProcessed--) { // Pop the first unused buffer from the queue ALuint buffer; alCheck(alSourceUnqueueBuffers(m_source, 1, &buffer)); // Find its number unsigned int bufferNum = 0; for (int i = 0; i < BufferCount; ++i) if (m_buffers[i] == buffer) { bufferNum = i; break; } // Retrieve its size and add it to the samples count if (m_endBuffers[bufferNum]) { // This was the last buffer: reset the sample count m_samplesProcessed = 0; m_endBuffers[bufferNum] = false; } else { ALint size, bits; alCheck(alGetBufferi(buffer, AL_SIZE, &size)); alCheck(alGetBufferi(buffer, AL_BITS, &bits)); // Bits can be 0 if the format or parameters are corrupt, avoid division by zero if (bits == 0) { err() << "Bits in sound stream are 0: make sure that the audio format is not corrupt " << "and initialize() has been called correctly" << std::endl; // Abort streaming (exit main loop) Lock lock(m_threadMutex); m_isStreaming = false; requestStop = true; break; } else { m_samplesProcessed += size / (bits / 8); } } // Fill it and push it back into the playing queue if (!requestStop) { if (fillAndPushBuffer(bufferNum)) requestStop = true; } } // Leave some time for the other threads if the stream is still playing if (SoundSource::getStatus() != Stopped) sleep(milliseconds(10)); } // Stop the playback alCheck(alSourceStop(m_source)); // Dequeue any buffer left in the queue clearQueue(); // Delete the buffers alCheck(alSourcei(m_source, AL_BUFFER, 0)); alCheck(alDeleteBuffers(BufferCount, m_buffers)); }