diff --git a/leaf/Inc/leaf-physical.h b/leaf/Inc/leaf-physical.h index 66cbf31..d0289c5 100644 --- a/leaf/Inc/leaf-physical.h +++ b/leaf/Inc/leaf-physical.h @@ -1260,7 +1260,71 @@ typedef struct _tStiffString void tStiffString_setDecayNoUpdate(tStiffString* const, Lfloat decay); void tStiffString_setDecayHighFreqNoUpdate(tStiffString* const, Lfloat decayHF); + //============================================================================== + /*! + @defgroup tshader tShaker + @ingroup physical + @brief PhISEM class - borrowed from STK + @{ + + @fn void tShaker_init (tShaker* const, Lfloat offset, Lfloat slope, LEAF* const leaf) + @brief Initialize a tShaker to the default mempool of a LEAF instance. + @param shaker A pointer to the tShaker to initialize. + @param leaf A pointer to the leaf instance. + + @fn void tShaker_initToPool (tShaker* const, Lfloat offset, Lfloat slope, tMempool* const) + @brief Initialize a tShaker to a specified mempool. + @param shaker A pointer to the tShaker to initialize. + @param mempool A pointer to the tMempool to use. + + @fn void tShaker_free (tShaker* const) + @brief Free a tShaker from its mempool. + @param shaker A pointer to the tShaker to free. + + @fn Lfloat tShaker_tick (tShaker* const, Lfloat input) + @brief + @param shaker A pointer to the relevant tShaker. + + @fn Lfloat tShaker_excite (tShaker* const, Lfloat energy) + @brief Excite the system with the given energy. + @param shaker A pointer to the relevant tShaker. + + @} */ + + typedef struct _tShaker + { + tMempool mempool; + Lfloat(*rand)(void); + + tNoise noise; + tBiQuad resonator; + + Lfloat energyDecay; + Lfloat soundDecay; + Lfloat probability; + Lfloat gain; + + Lfloat energy; + Lfloat level; + + } _tShaker; + + typedef _tShaker *tShaker; + void tShaker_init(tShaker *const, LEAF *const leaf); + void tShaker_initToPool(tShaker *const, tMempool *const); + void tShaker_free(tShaker *const); + + Lfloat tShaker_tick(tShaker *const); + Lfloat tShaker_excite(tShaker *const, Lfloat energy); + + void tShaker_setEnergyDecay(tShaker *const, Lfloat decay); + void tShaker_setSoundDecay(tShaker *const, Lfloat decay); + void tShaker_setProbability(tShaker *const, Lfloat prob); + void tShaker_setResonance (tShaker *const pm, Lfloat freq, Lfloat radius); + + //============================================================================== + #ifdef __cplusplus } #endif diff --git a/leaf/Src/leaf-physical.c b/leaf/Src/leaf-physical.c index ac47cae..f1e097f 100644 --- a/leaf/Src/leaf-physical.c +++ b/leaf/Src/leaf-physical.c @@ -3985,3 +3985,96 @@ void tStiffString_pluckNoUpdate(tStiffString* const mp, Lfloat amp) } + +/// Shaker model + +void tShaker_init(tShaker* const pm, LEAF* const leaf) +{ + tShaker_initToPool(pm, &leaf->mempool); +} + +void tShaker_initToPool(tShaker* const pm, tMempool* const mp) +{ + _tMempool* m = *mp; + _tShaker* p = *pm = (_tShaker*) mpool_alloc(sizeof(_tShaker), m); + p->mempool = m; + + LEAF* leaf = p->mempool->leaf; + p->rand = leaf->random; + + tBiQuad_initToPool(&p->resonator, mp); + tBiQuad_setResonance(&p->resonator, 4500., 0.99, false); + tNoise_initToPool(&p->noise, WhiteNoise, mp); + + p->energy = 0.0; + p->level = 0.0; + p->energyDecay = 0.98; + p->soundDecay = 0.95; + p->probability = 0.10; +} + +void tShaker_free(tShaker* const pm) +{ + _tShaker* p = *pm; + + mpool_free((char*)p, p->mempool); +} + +Lfloat tShaker_tick(tShaker* const pm) +{ + _tShaker* p = *pm; + + // exponential decay for system energy + p->energy *= p->energyDecay; + + // stochastic particle collision event + if(p->rand() < p->probability) + p->level += p->energy * p->gain; + + // exponential decay for sound + p->level *= p->soundDecay; + + // add noise, filter + Lfloat sample = p->level * tNoise_tick(&p->noise); + Lfloat output = tBiQuad_tick(&p->resonator, sample); + + return output; +} + +Lfloat tShaker_excite (tShaker* const pm, Lfloat energy) +{ + _tShaker* p = *pm; + + // excite the system + p->energy += energy; + return p->energy; +} + +void tShaker_setEnergyDecay (tShaker *const pm, Lfloat decay) +{ + _tShaker* p = *pm; + p->energyDecay = decay; +} + +void tShaker_setSoundDecay (tShaker *const pm, Lfloat decay) +{ + _tShaker* p = *pm; + p->soundDecay = decay; +} + +void tShaker_setProbability (tShaker *const pm, Lfloat prob) +{ + _tShaker* p = *pm; + + // set gain correction for number of particles + float nBeans = 1024.0 * prob; + float gain = (log(nBeans) / log(4.)) * (40/nBeans); + + p->probability = prob; + p->gain = gain; +} + +void tShaker_setResonance (tShaker *const pm, Lfloat freq, Lfloat radius) { + _tShaker* p = *pm; + tBiQuad_setResonance(&p->resonator, freq, radius, false); +}