Я хочу иметь возможность одновременно записывать звук и воспроизводить позиционный звук.

Для этого мне нужно использовать категорию аудиосеанса .playAndRecord, и одновременная запись и воспроизведение работают. Однако при использовании этой категории аудиофайл воспроизводится без позиционирования (т. Е. Не в пространстве) при использовании наушников Bluetooth. Это работает должным образом при использовании проводных наушников.

Если я установил категорию аудиосеанса на .playback, воспроизводимый звук будет правильно позиционирован как для проводных, так и для наушников Bluetooth, однако я не могу одновременно записывать.

Я пробовал различные категории / варианты аудиосессий, но мне не повезло.

import AVFoundation


class PlayerRecorder: ObservableObject {
    
    let engine = AVAudioEngine()
    let mixer = AVAudioEnvironmentNode()
    
    init() {
        let audioSession = AVAudioSession.sharedInstance()
        
        /*
         Using .playAndRecord both recording and playback works, however
         the audio that is played is NOT positional. .allowBluetooth is needed
         so that bluetooth headphones can be used.
         */
        try! audioSession.setCategory(.playAndRecord, mode: .default, options: .allowBluetooth)
        
        /*
         Using .playback the positional audio DOES work, however we are not able to record.
         */
        // try! audioSession.setCategory(.playback)
        
        self.engine.attach(self.mixer)
        let stereoFormat =  AVAudioFormat(standardFormatWithSampleRate: self.engine.outputNode.outputFormat(forBus: 0).sampleRate, channels: 2)
        self.engine.connect(self.mixer, to: self.engine.outputNode, format: stereoFormat)
        self.engine.prepare()
        try! self.engine.start()
        
    }
    
    func play() {
        let audioPlayer = AVAudioPlayerNode()
        self.engine.attach(audioPlayer)
        let monoFormat =  AVAudioFormat(standardFormatWithSampleRate: self.engine.outputNode.outputFormat(forBus: 0).sampleRate, channels: 1)
        self.engine.connect(audioPlayer, to: self.mixer, format: monoFormat)
        
        // This file has to be in mono
        let url = Bundle.main.url(forResource: "your-mono-audio-file.mp3", withExtension: nil)
        let f = try! AVAudioFile(forReading: url!)
        audioPlayer.scheduleFile(f, at: nil, completionHandler: nil)
        audioPlayer.renderingAlgorithm = .HRTFHQ
        audioPlayer.position = AVAudio3DPoint(x: 20.0, y: 5.0, z: 0.0)
        audioPlayer.play()
    }
    
}
2
Jez 11 Фев 2021 в 01:05

1 ответ

Лучший ответ

Я хочу иметь возможность одновременно записывать звук и воспроизводить позиционный звук.

Это невозможно по стандартному Bluetooth, если вы одновременно играете и записываете с гарнитуры Bluetooth. Параметр allowBluetooth не означает «разрешить Bluetooth». Это означает «предпочитать HFP, если он есть». (Это худшая из известных мне констант в Core Bluetooth.) HFP - это двусторонний аудиопротокол с низкой пропускной способностью, разработанный для телефонных звонков.

Если вы переключитесь на высокоскоростной аудиопротокол A2DP, вы обнаружите, что он однонаправленный, и поэтому вы не можете записывать с микрофона.

Не существует широко распространенного протокола Bluetooth, обеспечивающего высокое качество звука и доступ к микрофону. Если вы контролируете прошивку, вы можете разработать собственный аудиопоток микрофона через BLE (или iAP2, если это устройство MFi). Но в остальном текущего решения нет.

Я продолжаю надеяться, что LEA исправит это, но я не могу найти никаких намеков на то, что это будет. Я также надеялся, что aptX сможет это исправить (хотя iPhone не поддерживает это), но тут не повезло, либо. Я не уверен, почему этот вариант использования не разрабатывается комитетом и поставщиками Bluetooth, но, насколько мне известно, на горизонте ничего не видно.

3
Rob Napier 11 Фев 2021 в 23:30