Why is AVAudioRecorder creating corrupt files?

I'm attempting to record from a device's microphone (under iOS) using AVAudioRecorder. The examples are all quite simple, and I'm following the same method. But I'm getting error messages on attempts to record, and the resulting M4A file (after several seconds of recording) is only 552 bytes long and won't load. Here's the recorder usage:

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

    do
    {
        recorder = try AVAudioRecorder(url: tempFileURL(), settings: settings)
        recorder?.delegate = self
        recorder!.record()
        recording = true
    }
    catch
    {
        recording = false
        recordingFinished(success: false)
    }
}

The immediate sign of trouble appears to be the following, in the console. Note the 0 bits per channel and irrelevant 8K sample rate:

AudioQueueObject.cpp:1580 BuildConverter: AudioConverterNew returned -50 from: 0 ch, 8000 Hz, .... (0x00000000) 0 bits/channel, 0 bytes/packet, 0 frames/packet, 0 bytes/frame to: 1 ch, 8000 Hz, Int16

A subsequent attempt to load the file into AVAudioPlayer results in:

MP4_BoxParser.cpp:1089 DataSource read failed MP4AudioFile.cpp:4365 MP4Parser_PacketProvider->GetASBD() failed AudioFileObject.cpp:105 OpenFromDataSource failed AudioFileObject.cpp:80 Open failed

But that's not surprising given that it's only 500+ bytes and we had the earlier error. Anybody have an idea here? Every example on the Web shows essentially this exact method.

I've also tried constructing the recorder with

		let audioFormat = AVAudioFormat.init(standardFormatWithSampleRate: 44100, channels: 1)
		if audioFormat == nil
		{
			print("Audio format failed.")
		}
		else
		{
			do
			{
				recorder = try AVAudioRecorder(url: tempFileURL(), format: audioFormat!)
...

with mostly the same result. In that case the instantiation error message was the following, which at least mentions the requested sample rate:

AudioQueueObject.cpp:1580 BuildConverter: AudioConverterNew returned -50 from: 0 ch, 44100 Hz, .... (0x00000000) 0 bits/channel, 0 bytes/packet, 0 frames/packet, 0 bytes/frame to: 1 ch, 44100 Hz, Int32

Accepted Reply

Well, since there's inexplicably no way to delete or even edit this post, I'll follow up by saying that I found the problem. Some of my code was inadvertently reverted, and my app was creating a play-only (as opposed to record/play) audio session.

This of course raises the question as to why I was allowed to create an AVAudioRecorder under an inapplicable session, when the attempt is already a "try" operation and could have thrown an informative error right there. And why was there no error message at any stage of this, saying "trying to record in a playback-only session?" Pretty lame.

Replies

Well, since there's inexplicably no way to delete or even edit this post, I'll follow up by saying that I found the problem. Some of my code was inadvertently reverted, and my app was creating a play-only (as opposed to record/play) audio session.

This of course raises the question as to why I was allowed to create an AVAudioRecorder under an inapplicable session, when the attempt is already a "try" operation and could have thrown an informative error right there. And why was there no error message at any stage of this, saying "trying to record in a playback-only session?" Pretty lame.