2009-06-25 48 views
6

我在iPhone上使用OpenAL同時播放多個音頻樣本。在OpenAL中播放聲音時收到通知

我可以讓OpenAL在單個樣品完成播放時通知我嗎?

我想避免硬編碼樣本長度並設置計時器。

+0

這個問題已經有5年的歷史了,但是對於像我這樣的OpenAL的新手來說,現在有一個OpenAL的Objective-C API以及演示項目(`SourceNotificationsDemo`)中的一個類來演示這個功能。 – livingtech 2014-10-30 21:52:28

+0

@livingtech能否提供鏈接? – Zorayr 2015-06-17 18:55:35

+0

項目在這裏:https://github.com/kstenerud/ObjectAL-for-iPhone – livingtech 2015-06-17 20:57:43

回答

3

如果您的OpenAL的源抽象爲一類,我想你可以簡單地調用performSelector:afterDelay:當您啓動聲音:

- (void) play 
{ 
    [delegate performSelector:@selector(soundHasFinishedPlaying) 
     afterDelay:self.length]; 
    … 
} 

(如果你在此期間手動停止聲音,回調可取消了,看到NSObject Class Reference),或者你可以查詢AL_SOURCE_STATE

- (void) checkStatus 
{ 
    ALint state; 
    alGetSourcei(source, AL_SOURCE_STATE, &state); 
    if (state == AL_PLAYING) 
     return; 
    [timer invalidate]; 
    [delegate soundHasFinishedPlaying]; 
} 

我不知道如何有OpenAL的給你回電話。你想要什麼回調?有些東西可以在沒有回調的情況下更好地解決。

1

This OpenAL guide提出了一種可能的解決方案:

的「流」功能還告訴我們,如果流播放完畢。

...並提供示例源代碼來說明使用情況。

1

等一等,你說的是完成了一個樣本(例如44.1KHz音頻的1/44100秒)?或者你是否在談論知道某個源已經播放了緩衝區並且沒有更多音頻播放?

對於後者,我有很好的結果輪詢AL_BUFFERS_PROCESSED屬性的來源,當我流緩衝區到源;它可能適用於單緩衝區情況來查找此屬性的非零值。

4

我在OpenAL中沒有太多的回調。在我的狀態機中,我只是輪詢源,並延遲過渡,直到完成。


    - (BOOL)playing { 
     ALint sourceState; 
     alGetSourcei(sourceID, AL_SOURCE_STATE, &sourceState); 
     return sourceState == AL_PLAYING; 
    } 

// ... // 

    case QSTATE_DYING: 
     if (![audioSource playing]) 
      [self transitionTo:QSTATE_DEAD]; 

如果這不是你所需要的,那麼你最好打賭可能是一個計時器。你不應該需要硬編碼任何值。您可以在填充緩衝區時確定播放時間。

對問題「爲什麼」的一點洞察可能會提供一些額外的選擇。