【问题标题】:Swift 3 AVAudioEngine set microphone input formatSwift 3 AVAudioEngine 设置麦克风输入格式
【发布时间】:2017-05-25 15:24:28
【问题描述】:

我想在我的 iOS 上使用 Swift 3 处理从麦克风读取的字节。我目前使用 AVAudioEngine。

print(inputNode.inputFormat(forBus: bus).settings)
print(inputNode.inputFormat(forBus: bus).formatDescription)

这给了我以下输出:

["AVNumberOfChannelsKey": 1, "AVLinearPCMBitDepthKey": 32, "AVSampleRateKey": 16000, "AVLinearPCMIsNonInterleaved": 1, "AVLinearPCMIsBigEndianKey": 0, "AVFormatIDKey": 1819304813, "AVLinearPCMIsFloatKey": 1]
<CMAudioFormatDescription 0x14d5bbb0 [0x3a5fb7d8]> {
    mediaType:'soun' 
    mediaSubType:'lpcm' 
    mediaSpecific: {
        ASBD: {
            mSampleRate: 16000.000000 
            mFormatID: 'lpcm' 
            mFormatFlags: 0x29 
            mBytesPerPacket: 4 
            mFramesPerPacket: 1 
            mBytesPerFrame: 4 
            mChannelsPerFrame: 1 
            mBitsPerChannel: 32     } 
        cookie: {(null)} 
        ACL: {(null)}
        FormatList Array: {(null)} 
    } 
    extensions: {(null)}
}

问题是我要发送数据的服务器不需要 32 位浮点数,而是 16 位无符号整数。我想我必须更改 mFormatFlags。有谁知道我该怎么做以及正确的价值是什么?

生成的字节流应该与我在 android 上使用的字节流相同

AudioRecord recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, SAMPLES_PER_SECOND,
            AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT,
            recordSegmentSizeBytes);

我试过这个:

let cfmt = AVAudioCommonFormat.pcmFormatInt16
        inputNode.inputFormat(forBus: bus) = AVAudioFormat(commonFormat: cfmt, sampleRate: 16000.0, channels: 1, interleaved: false)

但出现此错误

无法赋值:函数调用返回不可变值

有什么想法吗?

【问题讨论】:

    标签: ios swift avaudioengine


    【解决方案1】:

    天哪,我想我明白了。我太盲目了,看不到您可以指定 installTap 回调的格式。这似乎有效

    let audioEngine  = AVAudioEngine()
    
    func startRecording() {
        let inputNode = audioEngine.inputNode!
        let bus = 0
    
        let format = AVAudioFormat(commonFormat: AVAudioCommonFormat.pcmFormatInt16, sampleRate: 16000.0, channels: 1, interleaved: false)
    
        inputNode.installTap(onBus: bus, bufferSize: 2048, format: format) { // inputNode.inputFormat(forBus: bus)
            (buffer: AVAudioPCMBuffer!, time: AVAudioTime!) -> Void in
    
            let values = UnsafeBufferPointer(start: buffer.int16ChannelData![0], count: Int(buffer.frameLength))
            let arr = Array(values)
            print(arr)
        }
    
    
        audioEngine.prepare()
        do {
            try audioEngine.start()
        } catch {
            print("Error info: \(error)")
        }
    }
    

    【讨论】:

    • 这会导致代码崩溃:错误:[0x3b49de40] >avae> AVAudioIONodeImpl.mm:884: SetOutputFormat: required condition is false: format.sampleRate == hwFormat.sampleRate 如果你有任何解决方案请发送
    • 对于遇到@HardikDarji 所描述的问题的其他人,请尝试将format 变量更改为:let format = inputNode.inputFormat(forBus: 0)
    • @MarkLyons 如果您将格式设置为 inputNode.inputFormat 那么您将无法获得 OP 要求的 16000 采样率,您将获得麦克风的采样率。 Hardik Darji的问题的解决方法是添加一个mixer节点,并以格式连接到主mixer节点。
    • @prewett 任何代码示例如何做到这一点?我尝试了很多方法,但无法使其工作(有时崩溃,有时只记录沉默)。我尝试了使用&不使用音频会话,不同的格式设置......等等。我可能在某个地方搞砸了,因为有时我能够获取数据(缓冲区)但只能保持沉默。我是否应该像这样明确地连接:inputNode -&gt; fooMixuteNode -&gt; mainMixureNode,然后点击 mainMixureNode?能否请您提供一些详细的提示。
    • @HassanTareq 我没有代码了,抱歉。我想我结束了AVAudioSession.sharedInstance().setPreferredSampleRate(16000.0)。这一直有效到 iOS 13,它似乎被忽略了,我就放弃了。
    猜你喜欢
    • 2015-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-07
    相关资源
    最近更新 更多