@@ -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; |