1
0
Fork 0

added tape and cicada emulator

This commit is contained in:
Rodrigo Franco 2023-12-04 11:14:07 -03:00
parent 9b5f5d8c05
commit d04f5dc9cc
1 changed files with 78 additions and 6 deletions

View File

@ -6,16 +6,34 @@
float sinetab[2048];
// structs
typedef struct oscillator {
uint32_t phasor;
uint32_t step;
float value;
} osc_t;
typedef struct tape_oscillator {
osc_t wowOsc; // Low-frequency oscillator for wow
osc_t flutterOsc; // Higher-frequency oscillator for flutter
float saturation; // Saturation level
} tape_osc_t;
typedef struct cicada_oscillator {
osc_t modOsc; // Modulator for cicada effect
float modDepth; // Depth of modulation
float saturation; // Saturation level
} cicada_osc_t;
void set_osc_freq(osc_t* o, float f) {
o->step = (uint32_t) ((f / 16000.0) * UINT32_MAX);
}
// updates
void update_osc(osc_t* o) {
uint16_t index;
o->phasor += o->step;
index = o->phasor >> (32-10);
index = o->phasor >> (32-11);
o->value = sinetab[index];
}
@ -26,8 +44,41 @@ void update_rand_osc(osc_t* o) {
o->value = sinetab[index] * ((rand() % 100) / 85.0 - 1); // Randomness in amplitude
}
void set_osc_freq(osc_t* o, float f) {
o->step = (uint32_t) ((f / 16000.0) * UINT32_MAX);
void update_tape_osc(tape_osc_t* t, osc_t* audioOsc) {
// Update wow and flutter oscillators
update_osc(&t->wowOsc);
update_osc(&t->flutterOsc);
// Apply wow and flutter as pitch modulation
float pitchMod = 1.0 + 0.002 * t->wowOsc.value + 0.0005 * t->flutterOsc.value;
set_osc_freq(audioOsc, audioOsc->step * pitchMod);
// Apply saturation (simple non-linear function)
audioOsc->value = tanh(t->saturation * audioOsc->value);
}
void update_cicada_osc(cicada_osc_t* c, osc_t* o, int* timer) {
if (*timer > 0) {
// Cicada sound is active
c->saturation=0.5;
update_osc(&c->modOsc); // Update the modulator
// Modulate frequency and amplitude
float modFactor = 1.0 + c->modDepth * c->modOsc.value;
o->step = (uint32_t) (((o->step / UINT32_MAX * 16000.0) * modFactor / 16000.0) * UINT32_MAX);
o->value *= modFactor;
o->value = tanh(c->saturation * o->value);
(*timer)--;
} else {
c->saturation=0;
o->value = tanh(c->saturation * o->value);
// Cicada sound is inactive, check if it should start
if (rand() % 1000000 < 5) {
*timer = rand() % (16000 * 100);
}
}
}
int main() {
@ -58,7 +109,7 @@ int main() {
set_osc_freq(&lisa[0], 0.0100);
set_osc_freq(&lisa[1], 0.0550);
set_osc_freq(&lisa[2], 0.1);
set_osc_freq(&lisa[2], 0.746);
lisa[1].phasor = 0.25*UINT32_MAX;
lisa[2].phasor = 0.5*UINT32_MAX;
@ -67,7 +118,7 @@ int main() {
set_osc_freq(&lfobank[2], 0.800);
set_osc_freq(&lfobank[3], 0.1100);
set_osc_freq(&oscbank[0], 1130.813);
set_osc_freq(&oscbank[0], 7469.826/86);
set_osc_freq(&oscbank[1], 1164.814);
set_osc_freq(&oscbank[2], 1195.998);
set_osc_freq(&oscbank[3], 1130.813/2);
@ -79,32 +130,53 @@ int main() {
randOsc.phasor = 1;
srand(time(NULL));
// tape osc
tape_osc_t tapeOsc;
set_osc_freq(&tapeOsc.wowOsc, 6765464679); // Low frequency for wow
set_osc_freq(&tapeOsc.flutterOsc, 74698268697276); // Higher frequency for flutter
tapeOsc.saturation = 0.4; // Adjust for desired saturation effect
// cicada osc
cicada_osc_t cicadaOsc;
set_osc_freq(&cicadaOsc.modOsc, 20.0); // Fast modulation for cicada effect
cicadaOsc.modDepth = 0.5; // Modulation depth
cicadaOsc.saturation = 0.0;
int cicadaTimer = 0; // Timer for cicada oscillator
while(1) {
update_osc(&lisa[0]);
update_osc(&lisa[1]);
update_osc(&lisa[2]);
for(int i=0; i<2048; i++) {
sinetab[i] = zero_five*((zero_five+zero_five*lisa[0].value)*coldtab[i] + (1 - zero_five - zero_five*lisa[0].value)*eventab[i]) +
zero_five*((zero_five+zero_five*lisa[1].value)*coldtab[i] + (1 - zero_five - zero_five*lisa[1].value)*oddtab[i]);
zero_five*((zero_five+zero_five*lisa[2].value)*coldtab[i] + (1 - zero_five - zero_five*lisa[2].value)*oddtab[i]);
}
for(int i=0; i<4; i++) {
update_osc(&lfobank[i]);
}
set_osc_freq(&oscbank[0], 22.111 + 0.25*(lfobank[0].value));
set_osc_freq(&oscbank[1], 64.814 - zero_five*(lfobank[1].value));
set_osc_freq(&oscbank[2], 95.998 + zero_three*(lfobank[2].value));
set_osc_freq(&oscbank[3], 30.813/2 - 50*(lfobank[3].value));
for(int i=0; i<5; i++) {
update_osc(&oscbank[i]);
update_rand_osc(&randOsc);
update_tape_osc(&tapeOsc, &oscbank[i]);
}
out = zero_oh_five*randOsc.value/4 +
update_cicada_osc(&cicadaOsc, &randOsc, &cicadaTimer);
out = zero_oh_five*randOsc.value/2 +
zero_oh_five*oscbank[0].value +
zero_oh_five*oscbank[1].value +
zero_oh_five*oscbank[2].value +
zero_oh_five*oscbank[3].value*(zero_five + zero_five*env.value);
out += zero_oh_five * randOsc.value;
out16 = (uint16_t) (UINT16_MAX/2)*(zero_five + zero_five*out);
fputc(out16 & 0xFF, fp);
fputc(out16 >> 8, fp);