/// <summary> /// Preload the buffers and prepare them for recording. /// </summary> /// <param name="curDevice">Device to use for recording</param> /// <param name="hwnd">Handle to a message window that will receive /// audio messages.</param> /// <param name="maxRecordLength_ms">Maximum length of recording</param> /// <param name="bufferSize">Size of buffers to use for recording. New /// buffers are added when needed until the maximum length is reached /// or the recording is stopped.</param> /// <returns>MMSYSERR.NOERROR if successful</returns> public Wave.MMSYSERR Preload(uint curDevice, IntPtr hwnd, int maxRecordLength_ms, int bufferSize) { // Do not allow recording to be interrupted if (m_recording) return Wave.MMSYSERR.ERROR; // If this file is already initialized then start over if (m_inited) { Stop(); FreeWaveBuffers(); } // Create an instance of WAVEINCAPS to check if our desired // format is supported WAVEINCAPS caps = new WAVEINCAPS(); waveInGetDevCaps(0, caps, caps.Size); if ((caps.dwFormats & Wave.WAVE_FORMAT_1S16) == 0) return Wave.MMSYSERR.NOTSUPPORTED; // Initialize a WAVEFORMATEX structure specifying the desired // format m_wfmt = new Wave.WAVEFORMATEX(); m_wfmt.wFormatTag = Wave.WAVEHDR.WAVE_FORMAT_PCM; m_wfmt.wBitsPerSample = 16; m_wfmt.nChannels = 2; m_wfmt.nSamplesPerSec = 44110;//11025; m_wfmt.nAvgBytesPerSec = (uint)(m_wfmt.nSamplesPerSec * m_wfmt.nChannels * (m_wfmt.wBitsPerSample / 8)); m_wfmt.nBlockAlign = (ushort)(m_wfmt.wBitsPerSample * m_wfmt.nChannels / 8); // Attempt to open the specified device with the desired wave format Wave.MMSYSERR result = waveInOpen(ref m_hwi, curDevice, m_wfmt, hwnd, 0, Wave.CALLBACK_WINDOW); if (result != Wave.MMSYSERR.NOERROR) return result; if (bufferSize == 0) return Wave.MMSYSERR.ERROR; m_bufferSize = (uint)bufferSize; // Force the buffers to align to nBlockAlign if (m_bufferSize % m_wfmt.nBlockAlign != 0) m_bufferSize += m_wfmt.nBlockAlign - (m_bufferSize % m_wfmt.nBlockAlign); // Determine the number of buffers needed to record the maximum length m_maxDataLength = (uint)(m_wfmt.nAvgBytesPerSec * maxRecordLength_ms / 1000); m_numBlocks = (int)(m_maxDataLength / m_bufferSize); if (m_numBlocks * m_bufferSize < m_maxDataLength) m_numBlocks++; // Allocate the list of buffers m_whdr = new Wave.WAVEHDR[m_numBlocks + 1]; // Allocate and initialize two buffers to start with m_whdr[0] = new Wave.WAVEHDR(); m_whdr[1] = new Wave.WAVEHDR(); result = InitBuffer(0); if (result != Wave.MMSYSERR.NOERROR) return result; result = InitBuffer(1); if (result != Wave.MMSYSERR.NOERROR) return result; m_curBlock = 0; m_inited = true; return Wave.MMSYSERR.NOERROR; }
/// <summary> /// Initialize a buffer for recording by allocating a data buffer, /// preparing the header, and adding it to the read queue. /// </summary> /// <param name="bufIndex">Index of buffer to allocate</param> /// <returns>MMSYSERR.NOERROR if successful</returns> public Wave.MMSYSERR InitBuffer(int bufIndex) { // Determine the size of the buffer to create uint writeLength = (uint)m_bufferSize; if (bufIndex < m_numBlocks) { uint remainingDataLength = (uint)(m_maxDataLength - bufIndex * m_bufferSize); if (m_bufferSize > remainingDataLength) writeLength = remainingDataLength; } // If the header is not already instanced then instance it if (m_whdr[bufIndex] == null) m_whdr[bufIndex] = new Wave.WAVEHDR(); // Allocate memory if not already allocated Wave.MMSYSERR result = m_whdr[bufIndex].Init(writeLength, false); if (result != Wave.MMSYSERR.NOERROR) return result; // Prepare the header result = waveInPrepareHeader(m_hwi, m_whdr[bufIndex], (uint)Marshal.SizeOf(m_whdr[bufIndex])); if (result != Wave.MMSYSERR.NOERROR) return result; // Put the buffer in the queue return waveInAddBuffer(m_hwi, m_whdr[bufIndex], (uint)Marshal.SizeOf(m_whdr[bufIndex])); }