【Python/numpy/soundfile】wavを指定したフォーマット(周波数など)に変換する

ネコニウム研究所

PCを利用したモノづくりに関連する情報や超個人的なナレッジを掲載するブログ

【Python/numpy/soundfile】wavを指定したフォーマット(周波数など)に変換する

2023-7-11 |

Pythonでnumpyとsoundfileを使ってwavを指定したフォーマット(周波数など)に変換したい!

概要

今回の記事では、Pythonでnumpyとsoundfileを使ってwavを指定したフォーマット(周波数など)に変換するサンプルを掲載する。

仕様書

環境

  • Python 3.10.6

手順書

今回はnumpyとsoundfileというライブラリを使うのでインストールする。

pip install numpy soundfile

下記は、inフォルダに保存されてるwavファイルをに指定のフォーマットに変換してoutフォルダに出力する例。

to_rateに周波数、to_subtypeにはエンコードの種類、to_channelsにチャンネル数を指定する。

import os
import wave
import numpy as np
import soundfile as sf

in_dir = "in/"
out_dir = "out/"

to_rate = 44100
to_subtype = 'PCM_16'
to_channels = 2

for filename in os.listdir(in_dir):
    if filename.endswith(".wav"):
        wav_path = os.path.join(in_dir, filename)
        print("formatting: ", wav_path)
        base_name = os.path.splitext(filename)[0]
        formated_dir = os.path.join(out_dir, base_name + ".wav")
        data, rate = sf.read(wav_path)

        if to_subtype == 'FLOAT' and info.subtype != 'FLOAT':
            print('to float32')
            to_data = data.astype(np.float32)
        elif to_subtype == 'DOUBLE' and info.subtype != 'DOUBLE':
            print('to float64')
            to_data = data.astype(np.float64)
        elif to_subtype == 'int8' and info.subtype != 'PCM_8':
            print('to int8')
            to_data = (data * np.iinfo(np.int8).max).astype(np.int8)
        elif to_subtype == 'PCM_16' and info.subtype != 'PCM_16':
            print('to int16')
            to_data = (data * np.iinfo(np.int16).max).astype(np.int16)
        elif to_subtype == 'PCM_24' and info.subtype != 'PCM_24':
            print('to int24')
            to_data = (data * np.iinfo(np.int24).max).astype(np.int24)
        elif to_subtype == 'PCM_32' and info.subtype != 'PCM_32':
            print('to int32')
            to_data = (data * np.iinfo(np.int32).max).astype(np.int32)
        elif to_subtype == 'PCM_64' and info.subtype != 'PCM_64':
            print('to int64')
            to_data = (data * np.iinfo(np.int64).max).astype(np.int64)
        elif to_subtype == 'PCM_128' and info.subtype != 'PCM_128':
            print('to int128')
            to_data = (data * np.iinfo(np.int128).max).astype(np.int128)
        else:
            print('to none')
            to_data = data

        if to_channels == 1 and to_data.shape[1] > 1:
            to_data = np.mean(to_data, axis=1)
        elif to_channels == 2 and len(to_data.shape) == 1:
            to_data = np.vstack([to_data, to_data]).T
        elif to_channels == 2 and len(to_data.shape) > 2:
            to_data = to_data[:, [0, 1]]
        elif to_channels == 3 and len(to_data.shape) > 3:
            to_data = to_data[:, [0, 1, 2]]

        print(to_data.shape)
        sf.write(formated_dir, to_data, to_rate, format='WAV', subtype=to_subtype)

今回はCDと同じ音質のWAVファイルに変換してる。

to_rate = 44100
to_subtype = 'PCM_16'
to_channels = 2

機械学習で使われるFLOAT型に変換したい場合は下記のような感じ。

to_rate = 44100
to_subtype = 'FLOAT'
to_channels = 2

よく使われるビット深度やチャンネル数の変換は実装してるんだけども、全パターンを網羅してるわけでないことを留意されたし。

まとめ(感想文)

これも、音声を機械学習させる前の下処理に使えるかもね!