[
  {
    "path": "LICENSE.txt",
    "content": "MIT License\r\n\r\nCopyright (c) 2020 Masahito Togami\r\n\r\nPermission is hereby granted, free of charge, to any person obtaining a copy\r\nof this software and associated documentation files (the \"Software\"), to deal\r\nin the Software without restriction, including without limitation the rights\r\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\ncopies of the Software, and to permit persons to whom the Software is\r\nfurnished to do so, subject to the following conditions:\r\n\r\nThe above copyright notice and this permission notice shall be included in all\r\ncopies or substantial portions of the Software.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r\nSOFTWARE."
  },
  {
    "path": "README.md",
    "content": "## Pythonで学ぶ音源分離（機械学習実践シリーズ）のソースコード\n\n![Python 3.6](https://img.shields.io/badge/Python-3.6-green.svg)\n![License](https://img.shields.io/badge/Code%20License-MIT-green.svg)\n\n本リポジトリでは、インプレス社機械学習実践シリーズの「Pythonで学ぶ音源分離」のサンプルコードを管理しています。\nなお、本ソースコードは、MITライセンスのもとで公開されています。LICENSE.txtを見てください。\n\n## 書籍概要\n\n![Pythonで学ぶ音源分離カバー](cover.jpg)\n* [Pythonで学ぶ音源分離（機械学習実践シリーズ）](https://book.impress.co.jp/books/1119101154 \"Pythonで学ぶ音源分離（機械学習実践シリーズ）\")\n* 価格: 3,500円+税\n* 発売日: 2020年8月24日\n* ページ数: 352\n* サイズ: B5変形判\n* 著者: 戸上 真人\n* ISBN: 9784295009849\n\n## 目次\n* 序章\n* 第1章 音源分離とは？\n* 第2章 音声処理の基礎\n* 第3章 音源分離で用いる数学的知識の基礎（線形代数、ベクトル・行列の微分）\n* 第4章 「最適化」に関する技法を理解する\n* 第5章 シミュレーターで音を作ってみる\n* 第6章 古典的な音源分離方法～ビームフォーミング～\n* 第7章 音源方向推定に基づく音源分離\n* 第8章 現代的な統計的モデルに基づく音源分離法\n* 第9章 響きのある音を響きのない音に変える残響除去法\n* 第10章 音源分離と残響除去を統合的に実行する\n* 第11章 音源分離関連のライブラリ紹介・その他のトピック・参考文献\n\n## 各章のサンプルコード\n* [本書の前提](install.md)\n* [第2章のサンプルコード](section2.md)\n* [第3章のサンプルコード](section3.md)\n* [第4章のサンプルコード](section4.md)\n* [第5章のサンプルコード](section5.md)\n* [第6章のサンプルコード](section6.md)\n* [第7章のサンプルコード](section7.md)\n* [第8章のサンプルコード](section8.md)\n* [第9章のサンプルコード](section9.md)\n* [第10章のサンプルコード](section10.md)\n* [第11章のサンプルコード](section11.md)\n## お詫びと訂正\nPythonで学ぶ音源分離（機械学習実践シリーズ）に誤りがありました。ここに謹んでお詫び申し上げますと共に，以下のページに正誤表を\n掲載させて頂きます。\n\n[本書の正誤表](errata.md)\n\n## License\nMIT\n"
  },
  {
    "path": "errata.md",
    "content": "## 正誤表\n|項番|該当箇所|誤|正|update|\n|---|---|---|---|---|\n|1|p.2| pip install itertools | 削除　|2020/08/24|\n|2|第4章第5節タイトル, p4, p.135 | Maximization-Majorization | Majorization-Minimization | 2020/08/24|\n|3|p.10| 「知り当たった」|「知り合った」|2020/08/24|\n|4|第二章|code2.1とcode2.9が欠番。（コードを削除したことに起因）|-|2020/08/24|\n|5|p.60|code2.14|code2.15|2020/08/24|\n|6|p.97|code3.9|result3.1|2020/08/24|\n|7|p.82| 「このとき、m<Mでβmは0となり、」|「このとき、m<Mでβmは0となることがありますが、」|2020/08/24|\n|8|p.151| 図5.5 雑音・残響環境のスペクトログラム ![図5.5](err_fig_5_5.png)|図5.5 雑音・残響環境のスペクトログラム ![図5.5](fig_5_5.png)|2020/08/24|\n|9|p.175| mic_alignments = np.array（［ ［［x,0.0,0.0］ for x in np.arange（-0.31,0.32,0.02）］ ］　） |  mic_alignments = np.array（ ［［x,0.0,0.0］ for x in np.arange（-0.31,0.32,0.02）］ 　）　|2020/08/24|\n|10|p.228| 「音声のスパース性に基づく音源分離の実行結果（マイクロホンの間隔40センチ）」|「マイクロホンの間隔を40センチに変更」|2020/08/24|\n|11|p.238| 「スパース性を利用した音源分離の実行例（マイクロホン間隔40センチ）」|「スパース性を利用した音源分離の実行例（マイクロホン36素子）」|2020/08/24|\n|12|p.326の表10-1の数値| LGM「14.69」、LGM＋Dreverb「20.71」|LGM「13.89」、LGM＋Dreverb「19.91」|2020/08/24|\n|13|p.336の表10-2の数値| ILRMA「14.38」、ILRMA+Dereverb「19.62」、ILRMA-T「18.05」|ILRMA「13.58」、ILRMA+Dereverb「18.82」、ILRMA-T「17.25」|2020/08/24|\n|14|p.340|「無残響環境と残響環境の二つの環境で実行しています。」 |「残響環境で実行しています。」|2020/08/24|\n|15|p.311|式(9.2)と |最小二乗法と|2020/08/25|\n|16|p.45|式(2.32) ![式2.32](err_eq_2_32.png) |式(2.32) ![式2.32](eq_2_32.png) |2020/08/27|\n|17|p.46|式(2.36) ![式2.36](err_eq_2_36.png) |式(2.36) ![式2.36](eq_2_36.png) |2020/08/27|\n|18|p.86|「単一行列 」|「大きさ1のベクトル」 |2020/08/27|\n|19|p.124|「という考え方です。」 |「という考え方に基づいてパラメータを最適化します。」|2020/08/27|\n|20|p.131|「と右辺が一致する（不等号の統合が成立する）」 |「であることから右辺が一致する（不等号の等号が成立する）」|2020/08/27|\n|21|p.139|「パラメータ法」 |「パラメータ最適化法」|2020/08/27|\n|22|p.41の5行目|「#複素共役を表示する」 |「#絶対値を表示する」|2020/11/13|\n|23|p.40|式(2.11) ![式2.11](err_eq_2_11.png) |式(2.11) ![式2.11](eq_2_11.png)|2021/05/25|\n|24|p.343|I. Dokmani? |I. Dokmanic|2021/05/25|\n|25|p.56|式(2.46) ![式2.46](err_eq_2_46.png) |式(2.46) ![式2.46](eq_2_46.png)|2021/05/25|\n|26|p.58|noise amp=np.power(np.mean(np.power(amp,p)［:,:n_noise_only_frame］,axis=1,keepdims=True),1./2) |noise amp=np.power(np.mean(np.power(amp,p)［:,:n_noise_only_frame］,axis=1,keepdims=True),1./p) |2021/05/25|\n\n"
  },
  {
    "path": "install.md",
    "content": "\n## 本書の前提\n* 本書の全てのソースコードは、Python3.6.4を使って動作を確認しています。\n* Python標準のライブラリ以外で必要となるライブラリをインストールする\nコマンドを以下に示します。\n```\n    $pip install numpy\n    $pip install scipy\n    $pip install matplotlib\n    $pip install sounddevice\n    $pip install pyroomacoustics\n    $pip install nara-wpe\n```\n    \n"
  },
  {
    "path": "section10/sample_code_c10_1.py",
    "content": "\r\nimport wave as wave\r\nimport pyroomacoustics as pa\r\nimport numpy as np\r\nimport scipy.signal as sp\r\nimport scipy as scipy\r\n\r\n#順列計算に使用\r\nimport itertools\r\nimport time\r\n\r\n#A: ...mn\r\n#B: ...ij\r\n#AとBの最後の二軸以外の次元は一致していることを前提とする\r\ndef batch_kron(A,B):\r\n if np.shape(A)[:-2]!=np.shape(B)[:-2]:\r\n     print(\"error\")\r\n     return None\r\n else:\r\n    return(np.reshape(np.einsum(\"...mn,...ij->...minj\",A,B),np.shape(A)[:-2]+(np.shape(A)[-2]*np.shape(B)[-2],np.shape(A)[-1]*np.shape(B)[-1])))\r\n\r\n\r\n#x:入力信号( M, Nk, Lt)\r\n#D:遅延フレーム数\r\n#Lh:残響除去フィルタのタップ長\r\n#return x_bar: 過去のマイク入力信号(Lh,M,Nk,Lt)\r\ndef make_x_bar(x,D,Lh):\r\n    \r\n    #フレーム数を取得\r\n    Lt=np.shape(x)[2]\r\n\r\n    #過去のマイク入力信号の配列を準備\r\n    x_bar=np.zeros(shape=(Lh,)+np.shape(x),dtype=np.complex)\r\n\r\n    for tau in range(Lh):\r\n        x_bar[tau,...,tau+D:]=x[:,:,:-(tau+D)]\r\n\r\n    return(x_bar)\r\n\r\n#IP法によるLGMのパラメータ推定法\r\n#x:入力信号( M, Nk, Lt)\r\n#Ns: 音源数\r\n#n_iterations: 繰り返しステップ数\r\n#return R 共分散行列(Nk,Ns,M,M) v 時間周波数分散(Nk,Ns,Lt),c_bar 音源分離信号(M,Ns,Nk,Lt), cost_buff コスト (T)\r\ndef execute_mm_lgm(x,Ns=2,n_iterations=20):\r\n    \r\n    #マイクロホン数・周波数・フレーム数を取得する\r\n    M=np.shape(x)[0]\r\n    Nk=np.shape(x)[1]\r\n    Lt=np.shape(x)[2]\r\n\r\n    #Rとvを初期化する\r\n    mask=np.random.uniform(size=Nk*Ns*Lt)\r\n    mask=np.reshape(mask,(Nk,Ns,Lt))\r\n    R=np.einsum(\"kst,mkt,nkt->kstmn\",mask,x,np.conjugate(x))\r\n    R=np.average(R,axis=2)\r\n    v=np.random.uniform(size=Nk*Ns*Lt)\r\n    v=np.reshape(v,(Nk,Ns,Lt))\r\n\r\n    cost_buff=[]\r\n    for t in range(n_iterations):\r\n        \r\n        #入力信号の共分散行列を求める\r\n        vR=np.einsum(\"kst,ksmn->kstmn\",v,R)\r\n        V=np.sum(vR,axis=1)\r\n        V_inverse=np.linalg.pinv(V)\r\n\r\n        #コスト計算\r\n        cost=np.sum(np.einsum(\"mkt,ktmn,nkt->kt\",np.conjugate(x),V_inverse,x) +np.log(np.abs(np.linalg.det(V))))\r\n        cost/=np.float(Lt)\r\n        cost=np.real(cost)\r\n        cost_buff.append(cost)\r\n\r\n        #パラメータを更新\r\n        \r\n        #Rの更新\r\n        V_inverseX=np.einsum('ktmn,nkt->ktm',V_inverse,x)\r\n        V_inverseXV_inverseX=np.einsum('ktm,ktn->ktmn',V_inverseX,np.conjugate(V_inverseX))\r\n        A=np.einsum('kst,ktmn->ksmn',v,V_inverse)\r\n        B=np.einsum('kst,ktmn->ksmn',v,V_inverseXV_inverseX)\r\n        RBR=np.einsum('ksmn,ksni,ksij->ksmj',R,B,R)\r\n        invA=np.linalg.pinv(A)\r\n        A_RBR=np.matmul(A,RBR)\r\n        R=np.concatenate([np.concatenate([np.matmul(invA[k,s,...],scipy.linalg.sqrtm(A_RBR[k,s,...]))[None,None,...] for k in range(Nk)],axis=0) for s in range(Ns)],axis=1)\r\n        R=(R+np.transpose(np.conjugate(R),[0,1,3,2]))/(2.0+0.0j)\r\n\r\n        #vの更新\r\n        v=v*np.sqrt(np.einsum('ktm,ktn,ksnm->kst',V_inverseX,np.conjugate(V_inverseX),R)/np.maximum(np.einsum('ktmn,ksnm->kst',V_inverse,R) ,1.e-18))\r\n\r\n       \r\n    vR=np.einsum(\"kst,ksmn->kstmn\",v,R)\r\n    V=np.sum(vR,axis=1)\r\n    V_inverse=np.linalg.pinv(V)\r\n    Wmwf=np.einsum(\"kstmi,ktin->kstmn\",vR,V_inverse)\r\n\r\n    #音源分離信号を得る\r\n    c_bar=np.einsum('kstmn,nkt->mskt',Wmwf,x)\r\n\r\n    return(R,v,c_bar,cost_buff)\r\n\r\n#LGMの音源分離と残響除去のパラメータ推定法\r\n#x:入力信号( M, Nk, Lt)\r\n#x_bar:過去のマイク入力信号(Lh,M, Nk, Lt)\r\n#Ns: 音源数\r\n#n_iterations: 繰り返しステップ数\r\n#return R 共分散行列(Nk,Ns,M,M) v 時間周波数分散(Nk,Ns,Lt),c_bar 音源分離信号(M,Ns,Nk,Lt), cost_buff コスト (T)\r\ndef execute_mm_lgm_dereverb(x,x_bar,Ns=2,n_iterations=20):\r\n    \r\n    #マイクロホン数・周波数・フレーム数を取得する\r\n    M=np.shape(x)[0]\r\n    Nk=np.shape(x)[1]\r\n    Lt=np.shape(x)[2]\r\n    Lh=np.shape(x_bar)[0]\r\n\r\n    x_bar=np.reshape(x_bar,[Lh*M,Nk,Lt])\r\n\r\n    #Rとvを初期化する\r\n    mask=np.random.uniform(size=Nk*Ns*Lt)\r\n    mask=np.reshape(mask,(Nk,Ns,Lt))\r\n    R=np.einsum(\"kst,mkt,nkt->kstmn\",mask,x,np.conjugate(x))\r\n    R=np.average(R,axis=2)\r\n    v=np.random.uniform(size=Nk*Ns*Lt)\r\n    v=np.reshape(v,(Nk,Ns,Lt))\r\n\r\n    #共分散行列を計算\r\n    x_bar_x_bar_H=np.einsum('ikt,jkt->ktij',x_bar,np.conjugate(x_bar))\r\n\r\n    #相関行列を計算\r\n    x_bar_x_H=np.einsum('ikt,mkt->ktim',x_bar,np.conjugate(x))\r\n\r\n    cost_buff=[]\r\n    for t in range(n_iterations):\r\n        #入力信号の共分散行列を求める\r\n        vR=np.einsum(\"kst,ksmn->kstmn\",v,R)\r\n        \r\n        V=np.sum(vR,axis=1)\r\n        V=V+np.eye(M,M)*1.e-8\r\n        V_inverse=np.linalg.inv(V)\r\n        \r\n        #残響除去フィルタを求める\r\n        x_barx_H_V_inv=np.einsum(\"ktim,ktmn->kin\",x_bar_x_H,V_inverse)\r\n\r\n        vec_x_bar_x_HV_inv=np.reshape(np.transpose(x_barx_H_V_inv,[0,2,1]),(Nk,Lh*M*M))\r\n        \r\n        #多次元配列対応版のクロネッカー積\r\n        V_inverse_x_x_H=batch_kron(np.transpose(V_inverse,(0,1,3,2)),x_bar_x_bar_H)\r\n\r\n        #vecHを求める\r\n        vec_h=np.einsum(\"kmr,kr->km\",np.linalg.inv(np.sum(V_inverse_x_x_H,axis=1)), vec_x_bar_x_HV_inv)\r\n        \r\n        #行列に戻す\r\n        h=np.transpose(np.reshape(vec_h,(Nk,M,Lh*M)),(0,2,1))\r\n\r\n        #残響除去を行う\r\n        x_reverb=np.einsum('kjm,jkt->mkt',np.conjugate(h),x_bar)\r\n        x_dereverb=x-x_reverb\r\n        \r\n\r\n        #コスト計算\r\n        cost=np.sum(np.einsum(\"mkt,ktmn,nkt->kt\",np.conjugate(x_dereverb),V_inverse,x_dereverb) +np.log(np.abs(np.linalg.det(V))))\r\n        cost/=np.float(Lt)\r\n        cost=np.real(cost)\r\n        cost_buff.append(cost)\r\n        #print(t,cost)\r\n        #パラメータを更新\r\n        \r\n        #Rの更新\r\n        V_inverseX=np.einsum('ktmn,nkt->ktm',V_inverse,x_dereverb)\r\n        V_inverseXV_inverseX=np.einsum('ktm,ktn->ktmn',V_inverseX,np.conjugate(V_inverseX))\r\n        A=np.einsum('kst,ktmn->ksmn',v,V_inverse)\r\n        B=np.einsum('kst,ktmn->ksmn',v,V_inverseXV_inverseX)\r\n        RBR=np.einsum('ksmn,ksni,ksij->ksmj',R,B,R)\r\n        invA=np.linalg.pinv(A)\r\n        A_RBR=np.matmul(A,RBR)\r\n        R=np.concatenate([np.concatenate([np.matmul(invA[k,s,...],scipy.linalg.sqrtm(A_RBR[k,s,...]))[None,None,...] for k in range(Nk)],axis=0) for s in range(Ns)],axis=1)\r\n        R=(R+np.transpose(np.conjugate(R),[0,1,3,2]))/(2.0+0.0j)\r\n\r\n        #vの更新\r\n        v=v*np.sqrt(np.einsum('ktm,ktn,ksnm->kst',V_inverseX,np.conjugate(V_inverseX),R)/np.maximum(np.einsum('ktmn,ksnm->kst',V_inverse,R) ,1.e-18))\r\n\r\n       \r\n    vR=np.einsum(\"kst,ksmn->kstmn\",v,R)\r\n    V=np.sum(vR,axis=1)\r\n    V_inverse=np.linalg.pinv(V)\r\n    Wmwf=np.einsum(\"kstmi,ktin->kstmn\",vR,V_inverse)\r\n\r\n    #音源分離信号を得る\r\n    c_bar=np.einsum('kstmn,nkt->mskt',Wmwf,x_dereverb)\r\n\r\n    return(R,v,c_bar,cost_buff)\r\n\r\n#周波数間の振幅相関に基づくパーミュテーション解法\r\n#s_hat: M,Nk,Lt\r\n#return permutation_index_result：周波数毎のパーミュテーション解 \r\ndef solver_inter_frequency_permutation(s_hat):\r\n    n_sources=np.shape(s_hat)[0]\r\n    n_freqs=np.shape(s_hat)[1]\r\n    n_frames=np.shape(s_hat)[2]\r\n\r\n    s_hat_abs=np.abs(s_hat)\r\n\r\n    norm_amp=np.sqrt(np.sum(np.square(s_hat_abs),axis=0,keepdims=True))\r\n    s_hat_abs=s_hat_abs/np.maximum(norm_amp,1.e-18)\r\n\r\n    spectral_similarity=np.einsum('mkt,nkt->k',s_hat_abs,s_hat_abs)\r\n    \r\n    frequency_order=np.argsort(spectral_similarity)\r\n    \r\n    #音源間の相関が最も低い周波数からパーミュテーションを解く\r\n    is_first=True\r\n    permutations=list(itertools.permutations(range(n_sources)))\r\n    permutation_index_result={}\r\n    \r\n    for freq in frequency_order:\r\n        \r\n        if is_first==True:\r\n            is_first=False\r\n\r\n            #初期値を設定する\r\n            accumurate_s_abs=s_hat_abs[:,frequency_order[0],:]\r\n            permutation_index_result[freq]=range(n_sources)\r\n        else:\r\n            max_correlation=0\r\n            max_correlation_perm=None\r\n            for perm in permutations:\r\n                s_hat_abs_temp=s_hat_abs[list(perm),freq,:]\r\n                correlation=np.sum(accumurate_s_abs*s_hat_abs_temp)\r\n                \r\n                \r\n                if max_correlation_perm is None:\r\n                    max_correlation_perm=list(perm)\r\n                    max_correlation=correlation\r\n                elif max_correlation < correlation:\r\n                    max_correlation=correlation\r\n                    max_correlation_perm=list(perm)\r\n            permutation_index_result[freq]=max_correlation_perm\r\n            accumurate_s_abs+=s_hat_abs[max_correlation_perm,freq,:]\r\n   \r\n    return(permutation_index_result)\r\n    \r\n#2バイトに変換してファイルに保存\r\n#signal: time-domain 1d array (float)\r\n#file_name: 出力先のファイル名\r\n#sample_rate: サンプリングレート\r\ndef write_file_from_time_signal(signal,file_name,sample_rate):\r\n    #2バイトのデータに変換\r\n    signal=signal.astype(np.int16)\r\n\r\n    #waveファイルに書き込む\r\n    wave_out = wave.open(file_name, 'w')\r\n\r\n    #モノラル:1、ステレオ:2\r\n    wave_out.setnchannels(1)\r\n\r\n    #サンプルサイズ2byte\r\n    wave_out.setsampwidth(2)\r\n\r\n    #サンプリング周波数\r\n    wave_out.setframerate(sample_rate)\r\n\r\n    #データを書き込み\r\n    wave_out.writeframes(signal)\r\n\r\n    #ファイルを閉じる\r\n    wave_out.close()\r\n\r\n#SNRをはかる\r\n#desired: 目的音、Lt\r\n#out:　雑音除去後の信号 Lt\r\ndef calculate_snr(desired,out):\r\n    wave_length=np.minimum(np.shape(desired)[0],np.shape(out)[0])\r\n\r\n    #消し残った雑音\r\n    desired=desired[:wave_length]\r\n    out=out[:wave_length]\r\n    noise=desired-out\r\n    snr=10.*np.log10(np.sum(np.square(desired))/np.sum(np.square(noise)))\r\n\r\n    return(snr)\r\n\r\n#乱数の種を初期化\r\nnp.random.seed(0)\r\n\r\n#畳み込みに用いる音声波形\r\nclean_wave_files=[\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\",\"./CMU_ARCTIC/cmu_us_axb_arctic/wav/arctic_a0002.wav\"]\r\n\r\n#音源数\r\nn_sources=len(clean_wave_files)\r\n\r\n#長さを調べる\r\nn_samples=0\r\n#ファイルを読み込む\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    if n_samples<wav.getnframes():\r\n        n_samples=wav.getnframes()\r\n    wav.close()\r\n\r\nclean_data=np.zeros([n_sources,n_samples])\r\n\r\n#ファイルを読み込む\r\ns=0\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    data=wav.readframes(wav.getnframes())\r\n    data=np.frombuffer(data, dtype=np.int16)\r\n    data=data/np.iinfo(np.int16).max\r\n    clean_data[s,:wav.getnframes()]=data\r\n    wav.close()\r\n    s=s+1\r\n\r\n\r\n# シミュレーションのパラメータ\r\n\r\n#シミュレーションで用いる音源数\r\nn_sim_sources=2\r\n\r\n#サンプリング周波数\r\nsample_rate=16000\r\n\r\n#フレームサイズ\r\nN=1024\r\n\r\n#フレームシフト\r\nNshift=int(N/4)\r\n\r\n#周波数の数\r\nNk=int(N/2+1)\r\n\r\n#各ビンの周波数\r\nfreqs=np.arange(0,Nk,1)*sample_rate/N\r\n\r\n#音声と雑音との比率 [dB]\r\nSNR=90.\r\n\r\n#方位角の閾値\r\nazimuth_th=30.\r\n\r\n#部屋の大きさ\r\nroom_dim = np.r_[10.0, 10.0, 10.0]\r\n\r\n#マイクロホンアレイを置く部屋の場所\r\nmic_array_loc = room_dim / 2 + np.random.randn(3) * 0.1 \r\n\r\n#マイクロホンアレイのマイク配置\r\nmic_directions=np.array(\r\n    [[np.pi/2., theta/180.*np.pi] for theta in np.arange(180,361,180)\r\n    ]    )\r\n\r\ndistance=0.01\r\nmic_alignments=np.zeros((3, mic_directions.shape[0]), dtype=mic_directions.dtype)\r\nmic_alignments[0, :] = np.cos(mic_directions[:, 1]) * np.sin(mic_directions[:, 0])\r\nmic_alignments[1, :] = np.sin(mic_directions[:, 1]) * np.sin(mic_directions[:, 0])\r\nmic_alignments[2, :] = np.cos(mic_directions[:, 0])\r\nmic_alignments *= distance\r\n\r\n#マイクロホン数\r\nn_channels=np.shape(mic_alignments)[1]\r\n\r\n#マイクロホンアレイの座標\r\nR=mic_alignments+mic_array_loc[:,None]\r\n\r\nis_use_reverb=True\r\n\r\nif is_use_reverb==False:\r\n    # 部屋を生成する\r\n    room = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0) \r\n    room_no_noise_left = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\n    room_no_noise_right = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\n\r\nelse:\r\n\r\n    room = pa.ShoeBox(room_dim, fs=sample_rate, max_order=17,absorption=0.4)\r\n    room_no_noise_left = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\n    room_no_noise_right = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\n\r\n# 用いるマイクロホンアレイの情報を設定する\r\nroom.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\nroom_no_noise_left.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\nroom_no_noise_right.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\n\r\n#音源の場所\r\ndoas=np.array(\r\n    [[np.pi/2., np.pi],\r\n     [np.pi/2., 0]\r\n    ]    )\r\n\r\n#音源とマイクロホンの距離\r\ndistance=1.\r\n\r\nsource_locations=np.zeros((3, doas.shape[0]), dtype=doas.dtype)\r\nsource_locations[0, :] = np.cos(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[1, :] = np.sin(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[2, :] = np.cos(doas[:, 0])\r\nsource_locations *= distance\r\nsource_locations += mic_array_loc[:, None]\r\n\r\n#各音源をシミュレーションに追加する\r\nfor s in range(n_sim_sources):\r\n    clean_data[s]/= np.std(clean_data[s])\r\n    room.add_source(source_locations[:, s], signal=clean_data[s])\r\n    if s==0:\r\n        room_no_noise_left.add_source(source_locations[:, s], signal=clean_data[s])\r\n    if s==1:\r\n        room_no_noise_right.add_source(source_locations[:, s], signal=clean_data[s])\r\n\r\n#シミュレーションを回す\r\nroom.simulate(snr=SNR)\r\nroom_no_noise_left.simulate(snr=90)\r\nroom_no_noise_right.simulate(snr=90)\r\n\r\n#畳み込んだ波形を取得する(チャンネル、サンプル）\r\nmulti_conv_data=room.mic_array.signals\r\nmulti_conv_data_left_no_noise=room_no_noise_left.mic_array.signals\r\nmulti_conv_data_right_no_noise=room_no_noise_right.mic_array.signals\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data_left_no_noise[0,:]*np.iinfo(np.int16).max/20.,\"./lgm_dereverb_left_clean.wav\",sample_rate)\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data_right_no_noise[0,:]*np.iinfo(np.int16).max/20.,\"./lgm_dereverb_right_clean.wav\",sample_rate)\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data[0,:]*np.iinfo(np.int16).max/20.,\"./lgm_dereverb_in_left.wav\",sample_rate)\r\nwrite_file_from_time_signal(multi_conv_data[0,:]*np.iinfo(np.int16).max/20.,\"./lgm_dereverb_in_right.wav\",sample_rate)\r\n\r\n#短時間フーリエ変換を行う\r\nf,t,stft_data=sp.stft(multi_conv_data,fs=sample_rate,window=\"hann\",nperseg=N,noverlap=N-Nshift)\r\n\r\n#ICAの繰り返し回数\r\nn_ica_iterations=50\r\n\r\n#残響除去のパラメータ\r\nD=2\r\nLh=5\r\n\r\n#過去のマイクロホン入力信号\r\nx_bar=make_x_bar(stft_data,D,Lh)\r\n\r\n#処理するフレーム数\r\nLt=np.shape(stft_data)[-1]\r\n\r\n#MM法に基づくLGM+Dereverb実行コード\r\nRlgm_mm_dereverb,vlgm_mm_dereverb,y_lgm_mm_dereverb,cost_buff_lgm_mm_dereverb=execute_mm_lgm_dereverb(stft_data,x_bar,Ns=n_sources,n_iterations=n_ica_iterations)\r\npermutation_index_result=solver_inter_frequency_permutation(y_lgm_mm_dereverb[0,...])\r\n\r\n#パーミュテーションを解く\r\nfor k in range(Nk):\r\n    y_lgm_mm_dereverb[:,:,k,:]=y_lgm_mm_dereverb[:,permutation_index_result[k],k,:]\r\n\r\n#MM法に基づくLGM実行コード\r\nRlgm_mm,vlgm_mm,y_lgm_mm,cost_buff_lgm_mm=execute_mm_lgm(stft_data,Ns=n_sources,n_iterations=n_ica_iterations)\r\npermutation_index_result=solver_inter_frequency_permutation(y_lgm_mm[0,...])\r\nfor k in range(Nk):\r\n    y_lgm_mm[:,:,k,:]=y_lgm_mm[:,permutation_index_result[k],k,:]\r\n\r\nt,y_lgm_mm=sp.istft(y_lgm_mm[0,...],fs=sample_rate,window=\"hann\",nperseg=N,noverlap=N-Nshift)\r\nt,y_lgm_mm_dereverb=sp.istft(y_lgm_mm_dereverb[0,...],fs=sample_rate,window=\"hann\",nperseg=N,noverlap=N-Nshift)\r\n\r\nsnr_pre=calculate_snr(multi_conv_data_left_no_noise[0,...],multi_conv_data[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],multi_conv_data[0,...])\r\nsnr_pre/=2.\r\n\r\nsnr_lgm_mm_post1=calculate_snr(multi_conv_data_left_no_noise[0,...],y_lgm_mm[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_lgm_mm[1,...])\r\nsnr_lgm_mm_post2=calculate_snr(multi_conv_data_left_no_noise[0,...],y_lgm_mm[1,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_lgm_mm[0,...])\r\n\r\nsnr_lgm_mm_post=np.maximum(snr_lgm_mm_post1,snr_lgm_mm_post2)\r\nsnr_lgm_mm_post/=2.\r\n\r\n\r\nsnr_lgm_mm_dereverb_post1=calculate_snr(multi_conv_data_left_no_noise[0,...],y_lgm_mm_dereverb[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_lgm_mm_dereverb[1,...])\r\nsnr_lgm_mm_dereverb_post2=calculate_snr(multi_conv_data_left_no_noise[0,...],y_lgm_mm_dereverb[1,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_lgm_mm_dereverb[0,...])\r\n\r\nsnr_lgm_mm_dereverb_post=np.maximum(snr_lgm_mm_dereverb_post1,snr_lgm_mm_dereverb_post2)\r\nsnr_lgm_mm_dereverb_post/=2.\r\n\r\nwrite_file_from_time_signal(y_lgm_mm[0,...]*np.iinfo(np.int16).max/20.,\"./lgm_mm_1.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_lgm_mm[1,...]*np.iinfo(np.int16).max/20.,\"./lgm_mm_2.wav\",sample_rate)\r\n\r\nwrite_file_from_time_signal(y_lgm_mm_dereverb[0,...]*np.iinfo(np.int16).max/20.,\"./lgm_mm_dereverb_1.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_lgm_mm_dereverb[1,...]*np.iinfo(np.int16).max/20.,\"./lgm_mm_dereverb_2.wav\",sample_rate)\r\n\r\n\r\nprint(\"method:    \", \"LGM-MM\",\"LGM-Dereverb-MM\")\r\nprint(\"Δsnr [dB]:  {:.2f}  {:.2f}\".format(snr_lgm_mm_post-snr_pre,snr_lgm_mm_dereverb_post-snr_pre))\r\n\r\n#コストの値を表示\r\n#for t in range(n_ica_iterations):\r\n#    print(t,cost_buff_lgm_mm[t],cost_buff_lgm_mm_dereverb[t])\r\n\r\n"
  },
  {
    "path": "section10/sample_code_c10_2.py",
    "content": "\r\nimport wave as wave\r\nimport pyroomacoustics as pa\r\nimport numpy as np\r\nimport scipy.signal as sp\r\nimport scipy as scipy\r\n\r\n#順列計算に使用\r\nimport itertools\r\n\r\n#A: ...mn\r\n#B: ...ij\r\n#AとBの最後の二軸以外の次元は一致していることを前提とする\r\ndef batch_kron(A,B):\r\n if np.shape(A)[:-2]!=np.shape(B)[:-2]:\r\n     print(\"error\")\r\n     return None\r\n else:\r\n    return(np.reshape(np.einsum(\"...mn,...ij->...minj\",A,B),np.shape(A)[:-2]+(np.shape(A)[-2]*np.shape(B)[-2],np.shape(A)[-1]*np.shape(B)[-1])))\r\n\r\n\r\n#x:入力信号( M, Nk, Lt)\r\n#D:遅延フレーム数\r\n#Lh:残響除去フィルタのタップ長\r\n#return x_bar: 過去のマイク入力信号(Lh,M,Nk,Lt)\r\ndef make_x_bar(x,D,Lh):\r\n    \r\n    #フレーム数を取得\r\n    Lt=np.shape(x)[2]\r\n\r\n    #過去のマイク入力信号の配列を準備\r\n    x_bar=np.zeros(shape=(Lh,)+np.shape(x),dtype=np.complex)\r\n\r\n    for tau in range(Lh):\r\n        x_bar[tau,...,tau+D:]=x[:,:,:-(tau+D)]\r\n\r\n    return(x_bar)\r\n\r\n\r\n#コントラスト関数の微分（球対称多次元ラプラス分布を仮定）\r\n#s_hat: 分離信号(M, Nk, Lt)\r\ndef phi_multivariate_laplacian(s_hat):\r\n\r\n    power=np.square(np.abs(s_hat))\r\n    norm=np.sqrt(np.sum(power,axis=1,keepdims=True))\r\n\r\n    phi=s_hat/np.maximum(norm,1.e-18)\r\n    return(phi)\r\n\r\n#コントラスト関数の微分（球対称ラプラス分布を仮定）\r\n#s_hat: 分離信号(M, Nk, Lt)\r\ndef phi_laplacian(s_hat):\r\n\r\n    norm=np.abs(s_hat)\r\n    phi=s_hat/np.maximum(norm,1.e-18)\r\n    return(phi)\r\n\r\n#コントラスト関数（球対称ラプラス分布を仮定）\r\n#s_hat: 分離信号(M, Nk, Lt)\r\ndef contrast_laplacian(s_hat):\r\n\r\n    norm=2.*np.abs(s_hat)\r\n    \r\n    return(norm)\r\n\r\n#コントラスト関数（球対称多次元ラプラス分布を仮定）\r\n#s_hat: 分離信号(M, Nk, Lt)\r\ndef contrast_multivariate_laplacian(s_hat):\r\n    power=np.square(np.abs(s_hat))\r\n    norm=2.*np.sqrt(np.sum(power,axis=1,keepdims=True))\r\n  \r\n    return(norm)\r\n\r\n#IP法による分離フィルタ更新\r\n#x:入力信号( M, Nk, Lt)\r\n#W: 分離フィルタ(Nk,M,M)\r\n#a: アクティビティ(B,M,Lt)\r\n#b: 基底(Nk,M,B)\r\n#n_iterations: 繰り返しステップ数\r\n#return W 分離フィルタ(Nk,M,M) s_hat 出力信号(M,Nk, Lt),cost_buff コスト (T)\r\ndef execute_ip_time_varying_gaussian_ilrma(x,W,a,b,n_iterations=20):\r\n    \r\n    #マイクロホン数・周波数・フレーム数を取得する\r\n    M=np.shape(x)[0]\r\n    Nk=np.shape(x)[1]\r\n    Lt=np.shape(x)[2]\r\n\r\n    cost_buff=[]\r\n    for t in range(n_iterations):\r\n        \r\n        #音源分離信号を得る\r\n        s_hat=np.einsum('kmn,nkt->mkt',W,x)\r\n        s_power=np.square(np.abs(s_hat)) \r\n\r\n        #時間周波数分散を更新\r\n        v=np.einsum(\"bst,ksb->skt\",a,b)\r\n\r\n        #アクティビティの更新\r\n        a=a*np.sqrt(np.einsum(\"ksb,skt->bst\",b,s_power/np.maximum(v,1.e-18)**2)/np.einsum(\"ksb,skt->bst\",b,1./np.maximum(v,1.e-18)))\r\n        \r\n        #基底の更新\r\n        b=b*np.sqrt(np.einsum(\"bst,skt->ksb\",a,s_power /np.maximum(v,1.e-18)**2) /np.einsum(\"bst,skt->ksb\",a,1./np.maximum(v,1.e-18)))\r\n        \r\n        #時間周波数分散を再度更新\r\n        v=np.einsum(\"bst,ksb->skt\",a,b)\r\n\r\n        #コスト計算\r\n        cost=np.sum(np.mean(s_power/np.maximum(v,1.e-18)+np.log(v),axis=-1)) -np.sum(2.*np.log(np.abs(np.linalg.det(W)) ))\r\n        cost_buff.append(cost)\r\n\r\n        #IP法による更新\r\n        Q=np.einsum('skt,mkt,nkt->tksmn',1./np.maximum(v,1.e-18),x,np.conjugate(x))\r\n        Q=np.average(Q,axis=0)\r\n        \r\n        for source_index in range(M):\r\n            WQ=np.einsum('kmi,kin->kmn',W,Q[:,source_index,:,:])\r\n            invWQ=np.linalg.pinv(WQ)\r\n            W[:,source_index,:]=np.conjugate(invWQ[:,:,source_index])\r\n            wVw=np.einsum('km,kmn,kn->k',W[:,source_index,:],Q[:,source_index,:,:],np.conjugate(W[:,source_index,:]))\r\n            wVw=np.sqrt(np.abs(wVw))\r\n            W[:,source_index,:]=W[:,source_index,:]/np.maximum(wVw[:,None],1.e-18)\r\n\r\n \r\n    s_hat=np.einsum('kmn,nkt->mkt',W,x)\r\n\r\n    return(W,s_hat,cost_buff)\r\n\r\n#IP法による分離フィルタ更新\r\n#x:入力信号( M, Nk, Lt)\r\n#x_bar:過去のマイク入力信号(Lh,M, Nk, Lt)\r\n#P: 音源分離・残響除去フィルタ(Nk,M,(Lh+1)*M)\r\n#a: アクティビティ(B,M,Lt)\r\n#b: 基底(Nk,M,B)\r\n#n_iterations: 繰り返しステップ数\r\n#return W 分離フィルタ(Nk,M,M) s_hat 出力信号(M,Nk, Lt),cost_buff コスト (T)\r\ndef execute_ip_time_varying_gaussian_ilrma_t(x,x_bar,P,a,b,n_iterations=20):\r\n    \r\n    \r\n    #マイクロホン数・周波数・フレーム数を取得する\r\n    M=np.shape(x)[0]\r\n    Nk=np.shape(x)[1]\r\n    Lt=np.shape(x)[2]\r\n    Lh=np.shape(x_bar)[0]\r\n    \r\n    x_bar=np.reshape(x_bar,[Lh*M,Nk,Lt])\r\n    x_hat=np.concatenate((x,x_bar),axis=0)\r\n\r\n    #共分散行列を計算\r\n    x_hat_x_hat_H=np.einsum('ikt,jkt->ktij',x_hat,np.conjugate(x_hat))\r\n\r\n    cost_buff=[]\r\n    for t in range(n_iterations):\r\n\r\n        #時間周波数分散を更新\r\n        v=np.einsum(\"bst,ksb->skt\",a,b)\r\n        \r\n        #音源分離と残響除去を行う\r\n        s_hat=np.einsum('kmj,jkt->mkt',P,x_hat)\r\n        s_power=np.square(np.abs(s_hat)) \r\n\r\n        #アクティビティの更新\r\n        a=a*np.sqrt(np.einsum(\"ksb,skt->bst\",b,s_power/np.maximum(v,1.e-18)**2)/np.einsum(\"ksb,skt->bst\",b,1./np.maximum(v,1.e-18)))\r\n        \r\n        #基底の更新\r\n        b=b*np.sqrt(np.einsum(\"bst,skt->ksb\",a,s_power /np.maximum(v,1.e-18)**2) /np.einsum(\"bst,skt->ksb\",a,1./np.maximum(v,1.e-18)))\r\n        \r\n        #時間周波数分散を再度更新\r\n        v=np.einsum(\"bst,ksb->skt\",a,b)\r\n        \r\n        #共分散行列を算出\r\n        Q=np.einsum(\"skt,ktij->tksij\",1./np.maximum(v,1.e-18),x_hat_x_hat_H)\r\n        Q=np.average(Q,axis=0)\r\n        Q_inverse=np.linalg.pinv(Q)\r\n\r\n        for source_index in range(M):            \r\n            P0=P[:,:,:M]\r\n            P0_inverse=np.linalg.pinv(P0)\r\n\r\n            #ステアリングベクトル\r\n            b_steering=P0_inverse[:,:,source_index] \r\n            \r\n            b_h_Q_inverse_b=np.einsum(\"km,kmn,kn->k\",np.conjugate(b_steering),Q_inverse[:,source_index,:M,:M],b_steering)\r\n            Q_inverse_b=np.einsum(\"kmn,kn->km\",Q_inverse[:,source_index,:,:M],b_steering)\r\n            p=np.einsum(\"km,k->km\",Q_inverse_b,1./np.sqrt(np.maximum(np.abs(b_h_Q_inverse_b),1.e-18)))\r\n            P[:,source_index,:]=np.conjugate(p)\r\n        \r\n        #コスト計算\r\n        cost=np.sum(np.mean(s_power/np.maximum(v,1.e-18)+np.log(v),axis=-1)) -np.sum(2.*np.log(np.abs(np.linalg.det(P[:,:,:M])) ))\r\n        cost_buff.append(cost)\r\n        #print(t,cost)\r\n\r\n\r\n    s_hat=np.einsum('kmj,jkt->mkt',P,x_hat)\r\n    W=P[:,:,:M]\r\n    return(W,s_hat,cost_buff)\r\n\r\n\r\n#IP法による分離フィルタ更新\r\n#x:入力信号( M, Nk, Lt)\r\n#x_bar:過去のマイク入力信号(Lh,M, Nk, Lt)\r\n#W: 分離フィルタ(Nk,M,M)\r\n#a: アクティビティ(B,M,Lt)\r\n#b: 基底(Nk,M,B)\r\n#n_iterations: 繰り返しステップ数\r\n#return W 分離フィルタ(Nk,M,M) s_hat 出力信号(M,Nk, Lt),cost_buff コスト (T)\r\ndef execute_ip_time_varying_gaussian_ilrma_dereverb(x,x_bar,W,a,b,n_iterations=20):\r\n\r\n    #マイクロホン数・周波数・フレーム数を取得する\r\n    M=np.shape(x)[0]\r\n    Nk=np.shape(x)[1]\r\n    Lt=np.shape(x)[2]\r\n    Lh=np.shape(x_bar)[0]\r\n    \r\n    x_bar=np.reshape(x_bar,[Lh*M,Nk,Lt])\r\n\r\n    #共分散行列を計算\r\n    x_bar_x_bar_H=np.einsum('ikt,jkt->ktij',x_bar,np.conjugate(x_bar))\r\n\r\n    #相関行列を計算\r\n    x_bar_x_H=np.einsum('ikt,mkt->ktim',x_bar,np.conjugate(x))\r\n\r\n\r\n    cost_buff=[]\r\n    for t in range(n_iterations):\r\n\r\n        #時間周波数分散を更新\r\n        v=np.einsum(\"bst,ksb->skt\",a,b)\r\n        \r\n        #入力信号の共分散行列を求める\r\n        V_inverse=np.einsum(\"skt,ksm,ksn->ktmn\",1./np.maximum(v,1.e-18),np.conjugate(W),W)\r\n        \r\n       \r\n        #残響除去フィルタを求める\r\n        x_barx_H_V_inv=np.einsum(\"ktim,ktmn->kin\",x_bar_x_H,V_inverse)\r\n\r\n        vec_x_bar_x_HV_inv=np.reshape(np.transpose(x_barx_H_V_inv,[0,2,1]),(Nk,Lh*M*M))\r\n        \r\n        #多次元配列対応版のクロネッカー積\r\n        V_inverse_x_x_H=batch_kron(np.transpose(V_inverse,(0,1,3,2)),x_bar_x_bar_H)\r\n\r\n        #vecHを求める\r\n        vec_h=np.einsum(\"kmr,kr->km\",np.linalg.inv(np.sum(V_inverse_x_x_H,axis=1)), vec_x_bar_x_HV_inv)\r\n        \r\n        #行列に戻す\r\n        h=np.transpose(np.reshape(vec_h,(Nk,M,Lh*M)),(0,2,1))\r\n\r\n        #残響除去を行う\r\n        x_reverb=np.einsum('kjm,jkt->mkt',np.conjugate(h),x_bar)\r\n        x_dereverb=x-x_reverb\r\n        \r\n        #音源分離信号を得る\r\n        s_hat=np.einsum('kmn,nkt->mkt',W,x_dereverb)\r\n        s_power=np.square(np.abs(s_hat)) \r\n\r\n        #アクティビティの更新\r\n        a=a*np.sqrt(np.einsum(\"ksb,skt->bst\",b,s_power/np.maximum(v,1.e-18)**2)/np.einsum(\"ksb,skt->bst\",b,1./np.maximum(v,1.e-18)))\r\n        \r\n        #基底の更新\r\n        b=b*np.sqrt(np.einsum(\"bst,skt->ksb\",a,s_power /np.maximum(v,1.e-18)**2) /np.einsum(\"bst,skt->ksb\",a,1./np.maximum(v,1.e-18)))\r\n        \r\n        #時間周波数分散を再度更新\r\n        v=np.einsum(\"bst,ksb->skt\",a,b)\r\n\r\n        #コスト計算\r\n        cost=np.sum(np.mean(s_power/np.maximum(v,1.e-18)+np.log(v),axis=-1)) -np.sum(2.*np.log(np.abs(np.linalg.det(W)) ))\r\n        cost_buff.append(cost)\r\n        #print(t,cost)\r\n\r\n        #IP法による更新\r\n        Q=np.einsum('skt,mkt,nkt->tksmn',1./np.maximum(v,1.e-18),x_dereverb,np.conjugate(x_dereverb))\r\n        Q=np.average(Q,axis=0)\r\n        \r\n        for source_index in range(M):\r\n            WQ=np.einsum('kmi,kin->kmn',W,Q[:,source_index,:,:])\r\n            invWQ=np.linalg.pinv(WQ)\r\n            W[:,source_index,:]=np.conjugate(invWQ[:,:,source_index])\r\n            wVw=np.einsum('km,kmn,kn->k',W[:,source_index,:],Q[:,source_index,:,:],np.conjugate(W[:,source_index,:]))\r\n            wVw=np.sqrt(np.abs(wVw))\r\n            W[:,source_index,:]=W[:,source_index,:]/np.maximum(wVw[:,None],1.e-18)\r\n\r\n \r\n    s_hat=np.einsum('kmn,nkt->mkt',W,x_dereverb)\r\n\r\n    return(W,s_hat,cost_buff)\r\n\r\n#プロジェクションバックで最終的な出力信号を求める\r\n#s_hat: M,Nk,Lt\r\n#W: 分離フィルタ(Nk,M,M)\r\n#retunr c_hat: マイクロホン位置での分離結果(M,M,Nk,Lt)\r\ndef projection_back(s_hat,W):\r\n    \r\n    #ステアリングベクトルを推定\r\n    A=np.linalg.pinv(W)\r\n    c_hat=np.einsum('kmi,ikt->mikt',A,s_hat)\r\n    return(c_hat)\r\n\r\n\r\n#2バイトに変換してファイルに保存\r\n#signal: time-domain 1d array (float)\r\n#file_name: 出力先のファイル名\r\n#sample_rate: サンプリングレート\r\ndef write_file_from_time_signal(signal,file_name,sample_rate):\r\n    #2バイトのデータに変換\r\n    signal=signal.astype(np.int16)\r\n\r\n    #waveファイルに書き込む\r\n    wave_out = wave.open(file_name, 'w')\r\n\r\n    #モノラル:1、ステレオ:2\r\n    wave_out.setnchannels(1)\r\n\r\n    #サンプルサイズ2byte\r\n    wave_out.setsampwidth(2)\r\n\r\n    #サンプリング周波数\r\n    wave_out.setframerate(sample_rate)\r\n\r\n    #データを書き込み\r\n    wave_out.writeframes(signal)\r\n\r\n    #ファイルを閉じる\r\n    wave_out.close()\r\n\r\n#SNRをはかる\r\n#desired: 目的音、Lt\r\n#out:　雑音除去後の信号 Lt\r\ndef calculate_snr(desired,out):\r\n    wave_length=np.minimum(np.shape(desired)[0],np.shape(out)[0])\r\n\r\n    #消し残った雑音\r\n    desired=desired[:wave_length]\r\n    out=out[:wave_length]\r\n    noise=desired-out\r\n    snr=10.*np.log10(np.sum(np.square(desired))/np.sum(np.square(noise)))\r\n\r\n    return(snr)\r\n\r\n#乱数の種を初期化\r\nnp.random.seed(0)\r\n\r\n#畳み込みに用いる音声波形\r\nclean_wave_files=[\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\",\"./CMU_ARCTIC/cmu_us_axb_arctic/wav/arctic_a0002.wav\"]\r\n\r\n#音源数\r\nn_sources=len(clean_wave_files)\r\n\r\n#長さを調べる\r\nn_samples=0\r\n#ファイルを読み込む\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    if n_samples<wav.getnframes():\r\n        n_samples=wav.getnframes()\r\n    wav.close()\r\n\r\nclean_data=np.zeros([n_sources,n_samples])\r\n\r\n#ファイルを読み込む\r\ns=0\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    data=wav.readframes(wav.getnframes())\r\n    data=np.frombuffer(data, dtype=np.int16)\r\n    data=data/np.iinfo(np.int16).max\r\n    clean_data[s,:wav.getnframes()]=data\r\n    wav.close()\r\n    s=s+1\r\n\r\n\r\n# シミュレーションのパラメータ\r\n\r\n#シミュレーションで用いる音源数\r\nn_sim_sources=2\r\n\r\n#サンプリング周波数\r\nsample_rate=16000\r\n\r\n#フレームサイズ\r\nN=1024\r\n\r\n#フレームシフト\r\nNshift=int(N/4)\r\n\r\n#周波数の数\r\nNk=int(N/2+1)\r\n\r\n#各ビンの周波数\r\nfreqs=np.arange(0,Nk,1)*sample_rate/N\r\n\r\n#音声と雑音との比率 [dB]\r\nSNR=90.\r\n\r\n#方位角の閾値\r\nazimuth_th=30.\r\n\r\n#部屋の大きさ\r\nroom_dim = np.r_[10.0, 10.0, 10.0]\r\n\r\n#マイクロホンアレイを置く部屋の場所\r\nmic_array_loc = room_dim / 2 + np.random.randn(3) * 0.1 \r\n\r\n#マイクロホンアレイのマイク配置\r\nmic_directions=np.array(\r\n    [[np.pi/2., theta/180.*np.pi] for theta in np.arange(180,361,180)\r\n    ]    )\r\n\r\ndistance=0.01\r\nmic_alignments=np.zeros((3, mic_directions.shape[0]), dtype=mic_directions.dtype)\r\nmic_alignments[0, :] = np.cos(mic_directions[:, 1]) * np.sin(mic_directions[:, 0])\r\nmic_alignments[1, :] = np.sin(mic_directions[:, 1]) * np.sin(mic_directions[:, 0])\r\nmic_alignments[2, :] = np.cos(mic_directions[:, 0])\r\nmic_alignments *= distance\r\n\r\n#マイクロホン数\r\nn_channels=np.shape(mic_alignments)[1]\r\n\r\n#マイクロホンアレイの座標\r\nR=mic_alignments+mic_array_loc[:,None]\r\n\r\nis_use_reverb=True\r\n\r\nif is_use_reverb==False:\r\n    # 部屋を生成する\r\n    room = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0) \r\n    room_no_noise_left = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\n    room_no_noise_right = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\n\r\nelse:\r\n\r\n    room = pa.ShoeBox(room_dim, fs=sample_rate, max_order=17,absorption=0.4)\r\n    room_no_noise_left = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\n    room_no_noise_right = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\n\r\n# 用いるマイクロホンアレイの情報を設定する\r\nroom.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\nroom_no_noise_left.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\nroom_no_noise_right.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\n\r\n#音源の場所\r\ndoas=np.array(\r\n    [[np.pi/2., np.pi],\r\n     [np.pi/2., 0]\r\n    ]    )\r\n\r\n#音源とマイクロホンの距離\r\ndistance=1.\r\n\r\nsource_locations=np.zeros((3, doas.shape[0]), dtype=doas.dtype)\r\nsource_locations[0, :] = np.cos(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[1, :] = np.sin(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[2, :] = np.cos(doas[:, 0])\r\nsource_locations *= distance\r\nsource_locations += mic_array_loc[:, None]\r\n\r\n#各音源をシミュレーションに追加する\r\nfor s in range(n_sim_sources):\r\n    clean_data[s]/= np.std(clean_data[s])\r\n    room.add_source(source_locations[:, s], signal=clean_data[s])\r\n    if s==0:\r\n        room_no_noise_left.add_source(source_locations[:, s], signal=clean_data[s])\r\n    if s==1:\r\n        room_no_noise_right.add_source(source_locations[:, s], signal=clean_data[s])\r\n\r\n#シミュレーションを回す\r\nroom.simulate(snr=SNR)\r\nroom_no_noise_left.simulate(snr=90)\r\nroom_no_noise_right.simulate(snr=90)\r\n\r\n#畳み込んだ波形を取得する(チャンネル、サンプル）\r\nmulti_conv_data=room.mic_array.signals\r\nmulti_conv_data_left_no_noise=room_no_noise_left.mic_array.signals\r\nmulti_conv_data_right_no_noise=room_no_noise_right.mic_array.signals\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data_left_no_noise[0,:]*np.iinfo(np.int16).max/20.,\"./lgm_dereverb_left_clean.wav\",sample_rate)\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data_right_no_noise[0,:]*np.iinfo(np.int16).max/20.,\"./lgm_dereverb_right_clean.wav\",sample_rate)\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data[0,:]*np.iinfo(np.int16).max/20.,\"./lgm_dereverb_in_left.wav\",sample_rate)\r\nwrite_file_from_time_signal(multi_conv_data[0,:]*np.iinfo(np.int16).max/20.,\"./lgm_dereverb_in_right.wav\",sample_rate)\r\n\r\n#短時間フーリエ変換を行う\r\nf,t,stft_data=sp.stft(multi_conv_data,fs=sample_rate,window=\"hann\",nperseg=N,noverlap=N-Nshift)\r\n\r\n#ICAの繰り返し回数\r\nn_ica_iterations=50\r\n\r\n#残響除去のパラメータ\r\nD=2\r\nLh=5\r\n\r\n#過去のマイクロホン入力信号\r\nx_bar=make_x_bar(stft_data,D,Lh)\r\n\r\n#ILRMAの基底数\r\nn_basis=2\r\n\r\n#処理するフレーム数\r\nLt=np.shape(stft_data)[-1]\r\n\r\n#分離フィルタを初期化\r\nWilrma=np.zeros(shape=(Nk,n_sources,n_sources),dtype=np.complex)\r\nPilrma_t=np.zeros(shape=(Nk,n_sources,(Lh+1)*n_sources),dtype=np.complex)\r\n\r\nWilrma=Wilrma+np.eye(n_sources)[None,...]\r\n\r\nWilrma_ip=Wilrma.copy()\r\n\r\nfor tau in range(0,Lh+1):\r\n    Pilrma_t[:,:,tau*n_sources:(tau+1)*n_sources]=Wilrma.copy()\r\n\r\n#ILRMA用\r\nb=np.ones(shape=(Nk,n_sources,n_basis))\r\na=np.random.uniform(size=(n_basis*n_sources*Lt))\r\na=np.reshape(a,(n_basis,n_sources,Lt))\r\n\r\n#ILRMA-T実行\r\nWilrma_t,s_ilrma_t,cost_buff_ilrma_t=execute_ip_time_varying_gaussian_ilrma_t(stft_data,x_bar,Pilrma_t,a.copy(),b.copy(),n_iterations=n_ica_iterations)\r\n\r\ny_ilrma_t=projection_back(s_ilrma_t,Wilrma_t)\r\n\r\n#ILRMA+Dereverb実行 (IP法ベース)\r\nWilrma_dereverb_ip,s_ilrma_dereverb_ip,cost_buff_ilrma_dereverb_ip=execute_ip_time_varying_gaussian_ilrma_dereverb(stft_data,x_bar,Wilrma_ip.copy(),a.copy(),b.copy(),n_iterations=n_ica_iterations)\r\n\r\ny_ilrma_dereverb_ip=projection_back(s_ilrma_dereverb_ip,Wilrma_dereverb_ip)\r\n\r\n#ILRMA実行 (IP法ベース)\r\nWilrma_ip,s_ilrma_ip,cost_buff_ilrma_ip=execute_ip_time_varying_gaussian_ilrma(stft_data,Wilrma_ip,a.copy(),b.copy(),n_iterations=n_ica_iterations)\r\n\r\ny_ilrma_ip=projection_back(s_ilrma_ip,Wilrma_ip)\r\n\r\nt,y_ilrma_ip=sp.istft(y_ilrma_ip[0,...],fs=sample_rate,window=\"hann\",nperseg=N,noverlap=N-Nshift)\r\nt,y_ilrma_t=sp.istft(y_ilrma_t[0,...],fs=sample_rate,window=\"hann\",nperseg=N,noverlap=N-Nshift)\r\nt,y_ilrma_dereverb_ip=sp.istft(y_ilrma_dereverb_ip[0,...],fs=sample_rate,window=\"hann\",nperseg=N,noverlap=N-Nshift)\r\n\r\nsnr_pre=calculate_snr(multi_conv_data_left_no_noise[0,...],multi_conv_data[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],multi_conv_data[0,...])\r\nsnr_pre/=2.\r\n\r\nsnr_ilrma_t_post1=calculate_snr(multi_conv_data_left_no_noise[0,...],y_ilrma_t[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_ilrma_t[1,...])\r\nsnr_ilrma_t_post2=calculate_snr(multi_conv_data_left_no_noise[0,...],y_ilrma_t[1,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_ilrma_t[0,...])\r\n\r\nsnr_ilrma_t_post=np.maximum(snr_ilrma_t_post1,snr_ilrma_t_post2)\r\nsnr_ilrma_t_post/=2.\r\n\r\nsnr_ilrma_ip_post1=calculate_snr(multi_conv_data_left_no_noise[0,...],y_ilrma_ip[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_ilrma_ip[1,...])\r\nsnr_ilrma_ip_post2=calculate_snr(multi_conv_data_left_no_noise[0,...],y_ilrma_ip[1,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_ilrma_ip[0,...])\r\n\r\nsnr_ilrma_ip_post=np.maximum(snr_ilrma_ip_post1,snr_ilrma_ip_post2)\r\nsnr_ilrma_ip_post/=2.\r\n\r\nsnr_ilrma_dereverb_ip_post1=calculate_snr(multi_conv_data_left_no_noise[0,...],y_ilrma_dereverb_ip[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_ilrma_dereverb_ip[1,...])\r\nsnr_ilrma_dereverb_ip_post2=calculate_snr(multi_conv_data_left_no_noise[0,...],y_ilrma_dereverb_ip[1,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_ilrma_dereverb_ip[0,...])\r\n\r\nsnr_ilrma_dereverb_ip_post=np.maximum(snr_ilrma_dereverb_ip_post1,snr_ilrma_dereverb_ip_post2)\r\nsnr_ilrma_dereverb_ip_post/=2.\r\n\r\nwrite_file_from_time_signal(y_ilrma_ip[0,...]*np.iinfo(np.int16).max/20.,\"./ilrma_ip_1.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_ilrma_ip[1,...]*np.iinfo(np.int16).max/20.,\"./ilrma_ip_2.wav\",sample_rate)\r\n\r\nwrite_file_from_time_signal(y_ilrma_dereverb_ip[0,...]*np.iinfo(np.int16).max/20.,\"./ilrma_dereverb_ip_1.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_ilrma_dereverb_ip[1,...]*np.iinfo(np.int16).max/20.,\"./ilrma_dereverb_ip_2.wav\",sample_rate)\r\n\r\nwrite_file_from_time_signal(y_ilrma_t[0,...]*np.iinfo(np.int16).max/20.,\"./ilrma_t_1.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_ilrma_t[1,...]*np.iinfo(np.int16).max/20.,\"./ilrma_t_2.wav\",sample_rate)\r\n\r\nprint(\"method:    \", \"ILRMA\", \"ILRMA-Dereverb\",\"ILRMA-T\")\r\nprint(\"Δsnr [dB]:  {:.2f}  {:.2f}  {:.2f}\".format(snr_ilrma_ip_post-snr_pre,snr_ilrma_dereverb_ip_post-snr_pre,snr_ilrma_t_post-snr_pre))\r\n\r\n#コストの値を表示\r\n#for t in range(n_ica_iterations):\r\n#    print(t,cost_buff_ilrma_ip[t],cost_buff_ilrma_dereverb_ip[t], cost_buff_ilrma_t[t])\r\n\r\n"
  },
  {
    "path": "section10.md",
    "content": "\n## 第10章のサンプルコード\n\n* [LGMに基づく音源分離と\n残響除去の統合的最適化法](section10/sample_code_c10_1.py)\n* [ILRMAに基づく音源分離と\n残響除去の統合的最適化法](section10/sample_code_c10_2.py)\n"
  },
  {
    "path": "section11/sample_code_c11_1.py",
    "content": "\r\n\r\nimport wave as wave\r\nimport pyroomacoustics as pa\r\nimport numpy as np\r\nimport scipy.signal as sp\r\nimport scipy as scipy\r\n\r\n#順列計算に使用\r\nimport itertools\r\nimport time\r\n\r\n\r\n\r\n#コントラスト関数の微分（球対称多次元ラプラス分布を仮定）\r\n#s_hat: 分離信号(M, Nk, Lt)\r\ndef phi_multivariate_laplacian(s_hat):\r\n\r\n    power=np.square(np.abs(s_hat))\r\n    norm=np.sqrt(np.sum(power,axis=1,keepdims=True))\r\n\r\n    phi=s_hat/np.maximum(norm,1.e-18)\r\n    return(phi)\r\n\r\n#コントラスト関数の微分（球対称ラプラス分布を仮定）\r\n#s_hat: 分離信号(M, Nk, Lt)\r\ndef phi_laplacian(s_hat):\r\n\r\n    norm=np.abs(s_hat)\r\n    phi=s_hat/np.maximum(norm,1.e-18)\r\n    return(phi)\r\n\r\n#コントラスト関数（球対称ラプラス分布を仮定）\r\n#s_hat: 分離信号(M, Nk, Lt)\r\ndef contrast_laplacian(s_hat):\r\n\r\n    norm=2.*np.abs(s_hat)\r\n    \r\n    return(norm)\r\n\r\n#コントラスト関数（球対称多次元ラプラス分布を仮定）\r\n#s_hat: 分離信号(M, Nk, Lt)\r\ndef contrast_multivariate_laplacian(s_hat):\r\n    power=np.square(np.abs(s_hat))\r\n    norm=2.*np.sqrt(np.sum(power,axis=1,keepdims=True))\r\n  \r\n    return(norm)\r\n\r\n#ICAによる分離フィルタ更新\r\n#x:入力信号( M, Nk, Lt)\r\n#W: 分離フィルタ(Nk,M,M)\r\n#mu: 更新係数\r\n#n_ica_iterations: 繰り返しステップ数\r\n#phi_func: コントラスト関数の微分を与える関数\r\n#contrast_func: コントラスト関数\r\n#is_use_non_holonomic: True (非ホロノミック拘束を用いる） False (用いない）\r\n#return W 分離フィルタ(Nk,M,M) s_hat 出力信号(M,Nk, Lt),cost_buff ICAのコスト (T)\r\ndef execute_natural_gradient_ica(x,W,phi_func=phi_laplacian,contrast_func=contrast_laplacian,mu=1.0,n_ica_iterations=20,is_use_non_holonomic=True):\r\n    \r\n    #マイクロホン数を取得する\r\n    M=np.shape(x)[0]\r\n\r\n    cost_buff=[]\r\n    for t in range(n_ica_iterations):\r\n        #音源分離信号を得る\r\n        s_hat=np.einsum('kmn,nkt->mkt',W,x)\r\n\r\n        #コントラスト関数を計算\r\n        G=contrast_func(s_hat)\r\n\r\n        #コスト計算\r\n        cost=np.sum(np.mean(G,axis=-1))-np.sum(2.*np.log(np.abs(np.linalg.det(W)) ))\r\n        cost_buff.append(cost)\r\n\r\n        #コンストラクト関数の微分を取得\r\n        phi=phi_func(s_hat)\r\n\r\n        phi_s=np.einsum('mkt,nkt->ktmn',phi,np.conjugate(s_hat))\r\n        phi_s=np.mean(phi_s,axis=1)\r\n\r\n        I=np.eye(M,M)\r\n        if is_use_non_holonomic==False:\r\n            deltaW=np.einsum('kmi,kin->kmn',I[None,...]-phi_s,W)\r\n        else:\r\n            mask=(np.ones((M,M))-I)[None,...]\r\n            deltaW=np.einsum('kmi,kin->kmn',np.multiply(mask,-phi_s),W)\r\n            \r\n        #フィルタを更新する\r\n        W=W+mu*deltaW\r\n    \r\n    #最後に出力信号を分離\r\n    s_hat=np.einsum('kmn,nkt->mkt',W,x)\r\n\r\n    return(W,s_hat,cost_buff)\r\n\r\n#EM法によるLGMのパラメータ推定法\r\n#x:入力信号( M, Nk, Lt)\r\n#Ns: 音源数\r\n#n_iterations: 繰り返しステップ数\r\n#return R 共分散行列(Nk,Ns,M,M) v 時間周波数分散(Nk,Ns,Lt),c_bar 音源分離信号(M,Ns,Nk,Lt), cost_buff コスト (T)\r\ndef execute_em_lgm(x,Ns=2,n_iterations=20):\r\n    \r\n    #マイクロホン数・周波数・フレーム数を取得する\r\n    M=np.shape(x)[0]\r\n    Nk=np.shape(x)[1]\r\n    Lt=np.shape(x)[2]\r\n\r\n    #Rとvを初期化する\r\n    mask=np.random.uniform(size=Nk*Ns*Lt)\r\n    mask=np.reshape(mask,(Nk,Ns,Lt))\r\n    R=np.einsum(\"kst,mkt,nkt->kstmn\",mask,x,np.conjugate(x))\r\n    R=np.average(R,axis=2)\r\n    v=np.random.uniform(size=Nk*Ns*Lt)\r\n    v=np.reshape(v,(Nk,Ns,Lt))\r\n\r\n    cost_buff=[]\r\n    for t in range(n_iterations):\r\n        \r\n        #入力信号の共分散行列を求める\r\n        vR=np.einsum(\"kst,ksmn->kstmn\",v,R)\r\n        V=np.sum(vR,axis=1)\r\n        V_inverse=np.linalg.pinv(V)\r\n\r\n        #コスト計算\r\n        cost=np.sum(np.einsum(\"mkt,ktmn,nkt->kt\",np.conjugate(x),V_inverse,x) +np.log(np.abs(np.linalg.det(V))))\r\n        cost/=np.float(Lt)\r\n        cost=np.real(cost)\r\n        cost_buff.append(cost)\r\n\r\n        Wmwf=np.einsum(\"kstmi,ktin->kstmn\",vR,V_inverse)\r\n\r\n        #事後確率計算に必要なパラメータを推定\r\n        c_bar=np.einsum('kstmn,nkt->kstm',Wmwf,x)\r\n        R_bar=np.einsum(\"kstmi,kstin->kstmn\",-1.*Wmwf+np.eye(M),vR)\r\n        P_bar=R_bar+np.einsum(\"kstm,kstn->kstmn\",c_bar,np.conjugate(c_bar))\r\n        \r\n        #パラメータを更新\r\n        R=np.average(P_bar/np.maximum(v,1.e-18)[...,None,None],axis=2)\r\n\r\n        R_inverse=np.linalg.pinv(R)\r\n        v=np.einsum(\"ksmi,kstim->kst\",R_inverse,P_bar)\r\n        v=v/np.float(M)\r\n\r\n\r\n    vR=np.einsum(\"kst,ksmn->kstmn\",v,R)\r\n    V=np.sum(vR,axis=1)\r\n    V_inverse=np.linalg.pinv(V)\r\n    Wmwf=np.einsum(\"kstmi,ktin->kstmn\",vR,V_inverse)\r\n\r\n    #音源分離信号を得る\r\n    c_bar=np.einsum('kstmn,nkt->mskt',Wmwf,x)\r\n\r\n    return(R,v,c_bar,cost_buff)\r\n\r\n#IP法によるLGMのパラメータ推定法\r\n#x:入力信号( M, Nk, Lt)\r\n#Ns: 音源数\r\n#n_iterations: 繰り返しステップ数\r\n#return R 共分散行列(Nk,Ns,M,M) v 時間周波数分散(Nk,Ns,Lt),c_bar 音源分離信号(M,Ns,Nk,Lt), cost_buff コスト (T)\r\ndef execute_mm_lgm(x,Ns=2,n_iterations=20):\r\n    \r\n    #マイクロホン数・周波数・フレーム数を取得する\r\n    M=np.shape(x)[0]\r\n    Nk=np.shape(x)[1]\r\n    Lt=np.shape(x)[2]\r\n\r\n    #Rとvを初期化する\r\n    mask=np.random.uniform(size=Nk*Ns*Lt)\r\n    mask=np.reshape(mask,(Nk,Ns,Lt))\r\n    R=np.einsum(\"kst,mkt,nkt->kstmn\",mask,x,np.conjugate(x))\r\n    R=np.average(R,axis=2)\r\n    v=np.random.uniform(size=Nk*Ns*Lt)\r\n    v=np.reshape(v,(Nk,Ns,Lt))\r\n\r\n    cost_buff=[]\r\n    for t in range(n_iterations):\r\n        \r\n        #入力信号の共分散行列を求める\r\n        vR=np.einsum(\"kst,ksmn->kstmn\",v,R)\r\n        V=np.sum(vR,axis=1)\r\n        V_inverse=np.linalg.pinv(V)\r\n\r\n        #コスト計算\r\n        cost=np.sum(np.einsum(\"mkt,ktmn,nkt->kt\",np.conjugate(x),V_inverse,x) +np.log(np.abs(np.linalg.det(V))))\r\n        cost/=np.float(Lt)\r\n        cost=np.real(cost)\r\n        cost_buff.append(cost)\r\n\r\n        #パラメータを更新\r\n        \r\n        #Rの更新\r\n        V_inverseX=np.einsum('ktmn,nkt->ktm',V_inverse,x)\r\n        V_inverseXV_inverseX=np.einsum('ktm,ktn->ktmn',V_inverseX,np.conjugate(V_inverseX))\r\n        A=np.einsum('kst,ktmn->ksmn',v,V_inverse)\r\n        B=np.einsum('kst,ktmn->ksmn',v,V_inverseXV_inverseX)\r\n        RBR=np.einsum('ksmn,ksni,ksij->ksmj',R,B,R)\r\n        invA=np.linalg.pinv(A)\r\n        A_RBR=np.matmul(A,RBR)\r\n        R=np.concatenate([np.concatenate([np.matmul(invA[k,s,...],scipy.linalg.sqrtm(A_RBR[k,s,...]))[None,None,...] for k in range(Nk)],axis=0) for s in range(Ns)],axis=1)\r\n        R=(R+np.transpose(np.conjugate(R),[0,1,3,2]))/(2.0+0.0j)\r\n\r\n        #vの更新\r\n        v=v*np.sqrt(np.einsum('ktm,ktn,ksnm->kst',V_inverseX,np.conjugate(V_inverseX),R)/np.maximum(np.einsum('ktmn,ksnm->kst',V_inverse,R) ,1.e-18))\r\n\r\n       \r\n    vR=np.einsum(\"kst,ksmn->kstmn\",v,R)\r\n    V=np.sum(vR,axis=1)\r\n    V_inverse=np.linalg.pinv(V)\r\n    Wmwf=np.einsum(\"kstmi,ktin->kstmn\",vR,V_inverse)\r\n\r\n    #音源分離信号を得る\r\n    c_bar=np.einsum('kstmn,nkt->mskt',Wmwf,x)\r\n\r\n    return(R,v,c_bar,cost_buff)\r\n\r\n#IP法による分離フィルタ更新\r\n#x:入力信号( M, Nk, Lt)\r\n#W: 分離フィルタ(Nk,M,M)\r\n#n_iterations: 繰り返しステップ数\r\n#return W 分離フィルタ(Nk,M,M) s_hat 出力信号(M,Nk, Lt),cost_buff コスト (T)\r\ndef execute_ip_multivariate_laplacian_iva(x,W,n_iterations=20):\r\n    \r\n    #マイクロホン数を取得する\r\n    M=np.shape(x)[0]\r\n\r\n    cost_buff=[]\r\n    for t in range(n_iterations):\r\n        \r\n        #音源分離信号を得る\r\n        s_hat=np.einsum('kmn,nkt->mkt',W,x)\r\n\r\n        #補助変数を更新する\r\n        v=np.sqrt(np.sum(np.square(np.abs(s_hat)),axis=1))\r\n\r\n        #コントラスト関数を計算\r\n        G=contrast_multivariate_laplacian(s_hat)\r\n\r\n        #コスト計算\r\n        cost=np.sum(np.mean(G,axis=-1))-np.sum(2.*np.log(np.abs(np.linalg.det(W)) ))\r\n        cost_buff.append(cost)\r\n\r\n        #IP法による更新\r\n        Q=np.einsum('st,mkt,nkt->tksmn',1./np.maximum(v,1.e-18),x,np.conjugate(x))\r\n        Q=np.average(Q,axis=0)\r\n        \r\n        for source_index in range(M):\r\n            WQ=np.einsum('kmi,kin->kmn',W,Q[:,source_index,:,:])\r\n            invWQ=np.linalg.pinv(WQ)\r\n            W[:,source_index,:]=np.conjugate(invWQ[:,:,source_index])\r\n            wVw=np.einsum('km,kmn,kn->k',W[:,source_index,:],Q[:,source_index,:,:],np.conjugate(W[:,source_index,:]))\r\n            wVw=np.sqrt(np.abs(wVw))\r\n            W[:,source_index,:]=W[:,source_index,:]/np.maximum(wVw[:,None],1.e-18)\r\n\r\n \r\n    s_hat=np.einsum('kmn,nkt->mkt',W,x)\r\n\r\n    return(W,s_hat,cost_buff)\r\n\r\n#IP法による分離フィルタ更新\r\n#x:入力信号( M, Nk, Lt)\r\n#W: 分離フィルタ(Nk,M,M)\r\n#a: アクティビティ(B,M,Lt)\r\n#b: 基底(Nk,M,B)\r\n#n_iterations: 繰り返しステップ数\r\n#return W 分離フィルタ(Nk,M,M) s_hat 出力信号(M,Nk, Lt),cost_buff コスト (T)\r\ndef execute_ip_time_varying_gaussian_ilrma(x,W,a,b,n_iterations=20):\r\n    \r\n    #マイクロホン数・周波数・フレーム数を取得する\r\n    M=np.shape(x)[0]\r\n    Nk=np.shape(x)[1]\r\n    Lt=np.shape(x)[2]\r\n\r\n    cost_buff=[]\r\n    for t in range(n_iterations):\r\n        \r\n        #音源分離信号を得る\r\n        s_hat=np.einsum('kmn,nkt->mkt',W,x)\r\n        s_power=np.square(np.abs(s_hat)) \r\n\r\n        #時間周波数分散を更新\r\n        v=np.einsum(\"bst,ksb->skt\",a,b)\r\n\r\n        #アクティビティの更新\r\n        a=a*np.sqrt(np.einsum(\"ksb,skt->bst\",b,s_power/np.maximum(v,1.e-18)**2)/np.einsum(\"ksb,skt->bst\",b,1./np.maximum(v,1.e-18)))\r\n        \r\n        #基底の更新\r\n        b=b*np.sqrt(np.einsum(\"bst,skt->ksb\",a,s_power /np.maximum(v,1.e-18)**2) /np.einsum(\"bst,skt->ksb\",a,1./np.maximum(v,1.e-18)))\r\n        \r\n        #時間周波数分散を再度更新\r\n        v=np.einsum(\"bst,ksb->skt\",a,b)\r\n\r\n        #コスト計算\r\n        cost=np.sum(np.mean(s_power/np.maximum(v,1.e-18)+np.log(v),axis=-1)) -np.sum(2.*np.log(np.abs(np.linalg.det(W)) ))\r\n        cost_buff.append(cost)\r\n\r\n        #IP法による更新\r\n        Q=np.einsum('skt,mkt,nkt->tksmn',1./np.maximum(v,1.e-18),x,np.conjugate(x))\r\n        Q=np.average(Q,axis=0)\r\n        \r\n        for source_index in range(M):\r\n            WQ=np.einsum('kmi,kin->kmn',W,Q[:,source_index,:,:])\r\n            invWQ=np.linalg.pinv(WQ)\r\n            W[:,source_index,:]=np.conjugate(invWQ[:,:,source_index])\r\n            wVw=np.einsum('km,kmn,kn->k',W[:,source_index,:],Q[:,source_index,:,:],np.conjugate(W[:,source_index,:]))\r\n            wVw=np.sqrt(np.abs(wVw))\r\n            W[:,source_index,:]=W[:,source_index,:]/np.maximum(wVw[:,None],1.e-18)\r\n\r\n \r\n    s_hat=np.einsum('kmn,nkt->mkt',W,x)\r\n\r\n    return(W,s_hat,cost_buff)\r\n\r\n\r\n#周波数間の振幅相関に基づくパーミュテーション解法\r\n#s_hat: M,Nk,Lt\r\n#return permutation_index_result：周波数毎のパーミュテーション解 \r\ndef solver_inter_frequency_permutation(s_hat):\r\n    n_sources=np.shape(s_hat)[0]\r\n    n_freqs=np.shape(s_hat)[1]\r\n    n_frames=np.shape(s_hat)[2]\r\n\r\n    s_hat_abs=np.abs(s_hat)\r\n\r\n    norm_amp=np.sqrt(np.sum(np.square(s_hat_abs),axis=0,keepdims=True))\r\n    s_hat_abs=s_hat_abs/np.maximum(norm_amp,1.e-18)\r\n\r\n    spectral_similarity=np.einsum('mkt,nkt->k',s_hat_abs,s_hat_abs)\r\n    \r\n    frequency_order=np.argsort(spectral_similarity)\r\n    \r\n    #音源間の相関が最も低い周波数からパーミュテーションを解く\r\n    is_first=True\r\n    permutations=list(itertools.permutations(range(n_sources)))\r\n    permutation_index_result={}\r\n    \r\n    for freq in frequency_order:\r\n        \r\n        if is_first==True:\r\n            is_first=False\r\n\r\n            #初期値を設定する\r\n            accumurate_s_abs=s_hat_abs[:,frequency_order[0],:]\r\n            permutation_index_result[freq]=range(n_sources)\r\n        else:\r\n            max_correlation=0\r\n            max_correlation_perm=None\r\n            for perm in permutations:\r\n                s_hat_abs_temp=s_hat_abs[list(perm),freq,:]\r\n                correlation=np.sum(accumurate_s_abs*s_hat_abs_temp)\r\n                \r\n                \r\n                if max_correlation_perm is None:\r\n                    max_correlation_perm=list(perm)\r\n                    max_correlation=correlation\r\n                elif max_correlation < correlation:\r\n                    max_correlation=correlation\r\n                    max_correlation_perm=list(perm)\r\n            permutation_index_result[freq]=max_correlation_perm\r\n            accumurate_s_abs+=s_hat_abs[max_correlation_perm,freq,:]\r\n   \r\n    return(permutation_index_result)\r\n    \r\n#プロジェクションバックで最終的な出力信号を求める\r\n#s_hat: M,Nk,Lt\r\n#W: 分離フィルタ(Nk,M,M)\r\n#retunr c_hat: マイクロホン位置での分離結果(M,M,Nk,Lt)\r\ndef projection_back(s_hat,W):\r\n    \r\n    #ステアリングベクトルを推定\r\n    A=np.linalg.pinv(W)\r\n    c_hat=np.einsum('kmi,ikt->mikt',A,s_hat)\r\n    return(c_hat)\r\n\r\n\r\n#2バイトに変換してファイルに保存\r\n#signal: time-domain 1d array (float)\r\n#file_name: 出力先のファイル名\r\n#sample_rate: サンプリングレート\r\ndef write_file_from_time_signal(signal,file_name,sample_rate):\r\n    #2バイトのデータに変換\r\n    signal=signal.astype(np.int16)\r\n\r\n    #waveファイルに書き込む\r\n    wave_out = wave.open(file_name, 'w')\r\n\r\n    #モノラル:1、ステレオ:2\r\n    wave_out.setnchannels(1)\r\n\r\n    #サンプルサイズ2byte\r\n    wave_out.setsampwidth(2)\r\n\r\n    #サンプリング周波数\r\n    wave_out.setframerate(sample_rate)\r\n\r\n    #データを書き込み\r\n    wave_out.writeframes(signal)\r\n\r\n    #ファイルを閉じる\r\n    wave_out.close()\r\n\r\n#SNRをはかる\r\n#desired: 目的音、Lt\r\n#out:　雑音除去後の信号 Lt\r\ndef calculate_snr(desired,out):\r\n    wave_length=np.minimum(np.shape(desired)[0],np.shape(out)[0])\r\n\r\n    #消し残った雑音\r\n    desired=desired[:wave_length]\r\n    out=out[:wave_length]\r\n    noise=desired-out\r\n    snr=10.*np.log10(np.sum(np.square(desired))/np.sum(np.square(noise)))\r\n\r\n    return(snr)\r\n\r\n#乱数の種を初期化\r\nnp.random.seed(0)\r\n\r\n#畳み込みに用いる音声波形\r\nclean_wave_files=[\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\",\"./CMU_ARCTIC/cmu_us_axb_arctic/wav/arctic_a0002.wav\"]\r\n\r\n#音源数\r\nn_sources=len(clean_wave_files)\r\n\r\n#長さを調べる\r\nn_samples=0\r\n#ファイルを読み込む\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    if n_samples<wav.getnframes():\r\n        n_samples=wav.getnframes()\r\n    wav.close()\r\n\r\nclean_data=np.zeros([n_sources,n_samples])\r\n\r\n#ファイルを読み込む\r\ns=0\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    data=wav.readframes(wav.getnframes())\r\n    data=np.frombuffer(data, dtype=np.int16)\r\n    data=data/np.iinfo(np.int16).max\r\n    clean_data[s,:wav.getnframes()]=data\r\n    wav.close()\r\n    s=s+1\r\n\r\n\r\n# シミュレーションのパラメータ\r\n\r\n#シミュレーションで用いる音源数\r\nn_sim_sources=2\r\n\r\n#サンプリング周波数\r\nsample_rate=16000\r\n\r\n#フレームサイズ\r\nN=1024\r\n\r\n#周波数の数\r\nNk=int(N/2+1)\r\n\r\n#各ビンの周波数\r\nfreqs=np.arange(0,Nk,1)*sample_rate/N\r\n\r\n#音声と雑音との比率 [dB]\r\nSNR=90.\r\n\r\n#方位角の閾値\r\nazimuth_th=30.\r\n\r\n#部屋の大きさ\r\nroom_dim = np.r_[10.0, 10.0, 10.0]\r\n\r\n#マイクロホンアレイを置く部屋の場所\r\nmic_array_loc = room_dim / 2 + np.random.randn(3) * 0.1 \r\n\r\n#マイクロホンアレイのマイク配置\r\nmic_directions=np.array(\r\n    [[np.pi/2., theta/180.*np.pi] for theta in np.arange(180,361,180)\r\n    ]    )\r\n\r\ndistance=0.01\r\nmic_alignments=np.zeros((3, mic_directions.shape[0]), dtype=mic_directions.dtype)\r\nmic_alignments[0, :] = np.cos(mic_directions[:, 1]) * np.sin(mic_directions[:, 0])\r\nmic_alignments[1, :] = np.sin(mic_directions[:, 1]) * np.sin(mic_directions[:, 0])\r\nmic_alignments[2, :] = np.cos(mic_directions[:, 0])\r\nmic_alignments *= distance\r\n\r\n#マイクロホン数\r\nn_channels=np.shape(mic_alignments)[1]\r\n\r\n#マイクロホンアレイの座標\r\nR=mic_alignments+mic_array_loc[:,None]\r\n\r\nis_use_reverb=True\r\n\r\nif is_use_reverb==False:\r\n    # 部屋を生成する\r\n    room = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0) \r\n    room_no_noise_left = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\n    room_no_noise_right = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\n\r\nelse:\r\n\r\n    room = pa.ShoeBox(room_dim, fs=sample_rate, max_order=17,absorption=0.4)\r\n    room_no_noise_left = pa.ShoeBox(room_dim, fs=sample_rate, max_order=17,absorption=0.4)\r\n    room_no_noise_right = pa.ShoeBox(room_dim, fs=sample_rate, max_order=17,absorption=0.4)\r\n\r\n# 用いるマイクロホンアレイの情報を設定する\r\nroom.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\nroom_no_noise_left.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\nroom_no_noise_right.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\n\r\n#音源の場所\r\ndoas=np.array(\r\n    [[np.pi/2., np.pi],\r\n     [np.pi/2., 0]\r\n    ]    )\r\n\r\n#音源とマイクロホンの距離\r\ndistance=1.\r\n\r\nsource_locations=np.zeros((3, doas.shape[0]), dtype=doas.dtype)\r\nsource_locations[0, :] = np.cos(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[1, :] = np.sin(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[2, :] = np.cos(doas[:, 0])\r\nsource_locations *= distance\r\nsource_locations += mic_array_loc[:, None]\r\n\r\n#各音源をシミュレーションに追加する\r\nfor s in range(n_sim_sources):\r\n    clean_data[s]/= np.std(clean_data[s])\r\n    room.add_source(source_locations[:, s], signal=clean_data[s])\r\n    if s==0:\r\n        room_no_noise_left.add_source(source_locations[:, s], signal=clean_data[s])\r\n    if s==1:\r\n        room_no_noise_right.add_source(source_locations[:, s], signal=clean_data[s])\r\n\r\n#シミュレーションを回す\r\nroom.simulate(snr=SNR)\r\nroom_no_noise_left.simulate(snr=90)\r\nroom_no_noise_right.simulate(snr=90)\r\n\r\n#畳み込んだ波形を取得する(チャンネル、サンプル）\r\nmulti_conv_data=room.mic_array.signals\r\nmulti_conv_data_left_no_noise=room_no_noise_left.mic_array.signals\r\nmulti_conv_data_right_no_noise=room_no_noise_right.mic_array.signals\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data_left_no_noise[0,:]*np.iinfo(np.int16).max/20.,\"./ica_left_clean.wav\",sample_rate)\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data_right_no_noise[0,:]*np.iinfo(np.int16).max/20.,\"./ica_right_clean.wav\",sample_rate)\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data[0,:]*np.iinfo(np.int16).max/20.,\"./ica_in_left.wav\",sample_rate)\r\nwrite_file_from_time_signal(multi_conv_data[0,:]*np.iinfo(np.int16).max/20.,\"./ica_in_right.wav\",sample_rate)\r\n\r\n#短時間フーリエ変換を行う\r\nf,t,stft_data=sp.stft(multi_conv_data,fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\n#ICAの繰り返し回数\r\nn_ica_iterations=50\r\n\r\n#ILRMAの基底数\r\nn_basis=2\r\n\r\n#処理するフレーム数\r\nLt=np.shape(stft_data)[-1]\r\n\r\n#ICAの分離フィルタを初期化\r\nWica=np.zeros(shape=(Nk,n_sources,n_sources),dtype=np.complex)\r\n#Wica=np.random.normal(size=Nk*n_sources*n_sources)+1.j*np.random.normal(size=Nk*n_sources*n_sources)\r\n#Wica=np.reshape(Wica,(Nk,n_sources,n_sources))\r\n\r\nWica=Wica+np.eye(n_sources)[None,...]\r\n\r\nWiva=Wica.copy()\r\nWiva_ip=Wica.copy()\r\nWilrma_ip=Wica.copy()\r\n\r\n#ILRMA用\r\nb=np.ones(shape=(Nk,n_sources,n_basis))\r\na=np.random.uniform(size=(n_basis*n_sources*Lt))\r\na=np.reshape(a,(n_basis,n_sources,Lt))\r\n\r\n#Pyroomacousticsによる音源分離\r\n#nframes, nfrequencies, nchannels\r\n#入力信号のインデックスの順番を( M, Nk, Lt)から(Lt,Nk,M)に変換する\r\ny_pa_auxiva=pa.bss.auxiva(np.transpose(stft_data,(2,1,0)),n_iter=n_ica_iterations)\r\ny_pa_auxiva=np.transpose(y_pa_auxiva,(2,1,0))[None,...]\r\n\r\ny_pa_ilrma=pa.bss.ilrma(np.transpose(stft_data,(2,1,0)),n_iter=n_ica_iterations)\r\ny_pa_ilrma=np.transpose(y_pa_ilrma,(2,1,0))[None,...]\r\n\r\ny_pa_fastmnmf=pa.bss.fastmnmf(np.transpose(stft_data,(2,1,0)),n_iter=n_ica_iterations,initialize_ilrma=True)\r\ny_pa_fastmnmf=np.transpose(y_pa_fastmnmf,(2,1,0))[None,...]\r\n\r\nstart_time=time.time()\r\n#自然勾配法に基づくIVA実行コード（引数に与える関数を変更するだけ)\r\nWiva,s_iva,cost_buff_iva=execute_natural_gradient_ica(stft_data,Wiva,phi_func=phi_multivariate_laplacian,contrast_func=contrast_multivariate_laplacian,mu=0.1,n_ica_iterations=n_ica_iterations,is_use_non_holonomic=False)\r\ny_iva=projection_back(s_iva,Wiva)\r\niva_time=time.time()\r\n\r\n#IP法に基づくIVA実行コード（引数に与える関数を変更するだけ)\r\nWilrma_ip,s_ilrma_ip,cost_buff_ilrma_ip=execute_ip_time_varying_gaussian_ilrma(stft_data,Wilrma_ip,a,b,n_iterations=n_ica_iterations)\r\ny_ilrma_ip=projection_back(s_ilrma_ip,Wilrma_ip)\r\nilrma_ip_time=time.time()\r\n\r\n#IP法に基づくIVA実行コード（引数に与える関数を変更するだけ)\r\nWiva_ip,s_iva_ip,cost_buff_iva_ip=execute_ip_multivariate_laplacian_iva(stft_data,Wiva_ip,n_iterations=n_ica_iterations)\r\ny_iva_ip=projection_back(s_iva_ip,Wiva_ip)\r\niva_ip_time=time.time()\r\n\r\nWica,s_ica,cost_buff_ica=execute_natural_gradient_ica(stft_data,Wica,mu=0.1,n_ica_iterations=n_ica_iterations,is_use_non_holonomic=False)\r\npermutation_index_result=solver_inter_frequency_permutation(s_ica)\r\ny_ica=projection_back(s_ica,Wica)\r\n#パーミュテーションを解く\r\nfor k in range(Nk):\r\n    y_ica[:,:,k,:]=y_ica[:,permutation_index_result[k],k,:]\r\n\r\nica_time=time.time()\r\n\r\n#MM法に基づくLGM実行コード\r\nRlgm_mm,vlgm_mm,y_lgm_mm,cost_buff_lgm_mm=execute_mm_lgm(stft_data,Ns=n_sources,n_iterations=n_ica_iterations)\r\npermutation_index_result=solver_inter_frequency_permutation(y_lgm_mm[0,...])\r\n#パーミュテーションを解く\r\nfor k in range(Nk):\r\n    y_lgm_mm[:,:,k,:]=y_lgm_mm[:,permutation_index_result[k],k,:]\r\n\r\nlgm_mm_time=time.time()\r\n\r\n#EMアルゴリズムに基づくLGM実行コード\r\nRlgm_em,vlgm_em,y_lgm_em,cost_buff_lgm_em=execute_em_lgm(stft_data,Ns=n_sources,n_iterations=n_ica_iterations)\r\npermutation_index_result=solver_inter_frequency_permutation(y_lgm_em[0,...])\r\n#パーミュテーションを解く\r\nfor k in range(Nk):\r\n    y_lgm_em[:,:,k,:]=y_lgm_em[:,permutation_index_result[k],k,:]\r\n\r\nlgm_em_time=time.time()\r\n\r\nt,y_pa_auxiva=sp.istft(y_pa_auxiva[0,...],fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,y_pa_ilrma=sp.istft(y_pa_ilrma[0,...],fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,y_pa_fastmnmf=sp.istft(y_pa_fastmnmf[0,...],fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,y_ica=sp.istft(y_ica[0,...],fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,y_iva=sp.istft(y_iva[0,...],fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,y_iva_ip=sp.istft(y_iva_ip[0,...],fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,y_ilrma_ip=sp.istft(y_ilrma_ip[0,...],fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,y_lgm_em=sp.istft(y_lgm_em[0,...],fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,y_lgm_mm=sp.istft(y_lgm_mm[0,...],fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\nsnr_pre=calculate_snr(multi_conv_data_left_no_noise[0,...],multi_conv_data[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],multi_conv_data[0,...])\r\nsnr_pre/=2.\r\n\r\nsnr_ica_post1=calculate_snr(multi_conv_data_left_no_noise[0,...],y_ica[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_ica[1,...])\r\nsnr_ica_post2=calculate_snr(multi_conv_data_left_no_noise[0,...],y_ica[1,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_ica[0,...])\r\n\r\nsnr_ica_post=np.maximum(snr_ica_post1,snr_ica_post2)\r\nsnr_ica_post/=2.\r\n\r\nsnr_pa_ilrma_post1=calculate_snr(multi_conv_data_left_no_noise[0,...],y_pa_ilrma[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_pa_ilrma[1,...])\r\nsnr_pa_ilrma_post2=calculate_snr(multi_conv_data_left_no_noise[0,...],y_pa_ilrma[1,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_pa_ilrma[0,...])\r\n\r\nsnr_pa_ilrma_post=np.maximum(snr_pa_ilrma_post1,snr_pa_ilrma_post2)\r\nsnr_pa_ilrma_post/=2.\r\n\r\nsnr_pa_fastmnmf_post1=calculate_snr(multi_conv_data_left_no_noise[0,...],y_pa_fastmnmf[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_pa_fastmnmf[1,...])\r\nsnr_pa_fastmnmf_post2=calculate_snr(multi_conv_data_left_no_noise[0,...],y_pa_fastmnmf[1,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_pa_fastmnmf[0,...])\r\n\r\nsnr_pa_fastmnmf_post=np.maximum(snr_pa_fastmnmf_post1,snr_pa_fastmnmf_post2)\r\nsnr_pa_fastmnmf_post/=2.\r\n\r\nsnr_pa_auxiva_post1=calculate_snr(multi_conv_data_left_no_noise[0,...],y_pa_auxiva[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_pa_auxiva[1,...])\r\nsnr_pa_auxiva_post2=calculate_snr(multi_conv_data_left_no_noise[0,...],y_pa_auxiva[1,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_pa_auxiva[0,...])\r\n\r\nsnr_pa_auxiva_post=np.maximum(snr_pa_auxiva_post1,snr_pa_auxiva_post2)\r\nsnr_pa_auxiva_post/=2.\r\n\r\nsnr_iva_post1=calculate_snr(multi_conv_data_left_no_noise[0,...],y_iva[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_iva[1,...])\r\nsnr_iva_post2=calculate_snr(multi_conv_data_left_no_noise[0,...],y_iva[1,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_iva[0,...])\r\n\r\nsnr_iva_post=np.maximum(snr_iva_post1,snr_iva_post2)\r\nsnr_iva_post/=2.\r\n\r\nsnr_iva_ip_post1=calculate_snr(multi_conv_data_left_no_noise[0,...],y_iva_ip[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_iva_ip[1,...])\r\nsnr_iva_ip_post2=calculate_snr(multi_conv_data_left_no_noise[0,...],y_iva_ip[1,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_iva_ip[0,...])\r\n\r\nsnr_iva_ip_post=np.maximum(snr_iva_ip_post1,snr_iva_ip_post2)\r\nsnr_iva_ip_post/=2.\r\n\r\nsnr_ilrma_ip_post1=calculate_snr(multi_conv_data_left_no_noise[0,...],y_ilrma_ip[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_ilrma_ip[1,...])\r\nsnr_ilrma_ip_post2=calculate_snr(multi_conv_data_left_no_noise[0,...],y_ilrma_ip[1,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_ilrma_ip[0,...])\r\n\r\nsnr_ilrma_ip_post=np.maximum(snr_ilrma_ip_post1,snr_ilrma_ip_post2)\r\nsnr_ilrma_ip_post/=2.\r\n\r\nsnr_lgm_mm_post1=calculate_snr(multi_conv_data_left_no_noise[0,...],y_lgm_mm[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_lgm_mm[1,...])\r\nsnr_lgm_mm_post2=calculate_snr(multi_conv_data_left_no_noise[0,...],y_lgm_mm[1,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_lgm_mm[0,...])\r\n\r\nsnr_lgm_mm_post=np.maximum(snr_lgm_mm_post1,snr_lgm_mm_post2)\r\nsnr_lgm_mm_post/=2.\r\n\r\nsnr_lgm_em_post1=calculate_snr(multi_conv_data_left_no_noise[0,...],y_lgm_em[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_lgm_em[1,...])\r\nsnr_lgm_em_post2=calculate_snr(multi_conv_data_left_no_noise[0,...],y_lgm_em[1,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_lgm_em[0,...])\r\n\r\nsnr_lgm_em_post=np.maximum(snr_lgm_em_post1,snr_lgm_em_post2)\r\nsnr_lgm_em_post/=2.\r\n\r\n\r\nwrite_file_from_time_signal(y_ica[0,...]*np.iinfo(np.int16).max/20.,\"./ica_1.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_ica[1,...]*np.iinfo(np.int16).max/20.,\"./ica_2.wav\",sample_rate)\r\n\r\nwrite_file_from_time_signal(y_pa_auxiva[0,...]*np.iinfo(np.int16).max/20.,\"./pa_auxiva_1.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_pa_auxiva[1,...]*np.iinfo(np.int16).max/20.,\"./pa_auxiva_2.wav\",sample_rate)\r\n\r\nwrite_file_from_time_signal(y_pa_ilrma[0,...]*np.iinfo(np.int16).max/20.,\"./pa_ilrma_1.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_pa_ilrma[1,...]*np.iinfo(np.int16).max/20.,\"./pa_ilrma_2.wav\",sample_rate)\r\n\r\nwrite_file_from_time_signal(y_pa_fastmnmf[0,...]*np.iinfo(np.int16).max/20.,\"./pa_fastmnmf_1.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_pa_fastmnmf[1,...]*np.iinfo(np.int16).max/20.,\"./pa_fastmnmf_2.wav\",sample_rate)\r\n\r\n\r\nwrite_file_from_time_signal(y_iva[0,...]*np.iinfo(np.int16).max/20.,\"./iva_1.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_iva[1,...]*np.iinfo(np.int16).max/20.,\"./iva_2.wav\",sample_rate)\r\n\r\nwrite_file_from_time_signal(y_iva_ip[0,...]*np.iinfo(np.int16).max/20.,\"./iva_ip_1.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_iva_ip[1,...]*np.iinfo(np.int16).max/20.,\"./iva_ip_2.wav\",sample_rate)\r\n\r\nwrite_file_from_time_signal(y_ilrma_ip[0,...]*np.iinfo(np.int16).max/20.,\"./ilrma_ip_1.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_ilrma_ip[1,...]*np.iinfo(np.int16).max/20.,\"./ilrma_ip_2.wav\",sample_rate)\r\n\r\nwrite_file_from_time_signal(y_lgm_em[0,...]*np.iinfo(np.int16).max/20.,\"./lgm_em_1.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_lgm_em[1,...]*np.iinfo(np.int16).max/20.,\"./lgm_em_2.wav\",sample_rate)\r\n\r\nwrite_file_from_time_signal(y_lgm_mm[0,...]*np.iinfo(np.int16).max/20.,\"./lgm_mm_1.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_lgm_mm[1,...]*np.iinfo(np.int16).max/20.,\"./lgm_mm_2.wav\",sample_rate)\r\n\r\n\r\nprint(\"method:    \", \"PA-AUXIVA\",\"PA-ILRMA\",\"PA-FASTMNMF\",\"NG-ICA\", \"NG-IVA\", \"AuxIVA\", \"ILRMA\",\"LGM-EM\",\"LGM-MM\")\r\nprint(\"処理時間[sec]: {:.2f} [sec]  {:.2f} [sec]  {:.2f} [sec]  {:.2f} [sec]  {:.2f} [sec] {:.2f} [sec]\".format(ica_time-iva_ip_time,iva_ip_time-ilrma_ip_time,iva_time-start_time,ilrma_ip_time-iva_time,lgm_em_time-lgm_mm_time,lgm_mm_time-ica_time))\r\nprint(\"Δsnr [dB]: {:.2f}   {:.2f}   {:.2f}   {:.2f}  {:.2f}  {:.2f}  {:.2f}   {:.2f}  {:.2f}\".format(snr_pa_auxiva_post-snr_pre,snr_pa_ilrma_post-snr_pre,snr_pa_fastmnmf_post-snr_pre,snr_ica_post-snr_pre,snr_iva_post-snr_pre,snr_iva_ip_post-snr_pre,snr_ilrma_ip_post-snr_pre,snr_lgm_em_post-snr_pre,snr_lgm_mm_post-snr_pre))\r\n\r\n#コストの値を表示\r\n#for t in range(n_ica_iterations):\r\n#    print(t,cost_buff_ica[t],cost_buff_iva[t],cost_buff_iva_ip[t],cost_buff_ilrma_ip[t],cost_buff_lgm_em[t],cost_buff_lgm_mm[t])\r\n"
  },
  {
    "path": "section11/sample_code_c11_2.py",
    "content": "\r\n\r\nimport wave as wave\r\nimport pyroomacoustics as pa\r\nimport numpy as np\r\nimport scipy.signal as sp\r\nimport scipy as scipy\r\n\r\nimport time\r\n\r\nimport nara_wpe.wpe as wpe\r\n\r\n\r\n\r\n#x:入力信号( M, Nk, Lt)\r\n#D:遅延フレーム数\r\n#Lh:残響除去フィルタのタップ長\r\n#return x_bar: 過去のマイク入力信号(Lh,M,Nk,Lt)\r\ndef make_x_bar(x,D,Lh):\r\n    \r\n    #フレーム数を取得\r\n    Lt=np.shape(x)[2]\r\n\r\n    #過去のマイク入力信号の配列を準備\r\n    x_bar=np.zeros(shape=(Lh,)+np.shape(x),dtype=np.complex)\r\n\r\n    for tau in range(Lh):\r\n        x_bar[tau,...,tau+D:]=x[:,:,:-(tau+D)]\r\n\r\n    return(x_bar)\r\n\r\n#最小二乗で除去\r\n#x:入力信号( M, Nk, Lt)\r\n#x_bar:過去のマイク入力信号(Lh,M, Nk, Lt)\r\n#return x_dereverb:残響除去後の信号(Nk,Lt)\r\ndef dereverberation_ls(x,x_bar):\r\n\r\n    #マイクロホン数・周波数・フレーム数・タップ長を取得する\r\n    M=np.shape(x)[0]\r\n    Nk=np.shape(x)[1]\r\n    Lt=np.shape(x)[2]\r\n    Lh=np.shape(x_bar)[0]\r\n\r\n    x_bar=np.reshape(x_bar,[Lh*M,Nk,Lt])\r\n    x_bar_x_bar_h=np.einsum('ikt,jkt->kij',x_bar,np.conjugate(x_bar))\r\n    #covariance_inverse=np.linalg.pinv(x_bar_x_bar_h)\r\n    \r\n    correlation=np.einsum('ikt,kt->ki',x_bar,np.conjugate(x[0,...]))\r\n    \r\n    filter=np.linalg.solve(x_bar_x_bar_h,correlation)\r\n\r\n    #filter=np.einsum('kij,kj->ki',covariance_inverse,correlation)\r\n    x_reverb=np.einsum('kj,jkt->kt',np.conjugate(filter),x_bar)\r\n\r\n    x_dereverb=x[0,...]-x_reverb\r\n        \r\n    return(x_dereverb)\r\n\r\n#WPEで残響を除去\r\n#x:入力信号( M, Nk, Lt)\r\n#x_bar:過去のマイク入力信号(Lh,M, Nk, Lt)\r\n#return x_dereverb:残響除去後の信号(Nk,Lt)\r\ndef dereverberation_wpe(x,x_bar,wpe_iterations=10):\r\n\r\n    #マイクロホン数・周波数・フレーム数・タップ長を取得する\r\n    M=np.shape(x)[0]\r\n    Nk=np.shape(x)[1]\r\n    Lt=np.shape(x)[2]\r\n    Lh=np.shape(x_bar)[0]\r\n\r\n    #入力信号の形式を変更・変数を初期化\r\n    x_bar=np.reshape(x_bar,[Lh*M,Nk,Lt])\r\n    v=np.square(np.abs(x[0,...]))\r\n\r\n    cost_buff=[]\r\n    for t in range(wpe_iterations):\r\n        #共分散行列を計算\r\n        x_bar_x_bar_h=np.einsum('kt,ikt,jkt->kij',1./v,x_bar,np.conjugate(x_bar))\r\n\r\n        #相関ベクトルを計算\r\n        correlation=np.einsum('kt,ikt,kt->ki',1./v,x_bar,np.conjugate(x[0,...]))\r\n\r\n        #フィルタ算出\r\n        filter=np.linalg.solve(x_bar_x_bar_h,correlation)\r\n        \r\n        #残響除去実施\r\n        x_reverb=np.einsum('kj,jkt->kt',np.conjugate(filter),x_bar)\r\n        x_dereverb=x[0,...]-x_reverb\r\n\r\n        #パラメータ更新\r\n        v=np.square(np.abs(x_dereverb))\r\n        v=np.maximum(v,1.e-8)\r\n\r\n        #コスト計算\r\n        cost=np.mean(np.log(v))\r\n        cost_buff.append(cost)\r\n    return(x_dereverb,cost_buff)\r\n\r\n\r\n#2バイトに変換してファイルに保存\r\n#signal: time-domain 1d array (float)\r\n#file_name: 出力先のファイル名\r\n#sample_rate: サンプリングレート\r\ndef write_file_from_time_signal(signal,file_name,sample_rate):\r\n    #2バイトのデータに変換\r\n    signal=signal.astype(np.int16)\r\n\r\n    #waveファイルに書き込む\r\n    wave_out = wave.open(file_name, 'w')\r\n\r\n    #モノラル:1、ステレオ:2\r\n    wave_out.setnchannels(1)\r\n\r\n    #サンプルサイズ2byte\r\n    wave_out.setsampwidth(2)\r\n\r\n    #サンプリング周波数\r\n    wave_out.setframerate(sample_rate)\r\n\r\n    #データを書き込み\r\n    wave_out.writeframes(signal)\r\n\r\n    #ファイルを閉じる\r\n    wave_out.close()\r\n\r\n#SNRをはかる\r\n#desired: 目的音、Lt\r\n#out:　雑音除去後の信号 Lt\r\ndef calculate_snr(desired,out):\r\n    wave_length=np.minimum(np.shape(desired)[0],np.shape(out)[0])\r\n\r\n    #消し残った雑音\r\n    desired=desired[:wave_length]\r\n    out=out[:wave_length]\r\n    noise=desired-out\r\n    snr=10.*np.log10(np.sum(np.square(desired))/np.sum(np.square(noise)))\r\n\r\n    return(snr)\r\n\r\n#乱数の種を初期化\r\nnp.random.seed(0)\r\n\r\n#畳み込みに用いる音声波形\r\nclean_wave_files=[\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\"]\r\n\r\n#音源数\r\nn_sources=len(clean_wave_files)\r\n\r\n#長さを調べる\r\nn_samples=0\r\n#ファイルを読み込む\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    if n_samples<wav.getnframes():\r\n        n_samples=wav.getnframes()\r\n    wav.close()\r\n\r\nclean_data=np.zeros([n_sources,n_samples])\r\n\r\n#ファイルを読み込む\r\ns=0\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    data=wav.readframes(wav.getnframes())\r\n    data=np.frombuffer(data, dtype=np.int16)\r\n    data=data/np.iinfo(np.int16).max\r\n    clean_data[s,:wav.getnframes()]=data\r\n    wav.close()\r\n    s=s+1\r\n\r\n\r\n# シミュレーションのパラメータ\r\n\r\n#シミュレーションで用いる音源数\r\nn_sim_sources=1\r\n\r\n#サンプリング周波数\r\nsample_rate=16000\r\n\r\n#フレームサイズ\r\nN=1024\r\n\r\n#フレームシフト\r\nNshift=int(N/4)\r\n\r\n\r\n#周波数の数\r\nNk=int(N/2+1)\r\n\r\n#各ビンの周波数\r\nfreqs=np.arange(0,Nk,1)*sample_rate/N\r\n\r\n#音声と雑音との比率 [dB]\r\nSNR=90.\r\n\r\n#方位角の閾値\r\nazimuth_th=30.\r\n\r\n#部屋の大きさ\r\nroom_dim = np.r_[10.0, 10.0, 10.0]\r\n\r\n#マイクロホンアレイを置く部屋の場所\r\nmic_array_loc = room_dim / 2 + np.random.randn(3) * 0.1 \r\n\r\n#マイクロホンアレイのマイク配置\r\nmic_directions=np.array(\r\n    [[np.pi/2., theta/180.*np.pi] for theta in np.arange(180,361,180)\r\n    ]    )\r\n\r\ndistance=0.01\r\nmic_alignments=np.zeros((3, mic_directions.shape[0]), dtype=mic_directions.dtype)\r\nmic_alignments[0, :] = np.cos(mic_directions[:, 1]) * np.sin(mic_directions[:, 0])\r\nmic_alignments[1, :] = np.sin(mic_directions[:, 1]) * np.sin(mic_directions[:, 0])\r\nmic_alignments[2, :] = np.cos(mic_directions[:, 0])\r\nmic_alignments *= distance\r\n\r\n#マイクロホン数\r\nn_channels=np.shape(mic_alignments)[1]\r\n\r\n#マイクロホンアレイの座標\r\nR=mic_alignments+mic_array_loc[:,None]\r\n\r\nis_use_reverb=True\r\nroom = pa.ShoeBox(room_dim, fs=sample_rate, max_order=17,absorption=0.4)\r\nroom_no_reverb = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\n\r\n# 用いるマイクロホンアレイの情報を設定する\r\nroom.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\nroom_no_reverb.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\n\r\n#音源の場所\r\ndoas=np.array(\r\n    [[np.pi/2., np.pi]\r\n    ]    )\r\n\r\n#音源とマイクロホンの距離\r\ndistance=1.\r\n\r\nsource_locations=np.zeros((3, doas.shape[0]), dtype=doas.dtype)\r\nsource_locations[0, :] = np.cos(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[1, :] = np.sin(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[2, :] = np.cos(doas[:, 0])\r\nsource_locations *= distance\r\nsource_locations += mic_array_loc[:, None]\r\n\r\n#各音源をシミュレーションに追加する\r\nfor s in range(n_sim_sources):\r\n    clean_data[s]/= np.std(clean_data[s])\r\n    room.add_source(source_locations[:, s], signal=clean_data[s])\r\n    room_no_reverb.add_source(source_locations[:, s], signal=clean_data[s])\r\n    \r\n\r\n#シミュレーションを回す\r\nroom.simulate(snr=SNR)\r\nroom_no_reverb.simulate(snr=90)\r\n\r\n#畳み込んだ波形を取得する(チャンネル、サンプル）\r\nmulti_conv_data=room.mic_array.signals\r\nmulti_conv_data_no_reverb=room_no_reverb.mic_array.signals\r\n\r\nwave_len=np.shape(multi_conv_data_no_reverb)[1]\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data_no_reverb[0,:wave_len]*np.iinfo(np.int16).max/20.,\"./dereverb_clean.wav\",sample_rate)\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data[0,:wave_len]*np.iinfo(np.int16).max/20.,\"./dereverb_in.wav\",sample_rate)\r\n\r\n#短時間フーリエ変換を行う\r\nf,t,stft_data=sp.stft(multi_conv_data,fs=sample_rate,window=\"hann\",nperseg=N,noverlap=N-Nshift)\r\n\r\n#WPEの繰り返し回数\r\nn_wpe_iterations=20\r\n\r\n#残響除去のパラメータ\r\nD=2\r\nLh=5\r\n\r\n#過去のマイクロホン入力信号\r\nx_bar=make_x_bar(stft_data,D,Lh)\r\n\r\n#WPEで残響除去\r\nx_dereverb_wpe,cost_buff_wpe=dereverberation_wpe(stft_data,x_bar,n_wpe_iterations)\r\n\r\n#nara WPEで残響除去\r\nx_dereverb_nara_wpe=wpe.wpe(np.transpose(stft_data,(1,0,2)),taps=Lh,delay=D,iterations=n_wpe_iterations)\r\nx_dereverb_nara_wpe=np.transpose(x_dereverb_nara_wpe,(1,0,2))[0,...]\r\n\r\n\r\n#x:入力信号( M, Nk, Lt)\r\n\r\nt,x_dereverb_wpe=sp.istft(x_dereverb_wpe,fs=sample_rate,window=\"hann\",nperseg=N,noverlap=N-Nshift)\r\nt,x_dereverb_nara_wpe=sp.istft(x_dereverb_nara_wpe,fs=sample_rate,window=\"hann\",nperseg=N,noverlap=N-Nshift)\r\n\r\nsnr_pre=calculate_snr(multi_conv_data_no_reverb[0,...],multi_conv_data[0,...])\r\nsnr_wpe_post=calculate_snr(multi_conv_data_no_reverb[0,...],x_dereverb_wpe)\r\nsnr_nara_wpe_post=calculate_snr(multi_conv_data_no_reverb[0,...],x_dereverb_nara_wpe)\r\n\r\nwrite_file_from_time_signal(x_dereverb_wpe[:wave_len]*np.iinfo(np.int16).max/20.,\"./dereverb_wpe_{}_{}.wav\".format(Lh,D),sample_rate)\r\nwrite_file_from_time_signal(x_dereverb_nara_wpe[:wave_len]*np.iinfo(np.int16).max/20.,\"./dereverb_nara_wpe.wav\",sample_rate)\r\n\r\n\r\n\r\nprint(\"method:    \", \"WPE\",\"NARA-WPE\")\r\nprint(\"Δsnr [dB]: {:.2f} {:.2f}\".format(snr_wpe_post-snr_pre,snr_nara_wpe_post-snr_pre))\r\n\r\n#コストの値を表示\r\n#for t in range(n_wpe_iterations):\r\n#    print(t,cost_buff_wpe[t])\r\n\r\n"
  },
  {
    "path": "section11.md",
    "content": "\n## 第11章のサンプルコード\n\n* [pyroomacousticsによる音源分離技術](section11/sample_code_c11_1.py)\n* [NARA-WPEを用いた残響除去](section11/sample_code_c11_2.py)\n\n"
  },
  {
    "path": "section2/sample_code_c2_1.py",
    "content": "\r\n#wave形式の音声波形を読み込むためのモジュール(wave)をインポート\r\nimport wave as wave\r\n\r\n#pyroomacousticsをインポート (ここではデータセットをダウンロードするために使用)\r\nimport pyroomacoustics as pa\r\n\r\n#numpyをインポート（波形データを2byteの数値列に変換するために使用）\r\nimport numpy as np\r\n\r\n#CMU ARCTIC Corpusをカレントディレクトリにダウンロード\r\npa.datasets.CMUArcticCorpus(basedir=\"./CMU_ARCTIC\",download=True,speaker=[\"aew\",\"axb\"])\r\n\r\n#読み込むサンプルファイル\r\nsample_wave_file=\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\"\r\n\r\n#ファイルを読み込む\r\nwav=wave.open(sample_wave_file)\r\n\r\n#ファイルの情報を出力する\r\nprint(\"サンプリング周波数[Hz]: \",wav.getframerate()) \r\nprint(\"サンプルサイズ[Byte]: \", wav.getsampwidth())\r\nprint(\"サンプル数: \",wav.getnframes()) \r\nprint(\"チャンネル数: \",wav.getnchannels()) \r\n\r\n#PCM形式の波形データを読み込み\r\ndata=wav.readframes(wav.getnframes())\r\n\r\n#dataを2バイトの数値列に変換\r\ndata=np.frombuffer(data, dtype=np.int16)\r\n\r\n#waveファイルを閉じる\r\nwav.close()\r\n\r\n"
  },
  {
    "path": "section2/sample_code_c2_10.py",
    "content": "\r\n\r\n#wave形式の音声波形を読み込むためのモジュール(wave)をインポート\r\nimport wave as wave\r\n\r\n#numpyをインポート（波形データを2byteの数値列に変換するために使用）\r\nimport numpy as np\r\n\r\n#scipyのsignalモジュールをインポート（stft等信号処理計算用)\r\nimport scipy.signal as sp\r\n\r\n#読み込むサンプルファイル\r\nsample_wave_file=\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\"\r\n\r\n#ファイルを読み込む\r\nwav=wave.open(sample_wave_file)\r\n\r\n#PCM形式の波形データを読み込み\r\ndata=wav.readframes(wav.getnframes())\r\n\r\n#dataを2バイトの数値列に変換\r\ndata=np.frombuffer(data, dtype=np.int16)\r\n\r\n#短時間フーリエ変換を行う\r\nf,t,stft_data=sp.stft(data,fs=wav.getframerate(),window=\"hann\",nperseg=512,noverlap=256)\r\n\r\n#時間領域の波形に戻す\r\nt,data_post=sp.istft(stft_data,fs=wav.getframerate(),window=\"hann\",nperseg=512,noverlap=256)\r\n\r\n#2バイトのデータに変換\r\ndata_post=data_post.astype(np.int16)\r\n\r\n#waveファイルに書き込む\r\nwave_out = wave.open(\"./istft_post_wave.wav\", 'w')\r\n\r\n#モノラル:1、ステレオ:2\r\nwave_out.setnchannels(1)\r\n\r\n#サンプルサイズ2byte\r\nwave_out.setsampwidth(2)\r\n\r\n#サンプリング周波数\r\nwave_out.setframerate(wav.getframerate())\r\n\r\n#データを書き込み\r\nwave_out.writeframes(data_post)\r\n\r\n#ファイルを閉じる\r\nwave_out.close()\r\n\r\n#waveファイルを閉じる\r\nwav.close()"
  },
  {
    "path": "section2/sample_code_c2_11.py",
    "content": "\r\n\r\n#wave形式の音声波形を読み込むためのモジュール(wave)をインポート\r\nimport wave as wave\r\n\r\n#numpyをインポート（波形データを2byteの数値列に変換するために使用）\r\nimport numpy as np\r\n\r\n#scipyのsignalモジュールをインポート（stft等信号処理計算用)\r\nimport scipy.signal as sp\r\n\r\n#sounddeviceモジュールをインポート\r\nimport sounddevice as sd\r\n\r\n#読み込むサンプルファイル\r\nsample_wave_file=\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\"\r\n\r\n#ファイルを読み込む\r\nwav=wave.open(sample_wave_file)\r\n\r\n#PCM形式の波形データを読み込み\r\ndata=wav.readframes(wav.getnframes())\r\n\r\n#dataを2バイトの数値列に変換\r\ndata=np.frombuffer(data, dtype=np.int16)\r\n\r\n#短時間フーリエ変換を行う\r\nf,t,stft_data=sp.stft(data,fs=wav.getframerate(),window=\"hann\",nperseg=512,noverlap=256)\r\n\r\n#特定の周波数成分を消す(100番目の周波数よりも高い周波数成分を全て消す)\r\nstft_data[100:,:]=0\r\n\r\n\r\n#時間領域の波形に戻す\r\nt,data_post=sp.istft(stft_data,fs=wav.getframerate(),window=\"hann\",nperseg=512,noverlap=256)\r\n\r\n#2バイトのデータに変換\r\ndata_post=data_post.astype(np.int16)\r\n\r\n#dataを再生する\r\nsd.play(data_post,wav.getframerate())\r\n\r\nprint(\"再生開始\")\r\n\r\n#再生が終わるまで待つ\r\nstatus = sd.wait()\r\n\r\n#waveファイルを閉じる\r\nwav.close()\r\n"
  },
  {
    "path": "section2/sample_code_c2_12.py",
    "content": "\r\n\r\n#wave形式の音声波形を読み込むためのモジュール(wave)をインポート\r\nimport wave as wave\r\n\r\n#numpyをインポート（波形データを2byteの数値列に変換するために使用）\r\nimport numpy as np\r\n\r\n#scipyのsignalモジュールをインポート（stft等信号処理計算用)\r\nimport scipy.signal as sp\r\n\r\n#sounddeviceモジュールをインポート\r\nimport sounddevice as sd\r\n\r\n#読み込むサンプルファイル\r\nsample_wave_file=\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\"\r\n\r\n#ファイルを読み込む\r\nwav=wave.open(sample_wave_file)\r\n\r\n#PCM形式の波形データを読み込み\r\ndata=wav.readframes(wav.getnframes())\r\n\r\n#dataを2バイトの数値列に変換\r\ndata=np.frombuffer(data, dtype=np.int16)\r\n\r\n#短時間フーリエ変換を行う\r\nf,t,stft_data=sp.stft(data,fs=wav.getframerate(),window=\"hann\",nperseg=512,noverlap=256)\r\n\r\n#特定の周波数成分を消す(50番目の周波数よりも低い周波数成分を全て消す)\r\nstft_data[:50,:]=0\r\n\r\n\r\n#時間領域の波形に戻す\r\nt,data_post=sp.istft(stft_data,fs=wav.getframerate(),window=\"hann\",nperseg=512,noverlap=256)\r\n\r\n#2バイトのデータに変換\r\ndata_post=data_post.astype(np.int16)\r\n\r\n#dataを再生する\r\nsd.play(data_post,wav.getframerate())\r\n\r\nprint(\"再生開始\")\r\n\r\n#再生が終わるまで待つ\r\nstatus = sd.wait()\r\n\r\n#waveファイルを閉じる\r\nwav.close()\r\n"
  },
  {
    "path": "section2/sample_code_c2_13.py",
    "content": "\r\n\r\n#wave形式の音声波形を読み込むためのモジュール(wave)をインポート\r\nimport wave as wave\r\n\r\n#numpyをインポート（波形データを2byteの数値列に変換するために使用）\r\nimport numpy as np\r\n\r\n#scipyのsignalモジュールをインポート（stft等信号処理計算用)\r\nimport scipy.signal as sp\r\n\r\n#sounddeviceモジュールをインポート\r\nimport sounddevice as sd\r\n\r\n#乱数の種を設定\r\nnp.random.seed(0)\r\n\r\n#読み込むサンプルファイル\r\nsample_wave_file=\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\"\r\n\r\n#ファイルを読み込む\r\nwav=wave.open(sample_wave_file)\r\n\r\n#音声区間の長さを取る\r\nn_speech=wav.getnframes()\r\n\r\n#サンプリングレートを取る\r\nsampling_rate=wav.getframerate()\r\n\r\n#PCM形式の波形データを読み込み\r\nspeech_signal=wav.readframes(wav.getnframes())\r\n\r\n#speech_signalを2バイトの数値列に変換\r\nspeech_signal=np.frombuffer(speech_signal, dtype=np.int16)\r\n\r\n\r\n#音声データに白色雑音を混ぜる\r\n\r\n#雑音だけの区間のサンプル数を設定\r\nn_noise_only=40000\r\n\r\n#全体の長さ\r\nn_sample=n_noise_only+n_speech\r\n\r\n#白色雑音を生成\r\nwgn_signal=np.random.normal(scale=0.04,size=n_sample)\r\n\r\n#2バイトのデータとして書き込むためにスケールを調整 \r\nwgn_signal=wgn_signal*np.iinfo(np.int16).max\r\n\r\n#2バイトのデータに変換\r\nwgn_signal=wgn_signal.astype(np.int16)\r\n\r\n#白色雑音を混ぜる\r\nmix_signal=wgn_signal\r\nmix_signal[n_noise_only:]+=speech_signal\r\n\r\n#短時間フーリエ変換を行う\r\nf,t,stft_data=sp.stft(mix_signal,fs=wav.getframerate(),window=\"hann\",nperseg=512,noverlap=256)\r\n\r\n#入力信号の振幅を取得\r\namp=np.abs(stft_data)\r\n\r\n#入力信号の位相を取得\r\nphase=stft_data/np.maximum(amp,1.e-20)\r\n\r\n#雑音だけの区間のフレーム数\r\nn_noise_only_frame=np.sum(t<(n_noise_only/sampling_rate))\r\n\r\n#スペクトルサブトラクションのパラメータ\r\np=1.0\r\nalpha=2.0\r\n\r\n#雑音の振幅を推定\r\nnoise_amp=np.power(np.mean(np.power(amp,p)[:,:n_noise_only_frame],axis=1,keepdims=True),1./p)\r\n\r\n\r\n#入力信号の振幅の1%を下回らないようにする\r\neps=0.01*np.power(amp,p)\r\n\r\n#出力信号の振幅を計算する\r\nprocessed_amp=np.power(np.maximum(np.power(amp,p)-alpha*np.power(noise_amp,p),eps), 1./p)\r\n\r\n#出力信号の振幅に入力信号の位相をかける\r\nprocessed_stft_data=processed_amp*phase\r\n\r\n#時間領域の波形に戻す\r\nt,processed_data_post=sp.istft(processed_stft_data,fs=wav.getframerate(),window=\"hann\",nperseg=512,noverlap=256)\r\n\r\n#2バイトのデータに変換\r\nprocessed_data_post=processed_data_post.astype(np.int16)\r\n\r\n#waveファイルに書き込む\r\nwave_out = wave.open(\"./process_wave_ss.wav\", 'w')\r\n\r\n#モノラル:1、ステレオ:2\r\nwave_out.setnchannels(1)\r\n\r\n#サンプルサイズ2byte\r\nwave_out.setsampwidth(2)\r\n\r\n#サンプリング周波数\r\nwave_out.setframerate(wav.getframerate())\r\n\r\n#データを書き込み\r\nwave_out.writeframes(processed_data_post)\r\n\r\n#ファイルを閉じる\r\nwave_out.close()\r\n\r\nimport matplotlib.pyplot as plt \r\n\r\n\r\n#スペクトログラムをプロットする\r\nfig=plt.figure(figsize=(10,4))\r\n\n#スペクトログラムを表示する\nspectrum,  freqs, t, im=plt.specgram(processed_data_post,NFFT=512,noverlap=512/16*15,Fs=wav.getframerate(),cmap=\"gray\")\n\n#カラーバーを表示する\nfig.colorbar(im).set_label('Intensity [dB]')\n\n#x軸のラベル\r\nplt.xlabel(\"Time [sec]\")\r\n\r\n#y軸のラベル\r\nplt.ylabel(\"Frequency [Hz]\")\r\n\r\n#音声ファイルを画像として保存\r\nplt.savefig(\"./spectrogram_ss_result.png\")\r\n\r\n#画像を画面に表示\r\nplt.show()\r\n\r\n\r\n#雑音込みの入力信号も時間領域の波形に戻す\r\nt,data_post=sp.istft(stft_data,fs=wav.getframerate(),window=\"hann\",nperseg=512,noverlap=256)\r\n\r\n#2バイトのデータに変換\r\ndata_post=data_post.astype(np.int16)\r\n\r\n#スペクトログラムをプロットする\r\nfig=plt.figure(figsize=(10,4))\r\n\n#スペクトログラムを表示する\nspectrum,  freqs, t, im=plt.specgram(data_post,NFFT=512,noverlap=512/16*15,Fs=wav.getframerate(),cmap=\"gray\")\n\n#カラーバーを表示する\nfig.colorbar(im).set_label('Intensity [dB]')\n\n#x軸のラベル\r\nplt.xlabel(\"Time [sec]\")\r\n\r\n#y軸のラベル\r\nplt.ylabel(\"Frequency [Hz]\")\r\n\r\n#音声ファイルを画像として保存\r\nplt.savefig(\"./spectrogram_noisy.png\")\r\n\r\n#画像を画面に表示\r\nplt.show()\r\n\r\n#waveファイルに書き込む\r\nwave_out = wave.open(\"./input_wave.wav\", 'w')\r\n\r\n#モノラル:1、ステレオ:2\r\nwave_out.setnchannels(1)\r\n\r\n#サンプルサイズ2byte\r\nwave_out.setsampwidth(2)\r\n\r\n#サンプリング周波数\r\nwave_out.setframerate(wav.getframerate())\r\n\r\n#データを書き込み\r\nwave_out.writeframes(data_post)\r\n\r\n#ファイルを閉じる\r\nwave_out.close()\r\n\r\n#waveファイルを閉じる\r\nwav.close()\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "section2/sample_code_c2_14.py",
    "content": "\r\n\r\n#wave形式の音声波形を読み込むためのモジュール(wave)をインポート\r\nimport wave as wave\r\n\r\n#numpyをインポート（波形データを2byteの数値列に変換するために使用）\r\nimport numpy as np\r\n\r\n#scipyのsignalモジュールをインポート（stft等信号処理計算用)\r\nimport scipy.signal as sp\r\n\r\n#sounddeviceモジュールをインポート\r\nimport sounddevice as sd\r\n\r\n#乱数の種を設定\r\nnp.random.seed(0)\r\n\r\n#読み込むサンプルファイル\r\nsample_wave_file=\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\"\r\n\r\n#ファイルを読み込む\r\nwav=wave.open(sample_wave_file)\r\n\r\n#音声区間の長さを取る\r\nn_speech=wav.getnframes()\r\n\r\n#サンプリングレートを取る\r\nsampling_rate=wav.getframerate()\r\n\r\n#PCM形式の波形データを読み込み\r\nspeech_signal=wav.readframes(wav.getnframes())\r\n\r\n#speech_signalを2バイトの数値列に変換\r\nspeech_signal=np.frombuffer(speech_signal, dtype=np.int16)\r\n\r\n\r\n#音声データに白色雑音を混ぜる\r\n\r\n#雑音だけの区間のサンプル数を設定\r\nn_noise_only=40000\r\n\r\n#全体の長さ\r\nn_sample=n_noise_only+n_speech\r\n\r\n#白色雑音を生成\r\nwgn_signal=np.random.normal(scale=0.04,size=n_sample)\r\n\r\n#2バイトのデータとして書き込むためにスケールを調整 \r\nwgn_signal=wgn_signal*np.iinfo(np.int16).max\r\n\r\n#2バイトのデータに変換\r\nwgn_signal=wgn_signal.astype(np.int16)\r\n\r\n#白色雑音を混ぜる\r\nmix_signal=wgn_signal\r\nmix_signal[n_noise_only:]+=speech_signal\r\n\r\n#短時間フーリエ変換を行う\r\nf,t,stft_data=sp.stft(mix_signal,fs=wav.getframerate(),window=\"hann\",nperseg=512,noverlap=256)\r\n\r\n#入力信号の振幅を取得\r\namp=np.abs(stft_data)\r\n\r\n#入力信号のパワーを取得\r\ninput_power=np.power(amp,2.0)\r\n\r\n#雑音だけの区間のフレーム数\r\nn_noise_only_frame=np.sum(t<(n_noise_only/sampling_rate))\r\n\r\n#ウィナーフィルタのパラメータ\r\nalpha=1.0\r\nmu=10\r\n\r\n#雑音のパワーを推定\r\nnoise_power=np.mean(np.power(amp,2.0)[:,:n_noise_only_frame],axis=1,keepdims=True)\r\n\r\n#入力信号の音量の1%を下回らないようにする\r\neps=0.01*input_power\r\n\r\n#出力信号の振幅を計算する\r\nprocessed_power=np.maximum(input_power-alpha*noise_power,eps)\r\n\r\n#比率\r\nwf_ratio= processed_power/(processed_power+mu*noise_power)\r\n\r\n#出力信号の振幅に入力信号の位相をかける\r\nprocessed_stft_data=wf_ratio*stft_data\r\n\r\n#時間領域の波形に戻す\r\nt,processed_data_post=sp.istft(processed_stft_data,fs=wav.getframerate(),window=\"hann\",nperseg=512,noverlap=256)\r\n\r\n#2バイトのデータに変換\r\nprocessed_data_post=processed_data_post.astype(np.int16)\r\n\r\n#waveファイルに書き込む\r\nwave_out = wave.open(\"./process_wave_wf.wav\", 'w')\r\n\r\n#モノラル:1、ステレオ:2\r\nwave_out.setnchannels(1)\r\n\r\n#サンプルサイズ2byte\r\nwave_out.setsampwidth(2)\r\n\r\n#サンプリング周波数\r\nwave_out.setframerate(wav.getframerate())\r\n\r\n#データを書き込み\r\nwave_out.writeframes(processed_data_post)\r\n\r\n#ファイルを閉じる\r\nwave_out.close()\r\n\r\nimport matplotlib.pyplot as plt \r\n\r\n\r\n#スペクトログラムをプロットする\r\nfig=plt.figure(figsize=(10,4))\r\n\r\n#スペクトログラムを表示する\r\nspectrum,  freqs, t, im=plt.specgram(processed_data_post,NFFT=512,noverlap=512/16*15,Fs=wav.getframerate(),cmap=\"gray\")\r\n\r\n#カラーバーを表示する\r\nfig.colorbar(im).set_label('Intensity [dB]')\r\n\r\n#x軸のラベル\r\nplt.xlabel(\"Time [sec]\")\r\n\r\n#y軸のラベル\r\nplt.ylabel(\"Frequency [Hz]\")\r\n\r\n#音声ファイルを画像として保存\r\nplt.savefig(\"./spectrogram_wf_result.png\")\r\n\r\n#画像を画面に表示\r\nplt.show()\r\n\r\n\r\n#雑音込みの入力信号も時間領域の波形に戻す\r\nt,data_post=sp.istft(stft_data,fs=wav.getframerate(),window=\"hann\",nperseg=512,noverlap=256)\r\n\r\n#2バイトのデータに変換\r\ndata_post=data_post.astype(np.int16)\r\n\r\n#スペクトログラムをプロットする\r\nfig=plt.figure(figsize=(10,4))\r\n\r\n#スペクトログラムを表示する\r\nspectrum,  freqs, t, im=plt.specgram(data_post,NFFT=512,noverlap=512/16*15,Fs=wav.getframerate(),cmap=\"gray\")\r\n\r\n#カラーバーを表示する\r\nfig.colorbar(im).set_label('Intensity [dB]')\r\n\r\n#x軸のラベル\r\nplt.xlabel(\"Time [sec]\")\r\n\r\n#y軸のラベル\r\nplt.ylabel(\"Frequency [Hz]\")\r\n\r\n#音声ファイルを画像として保存\r\nplt.savefig(\"./spectrogram_noisy.png\")\r\n\r\n#画像を画面に表示\r\nplt.show()\r\n\r\n#waveファイルに書き込む\r\nwave_out = wave.open(\"./input_wave.wav\", 'w')\r\n\r\n#モノラル:1、ステレオ:2\r\nwave_out.setnchannels(1)\r\n\r\n#サンプルサイズ2byte\r\nwave_out.setsampwidth(2)\r\n\r\n#サンプリング周波数\r\nwave_out.setframerate(wav.getframerate())\r\n\r\n#データを書き込み\r\nwave_out.writeframes(data_post)\r\n\r\n#ファイルを閉じる\r\nwave_out.close()\r\n\r\n#waveファイルを閉じる\r\nwav.close()\r\n\r\n\r\n\r\n"
  },
  {
    "path": "section2/sample_code_c2_2.py",
    "content": "\r\n#wave形式の音声波形を読み込むためのモジュール(wave)をインポート\r\nimport wave as wave\r\n\r\n#numpyをインポート（波形データを2byteの数値列に変換するために使用）\r\nimport numpy as np\r\n\r\n#可視化のためにmatplotlibモジュールをインポート\r\nimport matplotlib.pyplot as plt\r\n\r\n#読み込むサンプルファイル\r\nsample_wave_file=\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\"\r\n\r\n#ファイルを読み込む\r\nwav=wave.open(sample_wave_file)\r\n\r\n#PCM形式の波形データを読み込み\r\ndata=wav.readframes(wav.getnframes())\r\n\r\n#dataを2バイトの数値列に変換\r\ndata=np.frombuffer(data, dtype=np.int16)\r\n\r\n#dataの値を2バイトの変数が取り得る値の最大値で正規化\r\ndata=data/np.iinfo(np.int16).max\r\n\r\n#waveファイルを閉じる\r\nwav.close()\r\n\r\n#x軸の値\r\nx=np.array(range(wav.getnframes()))/wav.getframerate()\r\n\r\n#音声データをプロットする\r\nplt.figure(figsize=(10,4))\r\n\r\n#x軸のラベル\r\nplt.xlabel(\"Time [sec]\")\r\n\r\n#y軸のラベル\r\nplt.ylabel(\"Value [-1,1]\")\r\n\r\n#データをプロット\r\nplt.plot(x,data)\r\n\r\n#音声ファイルを画像として保存\r\nplt.savefig(\"./wave_form.png\")\r\n\r\n#画像を画面に表示\r\nplt.show()"
  },
  {
    "path": "section2/sample_code_c2_3.py",
    "content": "\r\n\r\nimport wave as wave\r\nimport numpy as np\r\nimport matplotlib.pyplot as plt\r\n\r\n#白色雑音のサンプル数を設定\r\nn_sample=40000\r\n\r\n#サンプリング周波数\r\nsample_rate=16000\r\n\r\n#乱数の種を設定\r\nnp.random.seed(0)\r\n\r\n#白色雑音を生成\r\ndata=np.random.normal(size=n_sample)\r\n\r\n#x軸の値\r\nx=np.array(range(n_sample))/sample_rate\r\n\r\n#音声データをプロットする\r\nplt.figure(figsize=(10,4))\r\n\r\n#x軸のラベル\r\nplt.xlabel(\"Time [sec]\")\r\n\r\n#y軸のラベル\r\nplt.ylabel(\"Value\")\r\n\r\n#データをプロット\r\nplt.plot(x,data)\r\n\r\n#音声ファイルを画像として保存\r\nplt.savefig(\"./wgn_wave_form.png\")\r\n\r\n#画像を画面に表示\r\nplt.show()\r\n"
  },
  {
    "path": "section2/sample_code_c2_4.py",
    "content": "\r\n\r\nimport wave as wave\r\nimport numpy as np\r\nimport matplotlib.pyplot as plt\r\n\r\n#白色雑音のサンプル数を設定\r\nn_sample=40000\r\n\r\n#サンプリング周波数\r\nsample_rate=16000\r\n\r\n#乱数の種を設定\r\nnp.random.seed(0)\r\n\r\n#白色雑音を生成\r\ndata=np.random.normal(scale=0.1,size=n_sample)\r\n\r\n#2バイトのデータとして書き込むためにスケールを調整 \r\ndata_scale_adjust=data*np.iinfo(np.int16).max\r\n\r\n#2バイトのデータに変換\r\ndata_scale_adjust=data_scale_adjust.astype(np.int16)\r\n\r\n\r\n#waveファイルに書き込む\r\nwave_out = wave.open(\"./wgn_wave.wav\", 'w')\r\n\r\n#モノラル:1、ステレオ:2\r\nwave_out.setnchannels(1)\r\n\r\n#サンプルサイズ2byte\r\nwave_out.setsampwidth(2)\r\n\r\n#サンプリング周波数\r\nwave_out.setframerate(sample_rate)\r\n\r\n#データを書き込み\r\nwave_out.writeframes(data_scale_adjust)\r\n\r\n#ファイルを閉じる\r\nwave_out.close()\r\n\r\n"
  },
  {
    "path": "section2/sample_code_c2_5.py",
    "content": "\r\n#wave形式の音声波形を読み込むためのモジュール(wave)をインポート\r\nimport wave as wave\r\n\r\n#numpyをインポート（波形データを2byteの数値列に変換するために使用）\r\nimport numpy as np\r\n\r\n#可視化のためにmatplotlibモジュールをインポート\r\nimport matplotlib.pyplot as plt\r\n\r\n#sounddeviceモジュールをインポート\r\nimport sounddevice as sd\r\n\r\n#読み込むサンプルファイル\r\nsample_wave_file=\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\"\r\n\r\n#ファイルを読み込む\r\nwav=wave.open(sample_wave_file)\r\n\r\n#PCM形式の波形データを読み込み\r\ndata=wav.readframes(wav.getnframes())\r\n\r\n#dataを2バイトの数値列に変換\r\ndata=np.frombuffer(data, dtype=np.int16)\r\n\r\n#dataを再生する\r\nsd.play(data,wav.getframerate())\r\n\r\nprint(\"再生開始\")\r\n\r\n#再生が終わるまで待つ\r\nstatus = sd.wait()"
  },
  {
    "path": "section2/sample_code_c2_6.py",
    "content": "\r\n#wave形式の音声波形を読み込むためのモジュール(wave)をインポート\r\nimport wave as wave\r\n\r\n#numpyをインポート（波形データを2byteの数値列に変換するために使用）\r\nimport numpy as np\r\n\r\n#可視化のためにmatplotlibモジュールをインポート\r\nimport matplotlib.pyplot as plt\r\n\r\n#sounddeviceモジュールをインポート\r\nimport sounddevice as sd\r\n\r\n#録音する音声データの長さ (秒)\r\nwave_length=5\r\n\r\n#サンプリング周波数\r\nsample_rate=16000\r\n\r\nprint(\"録音開始\")\r\n\r\n#録音開始\r\ndata = sd.rec(int(wave_length*sample_rate),sample_rate, channels=1)\r\n\r\n#録音が終了するまで待つ\r\nsd.wait() \r\n\r\n#2バイトのデータとして書き込むためにスケールを調整 \r\ndata_scale_adjust=data*np.iinfo(np.int16).max\r\n\r\n#2バイトのデータに変換\r\ndata_scale_adjust=data_scale_adjust.astype(np.int16)\r\n\r\n#waveファイルに書き込む\r\nwave_out = wave.open(\"./record_wave.wav\", 'w')\r\n\r\n#モノラル:1、ステレオ:2\r\nwave_out.setnchannels(1)\r\n\r\n#サンプルサイズ2byte\r\nwave_out.setsampwidth(2)\r\n\r\n#サンプリング周波数\r\nwave_out.setframerate(sample_rate)\r\n\r\n#データを書き込み\r\nwave_out.writeframes(data_scale_adjust)\r\n\r\n#ファイルを閉じる\r\nwave_out.close()\r\n"
  },
  {
    "path": "section2/sample_code_c2_7.py",
    "content": "\r\n#numpyをインポート\r\nimport numpy as np\r\n\r\n#複素数データを定義する\r\nz=1.0+2.0j\r\nu=2.0+3.0j\r\n\r\n#複素数を表示する\r\nprint(\"z=\",z)\r\n\r\nprint(\"u=\",u)\r\n\r\n#実部だけを表示する\r\nprint(\"Real(z)=\",np.real(z))\r\n\r\n#虚部だけを表示する\r\nprint(\"Imaginary(z)=\",np.imag(z))\r\n\r\n#複素共役を表示する\r\nprint(\"z^*=\",np.conjugate(z))\r\n\r\n#絶対値を表示する\r\nprint(\"|z|=\",np.abs(z))\r\n\r\n#zとuを足す\r\nv=z+u\r\nprint(\"z+u=\",v)\r\n\r\n#zからuを引く\r\nv=z-u\r\nprint(\"z-u=\",v)\r\n\r\n#zとuをかける\r\nv=z*u\r\nprint(\"z*u=\",v)\r\n\r\n#zをuで割る\r\nv=z/u\r\nprint(\"z/u=\",v)\r\n"
  },
  {
    "path": "section2/sample_code_c2_8.py",
    "content": "\r\n#wave形式の音声波形を読み込むためのモジュール(wave)をインポート\r\nimport wave as wave\r\n\r\n#numpyをインポート（波形データを2byteの数値列に変換するために使用）\r\nimport numpy as np\r\n\r\n#scipyのsignalモジュールをインポート（stft等信号処理計算用)\r\nimport scipy.signal as sp\r\n\r\n#読み込むサンプルファイル\r\nsample_wave_file=\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\"\r\n\r\n#ファイルを読み込む\r\nwav=wave.open(sample_wave_file)\r\n\r\n#PCM形式の波形データを読み込み\r\ndata=wav.readframes(wav.getnframes())\r\n\r\n#dataを2バイトの数値列に変換\r\ndata=np.frombuffer(data, dtype=np.int16)\r\n\r\n#短時間フーリエ変換を行う\r\nf,t,stft_data=sp.stft(data,fs=wav.getframerate(),window=\"hann\",nperseg=512,noverlap=256)\r\n\r\n#短時間フーリエ変換後のデータ形式を確認\r\nprint(\"短時間フーリエ変換後のshape: \",np.shape(stft_data))\r\n\r\n#周波数軸の情報\r\nprint(\"周波数軸 [Hz]: \",f)\r\n\r\n#時間軸の情報\r\nprint(\"時間軸[sec]: \",t)\r\n\r\n#waveファイルを閉じる\r\nwav.close()\r\n"
  },
  {
    "path": "section2/sample_code_c2_9.py",
    "content": "\r\n#wave形式の音声波形を読み込むためのモジュール(wave)をインポート\r\nimport wave as wave\r\n\r\n#numpyをインポート（波形データを2byteの数値列に変換するために使用）\r\nimport numpy as np\r\n\r\n#表示用\r\nimport matplotlib.pyplot as plt\r\n\r\n#読み込むサンプルファイル\r\nsample_wave_file=\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\"\r\n\r\n#ファイルを読み込む\r\nwav=wave.open(sample_wave_file)\r\n\r\n#PCM形式の波形データを読み込み\r\ndata=wav.readframes(wav.getnframes())\r\n\r\n#dataを2バイトの数値列に変換\r\ndata=np.frombuffer(data, dtype=np.int16)\r\n\r\n#スペクトログラムをプロットする\r\nfig=plt.figure(figsize=(10,4))\r\n\r\n#スペクトログラムを表示する\r\nspectrum,  freqs, t, im=plt.specgram(data,NFFT=512,noverlap=512/16*15,Fs=wav.getframerate(),cmap=\"gray\")\r\n\r\n#カラーバーを表示する\r\nfig.colorbar(im).set_label('Intensity [dB]')\r\n\r\n#x軸のラベル\r\nplt.xlabel(\"Time [sec]\")\r\n\r\n#y軸のラベル\r\nplt.ylabel(\"Frequency [Hz]\")\r\n\r\n#音声ファイルを画像として保存\r\nplt.savefig(\"./spectrogram.png\")\r\n\r\n#画像を画面に表示\r\nplt.show()\r\n\r\n#waveファイルを閉じる\r\nwav.close()"
  },
  {
    "path": "section2.md",
    "content": "\n## 第2章のサンプルコード\n\n* [音声ファイルを開く](section2/sample_code_c2_1.py)\n* [音声ファイルをグラフ化する](section2/sample_code_c2_2.py)\n* [白色雑音をグラフ化する](section2/sample_code_c2_3.py)\n* [ファイルに音声データを書き込む](section2/sample_code_c2_4.py)\n* [音声ファイルを再生する](section2/sample_code_c2_5.py)\n* [音声データを録音する](section2/sample_code_c2_6.py)\n* [NumPyを用いた複素数の四則演算](section2/sample_code_c2_7.py)\n* [stftによる短時間フーリエ変換](section2/sample_code_c2_8.py)\n* [短時間フーリエ変換で変換した信号のスペクトログラム表示](section2/sample_code_c2_9.py)\n* [短時間逆フーリエ変換により時間周波数領域の信号を時間領域の信号に戻す](section2/sample_code_c2_10.py)\n* [特定の周波数を消した音を再生する(高域成分を除去)](section2/sample_code_c2_11.py)\n* [特定の周波数を消した音を再生する(低域成分を除去)](section2/sample_code_c2_12.py)\n* [スペクトルサブトラクションによる雑音抑圧](section2/sample_code_c2_13.py)\n* [ウィナーフィルタによる雑音抑圧](section2/sample_code_c2_14.py)\n\n"
  },
  {
    "path": "section3/sample_code_c3_1.py",
    "content": "\r\n\n#numpyをインポート（行列を扱う各種関数を含む）\nimport numpy as np\n\n#行列を定義\nA=np.matrix([[3.,1.,2.],[2.,3.,1.]])\n\n#行列の大きさを表示\nprint(\"行列Aの大きさ(M行, N列): \", np.shape(A))\n\n#行列を表示\nprint(\"A= \\n\",A)\n\n#行列Aにスカラーcをかける\nc=2.\nprint(\"cA= \\n\",c*A)\n\n#行列Aに行列Bを足す\nB=np.matrix([[-1.,2.,4.],[1.,8.,6.]])\nprint(\"A+B= \\n\",A+B)\n\n#行列Aに行列Bをかける\nB=np.matrix([[4.,2.],[-1.,3.],[1.,5.]])\nprint(\"AB= \\n\",np.matmul(A,B))\nprint(\"AB= \\n\",np.einsum(\"mk,kn->mn\",A,B))\n\n\n#行列Aと行列Bのアダマール積\nB=np.matrix([[-1.,2.,4.],[1.,8.,6.]])\nprint(\"A*B= \\n\",np.multiply(A,B))\n\n#行列Aの転置\nprint(\"A^T= \\n\",A.T)\nprint(\"A^T= \\n\",np.transpose(A,axes=(1,0)))\nprint(\"A^T= \\n\",np.swapaxes(A,1,0))\n\n#複素行列のエルミート転置\nA=np.matrix([[3.,1.+2.j,2.+3.j],[2.,3.-4.j,1.+3.j]])\nprint(\"A^H= \\n\",A.H)\nprint(\"A^H= \\n\",np.swapaxes(np.conjugate(A),1,0))\n\n#行列の積に対するエルミート転置\nA=np.matrix([[3.,1.+2.j,2.+3.j],[2.,3.-4.j,1.+3.j]])\nB=np.matrix([[4.+4.j,2.-3.j],[-1.+1.j,3.-2.j],[1.+3.j,5.+5.j]])\nprint(\"(AB)^H= \\n\",(np.matmul(A,B)).H)\nprint(\"B^H A^H= \\n\",np.matmul(B.H,A.H))\n\n#単位行列の定義\nI=np.eye(N=3)\nprint(\"I = \\n\",I)\n"
  },
  {
    "path": "section3/sample_code_c3_2.py",
    "content": "\r\n\r\n#numpyをインポート（行列を扱う各種関数を含む）\r\nimport numpy as np\r\n\r\n#乱数の種を設定\r\nnp.random.seed(0)\r\n\r\n#テンソルの大きさを設定\r\nL=10\r\nK=5\r\nM=3\r\nR=3\r\nN=3\r\n#ランダムな複素数のテンソル(ndarray)を定義する\r\nA=np.random.uniform(size=L*K*M*R)+np.random.uniform(size=L*K*M*R)*1.j\r\nA=np.reshape(A,(L,K,M,R))\r\n\r\nB=np.random.uniform(size=K*R*N)+np.random.uniform(size=K*R*N)*1.j\r\nB=np.reshape(B,(K,R,N))\r\n\r\n#einsumを使って行列積を計算する\r\nC=np.einsum(\"lkmr,krn->lkmn\",A,B)\r\n\r\n#行列Cの大きさを表示\r\nprint(\"shape(C): \",np.shape(C))\r\n\r\n#l=0,k=0の要素について検算実施\r\nprint(\"A(0,0)B(0,0)=\\n\",np.matmul(A[0,0,...],B[0,...]))\r\nprint(\"C(0,0)=\\n\",C[0,0,...])\r\n\r\n\r\n#einsumを使って行列積をl,k毎に計算した後、かつl方向に和を取る\r\nC=np.einsum(\"lkmr,krn->kmn\",A,B)\r\n\r\n#行列Cの大きさを表示\r\nprint(\"shape(C): \",np.shape(C))\r\n\r\n#k=0の要素について検算実施\r\nfor l in range(L):\r\n    if l==0:\r\n        C_2=np.matmul(A[l,0,...],B[0,...])\r\n    else:\r\n        C_2=C_2+np.matmul(A[l,0,...],B[0,...])\r\n        \r\nprint(\"C_2(0)=\\n\",C_2)\r\nprint(\"C(0)=\\n\",C[0,...])\r\n\r\n#einsumを使ってアダマール積を計算する\r\nC=np.einsum(\"lkmn,kmn->lkmn\",A,B)\r\n\r\n#行列Cの大きさを表示\r\nprint(\"shape(C): \",np.shape(C))\r\n\r\n#l=0,k=0の要素について検算実施\r\nprint(\"A(0,0)B(0,0)=\\n\",np.multiply(A[0,0,...],B[0,...]))\r\nprint(\"C(0,0)=\\n\",C[0,0,...])\r\n\r\n\r\n"
  },
  {
    "path": "section3/sample_code_c3_3.py",
    "content": "\r\n\n#numpyをインポート（行列を扱う各種関数を含む）\nimport numpy as np\n\r\n#乱数の種を設定\r\nnp.random.seed(0)\r\n\n#テンソルの大きさを設定\r\nL=10\r\nK=5\r\nM=3\r\nR=3\r\nS=3\r\nN=3\r\n#ランダムな複素数のテンソル(ndarray)を定義する\r\nA=np.random.uniform(size=L*K*M*R)+np.random.uniform(size=L*K*M*R)*1.j\r\nA=np.reshape(A,(L,K,M,R))\r\n\r\nB=np.random.uniform(size=K*R*S)+np.random.uniform(size=K*R*S)*1.j\r\nB=np.reshape(B,(K,R,S))\r\n\r\n\r\nC=np.random.uniform(size=L*S*N)+np.random.uniform(size=L*S*N)*1.j\r\nC=np.reshape(C,(L,S,N))\r\n\r\n#einsumを使って行列積を計算する\r\nD=np.einsum(\"lkmr,krs,lsn->kmn\",A,B,C)\r\n\r\nprint(np.shape(D))\r\n\r\n#k=0の要素について検算実施\r\nfor l in range(L):\r\n    if l==0:\r\n        D_2=np.matmul(np.matmul(A[l,0,...],B[0,...]),C[l])\r\n    else:\r\n        D_2=D_2+np.matmul(np.matmul(A[l,0,...],B[0,...]),C[l])\r\n        \r\nprint(\"D_2(0)=\\n\",D_2)\r\nprint(\"D(0)=\\n\",D[0,...])"
  },
  {
    "path": "section3/sample_code_c3_4.py",
    "content": "\r\n#numpyをインポート（行列を扱う各種関数を含む）\r\nimport numpy as np\r\n\r\n#乱数の種を設定\r\nnp.random.seed(0)\r\n\r\n#行列の大きさを設定する\r\nL=10\r\nM=3\r\nN=3\r\n#ランダムな複素数のテンソル(ndarray)を定義する\r\nA=np.random.uniform(size=L*M*N)+np.random.uniform(size=L*M*N)*1.j\r\nA=np.reshape(A,(L,M,N))\r\n\r\n#行列式を計算する\r\ndetA=np.linalg.det(A)\r\n\r\nprint(\"detA(0): \",detA[0])\r\n\r\n#全ての要素を3倍した行列の行列式を計算する\r\ndet3A=np.linalg.det(3*A)\r\n\r\nprint(\"det3A(0): \",det3A[0])\r\n\r\n\r\n#逆行列を計算する\r\nA_inv=np.linalg.inv(A)\r\n\r\n#Aとかけて単位行列になっているかどうかを検算\r\nAA_inv=np.einsum(\"lmk,lkn->lmn\",A,A_inv)\r\nprint(\"単位行列?: \\n\",AA_inv[0])\r\n\r\nA_invA=np.einsum(\"lmk,lkn->lmn\",A_inv,A)\r\nprint(\"単位行列?: \\n\",A_invA[0])\r\n\r\n#一般化逆行列計算\r\nA_inv=np.linalg.pinv(A)\r\n\r\n#Aとかけて単位行列になっているかどうかを検算\r\nAA_inv=np.einsum(\"lmk,lkn->lmn\",A,A_inv)\r\nprint(\"単位行列?: \\n\",AA_inv[0])\r\n\r\nA_invA=np.einsum(\"lmk,lkn->lmn\",A_inv,A)\r\nprint(\"単位行列?: \\n\",A_invA[0])"
  },
  {
    "path": "section3/sample_code_c3_5.py",
    "content": "\r\n#numpyをインポート（行列を扱う各種関数を含む）\r\nimport numpy as np\r\n\r\n#行列を定義\r\nA=np.matrix([[3.,1.,2.],[2.,3.,1.]])\r\n\r\n#ベクトルを定義\r\nb=np.array([2.,1.,4.])\r\n\r\n#行列を表示\r\nprint(\"A= \\n\",A)\r\n\r\n#ベクトルを表示\r\nprint(\"b= \\n\",b)\r\n\r\n#行列Aにベクトルbをかける\r\nprint(\"Ab= \\n\",np.dot(A,b))\r\n\r\n"
  },
  {
    "path": "section3/sample_code_c3_6.py",
    "content": "\r\n#numpyをインポート（行列を扱う各種関数を含む）\r\nimport numpy as np\r\n\r\n#行列を定義\r\na=np.matrix([3.+2.j,1.-1.j,2.+2.j])\r\n\r\n#ベクトルを定義\r\nb=np.array([2.+5.j,1.-1.j,4.+1.j])\r\n\r\n#ベクトルの内積計算\r\nprint(\"a^Hb=\",np.inner(np.conjugate(a),b))\r\n\r\n#ベクトルの内積計算\r\nprint(\"a^Ha=\",np.inner(np.conjugate(a),a))\r\n\r\n\r\n"
  },
  {
    "path": "section3/sample_code_c3_7.py",
    "content": "\r\n#numpyをインポート（行列を扱う各種関数を含む）\r\nimport numpy as np\r\n\r\n#乱数の種を設定\r\nnp.random.seed(0)\r\n\r\n#行列の大きさを設定する\r\nL=10\r\nM=3\r\nN=3\r\n#ランダムな複素数のテンソル(ndarray)を定義する\r\nA=np.random.uniform(size=L*M*N)+np.random.uniform(size=L*M*N)*1.j\r\nA=np.reshape(A,(L,M,N))\r\n\r\n#ランダムな複素数のテンソル(ndarray)を定義する\r\nb=np.random.uniform(size=L*M)+np.random.uniform(size=L*M)*1.j\r\nb=np.reshape(b,(L,M))\r\n\r\n#行列Aのtrace\r\nprint(\"tr(A)= \\n\",np.trace(A,axis1=-2,axis2=-1))\r\n\r\n#einsumを用いたtrace計算\r\nprint(\"tr(A)= \\n\",np.einsum(\"lmm->l\",A))\r\n\r\n#b^H,A,bの計算\r\nprint(\"b^H A b=\\n\",np.einsum(\"lm,lmn,ln->l\",np.conjugate(b),A,b))\r\n#b^H,A,bの計算\r\nprint(\"trA bb^H =\\n\",np.trace(np.einsum(\"lmn,ln,lk->lmk\",A,b,np.conjugate(b)),axis1=-2,axis2=-1))\r\n\r\n"
  },
  {
    "path": "section3/sample_code_c3_8.py",
    "content": "\r\n#numpyをインポート（行列を扱う各種関数を含む）\r\nimport numpy as np\r\n\r\n#乱数の種を設定\r\nnp.random.seed(0)\r\n\r\n#行列の大きさを設定する\r\nL=10\r\nM=3\r\nN=3\r\n#ランダムな複素数のテンソル(ndarray)を定義する\r\nA=np.random.uniform(size=L*M*N)+np.random.uniform(size=L*M*N)*1.j\r\nA=np.reshape(A,(L,M,N))\r\n\r\n#正定エルミート行列を作る\r\nB=np.einsum(\"lmk,lnk->lmn\",A,np.conjugate(A))\r\n\r\n#Aの固有値分解実施\r\nw,v=np.linalg.eig(A)\r\n\r\n#固有値と固有ベクトルからAを復元できるか検証\r\nA_reconst=np.einsum(\"lmk,lk,lkn->lmn\",v,w,np.linalg.inv(v))\r\nprint(\"A[0]: \\n\",A[0])\r\nprint(\"A_reconst[0]: \\n\",A_reconst[0])\r\n\r\n#Bの固有値分解実施\r\nw,v=np.linalg.eigh(B)\r\n\r\n#固有値と固有ベクトルからBを復元できるか検証\r\nB_reconst=np.einsum(\"lmk,lk,lnk->lmn\",v,w,np.conjugate(v))\r\nprint(\"B[0]: \\n\",B[0])\r\nprint(\"B[0]: \\n\",B_reconst[0])"
  },
  {
    "path": "section3/sample_code_c3_9.py",
    "content": "\r\n#numpyをインポート（行列を扱う各種関数を含む）\r\nimport numpy as np\r\n\r\n#A: ...mn\r\n#B: ...ij\r\n#AとBの最後の二軸以外の次元は一致していることを前提とする\r\ndef batch_kron(A,B):\r\n if np.shape(A)[:-2]!=np.shape(B)[:-2]:\r\n     print(\"error\")\r\n     return None\r\n else:\r\n    return(np.reshape(np.einsum(\"...mn,...ij->...minj\",A,B),np.shape(A)[:-2]+(np.shape(A)[-2]*np.shape(B)[-2],np.shape(A)[-1]*np.shape(B)[-1])))\r\n\r\n\r\n#乱数の種を設定\r\nnp.random.seed(0)\r\n\r\n\r\n\r\n#行列の大きさを設定する\r\nL=10\r\nM=3\r\nR=3\r\nN=3\r\nT=3\r\n#ランダムな複素数のテンソル(ndarray)を定義する\r\nA=np.random.uniform(size=L*M*R)+np.random.uniform(size=L*M*R)*1.j\r\nA=np.reshape(A,(L,M,R))\r\n\r\nX=np.random.uniform(size=R*N)+np.random.uniform(size=R*N)*1.j\r\nX=np.reshape(X,(R,N))\r\n\r\nB=np.random.uniform(size=L*N*T)+np.random.uniform(size=L*N*T)*1.j\r\nB=np.reshape(B,(L,N,T))\r\n\r\n\r\nD=np.random.uniform(size=L*M*T)+np.random.uniform(size=L*M*T)*1.j\r\nD=np.reshape(D,(L,M,T))\r\n\r\n\r\n#1. 多次元配列対応版のクロネッカー積batch_kronの出力結果とnumpyのkronの出力結果が一致していることを確認\r\n\r\n#多次元配列対応版のクロネッカー積\r\nC=batch_kron(np.transpose(B,(0,2,1)),A)\r\n\r\n#numpyのkronでl=0のデータに対してクロネッカー積を計算\r\nC_2=np.kron(np.transpose(B[0,...],(1,0)),A[0,...])\r\n\r\n#多次元配列対応版のクロネッカー積とnumpyのkronとの誤差\r\nprint(\"誤差 = \",np.sum(np.abs(C[0,...]-C_2)))\r\n\r\n#2. vecAXBとCvecXが一致しているかどうかを確認する\r\n\r\n#Xをベクトル化する\r\nvecX=np.reshape(np.transpose(X,[1,0]),(N*R))\r\n\r\n#AXBを計算する\r\nAXB=np.einsum(\"lmr,rn,lnt->lmt\",A,X,B)\r\n\r\n#AXBをベクトル化する\r\nvecAXB=np.reshape(np.transpose(AXB,[0,2,1]),(L,T*M))\r\n\r\n#CvecX\r\nCvecX=np.einsum(\"lmr,r->lm\",C,vecX)\r\n\r\n#vecAXBとCvecXが一致しているかどうかを確認する\r\nprint(\"誤差 = \",np.sum(np.abs(vecAXB-CvecX)))\r\n\r\n#3. ΣAXB=ΣDを満たすようなXを求める\r\n\r\n#vecDを求める\r\nvecD=np.reshape(np.transpose(D,[0,2,1]),(L,T*M))\r\n\r\n#vecXを求める\r\nvecX=np.einsum(\"mr,r->m\",np.linalg.inv(np.sum(C,axis=0)), np.sum(vecD,axis=0))\r\n\r\n#Xに戻す\r\nX=np.transpose(np.reshape(vecX,(N,R)),(1,0))\r\n\r\n#答えがあっているかどうかを確認\r\nsum_AXB=np.einsum(\"lmr,rn,lnt->mt\",A,X,B)\r\n\r\nsum_D=np.sum(D,axis=0)\r\n\r\n#sum_AXBとsum_Dが一致しているかどうかを確認する\r\nprint(\"誤差 = \",np.sum(np.abs(sum_AXB-sum_D)))\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "section3.md",
    "content": "\n## 第3章のサンプルコード\n\n* [行列の基本的な演算](section3/sample_code_c3_1.py)\n* [アインシュタイン縮約記法を用いたテンソル計算](section3/sample_code_c3_2.py)\n* [アインシュタイン縮約記法を用いたテンソル計算(3つのテンソル)](section3/sample_code_c3_3.py)\n* [逆行列演算](section3/sample_code_c3_4.py)\n* [行列とベクトルの掛け算](section3/sample_code_c3_5.py)\n* [ベクトルの内積計算](section3/sample_code_c3_6.py)\n* [行列のトレース計算](section3/sample_code_c3_7.py)\n* [固有値計算](section3/sample_code_c3_8.py)\n* [クロネッカー積を用いた計算例](section3/sample_code_c3_9.py)\n\n"
  },
  {
    "path": "section4/sample_code_c4_1.py",
    "content": "\r\n#numpyをインポート（行列を扱う各種関数を含む）\r\nimport numpy as np\r\n\r\n#可視化のためにmatplotlibモジュールをインポート\r\nimport matplotlib.pyplot as plt\r\n\r\n#アニメーション用のモジュールをインポート\r\nimport matplotlib.animation as animation\r\n\r\n#確率密度関数の描画用\r\nfrom scipy.stats import norm\r\n\r\n\r\n\r\n#混合ガウス分布に基づく乱数を生成する\r\nnp.random.seed(0)\r\n\r\n#各ガウス分布のサンプル数\r\nn_samples=[200,400,400]\r\n\r\n#各ガウス分布の平均\r\nmeans=[-2,3,5]\r\n\r\n#各ガウス分布の分散\r\nsigmas=[3,2,0.5]\r\n\r\n#GMMに従う乱数を生成\r\nx=None\r\nfor n,mean,sigma in zip(n_samples,means,sigmas):\r\n    samples_for_each_dist=np.random.normal(mean,sigma, int(n))\r\n    if x is None:\r\n        x=samples_for_each_dist\r\n    else:\r\n        x=np.concatenate((x,samples_for_each_dist))\r\n\r\n#モデルパラメータを初期化する\r\nalpha=np.array([1./3.,1./3.,1./3.])\r\nvar=np.array([1.,1.,1.])\r\nmu=np.array([-1,0,1])\r\n\r\n#GMMを構成するガウス分布の数\r\nn_clusters=len(alpha)\r\n\r\n#繰り返し計算でパラメータを最適化する(ここでは100回繰り返す）\r\nn_iterations=101\r\nlog_likelihood=np.zeros(n_iterations)\r\nims=[]\r\nfor t in range(n_iterations):\r\n    print(\"t{}\".format(t))\r\n    if t==0:\r\n        alpha_buf=alpha[None,:]\r\n        var_buf=var[None,:]\r\n        mu_buf=mu[None,:]\r\n    else:\r\n        alpha_buf=np.concatenate((alpha_buf,alpha[None,:]),axis=0)\r\n        var_buf=np.concatenate((var_buf,var[None,:]),axis=0)\r\n        mu_buf=np.concatenate((mu_buf,mu[None,:]),axis=0)\r\n    #Eステップ\r\n    \r\n    #係数部\r\n    coef=alpha/np.sqrt(2.*np.pi*var)\r\n    \r\n    #exponent: n_sample, n_clusters\r\n    exponent=-1.*np.power(x[:,None]-mu[None,:],2.)/(2*var[None,:])\r\n\r\n    #βを求める\r\n    beta=coef[None,:]*np.exp(exponent)\r\n    likelihood_each_sample=np.maximum(np.sum(beta,axis=1,keepdims=True),1.e-18)\r\n    beta=beta/likelihood_each_sample\r\n\r\n    #対数尤度を求める\r\n    current_log_likelihood=np.average(np.log(likelihood_each_sample))\r\n    log_likelihood[t]=current_log_likelihood\r\n\r\n    #Mステップ(パラメータを更新する)\r\n    N=np.maximum(np.sum(beta,axis=0),1.e-18)\r\n    \r\n    #事前確率を更新\r\n    alpha=N/np.sum(N)\r\n\r\n    #平均値を更新\r\n    mu=np.einsum(\"ij,i->j\",beta,x)/N\r\n    #分散を計算\r\n    var=np.einsum(\"ij,ij->j\",beta,np.power(x[:,None]-mu[None,:],2.))/N\r\n    var=np.maximum(var,1.e-18)\r\n\r\n#対数ゆう度をグラフ化する\r\nplt.figure(figsize=(10,4))\r\nplt.plot(np.arange(0,n_iterations,1),log_likelihood,color=\"black\",linewidth=1,label=\"log likelihood\")\r\nplt.xlabel(\"Number of iterations\")\r\nplt.legend()\r\nplt.savefig(\"./log_likelihood_gmm.png\")\r\nplt.show()\r\n\r\n\r\n#パラメータ更新の様子をアニメーションで表示\r\ndef animation_update(t):\r\n    plt.cla()\r\n    plt.hist(x,bins=50,normed=True,label=\"observed samples\")\r\n\r\n    xmin=-20\r\n    xmax=20\r\n    plt.xlim([xmin,xmax])\r\n    plt.ylim([0,0.40])\r\n    x_range=np.arange(-20,20,0.01)\r\n\r\n    \r\n    #GMMを描画する\r\n    pdf=None\r\n    for alpha,var, mu in zip(alpha_buf[t],var_buf[t],mu_buf[t]):\r\n        pdf_each=alpha*norm.pdf(x_range,mu,np.sqrt(var))\r\n        if pdf is None:\r\n            pdf=pdf_each\r\n        else:\r\n            pdf=pdf+pdf_each\r\n\r\n    plt.plot(x_range,pdf,color=\"black\",linewidth=1,label=r\"$p(x|\\theta^{(t=\"+str(t)+\")})$\")\r\n    plt.legend()\r\n\r\n    if t==0:\r\n        plt.savefig(\"./initialized_gmm.png\")\r\n    if t==n_iterations-1:\r\n        plt.savefig(\"./learned_gmm.png\")\r\n\r\n#音声データをプロットする\r\nfig=plt.figure(figsize=(10,4))\r\n\r\nani=animation.FuncAnimation(fig,animation_update,interval=200,frames=n_iterations)\r\nplt.show()\r\n"
  },
  {
    "path": "section4.md",
    "content": "\n## 第4章のサンプルコード\n\n* [（参考）EMアルゴリズムによる混合ガウス分布のパラメータ最適化](section4/sample_code_c4_1.py)\n"
  },
  {
    "path": "section5/sample_code_c5_1.py",
    "content": "\r\nimport wave as wave\r\nimport pyroomacoustics as pa\r\nimport numpy as np\r\nimport scipy.signal as signal\r\n\r\n#乱数の種を初期化\r\nnp.random.seed(0)\r\n\r\n#畳み込みに用いる音声波形\r\nclean_wave_file=\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\"\r\n\r\nwav=wave.open(clean_wave_file)\r\ndata=wav.readframes(wav.getnframes())\r\ndata=np.frombuffer(data, dtype=np.int16)\r\ndata=data/np.iinfo(np.int16).max\r\nwav.close()\r\n\r\n#サンプリング周波数\r\nsample_rate=16000\r\n\r\n#畳み込むインパルス応答長\r\nn_impulse_length=512\r\n\r\n#インパルス応答を乱数で生成（ダミー）\r\nimpulse_response=np.random.normal(size=n_impulse_length)\r\n\r\nconv_data=signal.convolve(data,impulse_response,mode='full')\r\n\r\n#ファイルに書き込む\r\ndata_scale_adjust=conv_data*np.iinfo(np.int16).max/20.\r\ndata_scale_adjust=data_scale_adjust.astype(np.int16)\r\nwave_out=wave.open(\"./conv_out.wav\",\"w\")\r\nwave_out.setnchannels(1)\r\nwave_out.setsampwidth(2)\r\nwave_out.setframerate(sample_rate)\r\nwave_out.writeframes(data_scale_adjust)\r\nwave_out.close()\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "section5/sample_code_c5_2.py",
    "content": "\r\nimport wave as wave\r\nimport pyroomacoustics as pa\r\nimport numpy as np\r\n\r\n#乱数の種を初期化\r\nnp.random.seed(0)\r\n\r\n#畳み込みに用いる音声波形\r\nclean_wave_files=[\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\",\"./CMU_ARCTIC/cmu_us_axb_arctic/wav/arctic_a0002.wav\"]\r\n\r\n#音源数\r\nn_sources=len(clean_wave_files)\r\n\r\n#長さを調べる\r\nn_samples=0\r\n#ファイルを読み込む\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    if n_samples<wav.getnframes():\r\n        n_samples=wav.getnframes()\r\n    wav.close()\r\n\r\nclean_data=np.zeros([n_sources,n_samples])\r\n\r\n#ファイルを読み込む\r\ns=0\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    data=wav.readframes(wav.getnframes())\r\n    data=np.frombuffer(data, dtype=np.int16)\r\n    data=data/np.iinfo(np.int16).max\r\n    clean_data[s,:wav.getnframes()]=data\r\n    wav.close()\r\n    s=s+1\r\n    \r\n# シミュレーションのパラメータ\r\n\r\n#サンプリング周波数\r\nsample_rate=16000\r\n\r\n#音声と雑音との比率 [dB]\r\nSNR=90.\r\n\r\n#部屋の大きさ\r\nroom_dim = np.r_[10.0, 10.0, 10.0]\r\n\r\n#マイクロホンアレイを置く部屋の場所\r\nmic_array_loc = room_dim / 2 + np.random.randn(3) * 0.1 \r\n\r\n#マイクロホンアレイのマイク配置\r\nmic_alignments = np.array(\r\n    [\r\n        [-0.01, 0.0, 0.0],\r\n        [0.01, 0.0, 0.0],\r\n    ]\r\n)\r\n\r\n#マイクロホン数\r\nn_channels=np.shape(mic_alignments)[0]\r\n\r\n#マイクロホンアレイの座標系\r\nR=mic_alignments .T+mic_array_loc[:,None]\r\n\r\n# 部屋を生成する\r\nroom = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\n\r\n# 用いるマイクロホンアレイの情報を設定する\r\nroom.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\n\r\n#音源の場所\r\ndoas=np.array(\r\n    [[np.pi/2., 0],\r\n     [np.pi/2.,np.pi/2.]\r\n    ]    )\r\n\r\n#音源とマイクロホンの距離\r\ndistance=1.\r\nsource_locations=np.zeros((3, doas.shape[0]), dtype=doas.dtype)\r\nsource_locations[0, :] = np.cos(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[1, :] = np.sin(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[2, :] = np.cos(doas[:, 0])\r\nsource_locations *= distance\r\nsource_locations += mic_array_loc[:, None]\r\n\r\n#各音源をシミュレーションに追加する\r\nfor s in range(n_sources):\r\n    clean_data[s]/= np.std(clean_data[s])\r\n    room.add_source(source_locations[:, s], signal=clean_data[s])\r\n\r\n#シミュレーションを回す\r\nroom.simulate(snr=SNR)\r\n\r\n#畳み込んだ波形を取得する(チャンネル、サンプル）\r\nmulti_conv_data=room.mic_array.signals\r\n\r\n#ファイルに書き込む\r\nfor m in range(n_channels):\r\n    conv_data=multi_conv_data[m,:]\r\n    data_scale_adjust=conv_data*np.iinfo(np.int16).max/20.\r\n    data_scale_adjust=data_scale_adjust.astype(np.int16)\r\n    wave_out=wave.open(\"./conv_out_{}.wav\".format(m),\"w\")\r\n    wave_out.setnchannels(1)\r\n    wave_out.setsampwidth(2)\r\n    wave_out.setframerate(sample_rate)\r\n    wave_out.writeframes(data_scale_adjust)\r\n    wave_out.close()\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "section5/sample_code_c5_3.py",
    "content": "\r\nimport wave as wave\r\nimport pyroomacoustics as pa\r\nimport numpy as np\r\n\r\n#乱数の種を初期化\r\nnp.random.seed(0)\r\n\r\n#畳み込みに用いる音声波形\r\nclean_wave_files=[\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\",\"./CMU_ARCTIC/cmu_us_axb_arctic/wav/arctic_a0002.wav\"]\r\n\r\n#音源数\r\nn_sources=len(clean_wave_files)\r\n\r\n#長さを調べる\r\nn_samples=0\r\n\r\n#ファイルを読み込む\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    if n_samples<wav.getnframes():\r\n        n_samples=wav.getnframes()\r\n    wav.close()\r\n\r\nclean_data=np.zeros([n_sources,n_samples])\r\n\r\n#ファイルを読み込む\r\ns=0\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    data=wav.readframes(wav.getnframes())\r\n    data=np.frombuffer(data, dtype=np.int16)\r\n    data=data/np.iinfo(np.int16).max\r\n    clean_data[s,:wav.getnframes()]=data\r\n    wav.close()\r\n    s=s+1\r\n\r\n# シミュレーションのパラメータ\r\n\r\n#サンプリング周波数\r\nsample_rate=16000\r\n\r\n#音声と雑音との比率 [dB]\r\nSNR=90.\r\n\r\n#部屋の大きさ\r\nroom_dim = np.r_[10.0, 10.0, 10.0]\r\n\r\n#マイクロホンアレイを置く部屋の場所\r\nmic_array_loc = room_dim / 2 + np.random.randn(3) * 0.1 \r\n\r\n#マイクロホンアレイのマイク配置\r\nmic_alignments = np.array(\r\n    [\r\n    \t[-0.01, 0.0, 0.0],\r\n\t\t[0.01, 0.0, 0.0],\r\n\t\t[0.03, 0.0, 0.0]\r\n    ]\r\n)\r\n\r\n#マイクロホン数\r\nn_channels=np.shape(mic_alignments)[0]\r\n\r\n#マイクロホンアレイの座標\r\nR=mic_alignments .T+mic_array_loc[:,None]\r\n\r\n# 部屋を生成する\r\nroom = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\n\r\n# 用いるマイクロホンアレイの情報を設定する\r\nroom.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\n\r\n#音源の場所\r\ndoas=np.array(\r\n    [[np.pi/2., 0],\r\n     [np.pi/2.,np.pi/2.]\r\n    ]    )\r\n\r\n#音源とマイクロホンの距離\r\ndistance=1.\r\nsource_locations=np.zeros((3, doas.shape[0]), dtype=doas.dtype)\r\nsource_locations[0, :] = np.cos(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[1, :] = np.sin(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[2, :] = np.cos(doas[:, 0])\r\nsource_locations *= distance\r\nsource_locations += mic_array_loc[:, None]\r\n\r\n#各音源をシミュレーションに追加する\r\nfor s in range(n_sources):\r\n    clean_data[s]/= np.std(clean_data[s])\r\n    room.add_source(source_locations[:, s], signal=clean_data[s])\r\n\r\n#シミュレーションを回す\r\nroom.simulate(snr=SNR)\r\n\r\n#畳み込んだ波形を取得する(チャンネル、サンプル）\r\nmulti_conv_data=room.mic_array.signals\r\n\r\n#ファイルに書き込む\r\nfor m in range(n_channels):\r\n    conv_data=multi_conv_data[m,:]\r\n    data_scale_adjust=conv_data*np.iinfo(np.int16).max/20.\r\n    data_scale_adjust=data_scale_adjust.astype(np.int16)\r\n    wave_out=wave.open(\"./conv_out_{}.wav\".format(m),\"w\")\r\n    wave_out.setnchannels(1)\r\n    wave_out.setsampwidth(2)\r\n    wave_out.setframerate(sample_rate)\r\n    wave_out.writeframes(data_scale_adjust)\r\n    wave_out.close()\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "section5/sample_code_c5_4.py",
    "content": "\r\nimport wave as wave\r\nimport pyroomacoustics as pa\r\nimport numpy as np\r\n\r\n#乱数の種を初期化\r\nnp.random.seed(0)\r\n\r\n#畳み込みに用いる音声波形\r\nclean_wave_files=[\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\",\"./CMU_ARCTIC/cmu_us_axb_arctic/wav/arctic_a0002.wav\"]\r\n\r\n#音源数\r\nn_sources=len(clean_wave_files)\r\n\r\n#長さを調べる\r\nn_samples=0\r\n\r\n#ファイルを読み込む\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    if n_samples<wav.getnframes():\r\n        n_samples=wav.getnframes()\r\n    wav.close()\r\n\r\nclean_data=np.zeros([n_sources,n_samples])\r\n\r\n#ファイルを読み込む\r\ns=0\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    data=wav.readframes(wav.getnframes())\r\n    data=np.frombuffer(data, dtype=np.int16)\r\n    data=data/np.iinfo(np.int16).max\r\n    clean_data[s,:wav.getnframes()]=data\r\n    wav.close()\r\n    s=s+1\r\n\r\n# シミュレーションのパラメータ\r\n\r\n#サンプリング周波数\r\nsample_rate=16000\r\n\r\n#音声と雑音との比率 [dB]\r\nSNR=90.\r\n\r\n#部屋の大きさ\r\nroom_dim = np.r_[10.0, 10.0, 10.0]\r\n\r\n#マイクロホンアレイを置く部屋の場所\r\nmic_array_loc = room_dim / 2 + np.random.randn(3) * 0.1 \r\n\r\n#マイクロホンアレイのマイク配置\r\nmic_alignments = np.array(\r\n    [\r\n        [-0.01, 0.0, 0.0],\r\n        [0.01, 0.0, 0.0],\r\n    ]\r\n)\r\n\r\n#マイクロホン数\r\nn_channels=np.shape(mic_alignments)[0]\r\n\r\n#マイクロホンアレイの座標\r\nR=mic_alignments .T+mic_array_loc[:,None]\r\n\r\n# 部屋を生成する\r\nroom = pa.ShoeBox(room_dim, fs=sample_rate, max_order=17,absorption=0.35)\r\n\r\n# 用いるマイクロホンアレイの情報を設定する\r\nroom.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\n\r\n#音源の場所\r\ndoas=np.array(\r\n    [[np.pi/2., 0],\r\n     [np.pi/2.,np.pi/2.]\r\n    ]    )\r\n\r\n#音源とマイクロホンの距離\r\ndistance=1.\r\nsource_locations=np.zeros((3, doas.shape[0]), dtype=doas.dtype)\r\nsource_locations[0, :] = np.cos(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[1, :] = np.sin(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[2, :] = np.cos(doas[:, 0])\r\nsource_locations *= distance\r\nsource_locations += mic_array_loc[:, None]\r\n\r\n#各音源をシミュレーションに追加する\r\nfor s in range(n_sources):\r\n    clean_data[s]/= np.std(clean_data[s])\r\n    room.add_source(source_locations[:, s], signal=clean_data[s])\r\n\r\n#シミュレーションを回す\r\nroom.simulate(snr=SNR)\r\n\r\n#畳み込んだ波形を取得する(チャンネル、サンプル）\r\nmulti_conv_data=room.mic_array.signals\r\n\r\n#ファイルに書き込む\r\nfor m in range(n_channels):\r\n    conv_data=multi_conv_data[m,:]\r\n    data_scale_adjust=conv_data*np.iinfo(np.int16).max/20.\r\n    data_scale_adjust=data_scale_adjust.astype(np.int16)\r\n    wave_out=wave.open(\"./reverb_conv_out_{}.wav\".format(m),\"w\")\r\n    wave_out.setnchannels(1)\r\n    wave_out.setsampwidth(2)\r\n    wave_out.setframerate(sample_rate)\r\n    wave_out.writeframes(data_scale_adjust)\r\n    wave_out.close()\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "section5/sample_code_c5_5.py",
    "content": "\r\nimport wave as wave\r\nimport pyroomacoustics as pa\r\nimport numpy as np\r\n\r\n#乱数の種を初期化\r\nnp.random.seed(0)\r\n\r\n#畳み込みに用いる音声波形\r\nclean_wave_files=[\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\",\"./CMU_ARCTIC/cmu_us_axb_arctic/wav/arctic_a0002.wav\"]\r\n\r\n#音源数\r\nn_sources=len(clean_wave_files)\r\n\r\n#長さを調べる\r\nn_samples=0\r\n\r\n#ファイルを読み込む\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    if n_samples<wav.getnframes():\r\n        n_samples=wav.getnframes()\r\n    wav.close()\r\n\r\nclean_data=np.zeros([n_sources,n_samples])\r\n\r\n#ファイルを読み込む\r\ns=0\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    data=wav.readframes(wav.getnframes())\r\n    data=np.frombuffer(data, dtype=np.int16)\r\n    data=data/np.iinfo(np.int16).max\r\n    clean_data[s,:wav.getnframes()]=data\r\n    wav.close()\r\n    s=s+1\r\n\r\n# シミュレーションのパラメータ\r\n\r\n#サンプリング周波数\r\nsample_rate=16000\r\n\r\n#音声と雑音との比率 [dB]\r\nSNR=10.\r\n\r\n#部屋の大きさ\r\nroom_dim = np.r_[10.0, 10.0, 10.0]\r\n\r\n#マイクロホンアレイを置く部屋の場所\r\nmic_array_loc = room_dim / 2 + np.random.randn(3) * 0.1 \r\n\r\n#マイクロホンアレイのマイク配置\r\nmic_alignments = np.array(\r\n    [\r\n        [-0.01, 0.0, 0.0],\r\n        [0.01, 0.0, 0.0],\r\n    ]\r\n)\r\n\r\n#マイクロホン数\r\nn_channels=np.shape(mic_alignments)[0]\r\n\r\n#マイクロホンアレイの座標\r\nR=mic_alignments .T+mic_array_loc[:,None]\r\n\r\n# 部屋を生成する\r\nroom = pa.ShoeBox(room_dim, fs=sample_rate, max_order=17,absorption=0.35)\r\n\r\n# 用いるマイクロホンアレイの情報を設定する\r\nroom.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\n\r\n#音源の場所\r\ndoas=np.array(\r\n    [[np.pi/2., 0],\r\n     [np.pi/2.,np.pi/2.]\r\n    ]    )\r\n\r\n#音源とマイクロホンの距離\r\ndistance=1.\r\nsource_locations=np.zeros((3, doas.shape[0]), dtype=doas.dtype)\r\nsource_locations[0, :] = np.cos(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[1, :] = np.sin(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[2, :] = np.cos(doas[:, 0])\r\nsource_locations *= distance\r\nsource_locations += mic_array_loc[:, None]\r\n\r\n#各音源をシミュレーションに追加する\r\nfor s in range(n_sources):\r\n    clean_data[s]/= np.std(clean_data[s])\r\n    room.add_source(source_locations[:, s], signal=clean_data[s])\r\n\r\n#シミュレーションを回す\r\nroom.simulate(snr=SNR)\r\n\r\n#畳み込んだ波形を取得する(チャンネル、サンプル）\r\nmulti_conv_data=room.mic_array.signals\r\n\r\n#ファイルに書き込む\r\nfor m in range(n_channels):\r\n    conv_data=multi_conv_data[m,:]\r\n    data_scale_adjust=conv_data*np.iinfo(np.int16).max/20.\r\n    data_scale_adjust=data_scale_adjust.astype(np.int16)\r\n    wave_out=wave.open(\"./noise_reverb_conv_out_{}.wav\".format(m),\"w\")\r\n    wave_out.setnchannels(1)\r\n    wave_out.setsampwidth(2)\r\n    wave_out.setframerate(sample_rate)\r\n    wave_out.writeframes(data_scale_adjust)\r\n    wave_out.close()\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "section5/sample_code_c5_6.py",
    "content": "\r\nimport wave as wave\r\nimport pyroomacoustics as pa\r\nimport numpy as np\r\nimport matplotlib.pyplot as plt\r\n\r\n#乱数の種を初期化\r\nnp.random.seed(0)\r\n\r\n#畳み込みに用いる音声波形\r\nclean_wave_files=[\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\",\"./CMU_ARCTIC/cmu_us_axb_arctic/wav/arctic_a0002.wav\"]\r\n\r\n#音源数\r\nn_sources=len(clean_wave_files)\r\n\r\n#長さを調べる\r\nn_samples=0\r\n#ファイルを読み込む\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    if n_samples<wav.getnframes():\r\n        n_samples=wav.getnframes()\r\n    wav.close()\r\n\r\nclean_data=np.zeros([n_sources,n_samples])\r\n\r\n#ファイルを読み込む\r\ns=0\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    data=wav.readframes(wav.getnframes())\r\n    data=np.frombuffer(data, dtype=np.int16)\r\n    data=data/np.iinfo(np.int16).max\r\n    clean_data[s,:wav.getnframes()]=data\r\n    wav.close()\r\n    s=s+1\r\n# シミュレーションのパラメータ\r\n#サンプリング周波数\r\nsample_rate=16000\r\n\r\n#音声と雑音との比率 [dB]\r\nSNR=90.\r\n\r\n#部屋の大きさ\r\nroom_dim = np.r_[10.0, 10.0, 10.0]\r\n\r\n#マイクロホンアレイを置く部屋の場所\r\nmic_array_loc = room_dim / 2 + np.random.randn(3) * 0.1 \r\n\r\n#マイクロホンアレイのマイク配置\r\nmic_alignments = np.array(\r\n    [\r\n        [-0.01, 0.0, 0.0],\r\n        [0.01, 0.0, 0.0],\r\n    ]\r\n)\r\n\r\n#マイクロホン数\r\nn_channels=np.shape(mic_alignments)[0]\r\n\r\n#マイクロホンアレイの座標\r\nR=mic_alignments .T+mic_array_loc[:,None]\r\n\r\n# 部屋を生成する\r\nroom = pa.ShoeBox(room_dim, fs=sample_rate, max_order=17,absorption=0.35)\r\n\r\n# 用いるマイクロホンアレイの情報を設定する\r\nroom.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\n\r\n#音源の場所\r\ndoas=np.array(\r\n    [[np.pi/2., 0],\r\n     [np.pi/2.,np.pi/2.]\r\n    ]    )\r\n\r\n#音源とマイクロホンの距離\r\ndistance=1.\r\nsource_locations=np.zeros((3, doas.shape[0]), dtype=doas.dtype)\r\nsource_locations[0, :] = np.cos(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[1, :] = np.sin(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[2, :] = np.cos(doas[:, 0])\r\nsource_locations *= distance\r\nsource_locations += mic_array_loc[:, None]\r\n\r\n#各音源をシミュレーションに追加する\r\nfor s in range(n_sources):\r\n    clean_data[s]/= np.std(clean_data[s])\r\n    room.add_source(source_locations[:, s], signal=clean_data[s])\r\n\r\n#シミュレーションを回す\r\nroom.simulate(snr=SNR)\r\n\r\n#インパルス応答を取得する\r\n#room.rirにはマイク，音源の順番で各音源の各マイクのインパルス応答が入っている\r\nimpulse_responses=room.rir\r\n\r\nimpulse_length=np.shape(impulse_responses[0][0])[0]\r\n\r\n#残響時間を取得\r\nrt60=pa.experimental.measure_rt60(impulse_responses[0][0],fs=sample_rate)\r\nprint(\"残響時間:{} [sec]\".format(rt60))\r\n\r\nrir_power=np.square(impulse_responses[0][0])\r\n\r\n\r\nreverb_power=np.zeros_like(rir_power)\r\nfor t in range(impulse_length):\r\n    reverb_power[t]=10.*np.log10(np.sum(rir_power[t:])/np.sum(rir_power))\r\n    \r\n\r\n\r\n#x軸の値\r\nx=np.array(range(impulse_length))/sample_rate\r\n\r\n#音声データをプロットする\r\nplt.figure(figsize=(10,4))\r\n\r\n#x軸のラベル\r\nplt.xlabel(\"Time [sec]\")\r\n\r\n#y軸のラベル\r\nplt.ylabel(\"Value\")\r\n\r\n#x軸の範囲を設定する\r\nplt.xlim([0,0.5])\r\n\r\n#データをプロット\r\nplt.plot(x,impulse_responses[0][0])\r\n#plt.plot(x,reverb_power)\r\n\r\n#音声ファイルを画像として保存\r\nplt.savefig(\"./impulse_responses2.png\")\r\n\r\n#画像を画面に表示\r\nplt.show()\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "section5/sample_code_c5_7.py",
    "content": "\r\nimport wave as wave\r\nimport pyroomacoustics as pa\r\nimport numpy as np\r\nimport matplotlib.pyplot as plt\r\n\r\n#乱数の種を初期化\r\nnp.random.seed(0)\r\n\r\n#畳み込みに用いる音声波形\r\nclean_wave_files=[\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\",\"./CMU_ARCTIC/cmu_us_axb_arctic/wav/arctic_a0002.wav\"]\r\n\r\n#音源数\r\nn_sources=len(clean_wave_files)\r\n\r\n#長さを調べる\r\nn_samples=0\r\n#ファイルを読み込む\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    if n_samples<wav.getnframes():\r\n        n_samples=wav.getnframes()\r\n    wav.close()\r\n\r\nclean_data=np.zeros([n_sources,n_samples])\r\n\r\n#ファイルを読み込む\r\ns=0\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    data=wav.readframes(wav.getnframes())\r\n    data=np.frombuffer(data, dtype=np.int16)\r\n    data=data/np.iinfo(np.int16).max\r\n    clean_data[s,:wav.getnframes()]=data\r\n    wav.close()\r\n    s=s+1\r\n    \r\n# シミュレーションのパラメータ\r\n#サンプリング周波数\r\nsample_rate=16000\r\n\r\n#音声と雑音との比率 [dB]\r\nSNR=90.\r\n\r\n#部屋の大きさ\r\nroom_dim = np.r_[10.0, 10.0, 10.0]\r\n\r\n#マイクロホンアレイを置く部屋の場所\r\nmic_array_loc = room_dim / 2 + np.random.randn(3) * 0.1 \r\n\r\n#マイクロホンアレイのマイク配置\r\nmic_alignments = np.array(\r\n    [\r\n        [-0.01, 0.0, 0.0],\r\n        [0.01, 0.0, 0.0],\r\n    ]\r\n)\r\n\r\n#マイクロホン数\r\nn_channels=np.shape(mic_alignments)[0]\r\n\r\n#マイクロホンアレイの座標\r\nR=mic_alignments .T+mic_array_loc[:,None]\r\n\r\n# 部屋を生成する\r\nroom = pa.ShoeBox(room_dim, fs=sample_rate, max_order=30,absorption=0.2)\r\n\r\n# 用いるマイクロホンアレイの情報を設定する\r\nroom.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\n\r\n#音源の場所\r\ndoas=np.array(\r\n    [[np.pi/2., 0],\r\n     [np.pi/2.,np.pi/2.]\r\n    ]    )\r\n\r\n#音源とマイクロホンの距離\r\ndistance=1.\r\nsource_locations=np.zeros((3, doas.shape[0]), dtype=doas.dtype)\r\nsource_locations[0, :] = np.cos(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[1, :] = np.sin(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[2, :] = np.cos(doas[:, 0])\r\nsource_locations *= distance\r\nsource_locations += mic_array_loc[:, None]\r\n\r\n#各音源をシミュレーションに追加する\r\nfor s in range(n_sources):\r\n    clean_data[s]/= np.std(clean_data[s])\r\n    room.add_source(source_locations[:, s], signal=clean_data[s])\r\n\r\n#シミュレーションを回す\r\nroom.simulate(snr=SNR)\r\n\r\n#インパルス応答を取得する\r\n#room.rirにはマイク，音源の順番で各音源の各マイクのインパルス応答が入っている\r\nimpulse_responses=room.rir\r\n\r\nimpulse_length=np.shape(impulse_responses[0][0])[0]\r\n\r\n#残響時間を取得\r\nrt60=pa.experimental.measure_rt60(impulse_responses[0][0],fs=sample_rate)\r\nprint(\"残響時間:{} [sec]\".format(rt60))\r\n\r\nrir_power=np.square(impulse_responses[0][0])\r\n\r\n\r\nreverb_power=np.zeros_like(rir_power)\r\nfor t in range(impulse_length):\r\n    reverb_power[t]=10.*np.log10(np.sum(rir_power[t:])/np.sum(rir_power))\r\n    \r\n\r\n\r\n#x軸の値\r\nx=np.array(range(impulse_length))/sample_rate\r\n\r\n#音声データをプロットする\r\nplt.figure(figsize=(10,4))\r\n\r\n#x軸のラベル\r\nplt.xlabel(\"Time [sec]\")\r\n\r\n#y軸のラベル\r\nplt.ylabel(\"Value\")\r\n\r\n#x軸の範囲を設定する\r\nplt.xlim([0,0.5])\r\n\r\n#データをプロット\r\nplt.plot(x,impulse_responses[0][0])\r\n#plt.plot(x,reverb_power)\r\n\r\n#音声ファイルを画像として保存\r\nplt.savefig(\"./impulse_responses2.png\")\r\n\r\n#画像を画面に表示\r\nplt.show()\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "section5.md",
    "content": "## 第5章のサンプルコード\n\n* [インパルス応答の畳み込みの例](section5/sample_code_c5_1.py)\n* [Pyroomacousticsを用いた室内伝達関数のシミュレーションと畳み込み](section5/sample_code_c5_2.py)\n* [マイクロホンの数を変更](section5/sample_code_c5_3.py)\n* [残響の量を変更](section5/sample_code_c5_4.py)\n* [雑音を考慮したシミュレーション](section5/sample_code_c5_5.py)\n* [インパルス応答の取得と残響時間（RT60）の取得](section5/sample_code_c5_6.py)\n* [インパルス応答の取得と残響時間（RT60）の取得(残響の量を変更)](section5/sample_code_c5_7.py)\n"
  },
  {
    "path": "section6/sample_code_c6_1.py",
    "content": "\r\nimport numpy as np\r\n\r\n#ステアリングベクトルを算出\r\n#mic_position: 3 x M  dimensional ndarray [[x,y,z],[x,y,z]]\r\n#source_position: 3x Ns dimensional ndarray [[x,y,z],[x,y,z] ]\r\n#freqs: Nk dimensional array [f1,f2,f3...]\r\n#sound_speed: 音速 [m/s]\r\n#is_use_far: Farを使う場合はTrue, Nearの場合はFalse, \r\n#return: steering vector (Nk x Ns x M)\r\ndef calculate_steering_vector(mic_alignments,source_locations,freqs,sound_speed=340,is_use_far=False):\r\n    #マイク数を取得\r\n    n_channels=np.shape(mic_alignments)[1]\r\n\r\n    #音源数を取得\r\n    n_source=np.shape(source_locations)[1]\r\n\r\n    if is_use_far==True:\r\n        #音源位置を正規化\r\n        norm_source_locations=source_locations/np.linalg.norm(source_locations,2,axis=0,keepdims=True)\r\n\r\n        #位相を求める\r\n        steering_phase=np.einsum('k,ism,ism->ksm',2.j*np.pi/sound_speed*freqs,norm_source_locations[...,None],mic_alignments[:,None,:])\r\n\r\n        #ステアリングベクトルを算出\r\n        steering_vector=1./np.sqrt(n_channels)*np.exp(steering_phase)\r\n\r\n        return(steering_vector)\r\n\r\n    else:\r\n\r\n        #音源とマイクの距離を求める\r\n        #distance: Ns x Nm\r\n        distance=np.sqrt(np.sum(np.square(source_locations[...,None]-mic_alignments[:,None,:]),axis=0))\r\n\r\n        #遅延時間(delay) [sec]\r\n        delay=distance/sound_speed\r\n\r\n        #ステアリングベクトルの位相を求める\r\n        steering_phase=np.einsum('k,sm->ksm',-2.j*np.pi*freqs,delay)\r\n    \r\n        #音量の減衰\r\n        steering_decay_ratio=1./distance\r\n\r\n        #ステアリングベクトルを求める\r\n        steering_vector=steering_decay_ratio[None,...]*np.exp(steering_phase)\r\n\r\n        #大きさを1で正規化する\r\n        steering_vector=steering_vector/np.linalg.norm(steering_vector,2,axis=2,keepdims=True)\r\n\r\n    return(steering_vector)\r\n\r\n#サンプリングレート [Hz]\r\nsample_rate=16000\r\n\r\n#フレームサイズ\r\nN=1024\r\n\r\n#周波数の数\r\nNk=N/2+1\r\n\r\n#各ビンの周波数\r\nfreqs=np.arange(0,Nk,1)*sample_rate/N\r\n\r\n#マイクロホンアレイのマイク配置\r\nmic_alignments = np.array(\r\n    [\r\n        [-0.01, 0.0, 0.0],\r\n        [0.01, 0.0, 0.0],\r\n    ]\r\n).T\r\n\r\n#音源の方向\r\ndoas=np.array(\r\n    [[np.pi/2,0],\r\n     [np.pi/2,np.pi]\r\n    ]    )\r\n\r\n#音源とマイクロホンの距離\r\ndistance=1\r\n\r\n#音源の位置ベクトル\r\nsource_locations=np.zeros((3, doas.shape[0]), dtype=doas.dtype)\r\nsource_locations[0, :] = np.cos(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[1, :] = np.sin(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[2, :] = np.cos(doas[:, 0])\r\nsource_locations *= distance\r\n\r\n#Near仮定に基づくステアリングベクトルを計算: steering_vectors(Nk x Ns x M)\r\nnear_steering_vectors=calculate_steering_vector(mic_alignments,source_locations,freqs,is_use_far=False)\r\n\r\n#Far仮定に基づくステアリングベクトルを計算: steering_vectors(Nk x Ns x M)\r\nfar_steering_vectors=calculate_steering_vector(mic_alignments,source_locations,freqs,is_use_far=True)\r\n\r\n#内積を計算\r\ninner_product=np.einsum(\"ksm,ksm->ks\",np.conjugate(near_steering_vectors),far_steering_vectors)\r\nprint(np.average(np.abs(inner_product)))\r\n"
  },
  {
    "path": "section6/sample_code_c6_10.py",
    "content": "\r\n\r\nimport wave as wave\r\nimport pyroomacoustics as pa\r\nimport numpy as np\r\nimport scipy.signal as sp\r\n\r\n#ステアリングベクトルを算出\r\n#mic_position: 3 x M  dimensional ndarray [[x,y,z],[x,y,z]]\r\n#source_position: 3x Ns dimensional ndarray [[x,y,z],[x,y,z] ]\r\n#freqs: Nk dimensional array [f1,f2,f3...]\r\n#sound_speed: 音速 [m/s]\r\n#is_use_far: Farを使う場合はTrue, Nearの場合はFalse, \r\n#return: steering vector (Nk x Ns x M)\r\ndef calculate_steering_vector(mic_alignments,source_locations,freqs,sound_speed=340,is_use_far=False):\r\n    #マイク数を取得\r\n    n_channels=np.shape(mic_alignments)[1]\r\n\r\n    #音源数を取得\r\n    n_source=np.shape(source_locations)[1]\r\n\r\n    if is_use_far==True:\r\n        #音源位置を正規化\r\n        norm_source_locations=source_locations/np.linalg.norm(source_locations,2,axis=0,keepdims=True)\r\n\r\n        #位相を求める\r\n        steering_phase=np.einsum('k,ism,ism->ksm',2.j*np.pi/sound_speed*freqs,norm_source_locations[...,None],mic_alignments[:,None,:])\r\n\r\n        #ステアリングベクトルを算出\r\n        steering_vector=1./np.sqrt(n_channels)*np.exp(steering_phase)\r\n\r\n        return(steering_vector)\r\n\r\n    else:\r\n\r\n        #音源とマイクの距離を求める\r\n        #distance: Ns x Nm\r\n        distance=np.sqrt(np.sum(np.square(source_locations[...,None]-mic_alignments[:,None,:]),axis=0))\r\n\r\n        #遅延時間(delay) [sec]\r\n        delay=distance/sound_speed\r\n\r\n        #ステアリングベクトルの位相を求める\r\n        steering_phase=np.einsum('k,sm->ksm',-2.j*np.pi*freqs,delay)\r\n    \r\n        #音量の減衰\r\n        steering_decay_ratio=1./distance\r\n\r\n        #ステアリングベクトルを求める\r\n        steering_vector=steering_decay_ratio[None,...]*np.exp(steering_phase)\r\n\r\n        #大きさを1で正規化する\r\n        steering_vector=steering_vector/np.linalg.norm(steering_vector,2,axis=2,keepdims=True)\r\n\r\n    return(steering_vector)\r\n\r\n#2バイトに変換してファイルに保存\r\n#signal: time-domain 1d array (float)\r\n#file_name: 出力先のファイル名\r\n#sample_rate: サンプリングレート\r\ndef write_file_from_time_signal(signal,file_name,sample_rate):\r\n    #2バイトのデータに変換\r\n    signal=signal.astype(np.int16)\r\n\r\n    #waveファイルに書き込む\r\n    wave_out = wave.open(file_name, 'w')\r\n\r\n    #モノラル:1、ステレオ:2\r\n    wave_out.setnchannels(1)\r\n\r\n    #サンプルサイズ2byte\r\n    wave_out.setsampwidth(2)\r\n\r\n    #サンプリング周波数\r\n    wave_out.setframerate(sample_rate)\r\n\r\n    #データを書き込み\r\n    wave_out.writeframes(signal)\r\n\r\n    #ファイルを閉じる\r\n    wave_out.close()\r\n\r\n#乱数の種を初期化\r\nnp.random.seed(0)\r\n\r\n#畳み込みに用いる音声波形\r\nclean_wave_files=[\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\"]\r\n\r\n\r\n#雑音だけの区間のサンプル数を設定\r\nn_noise_only=40000\r\n\r\n#音源数\r\nn_sources=len(clean_wave_files)\r\n\r\n#長さを調べる\r\nn_samples=0\r\n#ファイルを読み込む\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    if n_samples<wav.getnframes():\r\n        n_samples=wav.getnframes()\r\n    wav.close()\r\n\r\nclean_data=np.zeros([n_sources,n_samples+n_noise_only])\r\n\r\n#ファイルを読み込む\r\ns=0\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    data=wav.readframes(wav.getnframes())\r\n    data=np.frombuffer(data, dtype=np.int16)\r\n    data=data/np.iinfo(np.int16).max\r\n    clean_data[s,n_noise_only:n_noise_only+wav.getnframes()]=data\r\n    wav.close()\r\n    s=s+1\r\n# シミュレーションのパラメータ\r\n\r\n#サンプリング周波数\r\nsample_rate=16000\r\n\r\n#フレームサイズ\r\nN=1024\r\n\r\n#周波数の数\r\nNk=N/2+1\r\n\r\n\r\n#各ビンの周波数\r\nfreqs=np.arange(0,Nk,1)*sample_rate/N\r\n\r\n#音声と雑音との比率 [dB]\r\nSNR=20.\r\n\r\n#部屋の大きさ\r\nroom_dim = np.r_[10.0, 10.0, 10.0]\r\n\r\n#マイクロホンアレイを置く部屋の場所\r\nmic_array_loc = room_dim / 2 + np.random.randn(3) * 0.1 \r\n\r\n#マイクロホンアレイのマイク配置\r\nmic_alignments = np.array(\r\n    [\r\n        [-0.01, 0.0, 0.0],\r\n        [0.01, 0.0, 0.0],\r\n    ]\r\n)\r\n\r\n#マイクロホン数\r\nn_channels=np.shape(mic_alignments)[0]\r\n\r\n#マイクロホンアレイの座標\r\nR=mic_alignments .T+mic_array_loc[:,None]\r\n\r\n# 部屋を生成する\r\nroom = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\n\r\n# 用いるマイクロホンアレイの情報を設定する\r\nroom.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\n\r\n#音源の場所\r\ndoas=np.array(\r\n    [[np.pi/2., 0]\r\n    ]    )\r\n\r\n#音源とマイクロホンの距離\r\ndistance=1.\r\nsource_locations=np.zeros((3, doas.shape[0]), dtype=doas.dtype)\r\nsource_locations[0, :] = np.cos(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[1, :] = np.sin(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[2, :] = np.cos(doas[:, 0])\r\nsource_locations *= distance\r\nsource_locations += mic_array_loc[:, None]\r\n\r\n#各音源をシミュレーションに追加する\r\nfor s in range(n_sources):\r\n    clean_data[s]/= np.std(clean_data[s])\r\n    room.add_source(source_locations[:, s], signal=clean_data[s])\r\n\r\n#シミュレーションを回す\r\nroom.simulate(snr=SNR)\r\n\r\n#畳み込んだ波形を取得する(チャンネル、サンプル）\r\nmulti_conv_data=room.mic_array.signals\r\n\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data[0,n_noise_only:]*np.iinfo(np.int16).max/20.,\"./mlbf_in.wav\",sample_rate)\r\n\r\n#Near仮定に基づくステアリングベクトルを計算: steering_vectors(Nk x Ns x M)\r\nnear_steering_vectors=calculate_steering_vector(R,source_locations,freqs,is_use_far=False)\r\n\r\n#短時間フーリエ変換を行う\r\nf,t,stft_data=sp.stft(multi_conv_data,fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\n#雑音だけの区間のフレーム数\r\nn_noise_only_frame=np.sum(t<(n_noise_only/sample_rate))\r\n\r\n#共分散行列を計算する\r\nRcov=np.einsum(\"mkt,nkt->kmn\",stft_data[...,:n_noise_only_frame],np.conjugate(stft_data[...,:n_noise_only_frame]))\r\n\r\n#共分散行列の逆行列を計算する\r\nRcov_inverse=np.linalg.pinv(Rcov)\r\n\r\n#フィルタを計算する\r\nRcov_inverse_a=np.einsum(\"kmn,kn->km\",Rcov_inverse,near_steering_vectors[:,0,:])\r\na_H_Rcov_inverse_a=np.einsum(\"kn,kn->k\",np.conjugate(near_steering_vectors[:,0,:]),Rcov_inverse_a)\r\nw_mvdr=Rcov_inverse_a/np.maximum(a_H_Rcov_inverse_a,1.e-18)[:,None]\r\n\r\n#フィルタをかける\r\ns_hat=np.einsum(\"km,mkt->kt\",np.conjugate(w_mvdr),stft_data)\r\n\r\n#ステアリングベクトルをかける\r\nc_hat=np.einsum(\"kt,km->mkt\",s_hat,near_steering_vectors[:,0,:])\r\n\r\n#時間領域の波形に戻す\r\nt,mvdr_out=sp.istft(c_hat[0],fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\n#大きさを調整する\r\nmvdr_out=mvdr_out*np.iinfo(np.int16).max/20.\r\n\r\n#ファイルに書き込む\r\nwrite_file_from_time_signal(mvdr_out[n_noise_only:],\"./mlbf_out.wav\",sample_rate)\r\n\r\n\r\n"
  },
  {
    "path": "section6/sample_code_c6_11.py",
    "content": "\r\n\r\nimport wave as wave\r\nimport pyroomacoustics as pa\r\nimport numpy as np\r\nimport scipy.signal as sp\r\nimport scipy as scipy\r\n\r\n#ステアリングベクトルを算出\r\n#mic_position: 3 x M  dimensional ndarray [[x,y,z],[x,y,z]]\r\n#source_position: 3x Ns dimensional ndarray [[x,y,z],[x,y,z] ]\r\n#freqs: Nk dimensional array [f1,f2,f3...]\r\n#sound_speed: 音速 [m/s]\r\n#is_use_far: Farを使う場合はTrue, Nearの場合はFalse, \r\n#return: steering vector (Nk x Ns x M)\r\ndef calculate_steering_vector(mic_alignments,source_locations,freqs,sound_speed=340,is_use_far=False):\r\n    #マイク数を取得\r\n    n_channels=np.shape(mic_alignments)[1]\r\n\r\n    #音源数を取得\r\n    n_source=np.shape(source_locations)[1]\r\n\r\n    if is_use_far==True:\r\n        #音源位置を正規化\r\n        norm_source_locations=source_locations/np.linalg.norm(source_locations,2,axis=0,keepdims=True)\r\n\r\n        #位相を求める\r\n        steering_phase=np.einsum('k,ism,ism->ksm',2.j*np.pi/sound_speed*freqs,norm_source_locations[...,None],mic_alignments[:,None,:])\r\n\r\n        #ステアリングベクトルを算出\r\n        steering_vector=1./np.sqrt(n_channels)*np.exp(steering_phase)\r\n\r\n        return(steering_vector)\r\n\r\n    else:\r\n\r\n        #音源とマイクの距離を求める\r\n        #distance: Ns x Nm\r\n        distance=np.sqrt(np.sum(np.square(source_locations[...,None]-mic_alignments[:,None,:]),axis=0))\r\n\r\n        #遅延時間(delay) [sec]\r\n        delay=distance/sound_speed\r\n\r\n        #ステアリングベクトルの位相を求める\r\n        steering_phase=np.einsum('k,sm->ksm',-2.j*np.pi*freqs,delay)\r\n    \r\n        #音量の減衰\r\n        steering_decay_ratio=1./distance\r\n\r\n        #ステアリングベクトルを求める\r\n        steering_vector=steering_decay_ratio[None,...]*np.exp(steering_phase)\r\n\r\n        #大きさを1で正規化する\r\n        steering_vector=steering_vector/np.linalg.norm(steering_vector,2,axis=2,keepdims=True)\r\n\r\n    return(steering_vector)\r\n\r\n#2バイトに変換してファイルに保存\r\n#signal: time-domain 1d array (float)\r\n#file_name: 出力先のファイル名\r\n#sample_rate: サンプリングレート\r\ndef write_file_from_time_signal(signal,file_name,sample_rate):\r\n    #2バイトのデータに変換\r\n    signal=signal.astype(np.int16)\r\n\r\n    #waveファイルに書き込む\r\n    wave_out = wave.open(file_name, 'w')\r\n\r\n    #モノラル:1、ステレオ:2\r\n    wave_out.setnchannels(1)\r\n\r\n    #サンプルサイズ2byte\r\n    wave_out.setsampwidth(2)\r\n\r\n    #サンプリング周波数\r\n    wave_out.setframerate(sample_rate)\r\n\r\n    #データを書き込み\r\n    wave_out.writeframes(signal)\r\n\r\n    #ファイルを閉じる\r\n    wave_out.close()\r\n\r\n#乱数の種を初期化\r\nnp.random.seed(0)\r\n\r\n#畳み込みに用いる音声波形\r\nclean_wave_files=[\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\"]\r\n\r\n\r\n#雑音だけの区間のサンプル数を設定\r\nn_noise_only=40000\r\n\r\n#音源数\r\nn_sources=len(clean_wave_files)\r\n\r\n#長さを調べる\r\nn_samples=0\r\n#ファイルを読み込む\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    if n_samples<wav.getnframes():\r\n        n_samples=wav.getnframes()\r\n    wav.close()\r\n\r\nclean_data=np.zeros([n_sources,n_samples+n_noise_only])\r\n\r\n#ファイルを読み込む\r\ns=0\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    data=wav.readframes(wav.getnframes())\r\n    data=np.frombuffer(data, dtype=np.int16)\r\n    data=data/np.iinfo(np.int16).max\r\n    clean_data[s,n_noise_only:n_noise_only+wav.getnframes()]=data\r\n    wav.close()\r\n    s=s+1\r\n# シミュレーションのパラメータ\r\n\r\n#サンプリング周波数\r\nsample_rate=16000\r\n\r\n#フレームサイズ\r\nN=1024\r\n\r\n#周波数の数\r\nNk=int(N/2+1)\r\n\r\n\r\n#各ビンの周波数\r\nfreqs=np.arange(0,Nk,1)*sample_rate/N\r\n\r\n#音声と雑音との比率 [dB]\r\nSNR=20.\r\n\r\n#部屋の大きさ\r\nroom_dim = np.r_[10.0, 10.0, 10.0]\r\n\r\n#マイクロホンアレイを置く部屋の場所\r\nmic_array_loc = room_dim / 2 + np.random.randn(3) * 0.1 \r\n\r\n#マイクロホンアレイのマイク配置\r\nmic_alignments = np.array(\r\n    [\r\n        [-0.01, 0.0, 0.0],\r\n        [0.01, 0.0, 0.0],\r\n    ]\r\n)\r\n\r\n#マイクロホン数\r\nn_channels=np.shape(mic_alignments)[0]\r\n\r\n#マイクロホンアレイの座標\r\nR=mic_alignments .T+mic_array_loc[:,None]\r\n\r\n# 部屋を生成する\r\nroom = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\n\r\n# 用いるマイクロホンアレイの情報を設定する\r\nroom.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\n\r\n#音源の場所\r\ndoas=np.array(\r\n    [[np.pi/2., 0]\r\n    ]    )\r\n\r\n#音源とマイクロホンの距離\r\ndistance=1.\r\nsource_locations=np.zeros((3, doas.shape[0]), dtype=doas.dtype)\r\nsource_locations[0, :] = np.cos(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[1, :] = np.sin(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[2, :] = np.cos(doas[:, 0])\r\nsource_locations *= distance\r\nsource_locations += mic_array_loc[:, None]\r\n\r\n#各音源をシミュレーションに追加する\r\nfor s in range(n_sources):\r\n    clean_data[s]/= np.std(clean_data[s])\r\n    room.add_source(source_locations[:, s], signal=clean_data[s])\r\n\r\n#シミュレーションを回す\r\nroom.simulate(snr=SNR)\r\n\r\n#畳み込んだ波形を取得する(チャンネル、サンプル）\r\nmulti_conv_data=room.mic_array.signals\r\n\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data[0,n_noise_only:]*np.iinfo(np.int16).max/20.,\"./maxsnr_in.wav\",sample_rate)\r\n\r\n#Near仮定に基づくステアリングベクトルを計算: steering_vectors(Nk x Ns x M)\r\nnear_steering_vectors=calculate_steering_vector(R,source_locations,freqs,is_use_far=False)\r\n\r\n#短時間フーリエ変換を行う\r\nf,t,stft_data=sp.stft(multi_conv_data,fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\n#雑音だけの区間のフレーム数\r\nn_noise_only_frame=np.sum(t<(n_noise_only/sample_rate))\r\n\r\nxx_H=np.einsum(\"mkt,nkt->ktmn\",stft_data,np.conjugate(stft_data))\r\n\r\n#雑音の共分散行列 freq,mic,mic\r\nRn=np.average(xx_H[:,:n_noise_only_frame,...],axis=1)\r\n\r\n#入力共分散行列\r\nRs=np.average(xx_H[:,n_noise_only_frame:,...],axis=1)\r\n\r\n#一般化固有値分解\r\nmax_snr_filter=None\r\nfor k in range(Nk):\r\n    w,v=scipy.linalg.eigh(Rs[k,...],Rn[k,...])\r\n    if max_snr_filter is None:\r\n        max_snr_filter=v[None,:,-1]\r\n    else:\r\n        max_snr_filter=np.concatenate((max_snr_filter,v[None,:,-1]),axis=0)\r\n    \r\n\r\nRs_w=np.einsum(\"kmn,kn->km\",Rs,max_snr_filter)\r\nbeta=Rs_w[:,0]/np.einsum(\"km,km->k\",np.conjugate(max_snr_filter),Rs_w)\r\nw_max_snr=beta[:,None]*max_snr_filter\r\n\r\n#フィルタをかける\r\nc_hat=np.einsum(\"km,mkt->kt\",np.conjugate(w_max_snr),stft_data)\r\n\r\n#時間領域の波形に戻す\r\nt,maxsnr_out=sp.istft(c_hat,fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\n#大きさを調整する\r\nmaxsnr_out=maxsnr_out*np.iinfo(np.int16).max/20.\r\n\r\n#ファイルに書き込む\r\nwrite_file_from_time_signal(maxsnr_out[n_noise_only:],\"./maxsnr_out.wav\",sample_rate)\r\n"
  },
  {
    "path": "section6/sample_code_c6_12.py",
    "content": "\r\n\r\nimport wave as wave\r\nimport pyroomacoustics as pa\r\nimport numpy as np\r\nimport scipy.signal as sp\r\nimport scipy as scipy\r\n\r\n#ステアリングベクトルを算出\r\n#mic_position: 3 x M  dimensional ndarray [[x,y,z],[x,y,z]]\r\n#source_position: 3x Ns dimensional ndarray [[x,y,z],[x,y,z] ]\r\n#freqs: Nk dimensional array [f1,f2,f3...]\r\n#sound_speed: 音速 [m/s]\r\n#is_use_far: Farを使う場合はTrue, Nearの場合はFalse, \r\n#return: steering vector (Nk x Ns x M)\r\ndef calculate_steering_vector(mic_alignments,source_locations,freqs,sound_speed=340,is_use_far=False):\r\n    #マイク数を取得\r\n    n_channels=np.shape(mic_alignments)[1]\r\n\r\n    #音源数を取得\r\n    n_source=np.shape(source_locations)[1]\r\n\r\n    if is_use_far==True:\r\n        #音源位置を正規化\r\n        norm_source_locations=source_locations/np.linalg.norm(source_locations,2,axis=0,keepdims=True)\r\n\r\n        #位相を求める\r\n        steering_phase=np.einsum('k,ism,ism->ksm',2.j*np.pi/sound_speed*freqs,norm_source_locations[...,None],mic_alignments[:,None,:])\r\n\r\n        #ステアリングベクトルを算出\r\n        steering_vector=1./np.sqrt(n_channels)*np.exp(steering_phase)\r\n\r\n        return(steering_vector)\r\n\r\n    else:\r\n\r\n        #音源とマイクの距離を求める\r\n        #distance: Ns x Nm\r\n        distance=np.sqrt(np.sum(np.square(source_locations[...,None]-mic_alignments[:,None,:]),axis=0))\r\n\r\n        #遅延時間(delay) [sec]\r\n        delay=distance/sound_speed\r\n\r\n        #ステアリングベクトルの位相を求める\r\n        steering_phase=np.einsum('k,sm->ksm',-2.j*np.pi*freqs,delay)\r\n    \r\n        #音量の減衰\r\n        steering_decay_ratio=1./distance\r\n\r\n        #ステアリングベクトルを求める\r\n        steering_vector=steering_decay_ratio[None,...]*np.exp(steering_phase)\r\n\r\n        #大きさを1で正規化する\r\n        steering_vector=steering_vector/np.linalg.norm(steering_vector,2,axis=2,keepdims=True)\r\n\r\n    return(steering_vector)\r\n\r\n#2バイトに変換してファイルに保存\r\n#signal: time-domain 1d array (float)\r\n#file_name: 出力先のファイル名\r\n#sample_rate: サンプリングレート\r\ndef write_file_from_time_signal(signal,file_name,sample_rate):\r\n    #2バイトのデータに変換\r\n    signal=signal.astype(np.int16)\r\n\r\n    #waveファイルに書き込む\r\n    wave_out = wave.open(file_name, 'w')\r\n\r\n    #モノラル:1、ステレオ:2\r\n    wave_out.setnchannels(1)\r\n\r\n    #サンプルサイズ2byte\r\n    wave_out.setsampwidth(2)\r\n\r\n    #サンプリング周波数\r\n    wave_out.setframerate(sample_rate)\r\n\r\n    #データを書き込み\r\n    wave_out.writeframes(signal)\r\n\r\n    #ファイルを閉じる\r\n    wave_out.close()\r\n\r\n#乱数の種を初期化\r\nnp.random.seed(0)\r\n\r\n#畳み込みに用いる音声波形\r\nclean_wave_files=[\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\"]\r\n\r\n\r\n#雑音だけの区間のサンプル数を設定\r\nn_noise_only=40000\r\n\r\n#音源数\r\nn_sources=len(clean_wave_files)\r\n\r\n#長さを調べる\r\nn_samples=0\r\n#ファイルを読み込む\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    if n_samples<wav.getnframes():\r\n        n_samples=wav.getnframes()\r\n    wav.close()\r\n\r\nclean_data=np.zeros([n_sources,n_samples+n_noise_only])\r\n\r\n#ファイルを読み込む\r\ns=0\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    data=wav.readframes(wav.getnframes())\r\n    data=np.frombuffer(data, dtype=np.int16)\r\n    data=data/np.iinfo(np.int16).max\r\n    clean_data[s,n_noise_only:n_noise_only+wav.getnframes()]=data\r\n    wav.close()\r\n    s=s+1\r\n# シミュレーションのパラメータ\r\n\r\n#サンプリング周波数\r\nsample_rate=16000\r\n\r\n#フレームサイズ\r\nN=1024\r\n\r\n#周波数の数\r\nNk=int(N/2+1)\r\n\r\n\r\n#各ビンの周波数\r\nfreqs=np.arange(0,Nk,1)*sample_rate/N\r\n\r\n#音声と雑音との比率 [dB]\r\nSNR=20.\r\n\r\n#部屋の大きさ\r\nroom_dim = np.r_[10.0, 10.0, 10.0]\r\n\r\n#マイクロホンアレイを置く部屋の場所\r\nmic_array_loc = room_dim / 2 + np.random.randn(3) * 0.1 \r\n\r\n#マイクロホンアレイのマイク配置\r\nmic_alignments = np.array(\r\n    [\r\n        [-0.01, 0.0, 0.0],\r\n        [0.01, 0.0, 0.0],\r\n    ]\r\n)\r\n\r\n#マイクロホン数\r\nn_channels=np.shape(mic_alignments)[0]\r\n\r\n#マイクロホンアレイの座標\r\nR=mic_alignments .T+mic_array_loc[:,None]\r\n\r\n# 部屋を生成する\r\nroom = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\n\r\n# 用いるマイクロホンアレイの情報を設定する\r\nroom.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\n\r\n#音源の場所\r\ndoas=np.array(\r\n    [[np.pi/2., 0]\r\n    ]    )\r\n\r\n#音源とマイクロホンの距離\r\ndistance=1.\r\nsource_locations=np.zeros((3, doas.shape[0]), dtype=doas.dtype)\r\nsource_locations[0, :] = np.cos(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[1, :] = np.sin(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[2, :] = np.cos(doas[:, 0])\r\nsource_locations *= distance\r\nsource_locations += mic_array_loc[:, None]\r\n\r\n#各音源をシミュレーションに追加する\r\nfor s in range(n_sources):\r\n    clean_data[s]/= np.std(clean_data[s])\r\n    room.add_source(source_locations[:, s], signal=clean_data[s])\r\n\r\n#シミュレーションを回す\r\nroom.simulate(snr=SNR)\r\n\r\n#畳み込んだ波形を取得する(チャンネル、サンプル）\r\nmulti_conv_data=room.mic_array.signals\r\n\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data[0,n_noise_only:]*np.iinfo(np.int16).max/20.,\"./mwf_in.wav\",sample_rate)\r\n\r\n#Near仮定に基づくステアリングベクトルを計算: steering_vectors(Nk x Ns x M)\r\nnear_steering_vectors=calculate_steering_vector(R,source_locations,freqs,is_use_far=False)\r\n\r\n#短時間フーリエ変換を行う\r\nf,t,stft_data=sp.stft(multi_conv_data,fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\n#雑音だけの区間のフレーム数\r\nn_noise_only_frame=np.sum(t<(n_noise_only/sample_rate))\r\n\r\nxx_H=np.einsum(\"mkt,nkt->ktmn\",stft_data,np.conjugate(stft_data))\r\n\r\n#雑音の倍率\r\nmu=1.0\r\n\r\n#雑音の共分散行列 freq,mic,mic\r\nRn=np.average(xx_H[:,:n_noise_only_frame,...],axis=1)\r\n\r\n#入力共分散行列\r\nRs=np.average(xx_H[:,n_noise_only_frame:,...],axis=1)-Rn\r\n\r\n#固有値分解をして半正定行列に変換\r\nw,v=np.linalg.eigh(Rs)\r\nRs_org=Rs.copy()\r\nw[np.real(w)<0]=0\r\nRs=np.einsum(\"kmi,ki,kni->kmn\",v,w,np.conjugate(v))\r\n\r\n#入力共分散行列\r\nRs_muRn=Rs+Rn*mu\r\ninvRs_muRn=np.linalg.pinv(Rs_muRn)\r\n\r\n#フィルタ生成\r\nW_mwf=np.einsum(\"kmi,kin->kmn\",invRs_muRn,Rs)\r\n\r\n#フィルタをかける\r\nc_hat=np.einsum(\"kim,ikt->mkt\",np.conjugate(W_mwf),stft_data)\r\n\r\n#時間領域の波形に戻す\r\nt,mwf_out=sp.istft(c_hat[0],fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\n#大きさを調整する\r\nmwf_out=mwf_out*np.iinfo(np.int16).max/20.\r\n\r\n#ファイルに書き込む\r\nwrite_file_from_time_signal(mwf_out[n_noise_only:],\"./mwf_out_{}.wav\".format(mu),sample_rate)\r\n"
  },
  {
    "path": "section6/sample_code_c6_13.py",
    "content": "\r\n\r\nimport wave as wave\r\nimport pyroomacoustics as pa\r\nimport numpy as np\r\nimport scipy.signal as sp\r\nimport scipy as scipy\r\n\r\n#ステアリングベクトルを算出\r\n#mic_position: 3 x M  dimensional ndarray [[x,y,z],[x,y,z]]\r\n#source_position: 3x Ns dimensional ndarray [[x,y,z],[x,y,z] ]\r\n#freqs: Nk dimensional array [f1,f2,f3...]\r\n#sound_speed: 音速 [m/s]\r\n#is_use_far: Farを使う場合はTrue, Nearの場合はFalse, \r\n#return: steering vector (Nk x Ns x M)\r\ndef calculate_steering_vector(mic_alignments,source_locations,freqs,sound_speed=340,is_use_far=False):\r\n    #マイク数を取得\r\n    n_channels=np.shape(mic_alignments)[1]\r\n\r\n    #音源数を取得\r\n    n_source=np.shape(source_locations)[1]\r\n\r\n    if is_use_far==True:\r\n        #音源位置を正規化\r\n        norm_source_locations=source_locations/np.linalg.norm(source_locations,2,axis=0,keepdims=True)\r\n\r\n        #位相を求める\r\n        steering_phase=np.einsum('k,ism,ism->ksm',2.j*np.pi/sound_speed*freqs,norm_source_locations[...,None],mic_alignments[:,None,:])\r\n\r\n        #ステアリングベクトルを算出\r\n        steering_vector=1./np.sqrt(n_channels)*np.exp(steering_phase)\r\n\r\n        return(steering_vector)\r\n\r\n    else:\r\n\r\n        #音源とマイクの距離を求める\r\n        #distance: Ns x Nm\r\n        distance=np.sqrt(np.sum(np.square(source_locations[...,None]-mic_alignments[:,None,:]),axis=0))\r\n\r\n        #遅延時間(delay) [sec]\r\n        delay=distance/sound_speed\r\n\r\n        #ステアリングベクトルの位相を求める\r\n        steering_phase=np.einsum('k,sm->ksm',-2.j*np.pi*freqs,delay)\r\n    \r\n        #音量の減衰\r\n        steering_decay_ratio=1./distance\r\n\r\n        #ステアリングベクトルを求める\r\n        steering_vector=steering_decay_ratio[None,...]*np.exp(steering_phase)\r\n\r\n        #大きさを1で正規化する\r\n        steering_vector=steering_vector/np.linalg.norm(steering_vector,2,axis=2,keepdims=True)\r\n\r\n    return(steering_vector)\r\n\r\n#2バイトに変換してファイルに保存\r\n#signal: time-domain 1d array (float)\r\n#file_name: 出力先のファイル名\r\n#sample_rate: サンプリングレート\r\ndef write_file_from_time_signal(signal,file_name,sample_rate):\r\n    #2バイトのデータに変換\r\n    signal=signal.astype(np.int16)\r\n\r\n    #waveファイルに書き込む\r\n    wave_out = wave.open(file_name, 'w')\r\n\r\n    #モノラル:1、ステレオ:2\r\n    wave_out.setnchannels(1)\r\n\r\n    #サンプルサイズ2byte\r\n    wave_out.setsampwidth(2)\r\n\r\n    #サンプリング周波数\r\n    wave_out.setframerate(sample_rate)\r\n\r\n    #データを書き込み\r\n    wave_out.writeframes(signal)\r\n\r\n    #ファイルを閉じる\r\n    wave_out.close()\r\n\r\n#遅延和アレイを実行する\r\n#x:入力信号( M, Nk, Lt)\r\n#a:ステアリングベクトル(Nk, M)\r\n#return y 出力信号(M, Nk, Lt)\r\ndef execute_dsbf(x,a):\r\n    #遅延和アレイを実行する\r\n    s_hat=np.einsum(\"km,mkt->kt\",np.conjugate(a),x)\r\n\r\n    #ステアリングベクトルをかける\r\n    c_hat=np.einsum(\"kt,km->mkt\",s_hat,a)\r\n\r\n    return(c_hat)\r\n\r\n#MVDRを実行する\r\n#x:入力信号( M, Nk, Lt)\r\n#y:共分散行列を計算する信号(M,Nk,Lt)\r\n#a:ステアリングベクトル(Nk, M)\r\n#return y 出力信号(M, Nk, Lt)\r\ndef execute_mvdr(x,y,a):\r\n    \r\n    #共分散行列を計算する\r\n    Rcov=np.einsum(\"mkt,nkt->kmn\",y,np.conjugate(y))\r\n\r\n    #共分散行列の逆行列を計算する\r\n    Rcov_inverse=np.linalg.pinv(Rcov)\r\n\r\n    #フィルタを計算する\r\n    Rcov_inverse_a=np.einsum(\"kmn,kn->km\",Rcov_inverse,a)\r\n    a_H_Rcov_inverse_a=np.einsum(\"kn,kn->k\",np.conjugate(a),Rcov_inverse_a)\r\n    w_mvdr=Rcov_inverse_a/np.maximum(a_H_Rcov_inverse_a,1.e-18)[:,None]\r\n\r\n    #フィルタをかける\r\n    s_hat=np.einsum(\"km,mkt->kt\",np.conjugate(w_mvdr),x)\r\n\r\n    #ステアリングベクトルをかける\r\n    c_hat=np.einsum(\"kt,km->mkt\",s_hat,a)\r\n    \r\n    return(c_hat)\r\n\r\n#MaxSNRを実行する\r\n#x:入力信号( M, Nk, Lt)\r\n#y:共分散行列を計算する信号(M,Nk,Lt)\r\n#return y 出力信号(M, Nk, Lt)\r\ndef execute_max_snr(x,y):\r\n   \r\n    #雑音の共分散行列 freq,mic,mic\r\n    Rn=np.average(np.einsum(\"mkt,nkt->ktmn\",y,np.conjugate(y)),axis=1)\r\n\r\n    #入力共分散行列\r\n    Rs=np.average(np.einsum(\"mkt,nkt->ktmn\",x,np.conjugate(x)),axis=1)\r\n\r\n    #周波数の数を取得\r\n    Nk=np.shape(Rs)[0]\r\n\r\n    #一般化固有値分解\r\n    max_snr_filter=None\r\n    for k in range(Nk):\r\n        w,v=scipy.linalg.eigh(Rs[k,...],Rn[k,...])\r\n        if max_snr_filter is None:\r\n            max_snr_filter=v[None,:,-1]\r\n        else:\r\n            max_snr_filter=np.concatenate((max_snr_filter,v[None,:,-1]),axis=0)\r\n    \r\n\r\n    Rs_w=np.einsum(\"kmn,kn->km\",Rs,max_snr_filter)\r\n    beta=Rs_w/np.einsum(\"km,km->k\",np.conjugate(max_snr_filter),Rs_w)[:,None]\r\n    w_max_snr=beta[:,None,:]*max_snr_filter[...,None]\r\n    \r\n    #フィルタをかける\r\n    c_hat=np.einsum(\"kim,ikt->mkt\",np.conjugate(w_max_snr),x)\r\n    \r\n    return(c_hat)\r\n\r\n#SNRをはかる\r\n#desired: 目的音、Lt\r\n#out:　雑音除去後の信号 Lt\r\ndef calculate_snr(desired,out):\r\n    wave_length=np.minimum(np.shape(desired)[0],np.shape(out)[0])\r\n\r\n    #消し残った雑音\r\n    desired=desired[:wave_length]\r\n    out=out[:wave_length]\r\n    noise=desired-out\r\n    snr=10.*np.log10(np.sum(np.square(desired))/np.sum(np.square(noise)))\r\n\r\n    return(snr)\r\n\r\n#ファイルに書き込む\r\n#MWFを実行する\r\n#x:入力信号( M, Nk, Lt)\r\n#y:共分散行列を計算する信号(M,Nk,Lt)\r\n#mu: 雑音共分散行列の係数\r\n#return y 出力信号(M, Nk, Lt)\r\ndef execute_mwf(x,y,mu):\r\n   \r\n    #雑音の共分散行列 freq,mic,mic\r\n    Rn=np.average(np.einsum(\"mkt,nkt->ktmn\",y,np.conjugate(y)),axis=1)\r\n\r\n    #入力共分散行列\r\n    Rs=np.average(np.einsum(\"mkt,nkt->ktmn\",x,np.conjugate(x)),axis=1)\r\n    \r\n    #固有値分解をして半正定行列に変換\r\n    w,v=np.linalg.eigh(Rs)\r\n    Rs_org=Rs.copy()\r\n    w[np.real(w)<0]=0\r\n    Rs=np.einsum(\"kmi,ki,kni->kmn\",v,w,np.conjugate(v))\r\n\r\n    #入力共分散行列\r\n    Rs_muRn=Rs+Rn*mu\r\n    invRs_muRn=np.linalg.pinv(Rs_muRn)\r\n\r\n    #フィルタ生成\r\n    W_mwf=np.einsum(\"kmi,kin->kmn\",invRs_muRn,Rs)\r\n\r\n    #フィルタをかける\r\n    c_hat=np.einsum(\"kim,ikt->mkt\",np.conjugate(W_mwf),x)\r\n\r\n    return(c_hat)\r\n\r\n#乱数の種を初期化\r\nnp.random.seed(0)\r\n\r\n#畳み込みに用いる音声波形\r\nclean_wave_files=[\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\",\"./CMU_ARCTIC/cmu_us_axb_arctic/wav/arctic_a0002.wav\"]\r\n\r\n#雑音だけの区間のサンプル数を設定\r\nn_noise_only=40000\r\n\r\n#音源数\r\nn_sources=len(clean_wave_files)\r\n\r\n#長さを調べる\r\nn_samples=0\r\n#ファイルを読み込む\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    if n_samples<wav.getnframes():\r\n        n_samples=wav.getnframes()\r\n    wav.close()\r\n\r\nclean_data=np.zeros([n_sources,n_samples+n_noise_only])\r\n\r\n#ファイルを読み込む\r\ns=0\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    data=wav.readframes(wav.getnframes())\r\n    data=np.frombuffer(data, dtype=np.int16)\r\n    data=data/np.iinfo(np.int16).max\r\n    clean_data[s,n_noise_only:n_noise_only+wav.getnframes()]=data\r\n    wav.close()\r\n    s=s+1\r\n\r\n\r\n# シミュレーションのパラメータ\r\n\r\n#シミュレーションで用いる音源数\r\nn_sim_sources=1\r\n\r\n#サンプリング周波数\r\nsample_rate=16000\r\n\r\n#フレームサイズ\r\nN=1024\r\n\r\n#周波数の数\r\nNk=int(N/2+1)\r\n\r\n\r\n#各ビンの周波数\r\nfreqs=np.arange(0,Nk,1)*sample_rate/N\r\n\r\n#音声と雑音との比率 [dB]\r\nSNR=10.\r\n\r\n#部屋の大きさ\r\nroom_dim = np.r_[10.0, 10.0, 10.0]\r\n\r\n#マイクロホンアレイを置く部屋の場所\r\nmic_array_loc = room_dim / 2 + np.random.randn(3) * 0.1 \r\n\r\n#マイクロホンアレイのマイク配置\r\nmic_alignments = np.array(\r\n    [\r\n        [x, 0.0, 0.0] for x in np.arange(-0.01,0.02,0.02)\r\n    ]\r\n)\r\n\r\n#マイクロホン数\r\nn_channels=np.shape(mic_alignments)[0]\r\n\r\n#マイクロホンアレイの座標\r\nR=mic_alignments .T+mic_array_loc[:,None]\r\n\r\n# 部屋を生成する\r\nroom = pa.ShoeBox(room_dim, fs=sample_rate, max_order=17,absorption=0.4)\r\nroom_no_noise = pa.ShoeBox(room_dim, fs=sample_rate, max_order=17,absorption=0.4)\r\n\r\n# 用いるマイクロホンアレイの情報を設定する\r\nroom.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\nroom_no_noise.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\n\r\n#音源の場所\r\ndoas=np.array(\r\n    [[np.pi/2., 0],\r\n     [np.pi/2., np.pi]\r\n    ]    )\r\n\r\n#音源とマイクロホンの距離\r\ndistance=1.\r\nsource_locations=np.zeros((3, doas.shape[0]), dtype=doas.dtype)\r\nsource_locations[0, :] = np.cos(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[1, :] = np.sin(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[2, :] = np.cos(doas[:, 0])\r\nsource_locations *= distance\r\nsource_locations += mic_array_loc[:, None]\r\n\r\n\r\n#各音源をシミュレーションに追加する\r\nfor s in range(n_sim_sources):\r\n    clean_data[s]/= np.std(clean_data[s])\r\n    room.add_source(source_locations[:, s], signal=clean_data[s])\r\n    if s==0:\r\n        room_no_noise.add_source(source_locations[:, s], signal=clean_data[s])\r\n\r\n#シミュレーションを回す\r\nroom.simulate(snr=SNR)\r\nroom_no_noise.simulate(snr=90)\r\n\r\n#畳み込んだ波形を取得する(チャンネル、サンプル）\r\nmulti_conv_data=room.mic_array.signals\r\nmulti_conv_data_no_noise=room_no_noise.mic_array.signals\r\n\r\n\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data_no_noise[0,n_noise_only:]*np.iinfo(np.int16).max/20.,\"./mwf_clean.wav\",sample_rate)\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data[0,n_noise_only:]*np.iinfo(np.int16).max/20.,\"./mwf_in.wav\",sample_rate)\r\n\r\n#Near仮定に基づくステアリングベクトルを計算: steering_vectors(Nk x Ns x M)\r\nnear_steering_vectors=calculate_steering_vector(R,source_locations,freqs,is_use_far=False)\r\n\r\n#短時間フーリエ変換を行う\r\nf,t,stft_data=sp.stft(multi_conv_data,fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\n#雑音だけの区間のフレーム数\r\nn_noise_only_frame=np.sum(t<(n_noise_only/sample_rate))\r\n\r\n#雑音だけのデータ\r\nnoise_data=stft_data[...,:n_noise_only_frame]\r\n\r\n#MWFの雑音の倍率\r\nmu=1.0\r\n\r\n#それぞれのフィルタを実行する\r\ndsbf_out=execute_dsbf(stft_data,near_steering_vectors[:,0,:])\r\nmvdr_out=execute_mvdr(stft_data,stft_data,near_steering_vectors[:,0,:])\r\nmlbf_out=execute_mvdr(stft_data,noise_data,near_steering_vectors[:,0,:])\r\nmax_snr_out=execute_max_snr(stft_data,noise_data)\r\nmwf_out=execute_mwf(stft_data,noise_data,mu)\r\n\r\n#評価するマイクロホン\r\neval_mic_index=0\r\n\r\n#時間領域の波形に戻す\r\nt,dsbf_out=sp.istft(dsbf_out[eval_mic_index],fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,mvdr_out=sp.istft(mvdr_out[eval_mic_index],fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,mlbf_out=sp.istft(mlbf_out[eval_mic_index],fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,max_snr_out=sp.istft(max_snr_out[eval_mic_index],fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,mwf_out=sp.istft(mwf_out[eval_mic_index],fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\n#SNRをはかる\r\nsnr_pre=calculate_snr(multi_conv_data_no_noise[eval_mic_index,n_noise_only:],multi_conv_data[eval_mic_index,n_noise_only:])\r\nsnr_dsbf_post=calculate_snr(multi_conv_data_no_noise[eval_mic_index,n_noise_only:],dsbf_out[n_noise_only:])\r\nsnr_mvdr_post=calculate_snr(multi_conv_data_no_noise[eval_mic_index,n_noise_only:],mvdr_out[n_noise_only:])\r\nsnr_mlbf_post=calculate_snr(multi_conv_data_no_noise[eval_mic_index,n_noise_only:],mlbf_out[n_noise_only:])\r\nsnr_max_snr_post=calculate_snr(multi_conv_data_no_noise[eval_mic_index,n_noise_only:],max_snr_out[n_noise_only:])\r\nsnr_mwf_post=calculate_snr(multi_conv_data_no_noise[eval_mic_index,n_noise_only:],mwf_out[n_noise_only:])\r\n\r\n#ファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data[eval_mic_index,n_noise_only:]*np.iinfo(np.int16).max/20.,\"./mix.wav\",sample_rate)\r\nwrite_file_from_time_signal(multi_conv_data_no_noise[eval_mic_index,n_noise_only:]*np.iinfo(np.int16).max/20.,\"./desired.wav\",sample_rate)\r\nwrite_file_from_time_signal(dsbf_out[n_noise_only:]*np.iinfo(np.int16).max/20.,\"./dsbf_out.wav\",sample_rate)\r\nwrite_file_from_time_signal(mvdr_out[n_noise_only:]*np.iinfo(np.int16).max/20.,\"./mvdr_out.wav\",sample_rate)\r\nwrite_file_from_time_signal(mlbf_out[n_noise_only:]*np.iinfo(np.int16).max/20.,\"./mlbf_out.wav\",sample_rate)\r\nwrite_file_from_time_signal(max_snr_out[n_noise_only:]*np.iinfo(np.int16).max/20.,\"./max_snr_out.wav\",sample_rate)\r\nwrite_file_from_time_signal(mwf_out[n_noise_only:]*np.iinfo(np.int16).max/20.,\"./mwf_out.wav\",sample_rate)\r\n\r\n\r\nprint(\"method:    \", \"DSBF\", \"MVDR\", \"MLBF\", \"MaxSNR\", \"MWF\")\r\n\r\nprint(\"Δsnr [dB]: {:.2f} {:.2f} {:.2f} {:.2f}   {:.2f}\".format(snr_dsbf_post-snr_pre,snr_mvdr_post-snr_pre,snr_mlbf_post-snr_pre,snr_max_snr_post-snr_pre,snr_mwf_post-snr_pre))\r\n"
  },
  {
    "path": "section6/sample_code_c6_14.py",
    "content": "\r\n\r\nimport wave as wave\r\nimport pyroomacoustics as pa\r\nimport numpy as np\r\nimport scipy.signal as sp\r\nimport scipy as scipy\r\n\r\n#ステアリングベクトルを算出\r\n#mic_position: 3 x M  dimensional ndarray [[x,y,z],[x,y,z]]\r\n#source_position: 3x Ns dimensional ndarray [[x,y,z],[x,y,z] ]\r\n#freqs: Nk dimensional array [f1,f2,f3...]\r\n#sound_speed: 音速 [m/s]\r\n#is_use_far: Farを使う場合はTrue, Nearの場合はFalse, \r\n#return: steering vector (Nk x Ns x M)\r\ndef calculate_steering_vector(mic_alignments,source_locations,freqs,sound_speed=340,is_use_far=False):\r\n    #マイク数を取得\r\n    n_channels=np.shape(mic_alignments)[1]\r\n\r\n    #音源数を取得\r\n    n_source=np.shape(source_locations)[1]\r\n\r\n    if is_use_far==True:\r\n        #音源位置を正規化\r\n        norm_source_locations=source_locations/np.linalg.norm(source_locations,2,axis=0,keepdims=True)\r\n\r\n        #位相を求める\r\n        steering_phase=np.einsum('k,ism,ism->ksm',2.j*np.pi/sound_speed*freqs,norm_source_locations[...,None],mic_alignments[:,None,:])\r\n\r\n        #ステアリングベクトルを算出\r\n        steering_vector=1./np.sqrt(n_channels)*np.exp(steering_phase)\r\n\r\n        return(steering_vector)\r\n\r\n    else:\r\n\r\n        #音源とマイクの距離を求める\r\n        #distance: Ns x Nm\r\n        distance=np.sqrt(np.sum(np.square(source_locations[...,None]-mic_alignments[:,None,:]),axis=0))\r\n\r\n        #遅延時間(delay) [sec]\r\n        delay=distance/sound_speed\r\n\r\n        #ステアリングベクトルの位相を求める\r\n        steering_phase=np.einsum('k,sm->ksm',-2.j*np.pi*freqs,delay)\r\n    \r\n        #音量の減衰\r\n        steering_decay_ratio=1./distance\r\n\r\n        #ステアリングベクトルを求める\r\n        steering_vector=steering_decay_ratio[None,...]*np.exp(steering_phase)\r\n\r\n        #大きさを1で正規化する\r\n        steering_vector=steering_vector/np.linalg.norm(steering_vector,2,axis=2,keepdims=True)\r\n\r\n    return(steering_vector)\r\n\r\n#2バイトに変換してファイルに保存\r\n#signal: time-domain 1d array (float)\r\n#file_name: 出力先のファイル名\r\n#sample_rate: サンプリングレート\r\ndef write_file_from_time_signal(signal,file_name,sample_rate):\r\n    #2バイトのデータに変換\r\n    signal=signal.astype(np.int16)\r\n\r\n    #waveファイルに書き込む\r\n    wave_out = wave.open(file_name, 'w')\r\n\r\n    #モノラル:1、ステレオ:2\r\n    wave_out.setnchannels(1)\r\n\r\n    #サンプルサイズ2byte\r\n    wave_out.setsampwidth(2)\r\n\r\n    #サンプリング周波数\r\n    wave_out.setframerate(sample_rate)\r\n\r\n    #データを書き込み\r\n    wave_out.writeframes(signal)\r\n\r\n    #ファイルを閉じる\r\n    wave_out.close()\r\n\r\n#遅延和アレイを実行する\r\n#x:入力信号( M, Nk, Lt)\r\n#a:ステアリングベクトル(Nk, M)\r\n#return y 出力信号(M, Nk, Lt)\r\ndef execute_dsbf(x,a):\r\n    #遅延和アレイを実行する\r\n    s_hat=np.einsum(\"km,mkt->kt\",np.conjugate(a),x)\r\n\r\n    #ステアリングベクトルをかける\r\n    c_hat=np.einsum(\"kt,km->mkt\",s_hat,a)\r\n\r\n    return(c_hat)\r\n\r\n#MVDRを実行する\r\n#x:入力信号( M, Nk, Lt)\r\n#y:共分散行列を計算する信号(M,Nk,Lt)\r\n#a:ステアリングベクトル(Nk, M)\r\n#return y 出力信号(M, Nk, Lt)\r\ndef execute_mvdr(x,y,a):\r\n    \r\n    #共分散行列を計算する\r\n    Rcov=np.einsum(\"mkt,nkt->kmn\",y,np.conjugate(y))\r\n\r\n    #共分散行列の逆行列を計算する\r\n    Rcov_inverse=np.linalg.pinv(Rcov)\r\n\r\n    #フィルタを計算する\r\n    Rcov_inverse_a=np.einsum(\"kmn,kn->km\",Rcov_inverse,a)\r\n    a_H_Rcov_inverse_a=np.einsum(\"kn,kn->k\",np.conjugate(a),Rcov_inverse_a)\r\n    w_mvdr=Rcov_inverse_a/np.maximum(a_H_Rcov_inverse_a,1.e-18)[:,None]\r\n\r\n    #フィルタをかける\r\n    s_hat=np.einsum(\"km,mkt->kt\",np.conjugate(w_mvdr),x)\r\n\r\n    #ステアリングベクトルをかける\r\n    c_hat=np.einsum(\"kt,km->mkt\",s_hat,a)\r\n    \r\n    return(c_hat)\r\n\r\n#MaxSNRを実行する\r\n#x:入力信号( M, Nk, Lt)\r\n#y:共分散行列を計算する信号(M,Nk,Lt)\r\n#return y 出力信号(M, Nk, Lt)\r\ndef execute_max_snr(x,y):\r\n   \r\n    #雑音の共分散行列 freq,mic,mic\r\n    Rn=np.average(np.einsum(\"mkt,nkt->ktmn\",y,np.conjugate(y)),axis=1)\r\n\r\n    #入力共分散行列\r\n    Rs=np.average(np.einsum(\"mkt,nkt->ktmn\",x,np.conjugate(x)),axis=1)\r\n\r\n    #周波数の数を取得\r\n    Nk=np.shape(Rs)[0]\r\n\r\n    #一般化固有値分解\r\n    max_snr_filter=None\r\n    for k in range(Nk):\r\n        w,v=scipy.linalg.eigh(Rs[k,...],Rn[k,...])\r\n        if max_snr_filter is None:\r\n            max_snr_filter=v[None,:,-1]\r\n        else:\r\n            max_snr_filter=np.concatenate((max_snr_filter,v[None,:,-1]),axis=0)\r\n    \r\n\r\n    Rs_w=np.einsum(\"kmn,kn->km\",Rs,max_snr_filter)\r\n    beta=Rs_w/np.einsum(\"km,km->k\",np.conjugate(max_snr_filter),Rs_w)[:,None]\r\n    w_max_snr=beta[:,None,:]*max_snr_filter[...,None]\r\n    \r\n    #フィルタをかける\r\n    c_hat=np.einsum(\"kim,ikt->mkt\",np.conjugate(w_max_snr),x)\r\n    \r\n    return(c_hat)\r\n\r\n#SNRをはかる\r\n#desired: 目的音、Lt\r\n#out:　雑音除去後の信号 Lt\r\ndef calculate_snr(desired,out):\r\n    wave_length=np.minimum(np.shape(desired)[0],np.shape(out)[0])\r\n\r\n    #消し残った雑音\r\n    desired=desired[:wave_length]\r\n    out=out[:wave_length]\r\n    noise=desired-out\r\n    snr=10.*np.log10(np.sum(np.square(desired))/np.sum(np.square(noise)))\r\n\r\n    return(snr)\r\n\r\n#ファイルに書き込む\r\n#MWFを実行する\r\n#x:入力信号( M, Nk, Lt)\r\n#y:共分散行列を計算する信号(M,Nk,Lt)\r\n#mu: 雑音共分散行列の係数\r\n#return y 出力信号(M, Nk, Lt)\r\ndef execute_mwf(x,y,mu):\r\n   \r\n    #雑音の共分散行列 freq,mic,mic\r\n    Rn=np.average(np.einsum(\"mkt,nkt->ktmn\",y,np.conjugate(y)),axis=1)\r\n\r\n    #入力共分散行列\r\n    Rs=np.average(np.einsum(\"mkt,nkt->ktmn\",x,np.conjugate(x)),axis=1)\r\n    \r\n    #固有値分解をして半正定行列に変換\r\n    w,v=np.linalg.eigh(Rs)\r\n    Rs_org=Rs.copy()\r\n    w[np.real(w)<0]=0\r\n    Rs=np.einsum(\"kmi,ki,kni->kmn\",v,w,np.conjugate(v))\r\n\r\n    #入力共分散行列\r\n    Rs_muRn=Rs+Rn*mu\r\n    invRs_muRn=np.linalg.pinv(Rs_muRn)\r\n\r\n    #フィルタ生成\r\n    W_mwf=np.einsum(\"kmi,kin->kmn\",invRs_muRn,Rs)\r\n\r\n    #フィルタをかける\r\n    c_hat=np.einsum(\"kim,ikt->mkt\",np.conjugate(W_mwf),x)\r\n\r\n    return(c_hat)\r\n\r\n#乱数の種を初期化\r\nnp.random.seed(0)\r\n\r\n#畳み込みに用いる音声波形\r\nclean_wave_files=[\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\",\"./CMU_ARCTIC/cmu_us_axb_arctic/wav/arctic_a0002.wav\"]\r\n\r\n#雑音だけの区間のサンプル数を設定\r\nn_noise_only=40000\r\n\r\n#音源数\r\nn_sources=len(clean_wave_files)\r\n\r\n#長さを調べる\r\nn_samples=0\r\n#ファイルを読み込む\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    if n_samples<wav.getnframes():\r\n        n_samples=wav.getnframes()\r\n    wav.close()\r\n\r\nclean_data=np.zeros([n_sources,n_samples+n_noise_only])\r\n\r\n#ファイルを読み込む\r\ns=0\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    data=wav.readframes(wav.getnframes())\r\n    data=np.frombuffer(data, dtype=np.int16)\r\n    data=data/np.iinfo(np.int16).max\r\n    clean_data[s,n_noise_only:n_noise_only+wav.getnframes()]=data\r\n    wav.close()\r\n    s=s+1\r\n\r\n\r\n# シミュレーションのパラメータ\r\n\r\n#シミュレーションで用いる音源数\r\nn_sim_sources=2\r\n\r\n#サンプリング周波数\r\nsample_rate=16000\r\n\r\n#フレームサイズ\r\nN=1024\r\n\r\n#周波数の数\r\nNk=int(N/2+1)\r\n\r\n\r\n#各ビンの周波数\r\nfreqs=np.arange(0,Nk,1)*sample_rate/N\r\n\r\n#音声と雑音との比率 [dB]\r\nSNR=10.\r\n\r\n#部屋の大きさ\r\nroom_dim = np.r_[10.0, 10.0, 10.0]\r\n\r\n#マイクロホンアレイを置く部屋の場所\r\nmic_array_loc = room_dim / 2 + np.random.randn(3) * 0.1 \r\n\r\n#マイクロホンアレイのマイク配置\r\nmic_alignments = np.array(\r\n    [\r\n        [x, 0.0, 0.0] for x in np.arange(-0.01,0.02,0.02)\r\n    ]\r\n)\r\n\r\n#マイクロホン数\r\nn_channels=np.shape(mic_alignments)[0]\r\n\r\n#マイクロホンアレイの座標\r\nR=mic_alignments .T+mic_array_loc[:,None]\r\n\r\n# 部屋を生成する\r\nroom = pa.ShoeBox(room_dim, fs=sample_rate, max_order=17,absorption=0.4)\r\nroom_no_noise = pa.ShoeBox(room_dim, fs=sample_rate, max_order=17,absorption=0.4)\r\n\r\n# 用いるマイクロホンアレイの情報を設定する\r\nroom.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\nroom_no_noise.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\n\r\n#音源の場所\r\ndoas=np.array(\r\n    [[np.pi/2., 0],\r\n     [np.pi/2., np.pi]\r\n    ]    )\r\n\r\n#音源とマイクロホンの距離\r\ndistance=1.\r\nsource_locations=np.zeros((3, doas.shape[0]), dtype=doas.dtype)\r\nsource_locations[0, :] = np.cos(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[1, :] = np.sin(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[2, :] = np.cos(doas[:, 0])\r\nsource_locations *= distance\r\nsource_locations += mic_array_loc[:, None]\r\n\r\n\r\n#各音源をシミュレーションに追加する\r\nfor s in range(n_sim_sources):\r\n    clean_data[s]/= np.std(clean_data[s])\r\n    room.add_source(source_locations[:, s], signal=clean_data[s])\r\n    if s==0:\r\n        room_no_noise.add_source(source_locations[:, s], signal=clean_data[s])\r\n\r\n#シミュレーションを回す\r\nroom.simulate(snr=SNR)\r\nroom_no_noise.simulate(snr=90)\r\n\r\n#畳み込んだ波形を取得する(チャンネル、サンプル）\r\nmulti_conv_data=room.mic_array.signals\r\nmulti_conv_data_no_noise=room_no_noise.mic_array.signals\r\n\r\n\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data_no_noise[0,n_noise_only:]*np.iinfo(np.int16).max/20.,\"./mwf_clean.wav\",sample_rate)\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data[0,n_noise_only:]*np.iinfo(np.int16).max/20.,\"./mwf_in.wav\",sample_rate)\r\n\r\n#Near仮定に基づくステアリングベクトルを計算: steering_vectors(Nk x Ns x M)\r\nnear_steering_vectors=calculate_steering_vector(R,source_locations,freqs,is_use_far=False)\r\n\r\n#短時間フーリエ変換を行う\r\nf,t,stft_data=sp.stft(multi_conv_data,fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\n#雑音だけの区間のフレーム数\r\nn_noise_only_frame=np.sum(t<(n_noise_only/sample_rate))\r\n\r\n#雑音だけのデータ\r\nnoise_data=stft_data[...,:n_noise_only_frame]\r\n\r\n#MWFの雑音の倍率\r\nmu=1.0\r\n\r\n#それぞれのフィルタを実行する\r\ndsbf_out=execute_dsbf(stft_data,near_steering_vectors[:,0,:])\r\nmvdr_out=execute_mvdr(stft_data,stft_data,near_steering_vectors[:,0,:])\r\nmlbf_out=execute_mvdr(stft_data,noise_data,near_steering_vectors[:,0,:])\r\nmax_snr_out=execute_max_snr(stft_data,noise_data)\r\nmwf_out=execute_mwf(stft_data,noise_data,mu)\r\n\r\n#評価するマイクロホン\r\neval_mic_index=0\r\n\r\n#時間領域の波形に戻す\r\nt,dsbf_out=sp.istft(dsbf_out[eval_mic_index],fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,mvdr_out=sp.istft(mvdr_out[eval_mic_index],fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,mlbf_out=sp.istft(mlbf_out[eval_mic_index],fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,max_snr_out=sp.istft(max_snr_out[eval_mic_index],fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,mwf_out=sp.istft(mwf_out[eval_mic_index],fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\n#SNRをはかる\r\nsnr_pre=calculate_snr(multi_conv_data_no_noise[eval_mic_index,n_noise_only:],multi_conv_data[eval_mic_index,n_noise_only:])\r\nsnr_dsbf_post=calculate_snr(multi_conv_data_no_noise[eval_mic_index,n_noise_only:],dsbf_out[n_noise_only:])\r\nsnr_mvdr_post=calculate_snr(multi_conv_data_no_noise[eval_mic_index,n_noise_only:],mvdr_out[n_noise_only:])\r\nsnr_mlbf_post=calculate_snr(multi_conv_data_no_noise[eval_mic_index,n_noise_only:],mlbf_out[n_noise_only:])\r\nsnr_max_snr_post=calculate_snr(multi_conv_data_no_noise[eval_mic_index,n_noise_only:],max_snr_out[n_noise_only:])\r\nsnr_mwf_post=calculate_snr(multi_conv_data_no_noise[eval_mic_index,n_noise_only:],mwf_out[n_noise_only:])\r\n\r\n#ファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data[eval_mic_index,n_noise_only:]*np.iinfo(np.int16).max/20.,\"./mix.wav\",sample_rate)\r\nwrite_file_from_time_signal(multi_conv_data_no_noise[eval_mic_index,n_noise_only:]*np.iinfo(np.int16).max/20.,\"./desired.wav\",sample_rate)\r\nwrite_file_from_time_signal(dsbf_out[n_noise_only:]*np.iinfo(np.int16).max/20.,\"./dsbf_out.wav\",sample_rate)\r\nwrite_file_from_time_signal(mvdr_out[n_noise_only:]*np.iinfo(np.int16).max/20.,\"./mvdr_out.wav\",sample_rate)\r\nwrite_file_from_time_signal(mlbf_out[n_noise_only:]*np.iinfo(np.int16).max/20.,\"./mlbf_out.wav\",sample_rate)\r\nwrite_file_from_time_signal(max_snr_out[n_noise_only:]*np.iinfo(np.int16).max/20.,\"./max_snr_out.wav\",sample_rate)\r\nwrite_file_from_time_signal(mwf_out[n_noise_only:]*np.iinfo(np.int16).max/20.,\"./mwf_out.wav\",sample_rate)\r\n\r\n\r\nprint(\"method:    \", \"DSBF\", \"MVDR\", \"MLBF\", \"MaxSNR\", \"MWF\")\r\n\r\nprint(\"Δsnr [dB]: {:.2f} {:.2f} {:.2f} {:.2f}   {:.2f}\".format(snr_dsbf_post-snr_pre,snr_mvdr_post-snr_pre,snr_mlbf_post-snr_pre,snr_max_snr_post-snr_pre,snr_mwf_post-snr_pre))\r\n"
  },
  {
    "path": "section6/sample_code_c6_2.py",
    "content": "\r\n\r\nimport wave as wave\r\nimport pyroomacoustics as pa\r\nimport numpy as np\r\nimport scipy.signal as sp\r\n\r\n#ステアリングベクトルを算出\r\n#mic_position: 3 x M  dimensional ndarray [[x,y,z],[x,y,z]]\r\n#source_position: 3x Ns dimensional ndarray [[x,y,z],[x,y,z] ]\r\n#freqs: Nk dimensional array [f1,f2,f3...]\r\n#sound_speed: 音速 [m/s]\r\n#is_use_far: Farを使う場合はTrue, Nearの場合はFalse, \r\n#return: steering vector (Nk x Ns x M)\r\ndef calculate_steering_vector(mic_alignments,source_locations,freqs,sound_speed=340,is_use_far=False):\r\n    #マイク数を取得\r\n    n_channels=np.shape(mic_alignments)[1]\r\n\r\n    #音源数を取得\r\n    n_source=np.shape(source_locations)[1]\r\n\r\n    if is_use_far==True:\r\n        #音源位置を正規化\r\n        norm_source_locations=source_locations/np.linalg.norm(source_locations,2,axis=0,keepdims=True)\r\n\r\n        #位相を求める\r\n        steering_phase=np.einsum('k,ism,ism->ksm',2.j*np.pi/sound_speed*freqs,norm_source_locations[...,None],mic_alignments[:,None,:])\r\n\r\n        #ステアリングベクトルを算出\r\n        steering_vector=1./np.sqrt(n_channels)*np.exp(steering_phase)\r\n\r\n        return(steering_vector)\r\n\r\n    else:\r\n\r\n        #音源とマイクの距離を求める\r\n        #distance: Ns x Nm\r\n        distance=np.sqrt(np.sum(np.square(source_locations[...,None]-mic_alignments[:,None,:]),axis=0))\r\n\r\n        #遅延時間(delay) [sec]\r\n        delay=distance/sound_speed\r\n\r\n        #ステアリングベクトルの位相を求める\r\n        steering_phase=np.einsum('k,sm->ksm',-2.j*np.pi*freqs,delay)\r\n    \r\n        #音量の減衰\r\n        steering_decay_ratio=1./distance\r\n\r\n        #ステアリングベクトルを求める\r\n        steering_vector=steering_decay_ratio[None,...]*np.exp(steering_phase)\r\n\r\n        #大きさを1で正規化する\r\n        steering_vector=steering_vector/np.linalg.norm(steering_vector,2,axis=2,keepdims=True)\r\n\r\n    return(steering_vector)\r\n\r\n#2バイトに変換してファイルに保存\r\n#signal: time-domain 1d array (float)\r\n#file_name: 出力先のファイル名\r\n#sample_rate: サンプリングレート\r\ndef write_file_from_time_signal(signal,file_name,sample_rate):\r\n    #2バイトのデータに変換\r\n    signal=signal.astype(np.int16)\r\n\r\n    #waveファイルに書き込む\r\n    wave_out = wave.open(file_name, 'w')\r\n\r\n    #モノラル:1、ステレオ:2\r\n    wave_out.setnchannels(1)\r\n\r\n    #サンプルサイズ2byte\r\n    wave_out.setsampwidth(2)\r\n\r\n    #サンプリング周波数\r\n    wave_out.setframerate(sample_rate)\r\n\r\n    #データを書き込み\r\n    wave_out.writeframes(signal)\r\n\r\n    #ファイルを閉じる\r\n    wave_out.close()\r\n\r\n#乱数の種を初期化\r\nnp.random.seed(0)\r\n\r\n#畳み込みに用いる音声波形\r\nclean_wave_files=[\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\"]\r\n\r\n#音源数\r\nn_sources=len(clean_wave_files)\r\n\r\n#長さを調べる\r\nn_samples=0\r\n#ファイルを読み込む\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    if n_samples<wav.getnframes():\r\n        n_samples=wav.getnframes()\r\n    wav.close()\r\n\r\nclean_data=np.zeros([n_sources,n_samples])\r\n\r\n#ファイルを読み込む\r\ns=0\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    data=wav.readframes(wav.getnframes())\r\n    data=np.frombuffer(data, dtype=np.int16)\r\n    data=data/np.iinfo(np.int16).max\r\n    clean_data[s,:wav.getnframes()]=data\r\n    wav.close()\r\n    s=s+1\r\n# シミュレーションのパラメータ\r\n\r\n#サンプリング周波数\r\nsample_rate=16000\r\n\r\n#フレームサイズ\r\nN=1024\r\n\r\n#周波数の数\r\nNk=N/2+1\r\n\r\n#各ビンの周波数\r\nfreqs=np.arange(0,Nk,1)*sample_rate/N\r\n\r\n#音声と雑音との比率 [dB]\r\nSNR=20.\r\n\r\n#部屋の大きさ\r\nroom_dim = np.r_[10.0, 10.0, 10.0]\r\n\r\n#マイクロホンアレイを置く部屋の場所\r\nmic_array_loc = room_dim / 2 + np.random.randn(3) * 0.1 \r\n\r\n#マイクロホンアレイのマイク配置\r\nmic_alignments = np.array(\r\n    [\r\n        [-0.01, 0.0, 0.0],\r\n        [0.01, 0.0, 0.0],\r\n    ]\r\n)\r\n\r\n#マイクロホン数\r\nn_channels=np.shape(mic_alignments)[0]\r\n\r\n#マイクロホンアレイの座標\r\nR=mic_alignments .T+mic_array_loc[:,None]\r\n\r\n# 部屋を生成する\r\nroom = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\n\r\n# 用いるマイクロホンアレイの情報を設定する\r\nroom.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\n\r\n#音源の場所\r\ndoas=np.array(\r\n    [[np.pi/2., 0]\r\n    ]    )\r\n\r\n#音源とマイクロホンの距離\r\ndistance=1.\r\nsource_locations=np.zeros((3, doas.shape[0]), dtype=doas.dtype)\r\nsource_locations[0, :] = np.cos(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[1, :] = np.sin(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[2, :] = np.cos(doas[:, 0])\r\nsource_locations *= distance\r\nsource_locations += mic_array_loc[:, None]\r\n\r\n#各音源をシミュレーションに追加する\r\nfor s in range(n_sources):\r\n    clean_data[s]/= np.std(clean_data[s])\r\n    room.add_source(source_locations[:, s], signal=clean_data[s])\r\n\r\n#シミュレーションを回す\r\nroom.simulate(snr=SNR)\r\n\r\n#畳み込んだ波形を取得する(チャンネル、サンプル）\r\nmulti_conv_data=room.mic_array.signals\r\n\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data[0]*np.iinfo(np.int16).max/20.,\"./mix_in.wav\",sample_rate)\r\n\r\n#Near仮定に基づくステアリングベクトルを計算: steering_vectors(Nk x Ns x M)\r\nnear_steering_vectors=calculate_steering_vector(R,source_locations,freqs,is_use_far=False)\r\n\r\n#短時間フーリエ変換を行う\r\nf,t,stft_data=sp.stft(multi_conv_data,fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\n#遅延和アレイを実行する\r\ns_hat=np.einsum(\"ksm,mkt->skt\",np.conjugate(near_steering_vectors),stft_data)\r\n\r\n#ステアリングベクトルをかける\r\nc_hat=np.einsum(\"skt,ksm->mskt\",s_hat,near_steering_vectors)\r\n\r\n#時間領域の波形に戻す\r\nt,ds_out=sp.istft(c_hat[0],fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\n#大きさを調整する\r\nds_out=ds_out*np.iinfo(np.int16).max/20.\r\n\r\n#ファイルに書き込む\r\nwrite_file_from_time_signal(ds_out,\"./ds_out.wav\",sample_rate)\r\n\r\n\r\n"
  },
  {
    "path": "section6/sample_code_c6_3.py",
    "content": "\r\n\r\nimport wave as wave\r\nimport pyroomacoustics as pa\r\nimport numpy as np\r\nimport scipy.signal as sp\r\n\r\n#ステアリングベクトルを算出\r\n#mic_position: 3 x M  dimensional ndarray [[x,y,z],[x,y,z]]\r\n#source_position: 3x Ns dimensional ndarray [[x,y,z],[x,y,z] ]\r\n#freqs: Nk dimensional array [f1,f2,f3...]\r\n#sound_speed: 音速 [m/s]\r\n#is_use_far: Farを使う場合はTrue, Nearの場合はFalse, \r\n#return: steering vector (Nk x Ns x M)\r\ndef calculate_steering_vector(mic_alignments,source_locations,freqs,sound_speed=340,is_use_far=False):\r\n    #マイク数を取得\r\n    n_channels=np.shape(mic_alignments)[1]\r\n\r\n    #音源数を取得\r\n    n_source=np.shape(source_locations)[1]\r\n\r\n    if is_use_far==True:\r\n        #音源位置を正規化\r\n        norm_source_locations=source_locations/np.linalg.norm(source_locations,2,axis=0,keepdims=True)\r\n\r\n        #位相を求める\r\n        steering_phase=np.einsum('k,ism,ism->ksm',2.j*np.pi/sound_speed*freqs,norm_source_locations[...,None],mic_alignments[:,None,:])\r\n\r\n        #ステアリングベクトルを算出\r\n        steering_vector=1./np.sqrt(n_channels)*np.exp(steering_phase)\r\n\r\n        return(steering_vector)\r\n\r\n    else:\r\n\r\n        #音源とマイクの距離を求める\r\n        #distance: Ns x Nm\r\n        distance=np.sqrt(np.sum(np.square(source_locations[...,None]-mic_alignments[:,None,:]),axis=0))\r\n\r\n        #遅延時間(delay) [sec]\r\n        delay=distance/sound_speed\r\n\r\n        #ステアリングベクトルの位相を求める\r\n        steering_phase=np.einsum('k,sm->ksm',-2.j*np.pi*freqs,delay)\r\n    \r\n        #音量の減衰\r\n        steering_decay_ratio=1./distance\r\n\r\n        #ステアリングベクトルを求める\r\n        steering_vector=steering_decay_ratio[None,...]*np.exp(steering_phase)\r\n\r\n        #大きさを1で正規化する\r\n        steering_vector=steering_vector/np.linalg.norm(steering_vector,2,axis=2,keepdims=True)\r\n\r\n    return(steering_vector)\r\n\r\n#2バイトに変換してファイルに保存\r\n#signal: time-domain 1d array (float)\r\n#file_name: 出力先のファイル名\r\n#sample_rate: サンプリングレート\r\ndef write_file_from_time_signal(signal,file_name,sample_rate):\r\n    #2バイトのデータに変換\r\n    signal=signal.astype(np.int16)\r\n\r\n    #waveファイルに書き込む\r\n    wave_out = wave.open(file_name, 'w')\r\n\r\n    #モノラル:1、ステレオ:2\r\n    wave_out.setnchannels(1)\r\n\r\n    #サンプルサイズ2byte\r\n    wave_out.setsampwidth(2)\r\n\r\n    #サンプリング周波数\r\n    wave_out.setframerate(sample_rate)\r\n\r\n    #データを書き込み\r\n    wave_out.writeframes(signal)\r\n\r\n    #ファイルを閉じる\r\n    wave_out.close()\r\n\r\n#乱数の種を初期化\r\nnp.random.seed(0)\r\n\r\n#畳み込みに用いる音声波形\r\nclean_wave_files=[\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\"]\r\n\r\n#音源数\r\nn_sources=len(clean_wave_files)\r\n\r\n#長さを調べる\r\nn_samples=0\r\n#ファイルを読み込む\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    if n_samples<wav.getnframes():\r\n        n_samples=wav.getnframes()\r\n    wav.close()\r\n\r\nclean_data=np.zeros([n_sources,n_samples])\r\n\r\n#ファイルを読み込む\r\ns=0\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    data=wav.readframes(wav.getnframes())\r\n    data=np.frombuffer(data, dtype=np.int16)\r\n    data=data/np.iinfo(np.int16).max\r\n    clean_data[s,:wav.getnframes()]=data\r\n    wav.close()\r\n    s=s+1\r\n# シミュレーションのパラメータ\r\n\r\n#サンプリング周波数\r\nsample_rate=16000\r\n\r\n#フレームサイズ\r\nN=1024\r\n\r\n#周波数の数\r\nNk=N/2+1\r\n\r\n#各ビンの周波数\r\nfreqs=np.arange(0,Nk,1)*sample_rate/N\r\n\r\n#音声と雑音との比率 [dB]\r\nSNR=20.\r\n\r\n#部屋の大きさ\r\nroom_dim = np.r_[10.0, 10.0, 10.0]\r\n\r\n#マイクロホンアレイを置く部屋の場所\r\nmic_array_loc = room_dim / 2 + np.random.randn(3) * 0.1 \r\n\r\n#マイクロホンアレイのマイク配置\r\nmic_alignments = np.array(\r\n    \r\n        [[x,0.0,0.0] for x in np.arange(-0.31,0.32,0.02)]\r\n    \r\n)\r\n\r\n#マイクロホン数\r\nn_channels=np.shape(mic_alignments)[0]\r\n\r\n#マイクロホンアレイの座標\r\nR=mic_alignments .T+mic_array_loc[:,None]\r\n\r\n# 部屋を生成する\r\nroom = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\n\r\n# 用いるマイクロホンアレイの情報を設定する\r\nroom.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\n\r\n#音源の場所\r\ndoas=np.array(\r\n    [[np.pi/2., 0]\r\n    ]    )\r\n\r\n#音源とマイクロホンの距離\r\ndistance=1.\r\nsource_locations=np.zeros((3, doas.shape[0]), dtype=doas.dtype)\r\nsource_locations[0, :] = np.cos(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[1, :] = np.sin(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[2, :] = np.cos(doas[:, 0])\r\nsource_locations *= distance\r\nsource_locations += mic_array_loc[:, None]\r\n\r\n#各音源をシミュレーションに追加する\r\nfor s in range(n_sources):\r\n    clean_data[s]/= np.std(clean_data[s])\r\n    room.add_source(source_locations[:, s], signal=clean_data[s])\r\n\r\n#シミュレーションを回す\r\nroom.simulate(snr=SNR)\r\n\r\n#畳み込んだ波形を取得する(チャンネル、サンプル）\r\nmulti_conv_data=room.mic_array.signals\r\n\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data[0]*np.iinfo(np.int16).max/20.,\"./ds_in_m32.wav\",sample_rate)\r\n\r\n#Near仮定に基づくステアリングベクトルを計算: steering_vectors(Nk x Ns x M)\r\nnear_steering_vectors=calculate_steering_vector(R,source_locations,freqs,is_use_far=False)\r\n\r\n#短時間フーリエ変換を行う\r\nf,t,stft_data=sp.stft(multi_conv_data,fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\n#遅延和アレイを実行する\r\ns_hat=np.einsum(\"ksm,mkt->skt\",np.conjugate(near_steering_vectors),stft_data)\r\n\r\n#ステアリングベクトルをかける\r\nc_hat=np.einsum(\"skt,ksm->mskt\",s_hat,near_steering_vectors)\r\n\r\n#時間領域の波形に戻す\r\nt,ds_out=sp.istft(c_hat[0],fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\n#大きさを調整する\r\nds_out=ds_out*np.iinfo(np.int16).max/20.\r\n\r\n#ファイルに書き込む\r\nwrite_file_from_time_signal(ds_out,\"./ds_out_m32.wav\",sample_rate)\r\n\r\n\r\n"
  },
  {
    "path": "section6/sample_code_c6_4.py",
    "content": "\r\n\r\nimport wave as wave\r\nimport pyroomacoustics as pa\r\nimport numpy as np\r\nimport scipy.signal as sp\r\n\r\n#ステアリングベクトルを算出\r\n#mic_position: 3 x M  dimensional ndarray [[x,y,z],[x,y,z]]\r\n#source_position: 3x Ns dimensional ndarray [[x,y,z],[x,y,z] ]\r\n#freqs: Nk dimensional array [f1,f2,f3...]\r\n#sound_speed: 音速 [m/s]\r\n#is_use_far: Farを使う場合はTrue, Nearの場合はFalse, \r\n#return: steering vector (Nk x Ns x M)\r\ndef calculate_steering_vector(mic_alignments,source_locations,freqs,sound_speed=340,is_use_far=False):\r\n    #マイク数を取得\r\n    n_channels=np.shape(mic_alignments)[1]\r\n\r\n    #音源数を取得\r\n    n_source=np.shape(source_locations)[1]\r\n\r\n    if is_use_far==True:\r\n        #音源位置を正規化\r\n        norm_source_locations=source_locations/np.linalg.norm(source_locations,2,axis=0,keepdims=True)\r\n\r\n        #位相を求める\r\n        steering_phase=np.einsum('k,ism,ism->ksm',2.j*np.pi/sound_speed*freqs,norm_source_locations[...,None],mic_alignments[:,None,:])\r\n\r\n        #ステアリングベクトルを算出\r\n        steering_vector=1./np.sqrt(n_channels)*np.exp(steering_phase)\r\n\r\n        return(steering_vector)\r\n\r\n    else:\r\n\r\n        #音源とマイクの距離を求める\r\n        #distance: Ns x Nm\r\n        distance=np.sqrt(np.sum(np.square(source_locations[...,None]-mic_alignments[:,None,:]),axis=0))\r\n\r\n        #遅延時間(delay) [sec]\r\n        delay=distance/sound_speed\r\n\r\n        #ステアリングベクトルの位相を求める\r\n        steering_phase=np.einsum('k,sm->ksm',-2.j*np.pi*freqs,delay)\r\n    \r\n        #音量の減衰\r\n        steering_decay_ratio=1./distance\r\n\r\n        #ステアリングベクトルを求める\r\n        steering_vector=steering_decay_ratio[None,...]*np.exp(steering_phase)\r\n\r\n        #大きさを1で正規化する\r\n        steering_vector=steering_vector/np.linalg.norm(steering_vector,2,axis=2,keepdims=True)\r\n\r\n    return(steering_vector)\r\n\r\n#2バイトに変換してファイルに保存\r\n#signal: time-domain 1d array (float)\r\n#file_name: 出力先のファイル名\r\n#sample_rate: サンプリングレート\r\ndef write_file_from_time_signal(signal,file_name,sample_rate):\r\n    #2バイトのデータに変換\r\n    signal=signal.astype(np.int16)\r\n\r\n    #waveファイルに書き込む\r\n    wave_out = wave.open(file_name, 'w')\r\n\r\n    #モノラル:1、ステレオ:2\r\n    wave_out.setnchannels(1)\r\n\r\n    #サンプルサイズ2byte\r\n    wave_out.setsampwidth(2)\r\n\r\n    #サンプリング周波数\r\n    wave_out.setframerate(sample_rate)\r\n\r\n    #データを書き込み\r\n    wave_out.writeframes(signal)\r\n\r\n    #ファイルを閉じる\r\n    wave_out.close()\r\n\r\n#乱数の種を初期化\r\nnp.random.seed(0)\r\n\r\n#畳み込みに用いる音声波形\r\nclean_wave_files=[\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\",\"./CMU_ARCTIC/cmu_us_axb_arctic/wav/arctic_a0002.wav\"]\r\n\r\n\r\n#音源数\r\nn_sources=len(clean_wave_files)\r\n\r\n#長さを調べる\r\nn_samples=0\r\n#ファイルを読み込む\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    if n_samples<wav.getnframes():\r\n        n_samples=wav.getnframes()\r\n    wav.close()\r\n\r\nclean_data=np.zeros([n_sources,n_samples])\r\n\r\n#ファイルを読み込む\r\ns=0\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    data=wav.readframes(wav.getnframes())\r\n    data=np.frombuffer(data, dtype=np.int16)\r\n    data=data/np.iinfo(np.int16).max\r\n    clean_data[s,:wav.getnframes()]=data\r\n    wav.close()\r\n    s=s+1\r\n# シミュレーションのパラメータ\r\n\r\n#サンプリング周波数\r\nsample_rate=16000\r\n\r\n#フレームサイズ\r\nN=1024\r\n\r\n#周波数の数\r\nNk=N/2+1\r\n\r\n#各ビンの周波数\r\nfreqs=np.arange(0,Nk,1)*sample_rate/N\r\n\r\n#音声と雑音との比率 [dB]\r\nSNR=90.\r\n\r\n#部屋の大きさ\r\nroom_dim = np.r_[10.0, 10.0, 10.0]\r\n\r\n#マイクロホンアレイを置く部屋の場所\r\nmic_array_loc = room_dim / 2 + np.random.randn(3) * 0.1 \r\n\r\n#マイクロホンアレイのマイク配置\r\nmic_alignments = np.array(\r\n    [\r\n        [-0.01, 0.0, 0.0],\r\n        [0.01, 0.0, 0.0],\r\n    ]\r\n)\r\n\r\n#マイクロホン数\r\nn_channels=np.shape(mic_alignments)[0]\r\n\r\n#マイクロホンアレイの座標\r\nR=mic_alignments .T+mic_array_loc[:,None]\r\n\r\n# 部屋を生成する\r\nroom = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\n\r\n# 用いるマイクロホンアレイの情報を設定する\r\nroom.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\n\r\n#音源の場所\r\ndoas=np.array(\r\n    [[np.pi/2., 0],\r\n     [np.pi/2.,np.pi/2.]\r\n    ]    )\r\n\r\n#音源とマイクロホンの距離\r\ndistance=1.\r\nsource_locations=np.zeros((3, doas.shape[0]), dtype=doas.dtype)\r\nsource_locations[0, :] = np.cos(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[1, :] = np.sin(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[2, :] = np.cos(doas[:, 0])\r\nsource_locations *= distance\r\nsource_locations += mic_array_loc[:, None]\r\n\r\n#各音源をシミュレーションに追加する\r\nfor s in range(n_sources):\r\n    clean_data[s]/= np.std(clean_data[s])\r\n    room.add_source(source_locations[:, s], signal=clean_data[s])\r\n\r\n#シミュレーションを回す\r\nroom.simulate(snr=SNR)\r\n\r\n#畳み込んだ波形を取得する(チャンネル、サンプル）\r\nmulti_conv_data=room.mic_array.signals\r\n\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data[0]*np.iinfo(np.int16).max/20.,\"./ds_in.wav\",sample_rate)\r\n\r\n#Near仮定に基づくステアリングベクトルを計算: steering_vectors(Nk x Ns x M)\r\nnear_steering_vectors=calculate_steering_vector(R,source_locations[:,:1],freqs,is_use_far=False)\r\n\r\n#短時間フーリエ変換を行う\r\nf,t,stft_data=sp.stft(multi_conv_data,fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\n#遅延和アレイを実行する\r\ns_hat=np.einsum(\"ksm,mkt->skt\",np.conjugate(near_steering_vectors),stft_data)\r\n\r\n#ステアリングベクトルをかける\r\nc_hat=np.einsum(\"skt,ksm->mskt\",s_hat,near_steering_vectors)\r\n\r\n#時間領域の波形に戻す\r\nt,ds_out=sp.istft(c_hat[0],fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\n#大きさを調整する\r\nds_out=ds_out*np.iinfo(np.int16).max/20.\r\n\r\n#ファイルに書き込む\r\nwrite_file_from_time_signal(ds_out,\"./ds_out.wav\",sample_rate)\r\n\r\n\r\n"
  },
  {
    "path": "section6/sample_code_c6_5.py",
    "content": "\r\n\r\nimport wave as wave\r\nimport pyroomacoustics as pa\r\nimport numpy as np\r\nimport scipy.signal as sp\r\n\r\n#ステアリングベクトルを算出\r\n#mic_position: 3 x M  dimensional ndarray [[x,y,z],[x,y,z]]\r\n#source_position: 3x Ns dimensional ndarray [[x,y,z],[x,y,z] ]\r\n#freqs: Nk dimensional array [f1,f2,f3...]\r\n#sound_speed: 音速 [m/s]\r\n#is_use_far: Farを使う場合はTrue, Nearの場合はFalse, \r\n#return: steering vector (Nk x Ns x M)\r\ndef calculate_steering_vector(mic_alignments,source_locations,freqs,sound_speed=340,is_use_far=False):\r\n    #マイク数を取得\r\n    n_channels=np.shape(mic_alignments)[1]\r\n\r\n    #音源数を取得\r\n    n_source=np.shape(source_locations)[1]\r\n\r\n    if is_use_far==True:\r\n        #音源位置を正規化\r\n        norm_source_locations=source_locations/np.linalg.norm(source_locations,2,axis=0,keepdims=True)\r\n\r\n        #位相を求める\r\n        steering_phase=np.einsum('k,ism,ism->ksm',2.j*np.pi/sound_speed*freqs,norm_source_locations[...,None],mic_alignments[:,None,:])\r\n\r\n        #ステアリングベクトルを算出\r\n        steering_vector=1./np.sqrt(n_channels)*np.exp(steering_phase)\r\n\r\n        return(steering_vector)\r\n\r\n    else:\r\n\r\n        #音源とマイクの距離を求める\r\n        #distance: Ns x Nm\r\n        distance=np.sqrt(np.sum(np.square(source_locations[...,None]-mic_alignments[:,None,:]),axis=0))\r\n\r\n        #遅延時間(delay) [sec]\r\n        delay=distance/sound_speed\r\n\r\n        #ステアリングベクトルの位相を求める\r\n        steering_phase=np.einsum('k,sm->ksm',-2.j*np.pi*freqs,delay)\r\n    \r\n        #音量の減衰\r\n        steering_decay_ratio=1./distance\r\n\r\n        #ステアリングベクトルを求める\r\n        steering_vector=steering_decay_ratio[None,...]*np.exp(steering_phase)\r\n\r\n        #大きさを1で正規化する\r\n        steering_vector=steering_vector/np.linalg.norm(steering_vector,2,axis=2,keepdims=True)\r\n\r\n    return(steering_vector)\r\n\r\n#2バイトに変換してファイルに保存\r\n#signal: time-domain 1d array (float)\r\n#file_name: 出力先のファイル名\r\n#sample_rate: サンプリングレート\r\ndef write_file_from_time_signal(signal,file_name,sample_rate):\r\n    #2バイトのデータに変換\r\n    signal=signal.astype(np.int16)\r\n\r\n    #waveファイルに書き込む\r\n    wave_out = wave.open(file_name, 'w')\r\n\r\n    #モノラル:1、ステレオ:2\r\n    wave_out.setnchannels(1)\r\n\r\n    #サンプルサイズ2byte\r\n    wave_out.setsampwidth(2)\r\n\r\n    #サンプリング周波数\r\n    wave_out.setframerate(sample_rate)\r\n\r\n    #データを書き込み\r\n    wave_out.writeframes(signal)\r\n\r\n    #ファイルを閉じる\r\n    wave_out.close()\r\n\r\n#乱数の種を初期化\r\nnp.random.seed(0)\r\n\r\n#畳み込みに用いる音声波形\r\nclean_wave_files=[\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\",\"./CMU_ARCTIC/cmu_us_axb_arctic/wav/arctic_a0002.wav\"]\r\n\r\n\r\n#音源数\r\nn_sources=len(clean_wave_files)\r\n\r\n#長さを調べる\r\nn_samples=0\r\n#ファイルを読み込む\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    if n_samples<wav.getnframes():\r\n        n_samples=wav.getnframes()\r\n    wav.close()\r\n\r\nclean_data=np.zeros([n_sources,n_samples])\r\n\r\n#ファイルを読み込む\r\ns=0\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    data=wav.readframes(wav.getnframes())\r\n    data=np.frombuffer(data, dtype=np.int16)\r\n    data=data/np.iinfo(np.int16).max\r\n    clean_data[s,:wav.getnframes()]=data\r\n    wav.close()\r\n    s=s+1\r\n# シミュレーションのパラメータ\r\n\r\n#サンプリング周波数\r\nsample_rate=16000\r\n\r\n#フレームサイズ\r\nN=1024\r\n\r\n#周波数の数\r\nNk=N/2+1\r\n\r\n#各ビンの周波数\r\nfreqs=np.arange(0,Nk,1)*sample_rate/N\r\n\r\n#音声と雑音との比率 [dB]\r\nSNR=90.\r\n\r\n#部屋の大きさ\r\nroom_dim = np.r_[10.0, 10.0, 10.0]\r\n\r\n#マイクロホンアレイを置く部屋の場所\r\nmic_array_loc = room_dim / 2 + np.random.randn(3) * 0.1 \r\n\r\n#マイクロホンアレイのマイク配置\r\n#マイクロホンアレイのマイク配置\r\nmic_alignments = np.array(\r\n    \r\n        [[x,0.0,0.0] for x in np.arange(-0.31,0.32,0.02)]\r\n    \r\n)\r\n#マイクロホン数\r\nn_channels=np.shape(mic_alignments)[0]\r\n\r\n#マイクロホンアレイの座標\r\nR=mic_alignments .T+mic_array_loc[:,None]\r\n\r\n# 部屋を生成する\r\nroom = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\n\r\n# 用いるマイクロホンアレイの情報を設定する\r\nroom.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\n\r\n#音源の場所\r\ndoas=np.array(\r\n    [[np.pi/2., 0],\r\n     [np.pi/2.,np.pi/2.]\r\n    ]    )\r\n\r\n#音源とマイクロホンの距離\r\ndistance=1.\r\nsource_locations=np.zeros((3, doas.shape[0]), dtype=doas.dtype)\r\nsource_locations[0, :] = np.cos(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[1, :] = np.sin(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[2, :] = np.cos(doas[:, 0])\r\nsource_locations *= distance\r\nsource_locations += mic_array_loc[:, None]\r\n\r\n#各音源をシミュレーションに追加する\r\nfor s in range(n_sources):\r\n    clean_data[s]/= np.std(clean_data[s])\r\n    room.add_source(source_locations[:, s], signal=clean_data[s])\r\n\r\n#シミュレーションを回す\r\nroom.simulate(snr=SNR)\r\n\r\n#畳み込んだ波形を取得する(チャンネル、サンプル）\r\nmulti_conv_data=room.mic_array.signals\r\n\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data[0]*np.iinfo(np.int16).max/20.,\"./ds_interference_in_m32.wav\",sample_rate)\r\n\r\n#Near仮定に基づくステアリングベクトルを計算: steering_vectors(Nk x Ns x M)\r\nnear_steering_vectors=calculate_steering_vector(R,source_locations[:,:1],freqs,is_use_far=False)\r\n\r\n#短時間フーリエ変換を行う\r\nf,t,stft_data=sp.stft(multi_conv_data,fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\n#遅延和アレイを実行する\r\ns_hat=np.einsum(\"ksm,mkt->skt\",np.conjugate(near_steering_vectors),stft_data)\r\n\r\n#ステアリングベクトルをかける\r\nc_hat=np.einsum(\"skt,ksm->mskt\",s_hat,near_steering_vectors)\r\n\r\n#時間領域の波形に戻す\r\nt,ds_out=sp.istft(c_hat[0],fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\n#大きさを調整する\r\nds_out=ds_out*np.iinfo(np.int16).max/20.\r\n\r\n#ファイルに書き込む\r\nwrite_file_from_time_signal(ds_out,\"./ds_interference_out_m32.wav\",sample_rate)\r\n\r\n\r\n"
  },
  {
    "path": "section6/sample_code_c6_6.py",
    "content": "\r\n\r\nimport numpy as np\r\nimport scipy.signal as sp\r\nimport matplotlib.pyplot as plt\r\n\r\n#ステアリングベクトルを算出\r\n#mic_position: 3 x M  dimensional ndarray [[x,y,z],[x,y,z]]\r\n#source_position: 3x Ns dimensional ndarray [[x,y,z],[x,y,z] ]\r\n#freqs: Nk dimensional array [f1,f2,f3...]\r\n#sound_speed: 音速 [m/s]\r\n#is_use_far: Farを使う場合はTrue, Nearの場合はFalse, \r\n#return: steering vector (Nk x Ns x M)\r\ndef calculate_steering_vector(mic_alignments,source_locations,freqs,sound_speed=340,is_use_far=False):\r\n    #マイク数を取得\r\n    n_channels=np.shape(mic_alignments)[1]\r\n\r\n    #音源数を取得\r\n    n_source=np.shape(source_locations)[1]\r\n\r\n    if is_use_far==True:\r\n        #音源位置を正規化\r\n        norm_source_locations=source_locations/np.linalg.norm(source_locations,2,axis=0,keepdims=True)\r\n\r\n        #位相を求める\r\n        steering_phase=np.einsum('k,ism,ism->ksm',2.j*np.pi/sound_speed*freqs,norm_source_locations[...,None],mic_alignments[:,None,:])\r\n\r\n        #ステアリングベクトルを算出\r\n        steering_vector=1./np.sqrt(n_channels)*np.exp(steering_phase)\r\n\r\n        return(steering_vector)\r\n\r\n    else:\r\n\r\n        #音源とマイクの距離を求める\r\n        #distance: Ns x Nm\r\n        distance=np.sqrt(np.sum(np.square(source_locations[...,None]-mic_alignments[:,None,:]),axis=0))\r\n\r\n        #遅延時間(delay) [sec]\r\n        delay=distance/sound_speed\r\n\r\n        #ステアリングベクトルの位相を求める\r\n        steering_phase=np.einsum('k,sm->ksm',-2.j*np.pi*freqs,delay)\r\n    \r\n        #音量の減衰\r\n        steering_decay_ratio=1./distance\r\n\r\n        #ステアリングベクトルを求める\r\n        steering_vector=steering_decay_ratio[None,...]*np.exp(steering_phase)\r\n\r\n        #大きさを1で正規化する\r\n        steering_vector=steering_vector/np.linalg.norm(steering_vector,2,axis=2,keepdims=True)\r\n\r\n    return(steering_vector)\r\n\r\n\r\n#サンプリング周波数\r\nsample_rate=16000\r\n\r\n#フレームサイズ\r\nN=1024\r\n\r\n#周波数の数\r\nNk=N/2+1\r\n\r\n#各ビンの周波数\r\nfreqs=np.arange(0,Nk,1)*sample_rate/N\r\n\r\n#マイクロホンアレイのマイク配置\r\nmic_alignments = np.array(\r\n   [[x,0.0,0.0] for x in np.arange(-0.01,0.02,0.02)]\r\n)\r\n\r\n#マイクロホン数\r\nn_channels=np.shape(mic_alignments)[0]\r\n\r\n#音源の場所\r\ndoas=np.array(\r\n    [[np.pi/2.,theta] for theta in np.arange(-np.pi,np.pi,1./180.*np.pi)]\r\n    )\r\n\r\n#音源とマイクロホンの距離\r\ndistance=1.\r\nsource_locations=np.zeros((3, doas.shape[0]), dtype=doas.dtype)\r\nsource_locations[0, :] = np.cos(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[1, :] = np.sin(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[2, :] = np.cos(doas[:, 0])\r\nsource_locations *= distance\r\n\r\n#Near仮定に基づくステアリングベクトルを計算: steering_vectors(Nk x Ns x M)\r\nnear_steering_vectors=calculate_steering_vector(mic_alignments.T,source_locations,freqs,is_use_far=False)\r\n\r\n#theta=0に最も近いステアリングベクトルを取り出す\r\ndesired_index=np.argmin(np.abs(doas[:,1]),axis=0)\r\n\r\n#所望音のステアリングベクトル\r\ndesired_steering_vector=near_steering_vectors[:,desired_index,:]\r\n\r\n#内積計算\r\ndirectivity_pattern=np.square(np.abs(np.einsum(\"km,ksm->ks\",np.conjugate(desired_steering_vector),near_steering_vectors)))\r\n\r\n#スタイル\r\nplt.style.use(\"grayscale\")\r\n#音声データをプロットする\r\nfig=plt.figure(figsize=(7,7))\r\n\r\n# plot\r\nax = plt.subplot(111, projection=\"polar\")\r\n\r\n#グラフの向き、グリッドの線種を指定\r\nax.set_theta_zero_location('N')\r\nax.set_theta_direction('clockwise')\r\nax.grid(linestyle=\"--\")\r\n\r\n#y軸のラベル調整\r\nax.yaxis.labelpad = -250\r\nylabel=plt.ylabel(\"Response [dB]\")\r\nylabel.set_position((0, 0.6))\r\nylabel.set_rotation(0)\r\nplt.yticks([-20,-10,0])\r\nplt.ylim([-30,0])\r\n\r\n#x軸のラベル\r\nplt.xlabel(\"Azimuth [degrees]\")\r\n\r\n\r\n#描画する周波数\r\ndraw_freqs=np.array([1000,2000,3000,4000])\r\n\r\ndraw_freq_list=np.argmin(np.abs(freqs[:,None]-draw_freqs[None,:]),axis=0)\r\n\r\n\r\nfor draw_freq_index in draw_freq_list:\r\n    #周波数毎に指向特性を描画\r\n    plt.plot(doas[:,1], 10.*np.log10(directivity_pattern[draw_freq_index,:]),lw=3,label=\"{} [Hz]\".format(freqs[draw_freq_index]))\r\n\r\nplt.legend(loc=(0.2,0.6))\r\n\r\n#音声ファイルを画像として保存\r\nplt.savefig(\"./directivity_pattern.png\")\r\n\r\n#画像を画面に表示\r\nplt.show()\r\n\r\n\r\n\r\n"
  },
  {
    "path": "section6/sample_code_c6_7.py",
    "content": "\r\n\r\nimport numpy as np\r\nimport scipy.signal as sp\r\nimport matplotlib.pyplot as plt\r\n\r\n#ステアリングベクトルを算出\r\n#mic_position: 3 x M  dimensional ndarray [[x,y,z],[x,y,z]]\r\n#source_position: 3x Ns dimensional ndarray [[x,y,z],[x,y,z] ]\r\n#freqs: Nk dimensional array [f1,f2,f3...]\r\n#sound_speed: 音速 [m/s]\r\n#is_use_far: Farを使う場合はTrue, Nearの場合はFalse, \r\n#return: steering vector (Nk x Ns x M)\r\ndef calculate_steering_vector(mic_alignments,source_locations,freqs,sound_speed=340,is_use_far=False):\r\n    #マイク数を取得\r\n    n_channels=np.shape(mic_alignments)[1]\r\n\r\n    #音源数を取得\r\n    n_source=np.shape(source_locations)[1]\r\n\r\n    if is_use_far==True:\r\n        #音源位置を正規化\r\n        norm_source_locations=source_locations/np.linalg.norm(source_locations,2,axis=0,keepdims=True)\r\n\r\n        #位相を求める\r\n        steering_phase=np.einsum('k,ism,ism->ksm',2.j*np.pi/sound_speed*freqs,norm_source_locations[...,None],mic_alignments[:,None,:])\r\n\r\n        #ステアリングベクトルを算出\r\n        steering_vector=1./np.sqrt(n_channels)*np.exp(steering_phase)\r\n\r\n        return(steering_vector)\r\n\r\n    else:\r\n\r\n        #音源とマイクの距離を求める\r\n        #distance: Ns x Nm\r\n        distance=np.sqrt(np.sum(np.square(source_locations[...,None]-mic_alignments[:,None,:]),axis=0))\r\n\r\n        #遅延時間(delay) [sec]\r\n        delay=distance/sound_speed\r\n\r\n        #ステアリングベクトルの位相を求める\r\n        steering_phase=np.einsum('k,sm->ksm',-2.j*np.pi*freqs,delay)\r\n    \r\n        #音量の減衰\r\n        steering_decay_ratio=1./distance\r\n\r\n        #ステアリングベクトルを求める\r\n        steering_vector=steering_decay_ratio[None,...]*np.exp(steering_phase)\r\n\r\n        #大きさを1で正規化する\r\n        steering_vector=steering_vector/np.linalg.norm(steering_vector,2,axis=2,keepdims=True)\r\n\r\n    return(steering_vector)\r\n\r\n\r\n#サンプリング周波数\r\nsample_rate=16000\r\n\r\n#フレームサイズ\r\nN=1024\r\n\r\n#周波数の数\r\nNk=N/2+1\r\n\r\n#各ビンの周波数\r\nfreqs=np.arange(0,Nk,1)*sample_rate/N\r\n\r\n#マイクロホンアレイのマイク配置\r\nmic_alignments = np.array(\r\n   [[x,0.0,0.0] for x in np.arange(-0.31,0.32,0.02)]\r\n)\r\n\r\n#マイクロホン数\r\nn_channels=np.shape(mic_alignments)[0]\r\n\r\n#音源の場所\r\ndoas=np.array(\r\n    [[np.pi/2.,theta] for theta in np.arange(-np.pi,np.pi,1./180.*np.pi)]\r\n    )\r\n\r\n#音源とマイクロホンの距離\r\ndistance=1.\r\nsource_locations=np.zeros((3, doas.shape[0]), dtype=doas.dtype)\r\nsource_locations[0, :] = np.cos(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[1, :] = np.sin(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[2, :] = np.cos(doas[:, 0])\r\nsource_locations *= distance\r\n\r\n#Near仮定に基づくステアリングベクトルを計算: steering_vectors(Nk x Ns x M)\r\nnear_steering_vectors=calculate_steering_vector(mic_alignments.T,source_locations,freqs,is_use_far=False)\r\n\r\n#theta=0に最も近いステアリングベクトルを取り出す\r\ndesired_index=np.argmin(np.abs(doas[:,1]),axis=0)\r\n\r\n#所望音のステアリングベクトル\r\ndesired_steering_vector=near_steering_vectors[:,desired_index,:]\r\n\r\n#内積計算\r\ndirectivity_pattern=np.square(np.abs(np.einsum(\"km,ksm->ks\",np.conjugate(desired_steering_vector),near_steering_vectors)))\r\n\r\n#スタイル\r\nplt.style.use(\"grayscale\")\r\n#音声データをプロットする\r\nfig=plt.figure(figsize=(7,7))\r\n\r\n# plot\r\nax = plt.subplot(111, projection=\"polar\")\r\n\r\n#グラフの向き、グリッドの線種を指定\r\nax.set_theta_zero_location('N')\r\nax.set_theta_direction('clockwise')\r\nax.grid(linestyle=\"--\")\r\nax.yaxis.labelpad = -30\r\n\r\n#x軸のラベル\r\nplt.xlabel(\"Azimuth [degrees]\")\r\n\r\n#y軸のラベル\r\nylabel=plt.ylabel(\"Response [dB]\")\r\n\r\nylabel.set_position((0, 0.6))\r\nylabel.set_rotation(0)\r\n\r\nplt.yticks([-20,-10,0])\r\nplt.ylim([-30,0])\r\n\r\n#描画する周波数\r\ndraw_freqs=np.array([1000,2000,3000,4000])\r\n\r\ndraw_freq_list=np.argmin(np.abs(freqs[:,None]-draw_freqs[None,:]),axis=0)\r\n\r\n\r\nfor draw_freq_index in draw_freq_list:\r\n    #周波数毎に指向特性を描画\r\n    plt.plot(doas[:,1], 10.*np.log10(directivity_pattern[draw_freq_index,:]),lw=3,label=\"{} [Hz]\".format(freqs[draw_freq_index]))\r\n\r\nplt.legend(loc=(0.2,0.6))\r\n\r\n#音声ファイルを画像として保存\r\nplt.savefig(\"./directivity_pattern_m32.png\")\r\n\r\n#画像を画面に表示\r\nplt.show()\r\n\r\n\r\n\r\n"
  },
  {
    "path": "section6/sample_code_c6_8.py",
    "content": "\r\n\r\nimport wave as wave\r\nimport pyroomacoustics as pa\r\nimport numpy as np\r\nimport scipy.signal as sp\r\n\r\n#ステアリングベクトルを算出\r\n#mic_position: 3 x M  dimensional ndarray [[x,y,z],[x,y,z]]\r\n#source_position: 3x Ns dimensional ndarray [[x,y,z],[x,y,z] ]\r\n#freqs: Nk dimensional array [f1,f2,f3...]\r\n#sound_speed: 音速 [m/s]\r\n#is_use_far: Farを使う場合はTrue, Nearの場合はFalse, \r\n#return: steering vector (Nk x Ns x M)\r\ndef calculate_steering_vector(mic_alignments,source_locations,freqs,sound_speed=340,is_use_far=False):\r\n    #マイク数を取得\r\n    n_channels=np.shape(mic_alignments)[1]\r\n\r\n    #音源数を取得\r\n    n_source=np.shape(source_locations)[1]\r\n\r\n    if is_use_far==True:\r\n        #音源位置を正規化\r\n        norm_source_locations=source_locations/np.linalg.norm(source_locations,2,axis=0,keepdims=True)\r\n\r\n        #位相を求める\r\n        steering_phase=np.einsum('k,ism,ism->ksm',2.j*np.pi/sound_speed*freqs,norm_source_locations[...,None],mic_alignments[:,None,:])\r\n\r\n        #ステアリングベクトルを算出\r\n        steering_vector=1./np.sqrt(n_channels)*np.exp(steering_phase)\r\n\r\n        return(steering_vector)\r\n\r\n    else:\r\n\r\n        #音源とマイクの距離を求める\r\n        #distance: Ns x Nm\r\n        distance=np.sqrt(np.sum(np.square(source_locations[...,None]-mic_alignments[:,None,:]),axis=0))\r\n\r\n        #遅延時間(delay) [sec]\r\n        delay=distance/sound_speed\r\n\r\n        #ステアリングベクトルの位相を求める\r\n        steering_phase=np.einsum('k,sm->ksm',-2.j*np.pi*freqs,delay)\r\n    \r\n        #音量の減衰\r\n        steering_decay_ratio=1./distance\r\n\r\n        #ステアリングベクトルを求める\r\n        steering_vector=steering_decay_ratio[None,...]*np.exp(steering_phase)\r\n\r\n        #大きさを1で正規化する\r\n        steering_vector=steering_vector/np.linalg.norm(steering_vector,2,axis=2,keepdims=True)\r\n\r\n    return(steering_vector)\r\n\r\n#2バイトに変換してファイルに保存\r\n#signal: time-domain 1d array (float)\r\n#file_name: 出力先のファイル名\r\n#sample_rate: サンプリングレート\r\ndef write_file_from_time_signal(signal,file_name,sample_rate):\r\n    #2バイトのデータに変換\r\n    signal=signal.astype(np.int16)\r\n\r\n    #waveファイルに書き込む\r\n    wave_out = wave.open(file_name, 'w')\r\n\r\n    #モノラル:1、ステレオ:2\r\n    wave_out.setnchannels(1)\r\n\r\n    #サンプルサイズ2byte\r\n    wave_out.setsampwidth(2)\r\n\r\n    #サンプリング周波数\r\n    wave_out.setframerate(sample_rate)\r\n\r\n    #データを書き込み\r\n    wave_out.writeframes(signal)\r\n\r\n    #ファイルを閉じる\r\n    wave_out.close()\r\n\r\n#乱数の種を初期化\r\nnp.random.seed(0)\r\n\r\n#畳み込みに用いる音声波形\r\nclean_wave_files=[\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\"]\r\n\r\n#音源数\r\nn_sources=len(clean_wave_files)\r\n\r\n#長さを調べる\r\nn_samples=0\r\n#ファイルを読み込む\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    if n_samples<wav.getnframes():\r\n        n_samples=wav.getnframes()\r\n    wav.close()\r\n\r\nclean_data=np.zeros([n_sources,n_samples])\r\n\r\n#ファイルを読み込む\r\ns=0\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    data=wav.readframes(wav.getnframes())\r\n    data=np.frombuffer(data, dtype=np.int16)\r\n    data=data/np.iinfo(np.int16).max\r\n    clean_data[s,:wav.getnframes()]=data\r\n    wav.close()\r\n    s=s+1\r\n# シミュレーションのパラメータ\r\n\r\n#サンプリング周波数\r\nsample_rate=16000\r\n\r\n#フレームサイズ\r\nN=1024\r\n\r\n#周波数の数\r\nNk=N/2+1\r\n\r\n\r\n#各ビンの周波数\r\nfreqs=np.arange(0,Nk,1)*sample_rate/N\r\n\r\n#音声と雑音との比率 [dB]\r\nSNR=20.\r\n\r\n#部屋の大きさ\r\nroom_dim = np.r_[10.0, 10.0, 10.0]\r\n\r\n#マイクロホンアレイを置く部屋の場所\r\nmic_array_loc = room_dim / 2 + np.random.randn(3) * 0.1 \r\n\r\n#マイクロホンアレイのマイク配置\r\nmic_alignments = np.array(\r\n    [\r\n        [-0.01, 0.0, 0.0],\r\n        [0.01, 0.0, 0.0],\r\n    ]\r\n)\r\n\r\n#マイクロホン数\r\nn_channels=np.shape(mic_alignments)[0]\r\n\r\n#マイクロホンアレイの座標\r\nR=mic_alignments .T+mic_array_loc[:,None]\r\n\r\n# 部屋を生成する\r\nroom = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\n\r\n# 用いるマイクロホンアレイの情報を設定する\r\nroom.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\n\r\n#音源の場所\r\ndoas=np.array(\r\n    [[np.pi/2., 0]\r\n    ]    )\r\n\r\n#音源とマイクロホンの距離\r\ndistance=1.\r\nsource_locations=np.zeros((3, doas.shape[0]), dtype=doas.dtype)\r\nsource_locations[0, :] = np.cos(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[1, :] = np.sin(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[2, :] = np.cos(doas[:, 0])\r\nsource_locations *= distance\r\nsource_locations += mic_array_loc[:, None]\r\n\r\n#各音源をシミュレーションに追加する\r\nfor s in range(n_sources):\r\n    clean_data[s]/= np.std(clean_data[s])\r\n    room.add_source(source_locations[:, s], signal=clean_data[s])\r\n\r\n#シミュレーションを回す\r\nroom.simulate(snr=SNR)\r\n\r\n#畳み込んだ波形を取得する(チャンネル、サンプル）\r\nmulti_conv_data=room.mic_array.signals\r\n\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data[0]*np.iinfo(np.int16).max/20.,\"./mvdr_in.wav\",sample_rate)\r\n\r\n#Near仮定に基づくステアリングベクトルを計算: steering_vectors(Nk x Ns x M)\r\nnear_steering_vectors=calculate_steering_vector(R,source_locations,freqs,is_use_far=False)\r\n\r\n#短時間フーリエ変換を行う\r\nf,t,stft_data=sp.stft(multi_conv_data,fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\n#共分散行列を計算する\r\nRcov=np.einsum(\"mkt,nkt->kmn\",stft_data,np.conjugate(stft_data))\r\n\r\n#共分散行列の逆行列を計算する\r\nRcov_inverse=np.linalg.pinv(Rcov)\r\n\r\n#フィルタを計算する\r\nRcov_inverse_a=np.einsum(\"kmn,kn->km\",Rcov_inverse,near_steering_vectors[:,0,:])\r\na_H_Rcov_inverse_a=np.einsum(\"kn,kn->k\",np.conjugate(near_steering_vectors[:,0,:]),Rcov_inverse_a)\r\nw_mvdr=Rcov_inverse_a/np.maximum(a_H_Rcov_inverse_a,1.e-18)[:,None]\r\n\r\n#フィルタをかける\r\ns_hat=np.einsum(\"km,mkt->kt\",np.conjugate(w_mvdr),stft_data)\r\n\r\n#ステアリングベクトルをかける\r\nc_hat=np.einsum(\"kt,km->mkt\",s_hat,near_steering_vectors[:,0,:])\r\n\r\n#時間領域の波形に戻す\r\nt,mvdr_out=sp.istft(c_hat[0],fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\n#大きさを調整する\r\nmvdr_out=mvdr_out*np.iinfo(np.int16).max/20.\r\n\r\n#ファイルに書き込む\r\nwrite_file_from_time_signal(mvdr_out,\"./mvdr_out.wav\",sample_rate)\r\n\r\n\r\n"
  },
  {
    "path": "section6/sample_code_c6_9.py",
    "content": "\r\n\r\nimport wave as wave\r\nimport pyroomacoustics as pa\r\nimport numpy as np\r\nimport scipy.signal as sp\r\n\r\n#ステアリングベクトルを算出\r\n#mic_position: 3 x M  dimensional ndarray [[x,y,z],[x,y,z]]\r\n#source_position: 3x Ns dimensional ndarray [[x,y,z],[x,y,z] ]\r\n#freqs: Nk dimensional array [f1,f2,f3...]\r\n#sound_speed: 音速 [m/s]\r\n#is_use_far: Farを使う場合はTrue, Nearの場合はFalse, \r\n#return: steering vector (Nk x Ns x M)\r\ndef calculate_steering_vector(mic_alignments,source_locations,freqs,sound_speed=340,is_use_far=False):\r\n    #マイク数を取得\r\n    n_channels=np.shape(mic_alignments)[1]\r\n\r\n    #音源数を取得\r\n    n_source=np.shape(source_locations)[1]\r\n\r\n    if is_use_far==True:\r\n        #音源位置を正規化\r\n        norm_source_locations=source_locations/np.linalg.norm(source_locations,2,axis=0,keepdims=True)\r\n\r\n        #位相を求める\r\n        steering_phase=np.einsum('k,ism,ism->ksm',2.j*np.pi/sound_speed*freqs,norm_source_locations[...,None],mic_alignments[:,None,:])\r\n\r\n        #ステアリングベクトルを算出\r\n        steering_vector=1./np.sqrt(n_channels)*np.exp(steering_phase)\r\n\r\n        return(steering_vector)\r\n\r\n    else:\r\n\r\n        #音源とマイクの距離を求める\r\n        #distance: Ns x Nm\r\n        distance=np.sqrt(np.sum(np.square(source_locations[...,None]-mic_alignments[:,None,:]),axis=0))\r\n\r\n        #遅延時間(delay) [sec]\r\n        delay=distance/sound_speed\r\n\r\n        #ステアリングベクトルの位相を求める\r\n        steering_phase=np.einsum('k,sm->ksm',-2.j*np.pi*freqs,delay)\r\n    \r\n        #音量の減衰\r\n        steering_decay_ratio=1./distance\r\n\r\n        #ステアリングベクトルを求める\r\n        steering_vector=steering_decay_ratio[None,...]*np.exp(steering_phase)\r\n\r\n        #大きさを1で正規化する\r\n        steering_vector=steering_vector/np.linalg.norm(steering_vector,2,axis=2,keepdims=True)\r\n\r\n    return(steering_vector)\r\n\r\n#2バイトに変換してファイルに保存\r\n#signal: time-domain 1d array (float)\r\n#file_name: 出力先のファイル名\r\n#sample_rate: サンプリングレート\r\ndef write_file_from_time_signal(signal,file_name,sample_rate):\r\n    #2バイトのデータに変換\r\n    signal=signal.astype(np.int16)\r\n\r\n    #waveファイルに書き込む\r\n    wave_out = wave.open(file_name, 'w')\r\n\r\n    #モノラル:1、ステレオ:2\r\n    wave_out.setnchannels(1)\r\n\r\n    #サンプルサイズ2byte\r\n    wave_out.setsampwidth(2)\r\n\r\n    #サンプリング周波数\r\n    wave_out.setframerate(sample_rate)\r\n\r\n    #データを書き込み\r\n    wave_out.writeframes(signal)\r\n\r\n    #ファイルを閉じる\r\n    wave_out.close()\r\n\r\n#乱数の種を初期化\r\nnp.random.seed(0)\r\n\r\n#畳み込みに用いる音声波形\r\nclean_wave_files=[\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\",\"./CMU_ARCTIC/cmu_us_axb_arctic/wav/arctic_a0002.wav\"]\r\n\r\n\r\n#音源数\r\nn_sources=len(clean_wave_files)\r\n\r\n#長さを調べる\r\nn_samples=0\r\n#ファイルを読み込む\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    if n_samples<wav.getnframes():\r\n        n_samples=wav.getnframes()\r\n    wav.close()\r\n\r\nclean_data=np.zeros([n_sources,n_samples])\r\n\r\n#ファイルを読み込む\r\ns=0\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    data=wav.readframes(wav.getnframes())\r\n    data=np.frombuffer(data, dtype=np.int16)\r\n    data=data/np.iinfo(np.int16).max\r\n    clean_data[s,:wav.getnframes()]=data\r\n    wav.close()\r\n    s=s+1\r\n# シミュレーションのパラメータ\r\n\r\n#サンプリング周波数\r\nsample_rate=16000\r\n\r\n#フレームサイズ\r\nN=1024\r\n\r\n#周波数の数\r\nNk=N/2+1\r\n\r\n#各ビンの周波数\r\nfreqs=np.arange(0,Nk,1)*sample_rate/N\r\n\r\n#音声と雑音との比率 [dB]\r\nSNR=90.\r\n\r\n#部屋の大きさ\r\nroom_dim = np.r_[10.0, 10.0, 10.0]\r\n\r\n#マイクロホンアレイを置く部屋の場所\r\nmic_array_loc = room_dim / 2 + np.random.randn(3) * 0.1 \r\n\r\n#マイクロホンアレイのマイク配置\r\nmic_alignments = np.array(\r\n    [\r\n        [-0.01, 0.0, 0.0],\r\n        [0.01, 0.0, 0.0],\r\n    ]\r\n)\r\n\r\n#マイクロホン数\r\nn_channels=np.shape(mic_alignments)[0]\r\n\r\n#マイクロホンアレイの座標\r\nR=mic_alignments .T+mic_array_loc[:,None]\r\n\r\n# 部屋を生成する\r\nroom = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\n\r\n# 用いるマイクロホンアレイの情報を設定する\r\nroom.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\n\r\n#音源の場所\r\ndoas=np.array(\r\n    [[np.pi/2., 0],\r\n     [np.pi/2.,np.pi/2.]\r\n    ]    )\r\n\r\n#音源とマイクロホンの距離\r\ndistance=1.\r\nsource_locations=np.zeros((3, doas.shape[0]), dtype=doas.dtype)\r\nsource_locations[0, :] = np.cos(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[1, :] = np.sin(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[2, :] = np.cos(doas[:, 0])\r\nsource_locations *= distance\r\nsource_locations += mic_array_loc[:, None]\r\n\r\n#各音源をシミュレーションに追加する\r\nfor s in range(n_sources):\r\n    clean_data[s]/= np.std(clean_data[s])\r\n    room.add_source(source_locations[:, s], signal=clean_data[s])\r\n\r\n#シミュレーションを回す\r\nroom.simulate(snr=SNR)\r\n\r\n#畳み込んだ波形を取得する(チャンネル、サンプル）\r\nmulti_conv_data=room.mic_array.signals\r\n\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data[0]*np.iinfo(np.int16).max/20.,\"./mvdr_interference_in.wav\",sample_rate)\r\n\r\n#Near仮定に基づくステアリングベクトルを計算: steering_vectors(Nk x Ns x M)\r\nnear_steering_vectors=calculate_steering_vector(R,source_locations[:,:1],freqs,is_use_far=False)\r\n\r\n#短時間フーリエ変換を行う\r\nf,t,stft_data=sp.stft(multi_conv_data,fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\n#共分散行列を計算する\r\nRcov=np.einsum(\"mkt,nkt->kmn\",stft_data,np.conjugate(stft_data))\r\n\r\n#共分散行列の逆行列を計算する\r\nRcov_inverse=np.linalg.pinv(Rcov)\r\n\r\n#フィルタを計算する\r\nRcov_inverse_a=np.einsum(\"kmn,kn->km\",Rcov_inverse,near_steering_vectors[:,0,:])\r\na_H_Rcov_inverse_a=np.einsum(\"kn,kn->k\",np.conjugate(near_steering_vectors[:,0,:]),Rcov_inverse_a)\r\nw_mvdr=Rcov_inverse_a/np.maximum(a_H_Rcov_inverse_a,1.e-18)[:,None]\r\n\r\n#フィルタをかける\r\ns_hat=np.einsum(\"km,mkt->kt\",np.conjugate(w_mvdr),stft_data)\r\n\r\n#ステアリングベクトルをかける\r\nc_hat=np.einsum(\"kt,km->mkt\",s_hat,near_steering_vectors[:,0,:])\r\n\r\n#時間領域の波形に戻す\r\nt,mvdr_out=sp.istft(c_hat[0],fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\n#大きさを調整する\r\nmvdr_out=mvdr_out*np.iinfo(np.int16).max/20.\r\n\r\n#ファイルに書き込む\r\nwrite_file_from_time_signal(mvdr_out,\"./mvdr_interference_out.wav\",sample_rate)\r\n"
  },
  {
    "path": "section6.md",
    "content": "## 第6章のサンプルコード\n\n* [Far/Nearの両方に対応したステアリングベクトル計算コード](section6/sample_code_c6_1.py)\n* [遅延和アレイによる雑音抑圧](section6/sample_code_c6_2.py)\n* [遅延和アレイによる雑音抑圧（マイクロホンの数を変更）](section6/sample_code_c6_3.py)\n* [他の人の声が混入した際に、遅延和アレイにより音源分離](section6/sample_code_c6_4.py)\n* [他の人の声が混入した際に、遅延和アレイにより音源分離（マイクロホンの数を変更）](section6/sample_code_c6_5.py)\n* [指向特性を計算](section6/sample_code_c6_6.py)\n* [指向特性を計算(マイクロホンの数を変更）](section6/sample_code_c6_7.py)\n* [最小分散無歪ビームフォーマMVDRを用いた雑音抑圧](section6/sample_code_c6_8.py)\n* [最小分散無歪ビームフォーマMVDRを用いた干渉音抑圧](section6/sample_code_c6_9.py)\n* [最ゆうビームフォーマ](section6/sample_code_c6_10.py)\n* [最大SNRビームフォーマ（MaxSNR）に基づく音源分離](section6/sample_code_c6_11.py)\n* [マルチチャンネルウィナーフィルタ（MWF）に基づく音源分離](section6/sample_code_c6_12.py)\n* [DSBF、MVDR、MaxSNR、MWFの全手法のSNR向上率を評価](section6/sample_code_c6_13.py)\n* [DSBF、MVDR、MaxSNR、MWFの全手法のSNR向上率を評価(音源数を2に設定)](section6/sample_code_c6_14.py)\n"
  },
  {
    "path": "section7/sample_code_c7_1.py",
    "content": "\r\n\r\nimport wave as wave\r\nimport pyroomacoustics as pa\r\nimport numpy as np\r\nimport scipy.signal as sp\r\nimport scipy as scipy\r\n\r\n\r\n\r\n#2バイトに変換してファイルに保存\r\n#signal: time-domain 1d array (float)\r\n#file_name: 出力先のファイル名\r\n#sample_rate: サンプリングレート\r\ndef write_file_from_time_signal(signal,file_name,sample_rate):\r\n    #2バイトのデータに変換\r\n    signal=signal.astype(np.int16)\r\n\r\n    #waveファイルに書き込む\r\n    wave_out = wave.open(file_name, 'w')\r\n\r\n    #モノラル:1、ステレオ:2\r\n    wave_out.setnchannels(1)\r\n\r\n    #サンプルサイズ2byte\r\n    wave_out.setsampwidth(2)\r\n\r\n    #サンプリング周波数\r\n    wave_out.setframerate(sample_rate)\r\n\r\n    #データを書き込み\r\n    wave_out.writeframes(signal)\r\n\r\n    #ファイルを閉じる\r\n    wave_out.close()\r\n\r\n#遅延和アレイを実行する\r\n#x_left:左の音源に近いマイクロホン(Nk, Lt)\r\n#x_right:右の音源に近いマイクロホン(Nk,Lt)\r\n#is_use_amplitude: 振幅差を使って分離を行う場合はTrue\r\n#return y_left 左のマイクに近い音源の出力信号(Nk, Lt)\r\n#       y_right 右のマイクに近い音源の出力信号(Nk,Lt)\r\ndef execute_two_microphone_sparse_separation(x_left,x_right,is_use_amplitude=False):\r\n\r\n    if is_use_amplitude==True:\r\n        #振幅比率を使った分離\r\n        amp_ratio=np.abs(x_left)/np.maximum(np.abs(x_right),1.e-18)\r\n\r\n        y_left=(amp_ratio > 1.).astype(np.float)*x_left\r\n\r\n        y_right=(amp_ratio <= 1.).astype(np.float)*x_right\r\n\r\n    else:\r\n        #位相差を用いた分離\r\n        phase_difference=np.angle(x_left/x_right)\r\n        \r\n        y_left=(phase_difference > 0.).astype(np.float)*x_left\r\n        \r\n        y_right=(phase_difference <= 0.).astype(np.float)*x_right\r\n\r\n    return(y_left,y_right)\r\n\r\n\r\n#SNRをはかる\r\n#desired: 目的音、Lt\r\n#out:　雑音除去後の信号 Lt\r\ndef calculate_snr(desired,out):\r\n    wave_length=np.minimum(np.shape(desired)[0],np.shape(out)[0])\r\n\r\n    #消し残った雑音\r\n    desired=desired[:wave_length]\r\n    out=out[:wave_length]\r\n    noise=desired-out\r\n    snr=10.*np.log10(np.sum(np.square(desired))/np.sum(np.square(noise)))\r\n\r\n    return(snr)\r\n\r\n#乱数の種を初期化\r\nnp.random.seed(0)\r\n\r\n#畳み込みに用いる音声波形\r\nclean_wave_files=[\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\",\"./CMU_ARCTIC/cmu_us_axb_arctic/wav/arctic_a0002.wav\"]\r\n\r\n#音源数\r\nn_sources=len(clean_wave_files)\r\n\r\n#長さを調べる\r\nn_samples=0\r\n#ファイルを読み込む\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    if n_samples<wav.getnframes():\r\n        n_samples=wav.getnframes()\r\n    wav.close()\r\n\r\nclean_data=np.zeros([n_sources,n_samples])\r\n\r\n#ファイルを読み込む\r\ns=0\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    data=wav.readframes(wav.getnframes())\r\n    data=np.frombuffer(data, dtype=np.int16)\r\n    data=data/np.iinfo(np.int16).max\r\n    clean_data[s,:wav.getnframes()]=data\r\n    wav.close()\r\n    s=s+1\r\n\r\n\r\n# シミュレーションのパラメータ\r\n\r\n#シミュレーションで用いる音源数\r\nn_sim_sources=2\r\n\r\n#サンプリング周波数\r\nsample_rate=16000\r\n\r\n#フレームサイズ\r\nN=1024\r\n\r\n#周波数の数\r\nNk=int(N/2+1)\r\n\r\n\r\n#各ビンの周波数\r\nfreqs=np.arange(0,Nk,1)*sample_rate/N\r\n\r\n#音声と雑音との比率 [dB]\r\nSNR=90.\r\n\r\n#部屋の大きさ\r\nroom_dim = np.r_[10.0, 10.0, 10.0]\r\n\r\n#マイクロホンアレイを置く部屋の場所\r\nmic_array_loc = room_dim / 2 + np.random.randn(3) * 0.1 \r\n\r\n#マイクロホンアレイのマイク配置\r\nmic_alignments = np.array(\r\n    [\r\n        [x, 0.0, 0.0] for x in np.arange(-0.01,0.02,0.02)\r\n    ]\r\n)\r\n\r\n#マイクロホン数\r\nn_channels=np.shape(mic_alignments)[0]\r\n\r\n#マイクロホンアレイの座標\r\nR=mic_alignments .T+mic_array_loc[:,None]\r\n\r\n# 部屋を生成する\r\nroom = pa.ShoeBox(room_dim, fs=sample_rate)\r\nroom_no_noise_left = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\nroom_no_noise_right = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\n\r\n# 用いるマイクロホンアレイの情報を設定する\r\nroom.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\nroom_no_noise_left.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\nroom_no_noise_right.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\n\r\n#音源の場所\r\ndoas=np.array(\r\n    [[np.pi/2., np.pi],\r\n     [np.pi/2., 0]\r\n    ]    )\r\n\r\n#音源とマイクロホンの距離\r\ndistance=1.\r\nsource_locations=np.zeros((3, doas.shape[0]), dtype=doas.dtype)\r\nsource_locations[0, :] = np.cos(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[1, :] = np.sin(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[2, :] = np.cos(doas[:, 0])\r\nsource_locations *= distance\r\nsource_locations += mic_array_loc[:, None]\r\n\r\n\r\n#各音源をシミュレーションに追加する\r\nfor s in range(n_sim_sources):\r\n    clean_data[s]/= np.std(clean_data[s])\r\n    room.add_source(source_locations[:, s], signal=clean_data[s])\r\n    if s==0:\r\n        room_no_noise_left.add_source(source_locations[:, s], signal=clean_data[s])\r\n    if s==1:\r\n        room_no_noise_right.add_source(source_locations[:, s], signal=clean_data[s])\r\n\r\n#シミュレーションを回す\r\nroom.simulate(snr=SNR)\r\nroom_no_noise_left.simulate(snr=90)\r\nroom_no_noise_right.simulate(snr=90)\r\n\r\n#畳み込んだ波形を取得する(チャンネル、サンプル）\r\nmulti_conv_data=room.mic_array.signals\r\nmulti_conv_data_left_no_noise=room_no_noise_left.mic_array.signals\r\nmulti_conv_data_right_no_noise=room_no_noise_right.mic_array.signals\r\n\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data_left_no_noise[0,:]*np.iinfo(np.int16).max/20.,\"./far_left_clean.wav\",sample_rate)\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data_right_no_noise[1,:]*np.iinfo(np.int16).max/20.,\"./far_right_clean.wav\",sample_rate)\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data[0,:]*np.iinfo(np.int16).max/20.,\"./far_in_left.wav\",sample_rate)\r\nwrite_file_from_time_signal(multi_conv_data[1,:]*np.iinfo(np.int16).max/20.,\"./far_in_right.wav\",sample_rate)\r\n\r\n#短時間フーリエ変換を行う\r\nf,t,stft_data=sp.stft(multi_conv_data,fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\n#位相差もしくは振幅差で分離\r\ny_phase_left,y_phase_right=execute_two_microphone_sparse_separation(stft_data[0,...],stft_data[1,...],False)\r\ny_amp_left,y_amp_right=execute_two_microphone_sparse_separation(stft_data[0,...],stft_data[1,...],True)\r\n\r\n#時間領域の波形に戻す\r\nt,y_phase_left=sp.istft(y_phase_left,fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,y_phase_right=sp.istft(y_phase_right,fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,y_amp_left=sp.istft(y_amp_left,fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,y_amp_right=sp.istft(y_amp_right,fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\n\r\n#SNRをはかる\r\nsnr_pre=calculate_snr(multi_conv_data_left_no_noise[0,...],multi_conv_data[0,...])+calculate_snr(multi_conv_data_right_no_noise[1,...],multi_conv_data[1,...])\r\nsnr_phase_post=calculate_snr(multi_conv_data_left_no_noise[0,...],y_phase_left)+calculate_snr(multi_conv_data_right_no_noise[1,...],y_phase_right)\r\nsnr_amp_post=calculate_snr(multi_conv_data_left_no_noise[0,...],y_amp_left)+calculate_snr(multi_conv_data_right_no_noise[1,...],y_amp_right)\r\nsnr_pre/=2.\r\nsnr_phase_post/=2.\r\nsnr_amp_post/=2.\r\n\r\n#ファイルに書き込む\r\nwrite_file_from_time_signal(y_phase_left*np.iinfo(np.int16).max/20.,\"./far_sparse_phase_left.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_phase_right*np.iinfo(np.int16).max/20.,\"./far_sparse_phase_right.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_amp_left*np.iinfo(np.int16).max/20.,\"./far_sparse_amp_left.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_amp_right*np.iinfo(np.int16).max/20.,\"./far_sparse_amp_right.wav\",sample_rate)\r\n\r\n\r\nprint(\"method:    \", \"PHASE\", \"AMPLITUDE\")\r\n\r\nprint(\"Δsnr [dB]: {:.2f} {:.2f} \".format(snr_phase_post-snr_pre,snr_amp_post-snr_pre))\r\n"
  },
  {
    "path": "section7/sample_code_c7_2.py",
    "content": "\r\n\r\nimport wave as wave\r\nimport pyroomacoustics as pa\r\nimport numpy as np\r\nimport scipy.signal as sp\r\nimport scipy as scipy\r\n\r\n\r\n\r\n#2バイトに変換してファイルに保存\r\n#signal: time-domain 1d array (float)\r\n#file_name: 出力先のファイル名\r\n#sample_rate: サンプリングレート\r\ndef write_file_from_time_signal(signal,file_name,sample_rate):\r\n    #2バイトのデータに変換\r\n    signal=signal.astype(np.int16)\r\n\r\n    #waveファイルに書き込む\r\n    wave_out = wave.open(file_name, 'w')\r\n\r\n    #モノラル:1、ステレオ:2\r\n    wave_out.setnchannels(1)\r\n\r\n    #サンプルサイズ2byte\r\n    wave_out.setsampwidth(2)\r\n\r\n    #サンプリング周波数\r\n    wave_out.setframerate(sample_rate)\r\n\r\n    #データを書き込み\r\n    wave_out.writeframes(signal)\r\n\r\n    #ファイルを閉じる\r\n    wave_out.close()\r\n\r\n#遅延和アレイを実行する\r\n#x_left:左の音源に近いマイクロホン(Nk, Lt)\r\n#x_right:右の音源に近いマイクロホン(Nk,Lt)\r\n#is_use_amplitude: 振幅差を使って分離を行う場合はTrue\r\n#return y_left 左のマイクに近い音源の出力信号(Nk, Lt)\r\n#       y_right 右のマイクに近い音源の出力信号(Nk,Lt)\r\ndef execute_two_microphone_sparse_separation(x_left,x_right,is_use_amplitude=False):\r\n\r\n    if is_use_amplitude==True:\r\n        #振幅比率を使った分離\r\n        amp_ratio=np.abs(x_left)/np.maximum(np.abs(x_right),1.e-18)\r\n\r\n        y_left=(amp_ratio > 1.).astype(np.float)*x_left\r\n\r\n        y_right=(amp_ratio <= 1.).astype(np.float)*x_right\r\n\r\n    else:\r\n        #位相差を用いた分離\r\n        phase_difference=np.angle(x_left/x_right)\r\n        \r\n        y_left=(phase_difference > 0.).astype(np.float)*x_left\r\n        \r\n        y_right=(phase_difference <= 0.).astype(np.float)*x_right\r\n\r\n    return(y_left,y_right)\r\n\r\n\r\n#SNRをはかる\r\n#desired: 目的音、Lt\r\n#out:　雑音除去後の信号 Lt\r\ndef calculate_snr(desired,out):\r\n    wave_length=np.minimum(np.shape(desired)[0],np.shape(out)[0])\r\n\r\n    #消し残った雑音\r\n    desired=desired[:wave_length]\r\n    out=out[:wave_length]\r\n    noise=desired-out\r\n    snr=10.*np.log10(np.sum(np.square(desired))/np.sum(np.square(noise)))\r\n\r\n    return(snr)\r\n\r\n#乱数の種を初期化\r\nnp.random.seed(0)\r\n\r\n#畳み込みに用いる音声波形\r\nclean_wave_files=[\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\",\"./CMU_ARCTIC/cmu_us_axb_arctic/wav/arctic_a0002.wav\"]\r\n\r\n#音源数\r\nn_sources=len(clean_wave_files)\r\n\r\n#長さを調べる\r\nn_samples=0\r\n#ファイルを読み込む\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    if n_samples<wav.getnframes():\r\n        n_samples=wav.getnframes()\r\n    wav.close()\r\n\r\nclean_data=np.zeros([n_sources,n_samples])\r\n\r\n#ファイルを読み込む\r\ns=0\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    data=wav.readframes(wav.getnframes())\r\n    data=np.frombuffer(data, dtype=np.int16)\r\n    data=data/np.iinfo(np.int16).max\r\n    clean_data[s,:wav.getnframes()]=data\r\n    wav.close()\r\n    s=s+1\r\n\r\n\r\n# シミュレーションのパラメータ\r\n\r\n#シミュレーションで用いる音源数\r\nn_sim_sources=2\r\n\r\n#サンプリング周波数\r\nsample_rate=16000\r\n\r\n#フレームサイズ\r\nN=1024\r\n\r\n#周波数の数\r\nNk=int(N/2+1)\r\n\r\n\r\n#各ビンの周波数\r\nfreqs=np.arange(0,Nk,1)*sample_rate/N\r\n\r\n#音声と雑音との比率 [dB]\r\nSNR=90.\r\n\r\n#部屋の大きさ\r\nroom_dim = np.r_[10.0, 10.0, 10.0]\r\n\r\n#マイクロホンアレイを置く部屋の場所\r\nmic_array_loc = room_dim / 2 + np.random.randn(3) * 0.1 \r\n\r\n#マイクロホンアレイのマイク配置\r\nmic_alignments = np.array(\r\n    [\r\n        [x, 0.0, 0.0] for x in np.arange(-0.2,0.21,0.4)\r\n    ]\r\n)\r\n\r\n\r\n\r\n#マイクロホン数\r\nn_channels=np.shape(mic_alignments)[0]\r\n\r\n#マイクロホンアレイの座標\r\nR=mic_alignments .T+mic_array_loc[:,None]\r\n\r\n# 部屋を生成する\r\nroom = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\nroom_no_noise_left = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\nroom_no_noise_right = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\n\r\n# 用いるマイクロホンアレイの情報を設定する\r\nroom.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\nroom_no_noise_left.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\nroom_no_noise_right.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\n\r\n#音源の場所\r\ndoas=np.array(\r\n    [[np.pi/2., np.pi],\r\n     [np.pi/2., 0.]\r\n    ]    )\r\n\r\n#音源とマイクロホンの距離\r\ndistance=1.\r\nsource_locations=np.zeros((3, doas.shape[0]), dtype=doas.dtype)\r\nsource_locations[0, :] = np.cos(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[1, :] = np.sin(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[2, :] = np.cos(doas[:, 0])\r\nsource_locations *= distance\r\nsource_locations += mic_array_loc[:, None]\r\n\r\n#各音源をシミュレーションに追加する\r\nfor s in range(n_sim_sources):\r\n    clean_data[s]/= np.std(clean_data[s])\r\n    room.add_source(source_locations[:, s], signal=clean_data[s])\r\n    if s==0:\r\n        room_no_noise_left.add_source(source_locations[:, s], signal=clean_data[s])\r\n    if s==1:\r\n        room_no_noise_right.add_source(source_locations[:, s], signal=clean_data[s])\r\n\r\n#シミュレーションを回す\r\nroom.simulate(snr=SNR)\r\nroom_no_noise_left.simulate(snr=90)\r\nroom_no_noise_right.simulate(snr=90)\r\n\r\n#畳み込んだ波形を取得する(チャンネル、サンプル）\r\nmulti_conv_data=room.mic_array.signals\r\nmulti_conv_data_left_no_noise=room_no_noise_left.mic_array.signals\r\nmulti_conv_data_right_no_noise=room_no_noise_right.mic_array.signals\r\n\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data_left_no_noise[0,:]*np.iinfo(np.int16).max/20.,\"./near_left_clean.wav\",sample_rate)\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data_right_no_noise[1,:]*np.iinfo(np.int16).max/20.,\"./near_right_clean.wav\",sample_rate)\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data[0,:]*np.iinfo(np.int16).max/20.,\"./near_in_left.wav\",sample_rate)\r\nwrite_file_from_time_signal(multi_conv_data[1,:]*np.iinfo(np.int16).max/20.,\"./near_in_right.wav\",sample_rate)\r\n\r\n#短時間フーリエ変換を行う\r\nf,t,stft_data=sp.stft(multi_conv_data,fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\n#位相差もしくは振幅差で分離\r\ny_phase_left,y_phase_right=execute_two_microphone_sparse_separation(stft_data[0,...],stft_data[1,...],False)\r\ny_amp_left,y_amp_right=execute_two_microphone_sparse_separation(stft_data[0,...],stft_data[1,...],True)\r\n\r\n#時間領域の波形に戻す\r\nt,y_phase_left=sp.istft(y_phase_left,fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,y_phase_right=sp.istft(y_phase_right,fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,y_amp_left=sp.istft(y_amp_left,fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,y_amp_right=sp.istft(y_amp_right,fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\n\r\n#SNRをはかる\r\nsnr_pre=calculate_snr(multi_conv_data_left_no_noise[0,...],multi_conv_data[0,...])+calculate_snr(multi_conv_data_right_no_noise[1,...],multi_conv_data[1,...])\r\nsnr_phase_post=calculate_snr(multi_conv_data_left_no_noise[0,...],y_phase_left)+calculate_snr(multi_conv_data_right_no_noise[1,...],y_phase_right)\r\nsnr_amp_post=calculate_snr(multi_conv_data_left_no_noise[0,...],y_amp_left)+calculate_snr(multi_conv_data_right_no_noise[1,...],y_amp_right)\r\nsnr_pre/=2.\r\nsnr_phase_post/=2.\r\nsnr_amp_post/=2.\r\n\r\n\r\n#ファイルに書き込む\r\nwrite_file_from_time_signal(y_phase_left*np.iinfo(np.int16).max/20.,\"./near_sparse_phase_left.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_phase_right*np.iinfo(np.int16).max/20.,\"./near_sparse_phase_right.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_amp_left*np.iinfo(np.int16).max/20.,\"./near_sparse_amp_left.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_amp_right*np.iinfo(np.int16).max/20.,\"./near_sparse_amp_right.wav\",sample_rate)\r\n\r\n\r\nprint(\"method:    \", \"PHASE\", \"AMPLITUDE\")\r\n\r\nprint(\"Δsnr [dB]: {:.2f} {:.2f} \".format(snr_phase_post-snr_pre,snr_amp_post-snr_pre))\r\n"
  },
  {
    "path": "section7/sample_code_c7_3.py",
    "content": "\r\n\r\nimport wave as wave\r\nimport pyroomacoustics as pa\r\nimport numpy as np\r\nimport scipy.signal as sp\r\nimport scipy as scipy\r\n\r\n\r\n\r\n#2バイトに変換してファイルに保存\r\n#signal: time-domain 1d array (float)\r\n#file_name: 出力先のファイル名\r\n#sample_rate: サンプリングレート\r\ndef write_file_from_time_signal(signal,file_name,sample_rate):\r\n    #2バイトのデータに変換\r\n    signal=signal.astype(np.int16)\r\n\r\n    #waveファイルに書き込む\r\n    wave_out = wave.open(file_name, 'w')\r\n\r\n    #モノラル:1、ステレオ:2\r\n    wave_out.setnchannels(1)\r\n\r\n    #サンプルサイズ2byte\r\n    wave_out.setsampwidth(2)\r\n\r\n    #サンプリング周波数\r\n    wave_out.setframerate(sample_rate)\r\n\r\n    #データを書き込み\r\n    wave_out.writeframes(signal)\r\n\r\n    #ファイルを閉じる\r\n    wave_out.close()\r\n\r\n\r\n#ステアリングベクトルを算出\r\n#mic_position: 3 x M  dimensional ndarray [[x,y,z],[x,y,z]]\r\n#source_position: 3x Ns dimensional ndarray [[x,y,z],[x,y,z] ]\r\n#freqs: Nk dimensional array [f1,f2,f3...]\r\n#sound_speed: 音速 [m/s]\r\n#is_use_far: Farを使う場合はTrue, Nearの場合はFalse, \r\n#return: steering vector (Nk x Ns x M)\r\ndef calculate_steering_vector(mic_alignments,source_locations,freqs,sound_speed=340,is_use_far=False):\r\n    #マイク数を取得\r\n    n_channels=np.shape(mic_alignments)[1]\r\n\r\n    #音源数を取得\r\n    n_source=np.shape(source_locations)[1]\r\n\r\n    if is_use_far==True:\r\n        #音源位置を正規化\r\n        norm_source_locations=source_locations/np.linalg.norm(source_locations,2,axis=0,keepdims=True)\r\n\r\n        #位相を求める\r\n        steering_phase=np.einsum('k,ism,ism->ksm',2.j*np.pi/sound_speed*freqs,norm_source_locations[...,None],mic_alignments[:,None,:])\r\n\r\n        #ステアリングベクトルを算出\r\n        steering_vector=1./np.sqrt(n_channels)*np.exp(steering_phase)\r\n\r\n        return(steering_vector)\r\n\r\n    else:\r\n\r\n        #音源とマイクの距離を求める\r\n        #distance: Ns x Nm\r\n        distance=np.sqrt(np.sum(np.square(source_locations[...,None]-mic_alignments[:,None,:]),axis=0))\r\n\r\n        #遅延時間(delay) [sec]\r\n        delay=distance/sound_speed\r\n\r\n        #ステアリングベクトルの位相を求める\r\n        steering_phase=np.einsum('k,sm->ksm',-2.j*np.pi*freqs,delay)\r\n    \r\n        #音量の減衰\r\n        steering_decay_ratio=1./distance\r\n\r\n        #ステアリングベクトルを求める\r\n        steering_vector=steering_decay_ratio[None,...]*np.exp(steering_phase)\r\n\r\n        #大きさを1で正規化する\r\n        steering_vector=steering_vector/np.linalg.norm(steering_vector,2,axis=2,keepdims=True)\r\n\r\n    return(steering_vector)\r\n\r\n\r\n#スパース性に基づく分離\r\n#input_vectors:マイクロホン入力信号(Nm,Nk, Lt)\r\n#steering_vectors:ステアリングベクトル(Nk,|Ω|,Nm)\r\n#omega: 目的音の範囲(Ns,|Ω|) \r\n#return y：出力信号(Nm,Ns,Nk, Lt)\r\ndef execute_doa_sparse_separation(input_vectors,steering_vectors,omega):\r\n    inner_product=np.einsum(\"kim,mkt->kit\",np.conjugate(steering_vectors),input_vectors)\r\n    \r\n    n_omega=np.shape(omega)[1]\r\n\r\n    estimate_doas=np.argmax(np.abs(inner_product),axis=1)\r\n\r\n    estimate_doa_mask=np.identity(n_omega)[estimate_doas]\r\n\r\n    output_mask=np.einsum(\"kti,si->skt\",estimate_doa_mask,omega)\r\n\r\n    y=np.einsum(\"skt,mkt->mskt\",output_mask,input_vectors)\r\n\r\n    return(y)\r\n\r\n\r\n#SNRをはかる\r\n#desired: 目的音、Lt\r\n#out:　雑音除去後の信号 Lt\r\ndef calculate_snr(desired,out):\r\n    wave_length=np.minimum(np.shape(desired)[0],np.shape(out)[0])\r\n\r\n    #消し残った雑音\r\n    desired=desired[:wave_length]\r\n    out=out[:wave_length]\r\n    noise=desired-out\r\n    snr=10.*np.log10(np.sum(np.square(desired))/np.sum(np.square(noise)))\r\n\r\n    return(snr)\r\n\r\n#乱数の種を初期化\r\nnp.random.seed(0)\r\n\r\n#畳み込みに用いる音声波形\r\nclean_wave_files=[\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\",\"./CMU_ARCTIC/cmu_us_axb_arctic/wav/arctic_a0002.wav\"]\r\n\r\n#音源数\r\nn_sources=len(clean_wave_files)\r\n\r\n#長さを調べる\r\nn_samples=0\r\n#ファイルを読み込む\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    if n_samples<wav.getnframes():\r\n        n_samples=wav.getnframes()\r\n    wav.close()\r\n\r\nclean_data=np.zeros([n_sources,n_samples])\r\n\r\n#ファイルを読み込む\r\ns=0\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    data=wav.readframes(wav.getnframes())\r\n    data=np.frombuffer(data, dtype=np.int16)\r\n    data=data/np.iinfo(np.int16).max\r\n    clean_data[s,:wav.getnframes()]=data\r\n    wav.close()\r\n    s=s+1\r\n\r\n\r\n# シミュレーションのパラメータ\r\n\r\n#シミュレーションで用いる音源数\r\nn_sim_sources=2\r\n\r\n#サンプリング周波数\r\nsample_rate=16000\r\n\r\n#フレームサイズ\r\nN=1024\r\n\r\n#周波数の数\r\nNk=int(N/2+1)\r\n\r\n#各ビンの周波数\r\nfreqs=np.arange(0,Nk,1)*sample_rate/N\r\n\r\n#音声と雑音との比率 [dB]\r\nSNR=90.\r\n\r\n#方位角の閾値\r\nazimuth_th=30.\r\n\r\n#部屋の大きさ\r\nroom_dim = np.r_[10.0, 10.0, 10.0]\r\n\r\n#マイクロホンアレイを置く部屋の場所\r\nmic_array_loc = room_dim / 2 + np.random.randn(3) * 0.1 \r\n\r\n#マイクロホンアレイのマイク配置\r\nmic_directions=np.array(\r\n    [[np.pi/2., theta/180.*np.pi] for theta in np.arange(0,360,10)\r\n    ]    )\r\n\r\ndistance=0.02\r\nmic_alignments=np.zeros((3, mic_directions.shape[0]), dtype=mic_directions.dtype)\r\nmic_alignments[0, :] = np.cos(mic_directions[:, 1]) * np.sin(mic_directions[:, 0])\r\nmic_alignments[1, :] = np.sin(mic_directions[:, 1]) * np.sin(mic_directions[:, 0])\r\nmic_alignments[2, :] = np.cos(mic_directions[:, 0])\r\nmic_alignments *= distance\r\n\r\n#マイクロホン数\r\nn_channels=np.shape(mic_alignments)[1]\r\n\r\n#マイクロホンアレイの座標\r\nR=mic_alignments+mic_array_loc[:,None]\r\n\r\n# 部屋を生成する\r\nroom = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\nroom_no_noise_left = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\nroom_no_noise_right = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\n\r\n# 用いるマイクロホンアレイの情報を設定する\r\nroom.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\nroom_no_noise_left.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\nroom_no_noise_right.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\n\r\n#音源の場所\r\ndoas=np.array(\r\n    [[np.pi/2., np.pi],\r\n     [np.pi/2., 0]\r\n    ]    )\r\n\r\n#音源とマイクロホンの距離\r\ndistance=1.\r\nsource_locations=np.zeros((3, doas.shape[0]), dtype=doas.dtype)\r\nsource_locations[0, :] = np.cos(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[1, :] = np.sin(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[2, :] = np.cos(doas[:, 0])\r\nsource_locations *= distance\r\nsource_locations += mic_array_loc[:, None]\r\n\r\n\r\n#ステアリングベクトルを算出するための仮想的な音源方向\r\nvirtual_doas=np.array(\r\n    [[np.pi/2., theta/180.*np.pi] for theta in np.arange(0,360,5)\r\n    ]    )\r\nvirtual_source_locations=np.zeros((3, virtual_doas.shape[0]), dtype=virtual_doas.dtype)\r\nvirtual_source_locations[0, :] = np.cos(virtual_doas[:, 1]) * np.sin(virtual_doas[:, 0])\r\nvirtual_source_locations[1, :] = np.sin(virtual_doas[:, 1]) * np.sin(virtual_doas[:, 0])\r\nvirtual_source_locations[2, :] = np.cos(virtual_doas[:, 0])\r\nvirtual_source_locations *= 100.\r\nvirtual_source_locations += mic_array_loc[:, None]\r\n\r\n#仮想的な音源方向のステアリングベクトル作成 \r\n#virtual steering vector: (Nk x Ns x M)\r\nvirtual_steering_vectors=calculate_steering_vector(R,virtual_source_locations,freqs,is_use_far=True)\r\n\r\ndef modify_angle_diff(diff):\r\n    diff=np.where(diff<-np.pi,diff+np.pi*2,diff)\r\n    diff=np.where(diff>np.pi,diff-np.pi*2,diff)\r\n    return(diff)\r\n\r\n#所望音の方向から±th度以内\r\nomega=np.array([ np.abs(modify_angle_diff(virtual_doas[:,1]-doas[s,1]))<azimuth_th/180.*np.pi   for s in range(n_sim_sources)]).astype(np.float)\r\n\r\n#各音源をシミュレーションに追加する\r\nfor s in range(n_sim_sources):\r\n    clean_data[s]/= np.std(clean_data[s])\r\n    room.add_source(source_locations[:, s], signal=clean_data[s])\r\n    if s==0:\r\n        room_no_noise_left.add_source(source_locations[:, s], signal=clean_data[s])\r\n    if s==1:\r\n        room_no_noise_right.add_source(source_locations[:, s], signal=clean_data[s])\r\n\r\n#シミュレーションを回す\r\nroom.simulate(snr=SNR)\r\nroom_no_noise_left.simulate(snr=90)\r\nroom_no_noise_right.simulate(snr=90)\r\n\r\n#畳み込んだ波形を取得する(チャンネル、サンプル）\r\nmulti_conv_data=room.mic_array.signals\r\nmulti_conv_data_left_no_noise=room_no_noise_left.mic_array.signals\r\nmulti_conv_data_right_no_noise=room_no_noise_right.mic_array.signals\r\n\r\n\r\n\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data_left_no_noise[0,:]*np.iinfo(np.int16).max/20.,\"./doa_left_clean.wav\",sample_rate)\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data_right_no_noise[0,:]*np.iinfo(np.int16).max/20.,\"./doa_right_clean.wav\",sample_rate)\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data[0,:]*np.iinfo(np.int16).max/20.,\"./doa_in_left.wav\",sample_rate)\r\nwrite_file_from_time_signal(multi_conv_data[0,:]*np.iinfo(np.int16).max/20.,\"./doa_in_right.wav\",sample_rate)\r\n\r\n#短時間フーリエ変換を行う\r\nf,t,stft_data=sp.stft(multi_conv_data,fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\n#DOA情報を使って分離\r\ny_doa=execute_doa_sparse_separation(stft_data,virtual_steering_vectors,omega)\r\n\r\n\r\n#時間領域の波形に戻す\r\nt,y_doa_left=sp.istft(y_doa[0,0,...],fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,y_doa_right=sp.istft(y_doa[0,1,...],fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\n\r\n#SNRを計算\r\nsnr_pre=calculate_snr(multi_conv_data_left_no_noise[0,...],multi_conv_data[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],multi_conv_data[0,...])\r\nsnr_doa_post=calculate_snr(multi_conv_data_left_no_noise[0,...],y_doa_left)+calculate_snr(multi_conv_data_right_no_noise[0,...],y_doa_right)\r\nsnr_pre/=2.\r\nsnr_doa_post/=2.\r\n\r\n#ファイルに書き込む\r\nwrite_file_from_time_signal(y_doa_left*np.iinfo(np.int16).max/20.,\"./sparse_doa_left.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_doa_right*np.iinfo(np.int16).max/20.,\"./sparse_doa_right.wav\",sample_rate)\r\n\r\n\r\nprint(\"method:    \", \"DOA\")\r\n\r\nprint(\"Δsnr [dB]: {:.2f} \".format(snr_doa_post-snr_pre))\r\n"
  },
  {
    "path": "section7/sample_code_c7_4.py",
    "content": "\r\n\r\nimport wave as wave\r\nimport pyroomacoustics as pa\r\nimport numpy as np\r\nimport scipy.signal as sp\r\nimport scipy as scipy\r\n\r\n\r\n\r\n#2バイトに変換してファイルに保存\r\n#signal: time-domain 1d array (float)\r\n#file_name: 出力先のファイル名\r\n#sample_rate: サンプリングレート\r\ndef write_file_from_time_signal(signal,file_name,sample_rate):\r\n    #2バイトのデータに変換\r\n    signal=signal.astype(np.int16)\r\n\r\n    #waveファイルに書き込む\r\n    wave_out = wave.open(file_name, 'w')\r\n\r\n    #モノラル:1、ステレオ:2\r\n    wave_out.setnchannels(1)\r\n\r\n    #サンプルサイズ2byte\r\n    wave_out.setsampwidth(2)\r\n\r\n    #サンプリング周波数\r\n    wave_out.setframerate(sample_rate)\r\n\r\n    #データを書き込み\r\n    wave_out.writeframes(signal)\r\n\r\n    #ファイルを閉じる\r\n    wave_out.close()\r\n\r\n\r\n#ステアリングベクトルを算出\r\n#mic_position: 3 x M  dimensional ndarray [[x,y,z],[x,y,z]]\r\n#source_position: 3x Ns dimensional ndarray [[x,y,z],[x,y,z] ]\r\n#freqs: Nk dimensional array [f1,f2,f3...]\r\n#sound_speed: 音速 [m/s]\r\n#is_use_far: Farを使う場合はTrue, Nearの場合はFalse, \r\n#return: steering vector (Nk x Ns x M)\r\ndef calculate_steering_vector(mic_alignments,source_locations,freqs,sound_speed=340,is_use_far=False):\r\n    #マイク数を取得\r\n    n_channels=np.shape(mic_alignments)[1]\r\n\r\n    #音源数を取得\r\n    n_source=np.shape(source_locations)[1]\r\n\r\n    if is_use_far==True:\r\n        #音源位置を正規化\r\n        norm_source_locations=source_locations/np.linalg.norm(source_locations,2,axis=0,keepdims=True)\r\n\r\n        #位相を求める\r\n        steering_phase=np.einsum('k,ism,ism->ksm',2.j*np.pi/sound_speed*freqs,norm_source_locations[...,None],mic_alignments[:,None,:])\r\n\r\n        #ステアリングベクトルを算出\r\n        steering_vector=1./np.sqrt(n_channels)*np.exp(steering_phase)\r\n\r\n        return(steering_vector)\r\n\r\n    else:\r\n\r\n        #音源とマイクの距離を求める\r\n        #distance: Ns x Nm\r\n        distance=np.sqrt(np.sum(np.square(source_locations[...,None]-mic_alignments[:,None,:]),axis=0))\r\n\r\n        #遅延時間(delay) [sec]\r\n        delay=distance/sound_speed\r\n\r\n        #ステアリングベクトルの位相を求める\r\n        steering_phase=np.einsum('k,sm->ksm',-2.j*np.pi*freqs,delay)\r\n    \r\n        #音量の減衰\r\n        steering_decay_ratio=1./distance\r\n\r\n        #ステアリングベクトルを求める\r\n        steering_vector=steering_decay_ratio[None,...]*np.exp(steering_phase)\r\n\r\n        #大きさを1で正規化する\r\n        steering_vector=steering_vector/np.linalg.norm(steering_vector,2,axis=2,keepdims=True)\r\n\r\n    return(steering_vector)\r\n\r\n#共分散行列からステアリングベクトルを推定する\r\n#Rs: 共分散行列(Ns, Nk, M, M)\r\n#steering_vector(Ns, Nk, M)\r\ndef estimate_steering_vector(Rs):\r\n\r\n    #固有値分解を実施して最大固有値を与える固有ベクトルを取得\r\n    w,v=np.linalg.eigh(Rs)\r\n    steering_vector=v[...,-1]\r\n    return(steering_vector)\r\n\r\n#マスクと入力信号から共分散行列を推定\r\n#x:入力信号(M,Nk,Lt)\r\n#mask：音源毎の時間周波数マスク(Ns, Nk, Lt)\r\n#return Rs 音源共分散行列(Ns, Nk,M,M), Rn 雑音共分散行列(Ns, Nk,M,M)\r\ndef estimate_covariance_matrix(x,mask):\r\n    \r\n    #目的音の共分散行列を推定する\r\n    Rs=np.einsum(\"skt,mkt,nkt->skmn\",mask,x,np.conjugate(x))\r\n    sum_mask=np.sum(mask,axis=2)\r\n    Rs=Rs/np.maximum(sum_mask,1.e-18)[...,None,None]\r\n\r\n    #雑音共分散行列を推定する\r\n    Rn=np.einsum(\"skt,mkt,nkt->skmn\",1.-mask,x,np.conjugate(x))\r\n    sum_noise_mask=np.sum(1.-mask,axis=2)\r\n    Rn=Rn/np.maximum(sum_noise_mask,1.e-18)[...,None,None]\r\n\r\n    \r\n    #固有値分解をして半正定行列に変換\r\n    w,v=np.linalg.eigh(Rs)\r\n    Rs_org=Rs.copy()\r\n    w[np.real(w)<1.e-18]=1.e-18\r\n    Rs=np.einsum(\"skmi,ski,skni->skmn\",v,w,np.conjugate(v))\r\n    w,v=np.linalg.eigh(Rn)\r\n    Rn_org=Rn.copy()\r\n    w[np.real(w)<1.e-18]=1.e-18\r\n    Rn=np.einsum(\"skmi,ski,skni->skmn\",v,w,np.conjugate(v))\r\n\r\n    return(Rs,Rn)\r\n\r\n#スパース性に基づく分離\r\n#x:入力信号(M,Nk,Lt)\r\n#mask：音源毎の時間周波数マスク(Ns, Nk, Lt)\r\n#return c_hat：出力信号(Nm,Ns,Nk, Lt)\r\ndef execute_sparse(x,mask):\r\n\r\n\r\n    c_hat=np.einsum(\"skt,mkt->mskt\",mask,x)\r\n\r\n    return(c_hat)\r\n\r\n#ファイルに書き込む\r\n#MWFを実行する\r\n#x:入力信号( M, Nk, Lt)\r\n#Rn: 雑音共分散行列(Ns, Nk,M,M)\r\n#Rs: 音源共分散行列(Ns, Nk,M,M)\r\n#return c_hat 出力信号(M, Ns,Nk, Lt)\r\ndef execute_mwf(x,Rn,Rs):\r\n    \r\n    #入力信号に対する共分散行列の逆行列を計算\r\n    Rx_inverse=np.linalg.pinv(Rn+Rs)\r\n    \r\n    #フィルタ生成\r\n    W_mwf=np.einsum(\"skmi,skin->skmn\",Rx_inverse,Rs)\r\n    \r\n    #フィルタをかける\r\n    c_hat=np.einsum(\"skim,ikt->mskt\",np.conjugate(W_mwf),x)\r\n\r\n    return(c_hat)\r\n\r\n#遅延和アレイを実行する\r\n#x:入力信号( M, Nk, Lt)\r\n#a:ステアリングベクトル(Ns,Nk, M)\r\n#return c_hat 出力信号(M, Ns,Nk, Lt)\r\ndef execute_dsbf(x,a):\r\n\r\n    #遅延和アレイを実行する\r\n    s_hat=np.einsum(\"skm,mkt->skt\",np.conjugate(a),x)\r\n\r\n    #ステアリングベクトルをかける\r\n    c_hat=np.einsum(\"skt,skm->mskt\",s_hat,a)\r\n\r\n    return(c_hat)\r\n\r\n#MVDRを実行する\r\n#x:入力信号( M, Nk, Lt)\r\n#Rn: 雑音共分散行列(Ns, Nk,M,M)\r\n#a:ステアリングベクトル(Ns,Nk, M)\r\n#return c_hat 出力信号(M, Ns,Nk, Lt)\r\ndef execute_mvdr(x,Rn,a):\r\n\r\n    #共分散行列の逆行列を計算する\r\n    Rn_inverse=np.linalg.pinv(Rn)\r\n\r\n    #フィルタを計算する\r\n    Rn_inverse_a=np.einsum(\"skmn,skn->skm\",Rn_inverse,a)\r\n    a_H_Rn_inverse_a=np.einsum(\"skn,skn->sk\",np.conjugate(a),Rn_inverse_a)\r\n    w_mvdr=Rn_inverse_a/np.maximum(a_H_Rn_inverse_a,1.e-18)[...,None]\r\n\r\n    #フィルタをかける\r\n    s_hat=np.einsum(\"skm,mkt->skt\",np.conjugate(w_mvdr),x)\r\n\r\n    #ステアリングベクトルをかける\r\n    c_hat=np.einsum(\"skt,skm->mskt\",s_hat,a)\r\n    \r\n    return(c_hat)\r\n\r\n#MVDR2を実行する(共分散行列のみから計算)\r\n#x:入力信号( M, Nk, Lt)\r\n#Rn: 雑音共分散行列(Ns, Nk,M,M)\r\n#Rs:目的音の共分散行列(Ns,Nk, M,M)\r\n#return c_hat 出力信号(M, Ns,Nk, Lt)\r\ndef execute_mvdr2(x,Rn,Rs):\r\n\r\n    #共分散行列の逆行列を計算する\r\n    Rn_inverse=np.linalg.pinv(Rn)\r\n\r\n    #フィルタを計算する\r\n    Rn_inverse_Rs=np.einsum(\"skmi,skin->skmn\",Rn_inverse,Rs)\r\n    \r\n    w_mvdr=Rn_inverse_Rs/np.maximum(np.trace(Rn_inverse_Rs,axis1=-2,axis2=-1),1.e-18)[...,None,None]\r\n\r\n    #フィルタをかける\r\n    c_hat=np.einsum(\"skmn,mkt->nskt\",np.conjugate(w_mvdr),x)\r\n\r\n    return(c_hat)\r\n\r\n#MaxSNRを実行する\r\n#x:入力信号( M, Nk, Lt)\r\n#Rn: 雑音共分散行列(Ns, Nk,M,M)\r\n#Rs:目的音の共分散行列(Ns,Nk, M,M)\r\n#return c_hat 出力信号(M, Ns,Nk, Lt)\r\ndef execute_max_snr(x,Rn,Rs):\r\n   \r\n    #音源・周波数・マイクロホンの数を取得\r\n    Ns=np.shape(Rs)[0]\r\n    Nk=np.shape(Rs)[1]\r\n    M=np.shape(Rs)[2]\r\n\r\n    #一般化固有値分解\r\n    max_snr_filter=None\r\n    for s in range(Ns):\r\n        for k in range(Nk):\r\n            w,v=scipy.linalg.eigh(Rs[s,k,...],Rn[s,k,...])\r\n            if max_snr_filter is None:\r\n                max_snr_filter=v[None,:,-1]\r\n            else:\r\n                max_snr_filter=np.concatenate((max_snr_filter,v[None,:,-1]),axis=0)\r\n    max_snr_filter=np.reshape(max_snr_filter,(Ns,Nk,M))\r\n\r\n    Rs_w=np.einsum(\"skmn,skn->skm\",Rs,max_snr_filter)\r\n    beta=Rs_w/np.einsum(\"skm,skm->sk\",np.conjugate(max_snr_filter),Rs_w)[...,None]\r\n    w_max_snr=beta[...,None,:]*max_snr_filter[...,None]\r\n    \r\n    #フィルタをかける\r\n    c_hat=np.einsum(\"skim,ikt->mskt\",np.conjugate(w_max_snr),x)\r\n    \r\n    return(c_hat)\r\n\r\n#時間周波数マスクを推定する\r\n#input_vectors:マイクロホン入力信号(Nm,Nk, Lt)\r\n#steering_vectors:ステアリングベクトル(Nk,|Ω|,Nm)\r\n#omega: 目的音の範囲(Ns,|Ω|) \r\n#return mask：出力信号(Ns,Nk, Lt)\r\ndef estimate_mask(input_vectors,steering_vectors,omega):\r\n    inner_product=np.einsum(\"kim,mkt->kit\",np.conjugate(steering_vectors),input_vectors)\r\n    \r\n    n_omega=np.shape(omega)[1]\r\n\r\n    estimate_doas=np.argmax(np.abs(inner_product),axis=1)\r\n\r\n    estimate_doa_mask=np.identity(n_omega)[estimate_doas]\r\n\r\n    mask=np.einsum(\"kti,si->skt\",estimate_doa_mask,omega)\r\n\r\n    return(mask)\r\n\r\n\r\n#SNRをはかる\r\n#desired: 目的音、Lt\r\n#out:　雑音除去後の信号 Lt\r\ndef calculate_snr(desired,out):\r\n    wave_length=np.minimum(np.shape(desired)[0],np.shape(out)[0])\r\n\r\n    #消し残った雑音\r\n    desired=desired[:wave_length]\r\n    out=out[:wave_length]\r\n    noise=desired-out\r\n    snr=10.*np.log10(np.sum(np.square(desired))/np.sum(np.square(noise)))\r\n\r\n    return(snr)\r\n\r\n#乱数の種を初期化\r\nnp.random.seed(0)\r\n\r\n#畳み込みに用いる音声波形\r\nclean_wave_files=[\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\",\"./CMU_ARCTIC/cmu_us_axb_arctic/wav/arctic_a0002.wav\"]\r\n\r\n#音源数\r\nn_sources=len(clean_wave_files)\r\n\r\n#長さを調べる\r\nn_samples=0\r\n#ファイルを読み込む\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    if n_samples<wav.getnframes():\r\n        n_samples=wav.getnframes()\r\n    wav.close()\r\n\r\nclean_data=np.zeros([n_sources,n_samples])\r\n\r\n#ファイルを読み込む\r\ns=0\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    data=wav.readframes(wav.getnframes())\r\n    data=np.frombuffer(data, dtype=np.int16)\r\n    data=data/np.iinfo(np.int16).max\r\n    clean_data[s,:wav.getnframes()]=data\r\n    wav.close()\r\n    s=s+1\r\n\r\n\r\n# シミュレーションのパラメータ\r\n\r\n#シミュレーションで用いる音源数\r\nn_sim_sources=2\r\n\r\n#サンプリング周波数\r\nsample_rate=16000\r\n\r\n#フレームサイズ\r\nN=1024\r\n\r\n#周波数の数\r\nNk=int(N/2+1)\r\n\r\n#各ビンの周波数\r\nfreqs=np.arange(0,Nk,1)*sample_rate/N\r\n\r\n#音声と雑音との比率 [dB]\r\nSNR=90.\r\n\r\n#方位角の閾値\r\nazimuth_th=30.\r\n\r\n#部屋の大きさ\r\nroom_dim = np.r_[10.0, 10.0, 10.0]\r\n\r\n#マイクロホンアレイを置く部屋の場所\r\nmic_array_loc = room_dim / 2 + np.random.randn(3) * 0.1 \r\n\r\n#マイクロホンアレイのマイク配置\r\nmic_directions=np.array(\r\n    [[np.pi/2., theta/180.*np.pi] for theta in np.arange(180,361,180)\r\n    ]    )\r\n\r\ndistance=0.01\r\nmic_alignments=np.zeros((3, mic_directions.shape[0]), dtype=mic_directions.dtype)\r\nmic_alignments[0, :] = np.cos(mic_directions[:, 1]) * np.sin(mic_directions[:, 0])\r\nmic_alignments[1, :] = np.sin(mic_directions[:, 1]) * np.sin(mic_directions[:, 0])\r\nmic_alignments[2, :] = np.cos(mic_directions[:, 0])\r\nmic_alignments *= distance\r\n\r\n#マイクロホン数\r\nn_channels=np.shape(mic_alignments)[1]\r\n\r\n#マイクロホンアレイの座標\r\nR=mic_alignments+mic_array_loc[:,None]\r\n\r\n# 部屋を生成する\r\nroom = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\nroom_no_noise_left = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\nroom_no_noise_right = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\n\r\n# 用いるマイクロホンアレイの情報を設定する\r\nroom.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\nroom_no_noise_left.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\nroom_no_noise_right.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\n\r\n#音源の場所\r\ndoas=np.array(\r\n    [[np.pi/2., np.pi],\r\n     [np.pi/2., 0]\r\n    ]    )\r\n\r\n#音源の誤差\r\ndoas_error=np.array(\r\n    [[0., 5./180.*np.pi],\r\n     [0., 5./180.*np.pi]\r\n    ]    )\r\n#音源とマイクロホンの距離\r\ndistance=1.\r\ndoas2=doas+doas_error\r\n\r\nsource_locations=np.zeros((3, doas2.shape[0]), dtype=doas2.dtype)\r\nsource_locations[0, :] = np.cos(doas2[:, 1]) * np.sin(doas2[:, 0])\r\nsource_locations[1, :] = np.sin(doas2[:, 1]) * np.sin(doas2[:, 0])\r\nsource_locations[2, :] = np.cos(doas2[:, 0])\r\nsource_locations *= distance\r\nsource_locations += mic_array_loc[:, None]\r\n\r\n\r\n#ステアリングベクトルを算出するための仮想的な音源方向\r\nvirtual_doas=np.array(\r\n    [[np.pi/2., theta/180.*np.pi] for theta in np.arange(0,360,5)\r\n    ]    )\r\nvirtual_source_locations=np.zeros((3, virtual_doas.shape[0]), dtype=virtual_doas.dtype)\r\nvirtual_source_locations[0, :] = np.cos(virtual_doas[:, 1]) * np.sin(virtual_doas[:, 0])\r\nvirtual_source_locations[1, :] = np.sin(virtual_doas[:, 1]) * np.sin(virtual_doas[:, 0])\r\nvirtual_source_locations[2, :] = np.cos(virtual_doas[:, 0])\r\nvirtual_source_locations *= 100.\r\nvirtual_source_locations += mic_array_loc[:, None]\r\n\r\n#仮想的な音源方向のステアリングベクトル作成 \r\n#virtual steering vector: (Nk x Ns x M)\r\nvirtual_steering_vectors=calculate_steering_vector(R,virtual_source_locations,freqs,is_use_far=True)\r\n\r\ndef modify_angle_diff(diff):\r\n    diff=np.where(diff<-np.pi,diff+np.pi*2,diff)\r\n    diff=np.where(diff>np.pi,diff-np.pi*2,diff)\r\n    return(diff)\r\n\r\n#所望音の方向から±th度以内\r\nomega=np.array([ np.abs(modify_angle_diff(virtual_doas[:,1]-doas[s,1]))<azimuth_th/180.*np.pi   for s in range(n_sim_sources)]).astype(np.float)\r\n\r\n#各音源をシミュレーションに追加する\r\nfor s in range(n_sim_sources):\r\n    clean_data[s]/= np.std(clean_data[s])\r\n    room.add_source(source_locations[:, s], signal=clean_data[s])\r\n    if s==0:\r\n        room_no_noise_left.add_source(source_locations[:, s], signal=clean_data[s])\r\n    if s==1:\r\n        room_no_noise_right.add_source(source_locations[:, s], signal=clean_data[s])\r\n\r\n#シミュレーションを回す\r\nroom.simulate(snr=SNR)\r\nroom_no_noise_left.simulate(snr=90)\r\nroom_no_noise_right.simulate(snr=90)\r\n\r\n#畳み込んだ波形を取得する(チャンネル、サンプル）\r\nmulti_conv_data=room.mic_array.signals\r\nmulti_conv_data_left_no_noise=room_no_noise_left.mic_array.signals\r\nmulti_conv_data_right_no_noise=room_no_noise_right.mic_array.signals\r\n\r\n\r\n\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data_left_no_noise[0,:]*np.iinfo(np.int16).max/20.,\"./doa_bf_left_clean.wav\",sample_rate)\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data_right_no_noise[0,:]*np.iinfo(np.int16).max/20.,\"./doa_bf_right_clean.wav\",sample_rate)\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data[0,:]*np.iinfo(np.int16).max/20.,\"./doa_bf_in_left.wav\",sample_rate)\r\nwrite_file_from_time_signal(multi_conv_data[0,:]*np.iinfo(np.int16).max/20.,\"./doa_bf_in_right.wav\",sample_rate)\r\n\r\n#短時間フーリエ変換を行う\r\nf,t,stft_data=sp.stft(multi_conv_data,fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\n#時間周波数マスクを推定する\r\ntf_mask=estimate_mask(stft_data,virtual_steering_vectors,omega)\r\n\r\n#共分散行列とステアリングベクトルを推定\r\nRs,Rn=estimate_covariance_matrix(stft_data,tf_mask)\r\ndesired_steering_vectors=estimate_steering_vector(Rs)\r\n\r\n#各フィルタを実行する\r\ny_sparse=execute_sparse(stft_data,tf_mask)\r\ny_dsbf=execute_dsbf(stft_data,desired_steering_vectors)\r\ny_mvdr=execute_mvdr(stft_data,Rn,desired_steering_vectors)\r\ny_mvdr2=execute_mvdr2(stft_data,Rn,Rs)\r\ny_max_snr=execute_max_snr(stft_data,Rn,Rs)\r\ny_mwf=execute_mwf(stft_data,Rn,Rs)\r\n\r\n\r\n\r\n#時間領域の波形に戻す\r\nt,y_sparse=sp.istft(y_sparse[0,...],fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,y_dsbf=sp.istft(y_dsbf[0,...],fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,y_mvdr=sp.istft(y_mvdr[0,...],fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,y_mvdr2=sp.istft(y_mvdr2[0,...],fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,y_max_snr=sp.istft(y_max_snr[0,...],fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,y_mwf=sp.istft(y_mwf[0,...],fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\n\r\n#SNRをはかる\r\nsnr_pre=calculate_snr(multi_conv_data_left_no_noise[0,...],multi_conv_data[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],multi_conv_data[0,...])\r\nsnr_doa_sparse_post=calculate_snr(multi_conv_data_left_no_noise[0,...],y_sparse[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_sparse[1,...])\r\nsnr_doa_dsbf_post=calculate_snr(multi_conv_data_left_no_noise[0,...],y_dsbf[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_dsbf[1,...])\r\nsnr_doa_mvdr_post=calculate_snr(multi_conv_data_left_no_noise[0,...],y_mvdr[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_mvdr[1,...])\r\nsnr_doa_mvdr2_post=calculate_snr(multi_conv_data_left_no_noise[0,...],y_mvdr2[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_mvdr2[1,...])\r\nsnr_doa_max_snr_post=calculate_snr(multi_conv_data_left_no_noise[0,...],y_max_snr[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_max_snr[1,...])\r\nsnr_doa_mwf_post=calculate_snr(multi_conv_data_left_no_noise[0,...],y_mwf[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_mwf[1,...])\r\n\r\nsnr_pre/=2.\r\nsnr_doa_sparse_post/=2.\r\nsnr_doa_dsbf_post/=2.\r\nsnr_doa_mvdr_post/=2.\r\nsnr_doa_mvdr2_post/=2.\r\nsnr_doa_max_snr_post/=2.\r\nsnr_doa_mwf_post/=2.\r\n\r\n#ファイルに書き込む\r\nwrite_file_from_time_signal(y_sparse[0,...]*np.iinfo(np.int16).max/20.,\"./sparse_doa_sparse_left.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_sparse[1,...]*np.iinfo(np.int16).max/20.,\"./sparse_doa_sparse_right.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_dsbf[0,...]*np.iinfo(np.int16).max/20.,\"./sparse_doa_dsbf_left.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_dsbf[1,...]*np.iinfo(np.int16).max/20.,\"./sparse_doa_dsbf_right.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_mvdr[0,...]*np.iinfo(np.int16).max/20.,\"./sparse_doa_mvdr_left.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_mvdr[1,...]*np.iinfo(np.int16).max/20.,\"./sparse_doa_mvdr_right.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_mvdr2[0,...]*np.iinfo(np.int16).max/20.,\"./sparse_doa_mvdr2_left.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_mvdr2[1,...]*np.iinfo(np.int16).max/20.,\"./sparse_doa_mvdr2_right.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_max_snr[0,...]*np.iinfo(np.int16).max/20.,\"./sparse_doa_max_snr_left.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_max_snr[1,...]*np.iinfo(np.int16).max/20.,\"./sparse_doa_max_snr_right.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_mwf[0,...]*np.iinfo(np.int16).max/20.,\"./sparse_doa_mwf_left.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_mwf[1,...]*np.iinfo(np.int16).max/20.,\"./sparse_doa_mwf_right.wav\",sample_rate)\r\n\r\n\r\n\r\nprint(\"method:    \", \"DOA_SPARSE\",\"DOA_DSBF\",\"DOA_MVDR\", \"DOA_MVDR2\", \"DOA_MAX_SNR\",\"DOA_MWF\")\r\n\r\nprint(\"Δsnr [dB]: {:.2f}       {:.2f}     {:.2f}    {:.2f}     {:.2f}       {:.2f}\".format(snr_doa_sparse_post-snr_pre,snr_doa_dsbf_post-snr_pre,snr_doa_mvdr_post-snr_pre,snr_doa_mvdr2_post-snr_pre,snr_doa_max_snr_post-snr_pre,snr_doa_mwf_post-snr_pre))\r\n"
  },
  {
    "path": "section7/sample_code_c7_5.py",
    "content": "\r\n\r\nimport wave as wave\r\nimport pyroomacoustics as pa\r\nimport numpy as np\r\nimport scipy.signal as sp\r\nimport scipy as scipy\r\n\r\n\r\n\r\n#2バイトに変換してファイルに保存\r\n#signal: time-domain 1d array (float)\r\n#file_name: 出力先のファイル名\r\n#sample_rate: サンプリングレート\r\ndef write_file_from_time_signal(signal,file_name,sample_rate):\r\n    #2バイトのデータに変換\r\n    signal=signal.astype(np.int16)\r\n\r\n    #waveファイルに書き込む\r\n    wave_out = wave.open(file_name, 'w')\r\n\r\n    #モノラル:1、ステレオ:2\r\n    wave_out.setnchannels(1)\r\n\r\n    #サンプルサイズ2byte\r\n    wave_out.setsampwidth(2)\r\n\r\n    #サンプリング周波数\r\n    wave_out.setframerate(sample_rate)\r\n\r\n    #データを書き込み\r\n    wave_out.writeframes(signal)\r\n\r\n    #ファイルを閉じる\r\n    wave_out.close()\r\n\r\n\r\n#ステアリングベクトルを算出\r\n#mic_position: 3 x M  dimensional ndarray [[x,y,z],[x,y,z]]\r\n#source_position: 3x Ns dimensional ndarray [[x,y,z],[x,y,z] ]\r\n#freqs: Nk dimensional array [f1,f2,f3...]\r\n#sound_speed: 音速 [m/s]\r\n#is_use_far: Farを使う場合はTrue, Nearの場合はFalse, \r\n#return: steering vector (Nk x Ns x M)\r\ndef calculate_steering_vector(mic_alignments,source_locations,freqs,sound_speed=340,is_use_far=False):\r\n    #マイク数を取得\r\n    n_channels=np.shape(mic_alignments)[1]\r\n\r\n    #音源数を取得\r\n    n_source=np.shape(source_locations)[1]\r\n\r\n    if is_use_far==True:\r\n        #音源位置を正規化\r\n        norm_source_locations=source_locations/np.linalg.norm(source_locations,2,axis=0,keepdims=True)\r\n\r\n        #位相を求める\r\n        steering_phase=np.einsum('k,ism,ism->ksm',2.j*np.pi/sound_speed*freqs,norm_source_locations[...,None],mic_alignments[:,None,:])\r\n\r\n        #ステアリングベクトルを算出\r\n        steering_vector=1./np.sqrt(n_channels)*np.exp(steering_phase)\r\n\r\n        return(steering_vector)\r\n\r\n    else:\r\n\r\n        #音源とマイクの距離を求める\r\n        #distance: Ns x Nm\r\n        distance=np.sqrt(np.sum(np.square(source_locations[...,None]-mic_alignments[:,None,:]),axis=0))\r\n\r\n        #遅延時間(delay) [sec]\r\n        delay=distance/sound_speed\r\n\r\n        #ステアリングベクトルの位相を求める\r\n        steering_phase=np.einsum('k,sm->ksm',-2.j*np.pi*freqs,delay)\r\n    \r\n        #音量の減衰\r\n        steering_decay_ratio=1./distance\r\n\r\n        #ステアリングベクトルを求める\r\n        steering_vector=steering_decay_ratio[None,...]*np.exp(steering_phase)\r\n\r\n        #大きさを1で正規化する\r\n        steering_vector=steering_vector/np.linalg.norm(steering_vector,2,axis=2,keepdims=True)\r\n\r\n    return(steering_vector)\r\n\r\n#共分散行列からステアリングベクトルを推定する\r\n#Rs: 共分散行列(Ns, Nk, M, M)\r\n#steering_vector(Ns, Nk, M)\r\ndef estimate_steering_vector(Rs):\r\n\r\n    #固有値分解を実施して最大固有値を与える固有ベクトルを取得\r\n    w,v=np.linalg.eigh(Rs)\r\n    steering_vector=v[...,-1]\r\n    return(steering_vector)\r\n\r\n#マスクと入力信号から共分散行列を推定\r\n#x:入力信号(M,Nk,Lt)\r\n#mask：音源毎の時間周波数マスク(Ns, Nk, Lt)\r\n#return Rs 音源共分散行列(Ns, Nk,M,M), Rn 雑音共分散行列(Ns, Nk,M,M)\r\ndef estimate_covariance_matrix(x,mask):\r\n    \r\n    #目的音の共分散行列を推定する\r\n    Rs=np.einsum(\"skt,mkt,nkt->skmn\",mask,x,np.conjugate(x))\r\n    sum_mask=np.sum(mask,axis=2)\r\n    Rs=Rs/np.maximum(sum_mask,1.e-18)[...,None,None]\r\n\r\n    #雑音共分散行列を推定する\r\n    Rn=np.einsum(\"skt,mkt,nkt->skmn\",1.-mask,x,np.conjugate(x))\r\n    sum_noise_mask=np.sum(1.-mask,axis=2)\r\n    Rn=Rn/np.maximum(sum_noise_mask,1.e-18)[...,None,None]\r\n\r\n    \r\n    #固有値分解をして半正定行列に変換\r\n    w,v=np.linalg.eigh(Rs)\r\n    Rs_org=Rs.copy()\r\n    w[np.real(w)<1.e-18]=1.e-18\r\n    Rs=np.einsum(\"skmi,ski,skni->skmn\",v,w,np.conjugate(v))\r\n    w,v=np.linalg.eigh(Rn)\r\n    Rn_org=Rn.copy()\r\n    w[np.real(w)<1.e-18]=1.e-18\r\n    Rn=np.einsum(\"skmi,ski,skni->skmn\",v,w,np.conjugate(v))\r\n\r\n    return(Rs,Rn)\r\n\r\n#スパース性に基づく分離\r\n#x:入力信号(M,Nk,Lt)\r\n#mask：音源毎の時間周波数マスク(Ns, Nk, Lt)\r\n#return c_hat：出力信号(Nm,Ns,Nk, Lt)\r\ndef execute_sparse(x,mask):\r\n\r\n\r\n    c_hat=np.einsum(\"skt,mkt->mskt\",mask,x)\r\n\r\n    return(c_hat)\r\n\r\n#ファイルに書き込む\r\n#MWFを実行する\r\n#x:入力信号( M, Nk, Lt)\r\n#Rn: 雑音共分散行列(Ns, Nk,M,M)\r\n#Rs: 音源共分散行列(Ns, Nk,M,M)\r\n#return c_hat 出力信号(M, Ns,Nk, Lt)\r\ndef execute_mwf(x,Rn,Rs):\r\n    \r\n    #入力信号に対する共分散行列の逆行列を計算\r\n    Rx_inverse=np.linalg.pinv(Rn+Rs)\r\n    \r\n    #フィルタ生成\r\n    W_mwf=np.einsum(\"skmi,skin->skmn\",Rx_inverse,Rs)\r\n    \r\n    #フィルタをかける\r\n    c_hat=np.einsum(\"skim,ikt->mskt\",np.conjugate(W_mwf),x)\r\n\r\n    return(c_hat)\r\n\r\n#遅延和アレイを実行する\r\n#x:入力信号( M, Nk, Lt)\r\n#a:ステアリングベクトル(Ns,Nk, M)\r\n#return c_hat 出力信号(M, Ns,Nk, Lt)\r\ndef execute_dsbf(x,a):\r\n\r\n    #遅延和アレイを実行する\r\n    s_hat=np.einsum(\"skm,mkt->skt\",np.conjugate(a),x)\r\n\r\n    #ステアリングベクトルをかける\r\n    c_hat=np.einsum(\"skt,skm->mskt\",s_hat,a)\r\n\r\n    return(c_hat)\r\n\r\n#MVDRを実行する\r\n#x:入力信号( M, Nk, Lt)\r\n#Rn: 雑音共分散行列(Ns, Nk,M,M)\r\n#a:ステアリングベクトル(Ns,Nk, M)\r\n#return c_hat 出力信号(M, Ns,Nk, Lt)\r\ndef execute_mvdr(x,Rn,a):\r\n\r\n    #共分散行列の逆行列を計算する\r\n    Rn_inverse=np.linalg.pinv(Rn)\r\n\r\n    #フィルタを計算する\r\n    Rn_inverse_a=np.einsum(\"skmn,skn->skm\",Rn_inverse,a)\r\n    a_H_Rn_inverse_a=np.einsum(\"skn,skn->sk\",np.conjugate(a),Rn_inverse_a)\r\n    w_mvdr=Rn_inverse_a/np.maximum(a_H_Rn_inverse_a,1.e-18)[...,None]\r\n\r\n    #フィルタをかける\r\n    s_hat=np.einsum(\"skm,mkt->skt\",np.conjugate(w_mvdr),x)\r\n\r\n    #ステアリングベクトルをかける\r\n    c_hat=np.einsum(\"skt,skm->mskt\",s_hat,a)\r\n    \r\n    return(c_hat)\r\n\r\n#MVDR2を実行する(共分散行列のみから計算)\r\n#x:入力信号( M, Nk, Lt)\r\n#Rn: 雑音共分散行列(Ns, Nk,M,M)\r\n#Rs:目的音の共分散行列(Ns,Nk, M,M)\r\n#return c_hat 出力信号(M, Ns,Nk, Lt)\r\ndef execute_mvdr2(x,Rn,Rs):\r\n\r\n    #共分散行列の逆行列を計算する\r\n    Rn_inverse=np.linalg.pinv(Rn)\r\n\r\n    #フィルタを計算する\r\n    Rn_inverse_Rs=np.einsum(\"skmi,skin->skmn\",Rn_inverse,Rs)\r\n    \r\n    w_mvdr=Rn_inverse_Rs/np.maximum(np.trace(Rn_inverse_Rs,axis1=-2,axis2=-1),1.e-18)[...,None,None]\r\n\r\n    #フィルタをかける\r\n    c_hat=np.einsum(\"skmn,mkt->nskt\",np.conjugate(w_mvdr),x)\r\n\r\n    return(c_hat)\r\n\r\n#MaxSNRを実行する\r\n#x:入力信号( M, Nk, Lt)\r\n#Rn: 雑音共分散行列(Ns, Nk,M,M)\r\n#Rs:目的音の共分散行列(Ns,Nk, M,M)\r\n#return c_hat 出力信号(M, Ns,Nk, Lt)\r\ndef execute_max_snr(x,Rn,Rs):\r\n   \r\n    #音源・周波数・マイクロホンの数を取得\r\n    Ns=np.shape(Rs)[0]\r\n    Nk=np.shape(Rs)[1]\r\n    M=np.shape(Rs)[2]\r\n\r\n    #一般化固有値分解\r\n    max_snr_filter=None\r\n    for s in range(Ns):\r\n        for k in range(Nk):\r\n            w,v=scipy.linalg.eigh(Rs[s,k,...],Rn[s,k,...])\r\n            if max_snr_filter is None:\r\n                max_snr_filter=v[None,:,-1]\r\n            else:\r\n                max_snr_filter=np.concatenate((max_snr_filter,v[None,:,-1]),axis=0)\r\n    max_snr_filter=np.reshape(max_snr_filter,(Ns,Nk,M))\r\n\r\n    Rs_w=np.einsum(\"skmn,skn->skm\",Rs,max_snr_filter)\r\n    beta=Rs_w/np.einsum(\"skm,skm->sk\",np.conjugate(max_snr_filter),Rs_w)[...,None]\r\n    w_max_snr=beta[...,None,:]*max_snr_filter[...,None]\r\n    \r\n    #フィルタをかける\r\n    c_hat=np.einsum(\"skim,ikt->mskt\",np.conjugate(w_max_snr),x)\r\n    \r\n    return(c_hat)\r\n\r\n#時間周波数マスクを推定する\r\n#input_vectors:マイクロホン入力信号(Nm,Nk, Lt)\r\n#steering_vectors:ステアリングベクトル(Nk,|Ω|,Nm)\r\n#omega: 目的音の範囲(Ns,|Ω|) \r\n#return mask：出力信号(Ns,Nk, Lt)\r\ndef estimate_mask(input_vectors,steering_vectors,omega):\r\n    inner_product=np.einsum(\"kim,mkt->kit\",np.conjugate(steering_vectors),input_vectors)\r\n    \r\n    n_omega=np.shape(omega)[1]\r\n\r\n    estimate_doas=np.argmax(np.abs(inner_product),axis=1)\r\n\r\n    estimate_doa_mask=np.identity(n_omega)[estimate_doas]\r\n\r\n    mask=np.einsum(\"kti,si->skt\",estimate_doa_mask,omega)\r\n\r\n    return(mask)\r\n\r\n\r\n#SNRをはかる\r\n#desired: 目的音、Lt\r\n#out:　雑音除去後の信号 Lt\r\ndef calculate_snr(desired,out):\r\n    wave_length=np.minimum(np.shape(desired)[0],np.shape(out)[0])\r\n\r\n    #消し残った雑音\r\n    desired=desired[:wave_length]\r\n    out=out[:wave_length]\r\n    noise=desired-out\r\n    snr=10.*np.log10(np.sum(np.square(desired))/np.sum(np.square(noise)))\r\n\r\n    return(snr)\r\n\r\n#乱数の種を初期化\r\nnp.random.seed(0)\r\n\r\n#畳み込みに用いる音声波形\r\nclean_wave_files=[\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\",\"./CMU_ARCTIC/cmu_us_axb_arctic/wav/arctic_a0002.wav\"]\r\n\r\n#音源数\r\nn_sources=len(clean_wave_files)\r\n\r\n#長さを調べる\r\nn_samples=0\r\n#ファイルを読み込む\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    if n_samples<wav.getnframes():\r\n        n_samples=wav.getnframes()\r\n    wav.close()\r\n\r\nclean_data=np.zeros([n_sources,n_samples])\r\n\r\n#ファイルを読み込む\r\ns=0\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    data=wav.readframes(wav.getnframes())\r\n    data=np.frombuffer(data, dtype=np.int16)\r\n    data=data/np.iinfo(np.int16).max\r\n    clean_data[s,:wav.getnframes()]=data\r\n    wav.close()\r\n    s=s+1\r\n\r\n\r\n# シミュレーションのパラメータ\r\n\r\n#シミュレーションで用いる音源数\r\nn_sim_sources=2\r\n\r\n#サンプリング周波数\r\nsample_rate=16000\r\n\r\n#フレームサイズ\r\nN=1024\r\n\r\n#周波数の数\r\nNk=int(N/2+1)\r\n\r\n#各ビンの周波数\r\nfreqs=np.arange(0,Nk,1)*sample_rate/N\r\n\r\n#音声と雑音との比率 [dB]\r\nSNR=90.\r\n\r\n#方位角の閾値\r\nazimuth_th=30.\r\n\r\n#部屋の大きさ\r\nroom_dim = np.r_[10.0, 10.0, 10.0]\r\n\r\n#マイクロホンアレイを置く部屋の場所\r\nmic_array_loc = room_dim / 2 + np.random.randn(3) * 0.1 \r\n\r\n#マイクロホンアレイのマイク配置\r\nmic_directions=np.array(\r\n    [[np.pi/2., theta/180.*np.pi] for theta in np.arange(180,361,180)\r\n    ]    )\r\n\r\ndistance=0.01\r\nmic_alignments=np.zeros((3, mic_directions.shape[0]), dtype=mic_directions.dtype)\r\nmic_alignments[0, :] = np.cos(mic_directions[:, 1]) * np.sin(mic_directions[:, 0])\r\nmic_alignments[1, :] = np.sin(mic_directions[:, 1]) * np.sin(mic_directions[:, 0])\r\nmic_alignments[2, :] = np.cos(mic_directions[:, 0])\r\nmic_alignments *= distance\r\n\r\n#マイクロホン数\r\nn_channels=np.shape(mic_alignments)[1]\r\n\r\n#マイクロホンアレイの座標\r\nR=mic_alignments+mic_array_loc[:,None]\r\n\r\n# 部屋を生成する\r\nroom = pa.ShoeBox(room_dim, fs=sample_rate, max_order=17,absorption=0.4)\r\nroom_no_noise_left = pa.ShoeBox(room_dim, fs=sample_rate, max_order=17,absorption=0.4)\r\nroom_no_noise_right = pa.ShoeBox(room_dim, fs=sample_rate, max_order=17,absorption=0.4)\r\n\r\n# 用いるマイクロホンアレイの情報を設定する\r\nroom.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\nroom_no_noise_left.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\nroom_no_noise_right.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\n\r\n#音源の場所\r\ndoas=np.array(\r\n    [[np.pi/2., np.pi],\r\n     [np.pi/2., 0]\r\n    ]    )\r\n\r\n#音源の誤差\r\ndoas_error=np.array(\r\n    [[0., 5./180.*np.pi],\r\n     [0., 5./180.*np.pi]\r\n    ]    )\r\n#音源とマイクロホンの距離\r\ndistance=1.\r\ndoas2=doas+doas_error\r\n\r\nsource_locations=np.zeros((3, doas2.shape[0]), dtype=doas2.dtype)\r\nsource_locations[0, :] = np.cos(doas2[:, 1]) * np.sin(doas2[:, 0])\r\nsource_locations[1, :] = np.sin(doas2[:, 1]) * np.sin(doas2[:, 0])\r\nsource_locations[2, :] = np.cos(doas2[:, 0])\r\nsource_locations *= distance\r\nsource_locations += mic_array_loc[:, None]\r\n\r\n\r\n#ステアリングベクトルを算出するための仮想的な音源方向\r\nvirtual_doas=np.array(\r\n    [[np.pi/2., theta/180.*np.pi] for theta in np.arange(0,360,5)\r\n    ]    )\r\nvirtual_source_locations=np.zeros((3, virtual_doas.shape[0]), dtype=virtual_doas.dtype)\r\nvirtual_source_locations[0, :] = np.cos(virtual_doas[:, 1]) * np.sin(virtual_doas[:, 0])\r\nvirtual_source_locations[1, :] = np.sin(virtual_doas[:, 1]) * np.sin(virtual_doas[:, 0])\r\nvirtual_source_locations[2, :] = np.cos(virtual_doas[:, 0])\r\nvirtual_source_locations *= 100.\r\nvirtual_source_locations += mic_array_loc[:, None]\r\n\r\n#仮想的な音源方向のステアリングベクトル作成 \r\n#virtual steering vector: (Nk x Ns x M)\r\nvirtual_steering_vectors=calculate_steering_vector(R,virtual_source_locations,freqs,is_use_far=True)\r\n\r\ndef modify_angle_diff(diff):\r\n    diff=np.where(diff<-np.pi,diff+np.pi*2,diff)\r\n    diff=np.where(diff>np.pi,diff-np.pi*2,diff)\r\n    return(diff)\r\n\r\n#所望音の方向から±th度以内\r\nomega=np.array([ np.abs(modify_angle_diff(virtual_doas[:,1]-doas[s,1]))<azimuth_th/180.*np.pi   for s in range(n_sim_sources)]).astype(np.float)\r\n\r\n#各音源をシミュレーションに追加する\r\nfor s in range(n_sim_sources):\r\n    clean_data[s]/= np.std(clean_data[s])\r\n    room.add_source(source_locations[:, s], signal=clean_data[s])\r\n    if s==0:\r\n        room_no_noise_left.add_source(source_locations[:, s], signal=clean_data[s])\r\n    if s==1:\r\n        room_no_noise_right.add_source(source_locations[:, s], signal=clean_data[s])\r\n\r\n#シミュレーションを回す\r\nroom.simulate(snr=SNR)\r\nroom_no_noise_left.simulate(snr=90)\r\nroom_no_noise_right.simulate(snr=90)\r\n\r\n#畳み込んだ波形を取得する(チャンネル、サンプル）\r\nmulti_conv_data=room.mic_array.signals\r\nmulti_conv_data_left_no_noise=room_no_noise_left.mic_array.signals\r\nmulti_conv_data_right_no_noise=room_no_noise_right.mic_array.signals\r\n\r\n\r\n\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data_left_no_noise[0,:]*np.iinfo(np.int16).max/20.,\"./reverb_doa_bf_left_clean.wav\",sample_rate)\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data_right_no_noise[0,:]*np.iinfo(np.int16).max/20.,\"./reverb_doa_bf_right_clean.wav\",sample_rate)\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data[0,:]*np.iinfo(np.int16).max/20.,\"./reverb_doa_bf_in_left.wav\",sample_rate)\r\nwrite_file_from_time_signal(multi_conv_data[0,:]*np.iinfo(np.int16).max/20.,\"./reverb_doa_bf_in_right.wav\",sample_rate)\r\n\r\n#短時間フーリエ変換を行う\r\nf,t,stft_data=sp.stft(multi_conv_data,fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\n#時間周波数マスクを推定する\r\ntf_mask=estimate_mask(stft_data,virtual_steering_vectors,omega)\r\n\r\n#共分散行列とステアリングベクトルを推定\r\nRs,Rn=estimate_covariance_matrix(stft_data,tf_mask)\r\ndesired_steering_vectors=estimate_steering_vector(Rs)\r\n\r\n#各フィルタを実行する\r\ny_sparse=execute_sparse(stft_data,tf_mask)\r\ny_dsbf=execute_dsbf(stft_data,desired_steering_vectors)\r\ny_mvdr=execute_mvdr(stft_data,Rn,desired_steering_vectors)\r\ny_mvdr2=execute_mvdr2(stft_data,Rn,Rs)\r\ny_max_snr=execute_max_snr(stft_data,Rn,Rs)\r\ny_mwf=execute_mwf(stft_data,Rn,Rs)\r\n\r\n\r\n\r\n#時間領域の波形に戻す\r\nt,y_sparse=sp.istft(y_sparse[0,...],fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,y_dsbf=sp.istft(y_dsbf[0,...],fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,y_mvdr=sp.istft(y_mvdr[0,...],fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,y_mvdr2=sp.istft(y_mvdr2[0,...],fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,y_max_snr=sp.istft(y_max_snr[0,...],fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,y_mwf=sp.istft(y_mwf[0,...],fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\n\r\n#SNRをはかる\r\nsnr_pre=calculate_snr(multi_conv_data_left_no_noise[0,...],multi_conv_data[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],multi_conv_data[0,...])\r\nsnr_doa_sparse_post=calculate_snr(multi_conv_data_left_no_noise[0,...],y_sparse[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_sparse[1,...])\r\nsnr_doa_dsbf_post=calculate_snr(multi_conv_data_left_no_noise[0,...],y_dsbf[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_dsbf[1,...])\r\nsnr_doa_mvdr_post=calculate_snr(multi_conv_data_left_no_noise[0,...],y_mvdr[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_mvdr[1,...])\r\nsnr_doa_mvdr2_post=calculate_snr(multi_conv_data_left_no_noise[0,...],y_mvdr2[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_mvdr2[1,...])\r\nsnr_doa_max_snr_post=calculate_snr(multi_conv_data_left_no_noise[0,...],y_max_snr[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_max_snr[1,...])\r\nsnr_doa_mwf_post=calculate_snr(multi_conv_data_left_no_noise[0,...],y_mwf[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_mwf[1,...])\r\n\r\nsnr_pre/=2.\r\nsnr_doa_sparse_post/=2.\r\nsnr_doa_dsbf_post/=2.\r\nsnr_doa_mvdr_post/=2.\r\nsnr_doa_mvdr2_post/=2.\r\nsnr_doa_max_snr_post/=2.\r\nsnr_doa_mwf_post/=2.\r\n\r\n#ファイルに書き込む\r\nwrite_file_from_time_signal(y_sparse[0,...]*np.iinfo(np.int16).max/20.,\"./reverb_sparse_doa_sparse_left.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_sparse[1,...]*np.iinfo(np.int16).max/20.,\"./reverb_sparse_doa_sparse_right.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_dsbf[0,...]*np.iinfo(np.int16).max/20.,\"./reverb_sparse_doa_dsbf_left.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_dsbf[1,...]*np.iinfo(np.int16).max/20.,\"./reverb_sparse_doa_dsbf_right.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_mvdr[0,...]*np.iinfo(np.int16).max/20.,\"./reverb_sparse_doa_mvdr_left.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_mvdr[1,...]*np.iinfo(np.int16).max/20.,\"./reverb_sparse_doa_mvdr_right.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_mvdr2[0,...]*np.iinfo(np.int16).max/20.,\"./reverb_sparse_doa_mvdr2_left.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_mvdr2[1,...]*np.iinfo(np.int16).max/20.,\"./reverb_sparse_doa_mvdr2_right.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_max_snr[0,...]*np.iinfo(np.int16).max/20.,\"./reverb_sparse_doa_max_snr_left.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_max_snr[1,...]*np.iinfo(np.int16).max/20.,\"./reverb_sparse_doa_max_snr_right.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_mwf[0,...]*np.iinfo(np.int16).max/20.,\"./reverb_sparse_doa_mwf_left.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_mwf[1,...]*np.iinfo(np.int16).max/20.,\"./reverb_sparse_doa_mwf_right.wav\",sample_rate)\r\n\r\n\r\n\r\nprint(\"method:    \", \"DOA_SPARSE\",\"DOA_DSBF\",\"DOA_MVDR\", \"DOA_MVDR2\", \"DOA_MAX_SNR\",\"DOA_MWF\")\r\n\r\nprint(\"Δsnr [dB]: {:.2f}       {:.2f}     {:.2f}    {:.2f}     {:.2f}       {:.2f}\".format(snr_doa_sparse_post-snr_pre,snr_doa_dsbf_post-snr_pre,snr_doa_mvdr_post-snr_pre,snr_doa_mvdr2_post-snr_pre,snr_doa_max_snr_post-snr_pre,snr_doa_mwf_post-snr_pre))\r\n"
  },
  {
    "path": "section7.md",
    "content": "## 第7章のサンプルコード\n\n* [音声のスパース性に基づく音源分離](section7/sample_code_c7_1.py)\n* [音声のスパース性に基づく音源分離（マイクロホンの間隔40センチ）](section7/sample_code_c7_2.py)\n* [音声のスパース性に基づく任意マイクロホン配置の音源分離](section7/sample_code_c7_3.py)\n* [音声のスパース性に基づくビームフォーマ法](section7/sample_code_c7_4.py)\n* [音声のスパース性に基づくビームフォーマ法(残響環境)](section7/sample_code_c7_5.py)\n"
  },
  {
    "path": "section8/sample_code_c8_1.py",
    "content": "\r\n\r\nimport wave as wave\r\nimport pyroomacoustics as pa\r\nimport numpy as np\r\nimport scipy.signal as sp\r\nimport scipy as scipy\r\n\r\n#順列計算に使用\r\nimport itertools as itertools\r\n\r\n\r\n\r\n\r\n#コントラスト関数の微分（球対称ラプラス分布を仮定）\r\n#s_hat: 分離信号(M, Nk, Lt)\r\ndef phi_laplacian(s_hat):\r\n\r\n    norm=np.abs(s_hat)\r\n    phi=s_hat/np.maximum(norm,1.e-18)\r\n    return(phi)\r\n\r\n#コントラスト関数（球対称ラプラス分布を仮定）\r\n#s_hat: 分離信号(M, Nk, Lt)\r\ndef contrast_laplacian(s_hat):\r\n\r\n    norm=2.*np.abs(s_hat)\r\n    \r\n    return(norm)\r\n\r\n#ICAによる分離フィルタ更新\r\n#x:入力信号( M, Nk, Lt)\r\n#W: 分離フィルタ(Nk,M,M)\r\n#mu: 更新係数\r\n#n_ica_iterations: 繰り返しステップ数\r\n#phi_func: コントラスト関数の微分を与える関数\r\n#contrast_func: コントラスト関数\r\n#is_use_non_holonomic: True (非ホロノミック拘束を用いる） False (用いない）\r\n#return W 分離フィルタ(Nk,M,M) s_hat 出力信号(M,Nk, Lt),cost_buff ICAのコスト (T)\r\ndef execute_natural_gradient_ica(x,W,phi_func=phi_laplacian,contrast_func=contrast_laplacian,mu=1.0,n_ica_iterations=20,is_use_non_holonomic=True):\r\n    \r\n    #マイクロホン数を取得する\r\n    M=np.shape(x)[0]\r\n\r\n    cost_buff=[]\r\n    for t in range(n_ica_iterations):\r\n        #音源分離信号を得る\r\n        s_hat=np.einsum('kmn,nkt->mkt',W,x)\r\n\r\n        #コントラスト関数を計算\r\n        G=contrast_func(s_hat)\r\n\r\n        #コスト計算\r\n        cost=np.sum(np.mean(G,axis=-1))-np.sum(2.*np.log(np.abs(np.linalg.det(W)) ))\r\n        cost_buff.append(cost)\r\n\r\n        #コンストラクト関数の微分を取得\r\n        phi=phi_func(s_hat)\r\n\r\n        phi_s=np.einsum('mkt,nkt->ktmn',phi,np.conjugate(s_hat))\r\n        phi_s=np.mean(phi_s,axis=1)\r\n\r\n        I=np.eye(M,M)\r\n        if is_use_non_holonomic==False:\r\n            deltaW=np.einsum('kmi,kin->kmn',I[None,...]-phi_s,W)\r\n        else:\r\n            mask=(np.ones((M,M))-I)[None,...]\r\n            deltaW=np.einsum('kmi,kin->kmn',np.multiply(mask,-phi_s),W)\r\n            \r\n        #フィルタを更新する\r\n        W=W+mu*deltaW\r\n    \r\n    #最後に出力信号を分離\r\n    s_hat=np.einsum('kmn,nkt->mkt',W,x)\r\n\r\n    return(W,s_hat,cost_buff)\r\n\r\n#周波数間の振幅相関に基づくパーミュテーション解法\r\n#s_hat: M,Nk,Lt\r\n#return permutation_index_result：周波数毎のパーミュテーション解 \r\ndef solver_inter_frequency_permutation(s_hat):\r\n    n_sources=np.shape(s_hat)[0]\r\n    n_freqs=np.shape(s_hat)[1]\r\n    n_frames=np.shape(s_hat)[2]\r\n\r\n    s_hat_abs=np.abs(s_hat)\r\n\r\n    norm_amp=np.sqrt(np.sum(np.square(s_hat_abs),axis=0,keepdims=True))\r\n    s_hat_abs=s_hat_abs/np.maximum(norm_amp,1.e-18)\r\n\r\n    spectral_similarity=np.einsum('mkt,nkt->k',s_hat_abs,s_hat_abs)\r\n    \r\n    frequency_order=np.argsort(spectral_similarity)\r\n    \r\n    #音源間の相関が最も低い周波数からパーミュテーションを解く\r\n    is_first=True\r\n    permutations=list(itertools.permutations(range(n_sources)))\r\n    permutation_index_result={}\r\n    \r\n    for freq in frequency_order:\r\n        \r\n        if is_first==True:\r\n            is_first=False\r\n\r\n            #初期値を設定する\r\n            accumurate_s_abs=s_hat_abs[:,frequency_order[0],:]\r\n            permutation_index_result[freq]=range(n_sources)\r\n        else:\r\n            max_correlation=0\r\n            max_correlation_perm=None\r\n            for perm in permutations:\r\n                s_hat_abs_temp=s_hat_abs[list(perm),freq,:]\r\n                correlation=np.sum(accumurate_s_abs*s_hat_abs_temp)\r\n                \r\n                \r\n                if max_correlation_perm is None:\r\n                    max_correlation_perm=list(perm)\r\n                    max_correlation=correlation\r\n                elif max_correlation < correlation:\r\n                    max_correlation=correlation\r\n                    max_correlation_perm=list(perm)\r\n            permutation_index_result[freq]=max_correlation_perm\r\n            accumurate_s_abs+=s_hat_abs[max_correlation_perm,freq,:]\r\n   \r\n    return(permutation_index_result)\r\n    \r\n#プロジェクションバックで最終的な出力信号を求める\r\n#s_hat: M,Nk,Lt\r\n#W: 分離フィルタ(Nk,M,M)\r\n#retunr c_hat: マイクロホン位置での分離結果(M,M,Nk,Lt)\r\ndef projection_back(s_hat,W):\r\n    \r\n    #ステアリングベクトルを推定\r\n    A=np.linalg.pinv(W)\r\n    c_hat=np.einsum('kmi,ikt->mikt',A,s_hat)\r\n    return(c_hat)\r\n\r\n\r\n#2バイトに変換してファイルに保存\r\n#signal: time-domain 1d array (float)\r\n#file_name: 出力先のファイル名\r\n#sample_rate: サンプリングレート\r\ndef write_file_from_time_signal(signal,file_name,sample_rate):\r\n    #2バイトのデータに変換\r\n    signal=signal.astype(np.int16)\r\n\r\n    #waveファイルに書き込む\r\n    wave_out = wave.open(file_name, 'w')\r\n\r\n    #モノラル:1、ステレオ:2\r\n    wave_out.setnchannels(1)\r\n\r\n    #サンプルサイズ2byte\r\n    wave_out.setsampwidth(2)\r\n\r\n    #サンプリング周波数\r\n    wave_out.setframerate(sample_rate)\r\n\r\n    #データを書き込み\r\n    wave_out.writeframes(signal)\r\n\r\n    #ファイルを閉じる\r\n    wave_out.close()\r\n\r\n#SNRをはかる\r\n#desired: 目的音、Lt\r\n#out:　雑音除去後の信号 Lt\r\ndef calculate_snr(desired,out):\r\n    wave_length=np.minimum(np.shape(desired)[0],np.shape(out)[0])\r\n\r\n    #消し残った雑音\r\n    desired=desired[:wave_length]\r\n    out=out[:wave_length]\r\n    noise=desired-out\r\n    snr=10.*np.log10(np.sum(np.square(desired))/np.sum(np.square(noise)))\r\n\r\n    return(snr)\r\n\r\n#乱数の種を初期化\r\nnp.random.seed(0)\r\n\r\n#畳み込みに用いる音声波形\r\nclean_wave_files=[\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\",\"./CMU_ARCTIC/cmu_us_axb_arctic/wav/arctic_a0002.wav\"]\r\n\r\n#音源数\r\nn_sources=len(clean_wave_files)\r\n\r\n#長さを調べる\r\nn_samples=0\r\n#ファイルを読み込む\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    if n_samples<wav.getnframes():\r\n        n_samples=wav.getnframes()\r\n    wav.close()\r\n\r\nclean_data=np.zeros([n_sources,n_samples])\r\n\r\n#ファイルを読み込む\r\ns=0\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    data=wav.readframes(wav.getnframes())\r\n    data=np.frombuffer(data, dtype=np.int16)\r\n    data=data/np.iinfo(np.int16).max\r\n    clean_data[s,:wav.getnframes()]=data\r\n    wav.close()\r\n    s=s+1\r\n\r\n\r\n# シミュレーションのパラメータ\r\n\r\n#シミュレーションで用いる音源数\r\nn_sim_sources=2\r\n\r\n#サンプリング周波数\r\nsample_rate=16000\r\n\r\n#フレームサイズ\r\nN=1024\r\n\r\n#周波数の数\r\nNk=int(N/2+1)\r\n\r\n#各ビンの周波数\r\nfreqs=np.arange(0,Nk,1)*sample_rate/N\r\n\r\n#音声と雑音との比率 [dB]\r\nSNR=90.\r\n\r\n#部屋の大きさ\r\nroom_dim = np.r_[10.0, 10.0, 10.0]\r\n\r\n#マイクロホンアレイを置く部屋の場所\r\nmic_array_loc = room_dim / 2 + np.random.randn(3) * 0.1 \r\n\r\n#マイクロホンアレイのマイク配置\r\nmic_directions=np.array(\r\n    [[np.pi/2., theta/180.*np.pi] for theta in np.arange(180,361,180)\r\n    ]    )\r\n\r\ndistance=0.01\r\nmic_alignments=np.zeros((3, mic_directions.shape[0]), dtype=mic_directions.dtype)\r\nmic_alignments[0, :] = np.cos(mic_directions[:, 1]) * np.sin(mic_directions[:, 0])\r\nmic_alignments[1, :] = np.sin(mic_directions[:, 1]) * np.sin(mic_directions[:, 0])\r\nmic_alignments[2, :] = np.cos(mic_directions[:, 0])\r\nmic_alignments *= distance\r\n\r\n#マイクロホン数\r\nn_channels=np.shape(mic_alignments)[1]\r\n\r\n#マイクロホンアレイの座標\r\nR=mic_alignments+mic_array_loc[:,None]\r\n\r\nis_use_reverb=True\r\n\r\nif is_use_reverb==False:\r\n    # 部屋を生成する\r\n    room = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0) \r\n    room_no_noise_left = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\n    room_no_noise_right = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\n\r\nelse:\r\n\r\n    room = pa.ShoeBox(room_dim, fs=sample_rate, max_order=17,absorption=0.4)\r\n    room_no_noise_left = pa.ShoeBox(room_dim, fs=sample_rate, max_order=17,absorption=0.4)\r\n    room_no_noise_right = pa.ShoeBox(room_dim, fs=sample_rate, max_order=17,absorption=0.4)\r\n\r\n# 用いるマイクロホンアレイの情報を設定する\r\nroom.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\nroom_no_noise_left.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\nroom_no_noise_right.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\n\r\n#音源の場所\r\ndoas=np.array(\r\n    [[np.pi/2., np.pi],\r\n     [np.pi/2., 0]\r\n    ]    )\r\n\r\n#音源とマイクロホンの距離\r\ndistance=1.\r\n\r\nsource_locations=np.zeros((3, doas.shape[0]), dtype=doas.dtype)\r\nsource_locations[0, :] = np.cos(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[1, :] = np.sin(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[2, :] = np.cos(doas[:, 0])\r\nsource_locations *= distance\r\nsource_locations += mic_array_loc[:, None]\r\n\r\n#各音源をシミュレーションに追加する\r\nfor s in range(n_sim_sources):\r\n    clean_data[s]/= np.std(clean_data[s])\r\n    room.add_source(source_locations[:, s], signal=clean_data[s])\r\n    if s==0:\r\n        room_no_noise_left.add_source(source_locations[:, s], signal=clean_data[s])\r\n    if s==1:\r\n        room_no_noise_right.add_source(source_locations[:, s], signal=clean_data[s])\r\n\r\n#シミュレーションを回す\r\nroom.simulate(snr=SNR)\r\nroom_no_noise_left.simulate(snr=90)\r\nroom_no_noise_right.simulate(snr=90)\r\n\r\n#畳み込んだ波形を取得する(チャンネル、サンプル）\r\nmulti_conv_data=room.mic_array.signals\r\nmulti_conv_data_left_no_noise=room_no_noise_left.mic_array.signals\r\nmulti_conv_data_right_no_noise=room_no_noise_right.mic_array.signals\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data_left_no_noise[0,:]*np.iinfo(np.int16).max/20.,\"./ica_left_clean.wav\",sample_rate)\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data_right_no_noise[0,:]*np.iinfo(np.int16).max/20.,\"./ica_right_clean.wav\",sample_rate)\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data[0,:]*np.iinfo(np.int16).max/20.,\"./ica_in_left.wav\",sample_rate)\r\nwrite_file_from_time_signal(multi_conv_data[0,:]*np.iinfo(np.int16).max/20.,\"./ica_in_right.wav\",sample_rate)\r\n\r\n#短時間フーリエ変換を行う\r\nf,t,stft_data=sp.stft(multi_conv_data,fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\n#ICAの繰り返し回数\r\nn_ica_iterations=200\r\n\r\n#ICAの分離フィルタを初期化\r\nWica=np.zeros(shape=(Nk,n_sources,n_sources),dtype=np.complex)\r\nWica=Wica+np.eye(n_sources)[None,...]\r\n\r\nWica,s_ica,cost_buff=execute_natural_gradient_ica(stft_data,Wica,mu=0.1,n_ica_iterations=n_ica_iterations,is_use_non_holonomic=False)\r\n\r\npermutation_index_result=solver_inter_frequency_permutation(s_ica)\r\n\r\ny_ica=projection_back(s_ica,Wica)\r\n\r\n#パーミュテーションを解く\r\nfor k in range(Nk):\r\n    y_ica[:,:,k,:]=y_ica[:,permutation_index_result[k],k,:]\r\n\r\nt,y_ica=sp.istft(y_ica[0,...],fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\nsnr_pre=calculate_snr(multi_conv_data_left_no_noise[0,...],multi_conv_data[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],multi_conv_data[0,...])\r\nsnr_pre/=2.\r\n\r\nsnr_ica_post1=calculate_snr(multi_conv_data_left_no_noise[0,...],y_ica[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_ica[1,...])\r\nsnr_ica_post2=calculate_snr(multi_conv_data_left_no_noise[0,...],y_ica[1,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_ica[0,...])\r\n\r\nsnr_ica_post=np.maximum(snr_ica_post1,snr_ica_post2)\r\nsnr_ica_post/=2.\r\n\r\nwrite_file_from_time_signal(y_ica[0,...]*np.iinfo(np.int16).max/20.,\"./ica_1.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_ica[1,...]*np.iinfo(np.int16).max/20.,\"./ica_2.wav\",sample_rate)\r\n\r\n\r\nprint(\"method:    \", \"ICA\")\r\n\r\nprint(\"Δsnr [dB]: {:.2f}\".format(snr_ica_post-snr_pre))\r\n\r\n\r\n\r\n#コストの値を表示\r\n#for t in range(n_ica_iterations):\r\n#    print(t,cost_buff[t])\r\n\r\n"
  },
  {
    "path": "section8/sample_code_c8_2.py",
    "content": "\r\n\r\nimport wave as wave\r\nimport pyroomacoustics as pa\r\nimport numpy as np\r\nimport scipy.signal as sp\r\nimport scipy as scipy\r\n\r\n#順列計算に使用\r\nimport itertools\r\nimport time\r\n\r\n\r\n#コントラスト関数の微分（球対称多次元ラプラス分布を仮定）\r\n#s_hat: 分離信号(M, Nk, Lt)\r\ndef phi_multivariate_laplacian(s_hat):\r\n\r\n    power=np.square(np.abs(s_hat))\r\n    norm=np.sqrt(np.sum(power,axis=1,keepdims=True))\r\n\r\n    phi=s_hat/np.maximum(norm,1.e-18)\r\n    return(phi)\r\n\r\n#コントラスト関数の微分（球対称ラプラス分布を仮定）\r\n#s_hat: 分離信号(M, Nk, Lt)\r\ndef phi_laplacian(s_hat):\r\n\r\n    norm=np.abs(s_hat)\r\n    phi=s_hat/np.maximum(norm,1.e-18)\r\n    return(phi)\r\n\r\n#コントラスト関数（球対称ラプラス分布を仮定）\r\n#s_hat: 分離信号(M, Nk, Lt)\r\ndef contrast_laplacian(s_hat):\r\n\r\n    norm=2.*np.abs(s_hat)\r\n    \r\n    return(norm)\r\n\r\n#コントラスト関数（球対称多次元ラプラス分布を仮定）\r\n#s_hat: 分離信号(M, Nk, Lt)\r\ndef contrast_multivariate_laplacian(s_hat):\r\n    power=np.square(np.abs(s_hat))\r\n    norm=2.*np.sqrt(np.sum(power,axis=1,keepdims=True))\r\n  \r\n    return(norm)\r\n\r\n#ICAによる分離フィルタ更新\r\n#x:入力信号( M, Nk, Lt)\r\n#W: 分離フィルタ(Nk,M,M)\r\n#mu: 更新係数\r\n#n_ica_iterations: 繰り返しステップ数\r\n#phi_func: コントラスト関数の微分を与える関数\r\n#contrast_func: コントラスト関数\r\n#is_use_non_holonomic: True (非ホロノミック拘束を用いる） False (用いない）\r\n#return W 分離フィルタ(Nk,M,M) s_hat 出力信号(M,Nk, Lt),cost_buff ICAのコスト (T)\r\ndef execute_natural_gradient_ica(x,W,phi_func=phi_laplacian,contrast_func=contrast_laplacian,mu=1.0,n_ica_iterations=20,is_use_non_holonomic=True):\r\n    \r\n    #マイクロホン数を取得する\r\n    M=np.shape(x)[0]\r\n\r\n    cost_buff=[]\r\n    for t in range(n_ica_iterations):\r\n        #音源分離信号を得る\r\n        s_hat=np.einsum('kmn,nkt->mkt',W,x)\r\n\r\n        #コントラスト関数を計算\r\n        G=contrast_func(s_hat)\r\n\r\n        #コスト計算\r\n        cost=np.sum(np.mean(G,axis=-1))-np.sum(2.*np.log(np.abs(np.linalg.det(W)) ))\r\n        cost_buff.append(cost)\r\n\r\n        #コンストラクト関数の微分を取得\r\n        phi=phi_func(s_hat)\r\n\r\n        phi_s=np.einsum('mkt,nkt->ktmn',phi,np.conjugate(s_hat))\r\n        phi_s=np.mean(phi_s,axis=1)\r\n\r\n        I=np.eye(M,M)\r\n        if is_use_non_holonomic==False:\r\n            deltaW=np.einsum('kmi,kin->kmn',I[None,...]-phi_s,W)\r\n        else:\r\n            mask=(np.ones((M,M))-I)[None,...]\r\n            deltaW=np.einsum('kmi,kin->kmn',np.multiply(mask,-phi_s),W)\r\n            \r\n        #フィルタを更新する\r\n        W=W+mu*deltaW\r\n    \r\n    #最後に出力信号を分離\r\n    s_hat=np.einsum('kmn,nkt->mkt',W,x)\r\n\r\n    return(W,s_hat,cost_buff)\r\n\r\n#IP法による分離フィルタ更新\r\n#x:入力信号( M, Nk, Lt)\r\n#W: 分離フィルタ(Nk,M,M)\r\n#n_iterations: 繰り返しステップ数\r\n#return W 分離フィルタ(Nk,M,M) s_hat 出力信号(M,Nk, Lt),cost_buff コスト (T)\r\ndef execute_ip_multivariate_laplacian_iva(x,W,n_iterations=20):\r\n    \r\n    #マイクロホン数を取得する\r\n    M=np.shape(x)[0]\r\n\r\n    cost_buff=[]\r\n    for t in range(n_iterations):\r\n        \r\n        #音源分離信号を得る\r\n        s_hat=np.einsum('kmn,nkt->mkt',W,x)\r\n\r\n        #補助変数を更新する\r\n        v=np.sqrt(np.sum(np.square(np.abs(s_hat)),axis=1))\r\n\r\n        #コントラスト関数を計算\r\n        G=contrast_multivariate_laplacian(s_hat)\r\n\r\n        #コスト計算\r\n        cost=np.sum(np.mean(G,axis=-1))-np.sum(2.*np.log(np.abs(np.linalg.det(W)) ))\r\n        cost_buff.append(cost)\r\n\r\n        #IP法による更新\r\n        Q=np.einsum('st,mkt,nkt->tksmn',1./np.maximum(v,1.e-18),x,np.conjugate(x))\r\n        Q=np.average(Q,axis=0)\r\n        \r\n        for source_index in range(M):\r\n            WQ=np.einsum('kmi,kin->kmn',W,Q[:,source_index,:,:])\r\n            invWQ=np.linalg.pinv(WQ)\r\n            W[:,source_index,:]=np.conjugate(invWQ[:,:,source_index])\r\n            wVw=np.einsum('km,kmn,kn->k',W[:,source_index,:],Q[:,source_index,:,:],np.conjugate(W[:,source_index,:]))\r\n            wVw=np.sqrt(np.abs(wVw))\r\n            W[:,source_index,:]=W[:,source_index,:]/np.maximum(wVw[:,None],1.e-18)\r\n\r\n \r\n    s_hat=np.einsum('kmn,nkt->mkt',W,x)\r\n\r\n    return(W,s_hat,cost_buff)\r\n\r\n#周波数間の振幅相関に基づくパーミュテーション解法\r\n#s_hat: M,Nk,Lt\r\n#return permutation_index_result：周波数毎のパーミュテーション解 \r\ndef solver_inter_frequency_permutation(s_hat):\r\n    n_sources=np.shape(s_hat)[0]\r\n    n_freqs=np.shape(s_hat)[1]\r\n    n_frames=np.shape(s_hat)[2]\r\n\r\n    s_hat_abs=np.abs(s_hat)\r\n\r\n    norm_amp=np.sqrt(np.sum(np.square(s_hat_abs),axis=0,keepdims=True))\r\n    s_hat_abs=s_hat_abs/np.maximum(norm_amp,1.e-18)\r\n\r\n    spectral_similarity=np.einsum('mkt,nkt->k',s_hat_abs,s_hat_abs)\r\n    \r\n    frequency_order=np.argsort(spectral_similarity)\r\n    \r\n    #音源間の相関が最も低い周波数からパーミュテーションを解く\r\n    is_first=True\r\n    permutations=list(itertools.permutations(range(n_sources)))\r\n    permutation_index_result={}\r\n    \r\n    for freq in frequency_order:\r\n        \r\n        if is_first==True:\r\n            is_first=False\r\n\r\n            #初期値を設定する\r\n            accumurate_s_abs=s_hat_abs[:,frequency_order[0],:]\r\n            permutation_index_result[freq]=range(n_sources)\r\n        else:\r\n            max_correlation=0\r\n            max_correlation_perm=None\r\n            for perm in permutations:\r\n                s_hat_abs_temp=s_hat_abs[list(perm),freq,:]\r\n                correlation=np.sum(accumurate_s_abs*s_hat_abs_temp)\r\n                \r\n                \r\n                if max_correlation_perm is None:\r\n                    max_correlation_perm=list(perm)\r\n                    max_correlation=correlation\r\n                elif max_correlation < correlation:\r\n                    max_correlation=correlation\r\n                    max_correlation_perm=list(perm)\r\n            permutation_index_result[freq]=max_correlation_perm\r\n            accumurate_s_abs+=s_hat_abs[max_correlation_perm,freq,:]\r\n   \r\n    return(permutation_index_result)\r\n    \r\n#プロジェクションバックで最終的な出力信号を求める\r\n#s_hat: M,Nk,Lt\r\n#W: 分離フィルタ(Nk,M,M)\r\n#retunr c_hat: マイクロホン位置での分離結果(M,M,Nk,Lt)\r\ndef projection_back(s_hat,W):\r\n    \r\n    #ステアリングベクトルを推定\r\n    A=np.linalg.pinv(W)\r\n    c_hat=np.einsum('kmi,ikt->mikt',A,s_hat)\r\n    return(c_hat)\r\n\r\n\r\n#2バイトに変換してファイルに保存\r\n#signal: time-domain 1d array (float)\r\n#file_name: 出力先のファイル名\r\n#sample_rate: サンプリングレート\r\ndef write_file_from_time_signal(signal,file_name,sample_rate):\r\n    #2バイトのデータに変換\r\n    signal=signal.astype(np.int16)\r\n\r\n    #waveファイルに書き込む\r\n    wave_out = wave.open(file_name, 'w')\r\n\r\n    #モノラル:1、ステレオ:2\r\n    wave_out.setnchannels(1)\r\n\r\n    #サンプルサイズ2byte\r\n    wave_out.setsampwidth(2)\r\n\r\n    #サンプリング周波数\r\n    wave_out.setframerate(sample_rate)\r\n\r\n    #データを書き込み\r\n    wave_out.writeframes(signal)\r\n\r\n    #ファイルを閉じる\r\n    wave_out.close()\r\n\r\n#SNRをはかる\r\n#desired: 目的音、Lt\r\n#out:　雑音除去後の信号 Lt\r\ndef calculate_snr(desired,out):\r\n    wave_length=np.minimum(np.shape(desired)[0],np.shape(out)[0])\r\n\r\n    #消し残った雑音\r\n    desired=desired[:wave_length]\r\n    out=out[:wave_length]\r\n    noise=desired-out\r\n    snr=10.*np.log10(np.sum(np.square(desired))/np.sum(np.square(noise)))\r\n\r\n    return(snr)\r\n\r\n#乱数の種を初期化\r\nnp.random.seed(0)\r\n\r\n#畳み込みに用いる音声波形\r\nclean_wave_files=[\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\",\"./CMU_ARCTIC/cmu_us_axb_arctic/wav/arctic_a0002.wav\"]\r\n\r\n#音源数\r\nn_sources=len(clean_wave_files)\r\n\r\n#長さを調べる\r\nn_samples=0\r\n#ファイルを読み込む\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    if n_samples<wav.getnframes():\r\n        n_samples=wav.getnframes()\r\n    wav.close()\r\n\r\nclean_data=np.zeros([n_sources,n_samples])\r\n\r\n#ファイルを読み込む\r\ns=0\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    data=wav.readframes(wav.getnframes())\r\n    data=np.frombuffer(data, dtype=np.int16)\r\n    data=data/np.iinfo(np.int16).max\r\n    clean_data[s,:wav.getnframes()]=data\r\n    wav.close()\r\n    s=s+1\r\n\r\n\r\n# シミュレーションのパラメータ\r\n\r\n#シミュレーションで用いる音源数\r\nn_sim_sources=2\r\n\r\n#サンプリング周波数\r\nsample_rate=16000\r\n\r\n#フレームサイズ\r\nN=1024\r\n\r\n#周波数の数\r\nNk=int(N/2+1)\r\n\r\n#各ビンの周波数\r\nfreqs=np.arange(0,Nk,1)*sample_rate/N\r\n\r\n#音声と雑音との比率 [dB]\r\nSNR=90.\r\n\r\n#部屋の大きさ\r\nroom_dim = np.r_[10.0, 10.0, 10.0]\r\n\r\n#マイクロホンアレイを置く部屋の場所\r\nmic_array_loc = room_dim / 2 + np.random.randn(3) * 0.1 \r\n\r\n#マイクロホンアレイのマイク配置\r\nmic_directions=np.array(\r\n    [[np.pi/2., theta/180.*np.pi] for theta in np.arange(180,361,180)\r\n    ]    )\r\n\r\ndistance=0.01\r\nmic_alignments=np.zeros((3, mic_directions.shape[0]), dtype=mic_directions.dtype)\r\nmic_alignments[0, :] = np.cos(mic_directions[:, 1]) * np.sin(mic_directions[:, 0])\r\nmic_alignments[1, :] = np.sin(mic_directions[:, 1]) * np.sin(mic_directions[:, 0])\r\nmic_alignments[2, :] = np.cos(mic_directions[:, 0])\r\nmic_alignments *= distance\r\n\r\n#マイクロホン数\r\nn_channels=np.shape(mic_alignments)[1]\r\n\r\n#マイクロホンアレイの座標\r\nR=mic_alignments+mic_array_loc[:,None]\r\n\r\nis_use_reverb=False\r\n\r\nif is_use_reverb==False:\r\n    # 部屋を生成する\r\n    room = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0) \r\n    room_no_noise_left = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\n    room_no_noise_right = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\n\r\nelse:\r\n\r\n    room = pa.ShoeBox(room_dim, fs=sample_rate, max_order=17,absorption=0.4)\r\n    room_no_noise_left = pa.ShoeBox(room_dim, fs=sample_rate, max_order=17,absorption=0.4)\r\n    room_no_noise_right = pa.ShoeBox(room_dim, fs=sample_rate, max_order=17,absorption=0.4)\r\n\r\n# 用いるマイクロホンアレイの情報を設定する\r\nroom.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\nroom_no_noise_left.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\nroom_no_noise_right.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\n\r\n#音源の場所\r\ndoas=np.array(\r\n    [[np.pi/2., np.pi],\r\n     [np.pi/2., 0]\r\n    ]    )\r\n\r\n#音源とマイクロホンの距離\r\ndistance=1.\r\n\r\nsource_locations=np.zeros((3, doas.shape[0]), dtype=doas.dtype)\r\nsource_locations[0, :] = np.cos(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[1, :] = np.sin(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[2, :] = np.cos(doas[:, 0])\r\nsource_locations *= distance\r\nsource_locations += mic_array_loc[:, None]\r\n\r\n#各音源をシミュレーションに追加する\r\nfor s in range(n_sim_sources):\r\n    clean_data[s]/= np.std(clean_data[s])\r\n    room.add_source(source_locations[:, s], signal=clean_data[s])\r\n    if s==0:\r\n        room_no_noise_left.add_source(source_locations[:, s], signal=clean_data[s])\r\n    if s==1:\r\n        room_no_noise_right.add_source(source_locations[:, s], signal=clean_data[s])\r\n\r\n#シミュレーションを回す\r\nroom.simulate(snr=SNR)\r\nroom_no_noise_left.simulate(snr=90)\r\nroom_no_noise_right.simulate(snr=90)\r\n\r\n#畳み込んだ波形を取得する(チャンネル、サンプル）\r\nmulti_conv_data=room.mic_array.signals\r\nmulti_conv_data_left_no_noise=room_no_noise_left.mic_array.signals\r\nmulti_conv_data_right_no_noise=room_no_noise_right.mic_array.signals\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data_left_no_noise[0,:]*np.iinfo(np.int16).max/20.,\"./ica_left_clean.wav\",sample_rate)\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data_right_no_noise[0,:]*np.iinfo(np.int16).max/20.,\"./ica_right_clean.wav\",sample_rate)\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data[0,:]*np.iinfo(np.int16).max/20.,\"./ica_in_left.wav\",sample_rate)\r\nwrite_file_from_time_signal(multi_conv_data[0,:]*np.iinfo(np.int16).max/20.,\"./ica_in_right.wav\",sample_rate)\r\n\r\n#短時間フーリエ変換を行う\r\nf,t,stft_data=sp.stft(multi_conv_data,fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\n#ICAの繰り返し回数\r\nn_ica_iterations=50\r\n\r\n#ICAの分離フィルタを初期化\r\nWica=np.zeros(shape=(Nk,n_sources,n_sources),dtype=np.complex)\r\n\r\nWica=Wica+np.eye(n_sources)[None,...]\r\n\r\nWiva=Wica.copy()\r\nWiva_ip=Wica.copy()\r\n\r\nstart_time=time.time()\r\n#自然勾配法に基づくIVA実行コード（引数に与える関数を変更するだけ)\r\nWiva,s_iva,cost_buff_iva=execute_natural_gradient_ica(stft_data,Wiva,phi_func=phi_multivariate_laplacian,contrast_func=contrast_multivariate_laplacian,mu=0.1,n_ica_iterations=n_ica_iterations,is_use_non_holonomic=False)\r\ny_iva=projection_back(s_iva,Wiva)\r\niva_time=time.time()\r\n\r\n#IP法に基づくIVA実行コード（引数に与える関数を変更するだけ)\r\nWiva_ip,s_iva_ip,cost_buff_iva_ip=execute_ip_multivariate_laplacian_iva(stft_data,Wiva_ip,n_iterations=n_ica_iterations)\r\ny_iva_ip=projection_back(s_iva_ip,Wiva_ip)\r\niva_ip_time=time.time()\r\n\r\nWica,s_ica,cost_buff_ica=execute_natural_gradient_ica(stft_data,Wica,mu=0.1,n_ica_iterations=n_ica_iterations,is_use_non_holonomic=False)\r\npermutation_index_result=solver_inter_frequency_permutation(s_ica)\r\ny_ica=projection_back(s_ica,Wica)\r\n\r\n#パーミュテーションを解く\r\nfor k in range(Nk):\r\n    y_ica[:,:,k,:]=y_ica[:,permutation_index_result[k],k,:]\r\n\r\nica_time=time.time()\r\n\r\nt,y_ica=sp.istft(y_ica[0,...],fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,y_iva=sp.istft(y_iva[0,...],fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,y_iva_ip=sp.istft(y_iva_ip[0,...],fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\nsnr_pre=calculate_snr(multi_conv_data_left_no_noise[0,...],multi_conv_data[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],multi_conv_data[0,...])\r\nsnr_pre/=2.\r\n\r\nsnr_ica_post1=calculate_snr(multi_conv_data_left_no_noise[0,...],y_ica[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_ica[1,...])\r\nsnr_ica_post2=calculate_snr(multi_conv_data_left_no_noise[0,...],y_ica[1,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_ica[0,...])\r\n\r\nsnr_ica_post=np.maximum(snr_ica_post1,snr_ica_post2)\r\nsnr_ica_post/=2.\r\n\r\nsnr_iva_post1=calculate_snr(multi_conv_data_left_no_noise[0,...],y_iva[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_iva[1,...])\r\nsnr_iva_post2=calculate_snr(multi_conv_data_left_no_noise[0,...],y_iva[1,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_iva[0,...])\r\n\r\nsnr_iva_post=np.maximum(snr_iva_post1,snr_iva_post2)\r\nsnr_iva_post/=2.\r\n\r\nsnr_iva_ip_post1=calculate_snr(multi_conv_data_left_no_noise[0,...],y_iva_ip[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_iva_ip[1,...])\r\nsnr_iva_ip_post2=calculate_snr(multi_conv_data_left_no_noise[0,...],y_iva_ip[1,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_iva_ip[0,...])\r\n\r\nsnr_iva_ip_post=np.maximum(snr_iva_ip_post1,snr_iva_ip_post2)\r\nsnr_iva_ip_post/=2.\r\n\r\nwrite_file_from_time_signal(y_ica[0,...]*np.iinfo(np.int16).max/20.,\"./ica_1.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_ica[1,...]*np.iinfo(np.int16).max/20.,\"./ica_2.wav\",sample_rate)\r\n\r\nwrite_file_from_time_signal(y_iva[0,...]*np.iinfo(np.int16).max/20.,\"./iva_1.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_iva[1,...]*np.iinfo(np.int16).max/20.,\"./iva_2.wav\",sample_rate)\r\n\r\nwrite_file_from_time_signal(y_iva_ip[0,...]*np.iinfo(np.int16).max/20.,\"./iva_ip_1.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_iva_ip[1,...]*np.iinfo(np.int16).max/20.,\"./iva_ip_2.wav\",sample_rate)\r\n\r\n\r\nprint(\"method:    \", \"NG-ICA\", \"NG-IVA\", \"AuxIVA\")\r\nprint(\"処理時間[sec]: {:.2f}  {:.2f}  {:.2f}\".format(ica_time-iva_ip_time,iva_ip_time-iva_time,iva_time-start_time))\r\nprint(\"Δsnr [dB]: {:.2f}  {:.2f}  {:.2f}\".format(snr_ica_post-snr_pre,snr_iva_post-snr_pre,snr_iva_ip_post-snr_pre))\r\n\r\n#コストの値を表示\r\n#for t in range(n_ica_iterations):\r\n#    print(t,cost_buff_ica[t],cost_buff_iva[t],cost_buff_iva_ip[t])\r\n\r\n"
  },
  {
    "path": "section8/sample_code_c8_3.py",
    "content": "\r\n\r\nimport wave as wave\r\nimport pyroomacoustics as pa\r\nimport numpy as np\r\nimport scipy.signal as sp\r\nimport scipy as scipy\r\n\r\n#順列計算に使用\r\nimport itertools\r\nimport time\r\n\r\n\r\n\r\n#コントラスト関数の微分（球対称多次元ラプラス分布を仮定）\r\n#s_hat: 分離信号(M, Nk, Lt)\r\ndef phi_multivariate_laplacian(s_hat):\r\n\r\n    power=np.square(np.abs(s_hat))\r\n    norm=np.sqrt(np.sum(power,axis=1,keepdims=True))\r\n\r\n    phi=s_hat/np.maximum(norm,1.e-18)\r\n    return(phi)\r\n\r\n#コントラスト関数の微分（球対称ラプラス分布を仮定）\r\n#s_hat: 分離信号(M, Nk, Lt)\r\ndef phi_laplacian(s_hat):\r\n\r\n    norm=np.abs(s_hat)\r\n    phi=s_hat/np.maximum(norm,1.e-18)\r\n    return(phi)\r\n\r\n#コントラスト関数（球対称ラプラス分布を仮定）\r\n#s_hat: 分離信号(M, Nk, Lt)\r\ndef contrast_laplacian(s_hat):\r\n\r\n    norm=2.*np.abs(s_hat)\r\n    \r\n    return(norm)\r\n\r\n#コントラスト関数（球対称多次元ラプラス分布を仮定）\r\n#s_hat: 分離信号(M, Nk, Lt)\r\ndef contrast_multivariate_laplacian(s_hat):\r\n    power=np.square(np.abs(s_hat))\r\n    norm=2.*np.sqrt(np.sum(power,axis=1,keepdims=True))\r\n  \r\n    return(norm)\r\n\r\n#ICAによる分離フィルタ更新\r\n#x:入力信号( M, Nk, Lt)\r\n#W: 分離フィルタ(Nk,M,M)\r\n#mu: 更新係数\r\n#n_ica_iterations: 繰り返しステップ数\r\n#phi_func: コントラスト関数の微分を与える関数\r\n#contrast_func: コントラスト関数\r\n#is_use_non_holonomic: True (非ホロノミック拘束を用いる） False (用いない）\r\n#return W 分離フィルタ(Nk,M,M) s_hat 出力信号(M,Nk, Lt),cost_buff ICAのコスト (T)\r\ndef execute_natural_gradient_ica(x,W,phi_func=phi_laplacian,contrast_func=contrast_laplacian,mu=1.0,n_ica_iterations=20,is_use_non_holonomic=True):\r\n    \r\n    #マイクロホン数を取得する\r\n    M=np.shape(x)[0]\r\n\r\n    cost_buff=[]\r\n    for t in range(n_ica_iterations):\r\n        #音源分離信号を得る\r\n        s_hat=np.einsum('kmn,nkt->mkt',W,x)\r\n\r\n        #コントラスト関数を計算\r\n        G=contrast_func(s_hat)\r\n\r\n        #コスト計算\r\n        cost=np.sum(np.mean(G,axis=-1))-np.sum(2.*np.log(np.abs(np.linalg.det(W)) ))\r\n        cost_buff.append(cost)\r\n\r\n        #コンストラクト関数の微分を取得\r\n        phi=phi_func(s_hat)\r\n\r\n        phi_s=np.einsum('mkt,nkt->ktmn',phi,np.conjugate(s_hat))\r\n        phi_s=np.mean(phi_s,axis=1)\r\n\r\n        I=np.eye(M,M)\r\n        if is_use_non_holonomic==False:\r\n            deltaW=np.einsum('kmi,kin->kmn',I[None,...]-phi_s,W)\r\n        else:\r\n            mask=(np.ones((M,M))-I)[None,...]\r\n            deltaW=np.einsum('kmi,kin->kmn',np.multiply(mask,-phi_s),W)\r\n            \r\n        #フィルタを更新する\r\n        W=W+mu*deltaW\r\n    \r\n    #最後に出力信号を分離\r\n    s_hat=np.einsum('kmn,nkt->mkt',W,x)\r\n\r\n    return(W,s_hat,cost_buff)\r\n\r\n#IP法による分離フィルタ更新\r\n#x:入力信号( M, Nk, Lt)\r\n#W: 分離フィルタ(Nk,M,M)\r\n#n_iterations: 繰り返しステップ数\r\n#return W 分離フィルタ(Nk,M,M) s_hat 出力信号(M,Nk, Lt),cost_buff コスト (T)\r\ndef execute_ip_multivariate_laplacian_iva(x,W,n_iterations=20):\r\n    \r\n    #マイクロホン数を取得する\r\n    M=np.shape(x)[0]\r\n\r\n    cost_buff=[]\r\n    for t in range(n_iterations):\r\n        \r\n        #音源分離信号を得る\r\n        s_hat=np.einsum('kmn,nkt->mkt',W,x)\r\n\r\n        #補助変数を更新する\r\n        v=np.sqrt(np.sum(np.square(np.abs(s_hat)),axis=1))\r\n\r\n        #コントラスト関数を計算\r\n        G=contrast_multivariate_laplacian(s_hat)\r\n\r\n        #コスト計算\r\n        cost=np.sum(np.mean(G,axis=-1))-np.sum(2.*np.log(np.abs(np.linalg.det(W)) ))\r\n        cost_buff.append(cost)\r\n\r\n        #IP法による更新\r\n        Q=np.einsum('st,mkt,nkt->tksmn',1./np.maximum(v,1.e-18),x,np.conjugate(x))\r\n        Q=np.average(Q,axis=0)\r\n        \r\n        for source_index in range(M):\r\n            WQ=np.einsum('kmi,kin->kmn',W,Q[:,source_index,:,:])\r\n            invWQ=np.linalg.pinv(WQ)\r\n            W[:,source_index,:]=np.conjugate(invWQ[:,:,source_index])\r\n            wVw=np.einsum('km,kmn,kn->k',W[:,source_index,:],Q[:,source_index,:,:],np.conjugate(W[:,source_index,:]))\r\n            wVw=np.sqrt(np.abs(wVw))\r\n            W[:,source_index,:]=W[:,source_index,:]/np.maximum(wVw[:,None],1.e-18)\r\n\r\n \r\n    s_hat=np.einsum('kmn,nkt->mkt',W,x)\r\n\r\n    return(W,s_hat,cost_buff)\r\n\r\n#IP法による分離フィルタ更新\r\n#x:入力信号( M, Nk, Lt)\r\n#W: 分離フィルタ(Nk,M,M)\r\n#a: アクティビティ(B,M,Lt)\r\n#b: 基底(Nk,M,B)\r\n#n_iterations: 繰り返しステップ数\r\n#return W 分離フィルタ(Nk,M,M) s_hat 出力信号(M,Nk, Lt),cost_buff コスト (T)\r\ndef execute_ip_time_varying_gaussian_ilrma(x,W,a,b,n_iterations=20):\r\n    \r\n    #マイクロホン数・周波数・フレーム数を取得する\r\n    M=np.shape(x)[0]\r\n    Nk=np.shape(x)[1]\r\n    Lt=np.shape(x)[2]\r\n\r\n    cost_buff=[]\r\n    for t in range(n_iterations):\r\n        \r\n        #音源分離信号を得る\r\n        s_hat=np.einsum('kmn,nkt->mkt',W,x)\r\n        s_power=np.square(np.abs(s_hat)) \r\n\r\n        #時間周波数分散を更新\r\n        v=np.einsum(\"bst,ksb->skt\",a,b)\r\n\r\n        #アクティビティの更新\r\n        a=a*np.sqrt(np.einsum(\"ksb,skt->bst\",b,s_power/np.maximum(v,1.e-18)**2)/np.einsum(\"ksb,skt->bst\",b,1./np.maximum(v,1.e-18)))\r\n        \r\n        #基底の更新\r\n        b=b*np.sqrt(np.einsum(\"bst,skt->ksb\",a,s_power /np.maximum(v,1.e-18)**2) /np.einsum(\"bst,skt->ksb\",a,1./np.maximum(v,1.e-18)))\r\n        \r\n        #時間周波数分散を再度更新\r\n        v=np.einsum(\"bst,ksb->skt\",a,b)\r\n\r\n        #コスト計算\r\n        cost=np.sum(np.mean(s_power/np.maximum(v,1.e-18)+np.log(v),axis=-1)) -np.sum(2.*np.log(np.abs(np.linalg.det(W)) ))\r\n        cost_buff.append(cost)\r\n\r\n        #IP法による更新\r\n        Q=np.einsum('skt,mkt,nkt->tksmn',1./np.maximum(v,1.e-18),x,np.conjugate(x))\r\n        Q=np.average(Q,axis=0)\r\n        \r\n        for source_index in range(M):\r\n            WQ=np.einsum('kmi,kin->kmn',W,Q[:,source_index,:,:])\r\n            invWQ=np.linalg.pinv(WQ)\r\n            W[:,source_index,:]=np.conjugate(invWQ[:,:,source_index])\r\n            wVw=np.einsum('km,kmn,kn->k',W[:,source_index,:],Q[:,source_index,:,:],np.conjugate(W[:,source_index,:]))\r\n            wVw=np.sqrt(np.abs(wVw))\r\n            W[:,source_index,:]=W[:,source_index,:]/np.maximum(wVw[:,None],1.e-18)\r\n\r\n \r\n    s_hat=np.einsum('kmn,nkt->mkt',W,x)\r\n\r\n    return(W,s_hat,cost_buff)\r\n\r\n\r\n#周波数間の振幅相関に基づくパーミュテーション解法\r\n#s_hat: M,Nk,Lt\r\n#return permutation_index_result：周波数毎のパーミュテーション解 \r\ndef solver_inter_frequency_permutation(s_hat):\r\n    n_sources=np.shape(s_hat)[0]\r\n    n_freqs=np.shape(s_hat)[1]\r\n    n_frames=np.shape(s_hat)[2]\r\n\r\n    s_hat_abs=np.abs(s_hat)\r\n\r\n    norm_amp=np.sqrt(np.sum(np.square(s_hat_abs),axis=0,keepdims=True))\r\n    s_hat_abs=s_hat_abs/np.maximum(norm_amp,1.e-18)\r\n\r\n    spectral_similarity=np.einsum('mkt,nkt->k',s_hat_abs,s_hat_abs)\r\n    \r\n    frequency_order=np.argsort(spectral_similarity)\r\n    \r\n    #音源間の相関が最も低い周波数からパーミュテーションを解く\r\n    is_first=True\r\n    permutations=list(itertools.permutations(range(n_sources)))\r\n    permutation_index_result={}\r\n    \r\n    for freq in frequency_order:\r\n        \r\n        if is_first==True:\r\n            is_first=False\r\n\r\n            #初期値を設定する\r\n            accumurate_s_abs=s_hat_abs[:,frequency_order[0],:]\r\n            permutation_index_result[freq]=range(n_sources)\r\n        else:\r\n            max_correlation=0\r\n            max_correlation_perm=None\r\n            for perm in permutations:\r\n                s_hat_abs_temp=s_hat_abs[list(perm),freq,:]\r\n                correlation=np.sum(accumurate_s_abs*s_hat_abs_temp)\r\n                \r\n                \r\n                if max_correlation_perm is None:\r\n                    max_correlation_perm=list(perm)\r\n                    max_correlation=correlation\r\n                elif max_correlation < correlation:\r\n                    max_correlation=correlation\r\n                    max_correlation_perm=list(perm)\r\n            permutation_index_result[freq]=max_correlation_perm\r\n            accumurate_s_abs+=s_hat_abs[max_correlation_perm,freq,:]\r\n   \r\n    return(permutation_index_result)\r\n    \r\n#プロジェクションバックで最終的な出力信号を求める\r\n#s_hat: M,Nk,Lt\r\n#W: 分離フィルタ(Nk,M,M)\r\n#retunr c_hat: マイクロホン位置での分離結果(M,M,Nk,Lt)\r\ndef projection_back(s_hat,W):\r\n    \r\n    #ステアリングベクトルを推定\r\n    A=np.linalg.pinv(W)\r\n    c_hat=np.einsum('kmi,ikt->mikt',A,s_hat)\r\n    return(c_hat)\r\n\r\n\r\n#2バイトに変換してファイルに保存\r\n#signal: time-domain 1d array (float)\r\n#file_name: 出力先のファイル名\r\n#sample_rate: サンプリングレート\r\ndef write_file_from_time_signal(signal,file_name,sample_rate):\r\n    #2バイトのデータに変換\r\n    signal=signal.astype(np.int16)\r\n\r\n    #waveファイルに書き込む\r\n    wave_out = wave.open(file_name, 'w')\r\n\r\n    #モノラル:1、ステレオ:2\r\n    wave_out.setnchannels(1)\r\n\r\n    #サンプルサイズ2byte\r\n    wave_out.setsampwidth(2)\r\n\r\n    #サンプリング周波数\r\n    wave_out.setframerate(sample_rate)\r\n\r\n    #データを書き込み\r\n    wave_out.writeframes(signal)\r\n\r\n    #ファイルを閉じる\r\n    wave_out.close()\r\n\r\n#SNRをはかる\r\n#desired: 目的音、Lt\r\n#out:　雑音除去後の信号 Lt\r\ndef calculate_snr(desired,out):\r\n    wave_length=np.minimum(np.shape(desired)[0],np.shape(out)[0])\r\n\r\n    #消し残った雑音\r\n    desired=desired[:wave_length]\r\n    out=out[:wave_length]\r\n    noise=desired-out\r\n    snr=10.*np.log10(np.sum(np.square(desired))/np.sum(np.square(noise)))\r\n\r\n    return(snr)\r\n\r\n#乱数の種を初期化\r\nnp.random.seed(0)\r\n\r\n#畳み込みに用いる音声波形\r\nclean_wave_files=[\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\",\"./CMU_ARCTIC/cmu_us_axb_arctic/wav/arctic_a0002.wav\"]\r\n\r\n#音源数\r\nn_sources=len(clean_wave_files)\r\n\r\n#長さを調べる\r\nn_samples=0\r\n#ファイルを読み込む\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    if n_samples<wav.getnframes():\r\n        n_samples=wav.getnframes()\r\n    wav.close()\r\n\r\nclean_data=np.zeros([n_sources,n_samples])\r\n\r\n#ファイルを読み込む\r\ns=0\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    data=wav.readframes(wav.getnframes())\r\n    data=np.frombuffer(data, dtype=np.int16)\r\n    data=data/np.iinfo(np.int16).max\r\n    clean_data[s,:wav.getnframes()]=data\r\n    wav.close()\r\n    s=s+1\r\n\r\n\r\n# シミュレーションのパラメータ\r\n\r\n#シミュレーションで用いる音源数\r\nn_sim_sources=2\r\n\r\n#サンプリング周波数\r\nsample_rate=16000\r\n\r\n#フレームサイズ\r\nN=1024\r\n\r\n#周波数の数\r\nNk=int(N/2+1)\r\n\r\n#各ビンの周波数\r\nfreqs=np.arange(0,Nk,1)*sample_rate/N\r\n\r\n#音声と雑音との比率 [dB]\r\nSNR=90.\r\n\r\n#部屋の大きさ\r\nroom_dim = np.r_[10.0, 10.0, 10.0]\r\n\r\n#マイクロホンアレイを置く部屋の場所\r\nmic_array_loc = room_dim / 2 + np.random.randn(3) * 0.1 \r\n\r\n#マイクロホンアレイのマイク配置\r\nmic_directions=np.array(\r\n    [[np.pi/2., theta/180.*np.pi] for theta in np.arange(180,361,180)\r\n    ]    )\r\n\r\ndistance=0.01\r\nmic_alignments=np.zeros((3, mic_directions.shape[0]), dtype=mic_directions.dtype)\r\nmic_alignments[0, :] = np.cos(mic_directions[:, 1]) * np.sin(mic_directions[:, 0])\r\nmic_alignments[1, :] = np.sin(mic_directions[:, 1]) * np.sin(mic_directions[:, 0])\r\nmic_alignments[2, :] = np.cos(mic_directions[:, 0])\r\nmic_alignments *= distance\r\n\r\n#マイクロホン数\r\nn_channels=np.shape(mic_alignments)[1]\r\n\r\n#マイクロホンアレイの座標\r\nR=mic_alignments+mic_array_loc[:,None]\r\n\r\nis_use_reverb=False\r\n\r\nif is_use_reverb==False:\r\n    # 部屋を生成する\r\n    room = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0) \r\n    room_no_noise_left = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\n    room_no_noise_right = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\n\r\nelse:\r\n\r\n    room = pa.ShoeBox(room_dim, fs=sample_rate, max_order=17,absorption=0.4)\r\n    room_no_noise_left = pa.ShoeBox(room_dim, fs=sample_rate, max_order=17,absorption=0.4)\r\n    room_no_noise_right = pa.ShoeBox(room_dim, fs=sample_rate, max_order=17,absorption=0.4)\r\n\r\n# 用いるマイクロホンアレイの情報を設定する\r\nroom.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\nroom_no_noise_left.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\nroom_no_noise_right.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\n\r\n#音源の場所\r\ndoas=np.array(\r\n    [[np.pi/2., np.pi],\r\n     [np.pi/2., 0]\r\n    ]    )\r\n\r\n#音源とマイクロホンの距離\r\ndistance=1.\r\n\r\nsource_locations=np.zeros((3, doas.shape[0]), dtype=doas.dtype)\r\nsource_locations[0, :] = np.cos(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[1, :] = np.sin(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[2, :] = np.cos(doas[:, 0])\r\nsource_locations *= distance\r\nsource_locations += mic_array_loc[:, None]\r\n\r\n#各音源をシミュレーションに追加する\r\nfor s in range(n_sim_sources):\r\n    clean_data[s]/= np.std(clean_data[s])\r\n    room.add_source(source_locations[:, s], signal=clean_data[s])\r\n    if s==0:\r\n        room_no_noise_left.add_source(source_locations[:, s], signal=clean_data[s])\r\n    if s==1:\r\n        room_no_noise_right.add_source(source_locations[:, s], signal=clean_data[s])\r\n\r\n#シミュレーションを回す\r\nroom.simulate(snr=SNR)\r\nroom_no_noise_left.simulate(snr=90)\r\nroom_no_noise_right.simulate(snr=90)\r\n\r\n#畳み込んだ波形を取得する(チャンネル、サンプル）\r\nmulti_conv_data=room.mic_array.signals\r\nmulti_conv_data_left_no_noise=room_no_noise_left.mic_array.signals\r\nmulti_conv_data_right_no_noise=room_no_noise_right.mic_array.signals\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data_left_no_noise[0,:]*np.iinfo(np.int16).max/20.,\"./ica_left_clean.wav\",sample_rate)\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data_right_no_noise[0,:]*np.iinfo(np.int16).max/20.,\"./ica_right_clean.wav\",sample_rate)\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data[0,:]*np.iinfo(np.int16).max/20.,\"./ica_in_left.wav\",sample_rate)\r\nwrite_file_from_time_signal(multi_conv_data[0,:]*np.iinfo(np.int16).max/20.,\"./ica_in_right.wav\",sample_rate)\r\n\r\n#短時間フーリエ変換を行う\r\nf,t,stft_data=sp.stft(multi_conv_data,fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\n#ICAの繰り返し回数\r\nn_ica_iterations=50\r\n\r\n#ILRMAの基底数\r\nn_basis=2\r\n\r\n#処理するフレーm数\r\nLt=np.shape(stft_data)[-1]\r\n\r\n#ICAの分離フィルタを初期化\r\nWica=np.zeros(shape=(Nk,n_sources,n_sources),dtype=np.complex)\r\n\r\nWica=Wica+np.eye(n_sources)[None,...]\r\n\r\nWiva=Wica.copy()\r\nWiva_ip=Wica.copy()\r\nWilrma_ip=Wica.copy()\r\n\r\n#ILRMA用\r\nb=np.ones(shape=(Nk,n_sources,n_basis))\r\na=np.random.uniform(size=(n_basis*n_sources*Lt))\r\na=np.reshape(a,(n_basis,n_sources,Lt))\r\n\r\nstart_time=time.time()\r\n\r\n#自然勾配法に基づくIVA実行コード\r\nWiva,s_iva,cost_buff_iva=execute_natural_gradient_ica(stft_data,Wiva,phi_func=phi_multivariate_laplacian,contrast_func=contrast_multivariate_laplacian,mu=0.1,n_ica_iterations=n_ica_iterations,is_use_non_holonomic=False)\r\ny_iva=projection_back(s_iva,Wiva)\r\niva_time=time.time()\r\n\r\n#IP法に基づくILRMA実行コード\r\nWilrma_ip,s_ilrma_ip,cost_buff_ilrma_ip=execute_ip_time_varying_gaussian_ilrma(stft_data,Wilrma_ip,a,b,n_iterations=n_ica_iterations)\r\ny_ilrma_ip=projection_back(s_ilrma_ip,Wilrma_ip)\r\nilrma_ip_time=time.time()\r\n\r\n#IP法に基づくIVA実行コード\r\nWiva_ip,s_iva_ip,cost_buff_iva_ip=execute_ip_multivariate_laplacian_iva(stft_data,Wiva_ip,n_iterations=n_ica_iterations)\r\ny_iva_ip=projection_back(s_iva_ip,Wiva_ip)\r\niva_ip_time=time.time()\r\n\r\n#自然勾配法に基づくICA実行コード\r\nWica,s_ica,cost_buff_ica=execute_natural_gradient_ica(stft_data,Wica,mu=0.1,n_ica_iterations=n_ica_iterations,is_use_non_holonomic=False)\r\npermutation_index_result=solver_inter_frequency_permutation(s_ica)\r\ny_ica=projection_back(s_ica,Wica)\r\n\r\n#パーミュテーションを解く\r\nfor k in range(Nk):\r\n    y_ica[:,:,k,:]=y_ica[:,permutation_index_result[k],k,:]\r\n\r\nica_time=time.time()\r\n\r\nt,y_ica=sp.istft(y_ica[0,...],fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,y_iva=sp.istft(y_iva[0,...],fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,y_iva_ip=sp.istft(y_iva_ip[0,...],fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,y_ilrma_ip=sp.istft(y_ilrma_ip[0,...],fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\nsnr_pre=calculate_snr(multi_conv_data_left_no_noise[0,...],multi_conv_data[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],multi_conv_data[0,...])\r\nsnr_pre/=2.\r\n\r\nsnr_ica_post1=calculate_snr(multi_conv_data_left_no_noise[0,...],y_ica[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_ica[1,...])\r\nsnr_ica_post2=calculate_snr(multi_conv_data_left_no_noise[0,...],y_ica[1,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_ica[0,...])\r\n\r\nsnr_ica_post=np.maximum(snr_ica_post1,snr_ica_post2)\r\nsnr_ica_post/=2.\r\n\r\nsnr_iva_post1=calculate_snr(multi_conv_data_left_no_noise[0,...],y_iva[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_iva[1,...])\r\nsnr_iva_post2=calculate_snr(multi_conv_data_left_no_noise[0,...],y_iva[1,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_iva[0,...])\r\n\r\nsnr_iva_post=np.maximum(snr_iva_post1,snr_iva_post2)\r\nsnr_iva_post/=2.\r\n\r\nsnr_iva_ip_post1=calculate_snr(multi_conv_data_left_no_noise[0,...],y_iva_ip[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_iva_ip[1,...])\r\nsnr_iva_ip_post2=calculate_snr(multi_conv_data_left_no_noise[0,...],y_iva_ip[1,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_iva_ip[0,...])\r\n\r\nsnr_iva_ip_post=np.maximum(snr_iva_ip_post1,snr_iva_ip_post2)\r\nsnr_iva_ip_post/=2.\r\n\r\nsnr_ilrma_ip_post1=calculate_snr(multi_conv_data_left_no_noise[0,...],y_ilrma_ip[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_ilrma_ip[1,...])\r\nsnr_ilrma_ip_post2=calculate_snr(multi_conv_data_left_no_noise[0,...],y_ilrma_ip[1,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_ilrma_ip[0,...])\r\n\r\nsnr_ilrma_ip_post=np.maximum(snr_ilrma_ip_post1,snr_ilrma_ip_post2)\r\nsnr_ilrma_ip_post/=2.\r\n\r\nwrite_file_from_time_signal(y_ica[0,...]*np.iinfo(np.int16).max/20.,\"./ica_1.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_ica[1,...]*np.iinfo(np.int16).max/20.,\"./ica_2.wav\",sample_rate)\r\n\r\nwrite_file_from_time_signal(y_iva[0,...]*np.iinfo(np.int16).max/20.,\"./iva_1.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_iva[1,...]*np.iinfo(np.int16).max/20.,\"./iva_2.wav\",sample_rate)\r\n\r\nwrite_file_from_time_signal(y_iva_ip[0,...]*np.iinfo(np.int16).max/20.,\"./iva_ip_1.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_iva_ip[1,...]*np.iinfo(np.int16).max/20.,\"./iva_ip_2.wav\",sample_rate)\r\n\r\nwrite_file_from_time_signal(y_ilrma_ip[0,...]*np.iinfo(np.int16).max/20.,\"./ilrma_ip_1.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_ilrma_ip[1,...]*np.iinfo(np.int16).max/20.,\"./ilrma_ip_2.wav\",sample_rate)\r\n\r\n\r\nprint(\"method:    \", \"NG-ICA\", \"NG-IVA\", \"AuxIVA\", \"ILRMA\")\r\nprint(\"処理時間[sec]: {:.2f}  {:.2f}  {:.2f}  {:.2f}\".format(ica_time-iva_ip_time,iva_ip_time-ilrma_ip_time,iva_time-start_time,ilrma_ip_time-iva_time))\r\nprint(\"Δsnr [dB]: {:.2f}  {:.2f}  {:.2f}  {:.2f}\".format(snr_ica_post-snr_pre,snr_iva_post-snr_pre,snr_iva_ip_post-snr_pre,snr_ilrma_ip_post-snr_pre))\r\n\r\n#コストの値を表示\r\n#for t in range(n_ica_iterations):\r\n#    print(t,cost_buff_ica[t],cost_buff_iva[t],cost_buff_iva_ip[t],cost_buff_ilrma_ip[t])\r\n\r\n"
  },
  {
    "path": "section8/sample_code_c8_4.py",
    "content": "\r\n\r\nimport wave as wave\r\nimport pyroomacoustics as pa\r\nimport numpy as np\r\nimport scipy.signal as sp\r\nimport scipy as scipy\r\n\r\n#順列計算に使用\r\nimport itertools\r\nimport time\r\n\r\n\r\n\r\n#コントラスト関数の微分（球対称多次元ラプラス分布を仮定）\r\n#s_hat: 分離信号(M, Nk, Lt)\r\ndef phi_multivariate_laplacian(s_hat):\r\n\r\n    power=np.square(np.abs(s_hat))\r\n    norm=np.sqrt(np.sum(power,axis=1,keepdims=True))\r\n\r\n    phi=s_hat/np.maximum(norm,1.e-18)\r\n    return(phi)\r\n\r\n#コントラスト関数の微分（球対称ラプラス分布を仮定）\r\n#s_hat: 分離信号(M, Nk, Lt)\r\ndef phi_laplacian(s_hat):\r\n\r\n    norm=np.abs(s_hat)\r\n    phi=s_hat/np.maximum(norm,1.e-18)\r\n    return(phi)\r\n\r\n#コントラスト関数（球対称ラプラス分布を仮定）\r\n#s_hat: 分離信号(M, Nk, Lt)\r\ndef contrast_laplacian(s_hat):\r\n\r\n    norm=2.*np.abs(s_hat)\r\n    \r\n    return(norm)\r\n\r\n#コントラスト関数（球対称多次元ラプラス分布を仮定）\r\n#s_hat: 分離信号(M, Nk, Lt)\r\ndef contrast_multivariate_laplacian(s_hat):\r\n    power=np.square(np.abs(s_hat))\r\n    norm=2.*np.sqrt(np.sum(power,axis=1,keepdims=True))\r\n  \r\n    return(norm)\r\n\r\n#ICAによる分離フィルタ更新\r\n#x:入力信号( M, Nk, Lt)\r\n#W: 分離フィルタ(Nk,M,M)\r\n#mu: 更新係数\r\n#n_ica_iterations: 繰り返しステップ数\r\n#phi_func: コントラスト関数の微分を与える関数\r\n#contrast_func: コントラスト関数\r\n#is_use_non_holonomic: True (非ホロノミック拘束を用いる） False (用いない）\r\n#return W 分離フィルタ(Nk,M,M) s_hat 出力信号(M,Nk, Lt),cost_buff ICAのコスト (T)\r\ndef execute_natural_gradient_ica(x,W,phi_func=phi_laplacian,contrast_func=contrast_laplacian,mu=1.0,n_ica_iterations=20,is_use_non_holonomic=True):\r\n    \r\n    #マイクロホン数を取得する\r\n    M=np.shape(x)[0]\r\n\r\n    cost_buff=[]\r\n    for t in range(n_ica_iterations):\r\n        #音源分離信号を得る\r\n        s_hat=np.einsum('kmn,nkt->mkt',W,x)\r\n\r\n        #コントラスト関数を計算\r\n        G=contrast_func(s_hat)\r\n\r\n        #コスト計算\r\n        cost=np.sum(np.mean(G,axis=-1))-np.sum(2.*np.log(np.abs(np.linalg.det(W)) ))\r\n        cost_buff.append(cost)\r\n\r\n        #コンストラクト関数の微分を取得\r\n        phi=phi_func(s_hat)\r\n\r\n        phi_s=np.einsum('mkt,nkt->ktmn',phi,np.conjugate(s_hat))\r\n        phi_s=np.mean(phi_s,axis=1)\r\n\r\n        I=np.eye(M,M)\r\n        if is_use_non_holonomic==False:\r\n            deltaW=np.einsum('kmi,kin->kmn',I[None,...]-phi_s,W)\r\n        else:\r\n            mask=(np.ones((M,M))-I)[None,...]\r\n            deltaW=np.einsum('kmi,kin->kmn',np.multiply(mask,-phi_s),W)\r\n            \r\n        #フィルタを更新する\r\n        W=W+mu*deltaW\r\n    \r\n    #最後に出力信号を分離\r\n    s_hat=np.einsum('kmn,nkt->mkt',W,x)\r\n\r\n    return(W,s_hat,cost_buff)\r\n\r\n#EM法によるLGMのパラメータ推定法\r\n#x:入力信号( M, Nk, Lt)\r\n#Ns: 音源数\r\n#n_iterations: 繰り返しステップ数\r\n#return R 共分散行列(Nk,Ns,M,M) v 時間周波数分散(Nk,Ns,Lt),c_bar 音源分離信号(M,Ns,Nk,Lt), cost_buff コスト (T)\r\ndef execute_em_lgm(x,Ns=2,n_iterations=20):\r\n    \r\n    #マイクロホン数・周波数・フレーム数を取得する\r\n    M=np.shape(x)[0]\r\n    Nk=np.shape(x)[1]\r\n    Lt=np.shape(x)[2]\r\n\r\n    #Rとvを初期化する\r\n    mask=np.random.uniform(size=Nk*Ns*Lt)\r\n    mask=np.reshape(mask,(Nk,Ns,Lt))\r\n    R=np.einsum(\"kst,mkt,nkt->kstmn\",mask,x,np.conjugate(x))\r\n    R=np.average(R,axis=2)\r\n    v=np.random.uniform(size=Nk*Ns*Lt)\r\n    v=np.reshape(v,(Nk,Ns,Lt))\r\n\r\n    cost_buff=[]\r\n    for t in range(n_iterations):\r\n        \r\n        #入力信号の共分散行列を求める\r\n        vR=np.einsum(\"kst,ksmn->kstmn\",v,R)\r\n        V=np.sum(vR,axis=1)\r\n        V_inverse=np.linalg.pinv(V)\r\n\r\n        #コスト計算\r\n        cost=np.sum(np.einsum(\"mkt,ktmn,nkt->kt\",np.conjugate(x),V_inverse,x) +np.log(np.abs(np.linalg.det(V))))\r\n        cost/=np.float(Lt)\r\n        cost=np.real(cost)\r\n        cost_buff.append(cost)\r\n\r\n        Wmwf=np.einsum(\"kstmi,ktin->kstmn\",vR,V_inverse)\r\n\r\n        #事後確率計算に必要なパラメータを推定\r\n        c_bar=np.einsum('kstmn,nkt->kstm',Wmwf,x)\r\n        R_bar=np.einsum(\"kstmi,kstin->kstmn\",-1.*Wmwf+np.eye(M),vR)\r\n        P_bar=R_bar+np.einsum(\"kstm,kstn->kstmn\",c_bar,np.conjugate(c_bar))\r\n        \r\n        #パラメータを更新\r\n        R=np.average(P_bar/np.maximum(v,1.e-18)[...,None,None],axis=2)\r\n\r\n        R_inverse=np.linalg.pinv(R)\r\n        v=np.einsum(\"ksmi,kstim->kst\",R_inverse,P_bar)\r\n        v=v/np.float(M)\r\n\r\n\r\n    vR=np.einsum(\"kst,ksmn->kstmn\",v,R)\r\n    V=np.sum(vR,axis=1)\r\n    V_inverse=np.linalg.pinv(V)\r\n    Wmwf=np.einsum(\"kstmi,ktin->kstmn\",vR,V_inverse)\r\n\r\n    #音源分離信号を得る\r\n    c_bar=np.einsum('kstmn,nkt->mskt',Wmwf,x)\r\n\r\n    return(R,v,c_bar,cost_buff)\r\n\r\n\r\n\r\n#IP法によるLGMのパラメータ推定法\r\n#x:入力信号( M, Nk, Lt)\r\n#Ns: 音源数\r\n#n_iterations: 繰り返しステップ数\r\n#return R 共分散行列(Nk,Ns,M,M) v 時間周波数分散(Nk,Ns,Lt),c_bar 音源分離信号(M,Ns,Nk,Lt), cost_buff コスト (T)\r\ndef execute_mm_lgm(x,Ns=2,n_iterations=20):\r\n    \r\n    #マイクロホン数・周波数・フレーム数を取得する\r\n    M=np.shape(x)[0]\r\n    Nk=np.shape(x)[1]\r\n    Lt=np.shape(x)[2]\r\n\r\n    #Rとvを初期化する\r\n    mask=np.random.uniform(size=Nk*Ns*Lt)\r\n    mask=np.reshape(mask,(Nk,Ns,Lt))\r\n    R=np.einsum(\"kst,mkt,nkt->kstmn\",mask,x,np.conjugate(x))\r\n    R=np.average(R,axis=2)\r\n    v=np.random.uniform(size=Nk*Ns*Lt)\r\n    v=np.reshape(v,(Nk,Ns,Lt))\r\n\r\n    cost_buff=[]\r\n    for t in range(n_iterations):\r\n        \r\n        #入力信号の共分散行列を求める\r\n        vR=np.einsum(\"kst,ksmn->kstmn\",v,R)\r\n        V=np.sum(vR,axis=1)\r\n        V_inverse=np.linalg.pinv(V)\r\n\r\n        #コスト計算\r\n        cost=np.sum(np.einsum(\"mkt,ktmn,nkt->kt\",np.conjugate(x),V_inverse,x) +np.log(np.abs(np.linalg.det(V))))\r\n        cost/=np.float(Lt)\r\n        cost=np.real(cost)\r\n        cost_buff.append(cost)\r\n\r\n        #パラメータを更新\r\n        \r\n        #Rの更新\r\n        V_inverseX=np.einsum('ktmn,nkt->ktm',V_inverse,x)\r\n        V_inverseXV_inverseX=np.einsum('ktm,ktn->ktmn',V_inverseX,np.conjugate(V_inverseX))\r\n        A=np.einsum('kst,ktmn->ksmn',v,V_inverse)\r\n        B=np.einsum('kst,ktmn->ksmn',v,V_inverseXV_inverseX)\r\n        RBR=np.einsum('ksmn,ksni,ksij->ksmj',R,B,R)\r\n        invA=np.linalg.pinv(A)\r\n        A_RBR=np.matmul(A,RBR)\r\n        R=np.concatenate([np.concatenate([np.matmul(invA[k,s,...],scipy.linalg.sqrtm(A_RBR[k,s,...]))[None,None,...] for k in range(Nk)],axis=0) for s in range(Ns)],axis=1)\r\n        R=(R+np.transpose(np.conjugate(R),[0,1,3,2]))/(2.0+0.0j)\r\n\r\n        #vの更新\r\n        v=v*np.sqrt(np.einsum('ktm,ktn,ksnm->kst',V_inverseX,np.conjugate(V_inverseX),R)/np.maximum(np.einsum('ktmn,ksnm->kst',V_inverse,R) ,1.e-18))\r\n\r\n       \r\n    vR=np.einsum(\"kst,ksmn->kstmn\",v,R)\r\n    V=np.sum(vR,axis=1)\r\n    V_inverse=np.linalg.pinv(V)\r\n    Wmwf=np.einsum(\"kstmi,ktin->kstmn\",vR,V_inverse)\r\n\r\n    #音源分離信号を得る\r\n    c_bar=np.einsum('kstmn,nkt->mskt',Wmwf,x)\r\n\r\n    return(R,v,c_bar,cost_buff)\r\n\r\n#IP法による分離フィルタ更新\r\n#x:入力信号( M, Nk, Lt)\r\n#W: 分離フィルタ(Nk,M,M)\r\n#n_iterations: 繰り返しステップ数\r\n#return W 分離フィルタ(Nk,M,M) s_hat 出力信号(M,Nk, Lt),cost_buff コスト (T)\r\ndef execute_ip_multivariate_laplacian_iva(x,W,n_iterations=20):\r\n    \r\n    #マイクロホン数を取得する\r\n    M=np.shape(x)[0]\r\n\r\n    cost_buff=[]\r\n    for t in range(n_iterations):\r\n        \r\n        #音源分離信号を得る\r\n        s_hat=np.einsum('kmn,nkt->mkt',W,x)\r\n\r\n        #補助変数を更新する\r\n        v=np.sqrt(np.sum(np.square(np.abs(s_hat)),axis=1))\r\n\r\n        #コントラスト関数を計算\r\n        G=contrast_multivariate_laplacian(s_hat)\r\n\r\n        #コスト計算\r\n        cost=np.sum(np.mean(G,axis=-1))-np.sum(2.*np.log(np.abs(np.linalg.det(W)) ))\r\n        cost_buff.append(cost)\r\n\r\n        #IP法による更新\r\n        Q=np.einsum('st,mkt,nkt->tksmn',1./np.maximum(v,1.e-18),x,np.conjugate(x))\r\n        Q=np.average(Q,axis=0)\r\n        \r\n        for source_index in range(M):\r\n            WQ=np.einsum('kmi,kin->kmn',W,Q[:,source_index,:,:])\r\n            invWQ=np.linalg.pinv(WQ)\r\n            W[:,source_index,:]=np.conjugate(invWQ[:,:,source_index])\r\n            wVw=np.einsum('km,kmn,kn->k',W[:,source_index,:],Q[:,source_index,:,:],np.conjugate(W[:,source_index,:]))\r\n            wVw=np.sqrt(np.abs(wVw))\r\n            W[:,source_index,:]=W[:,source_index,:]/np.maximum(wVw[:,None],1.e-18)\r\n\r\n \r\n    s_hat=np.einsum('kmn,nkt->mkt',W,x)\r\n\r\n    return(W,s_hat,cost_buff)\r\n\r\n#IP法による分離フィルタ更新\r\n#x:入力信号( M, Nk, Lt)\r\n#W: 分離フィルタ(Nk,M,M)\r\n#a: アクティビティ(B,M,Lt)\r\n#b: 基底(Nk,M,B)\r\n#n_iterations: 繰り返しステップ数\r\n#return W 分離フィルタ(Nk,M,M) s_hat 出力信号(M,Nk, Lt),cost_buff コスト (T)\r\ndef execute_ip_time_varying_gaussian_ilrma(x,W,a,b,n_iterations=20):\r\n    \r\n    #マイクロホン数・周波数・フレーム数を取得する\r\n    M=np.shape(x)[0]\r\n    Nk=np.shape(x)[1]\r\n    Lt=np.shape(x)[2]\r\n\r\n    cost_buff=[]\r\n    for t in range(n_iterations):\r\n        \r\n        #音源分離信号を得る\r\n        s_hat=np.einsum('kmn,nkt->mkt',W,x)\r\n        s_power=np.square(np.abs(s_hat)) \r\n\r\n        #時間周波数分散を更新\r\n        v=np.einsum(\"bst,ksb->skt\",a,b)\r\n\r\n        #アクティビティの更新\r\n        a=a*np.sqrt(np.einsum(\"ksb,skt->bst\",b,s_power/np.maximum(v,1.e-18)**2)/np.einsum(\"ksb,skt->bst\",b,1./np.maximum(v,1.e-18)))\r\n        \r\n        #基底の更新\r\n        b=b*np.sqrt(np.einsum(\"bst,skt->ksb\",a,s_power /np.maximum(v,1.e-18)**2) /np.einsum(\"bst,skt->ksb\",a,1./np.maximum(v,1.e-18)))\r\n        \r\n        #時間周波数分散を再度更新\r\n        v=np.einsum(\"bst,ksb->skt\",a,b)\r\n\r\n        #コスト計算\r\n        cost=np.sum(np.mean(s_power/np.maximum(v,1.e-18)+np.log(v),axis=-1)) -np.sum(2.*np.log(np.abs(np.linalg.det(W)) ))\r\n        cost_buff.append(cost)\r\n\r\n        #IP法による更新\r\n        Q=np.einsum('skt,mkt,nkt->tksmn',1./np.maximum(v,1.e-18),x,np.conjugate(x))\r\n        Q=np.average(Q,axis=0)\r\n        \r\n        for source_index in range(M):\r\n            WQ=np.einsum('kmi,kin->kmn',W,Q[:,source_index,:,:])\r\n            invWQ=np.linalg.pinv(WQ)\r\n            W[:,source_index,:]=np.conjugate(invWQ[:,:,source_index])\r\n            wVw=np.einsum('km,kmn,kn->k',W[:,source_index,:],Q[:,source_index,:,:],np.conjugate(W[:,source_index,:]))\r\n            wVw=np.sqrt(np.abs(wVw))\r\n            W[:,source_index,:]=W[:,source_index,:]/np.maximum(wVw[:,None],1.e-18)\r\n\r\n \r\n    s_hat=np.einsum('kmn,nkt->mkt',W,x)\r\n\r\n    return(W,s_hat,cost_buff)\r\n\r\n\r\n#周波数間の振幅相関に基づくパーミュテーション解法\r\n#s_hat: M,Nk,Lt\r\n#return permutation_index_result：周波数毎のパーミュテーション解 \r\ndef solver_inter_frequency_permutation(s_hat):\r\n    n_sources=np.shape(s_hat)[0]\r\n    n_freqs=np.shape(s_hat)[1]\r\n    n_frames=np.shape(s_hat)[2]\r\n\r\n    s_hat_abs=np.abs(s_hat)\r\n\r\n    norm_amp=np.sqrt(np.sum(np.square(s_hat_abs),axis=0,keepdims=True))\r\n    s_hat_abs=s_hat_abs/np.maximum(norm_amp,1.e-18)\r\n\r\n    spectral_similarity=np.einsum('mkt,nkt->k',s_hat_abs,s_hat_abs)\r\n    \r\n    frequency_order=np.argsort(spectral_similarity)\r\n    \r\n    #音源間の相関が最も低い周波数からパーミュテーションを解く\r\n    is_first=True\r\n    permutations=list(itertools.permutations(range(n_sources)))\r\n    permutation_index_result={}\r\n    \r\n    for freq in frequency_order:\r\n        \r\n        if is_first==True:\r\n            is_first=False\r\n\r\n            #初期値を設定する\r\n            accumurate_s_abs=s_hat_abs[:,frequency_order[0],:]\r\n            permutation_index_result[freq]=range(n_sources)\r\n        else:\r\n            max_correlation=0\r\n            max_correlation_perm=None\r\n            for perm in permutations:\r\n                s_hat_abs_temp=s_hat_abs[list(perm),freq,:]\r\n                correlation=np.sum(accumurate_s_abs*s_hat_abs_temp)\r\n                \r\n                \r\n                if max_correlation_perm is None:\r\n                    max_correlation_perm=list(perm)\r\n                    max_correlation=correlation\r\n                elif max_correlation < correlation:\r\n                    max_correlation=correlation\r\n                    max_correlation_perm=list(perm)\r\n            permutation_index_result[freq]=max_correlation_perm\r\n            accumurate_s_abs+=s_hat_abs[max_correlation_perm,freq,:]\r\n   \r\n    return(permutation_index_result)\r\n    \r\n#プロジェクションバックで最終的な出力信号を求める\r\n#s_hat: M,Nk,Lt\r\n#W: 分離フィルタ(Nk,M,M)\r\n#retunr c_hat: マイクロホン位置での分離結果(M,M,Nk,Lt)\r\ndef projection_back(s_hat,W):\r\n    \r\n    #ステアリングベクトルを推定\r\n    A=np.linalg.pinv(W)\r\n    c_hat=np.einsum('kmi,ikt->mikt',A,s_hat)\r\n    return(c_hat)\r\n\r\n\r\n#2バイトに変換してファイルに保存\r\n#signal: time-domain 1d array (float)\r\n#file_name: 出力先のファイル名\r\n#sample_rate: サンプリングレート\r\ndef write_file_from_time_signal(signal,file_name,sample_rate):\r\n    #2バイトのデータに変換\r\n    signal=signal.astype(np.int16)\r\n\r\n    #waveファイルに書き込む\r\n    wave_out = wave.open(file_name, 'w')\r\n\r\n    #モノラル:1、ステレオ:2\r\n    wave_out.setnchannels(1)\r\n\r\n    #サンプルサイズ2byte\r\n    wave_out.setsampwidth(2)\r\n\r\n    #サンプリング周波数\r\n    wave_out.setframerate(sample_rate)\r\n\r\n    #データを書き込み\r\n    wave_out.writeframes(signal)\r\n\r\n    #ファイルを閉じる\r\n    wave_out.close()\r\n\r\n#SNRをはかる\r\n#desired: 目的音、Lt\r\n#out:　雑音除去後の信号 Lt\r\ndef calculate_snr(desired,out):\r\n    wave_length=np.minimum(np.shape(desired)[0],np.shape(out)[0])\r\n\r\n    #消し残った雑音\r\n    desired=desired[:wave_length]\r\n    out=out[:wave_length]\r\n    noise=desired-out\r\n    snr=10.*np.log10(np.sum(np.square(desired))/np.sum(np.square(noise)))\r\n\r\n    return(snr)\r\n\r\n#乱数の種を初期化\r\nnp.random.seed(0)\r\n\r\n#畳み込みに用いる音声波形\r\nclean_wave_files=[\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\",\"./CMU_ARCTIC/cmu_us_axb_arctic/wav/arctic_a0002.wav\"]\r\n\r\n#音源数\r\nn_sources=len(clean_wave_files)\r\n\r\n#長さを調べる\r\nn_samples=0\r\n#ファイルを読み込む\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    if n_samples<wav.getnframes():\r\n        n_samples=wav.getnframes()\r\n    wav.close()\r\n\r\nclean_data=np.zeros([n_sources,n_samples])\r\n\r\n#ファイルを読み込む\r\ns=0\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    data=wav.readframes(wav.getnframes())\r\n    data=np.frombuffer(data, dtype=np.int16)\r\n    data=data/np.iinfo(np.int16).max\r\n    clean_data[s,:wav.getnframes()]=data\r\n    wav.close()\r\n    s=s+1\r\n\r\n\r\n# シミュレーションのパラメータ\r\n\r\n#シミュレーションで用いる音源数\r\nn_sim_sources=2\r\n\r\n#サンプリング周波数\r\nsample_rate=16000\r\n\r\n#フレームサイズ\r\nN=1024\r\n\r\n#周波数の数\r\nNk=int(N/2+1)\r\n\r\n#各ビンの周波数\r\nfreqs=np.arange(0,Nk,1)*sample_rate/N\r\n\r\n#音声と雑音との比率 [dB]\r\nSNR=90.\r\n\r\n#部屋の大きさ\r\nroom_dim = np.r_[10.0, 10.0, 10.0]\r\n\r\n#マイクロホンアレイを置く部屋の場所\r\nmic_array_loc = room_dim / 2 + np.random.randn(3) * 0.1 \r\n\r\n#マイクロホンアレイのマイク配置\r\nmic_directions=np.array(\r\n    [[np.pi/2., theta/180.*np.pi] for theta in np.arange(180,361,180)\r\n    ]    )\r\n\r\ndistance=0.01\r\nmic_alignments=np.zeros((3, mic_directions.shape[0]), dtype=mic_directions.dtype)\r\nmic_alignments[0, :] = np.cos(mic_directions[:, 1]) * np.sin(mic_directions[:, 0])\r\nmic_alignments[1, :] = np.sin(mic_directions[:, 1]) * np.sin(mic_directions[:, 0])\r\nmic_alignments[2, :] = np.cos(mic_directions[:, 0])\r\nmic_alignments *= distance\r\n\r\n#マイクロホン数\r\nn_channels=np.shape(mic_alignments)[1]\r\n\r\n#マイクロホンアレイの座標\r\nR=mic_alignments+mic_array_loc[:,None]\r\n\r\nis_use_reverb=False\r\n\r\nif is_use_reverb==False:\r\n    # 部屋を生成する\r\n    room = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0) \r\n    room_no_noise_left = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\n    room_no_noise_right = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\n\r\nelse:\r\n\r\n    room = pa.ShoeBox(room_dim, fs=sample_rate, max_order=17,absorption=0.4)\r\n    room_no_noise_left = pa.ShoeBox(room_dim, fs=sample_rate, max_order=17,absorption=0.4)\r\n    room_no_noise_right = pa.ShoeBox(room_dim, fs=sample_rate, max_order=17,absorption=0.4)\r\n\r\n# 用いるマイクロホンアレイの情報を設定する\r\nroom.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\nroom_no_noise_left.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\nroom_no_noise_right.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\n\r\n#音源の場所\r\ndoas=np.array(\r\n    [[np.pi/2., np.pi],\r\n     [np.pi/2., 0]\r\n    ]    )\r\n\r\n#音源とマイクロホンの距離\r\ndistance=1.\r\n\r\nsource_locations=np.zeros((3, doas.shape[0]), dtype=doas.dtype)\r\nsource_locations[0, :] = np.cos(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[1, :] = np.sin(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[2, :] = np.cos(doas[:, 0])\r\nsource_locations *= distance\r\nsource_locations += mic_array_loc[:, None]\r\n\r\n#各音源をシミュレーションに追加する\r\nfor s in range(n_sim_sources):\r\n    clean_data[s]/= np.std(clean_data[s])\r\n    room.add_source(source_locations[:, s], signal=clean_data[s])\r\n    if s==0:\r\n        room_no_noise_left.add_source(source_locations[:, s], signal=clean_data[s])\r\n    if s==1:\r\n        room_no_noise_right.add_source(source_locations[:, s], signal=clean_data[s])\r\n\r\n#シミュレーションを回す\r\nroom.simulate(snr=SNR)\r\nroom_no_noise_left.simulate(snr=90)\r\nroom_no_noise_right.simulate(snr=90)\r\n\r\n#畳み込んだ波形を取得する(チャンネル、サンプル）\r\nmulti_conv_data=room.mic_array.signals\r\nmulti_conv_data_left_no_noise=room_no_noise_left.mic_array.signals\r\nmulti_conv_data_right_no_noise=room_no_noise_right.mic_array.signals\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data_left_no_noise[0,:]*np.iinfo(np.int16).max/20.,\"./ica_left_clean.wav\",sample_rate)\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data_right_no_noise[0,:]*np.iinfo(np.int16).max/20.,\"./ica_right_clean.wav\",sample_rate)\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data[0,:]*np.iinfo(np.int16).max/20.,\"./ica_in_left.wav\",sample_rate)\r\nwrite_file_from_time_signal(multi_conv_data[0,:]*np.iinfo(np.int16).max/20.,\"./ica_in_right.wav\",sample_rate)\r\n\r\n#短時間フーリエ変換を行う\r\nf,t,stft_data=sp.stft(multi_conv_data,fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\n#ICAの繰り返し回数\r\nn_ica_iterations=50\r\n\r\n#ILRMAの基底数\r\nn_basis=2\r\n\r\n#処理するフレーm数\r\nLt=np.shape(stft_data)[-1]\r\n\r\n#ICAの分離フィルタを初期化\r\nWica=np.zeros(shape=(Nk,n_sources,n_sources),dtype=np.complex)\r\n\r\nWica=Wica+np.eye(n_sources)[None,...]\r\n\r\nWiva=Wica.copy()\r\nWiva_ip=Wica.copy()\r\nWilrma_ip=Wica.copy()\r\n\r\n#ILRMA用\r\nb=np.ones(shape=(Nk,n_sources,n_basis))\r\na=np.random.uniform(size=(n_basis*n_sources*Lt))\r\na=np.reshape(a,(n_basis,n_sources,Lt))\r\n\r\nstart_time=time.time()\r\n\r\n#自然勾配法に基づくIVA実行コード\r\nWiva,s_iva,cost_buff_iva=execute_natural_gradient_ica(stft_data,Wiva,phi_func=phi_multivariate_laplacian,contrast_func=contrast_multivariate_laplacian,mu=0.1,n_ica_iterations=n_ica_iterations,is_use_non_holonomic=False)\r\ny_iva=projection_back(s_iva,Wiva)\r\niva_time=time.time()\r\n\r\n#IP法に基づくILRMA実行コード\r\nWilrma_ip,s_ilrma_ip,cost_buff_ilrma_ip=execute_ip_time_varying_gaussian_ilrma(stft_data,Wilrma_ip,a,b,n_iterations=n_ica_iterations)\r\ny_ilrma_ip=projection_back(s_ilrma_ip,Wilrma_ip)\r\nilrma_ip_time=time.time()\r\n\r\n#IP法に基づくIVA実行コード\r\nWiva_ip,s_iva_ip,cost_buff_iva_ip=execute_ip_multivariate_laplacian_iva(stft_data,Wiva_ip,n_iterations=n_ica_iterations)\r\ny_iva_ip=projection_back(s_iva_ip,Wiva_ip)\r\niva_ip_time=time.time()\r\n\r\n#自然勾配法に基づくICA実行コード\r\nWica,s_ica,cost_buff_ica=execute_natural_gradient_ica(stft_data,Wica,mu=0.1,n_ica_iterations=n_ica_iterations,is_use_non_holonomic=False)\r\npermutation_index_result=solver_inter_frequency_permutation(s_ica)\r\ny_ica=projection_back(s_ica,Wica)\r\n\r\n#パーミュテーションを解く\r\nfor k in range(Nk):\r\n    y_ica[:,:,k,:]=y_ica[:,permutation_index_result[k],k,:]\r\n\r\nica_time=time.time()\r\n\r\n#MM法に基づくLGM実行コード\r\nRlgm_mm,vlgm_mm,y_lgm_mm,cost_buff_lgm_mm=execute_mm_lgm(stft_data,Ns=n_sources,n_iterations=n_ica_iterations)\r\npermutation_index_result=solver_inter_frequency_permutation(y_lgm_mm[0,...])\r\n#パーミュテーションを解く\r\nfor k in range(Nk):\r\n    y_lgm_mm[:,:,k,:]=y_lgm_mm[:,permutation_index_result[k],k,:]\r\n\r\nlgm_mm_time=time.time()\r\n\r\n#EMアルゴリズムに基づくLGM実行コード\r\nRlgm_em,vlgm_em,y_lgm_em,cost_buff_lgm_em=execute_em_lgm(stft_data,Ns=n_sources,n_iterations=n_ica_iterations)\r\npermutation_index_result=solver_inter_frequency_permutation(y_lgm_em[0,...])\r\n#パーミュテーションを解く\r\nfor k in range(Nk):\r\n    y_lgm_em[:,:,k,:]=y_lgm_em[:,permutation_index_result[k],k,:]\r\n\r\nlgm_em_time=time.time()\r\n\r\nt,y_ica=sp.istft(y_ica[0,...],fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,y_iva=sp.istft(y_iva[0,...],fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,y_iva_ip=sp.istft(y_iva_ip[0,...],fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,y_ilrma_ip=sp.istft(y_ilrma_ip[0,...],fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,y_lgm_em=sp.istft(y_lgm_em[0,...],fs=sample_rate,window=\"hann\",nperseg=N)\r\nt,y_lgm_mm=sp.istft(y_lgm_mm[0,...],fs=sample_rate,window=\"hann\",nperseg=N)\r\n\r\nsnr_pre=calculate_snr(multi_conv_data_left_no_noise[0,...],multi_conv_data[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],multi_conv_data[0,...])\r\nsnr_pre/=2.\r\n\r\nsnr_ica_post1=calculate_snr(multi_conv_data_left_no_noise[0,...],y_ica[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_ica[1,...])\r\nsnr_ica_post2=calculate_snr(multi_conv_data_left_no_noise[0,...],y_ica[1,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_ica[0,...])\r\n\r\nsnr_ica_post=np.maximum(snr_ica_post1,snr_ica_post2)\r\nsnr_ica_post/=2.\r\n\r\nsnr_iva_post1=calculate_snr(multi_conv_data_left_no_noise[0,...],y_iva[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_iva[1,...])\r\nsnr_iva_post2=calculate_snr(multi_conv_data_left_no_noise[0,...],y_iva[1,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_iva[0,...])\r\n\r\nsnr_iva_post=np.maximum(snr_iva_post1,snr_iva_post2)\r\nsnr_iva_post/=2.\r\n\r\nsnr_iva_ip_post1=calculate_snr(multi_conv_data_left_no_noise[0,...],y_iva_ip[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_iva_ip[1,...])\r\nsnr_iva_ip_post2=calculate_snr(multi_conv_data_left_no_noise[0,...],y_iva_ip[1,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_iva_ip[0,...])\r\n\r\nsnr_iva_ip_post=np.maximum(snr_iva_ip_post1,snr_iva_ip_post2)\r\nsnr_iva_ip_post/=2.\r\n\r\nsnr_ilrma_ip_post1=calculate_snr(multi_conv_data_left_no_noise[0,...],y_ilrma_ip[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_ilrma_ip[1,...])\r\nsnr_ilrma_ip_post2=calculate_snr(multi_conv_data_left_no_noise[0,...],y_ilrma_ip[1,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_ilrma_ip[0,...])\r\n\r\nsnr_ilrma_ip_post=np.maximum(snr_ilrma_ip_post1,snr_ilrma_ip_post2)\r\nsnr_ilrma_ip_post/=2.\r\n\r\nsnr_lgm_mm_post1=calculate_snr(multi_conv_data_left_no_noise[0,...],y_lgm_mm[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_lgm_mm[1,...])\r\nsnr_lgm_mm_post2=calculate_snr(multi_conv_data_left_no_noise[0,...],y_lgm_mm[1,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_lgm_mm[0,...])\r\n\r\nsnr_lgm_mm_post=np.maximum(snr_lgm_mm_post1,snr_lgm_mm_post2)\r\nsnr_lgm_mm_post/=2.\r\n\r\nsnr_lgm_em_post1=calculate_snr(multi_conv_data_left_no_noise[0,...],y_lgm_em[0,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_lgm_em[1,...])\r\nsnr_lgm_em_post2=calculate_snr(multi_conv_data_left_no_noise[0,...],y_lgm_em[1,...])+calculate_snr(multi_conv_data_right_no_noise[0,...],y_lgm_em[0,...])\r\n\r\nsnr_lgm_em_post=np.maximum(snr_lgm_em_post1,snr_lgm_em_post2)\r\nsnr_lgm_em_post/=2.\r\n\r\n\r\nwrite_file_from_time_signal(y_ica[0,...]*np.iinfo(np.int16).max/20.,\"./ica_1.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_ica[1,...]*np.iinfo(np.int16).max/20.,\"./ica_2.wav\",sample_rate)\r\n\r\nwrite_file_from_time_signal(y_iva[0,...]*np.iinfo(np.int16).max/20.,\"./iva_1.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_iva[1,...]*np.iinfo(np.int16).max/20.,\"./iva_2.wav\",sample_rate)\r\n\r\nwrite_file_from_time_signal(y_iva_ip[0,...]*np.iinfo(np.int16).max/20.,\"./iva_ip_1.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_iva_ip[1,...]*np.iinfo(np.int16).max/20.,\"./iva_ip_2.wav\",sample_rate)\r\n\r\nwrite_file_from_time_signal(y_ilrma_ip[0,...]*np.iinfo(np.int16).max/20.,\"./ilrma_ip_1.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_ilrma_ip[1,...]*np.iinfo(np.int16).max/20.,\"./ilrma_ip_2.wav\",sample_rate)\r\n\r\nwrite_file_from_time_signal(y_lgm_em[0,...]*np.iinfo(np.int16).max/20.,\"./lgm_em_1.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_lgm_em[1,...]*np.iinfo(np.int16).max/20.,\"./lgm_em_2.wav\",sample_rate)\r\n\r\nwrite_file_from_time_signal(y_lgm_mm[0,...]*np.iinfo(np.int16).max/20.,\"./lgm_mm_1.wav\",sample_rate)\r\nwrite_file_from_time_signal(y_lgm_mm[1,...]*np.iinfo(np.int16).max/20.,\"./lgm_mm_2.wav\",sample_rate)\r\n\r\n\r\nprint(\"method:    \", \"NG-ICA\", \"NG-IVA\", \"AuxIVA\", \"ILRMA\",\"LGM-EM\",\"LGM-MM\")\r\nprint(\"処理時間[sec]: {:.2f}   {:.2f}   {:.2f}   {:.2f}   {:.2f}  {:.2f}\".format(ica_time-iva_ip_time,iva_ip_time-ilrma_ip_time,iva_time-start_time,ilrma_ip_time-iva_time,lgm_em_time-lgm_mm_time,lgm_mm_time-ica_time))\r\nprint(\"Δsnr [dB]: {:.2f}  {:.2f}  {:.2f}  {:.2f}   {:.2f}  {:.2f}\".format(snr_ica_post-snr_pre,snr_iva_post-snr_pre,snr_iva_ip_post-snr_pre,snr_ilrma_ip_post-snr_pre,snr_lgm_em_post-snr_pre,snr_lgm_mm_post-snr_pre))\r\n\r\n#コストの値を表示\r\n#for t in range(n_ica_iterations):\r\n#    print(t,cost_buff_ica[t],cost_buff_iva[t],cost_buff_iva_ip[t],cost_buff_ilrma_ip[t],cost_buff_lgm_em[t],cost_buff_lgm_mm[t])\r\n\r\n"
  },
  {
    "path": "section8.md",
    "content": "\n## 第8章のサンプルコード\n\n* [自然勾配法に基づく独立成分分析と周波数間パーミュテーション解法、およびプ\nロジェクションバックの実行コード](section8/sample_code_c8_1.py)\n* [IP法に基づく独立ベクトル分析](section8/sample_code_c8_2.py)\n* [ILRMAによる音源分離](section8/sample_code_c8_3.py)\n* [マルチチャンネル時変ガウスモデル](section8/sample_code_c8_4.py)\n"
  },
  {
    "path": "section9/sample_code_c9_1.py",
    "content": "\r\n\r\nimport wave as wave\r\nimport pyroomacoustics as pa\r\nimport numpy as np\r\nimport scipy.signal as sp\r\nimport scipy as scipy\r\n\r\n#順列計算に使用\r\nimport itertools\r\n\r\n#x:入力信号( M, Nk, Lt)\r\n#D:遅延フレーム数\r\n#Lh:残響除去フィルタのタップ長\r\n#return x_bar: 過去のマイク入力信号(Lh,M,Nk,Lt)\r\ndef make_x_bar(x,D,Lh):\r\n    \r\n    #フレーム数を取得\r\n    Lt=np.shape(x)[2]\r\n\r\n    #過去のマイク入力信号の配列を準備\r\n    x_bar=np.zeros(shape=(Lh,)+np.shape(x),dtype=np.complex)\r\n\r\n    for tau in range(Lh):\r\n        x_bar[tau,...,tau+D:]=x[:,:,:-(tau+D)]\r\n\r\n    return(x_bar)\r\n\r\n#最小二乗で除去\r\n#x:入力信号( M, Nk, Lt)\r\n#x_bar:過去のマイク入力信号(Lh,M, Nk, Lt)\r\n#return x_dereverb:残響除去後の信号(Nk,Lt)\r\ndef dereverberation_ls(x,x_bar):\r\n\r\n    #マイクロホン数・周波数・フレーム数・タップ長を取得する\r\n    M=np.shape(x)[0]\r\n    Nk=np.shape(x)[1]\r\n    Lt=np.shape(x)[2]\r\n    Lh=np.shape(x_bar)[0]\r\n\r\n    x_bar=np.reshape(x_bar,[Lh*M,Nk,Lt])\r\n    x_bar_x_bar_h=np.einsum('ikt,jkt->kij',x_bar,np.conjugate(x_bar))\r\n    #covariance_inverse=np.linalg.pinv(x_bar_x_bar_h)\r\n    \r\n    correlation=np.einsum('ikt,kt->ki',x_bar,np.conjugate(x[0,...]))\r\n    \r\n    filter=np.linalg.solve(x_bar_x_bar_h,correlation)\r\n\r\n    #filter=np.einsum('kij,kj->ki',covariance_inverse,correlation)\r\n    x_reverb=np.einsum('kj,jkt->kt',np.conjugate(filter),x_bar)\r\n\r\n    x_dereverb=x[0,...]-x_reverb\r\n        \r\n    return(x_dereverb)\r\n\r\n#2バイトに変換してファイルに保存\r\n#signal: time-domain 1d array (float)\r\n#file_name: 出力先のファイル名\r\n#sample_rate: サンプリングレート\r\ndef write_file_from_time_signal(signal,file_name,sample_rate):\r\n    #2バイトのデータに変換\r\n    signal=signal.astype(np.int16)\r\n\r\n    #waveファイルに書き込む\r\n    wave_out = wave.open(file_name, 'w')\r\n\r\n    #モノラル:1、ステレオ:2\r\n    wave_out.setnchannels(1)\r\n\r\n    #サンプルサイズ2byte\r\n    wave_out.setsampwidth(2)\r\n\r\n    #サンプリング周波数\r\n    wave_out.setframerate(sample_rate)\r\n\r\n    #データを書き込み\r\n    wave_out.writeframes(signal)\r\n\r\n    #ファイルを閉じる\r\n    wave_out.close()\r\n\r\n#SNRをはかる\r\n#desired: 目的音、Lt\r\n#out:　雑音除去後の信号 Lt\r\ndef calculate_snr(desired,out):\r\n    wave_length=np.minimum(np.shape(desired)[0],np.shape(out)[0])\r\n\r\n    #消し残った雑音\r\n    desired=desired[:wave_length]\r\n    out=out[:wave_length]\r\n    noise=desired-out\r\n    snr=10.*np.log10(np.sum(np.square(desired))/np.sum(np.square(noise)))\r\n\r\n    return(snr)\r\n\r\n#乱数の種を初期化\r\nnp.random.seed(0)\r\n\r\n#畳み込みに用いる音声波形\r\nclean_wave_files=[\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\"]\r\n\r\n#音源数\r\nn_sources=len(clean_wave_files)\r\n\r\n#長さを調べる\r\nn_samples=0\r\n#ファイルを読み込む\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    if n_samples<wav.getnframes():\r\n        n_samples=wav.getnframes()\r\n    wav.close()\r\n\r\nclean_data=np.zeros([n_sources,n_samples])\r\n\r\n#ファイルを読み込む\r\ns=0\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    data=wav.readframes(wav.getnframes())\r\n    data=np.frombuffer(data, dtype=np.int16)\r\n    data=data/np.iinfo(np.int16).max\r\n    clean_data[s,:wav.getnframes()]=data\r\n    wav.close()\r\n    s=s+1\r\n\r\n\r\n# シミュレーションのパラメータ\r\n\r\n#シミュレーションで用いる音源数\r\nn_sim_sources=1\r\n\r\n#サンプリング周波数\r\nsample_rate=16000\r\n\r\n#フレームサイズ\r\nN=1024\r\n\r\n#フレームシフト\r\nNshift=int(N/4)\r\n\r\n\r\n#周波数の数\r\nNk=int(N/2+1)\r\n\r\n#各ビンの周波数\r\nfreqs=np.arange(0,Nk,1)*sample_rate/N\r\n\r\n#音声と雑音との比率 [dB]\r\nSNR=90.\r\n\r\n#部屋の大きさ\r\nroom_dim = np.r_[10.0, 10.0, 10.0]\r\n\r\n#マイクロホンアレイを置く部屋の場所\r\nmic_array_loc = room_dim / 2 + np.random.randn(3) * 0.1 \r\n\r\n#マイクロホンアレイのマイク配置\r\nmic_directions=np.array(\r\n    [[np.pi/2., theta/180.*np.pi] for theta in np.arange(180,361,180)\r\n    ]    )\r\n\r\ndistance=0.01\r\nmic_alignments=np.zeros((3, mic_directions.shape[0]), dtype=mic_directions.dtype)\r\nmic_alignments[0, :] = np.cos(mic_directions[:, 1]) * np.sin(mic_directions[:, 0])\r\nmic_alignments[1, :] = np.sin(mic_directions[:, 1]) * np.sin(mic_directions[:, 0])\r\nmic_alignments[2, :] = np.cos(mic_directions[:, 0])\r\nmic_alignments *= distance\r\n\r\n#マイクロホン数\r\nn_channels=np.shape(mic_alignments)[1]\r\n\r\n#マイクロホンアレイの座標\r\nR=mic_alignments+mic_array_loc[:,None]\r\n\r\nis_use_reverb=True\r\nroom = pa.ShoeBox(room_dim, fs=sample_rate, max_order=17,absorption=0.4)\r\nroom_no_reverb = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\n\r\n# 用いるマイクロホンアレイの情報を設定する\r\nroom.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\nroom_no_reverb.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\n\r\n#音源の場所\r\ndoas=np.array(\r\n    [[np.pi/2., np.pi]\r\n    ]    )\r\n\r\n#音源とマイクロホンの距離\r\ndistance=1.\r\n\r\nsource_locations=np.zeros((3, doas.shape[0]), dtype=doas.dtype)\r\nsource_locations[0, :] = np.cos(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[1, :] = np.sin(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[2, :] = np.cos(doas[:, 0])\r\nsource_locations *= distance\r\nsource_locations += mic_array_loc[:, None]\r\n\r\n#各音源をシミュレーションに追加する\r\nfor s in range(n_sim_sources):\r\n    clean_data[s]/= np.std(clean_data[s])\r\n    room.add_source(source_locations[:, s], signal=clean_data[s])\r\n    room_no_reverb.add_source(source_locations[:, s], signal=clean_data[s])\r\n    \r\n\r\n#シミュレーションを回す\r\nroom.simulate(snr=SNR)\r\nroom_no_reverb.simulate(snr=90)\r\n\r\n#畳み込んだ波形を取得する(チャンネル、サンプル）\r\nmulti_conv_data=room.mic_array.signals\r\nmulti_conv_data_no_reverb=room_no_reverb.mic_array.signals\r\n\r\nwave_len=np.shape(multi_conv_data_no_reverb)[1]\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data_no_reverb[0,:wave_len]*np.iinfo(np.int16).max/20.,\"./dereverb_clean.wav\",sample_rate)\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data[0,:wave_len]*np.iinfo(np.int16).max/20.,\"./dereverb_in.wav\",sample_rate)\r\n\r\n#短時間フーリエ変換を行う\r\nf,t,stft_data=sp.stft(multi_conv_data,fs=sample_rate,window=\"hann\",nperseg=N,noverlap=N-Nshift)\r\n\r\n#WPEの繰り返し回数\r\nn_wpe_iterations=20\r\n\r\n#残響除去のパラメータ\r\nD=2\r\nLh=5\r\n\r\n#過去のマイクロホン入力信号\r\nx_bar=make_x_bar(stft_data,D,Lh)\r\n\r\n#LSで残響除去\r\nx_dereverb_ls=dereverberation_ls(stft_data,x_bar)\r\n\r\n#x:入力信号( M, Nk, Lt)\r\n\r\nt,x_dereverb_ls=sp.istft(x_dereverb_ls,fs=sample_rate,window=\"hann\",nperseg=N,noverlap=N-Nshift)\r\n\r\nsnr_pre=calculate_snr(multi_conv_data_no_reverb[0,...],multi_conv_data[0,...])\r\nsnr_ls_post=calculate_snr(multi_conv_data_no_reverb[0,...],x_dereverb_ls)\r\n\r\nwrite_file_from_time_signal(x_dereverb_ls[:wave_len]*np.iinfo(np.int16).max/20.,\"./dereverb_ls_{}_{}.wav\".format(Lh,D),sample_rate)\r\n\r\nprint(\"method:    \", \"LS\")\r\nprint(\"Δsnr [dB]: {:.2f}\".format(snr_ls_post-snr_pre))\r\n\r\n"
  },
  {
    "path": "section9/sample_code_c9_2.py",
    "content": "\r\n\r\nimport wave as wave\r\nimport pyroomacoustics as pa\r\nimport numpy as np\r\nimport scipy.signal as sp\r\nimport scipy as scipy\r\n\r\n#順列計算に使用\r\nimport itertools\r\n\r\n#x:入力信号( M, Nk, Lt)\r\n#D:遅延フレーム数\r\n#Lh:残響除去フィルタのタップ長\r\n#return x_bar: 過去のマイク入力信号(Lh,M,Nk,Lt)\r\ndef make_x_bar(x,D,Lh):\r\n    \r\n    #フレーム数を取得\r\n    Lt=np.shape(x)[2]\r\n\r\n    #過去のマイク入力信号の配列を準備\r\n    x_bar=np.zeros(shape=(Lh,)+np.shape(x),dtype=np.complex)\r\n\r\n    for tau in range(Lh):\r\n        x_bar[tau,...,tau+D:]=x[:,:,:-(tau+D)]\r\n\r\n    return(x_bar)\r\n\r\n#最小二乗で除去\r\n#x:入力信号( M, Nk, Lt)\r\n#x_bar:過去のマイク入力信号(Lh,M, Nk, Lt)\r\n#return x_dereverb:残響除去後の信号(Nk,Lt)\r\ndef dereverberation_ls(x,x_bar):\r\n\r\n    #マイクロホン数・周波数・フレーム数・タップ長を取得する\r\n    M=np.shape(x)[0]\r\n    Nk=np.shape(x)[1]\r\n    Lt=np.shape(x)[2]\r\n    Lh=np.shape(x_bar)[0]\r\n\r\n    x_bar=np.reshape(x_bar,[Lh*M,Nk,Lt])\r\n    x_bar_x_bar_h=np.einsum('ikt,jkt->kij',x_bar,np.conjugate(x_bar))\r\n    #covariance_inverse=np.linalg.pinv(x_bar_x_bar_h)\r\n    \r\n    correlation=np.einsum('ikt,kt->ki',x_bar,np.conjugate(x[0,...]))\r\n    \r\n    filter=np.linalg.solve(x_bar_x_bar_h,correlation)\r\n\r\n    #filter=np.einsum('kij,kj->ki',covariance_inverse,correlation)\r\n    x_reverb=np.einsum('kj,jkt->kt',np.conjugate(filter),x_bar)\r\n\r\n    x_dereverb=x[0,...]-x_reverb\r\n        \r\n    return(x_dereverb)\r\n\r\n#WPEで残響を除去\r\n#x:入力信号( M, Nk, Lt)\r\n#x_bar:過去のマイク入力信号(Lh,M, Nk, Lt)\r\n#return x_dereverb:残響除去後の信号(Nk,Lt)\r\ndef dereverberation_wpe(x,x_bar,wpe_iterations=10):\r\n\r\n    #マイクロホン数・周波数・フレーム数・タップ長を取得する\r\n    M=np.shape(x)[0]\r\n    Nk=np.shape(x)[1]\r\n    Lt=np.shape(x)[2]\r\n    Lh=np.shape(x_bar)[0]\r\n\r\n    #入力信号の形式を変更・変数を初期化\r\n    x_bar=np.reshape(x_bar,[Lh*M,Nk,Lt])\r\n    v=np.square(np.abs(x[0,...]))\r\n\r\n    cost_buff=[]\r\n    for t in range(wpe_iterations):\r\n        #共分散行列を計算\r\n        x_bar_x_bar_h=np.einsum('kt,ikt,jkt->kij',1./v,x_bar,np.conjugate(x_bar))\r\n\r\n        #相関ベクトルを計算\r\n        correlation=np.einsum('kt,ikt,kt->ki',1./v,x_bar,np.conjugate(x[0,...]))\r\n\r\n        #フィルタ算出\r\n        filter=np.linalg.solve(x_bar_x_bar_h,correlation)\r\n        \r\n        #残響除去実施\r\n        x_reverb=np.einsum('kj,jkt->kt',np.conjugate(filter),x_bar)\r\n        x_dereverb=x[0,...]-x_reverb\r\n\r\n        #パラメータ更新\r\n        v=np.square(np.abs(x_dereverb))\r\n        v=np.maximum(v,1.e-8)\r\n\r\n        #コスト計算\r\n        cost=np.mean(np.log(v))\r\n        cost_buff.append(cost)\r\n    return(x_dereverb,cost_buff)\r\n\r\n\r\n#2バイトに変換してファイルに保存\r\n#signal: time-domain 1d array (float)\r\n#file_name: 出力先のファイル名\r\n#sample_rate: サンプリングレート\r\ndef write_file_from_time_signal(signal,file_name,sample_rate):\r\n    #2バイトのデータに変換\r\n    signal=signal.astype(np.int16)\r\n\r\n    #waveファイルに書き込む\r\n    wave_out = wave.open(file_name, 'w')\r\n\r\n    #モノラル:1、ステレオ:2\r\n    wave_out.setnchannels(1)\r\n\r\n    #サンプルサイズ2byte\r\n    wave_out.setsampwidth(2)\r\n\r\n    #サンプリング周波数\r\n    wave_out.setframerate(sample_rate)\r\n\r\n    #データを書き込み\r\n    wave_out.writeframes(signal)\r\n\r\n    #ファイルを閉じる\r\n    wave_out.close()\r\n\r\n#SNRをはかる\r\n#desired: 目的音、Lt\r\n#out:　雑音除去後の信号 Lt\r\ndef calculate_snr(desired,out):\r\n    wave_length=np.minimum(np.shape(desired)[0],np.shape(out)[0])\r\n\r\n    #消し残った雑音\r\n    desired=desired[:wave_length]\r\n    out=out[:wave_length]\r\n    noise=desired-out\r\n    snr=10.*np.log10(np.sum(np.square(desired))/np.sum(np.square(noise)))\r\n\r\n    return(snr)\r\n\r\n#乱数の種を初期化\r\nnp.random.seed(0)\r\n\r\n#畳み込みに用いる音声波形\r\nclean_wave_files=[\"./CMU_ARCTIC/cmu_us_aew_arctic/wav/arctic_a0001.wav\"]\r\n\r\n#音源数\r\nn_sources=len(clean_wave_files)\r\n\r\n#長さを調べる\r\nn_samples=0\r\n#ファイルを読み込む\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    if n_samples<wav.getnframes():\r\n        n_samples=wav.getnframes()\r\n    wav.close()\r\n\r\nclean_data=np.zeros([n_sources,n_samples])\r\n\r\n#ファイルを読み込む\r\ns=0\r\nfor clean_wave_file in clean_wave_files:\r\n    wav=wave.open(clean_wave_file)\r\n    data=wav.readframes(wav.getnframes())\r\n    data=np.frombuffer(data, dtype=np.int16)\r\n    data=data/np.iinfo(np.int16).max\r\n    clean_data[s,:wav.getnframes()]=data\r\n    wav.close()\r\n    s=s+1\r\n\r\n\r\n# シミュレーションのパラメータ\r\n\r\n#シミュレーションで用いる音源数\r\nn_sim_sources=1\r\n\r\n#サンプリング周波数\r\nsample_rate=16000\r\n\r\n#フレームサイズ\r\nN=1024\r\n\r\n#フレームシフト\r\nNshift=int(N/4)\r\n\r\n\r\n#周波数の数\r\nNk=int(N/2+1)\r\n\r\n#各ビンの周波数\r\nfreqs=np.arange(0,Nk,1)*sample_rate/N\r\n\r\n#音声と雑音との比率 [dB]\r\nSNR=90.\r\n\r\n#部屋の大きさ\r\nroom_dim = np.r_[10.0, 10.0, 10.0]\r\n\r\n#マイクロホンアレイを置く部屋の場所\r\nmic_array_loc = room_dim / 2 + np.random.randn(3) * 0.1 \r\n\r\n#マイクロホンアレイのマイク配置\r\nmic_directions=np.array(\r\n    [[np.pi/2., theta/180.*np.pi] for theta in np.arange(180,361,180)\r\n    ]    )\r\n\r\ndistance=0.01\r\nmic_alignments=np.zeros((3, mic_directions.shape[0]), dtype=mic_directions.dtype)\r\nmic_alignments[0, :] = np.cos(mic_directions[:, 1]) * np.sin(mic_directions[:, 0])\r\nmic_alignments[1, :] = np.sin(mic_directions[:, 1]) * np.sin(mic_directions[:, 0])\r\nmic_alignments[2, :] = np.cos(mic_directions[:, 0])\r\nmic_alignments *= distance\r\n\r\n#マイクロホン数\r\nn_channels=np.shape(mic_alignments)[1]\r\n\r\n#マイクロホンアレイの座標\r\nR=mic_alignments+mic_array_loc[:,None]\r\n\r\nis_use_reverb=True\r\nroom = pa.ShoeBox(room_dim, fs=sample_rate, max_order=17,absorption=0.4)\r\nroom_no_reverb = pa.ShoeBox(room_dim, fs=sample_rate, max_order=0)\r\n\r\n# 用いるマイクロホンアレイの情報を設定する\r\nroom.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\nroom_no_reverb.add_microphone_array(pa.MicrophoneArray(R, fs=room.fs))\r\n\r\n#音源の場所\r\ndoas=np.array(\r\n    [[np.pi/2., np.pi]\r\n    ]    )\r\n\r\n#音源とマイクロホンの距離\r\ndistance=1.\r\n\r\nsource_locations=np.zeros((3, doas.shape[0]), dtype=doas.dtype)\r\nsource_locations[0, :] = np.cos(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[1, :] = np.sin(doas[:, 1]) * np.sin(doas[:, 0])\r\nsource_locations[2, :] = np.cos(doas[:, 0])\r\nsource_locations *= distance\r\nsource_locations += mic_array_loc[:, None]\r\n\r\n#各音源をシミュレーションに追加する\r\nfor s in range(n_sim_sources):\r\n    clean_data[s]/= np.std(clean_data[s])\r\n    room.add_source(source_locations[:, s], signal=clean_data[s])\r\n    room_no_reverb.add_source(source_locations[:, s], signal=clean_data[s])\r\n    \r\n\r\n#シミュレーションを回す\r\nroom.simulate(snr=SNR)\r\nroom_no_reverb.simulate(snr=90)\r\n\r\n#畳み込んだ波形を取得する(チャンネル、サンプル）\r\nmulti_conv_data=room.mic_array.signals\r\nmulti_conv_data_no_reverb=room_no_reverb.mic_array.signals\r\n\r\nwave_len=np.shape(multi_conv_data_no_reverb)[1]\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data_no_reverb[0,:wave_len]*np.iinfo(np.int16).max/20.,\"./dereverb_clean.wav\",sample_rate)\r\n\r\n#畳み込んだ波形をファイルに書き込む\r\nwrite_file_from_time_signal(multi_conv_data[0,:wave_len]*np.iinfo(np.int16).max/20.,\"./dereverb_in.wav\",sample_rate)\r\n\r\n#短時間フーリエ変換を行う\r\nf,t,stft_data=sp.stft(multi_conv_data,fs=sample_rate,window=\"hann\",nperseg=N,noverlap=N-Nshift)\r\n\r\n#WPEの繰り返し回数\r\nn_wpe_iterations=20\r\n\r\n#残響除去のパラメータ\r\nD=2\r\nLh=5\r\n\r\n#過去のマイクロホン入力信号\r\nx_bar=make_x_bar(stft_data,D,Lh)\r\n\r\n#LSで残響除去\r\nx_dereverb_ls=dereverberation_ls(stft_data,x_bar)\r\n\r\n#WPEで残響除去\r\nx_dereverb_wpe,cost_buff_wpe=dereverberation_wpe(stft_data,x_bar,n_wpe_iterations)\r\n\r\n#x:入力信号( M, Nk, Lt)\r\n\r\nt,x_dereverb_ls=sp.istft(x_dereverb_ls,fs=sample_rate,window=\"hann\",nperseg=N,noverlap=N-Nshift)\r\nt,x_dereverb_wpe=sp.istft(x_dereverb_wpe,fs=sample_rate,window=\"hann\",nperseg=N,noverlap=N-Nshift)\r\n\r\nsnr_pre=calculate_snr(multi_conv_data_no_reverb[0,...],multi_conv_data[0,...])\r\nsnr_ls_post=calculate_snr(multi_conv_data_no_reverb[0,...],x_dereverb_ls)\r\nsnr_wpe_post=calculate_snr(multi_conv_data_no_reverb[0,...],x_dereverb_wpe)\r\n\r\nwrite_file_from_time_signal(x_dereverb_ls[:wave_len]*np.iinfo(np.int16).max/20.,\"./dereverb_ls_{}_{}.wav\".format(Lh,D),sample_rate)\r\nwrite_file_from_time_signal(x_dereverb_wpe[:wave_len]*np.iinfo(np.int16).max/20.,\"./dereverb_wpe_{}_{}.wav\".format(Lh,D),sample_rate)\r\n\r\n\r\n\r\nprint(\"method:    \", \"LS\",\"WPE\")\r\nprint(\"Δsnr [dB]: {:.2f}  {:.2f}\".format(snr_ls_post-snr_pre,snr_wpe_post-snr_pre))\r\n\r\n#コストの値を表示\r\n#for t in range(n_wpe_iterations):\r\n#    print(t,cost_buff_wpe[t])\r\n\r\n"
  },
  {
    "path": "section9.md",
    "content": "\n## 第9章のサンプルコード\n\n* [最小二乗法による残響除去](section9/sample_code_c9_1.py)\n* [WPEによる残響除去](section9/sample_code_c9_2.py)\n"
  }
]