New upstream version 20201012
Dennis Braun
3 years ago
48 | 48 | |
49 | 49 | |
50 | 50 | |
51 | #define VERSION "1.75 October 01 2020 abcmatch" | |
51 | #define VERSION "1.75 October 12 2020 abcmatch" | |
52 | 52 | #include <stdio.h> |
53 | 53 | #include <stdlib.h> |
54 | 54 | #include <ctype.h> |
13908 | 13908 | yapstree.c, etc. which replaces the change made on December 09 2019. |
13909 | 13909 | Except for yapstree.c, event_score_linebreak does nothing. |
13910 | 13910 | |
13911 | ||
13912 | October 10 2020 | |
13913 | midicopy new feature: -zerochannels will set all channel numbers in | |
13914 | the midi file to zero. Some midi files (http://scarlatti.antikytherapubs.com/ ) | |
13915 | adjust the tuning by assigning each pitch class to a separate channel | |
13916 | and applying an appropriate pitchbend to each of these channels. | |
13917 | This may pose a problem for some software which attempts to render the | |
13918 | midi file in music notation. | |
13919 | ||
13920 | ||
13921 | October 12 2020 | |
13922 | James Allwright has made significant improvements to parseabc.c, toabc.c, | |
13923 | and yapstree.c related to repeat checking. In parseabc.c, new functions | |
13924 | were introduced: init_voice_contexts, reset_parser_status, | |
13925 | interpret_voice_label, check_bar_repeats, and check_and_call_bar(). | |
13926 | The functions isnumberp(), init_voicecode(), and interpret_voicestring() | |
13927 | have been retired. Reset_parser_status() is called each time a new | |
13928 | X: reference field command is encountered. Check_bar_repeats() replaces | |
13929 | a lot of the code that appears in event_bar() defined in toabc.c and | |
13930 | yapstree.c. parsemusic() calls event_bar indirectly through the | |
13931 | function check_and_call_bar(). Minor changes were made to toabc.c, store.c | |
13932 | and yapstree.c to accommodate the changes to parseabc. In particular, | |
13933 | a new flag repcheck is introduced and connected to parseabc.c as | |
13934 | an extern (in parseabc.h). In addition a new struct (voice_context) | |
13935 | has been introduced in parseabc.h. | |
13936 | ||
13937 | ||
13938 | ||
13939 |
0 | 0 | abcMIDI : abc <-> MIDI conversion utilities |
1 | 1 | |
2 | 2 | midi2abc version 3.46 June 22 2020 |
3 | abc2midi version 4.42 October 01 2020 | |
4 | abc2abc version 2.10 October 01 2020 | |
5 | yaps version 1.80 October 07 2020 | |
6 | abcmatch version 1.74 October 01 2020 | |
7 | midicopy version 1.36 June 04 2019 | |
3 | abc2midi version 4.43 October 12 2020 | |
4 | abc2abc version 2.11 October 12 2020 | |
5 | yaps version 1.81 October 12 2020 | |
6 | abcmatch version 1.75 October 12 2020 | |
7 | midicopy version 1.37 October 10 2020 | |
8 | 8 | |
9 | 9 | 24th January 2002 |
10 | 10 | |
439 | 439 | -focusontrack n1,n2,... |
440 | 440 | -focusonchannel n1,n2,... |
441 | 441 | -attenuation n |
442 | -nobends | |
443 | -indrums n1,n2,... (drums to include) | |
444 | -xdrums n1,n2,... (drums to exclude) | |
445 | -onlydrums (only channel 10) | |
446 | -nodrums (exlcude channel 10) | |
447 | -zerochannels set all channel numbers to zero | |
442 | 448 | |
443 | 449 | |
444 | 450 | midicopy.exe -ver |
823 | 823 | /* used internally by other routines when octave=N is encountered */ |
824 | 824 | /* in I: or K: fields */ |
825 | 825 | int num; |
826 | int local; | |
826 | 827 | { |
827 | 828 | if (dotune) { |
828 | 829 | if (pastheader || local) { |
51 | 51 | |
52 | 52 | |
53 | 53 | |
54 | #define VERSION "1.36 June 04 2020 midicopy" | |
54 | #define VERSION "1.37 October 10 2020 midicopy" | |
55 | 55 | #include "midicopy.h" |
56 | 56 | #define NULLFUNC 0 |
57 | 57 | #define NULL 0 |
111 | 111 | int drumvelocity = 0; /* [SS] 2013-10-01 */ |
112 | 112 | int attenuation = 70; /* [SS] 2017-11-27 */ |
113 | 113 | int nobends = 0; /* [SS] 2017-12-15 */ |
114 | int zerochannels = 0; /* [SS] 2020-10-09 */ | |
114 | 115 | |
115 | 116 | long Mf_numbyteswritten = 0L; |
116 | 117 | long readvarinum (); |
1024 | 1025 | chanmessage (int status, int c1, int c2) |
1025 | 1026 | { |
1026 | 1027 | int chan = status & 0xf; |
1028 | if (zerochannels) chan = 0; /* [SS] 2020-10-09 */ | |
1027 | 1029 | haschannel[chan] = 1; |
1028 | 1030 | |
1029 | 1031 | if (!cut_beginning ()) |
1852 | 1854 | printf ("-xdrums n1,n2,... (drums to exclude)\n"); /* [SS] 2019-12-22 */ |
1853 | 1855 | printf ("-onlydrums (only channel 10)\n"); /* [SS] 2019-12-22 */ |
1854 | 1856 | printf ("-nodrums (exlcude channel 10)\n"); /* [SS] 2019-12-22 */ |
1857 | printf ("-zerochannels set all channel numbers to zero\n"); /* [SS] 2020-10-09 */ | |
1855 | 1858 | exit (1); |
1856 | 1859 | } |
1857 | 1860 | |
2136 | 2139 | arg = getarg("-nodrums",argc,argv); /* [SS] 2019-12-22 */ |
2137 | 2140 | if (arg >=0) ctocopy[9] = 0; |
2138 | 2141 | |
2142 | arg = getarg("-zerochannels",argc,argv); /* [SS] 2020-10-09 */ | |
2143 | if (arg >=0) zerochannels = 1; | |
2144 | ||
2139 | 2145 | F_in = fopen (argv[argc - 2], "rb"); |
2140 | 2146 | if (F_in == NULL) |
2141 | 2147 | { |
89 | 89 | char decorations[] = ".MLRH~Tuv'OPS"; /* 2020-05-01 */ |
90 | 90 | char *abbreviation[SIZE_ABBREVIATIONS]; |
91 | 91 | |
92 | int voicecodes = 0; | |
93 | /* [SS] 2015-03-16 allow 24 voices */ | |
94 | /*char voicecode[16][30]; for interpreting V: string */ | |
95 | char voicecode[24][30]; /*for interpreting V: string */ | |
92 | int num_voices = 0; /* [JA] 2020-10-12 */ | |
93 | int repcheck = 1; /* enables/ disables repeat checking */ | |
94 | /* abc2midi disables repeat checking because it does its own thing */ | |
95 | voice_context_t voicecode[MAX_VOICES]; | |
96 | int voicenum; /* current voice number */ | |
97 | int has_voice_fields = 0; | |
96 | 98 | |
97 | 99 | int decorators_passback[DECSIZE]; |
98 | 100 | /* this global array is linked as an external to store.c and |
327 | 329 | while (((int) **p != ' ') && ((int) **p != TAB) && (int) **p != '\0') |
328 | 330 | *p = *p + 1; |
329 | 331 | } |
330 | ||
331 | ||
332 | int | |
333 | isnumberp (p) | |
334 | char **p; | |
335 | /* returns 1 if positive number, returns 0 if not a positive number */ | |
336 | /* ie -4 or 1A both return 0. This function is needed to get the */ | |
337 | /* voice number. */ | |
338 | { | |
339 | char **c; | |
340 | c = p; | |
341 | while (( **c != ' ') && ( **c != TAB) && **c != '\0') | |
342 | { | |
343 | if (( **c >= 0) && (**c <= 9)) /*[SDG] 2020-06-03 */ | |
344 | *c = *c + 1; | |
345 | else | |
346 | return 0; | |
347 | } | |
348 | return 1; | |
349 | /* could use isdigit(**c) */ | |
350 | /* is zero a positive number? is V:0 ok? [SS] */ | |
351 | } | |
352 | ||
353 | ||
354 | 332 | |
355 | 333 | int |
356 | 334 | readnumf (num) |
787 | 765 | }; |
788 | 766 | } |
789 | 767 | |
790 | ||
791 | void | |
792 | init_voicecode () | |
768 | /* [JA] 2020-10-12 */ | |
769 | void init_voice_contexts (void) | |
793 | 770 | { |
794 | 771 | int i; |
795 | for (i = 0; i < 24; i++) /* [SS} 2015-03-15 */ | |
796 | voicecode[i][0] = 0; | |
797 | voicecodes = 0; | |
798 | } | |
772 | for (i = 0; i < MAX_VOICES; i++) { /* [SS} 2015-03-15 */ | |
773 | voicecode[i].label[0] = '\0'; | |
774 | voicecode[i].expect_repeat = 0; | |
775 | voicecode[i].repeat_count = 0; | |
776 | } | |
777 | } | |
778 | ||
779 | /* [JA] 2020-10-12 */ | |
780 | /* called at the start of each tune */ | |
781 | static void reset_parser_status (void) | |
782 | { | |
783 | voicenum = 0; | |
784 | has_voice_fields = 0; | |
785 | num_voices = 1; | |
786 | parserinchord = 0; | |
787 | ingrace = 0; | |
788 | slur = 0; | |
789 | init_voice_contexts (); | |
790 | } | |
791 | ||
799 | 792 | |
800 | 793 | void |
801 | 794 | print_voicecodes () |
802 | 795 | { |
803 | 796 | int i; |
804 | if (voicecodes == 0) | |
797 | if (num_voices == 0) | |
805 | 798 | return; |
806 | 799 | printf ("voice mapping:\n"); |
807 | for (i = 0; i < voicecodes; i++) | |
800 | for (i = 0; i < num_voices; i++) | |
808 | 801 | { |
809 | 802 | if (i % 4 == 3) |
810 | 803 | printf ("\n"); |
811 | printf ("%s %d ", voicecode[i], i + 1); | |
804 | printf ("%s %d ", voicecode[i].label, i + 1); | |
812 | 805 | } |
813 | 806 | printf ("\n"); |
814 | 807 | } |
815 | 808 | |
816 | int | |
817 | interpret_voicestring (char *s) | |
818 | { | |
819 | /* if V: is followed by a string instead of a number | |
820 | * we check to see if we have encountered this string | |
821 | * before. We assign the number associated with this | |
822 | * string and add it to voicecode if it was not encountered | |
823 | * before. If more than 16 distinct strings were encountered | |
824 | * we report an error -1. | |
809 | /* [JA] 2020-10-12 */ | |
810 | int interpret_voice_label (char *s, int num) | |
811 | /* We expect a numeric value indicating the voice number. | |
812 | * The assumption is that these will ocuur in the order in which voices | |
813 | * appear, so that we have V:1, V:2, ... V:N if there are N voices. | |
814 | * The abc standard 2.2 allows strings instead of these numbers to | |
815 | * represent voices. | |
816 | * This function should be called with either | |
817 | * an empty string and a valid num or | |
818 | * a valid string and num set to 0. | |
819 | * | |
820 | * If num is non-zero, we check that it is valid and return it. | |
821 | * If the number is one above the number of voices currently in use, | |
822 | * we allocate a new voice. | |
823 | * | |
824 | * If num is zero and the string is not empty, we check if string | |
825 | * has been assigned to one of the existing voices. If not, we | |
826 | * allocate a new voice and assign the string to it. | |
827 | * | |
828 | * If we exceed MAX_VOICES voices, we report an error. | |
829 | * | |
830 | * we return a voice number in the range 1 - num_voices | |
825 | 831 | */ |
832 | { | |
826 | 833 | int i; |
827 | 834 | char code[32]; |
828 | char msg[80]; /* [PHDM] 2012-11-22 */ | |
835 | char msg[80]; /* [PHDM] 2012-11-22 */ | |
829 | 836 | char *c; |
830 | 837 | c = readword (code, s); |
831 | 838 | |
839 | if (num > 0) | |
840 | { | |
841 | if (num > num_voices + 1) | |
842 | { | |
843 | char error_message[80]; | |
844 | ||
845 | snprintf(error_message, 80, "V:%d out of sequence, treating as V:%d", | |
846 | num, num_voices); | |
847 | event_warning(error_message); | |
848 | num = num_voices + 1; | |
849 | } | |
850 | /* declaring a new voice */ | |
851 | if (num == num_voices + 1) | |
852 | { | |
853 | if (num_voices >= MAX_VOICES) | |
854 | { | |
855 | event_warning("Number of available voices exceeded"); | |
856 | return 1; | |
857 | } | |
858 | num_voices = num_voices + 1; | |
859 | voicecode[num_voices - 1].label[0] = '\0'; | |
860 | } | |
861 | return num; | |
862 | } | |
832 | 863 | /* [PHDM] 2012-11-22 */ |
833 | if (*c != '\0' && *c != ' ' && *c != ']') | |
834 | { | |
835 | sprintf (msg, "invalid character `%c' in Voice ID", *c); | |
836 | event_error (msg); | |
837 | } | |
864 | if (*c != '\0' && *c != ' ' && *c != ']') { | |
865 | sprintf (msg, "invalid character `%c' in Voice ID", *c); | |
866 | event_error (msg); | |
867 | } | |
838 | 868 | /* [PHDM] 2012-11-22 */ |
839 | 869 | |
840 | 870 | if (code[0] == '\0') |
841 | return 0; | |
842 | if (voicecodes == 0) | |
843 | { | |
844 | strcpy (voicecode[voicecodes], code); | |
845 | voicecodes++; | |
846 | return voicecodes; | |
847 | } | |
848 | for (i = 0; i < voicecodes; i++) | |
849 | if (stringcmp (code, voicecode[i]) == 0) | |
850 | return (i + 1); | |
851 | if ((voicecodes + 1) > 23) /* [SS] 2015-03-16 */ | |
852 | return -1; | |
853 | strcpy (voicecode[voicecodes], code); | |
854 | voicecodes++; | |
855 | return voicecodes; | |
871 | { | |
872 | event_warning("Empty V: field, treating as V:1"); | |
873 | return 1; | |
874 | } | |
875 | /* Has supplied label been used for one of the existing voices ? */ | |
876 | if (has_voice_fields) | |
877 | { | |
878 | for (i = 0; i < num_voices; i++) { | |
879 | if (strcmp (code, voicecode[i].label) == 0) { | |
880 | return i + 1; | |
881 | } | |
882 | } | |
883 | } | |
884 | /* if we have got here, we have a new voice */ | |
885 | if ((num_voices + 1) > MAX_VOICES) {/* [SS] 2015-03-16 */ | |
886 | event_warning("Number of available voices exceeded"); | |
887 | return 1; | |
888 | } | |
889 | /* First V: field is a special case. We are already on voice 1, | |
890 | * so we don't increment the number of voices, but we will set | |
891 | * status->has_voice_fields on returning from this function. | |
892 | */ | |
893 | if (has_voice_fields) | |
894 | { | |
895 | num_voices++; | |
896 | } | |
897 | strncpy (voicecode[num_voices - 1].label, code, 31); | |
898 | return num_voices; | |
856 | 899 | } |
857 | 900 | |
858 | 901 | /* The following three functions parseclefs, parsetranspose, |
1478 | 1521 | vparams.other[0] = '\0'; /* [SS] 2011-04-18 */ |
1479 | 1522 | |
1480 | 1523 | skipspace (&s); |
1481 | if (isnumberp (&s) == 1) | |
1482 | { | |
1483 | num = readnump (&s); | |
1484 | } | |
1485 | else | |
1486 | { | |
1487 | num = interpret_voicestring (s); | |
1488 | if (num == 0) | |
1489 | event_error ("No voice number or string in V: field"); | |
1490 | if (num == -1) | |
1491 | { | |
1492 | event_error ("More than 16 voices encountered in V: fields"); | |
1493 | num = 0; | |
1494 | } | |
1495 | skiptospace (&s); | |
1496 | }; | |
1524 | num = 0; | |
1525 | if (isdigit(*s)) { /* [JA] 2020-10-12 */ | |
1526 | num = readnump (&s); | |
1527 | } | |
1528 | num = interpret_voice_label (s, num); | |
1529 | has_voice_fields = 1; | |
1530 | skiptospace (&s); | |
1531 | voicenum = num; | |
1497 | 1532 | skipspace (&s); |
1498 | 1533 | while (*s != '\0') |
1499 | 1534 | { |
2114 | 2149 | { |
2115 | 2150 | event_error ("second X: field in header"); |
2116 | 2151 | }; |
2152 | if (inbody) | |
2153 | { | |
2154 | /* [JA] 2020-10-14 */ | |
2155 | event_error ("Missing blank line before new tune"); | |
2156 | } | |
2117 | 2157 | event_refno (x); |
2118 | 2158 | ignore_line =0; /* [SS] 2017-04-12 */ |
2119 | init_voicecode (); /* [SS] 2011-01-01 */ | |
2159 | reset_parser_status(); /* [JA] 2020-10-12 */ | |
2120 | 2160 | inhead = 1; |
2121 | 2161 | inbody = 0; |
2122 | 2162 | parserinchord = 0; |
2375 | 2415 | printf ("\n"); |
2376 | 2416 | } |
2377 | 2417 | |
2418 | /* [JA] 2020-10-12 */ | |
2419 | /* Look for problems in the use of repeats */ | |
2420 | static void check_bar_repeats (int bar_type, char *replist) | |
2421 | { | |
2422 | voice_context_t *cv = &voicecode[voicenum]; | |
2423 | ||
2424 | switch (bar_type) { | |
2425 | case SINGLE_BAR: | |
2426 | break; | |
2427 | case DOUBLE_BAR: | |
2428 | break; | |
2429 | case THIN_THICK: | |
2430 | break; | |
2431 | case THICK_THIN: | |
2432 | break; | |
2433 | case BAR_REP: | |
2434 | if (cv->expect_repeat) { | |
2435 | event_warning ("Expecting repeat, found |:"); | |
2436 | }; | |
2437 | cv->expect_repeat = 1; | |
2438 | cv->repeat_count = cv->repeat_count + 1; | |
2439 | break; | |
2440 | case REP_BAR: | |
2441 | if (!cv->expect_repeat) { | |
2442 | char error_message[80]; | |
2443 | ||
2444 | if (cv->repeat_count == 0) | |
2445 | { | |
2446 | snprintf(error_message, 80, "Missing repeat at start ? Unexpected :|%s found", replist); | |
2447 | event_warning (error_message); | |
2448 | } | |
2449 | else | |
2450 | { | |
2451 | snprintf(error_message, 80, "Unexpected :|%s found", replist); | |
2452 | event_warning (error_message); | |
2453 | } | |
2454 | }; | |
2455 | cv->expect_repeat = 0; | |
2456 | cv->repeat_count = cv->repeat_count + 1; | |
2457 | break; | |
2458 | case BAR1: | |
2459 | if (!cv->expect_repeat) { | |
2460 | if (cv->repeat_count == 0) | |
2461 | { | |
2462 | event_warning ("Missing repeat at start ? found |1"); | |
2463 | } | |
2464 | else | |
2465 | { | |
2466 | event_warning ("found |1 in non-repeat section"); | |
2467 | } | |
2468 | }; | |
2469 | break; | |
2470 | case REP_BAR2: | |
2471 | if (!cv->expect_repeat) { | |
2472 | if (cv->repeat_count == 0) | |
2473 | { | |
2474 | event_warning ("Missing repeat at start ? found :|2"); | |
2475 | } | |
2476 | else | |
2477 | { | |
2478 | event_warning ("No repeat expected, found :|2"); | |
2479 | } | |
2480 | }; | |
2481 | cv->expect_repeat = 0; | |
2482 | cv->repeat_count = cv->repeat_count + 1; | |
2483 | break; | |
2484 | case DOUBLE_REP: | |
2485 | if (!cv->expect_repeat) { | |
2486 | if (cv->repeat_count == 0) | |
2487 | { | |
2488 | event_warning ("Missing repeat at start ? found ::"); | |
2489 | } | |
2490 | else | |
2491 | { | |
2492 | event_warning ("No repeat expected, found ::"); | |
2493 | } | |
2494 | }; | |
2495 | cv->expect_repeat = 1; | |
2496 | cv->repeat_count = cv->repeat_count + 1; | |
2497 | break; | |
2498 | }; | |
2499 | } | |
2500 | ||
2501 | /* [JA] 2020-10-12 */ | |
2502 | static void check_and_call_bar(int bar_type, char *replist) | |
2503 | { | |
2504 | if (repcheck) | |
2505 | { | |
2506 | check_bar_repeats (bar_type, replist); | |
2507 | } | |
2508 | event_bar (bar_type, replist); | |
2509 | } | |
2510 | ||
2378 | 2511 | void |
2379 | 2512 | parsemusic (field) |
2380 | 2513 | char *field; |
2458 | 2591 | switch (*p) |
2459 | 2592 | { |
2460 | 2593 | case ':': |
2461 | event_bar (BAR_REP, ""); | |
2594 | check_and_call_bar (BAR_REP, ""); | |
2462 | 2595 | p = p + 1; |
2463 | 2596 | break; |
2464 | 2597 | case '|': |
2465 | event_bar (DOUBLE_BAR, ""); | |
2598 | check_and_call_bar (DOUBLE_BAR, ""); | |
2466 | 2599 | p = p + 1; |
2467 | 2600 | break; |
2468 | 2601 | case ']': |
2469 | event_bar (THIN_THICK, ""); | |
2602 | check_and_call_bar (THIN_THICK, ""); | |
2470 | 2603 | p = p + 1; |
2471 | 2604 | break; |
2472 | 2605 | default: |
2473 | 2606 | p = getrep (p, playonrep_list); |
2474 | event_bar (SINGLE_BAR, playonrep_list); | |
2607 | check_and_call_bar (SINGLE_BAR, playonrep_list); | |
2475 | 2608 | }; |
2476 | 2609 | break; |
2477 | 2610 | case ':': |
2479 | 2612 | switch (*p) |
2480 | 2613 | { |
2481 | 2614 | case ':': |
2482 | event_bar (DOUBLE_REP, ""); | |
2615 | check_and_call_bar (DOUBLE_REP, ""); | |
2483 | 2616 | p = p + 1; |
2484 | 2617 | break; |
2485 | 2618 | case '|': |
2486 | 2619 | p = p + 1; |
2487 | 2620 | p = getrep (p, playonrep_list); |
2488 | event_bar (REP_BAR, playonrep_list); | |
2621 | check_and_call_bar (REP_BAR, playonrep_list); | |
2489 | 2622 | if (*p == ']') |
2490 | 2623 | p = p + 1; /* [SS] 2013-10-31 */ |
2491 | 2624 | break; |
2492 | 2625 | /* [JM] 2018-02-22 dotted bar line ... this is legal */ |
2493 | 2626 | default: |
2494 | 2627 | /* [SS] 2018-02-08 introducing DOTTED_BAR */ |
2495 | event_bar (DOTTED_BAR,""); | |
2628 | check_and_call_bar (DOTTED_BAR,""); | |
2496 | 2629 | }; |
2497 | 2630 | break; |
2498 | 2631 | case ' ': |
2557 | 2690 | { |
2558 | 2691 | case '|': |
2559 | 2692 | p = p + 1; |
2560 | event_bar (THICK_THIN, ""); | |
2693 | check_and_call_bar (THICK_THIN, ""); | |
2561 | 2694 | if (*p == ':') { /* [SS] 2015-04-13 [SDG] 2020-06-04 */ |
2562 | event_bar (BAR_REP, ""); | |
2695 | check_and_call_bar (BAR_REP, ""); | |
2563 | 2696 | p = p + 1; |
2564 | 2697 | } |
2565 | 2698 | break; |
2595 | 2728 | /*if (!inchordflag && *p == '|') { [SS] 2018-12-21 not THICK_THIN bar line*/ |
2596 | 2729 | if (!parserinchord && *p == '|') { /* [SS] 2019-06-06 not THICK_THIN bar line*/ |
2597 | 2730 | p = p + 1; /* skip over | */ |
2598 | event_bar (THIN_THICK, "");} | |
2731 | check_and_call_bar (THIN_THICK, "");} | |
2599 | 2732 | else { |
2600 | 2733 | readlen (&chord_n, &chord_m, &p); /* [SS] 2019-06-06 */ |
2601 | 2734 | event_chordoff (chord_n, chord_m); |
31 | 31 | char other[V_STRLEN+1]; /* [SS] 2011-04-18 */ |
32 | 32 | }; |
33 | 33 | |
34 | typedef struct voice_context { | |
35 | char label[31]; | |
36 | int expect_repeat; | |
37 | int repeat_count; | |
38 | } voice_context_t; | |
39 | ||
40 | #define MAX_VOICES 30 | |
41 | ||
34 | 42 | /* holds a fraction */ |
35 | 43 | struct fraction { |
36 | 44 | int num; |
37 | 45 | int denom; |
38 | 46 | }; |
39 | 47 | |
48 | extern int repcheck; /* allows backend to enable/disable repeat checking */ | |
49 | extern voice_context_t voicecode[MAX_VOICES]; | |
40 | 50 | |
41 | 51 | #ifndef KANDR |
42 | 52 | extern int readnump(char **p); |
184 | 184 | |
185 | 185 | */ |
186 | 186 | |
187 | #define VERSION "4.42 Ocober 01 2020 abc2midi" | |
187 | #define VERSION "4.43 Ocober 12 2020 abc2midi" | |
188 | 188 | |
189 | 189 | /* enables reading V: indication in header */ |
190 | 190 | #define XTEN1 1 |
891 | 891 | } else { |
892 | 892 | check = 0; |
893 | 893 | }; |
894 | /* disable repeat checking because abc2midi does its own workaround | |
895 | * attempting to fix various repeat errors. | |
896 | */ | |
897 | repcheck = 0; | |
894 | 898 | /* look for filename-from-tune-titles option */ |
895 | 899 | namelimit = 252; |
896 | 900 | titlenames = 0; |
150 | 150 | struct fract barcount; |
151 | 151 | int barno; |
152 | 152 | int barchecking; |
153 | int expect_repeat; | |
154 | 153 | int brokentype, brokenmult, brokenpending; |
155 | 154 | int tiespending; |
156 | 155 | struct feature* tie_place[MAX_TIES]; |
20 | 20 | |
21 | 21 | /* back-end for outputting (possibly modified) abc */ |
22 | 22 | |
23 | #define VERSION "2.10 October 06 2020 abc2abc" | |
23 | #define VERSION "2.11 October 12 2020 abc2abc" | |
24 | 24 | |
25 | 25 | /* for Microsoft Visual C++ 6.0 or higher */ |
26 | 26 | #ifdef _MSC_VER |
65 | 65 | struct fract breakpoint; /* used to break bar into beamed sets of notes */ |
66 | 66 | int barno; /* number of bar within tune */ |
67 | 67 | int newspacing; /* was -s option selected ? */ |
68 | int barcheck, repcheck; /* indicate -b and -r options selected */ | |
68 | int barcheck; /* indicate -b and -r options selected */ | |
69 | 69 | int echeck; /* was error-checking turned off ? (-e option) */ |
70 | 70 | int newbreaks; /* was -n option selected ? */ |
71 | 71 | int nodouble_accidentals; |
104 | 104 | |
105 | 105 | extern int nokey; /* signals no key signature assumed */ |
106 | 106 | extern int nokeysig; /* signals -nokeys or -nokeysf option */ |
107 | extern int voicecodes ; /* from parseabc.c */ | |
108 | extern char voicecode[16][30]; /*for interpreting V: string */ | |
109 | 107 | |
110 | 108 | struct voicetype { /* information needed for each voice */ |
111 | 109 | int number; /* voice number from V: field */ |
114 | 112 | struct abctext* currentline; |
115 | 113 | int bars_remaining; |
116 | 114 | int bars_complete; |
117 | int expect_repeat; /* [SS] 2018-12-01 */ | |
118 | 115 | int drumchan; |
119 | 116 | } voice[MAX_VOICES]; |
120 | 117 | int voicecount, this_voice, next_voice; |
1205 | 1202 | voice[voice_index].bars_complete = 0; |
1206 | 1203 | voice[voice_index].bars_remaining = bars_per_line; |
1207 | 1204 | voice[voice_index].drumchan = 0; |
1208 | voice[voice_index].expect_repeat = -1; /* [SS] 2018-12-01 */ | |
1209 | 1205 | }; |
1210 | 1206 | voice[voice_index].currentline = NULL; |
1211 | 1207 | return(voice_index); |
1235 | 1231 | }; |
1236 | 1232 | }; |
1237 | 1233 | }; |
1238 | if (strlen(s) == 0) { | |
1239 | if(voicecodes >= n) emit_string_sprintf("V:%s",voicecode[n-1]); | |
1240 | else emit_int_sprintf("V:%d", n); | |
1241 | if (vp->gotclef) {sprintf(output," clef=%s", vp->clefname); | |
1242 | emit_string(output);} | |
1243 | if (vp->gotoctave) {sprintf(output," octave=%d", vp->octave); | |
1244 | emit_string(output);} | |
1245 | if (vp->gottranspose) {sprintf(output," transpose=%d", vp->transpose); | |
1246 | emit_string(output);} | |
1247 | if (vp->gotname) {sprintf(output," name=%s", vp->namestring); | |
1248 | emit_string(output);} | |
1249 | if (vp->gotsname) {sprintf(output," sname=%s", vp->snamestring); | |
1250 | emit_string(output);} | |
1251 | if( vp->gotmiddle ) { sprintf(output, " middle=%s", vp->middlestring); | |
1252 | emit_string(output);} | |
1253 | if( vp->gotother ) { sprintf(output, " %s", vp->other); | |
1254 | emit_string(output);} /* [SS] 2011-04-18 */ | |
1255 | } else { | |
1256 | if(voicecodes >= n) emit_string_sprintf("V:%s",voicecode[n-1]); | |
1257 | emit_int_sprintf("V:%d ", n); | |
1258 | if (vp->gotclef) {sprintf(output," clef=%s", vp->clefname); | |
1259 | emit_string(output);} | |
1260 | if (vp->gotoctave) {sprintf(output," octave=%d", vp->octave); | |
1261 | emit_string(output);} | |
1262 | if (vp->gottranspose) {sprintf(output," transpose=%d", vp->transpose); | |
1263 | emit_string(output);} | |
1264 | if (vp->gotname) {sprintf(output," name=%s", vp->namestring); | |
1265 | emit_string(output);} | |
1266 | if( vp->gotmiddle ) { sprintf(output, " middle=%s", vp->middlestring); | |
1267 | emit_string(output);} | |
1268 | if( vp->gotother ) { sprintf(output, " %s", vp->other); | |
1269 | emit_string(output);} /* [SS] 2011-04-18 */ | |
1234 | if (strlen(voicecode[n-1].label) > 0) { | |
1235 | emit_string_sprintf("V:%s",voicecode[n-1].label); | |
1236 | } else { | |
1237 | emit_int_sprintf("V:%d", n); | |
1238 | } | |
1239 | if (vp->gotclef) {sprintf(output," clef=%s", vp->clefname); | |
1240 | emit_string(output);} | |
1241 | if (vp->gotoctave) {sprintf(output," octave=%d", vp->octave); | |
1242 | emit_string(output);} | |
1243 | if (vp->gottranspose) {sprintf(output," transpose=%d", vp->transpose); | |
1244 | emit_string(output);} | |
1245 | if (vp->gotname) {sprintf(output," name=%s", vp->namestring); | |
1246 | emit_string(output);} | |
1247 | if (vp->gotsname) {sprintf(output," sname=%s", vp->snamestring); | |
1248 | emit_string(output);} | |
1249 | if( vp->gotmiddle ) { sprintf(output, " middle=%s", vp->middlestring); | |
1250 | emit_string(output);} | |
1251 | if( vp->gotother ) { sprintf(output, " %s", vp->other); | |
1252 | emit_string(output);} /* [SS] 2011-04-18 */ | |
1253 | if (strlen(s) != 0) { | |
1270 | 1254 | emit_string(s); |
1271 | 1255 | }; |
1272 | 1256 | inmusic = 0; |
1425 | 1409 | count.denom = 1; |
1426 | 1410 | barno = 0; |
1427 | 1411 | tuplenotes = 0; |
1428 | /* expect_repeat is now a voice struct variable [SS] 2018-12-01 */ | |
1429 | /* expect_repeat = -1; repeat from start may occur [J-FM] 2012-06-04 */ | |
1430 | 1412 | inlinefield = 0; |
1431 | 1413 | if (barlen.num == 0) { |
1432 | 1414 | /* generate missing time signature */ |
1740 | 1722 | break; |
1741 | 1723 | case BAR_REP: |
1742 | 1724 | emit_string("|:"); |
1743 | if (voice[this_voice].expect_repeat > 0 && repcheck) | |
1744 | { | |
1745 | /* no error if first repeat [J-FM] 2012-06-04 */ | |
1746 | event_error("Expecting repeat, found |:"); | |
1747 | }; | |
1748 | voice[this_voice].expect_repeat = 1; | |
1749 | 1725 | break; |
1750 | 1726 | case REP_BAR: |
1751 | 1727 | emit_string_sprintf(":|%s", replist); |
1752 | if ((!voice[this_voice].expect_repeat) && (repcheck)) { | |
1753 | event_warning("No repeat expected, found :|"); | |
1754 | }; | |
1755 | voice[this_voice].expect_repeat = 0; | |
1756 | 1728 | break; |
1757 | 1729 | case BAR1: |
1758 | 1730 | emit_string("|1"); |
1759 | if ((!voice[this_voice].expect_repeat) && (repcheck)) { | |
1760 | event_warning("found |1 in non-repeat section"); | |
1761 | }; | |
1762 | 1731 | break; |
1763 | 1732 | case REP_BAR2: |
1764 | 1733 | emit_string(":|2"); |
1765 | if ((!voice[this_voice].expect_repeat) && (repcheck)) { | |
1766 | event_warning("No repeat expected, found :|2"); | |
1767 | }; | |
1768 | voice[this_voice].expect_repeat = 0; | |
1769 | 1734 | break; |
1770 | 1735 | case DOUBLE_REP: |
1771 | 1736 | emit_string("::"); |
1772 | if ((voice[this_voice].expect_repeat) && (repcheck)) { | |
1773 | event_error("No repeat expected, found ::"); | |
1774 | }; | |
1775 | voice[this_voice].expect_repeat = 1; | |
1776 | 1737 | break; |
1777 | 1738 | }; |
1778 | 1739 | if ((count.num*barlen.denom != barlen.num*count.denom) && |
21 | 21 | /* yapstree.c - back-end for abc parser. */ |
22 | 22 | /* generates a data structure suitable for typeset music */ |
23 | 23 | |
24 | #define VERSION "1.80 October 07 2020 yaps" | |
24 | #define VERSION "1.81 October 12 2020 yaps" | |
25 | 25 | #include <stdio.h> |
26 | 26 | #ifdef USE_INDEX |
27 | 27 | #define strchr index |
63 | 63 | char matchstring[256]; |
64 | 64 | int fileopen; |
65 | 65 | |
66 | int repcheck; | |
67 | 66 | int xinhead; |
68 | 67 | int xinbody; |
69 | 68 | int suppress; |
791 | 790 | v->inslur = 0; |
792 | 791 | v->ingrace = 0; |
793 | 792 | v->inchord = 0; |
794 | v->expect_repeat = 0; | |
795 | 793 | v->tuplenotes = 0; |
796 | 794 | v->thistuple = NULL; |
797 | 795 | v->tuple_count = 0; |
2194 | 2192 | checkbar(type); /* increment bar number if bar complete */ |
2195 | 2193 | /* [SS] 2015-11-15 * changed (void*) to (int *) */ |
2196 | 2194 | addfeature(type, (int *)cv->barno); /* save bar number */ |
2197 | switch(type) { | |
2198 | case SINGLE_BAR: | |
2199 | break; | |
2200 | case DOUBLE_BAR: | |
2201 | break; | |
2202 | case THIN_THICK: | |
2203 | break; | |
2204 | case THICK_THIN: | |
2205 | break; | |
2206 | case BAR_REP: | |
2207 | if ((cv->expect_repeat) && (repcheck)) { | |
2208 | event_error("Expecting repeat, found |:"); | |
2209 | }; | |
2210 | cv->expect_repeat = 1; | |
2211 | break; | |
2212 | case REP_BAR: | |
2213 | if ((!cv->expect_repeat) && (repcheck)) { | |
2214 | event_error("No repeat expected, found :|"); | |
2215 | }; | |
2216 | cv->expect_repeat = 0; | |
2217 | break; | |
2218 | case BAR1: | |
2219 | if ((!cv->expect_repeat) && (repcheck)) { | |
2220 | event_error("found |1 in non-repeat section"); | |
2221 | }; | |
2222 | break; | |
2223 | case REP_BAR2: | |
2224 | if ((!cv->expect_repeat) && (repcheck)) { | |
2225 | event_error("No repeat expected, found :|2"); | |
2226 | }; | |
2227 | cv->expect_repeat = 0; | |
2228 | break; | |
2229 | case DOUBLE_REP: | |
2230 | if ((!cv->expect_repeat) && (repcheck)) { | |
2231 | event_error("No repeat expected, found ::"); | |
2232 | }; | |
2233 | cv->expect_repeat = 1; | |
2234 | break; | |
2235 | }; | |
2236 | 2195 | if ((playonrep_list != NULL) && (strlen(playonrep_list) > 0)) { |
2237 | 2196 | event_playonrep(playonrep_list); |
2238 | 2197 | }; |