

[「スペクトラルノイズ除去による雑音除去」による音声再生](https://ja.stackoverflow.com/questions/83065)

上記質問のプログラムを実行すると以下のメッセージが表示され、音声は再生されるのですが、ノイズ除去が完了できません。  
対処方法を教えていただきたいです。

**エラーメッセージ**

[code]

    FutureWarning: Pass hop_length=512, win_length=2048 as keyword args. From version 0.10 passing these as positional arguments will result in an error
      return librosa.istft(y, hop_length, win_length)
    
[/code]

**ソースコード**

[code]

    import numpy as np
    from scipy.ndimage import maximum_filter1d
    
    def envelope(y, rate, threshold):
        """
        Args:
            - y: 信号データ
            - rate: サンプリング周波数
            - threshold: 雑音判断するしきい値
        Returns:
            - mask: 振幅がしきい値以上か否か
            - y_mean: Sound Envelop
        """
        y_mean = maximum_filter1d(np.abs(y), mode="constant", size=rate//20)
        mask = [mean > threshold for mean in y_mean]
        return mask, y_mean
    
    import librosa
    
    
    n_fft=2048  # STFTカラム間の音声フレーム数
    hop_length=512  # STFTカラム間の音声フレーム数
    win_length=2048  # ウィンドウサイズ
    n_std_thresh=1.5  # 信号とみなされるために、ノイズの平均値よりも大きい標準偏差（各周波数レベルでの平均値のdB）が何個あるかのしきい値
    
    def _stft(y, n_fft, hop_length, win_length):
        return librosa.stft(y=y, n_fft=n_fft, hop_length=hop_length, win_length=win_length)
    
    def _amp_to_db(x):
        return librosa.core.amplitude_to_db(x, ref=1.0, amin=1e-20, top_db=80.0)
    
    
    
    sample_rate= 32000
    
    # 音声ファイルの読み込み
    #noise_clip = open(r"C:\Users\1818067\birdvoice.wav")
    
    path=r'C:\Users\Owner\Desktop\elect\birdvoice.wav'
    sig, _ = librosa.load(path, sr=sample_rate)
    
    # ノイズデータ取得
    mask, noise_clip = envelope(sig, sample_rate, threshold=0.03)
    
    
    
    
    noise_stft = _stft(noise_clip, n_fft, hop_length, win_length)
    noise_stft_db = _amp_to_db(np.abs(noise_stft))  # dBに変換する
    
    mean_freq_noise = np.mean(noise_stft_db, axis=1)
    std_freq_noise = np.std(noise_stft_db, axis=1)
    noise_thresh = mean_freq_noise + std_freq_noise * n_std_thresh
    
    
    import scipy
    
    
    n_grad_freq = 2  # マスクで平滑化する周波数チャンネルの数
    n_grad_time = 4  # マスクを使って滑らかにする時間チャンネル数
    prop_decrease = 1.0  # ノイズをどの程度減らすか
    
    
    #data = open(r'C:\Users\1818067\birdvoice.wav')
    #audio_clip = envelope(data).envelop
    
    sample_rate= 32000
    
    # 音声ファイルの読み込み
    #noise_clip = open(r"C:\Users\1818067\birdvoice.wav")
    
    path=r'C:\Users\Owner\Desktop\elect\birdvoice.wav'
    sig, _ = librosa.load(path, sr=sample_rate)
    
    # ノイズデータ取得
    audio_clip, rate = librosa.load('birdvoice.wav')
    
    
    # 音源もSTFTで特徴量抽出する
    sig_stft = _stft(audio_clip, n_fft, hop_length, win_length)
    sig_stft_db = _amp_to_db(np.abs(sig_stft))
    
    # 時間と頻度でマスクの平滑化フィルターを作成
    smoothing_filter = np.outer(
            np.concatenate(
                [
                    np.linspace(0, 1, n_grad_freq + 1, endpoint=False),
                    np.linspace(1, 0, n_grad_freq + 2),
                ]
            )[1:-1],
            np.concatenate(
                [
                    np.linspace(0, 1, n_grad_time + 1, endpoint=False),
                    np.linspace(1, 0, n_grad_time + 2),
                ]
            )[1:-1],
        )
    smoothing_filter = smoothing_filter / np.sum(smoothing_filter)
    
    # 時間と周波数のしきい値の計算
    db_thresh = np.repeat(
            np.reshape(noise_thresh, [1, len(mean_freq_noise)]),
            np.shape(sig_stft_db)[1],
            axis=0,
        ).T
    sig_mask = sig_stft_db < db_thresh
    sig_mask = scipy.signal.fftconvolve(sig_mask, smoothing_filter, mode="same")
    sig_mask = sig_mask * prop_decrease
    
    mask_gain_dB = np.min(_amp_to_db(np.abs(sig_stft)))
    
    def _db_to_amp(x,):
        return librosa.core.db_to_amplitude(x, ref=1.0)
    
    sig_stft_db_masked = (
            sig_stft_db * (1 - sig_mask)
            + np.ones(np.shape(mask_gain_dB)) * mask_gain_dB * sig_mask
    )
    
    def _istft(y, hop_length, win_length):
        return librosa.istft(hop_length, win_length)
    
    sig_imag_masked = np.imag(sig_stft) * (1 - sig_mask)
    sig_stft_amp = (_db_to_amp(sig_stft_db_masked) * np.sign(sig_stft)) + (1j * sig_imag_masked)
    
    recovered_signal = _istft(sig_stft_amp, hop_length, win_length)
    
    import soundfile as sf
    
    sf.write('clearvoice.wav', recovered_signal, 22050, subtype='PCM_16')
    
    from playsound import playsound
    
    playsound('clearvoice.wav')
    
[/code]


CC BY-SA 4.0
2022-06-23T04:46:55.423
89540
2022-06-25T15:40:15.113
2022-06-23T06:21:55.050
3060
53170
question
python
「スペクトラルノイズ除去による雑音除去」によるノイズ除去について


結局は冗長な処理が残っていたのだと思われます。  
以下のようにすればファイルを何回も読んだり変換したりする処理は不要です。  
先頭に`########`でコメントを付けた部分が変更点です。

[code]

    ######## 音声処理関連の import は先頭にまとめて必要なもののみ残す
    import numpy as np
    import librosa
    import scipy
    
    ######## 元の音声データファイルをそのまま読み込むだけで変換処理は不要
    audio_clip, _ = librosa.load(r'C:\Users\Owner\Desktop\elect\birdvoice.wav')
    
    n_fft=2048  # STFTカラム間の音声フレーム数
    hop_length=512  # STFTカラム間の音声フレーム数
    win_length=2048  # ウィンドウサイズ
    n_std_thresh=1.5  # 信号とみなされるために、ノイズの平均値よりも大きい標準偏差（各周波数レベルでの平均値のdB）が何個あるかのしきい値
    
    def _stft(y, n_fft, hop_length, win_length):
        return librosa.stft(y=y, n_fft=n_fft, hop_length=hop_length, win_length=win_length)
    
    def _amp_to_db(x):
        return librosa.core.amplitude_to_db(x, ref=1.0, amin=1e-20, top_db=80.0)
    
    ######## 音声ファイルを変換する処理は不要なので削除して読み込む処理を先頭に移動
    
    ######## 下記行の noise_clip を audio_clip に変更
    noise_stft = _stft(audio_clip, n_fft, hop_length, win_length)
    noise_stft_db = _amp_to_db(np.abs(noise_stft))  # dBに変換する
    
    mean_freq_noise = np.mean(noise_stft_db, axis=1)
    std_freq_noise = np.std(noise_stft_db, axis=1)
    noise_thresh = mean_freq_noise + std_freq_noise * n_std_thresh
    
    n_grad_freq = 2  # マスクで平滑化する周波数チャンネルの数
    n_grad_time = 4  # マスクを使って滑らかにする時間チャンネル数
    prop_decrease = 1.0  # ノイズをどの程度減らすか
    
    ######## 音声ファイル/ノイズデータを読む処理は不要
    
    # 音源もSTFTで特徴量抽出する
    sig_stft = _stft(audio_clip, n_fft, hop_length, win_length)
    sig_stft_db = _amp_to_db(np.abs(sig_stft))
    
    # 時間と頻度でマスクの平滑化フィルターを作成
    smoothing_filter = np.outer(
            np.concatenate(
                [
                    np.linspace(0, 1, n_grad_freq + 1, endpoint=False),
                    np.linspace(1, 0, n_grad_freq + 2),
                ]
            )[1:-1],
            np.concatenate(
                [
                    np.linspace(0, 1, n_grad_time + 1, endpoint=False),
                    np.linspace(1, 0, n_grad_time + 2),
                ]
            )[1:-1],
        )
    smoothing_filter = smoothing_filter / np.sum(smoothing_filter)
    
    # 時間と周波数のしきい値の計算
    db_thresh = np.repeat(
            np.reshape(noise_thresh, [1, len(mean_freq_noise)]),
            np.shape(sig_stft_db)[1],
            axis=0,
        ).T
    sig_mask = sig_stft_db < db_thresh
    sig_mask = scipy.signal.fftconvolve(sig_mask, smoothing_filter, mode="same")
    sig_mask = sig_mask * prop_decrease
    
    mask_gain_dB = np.min(_amp_to_db(np.abs(sig_stft)))
    
    def _db_to_amp(x,):
        return librosa.core.db_to_amplitude(x, ref=1.0)
    
    sig_stft_db_masked = (
            sig_stft_db * (1 - sig_mask)
            + np.ones(np.shape(mask_gain_dB)) * mask_gain_dB * sig_mask
    )
    
    def _istft(y, hop_length, win_length):
        return librosa.istft(y, hop_length, win_length) ######## 質問時の転記ミス y, が不足していた
    
    sig_imag_masked = np.imag(sig_stft) * (1 - sig_mask)
    sig_stft_amp = (_db_to_amp(sig_stft_db_masked) * np.sign(sig_stft)) + (1j * sig_imag_masked)
    
    recovered_signal = _istft(sig_stft_amp, hop_length, win_length)
    
    import soundfile as sf
    
    sf.write('clearvoice.wav', recovered_signal, 22050, subtype='PCM_16')
    
    from playsound import playsound
    
    playsound('clearvoice.wav')
    
[/code]

それから、`FutureWarning:...`と表示された部分は警告であってエラーでは無いでしょう。  
もしかしたら何かしらの影響があるのかもしれませんが、今のところ問題は無いようです。

* * *

**追記**

@metropolis さんのコメントに従って、以下のようにキーワード指定にしたら警告メッセージは出なくなりましたね。

[code]

    def _istft(y, hop_length, win_length):
        return librosa.istft(y, hop_length=hop_length, win_length=win_length)
    
[/code]


CC BY-SA 4.0
2022-06-25T02:43:40.660
89583
2022-06-25T15:40:15.113
2022-06-25T15:40:15.113
26370
26370
89540
answer