首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >基于iOS的低通滤波器+采样率转换

基于iOS的低通滤波器+采样率转换
EN

Stack Overflow用户
提问于 2021-12-16 16:19:01
回答 2查看 403关注 0票数 10

我们正在进行一个项目,允许我们用一些低通滤波器& HighPass滤波器,用5k赫兹采样率从麦克风中记录一些声音。

我们正在使用的

为此,我们正在使用AvaudioEngine

我们正在使用AVAudioConverter降低抽样率。

我们使用AVAudioUnitEQ作为LowPass & HighPass过滤器。

代码语言:javascript
复制
let bus = 0
let inputNode = engine.inputNode

let equalizer = AVAudioUnitEQ(numberOfBands: 2)

equalizer.bands[0].filterType = .lowPass
equalizer.bands[0].frequency = 3000
equalizer.bands[0].bypass = false

equalizer.bands[1].filterType = .highPass
equalizer.bands[1].frequency = 1000
equalizer.bands[1].bypass = false
engine.attach(equalizer) //Attach equalizer

// Connect nodes
engine.connect(inputNode, to: equalizer, format: inputNode.inputFormat(forBus: 0))
engine.connect(equalizer, to: engine.mainMixerNode, format: inputNode.inputFormat(forBus: 0))
engine.connect(engine.mainMixerNode, to: engine.outputNode, format: inputNode.inputFormat(forBus: 0))

let outputFormat = AVAudioFormat(commonFormat: .pcmFormatInt16,
                                            sampleRate: 5000,
                                            channels: 1,
                                            interleaved: false)!

// Converter to downgrade sample rate
guard let converter: AVAudioConverter = AVAudioConverter(from: inputNode.inputFormat(forBus: 0), to: outputFormat) else {
           print("Can't convert in to this format")
           return
       }

engine.mainMixerNode.installTap(onBus: bus, bufferSize: 2688, format: engine.mainMixerNode.outputFormat(forBus: 0)) { (buffer, time) in
           
     var newBufferAvailable = true
           
     let inputCallback: AVAudioConverterInputBlock = { inNumPackets, outStatus in
           if newBufferAvailable {
                outStatus.pointee = .haveData
                newBufferAvailable = false
                return buffer
           } else {
                outStatus.pointee = .noDataNow
                return nil
           }
     }
           
           
     let convertedBuffer = AVAudioPCMBuffer(pcmFormat: outputFormat, frameCapacity: AVAudioFrameCount(outputFormat.sampleRate) * buffer.frameLength / AVAudioFrameCount(buffer.format.sampleRate))!

           var error: NSError?
           let status = converter.convert(to: convertedBuffer, error: &error, withInputFrom: inputCallback)
           assert(status != .error)

           
           if status == .haveData {
             // Process with converted buffer
           }
            
       }
       
       engine.prepare()
       
       do {
           try engine.start()
       } catch {
           print("Can't start the engine: \(error)")
       }

问题

低通和高通滤波器不起作用.

交替法

为了检查代码是否有效,我们增加了混响效果,而不是低通滤波器。混响效应(使用AVAudioUnitReverb)处理相同的代码)。

有人能帮我吗?我们在应用低通滤波器时做错了什么?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-12-17 10:50:38

我认为这段代码的主要问题是在调用AVAudioConverter之前创建了engine.prepare(),这可以并将更改mainMixerNode输出格式。除此之外,还有mainMixerNodeoutputNode的冗余连接,以及可能不正确的格式-- mainMixerNode被记录为自动创建并连接到“按需”输出节点。水龙头也不需要格式。

代码语言:javascript
复制
let bus = 0
let inputNode = engine.inputNode

let equalizer = AVAudioUnitEQ(numberOfBands: 2)

equalizer.bands[0].filterType = .lowPass
equalizer.bands[0].frequency = 3000
equalizer.bands[0].bypass = false

equalizer.bands[1].filterType = .highPass
equalizer.bands[1].frequency = 1000
equalizer.bands[1].bypass = false
engine.attach(equalizer) //Attach equalizer

// Connect nodes
engine.connect(inputNode, to: equalizer, format: inputNode.inputFormat(forBus: 0))
engine.connect(equalizer, to: engine.mainMixerNode, format: inputNode.inputFormat(forBus: 0))

// call before creating converter because this changes the mainMixer's output format
engine.prepare()

let outputFormat = AVAudioFormat(commonFormat: .pcmFormatInt16,
                                 sampleRate: 5000,
                                 channels: 1,
                                 interleaved: false)!

// Downsampling converter
guard let converter: AVAudioConverter = AVAudioConverter(from: engine.mainMixerNode.outputFormat(forBus: 0), to: outputFormat) else {
    print("Can't convert in to this format")
    return
}

engine.mainMixerNode.installTap(onBus: bus, bufferSize: 2688, format: nil) { (buffer, time) in
    var newBufferAvailable = true
    
    let inputCallback: AVAudioConverterInputBlock = { inNumPackets, outStatus in
        if newBufferAvailable {
            outStatus.pointee = .haveData
            newBufferAvailable = false
            return buffer
        } else {
            outStatus.pointee = .noDataNow
            return nil
        }
    }
    
    
    let convertedBuffer = AVAudioPCMBuffer(pcmFormat: outputFormat, frameCapacity: AVAudioFrameCount(outputFormat.sampleRate) * buffer.frameLength / AVAudioFrameCount(buffer.format.sampleRate))!
    
    var error: NSError?
    let status = converter.convert(to: convertedBuffer, error: &error, withInputFrom: inputCallback)
    assert(status != .error)
    
    
    if status == .haveData {
        // Process with converted buffer
    }
}

do {
    try engine.start()
} catch {
    print("Can't start the engine: \(error)")
}
票数 5
EN

Stack Overflow用户

发布于 2022-05-20 06:51:24

代码语言:javascript
复制
override func viewDidLoad() {
    super.viewDidLoad()
    lableItem.text = "Select Frequency"
    setUpDropdown()
    navigationItem.title = "High Pass Filter"
    
    do{
        try audioSession.setCategory(.playAndRecord, mode: .default, options: [.mixWithOthers, .defaultToSpeaker,.allowBluetoothA2DP,.allowAirPlay,.allowBluetooth])
        try audioSession.setActive(true)
    } catch{
        print(error.localizedDescription)
    }
    
    let bus = 0
    let inputNode = engine.inputNode
    
    let equalizer = AVAudioUnitEQ(numberOfBands: 2)
    
    equalizer.bands[0].filterType = .highPass
    equalizer.bands[0].frequency = 20000.0
    equalizer.bands[0].bypass = false
    
    equalizer.bands[1].filterType = .lowPass
    equalizer.bands[1].frequency = 1000.0
    equalizer.bands[1].bypass = false
    engine.attach(equalizer) //Attach equalizer
    
    
    // Connect nodes
    engine.connect(inputNode, to: equalizer, format: inputNode.inputFormat(forBus: 0))
    engine.connect(equalizer, to: engine.mainMixerNode, format: inputNode.inputFormat(forBus: 0))
    
    // call before creating converter because this changes the mainMixer's output format
    engine.prepare()
    
    let outputFormat = AVAudioFormat(commonFormat: .pcmFormatInt32,
                                     sampleRate: 44100,
                                     channels: 1,
                                     interleaved: false)!
    // Downsampling converter
    guard let converter: AVAudioConverter = AVAudioConverter(from: engine.mainMixerNode.outputFormat(forBus: 0), to: outputFormat) else {
        print("Can't convert in to this format")
        return
    }
    
    engine.mainMixerNode.installTap(onBus: bus, bufferSize: 2688, format: nil) { (buffer, time) in
        var newBufferAvailable = true
        
        let inputCallback: AVAudioConverterInputBlock = { inNumPackets, outStatus in
            if newBufferAvailable {
                outStatus.pointee = .haveData
                newBufferAvailable = false
                
                return buffer
            } else {
                outStatus.pointee = .noDataNow
                return nil
            }
        }
        
        
        let convertedBuffer = AVAudioPCMBuffer(pcmFormat: outputFormat, frameCapacity: AVAudioFrameCount(outputFormat.sampleRate) * buffer.frameLength / AVAudioFrameCount(buffer.format.sampleRate))!
        
        var error: NSError?
        let status = converter.convert(to: convertedBuffer, error: &error, withInputFrom: inputCallback)
        assert(status != .error)
        
        
        if status == .haveData {
            // Process with converted buffer
        }
    }
    
    do {
        try engine.start()
    } catch {
        print("Can't start the engine: \(error)")
    }
    
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70382340

复制
相关文章

相似问题

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