Я пытаюсь вернуть текущий уровень децибел с микрофона iPhone. Я собрал по кусочкам этот код ниже и не могу понять, почему он не работает. Я ожидаю, что на данный момент он будет постоянно выводить текущую пиковую мощность на консоль.

Итак, мои вопросы / проблемы:

  1. Будет ли "peakPowerForchannel" возвращать текущий уровень или максимум для всего аудиосеанса?
  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)
                }
            }
        }
    }
}
0
Epiaddikt 21 Фев 2021 в 22:37

1 ответ

Лучший ответ

Что касается пиковой мощности, вот что говорят документы:

Текущая пиковая мощность аудиоканала.

(в основном текущее окно)

Вам нужно на самом деле вызвать 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

С этими изменениями ваш код работает на меня.

1
jnpdx 21 Фев 2021 в 19:43