2010-04-30 3 views
2

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

- (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; 

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

+0

Насколько вы знакомы с многопоточным программированием? – lucius

ответ

0

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

+0

Привет, Люциус, я попробовал ваше предложение, и это не проблема. Смотри ниже. – munchine

1

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

[newPlayer release]; 

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

Смежные вопросы