Changed frequencies and added noise
This commit is contained in:
parent
565d718049
commit
44643fe4ad
222
jerdehl.c
222
jerdehl.c
|
@ -5,19 +5,17 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#define SINE_TABLE_SIZE 2048
|
#define SINE_TABLE_SIZE 2048
|
||||||
#define ZERO_FIVE 0.5
|
|
||||||
#define ZERO_THREE 0.3
|
|
||||||
#define UINT32_MAX_HALF (UINT32_MAX / 2)
|
#define UINT32_MAX_HALF (UINT32_MAX / 2)
|
||||||
#define CHORD_NOTES 3
|
#define CHORD_NOTES 3
|
||||||
#define CHORD_TYPES 21
|
#define CHORD_TYPES 7
|
||||||
|
|
||||||
float sinetab[SINE_TABLE_SIZE];
|
double sinetab[SINE_TABLE_SIZE];
|
||||||
|
|
||||||
typedef struct oscillator
|
typedef struct oscillator
|
||||||
{
|
{
|
||||||
uint32_t phasor;
|
uint32_t phasor;
|
||||||
uint32_t step;
|
uint32_t step;
|
||||||
float value;
|
double value;
|
||||||
} osc_t;
|
} osc_t;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -26,54 +24,70 @@ typedef struct
|
||||||
int noteDuration;
|
int noteDuration;
|
||||||
} PianoOscillator;
|
} PianoOscillator;
|
||||||
|
|
||||||
// Frequencies for chords in the key of C (C, Dm, Em, F, G, Am)
|
typedef struct noise_oscillator
|
||||||
|
{
|
||||||
|
uint32_t seed;
|
||||||
|
double value;
|
||||||
|
} noise_osc_t;
|
||||||
|
|
||||||
|
double generate_noise(noise_osc_t *n)
|
||||||
|
{
|
||||||
|
// A simple pseudo-random noise generator
|
||||||
|
n->seed = (n->seed * 1103515245 + 12345) & 0x7fffffff;
|
||||||
|
return (double)n->seed / 0x40000000 - 1.0; // Normalize to range -1.0 to 1.0
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
// Occasionally spike the volume to simulate louder crackles
|
||||||
|
if ((rand() % 100) < 40) // 10% chance for a louder crackle
|
||||||
|
{
|
||||||
|
volume += 0.5; // Increase volume for a louder crackle
|
||||||
|
}
|
||||||
|
// Clamp the volume to avoid clipping
|
||||||
|
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] = {
|
float chordFrequencies[CHORD_TYPES][CHORD_NOTES] = {
|
||||||
{65.41, 77.78, 98.00}, // Cm (C, Eb, G)
|
{65.41, 77.78, 98.00}, // Cm (C, Eb, G)
|
||||||
{87.31, 98.00, 116.54}, // Fm7 (F, G, Bb)
|
{73.42, 87.31, 97.99}, // Ddim (D, F, Ab)
|
||||||
{73.42, 87.31, 110.00}, // Ddim (D, F, A)
|
{82.41, 97.99, 123.47}, // Eb (Eb, G, Bb)
|
||||||
{61.74, 77.78, 92.50}, // G7 (G, B, F)
|
{87.31, 103.83, 130.81},// Fm (F, Ab, C)
|
||||||
{58.27, 73.42, 87.31}, // BbMaj (Bb, D, F)
|
{97.99, 116.54, 146.83},// Gm (G, Bb, D)
|
||||||
{65.41, 82.41, 103.83}, // Cm/Ab (Ab, C, Eb)
|
{103.83, 123.47, 155.56},// Ab (Ab, C, Eb)
|
||||||
{73.42, 92.50, 116.54}, // D7 (D, F#, A, C)
|
{116.54, 130.81, 155.56},// Bb (Bb, D, F)
|
||||||
{65.41, 77.78, 98.00}, // Cm (C, Eb, G) repeat
|
};
|
||||||
{58.27, 73.42, 87.31}, // BbMaj (Bb, D, F) repeat
|
float higherChordFrequencies[CHORD_TYPES][CHORD_NOTES] = {
|
||||||
{61.74, 77.78, 92.50}, // G7 (G, B, F) repeat
|
{130.81, 155.56, 196.00}, // Cm (C4, Eb4, G4)
|
||||||
{77.78, 98.00, 123.47}, // EbMaj (Eb, G, Bb)
|
{146.83, 174.61, 195.99}, // Ddim (D4, F4, Ab4)
|
||||||
{82.41, 103.83, 130.81}, // AbMaj (Ab, C, Eb)
|
{164.81, 195.99, 246.94}, // Eb (Eb4, G4, Bb4)
|
||||||
{87.31, 110.00, 130.81}, // FMaj7 (F, A, C, E)
|
{174.61, 207.65, 261.63}, // Fm (F4, Ab4, C5)
|
||||||
{98.00, 123.47, 146.83}, // GMaj (G, B, D)
|
{195.99, 233.08, 293.66}, // Gm (G4, Bb4, D5)
|
||||||
{103.83, 130.81, 155.56}, // AbMaj7 (Ab, C, Eb, G)
|
{207.65, 246.94, 311.13}, // Ab (Ab4, C5, Eb5)
|
||||||
{110.00, 130.81, 164.81}, // AMaj7 (A, C#, E, G#)
|
{233.08, 261.63, 311.13}, // Bb (Bb4, D5, F5)
|
||||||
{116.54, 146.83, 174.61}, // BbMaj (Bb, D, F)
|
|
||||||
{123.47, 155.56, 185.00}, // EbMaj7 (Eb, G, Bb, D)
|
|
||||||
{130.81, 164.81, 195.00}, // FMaj (F, A, C)
|
|
||||||
{146.83, 174.61, 220.00}, // GMaj7 (G, B, D, F#)
|
|
||||||
{65.41, 77.78, 98.00} // Cm (C, Eb, G)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
float higherChordFrequencies[CHORD_TYPES][CHORD_NOTES] = {
|
void set_osc_freq(osc_t *o, float f)
|
||||||
{130.82 * 2, 155.56 * 2, 196.00 * 2}, // Cm (C6, Eb6, G6)
|
{
|
||||||
{174.62 * 2, 196.00 * 2, 233.08 * 2}, // Fm7 (F6, G6, Bb6)
|
o->step = (uint32_t)((f / 16000.0) * UINT32_MAX);
|
||||||
{146.84 * 2, 174.62 * 2, 220.00 * 2}, // Ddim (D6, F6, A6)
|
o->phasor = 0; // Reset the phasor to start at the beginning of the sine wave
|
||||||
{123.48 * 2, 155.56 * 2, 185.00 * 2}, // G7 (G6, B6, F6)
|
}
|
||||||
{116.54 * 2, 146.84 * 2, 174.62 * 2}, // BbMaj (Bb6, D6, F6)
|
|
||||||
{130.82 * 2, 164.82 * 2, 207.66 * 2}, // Cm/Ab (Ab6, C6, Eb6)
|
|
||||||
{146.84 * 2, 185.00 * 2, 233.08 * 2}, // D7 (D6, F#6, A6, C6)
|
|
||||||
{130.82 * 2, 155.56 * 2, 196.00 * 2}, // Cm (C6, Eb6, G6) repeat
|
|
||||||
{116.54 * 2, 146.84 * 2, 174.62 * 2}, // BbMaj (Bb6, D6, F6) repeat
|
|
||||||
{123.48 * 2, 155.56 * 2, 185.00 * 2}, // G7 (G6, B6, F6) repeat
|
|
||||||
{155.56 * 2, 196.00 * 2, 246.94 * 2}, // EbMaj (Eb6, G6, Bb6)
|
|
||||||
{164.82 * 2, 207.66 * 2, 261.62 * 2}, // AbMaj (Ab6, C6, Eb6)
|
|
||||||
{174.62 * 2, 220.00 * 2, 261.62 * 2}, // FMaj7 (F6, A6, C6, E6)
|
|
||||||
{196.00 * 2, 246.94 * 2, 293.66 * 2}, // GMaj (G6, B6, D6)
|
|
||||||
{207.66 * 2, 261.62 * 2, 311.12 * 2}, // AbMaj7 (Ab6, C6, Eb6, G6)
|
|
||||||
{220.00 * 2, 261.62 * 2, 329.62 * 2}, // AMaj7 (A6, C#6, E6, G#6)
|
|
||||||
{233.08 * 2, 293.66 * 2, 349.22 * 2}, // BbMaj (Bb6, D6, F6)
|
|
||||||
{246.94 * 2, 311.12 * 2, 369.99 * 2}, // EbMaj7 (Eb6, G6, Bb6, D6)
|
|
||||||
{261.62 * 2, 329.62 * 2, 391.99 * 2}, // FMaj (F6, A6, C6)
|
|
||||||
{293.66 * 2, 349.22 * 2, 440.00 * 2}, // GMaj7 (G6, B6, D6, F#6)
|
|
||||||
{130.82 * 2, 155.56 * 2, 196.00 * 2} // Cm (C6, Eb6, G6)
|
|
||||||
};
|
|
||||||
|
|
||||||
void update_osc(osc_t *o)
|
void update_osc(osc_t *o)
|
||||||
{
|
{
|
||||||
|
@ -83,79 +97,37 @@ void update_osc(osc_t *o)
|
||||||
o->value = sinetab[index];
|
o->value = sinetab[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_osc_freq(osc_t *o, float f)
|
void update_piano_osc(PianoOscillator *p, float chordFrequencies[CHORD_TYPES][CHORD_NOTES], int notePlayChance) {
|
||||||
{
|
if (p->noteDuration > 0) {
|
||||||
o->step = (uint32_t)((f / 16000.0) * UINT32_MAX);
|
|
||||||
o->phasor = 0; // Reset the phasor to start at the beginning of the sine wave
|
|
||||||
}
|
|
||||||
|
|
||||||
void update_piano_osc(PianoOscillator *p)
|
|
||||||
{
|
|
||||||
if (p->noteDuration > 0)
|
|
||||||
{
|
|
||||||
// Continue playing the current chord
|
// Continue playing the current chord
|
||||||
p->noteDuration--; // Decrement the note duration
|
double fadeOutFactor = 1.0;
|
||||||
}
|
int twoThirdsDuration = (2 * p->noteDuration / 3);
|
||||||
else
|
if (p->noteDuration <= twoThirdsDuration) {
|
||||||
{
|
// Calculate fade-out factor
|
||||||
// Time to play a new chord
|
fadeOutFactor = (double)p->noteDuration / twoThirdsDuration;
|
||||||
int chordIndex = rand() % CHORD_TYPES;
|
}
|
||||||
for (int i = 0; i < CHORD_NOTES; ++i)
|
// Update the value for each oscillator in the chord with fade-out
|
||||||
{
|
for (int i = 0; i < CHORD_NOTES; ++i) {
|
||||||
// Assign a new frequency to each oscillator in the chord
|
update_osc(&p->noteOsc[i]);
|
||||||
set_osc_freq(&p->noteOsc[i], chordFrequencies[chordIndex][i]);
|
p->noteOsc[i].value *= fadeOutFactor; // Apply fade-out factor
|
||||||
}
|
}
|
||||||
p->noteDuration = (rand() % 5 + 1) * 16000; // Set a new random note duration
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the value for each oscillator in the chord
|
|
||||||
for (int i = 0; i < CHORD_NOTES; ++i)
|
|
||||||
{
|
|
||||||
update_osc(&p->noteOsc[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void update_high_piano_osc(PianoOscillator *p)
|
|
||||||
{
|
|
||||||
if (p->noteDuration > 0)
|
|
||||||
{
|
|
||||||
// Continue playing the current chord or silence
|
|
||||||
p->noteDuration--; // Decrement the note duration
|
p->noteDuration--; // Decrement the note duration
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// Random chance to play a new chord or not play anything (silence)
|
// Random chance to play a new chord or not play anything (silence)
|
||||||
if (rand() % 10 == 0)
|
if (rand() % notePlayChance == 0) {
|
||||||
{ // 50% chance to start a new chord, adjust as needed
|
|
||||||
int chordIndex = rand() % CHORD_TYPES;
|
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]);
|
||||||
// Assign a new frequency to each oscillator in the chord
|
|
||||||
set_osc_freq(&p->noteOsc[i], higherChordFrequencies[chordIndex][i]);
|
|
||||||
}
|
}
|
||||||
}
|
p->noteDuration = (rand() % 10 + 1) * 16000; // Set a new random note duration
|
||||||
else
|
} else {
|
||||||
{
|
|
||||||
// Set all oscillator values to zero to represent silence
|
// 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;
|
p->noteOsc[i].value = 0.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Set a new random note duration
|
|
||||||
p->noteDuration = (rand() % 5 + 1) * 16000; // E.g., between 1 and 5 seconds
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the value for each oscillator in the chord
|
|
||||||
if (p->noteDuration > 0)
|
|
||||||
{ // Only update oscillators if not in silence
|
|
||||||
for (int i = 0; i < CHORD_NOTES; ++i)
|
|
||||||
{
|
|
||||||
update_osc(&p->noteOsc[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
@ -181,38 +153,48 @@ int main()
|
||||||
|
|
||||||
// Initialize the first chord and duration for piano and high piano
|
// Initialize the first chord and duration for piano and high piano
|
||||||
int chordIndex = rand() % CHORD_TYPES;
|
int chordIndex = rand() % CHORD_TYPES;
|
||||||
pianoOsc.noteDuration = (rand() % 100 + 1) * 16000; // Start with a random duration
|
update_piano_osc(&pianoOsc, chordFrequencies, 10); // Start with a random duration
|
||||||
highPianoOsc.noteDuration = (rand() % 5 + 1) * 16000; // Start with a random duration
|
update_piano_osc(&highPianoOsc, higherChordFrequencies, 8); // Start with a random duration
|
||||||
|
// Set the frequencies for the first chord
|
||||||
for (int i = 0; i < CHORD_NOTES; ++i)
|
for (int i = 0; i < CHORD_NOTES; ++i)
|
||||||
{
|
{
|
||||||
set_osc_freq(&pianoOsc.noteOsc[i], chordFrequencies[chordIndex][i]);
|
set_osc_freq(&pianoOsc.noteOsc[i], chordFrequencies[chordIndex][i]);
|
||||||
set_osc_freq(&highPianoOsc.noteOsc[i], higherChordFrequencies[chordIndex][i]);
|
set_osc_freq(&highPianoOsc.noteOsc[i], higherChordFrequencies[chordIndex][i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
noise_osc_t fireCrackleOsc;
|
||||||
|
init_noise_osc(&fireCrackleOsc, time(NULL));
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
out = 0.0f; // Reset output each iteration
|
out = 0.0f; // Reset output each iteration
|
||||||
|
|
||||||
// Update the piano and high piano oscillators
|
// Update the piano and high piano oscillators
|
||||||
update_piano_osc(&pianoOsc);
|
// Update the piano oscillator
|
||||||
update_high_piano_osc(&highPianoOsc);
|
update_piano_osc(&pianoOsc, chordFrequencies, 10); // 10 for a 1 in 10 chance of silence
|
||||||
|
// Update the high piano oscillator
|
||||||
|
update_piano_osc(&highPianoOsc, higherChordFrequencies, 2); // 2 for a 1 in 2 chance of silence
|
||||||
|
|
||||||
// Mix the outputs from all oscillators
|
// Mix the outputs from all oscillators
|
||||||
for (int i = 0; i < CHORD_NOTES; ++i)
|
for (int i = 0; i < CHORD_NOTES; ++i)
|
||||||
{
|
{
|
||||||
out += pianoOsc.noteOsc[i].value + highPianoOsc.noteOsc[i].value;
|
out += pianoOsc.noteOsc[i].value + (highPianoOsc.noteOsc[i].value * -1.0f);
|
||||||
}
|
}
|
||||||
out /= CHORD_NOTES; // Correctly average the mixed notes
|
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;
|
||||||
|
|
||||||
// Increase the gain to make the signal louder
|
// Increase the gain to make the signal louder
|
||||||
float gain = 0.2f; // Adjust the gain factor as needed
|
float gain = 0.5f; // Adjust the gain factor as needed
|
||||||
out *= gain;
|
out *= gain;
|
||||||
|
|
||||||
// Ensure the signal does not exceed the maximum range
|
// Ensure the signal does not exceed the maximum range
|
||||||
if (out > 1.0f)
|
if (out > 1.0f)
|
||||||
out = 1.0f;
|
out = 1.0f;
|
||||||
if (out < -1.0f)
|
if (out < -1.0f)
|
||||||
out = 0.8f;
|
out = -1.0f;
|
||||||
|
|
||||||
// Scale to 16-bit output value
|
// Scale to 16-bit output value
|
||||||
out16 = (uint16_t)((UINT16_MAX / 2) * (0.5 + 0.5 * out));
|
out16 = (uint16_t)((UINT16_MAX / 2) * (0.5 + 0.5 * out));
|
||||||
|
@ -221,6 +203,6 @@ int main()
|
||||||
fwrite(&out16, sizeof(out16), 1, fp);
|
fwrite(&out16, sizeof(out16), 1, fp);
|
||||||
fwrite(&out16, sizeof(out16), 1, fp);
|
fwrite(&out16, sizeof(out16), 1, fp);
|
||||||
}
|
}
|
||||||
|
fclose(fp);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
Loading…
Reference in New Issue