我从网络摄像头捕获audiodata,使用VFW和音频捕获回调,同时,在同一捕获回调体内,使用waveOutWrite将采样数据定向到默认MAPPER。
网络摄像头的信号质量为1通道/ 8位/ 11025采样/秒。 默认音频设备支持声音格式,这要归功于带 FORMAT_QUERY 标志的 waveOpen 。
waveWriteOut 的回归是 NOERROR ,但我能听到的远非我的期望。在房间里很安静,听起来应该像空虚的白噪声。
请听声音YouTube rec
它启动,按包装大小约16K,WAVEHDR结构正常。 然后它逐渐减慢并退出系统未恢复的错误。
那是什么类似的?
下面是来自VFW的音频dta接收器代码,lpWHdr在视觉上是好的,甚至内部标志触发到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字节=看起来好像..
UPD:我刚刚将非托管缓冲区复制到托管中并查看了其值。看起来像锯齿或甚至超负荷的鼻窦。 0 4 0 3 0 32 109 213 255 251 255 243 241 97 0 7 0 2 1 1 0 5 0然后再次上下相同的数字和相同的周期。 不完全是,差不多(+/-)。 此外,我可以使用内部Windows录音机录制来自该摄像头的信号,我可以看到信号电平在我的声音上下跳跃,所以网络摄像头的麦克风也可以。 我想VFW输入音频信号馈线可能有问题。 即使它接受了WAVEFORMATEX并发送回WAVEHDR,它们都可以......但是缓冲区数据填充了一些其他来源,而不是网络摄像头,尽管VFW说必须来自网络摄像头,因为视频正在从相同的来源,它的工作,我只是添加了一个extramessage: SendMessage(camHwnd,WM_CAP_SET_CALLBACK_WAVESTREAM,0,audioCallback); 我非常确定如果我使用waveIn而不是VFW,它会正常工作.. 我稍后会检查.. 但为什么VFW的工作方式并不像它应该的那样?
答案 0 :(得分:0)
问题非常简单 - 那就是USB硬件故障。我需要拔掉USB Camera并重新插上电源。
但无论如何,我想分享我对此的了解。
1) 我们应该使用Asynchronous mechanizm来获取和发送音频数据包到播放端。 在第一个缓冲区播放之前,我们必须避免发送新缓冲区进行播放。该方法被称为 - “双重”或甚至“三重”缓冲。 使用VFW,您可以使用WM_CAP_GET_SEQUENCE_SETUP消息和CAPTUREPARAMS结构轻松组织它。 wNumAudioRequested参数用于设置循环使用多少个不同的缓冲区,以将audiodata发送到audioCallback。 它默认设置为10,绰绰有余。
2) 检查您的音频信号是否为有效信号的最佳方法是:在WAVESTREAM回调中,将接收缓冲区中的字节封装为audiodata到托管静态字节数组。 然后,在回调内部,使用Console.Write(array [i] +“”)输出50-100个样本值,并查看值是否正在改变您的语音。 考虑到零水平位于WAVEFORMATEX-> wBitsPerSample值的中间,在我的情况下(8位/样本),值为125 126 127 128 129.它被认为是静音,没有信号,或者零 - 噪声。 一旦你确定你有正确的audiodata,现在你可以进一步实现你的目标。
3) 请记住,当您从麦克风模式录制时,本地输出波设备最好关闭。您的目标是收集音频数据以通过网络进行录制或发送。不要尝试获取数据并在本地waveOuit它们。 有时候你的扬声器的延迟值比采样麦克风数据的速度要高一些,而且随着我的使用,你会对缓冲区产生混乱。 然后我就遵循了这样的原则 - “录制是指您收集,保存或发送audiodata时,应该在录制后或同时播放,但在终端PC上播放。
4) 继续使用代码