AVAudioEngine downsample issue

旧街凉风 提交于 2020-01-09 11:45:09

问题


I'm having an issue with downsampling audio taken from the microphone. I'm using AVAudioEngine to take samples from the microphone with the following code:

assert(self.engine.inputNode != nil)
let input = self.engine.inputNode!

let audioFormat = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: 8000, channels: 1, interleaved: false)    
let mixer = AVAudioMixerNode()
engine.attach(mixer)
engine.connect(input, to: mixer, format: input.inputFormat(forBus: 0))

do {
    try engine.start()

    mixer.installTap(onBus: 0, bufferSize: 1024, format: audioFormat, block: {
            (buffer: AVAudioPCMBuffer!, time: AVAudioTime!) -> Void in
        //some code here
    })

} catch let error {
    print(error.localizedDescription)
}

This code works great on the iPhone 5s since the microphone input is 8000Hz, and the buffer gets filled with data from the microphone.

The problem is that I want to be able to record from iPhone 6s (and upwards) which microphone records with 16000Hz. And whats weird is that if I connect the mixernode with the engines mainmixernode (with the following code):

engine.connect(mixer, to: mainMixer, format: audioFormat)

this actually works, and the buffer I get has the format of 8000Hz and the sound comes out perfectly downsampled, only problem is that the sound also comes out from the speaker which I don't want (and if I don't connect it the buffer is empty).

Does anyone know how to resolve this issue?

Any help, input or thought is very much appreciated.


回答1:


I solved this issue by simply changing my mixers volume to 0.

mixer.volume = 0

This makes me able to take advantage of the engines main mixer awesome ability to resample any samplerate to my desired samplerate, and not hearing the microphone feedback loop coming directly out from the speakers. If anyone needs any clarifying about this please let me know.

This is my code now:

assert(self.engine.inputNode != nil)
let input = self.engine.inputNode!

let audioFormat = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: 8000, channels: 1, interleaved: false)    
let mixer = AVAudioMixerNode()
engine.attach(mixer)
engine.connect(input, to: mixer, format: input.inputFormat(forBus: 0))
mixer.volume = 0
engine.connect(mixer, to: mainMixer, format: audioFormat)

do {
    try engine.start()

    mixer.installTap(onBus: 0, bufferSize: 1024, format: audioFormat, block: {
        (buffer: AVAudioPCMBuffer!, time: AVAudioTime!) -> Void in
        //some code here
    })

} catch let error {
    print(error.localizedDescription)
}



回答2:


The only thing I found that worked to change the sampling rate was

AVAudioSettings.sharedInstance().setPreferredSampleRate(...)

Unfortunately, there is no guarantee that you will get the sample rate that you want, although it seems like 8000, 12000, 16000, 22050, 44100 all worked.

The following did NOT work:

  1. Setting the my custom format in a tap off engine.inputNode. (Exception)
  2. Adding a mixer with my custom format and tapping that. (Exception)
  3. Adding a mixer, connecting it with the inputNode's format, connecting the mixer to the main mixer with my custom format, then removing the input of the outputNode so as not to send the audio to the speaker and get instant feedback. (Worked, but got all zeros)
  4. Not using my custom format at all in the AVAudioEngine, and using AVAudioConverter to convert from the hardware rate in my tap. [Length of the buffer was not set, no way to tell if results were correct]


来源:https://stackoverflow.com/questions/39595444/avaudioengine-downsample-issue

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!