//----------------------------------------------------------------
// Variable
//----------------------------------------------------------------
uint16_t phase_;
uint16_t phase_increment;
uint16_t ramp_start_;
uint16_t ramp_end_;
uint8_t ramp_a_;
uint8_t ramp_b_;
uint16_t value_;
//-----------------------------------------------------------------
// Envelope Phase
//-----------------------------------------------------------------
if (adsr1_phase == ATTACK)
{
// load 7Bit attack_value1 from encoder (0-127) and convert to 16Bit phase_increment
phase_increment = pgm_read_word (&(lut_res_env_portamento_increments[attack_value1]));
ramp_start_ = 0;
ramp_end_ = 65535;
ramp_a_ = 0;
ramp_b_ = 255;
envelope();
}
else if (adsr1_phase == DECAY)
{
// load 7Bit decay_value1 from encoder (0-127) and convert to 16Bit phase_increment
phase_increment = pgm_read_word (&(lut_res_env_portamento_increments[decay_value1]));
// load 7Bit sustain level from encoder (0-127) and convert to 16Bit phase_increment
ramp_start_ = pgm_read_word (&(sustain_level[sustain_value1]));
ramp_end_ = 65535;
ramp_a_ = 255;
ramp_b_ = 0;
envelope();
release_level = value_;
}
else if (adsr1_phase == RELEASE)
{
// load 7Bit release_value1 from encoder (0-127) and convert to 16Bit phase_increment
phase_increment = pgm_read_word (&(lut_res_env_portamento_increments[relaese_value1]));
ramp_start_ = 0;
ramp_end_ = release_level;
ramp_a_ = 255;
ramp_b_ = 0;
envelope();
}
if (midi_gate_flag == 0)
{
if (adsr1_phase < 3)
{
adsr1_phase = RELEASE;
phase_ = 0;
}
}
//-------------------------------------------------------------------------
// Envelope
//-------------------------------------------------------------------------
void envelope(void)
{
// increment 16Bit env_ramp
phase_ += phase_increment;
// check end of attack phase
if (phase_ < phase_increment)
{
// set next envelope phase
adsr1_phase ++;
phase_ = 0;
}
else
{
// interpolate 8Bit env_expo table with 16Bit phase_
uint8_t step = InterpolateSample(wav_res_env_expo, phase_);
// calc 16Bit envelope value
uint16_t ramp_expo = U8MixU16(ramp_a_, ramp_b_, step);
value_ = ramp_start_ + ((uint32_t)(ramp_end_ - ramp_start_) * ramp_expo >> 16);
// set envelope_out
adsr1_out = value_;
}
}
//---------------------------------------------------------------------------
// inline function and tables
//---------------------------------------------------------------------------
static inline uint8_t InterpolateSample(
//const uint8_t* table, uint16_t phase) {
const uint8_t table[], uint16_t phase) {
uint8_t result;
uint8_t work;
asm(
"movw r30, %A2" "\n\t" // copy base address to r30:r31
"add r30, %B3" "\n\t" // increment table address by phaseH
"adc r31, r1" "\n\t" // just carry
"mov %1, %A3" "\n\t" // move phaseL to working register
"lpm %0, z+" "\n\t" // load sample[n]
"lpm r1, z+" "\n\t" // load sample[n+1]
"mul %1, r1" "\n\t" // multiply second sample by phaseL
"movw r30, r0" "\n\t" // result to accumulator
"com %1" "\n\t" // 255 - phaseL -> phaseL
"mul %1, %0" "\n\t" // multiply first sample by phaseL
"add r30, r0" "\n\t" // accumulate L
"adc r31, r1" "\n\t" // accumulate H
"eor r1, r1" "\n\t" // reset r1 after multiplication
"mov %0, r31" "\n\t" // use sum H as output
: "=r" (result), "=r" (work)
: "r" (table), "r" (phase)
: "r30", "r31"
);
return result;
}
static inline uint16_t U8MixU16(uint8_t a, uint8_t b, uint8_t balance) {
uint16_t result;
asm(
"mul %3, %2" "\n\t" // b * balance
"movw %A0, r0" "\n\t" // to sum
"com %2" "\n\t" // 255 - balance
"mul %1, %2" "\n\t" // a * (255 - balance)
"com %2" "\n\t" // reset balance to its previous value
"add %A0, r0" "\n\t" // add to sum L
"adc %B0, r1" "\n\t" // add to sum H
"eor r1, r1" "\n\t" // reset r1 after multiplication
: "&=r" (result)
: "a" (a), "a" (balance), "a" (b)
);
return result;
}
//-------------------------------------------------------------------------
// Attack increments 16Bit
//-------------------------------------------------------------------------
const uint16_t lut_res_env_portamento_increments[] PROGMEM = {
65535, 18904, 16416, 14304, 12504, 10968, 9647, 8509,
7525, 6672, 5931, 5285, 4719, 4224, 3788, 3405,
3066, 2766, 2500, 2264, 2053, 1865, 1697, 1546,
1411, 1290, 1180, 1082, 993, 912, 839, 773,
713, 658, 608, 562, 521, 483, 448, 416,
387, 360, 335, 313, 292, 272, 255, 238,
223, 209, 196, 184, 172, 162, 152, 143,
135, 127, 119, 113, 106, 100, 95, 90,
85, 80, 76, 72, 68, 64, 61, 58,
55, 52, 50, 47, 45, 43, 41, 39,
37, 35, 33, 32, 30, 29, 28, 26,
25, 24, 23, 22, 21, 20, 19, 18,
18, 17, 16, 16, 15, 14, 14, 13,
13, 12, 12, 11, 11, 10, 10, 9,
9, 9, 8, 7, 7, 6, 6, 5,
5, 4, 4, 3, 3, 2, 2, 1
};
const uint8_t wav_res_env_expo[] PROGMEM = {
0, 4, 9, 14, 19, 23, 28, 32,
37, 41, 45, 49, 53, 57, 61, 65,
68, 72, 76, 79, 83, 86, 89, 92,
96, 99, 102, 105, 108, 111, 113, 116,
119, 121, 124, 127, 129, 132, 134, 136,
139, 141, 143, 145, 148, 150, 152, 154,
156, 158, 160, 161, 163, 165, 167, 169,
170, 172, 174, 175, 177, 178, 180, 181,
183, 184, 186, 187, 188, 190, 191, 192,
193, 195, 196, 197, 198, 199, 200, 201,
202, 203, 205, 206, 206, 207, 208, 209,
210, 211, 212, 213, 214, 215, 215, 216,
217, 218, 218, 219, 220, 221, 221, 222,
223, 223, 224, 225, 225, 226, 226, 227,
227, 228, 229, 229, 230, 230, 231, 231,
232, 232, 233, 233, 233, 234, 234, 235,
235, 236, 236, 236, 237, 237, 238, 238,
238, 239, 239, 239, 240, 240, 240, 241,
241, 241, 241, 242, 242, 242, 243, 243,
243, 243, 244, 244, 244, 244, 245, 245,
245, 245, 245, 246, 246, 246, 246, 246,
247, 247, 247, 247, 247, 248, 248, 248,
248, 248, 248, 248, 249, 249, 249, 249,
249, 249, 249, 250, 250, 250, 250, 250,
250, 250, 250, 251, 251, 251, 251, 251,
251, 251, 251, 251, 251, 252, 252, 252,
252, 252, 252, 252, 252, 252, 252, 252,
252, 253, 253, 253, 253, 253, 253, 253,
253, 253, 253, 253, 253, 253, 253, 253,
253, 254, 254, 254, 254, 254, 254, 254,
254, 254, 254, 254, 254, 254, 254, 254,
254, 254, 254, 254, 254, 254, 254, 255,
255
};
//-------------------------------------------------------------------------
// Sustain level 16Bit
//-------------------------------------------------------------------------
const uint16_t sustain_level[] PROGMEM = {
1, 11, 33, 65, 106, 157, 218, 287,
366, 454, 550, 655, 769, 891, 1022, 1162,
1310, 1466, 1630, 1803, 1984, 2173, 2370, 2576,
2789, 3011, 3240, 3477, 3723, 3976, 4237, 4506,
4783, 5068, 5360, 5660, 5968, 6284, 6607, 6938,
7277, 7623, 7977, 8338, 8707, 9084, 9468, 9860,
10259, 10666, 11080, 11502, 11931, 12367, 12811, 13263,
13722, 14188, 14661, 15142, 15630, 16126, 16629, 17139,
17657, 18181, 18713, 19253, 19799, 20353, 20914, 21483,
22058, 22641, 23231, 23828, 24432, 25043, 25662, 26288,
26920, 27560, 28207, 28862, 29523, 30191, 30867, 31549,
32239, 32935, 33639, 34350, 35068, 35792, 36524, 37263,
38009, 38762, 39522, 40288, 41062, 41843, 42631, 43425,
44227, 45036, 45851, 46674, 47503, 48339, 49182, 50033,
50889, 51753, 52624, 53502, 54386, 55278, 56176, 57081,
57993, 58912, 59837, 60770, 61709, 62655, 63608, 65535
};