Esta página aún no se ha traducido para esta versión. Puede ver la versión más reciente de esta página en inglés.

Generación de acordes de guitarra usando el algoritmo Karplus-Strong

Este ejemplo muestra cómo generar acordes de guitarra realistas usando el algoritmo Karplus-Strong y filtros de tiempo discreto.

Configuración

Comience definiendo las variables que usaremos más adelante, por ejemplo, la frecuencia de muestreo, la primera frecuencia armónica de la cadena A, el desplazamiento de cada cadena en relación con la cadena A.

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;

Generar el vector de frecuencia que utilizaremos para el análisis.

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

Generar 4 segundos de ceros para ser utilizado para generar las notas de guitarra.

x = zeros(Fs*4, 1);

Reproducir una nota en una cadena abierta

Cuando una cuerda de guitarra es arrancada o rasgada, produce una onda sonora con picos en el dominio de frecuencia que están igualmente espaciados. Estos se llaman los armónicos y dan a cada nota un sonido completo. Podemos generar ondas sonoras con estos armónicos con objetos de filtro de tiempo discreto.

Determine el retardo de retroalimentación basado en la primera frecuencia armónica.

delay = round(Fs/A);

Generar un filtro IIR cuyos polos se aproximan a los armónicos de la cuerda A. Los ceros se agregan para el modelado sutil del dominio de frecuencia.

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

Mostrar la respuesta de magnitud del filtro.

[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)');

Para generar una nota sintética de 4 segundos primero creamos un vector de estados con números aleatorios. Luego filtramos ceros usando estos estados iniciales. Esto obliga a los estados aleatorios a salir del filtro formado en los armónicos.

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

Normalizar el sonido del reproductor de audio.

note = note-mean(note); note = note/max(abs(note));  % To hear, type: hplayer = audioplayer(note, Fs); play(hplayer)

Reproducir una nota en una cuerda de trastes

Cada traste a lo largo del cuello de una guitarra permite al jugador tocar un tono medio más alto, o una nota cuyo primer armónico es

<math display="inline">
<mrow>
<msup>
<mrow>
<mn>2</mn>
</mrow>
<mrow>
<mrow>
<mrow>
<mn>1</mn>
</mrow>
<mo>/</mo>
<mrow>
<mn>12</mn>
</mrow>
</mrow>
</mrow>
</msup>
</mrow>
</math>
Superior.

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');

Rellene los estados con números aleatorios.

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

Cree una nota de 4 segundos.

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

Normalizar el sonido del reproductor de audio.

note = note-mean(note); note = note/max(note);  % To hear, type: hplayer = audioplayer(note, Fs); play(hplayer)

Tocar un acorde

Un acorde es un grupo de notas tocadas juntas cuyos armónicos se aplican mutuamente. Esto sucede cuando hay una pequeña relación de enteros entre las dos notas, por ejemplo, una relación de 2/3 significaría que el tercer armónico de las primeras notas se alinearía con las segundas notas de segundo armónico.

Defina los trastes para un acorde mayor G.

fret = [3 2 0 0 0 3];

Obtenga los retrasos de cada nota en función de los trastes y los desplazamientos de cadena.

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

Muestra la magnitud de todas las notas del acorde.

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');

Combina las notas y normalizalas.

combinedNote = sum(note,2); combinedNote = combinedNote/max(abs(combinedNote));  % To hear, type: hplayer = audioplayer(combinedNote, Fs); play(hplayer)

Añadir un efecto de strumming

Para añadir un efecto de rasgueo simplemente desfasamos cada nota previamente creada.

Defina el desplazamiento entre cadenas como 50 milisegundos.

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

Agregue 50 milisegundos entre cada nota anteponiendo ceros.

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)