ドキュメンテーション センター

  • 評価版
  • 製品アップデート

最新のリリースでは、このページがまだ翻訳されていません。 このページの最新版は英語でご覧になれます。

Karplus-Strong アルゴリズムを使ったギター コードの生成

この例は、Karplus-Strong アルゴリズムおよび離散時間フィルターを使用して実際のギターのような音色を生成する方法を示します。

設定

最初に、サンプリング周波数、5 弦の第一調波周波数、5 弦と比較した各弦のオフセットなど、後で使用する変数を定義します。

Fs       = 44100;
A        = 110; % The A string of a guitar is normally tuned to 110 Hz
Eoffset  = -5;
Doffset  = 5;
Goffset  = 10;
Boffset  = 14;
E2offset = 19;

解析に使用する周波数ベクトルを生成します。

F = linspace(1/Fs, 1000, 2^12);

ギターの音を生成するために使用する 4 秒間のゼロを生成します。

x = zeros(Fs*4, 1);

開放弦の音の再生

When a guitar string is plucked or strummed, it produces a sound wave
with peaks in the frequency domain that are equally spaced.  These are
called the harmonics and they give each note a full sound.  We can
generate sound waves with these harmonics with discrete-time filter
objects.

第一調波周波数に基づいて、フィードバック遅延を決定します。

delay = round(Fs/A);

生成する IIR フィルターの極を、5 弦の高調波に近似させます。周波数領域の微妙な形状に合わせるためゼロを追加します。

b  = firls(42, [0 1/delay 2/delay 1], [0 0 1 1]);
a  = [1 zeros(1, delay) -0.5 -0.5];

フィルターの振幅応答を表示します。

[H,W] = freqz(b, a, F, Fs);
plot(W, 20*log10(abs(H)));
title('Harmonics of an open A string');
xlabel('Frequency (Hz)');
ylabel('Magnitude (dB)');

4 秒の合成音を生成するには、最初に乱数をもつ状態ベクトルを作成します。次に、これらの初期状態を使用してゼロをフィルター処理します。これによって、フィルターからランダムな状態が排除され、高調波が形成されます。

zi = rand(max(length(b),length(a))-1,1);
note = filter(b, a, x, zi);

オーディオ プレイヤーの音声を正規化します。

note = note-mean(note);
note = note/max(abs(note));

hplayer = audioplayer(note, Fs);
play(hplayer);

フレットを使用した弦の音の再生

Each fret along a guitar's neck allows the player to play a half tone
higher, or a note whose first harmonic is 2^(1/12) higher.
fret  = 4;
delay = round(Fs/(A*2^(fret/12)));

b  = firls(42, [0 1/delay 2/delay 1], [0 0 1 1]);
a  = [1 zeros(1, delay) -0.5 -0.5];

[H,W] = freqz(b, a, F, Fs);
hold on
plot(W, 20*log10(abs(H)), 'r');
title('Harmonics of the A string');
legend('Open A string', 'A string on the 4th fret');

状態に乱数を指定します。

zi = rand(max(length(b),length(a))-1,1);

4 秒目の音を作成します。

note = filter(b, a, x, zi);

オーディオ プレイヤーの音声を正規化します。

note = note-mean(note);
note = note/max(note);

hplayer = audioplayer(note, Fs);
play(hplayer);

コードの再生

A chord is a group of notes played together whose harmonics enforce each
other. This happens when there is a small integer ratio between the two
notes, e.g. a ratio of 2/3 would mean that the first notes third
harmonic would align with the second notes second harmonic.

C コードのフレットを定義します。

fret = [3 3 2 0 1 3];

フレットと弦のオフセットに基づいて、音ごとに遅延を取得します。

delay = [round(Fs/(A*2^((fret(1)+Eoffset)/12))), ...
    round(Fs/(A*2^(fret(2)/12))), ...
    round(Fs/(A*2^((fret(3)+Doffset)/12))), ...
    round(Fs/(A*2^((fret(4)+Goffset)/12))), ...
    round(Fs/(A*2^((fret(5)+Boffset)/12))), ...
    round(Fs/(A*2^((fret(6)+E2offset)/12)))];


b = cell(length(delay),1);
a = cell(length(delay),1);
H = zeros(length(delay),4096);
note = zeros(length(x),length(delay));
for indx = 1:length(delay)

    % Build a cell array of numerator and denominator coefficients.
    b{indx} = firls(42, [0 1/delay(indx) 2/delay(indx) 1], [0 0 1 1]).';
    a{indx} = [1 zeros(1, delay(indx)) -0.5 -0.5].';

    % Populate the states with random numbers and filter the input zeros.
    zi = rand(max(length(b{indx}),length(a{indx}))-1,1);

    note(:, indx) = filter(b{indx}, a{indx}, x, zi);

    % Make sure that each note is centered on zero.
    note(:, indx) = note(:, indx)-mean(note(:, indx));

    [H(indx,:),W] = freqz(b{indx}, a{indx}, F, Fs);
end

コード内のすべての音の大きさを表示します。

hline = plot(W, 20*log10(abs(H.')));
title('Harmonics of the C chord');
xlabel('Frequency (Hz)');
ylabel('Magnitude (dB)');
legend(hline, 'E','A','D','G','B','E2');

音を組み合わせて正規化します。

combinedNote = sum(note,2);
combinedNote = combinedNote/max(abs(combinedNote));

hplayer = audioplayer(combinedNote, Fs);
play(hplayer);

ストラム効果の追加

To add a strumming effect we simply offset each previously created note.

弦の間のオフセットを 50 ミリ秒で定義します。

offset = 50;
offset = ceil(offset*Fs/1000);

先頭にゼロを追加して各音符間に 50 ミリ秒を追加します。

for indx = 1:size(note, 2)
    note(:, indx) = [zeros(offset*(indx-1),1); ...
                note((1:end-offset*(indx-1)), indx)];
end

combinedNote = sum(note,2);
combinedNote = combinedNote/max(abs(combinedNote));

hplayer = audioplayer(combinedNote, Fs);
play(hplayer);

filterguitar.mfilterguitar.m も参照してください。

この情報は役に立ちましたか?