Swift 4 AVFoundation - 同时录制多个音频源

时间:2017-10-15 16:14:16

标签: ios swift audio avfoundation audio-recording

我目前正在尝试同时监控iPhone内置麦克风的音频输入。

在下面提到的代码中,我正在用这行代码选择我想要监听的麦克风(米,底部,前部或后部麦克风):

try recordingSession.setInputDataSource(recordingSession.inputDataSources?[2])

不幸的是,我似乎只能为我的音频会话设置一个输入数据源。

可能有办法为每个录制通道设置输入数据源吗?

我已经尝试过探索其他解决方案,例如AVAudioEngine,但由于没有很多关于这个主题的Swift资源,因此分析哪种方式让我变得非常复杂。

import UIKit
import AVFoundation

        class ViewController: UIViewController, AVAudioRecorderDelegate, AVAudioPlayerDelegate {

            @IBOutlet var recordButton: UIButton!
            var recordingSession: AVAudioSession!
            var audioPlayer: AVAudioPlayer!
            var audioRecorder: AVAudioRecorder!

            var timer: Timer!

            override func viewDidLoad() {
                recordingSession = AVAudioSession.sharedInstance()

                do {
                    try recordingSession.setCategory(AVAudioSessionCategoryMultiRoute)
                    //try recordingSession.setMode(AVAudioSessionModeMeasurement)
                    try recordingSession.setActive(true)


                    try recordingSession.setInputDataSource(recordingSession.inputDataSources?[2])
                    try recordingSession.overrideOutputAudioPort(AVAudioSessionPortOverride.speaker)
                    recordingSession.requestRecordPermission() { [unowned self] allowed in
                        DispatchQueue.main.async {
                            if allowed {

                            } else {
                                // failed to record!
                            }
                        }
                    }
                } catch {
                    print("NOT ALLOWED")
                    // failed to record!
                }

            }

            @objc func updateMeters(){
                audioRecorder.updateMeters()


                print("CHANNEL 0 PEAK : \(audioRecorder.peakPower(forChannel: 0))")
                print("CHANNEL 1 PEAK : \(audioRecorder.peakPower(forChannel: 1))")
                print(audioRecorder.averagePower(forChannel: 0))
                print(audioRecorder.currentTime)
            }


            func startRecording() {
                let audioFilename = getDocumentsDirectory().appendingPathComponent("recording.m4a")

                let settings = [
                    AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
                    AVSampleRateKey: 12000,
                    AVNumberOfChannelsKey: 2,
                    AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
                ]

                do {

                    audioRecorder = try AVAudioRecorder(url: audioFilename, settings: settings)
                    audioRecorder.delegate = self
                    audioRecorder.isMeteringEnabled = true
                    audioRecorder.record()

                    recordButton.setTitle("Tap to Stop", for: .normal)

                    timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(updateMeters), userInfo: nil, repeats: true)
                } catch {
                    finishRecording(success: false)
                }
            }

            func getDocumentsDirectory() -> URL {
                let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
                let documentsDirectory = paths[0]
                return documentsDirectory
            }

            func finishRecording(success: Bool) {
                timer.invalidate()
                audioRecorder.stop()
                audioRecorder = nil

                if success {
                    recordButton.setTitle("Tap to Re-record", for: .normal)
                } else {
                    recordButton.setTitle("Tap to Record", for: .normal)
                    // recording failed :(
                }
            }

            @IBAction func recordTapped() {
                if audioRecorder == nil {
                    startRecording()
                } else {
                    finishRecording(success: true)
                }
            }

            func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) {
                if !flag {
                    finishRecording(success: false)
                }
            }

            @IBAction func play(_ sender: UIButton) {
                let fileURL = getDocumentsDirectory().appendingPathComponent("recording.m4a")
                    self.audioPlayer = try! AVAudioPlayer(contentsOf: fileURL)
                    self.audioPlayer.prepareToPlay()
                    self.audioPlayer.delegate = self
                    self.audioPlayer.play()
            }
        }

1 个答案:

答案 0 :(得分:0)

正如 smakusdod 在此reddit thread中提到的那样:

  

iphone有3个麦克风...根据哪个相机使用像阵列一样   是活跃的,或者如果你在扬声器模式等,如果苹果想要,   他们可以将这些话筒用于立体声录音。例如,使用   用于右声道的底部话筒和用于左声道的顶部话筒。目前   他们不允许这样做,而只是暴露单声道。

因为苹果仅提供单声道通道意味着iOS开发人员无法同时访问每个内置麦克风。

如果您认为应该可行,Apple会让您有机会让他们知道: https://www.apple.com/feedback/iphone.html