0

我有类似应用程序的键盘,并且我将每个新的 AVAudioPlayer 添加到 NSMutableArray 以便我可以叠加声音。我的问题是,那个 delagate 函数

-(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag

如果在短时间内有击键,则不会触发。例如,如果我以 0.5 秒或更长时间的间隔进行中风,一切正常。知道为什么吗?当他的声音播放完成时,我想释放内存并从数组中删除对象。

更新

。H

@interface .. <AVAudioPlayerDelegate>
{
    NSMutableArray *soundObjects;
}

@property (nonatomic,strong) AVAudioPlayer *audioPlayer;

.m

-(void)playSound {

    //
    //  play sound
    //

    _audioPlayer = [self loadWav:_soundID];
    _audioPlayer.delegate = self;

    [soundObjects addObject:_audioPlayer];
    AVAudioPlayer *temp = [soundObjects objectAtIndex:soundIndex];
    soundIndex = [soundObjects count];
    [temp play];
}

-(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
#ifdef DEBUG_SOUND
        NSLog(@"FLAG");
        soundIndex--;
        [soundObjects removeObjectAtIndex:soundIndex];
#endif
}

- (AVAudioPlayer *)loadWav:(NSString *)filename {
    NSURL * url = [[NSBundle mainBundle] URLForResource:filename withExtension:@"mp3"];
    NSError * error;

    AVAudioPlayer * player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];

    if (!player) {
#ifdef DEBUG_MODE
        NSLog(@"Error loading %@: %@", url, error.localizedDescription);
#endif
    } else {
        [player prepareToPlay];
    }
    return player;
}
4

2 回答 2

0

尝试在后台进程中触发播放。这是我第一次讨论这个问题,在不知道更多细节的情况下,我只能推测你是如何演奏这些声音的。如果您在主线程上播放声音,那么也在主线程上的键盘将无响应,而声音正在被缓冲并被触发以在同一线程上播放。在处理媒体时,您通常应该加载它并从主线程播放它,以消除竞争条件的可能性。如果加载图像是歌曲或电影,它通常不应该在主线程上,因为 UI 将无响应。

于 2012-11-20T03:28:11.937 回答
0

开发人员文档中有几个 NSQueue 示例作为一个快速示例,我将使用我自己的作品整理的 Obj C 食谱书中的改编。

//This method detatches the instruction from the main thread
-(void)keyStrokeSelector:(NSString*)objectSound{


       [NSThread detachNewThreadSelector:@selector(keyStroke:objectSound)
                                toTarget:self
                              withObject:nil];


 }

//this selector will acctually execute the task
-(void)keyStroke:(NSString *)objectSound
{
   @autoreleasepool {
      //code to play the sound
   }
}

我希望这个对你有用。关于上述代码的一些注意事项:您必须为每个单独的线程使用自动释放池,否则引用计数(MRC 或 ARC)将不起作用,因为它只能在自动释放池中工作,发生在主线程之外的线程中的代码应该被编码像其他任何东西一样,它只会执行并运行到完成。如果您在子线程中有无限循环,则在测试您的应用程序时可能不明显,但是如果我正确记住了后台线程的当前最大时间,操作系统将在十分钟后终止应用程序。更重要的是,如果您不创建特定于线程的@autoreleasepool,那么即使您没有在新线程中创建新对象,您的对象也不会被释放并且会占用内存,我对此怎么强调都不为过,

我希望这会有所帮助,祝你的程序好运

于 2012-11-21T03:24:34.270 回答