#ios #callback #avaudioplayer
#iOS #обратный вызов #avaudioplayer
Вопрос:
не могли бы вы, пожалуйста, дать мне какие-либо советы о том, в чем может быть проблема? Я очень новичок в ObjC, поэтому я вроде как застрял.
Я использую встроенную в C библиотеку, которая генерирует различные звуки, и я хотел бы воспроизвести эти звуки с помощью AVAudioPlayer. Тем не менее, я наблюдаю какое-то удивительное поведение audioPlayerDidFinishPlaying. Я проиллюстрирую это на следующем примере.
Это мой файл .h (с опущенным ненужным материалом):
#import <AVFoundation/AVFoundation.h>
@interface mytest_appViewController : UIViewController <AVAudioPlayerDelegate> {
AVAudioPlayer *player;
....
}
void HaveSoundCallback(const short *psSamples, long lSamplesNum, void *pOwner);
....
@property (nonatomic, retain) AVAudioPlayer *player;
@end
И это одна из частей реализации:
....
#import "MyCplusplusSoundGeneratingLibrary.h"
....
- (IBAction)GoButtonTouched:(UIButton *)sender{
// calling the C made GenerateSound and passing it the callback
int ret=GenerateSound(couple_of_parameters, HaveSoundCallback, self);
}
Обычно я не знаю, сколько звуков будет воспроизводить функция GenerateSound (за один вызов), но всякий раз, когда она его создает, она вызывает HaveSoundCallback, который должен позаботиться об этом (он также отправляет «self» в качестве «владельца» звука).
Теперь это реализация обратного вызова (она в том же .mm, но снаружи @implementation…@end ):
void HaveSoundCallback(const short *psSamples, long lSamplesNum, void *pOwner){
NSString *OutWave;
NSLog(@"Entered the callback function");
OutWave=[pOwner getDocumentFile:@"out.wav"];
[pOwner SaveSoundData:OutWave pcm:psSamples len:lSamplesNum];
[pOwner PlaySound:OutWave];
[OutWave release];
}
Это означает, что функция обратного вызова сохраняет звуковые данные в формате wav (вызывая SaveSoundData), а затем вызывает PlaySound для их воспроизведения. Реализация воспроизведения звука и audioPlayerDidFinishPlaying снова находится в классе mytest_appViewController:
- (void)PlaySound:(NSString *)WaveFile{
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath:WaveFile];
NSLog(@"Playing started");
self.player =[[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:nil];
self.player.delegate = self;
[self.player play];
while (self.player.playing) {
sleep(0.01);
}
[fileURL release];
NSLog(@"Playing finished");
}
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)p successfully:(BOOL)flag
{
NSLog(@"hi from audioPlayerDidFinishPlaying");
}
Я намеренно жду здесь в цикле while, чтобы проигрыватель не воспроизводил все возможные возвращаемые звуки одновременно — другой обратный вызов происходит после того, как проигрыватель прекращает воспроизведение текущего звука. Но я хотел бы инициировать завершенное воспроизведение плеером.делегировать. Итак, для моих экспериментальных (и ObjC «самообучения») целей я реализовал делегат audioPlayerDidFinishPlaying.
И теперь ситуация тестирования: допустим, что GenerateSound выдает 3 звука (с небольшими задержками между ними). Я бы ожидал, что консоль вывода будет чем-то вроде:
Entered the callback function
Playing started
hi from audioPlayerDidFinishPlaying
Playing finished
Entered the callback function
Playing started
hi from audioPlayerDidFinishPlaying
Playing finished
Entered the callback function
Playing started
hi from audioPlayerDidFinishPlaying
Playing finished
Но вместо этого audioPlayerDidFinishPlaying вызывается в самом конце 3 раза, т.Е.:
Entered the callback function
Playing started
Playing finished
Entered the callback function
Playing started
Playing finished
Entered the callback function
Playing started
Playing finished
hi from audioPlayerDidFinishPlaying
hi from audioPlayerDidFinishPlaying
hi from audioPlayerDidFinishPlaying
Что я делаю не так? Почему audioPlayerDidFinishPlaying не выполняется немедленно, когда воспроизведение действительно завершено, а вместо этого оно где-то складывается и выполняется 3 раза в конце?
Имеет ли это какое-то отношение к тому факту, что программа фактически все время находится внутри библиотечной функции C GenerateSound, и, следовательно, audioPlayerDidFinishPlaying выполняется, как только остается значение GenerateSound? И если да, есть ли какой-либо лучший способ реализовать функциональность, которую я хотел бы получить?
Заранее большое спасибо за любую помощь!