void processAudio(AudioBuffer &buffer) {
   float tune = getParameterValue(PARAMETER_A)*10.0 - 6.0;
   float fc = getParameterValue(PARAMETER_B)*10.0 - 4.0;
   float q = getParameterValue(PARAMETER_C)*3+0.75;
   float shape = getParameterValue(PARAMETER_E)*2;
   float pw = 0.5;
   if(shape > 1.0){
     pw += 0.49*(shape-1.0); // pw 0.5 to 0.99
     shape = 1.0; // square wave
   }
   float df = getParameterValue(PARAMETER_D)*4;
   int di = (int)df;
   float gain = 0.0f;
   switch(di){
     // a/d
   case 0: // l/s
     env.setAttack(1.0-df);
     env.setRelease(0.0);
     break;
   case 1: // s/s
     env.setAttack(0.0);
     env.setRelease(df-1);
     break;
   case 2: // s/l
     env.setAttack(df-2);
     env.setRelease(1.0);
     break;
   case 3: // l/l
     env.setAttack(1.0);
     env.setRelease(1.0);
     gain = df-3;
     break;
   }
   env.trigger(isButtonPressed(PUSHBUTTON), getSamplesSinceButtonPressed(PUSHBUTTON));
   FloatArray left = buffer.getSamples(LEFT_CHANNEL);
   FloatArray right = buffer.getSamples(RIGHT_CHANNEL);
   // vco
   hz.setTune(tune);
   float lfreq = hz.getFrequency(left[0]);
   osc.setFrequency(lfreq);
   osc.setShape(shape);
   osc.setPulseWidth(pw);
   osc.getSamples(left);
   // vcf
   hz.setTune(fc);
   fc = hz.getFrequency(right[0]);
   fc = min(0.999, max(0.01, fc/(getSampleRate()*2))); // normalised and bounded
   filter->setLowPass(fc, q);
   right.copyFrom(left);
   filter->process(right);
   right.multiply(0.8-q*0.2); // gain compensation for high q
   // vca
   env.getEnvelope(envelope);
   envelope.add(gain);
   left.multiply(envelope);
   right.multiply(envelope);
 }
 void processAudio(AudioBuffer &buffer){
   float cutoff=getParameterValue(PARAMETER_A);
   float resonance=10*getParameterValue(PARAMETER_B);
   FloatArray fa=buffer.getSamples(0);
   // fa.noise();
   filter->setLowPass(cutoff, resonance);
   filter->process(fa, fa, fa.getSize());
   buffer.getSamples(1).copyFrom(fa);
 }
 BiquadFilterTestPatch(){
   registerParameter(PARAMETER_A, "Cutoff");
   registerParameter(PARAMETER_B, "Resonance");
   int stages=3;
   filter=BiquadFilter::create(stages);
   float cutoff=0.2;
   float resonance=2;
   //test setLowPass
   FloatArray coefficients=FloatArray::create(5*stages);
   FloatArray states=FloatArray::create(2*stages);
   FilterStage stage(coefficients, states);
   filter->setLowPass(cutoff, resonance);
   stage.setLowPass(cutoff, resonance);
   for(int k=0; k<stages; k++){ 
     for(int n=0; n<5; n++){
       float filterC=filter->getFilterStage(k).getCoefficients()[n];
       float stageC=stage.getCoefficients()[n];
       ASSERT(filterC==stageC, "Coefficients not initialized"); //check that filter coefficients are properly initialized
     }
   }
   int signalLength=100;
   
   FloatArray x=FloatArray::create(signalLength);
   FloatArray x1=FloatArray::create(signalLength);
   FloatArray y=FloatArray::create(signalLength);
   FloatArray y1=FloatArray::create(signalLength);
   x.noise();
   x1.copyFrom(x);
   
   filter->process(x1, y1, x1.getSize());
   //manually compute the filter
   float b0=filter->getFilterStage(0).getCoefficients()[0];
   float b1=filter->getFilterStage(0).getCoefficients()[1];
   float b2=filter->getFilterStage(0).getCoefficients()[2];
   float a1=filter->getFilterStage(0).getCoefficients()[3];
   float a2=filter->getFilterStage(0).getCoefficients()[4];
   for(int n=0; n<stages; n++){
     float d1=0;
     float d2=0;
     for(int n=0; n<x.getSize(); n++){ //manually apply filter, one stage
       y[n] = b0 * x[n] + d1;
       d1 = b1 * x[n] + a1 * y[n] + d2;
       d2 = b2 * x[n] + a2 * y[n];   
     }
     x.copyFrom(y); //copy the output to the input for the next iteration. INEFFICIENT
   }
   //done with the filter
   for(int n=0; n<x.getSize(); n++){
     // ASSERT(abs(y[n]-y1[n])<0.0001, "");//BiquadFilter.process(FloatArray, FloatArray) result"); //TODO: fails for non-arm
   }
   FloatArray::destroy(x);
   FloatArray::destroy(x1);
   FloatArray::destroy(y);
   FloatArray::destroy(y1);
   debugMessage("All tests passed");
 }
 DrumVoice(float sr) : fs(sr) {
   // env = new AdsrEnvelope(sr);
   // env = FloatArray::create(1024);
   // for(int i=0; i<env.getSize(); ++i)
   //   env[i] = expf(-M_E*i/env.getSize());
   snare = 0;
   balance = 0.2;
   sine = new SineOscillator(sr);
   chirp = new ChirpOscillator(sr);
   impulse = new ImpulseOscillator();
   env1 = new ExponentialDecayEnvelope(sr);
   env2 = new ExponentialDecayEnvelope(sr);
   noise = new PinkNoiseOscillator();
   filter = BiquadFilter::create(1);
   filter->setLowPass(0.6, FilterStage::BUTTERWORTH_Q);
 }  
 void setSnap(float s){
   snare = s;
   balance = s*0.5;
   filter->setLowPass(0.25+balance, FilterStage::BUTTERWORTH_Q);
 }