Mohamed Salah
Mohamed Salah

Reputation: 1205

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

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!

Upvotes: 6

Views: 1879

Answers (1)

Pranavan SP
Pranavan SP

Reputation: 1865

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])

Upvotes: 3

Related Questions