summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/portmidi/pm_test/fastrcv.c
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/portmidi/pm_test/fastrcv.c')
-rw-r--r--3rdparty/portmidi/pm_test/fastrcv.c255
1 files changed, 255 insertions, 0 deletions
diff --git a/3rdparty/portmidi/pm_test/fastrcv.c b/3rdparty/portmidi/pm_test/fastrcv.c
new file mode 100644
index 00000000000..daee40c5fa0
--- /dev/null
+++ b/3rdparty/portmidi/pm_test/fastrcv.c
@@ -0,0 +1,255 @@
+/* fastrcv.c -- send many MIDI messages very fast.
+ *
+ * This is a stress test created to explore reports of
+ * pm_write() call blocking (forever) on Linux when
+ * sending very dense MIDI sequences.
+ *
+ * Modified 8 Aug 2017 with -n to send expired timestamps
+ * to test a theory about why Linux ALSA hangs in Audacity.
+ *
+ * Roger B. Dannenberg, Aug 2017
+ */
+
+#include "portmidi.h"
+#include "porttime.h"
+#include "stdlib.h"
+#include "stdio.h"
+#include "string.h"
+#include "assert.h"
+
+#define INPUT_BUFFER_SIZE 1000 /* big to avoid losing any input */
+#define DEVICE_INFO NULL
+#define DRIVER_INFO NULL
+#define TIME_PROC ((PmTimeProcPtr) 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 */
+// need to get declaration for Sleep()
+#ifdef WIN32
+#include "windows.h"
+#else
+#include <unistd.h>
+#define Sleep(n) usleep(n * 1000)
+#endif
+
+
+int deviceno = -9999;
+int verbose = FALSE;
+
+
+static void prompt_and_exit(void)
+{
+ printf("type ENTER...");
+ while (getchar() != '\n') ;
+ /* this will clean up open ports: */
+ exit(-1);
+}
+
+
+static PmError checkerror(PmError err)
+{
+ if (err == pmHostError) {
+ /* it seems pointless to allocate memory and copy the string,
+ * so I will do the work of Pm_GetHostErrorText directly
+ */
+ char errmsg[80];
+ Pm_GetHostErrorText(errmsg, 80);
+ printf("PortMidi found host error...\n %s\n", errmsg);
+ prompt_and_exit();
+ } else if (err < 0) {
+ printf("PortMidi call failed...\n %s\n", Pm_GetErrorText(err));
+ prompt_and_exit();
+ }
+ return err;
+}
+
+
+/* read a number from console */
+/**/
+int get_number(const char *prompt)
+{
+ int n = 0, i;
+ fputs(prompt, stdout);
+ while (n != 1) {
+ n = scanf("%d", &i);
+ while (getchar() != '\n') ;
+ }
+ return i;
+}
+
+
+void fastrcv_test()
+{
+ PmStream * midi;
+ PmError status, length;
+ PmEvent buffer[1];
+ PmTimestamp start;
+ /* every 10ms read all messages, keep counts */
+ /* every 1000ms, print report */
+ int msgcnt = 0;
+ /* expect repeating sequence of 60 through 71, alternating on/off */
+ int expected_pitch = 60;
+ int expected_on = TRUE;
+ int report_time;
+ PmTimestamp last_timestamp = -1;
+ PmTimestamp last_delta = -1;
+
+ /* It is recommended to start timer before PortMidi */
+ TIME_START;
+
+ /* open output device */
+ if (deviceno == Pm_CountDevices()) {
+ int id = Pm_CreateVirtualInput("fastrcv", NULL, DEVICE_INFO);
+ if (id < 0) checkerror(id); /* error reporting */
+ checkerror(Pm_OpenInput(&midi, id, DRIVER_INFO,
+ INPUT_BUFFER_SIZE, TIME_PROC, TIME_INFO));
+ } else {
+ Pm_OpenInput(&midi, deviceno, DRIVER_INFO, INPUT_BUFFER_SIZE,
+ TIME_PROC, TIME_INFO);
+ }
+ printf("Midi Input opened.\n");
+
+ /* wait a sec after printing previous line */
+ start = Pt_Time() + 1000;
+ while (start > Pt_Time()) {
+ Sleep(10);
+ }
+
+ report_time = Pt_Time() + 1000; /* report every 1s */
+ while (TRUE) {
+ PmTimestamp now = Pt_Time();
+ status = Pm_Poll(midi);
+ if (status == TRUE) {
+ length = Pm_Read(midi, buffer, 1);
+ if (length > 0) {
+ int status = Pm_MessageStatus(buffer[0].message);
+ if (status == 0x80) { /* convert NoteOff to NoteOn, vel=0 */
+ status = 0x90;
+ buffer[0].message = Pm_Message(status,
+ Pm_MessageData1(buffer[0].message), 0);
+ }
+ /* only listen to NOTEON messages */
+ if (status == 0x90) {
+ int pitch = Pm_MessageData1(buffer[0].message);
+ int vel = Pm_MessageData2(buffer[0].message);
+ int is_on = (vel > 0);
+ if (verbose) {
+ printf("Note pitch %d vel %d\n", pitch, vel);
+ }
+ msgcnt++;
+ if (pitch != expected_pitch || expected_on != is_on) {
+ printf("Unexpected note-on: pitch %d vel %d, "
+ "expected: pitch %d Note%s\n", pitch, vel,
+ expected_pitch, (expected_on ? "On" : "Off"));
+ }
+ if (is_on) {
+ expected_on = FALSE;
+ expected_pitch = pitch;
+ } else {
+ expected_on = TRUE;
+ expected_pitch = (pitch + 1) % 72;
+ if (expected_pitch < 60) expected_pitch = 60;
+ }
+ if (last_timestamp >= 0) {
+ last_delta = buffer[0].timestamp - last_timestamp;
+ }
+ last_timestamp = buffer[0].timestamp;
+ }
+ }
+ }
+ if (now >= report_time) {
+ printf("%d msgs/sec", msgcnt);
+ /* if available, print the last timestamp and last delta time */
+ if (last_timestamp >= 0) {
+ printf(" last timestamp %d", (int) last_timestamp);
+ last_timestamp = -1;
+ }
+ if (last_delta >= 0) {
+ printf(" last delta time %d", (int) last_delta);
+ last_delta = -1;
+ }
+ printf("\n");
+ report_time += 1000;
+ msgcnt = 0;
+ }
+ }
+}
+
+
+void show_usage()
+{
+ printf("Usage: fastrcv [-h] [-v] [-d device], where\n"
+ "device is the PortMidi device number,\n"
+ "-h means help,\n"
+ "-v means verbose (print messages)\n");
+}
+
+int main(int argc, char *argv[])
+{
+ int default_in;
+ int default_out;
+ char *deflt;
+
+ int i = 0, n = 0;
+ int test_input = 0, test_output = 0, test_both = 0, somethingStupid = 0;
+ int stream_test = 0;
+ int device_valid = FALSE;
+
+ if (sizeof(void *) == 8)
+ printf("Apparently this is a 64-bit machine.\n");
+ else if (sizeof(void *) == 4)
+ printf ("Apparently this is a 32-bit machine.\n");
+
+ if (argc <= 1) {
+ show_usage();
+ } else {
+ for (i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-h") == 0) {
+ show_usage();
+ } else if (strcmp(argv[i], "-v") == 0) {
+ verbose = TRUE;
+ } else if (strcmp(argv[i], "-d") == 0) {
+ i = i + 1;
+ deviceno = atoi(argv[i]);
+ printf("Device will be %d\n", deviceno);
+ } else {
+ show_usage();
+ }
+ }
+ }
+
+ /* list device information */
+ default_in = Pm_GetDefaultInputDeviceID();
+ default_out = Pm_GetDefaultOutputDeviceID();
+ for (i = 0; i < Pm_CountDevices(); i++) {
+ const PmDeviceInfo *info = Pm_GetDeviceInfo(i);
+ if (!info->output) {
+ printf("%d: %s, %s", i, info->interf, info->name);
+ if (i == deviceno) {
+ device_valid = TRUE;
+ deflt = "selected ";
+ } else if (i == default_out) {
+ deflt = "default ";
+ } else {
+ deflt = "";
+ }
+ printf(" (%sinput)\n", deflt);
+ }
+ }
+ printf("%d: Create virtual port named \"fastrcv\"", i);
+ if (i == deviceno) {
+ device_valid = TRUE;
+ deflt = "selected ";
+ } else {
+ deflt = "";
+ }
+ printf(" (%sinput)\n", deflt);
+
+ if (!device_valid) {
+ deviceno = get_number("Input device number: ");
+ }
+
+ fastrcv_test();
+ return 0;
+}