AVAudioEngine 在扬声器中录制和播放声音
我想用 AVAudioEngine 创建一个 iOS 应用程序,主要功能是从麦克风录制声音并在扬声器上播放声音。我想在扬声器(底部扬声器)和接收器(顶部扬声器)之间切换。我的代码如下,这在接收器上工作正常。我的问题是扬声器无法播放声音。请帮助我,非常感谢!
import AVFoundation
import UIKit
class XViewController: UIViewController {
let audioSession = AVAudioSession.sharedInstance()
var player: AVAudioPlayerNode!
var engine: AVAudioEngine!
deinit {
NotificationCenter.default.removeObserver(self)
}
override func viewDidLoad() {
super.viewDidLoad()
setupAudioSession()
setupNotifications()
initRecorder()
}
func setupAudioSession() {
do{
try audioSession.setPreferredSampleRate(16000)
try self.audioSession.setPreferredOutputNumberOfChannels(1)
try audioSession.setCategory(.playAndRecord, options: [])
try audioSession.overrideOutputAudioPort(.none)
try audioSession.setMode(.voiceChat)
try audioSession.setActive(true)
} catch{
print(error.localizedDescription)
}
}
func initRecorder() {
player = AVAudioPlayerNode()
engine = AVAudioEngine()
let input = engine.inputNode
engine.attach(player)
let bus = 0
let inputFormat = input.inputFormat(forBus: bus)
engine.connect(player, to: engine.outputNode, format: inputFormat)
let mixerNode = AVAudioMixerNode()
engine.attach(mixerNode)
engine.connect(input, to: mixerNode, format: nil)
input.installTap(onBus: bus, bufferSize: 2048, format: inputFormat) { (buffer, time) -> Void in
self.player.scheduleBuffer(buffer)
print(buffer)
}
}
func start() {
engine.prepare()
try! engine.start()
player.play()
}
func playToLoudSpeaker() {
do{
try self.audioSession.overrideOutputAudioPort(.speaker)
} catch{
print(error.localizedDescription)
}
}
func setupNotifications() {
NotificationCenter.default.addObserver(self,
selector: #selector(handleRouteChange),
name: AVAudioSession.routeChangeNotification,
object: nil)
}
@objc func handleRouteChange(notification: Notification) {
guard let userInfo = notification.userInfo,
let reasonValue = userInfo[AVAudioSessionRouteChangeReasonKey] as? UInt,
let reason = AVAudioSession.RouteChangeReason(rawValue: reasonValue) else {
return
}
// Switch over the route change reason.
switch reason {
case .override :
resume()
default: break
}
}
func resume() {
self.engine.stop()
self.player.stop()
self.engine.detach(player)
self.initRecorder()
engine.prepare()
try? self.engine.start()
player.play()
}
@IBAction private func startRecorderAndPlay(_ sender: UIButton) {
start()
}
@IBAction private func switchToLoudSpeaker(_ sender: UIButton) {
playToLoudSpeaker()
}
}
I want to create a iOS app with AVAudioEngine, main function is record sound from mic and play sound on speaker. I want to switch between loud speaker(bottom speaker) and receiver(top speaker). My code is below, this work fine on receiver. My problem is sound can not play in loud speaker. Please help me, many thanks!
import AVFoundation
import UIKit
class XViewController: UIViewController {
let audioSession = AVAudioSession.sharedInstance()
var player: AVAudioPlayerNode!
var engine: AVAudioEngine!
deinit {
NotificationCenter.default.removeObserver(self)
}
override func viewDidLoad() {
super.viewDidLoad()
setupAudioSession()
setupNotifications()
initRecorder()
}
func setupAudioSession() {
do{
try audioSession.setPreferredSampleRate(16000)
try self.audioSession.setPreferredOutputNumberOfChannels(1)
try audioSession.setCategory(.playAndRecord, options: [])
try audioSession.overrideOutputAudioPort(.none)
try audioSession.setMode(.voiceChat)
try audioSession.setActive(true)
} catch{
print(error.localizedDescription)
}
}
func initRecorder() {
player = AVAudioPlayerNode()
engine = AVAudioEngine()
let input = engine.inputNode
engine.attach(player)
let bus = 0
let inputFormat = input.inputFormat(forBus: bus)
engine.connect(player, to: engine.outputNode, format: inputFormat)
let mixerNode = AVAudioMixerNode()
engine.attach(mixerNode)
engine.connect(input, to: mixerNode, format: nil)
input.installTap(onBus: bus, bufferSize: 2048, format: inputFormat) { (buffer, time) -> Void in
self.player.scheduleBuffer(buffer)
print(buffer)
}
}
func start() {
engine.prepare()
try! engine.start()
player.play()
}
func playToLoudSpeaker() {
do{
try self.audioSession.overrideOutputAudioPort(.speaker)
} catch{
print(error.localizedDescription)
}
}
func setupNotifications() {
NotificationCenter.default.addObserver(self,
selector: #selector(handleRouteChange),
name: AVAudioSession.routeChangeNotification,
object: nil)
}
@objc func handleRouteChange(notification: Notification) {
guard let userInfo = notification.userInfo,
let reasonValue = userInfo[AVAudioSessionRouteChangeReasonKey] as? UInt,
let reason = AVAudioSession.RouteChangeReason(rawValue: reasonValue) else {
return
}
// Switch over the route change reason.
switch reason {
case .override :
resume()
default: break
}
}
func resume() {
self.engine.stop()
self.player.stop()
self.engine.detach(player)
self.initRecorder()
engine.prepare()
try? self.engine.start()
player.play()
}
@IBAction private func startRecorderAndPlay(_ sender: UIButton) {
start()
}
@IBAction private func switchToLoudSpeaker(_ sender: UIButton) {
playToLoudSpeaker()
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论