Mozzi Polyphonic experiment

campidelli
Posts: 3
Joined: Fri Aug 23, 2024 1:05 am

Mozzi Polyphonic experiment

Postby campidelli » Fri Aug 23, 2024 1:16 am

Hey everyone, this is my first post here, thanks!

I am working on a little experiment to create a standalone instrument (a melodica, and eventually an accordion) using an ESP32 board, a PCM5102 DAC and a PAM8403 amplifier.

I managed to make it work, as you can see in the video below:
https://www.youtube.com/watch?v=rba7DDyHNXI

The problem is, as you can notice at the end of the video when I play more than one note at the same time, the sound is weird, it is like it is oscillating. I don't know if it is because of my lack of knowledge of synthesizers, ESP32 concurrency, or both :?

Anyway, this is my sketch, I hope you can give me a tip about this.

Code: main.cpp Select all


#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();
}
Cheers!

Sprite
Espressif staff
Espressif staff
Posts: 10609
Joined: Thu Nov 26, 2015 4:08 am

Re: Mozzi Polyphonic experiment

Postby Sprite » Fri Aug 23, 2024 1:39 am

Potentially adding the waveforms for the two notes makes the total go out of range for the output... normally that would wrap around, giving an instantly recognizable 'bad sound', but your libraries may clip it instead, making the beat frequency between the two notes appear instead.

Who is online

Users browsing this forum: Amazon [Bot] and 5 guests