このホワイト ペーパーでは、librosa ベースの LFCC および CQCC 特徴抽出を実装し、主に librosa での MFCC 特徴抽出のプロセスを参照し、torchaudio を使用して LFCC の正確性を検証し、matlab を使用して CQCC の正確性を検証します。
LFCC
原理
LFCCとMFCCの違いはフィルターバンクの違いで、MFCCはメル周波数のフィルターバンクを使うのに対し、LFCCは周波数が線形に分布するフィルターバンクを使うので、MFCCのフィルターバンクの取得方法を変えるだけで他のコードを保持するには、変更しないでください。
達成
librosa ライブラリに基づいて実装された LFCC は次のとおりです。
import warnings
import numpy as np
import librosa
import scipy
def linear(sr, n_fft, n_filters=128, fmin=0.0, fmax=None, dtype=np.float32):
if fmax is None:
fmax = float(sr) / 2
# Initialize the weights
n_filters = int(n_filters)
weights = np.zeros((n_filters, int(1 + n_fft // 2)), dtype=dtype)
# Center freqs of each FFT bin
fftfreqs = librosa.fft_frequencies(sr=sr, n_fft=n_fft)
# 'Center freqs' of liner bands - uniformly spaced between limits
# * Need to validate
linear_f = np.linspace(fmin, fmax, n_filters + 2)
fdiff = np.diff(linear_f)
ramps = np.subtract.outer(linear_f, fftfreqs)
for i in range(n_filters):
# lower and upper slopes for all bins
lower = -ramps[i] / fdiff[i]
upper = ramps[i + 2] / fdiff[i + 1]
# .. then intersect them with each other and zero
weights[i] = np.maximum(0, np.minimum(lower, upper))
# Only check weights if f_mel[0] is positive
if not np.all((linear_f[:-2] == 0) | (weights.max(axis=1) > 0)):
# This means we have an empty channel somewhere
warnings.warn(
"Empty filters detected in linear frequency basis. "
"Some channels will produce empty responses. "
"Try increasing your sampling rate (and fmax) or "
"reducing n_filters.",
stacklevel=2,
)
return weights
def linear_spec(
y=None,
sr=22050,
S=None,
n_fft=2048,
hop_length=512,
win_length=None,
window='hann',
center=True,
pad_mode='constant',
power=2.0,
**kwargs
):
if S is not None:
# Infer n_fft from spectrogram shape, but only if it mismatches
if n_fft // 2 + 1 != S.shape[-2]:
n_fft = 2 * (S.shape[-2] - 1)
else:
S = (
np.abs(
librosa.stft(
y,
n_fft=n_fft,
hop_length=hop_length,
win_length=win_length,
center=center,
window=window,
pad_mode=pad_mode,
)
)
** power
)
# Build a linear filter
linear_basis = linear(sr=sr, n_fft=n_fft, **kwargs)
return np.einsum("...ft,mf->...mt", S, linear_basis, optimize=True)
def expand_to(x, *, ndim, axes):
try:
axes = tuple(axes)
except TypeError:
axes = tuple([axes])
if len(axes) != x.ndim:
raise Exception(
"Shape mismatch between axes={} and input x.shape={}".format(
axes, x.shape)
)
if ndim < x.ndim:
raise Exception(
"Cannot expand x.shape={} to fewer dimensions ndim={}".format(
x.shape, ndim)
)
shape = [1] * ndim
for i, axi in enumerate(axes):
shape[axi] = x.shape[i]
return x.reshape(shape)
def lfcc(y=None,
sr=22050,
S=None,
n_lfcc=20,
dct_type=2,
norm='ortho',
lifter=0,
**kwargs):
if S is None:
S = librosa.power_to_db(linear_spec(y=y, sr=sr, **kwargs))
M = scipy.fftpack.dct(S, axis=-2, type=dct_type,
norm=norm)[..., :n_lfcc, :]
if lifter > 0:
# shape lifter for broadcasting
LI = np.sin(np.pi * np.arange(1, 1 + n_lfcc, dtype=M.dtype) / lifter)
LI = expand_to(LI, ndim=S.ndim, axes=-2)
M *= 1 + (lifter / 2) * LI
return M
elif lifter == 0:
return M
else:
raise Exception(
"LFCC lifter={} must be a non-negative number".format(lifter)
)
torchaudio の既存の関数で検証します。
import torchaudio
import librosa
from torchaudio.transforms import LFCC
path = ''
# torchaudio
waveform, sample_rate = torchaudio.load(full_path)
print(waveform.shape)
lfcc_transform = LFCC(
sample_rate=sample_rate,
n_lfcc=13,
n_filter=128,
speckwargs={
"n_fft": 512, "hop_length": 160, },
)
torch_lfcc = lfcc_transform(waveform)
print(torch_lfcc[0, :, 0])
# librosa
wave, sr = librosa.load(full_path, sr=16000)
print(wave.shape)
librosa_lfcc = lfcc(
y=wave, sr=sr, n_lfcc=13, n_fft=512, hop_length=240, n_filters=128, pad_mode='reflect')
print(librosa_lfcc[:, 0])
操作の結果は次のとおりです。2
つによって得られる結果は基本的に同じです。
CQCC
原理
STFT と CQT は、時間信号の周波数ドメイン解析のための 2 つの兄弟メソッドと見なすことができます。
STFT では、長いシーケンスから固定長のフラグメントを抽出し、ウィンドウ関数を掛けて FFT を実行し、スライディング ウィンドウを繰り返し適用して最終的なスペクトルを取得します。
STFT は実際にはフィルター バンクであり、Q ファクターはフィルター帯域幅に対するフィルターの中心周波数の比率として定義されます。Q = fk δ f Q=\frac{f_k}{\delta f}Q=f _へkなSTFT では、各フィルターの帯域幅は一定であり、周波数が低周波数から高周波数になるにつれて Q ファクターが増加します。
ただし、人間の知覚システムの Q ファクターは 500Hz ~ 20KHz の間でほぼ一定であるため、少なくとも知覚の観点からは、STFT は音声信号の時間周波数分析には理想的ではない可能性があります。
そこで CQT 変換が提案され、最初のアルゴリズムは 1978 年にヤングバーグとボルによって提案され (Youngberg-Boll)、もう 1 つのアルゴリズムは 1986 年に鹿島とモンレイノー-カシマによって提案されました (モン レイノー)。これらの方法では、次の図に示すように、オクターブが幾何学的に分散されます。
CQT計算
離散時間領域信号x ( n ) x(n)x ( n )の CQT は以下のように計算されます:
XCQ ( k , n ) = ∑ j = n − ⌊ N k / 2 ⌋ n + ⌊ N k / 2 ⌋ x ( j ) ak ∗ ( j − n + N k / 2 ) X^{CQ}(k, n)=\sum_{j=n-\left\lfloor N_k / 2\right\rfloor}^{n+\left\lfloor N_k / 2\right\rfloor} x(j) a_k^*\左(j-n+N_k / 2\右)バツCQ (k,n )=j = n − ⌊ Nk/2 ⌋∑n + ⌊ Nk/2 ⌋x ( j ) ak∗( j−n+Nk/2 )
そのうち、k = 1 , 2 , ⋯ , K k = 1,2,\cdots, Kk=1 、2 、⋯、Kは周波数インデックスak ∗ ( n ) a_k^*(n)ak∗(n) 为 a k ( n ) a_k(n) ak( n )の複素共役N k N_kNk可変ウィンドウ サイズの場合、⌊ ⋅ ⌋ \left\lfloor \cdot \right\rfloor⌊ ⋅ ⌋は切り捨てを表し、基底関数ak ( n ) a_k(n)ak( n )定义如下:
ak ( n ) = 1 C ( n N k ) exp [ i ( 2 π nfkfs + Φ k ) ] a_k(n)=\frac{1}{C}\left(\frac{ n}{N_k}\right) \exp \left[i\left(2 \pi n \frac{f_k}{f_s}+\Phi_k\right)\right]ak( n )=ハ1(Nkn)指数[私( 2 πnへsへkな+ファイk) ]
その中で、fk f_kへkkk番目ですk周波数帯域の中心周波数fs f_sへsはサンプリング レートw ( t ) w(t)w ( t )は窓関数Φ k \Phi_kファイkは位相オフセット、スケーリング係数CCCによる下式:
C = ∑ l = − ⌊ N k / 2 ⌋ ⌊ N k / 2 ⌋ w ( l + N k / 2 N k ) C=\sum_{l=-\left\lfloor N_k / 2\right\rfloor}^{\left\lfloor N_k / 2\right\rfloor} w\left(\frac{l+N_k / 2}{N_k}\right)ハ=l = − ⌊ Nk/2 ⌋∑⌊N _k/2 ⌋w(Nkl+Nk/ 2)
一定の Q 変換を満たすために、中心周波数は次を満たす必要があります。
fk = f 1 2 k − 1 B f_k=f_1 2^{\frac{k-1}{B}}へk=へ12Bk − 1
ここでf 1 f_1へ1最低周波数帯域BBの中心周波数Bオクターブあたりの周波数帯域の数を決定します。
たとえば、B = 1 B=1とします。B=1の場合、fk = f 1 2 k − 1 f_k = f_1 2^{k-1}へk=へ12k − 1,取fs = 8000 Hz , f 1 = 500 Hz f_s=8000Hz, f_1 = 500Hzへs=8000ヘルツ、へ1=500 Hz,则f 2 = 1000 Hz , f 3 = 2000 Hz , f 4 = 4000 Hz , f 5 = 8000 Hz f_2=1000Hz, f_3=2000Hz, f_4=4000Hz, f_5=8000Hzへ2=1000ヘルツ、へ3=2000Hz 、_へ4=4000ヘルツ、へ5=8000Hz 、これ以上上がれません。ただし、DFT では、これらの周波数は直線的に変化します。
Q
= fkfk + 1 − fk = ( 2 1 / B − 1 ) − 1 Q=\frac{f_k}{f_{k+1}-f_k}=\left(2^ {1 / B}-1\right)^{-1}Q=へk + 1−へkへkな=( 21/ B−1 )− 1
同時窓関数長N k N_kNk満足:
N k = fsfk Q N_k=\frac{f_s}{f_k} QNk=へkへsなQ
CQCC抽出
まず、MFCC は次のように計算されます。
sum_{m =1}^M \log [MF(m)] \cos \left[\frac{q\left(m-\frac{1}{2}\right) \pi}{M}\right]MFCC ( q )=m = 1∑Mlog [ MF ( m ) ]コス[Mq(メートル−21)p]
ここで、メルスペクトルは次のように計算されます:
MF ( m ) = ∑ k = 1 K ∣ XDFT ( k ) ∣ 2 H m ( k ) MF(m)=\sum_{k=1}^K\left|X ^{ DFT}(k)\right|^2 H_m(k)MF (メートル)=k = 1∑K
なバツD FT (k)
な2Hメートル( k )
そのうちkkkは DFT 後の周波数インデックス係数、H m ( k ) H_m(k)Hメートル( k )はmmm Mel スケールの三角加重関数バンドパス フィルターここでMMM はフィルターの数を表します (MF ( m ) MF(m)MF ( m ) =MMM点のシーケンスqqq は、離散コサイン変換ポイントの数を表します。
XCQ ( k ) X^{CQ}(k)であるため、ケプストラム分析を CQT に直接使用することはできません。バツCQ (k)の余弦関数は、この問題は、幾何空間を線形空間に変換することで解決できます。
XCQ ( k ) X^{CQ}(k)からバツCQ(k) 中, k k k 個の周波数帯域は幾何学的に分布しており、信号再構築のプロセスは最初のkkK − k Kkの後、 K 個の周波数帯域 (低周波数部分) がダウンサンプリングされます。K−k個の周波数帯域 (高周波数部分) はアップサンプリングによって取得され、kk 番目k周波数帯域の中心周波数fk f_kへkおよび最初のバンドの中心周波数f 1 = fmin f_1=f_{min}へ1=へ分の周波数差は次のように記録されます:
Δ fk ↔ 1 = fk − f 1 = f 1 ( 2 k − 1 B − 1 ) \Delta f^{k \leftrightarrow 1}=f_k-f_1=f_1\left(2^ {\ frac{k-1}{B}}-1\right)f _k ↔ 1=へk−へ1=へ1( 2Bk − 1−1 )
そのうち、k = 1 , 2 , ⋯ , K k = 1,2,\cdots, Kk=1 、2 、⋯、Kは周波数インデックス、距離Δ fk ↔ 1 \Delta f^{k \leftrightarrow 1}f _k ↔ 1はkkkの増加関数。期間T l T_l をTlkl に関して k_l を決定するのと同じです。kl次のような関数:
T l = Δ fkl ↔ 1 T_l=\Delta f^{k_l \leftrightarrow 1}Tl=f _kl↔ 1
以下は、最初のオクターブを周期T l T_lTlddを実行するDは等分され、解はkl k_lkl阿:
f 1 d = f 1 ( 2 kl − 1 B − 1 ) → kl = B log 2 ( 1 + 1 d ) \frac{f_1}{d}=f_1\left(2^{\frac{k_l -1}{B}}-1\right) \rightarrow k_l=B \log _2\left(1+\frac{1}{d}\right)dへ1な=へ1( 2Bkl− 1−1 )→kl=Bログ_2( 1+d1)
新しい周波数は次のように計算されます:
F l = 1 T l = [ f 1 ( 2 kl − 1 B − 1 ) ] − 1 F_l=\frac{1}{T_l}=\left[f_1\left(2^ { \frac{k_l-1}{B}}-1\right)\right]^{-1}ふl=Tl1=[ f1( 2Bkl− 1−1 ) ]− 1
したがって、最初のオクターブにはddd一様サンプル、 2 番目のオクターブで2d 2d2d , j − 1 j-1j−1オクターブ2 jd 2^jd2j d.
信号再構成方法は、多相アンチエイリアシング フィルターとスプライン補間方法を使用し、均一なサンプリング レートF l F_lふl信号を再サンプリングします。
最後に、CQCC 係数は次のように計算されます
。 l=1 }^L \log \left|X^{CQ}(l)\right|^2 \cos \left[\frac{p\left(l-\frac{1}{2}\right) \円周率 {L}\右]CQCC ( p )=l = 1∑Lログ_
なバツCQ (l)
な2コス[Lp( l−21)p]
その中で、p = 0 , 1 , ⋯ , L − 1 p=0,1,\cdots,L-1p=0 、1 、⋯、L−1はリサンプリング後の周波数帯域インデックスです。
私の理解では、たとえば、set d = 5 d=5d=5、周波数500~1000Hz 500~1000Hz500−1000Hz間サンプリング500,600,700,800,900 500,600,700,800,900の5分割可能500 ,600 ,700 ,800 ,900、周波数1000 ~ 2000 Hz 1000 ~ 2000 Hz1000−2000Hz間のサンプリングを2分割 d=10 2d=102日=10 の周波数帯域、つまり1000 、 1100 、 1200 、⋯ 、 1900 1000,1100,1200,\cdots,19001000 ,1100 、1200 、⋯、1900、同様に周波数範囲は2000 ~ 4000 Hz 2000 ~ 4000 Hz2000年−4000 Hzの間の周波数は2 2 * 5 = 20 2^2*5=2022∗5=20 の周波数帯域など。このように、2 つの中心周波数の間には幾何学的な間隔がありますが、サンプルの数も幾何学的に増加するため、リサンプリングによって得られる最終的な周波数は依然として線形であるため、DCT 変換を実行できます。