5

水中での連続録音の大きな 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\xbc\xff@\x01\x00」のようになります。構造体を使用して解凍しようとしましたが、何をしても解凍すると、次のエラーが表示されます:「str サイズがフォーマットと一致しません」。これは、Python 構造体が 24 ビット データを処理できないことに関連していると思われます。

ウェーブ ファイルのパラメーターは次のようになります。

  • nチャンネル=2
  • サンプル幅=3
  • フレームレート=48000
  • nframes=283516532L
  • comptype='NONE'
  • compname='非圧縮'

24 ビットのステレオ WAV ファイルを numpy 配列に読み込む方法を知っている人はいますか?

4

3 に答える 3

6

以下は、任意の数のチャンネルを持つ 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
于 2013-11-15T11:03:52.787 に答える
2

同様の問題を抱えている人のために、私の解決策を投稿します。これにより、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'
于 2013-11-15T10:46:58.327 に答える