Unable to write audio queue to file to m4a

50 views Asked by At

I currently use AVAudioRecorder to record audio in an app. If the app crashes or something happens while recording, the file being recorded is lost so as an alternative, I'm trying to use Audio Queue Services to record and write to a file.

I have it working perfectly using LinearPCM but cannot get it to work with m4a encoding. I'm trying to replicate the file format that AVRecorder uses.The file gets written but can't be opened. I think it has to do with my settings but I can't be sure.

The settings I'm using in the AVAudioRecorder are;

        let settings = [
            AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
            AVSampleRateKey: 16000,
            AVNumberOfChannelsKey: 1,
            AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
        ]

This is what works with the Audio Queue Service;

        var recordingFormat = AudioStreamBasicDescription()
        memset(&recordingFormat, 0, MemoryLayout<AudioStreamBasicDescription>.size)
    
        recordingFormat.mFormatID = kAudioFormatLinearPCM
        recordingFormat.mChannelsPerFrame = 1
        recordingFormat.mSampleRate = 16000
        recordingFormat.mBitsPerChannel = 16
        recordingFormat.mBytesPerFrame = UInt32(1*MemoryLayout<Int16>.stride)
        recordingFormat.mFramesPerPacket = 1
        recordingFormat.mBytesPerPacket = UInt32(1*MemoryLayout<Int16>.stride)
        recordingFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked
        var propSize = UInt32(MemoryLayout<AudioStreamBasicDescription>.size)

and then writing to file using;

CheckError(AudioFileCreateWithURL(audioOutputFileName as CFURL,
                                          kAudioFileCAFType,
                                              &recordingFormat,
                                              AudioFileFlags.eraseFile,
                                              &self.outFile), "Write to file failed")

For M4A, I've tried a bunch of combinations and again, the file gets written out but can't be opened

Here is one example that I thought woudl work but doesn't

        recordingFormat.mFormatID = kAudioFormatMPEG4AAC
        recordingFormat.mSampleRate = 44100
        recordingFormat.mChannelsPerFrame = 1
        recordingFormat.mBitsPerChannel = 0
        recordingFormat.mBytesPerFrame = 0
        recordingFormat.mBytesPerPacket = 0
        recordingFormat.mFramesPerPacket = 1024

and to write out the file;

        CheckError(AudioFileCreateWithURL(audioOutputFileName as CFURL,
                                          kAudioFormatMPEG4AAC,
                                              &recordingFormat,
                                              AudioFileFlags.eraseFile,
                                              &self.outFile), "Write to file failed")

These settings actually crash the app. I've tried using various AudioFileTypeID values. Some crash and others will write the file but can't be opened.

1

There are 1 answers

4
Gordon Childs On

kAudioFileCAFType is not an M4A file, create it using kAudioFileM4AType instead. Make sure to call AudioFileClose() too, as that should write out the header.