Saturday, 12 October 2013

options to attack envelope


Ill keep it simple and share the graphic of the differences and options. Ramp legend is a linear ramp-up attack.
Following the example of period 128, we'd get : attack=32; decay=22; sustain=42; rlease=32.
the picture below is related to the ATTACK stage only.

More soon to come !



void adsr_calculation()
{
  uint16_t b = period >> 1;  // These operations help us achieve a cheap aproximation
  uint16_t a = b >> 3;  // of division by 3 (?!) with a loss of bits/precision, but weighed 
  //  enough for what we need, regarding the fact we wrap-up with  a modulo operator for
  //   the last variable sustain- a "greatest-integer function" of sorts .
 
 /*
 By combining the terms in an obvious manner we can reduce the number of operations:
   
   a = (period >> 2) + (period >> 4) 
   b += (b >> 4)
   b += (b >> 8)
   b += (b >> 16)
   There are more exciting ways to calculate division and remainders.
       b * 3 = shift left 1 bit and then add b
*/

  attack  = period >> 2; 
  decay   = (a <<1)+(a>>1)+(a>>2);
  rlease  = period >> 2;
  sustain = period -(attack + rlease + decay);
  // roughly the same as 
  // sustain = period %(attack + rlease + decay);
  led =!led;    //toggle led
  /* Serial.println ("a");
   Serial.println (a);
   Serial.println ("b");
   Serial.println (b);
   Serial.println ("attack");
   Serial.println (attack);
   Serial.println ("decay");
   Serial.println (decay);
   Serial.println ("sustain");
   Serial.println (sustain);
   Serial.println ("rlease");
   Serial.println (rlease);
   */
}

Regarding REAL division by three



// Crazy as this might sound, but the method below indeed does divide by 3. 
// All it needs for doing so is a single 64 bit multiplication and a shift 
// (multiplications might be 3 to 4 times faster than divisions 
// on your CPU). In a 64 bit application this code will be a lot faster than 
// in a 32 bit application (in a 32 bit application multiplying two 64 bit 
// numbers take 3 multiplications and 3 additions on 32 bit values) 
// - however, it might be still faster than a division on a 32 bit machine.
// It only works for constant numbers. Why ?!
// You always need to know the magic number (here 0xaaaaaaab, 
// 0b1010 1010 1010 1010 1010 1010 1010 1011 ; 2,863,311,531 decimal
// and the correct operations after the multiplication (shifts and/or additions 
// in most cases)and both is different depending on the number you want to divide// by (and to calculate both take too much CPU time, on the fly (that would be 
// slower than  hardware division). However, it's easy for a compiler to 
// calculate these during compile time 
static inline uint32_t div3 (
uint32_t bdivided
) {
  return (uint32_t)(((uint64_t)0xaaaaaaabULL * bdivided) >> 33);
}
void setup() {
  // put your setup code here, to run once:
  Serial.begin (115200);
}

void loop() {
  // put your main code here, to run repeatedly: 
  uint32_t test=1000;
  uint32_t avar=div3(test);
  Serial.println(avar);
  delay(500);
}

No comments:

Post a Comment

Feel free to contact me with any suggestions, doubts or requests.

Bless