Pythonのなみのり! ぱーと2
前回、と言っても相当前ですけど、Pythonでwavファイルを読み込むってのを記事にしました。
今回はその焼き直しですが、かなり仕様みたいのは買えました。
いちいちキー指定なんてしてらんねーよ。
と、自分でも思ったので。
オブジェクト指向的なプログラミングを意識したつもりなんですが、そもそもオブジェクト指向を理解していないので、全然違う実装になっていると思います。
ソースは以下。
struct.unpackのくだりが遅いのは相変わらず。
格納をリストではなく文字列にしたり、ファイルの読み込みの段階からunpackしたりして実効速度の向上を図ってみましたが、結局この方法に落ち着きました。
コメントの英語に対するツッコミはご遠慮願います。
ソースコード:
#!/usr/bin/env python #coding: utf-8 import struct class wavUtils(object): """ This class is utilities for wav file. At first, you make instance this class. Then, use "load" method for reading a wav file. """ def __init__(self): self.__raw = None self.__raw_data = None self.__raw_header = None self.__unpacked_header = None self.__unpacked_data = None self.__meta_data = None def getDataList(self): return self.__unpacked_data def getHeaderList(self): return self.__unpacked_header def getPropertyList(self): return self.__meta_data def getRawStr(self): return self.__raw def getRawDataStr(self): return self.__raw_data def getRawHeaderStr(self): return self.__raw_header def load(self, fname): """ At first, loading wav file in self.__raw. Then, separates self.__raw for header part and date part. Last, unpack binary data for int. Unpacking data needs time. """ fp = open(fname, "rb") self.__raw = fp.read() fp.close() # separate header part and data part. header_end = self.__raw.find('data')+8 self.__raw_header = self.__raw[:header_end] self.__raw_data = self.__raw[header_end:] # unpacked header and data self.__unpackRawHeader() self.__unpackRawData() def __unpackRawData(self): seek_head = 0 tmp_result = [] # counter tool's values cnt = 1 cnt_delta = len(self.__raw_data)/10 # 16 bit/sample? 8 bit/sample? if self.__unpacked_header[7] == 8: unpack_fmt = '<H' seek_delta = 1 else: unpack_fmt = '<h' seek_delta = 2 print "Now converting that binary for Integer..." while seek_head < len(self.__raw_data): tmp_result.append(struct.unpack(unpack_fmt, self.__raw_data[seek_head:seek_head+seek_delta])[0]) seek_head += seek_delta # counter tool's implements if seek_head >= (cnt_delta*cnt): for i in range(cnt): print ".", if cnt==10: print cnt*10, "% done. Converting finish!" else: print cnt*10, "% done." cnt+=1 self.__unpacked_data = tmp_result def __unpackRawHeader(self): """ This method unpack header from binary for int. And after unpacking, this makes property list. """ tmp_result = [] for current_chunk in ('RIFF','fmt','data'): tmp_value = 0 seek_head = self.__raw_header.find(current_chunk) if current_chunk == 'fmt': seek_head += 4 for seek_delta in (4,2,2,4,4,2,2): if seek_delta == 4: tmp_value = struct.unpack('<I',self.__raw_header[seek_head:seek_head+seek_delta])[0] else: tmp_value = struct.unpack('<H',self.__raw_header[seek_head:seek_head+seek_delta])[0] seek_head += seek_delta tmp_result.append(tmp_value) else: tmp_value = struct.unpack('<I',self.__raw_header[seek_head+4:seek_head+8])[0] tmp_result.append(tmp_value) self.__unpacked_header = tmp_result # Make property list. tmp_result = [] wav_head_ref = ("File size (minus 8 byte).", "fmt chunk size", "FormatID", "channel", "sampling rate", "Byte/sec", "block size(Byte/sample*channel)", "bit number(bit/sample)", "data size") for i in range(len(self.__unpacked_header)): tmp_result.append((wav_head_ref[i], self.__unpacked_header[i])) # add information of "bit rate". tmp_result.append(("bit rate (Byte/sec*8)", self.__unpacked_header[5]*8)) self.__meta_data = tmp_result def main(): wu = wavUtils() wu.load("sample.wav") print wu.getRawStr()[0:5], wu.getRawHeaderStr(), wu.getHeaderList()[7] print wu.getDataList()[100000:100100] print wu.getPropertyList() if __name__ == "__main__": main()
あとがき:
まあ、前回掲載したものよりは、使いやすいと思います。
ソースも、心なしすっきりしたように見えます。
ああ、気のせいですか、そうですか。
オブジェクト指向って、こういうのじゃないのかなぁ……