使用AVAudioEngine进行电平测量

hor*_*oe7 18 macos objective-c avfoundation ios avaudioengine

我刚看了WWDC视频(AVAudioEngine实践中的会话502 )AVAudioEngine,我非常高兴能够建立一个基于这种技术的应用程序.

我无法弄清楚如何对麦克风输入或调音台输出进行电平监控.

有人可以帮忙吗?为了清楚起见,我所说的是监控当前输入信号(并在UI中显示),而不是通道/轨道的输入/输出音量设置.

我知道你可以做到这一点AVAudioRecorder,但是这不是AVAudioNode它的AVAudioEngine需要.

Far*_*our 17

尝试在主混音器上安装一个水龙头,然后通过设置帧长度使其更快,然后读取样本并获得平均值,如下所示:

进口框架在上面

#import <Accelerate/Accelerate.h>
Run Code Online (Sandbox Code Playgroud)

添加属性

@property float averagePowerForChannel0;
@property float averagePowerForChannel1;
Run Code Online (Sandbox Code Playgroud)

那么下面的相同>>

self.mainMixer = [self.engine mainMixerNode];
[self.mainMixer installTapOnBus:0 bufferSize:1024 format:[self.mainMixer outputFormatForBus:0] block:^(AVAudioPCMBuffer * _Nonnull buffer, AVAudioTime * _Nonnull when) {
    [buffer setFrameLength:1024];
    UInt32 inNumberFrames = buffer.frameLength;

    if(buffer.format.channelCount>0)
    {
        Float32* samples = (Float32*)buffer.floatChannelData[0];
        Float32 avgValue = 0;

        vDSP_meamgv((Float32*)samples, 1, &avgValue, inNumberFrames);
        self.averagePowerForChannel0 = (LEVEL_LOWPASS_TRIG*((avgValue==0)?-100:20.0*log10f(avgValue))) + ((1-LEVEL_LOWPASS_TRIG)*self.averagePowerForChannel0) ;
        self.averagePowerForChannel1 = self.averagePowerForChannel0;
    }

    if(buffer.format.channelCount>1)
    {
        Float32* samples = (Float32*)buffer.floatChannelData[1];
        Float32 avgValue = 0;

        vDSP_meamgv((Float32*)samples, 1, &avgValue, inNumberFrames);
        self.averagePowerForChannel1 = (LEVEL_LOWPASS_TRIG*((avgValue==0)?-100:20.0*log10f(avgValue))) + ((1-LEVEL_LOWPASS_TRIG)*self.averagePowerForChannel1) ;
    }
}];
Run Code Online (Sandbox Code Playgroud)

然后,获得您想要的目标值

NSLog(@"===test===%.2f", self.averagePowerForChannel1);
Run Code Online (Sandbox Code Playgroud)

要获取峰值,请使用vDSP_maxmgv而不是vDSP_meamgv.


LEVEL_LOWPASS_TRIG是一个介于0.0到1.0之间的简单过滤器,如果设置为0.0,您将过滤所有值而不获取任何数据.如果将其设置为1.0,则会产生太多噪音.基本上,值越高,您将获得更多的数据变化.对于大多数应用来说,似乎0.10到0.30之间的值是好的.

  • LEVEL_LOWPASS_TRIG使用的值(或范围)是多少? (7认同)
  • 要使用vDSP_meamgv,请执行"import Accelerate"以使用Apple的高性能数学框架. (5认同)

She*_*shy 11

等同的Swift 3代码'Farhad Malekpour '的回答

进口框架在上面

import Accelerate
Run Code Online (Sandbox Code Playgroud)

全球宣布

private var audioEngine: AVAudioEngine?
    private var averagePowerForChannel0: Float = 0
    private var averagePowerForChannel1: Float = 0
let LEVEL_LOWPASS_TRIG:Float32 = 0.30
Run Code Online (Sandbox Code Playgroud)

在您需要的地方使用以下代码

let inputNode = audioEngine!.inputNode//since i need microphone audio level i have used `inputNode` otherwise you have to use `mainMixerNode`
let recordingFormat: AVAudioFormat = inputNode!.outputFormat(forBus: 0)
 inputNode!.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) {[weak self] (buffer:AVAudioPCMBuffer, when:AVAudioTime) in
                guard let strongSelf = self else {
                    return
                }
                strongSelf.audioMetering(buffer: buffer)
}
Run Code Online (Sandbox Code Playgroud)

计算

private func audioMetering(buffer:AVAudioPCMBuffer) {
            buffer.frameLength = 1024
            let inNumberFrames:UInt = UInt(buffer.frameLength)
            if buffer.format.channelCount > 0 {
                let samples = (buffer.floatChannelData![0])
                var avgValue:Float32 = 0
                vDSP_meamgv(samples,1 , &avgValue, inNumberFrames)
                var v:Float = -100
                if avgValue != 0 {
                    v = 20.0 * log10f(avgValue)
                }
                self.averagePowerForChannel0 = (self.LEVEL_LOWPASS_TRIG*v) + ((1-self.LEVEL_LOWPASS_TRIG)*self.averagePowerForChannel0)
                self.averagePowerForChannel1 = self.averagePowerForChannel0
            }

            if buffer.format.channelCount > 1 {
                let samples = buffer.floatChannelData![1]
                var avgValue:Float32 = 0
                vDSP_meamgv(samples, 1, &avgValue, inNumberFrames)
                var v:Float = -100
                if avgValue != 0 {
                    v = 20.0 * log10f(avgValue)
                }
                self.averagePowerForChannel1 = (self.LEVEL_LOWPASS_TRIG*v) + ((1-self.LEVEL_LOWPASS_TRIG)*self.averagePowerForChannel1)
            }
    }
Run Code Online (Sandbox Code Playgroud)

  • 菜鸟问题 - 如果节点设置在通道 0 上,为什么有 2 个通道? (2认同)