15

In an app I'm currently developing, I've more or less hit a brick wall. In the application you can enter a view which lists all locally saved audio files in a standard table view. From here you can click on them to play them, or hit a record button below to make a new recording, which will afterwards automatically get saved to the apps sandbox.

Now all of this actually works perfectly fine, most of the time. I can sit and make recordings and play them back. I can sit and test this on and on for around 45 with no problems whatsoever. Then suddenly at random times I will hit a very odd problem. The problem is that the recorder all of the sudden starts to save nothing but corrupt files which can't be played back and are exactly 4096 bytes in size, no matter how long you recorder for.

I use the AVAudioRecorder in a totally standard fashion, setting it up like this:

// Specific settings for the audio recording
NSDictionary *recordSettings = [NSDictionary dictionaryWithObjectsAndKeys:
    [NSNumber numberWithInt:AVAudioQualityMin],
    AVEncoderAudioQualityKey,
    [NSNumber numberWithInt:8], 
    AVEncoderBitRateKey,
    [NSNumber numberWithInt: 2], 
    AVNumberOfChannelsKey,
    [NSNumber numberWithFloat:22000.0], 
    AVSampleRateKey,
    nil];

NSError *error = nil;
audioRecorder = [[AVAudioRecorder alloc]
    initWithURL:contentURL
    settings:recordSettings
    error:&error];
audioRecorder.delegate = self;

I start the recording like this:

if (!isRecording) {
    isRecording = YES;
    [audioRecorder record];

    // Start the timer
    recordTiming = [NSDate date];

    timeCheck = [NSTimer
        scheduledTimerWithTimeInterval:1.0f
        target:self
        selector:@selector(timeCheck)
        userInfo:nil
        repeats:YES];
}

And then stopping it with this:

if (isRecording) {
    [audioRecorder stop];

    // Stop the timer
    [timeCheck invalidate];
}

I have no idea what could cause this problem to happen. So far I've tried almost everything. I've check to make sure that the recorder object is recycled properly (so you have a new instance for each now recording), and that the old reference is deallocated and so on, to make sure it has nothing to do with interfering objects, but nothing solves it.

Is there anyone who have a slight idea of what could cause problems with corrupted files?

Perception
  • 79,279
  • 19
  • 185
  • 195
CodingBeagle
  • 1,888
  • 2
  • 24
  • 52
  • 1
    So you are saying the error variable is always nil after audioRecorder is initialized, right ? – A-Live Mar 14 '12 at 15:53
  • Yes, correct :) Actually I do have some quick error checks below for the NSLog to make sure it is initialized correctly and that the NSError is nil and so forth. – CodingBeagle Mar 14 '12 at 15:56
  • Got it, let's improve your code then, the issue should probably become obvious or disappear. Instead of using isRecording var you could use an audioRecorder property recording; i can't see the audio session initialization but you've probably just omitted it. However i'd suggest you also to improve the error handling, the answer below could be used as a reference: http://stackoverflow.com/questions/1010343/how-do-i-record-audio-on-iphone-with-avaudiorecorder – A-Live Mar 14 '12 at 17:04
  • 1
    Yes, I've now tried to improve some of the error handling :) I also narrowed down the bug to be when I start recording, that is, at the line: [audioRecorder record]; I found out that in some cases it will kind of randomly return NO. Someone else suggested that I should start an audio session before recording. I have not gotten the bug yet, but perhaps it's still there. Hard to tell as the timing can be so random :) Do you think the audio session could play a part in it? By the way, thank you for the help so far :) It's much appriciated. – CodingBeagle Mar 14 '12 at 19:00
  • I should think so as that was me who suggested it at your another question. From my expirience – A-Live Mar 14 '12 at 19:57
  • I should think so as that was me who suggested it at your another question. From my experience the most troublesome parts of iOS audio is to prepare one solid version which you'll use later as there are not many samples available. Audio session is one of important things to be taken in consideration, but that's not 100% solution. It's critically important to perform all the possible checks while working with core audio as well as reading the documentation carefully. – A-Live Mar 14 '12 at 20:03
  • I saw your other question and it looked like the Session was the culprit here. Is that true? You are the only one I can find who has experienced this problem. I am working through it, but my session is being set to "Record" and activated just before starting recording. Was there anything else contributing to this? If I don't hear back here, I'll post my own. Thanks. – jbcaveman Mar 30 '12 at 15:22
  • Actually, I think I just fixed it. I had a "prepareRecorder" method that set up the record details and called prepareToRecord, waiting for the button to be hit (I saw this suggestion somewhere else proposed to help the recording start more quickly). It works with no errors so far after removing that, and putting everything in one method like this post: http://stackoverflow.com/questions/1010343/how-do-i-record-audio-on-iphone-with-avaudiorecorder – jbcaveman Mar 30 '12 at 15:42
  • Sorry for the delayed response, haven't checked stackoverflow in a while :) But yes, the solution was found in this question: http://stackoverflow.com/questions/9706020/avaudiorecorder-record-method-returns-no-at-random-times/9706731#comment12433148_9706731 where you can see the code snippet in the answer marked with green. It was indeed the Audio Session that was the culprit, and I had to make sure to put the audio session snippet before starting any recording :) I hope that helps to clarify things – CodingBeagle Apr 10 '12 at 11:23
  • @user1163640: could you please post your solution as an answer and accept it, so others can easily find it, too? – patric.schenke Mar 07 '13 at 18:31

1 Answers1

7

Note: Since the OP is inactive for some days and I guess this question should be answered for public's future reference, thus I post this answer.

The AVAudioSession has to be obtained before start recording.

AVAudioSession *audioSession = [AVAudioSession sharedInstance];
NSError *err = nil;
[audioSession setCategory :AVAudioSessionCategoryPlayAndRecord error:&err];
if(err){
   NSLog(@"audioSession: %@ %d %@", [err domain], [err code], [[err userInfo] description]);
   return;
}
err = nil;
[audioSession setActive:YES error:&err];
if(err){
   NSLog(@"audioSession: %@ %d %@", [err domain], [err code], [[err userInfo] description]);
   return;
}

Reference: https://stackoverflow.com/a/9706731/188331

Community
  • 1
  • 1
Raptor
  • 53,206
  • 45
  • 230
  • 366
  • This was indeed the problem :) It's been a while since I've checked my older questions so I'm sorry for that, but this is indeed the solution to the problem. – CodingBeagle Mar 11 '13 at 17:30