diff options
| author | Mitja Felicijan <mitja.felicijan@gmail.com> | 2024-10-07 19:30:56 +0200 |
|---|---|---|
| committer | Mitja Felicijan <mitja.felicijan@gmail.com> | 2024-10-07 19:30:56 +0200 |
| commit | 40a899bd6ee536eae093337bf2d0dcc8db4e46f1 (patch) | |
| tree | 485ace3e6fd28b91f394efd277732651e10824d8 /portmidi/pm_test/fastrcv.c | |
| parent | 6fc4bddfdf8e056469f316c1a0fe488efbb4253a (diff) | |
| download | ttdaw-40a899bd6ee536eae093337bf2d0dcc8db4e46f1.tar.gz | |
Moved example code examples folder
Diffstat (limited to 'portmidi/pm_test/fastrcv.c')
| -rw-r--r-- | portmidi/pm_test/fastrcv.c | 255 |
1 files changed, 0 insertions, 255 deletions
diff --git a/portmidi/pm_test/fastrcv.c b/portmidi/pm_test/fastrcv.c deleted file mode 100644 index dabf9fa..0000000 --- a/portmidi/pm_test/fastrcv.c +++ /dev/null | |||
| @@ -1,255 +0,0 @@ | |||
| 1 | /* fastrcv.c -- send many MIDI messages very fast. | ||
| 2 | * | ||
| 3 | * This is a stress test created to explore reports of | ||
| 4 | * pm_write() call blocking (forever) on Linux when | ||
| 5 | * sending very dense MIDI sequences. | ||
| 6 | * | ||
| 7 | * Modified 8 Aug 2017 with -n to send expired timestamps | ||
| 8 | * to test a theory about why Linux ALSA hangs in Audacity. | ||
| 9 | * | ||
| 10 | * Roger B. Dannenberg, Aug 2017 | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include "portmidi.h" | ||
| 14 | #include "porttime.h" | ||
| 15 | #include "stdlib.h" | ||
| 16 | #include "stdio.h" | ||
| 17 | #include "string.h" | ||
| 18 | #include "assert.h" | ||
| 19 | |||
| 20 | #define INPUT_BUFFER_SIZE 1000 /* big to avoid losing any input */ | ||
| 21 | #define DEVICE_INFO NULL | ||
| 22 | #define DRIVER_INFO NULL | ||
| 23 | #define TIME_PROC ((PmTimeProcPtr) Pt_Time) | ||
| 24 | #define TIME_INFO NULL | ||
| 25 | #define TIME_START Pt_Start(1, 0, 0) /* timer started w/millisecond accuracy */ | ||
| 26 | |||
| 27 | #define STRING_MAX 80 /* used for console input */ | ||
| 28 | // need to get declaration for Sleep() | ||
| 29 | #ifdef WIN32 | ||
| 30 | #include "windows.h" | ||
| 31 | #else | ||
| 32 | #include <unistd.h> | ||
| 33 | #define Sleep(n) usleep(n * 1000) | ||
| 34 | #endif | ||
| 35 | |||
| 36 | |||
| 37 | int deviceno = -9999; | ||
| 38 | int verbose = FALSE; | ||
| 39 | |||
| 40 | |||
| 41 | static void prompt_and_exit(void) | ||
| 42 | { | ||
| 43 | printf("type ENTER..."); | ||
| 44 | while (getchar() != '\n') ; | ||
| 45 | /* this will clean up open ports: */ | ||
| 46 | exit(-1); | ||
| 47 | } | ||
| 48 | |||
| 49 | |||
| 50 | static PmError checkerror(PmError err) | ||
| 51 | { | ||
| 52 | if (err == pmHostError) { | ||
| 53 | /* it seems pointless to allocate memory and copy the string, | ||
| 54 | * so I will do the work of Pm_GetHostErrorText directly | ||
| 55 | */ | ||
| 56 | char errmsg[80]; | ||
| 57 | Pm_GetHostErrorText(errmsg, 80); | ||
| 58 | printf("PortMidi found host error...\n %s\n", errmsg); | ||
| 59 | prompt_and_exit(); | ||
| 60 | } else if (err < 0) { | ||
| 61 | printf("PortMidi call failed...\n %s\n", Pm_GetErrorText(err)); | ||
| 62 | prompt_and_exit(); | ||
| 63 | } | ||
| 64 | return err; | ||
| 65 | } | ||
| 66 | |||
| 67 | |||
| 68 | /* read a number from console */ | ||
| 69 | /**/ | ||
| 70 | int get_number(const char *prompt) | ||
| 71 | { | ||
| 72 | int n = 0, i; | ||
| 73 | fputs(prompt, stdout); | ||
| 74 | while (n != 1) { | ||
| 75 | n = scanf("%d", &i); | ||
| 76 | while (getchar() != '\n') ; | ||
| 77 | } | ||
| 78 | return i; | ||
| 79 | } | ||
| 80 | |||
| 81 | |||
| 82 | void fastrcv_test() | ||
| 83 | { | ||
| 84 | PmStream * midi; | ||
| 85 | PmError status, length; | ||
| 86 | PmEvent buffer[1]; | ||
| 87 | PmTimestamp start; | ||
| 88 | /* every 10ms read all messages, keep counts */ | ||
| 89 | /* every 1000ms, print report */ | ||
| 90 | int msgcnt = 0; | ||
| 91 | /* expect repeating sequence of 60 through 71, alternating on/off */ | ||
| 92 | int expected_pitch = 60; | ||
| 93 | int expected_on = TRUE; | ||
| 94 | int report_time; | ||
| 95 | PmTimestamp last_timestamp = -1; | ||
| 96 | PmTimestamp last_delta = -1; | ||
| 97 | |||
| 98 | /* It is recommended to start timer before PortMidi */ | ||
| 99 | TIME_START; | ||
| 100 | |||
| 101 | /* open output device */ | ||
| 102 | if (deviceno == Pm_CountDevices()) { | ||
| 103 | int id = Pm_CreateVirtualInput("fastrcv", NULL, DEVICE_INFO); | ||
| 104 | if (id < 0) checkerror(id); /* error reporting */ | ||
| 105 | checkerror(Pm_OpenInput(&midi, id, DRIVER_INFO, | ||
| 106 | INPUT_BUFFER_SIZE, TIME_PROC, TIME_INFO)); | ||
| 107 | } else { | ||
| 108 | Pm_OpenInput(&midi, deviceno, DRIVER_INFO, INPUT_BUFFER_SIZE, | ||
| 109 | TIME_PROC, TIME_INFO); | ||
| 110 | } | ||
| 111 | printf("Midi Input opened.\n"); | ||
| 112 | |||
| 113 | /* wait a sec after printing previous line */ | ||
| 114 | start = Pt_Time() + 1000; | ||
| 115 | while (start > Pt_Time()) { | ||
| 116 | Sleep(10); | ||
| 117 | } | ||
| 118 | |||
| 119 | report_time = Pt_Time() + 1000; /* report every 1s */ | ||
| 120 | while (TRUE) { | ||
| 121 | PmTimestamp now = Pt_Time(); | ||
| 122 | status = Pm_Poll(midi); | ||
| 123 | if (status == TRUE) { | ||
| 124 | length = Pm_Read(midi, buffer, 1); | ||
| 125 | if (length > 0) { | ||
| 126 | int status = Pm_MessageStatus(buffer[0].message); | ||
| 127 | if (status == 0x80) { /* convert NoteOff to NoteOn, vel=0 */ | ||
| 128 | status = 0x90; | ||
| 129 | buffer[0].message = Pm_Message(status, | ||
| 130 | Pm_MessageData1(buffer[0].message), 0); | ||
| 131 | } | ||
| 132 | /* only listen to NOTEON messages */ | ||
| 133 | if (status == 0x90) { | ||
| 134 | int pitch = Pm_MessageData1(buffer[0].message); | ||
| 135 | int vel = Pm_MessageData2(buffer[0].message); | ||
| 136 | int is_on = (vel > 0); | ||
| 137 | if (verbose) { | ||
| 138 | printf("Note pitch %d vel %d\n", pitch, vel); | ||
| 139 | } | ||
| 140 | msgcnt++; | ||
| 141 | if (pitch != expected_pitch || expected_on != is_on) { | ||
| 142 | printf("Unexpected note-on: pitch %d vel %d, " | ||
| 143 | "expected: pitch %d Note%s\n", pitch, vel, | ||
| 144 | expected_pitch, (expected_on ? "On" : "Off")); | ||
| 145 | } | ||
| 146 | if (is_on) { | ||
| 147 | expected_on = FALSE; | ||
| 148 | expected_pitch = pitch; | ||
| 149 | } else { | ||
| 150 | expected_on = TRUE; | ||
| 151 | expected_pitch = (pitch + 1) % 72; | ||
| 152 | if (expected_pitch < 60) expected_pitch = 60; | ||
| 153 | } | ||
| 154 | if (last_timestamp >= 0) { | ||
| 155 | last_delta = buffer[0].timestamp - last_timestamp; | ||
| 156 | } | ||
| 157 | last_timestamp = buffer[0].timestamp; | ||
| 158 | } | ||
| 159 | } | ||
| 160 | } | ||
| 161 | if (now >= report_time) { | ||
| 162 | printf("%d msgs/sec", msgcnt); | ||
| 163 | /* if available, print the last timestamp and last delta time */ | ||
| 164 | if (last_timestamp >= 0) { | ||
| 165 | printf(" last timestamp %d", (int) last_timestamp); | ||
| 166 | last_timestamp = -1; | ||
| 167 | } | ||
| 168 | if (last_delta >= 0) { | ||
| 169 | printf(" last delta time %d", (int) last_delta); | ||
| 170 | last_delta = -1; | ||
| 171 | } | ||
| 172 | printf("\n"); | ||
| 173 | report_time += 1000; | ||
| 174 | msgcnt = 0; | ||
| 175 | } | ||
| 176 | } | ||
| 177 | } | ||
| 178 | |||
| 179 | |||
| 180 | void show_usage() | ||
| 181 | { | ||
| 182 | printf("Usage: fastrcv [-h] [-v] [-d device], where\n" | ||
| 183 | "device is the PortMidi device number,\n" | ||
| 184 | "-h means help,\n" | ||
| 185 | "-v means verbose (print messages)\n"); | ||
| 186 | } | ||
| 187 | |||
| 188 | int main(int argc, char *argv[]) | ||
| 189 | { | ||
| 190 | int default_in; | ||
| 191 | int default_out; | ||
| 192 | char *deflt; | ||
| 193 | |||
| 194 | int i = 0; | ||
| 195 | int test_input = 0, test_output = 0, test_both = 0; | ||
| 196 | int stream_test = 0; | ||
| 197 | int device_valid = FALSE; | ||
| 198 | |||
| 199 | if (sizeof(void *) == 8) | ||
| 200 | printf("Apparently this is a 64-bit machine.\n"); | ||
| 201 | else if (sizeof(void *) == 4) | ||
| 202 | printf ("Apparently this is a 32-bit machine.\n"); | ||
| 203 | |||
| 204 | if (argc <= 1) { | ||
| 205 | show_usage(); | ||
| 206 | } else { | ||
| 207 | for (i = 1; i < argc; i++) { | ||
| 208 | if (strcmp(argv[i], "-h") == 0) { | ||
| 209 | show_usage(); | ||
| 210 | } else if (strcmp(argv[i], "-v") == 0) { | ||
| 211 | verbose = TRUE; | ||
| 212 | } else if (strcmp(argv[i], "-d") == 0) { | ||
| 213 | i = i + 1; | ||
| 214 | deviceno = atoi(argv[i]); | ||
| 215 | printf("Device will be %d\n", deviceno); | ||
| 216 | } else { | ||
| 217 | show_usage(); | ||
| 218 | } | ||
| 219 | } | ||
| 220 | } | ||
| 221 | |||
| 222 | /* list device information */ | ||
| 223 | default_in = Pm_GetDefaultInputDeviceID(); | ||
| 224 | default_out = Pm_GetDefaultOutputDeviceID(); | ||
| 225 | for (i = 0; i < Pm_CountDevices(); i++) { | ||
| 226 | const PmDeviceInfo *info = Pm_GetDeviceInfo(i); | ||
| 227 | if (!info->output) { | ||
| 228 | printf("%d: %s, %s", i, info->interf, info->name); | ||
| 229 | if (i == deviceno) { | ||
| 230 | device_valid = TRUE; | ||
| 231 | deflt = "selected "; | ||
| 232 | } else if (i == default_out) { | ||
| 233 | deflt = "default "; | ||
| 234 | } else { | ||
| 235 | deflt = ""; | ||
| 236 | } | ||
| 237 | printf(" (%sinput)\n", deflt); | ||
| 238 | } | ||
| 239 | } | ||
| 240 | printf("%d: Create virtual port named \"fastrcv\"", i); | ||
| 241 | if (i == deviceno) { | ||
| 242 | device_valid = TRUE; | ||
| 243 | deflt = "selected "; | ||
| 244 | } else { | ||
| 245 | deflt = ""; | ||
| 246 | } | ||
| 247 | printf(" (%sinput)\n", deflt); | ||
| 248 | |||
| 249 | if (!device_valid) { | ||
| 250 | deviceno = get_number("Input device number: "); | ||
| 251 | } | ||
| 252 | |||
| 253 | fastrcv_test(); | ||
| 254 | return 0; | ||
| 255 | } | ||
