/// <summary>Opens a device for audio recording.</summary> /// <param name="deviceName">The device name.</param> /// <param name="frequency">The frequency that the data should be captured at.</param> /// <param name="sampleFormat">The requested capture buffer format.</param> /// <param name="bufferSize">The size of OpenAL's capture internal ring-buffer. This value expects number of samples, not bytes.</param> public AudioCapture(string deviceName, int frequency, ALFormat sampleFormat, int bufferSize) { if (!AudioDeviceEnumerator.IsOpenALSupported) { throw new DllNotFoundException("openal32.dll"); } if (frequency <= 0) { throw new ArgumentOutOfRangeException("frequency"); } if (bufferSize <= 0) { throw new ArgumentOutOfRangeException("bufferSize"); } // Try to open specified device. If it fails, try to open default device. device_name = deviceName; Handle = Alc.CaptureOpenDevice(deviceName, frequency, sampleFormat, bufferSize); if (Handle == IntPtr.Zero) { Debug.WriteLine(ErrorMessage(deviceName, frequency, sampleFormat, bufferSize)); device_name = "IntPtr.Zero"; Handle = Alc.CaptureOpenDevice(null, frequency, sampleFormat, bufferSize); } if (Handle == IntPtr.Zero) { Debug.WriteLine(ErrorMessage("IntPtr.Zero", frequency, sampleFormat, bufferSize)); device_name = AudioDeviceEnumerator.DefaultRecordingDevice; Handle = Alc.CaptureOpenDevice(AudioDeviceEnumerator.DefaultRecordingDevice, frequency, sampleFormat, bufferSize); } if (Handle == IntPtr.Zero) { // Everything we tried failed. Capture may not be supported, bail out. Debug.WriteLine(ErrorMessage(AudioDeviceEnumerator.DefaultRecordingDevice, frequency, sampleFormat, bufferSize)); device_name = "None"; throw new AudioDeviceException("All attempts to open capture devices returned IntPtr.Zero. See debug log for verbose list."); } // handle is not null, check for some Alc Error CheckErrors(); SampleFormat = sampleFormat; SampleFrequency = frequency; }
private void Dispose(bool manual) { if (!this.IsDisposed) { if (this.Handle != IntPtr.Zero) { if (this._isrecording) { this.Stop(); } Alc.CaptureCloseDevice(this.Handle); } this.IsDisposed = true; } }
public void Dispose() { AlcError error = Alc.GetError(this.Device); switch (error) { case AlcError.InvalidDevice: throw new AudioDeviceException(string.Format(AudioDeviceErrorChecker.ErrorString, (object)this.Device, (object)error)); case AlcError.InvalidContext: throw new AudioContextException(string.Format(AudioDeviceErrorChecker.ErrorString, (object)this.Device, (object)error)); case AlcError.InvalidValue: throw new AudioValueException(string.Format(AudioDeviceErrorChecker.ErrorString, (object)this.Device, (object)error)); case AlcError.OutOfMemory: throw new OutOfMemoryException(string.Format(AudioDeviceErrorChecker.ErrorString, (object)this.Device, (object)error)); } }
public AudioCapture(string deviceName, int frequency, ALFormat sampleFormat, int bufferSize) { if (!AudioDeviceEnumerator.IsOpenALSupported) { throw new DllNotFoundException("soft_oal.dll"); } if (frequency <= 0) { throw new ArgumentOutOfRangeException("frequency"); } if (bufferSize <= 0) { throw new ArgumentOutOfRangeException("bufferSize"); } this.device_name = deviceName; this.Handle = Alc.CaptureOpenDevice(deviceName, frequency, sampleFormat, bufferSize); if (this.Handle == IntPtr.Zero) { this.device_name = "IntPtr.Zero"; this.Handle = Alc.CaptureOpenDevice((string)null, frequency, sampleFormat, bufferSize); } if (this.Handle == IntPtr.Zero) { this.device_name = AudioDeviceEnumerator.DefaultRecordingDevice; this.Handle = Alc.CaptureOpenDevice(AudioDeviceEnumerator.DefaultRecordingDevice, frequency, sampleFormat, bufferSize); } if (this.Handle == IntPtr.Zero) { this.device_name = "None"; throw new AudioDeviceException("All attempts to open capture devices returned IntPtr.Zero. See debug log for verbose list."); } else { this.CheckErrors(); this.SampleFormat = sampleFormat; this.SampleFrequency = frequency; } }
private void Dispose(bool manual) { if (this.disposed) { return; } if (this.IsCurrent) { this.IsCurrent = false; } if (this.context_handle != ContextHandle.Zero) { AudioContext.available_contexts.Remove(this.context_handle); Alc.DestroyContext(this.context_handle); } if (this.device_handle != IntPtr.Zero) { Alc.CloseDevice(this.device_handle); } int num = manual ? 1 : 0; this.disposed = true; }
public void Dispose() { AlcError err = Alc.GetError(Device); switch (err) { case AlcError.OutOfMemory: throw new OutOfMemoryException(String.Format(ErrorString, Device, err)); case AlcError.InvalidValue: throw new AudioValueException(String.Format(ErrorString, Device, err)); case AlcError.InvalidDevice: throw new AudioDeviceException(String.Format(ErrorString, Device, err)); case AlcError.InvalidContext: throw new AudioContextException(String.Format(ErrorString, Device, err)); case AlcError.NoError: default: // everything went fine, do nothing break; } }
/// \internal /// <summary>Creates the audio context using the specified device.</summary> /// <param name="device">The device descriptor obtained through AudioContext.AvailableDevices, or null for the default device.</param> /// <param name="freq">Frequency for mixing output buffer, in units of Hz. Pass 0 for driver default.</param> /// <param name="refresh">Refresh intervals, in units of Hz. Pass 0 for driver default.</param> /// <param name="sync">Flag, indicating a synchronous context.</param> /// <param name="enableEfx">Indicates whether the EFX extension should be initialized, if present.</param> /// <param name="efxAuxiliarySends">Requires EFX enabled. The number of desired Auxiliary Sends per source.</param> /// <exception cref="ArgumentOutOfRangeException">Occurs when a specified parameter is invalid.</exception> /// <exception cref="AudioDeviceException"> /// Occurs when the specified device is not available, or is in use by another program. /// </exception> /// <exception cref="AudioContextException"> /// Occurs when an audio context could not be created with the specified parameters. /// </exception> /// <exception cref="NotSupportedException"> /// Occurs when an AudioContext already exists.</exception> /// <remarks> /// <para>For maximum compatibility, you are strongly recommended to use the default constructor.</para> /// <para>Multiple AudioContexts are not supported at this point.</para> /// <para> /// The number of auxilliary EFX sends depends on the audio hardware and drivers. Most Realtek devices, as well /// as the Creative SB Live!, support 1 auxilliary send. Creative's Audigy and X-Fi series support 4 sends. /// Values higher than supported will be clamped by the driver. /// </para> /// </remarks> void CreateContext(string device, int freq, int refresh, bool sync, bool enableEfx, MaxAuxiliarySends efxAuxiliarySends) { if (!AudioDeviceEnumerator.IsOpenALSupported) { throw new DllNotFoundException("openal32.dll"); } if (AudioDeviceEnumerator.Version == AudioDeviceEnumerator.AlcVersion.Alc1_1 && AudioDeviceEnumerator.AvailablePlaybackDevices.Count == 0) // Alc 1.0 does not support device enumeration. { throw new NotSupportedException("No audio hardware is available."); } if (context_exists) { throw new NotSupportedException("Multiple AudioContexts are not supported."); } if (freq < 0) { throw new ArgumentOutOfRangeException("freq", freq, "Should be greater than zero."); } if (refresh < 0) { throw new ArgumentOutOfRangeException("refresh", refresh, "Should be greater than zero."); } if (!String.IsNullOrEmpty(device)) { device_name = device; device_handle = Alc.OpenDevice(device); // try to open device by name } if (device_handle == IntPtr.Zero) { device_name = "IntPtr.Zero (null string)"; device_handle = Alc.OpenDevice(null); // try to open unnamed default device } if (device_handle == IntPtr.Zero) { device_name = AudioContext.DefaultDevice; device_handle = Alc.OpenDevice(AudioContext.DefaultDevice); // try to open named default device } if (device_handle == IntPtr.Zero) { device_name = "None"; throw new AudioDeviceException(String.Format("Audio device '{0}' does not exist or is tied up by another application.", String.IsNullOrEmpty(device) ? "default" : device)); } CheckErrors(); // Build the attribute list List <int> attributes = new List <int>(); if (freq != 0) { attributes.Add((int)AlcContextAttributes.Frequency); attributes.Add(freq); } if (refresh != 0) { attributes.Add((int)AlcContextAttributes.Refresh); attributes.Add(refresh); } attributes.Add((int)AlcContextAttributes.Sync); attributes.Add(sync ? 1 : 0); if (enableEfx && Alc.IsExtensionPresent(device_handle, "ALC_EXT_EFX")) { int num_slots; switch (efxAuxiliarySends) { case MaxAuxiliarySends.One: case MaxAuxiliarySends.Two: case MaxAuxiliarySends.Three: case MaxAuxiliarySends.Four: num_slots = (int)efxAuxiliarySends; break; default: case MaxAuxiliarySends.UseDriverDefault: Alc.GetInteger(device_handle, AlcGetInteger.EfxMaxAuxiliarySends, 1, out num_slots); break; } attributes.Add((int)AlcContextAttributes.EfxMaxAuxiliarySends); attributes.Add(num_slots); } attributes.Add(0); context_handle = Alc.CreateContext(device_handle, attributes.ToArray()); if (context_handle == ContextHandle.Zero) { Alc.CloseDevice(device_handle); throw new AudioContextException("The audio context could not be created with the specified parameters."); } CheckErrors(); // HACK: OpenAL SI on Linux/ALSA crashes on MakeCurrent. This hack avoids calling MakeCurrent when // an old OpenAL version is detect - it may affect outdated OpenAL versions different than OpenAL SI, // but it looks like a good compromise for now. if (AudioDeviceEnumerator.AvailablePlaybackDevices.Count > 0) { MakeCurrent(); } CheckErrors(); device_name = Alc.GetString(device_handle, AlcGetString.DeviceSpecifier); lock (audio_context_lock) { available_contexts.Add(this.context_handle, this); context_exists = true; } }
public void Stop() { Alc.CaptureStop(this.Handle); this._isrecording = false; }
static AudioDeviceEnumerator() { IntPtr device = IntPtr.Zero; ContextHandle context = ContextHandle.Zero; try { device = Alc.OpenDevice((string)null); int num1 = (int)Alc.GetError(device); context = Alc.CreateContext(device, (int[])null); int num2 = (int)Alc.GetError(device); bool flag = Alc.MakeContextCurrent(context); AlcError error1 = Alc.GetError(device); if (!flag) { throw new AudioContextException("Failed to create dummy Context. Device (" + device.ToString() + ") Context (" + context.Handle.ToString() + ") MakeContextCurrent " + (flag ? "succeeded" : "failed") + ", Alc Error (" + ((object)error1).ToString() + ") " + Alc.GetString(IntPtr.Zero, (AlcGetString)error1)); } else { if (Alc.IsExtensionPresent(IntPtr.Zero, "ALC_ENUMERATION_EXT")) { AudioDeviceEnumerator.version = AudioDeviceEnumerator.AlcVersion.Alc1_1; if (Alc.IsExtensionPresent(IntPtr.Zero, "ALC_ENUMERATE_ALL_EXT")) { AudioDeviceEnumerator.available_playback_devices.AddRange((IEnumerable <string>)Alc.GetString(IntPtr.Zero, AlcGetStringList.AllDevicesSpecifier)); AudioDeviceEnumerator.default_playback_device = Alc.GetString(IntPtr.Zero, AlcGetString.DefaultAllDevicesSpecifier); } else { AudioDeviceEnumerator.available_playback_devices.AddRange((IEnumerable <string>)Alc.GetString(IntPtr.Zero, AlcGetStringList.DeviceSpecifier)); AudioDeviceEnumerator.default_playback_device = Alc.GetString(IntPtr.Zero, AlcGetString.DefaultDeviceSpecifier); } } else { AudioDeviceEnumerator.version = AudioDeviceEnumerator.AlcVersion.Alc1_0; } AlcError error2 = Alc.GetError(device); if (error2 != AlcError.NoError) { throw new AudioContextException("Alc Error occured when querying available playback devices. " + ((object)error2).ToString()); } if (AudioDeviceEnumerator.version == AudioDeviceEnumerator.AlcVersion.Alc1_1 && Alc.IsExtensionPresent(IntPtr.Zero, "ALC_EXT_CAPTURE")) { AudioDeviceEnumerator.available_recording_devices.AddRange((IEnumerable <string>)Alc.GetString(IntPtr.Zero, AlcGetStringList.CaptureDeviceSpecifier)); AudioDeviceEnumerator.default_recording_device = Alc.GetString(IntPtr.Zero, AlcGetString.CaptureDefaultDeviceSpecifier); } AlcError error3 = Alc.GetError(device); if (error3 != AlcError.NoError) { throw new AudioContextException("Alc Error occured when querying available recording devices. " + ((object)error3).ToString()); } } } catch (DllNotFoundException ex) { Trace.WriteLine(ex.ToString()); AudioDeviceEnumerator.openal_supported = false; } catch (AudioContextException ex) { Trace.WriteLine(ex.ToString()); AudioDeviceEnumerator.lastError = ex.ToString(); AudioDeviceEnumerator.openal_supported = false; } finally { Alc.MakeContextCurrent(ContextHandle.Zero); if (context != ContextHandle.Zero && context.Handle != IntPtr.Zero) { Alc.DestroyContext(context); } if (device != IntPtr.Zero) { Alc.CloseDevice(device); } } }
/// <summary>Fills the specified buffer with samples from the internal capture ring-buffer. This method does not block: it is an error to specify a sampleCount larger than AvailableSamples.</summary> /// <param name="buffer">A pointer to a previously initialized and pinned array.</param> /// <param name="sampleCount">The number of samples to be written to the buffer.</param> public void ReadSamples(IntPtr buffer, int sampleCount) { Alc.CaptureSamples(Handle, buffer, sampleCount); }
private void CreateContext(string device, int freq, int refresh, bool sync, bool enableEfx, AudioContext.MaxAuxiliarySends efxAuxiliarySends) { if (!AudioDeviceEnumerator.IsOpenALSupported) { throw new DllNotFoundException("soft_oal.dll"); } if (AudioDeviceEnumerator.Version == AudioDeviceEnumerator.AlcVersion.Alc1_1 && AudioDeviceEnumerator.AvailablePlaybackDevices.Count == 0) { throw new NotSupportedException("No audio hardware is available."); } if (this.context_exists) { throw new NotSupportedException("Multiple AudioContexts are not supported."); } if (freq < 0) { throw new ArgumentOutOfRangeException("freq", (object)freq, "Should be greater than zero."); } if (refresh < 0) { throw new ArgumentOutOfRangeException("refresh", (object)refresh, "Should be greater than zero."); } if (!string.IsNullOrEmpty(device)) { this.device_name = device; this.device_handle = Alc.OpenDevice(device); } if (this.device_handle == IntPtr.Zero) { this.device_name = "IntPtr.Zero (null string)"; this.device_handle = Alc.OpenDevice((string)null); } if (this.device_handle == IntPtr.Zero) { this.device_name = AudioContext.DefaultDevice; this.device_handle = Alc.OpenDevice(AudioContext.DefaultDevice); } if (this.device_handle == IntPtr.Zero) { this.device_name = "None"; throw new AudioDeviceException(string.Format("Audio device '{0}' does not exist or is tied up by another application.", string.IsNullOrEmpty(device) ? (object)"default" : (object)device)); } else { this.CheckErrors(); List <int> list = new List <int>(); if (freq != 0) { list.Add(4103); list.Add(freq); } if (refresh != 0) { list.Add(4104); list.Add(refresh); } list.Add(4105); list.Add(sync ? 1 : 0); if (enableEfx && Alc.IsExtensionPresent(this.device_handle, "ALC_EXT_EFX")) { int data; switch (efxAuxiliarySends) { case AudioContext.MaxAuxiliarySends.One: case AudioContext.MaxAuxiliarySends.Two: case AudioContext.MaxAuxiliarySends.Three: case AudioContext.MaxAuxiliarySends.Four: data = (int)efxAuxiliarySends; break; default: Alc.GetInteger(this.device_handle, AlcGetInteger.EfxMaxAuxiliarySends, 1, out data); break; } list.Add(131075); list.Add(data); } list.Add(0); this.context_handle = Alc.CreateContext(this.device_handle, list.ToArray()); if (this.context_handle == ContextHandle.Zero) { Alc.CloseDevice(this.device_handle); throw new AudioContextException("The audio context could not be created with the specified parameters."); } else { this.CheckErrors(); if (AudioDeviceEnumerator.AvailablePlaybackDevices.Count > 0) { this.MakeCurrent(); } this.CheckErrors(); this.device_name = Alc.GetString(this.device_handle, AlcGetString.DeviceSpecifier); lock (AudioContext.audio_context_lock) { AudioContext.available_contexts.Add(this.context_handle, this); this.context_exists = true; } } } }
/// <summary> /// Start recording samples. /// The number of available samples can be obtained through the <see cref="AvailableSamples"/> property. /// The data can be queried with any <see cref="ReadSamples(IntPtr, int)"/> method. /// </summary> public void Start() { Alc.CaptureStart(Handle); _isrecording = true; }
/// <summary>Stop recording samples. This will not clear previously recorded samples.</summary> public void Stop() { Alc.CaptureStop(Handle); _isrecording = false; }
// Loads all available audio devices into the available_*_devices lists. static AudioDeviceEnumerator() { IntPtr dummy_device = IntPtr.Zero; ContextHandle dummy_context = ContextHandle.Zero; try { Debug.WriteLine("Enumerating audio devices."); Debug.Indent(); // need a dummy context for correct results dummy_device = Alc.OpenDevice(null); dummy_context = Alc.CreateContext(dummy_device, (int[])null); bool dummy_success = Alc.MakeContextCurrent(dummy_context); AlcError dummy_error = Alc.GetError(dummy_device); if (!dummy_success || dummy_error != AlcError.NoError) { throw new AudioContextException("Failed to create dummy Context. Device (" + dummy_device.ToString() + ") Context (" + dummy_context.Handle.ToString() + ") MakeContextCurrent " + (dummy_success ? "succeeded" : "failed") + ", Alc Error (" + dummy_error.ToString() + ") " + Alc.GetString(IntPtr.Zero, (AlcGetString)dummy_error)); } // Get a list of all known playback devices, using best extension available if (Alc.IsExtensionPresent(IntPtr.Zero, "ALC_ENUMERATION_EXT")) { version = AlcVersion.Alc1_1; if (Alc.IsExtensionPresent(IntPtr.Zero, "ALC_ENUMERATE_ALL_EXT")) { available_playback_devices.AddRange(Alc.GetString(IntPtr.Zero, AlcGetStringList.AllDevicesSpecifier)); default_playback_device = Alc.GetString(IntPtr.Zero, AlcGetString.DefaultAllDevicesSpecifier); } else { available_playback_devices.AddRange(Alc.GetString(IntPtr.Zero, AlcGetStringList.DeviceSpecifier)); default_playback_device = Alc.GetString(IntPtr.Zero, AlcGetString.DefaultDeviceSpecifier); } } else { version = AlcVersion.Alc1_0; Debug.Print("Device enumeration extension not available. Failed to enumerate playback devices."); } AlcError playback_err = Alc.GetError(dummy_device); if (playback_err != AlcError.NoError) { throw new AudioContextException("Alc Error occured when querying available playback devices. " + playback_err.ToString()); } // Get a list of all known recording devices, at least ALC_ENUMERATION_EXT is needed too if (version == AlcVersion.Alc1_1 && Alc.IsExtensionPresent(IntPtr.Zero, "ALC_EXT_CAPTURE")) { available_recording_devices.AddRange(Alc.GetString(IntPtr.Zero, AlcGetStringList.CaptureDeviceSpecifier)); default_recording_device = Alc.GetString(IntPtr.Zero, AlcGetString.CaptureDefaultDeviceSpecifier); } else { Debug.Print("Capture extension not available. Failed to enumerate recording devices."); } AlcError record_err = Alc.GetError(dummy_device); if (record_err != AlcError.NoError) { throw new AudioContextException("Alc Error occured when querying available recording devices. " + record_err.ToString()); } #if DEBUG Debug.WriteLine("Found playback devices:"); foreach (string s in available_playback_devices) { Debug.WriteLine(s); } Debug.WriteLine("Default playback device: " + default_playback_device); Debug.WriteLine("Found recording devices:"); foreach (string s in available_recording_devices) { Debug.WriteLine(s); } Debug.WriteLine("Default recording device: " + default_recording_device); #endif } catch (DllNotFoundException e) { Trace.WriteLine(e.ToString()); openal_supported = false; } catch (AudioContextException ace) { Trace.WriteLine(ace.ToString()); openal_supported = false; } finally { Debug.Unindent(); if (openal_supported) { try { // clean up the dummy context Alc.MakeContextCurrent(ContextHandle.Zero); if (dummy_context != ContextHandle.Zero && dummy_context.Handle != IntPtr.Zero) { Alc.DestroyContext(dummy_context); } if (dummy_device != IntPtr.Zero) { Alc.CloseDevice(dummy_device); } } catch { openal_supported = false; } } } }
public void Start() { Alc.CaptureStart(this.Handle); this._isrecording = true; }
/// <summary>Stop recording samples. This will not clear previously recorded samples.</summary> public void Stop() { Alc.CaptureStop(Handle); IsRunning = false; }
/// <summary> /// Start recording samples. /// The number of available samples can be obtained through the <see cref="AvailableSamples"/> property. /// The data can be queried with any <see cref="ReadSamples(IntPtr, int)"/> method. /// </summary> public void Start() { Alc.CaptureStart(Handle); IsRunning = true; }
private static void MakeCurrent(AudioContext context) { lock (AudioContext.audio_context_lock) { if (!Alc.MakeContextCurrent(context != null ? context.context_handle : ContextHandle.Zero)) { throw new AudioContextException(string.Format("ALC {0} error detected at {1}.", (object)((object)Alc.GetError(context != null ? (IntPtr)context.context_handle : IntPtr.Zero)).ToString(), context != null ? (object)context.ToString() : (object)"null")); } } }