/// <summary> /// Начинает запись звука на канале. /// </summary> /// <param name="aInChannelNumber">Номер канала.</param> /// <param name="aOutChannelsIds">Идентификаторы выходных каналов.</param> /// <param name="aRecordOwner">Инициатор записи.</param> public void StartRecord(int aInChannelNumber, int[] aOutChannelsIds, int aRecordOwner) { lock (stopRecordLock) { if (isBusy) { return; } isBusy = true; var bytePerSecond = samplePerSec*bytePerSample*channelsCount; var bufferLength = seconds*bytePerSecond; currentWaveInHdr = new WAVEHDR { LpData = Marshal.AllocHGlobal(bufferLength), DwBufferLength = (uint) (bufferLength), DwBytesRecorded = 0, DwUser = IntPtr.Zero, DwFlags = 0, DwLoops = 0 }; NativeMethods.waveInPrepareHeader(handle, ref currentWaveInHdr, (uint) Marshal.SizeOf(typeof (WAVEHDR))); currentInChannelId = aInChannelNumber; currentOutChannelsIds = aOutChannelsIds; currentRecordOwner = aRecordOwner; recordControlThread = new Thread(() => RecordControlMethod(aInChannelNumber, aRecordOwner)); recordControlThread.Start(); NativeMethods.waveInAddBuffer(handle, ref currentWaveInHdr, (uint) Marshal.SizeOf(typeof (WAVEHDR))); NativeMethods.waveInStart(handle); } }
/// <summary> /// Записываем звук в буфер устройства. /// </summary> /// <param name="aSoundData">Записываемые данные.</param> /// <param name="aChannelId">Номер канала воспроизведения. Если -1 => воспроизводим на всех каналах.</param> public void WriteDataToChannel(byte[] aSoundData, int aChannelId) { if (aSoundData == null) { throw new ArgumentNullException("aSoundData"); } if (aChannelId < -1 || aChannelId >= channelsCount) { throw new ArgumentException(string.Format("ChannelId={0} is out of range [0 - {1}]", aChannelId, channelsCount - 1)); } var dataLength = aSoundData.Length; var soundDataCopy = new byte[dataLength]; aSoundData.CopyTo(soundDataCopy, 0); if (aChannelId != -1) { ForbidChannelsExcept(soundDataCopy, aChannelId); } var pSoundData = Marshal.AllocHGlobal(dataLength); try { Marshal.Copy(soundDataCopy, 0, pSoundData, dataLength); var waveHdr = new WAVEHDR { LpData = pSoundData, DwBufferLength = (uint) dataLength, DwFlags = 0, DwLoops = 0 }; lock (writingLock) { var stepNumber = 0; var stepSpeed = 100; // миллисекунды var bytePerStep = 2*bytePerSample*samplePerSec*stepSpeed/1000; NativeMethods.waveOutPrepareHeader(this.handle, ref waveHdr, (uint) Marshal.SizeOf(typeof (WAVEHDR))); NativeMethods.waveOutWrite(this.handle, ref waveHdr, (uint) Marshal.SizeOf(typeof (WAVEHDR))); // ожидаем окончания воспроизведения и меняем текущий уровень на каналах while ((waveHdr.DwFlags & WAVEHDRFLAGS.WHDR_DONE) == 0) { var dataIndex = stepNumber*bytePerStep + aChannelId*2; if (dataIndex < dataLength) { var value = soundDataCopy[dataIndex] << 5; channelLevels[aChannelId] = value; //Logger.Info(value); stepNumber++; } Thread.Sleep(stepSpeed); } channelLevels[aChannelId] = 0; NativeMethods.waveOutUnprepareHeader(this.handle, ref waveHdr, (uint) Marshal.SizeOf(typeof (WAVEHDR))); NativeMethods.waveOutReset(this.handle); } } finally { // Освободим неуправляемую память Marshal.FreeHGlobal(pSoundData); } }
public static extern uint waveOutWrite(IntPtr hWaveOut, ref WAVEHDR pwh, uint cbwh);
public static extern uint waveOutUnprepareHeader(IntPtr hWaveOut, ref WAVEHDR pwh, uint cbwh);
public static extern uint waveOutPrepareHeader(IntPtr hWaveOut, ref WAVEHDR lpWaveOutHdr, uint uSize);
public static extern uint waveInPrepareHeader(IntPtr hWaveIn, ref WAVEHDR pwh, uint cbwh);
public static extern uint waveInAddBuffer(IntPtr hWaveIn, ref WAVEHDR pwh, uint cbwh);