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.