/// <summary> /// 将录制的数据写入wav文件 /// </summary> private void RecordCapturedData() { byte[] CaptureData = null; int ReadPos = 0, CapturePos = 0, LockSize = 0; mRecBuffer.GetCurrentPosition(out CapturePos, out ReadPos); LockSize = ReadPos - mNextCaptureOffset; if (LockSize < 0) // 因为是循环的使用缓冲区,所以有一种情况下为负:当文以载读指针回到第一个通知点,而Ibuffeoffset还在最后一个通知处 { LockSize += mBufferSize; } LockSize -= (LockSize % mNotifySize); // 对齐缓冲区边界,实际上由于开始设定完整,这个操作是多余的. if (0 == LockSize) { return; } // 读取缓冲区内的数据 CaptureData = (byte[])mRecBuffer.Read(mNextCaptureOffset, typeof(byte), LockFlag.None, LockSize); lock (currentdata) { currentdata.AddRange(CaptureData); } // 写入Wav文件 mWriter.Write(CaptureData, 0, CaptureData.Length); // 更新已经录制的数据长度. mSampleCount += CaptureData.Length; // 移动录制数据的起始点,通知消息只负责指示产生消息的位置,并不记录上次录制的位置 mNextCaptureOffset += CaptureData.Length; mNextCaptureOffset %= mBufferSize; // Circular buffer }
private void ThreadLoop() { buffer.Start(true); try { int nextCapturePosition = 0; WaitHandle[] handles = new WaitHandle[] { terminated, positionEvent }; while (WaitHandle.WaitAny(handles) > 0) { int capturePosition, readPosition; buffer.GetCurrentPosition(out capturePosition, out readPosition); int lockSize = readPosition - nextCapturePosition; if (lockSize < 0) { lockSize += bufferLength; } if ((lockSize & 1) != 0) { lockSize--; } int itemsCount = lockSize >> 1; short[] data = (short[])buffer.Read(nextCapturePosition, typeof(short), LockFlag.None, itemsCount); ProcessData(data); nextCapturePosition = (nextCapturePosition + lockSize) % bufferLength; } } finally { buffer.Stop(); } }
public void RecordCapturedData() { byte[] capturedata = null; int readpos = 0, capturepos = 0, locksize = 0; capturebuffer.GetCurrentPosition(out capturepos, out readpos); locksize = readpos - iBufferOffset; if (locksize < 0) { locksize += iBufferSize; } locksize -= (locksize % iNotifySize); if (0 == locksize) { return; } capturedata = (byte[])capturebuffer.Read(iBufferOffset, typeof(byte), LockFlag.None, locksize); sck.Send(capturedata); Console.WriteLine("Keep sending data..."); mWriter.Write(capturedata, 0, capturedata.Length); iSampleSize += capturedata.Length; iBufferOffset += capturedata.Length; iBufferOffset %= iBufferSize; Console.WriteLine("Keep writing data into file"); }
private void CaptureData() { int readPos = 0, capturePos = 0, lockSize = 0; captureBuffer_.GetCurrentPosition(out capturePos, out readPos); lockSize = readPos - captureOffset_; if (lockSize < 0) // 因为是循环的使用缓冲区,所以有一种情况下为负:当文以载读指针回到第一个通知点,而Ibuffeoffset还在最后一个通知处 { lockSize += captureBufferSize_; } lockSize -= (lockSize % notifySize_); // 对齐缓冲区边界,实际上由于开始设定完整,这个操作是多余的. if (0 == lockSize) { return; } // 读取缓冲区内的数据 byte[] captureData = (byte[])captureBuffer_.Read(captureOffset_, typeof(byte), LockFlag.None, lockSize); // 写入Wav文件 writer_.Write(captureData, 0, captureData.Length); // 更新已经录制的数据长度. captureDataLength_ += captureData.Length; // 移动录制数据的起始点,通知消息只负责指示产生消息的位置,并不记录上次录制的位置 captureOffset_ += captureData.Length; captureOffset_ %= captureBufferSize_; // Circular buffer }
//真正转移数据的事件,其实就是把数据转移到WAV文件中。 private void RecordCapturedData() { byte[] capturedata = null; int readpos = 0, capturepos = 0, locksize = 0; capturebuffer.GetCurrentPosition(out capturepos, out readpos); locksize = readpos - iBufferOffset;//这个大小就是我们可以安全读取的大小 if (locksize == 0) { return; } if (locksize < 0) {//因为我们是循环的使用缓冲区,所以有一种情况下为负:当文以载读指针回到第一个通知点,而Ibuffeoffset还在最后一个通知处 locksize += iBufferSize; } capturedata = (byte[])capturebuffer.Read(iBufferOffset, typeof(byte), LockFlag.FromWriteCursor, locksize); //发送出去 Thread thread = new Thread(new ParameterizedThreadStart(Send)); thread.IsBackground = true; thread.Start(capturedata); iSampleSize += capturedata.Length; iBufferOffset += capturedata.Length; iBufferOffset %= iBufferSize;//取模是因为缓冲区是循环的。 }
//真正转移数据的事件,其实就是把数据传送到网络上去。 private void RecordCapturedData(Socket Client, EndPoint epServer) { byte[] capturedata = null; int readpos = 0, capturepos = 0, locksize = 0; capturebuffer.GetCurrentPosition(out capturepos, out readpos); locksize = readpos - iBufferOffset;//这个大小就是我们可以安全读取的大小 if (locksize == 0) { return; } if (locksize < 0) {//因为我们是循环的使用缓冲区,所以有一种情况下为负:当文以载读指针回到第一个通知点,而Ibuffeoffset还在最后一个通知处 locksize += iBufferSize; } capturedata = (byte[])capturebuffer.Read(iBufferOffset, typeof(byte), LockFlag.FromWriteCursor, locksize); //capturedata = g729.Encode(capturedata);//语音编码 try { Console.WriteLine(new DateTime() + "=====传送语音"); Client.SendTo(capturedata, epServer);//传送语音 Console.WriteLine(new DateTime() + "=====播放语音"); GetVoiceData(capturedata.Length, capturedata); } catch (Exception ex) { Console.WriteLine("发送语音异常:" + ex.Message); throw new Exception(); } iBufferOffset += capturedata.Length; iBufferOffset %= iBufferSize;//取模是因为缓冲区是循环的。 }
//真正转移数据的事件,其实就是把数据传送到网络上去。 private void RecordCapturedData(EndPoint Client) { byte[] capturedata = null; int readpos = 0, capturepos = 0, locksize = 0; capturebuffer.GetCurrentPosition(out capturepos, out readpos); locksize = readpos - iBufferOffset;//这个大小就是我们可以安全读取的大小 if (locksize == 0) { return; } if (locksize < 0) {//因为我们是循环的使用缓冲区,所以有一种情况下为负:当文以载读指针回到第一个通知点,而Ibuffeoffset还在最后一个通知处 locksize += iBufferSize; } capturedata = (byte[])capturebuffer.Read(iBufferOffset, typeof(byte), LockFlag.FromWriteCursor, locksize); //capturedata = g729.Encode(capturedata);//语音编码 try { server.SendTo(capturedata, point); } catch { //throw new Exception(); } try { iBufferOffset += capturedata.Length; iBufferOffset %= iBufferSize;//取模是因为缓冲区是循环的。 } catch { } }
private void RecordCapturedData() { byte[] CaptureData = null; int ReadPos; int CapturePos; int LockSize; mRecBuffer.GetCurrentPosition(out CapturePos, out ReadPos); LockSize = ReadPos - mNextCaptureOffset; if (LockSize < 0) { LockSize += mBufferSize; } // 对齐缓冲区边界,实际上由于开始设定完整,这个操作是多余的. LockSize -= (LockSize % mNotifySize); if (0 == LockSize) { return; } // 读取缓冲区内的数据 CaptureData = (byte[])mRecBuffer.Read(mNextCaptureOffset, typeof(byte), LockFlag.None, LockSize); // 写入Wav文件 mWriter.Write(CaptureData, 0, CaptureData.Length); // 更新已经录制的数据长度. mSampleCount += CaptureData.Length; // 移动录制数据的起始点,通知消息只负责指示产生消息的位置,并不记录上次录制的位置 mNextCaptureOffset += CaptureData.Length; mNextCaptureOffset %= mBufferSize; // Circular buffer }
// Copies data from the capture buffer to the output buffer public void RecordCapturedData( ) { int ReadPos; byte[] CaptureData = null; int CapturePos; int LockSize; applicationBuffer.GetCurrentPosition(out CapturePos, out ReadPos); CalculationFunctions cf = new CalculationFunctions(); long CurrentPosition = (long)CapturePos; CurrentPositionInByte = CurrentPosition + SampleCount; dCurrentTime = cf.ConvertByteToTime(CurrentPosition, m_SampleRate, m_FrameSize); m_UpdateVMArrayLength = m_iCaptureBufferSize / 50; m_UpdateVMArrayLength = Convert.ToInt32(cf.AdaptToFrame(Convert.ToInt32(m_UpdateVMArrayLength), m_FrameSize)); arUpdateVM = new byte [m_UpdateVMArrayLength]; ReadPos = CapturePos; if (ReadPos < ((m_iCaptureBufferSize) - m_UpdateVMArrayLength)) { Array.Copy(applicationBuffer.Read(ReadPos, typeof(byte), LockFlag.None, m_UpdateVMArrayLength), arUpdateVM, m_UpdateVMArrayLength); //ob_UpdateVuMeter.NotifyUpdateVuMeter ( this, ob_UpdateVuMeter ) ; UpdateVuMeterFromRecorder(this, new events.AudioRecorderEvents.UpdateVuMeterFromRecorder()); } LockSize = ReadPos - NextCaptureOffset; if (LockSize < 0) { LockSize += m_iCaptureBufferSize; } // Block align lock size so that we are always write on a boundary LockSize -= (LockSize % m_iNotifySize); if (0 == LockSize) { return; } // Read the capture buffer. CaptureData = (byte[])applicationBuffer.Read(NextCaptureOffset, typeof(byte), LockFlag.None, LockSize); FileInfo fi = new FileInfo(m_sFileName); BinaryWriter Writer = new BinaryWriter(File.OpenWrite(m_sFileName)); // Write the data into the wav file"); Writer.BaseStream.Position = (long)(fi.Length); //Writer.Seek(0, SeekOrigin.End); Writer.Write(CaptureData, 0, CaptureData.Length); Writer.Close(); Writer = null; NotifyThread = null; // Update the number of samples, in bytes, of the file so far. //SampleCount+= datalength; SampleCount += (long)CaptureData.Length; // Move the capture offset along NextCaptureOffset += CaptureData.Length; NextCaptureOffset %= m_iCaptureBufferSize; // Circular buffer }
void RecordCapturedData() { //----------------------------------------------------------------------------- // Name: RecordCapturedData() // Desc: Copies data from the capture buffer to the output buffer //----------------------------------------------------------------------------- byte[] captureData = null; int readPos; int capturePos; int lockSize; try { buffer.GetCurrentPosition(out capturePos, out readPos); lockSize = readPos - nextCaptureOffset; if (lockSize < 0) { lockSize += captureBufferSize; } // Block align lock size so that we are always write on a boundary lockSize -= (lockSize % notifySize); if (0 == lockSize) { return; } // Read the capture buffer. captureData = (byte[])buffer.Read(nextCaptureOffset, typeof(byte), LockFlag.None, lockSize); OnBufferData(this, new DirectSoundBufferDataEventArgs(captureData)); if (writer != null) { // Write the data into the wav file writer.Write(captureData, 0, captureData.Length); } // Update the number of samples, in bytes, of the file so far. sampleCount += captureData.Length; // Move the capture offset along nextCaptureOffset += captureData.Length; nextCaptureOffset %= captureBufferSize; // Circular buffer } catch (Exception) { } finally { captureData = null; } }
private void CopyRecordedData() { // This copys the recorded data out of the capture buffer // and in to the wave file verbatam. The data is stored in // the capture buffer in the correct format and the wave file // header was previously written in the CreateTheRiff method int readCursor; int captureCursor; // Loads the captureCursor and readCursor with the buffer positions _recordBuffer.GetCurrentPosition(out captureCursor, out readCursor); // boundry used to check that we have located a valid boundry to // write from int boundry; boundry = readCursor - _nextRecordingPosition; if (boundry < 0) { boundry = boundry + _recordBufferSize; } // Align the block so that we will write on a boundry boundry = boundry - (boundry % _notificationAt); if (0 == boundry) { return; } // Set a temporary byte buffer to store the _recordBuffer data byte[] captured = null; // Copy the data out of the capture buffer captured = (byte[])_recordBuffer.Read(_nextRecordingPosition, typeof(byte), LockFlag.None, boundry); // Write out the data to the file previously setup _binaryWriter.Write(captured, 0, captured.Length); // Increase the running total of sample bytes (used when // finalising the file to update the length ) _sampleBytes = _sampleBytes + captured.Length; // Increase the capture buffer offset to the next position _nextRecordingPosition = _nextRecordingPosition + captured.Length; // Take in to account our circular buffer _nextRecordingPosition = _nextRecordingPosition % _recordBufferSize; }
/// <summary> /// 常時録音処理を行う。 /// </summary> private void RecordWorker() { short[] buffer = new short[DataBuffer.PacketSize / sizeof(short)]; while (isActive) { try { // キャプチャバッファが埋まるまで待機 notificationEvent.WaitOne(Timeout.Infinite, true); // キャプチャサイズを算出 int capturePosition, readPosition; applicationBuffer.GetCurrentPosition(out capturePosition, out readPosition); int lockSize = readPosition - nextCaptureOffset; if (lockSize < 0) { lockSize += captureBufferSize; } lockSize -= lockSize % notifySize; if (lockSize == 0) { continue; } // キャプチャデータ取得 byte[] captureData = (byte[])applicationBuffer.Read( nextCaptureOffset, typeof(byte), LockFlag.None, lockSize); // パケットに切り分けて処理 for (int i = 0; i < captureData.Length / DataBuffer.PacketSize; i++) { System.Buffer.BlockCopy(captureData, DataBuffer.PacketSize * i, buffer, 0, DataBuffer.PacketSize); dataBuffer.AddData(buffer, DetectTalking(buffer), DateTime.Now.Ticks); } // 次回のオフセットを計算 nextCaptureOffset += captureData.Length; if (nextCaptureOffset >= captureBufferSize) { nextCaptureOffset -= captureBufferSize; } } catch (Exception e) { SoundControl.WriteErrorLog(e.ToString()); } } }
private void RecordWorker() { try { byte[] buf = new byte[mBufferLength]; MemoryStream memStream = new MemoryStream(buf); int readLength = mBufferLength / 4; int latestReadCursor = 0; int latestReadPosition = 0; mBuffer.Start(true); setState(AudioDeviceState.Recording); double[] maxDbs; while (true) { int captureCursor, readCursor; mBuffer.GetCurrentPosition(out captureCursor, out readCursor); if (readCursor < latestReadCursor) { mCycleCount++; } int currentReadPosition = readCursor + (mCycleCount * mBufferLength); //Do read if there is more than readLength bytes to read or if recording has stopped if (mHasRecordingStopped) { memStream.Position = 0; mBuffer.Read(latestReadPosition % mBufferLength, memStream, currentReadPosition - latestReadPosition, LockFlag.None); mPCMOutoutStream.Write(buf, 0, currentReadPosition - latestReadPosition); handleRecordedData(buf, 0, currentReadPosition - latestReadPosition, out maxDbs); FireTime(getTimeEquivalent(readCursor + (mCycleCount * mBufferLength)), maxDbs); break; } else if (latestReadPosition + readLength < currentReadPosition) { memStream.Position = 0; mBuffer.Read(latestReadPosition % mBufferLength, memStream, currentReadPosition - latestReadPosition, LockFlag.None); mPCMOutoutStream.Write(buf, 0, currentReadPosition - latestReadPosition); handleRecordedData(buf, 0, currentReadPosition - latestReadPosition, out maxDbs); latestReadPosition = currentReadPosition; FireTime(getTimeEquivalent(readCursor + (mCycleCount * mBufferLength)), maxDbs); } latestReadCursor = readCursor; Thread.Sleep(WAIT_TIME_MS); } mBuffer.Dispose(); } catch (ThreadAbortException) { if (mBuffer != null) { if (!mBuffer.Disposed) { mBuffer.Dispose(); } } } }
//The real transfer of data events, in fact, the data is transferred to the WAV file. private void RecordCapturedData() { byte[] capturedata = null; int readpos = 0, capturepos = 0, locksize = 0; capturebuffer.GetCurrentPosition(out capturepos, out readpos); locksize = readpos - iBufferOffset;//This size is the size we can safely read if (locksize == 0) { return; } if (locksize < 0) { //Because we are using the buffer for the loop, //so there is a case of negative: //when the text to read the pointer back to the first notification point, //and Ibuffeoffset is still the last notification locksize += iBufferSize; } if (locksize % 2 == 1) { locksize -= 1; } capturedata = (byte[])capturebuffer.Read(iBufferOffset, typeof(byte), LockFlag.FromWriteCursor, locksize); for (int i = 0; i < locksize; i += 2) { int temp = ((capturedata[i + 1] << 8) | (capturedata[i])) << 48 >> 48; if (temp < minVoice && temp > (0 - minVoice)) { temp = 0; } float Ftemp = ((float)temp) / 65536; try { Monitor.Enter(queue); queue.Enqueue(Ftemp); Monitor.Exit(queue); } catch (Exception ex) { ; } } iSampleSize += capturedata.Length; iBufferOffset += capturedata.Length; iBufferOffset %= iBufferSize;//Modulo is because the buffer is looped. }
// Copies data from the capture buffer to the output buffer public void RecordCapturedData( ) { int ReadPos; int CapturePos; int LockSize; applicationBuffer.GetCurrentPosition(out CapturePos, out ReadPos); ReadPos = CapturePos; if (ReadPos < ((m_iCaptureBufferSize) - m_UpdateVMArrayLength)) { Array.Copy(applicationBuffer.Read(ReadPos, typeof(byte), LockFlag.None, m_UpdateVMArrayLength), arUpdateVM, m_UpdateVMArrayLength); ob_UpdateVuMeter.NotifyUpdateVuMeter(this, ob_UpdateVuMeter); } LockSize = ReadPos - NextCaptureOffset; if (LockSize < 0) { LockSize += m_iCaptureBufferSize; } // Block align lock size so that we are always write on a boundary LockSize -= (LockSize % m_iNotifySize); if (0 == LockSize) { return; } // Read the capture buffer. CaptureData = (byte[])applicationBuffer.Read(NextCaptureOffset, typeof(byte), LockFlag.None, LockSize); FileInfo fi = new FileInfo(m_sFileName); Writer = new BinaryWriter(File.OpenWrite(m_sFileName)); // Write the data into the wav file"); Writer.BaseStream.Position = (long)(fi.Length); //Writer.Seek(0, SeekOrigin.End); Writer.Write(CaptureData, 0, CaptureData.Length); Writer.Close(); // Writer = null; // Update the number of samples, in bytes, of the file so far. //SampleCount+= datalength; SampleCount += (long)CaptureData.Length; // Move the capture offset along NextCaptureOffset += CaptureData.Length; NextCaptureOffset %= m_iCaptureBufferSize; // Circular buffer }
//真正转移数据的事件,其实就是把数据传送到网络上去。 private void RecordCapturedData(RadioTCPClient Client) { byte[] capturedata = null; int readpos = 0, capturepos = 0, locksize = 0; capturebuffer.GetCurrentPosition(out capturepos, out readpos); locksize = readpos - iBufferOffset;//这个大小就是我们可以安全读取的大小 if (locksize == 0) { return; } if (locksize < 0) {//因为我们是循环的使用缓冲区,所以有一种情况下为负:当文以载读指针回到第一个通知点,而Ibuffeoffset还在最后一个通知处 locksize += iBufferSize; } capturedata = (byte[])capturebuffer.Read(iBufferOffset, typeof(byte), LockFlag.FromWriteCursor, locksize); //capturedata = g729.Encode(capturedata);//语音编码 try { if (Client.NetWork.Connected) { count++; Client.NetWork.GetStream().Write(capturedata, 0, capturedata.Length); if (count >= 4) { count = 0; //Client.NetWork.GetStream().Write(empty, 0, empty.Length/2); } } } catch { //throw new Exception(); } try { iBufferOffset += capturedata.Length; iBufferOffset %= iBufferSize;//取模是因为缓冲区是循环的。 } catch { } }
void RecordCapturedData() { //----------------------------------------------------------------------------- // Name: RecordCapturedData() // Desc: Copies data from the capture buffer to the output buffer //----------------------------------------------------------------------------- byte[] CaptureData = null; int ReadPos; int CapturePos; int LockSize; applicationBuffer.GetCurrentPosition(out CapturePos, out ReadPos); LockSize = ReadPos - NextCaptureOffset; if (LockSize < 0) { LockSize += CaptureBufferSize; } // Block align lock size so that we are always write on a boundary LockSize -= (LockSize % NotifySize); if (0 == LockSize) { return; } // Read the capture buffer. CaptureData = (byte[])applicationBuffer.Read(NextCaptureOffset, typeof(byte), LockFlag.None, LockSize); // Write the data into the wav file Writer.Write(CaptureData, 0, CaptureData.Length); // Update the number of samples, in bytes, of the file so far. SampleCount += CaptureData.Length; // Move the capture offset along NextCaptureOffset += CaptureData.Length; NextCaptureOffset %= CaptureBufferSize; // Circular buffer }
//真正转移数据的事件,其实就是把数据传送到网络上去。 private void RecordCapturedData() { byte[] capturedata = null; int readpos = 0, capturepos = 0, locksize = 0; capturebuffer.GetCurrentPosition(out capturepos, out readpos); locksize = readpos - iBufferOffset;//这个大小就是我们可以安全读取的大小 if (locksize == 0) { return; } if (locksize < 0) {//因为我们是循环的使用缓冲区,所以有一种情况下为负:当文以载读指针回到第一个通知点,而Ibuffeoffset还在最后一个通知处 locksize += iBufferSize; } capturedata = (byte[])capturebuffer.Read(iBufferOffset, typeof(byte), LockFlag.FromWriteCursor, locksize); mWriter.Write(capturedata, 0, capturedata.Length);//写入到文件 iSampleSize += capturedata.Length; iBufferOffset += capturedata.Length; iBufferOffset %= iBufferSize;//取模是因为缓冲区是循环的。 }
/// <summary> /// Copies data from the capture buffer to the output buffer /// </summary> private void RecordCapturedData(bool flush) { byte[] CaptureData = null; int ReadPos; int CapturePos; int LockSize; applicationBuffer.GetCurrentPosition(out CapturePos, out ReadPos); LockSize = ReadPos - nextCaptureOffset; if (LockSize < 0) { LockSize += captureBufferSize; } // Block align lock size so that we are always write on a boundary LockSize -= (LockSize % notifySize); if (0 == LockSize) { return; } // Read the capture buffer. CaptureData = (byte[])applicationBuffer.Read(nextCaptureOffset, typeof(byte), LockFlag.None, LockSize); filters.Input.Write(CaptureData, 0, CaptureData.Length); // Update the number of samples, in bytes, of the file so far. sampleByteCount += CaptureData.Length; // Move the capture offset along nextCaptureOffset += CaptureData.Length; nextCaptureOffset %= captureBufferSize; // Circular buffer if (flush) { filters.Input.Flush(); } }
private void captureLoop() { try { while (true) { int currentPos, pos2; // Смотрим, в каком месте находится курсор записи captureBuffer.GetCurrentPosition(out currentPos, out pos2); // Вычисляем размер записи int size = currentPos - readPos; if (size < 0) { size += bufferSize; } if (size == 0) { continue; } // Читаем данные в буфер byte[] streamBuffer = new byte[size]; var stream = new MemoryStream(streamBuffer); captureBuffer.Read(readPos, stream, size, LockFlag.None); bool voiceDetected = false; // Проверяем каждый семпл, смотрим громкость int peakVolume = 0; for (int i = 1; i < size; i += 2) { int sampleVolume = streamBuffer[i] * 0x100 + streamBuffer[i - 1]; if (sampleVolume > 32767) { sampleVolume -= 65536; // Оно со знаком } if (sampleVolume > peakVolume) { peakVolume = sampleVolume; // Вычисляем пик громкости } // Если она выше заданное громкости определения голоса... if (Math.Abs(sampleVolume) > DetectVolume) { voiceDetected = true; if (OnPeakMeter == null) { break; } //break; } } if (OnPeakMeter != null) { OnPeakMeter(peakVolume); } // Обнаружен голос if (voiceDetected) { // Если мы ещё не пишем... if (!IsRecording) { if (record != null) { record.Dispose(); } record = new MemoryStream(); IsRecording = true; recordTime = 0; // Сохраняем кусочек звука, который был до этого if (lastSample != null && lastSize > 0) { record.Write(lastSample, 0, lastSize); } } noRecordTime = 0; // Обнуляем счётчик времени без голоса } else // Если в микрофоне тишина... { if (IsRecording) // Если при этом идёт запись { noRecordTime++; // Увеличиваем счётчик времени без голоса // И если мы молчим уже достаточно долго if (noRecordTime >= SilenceLenghtMillisecondsMaximum / 100) { IsRecording = false; // Прекращаем запись // Проверяем на заданные условия if ((recordTime >= PhraseLengthMillisecondsMinimum / 100) && (recordTime <= PhraseLengthMillisecondsMaximum / 100)) { // Приостанавливаем запись captureBuffer.Stop(); // Отправляем записанное на обработку processRecord(record); // Снова запускаем запись captureBuffer.Start(true); } } } } // Если пишем, то добавляем данные в буфер if (IsRecording) { record.Write(streamBuffer, 0, size); recordTime++; } else { // Запомиаем семпл, пригодится lastSample = streamBuffer; lastSize = size; } // Запоминаем позицию readPos = currentPos; Thread.Sleep(100); } } catch (ThreadAbortException) { } catch (Exception ex) { captureThread = null; if (OnCaptureEror != null) { OnCaptureEror(ex); } } }
//private int m_circularBufferCapturePosition = -1; #endif private int circularBufferTransferData( #if !FORCE_SINGLE_NOTIFICATION_EVENT int eventIndex, bool catchingUp, #endif bool lastFlush ) { #if !FORCE_SINGLE_NOTIFICATION_EVENT #if SIMULATE_BUFFER_NOTIFICATION_SKIP Console.WriteLine(eventIndex); #endif if (!catchingUp) { #if SIMULATE_BUFFER_NOTIFICATION_SKIP // NOTIFICATIONS = 16, each REFRESH_INTERVAL_MS = 75 bool beginning = eventIndex == 0 || eventIndex == 1 || eventIndex == 2; bool end = eventIndex == 13 || eventIndex == 14 || eventIndex == 15; bool middle = eventIndex == 6 || eventIndex == 7 || eventIndex == 8; bool middleTwo = eventIndex == 3 || eventIndex == 4 || eventIndex == 5 || eventIndex == 9 || eventIndex == 10 || eventIndex == 11; //if (beginning) //if (end) //if (beginning || end) //if (beginning || middle) //if (middle || end) if (beginning || middle || end) //if (middle) //if (middleTwo) { Console.WriteLine("SKIPPED."); return(0); } #endif if ((m_previousEventIndex == -1 || m_previousEventIndex >= 0) && eventIndex >= 0) { int nextEventIndex = m_previousEventIndex + 1; if (nextEventIndex >= NOTIFICATIONS) { nextEventIndex = 0; } int toCatchUp = 0; if (eventIndex == nextEventIndex) { // OK } else if (eventIndex > nextEventIndex) { // ahead, but not looped back in circular buffer toCatchUp = eventIndex - nextEventIndex; } else if (eventIndex < nextEventIndex) { // ahead, but looped back in circular buffer toCatchUp = (NOTIFICATIONS - nextEventIndex) + eventIndex; } if (toCatchUp > 0) { #if SIMULATE_BUFFER_NOTIFICATION_SKIP Console.WriteLine("TO CATCHUP: {0}", toCatchUp); #endif for (int i = 0; i < toCatchUp; i++) { #if SIMULATE_BUFFER_NOTIFICATION_SKIP Console.WriteLine("Audio recording event catch-up {0}, {1} => {2}", eventIndex, m_previousEventIndex, nextEventIndex); #endif circularBufferTransferData(nextEventIndex, true, lastFlush); nextEventIndex++; if (nextEventIndex >= NOTIFICATIONS) { nextEventIndex = 0; } } //DebugFix.Assert(m_previousEventIndex == (eventIndex-1)); } } } m_previousEventIndex = eventIndex; #endif #if USE_SHARPDX int circularBufferCapturePosition = m_CircularBuffer.CurrentCapturePosition; //int readPosition = m_CircularBuffer.CurrentRealPosition; #else int circularBufferCapturePosition; int readPosition; // UNUSED m_CircularBuffer.GetCurrentPosition(out circularBufferCapturePosition, out readPosition); #endif //#if !FORCE_SINGLE_NOTIFICATION_EVENT // if (catchingUp) // { // circularBufferCapturePosition = m_circularBufferCapturePosition; // } // else // { // m_circularBufferCapturePosition = circularBufferCapturePosition; // } //#endif int circularBufferBytes = m_CircularBuffer. #if USE_SHARPDX Capabilities #else Caps #endif .BufferBytes ; int notifyChunk = circularBufferBytes / NOTIFICATIONS; int circularBufferBytesAvailableForReading = (circularBufferCapturePosition == m_CircularBufferReadPositon ? 0 : (circularBufferCapturePosition < m_CircularBufferReadPositon ? circularBufferCapturePosition + (circularBufferBytes - m_CircularBufferReadPositon) : circularBufferCapturePosition - m_CircularBufferReadPositon)); if (lastFlush) { #if !FORCE_SINGLE_NOTIFICATION_EVENT DebugFix.Assert(eventIndex == -1); #endif //circularBufferBytesAvailableForReading -= (circularBufferBytesAvailableForReading % notifyChunk); #if DEBUG Console.WriteLine("m_CircularBufferReadPositon: " + m_CircularBufferReadPositon); Console.WriteLine("circularBufferBytesAvailableForReading; " + circularBufferBytesAvailableForReading); #endif } else { #if !FORCE_SINGLE_NOTIFICATION_EVENT DebugFix.Assert(eventIndex >= 0); circularBufferBytesAvailableForReading = notifyChunk; #endif } if (circularBufferBytesAvailableForReading <= 0) { //Console.WriteLine(string.Format("circularBufferTransferData: no more bytes to fetch {0}", circularBufferBytesAvailableForReading)); return(circularBufferBytesAvailableForReading); } DebugFix.Assert(circularBufferBytesAvailableForReading <= circularBufferBytes); if (circularBufferBytesAvailableForReading > circularBufferBytes) { circularBufferBytesAvailableForReading = circularBufferBytes; } int circularBufferBytesAvailableForCapturing = circularBufferBytes - circularBufferBytesAvailableForReading; //int toRead = readPosition - m_CircularBufferReadPositon; //if (toRead < 0) // toRead += m_CircularBuffer.Caps.BufferBytes; //toRead -= (toRead % (m_CircularBuffer.Caps.BufferBytes / NOTIFICATIONS)); //if (toRead <= 0) //{ // Console.WriteLine(string.Format("BAD toRead {0}", toRead)); // continue; //} #if !FORCE_SINGLE_NOTIFICATION_EVENT if (eventIndex >= 0) { DebugFix.Assert(circularBufferBytesAvailableForReading == notifyChunk); int pos = eventIndex * notifyChunk; //DebugFix.Assert(pos == m_CircularBufferReadPositon); if (m_CircularBufferReadPositon != pos) { #if DEBUG Console.WriteLine("READ POS ADJUST: " + m_CircularBufferReadPositon + " != " + pos + " // " + notifyChunk + " -- " + (pos - m_CircularBufferReadPositon)); #endif m_CircularBufferReadPositon = pos; } } #endif #if USE_SHARPDX if (incomingPcmData == null) { Console.WriteLine("ALLOCATING incomingPcmData"); incomingPcmData = new byte[circularBufferBytesAvailableForReading]; } else if (incomingPcmData.Length < circularBufferBytesAvailableForReading) { Console.WriteLine("incomingPcmData.resize"); Array.Resize(ref incomingPcmData, circularBufferBytesAvailableForReading); } DebugFix.Assert(circularBufferBytesAvailableForReading <= incomingPcmData.Length); m_CircularBuffer.Read(incomingPcmData, 0, circularBufferBytesAvailableForReading, m_CircularBufferReadPositon, LockFlags.None); #else // !USE_SHARPDX byte[] incomingPcmData = (byte[])m_CircularBuffer.Read(m_CircularBufferReadPositon, typeof(byte), LockFlag.None, circularBufferBytesAvailableForReading); DebugFix.Assert(circularBufferBytesAvailableForReading == incomingPcmData.Length); #endif #if FORCE_SINGLE_NOTIFICATION_EVENT if (!lastFlush && m_DO_LOG_CircularBufferNotificationTimerMessage) { String msg = "DO_LOG_CircularBufferNotificationTimerMessage:: circularBufferBytes @ m_CircularBufferReadPositon # circularBufferCapturePosition - circularBufferBytesAvailableForReading / notifyChunk $ incomingPcmData.Length: " + circularBufferBytes + " @ " + m_CircularBufferReadPositon + " # " + circularBufferCapturePosition + " - " + circularBufferBytesAvailableForReading + " / " + notifyChunk + " $ " + (incomingPcmData == null ? "NULL" : ("" + incomingPcmData.Length)); #if DEBUG Console.WriteLine(msg); #endif CircularBufferNotificationTimerMessageHandler del_ = CircularBufferNotificationTimerMessage; if (del_ != null) { del_(this, new CircularBufferNotificationTimerMessageEventArgs(msg)); } } #endif //if (m_CircularBuffer != null && m_CircularBuffer.Capturing) //{ // int capturePosition; // int readPosition; // m_CircularBuffer.GetCurrentPosition(out capturePosition, out readPosition); // return // RecordingPCMFormat.ConvertBytesToTime(m_TotalRecordedBytes + capturePosition - // m_CircularBufferReadPositon); //} int length = circularBufferBytesAvailableForReading; DebugFix.Assert(length <= incomingPcmData.Length); if (length > incomingPcmData.Length) { length = incomingPcmData.Length; } if (m_TotalRecordedBytes >= (ulong.MaxValue - (ulong)length)) { #if DEBUG Debugger.Break(); #endif //DEBUG // Oh oh! :( if (CurrentState == State.Monitoring) { m_TotalRecordedBytes = 0; #if FORCE_SINGLE_NOTIFICATION_EVENT m_PreviousTotalRecordedBytes = 0; #endif } } else { if (CurrentState == State.Recording) { if (m_RecordingFileWriter == null) { string parentDir = Path.GetDirectoryName(m_RecordedFilePath); if (!Directory.Exists(parentDir)) { Directory.CreateDirectory(parentDir); //FileDataProvider.CreateDirectory(parentDir); } //FileInfo fi = new FileInfo(m_RecordedFilePath); //fi.FullName m_RecordingFileWriter = new BinaryWriter(File.OpenWrite(m_RecordedFilePath)); } m_RecordingFileWriter.BaseStream.Position = (long)m_TotalRecordedBytes + (long)m_RecordedFileRiffHeaderSize; // m_RecordingFileWriter.BaseStream.Length; m_RecordingFileWriter.Write(incomingPcmData, 0, length); } m_TotalRecordedBytes += (ulong)length; } m_CircularBufferReadPositon += length; m_CircularBufferReadPositon %= circularBufferBytes; PcmDataBufferAvailableHandler del = PcmDataBufferAvailable; if (del != null) { //if (m_PcmDataBuffer.Length != incomingPcmData.Length) //{ // //Console.WriteLine(string.Format(">>>>> Resizing buffer: m_PcmDataBuffer = {0}, incomingPcmData = {1}",m_PcmDataBuffer.Length, incomingPcmData.Length)); // Array.Resize(ref m_PcmDataBuffer, incomingPcmData.Length); //} //Array.Copy(incomingPcmData, m_PcmDataBuffer, m_PcmDataBuffer.Length); int min = Math.Min(m_PcmDataBufferLength, length); //Array.Copy(incomingPcmData, m_PcmDataBuffer, min); Buffer.BlockCopy(incomingPcmData, 0, m_PcmDataBuffer, 0, min); m_PcmDataBufferAvailableEventArgs.PcmDataBuffer = m_PcmDataBuffer; m_PcmDataBufferAvailableEventArgs.PcmDataBufferLength = min; del(this, m_PcmDataBufferAvailableEventArgs); } return(length); }
/// <summary> /// 将录制的数据写入wav文件 改写为UDP发送 /// </summary> private void RecordCapturedData(Socket Client, EndPoint epserver) { byte[] CaptureData = null; byte[] SendData = null; int ReadPos = 0; int CapturePos = 0; int LockSize = 0; mRecBuffer.GetCurrentPosition(out CapturePos, out ReadPos); LockSize = ReadPos - mNextCaptureOffset; if (LockSize < 0) { LockSize += mBufferSize; } // 对齐缓冲区边界,实际上由于开始设定完整,这个操作是多余的. LockSize -= (LockSize % mNotifySize); if (0 == LockSize) { return; } // 读取缓冲区内的数据 CaptureData = (byte[])mRecBuffer.Read(mNextCaptureOffset, typeof(byte), LockFlag.None, LockSize); // 更新已经录制的数据长度. mSampleCount += CaptureData.Length; //压缩数据,实测压缩率在50%左右 SendData = ZLibCompressor.Compress(CaptureData); // 写入Wav文件 ,在这里改成发送 // mWriter.Write(SendData, 0, SendData.Length); // mWriter.Write(CaptureData, 0, CaptureData.Length); //发送文件到网络 try { Client.SendTo(SendData, epServer);//传送语音 } catch (Exception e) { MessageBox.Show(e.Message, "错误"); } // 移动录制数据的起始点,通知消息只负责指示产生消息的位置,并不记录上次录制的位置 mNextCaptureOffset += CaptureData.Length; mNextCaptureOffset %= mBufferSize; // Circular buffer }