从C代码获取ALSA峰值

我正在尝试使用ALSA和C检索当前音频峰值。我希望将此值设置为介于0.0和1.0(或者可能为0和100)之间的标量。 在Windows上我使用IAudioMeterInformation ,它允许我构建一个非常基本的VU表。

编辑:我指的是仅检测扬声器输出,而不是麦克风。

ALSA没有当前的音频峰值。

在您编写或阅读样本时,循环遍历样本以获得最大值。

AFAIK没有办法查询ALSA中的当前音频峰值。


但是,如果你真的需要这个,实现它的一种方法如下。

  1. 设置虚拟环回设备
    – 创建新的虚拟捕获设备,只需播放真实播放设备的输出。

  2. 记录一个简短的样本
    – 从环回设备中捕获几毫秒的瞬时音频样本。

  3. 分析样本的统计数据
    – 计算样本中瞬时音频的峰值音量。

第1步涉及
– 构建和插入snd-aloop Linux内核模块
– 设置.asoundrc配置文件
这里提供了对整个过程的详细描述。

在覆盖如上所示的default设备链接之后,可以通过使用arecordsox的组合简单地实现步骤23 ,如下所示:

 $ arecord -Ddefault -d1 -twav -r48000 > rec.wav; \ sox -V -t wav -r48000 rec.wav -n stat 2>&1 | \ grep "Maximum amplitude" | awk '{print $3}' 

上面的片段
– 记录默认输入设备1秒钟
– 使用sox进行分析
– 解析其输出以获得最大振幅。

要使用C代码计算PCM-wav文件中音频样本的最大幅度,您可以研究sox的源代码 。 此处此处也可以使用C代码片段来执行相同的操作。

使用snd_pcm_readi似乎有效,请参阅下面的示例:

 static float GetLevel (void) { float result = 0.0f; snd_pcm_t* waveform; // Open and initialize a waveform if (snd_pcm_open (&waveform, "default", SND_PCM_STREAM_CAPTURE, 0) != 0) return 0; // Set the hardware parameters if (!snd_pcm_set_params (waveform, SND_PCM_FORMAT_S16_LE, SND_PCM_ACCESS_RW_INTERLEAVED, 2, 48000, 1, 0)) { // Read current samples short buffer[256]; if (snd_pcm_readi (waveform, buffer, 128) == 128) { // Compute the maximum peak value for (int i = 0; i < 256; ++i) { // Substitute better algorithm here if needed float s = buffer[i] / 32768.0f; if (s < 0) s *= -1; if (result < s) result = s; } } } snd_pcm_close (waveform); return result; } 

不过,我仍然持怀疑态度,这是一个很好的解决方案。