Skip to content

Instantly share code, notes, and snippets.

@mouseos
Last active July 17, 2024 02:21
Show Gist options
  • Save mouseos/6e163adda6b696314a34a79d0f69bf46 to your computer and use it in GitHub Desktop.
Save mouseos/6e163adda6b696314a34a79d0f69bf46 to your computer and use it in GitHub Desktop.
入力音声と同じ周波数特性を持ったノイズを生成する
import numpy as np
import matplotlib.pyplot as plt
from scipy.io import wavfile
from scipy.signal import stft, istft
import os
import japanize_matplotlib
# wavファイルを読み込む
sample_rate, data = wavfile.read('./output.wav')
bit_depth = data.dtype.itemsize * 8 # 量子化ビット数を計算する
full_scale = 2 ** (bit_depth - 1) # 0 dBFSの値を計算する
# ステレオの場合、片方のチャンネルのみを使用する
if len(data.shape) > 1:
data = data[:, 0]
# 10分間のサンプル数
segment_duration = 10 * 60 # 10分
segment_samples = segment_duration * sample_rate
# ディレクトリ作成
output_dir = './tmp'
os.makedirs(output_dir, exist_ok=True)
# 分割と処理
num_segments = len(data) // segment_samples
if num_segments == 0:
num_segments = 1
all_averages = []
for i in range(num_segments):
print(f'{i+1}/{num_segments}')
segment = data[i * segment_samples: (i + 1) * segment_samples]
f, t, Zxx = stft(segment,window='hann', fs=sample_rate, nperseg=4096*2*2)
magnitude = np.abs(Zxx)
magnitude_dbfs = 20 * np.log10(magnitude / full_scale + 1e-10)
average_magnitude_dbfs = np.mean(magnitude_dbfs, axis=1)
all_averages.append(average_magnitude_dbfs)
# 各セグメントの平均を結合
final_average = np.mean(all_averages, axis=0)
# ホワイトノイズの生成
duration = 60 # 60秒間のホワイトノイズを生成する
white_noise = np.random.randn(duration * sample_rate)
# ホワイトノイズのFFT解析
f_noise, t_noise, Zxx_noise = stft(white_noise,window='hann', fs=sample_rate, nperseg=4096*2*2)
magnitude_noise = np.abs(Zxx_noise)
magnitude_dbfs_noise = 20 * np.log10(magnitude_noise / full_scale + 1e-10)
# イコライザーカーブの適用
equalized_magnitude_dbfs = np.zeros_like(magnitude_dbfs_noise)
for i in range(len(f_noise)):
idx = np.argmin(np.abs(f_noise[i] - f))
equalized_magnitude_dbfs[i, :] = magnitude_dbfs_noise[i, :] + (final_average[idx] - np.mean(final_average))
# 逆FFTで時間領域に戻す
_, equalized_noise = istft(Zxx_noise * 10**(equalized_magnitude_dbfs / 20), fs=sample_rate)
# 音声ファイルとして保存する場合
wavfile.write('./equalized_output.wav', sample_rate, np.int16(equalized_noise * full_scale / np.max(np.abs(equalized_noise))))
print(f"処理済みのホワイトノイズを保存しました。")
# グラフを同じウィンドウに表示
plt.figure(figsize=(12, 10))
# 入力音源のFFT解析結果をプロット (折れ線グラフ)
plt.subplot(2, 1, 1)
plt.plot(f, average_magnitude_dbfs)
plt.title('入力音源のFFT解析 (dBFS)')
plt.xlabel('周波数 (Hz)')
plt.ylabel('振幅 (dBFS)')
plt.grid()
# イコライザーカーブを適用したホワイトノイズのFFT解析結果をプロット (折れ線グラフ)
plt.subplot(2, 1, 2)
plt.plot(f_noise, np.mean(equalized_magnitude_dbfs, axis=1)) # ここでは1つのタイムスライスのデータを使用しています
plt.title('周波数特性を一致させたホワイトノイズのFFT解析 (dBFS)')
plt.xlabel('周波数 (Hz)')
plt.ylabel('振幅 (dBFS)')
plt.grid()
plt.tight_layout()
plt.show()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment