Lab2/PDS - TP2

Propaganda
Processamento Digital de Sinais
Engenharia Biomédica
2º Semestre 2009/2010
Análise Espectral
13 de Março de 2010
Grupo 10
Joana Nunes
Nº 58497
João Marques
Nº 58513
1. Construção da função dtmfdial()
Este trabalho experimental baseia-se na utilização do sistema telefónico de
marcação por tons designado por Dual Tone Multi-Frequency (DTMF). Neste sistema,
cada tecla do telefone produz um som que resulta do somatório de duas ondas
sinusoidais com frequências 𝑓𝑎 e 𝑓𝑏 . A correspondência entre estas frequências e o
número marcado que foi utilizada na elaboração da função é a apresentada na Tabela 1.
𝒇𝒂 (𝑯𝒛)
Tabela 1. Correspondência entre as frequências 𝒇𝒂 e 𝒇𝒃 e os números do telefone.
𝟏𝟐𝟎𝟗
1
4
7
*
𝟔𝟗𝟕
𝟕𝟕𝟎
𝟖𝟓𝟐
𝟗𝟒𝟏
𝒇𝒃 (𝑯𝒛)
𝟏𝟑𝟑𝟔
2
5
8
0
𝟏𝟒𝟒𝟕
3
6
9
#
Na realização deste trabalho a frequência de amostragem utilizada do sinal é
8000𝐻𝑧.
A função dtmfdial(), dado um número sob a forma de string, recorre à
informação contida na Tabela 1 para identificar as frequências 𝑓𝑎 e 𝑓𝑏 , após esta
identificação é calculado o sinal correspondente, através de
2𝜋𝑓𝑎 𝑛
sin (
𝑓𝑠
) + sin (
2𝜋𝑓𝑏 𝑛
𝑓𝑠
)
(1)
onde 𝑛 é o vector que indica a duração do impulso, neste caso 200𝑚𝑠.
Entre cada impulso é ainda adicionada uma pausa, que corresponde a um vector
de zeros com uma duração de 50𝑚𝑠.
Código MATLAB
function [ x ] = dtmfdial( number )
%DTMFDIAL Esta funcao serve para converter um número num tom com
duas
%frequencias.
%
O input number deve vir sob a forma de string e apenas conter
%
caracteres admissiveis. Exemplo: '218412345'
%array de frequencias que correspondem a cada numero.
%Exemplo: Ao numero 3 correspondem fa(3) e fb(3)
fa=[697 697 697 770 770 770 852 852 852 941 941 941];
fb=[1209 1336 1447 1209 1336 1447 1209 1336 1447 1209 1336 1447];
%array com todos os digitos admissiveis
1
Trabalho 2
Análise Espectral
Processamento Digital de Sinais
tabdigitos='123456789*0#';
%frequencia de amostragem
fs=8000;
%inicializacao do vector de resposta
x=[];
%vector pausa: corresponde a 50ms
pausa = zeros(1,50*10^-3*8000);
%vector sobre o qual se aplicarão os senos: duracao de 200ms
n=1:200*10^-3*8000;
for i=1:length(number)
%encontrar o digito no array correspondente
digito = findstr(number(i),tabdigitos);
%calculo da parcela a acrescentar ao vector de resposta
x=[x sin(2*pi*fa(digito)*n/fs)+sin(2*pi*fb(digito)*n/fs)
pausa];
end
%reproducao do som
soundsc(x,fs);
2. Construção da função que detecta o número através de um ficheiro de som.
A construção desta função foi também baseada nas informações contidas na
Tabela 1 sobre as frequências do sinal. É também utilizado o espectrograma do sinal,
para obter a informação sobre as frequências que o constituem. A função utilizada para
este fim foi a inverso.m.
Em primeiro lugar, é calculado o espectrograma do sinal, de onde se tira não só
os valores deste (neste caso foram usados os valores absolutos de 0 até 1), mas também
os vectores de frequência e de tempo. De seguida, o espectrograma é percorrido em
dois ciclos numa tentativa de obter os instantes de tempo em que existem picos, e as
respectivas frequências. Naturalmente tem-se o cuidado de a duração destes picos ser
pelo menos 40𝑚𝑠. Sabendo depois as frequências, utiliza-se uma função auxiliar,
detectadigito.m para fazer a correspondência entre as frequências encontradas e o
respectivo dígito, recorrendo aos valores da Tabela 1. Por fim, o número encontrado é
acrescentado à resposta e continua-se a análise.
Para testar este algoritmo, fizeram-se testes com o ficheiro de som fornecido,
através do comando inverso(wavread(‘touchtone.wav’)) e o resultado obtido foi
‘218418296’. Testou-se ainda inverso(dtmfdial(‘218411234’)) e o resultado obtido foi
exactamente ‘218411234’.
Código MATLAB
function [ numero ] = inverso( x )
[B,F,T]=spectrogram(x,300,150,[],8000); %leitura do espectrograma
B = abs(B); %calculo do valor absoluto
%Spectrogram binarization
Y = 1.0*(B > max(max(B)) * 0.9);
%mesh(T, F, Y ); %plot 3D do espectrograma
%calculo do tamanho minimo de um impulso, que equivale a 40ms
nmin=round(40*10^-3*length(T)/max(T));
%resposta que começa como string vazia
2
Trabalho 2
Análise Espectral
Processamento Digital de Sinais
numero='';
i=1;
%iteracao no vector de tempos
while i<=length(T)
j=1;
f1=0; %primeira frequencia
f2=0; %segunda frequencia
%iteracao na frequencia
while j<=length(F)
if Y(j,i) == 1 %condicao de detecçao de pico
if f1==0 %se ainda nao se tiver atribuido nenhuma
frequencia
f1=j;
j=j+10; %garantir que nao se apanha 2 vezes a mesma
frequencia
elseif f2==0 %se ainda so se tiver apanhado 1
frequencia
f2=j;
j=length(F)+1; %saida da fronteira, ja temos 2
frequencias
end
else
j=j+1;
end
end
n=0;%comprimento do impulso detectado
if (f1~=0 && f2~=0) %se houverem duas frequencias nao estamos
numa pausa, mas num pico
while ((Y(f1,i)==1 && Y(f2,i)==1)) %enquanto houver pico
n=n+1; %incremento do comprimento do impulso
i=i+1; %avanço no tempo
end
if n>=nmin %se o comprimento do impulso for maior que o
minimo
digito =
detectadigito(f1*4000/length(F),f2*4000/length(F)); %encontrar o
digito
numero = [numero digito]; %acrescentar a resposta
end
else
i=i+1;
end
end
function [ digito ] = detectadigito( f1, f2 )
%DETECTADIGITO Função que dadas duas frequências devolve o digito
%correspondente
%
Esta função faz a correspondência entre a tabela dada e as
frequências
%
encontradas. Esta correspondencia e feita por proximidade, ou
seja, se
%
as frequencias dadas nao forem um match exacto, sao localizadas
as
%
frequencias da tabela que mais se aproximam.
fa = [697 770 852 941];
fb = [1209 1336 1477];
dif = inf;
fk1=0;
3
Trabalho 2
Análise Espectral
Processamento Digital de Sinais
fk2=0;
for i=1:length(fa)
if abs(fa(i)-f1)<dif
fk1=fa(i);
dif=abs(fa(i)-f1);
end
end
dif=inf;
for j=1:length(fb)
if abs(fb(j)-f2)<dif
fk2=fb(j);
dif=abs(fb(j)-f2);
end
end
if fk1 == 697
if fk2 == 1209
digito = '1';
elseif fk2 == 1336
digito = '2';
elseif fk2 == 1477
digito = '3';
end
elseif fk1 == 770
if fk2 == 1209
digito = '4';
elseif fk2 == 1336
digito = '5';
elseif fk2 == 1477
digito = '6';
end
elseif fk1 == 852
if fk2 == 1209
digito = '7';
elseif fk2 == 1336
digito = '8';
elseif fk2 == 1477
digito = '9';
end
elseif fk1 == 941
if fk2 == 1209
digito = '*';
elseif fk2 == 1336
digito = '0';
elseif fk2 == 1477
digito = '#';
end
end
end
3. Ajuste do tamanho da janela temporal de detecção dos dígitos.
O tamanho da janela utilizado para a detecção de dígitos é de grande
importância, já que uma janela temporal demasiado curta apresenta uma boa resolução
temporal e uma má resolução no domínio da frequência, enquanto que uma janela
demasiado grande apresenta uma boa resolução na frequência, mas uma má resolução
temporal. Assim, é necessário encontrar um compromisso entre tempo e frequência que
4
Trabalho 2
Análise Espectral
Processamento Digital de Sinais
seja propício à detecção dos dígitos correctamente. Neste caso, e utilizando sempre um
overlap de metade do tamanho da janela, e para um número ‘123456789*0#’ que
engloba todos os dígitos, verificou-se que janelas com um número de amostras inferior
a 90 conduz a uma má detecção dos dígitos. Por outro lado, também se deixa de ter uma
boa detecção com janelas superiores a 1200 amostras. Analisando estes valores, e tendo
em conta que a duração dos impulsos é de 200𝑚𝑠 e a duração das pausas é de 50𝑚𝑠,
estes resultados são bastante satisfatórios, já que 90 amostras corresponde (a uma
frequência de amostragem de 8000 amostras/s) a cerca de 11𝑚𝑠, e 1200 amostras
correspondem a 150𝑚𝑠, ou seja, o triplo da duração das pausas, levando à conclusão de
que é possível obter bons resultados mesmo com uma janela demasiado grande, ou seja,
com mais de o dobro da duração das pausas.
4. Introdução de uma componente aleatória na função implementada em 1.
Com o objectivo de testar a robustez do algoritmo desenvolvido em 1.,
introduziu-se uma componente aleatória no sinal produzido. Esta alteração tem de ser
feita com algum cuidado, já que demasiado ruído torna a reconstrução inversa
impossível. Assim, introduziu-se uma componente aleatória de (no máximo) 3% da
frequência normal. Estes 3% garantem que uma dada frequência não é, na altura da
reconstrução, confundida com uma das frequências adjacentes. O código referente a esta
alteração encontra-se na função dtmfdial_random.m. O único comentário feito no
código refere-se exactamente a esta componente introduzida.
Para testar esta introdução de uma componente aleatória no sinal, testou-se com
o seguinte comando: inverso(dtmfdial_rand(‘218411234’)), obtendo como resultado
‘218411234’, tal como era esperado.
Código MATLAB
function [ x ] = dtmfdial_rand( number )
%DTMFDIAL_RAND funcao semelhante a dtmfdial_rand com componente
aleatoria
%
A componente aleatoria introduzida depende da frequencia do
tom, já que
%
é feita da forma f*(1+aleatorio()*3/100). Assim, o peso máximo
que esta
%
componente tem é de 3%. Desta forma garante-se que não há
overlap dumas
%
frequências para as outras, já que a detecção é feita por
proximidade.
fa=[697 697 697 770 770 770 852 852 852 941 941 941];
fb=[1209 1336 1447 1209 1336 1447 1209 1336 1447 1209 1336 1447];
tabdigitos='123456789*0#';
fs=8000;
x=[];
pausa = zeros(1,50*10^-3*8000);
n=1:200*10^-3*8000;
for i=1:length(number)
digito = findstr(number(i),tabdigitos);
5
Trabalho 2
Análise Espectral
Processamento Digital de Sinais
%calculo da parcela a acrescentar ao vector de resposta, com a
%respectiva componente aleatoria
x=[x
sin(2*pi*fa(digito)*(1+3*aleatorio()/100)*n/fs)+sin(2*pi*fb(digito)
*(1+3*aleatorio()/100)*n/fs) pausa];
end
soundsc(x,fs);
function [ n ] = aleatorio()
% ALEATORIO: Funcao que devolve um número aleatório entre -1 e 1
%
A função tem distribuicao de probabilidade uniforme. É obtido
através
%
da funcao rand, que devolve um numero aleatorio uniforme entre
0 e 1. O
%
sinal é escolhido recorrendo a outro numero aleatorio com
distribuicao
%
normal de valor medio 0
n=rand(); %numero entre 0 e 1
k=randn(); %numero com distribuicao normal
if k<0 %condicao de troca de sinal
n=-n;
end
end
5. Estabelecimento de uma chamada telefónica com a marcação do número feita
através do algoritmo implementado
Neste último ponto, experimentou-se marcar um número num telefone (fixo)
encostando o microfone do telefone às colunas do PC. Para que funcione, é necessário
abrir a linha do telefone (em telefones antigos isso não é necessário). Depois, correu-se
a função dtmfdial(‘927564302’) com a linha do telefone aberta, e verificou-se que de
facto a ligação é estabelecida como pretendido.
6
Download