Optimizations 1
This commit is contained in:
+45
-15
@@ -12,8 +12,8 @@ const int I2S_LRC_PIN = 10; // Left-Right Clock (GP10)
|
||||
const int I2S_DOUT_PIN = 11; // Data Out (GP11)
|
||||
|
||||
// Audio parameters
|
||||
const int SAMPLE_RATE = 44100;
|
||||
const int16_t AMPLITUDE = 16383; // Use a lower amplitude to avoid clipping (max is 32767 for 16-bit)
|
||||
const int SAMPLE_RATE = 44100 / 2;
|
||||
const int16_t AMPLITUDE = 16383 / 2; // Use a lower amplitude to avoid clipping (max is 32767 for 16-bit)
|
||||
|
||||
// Create an I2S output object
|
||||
I2S i2s(OUTPUT);
|
||||
@@ -43,6 +43,7 @@ void setupAudio() {
|
||||
|
||||
// Initialize the portable synth engine
|
||||
globalSynth = new SynthEngine(SAMPLE_RATE);
|
||||
globalSynth->loadPreset(2);
|
||||
}
|
||||
|
||||
void loopAudio() {
|
||||
@@ -51,27 +52,56 @@ void loopAudio() {
|
||||
// Every 500ms, pick a new random note to play
|
||||
if (now - lastNoteChangeTime > 500) {
|
||||
lastNoteChangeTime = now;
|
||||
int noteIndex = random(0, SCALES[currentScaleIndex].numNotes);
|
||||
int noteIndex = random(0, SCALES[currentScaleIndex].numNotes + 2);
|
||||
|
||||
// Calculate frequency based on key, scale, and octave
|
||||
const float baseFrequency = 261.63f; // C4
|
||||
float keyFrequency = baseFrequency * pow(2.0f, currentKeyIndex / 12.0f);
|
||||
int semitoneOffset = SCALES[currentScaleIndex].semitones[noteIndex];
|
||||
currentFrequency = keyFrequency * pow(2.0f, semitoneOffset / 12.0f);
|
||||
bool rest = noteIndex >= SCALES[currentScaleIndex].numNotes;
|
||||
if (!rest) {
|
||||
// Calculate frequency based on key, scale, and octave
|
||||
const float baseFrequency = 261.63f; // C4
|
||||
float keyFrequency = baseFrequency * pow(2.0f, currentKeyIndex / 12.0f);
|
||||
int semitoneOffset = SCALES[currentScaleIndex].semitones[noteIndex];
|
||||
currentFrequency = keyFrequency * pow(2.0f, semitoneOffset / 12.0f);
|
||||
} else {
|
||||
currentFrequency = 0;
|
||||
}
|
||||
|
||||
if (globalSynth) {
|
||||
globalSynth->setFrequency(currentFrequency);
|
||||
globalSynth->setGate(true); // Trigger envelope
|
||||
globalSynth->setFrequency(currentFrequency > 0 ? currentFrequency : 440.0f);
|
||||
globalSynth->setGate(!rest); // Trigger envelope
|
||||
}
|
||||
Serial.println("Playing note: " + String(currentFrequency) + " Hz");
|
||||
}
|
||||
|
||||
const int BATCH_SIZE = 16;
|
||||
|
||||
// Ensure we don't generate samples faster than the I2S can consume them.
|
||||
// We write 2 samples (Left + Right) for every 1 synth sample.
|
||||
if (i2s.availableForWrite() < BATCH_SIZE * 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Process a small batch of samples
|
||||
int16_t samples[32];
|
||||
if (globalSynth) globalSynth->process(samples, 32);
|
||||
else memset(samples, 0, sizeof(samples));
|
||||
static int16_t samples[BATCH_SIZE];
|
||||
|
||||
for (int i = 0; i < 32; ++i) {
|
||||
// Generate sound samples
|
||||
if (globalSynth) {
|
||||
// using synth engine
|
||||
globalSynth->process(samples, BATCH_SIZE);
|
||||
} else {
|
||||
// using fallback sawtooth
|
||||
for (int i = 0; i < BATCH_SIZE; ++i) {
|
||||
if (currentFrequency > 0) {
|
||||
//samples[i] = (int16_t)(sin(phase) * AMPLITUDE);
|
||||
phase += 2.0 * M_PI * currentFrequency / SAMPLE_RATE;
|
||||
if (phase >= 2.0 * M_PI) phase -= 2.0 * M_PI;
|
||||
samples[i] = phase * 0.1f * AMPLITUDE;
|
||||
} else {
|
||||
samples[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// write out stereo samples
|
||||
for (int i = 0; i < BATCH_SIZE; ++i) {
|
||||
i2s.write(samples[i]);
|
||||
i2s.write(samples[i]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user