2011-07-06 84 views
3

我有6个按钮,每个播放一个.caf文件的音频样本。如果我按下按钮声音播放良好,如果我等待它结束并再次按下,它播放良好,但如果我快速按下按钮,声音将弹出并在播放前点击。按下一个按钮它会发出声音。点击按钮快速和声音播放弹出并点击

我最初没有这个弹出的问题,当简单地分配AVAudioPlayer每次按钮被点击,但这创造了一个内存泄漏与多个分配。所以我为每个按钮创建了6个AVAudioPlayers并重新使用它,这样摆脱了内存泄漏,但是现在样本在被覆盖时点击/弹出。

我已经尝试了很多不同的方法来阻止这种情况发生,从设置音量为0,在播放下一个示例等之前停止AVAudioPlayer实例,但无法找到正确的方式来重复播放相同的示例声音,停止弹出。

我的AVAudioPlayer属性保留在.h中,并在alloc语句中使用autorelease。

请帮忙吗?

**编辑:找到了一个解决方案,它不漂亮,但它的工作原理。

基本上我创建了10个自动释放的AVAudioPlayers,如果有一个[myPlayer1 isPlaying],那么我使用下一个。

例如

BOOL done = NO; 

if(![self.audioPlayer0 isPlaying] && done == NO) { 
    self.audioPlayer0 = [ [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil] autorelease ]; 
    [audioPlayer0 play]; 
    done = YES; 
} 

if(![self.audioPlayer1 isPlaying] && done == NO) { 
    self.audioPlayer1 = [ [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil] autorelease ]; 
    [audioPlayer1 play]; 
    done = YES; 
} 

if(![self.audioPlayer2 isPlaying] && done == NO) { 
    self.audioPlayer2 = [ [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil] autorelease ]; 
    [audioPlayer2 play]; 
    done = YES; 
} 

if(![self.audioPlayer3 isPlaying] && done == NO) { 
    self.audioPlayer3 = [ [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil] autorelease ]; 
    [audioPlayer3 play]; 
    done = YES; 
} 

if(![self.audioPlayer4 isPlaying] && done == NO) { 
    self.audioPlayer4 = [ [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil] autorelease ]; 
    [audioPlayer4 play]; 
    done = YES; 
} 

if(![self.audioPlayer5 isPlaying] && done == NO) { 
    self.audioPlayer5 = [ [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil] autorelease ]; 
    [audioPlayer5 play]; 
    done = YES; 
} 

if(![self.audioPlayer6 isPlaying] && done == NO) { 
    self.audioPlayer6 = [ [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil] autorelease ]; 
    [audioPlayer6 play]; 
    done = YES; 
} 

if(![self.audioPlayer7 isPlaying] && done == NO) { 
    self.audioPlayer7 = [ [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil] autorelease ]; 
    [audioPlayer7 play]; 
    done = YES; 
} 

if(![self.audioPlayer8 isPlaying] && done == NO) { 
    self.audioPlayer8 = [ [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil] autorelease ]; 
    [audioPlayer8 play]; 
    done = YES; 
} 

if(![self.audioPlayer9 isPlaying] && done == NO) { 
    self.audioPlayer9 = [ [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil] autorelease ]; 
    [audioPlayer9 play]; 
} 

回答

0

我不能肯定,但可能会出现问题,因为你是截断在非过零,这将导致在波形的垂直部(讨厌的谐音,咔嗒/噼噗)的浪潮。您需要淡化波形而不是将其切掉。研究升余弦平滑/整形。

+0

这也可以工作,但考虑到设置后,决定尝试生成一个新的AVAudioPlayer,如果现有的AVAudioPlayer仍在播放。这允许多个采样相互重叠,而不是一个AVAudioPlayer对象。不管怎么说,还是要谢谢你。 – GeoffCoope

1

为什么记得所有十个音频播放器而不是动态创建它们?

在您的新解决方案中,您实际上正在做的是循环播放所有音频播放器,以找到没有播放的音频播放器。为什么不在数组中做同样的事情?

for (int i=0; i<playerHolder.count; i++) 
{ 
    if (![[playerHolder objectAtIndex:i] isPlaying]) 
    { 
     AVAudioPlayer *freePlayer = [playerHolder objectAtIndex:i]; 
     freePlayer = [ [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil] autorelease ]; 
     [freePlayer play]; 
    } 
} 

从理论上讲,这应该做到同样的事情,你的解决方案,而不杂乱:

NSMutableArray *playerHolder = [[NSMutableArray alloc] init]; 
int maxNumberOfBuffers = 10; 

for (int i=0; i<maxNumberOfBuffers; i++) 
{ 
    AVAudioPlayer *audioPlayer; 
    [playerHolder addObject:audioPlayer]; 
} 

然后,只需通过数组时,试图打的东西看。

+0

请注意,在这两种解决方案中,没有任何事情可以处理所有玩家都在使用的情况。如果发生这种情况,声音就不会被播放。在这两种解决方案中,您可以将玩家人数增加到16人左右,而且没有问题。这一切都取决于你的声音的长度。 –

+0

这是一个更简洁的方式,感谢代码示例 – GeoffCoope

+0

现在,该阵列运行良好,必须对示例代码进行一些更改才能使其在我的结尾工作,但概念很完善。再次感谢。 – GeoffCoope