Unified · Split
| @@ -70,7 +70,7 @@ typedef enum oBool · 69 unmodified lines | ||
| 70 | 70 | #define TWO_TO_31 2147483648.0f |
| 71 | 71 | #define INV_TWO_TO_31 0.000000000465661f |
| 72 | 72 | |
| 73 | −// Erbe shaper | |
| 73 | +// Jones shaper | |
| 74 | 74 | float LEAF_shaper (float input, float m_drive); |
| 75 | 75 | float LEAF_reedTable (float input, float offset, float slope); |
| 76 | 76 | |
| @@ -46,7 +46,7 @@ typedef enum TableName · 45 unmodified lines | ||
| 46 | 46 | NUM_TABLES |
| 47 | 47 | } TableName; |
| 48 | 48 | |
| 49 | −// mtof lookup table based on input range [0.0,1.0) in 4096 increments - midi frequency values scaled between m25 and m134 (as done in previous code) | |
| 49 | +// mtof lookup table based on input range [0.0,1.0) in 4096 increments - midi frequency values scaled between m25 and m134 (from the Snyderphonics DrumBox code) | |
| 50 | 50 | |
| 51 | 51 | extern const float exp_decay[EXP_DECAY_TABLE_SIZE]; |
| 52 | 52 | extern const float attack_decay_inc[ATTACK_DECAY_INC_TABLE_SIZE]; |
| @@ -121,7 +121,7 @@ void t808Hihat_setOscNoiseMix(t808Hihat* const hihat, float oscNoiseMix) { · 120 unmodified lines | ||
| 121 | 121 | float t808Hihat_tick(t808Hihat* const hihat) { |
| 122 | 122 | |
| 123 | 123 | float sample = 0.0f; |
| 124 | − float gainScale = 0.1666f; | |
| 124 | + float gainScale = 0.3f; | |
| 125 | 125 | |
| 126 | 126 | for (int i = 0; i < 6; i++) |
| 127 | 127 | { |
| @@ -130,16 +130,15 @@ float t808Hihat_tick(t808Hihat* const hihat) { · 2 unmodified lines | ||
| 130 | 130 | |
| 131 | 131 | sample *= gainScale; |
| 132 | 132 | |
| 133 | − sample = (hihat->oscNoiseMix * sample) + ((1.0f-hihat->oscNoiseMix) * (0.8f * tNoise_tick(&hihat->n))); | |
| 133 | + sample = (hihat->oscNoiseMix * sample) + ((1.0f-hihat->oscNoiseMix) * (tNoise_tick(&hihat->n))); | |
| 134 | 134 | |
| 135 | 135 | sample = tSVF_tick(&hihat->bandpassOsc, sample); |
| 136 | 136 | |
| 137 | − sample *= tEnvelope_tick(&hihat->envGain); | |
| 138 | − | |
| 139 | − sample = 0.85f * LEAF_clip(0.0f, tHighpass_tick(&hihat->highpass, sample), 1.0f); | |
| 140 | − | |
| 141 | − sample += 0.15f * tEnvelope_tick(&hihat->envStick) * tSVF_tick(&hihat->bandpassStick, tNoise_tick(&hihat->stick)); | |
| 142 | − | |
| 137 | + float myGain = tEnvelope_tick(&hihat->envGain); | |
| 138 | + sample *= (myGain*myGain);//square the output gain envelope | |
| 139 | + sample = tHighpass_tick(&hihat->highpass, sample); | |
| 140 | + sample += ((0.5f * tEnvelope_tick(&hihat->envStick)) * tSVF_tick(&hihat->bandpassStick, tNoise_tick(&hihat->stick))); | |
| 141 | + | |
| 143 | 142 | return sample; |
| 144 | 143 | } |
| 145 | 144 | |
| @@ -158,16 +157,23 @@ void t808Hihat_setOscBandpassFreq(t808Hihat* const hihat, float freq) · 12 unmodified lines | ||
| 158 | 157 | tSVF_setFreq(&hihat->bandpassOsc,freq); |
| 159 | 158 | } |
| 160 | 159 | |
| 160 | +void t808Hihat_setStickBandPassFreq(t808Hihat* const hihat, float freq) | |
| 161 | +{ | |
| 162 | + tSVF_setFreq(&hihat->bandpassStick,freq); | |
| 163 | +} | |
| 164 | + | |
| 161 | 165 | |
| 162 | 166 | void t808Hihat_setOscFreq(t808Hihat* const hihat, float freq) |
| 163 | 167 | { |
| 164 | − tSquare_setFreq(&hihat->p[0], 2.0f * freq); | |
| 165 | − tSquare_setFreq(&hihat->p[1], 3.00f * freq); | |
| 166 | − tSquare_setFreq(&hihat->p[2], 4.16f * freq); | |
| 167 | − tSquare_setFreq(&hihat->p[3], 5.43f * freq); | |
| 168 | − tSquare_setFreq(&hihat->p[4], 6.79f * freq); | |
| 169 | − tSquare_setFreq(&hihat->p[5], 8.21f * freq); | |
| 170 | − | |
| 168 | + //if (freq < 5600.0f) //to avoid aliasing (for some reason high frequency settings here cause hard faults) | |
| 169 | + { | |
| 170 | + tSquare_setFreq(&hihat->p[0], 2.0f * freq); | |
| 171 | + tSquare_setFreq(&hihat->p[1], 3.00f * freq); | |
| 172 | + tSquare_setFreq(&hihat->p[2], 4.16f * freq); | |
| 173 | + tSquare_setFreq(&hihat->p[3], 5.43f * freq); | |
| 174 | + tSquare_setFreq(&hihat->p[4], 6.79f * freq); | |
| 175 | + tSquare_setFreq(&hihat->p[5], 8.21f * freq); | |
| 176 | + } | |
| 171 | 177 | } |
| 172 | 178 | |
| 173 | 179 | void t808Hihat_init(t808Hihat* const hihat) |
| @@ -181,11 +187,11 @@ void t808Hihat_init(t808Hihat* const hihat) · 7 unmodified lines | ||
| 181 | 187 | tNoise_init(&hihat->n, WhiteNoise); |
| 182 | 188 | |
| 183 | 189 | // need to fix SVF to be generic |
| 184 | − tSVF_init(&hihat->bandpassStick, SVFTypeBandpass,2500.0,1.5f); | |
| 185 | − tSVF_init(&hihat->bandpassOsc, SVFTypeBandpass,3500,0.5f); | |
| 190 | + tSVF_init(&hihat->bandpassStick, SVFTypeBandpass,2500.0,1.2f); | |
| 191 | + tSVF_init(&hihat->bandpassOsc, SVFTypeBandpass,3500,0.3f); | |
| 186 | 192 | |
| 187 | − tEnvelope_init(&hihat->envGain, 5.0f, 50.0f, OFALSE); | |
| 188 | − tEnvelope_init(&hihat->envStick, 5.0f, 15.0f, OFALSE); | |
| 193 | + tEnvelope_init(&hihat->envGain, 0.0f, 50.0f, OFALSE); | |
| 194 | + tEnvelope_init(&hihat->envStick, 0.0f, 4.0f, OFALSE); | |
| 189 | 195 | |
| 190 | 196 | tHighpass_init(&hihat->highpass, 7000.0f); |
| 191 | 197 | |
| @@ -427,7 +427,7 @@ float tSawtooth_tick(tSawtooth* const c) · 426 unmodified lines | ||
| 427 | 427 | w = ((20480.0f - c->freq) * INV_10240); |
| 428 | 428 | out = (c->table[T10240][idx] * w) + (c->table[T20480][idx] * (1.0f - w)); |
| 429 | 429 | } |
| 430 | − else | |
| 430 | + else if (c->freq <= 24000.0f) | |
| 431 | 431 | { |
| 432 | 432 | out = c->table[T20480][idx]; |
| 433 | 433 | } |
| @@ -557,7 +557,7 @@ float tTriangle_tick(tTriangle* const c) · 123 unmodified lines | ||
| 557 | 557 | w = ((20480.0f - c->freq) * INV_10240); |
| 558 | 558 | out = (c->table[T10240][idx] * w) + (c->table[T20480][idx] * (1.0f - w)); |
| 559 | 559 | } |
| 560 | − else | |
| 560 | + else if (c->freq <= 24000.0f) | |
| 561 | 561 | { |
| 562 | 562 | out = c->table[T20480][idx]; |
| 563 | 563 | } |
| @@ -622,8 +622,9 @@ float tSquare_tick(tSquare* const c) · 58 unmodified lines | ||
| 622 | 622 | |
| 623 | 623 | float out = 0.0f; |
| 624 | 624 | float w = 0.0f; |
| 625 | + | |
| 625 | 626 | int idx = (int)(c->phase * c->tsize); |
| 626 | − | |
| 627 | + | |
| 627 | 628 | // Wavetable synthesis |
| 628 | 629 | |
| 629 | 630 | if (c->freq <= 20.0f) |
| @@ -680,7 +681,7 @@ float tSquare_tick(tSquare* const c) · 50 unmodified lines | ||
| 680 | 681 | w = ((20480.0f - c->freq) * INV_10240); |
| 681 | 682 | out = (c->table[T10240][idx] * w) + (c->table[T20480][idx] * (1.0f - w)); |
| 682 | 683 | } |
| 683 | − else | |
| 684 | + else if (c->freq <= 24000.0f) | |
| 684 | 685 | { |
| 685 | 686 | out = c->table[T20480][idx]; |
| 686 | 687 | } |
| @@ -330,8 +330,8 @@ int tEnvelope_setDecay(tEnvelope* const env, float decay) · 329 unmodified lines | ||
| 330 | 330 | { |
| 331 | 331 | int32_t decayIndex; |
| 332 | 332 | |
| 333 | − if (decay < 0.0f) { | |
| 334 | − decayIndex = 0.0f; | |
| 333 | + if (decay <= 1.0f) { | |
| 334 | + decayIndex = 1; | |
| 335 | 335 | } else if (decay < 8192.0f) { |
| 336 | 336 | decayIndex = ((int32_t)(decay * 8.0f)) - 1; |
| 337 | 337 | } else { |
| @@ -3,12 +3,12 @@ Previously named OOPS, LEAF is a C library for Audio synthesis and processing cr · 2 unmodified lines | ||
| 3 | 3 | |
| 4 | 4 | The library consists of a set of high-level audio synthesis components (Oscillators, Filters, Envelopes, Delays, Reverbs, and other Utilities). |
| 5 | 5 | |
| 6 | −Our primary use case is embedded audio computing on 32-bit ARM microcontrollers that can run "bare-metal" (without an OS), such as the STM32f4 and STM32f7. The code, however, is general enough to be used in many other situations as well. We have included a JUCE VST/AU generating template to test the library (2), and the python script we use to generate wavetables. | |
| 6 | +Our primary use case is embedded audio computing on 32-bit ARM microcontrollers that can run "bare-metal" (without an OS), such as the STM32f4, STM32f7, and STM32H7. The code, however, is general enough to be used in many other situations as well. We have included a JUCE VST/AU generating template to test the library (2), and the python script we use to generate wavetables. | |
| 7 | 7 | |
| 8 | 8 | Most of these algorithms are sourced from other projects, especially the STK (Sound Toolkit) library and various discussions on the music-DSP mailing list. We also owe a lot to open source computer programming languages, such as C-sound, ChucK, PureData, and Supercollider. |
| 9 | 9 | |
| 10 | 10 | Other interesting projects to check out that similarly target embedded applicatons are: TeensyAudio (C++), Hoxton Owl (C++), Axoloti (C), and Mutable Instruments (C++). |
| 11 | 11 | |
| 12 | −(1) Dynamic allocation is avoided to meet the needs of a larger number of embedded applications. Embedded developers often utilize architectures that don't fully support stdlib memory allocation functions like calloc, malloc, and free. | |
| 12 | +(1) Use of standard malloc and calloc are avoided, and a custom memory pool implementation is included instead, allowing dynamic memory allocation/deallocation within a fixed block size. | |
| 13 | 13 | |
| 14 | 14 | (2) The template features an easily reconfigurable UI and simple block and tick setup to test the library components. Of course, if you intend to use the provided JUCE plugin project, you need to get JUCE and the Projucer ( https://www.juce.com/get-juce ). Check out the first tutorial to get started - it's fun an easy! If you intend to include the LEAF framework in your own C++ project using JUCE or other platforms, you will probably need to rename each source file from .c to .cpp. This should be straightforward. Contact the developer if you have any troubles (mrmulshine@gmail.com). |