| @@ -1,5 +1,5 @@ | |||
| /* Audio Library for Teensy 3.X | |||
| * Copyright (c) 2014, Paul Stoffregen, paul@pjrc.com | |||
| * Copyright (c) 2017, Paul Stoffregen, paul@pjrc.com | |||
| * | |||
| * Development of this audio library was funded by PJRC.COM, LLC by sales of | |||
| * Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop | |||
| @@ -37,15 +37,15 @@ | |||
| void AudioEffectEnvelope::noteOn(void) | |||
| { | |||
| __disable_irq(); | |||
| mult = 0; | |||
| mult_hires = 0; | |||
| count = delay_count; | |||
| if (count > 0) { | |||
| state = STATE_DELAY; | |||
| inc = 0; | |||
| inc_hires = 0; | |||
| } else { | |||
| state = STATE_ATTACK; | |||
| count = attack_count; | |||
| inc = (0x10000 / count) >> 3; | |||
| inc_hires = 0x40000000 / (int32_t)count; | |||
| } | |||
| __enable_irq(); | |||
| } | |||
| @@ -53,10 +53,11 @@ void AudioEffectEnvelope::noteOn(void) | |||
| void AudioEffectEnvelope::noteOff(void) | |||
| { | |||
| __disable_irq(); | |||
| state = STATE_RELEASE; | |||
| count = release_count; | |||
| mult = sustain_mult; | |||
| inc = (-mult / ((int32_t)count << 3)); | |||
| if (state != STATE_IDLE) { | |||
| state = STATE_RELEASE; | |||
| count = release_count; | |||
| inc_hires = (-mult_hires) / (int32_t)count; | |||
| } | |||
| __enable_irq(); | |||
| } | |||
| @@ -82,24 +83,24 @@ void AudioEffectEnvelope::update(void) | |||
| count = hold_count; | |||
| if (count > 0) { | |||
| state = STATE_HOLD; | |||
| mult = 0x10000; | |||
| inc = 0; | |||
| mult_hires = 0x40000000; | |||
| inc_hires = 0; | |||
| } else { | |||
| count = decay_count; | |||
| state = STATE_DECAY; | |||
| inc = ((sustain_mult - 0x10000) / ((int32_t)count << 3)); | |||
| count = decay_count; | |||
| inc_hires = (sustain_mult - 0x40000000) / (int32_t)count; | |||
| } | |||
| continue; | |||
| } else if (state == STATE_HOLD) { | |||
| state = STATE_DECAY; | |||
| count = decay_count; | |||
| inc = ((sustain_mult - 0x10000) / (int32_t)count) >> 3; | |||
| inc_hires = (sustain_mult - 0x40000000) / (int32_t)count; | |||
| continue; | |||
| } else if (state == STATE_DECAY) { | |||
| state = STATE_SUSTAIN; | |||
| count = 0xFFFF; | |||
| mult = sustain_mult; | |||
| inc = 0; | |||
| mult_hires = sustain_mult; | |||
| inc_hires = 0; | |||
| } else if (state == STATE_SUSTAIN) { | |||
| count = 0xFFFF; | |||
| } else if (state == STATE_RELEASE) { | |||
| @@ -114,11 +115,14 @@ void AudioEffectEnvelope::update(void) | |||
| } else if (state == STATE_DELAY) { | |||
| state = STATE_ATTACK; | |||
| count = attack_count; | |||
| inc = (0x10000 / count) >> 3; | |||
| inc_hires = 0x40000000 / count; | |||
| continue; | |||
| } | |||
| } | |||
| // process 8 samples, using only mult and inc | |||
| int32_t mult = mult_hires >> 14; | |||
| int32_t inc = inc_hires >> 17; | |||
| // process 8 samples, using only mult and inc (16 bit resolution) | |||
| sample12 = *p++; | |||
| sample34 = *p++; | |||
| sample56 = *p++; | |||
| @@ -148,6 +152,9 @@ void AudioEffectEnvelope::update(void) | |||
| *p++ = sample34; | |||
| *p++ = sample56; | |||
| *p++ = sample78; | |||
| // adjust the long-term gain using 30 bit resolution (fix #102) | |||
| // https://github.com/PaulStoffregen/Audio/issues/102 | |||
| mult_hires += inc_hires; | |||
| count--; | |||
| } | |||
| transmit(block); | |||
| @@ -1,5 +1,5 @@ | |||
| /* Audio Library for Teensy 3.X | |||
| * Copyright (c) 2014, Paul Stoffregen, paul@pjrc.com | |||
| * Copyright (c) 2017, Paul Stoffregen, paul@pjrc.com | |||
| * | |||
| * Development of this audio library was funded by PJRC.COM, LLC by sales of | |||
| * Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop | |||
| @@ -51,20 +51,23 @@ public: | |||
| } | |||
| void attack(float milliseconds) { | |||
| attack_count = milliseconds2count(milliseconds); | |||
| if (attack_count == 0) attack_count = 1; | |||
| } | |||
| void hold(float milliseconds) { | |||
| hold_count = milliseconds2count(milliseconds); | |||
| } | |||
| void decay(float milliseconds) { | |||
| decay_count = milliseconds2count(milliseconds); | |||
| if (decay_count == 0) decay_count = 1; | |||
| } | |||
| void sustain(float level) { | |||
| if (level < 0.0) level = 0; | |||
| else if (level > 1.0) level = 1.0; | |||
| sustain_mult = level * 65536.0; | |||
| sustain_mult = level * 1073741824.0; | |||
| } | |||
| void release(float milliseconds) { | |||
| release_count = milliseconds2count(milliseconds); | |||
| if (release_count == 0) release_count = 1; | |||
| } | |||
| using AudioStream::release; | |||
| virtual void update(void); | |||
| @@ -72,15 +75,16 @@ private: | |||
| uint16_t milliseconds2count(float milliseconds) { | |||
| if (milliseconds < 0.0) milliseconds = 0.0; | |||
| uint32_t c = ((uint32_t)(milliseconds*SAMPLES_PER_MSEC)+7)>>3; | |||
| if (c > 1103) return 1103; // allow up to 200 ms | |||
| if (c > 65535) c = 65535; // allow up to 11.88 seconds | |||
| return c; | |||
| } | |||
| audio_block_t *inputQueueArray[1]; | |||
| // state | |||
| uint8_t state; // idle, delay, attack, hold, decay, sustain, release | |||
| uint16_t count; // how much time remains in this state, in 8 sample units | |||
| int32_t mult; // attenuation, 0=off, 0x10000=unity gain | |||
| int32_t inc; // amount to change mult on each sample | |||
| uint8_t state; // idle, delay, attack, hold, decay, sustain, release | |||
| uint16_t count; // how much time remains in this state, in 8 sample units | |||
| int32_t mult_hires; // attenuation, 0=off, 0x40000000=unity gain | |||
| int32_t inc_hires; // amount to change mult_hires every 8 samples | |||
| // settings | |||
| uint16_t delay_count; | |||
| uint16_t attack_count; | |||