如何从 iPhone 麦克风 return 当前分贝水平

How to return current decibel level from iPhone mic

我正在尝试 return 来自 iPhone 麦克风的当前分贝级别。我在下面拼凑了这段代码,但无法弄清楚为什么它不起作用。我的期望是,现在它会持续将当前峰值功率打印到控制台。

所以我的 questions/issues 是:

  1. “peakPowerForchannel”return 是当前电平还是整个音频会话的最大值?
  2. 看来我的按钮从来没有转到停止录制模式,每次按下时都只是打印“录制开始”。
  3. 我不明白为什么分贝级别根本不打印。

感谢您的帮助!

import SwiftUI
import AVFoundation
import Foundation
import Combine

class AudioRecorder: ObservableObject {
    
    let objectWillChange = PassthroughSubject<AudioRecorder, Never>()
    var audioRecorder: AVAudioRecorder!
    var decibelLevelTimer = Timer()
    
    var recording = false {
        didSet {
            objectWillChange.send(self)
        }
        
    }
    
    func startRecording() {
            let recordingSession = AVAudioSession.sharedInstance()
        do {
                    try recordingSession.setCategory(.playAndRecord, mode: .default)
                    try recordingSession.setActive(true)
                } catch {
                    print("Failed to set up recording session")
                }
        let documentPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
        let audioFilename = documentPath.appendingPathComponent("\(Date().toString(dateFormat: "dd-MM-YY_'at'_HH:mm:ss")).m4a")
        let settings = [
                    AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
                    AVSampleRateKey: 12000,
                    AVNumberOfChannelsKey: 1,
                    AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
                ]
        do {
                    audioRecorder = try AVAudioRecorder(url: audioFilename, settings: settings)
                    audioRecorder.record()

                    recording = true
                    audioRecorder.isMeteringEnabled = true
            self.decibelLevelTimer = Timer.scheduledTimer(withTimeInterval: 0.02, repeats: true) { timer in
                self.audioRecorder.updateMeters()
                print(self.audioRecorder.peakPower(forChannel: 0))
            }
                } catch {
                    print("Could not start recording")
                }
        }
    
}


extension Date
{
    func toString( dateFormat format  : String ) -> String
    {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = format
        return dateFormatter.string(from: self)
    }
}


struct ContentView: View {
    
    @ObservedObject var audioRecorder: AudioRecorder
    
    var body: some View {
        VStack {
            if audioRecorder.recording == false {
                Button(action: {print("Start recording")}) {
                    Image(systemName: "circle.fill")
                        .resizable()
                        .aspectRatio(contentMode: .fill)
                        .frame(width: 100, height: 100)
                        .clipped()
                        .foregroundColor(.red)
                        .padding(.bottom, 40)
                }
            } else {
                Button(action: {print("Stop recording)")}) {
                    Image(systemName: "stop.fill")
                        .resizable()
                        .aspectRatio(contentMode: .fill)
                        .frame(width: 100, height: 100)
                        .clipped()
                        .foregroundColor(.red)
                        .padding(.bottom, 40)
                }
            }
        }
    }
}

关于峰值功率,文档是这样说的:

The audio channel’s current peak power.

(基本上就是现在的window)

您需要在 Button 的操作中实际调用 startRecording()(现在,您所做的只是打印):

Button(action: {
  audioRecorder.startRecording()
}) {

同样,您需要为另一个按钮创建并调用 stopRecording 操作:

func stopRecording() {
        audioRecorder.stop()
        recording = false
        decibelLevelTimer.invalidate()
}
//....
Button(action: {
  audioRecorder.stopRecording()
}) {

此外,如果您仍然没有输入,请确保您的麦克风权限设置正确:https://developer.apple.com/documentation/avfoundation/cameras_and_media_capture/requesting_authorization_for_media_capture_on_macos

经过这些更改,您的代码对我有用。