simple low pass filter

114 views
Skip to first unread message

C C

unread,
Apr 11, 2025, 7:35:54 PMApr 11
to Mozzi-users
I cannot get this to work for whatever reason, it only works at certain frequency like a cutoff at 5000Hz, and it sometimes still pass through audio when the cut off is 20Hz, most of the time there is just no sound. I am using an arduino mega 2560 if that matters

#define MOZZI_CONTROL_RATE 64
#include <Mozzi.h>
#include <Oscil.h>
#include <tables/saw2048_int8.h>
#include <tables/cos2048_int8.h>
#include <LowPassFilter.h>

Oscil<SAW2048_NUM_CELLS, MOZZI_AUDIO_RATE> aSaw(SAW2048_DATA);

LowPassFilter lpf;
char resonance = 70; // range 0-255, 255 is most resonant
uint8_t freq = 4800;

void setup() {
aSaw.setFreq(440);
startMozzi();
}

void updateControl() {
lpf.setCutoffFreqAndResonance(freq, resonance);
}

AudioOutput updateAudio() {
int audioIn = aSaw.next();
int filtered = lpf.next(audioIn);
//return MonoOutput::from8Bit(filtered);
//return MonoOutput::fromNBit(9, lpf.next(audioIn)).clip();
//return lpf.next(audioIn);
return filtered;
//return audioIn;
}

void loop() {
audioHook();
}

tomco...@live.fr

unread,
Apr 13, 2025, 6:26:14 AMApr 13
to Mozzi-users
Hello,

The problem lies by the fact that the cutoffFreq is not expressed in terms of Hz. As it is actually shown in your code, freq is an uint8_t, ranging from 0 to 255, so putting values greater than that will lead to rolloff: 256 is actually equivalent to 0, 257 to 1 etc. As per the doc (https://sensorium.github.io/Mozzi/doc/html/class_resonant_filter.html)

 > range 0-255 represents 0-8191 Hz (MOZZI_AUDIO_RATE/2) for ResonantFilter, range 0-65535 for ResonantFilter16 Be careful of distortion at the lower end, especially with high resonance.

So if you want to know exactly the cutoff frequency you need to compute it knowing that at 0 the filter is completely closed and completely open at 255.
If you need more resolution on the parameters you can use the 16bits version of this filter (ResonantFilter16).

Also note that #include <LowPassFilter.h> is deprecated (you should get a warning at compilation), people are encouraged to use ResonantFilter instead (which is completely equivalent but more versatile as other types of filters can also be used).

Hope this helps!

C C

unread,
Apr 13, 2025, 9:46:02 PMApr 13
to mozzi...@googlegroups.com
Hi, after changing the range it kind of made more sense. But now I have another problem. I set the resonance to 0 the cutoff to sweep from 0 ~ 200 and then back. but the filter output just goes out of control once it gets around maybe 190? I have also tried other resonance values and it makes a different but similar sound. It works normally when I only sweep from 0 ~ 180 tho. I will attach the code and audio below of it doing one cycle of  0 to 200 and back to 0, would you have any idea what the problem is?

#include <Mozzi.h>
#include <MozziGuts.h>
#include <Oscil.h>
#include <tables/saw2048_int8.h> // saw table for oscillator
#include <tables/cos2048_int8.h> // for filter modulation
#include <ResonantFilter.h>
#include <mozzi_rand.h>

Oscil <SAW2048_NUM_CELLS, AUDIO_RATE> aSaw1(SAW2048_DATA);

//Different types of filters available
//LowPassFilter rf; // Equivalent to ResonantFilter<LOWPASS>
ResonantFilter<LOWPASS> rf;
//ResonantFilter<HIGHPASS> rf; // HighPass filter
//ResonantFilter<BANDPASS> rf; // BandPass filter
//ResonantFilter<NOTCH> rf; // Notch filter

float smoothedCutoff = 0;
int cutOff = 0;
int direction = 1; // +1 or -1

void setup(){
startMozzi();
aSaw1.setFreq(1000);
}

void updateControl(){
// map the modulation into the filter range (0-255), corresponds with 0-MOZZI_AUDIO_RATE/(sqrt(2)*pi) Hz
//byte cutOff = smooth(analogRead(A0), smoothedCutoff, 0.01) * 255 / 1023;
//smoothedCutoff += (analogRead(A0) - smoothedCutoff) * 0.01;
//byte cutOff = smoothedCutoff * 255 / 1023;

cutOff += direction;

if (cutOff >= 200) {
cutOff = 200;
direction = -1;
} else if (cutOff <= 0) {
cutOff = 0;
direction = 1;
}
rf.setCutoffFreq(cutOff);
rf.setResonance(0);
}

AudioOutput updateAudio(){
char asig = rf.next(aSaw1.next());
//return MonoOutput::from8Bit(asig);
return MonoOutput::fromNBit(8, asig);
}

void loop(){
audioHook();
}


--
You received this message because you are subscribed to the Google Groups "Mozzi-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mozzi-users...@googlegroups.com.
To view this discussion, visit https://groups.google.com/d/msgid/mozzi-users/ee9f451e-a312-4263-bbfc-7bbb0e956dc1n%40googlegroups.com.
440 sweep.wav

tomco...@live.fr

unread,
Apr 14, 2025, 3:30:50 AMApr 14
to Mozzi-users
This sounds like an overflow in the output. Try to change asig to int16_t  and increase the number of bits of the output (for instance: return MonoOutput::fromNBit(10, asig);) . That's usually a good strategy to increase a bit this number if you get unexpected distortion in the output, just to pinpoint the problem and make sure you are not producing more bits than what you think. In theory, with a resonance of 0, the filter should not exceed the initial range, but there is no guaranty.

Side note: better to use setCutoffFreqAndResonancethan the separate versions, way more efficient, that's why the other two are written as deprecated in the doc ;).

What platform/board are you using? Arduino AVR?
Message has been deleted
Message has been deleted

C C

unread,
Apr 15, 2025, 2:04:05 AMApr 15
to Mozzi-users
I have tested int16_t and increasing the output to 10 bits and other higher bits, with a resonance of 0 it works normally if the cutoff is lower than around 190, but when the filter value gets higher than that, it just makes this clicking popping sound which sounds like a 2Hz saw wave.
I am on mac and using arduino IDE. I am using an arduino mega 2560 board, and am planning to get an MCP4822 dac soon, would you know if any of these problems are caused by not having a dac?

C C

unread,
Apr 15, 2025, 2:04:15 AMApr 15
to Mozzi-users
I changed the int16_t and the bit number as you suggested, but now when cutoff gets to around 190 it instead makes this popping clicking sound like a 2Hz saw wave.
I am on mac and using arduino IDE. I have a arduino 2560 mega and am planning on getting a MCP4822 DAC soon, any idea if this issue has to do with not having an included DAC?

On Monday, April 14, 2025 at 3:30:50 AM UTC-4 tomco...@live.fr wrote:

Mozzi-users

unread,
Apr 15, 2025, 2:11:48 AMApr 15
to Mozzi-users
My guess is that the filter is distorting and it's worth experimenting with 
- less resonance (lower values are more resonant, higher values less resonant), and 
- reducing the level of the input value to the filter... 

The arduino you have should be fine without a DAC.

tomco...@live.fr

unread,
Apr 15, 2025, 4:29:30 AMApr 15
to Mozzi-users
> - reducing the level of the input value to the filter...

Indeed that could help!

I am a bit confused though that this filter does not work with a 8bits input, I'll try to test here one of these days. Could you maybe send the last sketch you are playing with?

tomco...@live.fr

unread,
Apr 16, 2025, 9:11:20 AMApr 16
to Mozzi-users
Hello again,

I tried and I can confirm this. Did not search into details what is going wrong in the filter but I think that the saw wave's sharp transitions do throw something off in there. Interestingly, smoother waves (cos for instance) are not affected.
Different solutions are possible:
 - taming a bit the input level:
int asig = rf.next(aSaw.next()>>1);
return MonoOutput::fromNBit(8,asig);

- using a band limited saw table:
#include <tables/BandLimited_SAW/2048/saw_max_2730_at_16384_2048_int8.h>
Oscil<COS2048_NUM_CELLS, MOZZI_AUDIO_RATE> aSaw(SAW_MAX_2730_AT_16384_2048_DATA);

- changing for a version of the filter with more headroom (beware that the parameters are then encoded on 16bits and not 8) if you can afford the fact that this is less efficient on AVR):
LowPassFilter16 rf; // Equivalent to ResonantFilter<LOWPASS, int16_t>

Hope this helps!
Message has been deleted

Fumi SA

unread,
Jul 29, 2025, 6:27:28 AMJul 29
to Mozzi-users

Hi All,
I would like to use a low-pass filter with LowPassFilter.h.
However, when the cutOffFreq is around 180, the sound suddenly stops or becomes distorted as if it's broken.
Is there something wrong with my settings?
Here is my code:

cpp

#include <Mozzi.h>
#include <Oscil.h>
#include <EventDelay.h>
#include <tables/saw2048_int8.h>
#include <LowPassFilter.h>
#define MOZZI_CONTROL_RATE 64



Oscil<SAW2048_NUM_CELLS, MOZZI_AUDIO_RATE> aSaw(SAW2048_DATA);
LowPassFilter lpf;

EventDelay toggle;
bool noteOn = true; // Note on/off flag
const int analogPin1 = A0;
int freq = 55*2;
int8_t cutOffFreq = 180;

void setup(){
  startMozzi();
  aSaw.setFreq(freq);
  lpf.setCutoffFreq(cutOffFreq);
  toggle.start(50); // Wait time
}

void updateControl(){
  int potValue = mozziAnalogRead(analogPin1);

  //cutOffFreq = map(potValue, 0, 1023, 0, 254);
  //lpf.setCutoffFreq(cutOffFreq);

  if (toggle.ready()){
    noteOn = !noteOn;  // Toggle note on/off
    toggle.start(50);  // Wait
  }

  if (noteOn){
    aSaw.setFreq(freq);  // Set frequency
  } else {
    aSaw.setFreq(0);    // Stop
  }
}

AudioOutput updateAudio(){
  int audioSignal = aSaw.next();
  audioSignal = lpf.next(audioSignal);
  return MonoOutput::from8Bit(audioSignal);
}

void loop(){
  audioHook();
}


In the future, I plan to use a potentiometer, but for now that part is commented out.

2025年4月16日水曜日 22:11:20 UTC+9 tomco...@live.fr:

tomco...@live.fr

unread,
Jul 30, 2025, 7:16:48 AMJul 30
to Mozzi-users
Hi,

The output from the filter probably exceeds the 8bits range Mozzi is expecting in: return MonoOutput::from8Bit. The sample that you feed to the filter (aSaw.next()) is in the 8 bits range. However, as the filter can be resonant, its output (lpf.next()) can exceed that range.
The first thing is that you did not set the resonance of the filter. Setting the resonance at 0 will help keeping the output of the filter low.
You can also try to tell Mozzi that the signal you are sending is bigger than 8bits, for instance: return MonoOutput::fromNBit(10, audioSignal); It is usually worth experimenting there to find the best value in order not to reduce the sound level too much while not exceeding the range of the signal. Using .clip() could also help getting "less" distortion (https://sensorium.github.io/Mozzi/doc/html/struct_mono_output.html#a0e641cbab9732214c696cd1071e45de5)

Hope this helps,
Reply all
Reply to author
Forward
0 new messages