AVAudioPlayerNode возвращается с обработчиком слишком рано
Я хотел бы воспроизвести звук перед записью звука. Я играю звук с AVAudioPlayerNode, затем в обработчике завершения я начинаю запись. Моя проблема в том, что обработчик завершения запускается примерно за 0,45 секунды до того, как фактически закончится воспроизведение звука. Это потому, что я записываю 0,45 секунды звука в начале записи. Вместо этого я хотел бы начать запись именно тогда, когда закончится воспроизведение звука. Вот мой код:
@interface ViewController ()
@property (strong, nonatomic) NSMutableDictionary *recordingSettings;
@property (strong, nonatomic) AVAudioRecorder *audioRecorder;
@property (nonatomic, strong) AVAudioEngine *engine;
@property (nonatomic, strong) AVAudioPlayerNode *audioPlayerNode;
@property (nonatomic, strong) AVAudioFile *audioFile;
@property (strong, nonatomic) AVAudioPlayer *audioPlayer;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error: nil];
self.engine = [AVAudioEngine new];
self.audioPlayerNode = [AVAudioPlayerNode new];
[self.engine attachNode:self.audioPlayerNode];
NSString *path = [[NSBundle mainBundle] pathForResource:@"Sound.wav" ofType:nil];
self.audioFile = [[AVAudioFile alloc] initForReading:[NSURL fileURLWithPath:path]
error:nil];
AVAudioMixerNode *mixerNode = [self.engine mainMixerNode];
[self.engine connect:self.audioPlayerNode
to:mixerNode
format:self.audioFile.processingFormat];
NSError *error;
[self.engine startAndReturnError:&error];
if (error) {
NSLog(@"error:%@", error);
}
[self.audioPlayerNode play];
}
- (IBAction)record:(id)sender {
[self.audioPlayerNode scheduleFile:self.audioFile
atTime:nil
completionHandler:^{
NSArray *pathComponents = [NSArray arrayWithObjects:
[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject],
[NSString stringWithFormat:@"%@.m4a", @"testsound"],
nil];
NSURL *outputFileURL = [NSURL fileURLWithPathComponents:pathComponents];
self.recordingSettings = [[NSMutableDictionary alloc] init];
[self.recordingSettings setValue:[NSNumber numberWithInt:kAudioFormatMPEG4AAC] forKey:AVFormatIDKey];
[self.recordingSettings setValue:[NSNumber numberWithFloat:44100.0] forKey:AVSampleRateKey];
[self.recordingSettings setValue:[NSNumber numberWithInt:2] forKey:AVNumberOfChannelsKey];
NSError* error;
self.audioRecorder = [[AVAudioRecorder alloc] initWithURL:outputFileURL settings:self.recordingSettings error:&error];
if (error != nil) {
NSLog(@"RecordError: %@", error.localizedDescription);
}
self.audioRecorder.delegate = self;
self.audioRecorder.meteringEnabled = YES;
[self.audioRecorder prepareToRecord];
[self.audioRecorder record];
}];
}
- (IBAction)stopRecording:(id)sender {
[self.audioRecorder stop];
}
- (IBAction)play:(id)sender {
NSArray *pathComponents = [NSArray arrayWithObjects:
[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject],
[NSString stringWithFormat:@"%@.m4a", @"testsound"],
nil];
NSURL *outputFileURL = [NSURL fileURLWithPathComponents:pathComponents];
NSLog(@"%@",outputFileURL.absoluteString);
NSError* error;
self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:outputFileURL error:&error];
if (error != nil) {
NSLog(@"PlayError: %@", error.localizedDescription);
}
[self.audioPlayer setDelegate:self];
[self.audioPlayer prepareToPlay];
[self.audioPlayer play];
}
@end
В качестве обходного пути я откладываю запись на 0,45 секунды следующим образом:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.45 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
[self.audioRecorder record];
});
Скажите, пожалуйста, почему обработчик завершения вызывается до полного воспроизведения звука или есть лучший способ записи сразу после завершения воспроизведения звука?