2011-01-10 73 views
1

我使用AVAssetReader將PCM數據從iPod音軌複製到緩衝區,然後使用RemoteIO音頻單元播放。我正在嘗試創建一個單獨的線程來加載聲音數據,以便在加載到緩衝區時可以訪問和播放數據。用NSData解決生產者 - 消費者問題(用於音頻流)

我目前有一個大的NSMutableData對象,最終保存整首歌的數據。目前,我在一個單獨的線程使用的NSOperation像這樣加載音頻數據:

  1. AVAssetReaderOutput副本,至多,每次到CMBlockBuffer
  2. 複製8192個字節這些字節到NSData對象
  3. 追加此NSData對象到一個更大的NSMutableData對象(最終擁有整首歌曲)
  4. 完成後,通過在NSMutableData對象

我想是訪問每個數據包播放歌曲能夠播放歌曲WHILE複製這些字節。我不確定從同一時間寫入和讀取文件的好方法是什麼。

短想法我有:

  1. 創建和填充3個NSData的目的,在每個長度8192個字節,作爲緩衝液。
  2. 開始遊戲。當我完成播放第一個緩衝區時,將新數據加載到第一個緩衝區。
  3. 當我完成播放第二個緩衝區時,將新數據加載到第二個緩衝區中。相同的第三個
  4. 從第一個緩衝區再次開始播放,填補第三個。等等。

或者,創建一個包含3 * 8192 PCM單元的NSData對象,並以某種方式同時用兩個不同的線程寫入和讀取它。

我有我的代碼現在在兩個不同的線程上工作。我將數據追加到數組中,直到我按播放,此時它停止(可能是因爲線程被阻塞,但我現在不知道)並播放,直到它到達我加載的任何內容的末尾並導致EXC_BAD_ACCESS異常。

總之,我想找到當它被複制,也就是說,8192個字節在時間玩PCM數據的正確途徑。我可能需要使用另一個線程(我現在正在使用NSOperation),但是我不清楚如何同時寫入和讀取緩衝區,最好使用一些更高級別的Objective-C方法。

回答

1

我正在做這件事。您肯定需要在不同的線程上播放音頻(我正在使用RemoteIO來完成此操作)。您還需要使用循環緩衝區。如果您不熟悉這個數據結構,您可能會想要查看這個數據結構,因爲您將在此類操作中使用它。我的一般設置如下:

  • LoadTrackThread啓動並開始從AVAssetReader加載數據並將其作爲PCM存儲在文件中。
  • LoadPCMThread啓動後,將足夠的數據加載到我的PCM文件中,並根據需要將該文件本地加載到本地內存中以供RemoteIO線程使用。它通過將此數據提供給循環緩衝區來實現這一點,只要我的RemoteIO線程即使遠程接近耗盡樣本。
  • RemoteIO回放回調線程消耗循環緩衝區幀並將它們饋送到RemoteIO接口。它還會通知LoadPCMThread在需要開始加載更多樣本時喚醒。

這應該是關於所有你需要線程。您需要在兩個線程之間有某種互斥或信號量,以確保您在寫入文件的同時不嘗試讀取文件(這是錯誤的形式,並且會導致崩潰)。我只是讓我的線程設置一個布爾值並休眠一段時間,直到它未被設置。這樣做可能有更復雜的方式,但它適用於我的目的。

希望有幫助!