如何使用 C WinAPI 获取当前麦克风输入电平?
Posted
技术标签:
【中文标题】如何使用 C WinAPI 获取当前麦克风输入电平?【英文标题】:How can I get current microphone input level with C WinAPI? 【发布时间】:2019-11-02 04:12:09 【问题描述】:使用 Windows API,我想实现如下内容:
即获取当前麦克风输入电平。
我不允许使用外部音频库,但我可以使用 Windows 库。于是尝试使用waveIn
函数,但不知道如何实时处理音频输入数据。
这是我目前使用的方法:
-
记录 100 毫秒
从记录的数据缓冲区中选择最大值
永远重复
但我认为这太老套了,不推荐使用。我怎样才能正确地做到这一点?
【问题讨论】:
检查What is the smallest audio buffer needed to produce Tone sound without distotions with WaveOUT API和A full-duplex audio player in C# using the waveIn/waveOut APIs怎么样 【参考方案1】:已经为一个非常过时但众所周知的 A/V 会议应用程序构建了一个调整向导,您描述的内容与我所做的几乎相同。
一些注意事项:
通过 waveInAddBuffer 将这 100 毫秒缓冲区中的 5 到 10 个排队到音频设备中。 IIRC,当 waveIn 队列变空时,会发生奇怪的事情。然后当 waveInProc 回调发生时,按照您的描述在已完成的缓冲区中搜索具有最高绝对值的样本。然后将其绘制到您的可视化上。将完成的缓冲区重新排队。
将样本值如下线性映射到您的可视化上似乎很明显。
例如,绘制一个 16 位样本
// convert sample magnitude from 0..32768 to 0..N
length = (sample * N) / 32768;
DrawLine(length);
但是当你对着麦克风说话时,这种可视化看起来不会“活跃”或“充满活力”。
但更好的方法是为那些能量较低的样本提供更大的强度。简单的方法是沿着 μ-law 曲线重新绘制(或使用表格查找)。
length = (sample * N) / 32768;
length = log(1+length)/log(N);
length = max(length,N)
DrawLine(length);
您可以将上述方法调整为任何看起来不错的方法。
【讨论】:
【参考方案2】:您可以依赖 Windows 中的值,而不是自己计算这些值。这实际上是 Windows 设置屏幕截图中显示的值。
请参阅以下IAudioMeterInformation
接口示例:https://docs.microsoft.com/en-us/windows/win32/coreaudio/peak-meters。
它是为播放而设计的,但您也可以将其用于捕获。
一些注意事项,如果您为麦克风打开IAudioMeterInformation
,但没有应用程序打开来自该麦克风的流,则级别将为0。
这意味着当您想要显示麦克风峰值表时,您需要打开麦克风流,就像您已经做过的那样。
另请阅读有关IAudioMeterInformation
的文档,它可能不是您需要的,因为它是峰值。这取决于你想用它做什么。
【讨论】:
以上是关于如何使用 C WinAPI 获取当前麦克风输入电平?的主要内容,如果未能解决你的问题,请参考以下文章
使用 Core Audio 从 PCM 原始数据中获取电平值