선형 예측 분석(LPC)(= formant 분석)

안녕하세요.
선형 예측 분석(LPC) (Python으로 음성 신호 처리(2011/05/14)의 제20회째: LPC 스펙트럼 포락을 구한다)」(= formant 분석)이라는 기사를 발견했기 때문에, 거기의 코드를 거의 그대로 움직여 보자 네. 모음 「아」의 예입니다.


달린 코드는, 거기에 두고 있는 그대로입니다만, 써 둡니다( levinson_durbin.py 도 거기에서 취해 왔습니다):
  • 또한 「 Python(NumPy, SciPy)에서 포먼트 분석 수행 」라고 하는 기사에서도 이것을 이용하고 있는 것 같습니다.
  • 모음의 음성 파일 a.wav 도 어디에서인가 입수했습니다.
  • # coding:utf-8
    from __future__ import division
    import wave
    import numpy as np
    import scipy.io.wavfile
    import scipy.signal
    import pylab as P
    from levinson_durbin import autocorr, LevinsonDurbin
    
    """LPCスペクトル包絡を求める"""
    
    def wavread(filename):
        wf = wave.open(filename, "r")
        fs = wf.getframerate()
        x = wf.readframes(wf.getnframes())
        x = np.frombuffer(x, dtype="int16") / 32768.0  # (-1, 1)に正規化
        wf.close()
        return x, float(fs)
    
    def preEmphasis(signal, p):
        """プリエンファシスフィルタ"""
        # 係数 (1.0, -p) のFIRフィルタを作成
        return scipy.signal.lfilter([1.0, -p], 1, signal)
    
    def plot_signal(s, a, e, fs, lpcOrder, file):
        t = np.arange(0.0, len(s) / fs, 1/fs)
        # LPCで前向き予測した信号を求める
        predicted = np.copy(s)
        # 過去lpcOrder分から予測するので開始インデックスはlpcOrderから
        # それより前は予測せずにオリジナルの信号をコピーしている
        for i in range(lpcOrder, len(predicted)):
            predicted[i] = 0.0
            for j in range(1, lpcOrder):
                predicted[i] -= a[j] * s[i - j]
        # オリジナルの信号をプロット
        P.plot(t, s)
        # LPCで前向き予測した信号をプロット
        P.plot(t, predicted,"r",alpha=0.4)
        P.xlabel("Time (s)")
        P.xlim((-0.001, t[-1]+0.001))
        P.title(file)
        P.grid()
        P.show()
        return 0
    
    def plot_spectrum(s, a, e, fs, file):
        # LPC係数の振幅スペクトルを求める
        nfft = 2048   # FFTのサンプル数
        fscale = np.fft.fftfreq(nfft, d = 1.0 / fs)[:nfft/2]
        # オリジナル信号の対数スペクトル
        spec = np.abs(np.fft.fft(s, nfft))
        logspec = 20 * np.log10(spec)
        P.plot(fscale, logspec[:nfft/2])
        # LPC対数スペクトル
        w, h = scipy.signal.freqz(np.sqrt(e), a, nfft, "whole")
        lpcspec = np.abs(h)
        loglpcspec = 20 * np.log10(lpcspec)
        P.plot(fscale, loglpcspec[:nfft/2], "r", linewidth=2)
        P.xlabel("Frequency (Hz)")
        P.xlim((-100, 8100))
        P.title(file)
        P.grid()
        P.show()
        return 0
    
    def lpc_spectral_envelope(file):
        # 音声をロード
        wav, fs = wavread(file)
        t = np.arange(0.0, len(wav) / fs, 1/fs)
        # 音声波形の中心部分を切り出す
        center = len(wav) / 2  # 中心のサンプル番号
        cuttime = 0.04         # 切り出す長さ [s]
        s = wav[center - cuttime/2*fs : center + cuttime/2*fs]
        # プリエンファシスフィルタをかける
        p = 0.97         # プリエンファシス係数
        s = preEmphasis(s, p)
        # ハミング窓をかける
        hammingWindow = np.hamming(len(s))
        s = s * hammingWindow
        # LPC係数を求める
    #    lpcOrder = 12
        lpcOrder = 32
        r = autocorr(s, lpcOrder + 1)
        a, e  = LevinsonDurbin(r, lpcOrder)
        plot_signal(s, a, e, fs, lpcOrder, file)
        plot_spectrum(s, a, e, fs, file)
        return 0
    
    if __name__ == "__main__":
        file = "a.wav"
        lpc_spectral_envelope(file)
        exit(0)
    

    좋은 웹페이지 즐겨찾기