在 C# 中使用 waveIn/waveout api,一个全双工音频播放器

分享于 

4分钟阅读

多媒体

  繁體
  • 下载源文件-15.1 Kb
  • Sample Image - cswavrec.gif

    介绍

    本文介绍了一个示例应用程序,该示例应用程序通过P/Invoke在c#中使用waveIn和waveOut API捕获来自声卡输入的音频信号,并同时播放。

    使用代码

    此示例中的新类为WaveInRecorderFifoStream

    FifoStream类扩展了System.IO.Stream以实现字节的FIFO(先进先出)。重写的Write方法向FIFO的尾部添加数据,Read方法从FIFO的头部查看和删除数据,Length属性可随时返回缓冲数据的数量,调用Flush将清除所有挂起的数据。

    WaveInRecorder类似于WaveOutPlayer类,事实上,如果查看源文件,你将注意到这些类的实现非常相似,WaveOutPlayer一样,此类的接口被简化为严格最小值。

    创建WaveInRecorder的实例将导致系统立即开始记录,下面是创建WaveOutPlayerWaveInRecorder实例的代码。

    
    
    private void Start()
    
    
    {
    
    
     Stop();
    
    
     try
    
    
     {
    
    
     WaveLib.WaveFormat fmt = new WaveLib.WaveFormat(44100, 16, 2);
    
    
     m_Player = new WaveLib.WaveOutPlayer(-1, fmt, 16384, 3, 
    
    
     new WaveLib.BufferFillEventHandler(Filler));
    
    
     m_Recorder = new WaveLib.WaveInRecorder(-1, fmt, 16384, 3, 
    
    
     new WaveLib.BufferDoneEventHandler(DataArrived));
    
    
     }
    
    
     catch
    
    
     {
    
    
     Stop();
    
    
     throw;
    
    
     }
    
    
    }
    
    
    
    
    

    WaveInRecorder构造函数需要五个参数。除了最后一个参数,它们的含义与WaveOutPlayer中的相同

    在示例应用程序中,我们只将捕获的数据写入FIFO,如下所示:

    
    
    private void DataArrived(IntPtr data, int size)
    
    
    {
    
    
     if (m_RecBuffer == null || m_RecBuffer.Length < size)
    
    
     m_RecBuffer = new byte[size];
    
    
     System.Runtime.InteropServices.Marshal.Copy(data, m_RecBuffer, 0, size);
    
    
     m_Fifo.Write(m_RecBuffer, 0, m_RecBuffer.Length);
    
    
    }
    
    
    
    
    

    同样,每次播放需要更多数据时,都会调用Filler方法,实现只从FIFO读取数据,如下所示:

    
    
    private void Filler(IntPtr data, int size)
    
    
    {
    
    
     if (m_PlayBuffer == null || m_PlayBuffer.Length < size)
    
    
     m_PlayBuffer = new byte[size];
    
    
     if (m_Fifo.Length >= size)
    
    
     m_Fifo.Read(m_PlayBuffer, 0, size);
    
    
     else
    
    
     for (int i = 0; i < m_PlayBuffer.Length; i++)
    
    
     m_PlayBuffer[i] = 0;
    
    
     System.Runtime.InteropServices.Marshal.Copy(m_PlayBuffer, 
    
    
     0, data, size);
    
    
    }
    
    
    
    
    

    请注意,为了通过保存一些垃圾回收来提高性能,我们声明了临时缓冲区m_RecBufferm_PlayBuffer作为成员字段。

    要停止流式处理,只需在播放器上调用Dispose,并捕获对象,我们还需要刷新FIFO,以便下次调用Start时没有剩余的数据可以播放。

    
    
    private void Stop()
    
    
    {
    
    
     if (m_Player!= null)
    
    
     try
    
    
     {
    
    
     m_Player.Dispose();
    
    
     }
    
    
     finally
    
    
     {
    
    
     m_Player = null;
    
    
     }
    
    
     if (m_Recorder!= null)
    
    
     try
    
    
     {
    
    
     m_Recorder.Dispose();
    
    
     }
    
    
     finally
    
    
     {
    
    
     m_Recorder = null;
    
    
     }
    
    
     m_Fifo.Flush(); // clear all pending data
    
    
    }
    
    
    
    
    

    API  play  音频  播放器  WAV  WAVE  
    相关文章