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 utilizando 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

Empiece definiendo las variables que vamos a usar más adelante, por ejemplo, la frecuencia de muestreo, la primera frecuencia armónica de la cadena a, el desplazamiento de cada cadena relativa a 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;

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

Reproduzca una nota en una cadena abierta

Cuando una cuerda de guitarra es desplumada o rasguñada, produce una onda sonora con picos en el dominio de frecuencia que están igualmente espaciados. Estos se denominan 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);

Genere un filtro IIR cuyos polos aproximen los armónicos de la cadena A. Los ceros se agregan para el modelado de dominio de frecuencia sutil.

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

Muestra 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 en forma de armónicos.

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

Normalizar el sonido del AudioReproductor.

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

Reproduzca una nota en una cuerda Fretted

Cada traste a lo largo del cuello de una guitarra permite al jugador tocar un medio tono 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 AudioReproductor.

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 que se reproducen juntas cuyos armónicos se hacen valer 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 las primeras notas de tercer armónico se alinearían con las segundas notas segundo armónico.

Define los trastes para un acorde G mayor.

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

Mostrar la magnitud de todas las notas en el 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');

Combine las notas y normalizarlas.

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

Añade un efecto de rasgueo

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

Defina el desfase 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)