#include "MidiReader.h" #include "stdio.h" #include "DirectMidi/DM.h" DirectMidi DM; enum {ON = 1, OFF = 0}; int main(int argc, char *argv[]){ MidiReader *mr = new MidiReader(""); FILE *fp; // byte to read in from COM serial in char c; int i, min_freq = 10, // minimum read in 'c' (see above) value most_notes = 0, // which note has been read in most over a time (play this note) note = -1, // the note to play previous_note = 0, // the previoys note played avg_notes[128]; // store the accumulation of the notes read in // current and start time for timer (for note input sampling period) time_t timer, start_time; // open COM1 to read in from fp = fopen("COM1", "r"); // if COM1 is already open, exit app and warn if(fp == NULL) { printf("COM1 is busy, please close the application that is using COM1\n"); exit(0); } // infinitely loop through note playback while(1) { // get the current logochip timer value fgets(&c, 2, fp); // if this timer value is less than the minimum frequency, then it is a note off, // which has the frequency of the 60 cycle hum that the guitar produces when // no notes are being played if(int(c) < min_freq) { // turn off all notes that may be playing for(int i = 0; i < 128; i++) { mr->PlayMidiNote(i, OFF); } // set the previous note to no-note flag (-1) previous_note = -1; } // otherwise the frequency is usable, so play a note else { printf("new note ... "); // this note was just played, and there are a lot of initial harmonics, so // ignore the note until is has been playing for 500 ms, after which we have // the more pure tone of the note being played Sleep(500); printf("starting sampling\n"); // reset all of the previous average calculations for(int n = 0; n < 128; n++) { avg_notes[n] = 0; } // reset the timers start_time = clock(); timer = clock(); // until 700 ms have elapsed while((timer - start_time) < 700) { // update the timer timer = clock(); // get a new byte from the input fgets(&c, 2, fp); // set the note to the note given shifted up to a good range note = int(c) + 60 - 17; note = note > 127 ? 127 : note; note = note < 0 ? 0 : note; // if this read in value is a viable note (i.e. greater in frequency // than 60-cycle hum, or low freq noise) if(int(c) > min_freq) { // then increment the number of times this note was seen avg_notes[note]++; } } printf("done sampling\n"); // reset the largest accumulation of notes value most_notes = 0; // set the current note to the previous note initially note = previous_note; printf("\tThe following notes were sampled:\n\t\t"); // go through each possible note value for(n = 0; n < 128; n++) { // print the large accumulation of possible notes to play if(avg_notes[n] != 0) printf("(note: %d, number of: %d) ", n, avg_notes[n]); // get the maximum accumulation, this will be the note to play (the one that occurred // more often than any other) if(avg_notes[n] >= most_notes) { most_notes = avg_notes[n]; note = n; } } printf("\n"); // if this note is 0, go back to the beginning of the loop, do not play it if(note == 0) { continue; } // if this is a new note to play if(note != previous_note) { previous_note = note; // turn off all old notes for(int i = 0; i < 128; i++) { mr->PlayMidiNote(i, OFF); } printf("Playing note: %d\n\n\n", note); // and play this note mr->PlayMidiNote(note, ON); } // wait until the note is off (stop the note from sustaining and take hands off the // guitar string). unfortunately this is the best result i could obtain, where // each note must be played, then stopped before the next is played while(1) { // get new input value fgets(&c, 2, fp); // if it is back to around 60-cycle hum, then no note is sustaining, return to top of // loop and look for a new note if(int(c) < min_freq) { previous_note = -1; break; } } } } return 1; } MidiReader::MidiReader(const char *fileName){ DM.initializeDirectMidi(); } void MidiReader::PlayMidiNote(int note, bool on_or_off) { if(on_or_off == ON) { DM.sendMidiCommand(NOTE_ON, 1, note, 127); } else { DM.sendMidiCommand(NOTE_ON, 1, note, 0); } }