ref: 9171062fdeebb30bfe9ef1e5c5c688db55f8aac9
dir: /LEAF/Src/leaf-oscillator.c/
/*============================================================================== leaf-oscillator.c Created: 20 Jan 2017 12:00:58pm Author: Michael R Mulshine ==============================================================================*/ #if _WIN32 || _WIN64 #include "..\Inc\leaf-wavetables.h" #include "..\Inc\leaf-oscillator.h" #include "..\leaf.h" #else #include "../Inc/leaf-wavetables.h" #include "../Inc/leaf-oscillator.h" #include "../leaf.h" #endif void tNeuronSampleRateChanged(tNeuron* n) { } void tNeuron_init(tNeuron* const n) { tPoleZero_init(&n->f); tPoleZero_setBlockZero(&n->f, 0.99f); n->timeStep = 1.0f / 50.0f; n->current = 0.0f; // 100.0f for sound n->voltage = 0.0f; n->mode = NeuronNormal; n->P[0] = 0.0f; n->P[1] = 0.0f; n->P[2] = 1.0f; n->V[0] = -12.0f; n->V[1] = 115.0f; n->V[2] = 10.613f; n->gK = 36.0f; n->gN = 120.0f; n->gL = 0.3f; n->C = 1.0f; n->rate[2] = n->gL/n->C; } void tNeuron_free(tNeuron* const n) { tPoleZero_free(&n->f); leaf_free(n); } void tNeuron_reset(tNeuron* const n) { tPoleZero_setBlockZero(&n->f, 0.99f); n->timeStep = 1.0f / 50.0f; n->current = 0.0f; // 100.0f for sound n->voltage = 0.0f; n->mode = NeuronNormal; n->P[0] = 0.0f; n->P[1] = 0.0f; n->P[2] = 1.0f; n->V[0] = -12.0f; n->V[1] = 115.0f; n->V[2] = 10.613f; n->gK = 36.0f; n->gN = 120.0f; n->gL = 0.3f; n->C = 1.0f; n->rate[2] = n->gL/n->C; } void tNeuron_setV1(tNeuron* const n, float V1) { n->V[0] = V1; } void tNeuron_setV2(tNeuron* const n, float V2) { n->V[1] = V2; } void tNeuron_setV3(tNeuron* const n, float V3) { n->V[2] = V3; } void tNeuron_setTimeStep(tNeuron* const n, float timeStep) { n->timeStep = timeStep; } void tNeuron_setK(tNeuron* const n, float K) { n->gK = K; } void tNeuron_setL(tNeuron* const n, float L) { n->gL = L; n->rate[2] = n->gL/n->C; } void tNeuron_setN(tNeuron* const n, float N) { n->gN = N; } void tNeuron_setC(tNeuron* const n, float C) { n->C = C; n->rate[2] = n->gL/n->C; } float tNeuron_tick(tNeuron* const n) { float output = 0.0f; float voltage = n->voltage; n->alpha[0] = (0.01f * (10.0f - voltage)) / (expf((10.0f - voltage)/10.0f) - 1.0f); n->alpha[1] = (0.1f * (25.0f-voltage)) / (expf((25.0f-voltage)/10.0f) - 1.0f); n->alpha[2] = (0.07f * expf((-1.0f * voltage)/20.0f)); n->beta[0] = (0.125f * expf((-1.0f* voltage)/80.0f)); n->beta[1] = (4.0f * expf((-1.0f * voltage)/18.0f)); n->beta[2] = (1.0f / (expf((30.0f-voltage)/10.0f) + 1.0f)); for (int i = 0; i < 3; i++) { n->P[i] = (n->alpha[i] * n->timeStep) + ((1.0f - ((n->alpha[i] + n->beta[i]) * n->timeStep)) * n->P[i]); if (n->P[i] > 1.0f) n->P[i] = 0.0f; else if (n->P[i] < -1.0f) n->P[i] = 0.0f; } // rate[0]= k ; rate[1] = Na ; rate[2] = l n->rate[0] = ((n->gK * powf(n->P[0], 4.0f)) / n->C); n->rate[1] = ((n->gN * powf(n->P[1], 3.0f) * n->P[2]) / n->C); //calculate the final membrane voltage based on the computed variables n->voltage = voltage + (n->timeStep * n->current / n->C) - (n->timeStep * ( n->rate[0] * (voltage - n->V[0]) + n->rate[1] * (voltage - n->V[1]) + n->rate[2] * (voltage - n->V[2]))); if (n->mode == NeuronTanh) { n->voltage = 100.0f * tanhf(0.01f * n->voltage); } else if (n->mode == NeuronAaltoShaper) { float shapeVoltage = 0.01f * n->voltage; float w, c, xc, xc2, xc4; float sqrt8 = 2.82842712475f; float wscale = 1.30612244898f; float m_drive = 1.0f; xc = LEAF_clip(-sqrt8, shapeVoltage, sqrt8); xc2 = xc*xc; c = 0.5f * shapeVoltage * (3.0f - (xc2)); xc4 = xc2 * xc2; w = (1.0f - xc2 * 0.25f + xc4 * 0.015625f) * wscale; shapeVoltage = w * (c + 0.05f * xc2) * (m_drive + 0.75f); n->voltage = 100.0f * shapeVoltage; } if (n->voltage > 100.0f) n->voltage = 100.0f; else if (n->voltage < -100.) n->voltage = -100.0f; //(inputCurrent + (voltage - ((voltage * timeStep) / timeConstant)) + P[0] + P[1] + P[2]) => voltage; // now we should have a result //set the output voltage to the "step" ugen, which controls the DAC. output = n->voltage * 0.01f; // volts output = tPoleZero_tick(&n->f, output); return output; } void tNeuron_setMode (tNeuron* const n, NeuronMode mode) { n->mode = mode; } void tNeuron_setCurrent (tNeuron* const n, float current) { n->current = current; } // Cycle void tCycle_init(tCycle* const c) { c->inc = 0.0f; c->phase = 0.0f; } void tCycle_free(tCycle* const c) { leaf_free(c); } int tCycle_setFreq(tCycle* const c, float freq) { if (freq < 0.0f) freq = 0.0f; c->freq = freq; c->inc = freq * leaf.invSampleRate; return 0; } float tCycle_tick(tCycle* const c) { // Phasor increment c->phase += c->inc; if (c->phase >= 1.0f) c->phase -= 1.0f; // Wavetable synthesis float temp = SINE_TABLE_SIZE * c->phase; int intPart = (int)temp; float fracPart = temp - (float)intPart; float samp0 = sinewave[intPart]; if (++intPart >= SINE_TABLE_SIZE) intPart = 0; float samp1 = sinewave[intPart]; return (samp0 + (samp1 - samp0) * fracPart); } void tCycleSampleRateChanged (tCycle* const c) { c->inc = c->freq * leaf.invSampleRate; } /* Phasor */ void tPhasorSampleRateChanged (tPhasor* const p) { p->inc = p->freq * leaf.invSampleRate; }; int tPhasor_setFreq(tPhasor* const p, float freq) { if (freq < 0.0f) freq = 0.0f; p->freq = freq; p->inc = freq * leaf.invSampleRate; return 0; } float tPhasor_tick(tPhasor* const p) { p->phase += p->inc; if (p->phase >= 1.0f) p->phase -= 1.0f; return p->phase; } void tPhasor_init(tPhasor* const p) { p->phase = 0.0f; p->inc = 0.0f; } void tPhasor_free(tPhasor* const p) { leaf_free(p); } void tSawtooth_init(tSawtooth* const c) { c->inc = 0.0f; c->phase = 0.0f; } void tSawtooth_free(tSawtooth* const c) { leaf_free(c); } int tSawtooth_setFreq(tSawtooth* const c, float freq) { if (freq < 0.0f) freq = 0.0f; c->freq = freq; c->inc = freq * leaf.invSampleRate; return 0; } float tSawtooth_tick(tSawtooth* const c) { // Phasor increment c->phase += c->inc; if (c->phase >= 1.0f) c->phase -= 1.0f; float out = 0.0f; float w; int idx = (int)(c->phase * TRI_TABLE_SIZE); // Wavetable synthesis if (c->freq <= 20.0f) { out = sawtooth[T20][idx]; } else if (c->freq <= 40.0f) { w = ((40.0f - c->freq) * INV_20); out = (sawtooth[T20][idx] * w) + (sawtooth[T40][idx] * (1.0f - w)); } else if (c->freq <= 80.0f) { w = ((80.0f - c->freq) * INV_40); out = (sawtooth[T40][idx] * w) + (sawtooth[T80][idx] * (1.0f - w)); } else if (c->freq <= 160.0f) { w = ((160.0f - c->freq) * INV_80); out = (sawtooth[T80][idx] * w) + (sawtooth[T160][idx] * (1.0f - w)); } else if (c->freq <= 320.0f) { w = ((320.0f - c->freq) * INV_160); out = (sawtooth[T160][idx] * w) + (sawtooth[T320][idx] * (1.0f - w)); } else if (c->freq <= 640.0f) { w = ((640.0f - c->freq) * INV_320); out = (sawtooth[T320][idx] * w) + (sawtooth[T640][idx] * (1.0f - w)); } else if (c->freq <= 1280.0f) { w = ((1280.0f - c->freq) * INV_640); out = (sawtooth[T640][idx] * w) + (sawtooth[T1280][idx] * (1.0f - w)); } else if (c->freq <= 2560.0f) { w = ((2560.0f - c->freq) * INV_1280); out = (sawtooth[T1280][idx] * w) + (sawtooth[T2560][idx] * (1.0f - w)); } else if (c->freq <= 5120.0f) { w = ((5120.0f - c->freq) * INV_2560); out = (sawtooth[T2560][idx] * w) + (sawtooth[T5120][idx] * (1.0f - w)); } else if (c->freq <= 10240.0f) { w = ((10240.0f - c->freq) * INV_5120); out = (sawtooth[T5120][idx] * w) + (sawtooth[T10240][idx] * (1.0f - w)); } else if (c->freq <= 20480.0f) { w = ((20480.0f - c->freq) * INV_10240); out = (sawtooth[T10240][idx] * w) + (sawtooth[T20480][idx] * (1.0f - w)); } else { out = sawtooth[T20480][idx]; } return out; } void tSawtoothSampleRateChanged (tSawtooth* const c) { c->inc = c->freq * leaf.invSampleRate; } /* Triangle */ void tTriangle_start(tTriangle* const c) { } void tTriangle_init(tTriangle* const c) { c->inc = 0.0f; c->phase = 0.0f; } void tTriangle_free(tTriangle* const c) { leaf_free(c);} int tTriangle_setFreq(tTriangle* const c, float freq) { if (freq < 0.0f) freq = 0.0f; c->freq = freq; c->inc = freq * leaf.invSampleRate; return 0; } float tTriangle_tick(tTriangle* const c) { // Phasor increment c->phase += c->inc; if (c->phase >= 1.0f) c->phase -= 1.0f; float out = 0.0f; float w; int idx = (int)(c->phase * TRI_TABLE_SIZE); // Wavetable synthesis if (c->freq <= 20.0f) { out = triangle[T20][idx]; } else if (c->freq <= 40.0f) { w = ((40.0f - c->freq) * INV_20); out = (triangle[T20][idx] * w) + (triangle[T40][idx] * (1.0f - w)); } else if (c->freq <= 80.0f) { w = ((80.0f - c->freq) * INV_40); out = (triangle[T40][idx] * w) + (triangle[T80][idx] * (1.0f - w)); } else if (c->freq <= 160.0f) { w = ((160.0f - c->freq) * INV_80); out = (triangle[T80][idx] * w) + (triangle[T160][idx] * (1.0f - w)); } else if (c->freq <= 320.0f) { w = ((320.0f - c->freq) * INV_160); out = (triangle[T160][idx] * w) + (triangle[T320][idx] * (1.0f - w)); } else if (c->freq <= 640.0f) { w = ((640.0f - c->freq) * INV_320); out = (triangle[T320][idx] * w) + (triangle[T640][idx] * (1.0f - w)); } else if (c->freq <= 1280.0f) { w = ((1280.0f - c->freq) * INV_640); out = (triangle[T640][idx] * w) + (triangle[T1280][idx] * (1.0f - w)); } else if (c->freq <= 2560.0f) { w = ((2560.0f - c->freq) * INV_1280); out = (triangle[T1280][idx] * w) + (triangle[T2560][idx] * (1.0f - w)); } else if (c->freq <= 5120.0f) { w = ((5120.0f - c->freq) * INV_2560); out = (triangle[T2560][idx] * w) + (triangle[T5120][idx] * (1.0f - w)); } else if (c->freq <= 10240.0f) { w = ((10240.0f - c->freq) * INV_5120); out = (triangle[T5120][idx] * w) + (triangle[T10240][idx] * (1.0f - w)); } else if (c->freq <= 20480.0f) { w = ((20480.0f - c->freq) * INV_10240); out = (triangle[T10240][idx] * w) + (triangle[T20480][idx] * (1.0f - w)); } else { out = triangle[T20480][idx]; } return out; } void tTriangleSampleRateChanged (tTriangle* const c) { c->inc = c->freq * leaf.invSampleRate; } /* Square */ void tSquare_init(tSquare* const c) { c->inc = 0.0f; c->phase = 0.0f; } void tSquare_free(tSquare* const c) { leaf_free(c); } int tSquare_setFreq(tSquare* const c, float freq) { if (freq < 0.0f) freq = 0.0f; c->freq = freq; c->inc = freq * leaf.invSampleRate; return 0; } float tSquare_tick(tSquare* const c) { // Phasor increment c->phase += c->inc; if (c->phase >= 1.0f) c->phase -= 1.0f; float out = 0.0f; float w = 0.0f; int idx = (int)(c->phase * TRI_TABLE_SIZE); // Wavetable synthesis if (c->freq <= 20.0f) { out = squarewave[T20][idx]; } else if (c->freq <= 40.0f) { w = ((40.0f - c->freq) * INV_20); out = (squarewave[T20][idx] * w) + (squarewave[T40][idx] * (1.0f - w)); } else if (c->freq <= 80.0f) { w = ((80.0f - c->freq) * INV_40); out = (squarewave[T40][idx] * w) + (squarewave[T80][idx] * (1.0f - w)); } else if (c->freq <= 160.0f) { w = ((160.0f - c->freq) * INV_80); out = (squarewave[T80][idx] * w) + (squarewave[T160][idx] * (1.0f - w)); } else if (c->freq <= 320.0f) { w = ((320.0f - c->freq) * INV_160); out = (squarewave[T160][idx] * w) + (squarewave[T320][idx] * (1.0f - w)); } else if (c->freq <= 640.0f) { w = ((640.0f - c->freq) * INV_320); out = (squarewave[T320][idx] * w) + (squarewave[T640][idx] * (1.0f - w)); } else if (c->freq <= 1280.0f) { w = ((1280.0f - c->freq) * INV_640); out = (squarewave[T640][idx] * w) + (squarewave[T1280][idx] * (1.0f - w)); } else if (c->freq <= 2560.0f) { w = ((2560.0f - c->freq) * INV_1280); out = (squarewave[T1280][idx] * w) + (squarewave[T2560][idx] * (1.0f - w)); } else if (c->freq <= 5120.0f) { w = ((5120.0f - c->freq) * INV_2560); out = (squarewave[T2560][idx] * w) + (squarewave[T5120][idx] * (1.0f - w)); } else if (c->freq <= 10240.0f) { w = ((10240.0f - c->freq) * INV_5120); out = (squarewave[T5120][idx] * w) + (squarewave[T10240][idx] * (1.0f - w)); } else if (c->freq <= 20480.0f) { w = ((20480.0f - c->freq) * INV_10240); out = (squarewave[T10240][idx] * w) + (squarewave[T20480][idx] * (1.0f - w)); } else { out = squarewave[T20480][idx]; } return out; } void tSquareSampleRateChanged (tSquare* const c) { c->inc = c->freq * leaf.invSampleRate; } /* Noise */ void tNoise_init(tNoise* const n, NoiseType type) { n->type = type; n->rand = leaf.random; } void tNoise_free(tNoise* const n) { leaf_free(n); } float tNoise_tick(tNoise* const n) { float rand = n->rand(); if (n->type == PinkNoise) { float tmp; n->pinkb0 = 0.99765f * n->pinkb0 + rand * 0.0990460f; n->pinkb1 = 0.96300f * n->pinkb1 + rand * 0.2965164f; n->pinkb2 = 0.57000f * n->pinkb2 + rand * 1.0526913f; tmp = n->pinkb0 + n->pinkb1 + n->pinkb2 + rand * 0.1848f; return (tmp * 0.05f); } else // WhiteNoise { return rand; } }