This is really neat, taking the MIDI in note, a chord is formed from adding notes below the pitch to form a chord. In this case the drop is -4 and -9 from the original note (quoting Gordophone this this is a major triad in second inversion - a 6/4 chord).
Here's my code version:
/////////////////////////////////////////////////////////////////////// // // HondrouMidifier // // Initial testing using Gordon Good's Marmonizer as a base // http://gordophone.blogspot.co.uk/2010/01/marmonizer-v2.html // Gordon Good (velo27 <at> yahoo <dot> com) // // This uses the MIDI library from FortySevenEffects // http://fortyseveneffects.github.io/arduino_midi_library/ // // // implements a simple MIDI harmonizer. The harmonizarion ia simple; the // input note is the top voice of a triad in second inversion (e.g. if the // input note is E4, then the voices below are G3 and C4. For discussion of // what those note names mean, see http://en.wikipedia.org/wiki/C_%28musical_note%29 // The transposition pot is retained. // // Limitations: the algorithm always "maps down" so we may roll notes off the // deep end of the MIDI spec. #include <SoftwareSerial.h> #include <Midi.h> SoftwareSerial MusicSerial(2, 3); //Soft TX on 3, we don't use RX in this code // defines for MIDI Shield components only #define KNOB1 0 #define KNOB2 1 #define STAT1 7 #define STAT2 6 // Music shield pins - both digital #define MUSIC_PIN_MIDI_IN 3 // soft serial TX -> VS1053 RX #define MUSIC_PIN_RESET 4 // VS1053 RESET #define HARM_NOTE_1_OFFSET -4 #define HARM_NOTE_2_OFFSET -9 int trPotPin = KNOB1; // Analog pin for reading the transposition potentiometer int ledPin = STAT1; // LED pin to blink for debugging int transposition = 0; // number of semitones to transpose (negative = transpose down) void noteOnCallback(byte channel, byte pitch, byte velocity) { digitalWrite(ledPin, HIGH); noteOn(channel, pitch + transposition, velocity); noteOn(channel, pitch + transposition + HARM_NOTE_1_OFFSET, velocity); noteOn(channel, pitch + transposition + HARM_NOTE_2_OFFSET, velocity); } void noteOffCallback(byte channel, byte pitch, byte velocity) { digitalWrite(ledPin, LOW); noteOff(channel, pitch + transposition, velocity); noteOff(channel, pitch + transposition + HARM_NOTE_1_OFFSET, velocity); noteOff(channel, pitch + transposition + HARM_NOTE_2_OFFSET, velocity); } ///////////////////////////////////////////////////////////////////////////// // Setup routine ///////////////////////////////////////////////////////////////////////////// void setup() { pinMode(STAT1,OUTPUT); pinMode(STAT2,OUTPUT); // Initiate MIDI communications, listen to all channels MIDI.begin(MIDI_CHANNEL_OMNI); // Connect the HandleNoteOn function to the library, so it is called upon reception of // a NoteOn. MIDI.setHandleNoteOn(noteOnCallback); MIDI.setHandleNoteOff(noteOffCallback); pinMode(trPotPin, INPUT); digitalWrite(trPotPin, HIGH); // VS1053 //start serial with midi baudrate 31250 MusicSerial.begin(31250); // Reset the VS1053 pinMode(MUSIC_PIN_RESET, OUTPUT); digitalWrite(MUSIC_PIN_RESET, LOW); delay(100); digitalWrite(MUSIC_PIN_RESET, HIGH); delay(100); talkMIDI(0xB0, 0x07, 120); //0xB0 is channel message, set channel volume to near max (127) digitalWrite(STAT1,LOW); digitalWrite(STAT2,LOW); } ///////////////////////////////////////////////////////////////////////////// // Main loop ///////////////////////////////////////////////////////////////////////////// void loop() { // Read the transposition pot, and map the value to a + or - one octave transposition transposition = map(analogRead(trPotPin), 0, 1023, -12, 12); // Call MIDI.read the fastest you can for real-time performance. MIDI.read(); // There is no need to check if there are messages incoming if they are bound to a Callback // function. } ///////////////////////////////////////////////////////////////////////////// // Functions ///////////////////////////////////////////////////////////////////////////// //Send a MIDI note-on message. Like pressing a piano key //channel ranges from 0-15 void noteOn(byte channel, byte note, byte attack_velocity) { talkMIDI( (0x90 | channel), note, attack_velocity); } //Send a MIDI note-off message. Like releasing a piano key void noteOff(byte channel, byte note, byte release_velocity) { talkMIDI( (0x80 | channel), note, release_velocity); } //Plays a MIDI note. Doesn't check to see that cmd is greater than 127, or that data values are less than 127 void talkMIDI(byte cmd, byte data1, byte data2) { digitalWrite(STAT1,HIGH); MusicSerial.write(cmd); MusicSerial.write(data1); //Some commands only have one data byte. All cmds less than 0xBn have 2 data bytes //(sort of: http://253.ccarh.org/handout/midiprotocol/) if( (cmd & 0xF0) <= 0xB0) { MusicSerial.write(data2); } digitalWrite(STAT1,LOW); }
No comments:
Post a Comment