我几乎没有信号处理方面的知识,目前我正在尝试在Swift中实现一个函数,当sound pressure level增加时(例如,当人们尖叫时)触发一个事件。

我正在使用这样的回调进入AVAudioEngine的输入节点:

let recordingFormat = inputNode.outputFormat(forBus: 0)
inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat){
 (buffer : AVAudioPCMBuffer?, when : AVAudioTime) in
    let arraySize = Int(buffer.frameLength)
    let samples = Array(UnsafeBufferPointer(start: buffer.floatChannelData![0], count:arraySize))

   //do something with samples
    let volume = 20 * log10(floatArray.reduce(0){ $0 + $1} / Float(arraySize))
    if(!volume.isNaN){
       print("this is the current volume: \(volume)")
    }
}

将其转换为浮点数组后,我尝试通过计算平均值来大致估算声压级。

但这给我带来了很大的值(value)波动,即使iPad只是坐在一个很宽敞的房间里也是如此:
this is the current volume: -123.971
this is the current volume: -119.698
this is the current volume: -147.053
this is the current volume: -119.749
this is the current volume: -118.815
this is the current volume: -123.26
this is the current volume: -118.953
this is the current volume: -117.273
this is the current volume: -116.869
this is the current volume: -110.633
this is the current volume: -130.988
this is the current volume: -119.475
this is the current volume: -116.422
this is the current volume: -158.268
this is the current volume: -118.933

如果我在麦克风附近拍手,此值的确会显着增加。

因此,我可以做一些类似的事情,首先在准备阶段计算这些数量的平均值,然后比较在事件触发阶段差异是否显着增加:
 if(!volume.isNaN){
    if(isInThePreparingPhase){
        print("this is the current volume: \(volume)")
        volumeSum += volume
        volumeCount += 1
     }else if(isInTheEventTriggeringPhase){
         if(volume > meanVolume){
             //triggers an event
         }
      }
 }

在从准备阶段到触发事件阶段的过渡期间计算averageVolume:meanVolume = volumeSum / Float(volumeCount)
....

但是,如果我在麦克风之外播放响亮的音乐,似乎并没有明显增加。而且在极少数情况下,即使环境的音量没有明显增加(人耳可以听到),volume也比meanVolume大。

那么从AVAudioPCMBuffer提取声压级的正确方法是什么?

维基百科给出了这样的公式

ios - 从AVAudioPCMBuffer提取声压级时-LMLPHP

其中p是均方根声压,p0是引用声压。

但是我不知道AVAudioPCMBuffer.floatChannelData中的float值代表什么。 The apple page只说



我应该如何与他们合作?

最佳答案

我认为第一步是获取声音的envelope。您可以使用简单的平均值来计算包络,但是您需要添加一个校正步骤(通常意味着使用abs()或square()使所有样本为正)

更常见的是,使用简单的iir过滤器代替平均,并使用不同的常数进行攻击和衰减,这是lab。请注意,这些常数取决于采样频率,您可以使用以下公式来计算常数:

1 - exp(-timePerSample*2/smoothingTime)

第2步

有了包络后,您可以使用附加的滤波器对其进行平滑处理,然后比较两个包络以找到比基础电平响亮的声音,这是一个更大的complete lab

请注意,检测音频“事件”可能非常棘手,并且难以预测,请确保您有很多防抖帮助!

关于ios - 从AVAudioPCMBuffer提取声压级时,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40031738/

10-10 02:41