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.
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