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

标签 ios swift audio avfoundation audio-recording

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

在下面提到的代码中,我使用以下代码行选择我想要监控/计量的麦克风(底部、正面或背面麦克风):

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

不幸的是,我似乎只能为我的 Audio Session 设置一个输入数据源。

也许有办法为每个记录 channel 设置输入数据源?

我也尝试过探索其他解决方案,例如 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()
            }
        }

最佳答案

正如本文中提到的reddit thread作者:smakusdod:

The iphone has 3 mics... used like an array depending on which camera is active, or if you are in speakerphone mode etc. if apple wanted to, they could purpose these mics for stereo recording. E.g., using the bottom mic for right channel, and top mic for left channel. Currently they do not allow this, and instead only expose a mono channel.

因为苹果只提供单声道 channel ,这意味着 iOS 开发者不可能同时为我们访问每个内部麦克风。

如果您认为这是可能的,Apple 会给您机会让他们知道: https://www.apple.com/feedback/iphone.html

关于ios - Swift 4 AVFoundation - 同时录制多个音频源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46757156/

相关文章:

java - 为Android直播音频流

html - href mailto 和 iOS safari

ios - 在表格中快速单击按钮时删除并插入新按钮

arrays - 如何在 Swift 中比较两个协议(protocol)数组是否相等?

c# - 如何从头开始创建声音 C#

matlab - 参数均衡器的幅度响应

iphone - nsdate 转换的问题

ios - iPad 2/Retina iPad,应用程序如何识别它在哪个设备上运行?

ios - 基于 UILabel 的动态 UICollectionView header 大小

swift - 如何在进入后台或恢复到前台时重定向到主屏幕