Download sample_code_c5_2.py from tUeda1223/iPhoneBlindSourceSeparation: direct link, hf CLI and curl.
- Browser
- Download file 5.17 kB
-
https://huggingface.co/spaces/tUeda1223/iPhoneBlindSourceSeparation/resolve/main/sample_code_c5_2.py
- Command line
-
hf download hf://spaces/tUeda1223/iPhoneBlindSourceSeparation/sample_code_c5_2.py
-
curl -L -o sample_code_c5_2.py https://huggingface.co/spaces/tUeda1223/iPhoneBlindSourceSeparation/resolve/main/sample_code_c5_2.py
5.17 kB
| ''' | |
| このコードはPythonで学ぶ音源分離(第5章)のサンプルコード5-2を改変したものです. | |
| https://raw.githubusercontent.com/masahitotogami/python_source_separation/master/section5/sample_code_c5_2.py | |
| ''' | |
| import os | |
| import requests | |
| import tarfile | |
| import wave as wave | |
| import pyroomacoustics as pa | |
| import numpy as np | |
| import random | |
| def download_and_extract_cmu_arctic(): | |
| folder_name = "cmu_arctic_concat15" | |
| tar_filename = "cmu_arctic_concat15.tar.gz" | |
| url = "https://zenodo.org/records/3066489/files/cmu_arctic_concat15.tar.gz?download=1" | |
| # 既にフォルダがある場合は処理しない | |
| if os.path.exists(folder_name): | |
| print(f"📂 フォルダ '{folder_name}' は既に存在しています。ダウンロードしません。") | |
| return | |
| print(f"⬇️ '{folder_name}' が見つかりません。ダウンロード開始...") | |
| # ===== ダウンロード ===== | |
| response = requests.get(url, stream=True) | |
| response.raise_for_status() | |
| with open(tar_filename, "wb") as f: | |
| for chunk in response.iter_content(chunk_size=8192): | |
| f.write(chunk) | |
| print(f"📦 ダウンロード完了: {tar_filename}") | |
| # ===== 展開 ===== | |
| print(f"📂 展開中...") | |
| with tarfile.open(tar_filename, "r:gz") as tar: | |
| tar.extractall() | |
| print("🎉 展開完了!") | |
| # ===== ダウンロードファイル削除 ===== | |
| os.remove(tar_filename) | |
| print(f"🧹 掃除完了: {tar_filename} を削除しました") | |
| def main(audio_output="mixed_audio.wav"): | |
| # CMU Arcticデータセットをダウンロード・展開 | |
| download_and_extract_cmu_arctic() | |
| # 乱数の種を初期化 | |
| np.random.seed(0) | |
| # ===== ① 使用する音源ファイル ===== | |
| base_dir = "cmu_arctic_concat15/" | |
| files = os.listdir(base_dir) | |
| wav_files = [ | |
| base_dir + f for f in files | |
| if not f.startswith(".") and f.endswith(".wav") | |
| ] | |
| clean_wave_files = random.sample(wav_files, 2) | |
| # 音源数 | |
| n_sources = len(clean_wave_files) | |
| # 長さを調べる | |
| n_samples = 0 | |
| n_samples_min = 1e10 | |
| for clean_wave_file in clean_wave_files: | |
| wav = wave.open(clean_wave_file) | |
| if n_samples < wav.getnframes(): | |
| n_samples = wav.getnframes() | |
| n_samples_min = min(n_samples_min, wav.getnframes()) | |
| wav.close() | |
| clean_data = np.zeros([n_sources, n_samples]) | |
| # ファイルを読み込む | |
| s = 0 | |
| for clean_wave_file in clean_wave_files: | |
| wav = wave.open(clean_wave_file) | |
| data = wav.readframes(wav.getnframes()) | |
| data = np.frombuffer(data, dtype=np.int16) | |
| data = data / np.iinfo(np.int16).max # -1〜1に正規化 | |
| clean_data[s, :wav.getnframes()] = data | |
| wav.close() | |
| s = s + 1 | |
| # ===== シミュレーションのパラメータ ===== | |
| sample_rate = 16000 # サンプリング周波数 | |
| SNR = 50. # 音声と雑音の比率 [dB] | |
| room_dim = np.r_[10.0, 10.0, 10.0] # 部屋の大きさ | |
| # マイクロホンアレイを置く部屋の場所 | |
| mic_array_loc = room_dim / 2 + np.random.randn(3) * 0.1 | |
| # マイクロホンアレイのマイク配置(2ch固定) | |
| mic_alignments = np.array( | |
| [ | |
| [-0.01, 0.0, 0.0], | |
| [0.01, 0.0, 0.0], | |
| ] | |
| ) | |
| n_channels = mic_alignments.shape[0] | |
| R = mic_alignments.T + mic_array_loc[:, None] | |
| # 部屋を生成する | |
| room = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0) | |
| # マイクロホンアレイの情報を設定 | |
| room.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs)) | |
| # 音源の場所 | |
| doas = np.array( | |
| [[np.pi/2., 0], | |
| [np.pi/2., np.pi/2.]] | |
| ) | |
| distance = 1. | |
| source_locations = np.zeros((3, doas.shape[0]), dtype=doas.dtype) | |
| source_locations[0, :] = np.cos(doas[:, 1]) * np.sin(doas[:, 0]) | |
| source_locations[1, :] = np.sin(doas[:, 1]) * np.sin(doas[:, 0]) | |
| source_locations[2, :] = np.cos(doas[:, 0]) | |
| source_locations *= distance | |
| source_locations += mic_array_loc[:, None] | |
| # 各音源を部屋に追加 | |
| for s in range(n_sources): | |
| clean_data[s] /= np.std(clean_data[s]) | |
| room.add_source(source_locations[:, s], signal=clean_data[s]) | |
| # ===== シミュレーション実行 ===== | |
| room.simulate(snr=SNR) | |
| # ===== ステレオ1つのファイルとして保存 ===== | |
| multi_conv_data = room.mic_array.signals # (channels, samples) | |
| # int16スケール調整 | |
| data_scaled_L = (multi_conv_data[0] * np.iinfo(np.int16).max / 10).astype(np.int16) | |
| data_scaled_R = (multi_conv_data[1] * np.iinfo(np.int16).max / 10).astype(np.int16) | |
| # ステレオ結合 | |
| stereo_data = np.stack([data_scaled_L, data_scaled_R], axis=1)[:n_samples_min] | |
| # ===== 保存 ===== | |
| out = wave.open(audio_output, "w") | |
| out.setnchannels(2) | |
| out.setsampwidth(2) # int16 | |
| out.setframerate(sample_rate) | |
| out.writeframes(stereo_data.tobytes()) | |
| out.close() | |
| print(f"🎧 {audio_output} を生成しました(2chステレオ)") | |
| if __name__ == "__main__": | |
| main() |