2015-02-17 12 views
5

Bu bana bir günlük baş ağrısına neden oldu, ancak bunu anladığımdan beri yardımcı olması için bir yere göndermek istedim.Nota dizisini wave (wave scipy.io.wavfile) modülünü kullanarak tampon dosyasına yazmayın.

Bir dalga dosyasına veri yazmak için python'un dalga modülünü kullanıyorum. Ben scipy.io.wavfile kullanmıyorum çünkü veriler, bir kerede belleğe yüklenemeyen/istemediğim devasa bir vektör (16kHz'de ses) olabilir. Anladığım kadarıyla, scipy.io.wavfile sadece size tam dosya arabirimi verirken, dalga arabellekleri okuyup yazmanıza izin verebilir. Yanılıyorsam düzeltilmeyi çok isterim.

Karşılaştığım sorun, wave.writeframes işlevi için float verisinin byte'lere nasıl dönüştürüleceğini gösterir. Verilerim doğru sırada yazılmıyordu.

x0 = np.array([[0,1],[2,3],[4,5]],dtype='int8') 
x1 = np.array([[0,2,4],[1,3,5]],dtype='int8').transpose() 
if np.array_equal(x0, x1): 
    print "Data are equal" 
else: 
    print "Data are not equal" 
b0 = np.getbuffer(x0) 
b1 = np.getbuffer(x1) 

Sonuç:

Data are equal 

In [453]: [b for b in b0] 
Out[453]: ['\x00', '\x01', '\x02', '\x03', '\x04', '\x05'] 

In [454]: [b for b in b1] 
Out[454]: ['\x00', '\x02', '\x04', '\x01', '\x03', '\x05'] 

Emri kabul Verilerin yönünü saygı etmeyen, bayt veri dönüştürme numpy.getbuffer() fonksiyonu kullanılarak, çünkü bu bir numbt.transpose(), verileri yeniden yazmadığından, yalnızca bir görünüm döndürdüğünden, bayttan önce bellekte ilk ayırma tarafından belirlenir. Ancak bu gerçek, ara yüzün dizisel diziler tarafından gömülmesinden dolayı, bu sorunun çözüldüğünü bilmeden önce hata ayıklama bir doozy idi.

bir çözüm numpy ToString kullanmaktır() işlevi:

s0 = x0.tostring() 
s1 = x1.tostring() 
In [455]: s0 
Out[455]: '\x00\x01\x02\x03\x04\x05' 

In [456]: s1 
Out[456]: '\x00\x01\x02\x03\x04\x05' 

Bu ilk toString() fonksiyonunu söylemek kimseye muhtemelen açıktır, ama bir şekilde benim arama konusunda herhangi bir iyi belgelerine kazıp etmedi scipy.io.wavfile kullanmaktan başka bir dalga dosyası yazmak için tüm numpy dizisini biçimlendirmek. İşte burada. Sadece tamamlanması için ("özellikler" İle başlayan bu veri sırası sorunu vardı, bu yüzden de aslen n_channels x N_SAMPLES olduğuna dikkat:. Gayet iyi çalışıyor tostring Benim için

outfile = wave.open(output_file, mode='w') 
outfile.setnchannels(features.shape[0]) 
outfile.setframerate(fs) 
outfile.setsampwidth(2) 
bytes = (features*(2**15-1)).astype('i2').transpose().tostring() 
outfile.writeframes(bytes) 
outfile.close() 
+1

kullanabileceğiniz' struct.pack endianness ve size boyut belirtebilmenizi sağlar, bir örnek için http://stackoverflow.com/a/19999599/120261 adresine bakın. struct.unpack ile okuma, bu şekilde denemek istiyorsanız, umarım faydalı bir başlangıç ​​noktası olacaktır. – mtrw

+1

'np.getbuffer (x1.ravel())' 'ı deneyin. Ayrıca, '' x0.tostring() '' yerine '' x0.tofile() '' kullanma hakkında ne? Endianess hakkında endişeleriniz varsa http://docs.scipy.org/doc/numpy/user/basics.byteswapping.html – Dietrich

+0

'u unuttum: Çok boyutlu diziler oluştururken, "order" parametresini kullanarak belleğe yazılma yolu: http://docs.scipy.org/doc/numpy/reference/generated/numpy.array.html – Dietrich

cevap

1

o DALGA bir 8-bit dosyasını Not diğerleri (16 veya 32-bit) imzasız olması gerekir, oysa imzalanmalıdır

Benim için çalışan bazı kirli demo kodu:.

yerine tostring` `arasında
import wave 
import numpy as np 

SAMPLERATE=44100 
BITWIDTH=8 
CHANNELS=2 

def gensine(freq, dur): 
    t = np.linspace(0, dur, round(dur*SAMPLERATE)) 
    x = np.sin(2.0*np.pi*freq*t) 
    if BITWIDTH==8: 
     x = x+abs(min(x)) 
     x = np.array(np.round((x/max(x)) * 255) , dtype=np.dtype('<u1')) 
    else: 
     x = np.array(np.round(x * ((2**(BITWIDTH-1))-1)), dtype=np.dtype('<i%d' % (BITWIDTH/8))) 

    return np.repeat(x,CHANNELS).reshape((len(x),CHANNELS)) 

output_file="test.wav" 

outfile = wave.open(output_file, mode='wb') 
outfile.setparams((CHANNELS, BITWIDTH/8, SAMPLERATE, 0, 'NONE', 'not compressed')) 
outfile.writeframes(gensine(440, 1).tostring()) 
outfile.writeframes(gensine(880, 1).tostring()) 
outfile.close() 
İlgili konular