Чтение без потерь с микрофона - PullRequest
1 голос
/ 13 июля 2011

Я использую NAudio (но это относится и к чтению напрямую) для захвата данных с микрофона. Кажется, что если мое приложение занято, оно пропускает / пропускает некоторые входные данные с микрофона.

Я установил поток чтения на верхний приоритет, но одновременно выполняю тяжелые вычисления в нескольких других потоках.

Есть ли способ прочитать данные без потерь?
(Или это без потерь, и моя ошибка в другом месте?)

1 Ответ

0 голосов
/ 13 июля 2011

Когда я делал похожее приложение и у меня была похожая проблема, оказалось, что мне нужен буфер, который может хранить как минимум 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;
    }
}
...