private void Record() { // Create buffer queue Queue <GCHandle> gchHeaderQueue = new Queue <GCHandle>(); // Pin buffers and add them to queue int size = Marshal.SizeOf(typeof(MMInterop.WAVEHDR)); int mmr; foreach (GCHandle gchHeader in this.gchHeaders) { IntPtr pHeader = gchHeader.AddrOfPinnedObject(); mmr = MMInterop.waveInAddBuffer(this.hWaveIn, pHeader, (uint)size); if (mmr != 0) { throw new SoundException("waveInStart", mmr); } gchHeaderQueue.Enqueue(gchHeader); } // Start recording mmr = MMInterop.waveInStart(this.hWaveIn); if (mmr != 0) { throw new SoundException("waveInStart", mmr); } // Recording loop while (this.state != RecordingState.Opened) { // Wait a buffer become full this.recordingSemaphore.WaitOne(); // Get the buffer from buffer queue GCHandle gchHeader = gchHeaderQueue.Dequeue(); MMInterop.WAVEHDR header = (MMInterop.WAVEHDR)gchHeader.Target; // Copy data from the buffer to the output queue int bytesRecorded = (int)header.dwBytesRecorded; if (bytesRecorded > 0) { byte[] data = new byte[bytesRecorded]; Marshal.Copy(header.lpData, data, 0, bytesRecorded); lock (syncRoot) { if (output.Count == bufferCount) // Is output queue full? // Drop an item { byte[] outputData = output.Dequeue(); this.nBytesLost += outputData.Length; } // Add data to output queue output.Enqueue(data); } } if (this.state == RecordingState.Stopping) { if (gchHeaderQueue.Count == 0) // All the buffers are done { break; // No more recording } } else if (this.state == RecordingState.Recording) // Recording is not stopped { lock (syncRoot) { // Make sure recording is not stopped if (this.state == RecordingState.Recording) { IntPtr pHeader = gchHeader.AddrOfPinnedObject(); mmr = MMInterop.waveInAddBuffer(this.hWaveIn, pHeader, (uint)size); if (mmr != 0) { throw new SoundException("waveInAddBuffer", mmr); } gchHeaderQueue.Enqueue(gchHeader); } } } } // Stop recording mmr = MMInterop.waveInStop(this.hWaveIn); }