質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

1回答

431閲覧

音声プログラミングでビットデプスを落としたい

atushi3333

総合スコア15

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2022/09/01 10:24

編集2022/09/01 10:26

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()

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jbpb0

2022/09/01 23:18 編集

> 1Byteに落とすために256で割るだけでは、一般的な処理として不足しているのでしょうか? https://docs.python.org/ja/3/library/audioop.html#audioop.lin2lin の「audioop.lin2lin」の「注釈」に、 「8 bit に変換する場合は、変換結果に128を足さなければなりません」 と書かれてます
atushi3333

2022/09/02 08:29

ありがとうございます。 見事に解決しました。 waveのpydocを見てもあまり情報がありませんでしたが、audioopというのを内部で使っているんですね。 ノイズは、まさに符号付き二進数を符号なしに変換せず書き込んだせいです。 私が利用した音源は16bit時点で-1などが含まれていましたが、これをそのまま書き込んでしまえば8bit_wavが認識する値は255になってしまうので音がおかしくなるのも納得です。 音に関する理論はまだまだ理解が浅いですが、ひとまず解決しましたので、自己解決にコードを書いて終了とさせていただきます。ありがとうございました。
guest

回答1

0

自己解決

解決しました。
詳細は質問への追記・修正依頼をご覧ください。

※コードは完全ではありませんので注意してください

python

1 2def monaural_down_depth8(input_file: Path, output_file: Path = None): 3 if output_file is None: 4 output_file = Path(f"{input_file.parent}/{input_file.stem}_down_d8.wav") 5 6 wave_file = wave.open(str(input_file), "r") 7 8 print_wave_info(wave_file) 9 10 frames = wave_file.readframes(wave_file.getnframes()) # frameの読み込み 11 frames = np.frombuffer(frames, dtype="int16").copy() # numpy.arrayに変換 符号付き16bit整数 12 data = [] 13 14 i = 0 15 while True: 16 if frames.shape[0] - 1 <= i: 17 if frames.shape[0] % 2 != 0: 18 element1 = (((frames[i]) / (2 ** 8)).item()).to_bytes(1, byteorder="big", signed=False) # 1byteに収める 19 data.append(int.from_bytes(element1 + b'0')) 20 break 21 22 element1 = (int)(((frames[i]) / (2 ** 8)).item()) + 128 # 1byteに収める item()はnumpy.float64をfloatに 23 print(element1) 24 i += 1 25 element2 = (int)(((frames[i]) / (2 ** 8)).item()) + 128 # 1byteに収める 26 print(element2) 27 28 print(element1.to_bytes(1, byteorder="big", signed=False) + element2.to_bytes(1, byteorder="big", signed=False)) 29 i += 1 30 # print(element1.to_bytes(1, byteorder="big", signed=False)) 31 32 b = (element1.to_bytes(1, byteorder="big", signed=False) + element2.to_bytes(1, byteorder="big", signed=False)) 33 34 data.append(int.from_bytes(b, byteorder="big")) 35 36 data = np.array(data, dtype="int16") 37 38 # wavデータ書き込み用のファイルを作成 39 write_file = wave.open(str(output_file), "wb") 40 41 # wavを書き込むための設定 42 write_file.setnchannels(1) # チャンネル数 43 write_file.setsampwidth(1) # ビットデプス(サンプルノイズ) 44 write_file.setframerate(wave_file.getframerate()) # サンプリングレート 45 46 bytearray_data = bytearray(data) # listを元にbytearrayオブジェクトを作成 47 write_file.writeframes(bytearray_data) # ファイルに書き込み 48 write_file.close() 49

投稿2022/09/02 08:34

atushi3333

総合スコア15

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問