MATLAB: How can i detect frequency of dtmf tone (.wav )file

dtmf

i have a DTMF tone as a ( .wav ) file , this tone consist of a lot of numbers , and i want to detect its frequency then i want to know the numbers which the tone belong to note i have a .wav file and i want to detect it how can i do this ?

Best Answer

This code works with the attached (‘real world’) file provided by someone else who was interested in isolating the frequencies. This goes one step further and decodes the signal into its key-pad number positions:
pc = load('phonecall.mat');
x = pc.x;
fs = pc.fs;
% [S,F,T] = spectrogram(x, 1024, 512, 256*3, fs, 'yaxis');
[S,F,T] = spectrogram(x, 1024, 512*3/4, 256*3, fs, 'yaxis');
Sa = abs(S);
[r, c] = find(Sa >= 30);
Fr = F(r);
Tc = T(c)';
FT = [Tc Fr];
[C, ia, ic] = unique(FT(:,1)); % Find Unique Times
for k1 = 1:size(C,1) % Create Cell Array By Time
FrqTime{k1} = FT(FT(:,1) == C(k1),:); % Time & Frequency Cell
end
original_f = [697 770 852 941 1209 1336 1477]; % DTMF Frequencies
dtmf_dcd = [1 5; 1 6; 1 7; 2 5; 2 6; 2 7; 3 5; 3 6; 3 7; 4 5; 4 6; 4 7]; % Combination Codes w.r.t. ‘original_f’
nbr_map = ['1' '2' '3' '4' '5' '6' '7' '8' '9' '*' '0' '#']; % Number Key Map
for k1 = 1:size(C,1)
freq_dist = abs(bsxfun(@minus, FrqTime{k1}(:,2), original_f)); % Distance Of ‘FrqTime’ Frequencies From ‘original_f’ Frequencies
[~,freq_pos(:,k1)] = min(freq_dist,[],2); % Frequency Positions Of ‘FrqTime’ In ‘original_f’
num_pad(k1) = nbr_map(ismember(dtmf_dcd, freq_pos(:,k1)', 'rows')); % Map To Number Key Pad
end
I posted the sound file as a .mat file because it’s no longer possible to attach a .wav file. (It’s no longer an accepted file format.)
The first part of the code uses the spectrogram function to define the times and frequencies, then thresholds them, finds unique times, and creates a cell array of the time and frequency combinations. The second part finds the minimum distances between the ‘correct’ DTMF frequencies and the frequencies in ‘FrqTime’, then uses the ismember function to find the rows in ‘dtmf_dcd’ (‘dtmf decode’) that match ‘freq_pos’ (‘frequency position’) and uses those to map to ‘nbr_map’ elements that correspond to the row combinations in ‘dtmf_dcd’. The decoded DTMF signal is in the ‘num_pad’ string vector.
I cannot promise that it will work with your signal. You may have to experiment with the spectrogram call and the threshold (the ‘find(Sa >= 30)’ call).
There are probably File Exchange contributions that do this, and perhaps more efficiently, but I had fun writing this, so I’m posting it!