如何使用 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 获取当前麦克风输入电平?的主要内容,如果未能解决你的问题,请参考以下文章

获取麦克风输入电平 Nadio

使用 AVAudioEngine 进行电平测量

使用 Core Audio 从 PCM 原始数据中获取电平值

音频:如何设置默认麦克风的电平?

如何在不录制的情况下在 Android 上对麦克风进行采样以获得实时幅度/电平?

从剪贴板获取数据并重新设置 - WINAPI,C [重复]