private void DeleteHeader(GCHandle gchHeader) { // Unprepare header int size = Marshal.SizeOf(typeof(MMInterop.WAVEHDR)); IntPtr pHeader = gchHeader.AddrOfPinnedObject(); MMInterop.waveInUnprepareHeader(this.hWaveIn, pHeader, (uint)size); // Free buffer (allocated in the CreateHeader method) MMInterop.WAVEHDR header = (MMInterop.WAVEHDR)gchHeader.Target; if (header.lpData != IntPtr.Zero) { Marshal.FreeHGlobal(header.lpData); header.lpData = IntPtr.Zero; } // Unpin header if (gchHeader.IsAllocated) { gchHeader.Free(); } }
private GCHandle CreateHeader(int bufferSize) { // Create header int size = Marshal.SizeOf(typeof(MMInterop.WAVEHDR)); MMInterop.WAVEHDR header = new MMInterop.WAVEHDR(); header.dwBufferLength = (uint)bufferSize; header.lpData = Marshal.AllocHGlobal(bufferSize); // Prepare header // Wave headers need to be fixed in memory GCHandle gchHeader = GCHandle.Alloc(header, GCHandleType.Pinned); IntPtr pHeader = gchHeader.AddrOfPinnedObject(); int mmr = MMInterop.waveInPrepareHeader(this.hWaveIn, pHeader, (uint)size); if (mmr != 0) { throw new SoundException("waveInPrepareHeader", mmr); } return(gchHeader); }
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); }
private GCHandle CreateHeader(int bufferSize) { // Create header int size = Marshal.SizeOf(typeof(MMInterop.WAVEHDR)); MMInterop.WAVEHDR header = new MMInterop.WAVEHDR(); header.dwBufferLength = (uint)bufferSize; header.lpData = Marshal.AllocHGlobal(bufferSize); // Prepare header // Wave headers need to be fixed in memory GCHandle gchHeader = GCHandle.Alloc(header, GCHandleType.Pinned); IntPtr pHeader = gchHeader.AddrOfPinnedObject(); int mmr = MMInterop.waveInPrepareHeader(this.hWaveIn, pHeader, (uint)size); if (mmr != 0) { throw new SoundException("waveInPrepareHeader", mmr); } return gchHeader; }