MATLAB: How can i do detection in DTMF ? i want to enter a tone and get the numbers of it

dtmf

i want to enter a tone and get the numbers that consist it ….

Best Answer

  • Success!
    Sort of.
    I had to kludge it a bit because there are problems getting good time separation as well as good frequency separation, but — other than producing duplicate results — this works and gives reasonable answers. You will likely want to experiment with it. It is quite likely not robust, and may only work with the file you sent. (I left the spectrogram plot in but commented it out. Un-comment it if you want to see what it does.) The ‘TL’ and ‘TH’ vectors seem to make no sense in the context of the length of the signal and the sampling frequency, since your entire signal is only about 3.63 seconds in length.
    The code:
    dtmf_tones = load('Eng Abeer dtmf.mat');
    xr = dtmf_tones.R;
    fs = dtmf_tones.fs;
    x = xr - mean(xr); % Remove d-c Component
    [S,F,T] = spectrogram(x, 1536, 64, 512, fs, 'yaxis');
    % Fm = repmat(F, 1, length(T));
    % Tm = repmat(T, length(F), 1);
    % figure(2)
    % surf(Fm, Tm, abs(S))
    % xlabel('Frequency')
    % ylabel('Time')
    % axis([0 2000 ylim zlim])
    % grid on
    Sa = abs(S);
    [r, c] = find(Sa >= 20);
    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
    if size(FrqTime{k1},1) > 2
    FrqTime{k1} = [FrqTime{k1}(1,:); mean(FrqTime{k1}(2:end,:))]; % If MoreThan 2 Rows, Second Row Is Mean Of Last 2 Rows
    end
    end
    FrqTime{1:10}
    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
    The only other way to approach this would be to create bandpass filters for each DTMF frequency, then program the logic to decode each one of those frequency pairs. The spectrogram approach has the virtue of being easier.