Loud white noise on the edge of filter

Status
Not open for further replies.

Jat

Member
Hello,

my nunchuck/Ps2keyboard synth is pretty well advanced... But I have a little issue on my filter (Chamberlin), when it's set above 16000hz and resonance under 1.05 the synth produce a loud white noise (with some "fm" sound when getting in).
All my other stuffs work great, here is my patch:
patch2017_01_08.jpg

abstract of serialmonitor:
Proc = 12.12 (55.81), Mem = 101 (255)
Proc = 12.16 (55.86), Mem = 168 (255)
Proc = 12.10 (55.86), Mem = 235 (255)
Proc = 12.11 (55.86), Mem = 47 (255)
Proc = 12.08 (55.86), Mem = 114 (255)
Proc = 12.08 (55.86), Mem = 182 (255)
Proc = 12.10 (55.86), Mem = 249 (255)
Perhaps I was too greedy...
AudioMemoryUsageMax() every 5 seconds return me (255) everytime... and AudioMemoryUsage() within 60-230
I'm a musician doing "noise" and experimental music, so it's not a big issue for me but I would to understand what's happen

full code:
Code:
#include <Audio.h>
#include <i2c_t3.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioSynthWaveformSine   sine;          //xy=55,118
AudioSynthWaveform       triangle;      //xy=55,170
AudioSynthWaveform       square;      //xy=55,226
AudioSynthNoiseWhite     noise;         //xy=56,294
AudioMixer4              mixerfm;         //xy=229,161
AudioMixer4              mixerfilter;         //xy=271,251
AudioSynthWaveformSineModulated sinefm;       //xy=350,161
AudioEffectBitcrusher    bitcrusher1;    //xy=489,161
AudioFilterStateVariable filter1;        //xy=624,172
AudioMixer4              mixer;         //xy=741,180
AudioMixer4              left;         //xy=864,139
AudioMixer4              right;         //xy=867,219
AudioOutputAnalogStereo  dacs;          //xy=985,175
AudioConnection          patchCord1(sine, 0, mixerfm, 0);
AudioConnection          patchCord2(sine, 0, mixerfilter, 0);
AudioConnection          patchCord3(triangle, 0, mixerfm, 1);
AudioConnection          patchCord4(triangle, 0, mixerfilter, 1);
AudioConnection          patchCord5(square, 0, mixerfm, 2);
AudioConnection          patchCord6(square, 0, mixerfilter, 2);
AudioConnection          patchCord7(noise, 0, mixerfm, 3);
AudioConnection          patchCord8(noise, 0, mixerfilter, 3);
AudioConnection          patchCord9(mixerfm, sinefm);
AudioConnection          patchCord10(mixerfilter, 0, filter1, 1);
AudioConnection          patchCord11(sinefm, bitcrusher1);
AudioConnection          patchCord12(bitcrusher1, 0, filter1, 0);
AudioConnection          patchCord13(filter1, 0, mixer, 0);
AudioConnection          patchCord14(filter1, 1, mixer, 1);
AudioConnection          patchCord15(filter1, 2, mixer, 2);
AudioConnection          patchCord16(mixer, 0, left, 0);
AudioConnection          patchCord17(mixer, 0, right, 0);
AudioConnection          patchCord18(left, 0, dacs, 0);
AudioConnection          patchCord19(right, 0, dacs, 1);
// GUItool: end automatically generated code


#include "Nunchuk.h"
IntervalTimer NuchukTimer;
Nunchuk nc = Nunchuk();
volatile float NcAccel;
volatile int NcAccelX;
volatile int NcAccelY;
volatile int NcAccelZ;
volatile bool NcBtnZ;
volatile bool NcBtnC;
volatile int NcJoyX;
volatile int NcJoyY;
volatile float NcTiltX;
volatile float NcTiltY;
volatile float NcTiltZ;
int NcJoyX_offset = 0; // offset for joystick x achsis
int NcJoyY_offset = 0; // offset for joystick yS achsis

#include <PS2Keyboard.h>
const int DataPin = 26;///clavier pins
const int IRQpin =  25;
byte test = 1;
byte c = 20;
float srcrush;
unsigned long last_time = millis();
PS2Keyboard keyboard;

void setup() {

  NVIC_SET_PRIORITY(IRQ_PORTA, 0);        ////////////////////// Interrupts Priority (PS2 debug)
  NVIC_SET_PRIORITY(IRQ_PORTB, 0);
  NVIC_SET_PRIORITY(IRQ_PORTC, 0);
  NVIC_SET_PRIORITY(IRQ_PORTD, 0);
  NVIC_SET_PRIORITY(IRQ_PORTE, 0);
  AudioMemory(200);////////////////////////////////////
  analogReadRes(13);
  delay(500);
  keyboard.begin(DataPin, IRQpin);
  Serial.begin(9600);
  Serial.println("serialOk");

  pinMode(13, OUTPUT);
  digitalWrite(13, HIGH);

  // Initialize the Nunchuk.
  nc.begin();
  NuchukTimer.begin(readNuchuk, 10000);// all 10ms
  elapsedMillis waiting;     // "waiting" starts at zero
  while (waiting < 2000) {
    NcJoyX_offset = runningAverageX(NcJoyX);
    NcJoyY_offset = runningAverageY(NcJoyY);
  }
  NcJoyX_offset *= -1;
  NcJoyY_offset *= -1;
  Serial.print("offset X: ");
  Serial.print(NcJoyX_offset);
  Serial.print("offset Y: ");
  Serial.println(NcJoyY_offset);

  sine.amplitude(1);///////////////////////
  sine.frequency(440);
  sine.phase(0);
  triangle.begin(WAVEFORM_TRIANGLE);///////
  triangle.amplitude(1);
  triangle.frequency(440);
  triangle.phase(0);
  square.begin(WAVEFORM_SQUARE);///////
  square.amplitude(1);
  square.frequency(440);
  square.phase(0);
  noise.amplitude(1);//////////////////////
  mixerfm.gain(0, 0); ///////////////////////
  mixerfm.gain(1, 0);
  mixerfm.gain(2, 0);
  mixerfm.gain(3, 0);
  sinefm.amplitude(0.7);//////////////////
  sinefm.frequency(110);
  sinefm.phase(0);
  bitcrusher1.bits(16); /////////////////
  bitcrusher1.sampleRate(44100);
  mixerfilter.gain(0, 0); //////////////////
  mixerfilter.gain(1, 0);
  mixerfilter.gain(2, 0);
  mixerfilter.gain(3, 0);
  mixer.gain(0, 0); ///////////////////////
  mixer.gain(1, 0);
  mixer.gain(2, 0);
  mixer.gain(3, 0);
  left.gain(0,0.7);
  left.gain(1,0);
  left.gain(2,0);
  left.gain(3,0);
  right.gain(0,0.7);
  right.gain(1,0);
  right.gain(2,0);
  right.gain(3,0);
  filter1.frequency(22000);
  filter1.resonance(1.2); //0.7 to 5.0
  filter1.octaveControl(7); // 0 to 7
  dacs.analogReference(INTERNAL);
  AudioProcessorUsageMaxReset();
  AudioMemoryUsageMaxReset();
  delay(50);
  
  mixer.gain(0, 1);
 delay(50);
  sinefm.frequency(110);
  delay(250);
  sinefm.frequency(220);
  delay(250);
  sinefm.frequency(440);
  delay(250);
  sinefm.frequency(880);
  delay(250);
  sinefm.frequency(1760);
  delay(250);
  sinefm.frequency(10);
  delay(250);
  
}
/// -------Nunchuk Timer Function all 10ms---
void readNuchuk() {
  nc.read();
  if ( nc.isOk() )
  { NcAccel = nc.getAccel();
    NcAccelX = nc.getAccelX();
    NcAccelY = nc.getAccelY();
    NcAccelZ = nc.getAccelZ();
    NcBtnZ = nc.getButtonZ();
    NcBtnC = nc.getButtonC();
    NcJoyX = nc.getJoyX();
    NcJoyY = nc.getJoyY();
    NcTiltX = nc.getTiltX();
    NcTiltY = nc.getTiltY();
    NcTiltZ = nc.getTiltZ();
  }
}

///------------------ Main LOOP ---------------- Main LOOP ------------------- Main LOOP ---------------- Main LOOP -------------------------- Main LOOP --------
void loop() {
  
      //serial_print_all_nunchuk_inputs();  //--------DEBUG---------
      //serial_print_pots();
//  if (millis() - last_time >= 5000) {
//    Serial.print("Proc = ");
//    Serial.print(AudioProcessorUsage());
//    Serial.print(" (");
//    Serial.print(AudioProcessorUsageMax());
//    Serial.print("),  Mem = ");
//    Serial.print(AudioMemoryUsage());
//    Serial.print(" (");
//    Serial.print(AudioMemoryUsageMax());
//    Serial.println(")");
//    AudioMemoryUsageMaxReset();
//    last_time = millis();
//  }
  if (keyboard.available()) {
    // read the next key
    c = keyboard.read();
    Serial.println(c);
    digitalWrite(13, LOW);
    delay(7);
    digitalWrite(13, HIGH);
  }
  
  srcrush =  sq(analogRead(A10))/1521 + analogRead(A14);
  bitcrusher1.sampleRate(srcrush);
  int bitcrush = analogRead(A11) / 512 ;
  bitcrusher1.bits(bitcrush);
 // Serial.print(srcrush); Serial.println(bitcrush);
  sinefm.frequency((float)c * c / 4 + 20 * NcTiltX);
  int ffilter =sq(analogRead(A8))/3000;
  float res = (float)analogRead(A9) / 1700 + 0.7;
  Serial.print(ffilter); Serial.print( "\t" ); Serial.println (res);
  filter1.frequency(ffilter);
  filter1.resonance(res);
  
  mixerfm.gain(3, ((float)analogRead(A25) / 8192));
  float leftlvl = sin(((float)NcJoyX + (float)NcJoyX_offset +75)*3.14159265359/300); leftlvl = constrain(leftlvl, 0, 1);
  float rightlvl = cos(((float)NcJoyX + (float)NcJoyX_offset +75)*3.14159265359/300); rightlvl = constrain(rightlvl, 0, 1);
  left.gain(0,leftlvl);
  right.gain(0,rightlvl);
  mixerfilter.gain(3,(float)analogRead(A13)/8192); Serial.println(analogRead(A13)/8192);
  
  delay(5);
  
}
///------------------ Main LOOP ---------------- Main LOOP ------------------- Main LOOP ---------------- Main LOOP -------------------------- Main LOOP --------
//------------ DEBUG Nunchuck ---------
void serial_print_all_nunchuk_inputs() {
  Serial.print( NcBtnZ, DEC );
  Serial.print( "\t" );
  Serial.print( NcBtnC, DEC );
  Serial.print( "\t" );
  Serial.print( NcJoyX + NcJoyX_offset, DEC );
  Serial.print( "\t" );
  Serial.print( NcJoyY + NcJoyY_offset, DEC );
  Serial.print( "\t" );
  Serial.print( NcTiltX, DEC );
  Serial.print( "\t" );
  Serial.print( NcTiltY, DEC );
  Serial.print( "\t" );
  //  Serial.print( NcTiltZ, DEC );
  Serial.print( "\n" );
}
void serial_print_pots() {

  Serial.print( "A10 :" ); Serial.print( analogRead(A10) ); Serial.print( "_____" );
  Serial.print( "A11 :" ); Serial.print( analogRead(A11) ); Serial.print( "_____" );
  Serial.print( "A25 :" ); Serial.print( analogRead(A25) ); Serial.print( "_____" );
  Serial.print( "A13 :" ); Serial.print( analogRead(A13) ); Serial.print( "_____" );
  Serial.print( "A12 :" ); Serial.print( analogRead(A12) ); Serial.print( "_____" );
  Serial.print( "A2 :" ); Serial.print( analogRead(A2) ); Serial.print( "\t" );
  Serial.print( "A3 :" ); Serial.print( analogRead(A3) ); Serial.print( "\t" );
  Serial.print( "A6 :" ); Serial.print( analogRead(A6) ); Serial.print( "\t" );
  Serial.print( "A7 :" ); Serial.print( analogRead(A7) ); Serial.print( "\t" );
  Serial.print( "A8 :" ); Serial.print( analogRead(A8) ); Serial.print( "\t" );
  Serial.print( "A9 :" ); Serial.print( analogRead(A9) ); Serial.print( "\t" );
  Serial.print( "\n" );
}

// -----------Functions----------

/// simple Average filter
long runningAverageX(int M) {
#define LM_SIZE 20
  static int LM[LM_SIZE];      // LastMeasurements
  static byte index = 0;
  static long sum = 0;
  static byte count = 0;
  // keep sum updated to improve speed.
  sum -= LM[index];
  LM[index] = M;
  sum += LM[index];
  index++;
  index = index % LM_SIZE;
  if (count < LM_SIZE) count++;
  return sum / count;
}
long runningAverageY(int M) {
#define LM_SIZE 20
  static int LM[LM_SIZE];      // LastMeasurements
  static byte index = 0;
  static long sum = 0;
  static byte count = 0;
  // keep sum updated to improve speed.
  sum -= LM[index];
  LM[index] = M;
  sum += LM[index];
  index++;
  index = index % LM_SIZE;
  if (count < LM_SIZE) count++;
  return sum / count;
}

thank's...
cheer's
 
Last edited:
I have the same issue in my synth. It's one of those nagging loose ends that I have not even had the time to look for yet. Filter freq knob too far to the right AND resonance knob too far to the left makes a loud hissing noise. Fortunately those are not normal operating conditions, and they can be eliminated with some bounds checking. It would be nice to know why it happens though.
 
It's probably a stability problem within the filter algorithm. :(

Chamberlin filters are only stable up to 1/4 the sample frequency. I implemented 2X oversampling, which is supposed to allow usage all the way up to 1/2 the sample frequency (approx 22.05 kHz). But maybe not?

Higher cut-off frequency and lower Q are the stability problem areas for this algorithm.
 
ok, great job anyway!

restricting Q above 1.05 kill the problem, without sensation of resonance presence...
Thank's for precision!
 
Status
Not open for further replies.
Back
Top