分贝测量值不正确 AVFoundation

问题描述 投票:0回答:1

如果我制造的噪音上升到 0.02 - 0.03,我在静音时得到 0.00 时输出错误的分贝值。我做错了什么,因为我用另一个静音应用程序进行了测量,我得到大约 20 分贝,噪音大约 50 分贝。 我希望你能告诉我需要修复的地方。

struct NoiseMeterView: View {

    let audioRecorder: AVAudioRecorder
    @State var timer: Timer?
    @State var decibels: Float = 0

    init() {
        let audioFileURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent("audio.m4a")
        let settings = [
            AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
            AVSampleRateKey: 16000,
            AVNumberOfChannelsKey: 1,
            AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
        ]

        do {
            audioRecorder = try AVAudioRecorder(url: audioFileURL, settings: settings)
        } catch let error {
            fatalError("Error creating audio recorder: \(error.localizedDescription)")
        }
    }

    var body: some View {
        VStack {
            Text("Noise Level: \(String(format: "%.2f", decibels)) dB")
                .font(.title)
                .padding()
            Button(action: {
                if timer == nil {
                    startMetering()
                } else {
                    stopMetering()
                }
            }) {
                Text(timer == nil ? "Start" : "Stop")
                    .padding()
                    .background(Color.blue)
                    .foregroundColor(.white)
                    .cornerRadius(10)
            }
        }
    }

    func startMetering() {
        do {
            try AVAudioSession.sharedInstance().setCategory(.record)
            try AVAudioSession.sharedInstance().setActive(true)
        } catch let error {
            print("Error setting up audio session: \(error.localizedDescription)")
            return
        }
        audioRecorder.isMeteringEnabled = true
        audioRecorder.record()
        timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { _ in
                audioRecorder.updateMeters()
                var decibels = audioRecorder.peakPower(forChannel: 0)
                decibels = min(max(decibels, -120), 0)
                self.decibels = pow(10, (decibels / 20))
            }
    }

    func stopMetering() {
        timer?.invalidate()
        timer = nil
        audioRecorder.stop()
    }
}

需要使范围从0到120 dB

swift xcode swiftui avfoundation
1个回答
1
投票

这段代码没有意义:

var decibels = audioRecorder.peakPower(forChannel: 0)
decibels = min(max(decibels, -120), 0)
self.decibels = pow(10, (decibels / 20)) 

这是将分贝转换为振幅分数(即将对数值转换为线性值),这与您建议的相反。根据您的描述,您可能指的代码是:

var decibels = audioRecorder.peakPower(forChannel: 0)
decibels = min(max(decibels, -120), 0)
self.decibels = decibels + 120  // <<---

这将使范围 [-160,-120] 处于 0dB,0 峰值处于 120dB,如您所说。 dB 始终是比率,因此您可以改变它们并声明任何您想要为零的值。 “0dB”没有通用的定义。有很多定义取决于你在做什么。

peakPower
的输出单位是dBFS,也就是说0dB是“麦克风可以输出的最大信号”,-160dB是“麦克风可以输出的最小信号”。这些不一定对应于您可能正在寻找的特定 SPL(声压级)测量值。不同的麦克风可以有不同的灵敏度和范围。我不知道有任何针对 iPhone 麦克风的校准记录,因此您可能需要自己使用声压计进行校准。 (当我构建这些东西时,它总是用于定制硬件;我从来不需要它用于内置麦克风。)

您描述的值(安静的房间为 20dB,正常对话为 50dB)与 dBSPL 标度相匹配,这很常见。您的“其他应用程序”可能正在使用A-weighting,这是一种更准确的测量声音如何影响人类听力的方法,但它可能只是使用 dBSPL,因为它更容易计算。您只需要获得一个 SPL 表并计算出要添加的偏移量。 ResearchKit 包括以下硬编码偏移量,但我还没有完全弄清楚它们在代码中的使用方式,我有点惊讶所有 iPhone 麦克风都具有相同的灵敏度(但这是可能的):

<dict>
    <key>iPhone</key>
    <real>-23.3</real>
    <key>iPod touch</key>
    <real>-23.3</real>
    <key>iPad</key>
    <real>-29.3</real>
</dict>
© www.soinside.com 2019 - 2024. All rights reserved.