直接从Webcam音频捕获回调



我正在从Webcam捕获音频数据,使用VFW和音频捕获回调,同时,在同一捕获回调的内部,直接采样数据到默认的MAPPER,使用wavewrite。

来自网络摄像头的信号质量为1通道/8位/11025个样本/秒。由于waveOpen带有FORMAT_QUERY标志,默认音频设备支持该声音格式。

waveWriteOut的返回值是NOERROR,但我能听到的与我的期望相差甚远。在房间里是安静的,它应该听起来像空虚的白噪音。

请听听YouTube的声音

它开始,一包一包大小约16K, WAVEHDR结构是ok的。然后逐渐变慢,并以系统未恢复错误退出。

这与什么相似?

下面是来自VFW的音频数据接收器代码,lpWHdr在视觉上是Ok的,甚至内部标志触发为2 =准备…似乎VFW和WaveAudio是互相创建的:)

public static void capAudioStreamCallback(UIntPtr hWnd, ref WAVE.WAVEHDR lpWHdr) {
    Say(String.Format(DateTime.Now.ToString("mm:ss:fff ") + "Received {0} of audio data", lpWHdr.dwBytesRecorded.ToString()));
    Application.DoEvents();
    WA.WAVEHDR_FLAGS flag = (WA.WAVEHDR_FLAGS) lpWHdr.dwFlags;
    if ((WA.WAVEHDR_FLAGS)lpWHdr.dwFlags != WA.WAVEHDR_FLAGS.WHDR_PREPARED)
                CheckWAError("waveOutPrepareHeader", WA.waveOutPrepareHeader(phwo, lpWHdr, (uint)Marshal.SizeOf(lpWHdr)));
    CheckWAError("waveOutWrite", WA.waveOutWrite(phwo, lpWHdr, (uint)Marshal.SizeOf(lpWHdr)));
    CheckWAError("waveOutUnprepareHeader", WA.waveOutUnprepareHeader(phwo, lpWHdr, (uint)Marshal.SizeOf(lpWHdr)));
    return;
}
    static void CheckWAError(string Func, WA.MMSYSERR err) {
        if (err == WA.MMSYSERR.MMSYSERR_BASE_NOERROR) { Say(Func + " WA Ok"); return; }
        IntPtr str = Marshal.AllocHGlobal(200);
        string s = "";
        WA.waveOutGetErrorText(err, str, 200);
        s = Marshal.PtrToStringAnsi(str);
        Marshal.FreeHGlobal(str);
        Say(Func + " err: " + s);
    }

我认为缓冲区没有溢出,因为您可以看到DateTime毫秒戳,它每1400毫秒滴答一次,采样率= 11025,缓冲区大小约为16500字节=看起来像Ok..

UPD:我只是将非托管缓冲区复制到托管缓冲区并查看其值。看起来像是锯齿,甚至是超负荷的鼻窦。0 4 0 3 0 32 109 213 255 251 255 243 241 97 0 7 0 21 10 5 0然后在相同的数字和相同的时期上下。不完全一样,差不多一样(+/-)另外,我可以用Windows内部的录音机记录摄像头的信号,我可以看到信号水平在我的声音上上下跳动,所以摄像头的麦克风也没问题。我想这可能是VFW输入音频信号馈线有问题。即使它接受WAVEFORMATEX并发送回WAVEHDR,它们都没问题…但是缓冲区数据填充了一些其他来源,而不是网络摄像头,虽然VFW说它必须来自网络摄像头,因为视频是从同一来源捕获的,它正在工作,我只是添加了一个额外的消息:SendMessage(camHwnd, wm_cap_set_callback_waveream, 0, audioCallback);我很确定,如果我使用waveIn而不是VFW,它会工作得很好。我过会儿再查。但为什么海外退伍军人管理局的运作方式与预期不同呢?

问题很简单——USB硬件故障。我需要拔掉USB相机插头,然后再插上。

但无论如何,我想分享我的知识。

1)我们应该使用异步机制来获取和发送音频数据包到播放端。在第一个缓冲区被回放之前,我们必须避免发送新的缓冲区进行回放。这种方法被称为"双"或甚至"三重"缓冲。使用VFW,您可以使用WM_CAP_GET_SEQUENCE_SETUP消息和CAPTUREPARAMS结构非常舒适地组织它。wnumaudiorerequested参数用于设置将循环使用多少不同的缓冲区,以将audiodata发送到audioCallback。默认设置为10,绰绰有余。

2)检查您的音频信号是否是有效信号的最佳方法是:在WAVESTREAM回调中,将接收到的音频数据缓冲区中的字节封送到托管的静态字节数组中。然后,在回调中,使用Console输出50-100个样本值。写入(array[i] + " "),看看你的声音的值是否在上下变化。考虑到零电平是在WAVEFORMATEX->wBitsPerSample值的中间,在我的情况下(8位/样本)的值是125 126 127 128 129。它被认为是沉默,没有信号,或者零噪音。一旦你确定你有正确的音频数据,现在你可以进一步实现你的目标。

3)记住,当你在麦克风模式下录音时,最好关闭本地输出波设备。您的目标是收集音频数据记录或通过网络发送。不要尝试在本地获取数据并进行waveOuit。有时你的扬声器的延迟值比麦克风数据的采样速度要快一些,你会因为缓冲而变得混乱,就像我的情况一样。然后我就遵循了这个原则——"录音是当你收集、保存或发送音频数据时,它应该在录音后或同时播放,但在端点PC上。

4)继续代码

相关内容

  • 没有找到相关文章

最新更新