--- author: "Flávio Schiavoni" description: O Blesq Blom! --- #include #include #define INPUT_BUFFER_SIZE 100 #define OUTPUT_BUFFER_SIZE 0 #define DRIVER_INFO NULL #define TIME_PROC ((int32_t (*)(void *)) Pt_Time) #define TIME_INFO NULL #define TIME_START Pt_Start(1, 0, 0) /* timer started w/millisecond accuracy */ #define STRING_MAX 80 /* used for console input */ #define chord_size 5 int32_t latency = 0; int main(int argc, char* argv) { PmStream * midi; char line[80]; int32_t off_time; int chord[] = { 60, 67, 76, 83, 90 }; PmEvent buffer[chord_size]; PmTimestamp timestamp; /* determine which output device to use */ int i = get_number("Type output number: "); /* It is recommended to start timer before PortMidi */ TIME_START; /* open output device -- since PortMidi avoids opening a timer when latency is zero, we will pass in a NULL timer pointer for that case. If PortMidi tries to access the time_proc, we will crash, so this test will tell us something. */ Pm_OpenOutput(&midi, i, DRIVER_INFO, OUTPUT_BUFFER_SIZE, (latency == 0 ? NULL : TIME_PROC), (latency == 0 ? NULL : TIME_INFO), latency); printf("Midi Output opened with %ld ms latency.\n", (long) latency); /* output note on/off w/latency offset; hold until user prompts */ printf("ready to send program 1 change... (type RETURN):"); fgets(line, STRING_MAX, stdin); /* if we were writing midi for immediate output, we could always use timestamps of zero, but since we may be writing with latency, we will explicitly set the timestamp to "now" by getting the time. The source of timestamps should always correspond to the TIME_PROC and TIME_INFO parameters used in Pm_OpenOutput(). */ buffer[0].timestamp = TIME_PROC(TIME_INFO); /* Send a program change to increase the chances we will hear notes */ /* Program 0 is usually a piano, but you can change it here: */ #define PROGRAM 0 buffer[0].message = Pm_Message(0xC0, PROGRAM, 0); Pm_Write(midi, buffer, 1); printf("ready to note-on... (type RETURN):"); fgets(line, STRING_MAX, stdin); buffer[0].timestamp = TIME_PROC(TIME_INFO); buffer[0].message = Pm_Message(0x90, 60, 100); Pm_Write(midi, buffer, 1); printf("ready to note-off... (type RETURN):"); fgets(line, STRING_MAX, stdin); buffer[0].timestamp = TIME_PROC(TIME_INFO); buffer[0].message = Pm_Message(0x90, 60, 0); Pm_Write(midi, buffer, 1); /* output short note on/off w/latency offset; hold until user prompts */ printf("ready to note-on (short form)... (type RETURN):"); fgets(line, STRING_MAX, stdin); Pm_WriteShort(midi, TIME_PROC(TIME_INFO), Pm_Message(0x90, 60, 100)); printf("ready to note-off (short form)... (type RETURN):"); fgets(line, STRING_MAX, stdin); Pm_WriteShort(midi, TIME_PROC(TIME_INFO), Pm_Message(0x90, 60, 0)); /* output several note on/offs to test timing. Should be 1s between notes */ printf("chord will arpeggiate if latency > 0\n"); printf("ready to chord-on/chord-off... (type RETURN):"); fgets(line, STRING_MAX, stdin); timestamp = TIME_PROC(TIME_INFO); for (i = 0; i < chord_size; i++) { buffer[i].timestamp = timestamp + 1000 * i; buffer[i].message = Pm_Message(0x90, chord[i], 100); } Pm_Write(midi, buffer, chord_size); off_time = timestamp + 1000 + chord_size * 1000; while (TIME_PROC(TIME_INFO) < off_time) /* busy wait */; for (i = 0; i < chord_size; i++) { buffer[i].timestamp = timestamp + 1000 * i; buffer[i].message = Pm_Message(0x90, chord[i], 0); } Pm_Write(midi, buffer, chord_size); /* close device (this not explicitly needed in most implementations) */ printf("ready to close and terminate... (type RETURN):"); fgets(line, STRING_MAX, stdin); Pm_Close(midi); Pm_Terminate(); printf("done closing and terminating...\n"); }