首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >AVAudioEngine:过滤实时音频

AVAudioEngine:过滤实时音频
EN

Stack Overflow用户
提问于 2021-12-17 15:39:35
回答 2查看 330关注 0票数 -1

我已经通过了苹果的用vDSP实现音频均衡的示例代码,在那里的音频文件过滤在AVAudioSourceNode和复制。

我的目标是做完全相同的事情,但不是从音频文件中获取音频,而是从麦克风中实时获取音频。在AVAudioEngine中可以这样做吗?这样做的几种方法是基于installTapAVAudioSinkNode,如第一策略和第二策略部分所述。

到目前为止,我已经接近了我的目标,有以下两个策略。

第一策略

代码语言:javascript
运行
复制
// Added new class variables
private lazy var sinkNode = AVAudioSinkNode { (timestep, frames, audioBufferList) -> OSStatus in
    let ptr = audioBufferList.pointee.mBuffers.mData?.assumingMemoryBound(to: Float.self)
    var monoSamples = [Float]()
    monoSamples.append(contentsOf: UnsafeBufferPointer(start: ptr, count: Int(frames)))
    self.page = monoSamples.
    for frame in 0..<frames {
          print("sink: " + String(monoSamples[Int(frame)]))
        }
    return noErr
}
// AVAudioEngine connections

engine.attach(sinkNode)
// Audio input is passed to the AVAudioSinkNode and the [Float] array is pased to the AVAudioSourceNode through the _page_ variable
engine.connect(input, to: sinkNode, format: formatt)

engine.attach(srcNode)

engine.connect(srcNode,
                   to: engine.mainMixerNode,
                   format: format)

engine.connect(engine.mainMixerNode,
                   to: engine.outputNode,
                   format: format)

// The AVAudioSourceNode access the self.page array through the getSinalElement() function.
private func getSignalElement() -> Float {
    return page.isEmpty ? 0 : page.removeFirst()
}

这种方法使通过AVAudioSourceNode播放音频成为可能,但是,音频在几秒钟后停止播放(尽管我仍然成功地在AVAudioSourceNode中获得了self.page数组),并且应用程序最终崩溃了。

2战略

在类似的方法中,我使用了installtap engine.attach(srcNode)

代码语言:javascript
运行
复制
    engine.connect(srcNode,
                   to: engine.mainMixerNode,
                   format: format)

    engine.connect(engine.mainMixerNode,
                   to: engine.outputNode,
                   format: format)
    input.installTap(onBus: 0, bufferSize:1024, format:formatt, block: { [weak self] buffer, when in
        let arraySize = Int(buffer.frameLength)
        let samples = Array(UnsafeBufferPointer(start: buffer.floatChannelData![0], count:arraySize))
        self!.page = samples
    })

// The AVAudioSourceNode access the self.page array through the getSinalElement() function.
private func getSignalElement() -> Float {
    return page.isEmpty ? 0 : page.removeFirst()
}

第二种策略实施后的结果与第一种策略相同。使这些方法失败的问题是什么?

EN

回答 2

Stack Overflow用户

发布于 2021-12-17 15:51:24

您可以使用AvAudioEngine().inputNode,如下所示:

代码语言:javascript
运行
复制
    let engine = AVAudioEngine()
    private lazy var srcNode = AVAudioSourceNode { _, _, frameCount, audioBufferList -> OSStatus in
    
    return noErr
    }
    // Attach First
    engine.attach(srcNode)
    // Then connect nodes

    let input = engine.inputNode

    engine.connect(input, to: srcNode, format: input.inputFormat(forBus: 0))

使用input.inputFormat(...)作为格式类型非常重要。

票数 0
EN

Stack Overflow用户

发布于 2022-05-20 13:06:46

代码语言:javascript
运行
复制
   do{
        try audioSession.setCategory(.playAndRecord, mode: .default, options: [.mixWithOthers, .defaultToSpeaker,.allowBluetoothA2DP,.allowAirPlay,.allowBluetooth])
        try audioSession.setActive(true)
    } catch{
        print(error.localizedDescription)
    }
    
    engine.attach(player)
    //Add this only you want putch
    let pitch = AVAudioUnitTimePitch()
    
   // pitch.pitch = 1000 //Filtered Voice
    //pitch.rate = 1 //Normal rate
    
    // engine.attach(pitch)
    engine.attach(srcNode)
    
    engine.connect(srcNode,
                   to: engine.mainMixerNode,
                   format: engine.inputNode.inputFormat(forBus: 0))
    
    engine.connect(engine.mainMixerNode,
                   to: engine.outputNode,
                   format: engine.inputNode.inputFormat(forBus: 0))
    engine.prepare()
    
    
    engine.inputNode.installTap(onBus: 0, bufferSize: 512, format: engine.inputNode.inputFormat(forBus: 0)) { (buffer, time) -> Void in
        //   self.player.scheduleBuffer(buffer)
        let arraySize = Int(buffer.frameLength)
        let samples = Array(UnsafeBufferPointer(start: buffer.floatChannelData![0], count:arraySize))
        self.page = samples
        print("samples",samples)
    }
    
    
    engine.mainMixerNode.outputVolume = 0.5
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70395504

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档