В этом примере показано, как сгенерировать реалистические хорды гитары с помощью Karplus-сильного Алгоритма и фильтров дискретного времени.
Начните путем определения переменных, которые мы будем использовать позже, e.g. частота дискретизации, первая гармоническая частота строка, смещение каждой строки относительно строка.
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);
Когда строку гитары щипают или играют, она производит звуковую волну с peaks в частотном диапазоне, который равномерно распределен. Они называются гармониками, и они дают каждое указание полный звук. Мы можем сгенерировать звуковые волны с этими гармониками с объектами фильтра дискретного времени.
Определите задержку обратной связи на основе первой гармонической частоты.
delay = round(Fs/A);
Сгенерируйте БИХ-фильтр, полюса которого аппроксимируют гармоники строка. Нули добавляются для тонкого формирования частотного диапазона.
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);
Нормируйте звук для audioplayer.
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);
Нормируйте звук для audioplayer.
note = note-mean(note);
note = note/max(note);
% To hear, type: hplayer = audioplayer(note, Fs); play(hplayer)
Хорда является группой примечаний, проигрываемых вместе, чьи гармоники осуществляют друг друга. Это происходит, когда существует маленькое целочисленное отношение между двумя примечаниями, e.g. отношение 2/3 означало бы, что первая гармоника трети примечаний выровняет со вторыми примечаниями вторую гармонику.
Задайте раздражения для соль-мажорной хорды.
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)