AvaudioEngine - Record voice at specific sample rate AvaudioEngine for Analysis
Asked Answered
C

1

9

we are working on a project which records voice from an external microphone. For analysis purposes, we need to have a sample rate of about 5k Hz.

We are using AvAudioEngine to record a voice. We know Apple devices want able to record at a specific rate, so we are using AVAudioConverter to downgrade the sample rate.

But as you know it is similar to the compression, so the lower we reduce sample rate, file size and file duration affect the same. Which is currently happening(Correct me if I am wrong in this).

Issue

**Issue is downgrading sample rate shorter the file length and its effects on calculation & analysis. For example, a 1-hour recording was downgraded to 45 mins. So suppose if we are making analysis on 5 minute period interval, it goes wrong

What will be the best solution for this?**

Query

We have searched over the internet but we could not figure out how buffer size on installTap affects? In the current code, we have set it to 2688.

Can anyone clarify?

Code

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)")
}

Expecting Result

We are fine with compression of buffer but We would like to have the same recording duration in the output file. If we record for 10 minutes output file should have 10 minutes of data.

Clarion answered 22/12, 2021 at 7:8 Comment(3)
I'd appreciate it if you shared your solution once you have itPatricepatrich
I don't know what you mean by: "the lower we reduce sample rate, file size and file duration affect the same." Also don't understand "downgrading sample rate shorter the file length"... I think I understand "a 1-hour recording was downgraded to 45 mins." So are you surprised that a lower sample rate results in a smaller file? Why would that be a problem? And how do you know anything about the file size when you are not doing anything with the converted buffer? It just says "// Process with converted buffer"Snowstorm
@NerdyBunz I am expecting file size to be reduced but I am surprised why the duration of the audio file is reduced. So suppose if we are compressing any audio it reduces its size not the duration(Total Time) of the file. But in my case, the total recording time in the output file is different from the actual recording timeClarion
S
2

Digitized audio doesn't have an intrinsic duration since it can be played back at any sample rate.

In order for the resulting file's duration to be what you expect, the sample rates have to be what you expect at each stage: Recording, processing, and playback.

I suspect that one of two possible things is happening:

A) the sample rate of the buffer you receive inside installtap is not what you assumed it would be... and you are converting from the wrong format.

B) You are playing back your audio at sample rates than are different that what you are assuming they are. (How do you know that your player is playing at 5000hz)?

In order to check this, you would have to break the process down into smaller pieces and check the sample rate at each stage.

Snowstorm answered 24/12, 2021 at 18:22 Comment(1)
thank you for the clarity. In my case issue is nothing with the code and nothing with playing back. The issue occurs on writing buffer in a file. I am saving buffer at the same moment I received from the callback. So instead of saving buffer directly into the file, I have stored it in a local variable and saved all data into a file once the user pressed the stop record button. I am upvoting your answer for your clarity on finding the problem. Thanks :)Clarion

© 2022 - 2024 — McMap. All rights reserved.