Audio from a file generated from an AVAudioEngine bus tap has different speed than the one played on device output

I am generating audio with an AVAudioEngine. I am then installing a tap on the mainMixerNode output of the engine which provides an AVAudioPCMBuffer which is then written into an MPEG4ACC AVAudioFile. The input Audio nodes to the engine are AVAudioUnitSampler nodes. The issue I have is that the audio played on the resulting .m4a file is slower in speed than the one that you can hear on the device output itself (speakers, headphones). This is the code I am implementing:


// Audio Format
let audioFormat = AVAudioFormat(standardFormatWithSampleRate: 44100, channels: 2)

// Engine
var engine = AVAudioEngine()

// Two AVAudioNodes are hooked up to the AVAudioEngine
engine.connect(myAVAudioNode0, to: engine.mainMixerNode, format: audioFormat)
engine.connect(myAVAudioNode1, to: engine.mainMixerNode, format: audioFormat)

// Function to Write Audio to a File
func writeAudioToFile() {
        // File to write
        let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
        let audioURL = documentsDirectory.appendingPathComponent("share.m4a")

        // Format parameters
        let sampleRate = Int(audioFormat!.sampleRate)
        let channels = Int(audioFormat!.channelCount)
        
        // Audio File settings
        let settings = [
            AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
            AVSampleRateKey: Int(audioFormat!.sampleRate),
            AVNumberOfChannelsKey: Int(audioFormat!.channelCount),
            AVEncoderAudioQualityKey: AVAudioQuality.max.rawValue
        ]
        
        // Audio File
        var audioFile = AVAudioFile()
        do {
            audioFile = try AVAudioFile(forWriting: audioURL, settings: settings, commonFormat: .pcmFormatFloat32, interleaved: false)
        }
        catch {
            print ("Failed to open Audio File For Writing: \(error.localizedDescription)")
        }
        
        // Install Tap on mainMixer
        // Write into buffer and then write buffer into AAC file
        engine.mainMixerNode.installTap(onBus: 0, bufferSize: 8192, format: nil, block: { (pcmBuffer, when) in
            do {
                try audioFile.write(from: pcmBuffer)
            }
            catch {
                print("Failed to write Audio File: \(error.localizedDescription)")
            }
        })
}
Answered by fermor in 412259022

I printed out the AVAudioPCMBuffer format and for some undocumented reason (not the first time, this seems to be a recurring theme with Apple's APIs) the sample rate defaults to 48000Hz. This is what is causing the speed discrepancy. Changing the following line of code, fixes the issue:


let audioFormat = AVAudioFormat(standardFormatWithSampleRate:48000, channels: 2) 
Accepted Answer

I printed out the AVAudioPCMBuffer format and for some undocumented reason (not the first time, this seems to be a recurring theme with Apple's APIs) the sample rate defaults to 48000Hz. This is what is causing the speed discrepancy. Changing the following line of code, fixes the issue:


let audioFormat = AVAudioFormat(standardFormatWithSampleRate:48000, channels: 2) 
To complement the answer above, the sample rate can vary depending on the device, or the audio output (speakers, headphones, bluetooth, etc). It is necessary to determine the sample rate, by looking into the sample rate of the audio session:

Code Block
let audioSession = AVAudioSession.sharedInstance()
let sampleRate = audioSession.sampleRate
let audioFormat = AVAudioFormat(standardFormatWithSampleRate: sampleRate, channels: 2)


Audio from a file generated from an AVAudioEngine bus tap has different speed than the one played on device output
 
 
Q