Сбой AVAudioPlayer после воспроизведения с AVAudioPlayer

У меня есть кнопка, которую пользователь нажимает, чтобы начать запись, и нажмите еще раз, чтобы остановить. Когда он остановится, я хочу, чтобы записанный голос «эхо» вернулся, чтобы пользователь мог услышать то, что было записано. Это отлично работает с первого раза. Если я нажму кнопку в третий раз, начнется новая запись, а когда я нажму «Стоп», произойдет сбой с EXC_BAD_ACCESS.

- (IBAction) readToMeTapped {

        if(recording)

        {
        recording = NO;
        [readToMeButton setTitle:@"Stop Recording" forState: UIControlStateNormal ];    

        NSMutableDictionary *recordSetting = [[NSDictionary alloc] initWithObjectsAndKeys:
         [NSNumber numberWithFloat: 44100.0],                 AVSampleRateKey,
         [NSNumber numberWithInt: kAudioFormatAppleLossless], AVFormatIDKey,
         [NSNumber numberWithInt: 1],                         AVNumberOfChannelsKey,
         [NSNumber numberWithInt: AVAudioQualityMax],         AVEncoderAudioQualityKey,
         nil];

        // Create a new dated file
        NSDate *now = [NSDate dateWithTimeIntervalSinceNow:0];
        NSString *caldate = [now description];          
        recordedTmpFile = [NSURL fileURLWithPath:[[NSString stringWithFormat:@"%@/%@.caf", DOCUMENTS_FOLDER, caldate] retain]];
        error = nil;
        recorder = [[ AVAudioRecorder alloc] initWithURL:recordedTmpFile settings:recordSetting error:&error];
        [recordSetting release];
        if(!recorder){
            NSLog(@"recorder: %@ %d %@", [error domain], [error code], [[error userInfo] description]);
            UIAlertView *alert =
            [[UIAlertView alloc] initWithTitle: @"Warning"
                                       message: [error localizedDescription]
                                      delegate: nil
                             cancelButtonTitle:@"OK"
                             otherButtonTitles:nil];
            [alert show];
            [alert release];
            return;
        }


        NSLog(@"Using File called: %@",recordedTmpFile);
        //Setup the recorder to use this file and record to it.

        [recorder setDelegate:self];
        [recorder prepareToRecord];

        [recorder recordForDuration:(NSTimeInterval) 5]; //recording for a limited time

    }
    else
    { // it crashes the second time it gets here!
        recording = YES;            
        NSLog(@"Recording YES Using File called: %@",recordedTmpFile);
        [readToMeButton setTitle:@"Start Recording" forState:UIControlStateNormal ];

        [recorder stop]; //Stop the recorder.

        //playback recording
        AVAudioPlayer * newPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:recordedTmpFile error:&error];
        [recordedTmpFile release];

        self.aPlayer = newPlayer;
        [newPlayer release];

        [aPlayer setDelegate:self];
        [aPlayer prepareToPlay];
        [aPlayer play];
        }   
}

- (void)audioRecorderDidFinishRecording:(AVAudioRecorder *)sender successfully:(BOOL)flag {

        NSLog (@"audioRecorderDidFinishRecording:successfully:");

        [recorder release];
        recorder = nil;
}

Проверяя отладчик, он помечает здесь ошибку

@synthesize aPlayer, recorder;

Это та часть, которую я не понимаю. Я думал, что это может иметь какое-то отношение к освобождению памяти, но я был осторожен. Я что-то упустил?


person munchine    schedule 30.04.2010    source источник
comment
Насколько вы знакомы с многопоточным программированием?   -  person lucius    schedule 30.04.2010


Ответы (2)


Поработав над этим некоторое время, я наткнулся на этот совет по отладке. Он показал мне, что AVAudioPlayer был освобожден во второй раз, что привело к сбою. Значит, делегат, должно быть, подчистил? Я проверил этот поток SO, и он предложение, что Делегат не освобождает. Однако, если я удалю строку

   [newPlayer release]; 

Моя программа работает! Прочитав эту ветку SO, я считаю, что моя проблема в том, что я должен реализовать метод AVAudioPlayerDelegate's - (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag и отпустить там аудиоплеер после того, как звук будет воспроизведен. Я сделал это для AVAudioRecorder.

person munchine    schedule 30.04.2010

Вы удостоверились, что @property (retain) не включает неатомные? Я думаю, что часть кода, который обращается к этим свойствам, может делать это из другого потока. Кроме того, вы всегда должны получать доступ к этим свойствам через их геттеры, используя self.recorder и self.player, чтобы быть уверенным, что они доступны в пределах их соответствующих блокировок.

person lucius    schedule 30.04.2010
comment
Привет, Люциус, я попробовал твое предложение, и проблема не в этом. Увидеть ниже. - person munchine; 01.05.2010