当前位置: 首页 > 面试题库 >

AVAudioSession .defaultToSpeaker更改麦克风输入

叶冥夜
2023-03-14
问题内容

我有一个应用程序可以点击麦克风,还可以根据麦克风输入播放声音(不必同时通过tho)。下面的代码有效。但是一个问题是输出在小型顶部扬声器而不是底部真实扬声器上播放。我可以通过
在播放器开始播放之前 将3行放在下面来奇怪地解决此问题,然后我可以听到扬声器上的声音。 但是,麦克风停止收听
!即使在播放器停止播放之后。基本上麦克风不喜欢

.defaultToSpeaker

任何想法?

这里也记录了我想做的是正确的:

https://developer.apple.com/documentation/avfoundation/avaudiosession/categoryoptions/1616462-defaulttospeaker

更新: 我最小化了问题。没有球员只是麦克风。在下面的代码中,麦克风为“
.defaultToSpeaker”时,麦克风无法“运行”。经过一些调试后,我意识到defaultToSpeaker将麦克风从“底部”切换到“前部”。和

 try preferredPort.setPreferredDataSource(source)

似乎无法再次将其更改为底部。(我可以为此提供代码)并且当category为defaultToSpeaker时,tap缓冲区的帧长显然是4800,而不是4410。这种差异似乎在我的代码中造成了麻烦,因为我需要44100。所以mic实际上正在工作,但后来在代码中失败由于SR不同而无法胜任。下面的代码可以解释更多。

 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是必需的。但是,如果这样做,我可以提供更多代码。


问题答案:

感谢所有花时间发表评论的人。我从每条评论中学到了新东西。好像我找到了解决方案。这实际上很简单。当AVAudioSession类别显然是.defaultToSpeaker(或overrideOutputAudioPort)时,抽头输入缓冲区的帧长将从4410更改为4800。

无论使用哪种麦克风,都会发生这种奇怪的情况 。所以用

AVAudioSession.sharedInstance().setInputDataSource(datasource);

没有 帮助。

这种差异似乎在稍后的代码中引起问题。因此mic实际上可以正常工作,但是在后来的代码中,由于帧长不同,它无法完成工作。

解决方案/解决方法是,我基本上将水龙头的帧长硬编码。由于我使用转换器,所以我认为这不会成为问题。这意味着我可以设置“
.defaultToSpeaker”,并且麦克风仍按预期运行。

容量= 4410(DUH!)

也许有不同/更好的方法来解决此问题。因此,请随意添加答案。



 类似资料:
  • 问题内容: 我正在寻找一种将文件中的音频数据馈送到麦克风的方法,因此,当第三方应用程序(例如 arecord 或Chromium的“按语音搜索”功能)使用麦克风进行音频输入时,它们会从文件中接收音频数据代替。 这是我的情况 :我编写的一个应用程序记录了来自麦克风的音频数据(使用ALSA)并将其保存到文件(audioFile0.raw)中。在将来的某个未知时间点,某些未知的第三方应用程序(例如,我没

  • 我想直播Android麦克风,可以使用VLC播放器等听到。 Playstore主要提供IP摄像头应用,但这些应用是通过内部网络实现的。我想在互联网上播放流媒体。 可能吗? 我尝试了以下代码片段,但目前不起作用: 在VLC播放器前,我试着听(媒体)- 还有别的办法吗?

  • 播放音符 播放声音 录制 文字转语音

  • 问题内容: 我正在尝试通过Java访问麦克风的级别。我不需要录制任何东西,我只想知道声音水平的相对范围。 这可以实时吗? 如果这是不可能的,那么这可能会起作用:当电平超过某个值时开始记录,当电平下降到一定水平以下一段时间后停止录制四分之一秒的位并读取它的音量,如果它在阈值以下停止录音。 提前致谢 问题答案: 您可以通过Sound API访问麦克风,但不会给您简单的响度级别。您只需要捕获数据并就其声

  • 问题内容: 我已经读了几天的Java声音API了,我无法理解。我是一个体面的程序员,只是很难理解API。 我一直在尝试从麦克风捕获音频并实时显示波形图。 我在捕捉音频时遇到麻烦,他们在教程中说要这样做,但是我似乎无法使它正常工作。 任何建议和帮助将不胜感激,逐行回答将是理想的。 谢谢,麻烦您了。 问题答案: 这将为您提供操作系统默认的设置。 要选择特定的输入设备(TargetDataLine),最

  • 更新时间:2018-09-17 11:37:10 功能说明 高感度麦克风模块。rf13 是一款高感度麦克风模块,这里我们用该模块采集周围环境声音的大小。 硬件资源 1.ESP32Kit 开发板 2.RF13 模块 3.接线 rf13 GND 引脚接 esp32Kit GND 引脚 rf13 VCC 引脚接 esp32Kit 3.3V 引脚 rf13 AO 引脚接 esp32Kit IO34 引脚