Block that does simple tone detection

Hi all,
I have been building a simple block that can detect energy at a
particular frequency, i.e. a tone detection block. The signal
processing seemed simple enough for me, so I directly coded it.
Essentially my tone_sink takes in float point samples of the input
signal (passed through a narrow bandpass filter), squares them and
keeps a short term and long term average (I use an EWMA with different
alpha’s). I then generate a message if the short term avg is becomes
much greater than the long term average. here is the .cc code

int
tone_sink::work (int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
float *in = (float *) input_items[0];
int count=0;
float sample_sqr;

while (count < noutput_items){

//update both averages and observe the behavior over a period of
time.

sample_sqr=in[count]*in[count];//need to square to get energy of
signal

d_short_term_avg=d_alpha_short*sample_sqr+(1.0f -
d_alpha_short)*d_short_term_avg;

d_long_term_avg=d_alpha_long*sample_sqr+(1.0f -
d_alpha_long)*d_long_term_avg;

if ( (d_short_term_avg-d_long_term_avg) > THRESHOLD){

 gr_message_sptr msg = gr_make_message(0, 0, 0, 1);//make a byte pkt

to signal tone detection
d_target_queue->insert_tail(msg); // send it
msg.reset(); // free it up

}

}

// Tell runtime system how many input items we consumed on
// each input stream.

consume_each (noutput_items);

// Tell runtime system how many output items we produced.
return noutput_items;
}

However when I connect this sink on in a flow graph, my programs stalls.

here is the python code

class tone_graph(gr.top_block):

 def __init__(self):
     gr.top_block.__init__(self)
     audio_rate = AUDIO_RATE
     self.rcvd_pktq = gr.msg_queue()

     src = gr.wavfile_source("./tone.wav", False)

     bp_coeff =

gr.firdes.band_pass(1,audio_rate,TONE_FREQ-500,TONE_FREQ+500,100)
bpf = gr.fir_filter_fff(1,bp_coeff)

     #speaker = audio.sink(audio_rate);


     sink = tone.sink(self.rcvd_pktq,0.5,0.95)
     #raw_wave = gr.wavfile_sink("raw.wav", 1, audio_rate,16)
     filt_wave = gr.wavfile_sink("filtered.wav", 1, audio_rate, 16)

     self.connect(src,bpf,filt_wave)
     #self.connect(src,raw_wave)
     #self.connect(src, speaker)
     self.connect(bpf,sink)# link the output of band pass filter

to my tone rx module

     self.watcher = _queue_watcher_thread(self.rcvd_pktq,

message_callback)

def main():

 fg = tone_graph()
 fg.start()

 try:
     print "Hit Ctrl-D to exit NOW."
     while True:
         raw_input("")
 except EOFError:
     print "\nExiting."
 #    #fg.wait()

Main python entry

Further debugging this I observed that my CPU saturated while running
the code on my sink block (I verified this using the activity monitor
on my PowerBook G4, yes quite old PPC). So now the question is, am I
doing something that intensive that a simple multiplication and EWMA
update per sample is asking too much OR is there something wrong that
I am doing ? Other seemingly as intensive functions from the GNU core
work on my system so I am little surprised with this result.

Since the tone is at 18Khz I have lowered my AUDIO_RATE upto 40K but
still now enough.

Thanks for your help

Affan.

On Fri, Feb 26, 2010 at 02:26:53PM -0800, Affan Syed wrote:

Hi all,
I have been building a simple block that can detect energy at a
particular frequency, i.e. a tone detection block. The signal
processing seemed simple enough for me, so I directly coded it.
Essentially my tone_sink takes in float point samples of the input
signal (passed through a narrow bandpass filter), squares them and
keeps a short term and long term average (I use an EWMA with
different alpha’s). I then generate a message if the short term avg
is becomes much greater than the long term average. here is the .cc
code

Assuming that you’ve subclassed gr_sync_block, you shouldn’t be
calling consume_each.

FWIW, you may want to look at the Goertzel algorithm for computing
power at a single frequency.

Eric

On Fri, Feb 26, 2010 at 14:49, Eric B. [email protected] wrote:

FWIW, you may want to look at the Goertzel algorithm for computing
power at a single frequency.

…which is conveniently implemented in gr.goertzel_fc() :slight_smile:

Johnathan