https://forum.pjrc.com/threads/27806-Clicking-envelope-with-Audio-Librarydds
@@ -33,19 +33,26 @@ | |||
#define STATE_DECAY 4 | |||
#define STATE_SUSTAIN 5 | |||
#define STATE_RELEASE 6 | |||
#define STATE_FORCED 7 | |||
void AudioEffectEnvelope::noteOn(void) | |||
{ | |||
__disable_irq(); | |||
mult_hires = 0; | |||
count = delay_count; | |||
if (count > 0) { | |||
state = STATE_DELAY; | |||
inc_hires = 0; | |||
} else { | |||
state = STATE_ATTACK; | |||
count = attack_count; | |||
inc_hires = 0x40000000 / (int32_t)count; | |||
if (state == STATE_IDLE || state == STATE_DELAY || release_forced_count == 0) { | |||
mult_hires = 0; | |||
count = delay_count; | |||
if (count > 0) { | |||
state = STATE_DELAY; | |||
inc_hires = 0; | |||
} else { | |||
state = STATE_ATTACK; | |||
count = attack_count; | |||
inc_hires = 0x40000000 / (int32_t)count; | |||
} | |||
} else if (state != STATE_FORCED) { | |||
state = STATE_FORCED; | |||
count = release_forced_count; | |||
inc_hires = (-mult_hires) / (int32_t)count; | |||
} | |||
__enable_irq(); | |||
} | |||
@@ -53,7 +60,7 @@ void AudioEffectEnvelope::noteOn(void) | |||
void AudioEffectEnvelope::noteOff(void) | |||
{ | |||
__disable_irq(); | |||
if (state != STATE_IDLE) { | |||
if (state != STATE_IDLE && state != STATE_FORCED) { | |||
state = STATE_RELEASE; | |||
count = release_count; | |||
inc_hires = (-mult_hires) / (int32_t)count; | |||
@@ -112,6 +119,17 @@ void AudioEffectEnvelope::update(void) | |||
*p++ = 0; | |||
} | |||
break; | |||
} else if (state == STATE_FORCED) { | |||
mult_hires = 0; | |||
count = delay_count; | |||
if (count > 0) { | |||
state = STATE_DELAY; | |||
inc_hires = 0; | |||
} else { | |||
state = STATE_ATTACK; | |||
count = attack_count; | |||
inc_hires = 0x40000000 / (int32_t)count; | |||
} | |||
} else if (state == STATE_DELAY) { | |||
state = STATE_ATTACK; | |||
count = attack_count; |
@@ -37,12 +37,13 @@ class AudioEffectEnvelope : public AudioStream | |||
public: | |||
AudioEffectEnvelope() : AudioStream(1, inputQueueArray) { | |||
state = 0; | |||
delay(0.0); // default values... | |||
attack(1.5); | |||
hold(0.5); | |||
decay(15.0); | |||
sustain(0.667); | |||
release(30.0); | |||
delay(0.0f); // default values... | |||
attack(10.5f); | |||
hold(2.5f); | |||
decay(35.0f); | |||
sustain(0.5f); | |||
release(300.0f); | |||
releaseNoteOn(5.0f); | |||
} | |||
void noteOn(); | |||
void noteOff(); | |||
@@ -69,6 +70,10 @@ public: | |||
release_count = milliseconds2count(milliseconds); | |||
if (release_count == 0) release_count = 1; | |||
} | |||
void releaseNoteOn(float milliseconds) { | |||
release_forced_count = milliseconds2count(milliseconds); | |||
if (release_count == 0) release_count = 1; | |||
} | |||
using AudioStream::release; | |||
virtual void update(void); | |||
private: | |||
@@ -80,7 +85,7 @@ private: | |||
} | |||
audio_block_t *inputQueueArray[1]; | |||
// state | |||
uint8_t state; // idle, delay, attack, hold, decay, sustain, release | |||
uint8_t state; // idle, delay, attack, hold, decay, sustain, release, forced | |||
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 | |||
@@ -92,6 +97,7 @@ private: | |||
uint16_t decay_count; | |||
int32_t sustain_mult; | |||
uint16_t release_count; | |||
uint16_t release_forced_count; | |||
}; | |||
@@ -2383,13 +2383,13 @@ double s_freq = .0625;</p> | |||
default is zero, for no delay. | |||
</p> | |||
<p class=func><span class=keyword>attack</span>(milliseconds);</p> | |||
<p class=desc>Set the attack time. The default is 1.5 milliseconds. | |||
<p class=desc>Set the attack time. The default is 10.5 milliseconds. | |||
</p> | |||
<p class=func><span class=keyword>hold</span>(milliseconds);</p> | |||
<p class=desc>Set the hold time. The default is 0.5 milliseconds. | |||
<p class=desc>Set the hold time. The default is 2.5 milliseconds. | |||
</p> | |||
<p class=func><span class=keyword>decay</span>(milliseconds);</p> | |||
<p class=desc>Set the decay time. The default is 15 milliseconds. | |||
<p class=desc>Set the decay time. The default is 35 milliseconds. | |||
</p> | |||
<p class=func><span class=keyword>sustain</span>(level);</p> | |||
<p class=desc>Set the sustain level. The range is 0 to 1.0. The | |||
@@ -2397,7 +2397,15 @@ double s_freq = .0625;</p> | |||
until noteOff() is called. | |||
</p> | |||
<p class=func><span class=keyword>release</span>(milliseconds);</p> | |||
<p class=desc>Set the release time. The default is 30 millisecond. | |||
<p class=desc>Set the release time. The default is 300 millisecond. | |||
</p> | |||
<p class=func><span class=keyword>releaseNoteOn</span>(milliseconds);</p> | |||
<p class=desc>Set a quick release time to be used when a new note is | |||
started while the envelop is in any state passing the signal. | |||
This will add latency before your new attack phase begins, so | |||
short times are recommended. Zero may be used to completely | |||
disable this feature (never extra latency). Longer times help | |||
reduce clicks or pops. The default is 5 millisecond. | |||
</p> | |||
<h3>Examples</h3> | |||
<p class=exam>File > Examples > Audio > Synthesis > PlaySynthMusic |
@@ -116,6 +116,7 @@ hold KEYWORD2 | |||
decay KEYWORD2 | |||
sustain KEYWORD2 | |||
release KEYWORD2 | |||
releaseNoteOn KEYWORD2 | |||
inputLevel KEYWORD2 | |||
inputSelect KEYWORD2 | |||
muteHeadphone KEYWORD2 |