1
0
Fork 0

The fire of Jerdehl burns.

This commit is contained in:
Rodrigo Franco 2023-12-21 12:33:48 -03:00
parent 44643fe4ad
commit 96393f6db0
1 changed files with 70 additions and 37 deletions

107
jerdehl.c
View File

@ -32,8 +32,8 @@ typedef struct noise_oscillator
double generate_noise(noise_osc_t *n)
{
// A simple pseudo-random noise generator
n->seed = (n->seed * 1103515245 + 12345) & 0x7fffffff;
// A simple pseudo-random noise generator
n->seed = (n->seed * 1235515245 + 12345) & 0x7ffaffff;
return (double)n->seed / 0x40000000 - 1.0; // Normalize to range -1.0 to 1.0
}
@ -42,36 +42,33 @@ void init_noise_osc(noise_osc_t *n, uint32_t seed)
n->seed = seed;
}
double update_crackle(noise_osc_t *n)
{
// Generate the base noise
double noise = generate_noise(n);
// Apply random volume modulation to simulate the crackling effect
double volume = 0 + ((double)rand() / RAND_MAX) * 0.5; // Random volume between 0.2 and 1.0
double volume = 0 + ((double)rand() / RAND_MAX) * 0.2; // Random volume between 0.2 and 1.0
// Occasionally spike the volume to simulate louder crackles
if ((rand() % 100) < 40) // 10% chance for a louder crackle
if ((rand() % 100) < 20) // 20% chance for a louder crackle
{
volume += 0.5; // Increase volume for a louder crackle
volume += 15.0; // Increase volume for a louder crackle
}
// Clamp the volume to avoid clipping
volume = (volume > 1.0) ? 1.0 : volume;
// volume = (volume > 1.0) ? 1.0 : volume;
// Apply the volume to the noise
noise *= volume;
// Clamp the noise to avoid clipping
return noise;
}
float chordFrequencies[CHORD_TYPES][CHORD_NOTES] = {
{65.41, 77.78, 98.00}, // Cm (C, Eb, G)
{73.42, 87.31, 97.99}, // Ddim (D, F, Ab)
{82.41, 97.99, 123.47}, // Eb (Eb, G, Bb)
{87.31, 103.83, 130.81},// Fm (F, Ab, C)
{97.99, 116.54, 146.83},// Gm (G, Bb, D)
{103.83, 123.47, 155.56},// Ab (Ab, C, Eb)
{116.54, 130.81, 155.56},// Bb (Bb, D, F)
{65.41, 77.78, 98.00}, // Cm (C, Eb, G)
{73.42, 87.31, 97.99}, // Ddim (D, F, Ab)
{82.41, 97.99, 123.47}, // Eb (Eb, G, Bb)
{87.31, 103.83, 130.81}, // Fm (F, Ab, C)
{97.99, 116.54, 146.83}, // Gm (G, Bb, D)
{103.83, 123.47, 155.56}, // Ab (Ab, C, Eb)
{116.54, 130.81, 155.56}, // Bb (Bb, D, F)
};
float higherChordFrequencies[CHORD_TYPES][CHORD_NOTES] = {
{130.81, 155.56, 196.00}, // Cm (C4, Eb4, G4)
@ -85,7 +82,7 @@ float higherChordFrequencies[CHORD_TYPES][CHORD_NOTES] = {
void set_osc_freq(osc_t *o, float f)
{
o->step = (uint32_t)((f / 16000.0) * UINT32_MAX);
o->step = (uint32_t)((f / 16000) * UINT32_MAX);
o->phasor = 0; // Reset the phasor to start at the beginning of the sine wave
}
@ -94,35 +91,46 @@ void update_osc(osc_t *o)
uint16_t index;
o->phasor += o->step;
index = o->phasor >> (32 - 11); // We are using an 11-bit index for a 2048-entry table
o->value = sinetab[index];
o->value = sinetab[index] > 0 ? 1.0 : -1.0;
}
void update_piano_osc(PianoOscillator *p, float chordFrequencies[CHORD_TYPES][CHORD_NOTES], int notePlayChance) {
if (p->noteDuration > 0) {
void update_piano_osc(PianoOscillator *p, float chordFrequencies[CHORD_TYPES][CHORD_NOTES], int notePlayChance)
{
if (p->noteDuration > 0)
{
// Continue playing the current chord
double fadeOutFactor = 1.0;
double fadeOutFactor = 1;
int twoThirdsDuration = (2 * p->noteDuration / 3);
if (p->noteDuration <= twoThirdsDuration) {
if (p->noteDuration <= twoThirdsDuration)
{
// Calculate fade-out factor
fadeOutFactor = (double)p->noteDuration / twoThirdsDuration;
}
// Update the value for each oscillator in the chord with fade-out
for (int i = 0; i < CHORD_NOTES; ++i) {
for (int i = 0; i < CHORD_NOTES; ++i)
{
update_osc(&p->noteOsc[i]);
p->noteOsc[i].value *= fadeOutFactor; // Apply fade-out factor
}
p->noteDuration--; // Decrement the note duration
} else {
}
else
{
// Random chance to play a new chord or not play anything (silence)
if (rand() % notePlayChance == 0) {
if (rand() % notePlayChance == 0)
{
int chordIndex = rand() % CHORD_TYPES;
for (int i = 0; i < CHORD_NOTES; ++i) {
for (int i = 0; i < CHORD_NOTES; ++i)
{
set_osc_freq(&p->noteOsc[i], chordFrequencies[chordIndex][i]);
}
p->noteDuration = (rand() % 10 + 1) * 16000; // Set a new random note duration
} else {
p->noteDuration = (rand() % 20 + 1) * 16000; // Set a new random note duration
}
else
{
// Set all oscillator values to zero to represent silence
for (int i = 0; i < CHORD_NOTES; ++i) {
for (int i = 0; i < CHORD_NOTES; ++i)
{
p->noteOsc[i].value = 0.0f;
}
}
@ -130,6 +138,8 @@ void update_piano_osc(PianoOscillator *p, float chordFrequencies[CHORD_TYPES][CH
}
int main()
{
int c, d;
FILE *fp;
PianoOscillator pianoOsc;
PianoOscillator highPianoOsc;
@ -146,15 +156,16 @@ int main()
srand(time(NULL));
for (int i = 0; i < SINE_TABLE_SIZE; i++)
for (int i = 0; i < SINE_TABLE_SIZE / 2; i++)
{
sinetab[i] = sin(i * 2 * M_PI / SINE_TABLE_SIZE);
sinetab[i] = 1.0;
sinetab[i + SINE_TABLE_SIZE / 2] = -1.0;
}
// Initialize the first chord and duration for piano and high piano
int chordIndex = rand() % CHORD_TYPES;
update_piano_osc(&pianoOsc, chordFrequencies, 10); // Start with a random duration
update_piano_osc(&highPianoOsc, higherChordFrequencies, 8); // Start with a random duration
update_piano_osc(&pianoOsc, chordFrequencies, 60); // Start with a random duration
update_piano_osc(&highPianoOsc, higherChordFrequencies, 25); // Start with a random duration
// Set the frequencies for the first chord
for (int i = 0; i < CHORD_NOTES; ++i)
{
@ -165,8 +176,13 @@ int main()
noise_osc_t fireCrackleOsc;
init_noise_osc(&fireCrackleOsc, time(NULL));
int j = 20000000;
while (1)
{
if (j == 0) {
j = 20000000;
}
out = 0.0f; // Reset output each iteration
// Update the piano and high piano oscillators
@ -176,15 +192,31 @@ int main()
update_piano_osc(&highPianoOsc, higherChordFrequencies, 2); // 2 for a 1 in 2 chance of silence
// Mix the outputs from all oscillators
for (int i = 0; i < CHORD_NOTES; ++i)
{
out += pianoOsc.noteOsc[i].value + (highPianoOsc.noteOsc[i].value * -1.0f);
if (j % 179 == 0)
{
out += pianoOsc.noteOsc[i].value + (highPianoOsc.noteOsc[i].value * -0.5f);
}
else if (j % 150 == 0)
{
out += pianoOsc.noteOsc[i].value;
}
else
{
out += (highPianoOsc.noteOsc[i].value * -0.6f);
}
}
out /= (2 * CHORD_NOTES); // Correctly average the mixed notes, considering both piano and high piano
// Fire crackling noise
double crackle = update_crackle(&fireCrackleOsc);
out += crackle * 0.1f;
if (j % 2000 == 0)
{
double crackle = update_crackle(&fireCrackleOsc);
out += crackle * 1.0f;
}
// Increase the gain to make the signal louder
float gain = 0.5f; // Adjust the gain factor as needed
@ -197,11 +229,12 @@ int main()
out = -1.0f;
// Scale to 16-bit output value
out16 = (uint16_t)((UINT16_MAX / 2) * (0.5 + 0.5 * out));
out16 = (uint16_t)((UINT16_MAX / 2) * (0.6 + 1.0 * out));
// Write output value for stereo channels
fwrite(&out16, sizeof(out16), 1, fp);
fwrite(&out16, sizeof(out16), 1, fp);
j--;
}
fclose(fp);
return 0;