Author Topic: DTMF question  (Read 2523 times)

fmcoder

  • Posts: 461
DTMF question
« on: 24 Nov '10 - 17:47 »
Hello,

I'm trying to detect DTMF tones, it works with ideal samples (like ones from Wikipedia - http://en.wikipedia.org/wiki/Dtmf). But, it absolutely fails to work "in real life".

How I did it:
1) get FFT512 via BASS_ChannelGetData to array buf
2) compare all frequencies from my DTMF array with values I got from FFT representation
Code: [Select]
   Pos := Round(FFTSIZE * DTMFCodes[Idx].H / chan_freq);
    AmpH := buf[Pos];
    Pos := Round(FFTSIZE * DTMFCodes[Idx].L / chan_freq);
    AmpL := buf[Pos];
    if (AmpH >= 0.3) and (AmpL >= 0.3) then //got the code
3) all this done in a loop until stream reaches end
Problem is, when I analyze source file like one attached, it fails to detect anything :( The values from FFT array are too small...
chan_freq is 44100
FFTSIZE is 512
DTMFCodes contain frequencies for every DTMF tone.

Maybe, I missed something big?
« Last Edit: 24 Nov '10 - 17:56 by fmcoder »

fmcoder

  • Posts: 461
Re: DTMF question
« Reply #1 on: 24 Nov '10 - 17:55 »
Here is the code:
Code: [Select]
var
  C: HCHANNEL;
  buf: array of Single;
  pos, i: integer;
  amph, ampl: Single;
  ci: BASS_CHANNELINFO;
begin
  C := BASS_StreamCreateFile(false,
    pchar('N:\Programs\DTMF Detector\8bit_noise.wav'),
    0, 0, BASS_UNICODE or BASS_SAMPLE_FLOAT or BASS_STREAM_DECODE);
  BASS_ChannelGetInfo(C, ci);
  SetLength(buf, 256);
  while BASS_ChannelGetData(C, @buf[0], BASS_DATA_FFT512) <> DWORD(-1) do
  begin
    for i := 0 to High(DTMFCodes) do
    begin
      Pos := Round(512 * DTMFCodes[i].H / ci.freq);
      AmpH := buf[Pos];
      Pos := Round(512 * DTMFCodes[i].L / ci.freq);
      AmpL := buf[Pos];
      if (AmpH >= 0.4) and (AmpL >= 0.4) then //got the code
        Memo1.Lines.Add(IntToStr(i));
    end;
  end;
end;

fmcoder

  • Posts: 461
Re: DTMF question
« Reply #2 on: 28 Nov '10 - 19:05 »
Anyone? :(
I spent several days trying to make DTMF detection work, but no luck... Maybe someone did this before and could help on this one?

Ian @ un4seen

  • Administrator
  • Posts: 23890
Re: DTMF question
« Reply #3 on: 29 Nov '10 - 15:22 »
Looking for fixed levels (eg. 0.3 or 0.4) is unlikely to be reliable (it will depend on the recording level). You could instead compare the level of the target frequency with the level of the other frequencies, eg. see if it's higher than the average.

You can also increase the frequency resolution (so that the target frequencies are more isolated from others) by lowering the sample rate; 44100Hz is probably unnecessarily high for this.

fmcoder

  • Posts: 461
Re: DTMF question
« Reply #4 on: 2 Dec '10 - 13:33 »
Ian, thanks. I thought, that level is always the same, that's why I used fixed levels. Also lowered sample freq to 11050, and, it works! :)

Pedro Leonardo

  • Posts: 84
Re: DTMF question
« Reply #5 on: 19 Jul '21 - 17:59 »
Hi Ian

The variable DTMFCodes[] is an array of what type?

Regards

Ian @ un4seen

  • Administrator
  • Posts: 23890
Re: DTMF question
« Reply #6 on: 20 Jul '21 - 18:02 »
I don't know what type fmcoder used (it isn't shown in his code snippets above), but the Wikipedia page shows that the highest DTMF frequency is 1633 Hz, so you could use any type that's able to hold that. Pretty much any integer or float type except an 8-bit byte.

fmcoder

  • Posts: 461
Re: DTMF question
« Reply #7 on: 22 Jul '21 - 20:31 »
This was a long time ago so I can't find the original code. I guess it was something like this
Code: [Select]
TDTMFCode = record
  H, L: Integer;
end;

TDTMFCodes = array[0..15] of TDtmfCode;

It's populated with the DTMF frequencies for each digit, e.g.
Code: [Select]
//digit 1
DTMFCodes[0].H := 1209;
DTMFCodes[0].L := 697;

You need to check that both levels are above certain threshold (compared to the overall level of the recording) and that two frequencies are at about the same power level, if both conditions are met, then the tone is "detected".

Pedro Leonardo

  • Posts: 84
Re: DTMF question
« Reply #8 on: 27 Jul '21 - 17:33 »
Hi Fmcoder,

Thank you very much. It clarified my doubt. now it worked well.

Regards