added tape and cicada emulator
This commit is contained in:
parent
9b5f5d8c05
commit
d04f5dc9cc
84
jerdehl.c
84
jerdehl.c
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue