Skip to content

Commit

Permalink
Merge pull request #16 from cwrowley/stiff-string
Browse files Browse the repository at this point in the history
Add physical model for string with stiffness
  • Loading branch information
spiricom authored Jan 12, 2024
2 parents 8f8f251 + 80e1a18 commit 1c3fe80
Show file tree
Hide file tree
Showing 2 changed files with 154 additions and 5 deletions.
38 changes: 33 additions & 5 deletions leaf/Inc/leaf-physical.h
Original file line number Diff line number Diff line change
Expand Up @@ -1203,15 +1203,43 @@ void tTString_setPickupAmount (tTString* const bw, Lfloat amoun
Lfloat tReedTable_tanh_tick (tReedTable* const, Lfloat input); //tanh softclip version of reed table - replacing the hard clip in original stk code
void tReedTable_setOffset (tReedTable* const, Lfloat offset);
void tReedTable_setSlope (tReedTable* const, Lfloat slope);

//==============================================================================


//==============================================================================

typedef struct _tStiffString
{
tMempool mempool;
int numModes;
tCycle *osc; // array of oscillators
Lfloat *amplitudes;
Lfloat *outputWeights;
Lfloat freqHz; // the frequency of the whole string, determining delay length

Lfloat stiffness;
Lfloat pluckPos; // the pick position, dividing the string in two, in ratio
Lfloat pickupPos; // the preparation position, dividing the string in two, in ratio
Lfloat decay;
Lfloat decayHighFreq;
Lfloat sampleRate;
Lfloat twoPiTimesInvSampleRate;
} _tStiffString;

typedef _tStiffString* tStiffString;

void tStiffString_init (tStiffString* const, int numModes, LEAF* const leaf);
void tStiffString_initToPool (tStiffString* const, int numModes, tMempool* const);
void tStiffString_free (tStiffString* const);

Lfloat tStiffString_tick(tStiffString* const);
void tStiffString_setStiffness(tStiffString* const, Lfloat newValue);
void tStiffString_setFreq(tStiffString* const, Lfloat newFreq);
void tStiffString_setFreqFast(tStiffString* const, Lfloat newFreq);
void tStiffString_setInitialAmplitudes(tStiffString* const);

#ifdef __cplusplus
}
#endif

#endif // LEAF_PHYSICAL_H_INCLUDED

//==============================================================================


121 changes: 121 additions & 0 deletions leaf/Src/leaf-physical.c
Original file line number Diff line number Diff line change
Expand Up @@ -3678,3 +3678,124 @@ void tReedTable_setSlope (tReedTable* const pm, Lfloat slope)
_tReedTable* p = *pm;
p->slope = slope;
}

/* ============================ */

void tStiffString_init (tStiffString* const pm, int numModes, LEAF* const leaf)
{
tStiffString_initToPool(pm, numModes, &leaf->mempool);
}

void tStiffString_updateOutputWeights(tStiffString const p);

void tStiffString_initToPool (tStiffString* const pm, int numModes, tMempool* const mp)
{
_tMempool* m = *mp;
_tStiffString* p = *pm = (_tStiffString*) mpool_alloc(sizeof(_tStiffString), m);
p->mempool = m;

// initialize variables
p->numModes = numModes;
p->freqHz = 440.0f;
p->stiffness = 0.001f;
p->pluckPos = 0.2f;
p->pickupPos = 0.3f;
p->decay = 0.0001f;
p->decayHighFreq = 0.0003f;
p->sampleRate = m->leaf->sampleRate;
p->twoPiTimesInvSampleRate = m->leaf->twoPiTimesInvSampleRate;

// allocate memory
p->osc = (tCycle *) mpool_alloc(numModes * sizeof(tCycle), m);
for (int i; i < numModes; ++i) {
tCycle_initToPool(&p->osc[i], &m);
}
p->amplitudes = (Lfloat *) mpool_alloc(numModes * sizeof(Lfloat), m);
p->outputWeights = (Lfloat *) mpool_alloc(numModes * sizeof(Lfloat), m);
tStiffString_updateOutputWeights(p);
}

void tStiffString_updateOutputWeights(tStiffString const p)
{
Lfloat x0 = p->pickupPos * 0.5f * PI;
for (int i = 0; i < p->numModes; ++i) {
p->outputWeights[i] = sinf((i + 1) * x0);
}
}

void tStiffString_free (tStiffString* const pm)
{
_tStiffString* p = *pm;

for (int i; i < p->numModes; ++i) {
tCycle_free(&p->osc[i]);
}
mpool_free((char *) p->osc, p->mempool);
mpool_free((char *) p->amplitudes, p->mempool);
mpool_free((char *) p->outputWeights, p->mempool);
mpool_free((char *) p, p->mempool);
}

Lfloat tStiffString_tick (tStiffString* const pm)
{
_tStiffString *p = *pm;
Lfloat sample = 0.0f;
for (int i = 0; i < p->numModes; ++i) {
sample += tCycle_tick(&p->osc[i]) * p->amplitudes[i] * p->outputWeights[i];
int n = i + 1;
Lfloat sig = p->decay + p->decayHighFreq * (n * n);
//amplitudes[i] *= expf(-sig * freqHz * leaf->twoPiTimesInvSampleRate);
sig = LEAF_clip(0.f, sig, 1.f);
p->amplitudes[i] *= 1.0f -sig * p->freqHz * p->twoPiTimesInvSampleRate;
}
return sample;
}

void tStiffString_setStiffness(tStiffString* const pm, Lfloat newValue)
{
tStiffString p = *pm;
p->stiffness = newValue;
}

void tStiffString_setFreq(tStiffString* const pm, Lfloat newFreq)
{
_tStiffString *p = *pm;
p->freqHz = newFreq;
Lfloat kappa_sq = p->stiffness * p->stiffness;
for (int i = 0; i < p->numModes; ++i) {
int n = i + 1;
int n_sq = n * n;
Lfloat sig = p->decay + p->decayHighFreq * n_sq;
Lfloat w0 = n * sqrtf(1.0f + kappa_sq * n_sq);
Lfloat zeta = sig / w0;
Lfloat w = w0 * sqrtf(1.0f - zeta * zeta);
tCycle_setFreq(&p->osc[i], p->freqHz * w);
}
}

void tStiffString_setFreqFast(tStiffString* const pm, Lfloat newFreq)
{
_tStiffString *p = *pm;
p->freqHz = newFreq;
Lfloat kappa_sq = p->stiffness * p->stiffness;
for (int i = 0; i < p->numModes; ++i) {
int n = i + 1;
int n_sq = n * n;
Lfloat sig = p->decay + p->decayHighFreq * n_sq;
Lfloat w0 = n * (1.0f + 0.5f * kappa_sq * n_sq);
Lfloat zeta = sig / w0;
Lfloat w = w0 * (1.0f - 0.5f * zeta * zeta);
tCycle_setFreq(&p->osc[i], p->freqHz * w);
}
}

void tStiffString_setInitialAmplitudes(tStiffString* const mp)
{
_tStiffString* p = *mp;
Lfloat x0 = p->pluckPos * 0.5f * PI;
for (int i = 0; i < p->numModes; ++i) {
int n = i + 1;
float denom = n * n * x0 * (PI - x0);
p->amplitudes[i] = 2.0f * sinf(x0 * n) / denom;
}
}

0 comments on commit 1c3fe80

Please sign in to comment.