0

このリンクをたどって、プロトタイプの音声認識システムを作成しようとしています: http://www.ifp.illinois.edu/~minhdo/teaching/speaker_recognition/ . 非常に簡単なので、心配する必要はほとんどありません。しかし、私の問題はメル周波数関数にあります。ウェブサイトで提供されているコードは次のとおりです。

function m = melfb(p, n, fs)
% MELFB         Determine matrix for a mel-spaced filterbank
%
% Inputs:       p   number of filters in filterbank
%               n   length of fft
%               fs  sample rate in Hz
%
% Outputs:      x   a (sparse) matrix containing the filterbank amplitudes
%                   size(x) = [p, 1+floor(n/2)]
%
% Usage:        For example, to compute the mel-scale spectrum of a
%               colum-vector signal s, with length n and sample rate fs:
%
%               f = fft(s);
%               m = melfb(p, n, fs);
%               n2 = 1 + floor(n/2);
%               z = m * abs(f(1:n2)).^2;
%
%               z would contain p samples of the desired mel-scale spectrum
%
%               To plot filterbanks e.g.:
%
%               plot(linspace(0, (12500/2), 129), melfb(20, 256, 12500)'),
%               title('Mel-spaced filterbank'), xlabel('Frequency (Hz)');

f0 = 700 / fs;
fn2 = floor(n/2);

lr = log(1 + 0.5/f0) / (p+1);

% convert to fft bin numbers with 0 for DC term
bl = n * (f0 * (exp([0 1 p p+1] * lr) - 1));

b1 = floor(bl(1)) + 1;
b2 = ceil(bl(2));
b3 = floor(bl(3));
b4 = min(fn2, ceil(bl(4))) - 1;

pf = log(1 + (b1:b4)/n/f0) / lr;
fp = floor(pf);
pm = pf - fp;

r = [fp(b2:b4) 1+fp(1:b3)];
c = [b2:b4 1:b3] + 1;
v = 2 * [1-pm(b2:b4) pm(1:b3)];

m = sparse(r, c, v, p, 1+fn2);

しかし、それは私にエラーを与えました:

使用中のエラー * 内部マトリックスの次元は一致する必要があります。

MFFC のエラー (17 行目) z = m * abs(f(1:n2)).^2;

17 行目の直前に次の 2 行を含めると、次のようになります。

size(m)
size(abs(f(1:n2)).^2)

それは私に与えました:

ans =

    20    65


ans =

     1    65

では、2 番目の行列を転置する必要がありますか? または、これを行単位の乗算として解釈し、コードを変更する必要がありますか?

編集:これが主な機能です(私は単にMFCC()を実行します):

function result = MFFC()
[y Fs] = audioread('s1.wav');
% sound(y,Fs)

Frames = Frame_Blocking(y,128);
Windowed = Windowing(Frames);
spectrum = FFT_After_Windowing(Windowed);
%imagesc(mag2db(abs(spectrum)))

p = 20;
S = size(spectrum);
n = S(2);

f = spectrum;
m = melfb(p, n, Fs);
n2 = 1 + floor(n/2);
size(m)
size(abs(f(1:n2)).^2)
z = m * abs(f(1:n2)).^2;

result = z;

そして、ここに補助機能があります:

function f = Frame_Blocking(y,N)
% Parameters: M = 100, N = 256
% Default : M = 100; N = 256;
M = fix(N/3);

Frames = [];
first = 1; last = N;
len = length(y);
while last <= len
    Frames = [Frames; y(first:last)'];
    first = first + M;
    last  = last + M;
end;
if last < len
    first = first + M;
    Frames = [Frames; y(first : len)];
end
f = Frames;

function f = Windowing(Frames)
S = size(Frames);
N = S(2);
M = S(1);
Windowed = zeros(M,N);
nn = 1:N;
wn = 0.54 - 0.46*cos(2*pi/(N-1)*(nn-1));
for ii = 1:M
    Windowed(ii,:) = Frames(ii,:).*wn;
end;
f = Windowed;

function f = FFT_After_Windowing(Windowed)
spectrum = fft(Windowed);
f = spectrum;
4

2 に答える 2

1

結果を転置sまたは転置しますf(これは単なる慣習の問題です)。

使用している関数に問題はありませんmelfb。実行しようとしている例の信号の次元だけです (コメント行 14 ~ 17)。

%  f = fft(s);
%  m = melfb(p, n, fs);
%  n2 = 1 + floor(n/2);
%  z = m * abs(f(1:n2)).^2;

この例では、 「列ベクトル信号 s」を使用していると想定しています。変換されたフーリエのサイズf(fft入力信号の次元を考慮して実行) から、入力信号s行ベクトル信号です。

エラーを与える部分は、p x n2行列にn2 x 1列ベクトルを乗算する必要がある実際のフィルタリング操作です (つまり、各フィルターの応答は、入力信号のフーリエで点ごとに乗算されます)。あなたの入力sはであるため1 x n、あなたfは に1 x nなり、ベクトル乗算の最終的な行列zはエラーになります。

于 2016-01-04T14:49:57.307 に答える
0

gevang さんの回答のおかげで、自分の間違いを見つけることができました。コードを変更した方法は次のとおりです。

function result = MFFC()
[y Fs] = audioread('s2.wav');
% sound(y,Fs)

Frames = Frame_Blocking(y,128);
Windowed = Windowing(Frames);
%spectrum = FFT_After_Windowing(Windowed');
%imagesc(mag2db(abs(spectrum)))

p = 20;
%S = size(spectrum);
%n = S(2);

%f = spectrum;

S1 = size(Windowed);

n  = S1(2);
n2 = 1 + floor(n/2);
%z  = zeros(S1(1),n2);
z = zeros(20,S1(1));
for ii=1: S1(1)

    s = (FFT_After_Windowing(Windowed(ii,:)'));

    f = fft(s);
    m = melfb(p,n,Fs);
    % n2 = 1 + floor(n/2);
    z(:,ii) = m * abs(f(1:n2)).^2;
end;


%f = FFT_After_Windowing(Windowed');
%S = size(f);
%n = S(2);
%size(f)
%m = melfb(p, n, Fs);
%n2 = 1 + floor(n/2);
%size(m)
%size(abs(f(1:n2)).^2)
%z = m * abs(f(1:n2)).^2;

result = z;

ご覧のとおり、この関数は行方向の行列を処理すると単純に想定していましたが、実際には列ベクトル (およびおそらく列方向の行列) を処理しています。そのため、入力行列の各列を繰り返し処理し、結果を結合します。しかし、これは効率的でベクトル化されたコードではないと思います。また、ループを使用する代わりに、入力行列に対して列単位の操作を行う方法をまだ理解できません (ウィンドウ化 - ウィンドウ化ステップの後)。

于 2016-01-04T16:55:30.400 に答える