67 lines
2.0 KiB
C++
67 lines
2.0 KiB
C++
#include "AudioThread.h"
|
|
#include "SharedState.h"
|
|
#include <I2S.h>
|
|
#include <math.h>
|
|
|
|
// I2S Pin definitions
|
|
// You may need to change these to match your hardware setup (e.g., for a specific DAC).
|
|
const int I2S_BCLK_PIN = 9; // Bit Clock (GP9)
|
|
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)
|
|
|
|
// Create an I2S output object
|
|
I2S i2s(OUTPUT);
|
|
|
|
// --- Synthesizer State ---
|
|
// Frequencies for a C-Major scale to pick from
|
|
const float NOTE_FREQUENCIES[] = {
|
|
261.63, 293.66, 329.63, 349.23, 392.00, 440.00, 493.88, 523.25
|
|
};
|
|
const int NUM_NOTES = sizeof(NOTE_FREQUENCIES) / sizeof(NOTE_FREQUENCIES[0]);
|
|
|
|
float currentFrequency = 440.0f;
|
|
double phase = 0.0;
|
|
unsigned long lastNoteChangeTime = 0;
|
|
// ---
|
|
|
|
void setupAudio() {
|
|
// Configure I2S pins
|
|
i2s.setBCLK(I2S_BCLK_PIN);
|
|
i2s.setDATA(I2S_DOUT_PIN);
|
|
|
|
// Set the sample rate and start I2S communication
|
|
i2s.setFrequency(SAMPLE_RATE);
|
|
if (!i2s.begin()) {
|
|
Serial.println("Failed to initialize I2S!");
|
|
while (1); // Halt on error
|
|
}
|
|
|
|
// Seed the random number generator from an unconnected analog pin
|
|
randomSeed(analogRead(A0));
|
|
}
|
|
|
|
void loopAudio() {
|
|
unsigned long now = millis();
|
|
|
|
// Every 500ms, pick a new random note to play
|
|
if (now - lastNoteChangeTime > 500) {
|
|
lastNoteChangeTime = now;
|
|
int noteIndex = random(0, NUM_NOTES);
|
|
currentFrequency = NOTE_FREQUENCIES[noteIndex];
|
|
Serial.println("Playing note: " + String(currentFrequency) + " Hz");
|
|
}
|
|
|
|
// Generate the sine wave sample
|
|
double phaseIncrement = 2.0 * M_PI * currentFrequency / SAMPLE_RATE;
|
|
phase = fmod(phase + phaseIncrement, 2.0 * M_PI);
|
|
int16_t sample = static_cast<int16_t>(AMPLITUDE * sin(phase));
|
|
|
|
// Write the same sample to both left and right channels (mono audio).
|
|
// This call is blocking and will wait until there is space in the DMA buffer.
|
|
i2s.write(sample);
|
|
i2s.write(sample);
|
|
} |