C# DirectSound - 捕获缓冲区不连续

发布于 2024-08-08 19:23:10 字数 3417 浏览 8 评论 0 原文

我正在尝试使用 DirectSound 从线路输入捕获原始数据。

我的问题是,从一个缓冲区到另一个缓冲区的数据不一致,例如,如果我捕获正弦,我会看到从上一个缓冲区和新缓冲区之间的跳转。为了检测到这一点,我使用图形小部件绘制最后一个缓冲区的前 500 个元素以及新缓冲区中的 500 个元素:

snapshot >>
<a href=http://img199.imageshack.us/img199/206/demodsnap.jpg

我以这种方式初始化了我的缓冲区:

   format = new WaveFormat {
            SamplesPerSecond = 44100,
            BitsPerSample = (short)bitpersample,           
            Channels = (short)channels,
            FormatTag = WaveFormatTag.Pcm
        };

        format.BlockAlign = (short)(format.Channels * (format.BitsPerSample / 8));
        format.AverageBytesPerSecond = format.SamplesPerSecond * format.BlockAlign;

        _dwNotifySize = Math.Max(4096, format.AverageBytesPerSecond / 8);
        _dwNotifySize -= _dwNotifySize % format.BlockAlign;
        _dwCaptureBufferSize = NUM_BUFFERS * _dwNotifySize; // my capture buffer
        _dwOutputBufferSize = NUM_BUFFERS * _dwNotifySize / channels; // my output buffer

我将通知设置为缓冲区一半处的通知,以及缓冲区末尾处的通知:

     _resetEvent = new AutoResetEvent(false);
        _notify = new Notify(_dwCapBuffer);

        bpn1 = new BufferPositionNotify();
        bpn1.Offset = ((_dwCapBuffer.Caps.BufferBytes) / 2) - 1;
        bpn1.EventNotifyHandle = _resetEvent.SafeWaitHandle.DangerousGetHandle();
        bpn2 = new BufferPositionNotify();
        bpn2.Offset = (_dwCapBuffer.Caps.BufferBytes) - 1;
        bpn2.EventNotifyHandle = _resetEvent.SafeWaitHandle.DangerousGetHandle();

        _notify.SetNotificationPositions(new BufferPositionNotify[] { bpn1, bpn2 });

        observer.updateSamplerStatus("Events listener initialization complete!\r\n");

以下是我处理事件的方式。

/* Process thread */
private void eventReceived()
        {
            int offset = 0;
            _dwCaptureThread = new Thread((ThreadStart)delegate
            {

                _dwCapBuffer.Start(true);

                while (isReady)
                {
                    _resetEvent.WaitOne(); // Notification received
                    /* Read the captured buffer */
                    Array read = _dwCapBuffer.Read(offset, typeof(short), LockFlag.None, _dwOutputBufferSize - 1);

                    observer.updateTextPacket("Buffer: " + count.ToString() + " # " + read.GetValue(read.Length - 1).ToString() + " # " + read.GetValue(0).ToString() + "\r\n");
                    /* Print last/new part of the buffer to the debug graph */
                    short[] graphData = new short[1001];
                    Array.Copy(read, graphData, 1000);

                    db.SetBufferDebug(graphData, 500);
                    observer.updateGraph(db.getBufferDebug());



                    offset = (offset + _dwOutputBufferSize) % _dwCaptureBufferSize;

                    /* Out buffer not used */
                    /*_dwDevBuffer.Write(0, read, LockFlag.EntireBuffer);

                    _dwDevBuffer.SetCurrentPosition(0);
                    _dwDevBuffer.Play(0, BufferPlayFlags.Default);*/

                }

                _dwCapBuffer.Stop();
            });
            _dwCaptureThread.Start();

        }

有什么建议吗?我确信我在事件处理中的某个地方失败了,但我找不到哪里。

我使用 WaveIn API 开发了相同的应用程序,并且运行良好。

多谢...

I'm trying to capture raw data from my line-in using DirectSound.

My problem is that, from a buffer to another the data are just inconsistent, if for example I capture a sine I see a jump from my last buffer and the new one. To detected this I use a graph widget to draw the first 500 elements of the last buffer and the 500 elements from the new one:

snapshot
http://img199.imageshack.us/img199/206/demodsnap.jpg

I initialized my buffer this way:

   format = new WaveFormat {
            SamplesPerSecond = 44100,
            BitsPerSample = (short)bitpersample,           
            Channels = (short)channels,
            FormatTag = WaveFormatTag.Pcm
        };

        format.BlockAlign = (short)(format.Channels * (format.BitsPerSample / 8));
        format.AverageBytesPerSecond = format.SamplesPerSecond * format.BlockAlign;

        _dwNotifySize = Math.Max(4096, format.AverageBytesPerSecond / 8);
        _dwNotifySize -= _dwNotifySize % format.BlockAlign;
        _dwCaptureBufferSize = NUM_BUFFERS * _dwNotifySize; // my capture buffer
        _dwOutputBufferSize = NUM_BUFFERS * _dwNotifySize / channels; // my output buffer

I set my notifications one at half the buffer and one at the end:

     _resetEvent = new AutoResetEvent(false);
        _notify = new Notify(_dwCapBuffer);

        bpn1 = new BufferPositionNotify();
        bpn1.Offset = ((_dwCapBuffer.Caps.BufferBytes) / 2) - 1;
        bpn1.EventNotifyHandle = _resetEvent.SafeWaitHandle.DangerousGetHandle();
        bpn2 = new BufferPositionNotify();
        bpn2.Offset = (_dwCapBuffer.Caps.BufferBytes) - 1;
        bpn2.EventNotifyHandle = _resetEvent.SafeWaitHandle.DangerousGetHandle();

        _notify.SetNotificationPositions(new BufferPositionNotify[] { bpn1, bpn2 });

        observer.updateSamplerStatus("Events listener initialization complete!\r\n");

And here is how I process the events.

/* Process thread */
private void eventReceived()
        {
            int offset = 0;
            _dwCaptureThread = new Thread((ThreadStart)delegate
            {

                _dwCapBuffer.Start(true);

                while (isReady)
                {
                    _resetEvent.WaitOne(); // Notification received
                    /* Read the captured buffer */
                    Array read = _dwCapBuffer.Read(offset, typeof(short), LockFlag.None, _dwOutputBufferSize - 1);

                    observer.updateTextPacket("Buffer: " + count.ToString() + " # " + read.GetValue(read.Length - 1).ToString() + " # " + read.GetValue(0).ToString() + "\r\n");
                    /* Print last/new part of the buffer to the debug graph */
                    short[] graphData = new short[1001];
                    Array.Copy(read, graphData, 1000);

                    db.SetBufferDebug(graphData, 500);
                    observer.updateGraph(db.getBufferDebug());



                    offset = (offset + _dwOutputBufferSize) % _dwCaptureBufferSize;

                    /* Out buffer not used */
                    /*_dwDevBuffer.Write(0, read, LockFlag.EntireBuffer);

                    _dwDevBuffer.SetCurrentPosition(0);
                    _dwDevBuffer.Play(0, BufferPlayFlags.Default);*/

                }

                _dwCapBuffer.Stop();
            });
            _dwCaptureThread.Start();

        }

Any advise? I'm sure I'm failing somewhere in the event processing, but I cant find where.

I had developed the same application using the WaveIn API and it worked well.

Thanks a lot...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

送君千里 2024-08-15 19:23:10

仔细看看 _dwCapBuffer.Read 的最后一个参数
它的类型是,params int[]ranks
我有同样的问题,刚刚发现这个问题。我希望这对你和我都有帮助。

Look very closely at the last parameter of _dwCapBuffer.Read
its type is , params int[] ranks
I have the same problem and just found out about this. I hope this helps both you and me.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文