115 lines
4.1 KiB
C
115 lines
4.1 KiB
C
---
|
|
author: "Flávio Schiavoni"
|
|
description: O Blesq Blom!
|
|
---
|
|
|
|
#include <stdio.h>
|
|
#include <portmidi.h>
|
|
|
|
#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");
|
|
}
|
|
|