/// <summary> /// Disposes the object. /// </summary> /// <param name="disposing">The disposing state.</param> protected virtual void Dispose(bool disposing) { _beginDispose = true; if (PlaybackState != PlaybackState.Stopped) { lock (_locker) { OpenAL.alSourceStop(_source.SourceId); PlaybackState = PlaybackState.Stopped; RaisePlaybackChanged(); } } if (_source.SourceId != 0) { lock (_locker) { var queuedBuffers = new uint[3]; OpenAL.alSourceUnqueueBuffers(_source.SourceId, 3, queuedBuffers); OpenAL.alDeleteBuffers(3, queuedBuffers); } Owner.SourcePool.FreeSource(_source); Owner.DestroyAudioBuffer(this); } if (disposing) { } }
/// <summary> /// Resumes the playback. /// </summary> public void Resume() { lock (_locker) { Owner.Context.MakeCurrent(); OpenAL.alSourcePlay(_source.SourceId); PlaybackState = PlaybackState.Playing; RaisePlaybackChanged(); } }
/// <summary> /// Stops the playback. /// </summary> public void Stop() { lock (_locker) { Owner.Context.MakeCurrent(); OpenAL.alSourceStop(_source.SourceId); PlaybackState = PlaybackState.Stopped; RaisePlaybackChanged(); } }
/// <summary> /// Requests a Source from the source pool. /// </summary> /// <returns>OpenALSource.</returns> public OpenALSource RequestSource() { _context.MakeCurrent(); var sources = new uint[1]; OpenAL.alGenSources(1, sources); var source = new OpenALSource(sources[0]); _sources.Add(source); return(source); }
/// <summary> /// Initializes the device. /// </summary> private void InitializeDevice() { if (_deviceHandle != IntPtr.Zero) { return; } _disposing = false; _deviceHandle = OpenAL.alcOpenDevice(Name); Context = OpenALContext.CreateContext(_deviceHandle); SourcePool = new OpenALSourcePool(Context); }
/// <summary> /// Frees a source. /// </summary> /// <param name="source">The OpenALSource.</param> public void FreeSource(OpenALSource source) { if (_sources.Contains(source)) { _sources.Remove(source); if (source.SourceId != 0) { _context.MakeCurrent(); var sources = new uint[1]; sources[0] = source.SourceId; OpenAL.alDeleteSources(1, sources); source.Reset(); } } }
/// <summary> /// Disposes the object. /// </summary> /// <param name="disposing">The disposing state.</param> public virtual void Dispose(bool disposing) { if (disposing) { SourcePool.Dispose(); } if (_deviceHandle == IntPtr.Zero) { return; } _disposing = true; Context.Destroy(); OpenAL.alcCloseDevice(_deviceHandle); _deviceHandle = IntPtr.Zero; Context = null; }
/// <summary> /// Initializes the OpenALAudioBuffer class. /// </summary> /// <param name="audioData">The Buffer.</param> /// <param name="format">The WaveFormat.</param> /// <param name="latency">The Latency.</param> public void Initialize(byte[] audioData, WaveFormat format, int latency) { lock (_locker) { Owner.Context.MakeCurrent(); OpenAL.alListener3f(SourceProperty.Position, 0, 0, 1); OpenAL.alListener3f(SourceProperty.Velocity, 0, 0, 0); OpenAL.alListenerfv(SourceProperty.Orientation, new float[] { 0, 0, 1, 0, 1, 0 }); OpenAL.alSourcef(_source.SourceId, SourceProperty.Gain, _audioMixer.Volume); OpenAL.alSourcefv(_source.SourceId, SourceProperty.Position, new[] { _audioMixer.Pan, 0, 0 }); } SampleRate = (uint)format.SamplesPerSec; Latency = latency; _audioData = audioData; WaveFormat = format; Length = audioData.Length / format.AvgBytesPerSec * 1000; _bufferSize = format.AvgBytesPerSec / 1000 * latency; _processedBytes = 0; }
/// <summary> /// Disposes the object. /// </summary> /// <param name="disposing">The disposing state.</param> protected virtual void Dispose(bool disposing) { _context.MakeCurrent(); foreach (var source in _sources) { if (source != null && source.SourceId != 0) { var sources = new uint[1]; sources[0] = source.SourceId; OpenAL.alDeleteSources(1, sources); source.Reset(); } #if DEBUG _logger.Info("Source automatically disposed."); #endif } if (disposing) { _sources.Clear(); } }
/// <summary> /// Fills the buffer. /// </summary> /// <param name="target">The OpenALDataBuffer.</param> private void FillBuffer(OpenALDataBuffer target) { lock (_locker) { var unqueueBuffer = new uint[1]; OpenAL.alSourceUnqueueBuffers(_source.SourceId, 1, unqueueBuffer); var data = new byte[_bufferSize]; var datalength = _bufferSize; if (_bufferSize > _audioData.Length - _processedBytes) { Buffer.BlockCopy(_audioData, _processedBytes, data, 0, _audioData.Length - _processedBytes); datalength = _audioData.Length - _processedBytes; _processedBytes += datalength; } else { Buffer.BlockCopy(_audioData, _processedBytes, data, 0, _bufferSize); _processedBytes += _bufferSize; } _audioMixer.ApplyEffects(data, WaveFormat); OpenAL.alBufferData(target.Id, Format, data, datalength, SampleRate); OpenAL.alSourceQueueBuffers(_source.SourceId, 1, new[] { target.Id }); } }
/// <summary> /// Starts the playback. /// </summary> private void StartPlayback() { if (PlaybackState == PlaybackState.Stopped) { PlaybackState = PlaybackState.Playing; RaisePlaybackChanged(); _processedBytes = 0; _playbackThread = new Task(() => { OpenALDataBuffer buffer1; OpenALDataBuffer buffer2; OpenALDataBuffer buffer3; lock (_locker) { Owner.Context.MakeCurrent(); buffer1 = OpenALDataBuffer.CreateBuffer(); buffer2 = OpenALDataBuffer.CreateBuffer(); buffer3 = OpenALDataBuffer.CreateBuffer(); } buffer1.Next = buffer2; buffer2.Next = buffer3; buffer3.Next = buffer1; OpenALDataBuffer currentBuffer = buffer1; FillBuffer(currentBuffer); currentBuffer = currentBuffer.Next; FillBuffer(currentBuffer); currentBuffer = currentBuffer.Next; FillBuffer(currentBuffer); lock (_locker) { OpenAL.alSourcePlay(_source.SourceId); } while (_processedBytes < _audioData.Length) { if (_beginDispose) { return; } switch (PlaybackState) { case PlaybackState.Paused: _playbackThread.Wait(Latency); continue; case PlaybackState.Stopped: return; } int finishedBuffers; lock (_locker) { OpenAL.alGetSourcei(_source.SourceId, SourceProperty.AllBuffersProcessed, out finishedBuffers); } if (finishedBuffers == 0) { _playbackThread.Wait(Latency); } while (finishedBuffers > 0) { finishedBuffers--; currentBuffer = currentBuffer.Next; FillBuffer(currentBuffer); } Position = _processedBytes / WaveFormat.AvgBytesPerSec * 1000; //if the audio stops where it should not, restart playback lock (_locker) { int sourceState; OpenAL.alGetSourcei(_source.SourceId, SourceProperty.SourceState, out sourceState); if ((SourceState)sourceState == SourceState.Stopped) { OpenAL.alSourcePlay(_source.SourceId); } } } PlaybackState = PlaybackState.Stopped; var queuedBuffers = new uint[3]; RaisePlaybackChanged(); lock (_locker) { OpenAL.alSourceUnqueueBuffers(_source.SourceId, 3, queuedBuffers); OpenAL.alDeleteBuffers(3, queuedBuffers); } }); _playbackThread.Start(); } }
/// <summary> /// Creates a new OpenALContext on the specified OpenALDevice. /// </summary> /// <param name="openALDeviceHandle">The OpenALDevice.</param> public static OpenALContext CreateContext(IntPtr openALDeviceHandle) { return(new OpenALContext(OpenAL.alcCreateContext(openALDeviceHandle, IntPtr.Zero))); }
/// <summary> /// Destroys the Context. /// </summary> public void Destroy() { OpenAL.alcDestroyContext(_handle); }
/// <summary> /// Makes the context the current Context. /// </summary> public void MakeCurrent() { OpenAL.alcMakeContextCurrent(_handle); }