/// <summary> /// Processes data and frees buffers that have been used by the application. /// </summary> private void ProcessDone() { IntPtr header; // Pull the header data back out of unmanaged memory lock (this.bufferingLock) { header = this.bufferReleaseQueue.Dequeue(); Monitor.Pulse(this.bufferingLock); } NativeMethods.WAVEHDR pwh = (NativeMethods.WAVEHDR)Marshal.PtrToStructure(header, typeof(NativeMethods.WAVEHDR)); // Find and copy the buffer data IntPtr data = pwh.lpData; // Copy the data and fire the DataReady event if necessary if (pwh.dwBytesRecorded > 0 && this.DataReady != null) { byte[] newData = new byte[pwh.dwBytesRecorded]; Marshal.Copy(data, newData, 0, (int)pwh.dwBytesRecorded); this.DataReady(this, new DataReadyEventArgs(newData)); } // Unprepare the header NativeMethods.Throw( NativeMethods.waveInUnprepareHeader(this.handle, header, (uint)Marshal.SizeOf(typeof(NativeMethods.WAVEHDR))), NativeMethods.ErrorSource.WaveIn); // Free the unmanaged memory Marshal.FreeHGlobal(data); Marshal.FreeHGlobal(header); }
/// <summary> /// Writes a block of data (in the current forma, set during Open) to the device. /// </summary> /// <param name="bufferData">The data to send to the device.</param> public void Write(byte[] bufferData) { lock (this.startStopLock) { IntPtr mem = Marshal.AllocHGlobal(bufferData.Length); Marshal.Copy(bufferData, 0, mem, bufferData.Length); NativeMethods.WAVEHDR pwh = new NativeMethods.WAVEHDR(); pwh.dwBufferLength = (uint)bufferData.Length; pwh.dwFlags = 0; pwh.lpData = mem; pwh.dwUser = new IntPtr(12345); IntPtr header = Marshal.AllocHGlobal(Marshal.SizeOf(pwh)); Marshal.StructureToPtr(pwh, header, false); NativeMethods.Throw( NativeMethods.waveOutPrepareHeader(this.handle, header, (uint)Marshal.SizeOf(typeof(NativeMethods.WAVEHDR))), NativeMethods.ErrorSource.WaveOut); NativeMethods.Throw( NativeMethods.waveOutWrite(this.handle, header, (uint)Marshal.SizeOf(typeof(NativeMethods.WAVEHDR))), NativeMethods.ErrorSource.WaveOut); lock (this.bufferingLock) { this.bufferQueueCount++; Monitor.Pulse(this.bufferingLock); } } }
/// <summary> /// Adds a buffer to the queue. /// </summary> private void AddBuffer() { // Allocate unmanaged memory for the buffer int bufferLength = this.bufferSize * this.recordingFormat.BlockAlign; IntPtr mem = Marshal.AllocHGlobal(bufferLength); // Initialize the buffer header, including a reference to the buffer memory NativeMethods.WAVEHDR pwh = new NativeMethods.WAVEHDR(); pwh.dwBufferLength = (uint)bufferLength; pwh.dwFlags = 0; pwh.lpData = mem; pwh.dwUser = new IntPtr(12345); // Copy the header into unmanaged memory IntPtr header = Marshal.AllocHGlobal(Marshal.SizeOf(pwh)); Marshal.StructureToPtr(pwh, header, false); // Prepare the header NativeMethods.Throw( NativeMethods.waveInPrepareHeader(this.handle, header, (uint)Marshal.SizeOf(typeof(NativeMethods.WAVEHDR))), NativeMethods.ErrorSource.WaveOut); // Add the buffer to the device NativeMethods.Throw( NativeMethods.waveInAddBuffer(this.handle, header, (uint)Marshal.SizeOf(typeof(NativeMethods.WAVEHDR))), NativeMethods.ErrorSource.WaveOut); lock (this.bufferingLock) { this.bufferQueueCount++; Monitor.Pulse(this.bufferingLock); } }
/// <summary> /// Frees buffers that have been used by the application. /// </summary> private void ProcessDone() { IntPtr header; // Pull the header data back out of unmanaged memory lock (this.bufferingLock) { header = this.bufferReleaseQueue.Dequeue(); Monitor.Pulse(this.bufferingLock); } NativeMethods.WAVEHDR pwh = (NativeMethods.WAVEHDR)Marshal.PtrToStructure(header, typeof(NativeMethods.WAVEHDR)); IntPtr data = pwh.lpData; NativeMethods.Throw( NativeMethods.waveOutUnprepareHeader(this.handle, header, (uint)Marshal.SizeOf(typeof(NativeMethods.WAVEHDR))), NativeMethods.ErrorSource.WaveOut); Marshal.FreeHGlobal(data); Marshal.FreeHGlobal(header); }
public static void Play(double[] signal, int samplingRate) { // Dies ist noch sehr unsauber! // TODO: auf Fehler reagieren; Speicherlecks vermeiden // TODO: Iterator statt komplettem Array benutzen short[] buffer = new short[signal.Length]; for (int i = 0; i < signal.Length; i++) { buffer[i] = (short)(short.MaxValue * signal[i]); } GCHandle hBuffer = GCHandle.Alloc(buffer, GCHandleType.Pinned); IntPtr hWaveOut = IntPtr.Zero; NativeMethods.WAVEFORMATEX format = new NativeMethods.WAVEFORMATEX(); format.wFormatTag = 1; format.nChannels = 1; format.nSamplesPerSec = (uint)samplingRate; format.nAvgBytesPerSec = (uint)(samplingRate * sizeof(short)); format.nBlockAlign = sizeof(short); format.wBitsPerSample = 16; format.cbSize = 0; NativeMethods.waveOutOpen(ref hWaveOut, new IntPtr(-1), ref format, IntPtr.Zero, IntPtr.Zero, 0); NativeMethods.WAVEHDR header = new NativeMethods.WAVEHDR(); header.lpData = Marshal.UnsafeAddrOfPinnedArrayElement(buffer, 0); header.dwBufferLength = (uint)(buffer.Length * sizeof(short)); NativeMethods.waveOutPrepareHeader(hWaveOut, ref header, (uint)Marshal.SizeOf(header)); NativeMethods.waveOutWrite(hWaveOut, ref header, (uint)Marshal.SizeOf(header)); while ((header.dwFlags & 1) == 0) { System.Threading.Thread.Sleep(100); } NativeMethods.waveOutUnprepareHeader(hWaveOut, ref header, (uint)Marshal.SizeOf(header)); NativeMethods.waveOutClose(hWaveOut); hBuffer.Free(); }