Wizard Notes

Python, JavaScript を使った音楽信号分析の技術録、作曲活動に関する雑記

Python:様々な拡張子&複数の楽曲ファイルを読み込んでNumPy配列として格納(wav, flac, mp3, aac, m4a, alac, etc.)

表題のとおり,様々な拡張子に対応し,複数の楽曲ファイルを一括でNumpy配列に変換する関数です。

大量の音楽ファイルを分析する場合にオススメです。

ファイルの読み込みは librosa.load() を使っています。

librosa.load()は引数にサンプリング周波数を与えることで,楽曲ファイルのサンプリング周波数と引数にサンプリング周波数が異なる場合,resampy でリサンプリングしてくれます

ただし、リサンプリングは割と処理時間がかかるので注意が必要です*1

librosa.load()が扱いにくい場合は、PySoundFileを直接使うのがよいと思います。

# -*- coding: utf-8 -*-
import os, sys
import glob
import librosa
import numpy as np
from pathlib import Path
from itertools import chain
from pprint import pprint


def load_multiple_audio_files(
        dirpath,
        sr=44100,
        exts=[".wav", ".flac", ".mp3", ".m4a"],
    ):
    exts = exts + [_.upper() for _ in exts]
    if os.path.isdir(dirpath):
        p = Path(dirpath)
        filepath_list = list(chain.from_iterable([list(p.glob(f"*{ext}")) for ext in exts]))
    
        if len(filepath_list) < 1:
            print(f"the directory does not contain any audio files")
            return [], []
    
        print(filepath_list)
        signal_list = [None for k in range(len(filepath_list))]

        for idx, filepath in enumerate(filepath_list):
            #filepath = os.path.normpath(filepath).replace("\\", "/")
            filepath = str(filepath)
            filename = os.path.splitext(os.path.split(filepath)[1])[0]
            try:
                y, _ = librosa.load(filepath, sr=sr, mono=False, 
                                offset=0, duration=None)
            except Exception as e:
                print("Error: can not load the audiofile:")
                print(f"\t{filepath}")
                print(f"\t{e}")
                return [], []
            
            signal_list[idx] = y
    else:
        print("the directory is not exists:")
        print(f"\t{dirpath}")
        signal_list, filepath_list = [], []
        
    return signal_list, filepath_list 


if __name__ == '__main__':
    dirpath = sys.argv[1]
    signal_list, filepath_list  = load_multiple_audio_files(dirpath)

    import code
    console = code.InteractiveConsole(locals=locals())
    console.interact()

*1:特に,48 kHz <=> 44.1 kHz のような補間係数/補完係数が大きくなる変換