物理の駅 Physics station by 現役研究者

テクノロジーは共有されてこそ栄える

音源編集(3) 分割と結合

ノイズ処理のためには、長尺音源は分割したほうがメモリの観点で処理速度が速くなる。以下は300秒ごとに5秒ごとのオーバーラップ付きで分割する方法。300秒のところは尺にあわせて調整すべし。

import librosa
import soundfile as sf
import os
import numpy as np

# 入力ファイルと出力先
input_path = 'input.wav'
output_dir = './split_audio'
os.makedirs(output_dir, exist_ok=True)

# ロード
y, sr = librosa.load(input_path, sr=None, mono=False)  # shape: (2, n_samples)

# パラメータ
chunk_duration = 300  # 秒
overlap = 5           # 秒
chunk_samples = int(chunk_duration * sr)
overlap_samples = int(overlap * sr)
step = chunk_samples - overlap_samples
total_samples = y.shape[1]

# 分割と保存
start = 0
index = 0
while start < total_samples:
    end = min(start + chunk_samples, total_samples)
    chunk = y[:, start:end]
    output_path = os.path.join(output_dir, f'chunk_{index:03}.wav')
    sf.write(output_path, chunk.T, sr)
    index += 1
    start += step

分割した音源に何らかの処理を適用した想定で、オーバーラップの5秒部分をフェードしながら結合する。単純に係数 0-1、1-0でフェードして線形結合するだけ。natsort は pip install natsort でインストールする。

import soundfile as sf
import numpy as np
import glob
import os
from natsort import natsorted

# パス設定
folder = "./split_audio"
files = natsorted(glob.glob(os.path.join(folder, "*(Vocals).wav")))
output_path = "output.wav"

# パラメータ
sr = None
fade_duration = 5  # 秒
fade_samples = None
output = None

for i, filepath in enumerate(files):
    y, sr = sf.read(filepath)  # shape: (samples, channels)
    y = y.T  # (channels, samples)
    
    if fade_samples is None:
        fade_samples = int(fade_duration * sr)

    if i == 0:
        output = y
    else:
        # 前の末尾と現在の先頭をフェード処理
        prev = output[:, -fade_samples:]
        curr = y[:, :fade_samples]

        # フェード係数
        fade_out = np.linspace(1, 0, fade_samples)
        fade_in = np.linspace(0, 1, fade_samples)

        # クロスフェード
        crossfaded = prev * fade_out + curr * fade_in

        # 結合
        output = np.concatenate([output[:, :-fade_samples], crossfaded, y[:, fade_samples:]], axis=1)

# 出力
sf.write(output_path, output.T, sr)  # (samples, channels)