pythonで音声(wavファイル)のビットデプスを落としたいです。(16bit→8bit)
プログラムを作成してみたのですが、音がかなりバリバリしていてノイズものっていて、あまり聞けるようなものではありませんでした。
wavを読み込む(モノラルでビットデプスは2Byte) ↓ 2Byteずつ読み込み、1Byteに落とす 。(1Byteに落とすために256で割っただけ) ↓ wavを出力
1Byteに落とすために256で割るだけでは、一般的な処理として不足しているのでしょうか?
該当のソースコード
python
1import pathlib 2import wave 3import pydub 4import numpy as np 5from pathlib import Path 6 7def monaural_down_depth(input_file: Path, output_file: Path): 8 9 wave_file = wave.open(str(input_path), "r") 10 11 frames = wave_file.readframes(wave_file.getnframes()) # frameの読み込み 12 frames = np.frombuffer(frames, dtype="int16").copy() # numpy.arrayに変換 13 14 data = [] 15 i = 0 16 while True: 17 if frames.shape[0]-1 <= i: 18 break 19 20 element1 = (int)(((frames[i]) / (2 ** 8)).item())#1byteに収める 21 i += 1 22 element2 = (int)(((frames[i]) / (2 ** 8)).item())#1byteに収める 23 i += 1 24 25 b = (element1.to_bytes(1, byteorder="big", signed=True) + element2.to_bytes(1, byteorder="big", signed=True)) 26 data.append(int.from_bytes(b, byteorder="big")) 27 28 data = np.array(data, dtype="int16") 29 30 # wavデータ書き込み用のファイルを作成 31 write_file = wave.open(str(output_file), "wb") 32 33 # wavを書き込むための設定 34 write_file.setnchannels(1) # チャンネル数 35 write_file.setsampwidth(1) # ビットデプス 36 write_file.setframerate(wave_file.getframerate()) # サンプリングレート 37 38 bytearray_data = bytearray(data) # listを元にbytearrayオブジェクトを作成 39 write_file.writeframes(bytearray_data) # ファイルに書き込み 40 write_file.close()
> 1Byteに落とすために256で割るだけでは、一般的な処理として不足しているのでしょうか?
https://docs.python.org/ja/3/library/audioop.html#audioop.lin2lin
の「audioop.lin2lin」の「注釈」に、
「8 bit に変換する場合は、変換結果に128を足さなければなりません」
と書かれてます
ありがとうございます。
見事に解決しました。
waveのpydocを見てもあまり情報がありませんでしたが、audioopというのを内部で使っているんですね。
ノイズは、まさに符号付き二進数を符号なしに変換せず書き込んだせいです。
私が利用した音源は16bit時点で-1などが含まれていましたが、これをそのまま書き込んでしまえば8bit_wavが認識する値は255になってしまうので音がおかしくなるのも納得です。
音に関する理論はまだまだ理解が浅いですが、ひとまず解決しましたので、自己解決にコードを書いて終了とさせていただきます。ありがとうございました。
回答1件
あなたの回答
tips
プレビュー