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);
}