private void PlatformStop(bool immediate) { if (!SourceId.HasValue) { return; } AL.SourceStop(SourceId.Value); ALHelper.CheckError("Failed to stop source."); // Reset the SendFilter to 0 if we are NOT using reverb since sources are recycled if (Controller.Efx.IsAvailable) { Controller.Efx.BindSourceToAuxiliarySlot(SourceId.Value, 0, 0, 0); ALHelper.CheckError("Failed to unset reverb."); AL.Source(SourceId.Value, ALSourcei.EfxDirectFilter, 0); ALHelper.CheckError("Failed to unset filter."); } AL.Source(SourceId.Value, ALSourcei.Buffer, 0); ALHelper.CheckError("Failed to free source from buffer."); Controller.RecycleSource(SourceId.Value); SourceId = null; }
private void PlatformApply3D(AudioListener listener, AudioEmitter emitter) { if (!SourceId.HasValue) { return; } AL.GetListener(ALListener3f.Position, out float x, out float y, out float z); ALHelper.CheckError("Failed to get source position."); // get the emitter offset from origin Vector3 posOffset = emitter.Position - listener.Position; // set up orientation matrix var orientation = Matrix4x4.CreateWorld(Vector3.Zero, listener.Forward, listener.Up); // set up our final position and velocity according to orientation of listener var finalPos = Vector3.Transform(new Vector3(x, y, z) + posOffset, orientation); var finalVel = Vector3.Transform(emitter.Velocity, orientation); // set the position based on relative positon AL.Source(SourceId.Value, ALSource3f.Position, finalPos.X, finalPos.Y, finalPos.Z); ALHelper.CheckError("Failed to set source position."); AL.Source(SourceId.Value, ALSource3f.Velocity, finalVel.X, finalVel.Y, finalVel.Z); ALHelper.CheckError("Failed to set source velocity."); AL.Source(SourceId.Value, ALSourcef.ReferenceDistance, SoundEffect.DistanceScale); ALHelper.CheckError("Failed to set source distance scale."); AL.DopplerFactor(SoundEffect.DopplerScale); ALHelper.CheckError("Failed to set Doppler scale."); }
private SoundState PlatformGetState() { if (!SourceId.HasValue) { return(SoundState.Stopped); } var alState = AL.GetSourceState(SourceId.Value); ALHelper.CheckError("Failed to get source state."); switch (alState) { case ALSourceState.Initial: case ALSourceState.Stopped: SoundState = SoundState.Stopped; break; case ALSourceState.Paused: SoundState = SoundState.Paused; break; case ALSourceState.Playing: SoundState = SoundState.Playing; break; } return(SoundState); }
private void PlatformSetPitch(float value) { if (SourceId.HasValue) { AL.Source(SourceId.Value, ALSourcef.Pitch, value); ALHelper.CheckError("Failed to set source pitch."); } }
private void PlatformSetPan(float value) { if (SourceId.HasValue) { AL.Source(SourceId.Value, ALSource3f.Position, value, 0f, 0.1f); ALHelper.CheckError("Failed to set source pan."); } }
private void PlatformSetVolume(float value) { _alVolume = value; if (SourceId.HasValue) { AL.Source(SourceId.Value, ALSourcef.Gain, _alVolume); ALHelper.CheckError("Failed to set source volume."); } }
private void PlatformSetIsLooped(bool value) { _looped = value; if (SourceId.HasValue) { AL.Source(SourceId.Value, ALSourceb.Looping, _looped); ALHelper.CheckError("Failed to set source loop state."); } }
private void ApplyReverb() { if (_reverb <= 0f || SoundEffect.ReverbSlot == 0) { return; } Controller.Efx.BindSourceToAuxiliarySlot(SourceId !.Value, (int)SoundEffect.ReverbSlot, 0, 0); ALHelper.CheckError("Failed to set reverb."); }
private void PlatformCreate() { PlatformInitialize(); SourceId = Controller.ReserveSource(); // Ensure that the source is not looped (due to source recycling) AL.Source(SourceId.Value, ALSourceb.Looping, false); ALHelper.CheckError("Failed to set source loop state."); }
private void PlatformPause() { if (!SourceId.HasValue || SoundState != SoundState.Playing) { return; } AL.SourcePause(SourceId.Value); ALHelper.CheckError("Failed to pause source."); SoundState = SoundState.Paused; }
public void RecycleSource(uint sourceId) { AL.Source(sourceId, ALSourcei.Buffer, 0); ALHelper.CheckError("Failed to free source from buffers."); lock (_availableSources) { if (_sourcesInUse.Remove(sourceId)) { _availableSources.Enqueue(sourceId); } } }
private void PlatformResume() { if (!SourceId.HasValue) { PlatformPlay(); return; } if (SoundState == SoundState.Paused) { AL.SourcePlay(SourceId.Value); ALHelper.CheckError("Failed to play source."); SoundState = SoundState.Playing; } }
private void PlatformStop() { AL.SourceStop(SourceId.Value); ALHelper.CheckError("Failed to stop the source."); // Remove all queued buffers AL.Source(SourceId.Value, ALSourcei.Buffer, 0); ALHelper.CheckError("Failed to unbind the buffer."); lock (_queuedBuffers) { while (_queuedBuffers.Count > 0) { var buffer = _queuedBuffers.Dequeue(); ALBufferPool.Return(buffer); } } }
public void ClearBuffer() { if (IsDisposed || BufferId == 0) { return; } bool isBuffer = AL.IsBuffer(BufferId); ALHelper.CheckError("Failed to fetch buffer state."); if (isBuffer) { AL.DeleteBuffer(BufferId); BufferId = 0; ALHelper.CheckError("Failed to delete buffer."); } }
private void PlatformPlay() { if (!SourceId.HasValue) { SourceId = Controller.ReserveSource(); } AL.Source(SourceId.Value, ALSourcei.Buffer, _effect !.SoundBuffer !.BufferId); ALHelper.CheckError("Failed to bind buffer to source."); // update the position, gain, looping, pitch, and distance model AL.Source(SourceId.Value, ALSourcei.SourceRelative, 1); ALHelper.CheckError("Failed set source relative."); AL.DistanceModel(ALDistanceModel.InverseDistanceClamped); ALHelper.CheckError("Failed set source distance."); AL.Source(SourceId.Value, ALSource3f.Position, _pan, 0f, 0f); ALHelper.CheckError("Failed to set source pan."); AL.Source(SourceId.Value, ALSource3f.Velocity, 0f, 0f, 0f); ALHelper.CheckError("Failed to set source pan."); AL.Source(SourceId.Value, ALSourcef.Gain, _alVolume); ALHelper.CheckError("Failed to set source volume."); AL.Source(SourceId.Value, ALSourceb.Looping, IsLooped); ALHelper.CheckError("Failed to set source loop state."); AL.Source(SourceId.Value, ALSourcef.Pitch, _pitch); ALHelper.CheckError("Failed to set source pitch."); ApplyReverb(); ApplyFilter(); AL.SourcePlay(SourceId.Value); ALHelper.CheckError("Failed to play source."); SoundState = SoundState.Playing; }
private void ApplyFilter() { if (!_needsFilterUpdate || Controller.Filter == 0) { return; } float freq = _frequency / 20000f; float lf = 1f - freq; var efx = Controller.Efx; efx.Filter(Controller.Filter, EfxFilteri.FilterType, (int)_filterType); ALHelper.CheckError("Failed to set filter."); switch (_filterType) { case EfxFilterType.Lowpass: efx.Filter(Controller.Filter, EfxFilterf.LowpassGainHF, freq); ALHelper.CheckError("Failed to set LowpassGainHF."); break; case EfxFilterType.Highpass: efx.Filter(Controller.Filter, EfxFilterf.HighpassGainLF, freq); ALHelper.CheckError("Failed to set HighpassGainLF."); break; case EfxFilterType.Bandpass: efx.Filter(Controller.Filter, EfxFilterf.BandpassGainHF, freq); ALHelper.CheckError("Failed to set BandpassGainHF."); efx.Filter(Controller.Filter, EfxFilterf.BandpassGainLF, lf); ALHelper.CheckError("Failed to set BandpassGainLF."); break; } AL.Source(SourceId !.Value, ALSourcei.EfxDirectFilter, Controller.Filter); ALHelper.CheckError("Failed to set DirectFilter."); _needsFilterUpdate = false; }
public void BufferData <T>( ReadOnlySpan <T> data, ALFormat format, int sampleRate, int sampleAlignment = 0) where T : unmanaged { AssertNotDisposed(); var controller = ALController.Get(); if (!controller.SupportsFloat32 && (format == ALFormat.MonoFloat32 || format == ALFormat.StereoFloat32)) { throw new InvalidOperationException("Float data is not supported by this OpenAL driver."); } if (!controller.SupportsAdpcm && (format == ALFormat.MonoMSAdpcm || format == ALFormat.StereoMSAdpcm)) { throw new InvalidOperationException("MS-ADPCM is not supported by this OpenAL driver."); } if (!controller.SupportsIma4 && (format == ALFormat.MonoIma4 || format == ALFormat.StereoIma4)) { throw new InvalidOperationException("IMA/ADPCM is not supported by this OpenAL driver."); } if (BufferId != 0) { ClearBuffer(); } BufferId = AL.GenBuffer(); ALHelper.CheckError("Failed to generate OpenAL data buffer."); if (sampleAlignment > 0) { AL.Bufferi(BufferId, ALBufferi.UnpackBlockAlignmentSoft, sampleAlignment); ALHelper.CheckError("Failed to set buffer alignment."); } AL.BufferData(BufferId, format, MemoryMarshal.AsBytes(data), sampleRate); ALHelper.CheckError("Failed to fill buffer."); }
/// <summary> /// Sets up the hardware resources used by the controller. /// </summary> private ALController() { if (AL.NativeLibrary == IntPtr.Zero) { throw new DllNotFoundException( "Couldn't initialize OpenAL because the native binaries couldn't be found."); } if (!Open()) { throw new AudioHardwareException( "OpenAL device could not be initialized, see console output for details."); } Efx = new EffectsExtension(Device); if (ALC.IsExtensionPresent(Device, "ALC_EXT_CAPTURE")) { Microphone.PopulateCaptureDevices(); } // We have hardware here and it is ready _allSources = new uint[MaxNumberOfSources]; AL.GenSources(_allSources); ALHelper.CheckError("Failed to generate sources."); // TODO: allow more effects if (Efx.IsAvailable) { Filter = Efx.GenFilter(); } _availableSources = new Queue <uint>(_allSources); _sourcesInUse = new HashSet <uint>(); }
/// <summary> /// Disposes the <see cref="ALController"/>. /// </summary> /// <param name="disposing">If true, the managed resources are to be disposed.</param> private void Dispose(bool disposing) { if (!_isDisposed) { if (disposing) { Streamer.Dispose(); if (Filter != 0 && Efx.IsAvailable) { Efx.DeleteFilter(Filter); } SoundEffectInstancePool.DisposeInstances(); AL.DeleteSources(_allSources); ALHelper.CheckError("Failed to delete source."); Microphone.StopMicrophones(); DestroyContexts(); } _isDisposed = true; } }
public double GetSourceCurrentPosition(uint sourceId) { AL.GetSource(sourceId, ALGetSourcei.SampleOffset, out int pos); ALHelper.CheckError("Failed to set source offset."); return(pos); }
private void PlatformResume() { AL.SourcePlay(SourceId.Value); ALHelper.CheckError("Failed to play the source."); }
private void PlatformPause() { AL.SourcePause(SourceId.Value); ALHelper.CheckError("Failed to pause the source."); }