2009-03-03 135 views
4

我正在使用AVAudioPlayer在我的應用程序的單獨線程中播放聲音效果。現在我的應用程序非常簡單,我有一個滾動背景的UIScrollView,以及一些代表玩家和敵人的CALayers,在一個簡單的側面滾動類型的遊戲中(想想馬里奧或者功夫或者是什麼)......我可以左右移動播放器,使視圖適當滾動而不會出現問題。我有一個可以播放音效的「攻擊」按鈕......並且很多時候,當我播放音效時,我都會用圖形的方式獲得一點點順暢。這僅僅是使用Quartz的iPhone上的課程嗎?有沒有辦法讓這個表現更順利一些而不開始研究OpenGL?在iPhone遊戲中播放聲音 - 減速

回答

2

你打這個聲音怎麼樣?如果我要猜測的話,那就是每次播放聲音時,操作系統實際上都是從磁盤加載並播放它。

更新:

好吧,你真的不需要創建一個新的線程來播放聲音。這僅僅會導致遊戲中出現口吃並且也是多餘的 - AVAudioPlayer播放方法是異步的 - 它會立即返回,而不是在聲音結束時返回。

1

(使用一個答案,而不是長度的評論,所以我可以證明代碼):

我的聲音播放方法如下:

- (void)playSoundThreaded:(id)soundPlayer 
{ 
    if(soundPlayer == nil) 
    return; 

    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; 
    [(AVAudioPlayer*)soundPlayer play]; 
    [pool release]; 
} 

- (void)playSound:(AVAudioPlayer*)player 
{ 
    if(player == nil) 
    return; 

    [NSThread detachNewThreadSelector:@selector(playSoundThreaded:) 
    toTarget:self withObject:(id)player]; 
} 

而且聲音裝起來,如下所示:

fxPlayer = [[AVAudioPlayer alloc] initWithData: 
    [NSData dataWithContentsOfFile: 
    [[NSBundle mainBundle] pathForResource:@"voicehiya" ofType:@"caf"]] error:NULL]; 

我們已經有一些端倪了聲音正在從磁盤每次重裝......但不知道,爲什麼是或如何防止它。

4

使用NSData dataWithContentsOfMappedFile代替dataWithContentsOfFile。

此外AVAudioPlayer處理它自己的線程,你不需要創建一個。 [AVAudioPlayer播放]在開始播放後返回,而不是在播放完成後返回。

當你不再需要AVAudioPlayer時,不要忘記發佈你的AVAudioPlayer,例如,如果你只想播放聲音,執行audioPlayerDidFinishPlaying:成功:委託並釋放它。

1

我認爲線程已經結束讓玩家複雜化。嘗試此一展身手:

/* setup the sound player */ 
AVAudioPlayer *player1=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL  fileURLWithPath:audioFilePath] error:NULL]; 
player1.numberOfLoops = 0; 
player1.volume=1.0f; 
[player1 prepareToPlay]; 

然後playSound成爲

[player play]; 

而且不要忘了有AudioSession類別設置正確了。

2

我有同樣的問題,放緩。爲了解決這個問題,我首先播放和暫停的聲音,當它在體積0首次加載 - 這個作品比prepareToPlay好這似乎仍然是導致經濟放緩:

player.volume = 0.0; 
[player play]; 
[player pause]; 
player.volume = 1.0; 

當談到時間來播放聲音我只是[玩家玩];然後每一個更新週期循環播放所有主動聲音,並捕捉即將結束並倒帶的聲音,而不是讓它們過期 - 這樣可以避免從頭開始播放聲音的開銷和減速。這裏的示例停止聲音的1/15秒的聲音:

for ({each player in active sounds}) 
{ 
    if ((player.duration - player.currentTime) <= (1.0/15.0)) 
    { 
    [player pause]; 
    player.currentTime = 0.0; 
    } 
} 

現在它已準備好接下來的播放。似乎工作正常!

更新:原來,我第一次播放聲音時仍然有些停頓。我認爲以零音量播放它實際上並沒有做任何事情,但我將它改爲以0.0001的音量播放,然後暫停 - 這是聽不見的,但似乎做了準備聲音的工作。

1

爲什麼不直接使用AudioServicesPlaySystemSound?這非常適合音效。

我在我的遊戲(vConqr)中使用它,該遊戲也基於UIScrollView和許多其他視圖(因此它們都有自己的CALayer),並且不會顯着影響性能。

+0

AudioServicesPlaySystemSound沒有單獨的音量控制。我原來是這樣做的,它沒有口吃。 – GoatRider 2009-04-20 17:23:38

2

起初有同樣的問題。每次聲音播放完畢後,您需要爲每個文檔調用「prepareToPlay」。採用AVAudioPlayerDelegate協議並添加以下方法將執行此操作。

-(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag{ 
    [player prepareToPlay]; 
} 
0

由於我在工作中的一個項目,我一直在調查這幾天。我在代碼中添加了一些家庭滾動的分析功能,並發現在我的OpenGL遊戲中,播放聲音的調用會導致幀頻問題。我有根據我已經找到了你幾個建議:

  1. 使用一個AVAudioPlayer打你的背景音樂的MP3。

  2. 將OpenAL用於您的音效。

  3. 對於聲音效果,請使用蘋果的音頻轉換器命令行工具將您的聲音變爲.caf格式。這是一種非壓縮格式,在將聲音發送到聲卡之前不需要CPU將聲音解壓縮到內存。它可以直接進行,節省您的時間。使用該工具的說明可以在HERE找到。 (滾動到頁面的最底部)

  4. 使用仍然聽起來不錯的最低比特深度。你真的不需要128kbps - 你可以用20來換取很多東西。較低的比特率=較少的處理=較快的聲音。

如果我發現其他任何有用的東西,我會通知您!祝你好運!