从麦克风无损读取

时间:2011-07-13 14:07:26

标签: windows audio naudio wave

我正在使用NAudio(但它适用于直接阅读)来捕获麦克风波数据。似乎如果我的应用程序忙,它会从麦克风中删除/跳过一些输入数据。

我将读取线程设置为最高优先级,但我同时在其他几个线程中进行了大量计算。

有没有办法读取无损数据? (或者它是无损的,我的其他地方的错误?)

1 个答案:

答案 0 :(得分:0)

当我制作类似的应用程序并遇到类似的问题时,我发现我需要一个可以容纳至少3秒数据的缓冲区。尝试将缓冲区增加到10秒的数据,如果它不能解决您的问题,则会出现更多问题。如果有效,请尝试减小缓冲区大小,直到它正常工作

编辑:这里有一个快速的&脏的托管dx录音供你试试。

    public class BMSRecordingEventArgs : EventArgs
{
    byte[] data;
    bool endRec;

    public BMSRecordingEventArgs(byte[] data, bool endRec)
    {
        this.data = data;
        this.endRec = endRec;
    }
    public byte[] Data
    {
        get { return data; }
    }
    public bool EndRec
    {
        get { return endRec; }
    }
}
public class AudioRecorder
{
    public delegate void DataReceivedHandler(object sender, BMSRecordingEventArgs e);
    public event DataReceivedHandler DataReceivedHandle;

    public const int CAPTURE_BUFFER_SIZE = 32000;
    DXS.Capture dxsCapDev;
    DXS.CaptureBuffer dxsCapBuffer;
    DXS.CaptureBufferDescription dxsCapBufferDesc;
    System.Threading.Thread thrdCapturingThread;
    DXS.BufferPositionNotify[] dxsBpna;
    private volatile bool StopRec;

    System.Threading.ManualResetEvent mreStillRunning = new System.Threading.ManualResetEvent(false);
    DXS.BufferPositionNotify dxsBPNHalf;
    DXS.BufferPositionNotify dxsBPNFull;
    DXS.Notify Notify;
    System.Threading.AutoResetEvent ARE;

    public AudioRecorder(Guid DeviceGuid,DXS.WaveFormat wfWaveFormat,DXS.CaptureEffectDescription[] dxsCapEffectDesc)
    {

        dxsCapDev = new Microsoft.DirectX.DirectSound.Capture(DeviceGuid);
        dxsCapBufferDesc = new Microsoft.DirectX.DirectSound.CaptureBufferDescription();
        dxsCapBufferDesc.BufferBytes = CAPTURE_BUFFER_SIZE;
        dxsCapBufferDesc.Format = wfWaveFormat;
        dxsCapBufferDesc.WaveMapped = true;
        dxsCapBufferDesc.CaptureEffectDescription = dxsCapEffectDesc;
        dxsCapBufferDesc.ControlEffects = true;


        dxsCapBuffer = new Microsoft.DirectX.DirectSound.CaptureBuffer(dxsCapBufferDesc, dxsCapDev);

        ARE = new System.Threading.AutoResetEvent(false);
        dxsBPNHalf = new Microsoft.DirectX.DirectSound.BufferPositionNotify();
        dxsBPNFull = new Microsoft.DirectX.DirectSound.BufferPositionNotify();
        dxsBPNHalf.Offset = CAPTURE_BUFFER_SIZE / 2 - 1;
        dxsBPNFull.Offset = CAPTURE_BUFFER_SIZE-1;
        dxsBPNFull.EventNotifyHandle = ARE.SafeWaitHandle.DangerousGetHandle();
        dxsBPNHalf.EventNotifyHandle = ARE.SafeWaitHandle.DangerousGetHandle();


        dxsBpna = new Microsoft.DirectX.DirectSound.BufferPositionNotify[2];
        dxsBpna[0] = dxsBPNHalf;
        dxsBpna[1] = dxsBPNFull;

        Notify = new Microsoft.DirectX.DirectSound.Notify(dxsCapBuffer);
        Notify.SetNotificationPositions(dxsBpna);

    }

    public void StartRecording()
    {
        if (thrdCapturingThread != null)
            throw new Exception("Already Recording !");
        StopRec = false;
        thrdCapturingThread = new System.Threading.Thread(Record);
        thrdCapturingThread.Start();


    }
    private void Record()
    {
        DataReceivedHandler drh2 = DataReceivedHandle;


        dxsCapBuffer.Start(true);
        byte[] TempBaf = new byte[CAPTURE_BUFFER_SIZE / 2];
        int StartingOffset = 0;
        while (dxsCapBuffer.Capturing && !StopRec)
        {
            ARE.WaitOne(-1,false);

                StartingOffset %= CAPTURE_BUFFER_SIZE;
                TempBaf = (byte[])dxsCapBuffer.Read(StartingOffset, typeof(byte), Microsoft.DirectX.DirectSound.LockFlag.FromWriteCursor, CAPTURE_BUFFER_SIZE / 2);
                StartingOffset += TempBaf.Length;
                if (drh2 != null)
                    drh2(this, new BMSRecordingEventArgs(TempBaf, false));

        }
        dxsCapBuffer.Stop();
        if (drh2 != null)
            drh2(this, new BMSRecordingEventArgs(TempBaf, true));

        mreStillRunning.Set();


    }
    public void StopRecording()
    {
        StopRec = true;
        mreStillRunning.WaitOne(-1,false);
        thrdCapturingThread = null;
    }
}