Hey, we have some sound being triggered now!
Only four notes (C, D, E and F) sampling at the octave 4.
Is it Polyphonic? Hum, sort of? I mean, it plays the four notes at the same time. Is it pleasant to hear? Nope, not at all (yet!).
Here are all the pieces together:

And the sketch that is producing this wonderful sound haha:
#include "MozziConfigValues.h"
#define MOZZI_AUDIO_MODE MOZZI_OUTPUT_I2S_DAC
#define MOZZI_I2S_PIN_BCK 26
#define MOZZI_I2S_PIN_WS 25
#define MOZZI_I2S_PIN_DATA 22
#define MOZZI_CONTROL_RATE 256
#include <Arduino.h>
#include <Keypad.h>
#include <Mozzi.h>
#include <Oscil.h>
#include <tables/cos8192_int8.h>
#include <mozzi_midi.h>
#include <ADSR.h>
// Envelope controllers
#define ATTACK 100
#define DECAY 200
#define SUSTAIN 500 // Reduced sustain time
#define RELEASE 500 // Reduced release time
#define ATTACK_LEVEL 127 // Lower maximum amplitude level
#define DECAY_LEVEL 127 // Lower decay level
// SETTINGS
#define OCTAVE 4
#define MAX_POLYPHONY LIST_MAX
// Keypad configuration
const byte ROWS = 2;
const byte COLS = 2;
byte key_indexes[ROWS][COLS] = {
{1, 2},
{3, 4}
};
byte rowPins[ROWS] = {14, 12};
byte colPins[COLS] = {32, 33};
Keypad keypad = Keypad(makeKeymap(key_indexes), rowPins, colPins, ROWS, COLS);
// Voices
struct Voice {
Oscil<COS8192_NUM_CELLS, AUDIO_RATE> osc;
ADSR<MOZZI_CONTROL_RATE, AUDIO_RATE> env;
byte note;
};
Voice voices[MAX_POLYPHONY];
void noteOff(byte note) {
for (int i = 0; i < MAX_POLYPHONY; i++) {
if (voices[i].note == note) {
voices[i].env.noteOff();
voices[i].note = 0;
Serial.print("Note Off: ");
Serial.println(note);
return;
}
}
}
void noteOn(byte note) {
int noteIndex = 0;
for (; noteIndex < MAX_POLYPHONY; noteIndex++) {
if (!voices[noteIndex].env.playing()) {
// This voice is not playing, let's use it then
break;
}
if (voices[noteIndex].note == note) {
// This note is already playing, ignore
return;
}
if (noteIndex + 1 == MAX_POLYPHONY) {
// This is the last voice and it is occupied,
// let's steal the oldest voice (index 0) and reuse it
noteIndex = 0;
break;
}
}
voices[noteIndex].note = note;
voices[noteIndex].osc.setFreq(mtof(note));
voices[noteIndex].env.noteOn();
Serial.print("Note On: ");
Serial.println(note);
}
void play() {
if (keypad.getKeys()) {
for (int i = 0; i < LIST_MAX; i++) {
if (keypad.key[i].stateChanged) {
byte note = (OCTAVE * 12) + 11 + keypad.key[i].kchar;
KeyState state = keypad.key[i].kstate;
if (state == PRESSED) {
noteOn(note);
} else if (state == RELEASED) {
noteOff(note);
}
}
}
}
}
void setup() {
Serial.begin(115200);
for (int i = 0; i < MAX_POLYPHONY; i++) {
voices[i].osc.setTable(COS8192_DATA);
voices[i].env.setADLevels(ATTACK_LEVEL, DECAY_LEVEL);
voices[i].env.setTimes(ATTACK, DECAY, SUSTAIN, RELEASE);
}
startMozzi(MOZZI_CONTROL_RATE);
}
void updateControl() {
play();
for (int i = 0; i < MAX_POLYPHONY; i++) {
voices[i].env.update();
}
}
AudioOutput updateAudio() {
long currentSample = 0;
for (unsigned int i = 0; i < MAX_POLYPHONY; i++) {
if (voices[i].env.playing()) {
currentSample += voices[i].osc.next() * voices[i].env.next();
}
}
return MonoOutput::fromAlmostNBit(20, currentSample);
}
void loop() {
audioHook();
}
Next step: more buttons!
Bruno Campidelli
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.