Showing posts with label Decay. Show all posts
Showing posts with label Decay. Show all posts

Tuesday, 29 July 2014

Dub && Wise Synth


*some decoupling capacitors 100nFclose to the analog pins should be added.




My initial intention was to create something focused for the soundsystem culture. This turned out to be much more difficult than i thought .
Dub siren/Elec tom synth/And oscilattor+ MAD Lfos (some trying to recreate some of the sounds in a synare that Jah Shaka got us all used to)...All this synthesized on the fly with the help of some wavetables (all created during the start up)
.
Pots for :
-Oscillator wave selector ( Sine,cosine  Saw, Inverted Saw, Square wave, triangle and 1 extra slots for now )
-LFO rate
-LFO modulator type select ( Any of the above tables, plus a few more specific and tailored options)
-Attack
-Release
* Both attack and release can interact with the LFO
- Mode selector ( Dub Siren, Sound effects " a la Synare", Elec-Tom synth)

This video is just as an update on the proceedings.
Here i am using the Arduino Due.
Due to its complexity, i ended up re-writing the whole code from scratch and fresh to suit this specific idea.
Already started porting a similar idea to the chipKit DP32, and Pinguino and an Xmos version also soon to come, subject to availability of spare time.



Wednesday, 6 November 2013

Quick pictures update on ADSR

 Exp.attack at 0.4 and sustain level at 7/8 ( 20 Ms div)




A quick update to show that first try, worked as expected. Spent a few good hours in the process of starting to optimize the different building blocks id gathered, and make them interact. Tried to keep it as readable as possible and document the little quirks, and possible variations, references, etc in the implementation methods.
We have officially an ADSR with variable exponential attack, variable "decay-sustain ratio" ( allows both bypassing the sustain stage, and also looping/extending the sustain stage ), and variable duration/period... For now !


Next comes LFO's from all the wavetables available, simple filters, and start implementing simple convolution reverb. Lets see how far can i  "push the envelope" ( No pun intended).





Square wave and exp.attack at 0.5 ( .2 s Div )


Monday, 28 October 2013

ADSR Exercises...

The exponential attack curves available will have these different options, in the final version !

I had to try to rethink the ADSR block of my project, as there are some variations that i want to include, and that make it different from other methods more popular often used in synths. Plus, what im building is not your average synth either, so here are some of the results of my tests ! Still need to test it as far as performance goes to be able to decide if ill go with an exponential attack( i am quite confident it can be calculated between interrupts, so as not to weigh too much on the interrupt load, itself !
I tried to make it as readable as possible; There are a lot of short cuts available to make it more efficient and optimize it. Which shall be taken into consideration in the final code . This one was wrote in tutorial style; several of the calculations can be shortened , optimized, for better performance. But then, it wouldn't have been as readable as this, i guess !
So, here it is for now !.


//*    Synth Building blocks 
//*    ATTACK-DECAY-SUSTAIN-RELEASE for Wavetable-based Generator #0.1
//*    Check section "Synth building blocks related" @
//*    http://dubworks.blogspot.co.uk/p/my-self-documented-tutorials.html
//*    Result of my experiences into the ADSR part of my project. Keep in mind that i decided to re-trhink it, 
//*    as what im working on is not your usual synth, but something else slightly(?!) different.
//*    This code was wrote for readability more than anything else ! There are a lot of short cuts available
//*    to make it more efficient and optimize it. Which shall be taken into consideration in the final code 

#define xinc (1.00/param.attack) // Allows an exponential attack
#define sigl 4095 // Despite being a constant here, it should be replaced by the wavetable equivalent
//
uint32_t phaseinc,output;
//
//  Declare the struct for our ADSR
struct ADSR {
  uint16_t period;  // total of the whole period
  uint16_t attack;
  uint16_t decay;
  uint16_t sustain;
  uint16_t rlease;
  float x;  // increment for period, to accum xinc by addition
};
struct ADSR param; // initialize the structure, so it is in scope !
//
//boolean led = false; 
//
void update (){
  if(phaseinc <= param.period){
    //
    if(phaseinc < param.attack){
      float y;
      y= pow(param.x , 0.50);  // Expon. attack-generator. This is where my latest tests been focusing on
      output= sigl * y;  //Ramp up can be achieved by just multiplying it by param.x as well, though 
      //  it would be a waste of computing power, as there are easier and "cheaper" ways to do it !

      //      Serial.print ("attack ");
      //      Serial.println (attack);
      //      Serial.print ("Output ");
      //      Serial.println (output);
    }
    else if(phaseinc >= param.attack && phaseinc <(param.attack + param.decay)){
      //
      output = sigl-((phaseinc - param.attack)*(512.0/param.decay)); //512= 4096 * 1/8
      //      Serial.println ("decay");
      //      Serial.println (param.decay);
      //      Serial.print ("Output ");
      //      Serial.println (output);
    }
    else if(phaseinc >=(param.attack + param.decay) && phaseinc <(param.attack + param.decay + param.sustain)){
      //
      //      Serial.print ("sustain");
      //      Serial.println (param.sustain);
      output = sigl *(7/8.00);
      //      Serial.print ("Output ");
      //      Serial.println (output);
    }
    else if(phaseinc >(param.attack + param.decay + param.sustain) && phaseinc < param.period){
      //
      //      Serial.print ("rlease");
      //      Serial.println (param.rlease);
      output=(param.rlease-(phaseinc-(param.attack+param.decay+param.sustain)))*((sigl*(7/8.00))/param.rlease);
      //      Serial.print ("Output ");
      //      Serial.println (output);  
    }
  }
}
//
void ADSR_calculation()
{ 
  //  There are more exciting ways to calculate division and remainders.
  //  We wrap-up with  a "modulo-like" operator for
  //  the last variable sustain- a "greatest-integer function" of sorts .
  //  This way we can go from decay to release directly. Todo list is to loop inside the sustain
  //  For now im planning using 3 sec/1 as MAXIMUM of the whole period for ADSR.
  uint16_t b    = param.period >> 1;  // These operations help us achieve a cheap aproximation
  param.attack  = param.period >> 2; 
  param.decay   = b/3;
  param.rlease  = param.period >> 2;
  param.sustain = param.period -(param.attack + param.rlease + param.decay); 
  // same as 
  // param.sustain = param.period %(param.attack + param.rlease + param.decay);
  /*if(Serial){
   Serial.print ("attack ");
   Serial.println (param.attack);
   Serial.print ("decay ");
   Serial.println (param.decay);
   Serial.print ("sustain ");
   Serial.println (param.sustain);
   Serial.print ("rlease ");
   Serial.println (param.rlease);
   }*/
}
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  //variable for the period; To be analogous to the analog read/s and should be declared with an initial 
  //value(21504?!), before the buffering of the initial values , at the time of wavetable generation
  param.period=128;  //this value should be the sum of all ADSR values, so we can have variable-lenght 
  //  on each of the individual parameters of the ADSR !It is already in the tODO list !
  //  But for now, ill leave it as it is: weighed proportionally !
  //
  ADSR_calculation();
}

void loop() {

//  if(Serial){
//    Serial.print ("phaseinc ");
//    Serial.println (phaseinc);
//  }
  //
  update();  
  //This can be done between interrupts, as there is some calculations involved.

  phaseinc++;
  //Serial.println(phaseinc);
  if( phaseinc >= param.period ){
    phaseinc= phaseinc - param.period;
    ADSR_calculation();
  }
  param.x += xinc;
  if (param.x >= 1){
    param.x = 0;
  }
  Serial.println (output);
}