Не могли бы вы дать мне несколько советов, где может быть проблема? Я очень плохо знаком с 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 для их воспроизведения. Реализация 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, чтобы предотвратить одновременное проигрывание проигрывателем всех возможных звуков возврата - другой обратный вызов происходит после того, как проигрыватель перестает воспроизводить текущий звук. Но я хотел бы запустить законченную игру player.delegate. Поэтому для моих экспериментальных (и 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 остается? И если да, есть ли лучший способ реализовать функциональность, которую я хотел бы получить?
Заранее большое спасибо за любую помощь!