From fe929b835e59a17b6e6b5cdaa9995908e6a6d67b Mon Sep 17 00:00:00 2001 From: Jakob Bak Date: Tue, 5 Feb 2013 10:23:08 +0100 Subject: [PATCH] Updated Music.h and added MIDI functionality to it --- hardware/eagle/v1/mm.controller.v1.pdf | Bin 0 -> 44999 bytes software/lib/MMM/Music.h | 481 +++++++++++++++++++++---- 2 files changed, 406 insertions(+), 75 deletions(-) create mode 100644 hardware/eagle/v1/mm.controller.v1.pdf diff --git a/hardware/eagle/v1/mm.controller.v1.pdf b/hardware/eagle/v1/mm.controller.v1.pdf new file mode 100644 index 0000000000000000000000000000000000000000..8b77b731eaecc7bf03fc95edbf1ea5d18ef1611a GIT binary patch literal 44999 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 L&#$Vl#{B;P+xA4I literal 0 HcmV?d00001 diff --git a/software/lib/MMM/Music.h b/software/lib/MMM/Music.h index 4b4e9ba..59ce681 100644 --- a/software/lib/MMM/Music.h +++ b/software/lib/MMM/Music.h @@ -25,49 +25,114 @@ #ifndef Music_h // include guard #define Music_h +//#include // see if needed #include "Arduino.h" #include #include #include - #include "Wavetable.h" + + + // current sample rate is 15625 as defined in the init() section #define SAMPLE_RATE 15625 -#ifndef NUM_OSCILLATORS - #define NUM_OSCILLATORS 1 -#elif (NUM_OSCILLATORS == 1)||(NUM_OSCILLATORS == 2)||(NUM_OSCILLATORS == 3) -#else -#error NUM_OSCILLATORS shall be 1, 2 or 3 -#endif - -#ifndef BIT_DEPTH -#define BIT_DEPTH 8 -#elif (BIT_DEPTH == 8)||(BIT_DEPTH == 12) -#else -#error BIT_DEPTH shall be 8 or 12 -#endif - - -// Maximum possible value for amplification envelope -#define MAX_ENV_GAIN 65535 - - -// Table of MIDI note values to frequency in Hertz -prog_uint16_t hertsTable[] PROGMEM = {8,8,9,9,10,10,11,12,12,13,14,15,16,17,18,19,20,21,23,24,25,27,29,30,32,34,36,38,41,43,46,48,51,54,58,61,65,69,73,77,82,87,92,97,103,109,116,123,130,138,146,155,164,174,184,195,207,219,233,246,261,277,293,311,329,349,369,391,415,440,466,493,523,554,587,622,659,698,739,783,830,880,932,987,1046,1108,1174,1244,1318,1396,1479,1567,1661,1760,1864,1975,2093,2217,2349,2489,2637,2793,2959,3135,3322,3520,3729,3951,4186,4434,4698,4978,5274,5587,5919,6271,6644,7040,7458,7902,8372,8869,9397,9956,10548,11175,11839,12543}; - -prog_uint32_t envTimeTable[] PROGMEM = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,33,34,35,36,37,38,39,41,42,43,45,46,48,49,51,53,55,57,59,61,63,65,67,70,73,75,78,81,85,88,92,96,100,104,109,114,119,125,131,138,146,154,163,172,183,195,209,225,242,261,284,310,341,379,425,482,556,654,792,998,1342,2030,4095}; - -float semitoneTable[] = {0.25,0.2648658,0.2806155,0.29730177,0.31498027,0.33370996,0.35355338,0.37457678,0.39685026,0.4204482,0.44544938,0.47193715,0.5,0.5297315,0.561231,0.59460354,0.62996054,0.6674199,0.70710677,0.74915355,0.7937005,0.8408964,0.8908987,0.9438743,1.0,1.0594631,1.122462,1.1892071,1.2599211,1.3348398,1.4142135,1.4983071,1.587401,1.6817929,1.7817974,1.8877486,2.0,2.1189263,2.244924,2.3784142,2.5198421,2.6696796,2.828427,2.9966142,3.174802,3.3635857,3.563595,3.7754972,4.0}; - // Defining which pins the SPI interface is connected to. #define SPI_SCK 5 #define SPI_MOSI 3 +// Checking of NUM_OSCILLATORS is set, and if not, default to 1 oscillator +#ifndef NUM_OSCILLATORS + #define NUM_OSCILLATORS 1 +#elif (NUM_OSCILLATORS == 1)||(NUM_OSCILLATORS == 2)||(NUM_OSCILLATORS == 3) +#else + #error NUM_OSCILLATORS shall be 1, 2 or 3 +#endif + +// Checking of BIT_DEPTH is set, and if not, default to 8bit +#ifndef BIT_DEPTH + #define BIT_DEPTH 8 +#elif (BIT_DEPTH == 8)||(BIT_DEPTH == 12) +#else + #error BIT_DEPTH shall be 8 or 12 +#endif + +// Shortnames for waveforms +#define SINE 0 +#define SQUARE 1 +#define PULSE 2 +#define TRIANGLE 3 +#define SAW 4 +#define FUZZ 5 +#define DIGI1 6 +#define DIGI2 7 +#define DIGI3 8 +#define DIGI4 9 +#define NOISE 10 +#define DIGI6 11 +#define TAN1 12 +#define TAN2 13 +#define TAN3 14 +#define TAN4 15 + +// Maximum possible value for amplification envelope in audio code +#define MAX_ENV_GAIN 65535 + +// MIDI specific constants +#ifndef MIDI_CHANNEL + #define MIDI_CHANNEL 1 +#elif (MIDI_CHANNEL > 0)&&(MIDI_CHANNEL < 17) +#else + #error MIDI_CHANNEL should be between 1 - 16 +#endif + +//synth parameters as MIDI controller numbers +#define DETUNE 4 +#define WAVEFORM 5 +#define PORTAMENTO 6 // not implemented yet + +#define FREQUENCY1 10 +#define SEMITONE1 11 +#define DETUNE1 12 +#define GAIN1 13 +#define WAVEFORM1 14 + +#define FREQUENCY2 20 +#define SEMITONE2 21 +#define DETUNE2 22 +#define GAIN2 23 +#define WAVEFORM2 24 + +#define FREQUENCY3 30 +#define SEMITONE3 31 +#define DETUNE3 32 +#define GAIN3 33 +#define WAVEFORM3 34 + +#define ENV_ATTACK 114 +#define ENV_DECAY 115 +#define ENV_SUSTAIN 116 +#define ENV_RELEASE 117 + + + +// Table of MIDI note values to frequency in Hertz +prog_uint16_t hertzTable[] PROGMEM = {8,8,9,9,10,10,11,12,12,13,14,15,16,17,18,19,20,21,23,24,25,27,29,30,32,34,36,38,41,43,46,48,51,54,58,61,65,69,73,77,82,87,92,97,103,109,116,123,130,138,146,155,164,174,184,195,207,219,233,246,261,277,293,311,329,349,369,391,415,440,466,493,523,554,587,622,659,698,739,783,830,880,932,987,1046,1108,1174,1244,1318,1396,1479,1567,1661,1760,1864,1975,2093,2217,2349,2489,2637,2793,2959,3135,3322,3520,3729,3951,4186,4434,4698,4978,5274,5587,5919,6271,6644,7040,7458,7902,8372,8869,9397,9956,10548,11175,11839,12543}; + +// Used in the functions that set the envelope timing +prog_uint32_t envTimeTable[] PROGMEM = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,73,75,77,79,81,83,85,87,89,92,95,98,101,104,108,112,116,120,124,128,132,136,140,145,150,155,160,165,170,176,182,188,194,201,208,215,222,230,238,247,257,268,280,293,307,322,341,379,425,482,556,654,792,998,1342,2030,4095}; + +float semitoneTable[] = {0.25,0.2648658,0.2806155,0.29730177,0.31498027,0.33370996,0.35355338,0.37457678,0.39685026,0.4204482,0.44544938,0.47193715,0.5,0.5297315,0.561231,0.59460354,0.62996054,0.6674199,0.70710677,0.74915355,0.7937005,0.8408964,0.8908987,0.9438743,1.0,1.0594631,1.122462,1.1892071,1.2599211,1.3348398,1.4142135,1.4983071,1.587401,1.6817929,1.7817974,1.8877486,2.0,2.1189263,2.244924,2.3784142,2.5198421,2.6696796,2.828427,2.9966142,3.174802,3.3635857,3.563595,3.7754972,4.0}; + + + + +// MMusic class for handling sound engine + class MMusic { public: @@ -99,14 +164,14 @@ public: void setWaveform3(uint16_t waveForm); // // GAIN FUNCTIONS - void setGain(float value); // 0.0 - 1.0 USE THIS - void setGain1(float value); // 0.0 - 1.0 USE THIS - void setGain2(float value); // 0.0 - 1.0 USE THIS - void setGain3(float value); // 0.0 - 1.0 USE THIS - float getGain(); // 0.0 - 1.0 USE THIS - float getGain1(); // 0.0 - 1.0 USE THIS - float getGain2(); // 0.0 - 1.0 USE THIS - float getGain3(); // 0.0 - 1.0 USE THIS + void setGain(float value); // 0.0 - 1.0 + void setGain1(float value); // 0.0 - 1.0 + void setGain2(float value); // 0.0 - 1.0 + void setGain3(float value); // 0.0 - 1.0 + float getGain(); // 0.0 - 1.0 + float getGain1(); // 0.0 - 1.0 + float getGain2(); // 0.0 - 1.0 + float getGain3(); // 0.0 - 1.0 // NOTE FUNCTIONS void noteOn(uint8_t note, uint8_t vel); // 0 - 255 @@ -125,10 +190,10 @@ public: void setSustain16bit(uint16_t sus); // 0 - 65535 void setRelease16bit(uint16_t rel); // 0 - 65535 - void setAttack(uint8_t att); // 0 - 127 USE THESE ONES - void setDecay(uint8_t dec); // 0 - 127 USE THESE ONES - void setSustain(uint8_t sus); // 0 - 127 USE THESE ONES - void setRelease(uint8_t rel); // 0 - 127 USE THESE ONES + void setAttack(uint8_t att); // 0 - 127 + void setDecay(uint8_t dec); // 0 - 127 + void setSustain(uint8_t sus); // 0 - 127 + void setRelease(uint8_t rel); // 0 - 127 void setVelSustain(uint8_t vel); // 0 - 127 void setVelPeak(uint8_t vel); // 0 - 127 @@ -207,6 +272,67 @@ extern MMusic Music; +#ifdef MIDI + +// MMidi class for handling MIDI implementation + +class MMidi { +public: + void init(); + void checkMidi(); + + void midiHandler(); + void noteOff(uint8_t channel, uint8_t note, uint8_t vel); + void noteOn(uint8_t channel, uint8_t note, uint8_t vel); + void aftertouch(uint8_t channel, uint8_t note, uint8_t pressure); + void controller(uint8_t channel, uint8_t number, uint8_t value); + void programChange(uint8_t channel, uint8_t number); + void channelPressure(uint8_t channel, uint8_t pressure); + void pitchWheel(uint8_t channel, uint8_t highBits, uint8_t lowBits); + +private: + + // MIDI + uint8_t data; + uint8_t midiBuffer[3]; + uint8_t midiChannel; + + int midiBufferIndex; + uint16_t frequency; + uint8_t notePlayed; +}; + +extern MMidi Midi; + +#endif + + + +////////////////////////////////////////////////////////// +// +// AUDIO INTERRUPT - The pre-processor selects 8 or 12 bit +// +////////////////////////////////////////////////////////// +ISR(TIMER2_COMPA_vect) { // timer 2 is audio interrupt timer + + OCR2A = 127; // don't change this + +#if BIT_DEPTH == 8 + + Music.synthInterrupt8bit(); + +#endif +#if BIT_DEPTH == 12 + + Music.synthInterrupt12bitSine(); + +#endif + +} + + + + ///////////////////////////////////////////////////////// // @@ -283,15 +409,15 @@ void inline MMusic::synthInterrupt8bit() envStage = 0; } } - - // No gain - else if (envStage == 0) { - env = 0; - accumulator1 = 0; - accumulator2 = 0; - accumulator3 = 0; - } - + /* + // No gain + else if (envStage == 0) { + env = 0; + //accumulator1 = 0; + //accumulator2 = 0; + //accumulator3 = 0; + } + */ } else { env = 65535; } @@ -428,7 +554,6 @@ void MMusic::synthInterrupt12bitSine() // Frame sync high PORTD |= (1<<3); - } @@ -436,31 +561,9 @@ void MMusic::synthInterrupt12bitSine() MMusic Music; - - - -////////////////////////////////////////////////////////// -// -// AUDIO INTERRUPT. USE EITHER 8bit or 12bitSine VERSION -// COMMENT OUT THE ONE YOU ARE NOT USING -// -////////////////////////////////////////////////////////// -ISR(TIMER2_COMPA_vect) { // timer 2 is audio interrupt timer - - OCR2A = 127; // don't change this - -#if BIT_DEPTH == 8 - - Music.synthInterrupt8bit(); - +#ifdef MIDI +MMidi Midi; #endif -#if BIT_DEPTH == 12 - - Music.synthInterrupt12bitSine(); - -#endif - -} @@ -760,7 +863,7 @@ void MMusic::noteOn(uint8_t note, uint8_t vel) setVelSustain(vel); setVelPeak(vel); notePlayed = note; - memcpy_P(&frequency16bit, &hertsTable[notePlayed],2); + memcpy_P(&frequency16bit, &hertzTable[notePlayed],2); setFrequency1(frequency16bit); setFrequency2(frequency16bit); setFrequency3(frequency16bit); @@ -773,7 +876,7 @@ void MMusic::noteOn(uint8_t note) setVelSustain(127); setVelPeak(127); notePlayed = note; - memcpy_P(&frequency16bit, &hertsTable[notePlayed],2); + memcpy_P(&frequency16bit, &hertzTable[notePlayed],2); setFrequency1(frequency16bit); setFrequency2(frequency16bit); setFrequency3(frequency16bit); @@ -882,5 +985,233 @@ void MMusic::setVelPeak(uint8_t vel) velPeak = vel * (MAX_ENV_GAIN / 128); } + + + +#ifdef MIDI + +///////////////////////////////////// +// +// MIDI specific functions +// +///////////////////////////////////// + +bool midiRead = false; + +void MMidi::init() +{ + Serial.begin(115200); + + midiBufferIndex = 0; + midiChannel = MIDI_CHANNEL - 1; + if(midiChannel < 0 || midiChannel > 15) midiChannel = 0; + +} + +void MMidi::checkMidi() +{ + while(Serial.available() > 0) { + + data = Serial.read(); + + if(data & 0x80 && (data & 0x0F) == midiChannel) { // bitmask with 10000000 to see if byte is over 127 (data&0x80) + midiBufferIndex = 0; // and check if the midi channel corresponds to the midiChannel + midiRead = true; // the device is set to listen to. + } else if(data & 0x80) { // Else if the byte is over 127 (but not on the device's + midiRead = false; // midiChannel, don't read this or any following bytes. + } + + if(midiRead) { + midiBuffer[midiBufferIndex] = data; + midiBufferIndex++; + if (midiBufferIndex > 2) { + midiHandler(); + } + } + } +} + + +void MMidi::midiHandler() { + + uint8_t midiChannel = (midiBuffer[0] & 0x0F); + + + switch(midiBuffer[0] & 0xF0) { // bit mask with &0xF0 ? + case 0x80: + noteOff (midiBuffer[0] & 0x0F, // midi channel 0-16 + midiBuffer[1] & 0x7F, // note value 0-127 + midiBuffer[2] & 0x7F); // note velocity 0-127 + break; + + case 0x90: + noteOn (midiBuffer[0] & 0x0F, // midi channel 0-16 + midiBuffer[1] & 0x7F, // note value 0-127 + midiBuffer[2] & 0x7F); // note velocity 0-127 + break; + + case 0xA0: + aftertouch (midiBuffer[0] & 0x0F, // midi channel 0-16 + midiBuffer[1] & 0x7F, // note value 0-127 + midiBuffer[2] & 0x7F);// note velocity 0-127 + break; + + case 0xB0: + controller (midiBuffer[0] & 0x0F, // midi channel 0-16 + midiBuffer[1] & 0x7F, // controller number 0-127 + midiBuffer[2] & 0x7F);// controller value 0-127 + break; + + case 0xC0: + programChange (midiBuffer[0] & 0x0F, // midi channel 0-16 + midiBuffer[1] & 0x7F); // program number 0-127 + break; + + case 0xD0: + channelPressure (midiBuffer[0] & 0x0F, // midi channel 0-16 + midiBuffer[1] & 0x7F); // pressure amount 0-127 + break; + + case 0xE0: + pitchWheel (midiBuffer[0] & 0x0F, // midi channel 0-16 + midiBuffer[1] & 0x7F, // higher bits 0-6 + midiBuffer[2] & 0x7F);// lower bits 7-13 + break; + + default: + break; + } +} + + +void MMidi::noteOff(uint8_t channel, uint8_t note, uint8_t vel) { + + if(notePlayed == note) { + Music.setEnvStage(4); + } +} + + +void MMidi::noteOn(uint8_t channel, uint8_t note, uint8_t vel) { + + Music.setEnvStage(1); + Music.setVelSustain(vel); + Music.setVelPeak(vel); + notePlayed = note; + memcpy_P(&frequency, &hertzTable[notePlayed],2); + Music.setFrequency1(frequency); + Music.setFrequency2(frequency); + Music.setFrequency3(frequency); +} + + +void MMidi::aftertouch(uint8_t channel, uint8_t note, uint8_t pressure) { + // Write code here for Aftertouch +} + + +void MMidi::controller(uint8_t channel, uint8_t number, uint8_t value) { + + switch(number) { + case DETUNE: + Music.setDetune(value/5120.0); + break; + case PORTAMENTO: + //Music.setPortamento(value); // function to be defined, also argument + break; + case DETUNE1: + Music.setDetune1(value/5120.0); + break; + case DETUNE2: + Music.setDetune2(value/5120.0); + break; + case DETUNE3: + Music.setDetune3(value/5120.0); + break; + case SEMITONE1: + if(15 < value && value < 113) { + int8_t val = (((value-16)/2)-24); + Music.setSemitone1(val); + } else if (value < 16) { + Music.setSemitone1(-24); + } else { + Music.setSemitone1(24); + } + break; + case SEMITONE2: + if(15 < value && value < 113) { + int8_t val = (((value-16)/2)-24); + Music.setSemitone2(val); + } else if (value < 16) { + Music.setSemitone2(-24); + } else { + Music.setSemitone2(24); + } + break; + case SEMITONE3: + if(15 < value && value < 113) { + int8_t val = (((value-16)/2)-24); + Music.setSemitone3(val); + } else if (value < 16) { + Music.setSemitone3(-24); + } else { + Music.setSemitone3(24); + } + break; + case GAIN1: + Music.setGain1(value / 127.0); + break; + case GAIN2: + Music.setGain2(value / 127.0); + break; + case GAIN3: + Music.setGain3(value / 127.0); + break; + case WAVEFORM: + Music.setWaveform(value / 8); + break; + case WAVEFORM1: + Music.setWaveform1(value / 8); + break; + case WAVEFORM2: + Music.setWaveform2(value / 8); + break; + case WAVEFORM3: + Music.setWaveform3(value / 8); + break; + case ENV_ATTACK: + Music.setAttack(value); + break; + case ENV_DECAY: + Music.setDecay(value); + break; + case ENV_SUSTAIN: + Music.setSustain(value); + break; + case ENV_RELEASE: + Music.setRelease(value); + break; + default: + break; + } +} + + +void MMidi::programChange(uint8_t channel, uint8_t number) { + // Write code here for Program Change +} + + +void MMidi::channelPressure(uint8_t channel, uint8_t pressure) { + // Write code here for Channel Pressure +} + + +void MMidi::pitchWheel(uint8_t channel, uint8_t highBits, uint8_t lowBits) { + // Write code here for Pitch Wheel +} + +#endif + #endif // close guard Music_h