Capture audio samples with a specific sample rate like Android in iOS Swift
Asked Answered
I

1

6

I am a beginner in working with sound processing and AVAudioEngine in iOS, and I'm developing an application that captures the audio samples as a buffer and analyzes it. Furthermore, the sample rate must be 8000 kHz and also must be encoded as PCM16Bit, but the default inputNode in the AVAudioEngine is 44.1 kHz.

In Android, the process is quite simple:

AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
                8000, AudioFormat.CHANNEL_IN_MONO,
                AudioFormat.ENCODING_PCM_16BIT, bufferSize);

and then start the reading function for the buffer. I searched a lot, but I didn't find any similar example. Instead, all the examples in which I encountered are capturing the samples in the default node's sample rate(44.1 kHz) like:

let input = audioEngine.inputNode
let inputFormat = input.inputFormat(forBus: 0)
input.installTap(onBus: 0, bufferSize: 640, format: inputFormat) { (buffer, time) -> Void in
    print(inputFormat)
    if let channel1Buffer = buffer.floatChannelData?[0] {
        for i in 0...Int(buffer.frameLength-1) {
            print(channel1Buffer[i])
        }
    }
}
try! audioEngine.start()

So I would like to capture audio samples using AVAudioEngine with 8000 kHz sample rate and PCM16Bit encoding.

Edit: I reached a solution to transform the input to 8 kHz:

let inputNode = audioEngine.inputNode
let downMixer = AVAudioMixerNode()
let main = audioEngine.mainMixerNode

let format = inputNode.inputFormat(forBus: 0)
let format16KHzMono = AVAudioFormat(commonFormat: AVAudioCommonFormat.pcmFormatInt16, sampleRate: 8000, channels: 1, interleaved: true)

audioEngine.attach(downMixer)
downMixer.installTap(onBus: 0, bufferSize: 640, format: format16KHzMono) { (buffer, time) -> Void in
    do{
        print(buffer.description)
        if let channel1Buffer = buffer.int16ChannelData?[0] {
            // print(channel1Buffer[0])
            for i in 0 ... Int(buffer.frameLength-1) {
                print((channel1Buffer[i]))
            }
        }
    }
}

audioEngine.connect(inputNode, to: downMixer, format: format)
audioEngine.connect(downMixer, to: main, format: format16KHzMono)
audioEngine.prepare()
try! audioEngine.start()

, but when I use .pcmFormatInt16 it doesn't work. However, when I use .pcmFormatFloat32 it works fine!

Is answered 7/8, 2018 at 12:19 Comment(5)
This may help you github.com/google/ringdroidParfitt
AVAudioEngine has attachNode method, to which you can pass custom AVAudioNodeCorbett
@SatenderKumar how does an Android library help?Corbett
@Corbett can you please clarify with an example.Is
I was going to say that this answers your question, but I see you already found it! https://mcmap.net/q/1445427/-how-to-change-sample-rate-properly-in-avfoundationLombard
A
3

Have you checked with settings parameter

let format16KHzMono = AVAudioFormat(settings: [AVFormatIDKey: AVAudioCommonFormat.pcmFormatInt16,
                                                               AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue,
                                                               AVEncoderBitRateKey: 16,
                                                               AVNumberOfChannelsKey: 1,
                                                               AVSampleRateKey: 8000.0] as [String : AnyObject])
Alisonalissa answered 14/8, 2018 at 11:8 Comment(1)
Actually, I have found the solution, but the bounty gonna expire in 15 hours. So, Because you are the only one who answered the question, YOU DESERVE IT.Is

© 2022 - 2024 — McMap. All rights reserved.