このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。
Karplus-Strong アルゴリズムを使用したギター コードの生成
この例は、Karplus-Strong アルゴリズムおよび離散時間フィルターを使用して実際のギターのような音色を生成する方法を示します。
設定
最初に、サンプリング周波数、5 弦の 1 次高調波周波数、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);
開放弦の音の再生
ギターの弦を弾くと、周波数領域に等間隔のピークをもつ音波が生成されます。これらは高調波と呼ばれ、それぞれの音にすべての音が与えられます。離散時間フィルター オブジェクトを使用して、これらの高調波の音波を生成できます。
1 次高調波周波数に基づいて、フィードバック遅延を決定します。
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));
% To hear, type: hplayer = audioplayer(note, Fs); play(hplayer)
フレットを使用した弦の音の再生
ギターのネックに沿った各フレットで、プレーヤーが半音高い音を弾いたり、最初の高調波が だけ高い音を弾くことができます。
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))); 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);
% To hear, type: hplayer = audioplayer(note, Fs); play(hplayer)
コードの再生
コードは一緒に弾かれる音のグループで、その高調波が相互に強調されます。これは 2 つの音の整数比が小さい場合に発生し、たとえば、比が 2/3 の場合、最初の音の第 3 の高調波が 2 番目の音の第 2 の高調波と合うことを意味します。
G メジャー コードのフレットを定義します。
fret = [3 2 0 0 0 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 a G major chord'); xlabel('Frequency (Hz)'); ylabel('Magnitude (dB)'); legend(hline,'G','B','D','G','B','G2');
音を組み合わせて正規化します。
combinedNote = sum(note,2);
combinedNote = combinedNote/max(abs(combinedNote));
% To hear, type: hplayer = audioplayer(combinedNote, Fs); play(hplayer)
ストラム効果の追加
ストラム効果を追加するには、前に作成した各音をオフセットするだけです。
弦の間のオフセットを 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)); % To hear, type: hplayer = audioplayer(combinedNote, Fs); play(hplayer)