最近写个录音相关的程序,参考了网上的源码,自己改了改测试的时候有个问题没有搞懂。代码是通过C#封装后的Wave系列API来实现。播放和录音是单独的线程。问题:即使我没有将播放的缓存中放入数据,录音线程仍然抓到了我生成的信号?没可能啊
下面是代码片段:
//Main
bool isTesting = falseprivate void Start()
{
   Stop();   try
   {
       _waveFormat = new WaveFormat(_audioFrameSize, _audioBitsPerSample, _audioChannels);
       if (!isTesting)
          _Player = new WaveOutPlayer(-1, _waveFormat, _audioFrameSize*2, 3, new BufferFillEventHandler(Filler));
       _Recorder = new WaveInRecorder(-1, _waveFormat, _audioFrameSize*2, 3, new BufferDoneEventHandler(DataArrived));
    }
    catch (System.Exception ex)
    {
     //   
    }
}private void Filler(IntPtr data, int size)
{
    if (isTesting == false)
    {
          // ……          for (int i = 0; i < _playerBuffer.Length; i++)//生成信号sin波,_playerBuffer是全局数组
          {
                    _playerBuffer[i] = (byte)(128 * Math.Sin(2*Math.PI*i/512));// (byte)i;
          }
          //!!!!!!!!注意这里,我没有COPY到播放设备的缓存上啊!!我Mark掉了录音时还抓到了sin波
          //System.Runtime.InteropServices.Marshal.Copy(_playerBuffer, 0, data, size);
     }
}private void DataArrived(IntPtr data, int size)
{
       if (_recorderBuffer == null || _recorderBuffer.Length < size)
            _recorderBuffer = new byte[size];
       if (_recorderBuffer != null)
       {
            System.Runtime.InteropServices.Marshal.Copy(data, _recorderBuffer, 0, size);
            //if (isTesting == false)
            //   _stream.Write(_recorderBuffer, 0, _recorderBuffer.Length);
            //_audioFrame.Process(ref _recorderBuffer);
            //_audioFrame.RenderTimeDomain(ref pictureBox1);
            //_audioFrame.RenderFrequencyDomain(ref pictureBox2);
            }
        }//Waveout Class
public class WaveOutPlayer : IDisposable
{
    private IntPtr m_WaveOut;
    private WaveOutBuffer m_Buffers; // linked list
    private WaveOutBuffer m_CurrentBuffer;
    private Thread m_Thread;
    private BufferFillEventHandler m_FillProc;
    private bool m_Finished;
    private byte m_zero;    private WaveNative.WaveDelegate m_BufferProc = new WaveNative.WaveDelegate(WaveOutBuffer.WaveOutProc);    public WaveOutPlayer(int device, WaveFormat format, int bufferSize, int bufferCount, BufferFillEventHandler fillProc)
   {
m_zero = format.wBitsPerSample == 8 ? (byte)128 : (byte)0;
         m_FillProc = fillProc;//Filler
         WaveOutHelper.Try(WaveNative.waveOutOpen(out m_WaveOut, device, format, m_BufferProc, 0, WaveNative.CALLBACK_FUNCTION));
         //分配缓存……
         m_Thread = new Thread(new ThreadStart(ThreadProc));
         m_Thread.Start();
    }    internal static void WaveOutProc(IntPtr hdrvr, int uMsg, int dwUser, ref WaveNative.WaveHdr wavhdr, int dwParam2)
    {
        if (uMsg == WaveNative.MM_WOM_DONE)
        {
            try
            {
                GCHandle h = (GCHandle)wavhdr.dwUser;
                WaveOutBuffer buf = (WaveOutBuffer)h.Target;
                buf.OnCompleted();
            }
            catch
            {}
        }
    }
    //……}
//WaveIn Class
public class WaveInRecorder : IDisposable
{
private IntPtr m_WaveIn;
private WaveInBuffer m_Buffers; // linked list
private WaveInBuffer m_CurrentBuffer;
private Thread m_Thread;
private BufferDoneEventHandler m_DoneProc;
private bool m_Finished;
         //回调
private WaveNative.WaveDelegate m_BufferProc = new WaveNative.WaveDelegate(WaveInBuffer.WaveInProc); public WaveInRecorder(int device, WaveFormat format, int bufferSize, int bufferCount, BufferDoneEventHandler doneProc)
{
m_DoneProc = doneProc;//DataArrived
                  WaveInHelper.Try(WaveNative.waveInOpen(out m_WaveIn, device, format, m_BufferProc, 0, WaveNative.CALLBACK_FUNCTION));//打开录音设备
//分配缓存 …… 
                  WaveInHelper.Try(WaveNative.waveInStart(m_WaveIn));//开始录音
m_Thread = new Thread(new ThreadStart(ThreadProc));//启动线程
m_Thread.Start();
} internal static void WaveInProc(IntPtr hdrvr, int uMsg, int dwUser, ref WaveNative.WaveHdr wavhdr, int dwParam2)
{
    if (uMsg == WaveNative.MM_WIM_DATA)
    {
try
{
    GCHandle h = (GCHandle)wavhdr.dwUser;
    WaveInBuffer buf = (WaveInBuffer)h.Target;
    buf.OnCompleted();
}
catch
{}
     }
}         // ……
}