-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAudioEffectIntegrator.h
More file actions
84 lines (78 loc) · 2.41 KB
/
AudioEffectIntegrator.h
File metadata and controls
84 lines (78 loc) · 2.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
// AudioEffectIntegrator - integrating envelope
// An additional Teensy Audio library effect
//
// Implements a simple impulse-response-integrator envelope generator.
//
// Mimics the behaviour of envelopes generated by simple R-C-networks
// as used in analog synthesizers like the TB-303.
//
// noteOn(velocity) triggers the attack but ties the signal to the given velocity (just adds enough energy to keep it)
//
// pulse(velocity) triggers the attack but adds to the existing energy.
//
// The implementation uses two "energy buckets":
// The attack bucket is filled by noteOn() or pulse() and transfers energy to the decay bucket (usually very fast).
// The decay bucket is filled by transfers from the attack bucket and drains energy to a damper (usually slow).
// The incoming audio is just attenuated according to the decay bucket energy.
//
class AudioEffectIntegrator : public AudioStream
{
public:
AudioEffectIntegrator() : AudioStream(1, inputQueueArray) {
attack(0.01f);
decay(1.f);
}
using AudioStream::release;
void noteOn(float velocity)
{
__disable_irq();
energy_in=velocity-energy;
__enable_irq();
}
void pulse(float velocity)
{
__disable_irq();
energy_in+=velocity;
if(energy+energy_in>1.f) energy_in=1.f-energy;
__enable_irq();
}
// set attack time (time until 9/10 of energy is transfered)
void attack(float milliseconds) {
__disable_irq();
if(milliseconds<=0.f)
attack_valve=0.f;
else
attack_valve = pow(0.1,1.f/(AUDIO_SAMPLE_RATE_EXACT*0.001f*milliseconds));
__enable_irq();
}
// set decay time (time until 9/10 of energy is drained)
void decay(float milliseconds) {
__disable_irq();
if(milliseconds<=0.f)
decay_valve=0.f;
else
decay_valve = pow(0.1,1.f/(AUDIO_SAMPLE_RATE_EXACT*0.001f*milliseconds));
__enable_irq();
}
virtual void update(void) {
int16_t *p, *end;
audio_block_t* block = receiveWritable();
if (!block) return;
p = (int16_t*)(block->data);
end = p + AUDIO_BLOCK_SAMPLES;
float attack_flow=1.-attack_valve;
while (p < end) {
// TODO fast integer implementation.
float de=energy_in*attack_flow;
energy = energy*decay_valve + de;
energy_in = energy_in - de;
(*p++)*=energy;
}
transmit(block);
release(block);
}
private:
audio_block_t *inputQueueArray[1];
float energy_in=0.f,energy=0.f;
float attack_valve, decay_valve;
};