DTFM decoding using goertzel algorithm and peak-picking

15 views (last 30 days)
Sorry for what will be a lengthy question. I am working on a project that will decode an array of DTMF tones. These tones can be of variable length as can the pauses between them. I am having trouble figuring out how to analyze the output of the goertzel function to distinguish between the different key strokes.
Here is what I have so far, I am sure their is a more elegant way to do it but I am just trying to get it to work before streamlining it.
First I generate the 7 DTMF frequencies using this function:
% Sinusoid.m
% Generates a sinudoid of frequency omega_0, sampled at a frequency of
% omega_s, for a duration of dur seconds.
function [x,t] = sinusoid(omega_0,dur,omega_s)
ts= (1)/(omega_s);
n = [0:fix(dur/ts)];
t = n.*ts;
x = sin(omega_0*t);
[x1] = sinusoid(697*pit,.25,8000*pit);
[x2] = sinusoid(770*pit,.25,8000*pit);
[x3] = sinusoid(852*pit,.25,8000*pit);
[x4] = sinusoid(941*pit,.25,8000*pit);
[y1] = sinusoid(1209*pit,.25,8000*pit);
[y2] = sinusoid(1336*pit,.25,8000*pit);
[y3] = sinusoid(1477*pit,.25,8000*pit);
[pause,t] = sinusoid(0,.25,8000*pit);
Next I sum the appropriate frequency pairs:
one = x1+y1;
two = x1+y2;
three = x1+y3;
four = x2+y1;
five = x2+y2;
six = x2+y3;
seven = x3+y1;
eight = x3+y2;
nine = x3+y3;
star = x4+y1;
zero = x4+y2;
pound = x4+y3;
Finally I create the array:
array = [eight pause eight pause eight pause four pause three pause eight pause six pause four pause three pause eight pause]; %888 438 6438
Then I run it through the my decoding function which is still a work in progress:
% phone.m
% Takes an array of DTMF tones and decodes it into a phone number.
function [phoneNum] = phone(array)
digitIndex = find(array); % locates the non-zero indices
start = 1; % Initializing start and stop which will act at the limits of
stop = 1; % individual tones.
x = 1;
for k = 1:length(digitIndex)-1
if digitIndex(k) ~= digitIndex(k+1)- 1
% if the values of digitIndex are non-sequential it indicates a
% break has occured due to a pause.
stop = k; % Sets end of array equal to break point.
tone = array(start:start+127);
start = digitIndex(k+2); % updates start to begining of next digit.
TONE = goertzel(tone); % takes DFT of digit using goertzel algorithm
subplot(4,3,x)
stem(abs(TONE))
title (x)
axis([-10,210,0,100])
x = x + 1;
end
end
I can see that the numbers have unique characteristics so I know I am gathering the data. I just do not know how to do a peak picking algorithm that will result in the frequency pairs and allow for decoding.
I appreciate everyones time in helping out.

Accepted Answer

jarick cammarato
jarick cammarato on 25 Nov 2012
I figured it out. It came down to a garbage in garbage out problem. My tone generation was bad. I wound up using this code instead, it is mostly an implementation of snippets from the 'dtmfdemo' code.
symbol = {'1','2','3','4','5','6','7','8','9','*','0','#'};
lfg = [697 770 852 941]; % Low frequency group
hfg = [1209 1336 1477]; % High frequency group
f = [];
for c=1:4,
for r=1:3,
f = [ f [lfg(c);hfg(r)] ];
end
end
Fs = 8000; % Sampling frequency 8 kHz
N = 800; % Tones of 100 ms
t = (0:N-1)/Fs; % 800 samples at Fs
pit = 2*pi*t;
tones = zeros(N,size(f,2));
for button=1:12,
tones(:,button) = sum(sin(f(:,button)*pit))';
end
one = tones(:,1)';
two = tones(:,2)';
three = tones(:,3)';
four = tones(:,4)';
five = tones(:,5)';
six = tones(:,6)';
seven = tones(:,7)';
eight = tones(:,8)';
nine = tones(:,9)';
star = tones(:,10)';
zero = tones(:,11)';
pound = tones(:,12)';
pause = zeros(1,800);
array = [one pause two pause three pause four pause five pause six ...
pause seven pause eight pause nine pause star pause zero pause...
pound];
Then I defined the function Phone Decode:
% phoneDecode.m
% Recieves an array representing variable length DTMF tones alternated with
% variable length pauses and returns a string corresponding to the phone
% number provided.
% Written by Jarick Cammarato on 11/24/12.
function [phoneNum] = phoneDecode(array)
phoneNum = [];
buttonArray =['1' '2' '3'
'4' '5' '6'
'7' '8' '9'
'*' '0' '#'];
digitIndex = find(array); % locates the non-zero indices
start = 1; % Initializing start and stop which will act at the limits of
stop = 1; % individual tones.
x = 1;
original_f = [697; 770; 852; 941; 1209; 1336; 1477];
L = round(original_f/8000*205); % Indices of the DFT
estim_f = round(L*8000/205);
for k = 1:length(digitIndex)-1
if digitIndex(k) ~= digitIndex(k+1)- 1 && ...
digitIndex(k-2) ~= digitIndex(k+1)- 4 || ...
k == length(digitIndex) - 1
% if the values of digitIndex are non-sequential it indicates a
% break has occured due to a pause. If the array end is reached
% then the final digit must be captured.
stop = k; % Sets end of array equal to break point.
tone = array(start:start+204)';
start = digitIndex(k+1); % updates start to begining of next digit.
TONE = abs(goertzel(tone,L+1)); % takes DFT of digit using goertzel algorithm
vert = TONE(1:4)>50;
horz = TONE(5:7)>50;
phoneNum = cat(2,phoneNum,buttonArray(vert,horz));
subplot(4,3,x)
stem(estim_f,TONE)
title (phoneNum(:,x))
ylabel('DFT Magnitude');
xlabel('Frequency (Hz)')
x = x + 1;
end
end
set(gca, 'XTick', estim_f, 'XTickLabel', estim_f, 'XLim', [650 1550]);
ylabel('DFT Magnitude');

More Answers (0)

Products

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!