public static WaveOutDeviceInfo[] GetWaveOutDevices() { // enumerate WaveOut devices int device_count = WaveNative.waveOutGetNumDevs(); WaveOutDeviceInfo[] result = new WaveOutDeviceInfo[device_count + 1]; WaveNative.WAVEOUTCAPS caps = new WaveNative.WAVEOUTCAPS(); result[0] = new WaveOutDeviceInfo(); for (int i = 0; i < device_count; i++) { WaveNative.waveOutGetDevCaps((IntPtr)i, ref caps, (uint)Marshal.SizeOf(caps)); result[i + 1] = new WaveOutDeviceInfo(); result[i + 1].DisplayName = caps.szPname; } // expand names GCHandle result_handle = GCHandle.Alloc(result); WaveNative.DirectSoundEnumerate(new WaveNative.DSEnumCallback(EnumCallback), (IntPtr)result_handle); result_handle.Free(); if (string.IsNullOrEmpty(result[0].DisplayName)) { result[0].DisplayName = "(default)"; } return(result); }
/// <summary> /// Starts wave out device /// </summary> /// <returns></returns> public bool Start() { WaveNative.MMRESULT error; // create thread event m_thread_event = new AutoResetEvent(false); m_wave_out_format = new WaveNative.WaveFormat(SampleRate, 16, ChannelCount); // open wave device error = WaveNative.waveOutOpen(out m_wave_out_device_handle, m_device_id, m_wave_out_format, m_buffer_proc, 0, (uint)WaveNative.WaveInOutOpenFlags.CALLBACK_FUNCTION); if (error == WaveNative.MMRESULT.MMSYSERR_NOERROR) { // start thread m_thread_running = true; m_thread = new Thread(new ThreadStart(ThreadProc)); m_thread.Priority = ThreadPriority.AboveNormal; m_thread.Start(); } else { m_thread_event.Dispose(); m_thread_event = null; m_wave_out_format = null; m_thread = null; m_thread_running = false; } return(error == WaveNative.MMRESULT.MMSYSERR_NOERROR); }
/// <summary> /// Dispose of non managed resources /// </summary> public void Dispose() { if (Parent != null) { // release header WaveNative.Try(WaveNative.waveOutUnprepareHeader(Parent.Handle, m_header_handle.AddrOfPinnedObject(), Marshal.SizeOf(Header))); Parent = null; } if (m_header_handle.IsAllocated) { m_header_handle.Free(); } if (m_data_handle.IsAllocated) { m_data_handle.Free(); } if (m_this.IsAllocated) { m_this.Free(); } Data = null; }
/// <summary> /// Enqueues buffer for playback /// </summary> public void Enqueue() { Free = false; // write header WaveNative.Try(WaveNative.waveOutWrite(Parent.Handle, m_header_handle.AddrOfPinnedObject(), Marshal.SizeOf(Header))); }
/// <summary> /// Waveout thread procedure /// </summary> private void ThreadProc() { WaveOutBuffer buffer; // create buffers m_wave_out_buffers = new WaveOutBuffer[BufferCount]; for (int i = 0; i < BufferCount; i++) { m_wave_out_buffers[i] = new WaveOutBuffer(this, i); m_wave_out_buffers[i].ClearBuffer(); } // queue buffers for (int i = 0; i < BufferCount; i++) { m_wave_out_buffers[i].Enqueue(); } // thread loop while (m_thread_running) { // wait for wave event m_thread_event.WaitOne(); // find finished buffers and dequeue, fill and enqueue them for (int i = 0; i < BufferCount && m_thread_running; i++) { buffer = m_wave_out_buffers[i]; if (buffer.Free) { buffer.Dequeue(); OnSampleRequest?.Invoke(buffer.Data); buffer.Enqueue(); } } } // stop wave out WaveNative.waveOutReset(m_wave_out_device_handle); // release buffers for (int i = 0; i < BufferCount; i++) { m_wave_out_buffers[i].Dispose(); } // close wave out WaveNative.waveOutClose(m_wave_out_device_handle); m_wave_out_buffers = null; m_wave_out_device_handle = IntPtr.Zero; m_thread = null; m_thread_event.Dispose(); m_thread_event = null; }
public void Enqueue() { Free = false; // write header //Debug.WriteLine("E: " + BufferIndex.ToString()); WaveNative.Try(WaveNative.waveOutWrite(Parent.Handle, m_header_handle.AddrOfPinnedObject(), Marshal.SizeOf(Header))); }
/// <summary> /// Waveout buffer default constructor /// </summary> /// <param name="in_parent">Parent Waveout class</param> /// <param name="in_buffer_index">NUmber of the wave buffer</param> public WaveOutBuffer(WaveOut in_parent, int in_buffer_index) { Parent = in_parent; BufferIndex = in_buffer_index; Free = true; Header = new WaveNative.WaveHdr(); Data = new short[in_parent.BufferLength * in_parent.ChannelCount]; m_this = GCHandle.Alloc(this); m_header_handle = GCHandle.Alloc(Header, GCHandleType.Pinned); m_data_handle = GCHandle.Alloc(Data, GCHandleType.Pinned); Header.lpData = m_data_handle.AddrOfPinnedObject(); Header.dwBufferLength = sizeof(short) * Data.Length; Header.dwUser = (IntPtr)m_this; // prepare header WaveNative.Try(WaveNative.waveOutPrepareHeader(Parent.Handle, m_header_handle.AddrOfPinnedObject(), Marshal.SizeOf(Header))); }