Making sound again
This commit is contained in:
parent
41bbfdc1d7
commit
8aa7312ed5
3
Makefile
3
Makefile
|
@ -1,6 +1,9 @@
|
||||||
FQBN = adafruit:samd:adafruit_trellis_m4
|
FQBN = adafruit:samd:adafruit_trellis_m4
|
||||||
|
UF2_MOUNT = /mnt/chromeos/removable/TRELM4BOOT
|
||||||
|
|
||||||
default: build/uilleann.ino.uf2
|
default: build/uilleann.ino.uf2
|
||||||
|
install: build/uilleann.ino.uf2
|
||||||
|
./install.sh $< $(UF2_MOUNT)
|
||||||
|
|
||||||
# uf2conv.py is covered by an MIT license.
|
# uf2conv.py is covered by an MIT license.
|
||||||
build/uf2conv.py:
|
build/uf2conv.py:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// FM Algorithms used by the DX9
|
// Various FM Algorithms
|
||||||
// Excellent write-up:
|
// Excellent write-up:
|
||||||
// https://gist.github.com/bryc/e997954473940ad97a825da4e7a496fa
|
// https://gist.github.com/bryc/e997954473940ad97a825da4e7a496fa
|
||||||
|
|
||||||
|
@ -7,8 +7,37 @@
|
||||||
// Each operator has 4 input gains and one output gain:
|
// Each operator has 4 input gains and one output gain:
|
||||||
// { 1→, 2→, 3→, 4→, →out}
|
// { 1→, 2→, 3→, 4→, →out}
|
||||||
|
|
||||||
|
// 1→
|
||||||
|
#define ALG_SIMPLE \
|
||||||
|
{ \
|
||||||
|
{0, 0, 0, 0, 1}, \
|
||||||
|
{0}, \
|
||||||
|
{0}, \
|
||||||
|
{0}, \
|
||||||
|
}
|
||||||
|
|
||||||
|
// ⮎2→1→
|
||||||
|
#define ALG_OPL2_1(feedback) \
|
||||||
|
{ \
|
||||||
|
{0, 1, 0, 0, 1}, \
|
||||||
|
{0, feedback, 0, 0, 0}, \
|
||||||
|
{0}, \
|
||||||
|
{0}, \
|
||||||
|
}
|
||||||
|
|
||||||
|
// ⮎2→
|
||||||
|
// 1→
|
||||||
|
#define ALG_OPL2_2(feedback) \
|
||||||
|
{ \
|
||||||
|
{0, 0, 0, 0, 1} \
|
||||||
|
{0, feedback, 0, 0, 1} \
|
||||||
|
{0}, \
|
||||||
|
{0}, \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ⮎4→3→2→1→
|
// ⮎4→3→2→1→
|
||||||
#define DX9_ALG_1(feedback) \
|
#define ALG_DX9_1(feedback) \
|
||||||
{ \
|
{ \
|
||||||
{0, 1, 0, 0, 1}, \
|
{0, 1, 0, 0, 1}, \
|
||||||
{0, 0, 1, 0, 0}, \
|
{0, 0, 1, 0, 0}, \
|
||||||
|
@ -18,7 +47,7 @@
|
||||||
|
|
||||||
// ⮎4⬎
|
// ⮎4⬎
|
||||||
// 3→2→1→
|
// 3→2→1→
|
||||||
#define DX9_ALG_2(feedback) \
|
#define ALG_DX9_2(feedback) \
|
||||||
{ \
|
{ \
|
||||||
{0, 1, 0, 0, 1}, \
|
{0, 1, 0, 0, 1}, \
|
||||||
{0, 0, 1, 1, 0}, \
|
{0, 0, 1, 1, 0}, \
|
||||||
|
@ -28,7 +57,7 @@
|
||||||
|
|
||||||
// ⮎4⬎
|
// ⮎4⬎
|
||||||
// 3→2→1→
|
// 3→2→1→
|
||||||
#define DX9_ALG_3(feedback) \
|
#define ALG_DX9_3(feedback) \
|
||||||
{ \
|
{ \
|
||||||
{0, 1, 0, 1, 1}, \
|
{0, 1, 0, 1, 1}, \
|
||||||
{0, 0, 1, 0, 0}, \
|
{0, 0, 1, 0, 0}, \
|
||||||
|
@ -38,7 +67,7 @@
|
||||||
|
|
||||||
// ⮎4→3⬎
|
// ⮎4→3⬎
|
||||||
// 2→1→
|
// 2→1→
|
||||||
#define DX9_ALG_4(feedback) \
|
#define ALG_DX9_4(feedback) \
|
||||||
{ \
|
{ \
|
||||||
{0, 1, 0, 1, 1}, \
|
{0, 1, 0, 1, 1}, \
|
||||||
{0, 0, 1, 0, 0}, \
|
{0, 0, 1, 0, 0}, \
|
||||||
|
@ -48,7 +77,7 @@
|
||||||
|
|
||||||
// ⮎4→3→
|
// ⮎4→3→
|
||||||
// 2→1→
|
// 2→1→
|
||||||
#define DX9_ALG_5(feedback) \
|
#define ALG_DX9_5(feedback) \
|
||||||
{ \
|
{ \
|
||||||
{0, 1, 0, 0, 1}, \
|
{0, 1, 0, 0, 1}, \
|
||||||
{0, 0, 0, 0, 0}, \
|
{0, 0, 0, 0, 0}, \
|
||||||
|
@ -59,7 +88,7 @@
|
||||||
// 1→
|
// 1→
|
||||||
// ⮎4→2→
|
// ⮎4→2→
|
||||||
// 3→
|
// 3→
|
||||||
#define DX9_ALG_6(feedback) \
|
#define ALG_DX9_6(feedback) \
|
||||||
{ \
|
{ \
|
||||||
{0, 0, 0, 0, 1}, \
|
{0, 0, 0, 0, 1}, \
|
||||||
{0, 0, 0, 1, 1}, \
|
{0, 0, 0, 1, 1}, \
|
||||||
|
@ -70,7 +99,7 @@
|
||||||
// 1→
|
// 1→
|
||||||
// 2→
|
// 2→
|
||||||
// ⮎4→3→
|
// ⮎4→3→
|
||||||
#define DX9_ALG_7(feedback) \
|
#define ALG_DX9_7(feedback) \
|
||||||
{ \
|
{ \
|
||||||
{0, 0, 0, 0, 1}, \
|
{0, 0, 0, 0, 1}, \
|
||||||
{0, 0, 0, 0, 1}, \
|
{0, 0, 0, 0, 1}, \
|
||||||
|
@ -82,7 +111,7 @@
|
||||||
// 2→
|
// 2→
|
||||||
// 3→
|
// 3→
|
||||||
// ⮎4→
|
// ⮎4→
|
||||||
#define DX9_ALG_8(feedback) \
|
#define ALG_DX9_8(feedback) \
|
||||||
{ \
|
{ \
|
||||||
{0, 0, 0, 0, 1}, \
|
{0, 0, 0, 0, 1}, \
|
||||||
{0, 0, 0, 0, 1}, \
|
{0, 0, 0, 0, 1}, \
|
|
@ -0,0 +1,15 @@
|
||||||
|
#! /bin/sh
|
||||||
|
|
||||||
|
src=$1
|
||||||
|
dst=$2
|
||||||
|
|
||||||
|
info=$dst/INFO_UF2.txt
|
||||||
|
echo -n "Waiting for $info to appear..."
|
||||||
|
while ! [ -f $info ]; do
|
||||||
|
echo -n "."
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
echo "👍"
|
||||||
|
|
||||||
|
cp $src $dst
|
||||||
|
echo "Installed!"
|
|
@ -19,12 +19,9 @@ void setupJustPitches(uint8_t baseNote, float basePitch) {
|
||||||
JustPitches[baseNote + 7] = basePitch * 3 / 2; // A
|
JustPitches[baseNote + 7] = basePitch * 3 / 2; // A
|
||||||
JustPitches[baseNote + 8] = basePitch * 8 / 5; // Bb
|
JustPitches[baseNote + 8] = basePitch * 8 / 5; // Bb
|
||||||
JustPitches[baseNote + 9] = basePitch * 5 / 3; // B
|
JustPitches[baseNote + 9] = basePitch * 5 / 3; // B
|
||||||
JustPitches[baseNote + 10] = basePitch * 9 / 5; // C
|
JustPitches[baseNote + 10] = basePitch * 16 / 9; // C (fourth up from G)
|
||||||
JustPitches[baseNote + 11] = basePitch * 15 / 8; // C#
|
JustPitches[baseNote + 11] = basePitch * 15 / 8; // C#
|
||||||
|
|
||||||
// Two fourths up from the base pitch, so G major scale sounds right
|
|
||||||
JustPitches[baseNote + 11] = basePitch * 8 / 3; // C#
|
|
||||||
|
|
||||||
// Octaves
|
// Octaves
|
||||||
for (int note = baseNote; note < baseNote + 12; note++) {
|
for (int note = baseNote; note < baseNote + 12; note++) {
|
||||||
for (int i = 1; i < 9; i++) {
|
for (int i = 1; i < 9; i++) {
|
||||||
|
|
26
patches.h
26
patches.h
|
@ -1,24 +1,30 @@
|
||||||
// "Factory" patches
|
// "Factory" patches
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "dx9.h"
|
#include "algorithms.h"
|
||||||
|
|
||||||
// Waveform, offset, multiplier, delay, attack, holdAmp, hold, decay, sustainAmp, release
|
// Waveform, offset, multiplier, delay, attack, holdAmp, hold, decay, sustainAmp, release
|
||||||
FMPatch Bank[] = {
|
FMPatch Bank[] = {
|
||||||
{
|
{
|
||||||
"Venus Oboe",
|
"Square",
|
||||||
DX9_ALG_5(0),
|
ALG_SIMPLE,
|
||||||
{
|
{
|
||||||
// Waveform off mult del att hldA hld dec susA rel
|
// Waveform offs mult dely attk hldA hld decy susA rels
|
||||||
{WAVEFORM_SINE, 0, 1.00, 0, 10.5, 1.0, 10.5, 0, 0.75, 5},
|
{WAVEFORM_SQUARE, 0, 1.00, 0, 10.5, 0.8, 10.5, 10, 0.50, 5},
|
||||||
{WAVEFORM_SINE, 0, 4.00, 0, 10.5, 1.0, 10.5, 0, 0.80, 5},
|
},
|
||||||
{WAVEFORM_SINE, 0, 8.00, 0, 10.5, 1.0, 10.5, 0, 0.50, 5},
|
},
|
||||||
{WAVEFORM_SINE, 0, 16.00, 0, 10.5, 1.0, 50.0, 0, 0.75, 5},
|
{
|
||||||
|
"Tubey",
|
||||||
|
ALG_OPL2_1(0),
|
||||||
|
{
|
||||||
|
// Waveform offs mult dely attk hldA hld decy susA rels
|
||||||
|
{WAVEFORM_SINE, 0, 1.00, 0, 10.5, 1.0, 10.5, 10, 0.80, 5},
|
||||||
|
{WAVEFORM_SINE, 0, 8.00, 0, 10.5, 0.2, 10.5, 10, 0.10, 5},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"IWantPizza",
|
"IWantPizza",
|
||||||
DX9_ALG_1(0),
|
ALG_DX9_1(0),
|
||||||
{
|
{
|
||||||
{WAVEFORM_SINE, 0, 4.00, 0, 10.5, 1.0, 10.5, 0, 0.35, 20},
|
{WAVEFORM_SINE, 0, 4.00, 0, 10.5, 1.0, 10.5, 0, 0.35, 20},
|
||||||
{WAVEFORM_SINE, 0, 1.00, 0, 10.5, 1.0, 10.5, 0, 0.30, 20},
|
{WAVEFORM_SINE, 0, 1.00, 0, 10.5, 1.0, 10.5, 0, 0.30, 20},
|
||||||
|
@ -28,7 +34,7 @@ FMPatch Bank[] = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Ray Gun",
|
"Ray Gun",
|
||||||
DX9_ALG_1(0),
|
ALG_DX9_1(0),
|
||||||
{
|
{
|
||||||
{WAVEFORM_SINE, 0, 1.00, 0, 10.5, 1.0, 10.5, 0, 0.35, 20},
|
{WAVEFORM_SINE, 0, 1.00, 0, 10.5, 1.0, 10.5, 0, 0.35, 20},
|
||||||
{WAVEFORM_SINE, 0, 1.00, 0, 10.5, 1.0, 10.5, 0, 0.30, 20},
|
{WAVEFORM_SINE, 0, 1.00, 0, 10.5, 1.0, 10.5, 0, 0.30, 20},
|
||||||
|
|
|
@ -20,6 +20,7 @@ void FMVoiceLoadPatch(FMVoice *v, FMPatch *p) {
|
||||||
}
|
}
|
||||||
v->outputMixer.gain(i, p->gains[i][NUM_OPERATORS]);
|
v->outputMixer.gain(i, p->gains[i][NUM_OPERATORS]);
|
||||||
}
|
}
|
||||||
|
v->patch = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FMVoiceSetPitch(FMVoice *v, float freq) {
|
void FMVoiceSetPitch(FMVoice *v, float freq) {
|
||||||
|
|
4
synth.h
4
synth.h
|
@ -93,11 +93,11 @@ typedef struct FMVoice {
|
||||||
#define FMOperatorWiring(name, i) \
|
#define FMOperatorWiring(name, i) \
|
||||||
{name.mixers[i], 0, name.oscillators[i], 0}, \
|
{name.mixers[i], 0, name.oscillators[i], 0}, \
|
||||||
{name.oscillators[i], 0, name.envelopes[i], 0}, \
|
{name.oscillators[i], 0, name.envelopes[i], 0}, \
|
||||||
{name.envelopes[i], 0, name.outputMixer, i}, \
|
|
||||||
{name.envelopes[i], 0, name.mixers[0], i}, \
|
{name.envelopes[i], 0, name.mixers[0], i}, \
|
||||||
{name.envelopes[i], 0, name.mixers[1], i}, \
|
{name.envelopes[i], 0, name.mixers[1], i}, \
|
||||||
{name.envelopes[i], 0, name.mixers[2], i}, \
|
{name.envelopes[i], 0, name.mixers[2], i}, \
|
||||||
{name.envelopes[i], 0, name.mixers[3], i}
|
{name.envelopes[i], 0, name.mixers[3], i}, \
|
||||||
|
{name.envelopes[i], 0, name.outputMixer, i}
|
||||||
|
|
||||||
/** FMVoiceWiring outputs AudioConnection initializer to wire one FMVoice
|
/** FMVoiceWiring outputs AudioConnection initializer to wire one FMVoice
|
||||||
*/
|
*/
|
||||||
|
|
23
uilleann.ino
23
uilleann.ino
|
@ -9,6 +9,7 @@
|
||||||
#include "notes.h"
|
#include "notes.h"
|
||||||
#include "fingering.h"
|
#include "fingering.h"
|
||||||
|
|
||||||
|
#define DEBUG
|
||||||
#define KNEE_OFFSET 0
|
#define KNEE_OFFSET 0
|
||||||
#define KEY_OFFSET 2
|
#define KEY_OFFSET 2
|
||||||
|
|
||||||
|
@ -23,7 +24,16 @@ AudioMixer4 mixL;
|
||||||
AudioMixer4 mixR;
|
AudioMixer4 mixR;
|
||||||
AudioOutputAnalogStereo dacs1;
|
AudioOutputAnalogStereo dacs1;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
AudioSynthNoiseWhite debug;
|
||||||
|
#endif
|
||||||
|
|
||||||
AudioConnection FMVoicePatchCords[] = {
|
AudioConnection FMVoicePatchCords[] = {
|
||||||
|
#ifdef DEBUG
|
||||||
|
{debug, 0, mixL, 3},
|
||||||
|
{debug, 0, mixR, 3},
|
||||||
|
#endif
|
||||||
|
|
||||||
{Chanter.outputMixer, 0, biquad1, 0},
|
{Chanter.outputMixer, 0, biquad1, 0},
|
||||||
{biquad1, 0, mixL, 0},
|
{biquad1, 0, mixL, 0},
|
||||||
{biquad1, 0, mixR, 0},
|
{biquad1, 0, mixR, 0},
|
||||||
|
@ -61,7 +71,6 @@ Adafruit_NeoTrellisM4 trellis = Adafruit_NeoTrellisM4();
|
||||||
MicroOLED oled(9, 1);
|
MicroOLED oled(9, 1);
|
||||||
QwiicButton bag;
|
QwiicButton bag;
|
||||||
|
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
setupJustPitches(NOTE_D4, PITCH_D4);
|
setupJustPitches(NOTE_D4, PITCH_D4);
|
||||||
pinMode(LED_BUILTIN, OUTPUT);
|
pinMode(LED_BUILTIN, OUTPUT);
|
||||||
|
@ -102,6 +111,12 @@ void setup() {
|
||||||
// Initialize processor and memory measurements
|
// Initialize processor and memory measurements
|
||||||
AudioProcessorUsageMaxReset();
|
AudioProcessorUsageMaxReset();
|
||||||
AudioMemoryUsageMaxReset();
|
AudioMemoryUsageMaxReset();
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
debug.amplitude(0.1);
|
||||||
|
mixL.gain(3, 0.1);
|
||||||
|
mixR.gain(3, 0.1);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#define BUTTON_UP 0
|
#define BUTTON_UP 0
|
||||||
|
@ -152,8 +167,10 @@ void updateTunables(uint8_t buttons, int note) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mixL.gain(0, gain);
|
for (int i=0; i<3; i++) {
|
||||||
mixR.gain(0, gain);
|
mixL.gain(i, gain);
|
||||||
|
mixR.gain(i, gain);
|
||||||
|
}
|
||||||
trellis.setPixelColor(BUTTON_VOLUME, trellis.ColorHSV(uint16_t(gain * 65535), 255, 80));
|
trellis.setPixelColor(BUTTON_VOLUME, trellis.ColorHSV(uint16_t(gain * 65535), 255, 80));
|
||||||
|
|
||||||
if (!note || (note == NOTE_CS5)) {
|
if (!note || (note == NOTE_CS5)) {
|
||||||
|
|
Loading…
Reference in New Issue