It should work…

Cuando cualquier trasto es útil

It should work… header image 2

Descodificar tonos DTMF usando Matlab

November 25th, 2009 · 10 Comments · programming

Ya vimos como crear tonos DTMF usando Matlab y han pedido en un par de comentarios [1] [2] cómo se haría a la inversa, así que aquí va ;)

He cogido el script para generar los tonos del otro post y lo he cambiado para los pitidos duren 40ms (que se resume a cambiar que use 320 muestras en lugar de 1200 para cada pitido o silencio), para que sea un poco más real. El wav que voy a usar será el siguiente: ring.wav

Empezamos, ¿qué necesitamos? Cada pitido estará compuesto por una pareja de tonos así que para saber qué número es deberemos reconocer las dos frecuencias principales que tienen los pitidos, y conocer la frecuencia viene a ser lo mismo que saber el periodo.

Hace un tiempo hice una práctica de Tratamiento Digital de la Señal en la que se hacían cosas de estas, uno de los códigos no es mío, está indicado. El resto los hicimos Rafa y yo en su día.

Aprovechándonos de la Transformada de Fourier:

function [P,f]=periodograma(x,N)
% [P f]=periodograma(x,N)
% Calcula N muestras del periodograma de las muestras en x
% N debe ser > que length(x)
%
% P: Periodograma propiamente
% f frecuencias correspondientes
 
k=0:N-1;
f=k./N;
 
L=length(x);
P=1/L*(fft(x,N)).^2;

Pero lo propio será usar un programa que use ventanas para su propósito:

function [P,f]=periodmodif(x,ventana,N)
% [P ,f]=periodmodif(x,ventana,N)
%
% Calcula N muestras del periodograma modificado de las muestras en x
% N debe ser > que length(x)
%
% P: Periodograma propiamente
% f frecuencias correspondientes
 
if N <= length(x)
   error('N debe ser > que length(x)');
else
   k=0:N-1;
   f=k./N;
 
   L=length(x);
   m=0:L-1;
 
   U=1/L*(sum(ventana(m+1).^2));
   P=1/(L*U)*abs(fft(x.*ventana,N)).^2;
end

Cargamos el fichero ring.wav

>> [x,fs,nbits]= wavread('ring.wav')
>> t=0:1/fs:1/fs*(length(x)-1);
>> plot(x)

ring

Ahora tendremos que calcular de cuanto es nuestra ventana mínima. La separación mínima entre tonos es de 320 muestras (que además en este caso es la misma entre todos los tonos) luego la frecuencia digital será 320 / fs = 320/8000 = 0.04

Y aquí un poco de teoría sobre ventanas gracias a los Apuntes de Pak:

ventanas_LTDS_pak

Pero no voy a aburriros con ella así que nos quedaremos en que vamos a usar una ventana tipo Hamming, luego necesitaremos una longitud de ventana L = 4 / resolución = 4 / 0.04 = 100 muestras

Ahora vamos a determinar los dígitos, y para ello vamos a hacer uso de la siguiente función para búscar máximos:

function p=buscapicosu(x,umbral)
%posi_picos=buscapicosu(x,umbral)
% Busca los máximos locales de un vector mayores que un cierto umbral
% umbral se expresa en % respecto al valor máximo del vector.
% Ej. buscapicos(x,60) buscaria los picos mayores o iguales al 60% del
% pico más alto
%
% posi_picos son los indices del vector de entrada correspondientes a los picos.
 
% (C) Antonio Albiol , 2003
 
%Primero descarto los valores menores que el umbral
 
umbral=max(x(:))*umbral/100;
 
x=x.*(x>umbral);
 
%Ahora buscaré los máximos
 
%Primero creo un vector con dos valores muy pequeños en los extremos
xe=[-inf;x(:);-inf];
 
%Ahora calculo la derivada
d1=diff(xe);
ld1=length(d1);
%Ahora busco valores de la derivada de signo diferente consecutivos y que sean máximos
p=find(sign(d1(2:ld1)).*sign(d1(1:(ld1-1)))<0 & sign(d1(1:ld1-1))>0);

Cada pitido y cada silencio dura 320 muestras luego calculamos periodos en esas zonas. Vamos a por el primer dígito, con ventana Hamming de 100 y usando 1024 puntos:

>> [P,f]=periodmodif(x(320:320+99),hamming(100),1024);
>> buscapicosu(abs(P),50)
 
ans =
 
   110
   190
   836
   916

En el espectro digital, de 0 a 1, veremos que las frecuencias se repiten en espejo a partir de 0.5. Luego la frecuencia 110 se corresponde con la 916, igualmente ocurre entre la de 190 y 836, son lo mismo. Así que sólo tenemos que ver a qué corresponden 110 y 190.

Nota a tener en cuenta: en las FFTs (Fast Fourier Transforms) el cálculo se hace mucho más rapido cuando N es una potencia de 2, por eso la elección de hacerlo en 1024 puntos no ha sido del todo al azar.

>> 110/1024*fs
 
ans =
 
  859.3750
 
>> 190/1024*fs
 
ans =
 
  1.4844e+003

Nos vamos a la tablita y vemos con qué 2 valores más cercanos concuerdan 859.375 y 1484.4 Hz. Claramente sería con 852 y 1477 Hz que juntos corresponden con el dígito 9.

dtmf1

Y así con cada uno de los dígitos :)

Sé que estaría mucho mejor un script que hiciera todo el proceso entero y obtuviera qué número es de la tabla pero últimamente necesito días de 30 horas así os tendréis que conformar con esto. ¿A qué número he llamado?


Fuente original en http://vierito.es/wordpress

Similar Posts:

Tags: ···

10 responses so far ↓

  • 1 papanoel // Nov 25, 2009 at 11:46 am

    A….. Telefonicaaaaaaaaaaaaaaaaaaaaaaaaa, una pasión día a díaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    (realmente no es ese, pero lo dejo para el intrépido lector ;) )

  • 2 vierito5 // Nov 25, 2009 at 2:50 pm

    Una pasión día a díaaaaaaaaaaaa
    http://www.megaupload.com/?d=JIFHKDRP

    Vamos a dar lo mejooooooooor!

  • 3 mageles // Nov 25, 2009 at 5:12 pm

    Os odio ¬¬

    Perdón por el comentario troll, pero de lo de matlab no tengo nada que aportar :$

  • 4 vierito5 // Nov 25, 2009 at 5:14 pm

    Es que cuando hacíamos la parte de filtrado digital en LTDS usabamos la canción de Telefónica como conejillo de indias siempre jeje. No te creas que mejoraba mucho el asunto porque por defecto nos daban una canción de Julio Iglesias, también muy dura.

  • 5 paola // Nov 14, 2010 at 1:20 am

    hola

  • 6 vierito5 // Nov 14, 2010 at 3:03 am

    …hola xD

  • 7 papanoel // Nov 14, 2010 at 12:28 pm

    …hola!! :D

  • 8 mageles // Nov 14, 2010 at 4:16 pm

    Hola holita!

  • 9 Saul // Oct 28, 2012 at 9:42 pm

    Hola que tal disculpa me urge saber si el numero que se digita del ring.wav es el siguiente: 96123456,… ya que lo estoy usando en mi programa y quiero verificar el numero podrias confirmarme si este es el numero :S?

  • 10 Claudia // Mar 20, 2013 at 1:04 pm

    cuelga xfavor el script!! es un proyecto q tenemos q hacer!! xfavor entero!!
    eres un crack!!

Leave a Comment