source: buchla-68k/orig/GEMDOS/MVIEW.C

Last change on this file was 3ae31e9, checked in by Thomas Lopatic <thomas@…>, 7 years ago

Imported original source code.

  • Property mode set to 100755
File size: 20.7 KB
Line 
1/*
2 =============================================================================
3 mview.c -- display MIDI data
4 See VERMSG below for version and date.
5
6 Loosely based on the GEM program:
7 midiview.c -- a MIDI data display program -- 7/22/87 by J. Johnson
8
9 Set up for Alcyon C.
10 =============================================================================
11*/
12
13#define VERMSG "mview -- Version 2.08 -- 1989-12-12 -- D.N. Lynx Crowe"
14
15#include "stdio.h"
16#include "osbind.h"
17#include "stddefs.h"
18
19#define void int
20
21#define SNAPFILE "MVIEWSNP.DAT"
22
23#define MBUFSZ (unsigned short)(16*1024)
24
25#define n_str "CCDDEFFGGAAB" /* For data to note conversion */
26
27#define MAXNOL 2
28
29#define FORMAT1 "\n%5u %02.2xH %-16.16s"
30#define FORMAT2 " %02.2xH %3u %-14.14s"
31#define FORMAT3 "\n%5u "
32
33extern char *malloc();
34
35void PrMIDI(), cleanbf(), interp();
36void type2tx(), n2note(), n2cc(), n2pb();
37void n2spp(), itoa(), r_strng();
38
39int SetMBuf(), midi_in(), m_stat(), n2stat(), n2chms();
40
41struct iorec { /* structure for MIDI buffer description */
42
43 char *ibuf;
44 short ibufsz;
45 short ibufhd;
46 short ibuftl;
47 short ibuflo;
48 short ibufhi;
49};
50
51unsigned int indx; /* MIDI input byte number */
52
53int feseen; /* active sensing seen */
54int nbyte = 1; /* counter for two byte MIDI data fields */
55int nol; /* number of MIDI data bytes on the line */
56
57FILE *ofp; /* output file pointer */
58FILE *sfp; /* snap file pointer */
59
60char *newbuf;
61char *oldbuf; /* old MIDI buffer pointer */
62short oldbsz;
63short oldbhi;
64short oldblo;
65
66struct iorec *m_buff; /* MIDI iorec pointer */
67
68/*
69
70*/
71
72/* SetMBuf -- set up MIDI buffer */
73
74int
75SetMBuf()
76{
77 unsigned short size;
78
79 size = MBUFSZ; /* MIDI buffer */
80
81 m_buff = (struct iorec *)Iorec(2); /* pointer to buffer descriptor */
82
83 oldbuf = m_buff->ibuf;
84 oldbsz = m_buff->ibufsz;
85 oldbhi = m_buff->ibufhi;
86 oldblo = m_buff->ibuflo;
87
88 if ((char *)NULL EQ (newbuf = (char *)malloc(size))) {
89
90 printf ("ERROR -- unable to allocate MIDI buffer.\n");
91 return(FAILURE);
92 }
93
94 /* clear out the buffer */
95
96 m_buff->ibufhd = 0; /* reset the head index */
97 m_buff->ibuftl = 0; /* reset the tail index */
98
99 /* we do this twice because we aren't disabling interrupts ... */
100
101 m_buff->ibufhd = 0; /* reset the head index */
102 m_buff->ibuftl = 0; /* reset the tail index */
103
104 m_buff->ibuf = newbuf; /* change address of buffer */
105 m_buff->ibufsz = size; /* change size of buffer */
106
107 indx = 0; /* reset the byte index */
108
109 return(SUCCESS);
110}
111
112/* get MIDI byte */
113
114int
115midi_in()
116{
117 return((int)Bconin(3) & 0X00FF);
118}
119
120/* output an interpreted MIDI data byte */
121
122void
123PrMIDI(M_Byte)
124int M_Byte;
125{
126 char i_str[120];
127
128 if ((0x00FF & M_Byte) EQ 0x00FE) {
129
130 if (NOT feseen) {
131
132 printf("\nActive sense is active\n");
133
134 if ((FILE *)NULL NE ofp)
135 fprintf(ofp, "\nActive sense is active\n");
136 }
137
138 nol = 0;
139 feseen = TRUE;
140
141 } else {
142
143 interp(M_Byte, i_str);
144
145 ++indx;
146
147 if (0x0080 & M_Byte) { /* new status byte */
148
149 nol = 0;
150 printf(FORMAT1, indx, M_Byte, i_str);
151
152 if ((FILE *)NULL NE ofp)
153 fprintf(ofp, FORMAT1, indx, M_Byte, i_str);
154
155 } else { /* data byte */
156
157 if (++nol > MAXNOL) {
158
159 printf(FORMAT3, indx);
160
161 if ((FILE *)NULL NE ofp)
162 fprintf(ofp, FORMAT3, indx);
163
164 nol = 1;
165 }
166
167 printf(FORMAT2, M_Byte, M_Byte, i_str);
168
169 if ((FILE *)NULL NE ofp)
170 fprintf(ofp, FORMAT2, M_Byte, M_Byte, i_str);
171 }
172 }
173
174 fflush(stdout);
175
176 if ((FILE *)NULL NE ofp)
177 fflush(ofp);
178}
179
180/* check midi status */
181
182int
183m_stat()
184{
185 return((int)Bconstat(3) ? TRUE : FALSE);
186}
187
188/* clean out MIDI buffer */
189
190void
191cleanbf()
192{
193 int mstat;
194
195 printf("Clearing MIDI input buffer ...\n");
196
197 /* clear out the buffer by resetting the head and tail indices */
198
199 m_buff->ibufhd = 0; /* reset the head index */
200 m_buff->ibuftl = 0; /* reset the tail index */
201
202 /* we do this twice because we aren't disabling interrupts ... */
203
204 m_buff->ibufhd = 0; /* reset the head index */
205 m_buff->ibuftl = 0; /* reset the tail index */
206
207 /* make sure it's really drained */
208
209 mstat = m_stat();
210
211 while (mstat) {
212
213 midi_in();
214 mstat = m_stat();
215 }
216
217 indx = 0;
218}
219
220void
221interp(M_Byte, i_str)
222int M_Byte;
223char *i_str;
224{
225 static int type;
226
227 if (M_Byte & 0x0080) { /* status byte */
228
229 type = n2stat(M_Byte, i_str, type);
230
231 } else if (nbyte == 1) { /* 1st data byte */
232
233 switch (type) {
234
235 case 0:
236 type2tx(type, i_str);
237 break;
238 case 1:
239 case 2:
240 n2note(M_Byte, i_str);
241 break;
242 case 3:
243 n2cc(M_Byte, i_str);
244 break;
245 case 4:
246 type2tx(type, i_str);
247 break;
248 case 5:
249 n2pb(M_Byte, i_str);
250 break;
251 case 6:
252 n2spp(M_Byte, i_str);
253 break;
254 }
255
256 } else { /* subsequent data bytes */
257
258 switch (type) {
259
260 case 0:
261 case 1:
262 case 2:
263 case 3:
264 case 4:
265 type2tx(type, i_str);
266 break;
267 case 5:
268 n2pb(M_Byte, i_str);
269 break;
270 case 6:
271 n2spp(M_Byte, i_str);
272 break;
273 }
274 }
275
276 return;
277}
278
279/* convert MIDI status byte to text description */
280
281int
282n2stat(M_Byte, i_str, O_type)
283int M_Byte, O_type;
284char *i_str;
285{
286 char *int_str;
287 int N_type;
288
289 N_type = O_type;
290
291 if (M_Byte < 240) {
292
293 N_type = n2chms(M_Byte, i_str, N_type);
294 nbyte = 1;
295
296 } else {
297
298 switch (M_Byte) {
299
300 case 240:
301 int_str = "SysEx";
302 N_type = 4;
303 nbyte = 1;
304 break;
305 case 242:
306 int_str = "Song Pos";
307 N_type = 6;
308 nbyte = 1;
309 break;
310 case 243:
311 int_str = "Song Sel";
312 N_type = 4;
313 nbyte = 1;
314 break;
315 case 246:
316 int_str = "Tune";
317 N_type = 0;
318 break;
319 case 247:
320 int_str = "End SysEx";
321 N_type = 0;
322 break;
323 case 248:
324 int_str = "Clock";
325 break;
326 case 250:
327 int_str = "Start";
328 break;
329 case 251:
330 int_str = "Continue";
331 break;
332 case 252:
333 int_str = "Stop";
334 break;
335 case 254:
336 int_str = "Act Sense";
337 break;
338 case 255:
339 int_str = "Sys Reset";
340 break;
341 default:
342 int_str = "Undefined";
343 N_type = 0;
344 break;
345 }
346
347 strcpy(i_str, int_str);
348 }
349
350 return(N_type);
351}
352
353/* convert MIDI byte to channel message description */
354
355int
356n2chms(M_Byte, i_str, O_type)
357int M_Byte, O_type;
358char *i_str;
359{
360 int T_nybl, channel, N_type;
361 char ch_strg[3], *int_str;
362
363 N_type = O_type;
364 T_nybl = ((M_Byte & 0x0070) >> 4);
365 channel = (M_Byte & 0x000F) + 1;
366 int_str = "???";
367
368 switch (T_nybl) {
369
370 case 0:
371 int_str = "Note Off, Ch ";
372 N_type = 1;
373 break;
374 case 1:
375 int_str = "Note On , Ch ";
376 N_type = 1;
377 break;
378 case 2:
379 int_str = "Key Pres, Ch ";
380 N_type = 2;
381 break;
382 case 3:
383 int_str = "Ctrl Chg, Ch ";
384 N_type = 3;
385 break;
386 case 4:
387 int_str = "Prog Chg, Ch ";
388 N_type = 4;
389 break;
390 case 5:
391 int_str = "Chan Prs, Ch ";
392 N_type = 2;
393 break;
394 case 6:
395 int_str = "Pch Bend, Ch ";
396 N_type = 5;
397 break;
398 }
399
400 strcpy(i_str, int_str);
401 itoa(channel, ch_strg);
402 strcat(i_str, ch_strg);
403 return(N_type);
404}
405
406/* convert MIDI data byte to text description */
407
408void
409type2tx(number, text)
410int number;
411char *text;
412{
413 char *string;
414
415 switch (number) {
416
417 default:
418 case 0:
419 string = "????";
420 break;
421 case 1:
422 string = "Vel ";
423 nbyte = 1;
424 break;
425 case 2:
426 case 3:
427 string = "Val ";
428 nbyte = 1;
429 break;
430 case 4:
431 string = "Data";
432 break;
433 }
434
435 strcpy(text, string);
436}
437
438/* convert MIDI note number to Dr. T pitch notation */
439/* data types 1 & 2 */
440
441void
442n2note(number, note)
443int number;
444char *note;
445{
446 int octave, pitch;
447
448 nbyte = 2; /* next byte is velocity value */
449 *(note + 3) = '\0';
450 octave = (number / 12) - 1;
451
452 switch (octave) {
453
454 case -1:
455 *(note + 2) = '-';
456 break;
457
458 default:
459 *(note + 2) = octave + 48;
460 break;
461 }
462
463 pitch = number % 12;
464 *note = n_str[pitch];
465
466 switch (pitch) {
467
468 case 1:
469 case 3:
470 case 6:
471 case 8:
472 case 10:
473 *(note + 1) = '#';
474 break;
475 default:
476 *(note + 1) = ' ';
477 break;
478 }
479}
480
481
482/* convert MIDI controller to text description */
483/* data type 3 */
484
485void
486n2cc(number, ctrler)
487int number;
488char *ctrler;
489{
490 char *string;
491
492 nbyte = 2;
493
494 switch(number) {
495
496 case 1:
497 case 33:
498 string = "Mod Wheel";
499 break;
500 case 2:
501 case 34:
502 string = "Brth Ctrl";
503 break;
504 case 3: /* not in the 9/1/86 MIDI controller list */
505 case 35:
506 string = "DX7 Prs";
507 break;
508 case 4:
509 case 36:
510 string = "Pedal";
511 break;
512 case 5:
513 case 37:
514 string = "Port Time";
515 break;
516 case 6:
517 case 38:
518 string = "Data Entry";
519 break;
520 case 7:
521 case 39:
522 string = "Volume";
523 break;
524 case 8:
525 case 40:
526 string = "Balance";
527 break;
528 case 10:
529 case 42:
530 string = "Pan";
531 break;
532 case 11:
533 case 43:
534 string = "Expression";
535 break;
536 case 16:
537 case 48:
538 string = "GPC #1";
539 break;
540 case 17:
541 case 49:
542 string = "GPC #2";
543 break;
544 case 18:
545 case 50:
546 string = "GPC #3";
547 break;
548 case 19:
549 case 51:
550 string = "GPC #4";
551 break;
552 case 64:
553 string = "Sustain Sw";
554 break;
555 case 65:
556 string = "Port Sw";
557 break;
558 case 66:
559 string = "Sustenuto Sw";
560 break;
561 case 67:
562 string = "Soft Pedal";
563 break;
564 case 69:
565 string = "Hold 2 Sw";
566 break;
567 case 80:
568 string = "GPC #5";
569 break;
570 case 81:
571 string = "GPC #6";
572 break;
573 case 82:
574 string = "GPC #7";
575 break;
576 case 83:
577 string = "GPC #8";
578 break;
579 case 91:
580 string = "FX Depth";
581 break;
582 case 92:
583 string = "Tremolo";
584 break;
585 case 93:
586 string = "Chorus";
587 break;
588 case 94:
589 string = "Celeste";
590 break;
591 case 95:
592 string = "Phaser";
593 break;
594 case 96:
595 string = "Data Inc";
596 break;
597 case 97:
598 string = "Data Dec";
599 break;
600 case 98:
601 string = "NReg Param MSB"; /* ? */
602 break;
603 case 99:
604 string = "NReg Param LSB"; /* ? */
605 break;
606 case 100:
607 string = "Reg Param MSB"; /* ? */
608 break;
609 case 101:
610 string = "Reg Param LSB"; /* ? */
611 break;
612 case 122:
613 string = "Local Control";
614 break;
615 case 123:
616 string = "All Notes Off";
617 break;
618 case 124:
619 string = "Omni Off";
620 break;
621 case 125:
622 string = "Omni On";
623 break;
624 case 126:
625 string = "Mono On";
626 break;
627 case 127:
628 string = "Poly On";
629 break;
630 default:
631 string = "Unasg Ctrl";
632 break;
633 }
634
635 strcpy(ctrler, string);
636
637 if ((number > 31) && (number < 64))
638 strcat(ctrler, ", LSB");
639}
640
641/* convert MIDI pitch bend to value */
642/* data type 5 */
643
644void
645n2pb(number, value)
646int number;
647char *value;
648{
649 char *string;
650 static int P_bend;
651
652 if (nbyte == 1) {
653
654 string = " ";
655 P_bend = number;
656 nbyte = 2;
657 strcpy(value, string);
658
659 } else {
660
661 P_bend += (number << 7);
662 P_bend -= 8192;
663 itoa(P_bend, value);
664 nbyte = 1;
665 }
666}
667
668/* convert MIDI song position pointer to text description */
669/* data type 6 */
670
671void
672n2spp(number, pointer)
673int number;
674char *pointer;
675{
676 int measure, beat, clock;
677 static int spp;
678 char *string, b[3], c[3], *colon;
679
680 colon = ":";
681
682 if (nbyte == 1) {
683
684 string = " ";
685 spp = number;
686 nbyte = 2;
687 strcpy(pointer, string);
688
689 } else {
690
691 spp += number * 128;
692 measure = (spp / 16) + 1;
693 itoa(measure, pointer);
694 beat = ((spp % 16) / 4) + 1;
695 itoa(beat,b);
696 clock = (6 * ((spp % 16) % 4) + 1);
697 itoa(clock, c);
698 strcat(pointer, colon);
699 strcat(pointer, b);
700 strcat(pointer, colon);
701 strcat(pointer, c);
702 nbyte = 1;
703 }
704}
705
706/* convert integer to string */
707
708void
709itoa(number, string)
710char string[];
711int number;
712{
713 int i, sign;
714
715 if ((sign = number) < 0 )
716 number = -number;
717
718 i = 0;
719
720 do {
721
722 string[i++] = number % 10 + '0';
723
724 } while ((number /= 10) > 0);
725
726 if (sign < 0)
727 string[i++] = '-';
728
729 string[i] = '\0';
730 r_strng(string);
731}
732
733/* reverse string in place */
734
735void
736r_strng(string)
737char string[];
738{
739 int c, i, j;
740
741 for (i = 0, j = strlen(string) - 1; i < j; i++, j--) {
742
743 c = string[i];
744 string[i] = string[j];
745 string[j] = c;
746 }
747}
748
749
750/*
751
752*/
753
754main(argc, argv)
755int argc;
756char *argv[];
757{
758 int ch, runtag;
759
760 ofp = (FILE *)NULL;
761
762 printf("\033E%s\n\n", VERMSG);
763 printf("ESC to quit, / to clear buffer, space to pause output.\n\n");
764
765 if (SetMBuf()) /* move MIDI buffer & increase its size */
766 exit(2);
767
768 printf("%u byte MIDI buffer allocated at 0x%08.8lx\n",
769 MBUFSZ, (long)newbuf);
770
771 cleanbf(); /* clear out MIDI buffer */
772
773 if (argc EQ 2) {
774
775 if ((FILE *)NULL EQ (ofp = fopen(argv[1], "w"))) {
776
777 printf("ERROR -- Unable to open \"%s\" for output.\n",
778 argv[1]);
779
780 exit(2);
781
782 } else {
783
784 printf("Outputting to file \"%s\".\n", argv[1]);
785 }
786 }
787
788 printf("Ready for MIDI data.\n");
789 runtag = TRUE;
790
791 while (runtag) {
792
793 if (Bconstat(2)) {
794
795 ch = 0x00FF & Bconin(2);
796
797 switch (ch) {
798
799 case '\033': /* escape */
800
801 runtag = FALSE;
802 break;
803
804 case ' ': /* space = pause */
805
806 printf("PAUSED");
807 Bconin(2);
808 printf("\b\b\b\b\b\b \b\b\b\b\b\b");
809
810 break;
811
812 case '/': /* / = clear buffer and screen */
813
814 cleanbf();
815 printf("\033E");
816 printf("Ready for MIDI data.\n");
817
818 if ((FILE *)NULL NE ofp) {
819
820 fprintf(ofp, "\n\nMIDI buffer flushed.\n\n");
821 fflush(ofp);
822 }
823
824 break;
825
826 case 'w': /* w = write to SNAPFILE */
827
828 if ((FILE *)NULL EQ (sfp = fopenb(SNAPFILE, "w"))) {
829
830 printf("ERROR -- Unable to open \"%s\" for output.\n",
831 SNAPFILE);
832
833 exit(2);
834
835 } else {
836
837 printf("\n\nOutputting to file \"%s\".\n", SNAPFILE);
838 }
839
840 fwrite(newbuf, indx, 1, sfp);
841
842 fflush(sfp);
843 fclose(sfp);
844
845 printf("\nFile written and closed.\n\n");
846 break;
847 }
848 }
849
850 if (m_stat())
851 PrMIDI(midi_in());
852
853 if ((FILE *)NULL NE ofp)
854 fflush(ofp);
855 }
856
857 if ((FILE *)NULL NE ofp) {
858
859 fprintf(ofp, "\n");
860 fflush(ofp);
861 fclose(ofp);
862 }
863
864 /* clear out the buffer */
865
866 m_buff->ibufhd = 0; /* reset the head index */
867 m_buff->ibuftl = 0; /* reset the tail index */
868
869 /* we do this twice because we aren't disabling interrupts ... */
870
871 m_buff->ibufhd = 0; /* reset the head index */
872 m_buff->ibuftl = 0; /* reset the tail index */
873
874 m_buff->ibufsz = oldbsz; /* restore the old buffer size */
875 m_buff->ibuf = oldbuf; /* restore the old buffer address */
876
877 free(newbuf); /* give back the big MIDI buffer */
878
879 printf("\n");
880 fflush(stdout);
881 exit(0);
882}
Note: See TracBrowser for help on using the repository browser.