It displays two analog-style VU meters on two 128×64 OLED displays.
The VU meters imitate the inertia and ballistics of real analog VU meters.
It acts as a USB Audio DAC (Digital-to-Analog Converter).
Add a capacitor between the reset pin of the displays and ground, and a resistor from reset to 3.3V. The values are not critical, 0.1µF and 10kΩ work fine.
You do need some way to reset the displays, without it, it won't work.
Alternatively, you could use an IO pin from the Teensy to reset the displays, but this just "wastes" a pin.
Upload the sketch, and select the Control Surface as the audio output of your computer. Connect the output of the DAC to a pair of headphones or powered speakers, and play some music.
You should see the VU meters come to life and jump around to the music.
You can now adjust the volume using the potentiometer on pin A0, and the gain/sensitivity of the meters using the potentiometer on pin A1.
None.
constexpr uint8_t SCREEN_WIDTH = 128;
constexpr uint8_t SCREEN_HEIGHT = 64;
constexpr int8_t OLED_DC = 17;
constexpr int8_t OLED_reset = -1;
constexpr int8_t OLED_CS_L = 10;
constexpr int8_t OLED_CS_R = 18;
Adafruit_SSD1306 ssd1306Display_L = {
SCREEN_WIDTH, SCREEN_HEIGHT, &SPI, OLED_DC,
OLED_reset, OLED_CS_L, SPI_Frequency,
};
Adafruit_SSD1306 ssd1306Display_R = {
SCREEN_WIDTH, SCREEN_HEIGHT, &SPI, OLED_DC,
OLED_reset, OLED_CS_R, SPI_Frequency,
};
public:
MySSD1306_DisplayInterface(Adafruit_SSD1306 &display)
if (!disp.begin())
#ifdef DIGITAL_VU
disp.setRotation(1);
#endif
}
} display_L = ssd1306Display_L, display_R = ssd1306Display_R;
AudioInputUSB audioInputUSB;
AudioMixer4 mixer_L;
AudioAnalyzeRMS rms_L;
AudioMixer4 mixer_R;
AudioAnalyzeRMS rms_R;
AudioOutputI2S audioOutputI2S;
AudioConnection patchCord1(audioInputUSB, 0, mixer_L, 0);
AudioConnection patchCord2(audioInputUSB, 0, rms_L, 0);
AudioConnection patchCord3(audioInputUSB, 1, mixer_R, 0);
AudioConnection patchCord4(audioInputUSB, 1, rms_R, 0);
AudioConnection patchCord5(mixer_L, 0, audioOutputI2S, 0);
AudioConnection patchCord6(mixer_R, 0, audioOutputI2S, 1);
#ifdef DIGITAL_VU
MCU::VUDisplay vu_display_L = {display_L, vu_L, {0, 127}, 64, 4, 1, WHITE};
MCU::VUDisplay vu_display_R = {display_R, vu_R, {0, 127}, 64, 4, 1, WHITE};
#else
display_L,
vu_L,
{63, 63},
63,
-140 * PI / 180,
100 * PI / 180,
WHITE,
};
display_R, vu_R, {63, 63}, 63, -140 * PI / 180, 100 * PI / 180, WHITE,
};
#endif
constexpr float maxGain = 5;
FilteredAnalog<> gainKnob = A1;
void setup() {
AudioMemory(8);
SPI.setMOSI(7);
FilteredAnalog<>::setupADC();
display_L.begin();
display_R.begin();
}
void loop() {
const unsigned long frametime = 1000000 /
MAX_FPS;
static unsigned long previousFrameTime = micros();
if (micros() - previousFrameTime >= frametime) {
previousFrameTime += frametime;
}
if (gainKnob.update()) {
float gain = gainKnob.getFloatValue() * maxGain;
}
}