macOS + AVAudioEngine + AVAudioUnitEQ + Bluetooth = искаженное аудио - PullRequest
0 голосов
/ 05 февраля 2019

Всем доброго времени суток.

Последние 3 недели я пытался решить возникающие у меня проблемы с выравниванием простого аудиопотока в macOS через Bluetooth.

настройки в основном таковы: плеер -> модуль эквалайзера -> микшер -> аудиоустройство Bluetooth всякий раз, когда я использую проводное аудиоустройство (HDMI, внутренний динамик, разъем 3,5 мм и т. д.), все работает великолепно.Если я пытаюсь использовать устройство Bluetooth (пробовал много, дешевых и очень дорогих наушников), на первый взгляд все работает нормально, но когда вы начинаете увеличивать усиление на полосах, результирующий звук становится очень искаженным.При проводном соединении с одинаковыми значениями усиления все работает отлично, усиление увеличивается должным образом и звучит великолепно.Сначала я думал, что это как-то связано с Sampling Rate, но, поиграв с ним некоторое время, я определенно не проблема.

Я собрал быстрый пример на Swift Playground, который может попробовать любой.out (вам нужно добавить файл track.mp3 к ресурсам Playground):

import Cocoa
import AVFoundation

func getCurrentOutputDeviceId () -> AudioDeviceID {
    var addr = AudioObjectPropertyAddress(
        mSelector: kAudioHardwarePropertyDefaultOutputDevice,
        mScope: kAudioObjectPropertyScopeGlobal,
        mElement: kAudioObjectPropertyElementMaster)

    var id: AudioObjectID = kAudioDeviceUnknown
    var size = UInt32(MemoryLayout.size(ofValue: id))
    AudioObjectGetPropertyData(
        AudioObjectID(kAudioObjectSystemObject),
        &addr,
        0,
        nil,
        &size,
        &id
    )
    return id
}

let engine = AVAudioEngine()

// File
let path = Bundle.main.path(forResource: "track", ofType: "mp3")!
let url = URL(fileURLWithPath: path)
let file = try! AVAudioFile(forReading: url)
let fileFormat = file.processingFormat
let frameCount = UInt32(file.length)
let buffer = AVAudioPCMBuffer(pcmFormat: fileFormat, frameCapacity: frameCount)!
try! file.read(into: buffer, frameCount: frameCount)

let player = AVAudioPlayerNode()

let eq = AVAudioUnitEQ(numberOfBands: 3)
eq.globalGain = 0
eq.bypass = false

let gain = Float32(23.0)
let band1 = eq.bands[0]
band1.filterType = .parametric
band1.bandwidth = 0.5
band1.gain = gain
band1.frequency = 32.0
band1.bypass = false

let band2 = eq.bands[1]
band2.filterType = .parametric
band2.bandwidth = 0.5
band2.gain = gain
band2.frequency = 64.0
band2.bypass = false

let band3 = eq.bands[2]
band3.filterType = .parametric
band3.bandwidth = 0.5
band3.gain = gain
band3.frequency = 125.0
band3.bypass = false


var converter = AVAudioMixerNode()

// Why do I have to do this to force playback through an already selected device?
// I don't need to do this on Non Bluetooth Devices.
// Also sometimes works if you switch to internal Microphone rather than the Bluetooth Device Mic
try! engine.outputNode.auAudioUnit.setDeviceID(getCurrentOutputDeviceId())
let deviceFormat = engine.outputNode.outputFormat(forBus: 0)

engine.attach(player)
engine.attach(eq)
engine.attach(converter)
engine.connect(player, to: eq, format: fileFormat)
engine.connect(eq, to:converter, format: fileFormat)
engine.connect(converter, to: engine.mainMixerNode, format: deviceFormat)

engine.prepare()
try! engine.start()
print(engine)

player.play()
player.scheduleBuffer(buffer, at: AVAudioTime(hostTime: 0), options:.loops, completionHandler: nil)

Пожалуйста, попробуйте его на проводном или беспроводном устройстве, и вы сразу увидите разницу.

Несколько вещей, которые я заметил во время моего болезненного процесса отладки:

  1. Посмотрите на строки 66-69, я должен делать это только при использовании устройства Bluetooth, в противном случае, естьпетля обратной связи микрофона в течение полсекунды и звука после этого не будет.

  2. Если я захожу в «Системные настройки» -> «Звук» и переключаюсь на вкладку «Вход», всякий раз, когда у меня выбраны наушники Bluetooth,может подключиться к петле обратной связи микрофона (только если выбран тот же микрофонный вход устройства Bluetooth)

Моя настройка:

macOS 10.14 (18A391) Xcode 10.1 (10B61)

macOS SDK 10.14

Я пытаюсь переписать мое приложение https://github.com/nodeful/eqMac2 в Swift и AVAudioEngine, поскольку AUGraph устарела (я слышал?).Эта ошибка сдерживает меня, хотелось бы решить эту проблему.

С уважением,

Роман

PS Я также задавал тот же вопрос на форумах Apple Dev: https://forums.developer.apple.com/message/348717 на всякий случай, если кто-то последует за ним.

...