У меня есть приложение, которое касается микрофона, а также воспроизводит звуки в зависимости от микрофонного входа (не обязательно одновременно). Этот код ниже работает.Но одна проблема заключается в том, что выход воспроизводится на маленьком верхнем динамике, а не на нижних реальных громких динамиках.Я мог бы решить эту проблему странным образом, поместив 3 строки ниже непосредственно перед запуском проигрывателя , затем я могу услышать звук на динамиках. Но тогда микрофон перестает слушать !Даже после того, как игрок перестает играть.В основном микрофон не любит, когда он
.defaultToSpeaker
Любая идея?
Здесь также задокументировано, что я пытаюсь сделать правильно:
https://developer.apple.com/documentation/avfoundation/avaudiosession/categoryoptions/1616462-defaulttospeaker
ОБНОВЛЕНИЕ: Я минимизировал проблему.Нет игрока, просто микрофон.Код ниже, микрофон не «работает», когда он «.defaultToSpeaker».После некоторой отладки я понял, что defaultToSpeaker переключает микрофон с «нижнего» на «передний».И
try preferredPort.setPreferredDataSource(source)
Кажется, не могу снова изменить его на дно.(Я могу предоставить код для этого) А когда категория defaultToSpeaker, по-видимому, имеет длину кадра буфера крана 4800, а не 4410. Эта разница, кажется, вызывает проблемы в моем коде, потому что мне нужно ровно 44100. Таким образом, микрофон действительно работает, но позже в коде он не работаетделать свою работу из-за разных СР.Ниже код может объяснить больше.
func tapMicrophone() {
try? AVAudioSession.sharedInstance().setActive(false)
try? AVAudioSession.sharedInstance().setCategory(.playAndRecord, options: [.defaultToSpeaker])
//setBottomMic()
try? AVAudioSession.sharedInstance().setActive(true)
//tracker.start()
let input = engine.inputNode
let inputFormat = input.outputFormat(forBus: 0)
let sampleRate = Double(11025)
let outputFormat = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: sampleRate, channels: 1, interleaved: true)!
let converter = AVAudioConverter(from: inputFormat, to: outputFormat)!
let inputBufferSize = 44100 // 100ms of 44.1K = 4410 samples.
let sampleRateRatio = 44100 / sampleRate
input.installTap(onBus: 0, bufferSize: AVAudioFrameCount(inputBufferSize), format: inputFormat) {
buffer, time in
var error: NSError? = nil
let capacity = Int(Double(buffer.frameCapacity) / sampleRateRatio)
let bufferPCM16 = AVAudioPCMBuffer(pcmFormat: outputFormat, frameCapacity: AVAudioFrameCount(capacity))!
converter.convert(to: bufferPCM16, error: &error) { inNumPackets, outStatus in
outStatus.pointee = AVAudioConverterInputStatus.haveData
return buffer
}
}
engine.prepare()
try! engine.start()
}
В этом случае, кажется, у меня есть 2 варианта.Или решите проблему на уровне микрофона, если возможно, сделайте так, чтобы этот код работал с ".defaultToSpeaker".Или не используйте категорию .playandrecord, но переключайтесь между .playback и .record, когда микрофон не нужен.Это тоже не казалось простым, так как требует много запуска / остановки всего аудио, что необходимо для активации и деактивации AVAudioSession.Но если это путь, я могу предоставить больше кода.