Você está na página 1de 4

function power=goert3(samples, freq)

% Função goert3(samples, freq.): Algoritmo de Goertzel


%
% Entradas: vetor com sinal amostrado (samples) e frequência desejada para
% afinação (freq.).
%
% Saída: magnitude normalizada (Power) da resposta em frequência após
% passagem pelo filtro digital.
%
persistent SAMPLEFREQUENCY; % Cria uma variável persistente e a inicializa num vetor vazio
if isempty(SAMPLEFREQUENCY) % Verifica se esse vetor está vazio, se sim, segue na condição
SAMPLEFREQUENCY=8000; %frequência de amostragem utilizada.
end

% inicialização de variáveis:
s_prev = 0;
s_prev2 = 0;
totalpower = 0;

N=length(samples); %total de amostras


normalizedfreq = freq./SAMPLEFREQUENCY; %frequência normalizada
coeff = 2*cos(2*pi*normalizedfreq); %coeficiente pre-calculado

% Iteração para primeira etapa do filtro digital:


for i=1:N
totalpower = totalpower + samples(i)*samples(i); %rev1
s = samples(i) + coeff*s_prev - s_prev2;
s_prev2 = s_prev;
s_prev = s;
end
% Cálculo da magnitude da resposta (já incluindo os cálculso da segunda
% etapa do filtro digital):
Power = s_prev2*s_prev2+s_prev*s_prev-coeff*s_prev*s_prev2;

% Normalização da magnitude da saída:


if(totalpower)
power = power/totalpower/N;
else
power = power/(1e-7)/N;
end
end

function [freqpk,fcents]=tuneloop(fsel,varargin)
% [freqpk,fcents]=tuneloop(fsel,varargin) - Função para determinar a
% frequência do sinal de entrada (freqpk) e seu desvio (fcents) em relação à frequência de
% afinação (fsel) desejada. Deve ser informado o modo de afinação desejado (varagin)
% e, caso seja um dos modos de teste, o valor do desvio percentual (deltf)
% da frequência do sinal de entrada a simular.
%
% Uso:
% Modo de teste sem gravação: [freqpk,fcents]=tuneloop(fsel,'test',deltf);
% Modo de teste com gravação: [freqpk,fcents]=tuneloop(fsel,'autorec',deltf);
% Modo de gravação (sinal ambiente): [freqpk,fcents]=tuneloop(fsel,'rec');
%
% Diferença entre os modos de uso:
% * No modo de teste sem gravação, o programa gera um vetor com os valores
% calculados para uma senoide na frequência f_in=fsel+*(1+deltf/100), ao
% invés de capturar e amostrar um sinal de áudio. Desta forma, pode-se
% validar todo o algoritmo responsável pelo processamento do sinal, sem
% estar sujeito aos possíveis erros advindos do processo de captura com o
% microfone.
%
% * No modo de teste com gravação, novamente é gerado um vetor senoidal com
% o mesmo método, mas desta vez é utilizada a função sound do Matlab para
% emitir a nota correspondente à frequência f_in através da caixa de som.
% Enquanto o áudio é emitido, é utilizada a função recordblocking do
% Matlab para capturar e amostrar este mesmo áudio através do microfone
% do computador, armazenando o sinal amostrado em um vetor. Desta forma,
% pode-se testar o processamento já incluindo a captura de um sinal de
% áudio cuja frequência pode-se escolher livremente e com uma boa
% confiança (sujeita apenas à qualidade da caixa de som usada).
%
% * No modo de gravação, o afinador opera na forma convencional,
% simplesmente gravando e amostrando um sinal de áudio através do
% microfone do computador, para então processá-lo.
%
% Processamento do sinal:
% O processamento se dá incialmente pela passagem do vetor de sinal
% amostrado por um filtro digital (Algoritmo de Goertzel) e, em seguida,
% pela avaliação do quão distante sua frequência se encontra da
% frequência desejada de afinação (fsel). O resultado é a frequência para
% a qual a saída do filtro teve maior amplitude (dentre a faixa de
% frequências analisadas), e o valor percentual do desvio desta
% frequência em relação a fsel. Um desvio fcents=-100 indica que a nota
% já está a cerca de um semi-tom abaixo da afinação, enquanto o valor de
% fcents=50 indica um desvio de um quarto de tom acima da nota desejada.
%

% clc;
% clear;
% close all;

tstart=tic; %inicia contagem de tempo de execução do programa.

TMAX=0.5; %tempo de amostragem


SAMPLEFREQ=8000; %frequência de amostragem

% Frequências das cordas do violão na afinação EADGBE:


E2=82.41;
A2=110;
D3=146.83;
G3=196;
B3=246.94;
E4=329.63;

% Determinação da frequência para afinação:


if ischar(fsel) %Verifica se o valor de entrada é um caractere e retorna 1 se positivo.
switch upper(fsel) %Torna todos os caracteres maiúsculos (upper) e compara (switch)
case 'E2'
fsel=E2; %Caso seja E2 definirá fsel com a frequência da corda mi
case 'A2'
fsel=A2;
case 'D3'
fsel=D3;
case 'G3'
fsel=G3;
case 'B3'
fsel=B3;
case 'E4'
fsel=E4;
otherwise %Se nenhum dos caracteres correspondente
disp('Parâmetro inválido.'); %Informa a frase no display
end
end

% Criação do vetor de frequências de teste:


fpoints=21; %varredura em 21 frequências em torno de fsel (frequência definida de afinação).
ftest=linspace(0.9405*fsel,1.0595*fsel,fpoints); %Corresponde a ±0,595% da nota, ou seja, ±semitom
%Cria uma amostra de fpoints(21) de um semitom abaixo a
%um semitom acima para definir desvio padrão
tunemode = varargin{1}; %Função varargin cria vetores de tamanho variado, nesse caso, a escolha do modo Commented [DFdM1]: Executando
%será o primeiro vetor dessa função. tuneloop(fsel,varargin), como exemplo, tuneloop(e2,rec),
resultmode=0;
estou indicando que varargin{1} terá o vetor ‘rec’ que será
armazenado na variável tunemode e será utilizada para
% Configuração conforme modo de afinação:
comparação e determinação do modo escolhido. Caso seja,
if (strcmpi(tunemode,'test') || strcmpi(tunemode,'autorec') || strcmpi(tunemode,'testsq'))
tuneloop(e2,test,5), estou indicando que varargin{2} será a
% Parametros de geração do sinal:
deltf = varargin{2}; %Define deltf como o argumento recebido no vetor 2 de varargin variável deltf e esta terá o valor 5, que corresponde ao
f_in=fsel*(1+deltf/100); %Cria a frequência de teste a partir da frequência de entrada desejada desvio padrão de +0,5% em relação a fsel.
t=0:1/SAMPLEFREQ:TMAX; %Cria vetor de 0 a TMAX(0.5s) em intervalos da freq. de amost. (125us) Commented [DFdM2R1]:
y=sin(2*pi*f_in*t); %Cria senóide de teste
if (strcmpi(tunemode,'testsq')) Commented [DFdM3R1]:
y=square(2*pi*f_in*t); %Gera uma onda quadrada de teste
end Commented [DFdM4]: Verifica se os caracteres são
ly=length(y); %Armazena o tamanho do vetor y na variável Ly ( 5e+6/125=4000) iguais, no caso, verifica se o valor presente em tunemode é
end igual à comparação.
if (strcmpi(tunemode,'autorec'))
sound(y,SAMPLEFREQ); %Saída para caixa de som, emite a frequência de teste (f_in=fsel*desvio)
end
if (strcmpi(tunemode,'autorec') || strcmpi(tunemode,'rec'))
f_in=fsel;
t=0:1/SAMPLEFREQ:TMAX;
if (strcmpi(tunemode,'rec') && size(varargin,2)>=2) Commented [DFdM5]: Esta função retorna o tamanho
resultmode=varargin{2}; %Armazena na variável o vetor modo de operação, no caso, rec. do argumento que está localizado no segundo vetor de
end varargin que corresponde ao modo de operação e logo em
%captura e amostragem de áudio:
seguida compara se é igual ou maior que 2. No caso de ‘rec’
r=audiorecorder(SAMPLEFREQ,8,1); %Prepara para gravar em 8000hz ,8bits e mono(1) e armazenar
= [r e c], ele retornará 3.a
%na variável r
recordblocking(r,TMAX); %Grava em r uma amostra de 0.5s
y=getaudiodata(r); %Converte dados do vetor r para double (-1 a 1)
y=y';
ly=length(y);
end

% Filtragem e avaliação do desvio da frequência:


fpwr=zeros(1,fpoints); %Cria uma matriz 1xfpoints de zero, ou seja, um vetor de 21 zeros.
for indf=1:fpoints %Cria vetor de 20 pontos
fpwr(indf)=goert3(y,ftest(indf)); %Chamada ao Algoritmo de Goertzel
end
[fpwr_max indfpk]=max(fpwr); %Calcula a maior frequencia de fpwr e o seu indice correpondente Commented [DF6]: Deve-se lembrar que o valor de fpwr
freqpk=ftest(indfpk); corresponde a maior amplitude da frequência encontrada
fcents=100*((freqpk/fsel)-1)/0.0595; %Calcula o desvio da frequencia de referencia
resultante da transformada de Fourier. Portanto, o valor
if(-50<fcents && fcents<50)
correspondente à frequência de maior amplitude é definida
inrange=1;
em freqpk que utiliza o índice da transformada para
else
encontrar a frequência no vetor ftest.
inrange=0;
end

% Saída de dados em gráfico:


if(~strcmp(resultmode,'noplot'))
plot(y);
title('vetor y');
% maxY=max(y)
figure;
plot(ftest,fpwr);
ylm=ylim;
ylim([0 ylm(2)]);
xlm=xlim;
text(xlm(1)+0.25*(xlm(2)-xlm(1)),5*ylm(2)/8,sprintf('pico: %f em %.2fHz
(f_i_n=%.2fHz)',fpwr_max,freqpk,f_in));
text(xlm(1)+0.25*(xlm(2)-xlm(1)),ylm(2)/2,sprintf('erro: %.2f%%.',100*(freqpk/f_in-1)));
if(inrange)
text(xlm(1)+0.25*(xlm(2)-xlm(1)),3*ylm(2)/8,sprintf('Medição: %.2fHz %+.1f centésimos.',fsel,fcents));
else
if(fcents<0)
text(xlm(1)+0.25*(xlm(2)-xlm(1)),3*ylm(2)/8,sprintf('Frequência muito abaixo de %.2fHz.',fsel));
else
text(xlm(1)+0.25*(xlm(2)-xlm(1)),3*ylm(2)/8,sprintf('Frequência muito acima de %.2fHz.',fsel));
end
end
end

% Refinamento caso o desvio esteja entre -50 e 50:


if(inrange)
fpwr2=zeros(1,fpoints);
ftest2=linspace(ftest(indfpk-1),ftest(indfpk+1),fpoints);
for indf=1:fpoints
fpwr2(indf)=goert3(y,ftest2(indf));
end
[fpwr2_max indfpk2]=max(fpwr2);
freqpk2=ftest2(indfpk2);
fcents2=100*((freqpk2/fsel)-1)/0.0595;
% Nova saída de dados refinados (em gráfico):
if(~strcmp(resultmode,'noplot'))
figure;
plot(ftest2,fpwr2);
ylm=ylim;
ylim([0 ylm(2)]);
xlm=xlim;
text(xlm(1)+0.25*(xlm(2)-xlm(1)),5*ylm(2)/8,sprintf('pico: %f em %.2fHz
(f_i_n=%.2fHz)',fpwr2_max,freqpk2,f_in));
text(xlm(1)+0.25*(xlm(2)-xlm(1)),ylm(2)/2,sprintf('erro: %.2f%% ->otimização: %.2f',100*(freqpk2/f_in-
1),100*(freqpk2/f_in-1)-100*(freqpk/f_in-1)));
text(xlm(1)+0.25*(xlm(2)-xlm(1)),3*ylm(2)/8,sprintf('Medição: %.2fHz %+.1f centésimos.',fsel,fcents2));
end
freqpk=freqpk2;
fcents=fcents2;
fpwr_max=fpwr2_max;
end

% Exibição do resultado:
fprintf('\n\nMedição: %.2fHz %+.1f centésimos (=%.2fHz).\n',fsel,fcents,freqpk);
% fprintf('\nPotência: %7.3f%%\n',100*fpwr_max/0.5); %em relação ao máximo esperado

%Exibição do tempo de execução do programa:


tEnd=toc(tstart);
tH=floor(tEnd/3600);
tMin=floor(rem(tEnd,3600)/60);
tSec=tEnd-tH*3600-tMin*60;
fprintf('\nTempo de execução do programa: %.0fh %.0fmin %.1fs.\n\n',tH,tMin,tSec);

end

Você também pode gostar