我正在使用NAudio(但它适用于直接读取)来捕获麦克风波数据。看来,如果我的应用程序很忙,它将丢弃/跳过麦克风中的一些输入数据。

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

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

最佳答案

当我制作一个类似的应用程序并遇到类似的问题时,事实证明我需要一个缓冲区,该缓冲区可以保存至少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;
    }
}

10-06 09:01