Last active
July 17, 2024 02:21
-
-
Save mouseos/6e163adda6b696314a34a79d0f69bf46 to your computer and use it in GitHub Desktop.
入力音声と同じ周波数特性を持ったノイズを生成する
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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