25 May '13 - 09:12 *
Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
 
   Home   Help Search Login Register  
Pages: [1]
  Reply  |  Print  
Author Topic: How to detect a frequency tone?  (Read 3863 times)
MB_SOFT
Posts: 246


« on: 26 Oct '05 - 23:03 »
Reply with quoteQuote

Hi,
i have to detect the precense of a frequency tone of 16500 hz during the playback of an url stream. This tone is used by a main radio station to switch other stations from network to local programs.
The main radio station play this tone on the left channel for some seconds. You can hear the tone downloading this sample:
http://www.mbsoft.biz/download/fmitalia2.wav

I suppose i have to use BASS_ChannelGetData with FFT flag but i don't know how to monitor the audio level of the frequencies around 16500 hz. Note: i don't have to display anything, i just want to detect the presence of this tone....someone have some tips or some sample source on any language?
Logged
Ian @ un4seen
Administrator
Posts: 15276


« Reply #1 on: 27 Oct '05 - 12:18 »
Reply with quoteQuote

If the stream is 44100hz, then 16500hz will be around bin 191 of a 512 sample FFT (512*16500/44100). If the tone is just on the left channel, you'll probably want to get separate FFT data for each channel.

float fft[256][2],a16500;
BASS_ChannelGetData(channel,fft,BASS_DATA_FFT512|BASS_DATA_FFT_INDIVIDUAL); // perform fft
a16500=fft[512*16500/44100][0]; // get amplitude at ~16500hz on left channel
Logged
MB_SOFT
Posts: 246


« Reply #2 on: 27 Oct '05 - 18:06 »
Reply with quoteQuote

thank you Ian, it works perfectly!!  Smiley
Logged
vital
Posts: 13


« Reply #3 on: 10 Nov '05 - 10:32 »
Reply with quoteQuote

Can you post example?
Logged
MB_SOFT
Posts: 246


« Reply #4 on: 11 Nov '05 - 02:23 »
Reply with quoteQuote

I have a timer executing this code every 100ms

Local fft(512) as Single, reed as Long, value as Long
reed = BASS_ChannelGetData(myhandle, V:fft(0), BASS_DATA_FFT512 | BASS_DATA_FFT_INDIVIDUAL)
      If reed => 0
        value = Trunc(fft(384) * 1000) ' here i get the sound level at 16500 hz on the left channel
         If value => 100
             ' if the value is 100 or greater than...the 16500 tone is detected
             ' do something
       
« Last Edit: 11 Nov '05 - 02:25 by MB_SOFT » Logged
radio42
Posts: 4012


« Reply #5 on: 11 Nov '05 - 08:27 »
Reply with quoteQuote

Just for info - to whom it might concern:
In the latest BASS .NET API 2.2.0.3 I have added some helper methods for FFT handling, which might be useful:

a) In Un4seen.Bass.Utils:
//Returns the index of a specific frequency for FFT data.
int FFTFrequency2Index(int frequency, int length, int samplerate)

b) In Un4seen.Bass.Utils:
// Returns the frequency of a specific index in FFT data.
int FFTIndex2Frequency(int index, int length, int samplerate)

c) Un4seen.Bass.Misc.Visuals:
// Gets the interpolated amplification value for a given frequency band.
float DetectFrequency(int channel, int freq1, int freq2, bool linear)

Example:
// The following line would adjust the scaling factor...
//Un4seen.Bass.Misc.Visuals.ScaleFactorSqr = 5;
//Un4seen.Bass.Misc.Visuals.ScaleFactorLinear = 10;

float amp = Un4seen.Bass.Misc.Visuals.DetectFrequency(_stream, 16495, 16505, false);
// depending on the scaling factor the amp value would be a float between 0..1..Scale:
// scaling-linear just applies the factor, scaling Sqr makes low values more visible
if (amp > 0.45)
{
    // detected...
}
Logged
Mickael
Posts: 60


« Reply #6 on: 14 Jul '06 - 22:40 »
Reply with quoteQuote


Hello, I seek in delphi7...

procedure TForm1.toneTimer(Sender: TObject);
var
fft : array [0..255] of Single; // 255 or 511 ?
reed : Integer;
value : Integer;
begin

  if BASS_ChannelIsActive(chan) = 1 then
  begin
  // Detection

  reed := BASS_ChannelGetData(chan, @fft, BASS_DATA_FFT512);

      if (reed >= 0) then
        begin
        // trunc Réel > Entier
          value := Trunc(@fft(384) * 1000); // here i get the sound level at 16500 hz
          if (value >= 100) then
            begin
            Button1.Click();
            tone.Enabled := False;
          end;
        end;

    end;

end;



error:

[Error] Unit1.pas(542): Opérateur ou point-virgule manquant
[Error] Unit1.pas(542): Opérateur non applicable à ce type d'opérande

line 542: value := Trunc(@fft(384) * 1000);

:-(


thanks..
(sorry for my english, i'm french)
Logged
Mickael
Posts: 60


« Reply #7 on: 15 Jul '06 - 13:44 »
Reply with quoteQuote

Hello !

I'm successfully modify...

My code:

procedure TForm1.toneTimer(Sender: TObject);
var
fft : array [0..511] of Single; // 255 or 511 ?
reed : Integer;
value : Integer;
begin

  if BASS_ChannelIsActive(chan) = 1 then
  begin
  // Detection

  reed := BASS_ChannelGetData(chan, @fft[0], BASS_DATA_FFT512);

      if (reed >= 0) then
        begin
        // trunc Réel > Entier
          value := Trunc(fft[384] * 1000); // here i get the sound level at 16500 hz

          Memo.Lines.Add('value:' + IntToStr(value));

          if (value >= 100) then
            begin
            Button1.Click();
            tone.Enabled := False;
          end;
        end;

    end;

end;


Response:

value:0
value:0
value:0
value:0
value:0
value:0
value:0
value:0
value:0
value:0
value:0
value:0


:-((

Please help ... Sad
Logged
Chris
Posts: 1507


« Reply #8 on: 15 Jul '06 - 14:30 »
Reply with quoteQuote

float fft[256][2],a16500;
BASS_ChannelGetData(channel,fft,BASS_DATA_FFT512|BASS_DATA_FFT_INDIVIDUAL); // perform fft
a16500=fft[512*16500/44100][0]; // get amplitude at ~16500hz on left channel

hi
here a little not tested delphi translation
var
 fft : array[0..255]of array[0..1]of single;
 a16500 : single;
begin
   BASS_ChannelGetData(channel,@fft,BASS_DATA_FFT512 or BASS_DATA_FFT_INDIVIDUAL); // perform fft
   a16500 := fft[512*16500/44100][0];//get amplitude at ~16500hz on left channel
Greets Chris
 
« Last Edit: 15 Jul '06 - 14:36 by Chris » Logged
Keyman
Posts: 167


« Reply #9 on: 16 Jul '06 - 15:11 »
Reply with quoteQuote

It's not so hard to explain:

reed := BASS_ChannelGetData(chan, @fft[0], BASS_DATA_FFT512);
This fills only the first half of your array.

Thus your declaration of var:
  fft : array [0..511] of Single;
should indeed be
  fft : array [0..255] of Single;

Also, frequency 16500 is at array element 191 and not at 384.
=> (512*16500/44100) = 191

So fft[384] should be replaced with fft[191] and you're good!
Logged
Pages: [1]
  Reply  |  Print  
 
Jump to:  

Powered by SMF 1.1.18 | SMF © 2013, Simple Machines