Problem of filtering a signal

lorraineber4

New member
Hi,
Our project consists in recognizing an alarm thanks to the Teensy.
We managed to recognize the frequencies and therefore characterize the alarm but for a better result, we want to filter the signal. We managed to filter the signal but when we perform the FFT, the teensy does not recognize the signal. Moreover, when we increase the filter order, the teensy no longer recognizes the signal.
This is our program :
GraphiqueCollé-1.png

What do you think is the problem?
Thanks !
 
I'm confused. You said FFT but your program looks like using AudioAnalyzeNoteFrequency which uses the YIN algorithm, not FFT.

Even with the full source code, for anyone to try to reproduce this problem a copy of ALARME.WAV would also be needed.
 
Hello, I am working with her on this project. The goal is to create, in the future, a device using the Teensy board that can recognize critical alarms in the operating room. According to the standard, the first note of the alarm can be between 150 and 1000Hz, which is why we are using the YIN algorithm. The recognition is done through a microphone that constantly listens and a code we have written for recognition and characterization. However, we need to filter the signal received by the microphone to isolate the frequencies we need (from 150 to 2000Hz). We are testing our program with an FFT created using the LABVIEW software, which is why it is not included in the code.

For this program, we use the function AudioAnalyzeNoteFrequency to verify that the FFT is correct. We do have a signal, but it seems that the filter is not working. When we set the order to 1, the signal is not sent, and with an order of 2 or 3, the program does not execute.

Thanks for your answer !

Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioPlaySdWav           playSdWav1;     //xy=161,219
AudioMixer4              mixer1;         //xy=383,204
AudioFilterBiquad        biquad1;        //xy=565,231
AudioOutputI2S           i2s1;           //xy=763,239
AudioAnalyzeNoteFrequency notefreq1;      //xy=798,315
AudioConnection          patchCord1(playSdWav1, 0, mixer1, 0);
AudioConnection          patchCord2(playSdWav1, 1, mixer1, 1);
AudioConnection          patchCord3(mixer1, biquad1);
AudioConnection          patchCord4(biquad1, 0, i2s1, 0);
AudioConnection          patchCord5(biquad1, notefreq1);
AudioControlSGTL5000     sgtl5000_1;     //xy=466,362
// GUItool: end automatically generated code



#define SDCARD_CS_PIN    10
#define SDCARD_MOSI_PIN  7   
#define SDCARD_SCK_PIN   14 


void setup() {
  Serial.begin(9600);
  AudioMemory(80);

  sgtl5000_1.enable();
  sgtl5000_1.volume(1);
  biquad1.setLowpass(0, 2000, 0.707);
  SPI.setMOSI(SDCARD_MOSI_PIN);
  SPI.setSCK(SDCARD_SCK_PIN);
  notefreq1.begin(.15);
  if (!(SD.begin(SDCARD_CS_PIN))) {

    while (1) {
      Serial.println("Unable to access the SD card");
      delay(500);
    }
  }
}

void playFile(const char *filename)
{
  Serial.print("Playing file: ");
  Serial.println(filename);
  playSdWav1.play(filename);
  delay(25);
}

void loop() {
playFile("ALARME.WAV"); 
  while (playSdWav1.isPlaying()) {
      if (notefreq1.available()) {
        float note = notefreq1.read();
        float prob = notefreq1.probability();
        Serial.printf("Note: %3.2f | Probability: %.2f\n", note, prob);
      }
    }
}

LINK OF ALARME.WAV
 
Hi,
You can see the program in my co-worker's post below, thank
I think that you are misinterpreting how to use the Teensy biquad filter. The teensy biquad class is not a generic IIR filter, it is a biquad. A biquad is 2nd order. There is no filter order to choose.

I'm guessing that you might have thought that the first argument of the "setLowpass()" method is supposed to be the filter order. Nope. Sorry. For simplicity, just leave that first argument as being a value of zero, as you are already showing in your example code above.

What you have written above should successfully create a 2nd order lowpass filter that starts to attenuate frequencies above 2000 Hz. I see that you're also using the default "q" value of 0.707, which means it should be critically damped (a nice thing), which should make the filter behave like a Butterworth filter (also a nice thing).

Being only a 2nd order filter, the filter does attenuate sharply above your cutoff frequency . It rolls off gently. Since you were asking about higher order filters, I'm guessing you might want a sharper filter. If so, you cannot increase the order of the biquad (a biquad is 2nd order). Instead, you can make a sharper roll-off by cascading multiple biquad filters, one into the next.

In your code, this means that you would create a second biquad (or a third!) and you would configure it using the setLowpass in a similar way. Next, you would create the AudioConnections so that you feed the output of the first biquad into the input of the second quad. Two biquads in series will be similar to a single 4th order filter; 3 biquads will be similar to 6th order, etc.

Good luck!

Chip
 
Hello, thank you for your response. I applied the technique you suggested and created a cascade of filters. However, for the FFT (done with LABVIEW), it required a LOT of filters to truly achieve a cutting filter. Here is my code, the audio design tool, and also the FFT so that you can see what I have implemented. I'm not sure if this is ideal, but it's clear that it works, so thank you!


1700492221823.png


1700492296628.png





Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioPlaySdWav           playSdWav1;     //xy=72,26
AudioMixer4              mixer1;         //xy=245,35
AudioFilterBiquad        biquad1;        //xy=366,87
AudioFilterBiquad        biquad10;       //xy=368,474
AudioFilterBiquad        biquad8;        //xy=369,395
AudioFilterBiquad        biquad3;        //xy=370,173
AudioFilterBiquad        biquad11;       //xy=369,515
AudioFilterBiquad        biquad2;        //xy=371,130
AudioFilterBiquad        biquad9;        //xy=370,434
AudioFilterBiquad        biquad14;       //xy=370.14286041259766,648.2857046127319
AudioFilterBiquad        biquad4;        //xy=372,215
AudioFilterBiquad        biquad5;        //xy=372,259
AudioFilterBiquad        biquad7;        //xy=372,346
AudioFilterBiquad        biquad13;       //xy=372,609
AudioFilterBiquad        biquad6;        //xy=374,304
AudioFilterBiquad        biquad12;       //xy=374,559
AudioFilterBiquad        biquad15;       //xy=376.14286041259766,697.2857046127319
AudioFilterBiquad        biquad16;       //xy=377.14286041259766,745.2857046127319
AudioFilterBiquad        biquad17;       //xy=379.14286041259766,791.2857046127319
AudioFilterBiquad        biquad19;       //xy=379.14286041259766,881.2857046127319
AudioFilterBiquad        biquad20;       //xy=379.14286041259766,925.2857046127319
AudioFilterBiquad        biquad18;       //xy=383.14286041259766,838.2857046127319
AudioFilterBiquad        biquad21;       //xy=608.8095397949219,81.1904706954956
AudioFilterBiquad        biquad22;       //xy=614.5238298688616,119.76189953940256
AudioFilterBiquad        biquad34;       //xy=613.5714302062988,638.3333282470703
AudioFilterBiquad        biquad23;       //xy=618.8095011029925,159.76189858572826
AudioFilterBiquad        biquad24;       //xy=618.8095278058734,199.7619071687971
AudioFilterBiquad        biquad25;       //xy=618.8095430646624,241.19047505514965
AudioFilterBiquad        biquad33;       //xy=618.8095239911761,592.619048663548
AudioFilterBiquad        biquad28;       //xy=620.2381319318499,368.33332593100414
AudioFilterBiquad        biquad35;       //xy=619.2857562473841,685.4761949266706
AudioFilterBiquad        biquad32;       //xy=620.2381128583636,542.6190057482038
AudioFilterBiquad        biquad26;       //xy=621.666728428432,284.0475917543684
AudioFilterBiquad        biquad27;       //xy=621.6666940961566,326.90475422995434
AudioFilterBiquad        biquad29;       //xy=623.095267704555,409.7618880953108
AudioFilterBiquad        biquad30;       //xy=623.0952333722796,452.61902959006176
AudioFilterBiquad        biquad31;       //xy=624.523864201137,498.3333574022566
AudioFilterBiquad        biquad37;       //xy=626.4286422729492,788.3333492279053
AudioFilterBiquad        biquad38;       //xy=626.428653717041,830.2380905151367
AudioFilterBiquad        biquad36;       //xy=627.8571848188127,739.7619092123849
AudioFilterBiquad        biquad40;       //xy=627.6190643310547,916.190486907959
AudioFilterBiquad        biquad39;       //xy=629.0476722717285,873.8095035552979
AudioAnalyzeNoteFrequency notefreq1;      //xy=863.3333168029785,910.9523067474365
AudioOutputI2S           i2s1;           //xy=864.7142753601074,837.7142148017883
AudioConnection          patchCord1(playSdWav1, 0, mixer1, 0);
AudioConnection          patchCord2(playSdWav1, 1, mixer1, 1);
AudioConnection          patchCord3(mixer1, biquad1);
AudioConnection          patchCord4(biquad1, biquad2);
AudioConnection          patchCord5(biquad10, biquad11);
AudioConnection          patchCord6(biquad8, biquad9);
AudioConnection          patchCord7(biquad3, biquad4);
AudioConnection          patchCord8(biquad11, biquad12);
AudioConnection          patchCord9(biquad2, biquad3);
AudioConnection          patchCord10(biquad9, biquad10);
AudioConnection          patchCord11(biquad14, biquad15);
AudioConnection          patchCord12(biquad4, biquad5);
AudioConnection          patchCord13(biquad5, biquad6);
AudioConnection          patchCord14(biquad7, biquad8);
AudioConnection          patchCord15(biquad13, biquad14);
AudioConnection          patchCord16(biquad6, biquad7);
AudioConnection          patchCord17(biquad12, biquad13);
AudioConnection          patchCord18(biquad15, biquad16);
AudioConnection          patchCord19(biquad16, biquad17);
AudioConnection          patchCord20(biquad17, biquad18);
AudioConnection          patchCord21(biquad19, biquad20);
AudioConnection          patchCord22(biquad20, biquad21);
AudioConnection          patchCord23(biquad18, biquad19);
AudioConnection          patchCord24(biquad21, biquad22);
AudioConnection          patchCord25(biquad22, biquad23);
AudioConnection          patchCord26(biquad34, biquad35);
AudioConnection          patchCord27(biquad23, biquad24);
AudioConnection          patchCord28(biquad24, biquad25);
AudioConnection          patchCord29(biquad25, biquad26);
AudioConnection          patchCord30(biquad33, biquad34);
AudioConnection          patchCord31(biquad28, biquad29);
AudioConnection          patchCord32(biquad35, biquad36);
AudioConnection          patchCord33(biquad32, biquad33);
AudioConnection          patchCord34(biquad26, biquad27);
AudioConnection          patchCord35(biquad27, biquad28);
AudioConnection          patchCord36(biquad29, biquad30);
AudioConnection          patchCord37(biquad30, biquad31);
AudioConnection          patchCord38(biquad31, biquad32);
AudioConnection          patchCord39(biquad37, biquad38);
AudioConnection          patchCord40(biquad38, biquad39);
AudioConnection          patchCord41(biquad36, biquad37);
AudioConnection          patchCord42(biquad40, 0, i2s1, 0);
AudioConnection          patchCord43(biquad40, notefreq1);
AudioConnection          patchCord44(biquad40, 0, i2s1, 1);
AudioConnection          patchCord45(biquad39, biquad40);
AudioControlSGTL5000     sgtl5000_1;     //xy=129,450
// GUItool: end automatically generated code





#define SDCARD_CS_PIN    10
#define SDCARD_MOSI_PIN  7   
#define SDCARD_SCK_PIN   14 


void setup() {
  Serial.begin(9600);
  AudioMemory(80);

  sgtl5000_1.enable();
  sgtl5000_1.volume(1);
  biquad1.setLowpass(0, 2000, 0.707);
  biquad2.setLowpass(0, 2000, 0.707);
  biquad3.setLowpass(0, 2000, 0.707);
  biquad4.setLowpass(0, 2000, 0.707);
  biquad5.setLowpass(0, 2000, 0.707);
  biquad6.setLowpass(0, 2000, 0.707);
  biquad7.setLowpass(0, 2000, 0.707);
  biquad8.setLowpass(0, 2000, 0.707);
  biquad9.setLowpass(0, 2000, 0.707);
  biquad10.setLowpass(0, 2000, 0.707);
  biquad11.setLowpass(0, 2000, 0.707);
  biquad12.setLowpass(0, 2000, 0.707);
  biquad13.setLowpass(0, 2000, 0.707);
  biquad14.setLowpass(0, 2000, 0.707);
  biquad15.setLowpass(0, 2000, 0.707);
  biquad16.setLowpass(0, 2000, 0.707);
  biquad17.setLowpass(0, 2000, 0.707);
  biquad18.setLowpass(0, 2000, 0.707);
  biquad19.setLowpass(0, 2000, 0.707);
  biquad20.setLowpass(0, 2000, 0.707);
  biquad21.setHighpass(0, 150, 0.707);
  biquad22.setHighpass(0, 150, 0.707);
  biquad23.setHighpass(0, 150, 0.707);
  biquad24.setHighpass(0, 150, 0.707);
  biquad25.setHighpass(0, 150, 0.707);
  biquad26.setHighpass(0, 150, 0.707);
  biquad27.setHighpass(0, 150, 0.707);
  biquad28.setHighpass(0, 150, 0.707);
  biquad29.setHighpass(0, 150, 0.707);
  biquad30.setHighpass(0, 150, 0.707);
  biquad31.setHighpass(0, 150, 0.707);
  biquad32.setHighpass(0, 150, 0.707);
  biquad33.setHighpass(0, 150, 0.707);
  biquad34.setHighpass(0, 150, 0.707);
  biquad35.setHighpass(0, 150, 0.707);
  biquad36.setHighpass(0, 150, 0.707);
  biquad37.setHighpass(0, 150, 0.707);
  biquad38.setHighpass(0, 150, 0.707);
  biquad39.setHighpass(0, 150, 0.707);
  biquad40.setHighpass(0, 150, 0.707);
  SPI.setMOSI(SDCARD_MOSI_PIN);
  SPI.setSCK(SDCARD_SCK_PIN);
  notefreq1.begin(.15);
  if (!(SD.begin(SDCARD_CS_PIN))) {

    while (1) {
      Serial.println("Unable to access the SD card");
      delay(500);
    }
  }
}

void playFile(const char *filename)
{
  Serial.print("Playing file: ");
  Serial.println(filename);
  playSdWav1.play(filename);
  delay(25);
}

void loop() {
playFile("ALARME.WAV"); 
  while (playSdWav1.isPlaying()) {
      if (notefreq1.available()) {
        float note = notefreq1.read();
        float prob = notefreq1.probability();
        Serial.printf("Note: %3.2f | Probability: %.2f\n", note, prob);
      }
    }
}
 
In frequency, how close is the noise that you're trying to remove? I do not believe that you have described the noise that you are seeing. Can you describe the noise? Or, can you provide a sample of the noise, like you provided a sample of the alarm signal?

For a lowpass filter using a biquad, it is a 2nd-order filter, so it will roll-off at 12 dB for every 2x change in frequency above the cutoff frequency. You are cascading 20 of these biquad filters. This is very unusual. To me, it suggests that you must be trying to cut noise that is really close to the filter's cutoff frequency? In other words, you want a filter that rolls-off very sharply with frequency?

Normally, if someone wants this kind of fine frequency resolution, one uses an FFT. An FFT is very sharp. It allows you to detect signals at one frequency while permitting you to ignore noise at a frequencies very near-by. Adding basic highpass and lowpass filters before an FFT does not (generally) improve an FFT's ability to detect tonal signals within noise. So, it feels like your use of the biquad filters is not an approach that will solve your problem.

So, to help you better, we need to know more about the noise that you're trying to filter away. A sample of it would be great.

Chip
 
The way I did this type of design is to generate me the filter in, say Matlab and then to convert the filter to biquads to be programmed to Teensy. Matlab has tools for that.
I have not done it for a while, but I never have seem 20 biquads with identical parameters.
 
This may or may not be relevant, but as a general rule of thumb with filters, achieve better (steeper) roll off in frequency tends to have trade-offs in the phase response. If you only ever analyze the frequency response, you can end up believing you have a really excellent filter. And if frequency is all that matters, then maybe you don't care about things like phase shift or the response over time to inputs like a sudden step change. But if you do also care about those, remember to check them because optimizing for one thing tends to have trade-offs with others.
 
Back
Top