0

I'm implementing a low pass filter in C wih the PortAudio library. I record my microphone input with a script from PortAudio itself. There I added the following code:

float cutoff = 4000.0;

float filter(float cutofFreq){
    float RC = 1.0/(cutofFreq * 2 * M_PI);
    float dt = 1.0/SAMPLE_RATE;
    float alpha = dt/(RC+dt);

    return alpha;
}

float filteredArray[numSamples];
filteredArray[0] = data.recordedSamples[0];

for(i=1; i<numSamples; i++){
    if(i%SAMPLE_RATE == 0){
        cutoff = cutoff - 400;
    }
    data.recordedSamples[i] = data.recordedSamples[i-1] + (filter(cutoff)*(data.recordedSamples[i] - data.recordedSamples[i-1]));
}

When I run this script for 5 seconds it works. But when I try to run this for more then 5 seconds it fails. The application records everything, but crashes on playback. If I remove the filter, the application works.

Any advice?

boortmans
  • 1,138
  • 2
  • 24
  • 40
  • don't get for what you need this: `if(i%SAMPLE_RATE == 0)...` also you want to do continuous sampling in RT or sample first then filter? for the first option you should not filter all the samples but just the new added ones ... also you are filtering using `i-1`,`i` so you should have `i--` in for loop not the other way around (you are affecting `i-1` item before its use ... – Spektre Nov 24 '14 at 13:48
  • I'm trying to make filter which will work real time, so I'll need continuos sampling I think. The first if is used because I don't want to change the cutoff every second 44100 times but just once. – boortmans Nov 24 '14 at 13:54
  • added answer ... your main issue most likely after 5 seconds is your cutoff value out of your usable area (negative) – Spektre Nov 24 '14 at 14:16

1 Answers1

0

The problem:

  1. you are lowering the cutoff frequency by 400 Hz everytime i%SAMPLE_RATE == 0

    • never stop so you go below zero
    • this is not done once per second !!!
    • instead every time your for passes through second barrier in your data
    • that can occur more often then you think if you are not calling your calls in the right place
    • which is not seen in your code
  2. you are filtering in wrong oorder

    • ... a[i]=f(a[i],a[i-1]; i++;
    • that means you are filtering with already filtered a[i-1] value

What to do with it

  1. check the code placement

    • it should be in some event like on packed done sompling
    • or in thread after some Sleep(...); (or inside timer)
    • change the cut off changing (handle edge cases)
  2. reverse filter for direction

Something like this:

int i_done=0;

void on_some_timer()
 {
 cutoff-=400;
 if (cutoff<1) cutoff=1; // here change 1 for limit frequency

 if (numSamples!=i_done)
  for (i=numSamples-1,i>=i_done;i--)
   data.recordedSamples[i] = data.recordedSamples[i-1] + (filter(cutoff)*(data.recordedSamples[i] - data.recordedSamples[i-1]));
 i_done=numSamples;
 }

if your code is already OK (you did not post th whole thing so I can missing something)

  • then just add the if (cutoff<1) cutoff=1; after cutoff change
Spektre
  • 49,595
  • 11
  • 110
  • 380
  • So, if my array is filled with audiosamples, I should start a timer, loop through the array and once a timerevent occurs, change the cutoff? – boortmans Nov 24 '14 at 14:41
  • `cutoff-=cutoff-400;` is the same as `cutoff=400;` – mch Nov 24 '14 at 14:52