2013-10-02 76 views
1

我有一些原始的ADPCM壓縮音頻流,我想用pygame來播放它們,但據我所知,pygame是不可能的。我如何使用python將它們解壓縮到正常的PCM流(或其他pygame可以播放的內容),然後用pygame播放它們?用Pygame播放ADPCM流

我已經嘗試過audioop模塊,因爲它已經將ADPCM轉換爲線性流,但我不知道線性流是什麼,也不知道如何使用轉換它們的函數。

回答

4

我已經嘗試過audioop模塊,因爲它已經將ADPCM轉換爲線性流,但我不知道線性流是什麼,也不知道如何使用轉換它們的函數。

短版本:「線性」是你想要的。*所以,你想要的功能是adpcm2lin


你如何使用它?

幾乎在audioop中的所有內容都以相同的方式工作:循環播放幀並在每幀上調用函數。如果您的輸入數據具有某些固有的幀大小,例如從MP3文件中讀取(使用外部庫),或者您的輸出庫需要某種特定的幀大小,則您對如何確定幀的方式有點束縛。但是,當你要處理的原始PCM格式,框架是任何你想要的大小,從單個樣品到整個文件**

讓我們先做整個文件,爲簡單起見:

with open('spam.adpcm', 'rb') as f: 
    adpcm = f.read() 
pcm, _ = audioop.adpcm2lin(adpcm, 2, None) 

如果您adpcm文件太大加載到內存並處理所有一次,你需要保持state的軌道,所以:

with open('spam.adpcm', 'rb') as f: 
    state = None 
    while True: 
     adpcm = f.read(BLOCKSIZE) 
     if not adpcm: 
      return 
     pcm, state = audioop.adpcm2lin(adpcm, 2, state) 
     yield pcm 

當然,我的屁股如果你不需要轉換採樣率或做其他任何事情。如果你這樣做,任何這種轉換應該來的ADPCM解壓後***


*長的版本:「線性」是指直接將樣品進行編碼,而不是通過另一種算法映射。例如,如果您有16位A到D,並且您將音頻保存在8位線性PCM文件中,那麼您只需保存每個採樣的前8位。這給你一個非常動態的範圍,所以更安靜的聲音迷失在噪音中。有各種壓擴算法可以爲相同數量的比特提供更寬的動態範圍(當然,以損失其他信息爲代價);有關它們如何工作的詳細信息,請參閱μ-law算法。但是如果你能保持在16位,線性就好了。

**實際上,使用4位原始ADPCM,您實際上不能做一個樣本......但您可以做2個樣本,它足夠接近。 ***如果你真的很挑剔,你可能想先轉換爲32位,然後做這項工作,然後轉換回16位以避免累積損失。但是當你開始使用4位ADPCM時,你不會在這裏尋找高保真音響。

+0

很好的回答,謝謝。 – user2746752

+0

'adpcm'中的值必須是什麼格式(字符串,整型,字節等)? – chwi