如果我制造的噪音上升到 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
这段代码没有意义:
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>