summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arduino-monosynth.ino128
1 files changed, 93 insertions, 35 deletions
diff --git a/arduino-monosynth.ino b/arduino-monosynth.ino
index 87f99a2..df36f5c 100644
--- a/arduino-monosynth.ino
+++ b/arduino-monosynth.ino
@@ -26,7 +26,9 @@
#include <ADSR.h>
#include <mozzi_fixmath.h>
#include <Portamento.h>
-#include <tables/cos2048_int8.h> // table for Oscils to play
+#include <tables/cos512_int8.h> // table for Oscils to play
+#include <tables/square_analogue512_int8.h>
+#include <tables/triangle_analogue512_int8.h>
#include <tables/saw_analogue512_int8.h> // table for Oscils to play
// use #define for CONTROL_RATE, not a constant
@@ -35,12 +37,18 @@
// Mozzi example uses COS waves for carrier and modulator
// Shit gets brutal very fast if you use a saw/square carrier
// Shit gets subtly more brutal if you use smaller wavetables (fewer samples per cycle)
-Oscil<SAW_ANALOGUE512_NUM_CELLS, AUDIO_RATE> oscCarrierMaster(SAW_ANALOGUE512_DATA);
-Oscil<SAW_ANALOGUE512_NUM_CELLS, AUDIO_RATE> oscCarrierSlave1(SAW_ANALOGUE512_DATA);
-Oscil<SAW_ANALOGUE512_NUM_CELLS, AUDIO_RATE> oscCarrierSlave2(SAW_ANALOGUE512_DATA);
+Oscil<SAW_ANALOGUE512_NUM_CELLS, AUDIO_RATE> oscils[3] =
+ {(SAW_ANALOGUE512_DATA), (SAW_ANALOGUE512_DATA), (SAW_ANALOGUE512_DATA)};
-Oscil<COS2048_NUM_CELLS, AUDIO_RATE> oscModulator(COS2048_DATA);
-Oscil<COS2048_NUM_CELLS, AUDIO_RATE> oscLFO(COS2048_DATA);
+Oscil<COS512_NUM_CELLS, AUDIO_RATE> oscModulator(COS512_DATA);
+Oscil<COS512_NUM_CELLS, AUDIO_RATE> oscLFO(COS512_DATA);
+
+enum TableType {
+ Cosine,
+ Square,
+ Saw,
+ Triangle
+} currentTable;
// envelope generator
ADSR <CONTROL_RATE, AUDIO_RATE> envelope;
@@ -49,6 +57,7 @@ Portamento <CONTROL_RATE>aPortamento;
MIDI_CREATE_DEFAULT_INSTANCE();
#define LED 13 // to see if MIDI is being recieved
+#define TABLE_TOGGLE 10
unsigned long vibrato = 0;
float carrierFreq = 10.f;
@@ -57,7 +66,11 @@ float modDepth = 0.5;
float amplitude = 0.f;
float modOffset = 1;
byte lastnote = 0;
-int portSpeed = 100;
+//int portSpeed = 100;
+byte detuneCents = 0;
+
+byte tableToggleTimer = 0;
+byte tableToggleTimerMax = 1000;
float detuneCoefficient1 = 1;
float detuneCoefficient2 = 1;
@@ -73,18 +86,19 @@ float modOffsets[] = {
void setup()
{
pinMode(LED, OUTPUT);
-
+ pinMode(TABLE_TOGGLE, INPUT);
+
MIDI.begin(MIDI_CHANNEL_OMNI);
MIDI.setHandleNoteOn(HandleNoteOn);
MIDI.setHandleNoteOff(HandleNoteOff);
MIDI.setHandleControlChange(HandleControlChange);
MIDI.setHandlePitchBend(HandlePitchBend);
- MIDI.setHandleProgramChange(HandleProgramChange);
- MIDI.setHandleContinue(HandleContinue);
+ MIDI.setHandleProgramChange(HandleProgramChange);
envelope.setADLevels(255, 174);
- envelope.setTimes(10, 50, 50, 1000); // 20000 is so the note will sustain 20 seconds unless a noteOff comes
- aPortamento.setTime(50u);
+ envelope.setTimes(188, 345, 65000000, 345); // 20000 is so the note will sustain 20 seconds unless a noteOff comes
+ envelope.setSustainLevel(255);
+ //aPortamento.setTime(50u);
oscLFO.setFreq(10); // default frequency
startMozzi(CONTROL_RATE);
@@ -99,26 +113,15 @@ void HandleProgramChange (byte channel, byte number)
void HandleNoteOn(byte channel, byte note, byte velocity)
{
- aPortamento.start((byte)(((int) note) - 5));
+ //aPortamento.start((byte)(((int) note) - 5));
lastnote = note;
envelope.noteOn();
-
+ oscLFO.setPhase(0);
+ oscModulator.setPhase(0);
digitalWrite(LED, HIGH);
}
-void HandleContinue ()
-{
- portSpeed += 100;
-
- if (portSpeed > 500)
- {
- portSpeed = 0;
- }
-
- aPortamento.setTime(portSpeed);
-}
-
void HandleNoteOff(byte channel, byte note, byte velocity)
{
if (note == lastnote)
@@ -132,6 +135,7 @@ void HandlePitchBend (byte channel, int bend)
{
float shifted = float ((bend + 8500) / 2048.f) + 0.1f;
oscLFO.setFreq(shifted);
+
}
void HandleControlChange (byte channel, byte number, byte value)
@@ -151,21 +155,65 @@ void HandleControlChange (byte channel, byte number, byte value)
}
}
+void readPotsAndUpdate() {
+ if (tableToggleTimer > tableToggleTimerMax) {
+ byte toggled = digitalRead(TABLE_TOGGLE);
+ digitalWrite(LED, toggled);
+ if (toggled) {
+ currentTable = (TableType)(((byte)currentTable + 1) % 4);
+ tableToggleTimer = 0;
+ }
+ } else {
+ tableToggleTimer++;
+ }
+
+ /*
+ int pot0 = mozziAnalogRead(0);
+ if (currentTable != Cosine && pot0 < 256) {
+ oscCarrierMaster.setTable(COS512_DATA);
+ oscCarrierSlave1.setTable(COS512_DATA);
+ oscCarrierSlave2.setTable(COS512_DATA);
+ currentTable = Cosine;
+ } else if (currentTable != Saw && pot0 < 512) {
+ oscCarrierMaster.setTable(SAW_ANALOGUE512_DATA);
+ oscCarrierSlave1.setTable(SAW_ANALOGUE512_DATA);
+ oscCarrierSlave2.setTable(SAW_ANALOGUE512_DATA);
+ currentTable = Saw;
+ } else if (currentTable != Square && pot0 < 768) {
+ oscCarrierMaster.setTable(SQUARE_ANALOGUE512_DATA);
+ oscCarrierSlave1.setTable(SQUARE_ANALOGUE512_DATA);
+ oscCarrierSlave2.setTable(SQUARE_ANALOGUE512_DATA);
+ currentTable = Square;
+ } else if (currentTable != Triangle && pot0 <= 1024) {
+ oscCarrierMaster.setTable(TRIANGLE_ANALOGUE512_DATA);
+ oscCarrierSlave1.setTable(TRIANGLE_ANALOGUE512_DATA);
+ oscCarrierSlave2.setTable(TRIANGLE_ANALOGUE512_DATA);
+ currentTable = Triangle;
+ }
+ */
+ int pot1 = mozziAnalogRead(1);
+ detuneCents = map(pot1, 0, 1024, 0, 100);
+}
+
void updateControl()
{
MIDI.read();
envelope.update();
- carrierFreq = Q16n16_to_float (aPortamento.next()); //NB presumably returns frequency as Q16n16
+ carrierFreq = mtof(lastnote);
modFreq = carrierFreq * modOffset;
- const unsigned short cents = 40;
- detuneCoefficient1 = 1 + 0.0005946 * cents;
- detuneCoefficient2 = 1 - 0.0005946 * cents;
+ // update oscil types
+ readPotsAndUpdate();
+
+ detuneCoefficient1 = 1 + 0.0005946 * detuneCents;
+ detuneCoefficient2 = 1 - 0.0005946 * detuneCents;
+
+
// set carrier frequencies
- oscCarrierMaster.setFreq(carrierFreq);
- oscCarrierSlave1.setFreq(carrierFreq * detuneCoefficient1);
- oscCarrierSlave2.setFreq(carrierFreq * detuneCoefficient2);
+ oscils[0].setFreq(carrierFreq);
+ oscils[1].setFreq(carrierFreq * detuneCoefficient1);
+ oscils[2].setFreq(carrierFreq * detuneCoefficient2);
oscModulator.setFreq(modFreq);
}
@@ -174,8 +222,18 @@ int updateAudio()
{
vibrato = (unsigned long) (oscLFO.next() * oscModulator.next()) >> 7;
vibrato *= (unsigned long) (carrierFreq * modDepth) >> 3;
- int carrierSum = (oscCarrierMaster.phMod(vibrato) + oscCarrierSlave1.phMod(vibrato) + oscCarrierSlave2.phMod(vibrato)) >> 3;
- return (int) (carrierSum * (envelope.next())) >> 8;
+ //int carrierSum = (oscCarrierMaster.phMod(vibrato) >> 3) + (oscCarrierSlave1.phMod(vibrato) >> 3) + (oscCarrierSlave2.phMod(vibrato) >> 3);
+
+ int carrierSum = 0;
+ for (int i = 0; i < sizeof(oscils)/sizeof(oscils[0]); i++) {
+ carrierSum += (oscils[i].next() >> 3);
+ }
+
+ int total = (carrierSum * (envelope.next() >> 1)) >> 8;
+ if (abs(total) < 5)
+ return 0;
+ else
+ return total;
}
void loop()