2013-10-31 27 views
4

我已經給出了一個連續水下錄製的大型WAV文件,我想將其轉換爲用於分析的numpy數組。我正在努力做到這一點。將3個字節的立體聲WAV文件轉換爲numpy陣列

到目前爲止,我有:

import numpy as np 
import scipy as sp 
import wave as wv 
import struct 

wavefile = wv.open(filename,'r') 
(nchannels,sampwidth,framerate,nframes,comptype,compname) = wavefile.getparams() 

// read a sample as example 

wavedata =wavefile.readframes(1) 

第一幀看起來是這樣的: '\ XCD \命苦\ XFF @ \ X01 \ X00'。我試圖使用結構解壓縮它,但解壓縮任何我做我會得到以下錯誤:「字符大小不匹配格式」。我想這與Python結構無法處理24位數據的事實有關。

波文件的參數看起來如下:

  • nchannels = 2
  • sampwidth = 3
  • 幀率= 48000
  • 將爲nframes = 283516532L
  • comptype = 'NONE'
  • compname ='not compressed'

有人知道如何將24位立體聲WAV文件讀入numpy數組中嗎?

+0

我認爲'scipy'讀取24位wav文件到的32個的整數的數組,但它不寫24位wavs。你總是可以一次讀取一個字節,然後把它們轉換成24位的值,就像'w24 =(w8_3 << 16)| (w8_2 << 8)| w8_1' – Jaime

回答

0

對於那些有類似問題我張貼我的解決方案。請注意,這會將24位波形文件轉換爲有符號浮點numpy數組。僅當轉換爲整數時,將/ int2float部分留出。

frames = wavfile.readframes(nsamples) 

ch1 = np.zeros(nsamples) 
ch2 = np.zeros(nsamples) 
int2float = (2**23)-1 

for x in np.arange(int(nsamples)): 
    ch1_24bit_sample = frames[x*6:x*6+3] 
    ch2_24bit_sample = frames[x*6+3:x*6+6] 
    ch1_32bit_sample = bit24_2_32(ch1_24bit_sample) 
    ch2_32bit_sample = bit24_2_32(ch2_24bit_sample) 
    ch1[x]=struct.unpack('i',ch_32bit_sample)[0] 
    ch2[x]=struct.unpack('i',ch_32bit_sample)[0] 
    ch1[x]=ch1[x]/int2float 
    ch2[x]=ch2[x]/int2float 

def bit24_2_32(strbytes): 
    if strbytes[2] < '\x80': 
     return strbytes+'\x00' 
    else: 
     return strbytes+'\xff' 
3

這裏的一個循環,處理2,圖3,以及與信道的任意數4字節WAV文件:

def dataFromWave(fname): 
""" return list with interleaved samples """ 
    f = wave.open(fname, 'rb') 
    chans = f.getnchannels() 
    samps = f.getnframes() 
    sampwidth = f.getsampwidth() 
    if sampwidth == 3: #have to read this one sample at a time 
     s = '' 
     for k in xrange(samps): 
      fr = f.readframes(1) 
      for c in xrange(0,3*chans,3):     
       s += '\0'+fr[c:(c+3)] # put TRAILING 0 to make 32-bit (file is little-endian) 
    else: 
     s = f.readframes(samps) 
    f.close() 
    unpstr = '<{0}{1}'.format(samps*chans, {1:'b',2:'h',3:'i',4:'i',8:'q'}[sampwidth]) 
    x = list(struct.unpack(unpstr, s)) 
    if sampwidth == 3: 
     x = [k >> 8 for k in x] #downshift to get +/- 2^24 with sign extension 
    return x 
+0

好的一段代碼;如果你使用python 2.6或更高版本。 – Cnoobplusplus

+0

謝謝。出於好奇,什麼需要2.6? – mtrw

+0

我認爲字符串格式是在v2.6中引入的。它不適用於我被迫使用的v2.4.3。 – Cnoobplusplus