private void PerformStreamingUpdate(AudioData audioDataRes) { int num; AL.GetSource(this.alSource, ALGetSourcei.BuffersProcessed, out num); while (num > 0) { num--; int unqueued; unqueued = AL.SourceUnqueueBuffer(this.alSource); if (OggVorbis.IsStreamValid(this.strOvStr)) { PcmData pcm; bool eof = !OggVorbis.StreamChunk(this.strOvStr, out pcm); if (eof) { OggVorbis.EndStream(ref this.strOvStr); if (this.looped) { OggVorbis.BeginStreamFromMemory(audioDataRes.OggVorbisData, out this.strOvStr); if (pcm.dataLength == 0) { eof = !OggVorbis.StreamChunk(this.strOvStr, out pcm); } else { eof = false; } } } if (pcm.dataLength > 0) { AL.BufferData( unqueued, pcm.channelCount == 1 ? ALFormat.Mono16 : ALFormat.Stereo16, pcm.data, pcm.dataLength * PcmData.SizeOfDataElement, pcm.sampleRate); AL.SourceQueueBuffer(this.alSource, unqueued); } if (pcm.dataLength == 0 || eof) { this.strStopReq = StopRequest.EndOfStream; break; } } } }
private void PerformStreamingBegin(AudioData audioDataRes) { // Generate streaming buffers this.strAlBuffers = new int[3]; for (int i = 0; i < this.strAlBuffers.Length; ++i) { AL.GenBuffers(1, out this.strAlBuffers[i]); } // Begin streaming OggVorbis.BeginStreamFromMemory(audioDataRes.OggVorbisData, out this.strOvStr); // Initially, completely fill all buffers for (int i = 0; i < this.strAlBuffers.Length; ++i) { PcmData pcm; bool eof = !OggVorbis.StreamChunk(this.strOvStr, out pcm); if (pcm.dataLength > 0) { AL.BufferData( this.strAlBuffers[i], pcm.channelCount == 1 ? ALFormat.Mono16 : ALFormat.Stereo16, pcm.data, pcm.dataLength * PcmData.SizeOfDataElement, pcm.sampleRate); AL.SourceQueueBuffer(this.alSource, this.strAlBuffers[i]); if (eof) { break; } } else { break; } } }
private static void ThreadStreamFunc(object param) { SoundInstance sndInst = (SoundInstance)param; while (true) { lock (sndInst.strLock) { if (sndInst.Disposed) { return; } if (!DualityApp.Sound.IsAvailable) { return; } ALSourceState stateTemp = ALSourceState.Stopped; if (sndInst.alSource > AlSource_NotAvailable) { stateTemp = AL.GetSourceState(sndInst.alSource); } if (stateTemp == ALSourceState.Stopped && sndInst.strStopReq != StopRequest.None) { // Stopped due to regular EOF. If strStopReq is NOT set, // the source stopped playing because it reached the end of the buffer // but in fact only because we were too slow inserting new data. return; } else if (sndInst.strStopReq == StopRequest.Immediately) { // Stopped intentionally due to Stop() if (sndInst.alSource > AlSource_NotAvailable) { AL.SourceStop(sndInst.alSource); } return; } Sound soundRes = sndInst.sound.Res; AudioData audioDataRes = sndInst.audioData.Res; if (soundRes == null || audioDataRes == null) { sndInst.Dispose(); return; } if (stateTemp == ALSourceState.Initial) { // Generate streaming buffers sndInst.strAlBuffers = new int[3]; for (int i = 0; i < sndInst.strAlBuffers.Length; ++i) { AL.GenBuffers(1, out sndInst.strAlBuffers[i]); } // Begin streaming OggVorbis.BeginStreamFromMemory(audioDataRes.OggVorbisData, out sndInst.strOvStr); // Initially, completely fill all buffers for (int i = 0; i < sndInst.strAlBuffers.Length; ++i) { PcmData pcm; bool eof = !OggVorbis.StreamChunk(sndInst.strOvStr, out pcm); if (pcm.dataLength > 0) { AL.BufferData( sndInst.strAlBuffers[i], pcm.channelCount == 1 ? ALFormat.Mono16 : ALFormat.Stereo16, pcm.data, pcm.dataLength * PcmData.SizeOfDataElement, pcm.sampleRate); AL.SourceQueueBuffer(sndInst.alSource, sndInst.strAlBuffers[i]); if (eof) { break; } } else { break; } } // Initially play source AL.SourcePlay(sndInst.alSource); stateTemp = AL.GetSourceState(sndInst.alSource); } else { int num; AL.GetSource(sndInst.alSource, ALGetSourcei.BuffersProcessed, out num); while (num > 0) { num--; int unqueued; unqueued = AL.SourceUnqueueBuffer(sndInst.alSource); if (OggVorbis.IsStreamValid(sndInst.strOvStr)) { PcmData pcm; bool eof = !OggVorbis.StreamChunk(sndInst.strOvStr, out pcm); if (eof) { OggVorbis.EndStream(ref sndInst.strOvStr); if (sndInst.looped) { OggVorbis.BeginStreamFromMemory(audioDataRes.OggVorbisData, out sndInst.strOvStr); if (pcm.dataLength == 0) { eof = !OggVorbis.StreamChunk(sndInst.strOvStr, out pcm); } } } if (pcm.dataLength > 0) { AL.BufferData( unqueued, pcm.channelCount == 1 ? ALFormat.Mono16 : ALFormat.Stereo16, pcm.data, pcm.dataLength * PcmData.SizeOfDataElement, pcm.sampleRate); AL.SourceQueueBuffer(sndInst.alSource, unqueued); } if (pcm.dataLength == 0 || eof) { sndInst.strStopReq = StopRequest.EndOfStream; break; } } } } if (stateTemp == ALSourceState.Stopped && sndInst.strStopReq == StopRequest.None) { // If the source stopped unintentionally, restart it. (See above) AL.SourcePlay(sndInst.alSource); } } Thread.Sleep(16); } }