viernes, 14 de noviembre de 2014

Afinador de guitarra con matlab (guitar tuner)

 

PROYECTO  DE SOFTWARE DE SIMULACION

AFINADOR DE GUITARRA

 

Descargar programa: https://www.dropbox.com/sh/rqftcx8iu0aogjy/AABqMu7ldu2Qcw186dERTRU6a?dl=0



         RESUMEN: En el presente proyecto de investigación se intenta utilizar los conocimientos adquiridos durante el presente curso para realizar una implementación práctica, como es la afinación de una guitarra utilizando Matlab.
Comenzamos grabando el sonido producido por la guitarra y lo analizamos en el dominio de la frecuencia utilizando la Transformada de Fourier. Al obtener la frecuencia del sonido correspondiente una determinada cuerda de la guitarra podemos compararla con el valor teórico prestablecido que corresponde a dicha cuerda afinada. Al realizar esta comparación nos damos cuenta de los ajustes que deben ser realizados en la guitarra para poder afinarla.
Finalmente para una mejor experiencia con el usuario este procedimiento se implementara en una interfaz grafica (GUI).

PALABRAS CLAVE: afinador, guitarra, Matlab




1 INTRODUCCIÓN

La importancia de estar familiarizado con diferentes tipos de expresión artística como es la música nos lleva a la necesidad interpretarla con un instrumento, en nuestro caso una guitarra. Para ello es importante que la guitarra este correctamente afinada logrando así producir un sonido de calidad y adecuado. Pese a que existen métodos tradicionales para afinar una guitarra como es la técnica de oído, este método no es tan confiable ya que el ser humano tiende a cometer errores, es por esto que desarrollaremos el método de análisis digital del sonido utilizando Matlab.

2 ANALISIS DE UNA SEÑAL

2.1 SEÑAL DE AUDIO


Una señal es la variación de una magnitud física en el tiempo. Esta señal  nos indica el comportamiento del sistema físico.

En el caso de las señales de sonido es necesario captar las variaciones en la presión del aire con ayuda de un micrófono. El micrófono convierte estas variaciones en variaciones de voltaje es decir una señal eléctrica.

2.2 TASA DE MUESTREO

Es la frecuencia con la que se registranlos datos. Es el número de muestras que se toma en una unidad de tiempo

2.3 TIPOS DE SEÑALES

2.3.1 SEÑALES ANALOGICA

Esta señal es continua es decir esta definida para todo instante del tiempo debido a que la variable tiempo es una variable continua. Además su amplitud puede tomar cualquier valor. Se representa matemáticamente con una función amplitud en función del tiempo.

2.3.2 SEÑALES DIGITAL


Esta señal es discreta porque está definida solo para ciertos valores de tiempo. Su amplitud solo toma valores específicos.


2.4 ESPECTRO DE FRECUENCIAS


Es el rango que abraca las frecuencias de ondas de sonoras, luminosas y electromagnéticas midiendo su intensidad. [1]


 

2.5 ANÁLISIS ESPECTRAL

El análisis espectral [2] es un proceso para simplificar el estudio de estas señales el cual cuantifica las intensidades de cada frecuencia.

La transformada de Fourier [3] relaciona una señal función del tiempo, mostrada con una función en el dominio de la frecuencia.
                   
Las frecuencias son representadas como picos en el dominio de la frecuencia.La magnitud de estos picos es  la potencia,la magnitud de esta cantidad es elevada al cuadrado para su representación grafica que tiene como nombre espectro de potencia. [4]

                         
El espectro de potencia proporciona una descripción en el dominio de la frecuencia del momento de segundo orden del proceso.

3 GENERACIÓN DE MÚSICA

Una nota es un tono a una frecuencia perceptible determinada con cero o más armónicos de ese tono. [5] Un armónicos una sucesión de los sonidos cuyas frecuencias son múltiplos de la frecuencia fundamental que es la más baja del espectro de frecuencias. La música consiste en generar una melodía como una sucesión de tonos.

3.1 NOTAS MUSICALES

Las notas musicales son la representación de sonidos o vibraciones que tienen por una frecuencia determinada.Las notas musicales son siete: Do, Re, Mi, Fa, Sol, La, Si.

3.2 FRECUENCIA DE LAS CUERDAS

Cada cuerda de la guitarra tiene una frecuencia determinada [6], en nuestro caso debido a que utilizaremos una guitarra electroacústica las frecuencias serán parecidas a la de una guitarra eléctrica, pero pueden variar de octava ya que es una mezcla entre una guitarra acústica y una eléctrica, pero tomaremos de referencia las frecuencias de la guitarra eléctrica que son las  siguientes:

Primera cuerda   = Mi4 = 659.255  Hz
Segunda cuerda = Si3 = 483.833  Hz
Tercera cuerda   = Sol3 = 391.995 Hz
Cuarta cuerda     = Re3 = 293.655 Hz
Quinta cuerda     = La2 = 220 Hz
Sexta cuerda       = Mi 2= 164.814 Hz

En la guitarra acústica o convencional cada cuerda pertenece a una octava inferior, por ende cada frecuencia corresponderá a la mitad que las de la eléctrica.

4 FUNCIONES UTILIZADAS

4.1 AUDIORECORDER

Esta función [7] nos permite grabar el audio que luego analizaremos para afinar la guitarra, Su sintaxis es la siguiente:

recorder = audiorecorder(Fs,nBits,nChannels)

La variable recorder contendrá los datos del sonido grabado que son:

Fs = La frecuencia de muestreo
nbits = Numero de bits por muestra
nChannels = Los canales de audio.(1) mono o (2)    estéreo

4.2  WAVWRITE

Esta función [8] nos permite almacenar el sonido grabado. Su sintaxis es la siguiente:

wavwrite(y,Fs,'nota');

y = Es el sonido grabado.
Fs = La frecuencia de muestreo.
‘nota’ = El nombre con el que se almacena.

4.3 WAVREAD

Esta función [9] nos permite cargar el sonido grabado. Su sintaxis es la siguiente:

[y,fs]= wavread('nota');

y = Es el sonido grabado.
Fs = La frecuencia de muestreo.
‘nota’ = El nombre del archivo que se va a usar.

4.4 GETAUDIODATA

Esta función [10] nos permite obtener los datos asociados al archivo de audio grabado. Su sintaxis es la siguiente:

y = getaudiodata(r);

y = Contiene los datos del archivo de audio.
r = Variable que contiene el archivo de audio.

4.5 FFT

Esta función [11] retorna la transformada de Fourier discreta de un vector, calculada con la Transformada rápida de Fourier. Su sintaxis es la siguiente:

Y = fft(x)

Los elementos de Y son números complejos.

5 PROGRAMA UTILIZADO

El codigo de programa está al final en los anexos
El programa es realizado utilizando guide, con la siguiente representación:

El usuario deberá escoger la cuerda que desea afinar, por lo que incluimos un popupmenu, posterior a su selección el usuario debe presionar el botón afinar y de inmediato tendrá que tocar la cuerda que desea afinar. Entonces el programa grabará ese sonido, con una frecuencia de muestreo de 44100 [Hz], lo guardará en formato *.wav. Abrirá el archivo, dicha señal será graficada en el primer axes, esta señal estará en el dominio del tiempo.

Posterior a esto, el programa aplicará la transformada de Fourier, para obtener la señal en el dominio de la frecuencia, después elevando al cuadrado el valor absoluto de la transformada, se determinará la potencia espectral, que nos servirá de ayuda para reconocer gráficamente la frecuencia de la señal grabada, debido a que existen varias frecuencias se escogerá la correspondiente al valor más alto de la potencia espectral.
 
Dicha frecuencia se comparará con la frecuencia correspondiente a la cuerda que se desea afinar, aplicando la teoría de errores que corresponde al error relativo porcentual, además de esto se comparará graficando tanto la frecuencia   medida como la real. Nótese que la frecuencia real es la línea de color rojo y la medida es la de color verde.



6 CONCLUSIONES

En el presente trabajo se diseño e implemento una interfaz grafica para la afinación de una guitarra. La afinación de la guitarra se logro utilizando herramientas matemáticas como la transformada de Fourier la cual es necesaria para facilitar el análisis de una señal de audio. Esta herramienta matemática nos permite determinar la frecuencia con mayor potencia de la señal, la cual será la frecuencia del sonido  necesaria para afinación de la guitarra.

Los resultados obtenidos fueron los esperados ya que el programa funciona con un considérale exactitud asegurando de esta forma la  correcta afinación de la guitarra.

Las frecuencias registradas por el programa dependían de muchos factores por ejemplo la acústica de la guitarra, el ruido, el micrófono interno de la guitarra, la fuerza o forma con la que se tocaba la cuerda, por lo que estas variaban variaban de octava, pero no de nota es decir correspondían a la misma nota pero en una octava diferente.  

El programa también se podría utilizar en la afinación de otros instrumentos por ejemplo el piano, solamente se tendrían que establecer las frecuencias de cada nota que corresponde a cada tecla del piano.

Finalmente una mejora que se puede implementar al programa es crear un archivo ejecutable que pueda ser trasladado a cualquier computador sin la necesidad de Matlab.

7 REFERENCIAS


[1] [En línea]. Available: http://es.wikipedia.org/wiki/Espectro_electromagn%C3%A9tico

[2] [En línea]. Available: http://es.wikipedia.org/wiki/Espectro_de_frecuencias

[3] [En línea]. Available: http://es.wikipedia.org/wiki/Transformada_de_Fourier

[4] [En línea]. Available: http://physionet.cps.unizar.es/~eduardo/docencia/tds/librohtml/powspec.htm

[5] [En línea]. Available: http://es.wikipedia.org/wiki/Serie_arm%C3%B3nica_(m%C3%BAsica)

[6] [En línea]. Available: http://www.guitarraonline.com.ar/index.php?sec=lecciones/afinacion&titulo=Principios%20Basicos

[7] [En línea]. Available: http://www.mathworks.com/help/matlab/ref/audiorecorder.html

[8] [En línea]. Available: http://www.mathworks.com/help/matlab/ref/wavwrite.html

[9] [En línea]. Available: http://www.mathworks.com/help/matlab/ref/wavread.html

[10] [En línea]. Available: http://www.mathworks.com/help/matlab/ref/audiorecorder.getaudiodata.html

[11] [En línea]. Available:
http://www.mathworks.com/help/matlab/ref/fft.html


CODIGO DEL PROGRAMA


function varargout = afinador(varargin)
% AFINADOR MATLAB code for afinador.fig
%      AFINADOR, by itself, creates a new AFINADOR or raises the existing
%      singleton*.
%
%      H = AFINADOR returns the handle to a new AFINADOR or the handle to
%      the existing singleton*.
%
%      AFINADOR('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in AFINADOR.M with the given input arguments.
%
%      AFINADOR('Property','Value',...) creates a new AFINADOR or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before afinador_OpeningFcn gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to afinador_OpeningFcn via varargin.
%
%      *See GUI Options on GUIDE's Tools menu.  Choose "GUI allows only one
%      instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES

% Edit the above text to modify the response to help afinador

% Last Modified by GUIDE v2.5 27-Nov-2013 08:32:56

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @afinador_OpeningFcn, ...
                   'gui_OutputFcn',  @afinador_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT


% --- Executes just before afinador is made visible.
function afinador_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to afinador (see VARARGIN)

% Choose default command line output for afinador
handles.output = hObject;

% Update handles structure
guidata(hObject, handles);

% UIWAIT makes afinador wait for user response (see UIRESUME)
% uiwait(handles.figure1);


% --- Outputs from this function are returned to the command line.
function varargout = afinador_OutputFcn(hObject, eventdata, handles)
% varargout  cell array for returning output args (see VARARGOUT);
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Get default command line output from handles structure
varargout{1} = handles.output;


% --- Executes on selection change in popupmenu1.
function popupmenu1_Callback(hObject, eventdata, handles)
% hObject    handle to popupmenu1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: contents = cellstr(get(hObject,'String')) returns popupmenu1 contents as cell array
%        contents{get(hObject,'Value')} returns selected item from popupmenu1


% --- Executes during object creation, after setting all properties.
function popupmenu1_CreateFcn(hObject, eventdata, handles)
% hObject    handle to popupmenu1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: popupmenu controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end


% --- Executes on button press in pushbutton1.
function pushbutton1_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% obtenemos el valor seleccionado en el popupmenu1
opcion = get(handles.popupmenu1,'value');
%Frecuencia de muestreo
Fs = 44100;
%Variacion de t
dt=1/Fs;   
%Grabamos el archivo de sonido, usando la funcion  audiorecorder(Fs, NBITS, numero de canales)   
r = audiorecorder(Fs, 16, 1);
record(r);
%El archivbo de sonido durará 3 s.    
pause(3)
pause(r);
%Obtenemos los datos de la grabacion de audio r     
y = getaudiodata(r);
%Guardamos el archivo de sonido en formato wav.
wavwrite(y,Fs,'nota');
%Leemos el archivo .wav
[y,fs]= wavread('nota');
%Sabemos que t=n/f, entonces calculamos el tiempo.
T=length(y)/fs;
%Creamos un vector tiempo n=tiempo*fs
t=linspace(0,T,T*fs);
axes(handles.axes1)

plot(t,y)
xlabel('Tiempo')
ylabel('f(t)')
%Aplicamos la transformada de fourier para obtener la frecuencia de la
%señal
g=fft(y);
%Calculamos la potencia espectral, de la señal g, para poder obtener la
%frecuencia predominante de la señal
potencia=abs(g).^2;
%Calculamos el tamaños de cada intervalo de frecuencia
df=1/(length(y)*dt);
%Realizamos el vector frecuencia
f=(0:length(y)-1)*df;
%Obtenemos el valor y posicion maximo de la potencia espectral, siendo k la
%posicion de este elemento
[r,k]=max(potencia);
%Obtenemos el valor de frecuencia que corresponde a la posicion de la
%frecuencia maxima.
fn=f(k)
axes(handles.axes2)
%Graficamos la potencia en funcion de la frecuencia
plot(f,potencia)
axis([0 700 0 400000])
xlabel('Frecuencia')
ylabel('Potencia espectral')
j=linspace(0,5);

switch opcion
    case 1
        axes(handles.axes3)
        cla reset %Borramos los datos de axes3
        %Calculamos el error relativo
        e=(fn-659.255)*100/659.255;
        %Enviamos al valor del error al edit1
        set(handles.edit1,'string',e);
        %Sabemos que la frecuencia que corresponde a MI4 es 659.255 Hz
        %Realizamos una comparacion grafica de las frecuencias
        plot(659.255,j, 'r')
        axis([0 1200 0 5])
        hold on
        plot(fn,j, 'g')
        axis([0 1200 0 5])
    case 2
        axes(handles.axes3)
        cla reset
        e=(fn-246.94)*100/246.94;
        set(handles.edit1,'string',e);
        plot(246.94,j, 'r')
        axis([0 500 0 5])
        hold on
        plot(fn,j, 'g')
         axis([0 500 0 5])
    case 3
        axes(handles.axes3)
        cla reset
        e=(fn-392)*100/392;
        set(handles.edit1,'string',e);
        plot(392,j, 'r')
        axis([0 800 0 5])
        hold on
        plot(fn,j, 'g')
        axis([0 800 0 5])
    case 4
        axes(handles.axes3)
        cla reset
        e=(fn-293.66)*100/293.66;
        set(handles.edit1,'string',e);
        plot(293.66,j, 'r')
        axis([0 600 0 5])
        hold on
        axis([0 600 0 5])
        plot(fn,j, 'g')
    case 5
        axes(handles.axes3)
        cla reset
        e=(fn-110)*100/110;
        set(handles.edit1,'string',e);
        plot(110,j, 'r')
        axis([0 220 0 5])
        hold on
        plot(fn,j, 'g')
    case 6
        axes(handles.axes3)
        cla reset
        e=(fn-82.41)*100/82.41;
        set(handles.edit1,'string',e);
        plot(82.41,j, 'r')
        axis([0 200 0 5])
        hold on
        plot(fn,j, 'g')
        axis([0 200 0 5])
    otherwise
        disp('Su seleccion es incorrecta');
end



function edit1_Callback(hObject, eventdata, handles)
% hObject    handle to edit1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents ofdit1 as text
%        str2double(get(hObject,'String')) returns contents of edit1 as a double


% --- Executes during object creation, after setting all properties.
function edit1_CreateFcn(hObject, eventdata, handles)
% hObject    handle to edit1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end