录制时通过 Swift OSX 音频

Posted

技术标签:

【中文标题】录制时通过 Swift OSX 音频【英文标题】:Swift OSX Audio pass thru while recording 【发布时间】:2017-08-17 15:47:02 【问题描述】:

我在 Xcode 9 - swift 4 - macOS 而非 ios 中编程

我在下面有一个基本的录音音频设置,用于用耳机和麦克风录制歌手。我希望它像 Logic X 一样做出反应。

在 Logic X 中,您将要录制的音轨放入准备就绪的录音中,同时将麦克风路由到耳机,以便歌手可以听到他/她自己的声音。在回放时,录音准备被静音,因此歌手可以在这里录制什么。如果在播放过程中按下录音按钮,则歌手会听到正在录制的人声。

我遇到的问题是将音频直接路由到音频输出。我不确定我应该使用什么音频系统 AVAudioSession 显然适用于 iOS .我必须去Core Audio吗?我想坚持使用 swift 4

任何建议将不胜感激

这是我目前所拥有的

import Cocoa
import AVFoundation

enum RecordingPreset: Int 
    case Low = 0
    case Medium
    case High

    func settings() -> Dictionary<String, Int> 
        switch self 
        case .Low:
            return [AVLinearPCMBitDepthKey: 16, AVNumberOfChannelsKey : 1, AVSampleRateKey : 12_000, AVLinearPCMIsBigEndianKey : 0, AVLinearPCMIsFloatKey : 0]

        case .Medium:
            return [AVLinearPCMBitDepthKey: 16, AVNumberOfChannelsKey : 1, AVSampleRateKey : 24_000, AVLinearPCMIsBigEndianKey : 0, AVLinearPCMIsFloatKey : 0]

        case .High:
            return [AVLinearPCMBitDepthKey: 16, AVNumberOfChannelsKey : 1, AVSampleRateKey : 48_000, AVLinearPCMIsBigEndianKey : 0, AVLinearPCMIsFloatKey : 0]
        
    

    func exportSettings() -> Dictionary <String, Int> 

        var recordingSetting = self.settings()
        recordingSetting[AVFormatIDKey] = Int(kAudioFormatLinearPCM)
        recordingSetting[AVLinearPCMIsNonInterleaved] = 0
        return recordingSetting
    
//eo RecordingPreset



extension Array 
    func firstObject() -> Element? 
        var firstObject: Element?
        if self.count > 0 
            firstObject = self[0]
        
        return firstObject
    

    func lastObject() -> Element? 
        var lastObject: Element?
        if self.count > 0 
            lastObject = self[self.endIndex - 1]
        
        return lastObject
    


class MainWindowController: NSWindowController 
    var audioEngine:AVAudioEngine!
    var player:AVAudioPlayer!
    var recorder: AVAudioRecorder?

    override func windowDidLoad() 
        super.windowDidLoad()

    //EO Overide

    func createRecorder() -> () 
        var initialisedRecorder: AVAudioRecorder?
        let currentDate = NSDate()
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "dd-MM-yy HHmmss"
        let fileName = "/RECORDING/Audio/Recording on " + dateFormatter.string(from: currentDate as Date) + ".wav"
        let filePaths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
        if let firstPath = filePaths.firstObject() 
            let recordingPath = firstPath + fileName
            let url = NSURL(fileURLWithPath: recordingPath)
            let selectedPreset = RecordingPreset.High
            do 
                initialisedRecorder = try AVAudioRecorder(url: url as URL, settings: selectedPreset.settings()
                )
            catch 
                print("nope")
            
            initialisedRecorder!.isMeteringEnabled = true
            initialisedRecorder!.prepareToRecord()
        
        recorder = initialisedRecorder
    //eo createRecorder



    @IBAction func myRecord(_ sender: Any) 
        print("RECORD")
        createRecorder()
        recorder?.record()
    


    @IBAction func myStop(_ sender: Any) 
        print("STOP")
        recorder?.stop()
        recorder = nil
    



//EnD oF thE wORld

【问题讨论】:

【参考方案1】:

您可以直接使用 AVFoundation 框架代替 Core Audio。对于直通音频,您可以创建自定义 V3 AUAudioUnit 子类,并将数据从实例化音频对象的输入渲染块传递到其输出缓冲区(可能使用循环 FIFO),并且延迟相当低。

请注意,Apple(在 2017 年关于 Core Audio 的 WWDC 会议中)建议不要在实时音频上下文中使用 Swift 或 Objective C 方法,因此您可能需要在 C 中编写一小部分(缓冲区副本)。

【讨论】:

以上是关于录制时通过 Swift OSX 音频的主要内容,如果未能解决你的问题,请参考以下文章

Swift IOS 使用 AVFoundation 录制视频和音频

使用 Swift 通过 iPhone 扬声器强制播放音频文件

在没有内核扩展的情况下录制系统音频

Swift + AVAudioRecorder 非常安静地录制

HTML5 音频 - 录制保存文件正常,但通过音频控制播放时没有声音

如何在 Swift 中以 wav 格式录制音频?