diff --git a/Makefile b/Makefile index 6ac212a..80aa05f 100644 --- a/Makefile +++ b/Makefile @@ -53,13 +53,13 @@ datadir = ${prefix}/share docdir = ${prefix}/share/doc/abcmidi mandir = ${prefix}/share/man/man1 -binaries=abc2midi midi2abc abc2abc mftext yaps midicopy abcmatch +binaries=abc2midi midi2abc abc2abc mftext yaps midicopy abcmatch midistats -all : abc2midi midi2abc abc2abc mftext yaps midicopy abcmatch +all : abc2midi midi2abc abc2abc mftext yaps midicopy abcmatch midistats OBJECTS_ABC2MIDI=parseabc.o store.o genmidi.o midifile.o queues.o parser2.o stresspat.o music_utils.o abc2midi : $(OBJECTS_ABC2MIDI) - $(CC) $(CFLAGS) -o abc2midi $(OBJECTS_ABC2MIDI) $(LDFLAGS) -lm + $(CC) $(CFLAGS) -o abc2midi $(OBJECTS_ABC2MIDI) $(LDFLAGS) $(OBJECTS_ABC2MIDI): abc.h parseabc.h config.h Makefile OBJECTS_ABC2ABC=parseabc.o toabc.o music_utils.o @@ -72,6 +72,11 @@ midi2abc : $(OBJECTS_MIDI2ABC) $(CC) $(CFLAGS) -o midi2abc $(OBJECTS_MIDI2ABC) $(LDFLAGS) $(OBJECTS_MIDI2ABC): abc.h midifile.h config.h Makefile +OBJECTS_MIDISTATS=midifile.o midistats.o +midistats : $(OBJECTS_MIDISTATS) + $(CC) $(CFLAGS) -o midistats $(OBJECTS_MIDISTATS) $(LDFLAGS) +$(OBJECTS_MIDISTATS): abc.h midifile.h config.h Makefile + OBJECTS_MFTEXT=midifile.o mftext.o crack.o mftext : $(OBJECTS_MFTEXT) $(CC) $(CFLAGS) -o mftext $(OBJECTS_MFTEXT) $(LDFLAGS) @@ -114,6 +119,8 @@ midifile.o : midifile.c midifile.h midi2abc.o : midi2abc.c midifile.h +midistats.o : midistats.c midifile.h + midicopy.o : midicopy.c midicopy.h abcmatch.o: abcmatch.c abc.h @@ -141,7 +148,7 @@ matchsup.o : matchsup.c abc.h parseabc.h parser2.h clean : rm *.o ${binaries} -install: abc2midi midi2abc abc2abc mftext midicopy yaps abcmatch +install: abc2midi midi2abc abc2abc mftext midicopy yaps abcmatch midistats $(INSTALL) -d $(DESTDIR)$(bindir) $(INSTALL) -m 755 ${binaries} $(DESTDIR)$(bindir) @@ -164,6 +171,7 @@ uninstall: rm -f $(DESTDIR)$(bindir)/abc2abc rm -f $(DESTDIR)$(bindir)/yaps rm -f $(DESTDIR)$(bindir)/midi2abc + rm -f $(DESTDIR)$(bindir)/midistats rm -f $(DESTDIR)$(bindir)/mftext rm -f $(DESTDIR)$(bindir)/abcmatch rm -f $(DESTDIR)$(bindir)/midicopy diff --git a/Makefile.in b/Makefile.in index 9c02eb6..8a4837b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -53,13 +53,13 @@ datadir = @datarootdir@ docdir = @datarootdir@/doc/abcmidi mandir = @datarootdir@/man/man1 -binaries=abc2midi midi2abc abc2abc mftext yaps midicopy abcmatch +binaries=abc2midi midi2abc abc2abc mftext yaps midicopy abcmatch midistats -all : abc2midi midi2abc abc2abc mftext yaps midicopy abcmatch +all : abc2midi midi2abc abc2abc mftext yaps midicopy abcmatch midistats OBJECTS_ABC2MIDI=parseabc.o store.o genmidi.o midifile.o queues.o parser2.o stresspat.o music_utils.o abc2midi : $(OBJECTS_ABC2MIDI) - $(CC) $(CFLAGS) -o abc2midi $(OBJECTS_ABC2MIDI) $(LDFLAGS) -lm + $(CC) $(CFLAGS) -o abc2midi $(OBJECTS_ABC2MIDI) $(LDFLAGS) $(OBJECTS_ABC2MIDI): abc.h parseabc.h config.h Makefile OBJECTS_ABC2ABC=parseabc.o toabc.o music_utils.o @@ -72,6 +72,11 @@ midi2abc : $(OBJECTS_MIDI2ABC) $(CC) $(CFLAGS) -o midi2abc $(OBJECTS_MIDI2ABC) $(LDFLAGS) $(OBJECTS_MIDI2ABC): abc.h midifile.h config.h Makefile +OBJECTS_MIDISTATS=midifile.o midistats.o +midistats : $(OBJECTS_MIDISTATS) + $(CC) $(CFLAGS) -o midistats $(OBJECTS_MIDISTATS) $(LDFLAGS) +$(OBJECTS_MIDISTATS): abc.h midifile.h config.h Makefile + OBJECTS_MFTEXT=midifile.o mftext.o crack.o mftext : $(OBJECTS_MFTEXT) $(CC) $(CFLAGS) -o mftext $(OBJECTS_MFTEXT) $(LDFLAGS) @@ -114,6 +119,8 @@ midifile.o : midifile.c midifile.h midi2abc.o : midi2abc.c midifile.h +midistats.o : midistats.c midifile.h + midicopy.o : midicopy.c midicopy.h abcmatch.o: abcmatch.c abc.h @@ -141,7 +148,7 @@ matchsup.o : matchsup.c abc.h parseabc.h parser2.h clean : rm *.o ${binaries} -install: abc2midi midi2abc abc2abc mftext midicopy yaps abcmatch +install: abc2midi midi2abc abc2abc mftext midicopy yaps abcmatch midistats $(INSTALL) -d $(DESTDIR)$(bindir) $(INSTALL) -m 755 ${binaries} $(DESTDIR)$(bindir) @@ -164,6 +171,7 @@ uninstall: rm -f $(DESTDIR)$(bindir)/abc2abc rm -f $(DESTDIR)$(bindir)/yaps rm -f $(DESTDIR)$(bindir)/midi2abc + rm -f $(DESTDIR)$(bindir)/midistats rm -f $(DESTDIR)$(bindir)/mftext rm -f $(DESTDIR)$(bindir)/abcmatch rm -f $(DESTDIR)$(bindir)/midicopy diff --git a/VERSION b/VERSION index 599a317..e43dc4b 100644 --- a/VERSION +++ b/VERSION @@ -1,2 +1,2 @@ -September 01 2022 +December 07 2022 diff --git a/config.log b/config.log index c23a207..4eb319c 100644 --- a/config.log +++ b/config.log @@ -12,14 +12,14 @@ generated by GNU Autoconf 2.67. Invocation command line was hostname = seymour-VirtualBox uname -m = x86_64 -uname -r = 5.4.0-51-generic +uname -r = 5.15.0-56-generic uname -s = Linux -uname -v = #56-Ubuntu SMP Mon Oct 5 14:28:49 UTC 2020 +uname -v = #62-Ubuntu SMP Tue Nov 22 19:54:14 UTC 2022 -/usr/bin/uname -p = unknown +/usr/bin/uname -p = x86_64 /bin/uname -X = unknown -/bin/arch = unknown +/bin/arch = x86_64 /usr/bin/arch -k = unknown /usr/convex/getsysinfo = unknown /usr/bin/hostinfo = unknown @@ -27,7 +27,6 @@ uname -v = #56-Ubuntu SMP Mon Oct 5 14:28:49 UTC 2020 /usr/bin/oslevel = unknown /bin/universe = unknown -PATH: /home/seymour/bin PATH: /usr/local/sbin PATH: /usr/local/bin PATH: /usr/sbin @@ -37,9 +36,7 @@ PATH: /bin PATH: /usr/games PATH: /usr/local/games PATH: /snap/bin -PATH: /usr/local/bin -PATH: /home/seymour/jdk1.6.0_02/bin -PATH: /home/seymour/bin +PATH: /home/seymour/humdrum-tools/humextra/bin PATH: . @@ -47,85 +44,87 @@ PATH: . ## Core tests. ## ## ----------- ## -configure:2174: checking for gcc -configure:2190: found /usr/bin/gcc -configure:2201: result: gcc -configure:2430: checking for C compiler version -configure:2439: gcc --version >&5 -gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0 -Copyright (C) 2019 Free Software Foundation, Inc. +configure:2178: checking for gcc +configure:2194: found /usr/bin/gcc +configure:2205: result: gcc +configure:2434: checking for C compiler version +configure:2443: gcc --version >&5 +gcc (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0 +Copyright (C) 2021 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -configure:2450: $? = 0 -configure:2439: gcc -v >&5 +configure:2454: $? = 0 +configure:2443: gcc -v >&5 Using built-in specs. COLLECT_GCC=gcc -COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper -OFFLOAD_TARGET_NAMES=nvptx-none:hsa +COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/11/lto-wrapper +OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa OFFLOAD_TARGET_DEFAULT=1 Target: x86_64-linux-gnu -Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.3.0-17ubuntu1~20.04' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-HskZEa/gcc-9-9.3.0/debian/tmp-nvptx/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu +Configured with: ../src/configure -v --with-pkgversion='Ubuntu 11.3.0-1ubuntu1~22.04' --with-bugurl=file:///usr/share/doc/gcc-11/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-11 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --enable-cet --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-11-xKiWfi/gcc-11-11.3.0/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-11-xKiWfi/gcc-11-11.3.0/debian/tmp-gcn/usr --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-serialization=2 Thread model: posix -gcc version 9.3.0 (Ubuntu 9.3.0-17ubuntu1~20.04) -configure:2450: $? = 0 -configure:2439: gcc -V >&5 -gcc: error: unrecognized command line option '-V' +Supported LTO compression algorithms: zlib zstd +gcc version 11.3.0 (Ubuntu 11.3.0-1ubuntu1~22.04) +... rest of stderr output deleted ... +configure:2454: $? = 0 +configure:2443: gcc -V >&5 +gcc: error: unrecognized command-line option '-V' gcc: fatal error: no input files compilation terminated. -configure:2450: $? = 1 -configure:2439: gcc -qversion >&5 -gcc: error: unrecognized command line option '-qversion'; did you mean '--version'? +configure:2454: $? = 1 +configure:2443: gcc -qversion >&5 +gcc: error: unrecognized command-line option '-qversion'; did you mean '--version'? gcc: fatal error: no input files compilation terminated. -configure:2450: $? = 1 -configure:2470: checking whether the C compiler works -configure:2492: gcc conftest.c >&5 -configure:2496: $? = 0 -configure:2544: result: yes -configure:2547: checking for C compiler default output file name -configure:2549: result: a.out -configure:2555: checking for suffix of executables -configure:2562: gcc -o conftest conftest.c >&5 -configure:2566: $? = 0 -configure:2588: result: -configure:2610: checking whether we are cross compiling -configure:2618: gcc -o conftest conftest.c >&5 -configure:2622: $? = 0 -configure:2629: ./conftest -configure:2633: $? = 0 -configure:2621: result: no -configure:2626: checking for suffix of object files -configure:2648: gcc -c conftest.c >&5 -configure:2652: $? = 0 -configure:2673: result: o -configure:2677: checking whether we are using the GNU C compiler -configure:2696: gcc -c conftest.c >&5 -configure:2696: $? = 0 -configure:2705: result: yes -configure:2714: checking whether gcc accepts -g -configure:2734: gcc -c -g conftest.c >&5 -configure:2734: $? = 0 -configure:2775: result: yes -configure:2792: checking for gcc option to accept ISO C89 -configure:2856: gcc -c -g -O2 conftest.c >&5 -configure:2856: $? = 0 -configure:2869: result: none needed -configure:2947: checking for a BSD-compatible install -configure:3015: result: /usr/bin/install -c -configure:3030: checking for main in -lm -configure:3049: gcc -o conftest -O2 conftest.c -lm >&5 -configure:3049: $? = 0 -configure:3058: result: yes -configure:3076: checking how to run the C preprocessor -configure:3107: gcc -E conftest.c -configure:3107: $? = 0 -configure:3121: gcc -E conftest.c +configure:2454: $? = 1 +configure:2474: checking whether the C compiler works +configure:2496: gcc conftest.c >&5 +configure:2500: $? = 0 +configure:2548: result: yes +configure:2551: checking for C compiler default output file name +configure:2553: result: a.out +configure:2559: checking for suffix of executables +configure:2566: gcc -o conftest conftest.c >&5 +configure:2570: $? = 0 +configure:2592: result: +configure:2614: checking whether we are cross compiling +configure:2622: gcc -o conftest conftest.c >&5 +configure:2626: $? = 0 +configure:2633: ./conftest +configure:2637: $? = 0 +configure:2652: result: no +configure:2657: checking for suffix of object files +configure:2679: gcc -c conftest.c >&5 +configure:2683: $? = 0 +configure:2704: result: o +configure:2708: checking whether we are using the GNU C compiler +configure:2727: gcc -c conftest.c >&5 +configure:2727: $? = 0 +configure:2736: result: yes +configure:2745: checking whether gcc accepts -g +configure:2765: gcc -c -g conftest.c >&5 +configure:2765: $? = 0 +configure:2806: result: yes +configure:2823: checking for gcc option to accept ISO C89 +configure:2887: gcc -c -g -O2 conftest.c >&5 +configure:2887: $? = 0 +configure:2900: result: none needed +configure:2978: checking for a BSD-compatible install +configure:3046: result: /usr/bin/install -c +configure:3061: checking for main in -lm +configure:3080: gcc -o conftest -O2 conftest.c -lm >&5 +configure:3080: $? = 0 +configure:3089: result: yes +configure:3107: checking how to run the C preprocessor +configure:3138: gcc -E conftest.c +configure:3138: $? = 0 +configure:3152: gcc -E conftest.c conftest.c:10:10: fatal error: ac_nonexistent.h: No such file or directory 10 | #include | ^~~~~~~~~~~~~~~~~~ compilation terminated. -configure:3121: $? = 1 +configure:3152: $? = 1 configure: failed program was: | /* confdefs.h */ | #define PACKAGE_NAME "abcmidi" @@ -137,15 +136,15 @@ configure: failed program was: | #define HAVE_LIBM 1 | /* end confdefs.h. */ | #include -configure:3146: result: gcc -E -configure:3166: gcc -E conftest.c -configure:3166: $? = 0 -configure:3180: gcc -E conftest.c +configure:3177: result: gcc -E +configure:3197: gcc -E conftest.c +configure:3197: $? = 0 +configure:3211: gcc -E conftest.c conftest.c:10:10: fatal error: ac_nonexistent.h: No such file or directory 10 | #include | ^~~~~~~~~~~~~~~~~~ compilation terminated. -configure:3180: $? = 1 +configure:3211: $? = 1 configure: failed program was: | /* confdefs.h */ | #define PACKAGE_NAME "abcmidi" @@ -157,67 +156,67 @@ configure: failed program was: | #define HAVE_LIBM 1 | /* end confdefs.h. */ | #include -configure:3209: checking for grep that handles long lines and -e -configure:3267: result: /bin/grep -configure:3272: checking for egrep -configure:3334: result: /bin/grep -E -configure:3339: checking for ANSI C header files -configure:3359: gcc -c -O2 conftest.c >&5 -configure:3359: $? = 0 -configure:3432: gcc -o conftest -O2 conftest.c -lm >&5 -configure:3432: $? = 0 -configure:3432: ./conftest -configure:3432: $? = 0 -configure:3443: result: yes -configure:3456: checking for sys/types.h -configure:3456: gcc -c -O2 conftest.c >&5 -configure:3456: $? = 0 -configure:3456: result: yes -configure:3456: checking for sys/stat.h -configure:3456: gcc -c -O2 conftest.c >&5 -configure:3456: $? = 0 -configure:3456: result: yes -configure:3456: checking for stdlib.h -configure:3456: gcc -c -O2 conftest.c >&5 -configure:3456: $? = 0 -configure:3456: result: yes -configure:3456: checking for string.h -configure:3456: gcc -c -O2 conftest.c >&5 -configure:3456: $? = 0 -configure:3456: result: yes -configure:3456: checking for memory.h -configure:3456: gcc -c -O2 conftest.c >&5 -configure:3456: $? = 0 -configure:3456: result: yes -configure:3456: checking for strings.h -configure:3456: gcc -c -O2 conftest.c >&5 -configure:3456: $? = 0 -configure:3456: result: yes -configure:3456: checking for inttypes.h -configure:3456: gcc -c -O2 conftest.c >&5 -configure:3456: $? = 0 -configure:3456: result: yes -configure:3456: checking for stdint.h -configure:3456: gcc -c -O2 conftest.c >&5 -configure:3456: $? = 0 -configure:3456: result: yes -configure:3456: checking for unistd.h -configure:3456: gcc -c -O2 conftest.c >&5 -configure:3456: $? = 0 -configure:3456: result: yes -configure:3471: checking for stdlib.h -configure:3471: result: yes -configure:3471: checking for string.h -configure:3471: result: yes -configure:3483: checking for size_t -configure:3483: gcc -c -O2 conftest.c >&5 -configure:3483: $? = 0 -configure:3483: gcc -c -O2 conftest.c >&5 +configure:3240: checking for grep that handles long lines and -e +configure:3298: result: /usr/bin/grep +configure:3303: checking for egrep +configure:3365: result: /usr/bin/grep -E +configure:3370: checking for ANSI C header files +configure:3390: gcc -c -O2 conftest.c >&5 +configure:3390: $? = 0 +configure:3463: gcc -o conftest -O2 conftest.c -lm >&5 +configure:3463: $? = 0 +configure:3463: ./conftest +configure:3463: $? = 0 +configure:3474: result: yes +configure:3487: checking for sys/types.h +configure:3487: gcc -c -O2 conftest.c >&5 +configure:3487: $? = 0 +configure:3487: result: yes +configure:3487: checking for sys/stat.h +configure:3487: gcc -c -O2 conftest.c >&5 +configure:3487: $? = 0 +configure:3487: result: yes +configure:3487: checking for stdlib.h +configure:3487: gcc -c -O2 conftest.c >&5 +configure:3487: $? = 0 +configure:3487: result: yes +configure:3487: checking for string.h +configure:3487: gcc -c -O2 conftest.c >&5 +configure:3487: $? = 0 +configure:3487: result: yes +configure:3487: checking for memory.h +configure:3487: gcc -c -O2 conftest.c >&5 +configure:3487: $? = 0 +configure:3487: result: yes +configure:3487: checking for strings.h +configure:3487: gcc -c -O2 conftest.c >&5 +configure:3487: $? = 0 +configure:3487: result: yes +configure:3487: checking for inttypes.h +configure:3487: gcc -c -O2 conftest.c >&5 +configure:3487: $? = 0 +configure:3487: result: yes +configure:3487: checking for stdint.h +configure:3487: gcc -c -O2 conftest.c >&5 +configure:3487: $? = 0 +configure:3487: result: yes +configure:3487: checking for unistd.h +configure:3487: gcc -c -O2 conftest.c >&5 +configure:3487: $? = 0 +configure:3487: result: yes +configure:3502: checking for stdlib.h +configure:3502: result: yes +configure:3502: checking for string.h +configure:3502: result: yes +configure:3514: checking for size_t +configure:3514: gcc -c -O2 conftest.c >&5 +configure:3514: $? = 0 +configure:3514: gcc -c -O2 conftest.c >&5 conftest.c: In function 'main': conftest.c:58:21: error: expected expression before ')' token 58 | if (sizeof ((size_t))) | ^ -configure:3483: $? = 1 +configure:3514: $? = 1 configure: failed program was: | /* confdefs.h */ | #define PACKAGE_NAME "abcmidi" @@ -281,37 +280,37 @@ configure: failed program was: | ; | return 0; | } -configure:3483: result: yes -configure:3496: checking for error_at_line -configure:3512: gcc -o conftest -O2 conftest.c -lm >&5 -configure:3512: $? = 0 -configure:3520: result: yes -configure:3533: checking for stdlib.h -configure:3533: result: yes -configure:3543: checking for GNU libc compatible malloc -configure:3567: gcc -o conftest -O2 conftest.c -lm >&5 -configure:3567: $? = 0 -configure:3567: ./conftest -configure:3567: $? = 0 -configure:3577: result: yes -configure:3601: checking for strcasecmp -configure:3601: gcc -o conftest -O2 conftest.c -lm >&5 +configure:3514: result: yes +configure:3527: checking for error_at_line +configure:3543: gcc -o conftest -O2 conftest.c -lm >&5 +configure:3543: $? = 0 +configure:3551: result: yes +configure:3564: checking for stdlib.h +configure:3564: result: yes +configure:3574: checking for GNU libc compatible malloc +configure:3598: gcc -o conftest -O2 conftest.c -lm >&5 +configure:3598: $? = 0 +configure:3598: ./conftest +configure:3598: $? = 0 +configure:3608: result: yes +configure:3632: checking for strcasecmp +configure:3632: gcc -o conftest -O2 conftest.c -lm >&5 conftest.c:47:6: warning: conflicting types for built-in function 'strcasecmp'; expected 'int(const char *, const char *)' [-Wbuiltin-declaration-mismatch] 47 | char strcasecmp (); | ^~~~~~~~~~ -configure:3601: $? = 0 -configure:3601: result: yes -configure:3601: checking for strchr -configure:3601: gcc -o conftest -O2 conftest.c -lm >&5 +configure:3632: $? = 0 +configure:3632: result: yes +configure:3632: checking for strchr +configure:3632: gcc -o conftest -O2 conftest.c -lm >&5 conftest.c:48:6: warning: conflicting types for built-in function 'strchr'; expected 'char *(const char *, int)' [-Wbuiltin-declaration-mismatch] 48 | char strchr (); | ^~~~~~ conftest.c:36:1: note: 'strchr' is declared in header '' 35 | # include 36 | #else -configure:3601: $? = 0 -configure:3601: result: yes -configure:3708: creating ./config.status +configure:3632: $? = 0 +configure:3632: result: yes +configure:3739: creating ./config.status ## ---------------------- ## ## Running config.status. ## @@ -328,8 +327,9 @@ generated by GNU Autoconf 2.67. Invocation command line was on seymour-VirtualBox -config.status:813: creating Makefile -config.status:813: creating config.h +config.status:817: creating Makefile +config.status:817: creating config.h +config.status:991: config.h is unchanged ## ---------------- ## ## Cache variables. ## @@ -370,8 +370,8 @@ ac_cv_header_unistd_h=yes ac_cv_lib_error_at_line=yes ac_cv_lib_m_main=yes ac_cv_objext=o -ac_cv_path_EGREP='/bin/grep -E' -ac_cv_path_GREP=/bin/grep +ac_cv_path_EGREP='/usr/bin/grep -E' +ac_cv_path_GREP=/usr/bin/grep ac_cv_path_install='/usr/bin/install -c' ac_cv_prog_CPP='gcc -E' ac_cv_prog_ac_ct_CC=gcc @@ -391,9 +391,9 @@ DEFS='-DHAVE_CONFIG_H' ECHO_C='' ECHO_N='-n' ECHO_T='' -EGREP='/bin/grep -E' +EGREP='/usr/bin/grep -E' EXEEXT='' -GREP='/bin/grep' +GREP='/usr/bin/grep' INSTALL_DATA='${INSTALL} -m 644' INSTALL_PROGRAM='${INSTALL}' INSTALL_SCRIPT='${INSTALL}' diff --git a/config.status b/config.status index 94fe7b3..4049305 100755 --- a/config.status +++ b/config.status @@ -612,8 +612,8 @@ echo 'BEGIN {' >"$tmp/subs1.awk" && cat >>"$tmp/subs1.awk" <<\_ACAWK && S["LTLIBOBJS"]="" S["LIBOBJS"]="" -S["EGREP"]="/bin/grep -E" -S["GREP"]="/bin/grep" +S["EGREP"]="/usr/bin/grep -E" +S["GREP"]="/usr/bin/grep" S["CPP"]="gcc -E" S["INSTALL_DATA"]="${INSTALL} -m 644" S["INSTALL_SCRIPT"]="${INSTALL}" diff --git a/doc/CHANGES b/doc/CHANGES index 428f6ac..34fd6c5 100644 --- a/doc/CHANGES +++ b/doc/CHANGES @@ -14858,3 +14858,10 @@ August 23 2022, September 01 2022 midi2abc -midistats introducing quietTime. +December 5 2022 + +Midi2abc has been getting too big and it is time to split it into +separate applications. Midistats is a new application that will replace +the midi2abc -midistats option. + + diff --git a/doc/midi2abc-stats.txt b/doc/midi2abc-stats.txt deleted file mode 100644 index 5113d46..0000000 --- a/doc/midi2abc-stats.txt +++ /dev/null @@ -1,106 +0,0 @@ -The output of midi2abc with the -stats is used by -the midiexplorer application which can by found on -sourceforge.net. The output looks something like this - -seymour@corsair:~/abc$ midi2abc summer.mid -stats -ntrks 10 -ppqn 120 -trk 1 -timesig 4/4 0.00 -keysig C 0 0 0.00 -tempo 132.00 bpm -trk 2 -metatext 3 Synth Bass 1 -program 1 38 -trkinfo 1 38 156 774 41022 50468 -trk 3 -metatext 3 Brass 1 -program 2 61 -trkinfo 2 61 102 0 6618 2982 -trk 4 -... -trk 10 -metatext 3 Drums -program 10 17 -trkinfo 10 17 1390 1158 108340 25777 -npulses 58552 -tempocmds 1 -pitchbends 0 -programcmd 0 -progs 35 38 50 54 61 80 81 102 -progsact 49460 50468 15426 3237 2982 22295 15938 4703 -progcolor 0.00 0.00 0.00 0.00 0.00 1.71 0.00 0.26 0.06 0.05 0.00 0.00 0.00 0.65 0.00 0.08 0.00 -drums 36 38 39 42 54 -drumhits 548 287 128 1073 512 -pitches 473 0 1267 216 20 344 36 717 0 321 364 0 -pitchact 0.32 0.00 1.10 0.15 0.03 0.22 0.03 0.51 0.00 0.26 0.20 0.00 -chnact 0.86 0.05 0.06 0.27 0.38 0.26 0.08 0.84 0.00 0.44 0.00 0.00 0.00 0.00 0.00 0.00 -pitchentropy 2.567729 - - -Here is a description of some of the values which are outputted. - -timesig 4/4 beat number -is issued each time the time signature is redefined. The beat number -is a decimal number in quarter beats. - -The same apples for keysig (key signature) and tempo redefinition. - -For each channel, midi2abc prints a trkinfo vector which contains -the following information. - -the channel number -the first program number assigned to the channel -the number of notes not appearing inside a chord -the number of notes appearing in a chord -the sum of all the MIDI pitches of the notes -the sum of all the note durations in pulses - -Finally, midi2abc outputs the following data. - -npulses -- the length of the longest track in pulses -tempocmds - the number of tempo commands encountered -pitchbends - the number of pitchbend commands encountered -programcmd - the number of times the program assignment is - reassigned -progs vector - list of all the MIDI programs used -progsact vector - the activity for each of the above MIDI programs. The -activity is the sum of the note durations in pulses for each of the -above programs. -progcolor - described below -drums - a list of all the MIDI percussion numbers used -drumhits - the number of note on commands for each of the above percussion -instruments. -pitches - the number of note on commands for each of the 12 pitch -classes (C, C#, D, D# ... B) -pitchact - duration in pulses of all notes grouped by pitch classes -chnact - duration in pulses of all notes grouped by channel -pitchentropy - entropy of the pitchact probability density function - - -progcolor: The 128 MIDI program numbers are mapped into 17 classes. -These classes group keyboard instruments, brass instruments, guitar -instruments etc into separate groups defined here. -static int progmapper[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 1, 1, 1, 1, 1, 2, - 3, 3, 3, 3, 3, 3, 3, 3, - 2, 2, 4, 4, 4, 4, 4, 2, - 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 2, 7, 10, - 7, 7, 7, 7, 8, 8, 8, 8, - 9, 9, 9, 9, 9, 9, 9, 9, -11, 11, 11, 11, 11, 11, 11, 11, -12, 12, 12, 12, 12, 12, 12, 12, -13, 13, 13, 13, 13, 13, 13, 13, -14, 14, 14, 14, 14, 14, 14, 14, -15, 15, 15, 15, 15, 15, 15, 15, - 2, 2, 2, 2, 2, 12, 6, 12, - 1, 1, 10, 10, 10, 10, 10, 1, -16, 16, 16, 16, 16, 16, 16, 16 -}; - -The activity in each of these programs is measured, normalized to -a unit length vector and returned in the progcolor vector. - - diff --git a/doc/midistats.1 b/doc/midistats.1 new file mode 100644 index 0000000..737ad80 --- /dev/null +++ b/doc/midistats.1 @@ -0,0 +1,82 @@ +.TH MIDISTATS 1 "3 December 2022" +.SH NAME +\fBmidistats\fP \- program to summarize the statistical properties of a midi file +.SH SYNOPSIS +midistats \fIinfile\fP + +.SH DESCRIPTION +\fImidistats\fP analyzes the contents of a midi file and outputs key +information and various statistical measures. Each line of output +starts with the name of the variable or variable array and the +associated values. The output is interpreted by the user interface +midiexplorer.tcl. Both programs are still being improved. Here +is an explanation of some of the output. +.PP +ntrks indicates the number of tracks in the midi file. +.PP +ppqn the number of midi pulses per quarter note. +.PP +keysig the key signature, followed by a major/minor flag, the number +of sharps (positive) or flats (negative) in the key, and the beat number +where the key signature was found. +.PP +trk is followed by the track number for which the following information +applies. +.PP +program is followed by the channel number and the General Midi Program +number. +.PP +trkinfo is an array of 8 numbers which indicates the statistical properties +of the track of interest. The following data is given: +the channel number, +the first program assigned to this channel, +the number of notes for this channel counting any chords as one note, +the total number of notes for this for this channel, +the sum of the MIDI pitches for all the notes, +the sum of the note durations in MIDI pulse units, +the number of control parameter messages, +and the number of pressure messages. + +.PP +After processing all the individual tracks, the following information +applies to the entire midi file. +.PP +rhythmPatterns indicates the number of distinct rhythm patterns for each +channel. A large number likely implies that the melody line occurs in +this channel, while a small number indicates that this channel probably +is used for chordal support. +.PP +npulses is the length of the longest midi track in midi pulse units +.PP +tempocmds specifies the number of times the tempo is changed in this +file. +.PP +pitchbends specifies the total number of pitchbends in this file. +.PP +progs is a list of all the midi programs addressed +.PP +progsact the amount of activity for each of the above midi programs. +The activity is the sum of the note durations in midi pulse units. +.PP +progcolor: is a 17 dimensional vector where each component maps into +a specific group of MIDI programs. Some of these groups are, keyboard +instruments, brass instruments, wind instruments, and etc. More information +can be found in the midiexplorer documentation. +.PP +drums is a list of all the percussion instruments (channel 9) that were +used. +.PP +drumhits indicates the number of notes for each of the above percussion +instruments. +.PP +pitches is a histogram for the 11 pitch classes (C, C#, D ...B) +that occur in the midi file. +.PP +pitchact is a similar histogram but is weighted by the length of +the notes. + +.SH AUTHOR +Seymour Shlien + + + diff --git a/doc/readme.txt b/doc/readme.txt index 31e2420..9938c11 100644 --- a/doc/readme.txt +++ b/doc/readme.txt @@ -6,6 +6,7 @@ abc2abc version 2.18 June 14 2022 yaps version 1.90 June 14 2022 abcmatch version 1.82 June 14 2022 midicopy version 1.38 May 06 2022 +midistats version 0.56 December 07 2022 24th January 2002 diff --git a/midistats.c b/midistats.c new file mode 100644 index 0000000..21d2dd3 --- /dev/null +++ b/midistats.c @@ -0,0 +1,964 @@ +/* midistats - program to extract statistics from MIDI files + * Derived from midi2abc.c + * Copyright (C) 1998 James Allwright + * e-mail: J.R.Allwright@westminster.ac.uk + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define VERSION "0.56 December 07 2022 midistats" + +#include +/* Microsoft Visual C++ Version 6.0 or higher */ +#ifdef _MSC_VER +#define snprintf _snprintf +#define ANSILIBS +#endif + +#include +#include +#ifdef PCCFIX +#define stdout 1 +#endif + +/* define USE_INDEX if your C libraries have index() instead of strchr() */ +#ifdef USE_INDEX +#define strchr index +#endif + +#ifdef ANSILIBS +#include +#include +#include +#else +extern char* malloc(); +extern char* strchr(); +#endif +#include "midifile.h" +void initfuncs(); +void stats_finish(); +float histogram_entropy (int *histogram, int size); +void stats_noteoff(int chan,int pitch,int vol); +void stats_eot (); + + +/* Global variables and structures */ + +extern long Mf_toberead; + +static FILE *F; +static FILE *outhandle; /* for producing the abc file */ + +int tracknum=0; /* track number */ +int division; /* pulses per quarter note defined in MIDI header */ +int quietLimit; /* minimum number of pulses with no activity */ +long tempo = 500000; /* the default tempo is 120 quarter notes/minute */ +long laston = 0; /* length of MIDI track in pulses or ticks */ +int key[12]; +int sharps; +int trackno; +int maintrack; +int format; /* MIDI file type */ +int debug; +int chordthreshold; /* number of maximum number of pulses separating note */ +int beatsPerBar = 4; /* 4/4 time */ +int divisionsPerBar; +int unitDivision; + + + +int tempocount=0; /* number of tempo indications in MIDI file */ + +int stats = 0; /* flag - gather and print statistics */ + + + +/* can cope with up to 64 track MIDI files */ +int trackcount = 0; + +int notechan[2048],notechanvol[2048]; /*for linking on and off midi + channel commands */ +int last_tick[17]; /* for getting last pulse number in MIDI file */ +int last_on_tick[17]; /* for detecting chords [SS] 2019-08-02 */ + + + + +/* The following variables are used by the -stats option + * which is used by a separate application called midiexplorer.tcl. + * The channel numbers go from 1 to 16 instead of 0 to 15 + */ +struct trkstat { + int notecount[17]; + int chordcount[17]; + int notemeanpitch[17]; + int notelength[17]; + int pitchbend[17]; + int pressure[17]; + int cntlparam[17]; + int program[17]; + int tempo[17]; + int npulses[17]; + int lastNoteOff[17]; + int quietTime[17]; + int rhythmpatterns[17]; + } trkdata; + +/* The trkstat references the individual channels in the midi file. + * notecount is the number of notes or bass notes in the chord. + * chordcount is the number of notes not counting the bass notes. + * notemeanpitch is the average pitch for the channel. + * notelength is the average note length. + * pitchbend is the number of pitch bends for the channel. + * pressure is the number of control pressure commands. + * cntlparam is the number of control parameter commands. + * program is number of times there is a program command for the channel. + * tempo is the number of times there is a tempo command. + * npulses is the number of pulses. + */ + +int progcolor[17]; /* used by stats_program */ +int drumhistogram[82]; /* counts drum noteons */ +int pitchhistogram[12]; /* pitch distribution for non drum notes */ +int channel2prog[17]; /* maps channel to program */ +int channel2nnotes[17]; /*maps channel to note count */ +int chnactivity[17]; /* [SS] 2018-02-02 */ +int progactivity[128]; /* [SS] 2018-02-02 */ +int pitchclass_activity[12]; /* [SS] 2018-02-02 */ + + +/* [SS] 2017-11-01 */ +static int progmapper[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 2, + 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 4, 4, 4, 4, 4, 2, + 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 2, 7, 10, + 7, 7, 7, 7, 8, 8, 8, 8, + 9, 9, 9, 9, 9, 9, 9, 9, +11, 11, 11, 11, 11, 11, 11, 11, +12, 12, 12, 12, 12, 12, 12, 12, +13, 13, 13, 13, 13, 13, 13, 13, +14, 14, 14, 14, 14, 14, 14, 14, +15, 15, 15, 15, 15, 15, 15, 15, + 2, 2, 2, 2, 2, 12, 6, 12, + 1, 1, 10, 10, 10, 10, 10, 1, +16, 16, 16, 16, 16, 16, 16, 16 +}; + + +struct barPattern { + int activeBarNumber; + int rhythmPattern; +} barChn[17]; + + +#define HashSize 255 +struct hashStruct { + int pattern[HashSize]; + int count[HashSize]; +} hasher[17] = {0}; + +int ncollisions = 0; + +void put_pattern (int chan, int pattern) { +int hashindex; +hashindex = pattern % HashSize; +if (hasher[chan].pattern[hashindex] == 0) { + hasher[chan].pattern[hashindex] = pattern; + /*printf ("hasher[%d].pattern[%d] = %d\n",chan,hashindex,pattern);*/ + } else { + if (hasher[chan].pattern[hashindex] != pattern) { + /* printf("collision\n"); */ + ncollisions++; + } + } +hasher[chan].count[hashindex]++; +} + +int count_patterns_for (int chan) { +int i; +int sum; +sum = 0; +for (i = 0; i 0) sum++; + /* hasher[chan].pattern[i] = 0; reset hasher */ + } +trkdata.rhythmpatterns[chan] = sum; +return sum; +} + + +void output_hasher_results () { +int i; +printf("rhythmPatterns "); +for (i = 0; i<16; i++) { + trkdata.rhythmpatterns[i] = count_patterns_for(i); + printf("%d ",count_patterns_for (i)); + } +printf("\n"); +printf("collisions %d\n",ncollisions); +ncollisions = 0; +} + + +int filegetc() +{ + return(getc(F)); +} + + +void fatal_error(s) +char* s; +/* fatal error encounterd - abort program */ +{ + fprintf(stderr, "%s\n", s); + exit(1); +} + + +void event_error(s) +char *s; +/* problem encountered but OK to continue */ +{ + char msg[256]; + + sprintf(msg, "Error: Time=%ld Track=%d %s\n", Mf_currtime, trackno, s); + printf("%s",msg); +} + + +int* checkmalloc(bytes) +/* malloc with error checking */ +int bytes; +{ + int *p; + + p = (int*) malloc(bytes); + if (p == NULL) { + fatal_error("Out of memory error - cannot malloc!"); + }; + return (p); +} + + + + +FILE * +efopen(name,mode) +char *name; +char *mode; +{ + FILE *f; + + if ( (f=fopen(name,mode)) == NULL ) { + char msg[256]; + sprintf(msg,"Error - Cannot open file %s",name); + fatal_error(msg); + } + return(f); +} + +void error(s) +char *s; +{ + fprintf(stderr,"Error: %s\n",s); +} + + +/* [SS] 2017-11-19 */ +void stats_error(s) +char *s; +{ + fprintf(stderr,"Error: %s\n",s); + fprintf(stderr,"activetrack %d\n",tracknum); + stats_finish(); +} + + + + +/* Dummy functions for handling MIDI messages. + * */ + void no_op0() {} + void no_op1(int dummy1) {} + void no_op2(int dummy1, int dummy2) {} + void no_op3(int dummy1, int dummy2, int dummy3) { } + void no_op4(int dummy1, int dummy2, int dummy3, int dummy4) { } + void no_op5(int dummy1, int dummy2, int dummy3, int dummy4, int dummy5) { } + + + +/* In order to associate a channel note off message with its + * corresponding note on message, we maintain the information + * the notechan array. When a midi pitch (0-127) is switched + * on for a particular channel, we record the time that it + * was turned on in the notechan array. As there are 16 channels + * and 128 pitches, we initialize an array 128*16 = 2048 elements + * long. +**/ +void init_notechan() +{ +/* signal that there are no active notes */ + int i; + for (i = 0; i < 2048; i++) notechan[i] = -1; +} + + + +char * pitch2key(int note) +{ +static char name[16]; /* [SDG] 2020-06-03 */ +char* s = name; + switch(note % 12) + { + case 0: *s++ = 'c'; break; + case 1: *s++ = 'c'; *s++ = '#'; break; + case 2: *s++ = 'd'; break; + case 3: *s++ = 'd'; *s++ = '#'; break; + case 4: *s++ = 'e'; break; + case 5: *s++ = 'f'; break; + case 6: *s++ = 'f'; *s++ = '#'; break; + case 7: *s++ = 'g'; break; + case 8: *s++ = 'g'; *s++ = '#'; break; + case 9: *s++ = 'a'; break; + case 10: *s++ = 'a'; *s++ = '#'; break; + case 11: *s++ = 'b'; break; + } + sprintf(s, "%d", (note / 12)-1); /* octave (assuming Piano C4 is 60)*/ + return name; +} + + +void pitch2drum(midipitch) +int midipitch; +{ +static char *drumpatches[] = { + "Acoustic Bass Drum", "Bass Drum 1", "Side Stick", "Acoustic Snare", + "Hand Clap", "Electric Snare", "Low Floor Tom", "Closed Hi Hat", + "High Floor Tom", "Pedal Hi-Hat", "Low Tom", "Open Hi-Hat", + "Low-Mid Tom", "Hi Mid Tom", "Crash Cymbal 1", "High Tom", + "Ride Cymbal 1", "Chinese Cymbal", "Ride Bell", "Tambourine", + "Splash Cymbal", "Cowbell", "Crash Cymbal 2", "Vibraslap", + "Ride Cymbal 2", "Hi Bongo", "Low Bongo", "Mute Hi Conga", + "Open Hi Conga", "Low Conga", "High Timbale", "Low Timbale", + "High Agogo", "Low Agogo", "Cabasa", "Maracas", + "Short Whistle", "Long Whistle", "Short Guiro", "Long Guiro", + "Claves", "Hi Wood Block", "Low Wood Block", "Mute Cuica", + "Open Cuica", "Mute Triangle", "Open Triangle" }; +if (midipitch >= 35 && midipitch <= 81) { + printf(" (%s)",drumpatches[midipitch-35]); + } +} + + + + +void stats_header (int format, int ntrks, int ldivision) +{ + int i; + division = ldivision; + quietLimit = ldivision*8; + divisionsPerBar = division*beatsPerBar; + unitDivision = divisionsPerBar/24; + printf("ntrks %d\n",ntrks); + printf("ppqn %d\n",ldivision); + chordthreshold = ldivision/16; /* [SS] 2018-01-21 */ + trkdata.tempo[0] = 0; + trkdata.pressure[0] = 0; + trkdata.program[0] = 0; + for (i=0;i<17;i++) { + trkdata.npulses[i] = 0; + trkdata.pitchbend[i] = 0; + trkdata.cntlparam[i] = 0; /* [SS] 2022-03-04 */ + trkdata.pressure[i] = 0; /* [SS] 2022-03-04 */ + trkdata.quietTime[i] = 0; /* [SS] 2022-08-22 */ + progcolor[i] = 0; + channel2prog[i] = -1; + channel2nnotes[i] = 0; + chnactivity[i] = 0; /* [SS] 2018-02-02 */ + } + for (i=0;i<82;i++) drumhistogram[i] = 0; + for (i=0;i<12;i++) pitchhistogram[i] = 0; /* [SS] 2017-11-01 */ + for (i=0;i<12;i++) pitchclass_activity[i] = 0; /* [SS] 2018-02-02 */ + for (i=0;i<128;i++) progactivity[i] = 0; /* [SS] 2018-02-02 */ +} + +void determine_progcolor () +{ +int i; +for (i=0;i<17;i++) progcolor[i] =0; +for (i=0;i<128;i++) { + progcolor[progmapper[i]] += progactivity[i]; + } +} + + +/* [SS] 2018-04-24 */ +void output_progs_data () { +int i; +/* check that there is valid progactivity */ + + printf("progs "); + for (i=0;i<128;i++) + if(progactivity[i] > 0) printf(" %d",i); + printf("\nprogsact "); + for (i=0;i<128;i++) + if(progactivity[i] > 0) printf(" %d",progactivity[i]); + } + + + +void stats_finish() +{ +int i; /* [SDG] 2020-06-03 */ +int npulses; +int nprogs; +double delta; + + +npulses = trkdata.npulses[0]; +printf("npulses %d\n",trkdata.npulses[0]); +printf("tempocmds %d\n",trkdata.tempo[0]); +printf("pitchbends %d\n",trkdata.pitchbend[0]); +for (i=1;i<17;i++) { + if (trkdata.pitchbend[i] > 0) { + printf("pitchbendin %d %d\n",i,trkdata.pitchbend[i]); } + } + +if (trkdata.pressure[0] > 0) + printf("pressure %d\n",trkdata.pressure[0]); +printf("programcmd %d\n",trkdata.program[0]); + +nprogs = 0; /* [SS] 2018-04-24 */ +for (i=1;i<128;i++) + if(progactivity[i] >0) nprogs++; +if (nprogs > 0) output_progs_data(); +else { + for (i=0;i<17;i++) + if(chnactivity[i] > 0) + progactivity[channel2prog[i]] = chnactivity[i]; + output_progs_data(); + } + +determine_progcolor(); +printf("\nprogcolor "); +if (npulses > 0) + for (i=0;i<17;i++) printf("%5.2f ",progcolor[i]/(double) npulses); +else + for (i=0;i<17;i++) printf("%5.2f ",(double) progcolor[i]); +printf("\n"); + +printf("drums "); +for (i=35;i<82;i++) { + if (drumhistogram[i] > 0) printf("%d ",i); + } +printf("\ndrumhits "); +for (i=35;i<82;i++) { + if (drumhistogram[i] > 0) printf("%d ",drumhistogram[i]); + } + +printf("\npitches "); /* [SS] 2017-11-01 */ +for (i=0;i<12;i++) printf("%d ",pitchhistogram[i]); +printf("\npitchact "); /* [SS] 2018-02-02 */ +if (npulses > 0) + for (i=0;i<12;i++) printf("%5.2f ",pitchclass_activity[i]/(double) npulses); +else + for (i=0;i<12;i++) printf("%5.2f ",(double) pitchclass_activity[i]); +printf("\nchnact "); /* [SS] 2018-02-08 */ +if (npulses > 0) + for (i=1;i<17;i++) printf("%5.2f ",chnactivity[i]/(double) trkdata.npulses[0]); +else + for (i=0;i<17;i++) printf("%5.2f ",(double) chnactivity[i]); +printf("\nquietTime "); +for (i=1;i<17;i++) { + delta = trkdata.npulses[0] - trkdata.quietTime[i]; + if (trkdata.quietTime[i] < quietLimit) delta = 0; + delta = delta / (double) trkdata.npulses[0]; + /* printf (" %5.3f ", delta); */ + printf (" %d ", trkdata.quietTime[i]); + } + +printf("\npitchentropy %f\n",histogram_entropy(pitchclass_activity,12)); +printf("\n"); +} + + + +float histogram_entropy (int *histogram, int size) + { + int i; + int total; + float entropy; + float e,p; + total = 0; + entropy = 0.0; + for (i=0;i0) { + printf("%s ",name); + printf("%d %d ",i,data_array[i]); + printf("\n"); + } + } +} + + + +void output_track_summary () { +int i; +/* find first channel containing data */ +output_hasher_results(); +for (i=1;i<17;i++) { + if(trkdata.notecount[i] == 0 && trkdata.chordcount[i] == 0) continue; + printf("trkinfo "); + printf("%d %d ",i,trkdata.program[i]); /* channel number and program*/ + printf("%d %d ",trkdata.notecount[i],trkdata.chordcount[i]); + printf("%d %d ",trkdata.notemeanpitch[i], trkdata.notelength[i]); + printf("%d %d ",trkdata.cntlparam[i],trkdata.pressure[i]); /* [SS] 2022-03-04 */ + printf("%d %d",trkdata.quietTime[i],trkdata.rhythmpatterns[i]); + trkdata.quietTime[i] = 0; + printf("\n"); + + channel2nnotes[i] += trkdata.notecount[i] + trkdata.chordcount[i]; + } +} + + + + +void stats_trackstart() +{ + int i; + tracknum++; + for (i=0;i<17;i++) { + trkdata.notecount[i] = 0; + trkdata.notemeanpitch[i] = 0; + trkdata.notelength[i] = 0; + trkdata.chordcount[i] = 0; + trkdata.cntlparam[i] = 0; + last_tick[i] = -1; + last_on_tick[i] = -1; + } + printf("trk %d \n",tracknum); +} + +void stats_trackend() +{ + trkdata.npulses[tracknum] = Mf_currtime; + if (trkdata.npulses[0] < Mf_currtime) trkdata.npulses[0] = Mf_currtime; + output_track_summary(); +} + + + +void stats_noteon(chan,pitch,vol) +int chan, pitch, vol; +{ + int delta; + int barnum; + int unit; + + if (vol == 0) { + /* treat as noteoff */ + stats_noteoff(chan,pitch,vol); + trkdata.lastNoteOff[chan+1] = Mf_currtime; /* [SS] 2022.08.22 */ + return; + } + trkdata.notemeanpitch[chan+1] += pitch; + if (trkdata.lastNoteOff[chan+1] >= 0) { + delta = Mf_currtime - trkdata.lastNoteOff[chan+1]; + trkdata.lastNoteOff[chan+1] = -1; /* in case of chord */ + if (delta > quietLimit) { + trkdata.quietTime[chan+1] += delta; + } + } + + if (abs(Mf_currtime - last_on_tick[chan+1]) < chordthreshold) trkdata.chordcount[chan+1]++; + else trkdata.notecount[chan+1]++; /* [SS] 2019-08-02 */ + last_tick[chan+1] = Mf_currtime; + last_on_tick[chan+1] = Mf_currtime; /* [SS] 2019-08-02 */ + /* last_on_tick not updated by stats_noteoff */ + + + if (chan != 9) { + barnum = Mf_currtime/divisionsPerBar; + if (barnum != barChn[chan].activeBarNumber) { + /*printf("%d %d %d\n",chan,barChn[chan].activeBarNumber, + barChn[chan].rhythmPattern); */ + put_pattern (chan+1, barChn[chan].rhythmPattern); + + barChn[chan].rhythmPattern = 0; + barChn[chan].activeBarNumber = barnum; + } + unit = (Mf_currtime % divisionsPerBar)/unitDivision; + //printf("unit = %d pattern = %d \n",unit,barChn[chan].rhythmPattern); + barChn[chan].rhythmPattern = barChn[chan].rhythmPattern |= (1UL << unit); + } + + + + if (chan == 9) { + if (pitch < 0 || pitch > 81) + printf("****illegal drum value %d\n",pitch); + else drumhistogram[pitch]++; + } + else pitchhistogram[pitch % 12]++; /* [SS] 2017-11-01 */ +} + + +void stats_eot () { +trkdata.lastNoteOff[0] = Mf_currtime; /* [SS] 2022.08.24 */ +} + +void stats_noteoff(int chan,int pitch,int vol) +{ + int length; + int program; + /* ignore if there was no noteon */ + if (last_tick[chan+1] == -1) return; + length = Mf_currtime - last_tick[chan+1]; + trkdata.notelength[chan+1] += length; + trkdata.lastNoteOff[chan+1] = Mf_currtime; /* [SS] 2022.08.22 */ + chnactivity[chan+1] += length; + if (chan == 9) return; /* drum channel */ + pitchclass_activity[pitch % 12] += length; + program = trkdata.program[chan+1]; + progactivity[program] += length; + /* [SS] 2018-04-18 */ + if(Mf_currtime > last_tick[chan+1]) last_tick[chan+1] = Mf_currtime; +} + + +void stats_pitchbend(chan,lsb,msb) +int chan, lsb, msb; +{ +trkdata.pitchbend[0]++; +trkdata.pitchbend[chan+1]++; +} + +void stats_pressure(chan,press) +int chan, press; +{ +trkdata.pressure[0]++; +trkdata.pressure[chan+1]++; /* [SS] 2022.04.28 */ +} + + + +void stats_program(chan,program) +int chan, program; +{ +int beatnumber; +if (program <0 || program > 127) return; /* [SS] 2018-03-06 */ +if (trkdata.program[chan+1] != 0) { + beatnumber = Mf_currtime/division; + printf("cprogram %d %d %d\n",chan+1,program,beatnumber); + /* count number of times the program was modified for a channel */ + trkdata.program[0] = trkdata.program[0]+1; + } else { + printf("program %d %d\n",chan+1,program); + trkdata.program[chan+1] = program; + } + if (channel2prog[chan+1]== -1) channel2prog[chan+1] = program; +} + + + +void stats_parameter(chan,control,value) +int chan, control, value; +{ +/*if (control == 7) { + printf("cntrlvolume %d %d \n",chan+1,value); + } +*/ +trkdata.cntlparam[chan+1]++; +} + + + +void stats_metatext(type,leng,mess) +int type, leng; +char *mess; +{ +int i; +if (type != 3) return; +printf("metatext %d ",type); +for (i=0;i12) return; + if (mi) + printf("keysig %s %d %d %6.2f\n",minor[index],sf,mi,beatnumber); + else + printf("keysig %s %d %d %6.2f\n",major[index],sf,mi,beatnumber); +} + + + +/* [SS] 2018-01-02 */ +void stats_tempo(ltempo) +long ltempo; +{ + float beatnumber; + tempo = ltempo; + beatnumber = Mf_currtime/division; + if (trkdata.tempo[0] == 0) printf("tempo %6.2f bpm\n",60000000.0/tempo); + else if (trkdata.tempo[0] < 10) printf("ctempo %6.2f %6.2f\n",60000000.0/tempo,beatnumber); + trkdata.tempo[0]++; +} + + +void stats_timesig(nn,dd,cc,bb) +int nn, dd, cc, bb; +{ + float beatnumber; + int denom = 1; + beatnumber = Mf_currtime/division; + while ( dd-- > 0 ) + denom *= 2; + printf("timesig %d/%d %6.2f\n",nn,denom,beatnumber); +} + + + + +void initfunc_for_stats() +{ + Mf_error = stats_error; /* [SS] 2017-11-19 */ + Mf_header = stats_header; + Mf_trackstart = stats_trackstart; + Mf_trackend = stats_trackend; + Mf_noteon = stats_noteon; + Mf_noteoff = stats_noteoff; + Mf_pressure = no_op3; + Mf_parameter = stats_parameter; + Mf_pitchbend = stats_pitchbend; + Mf_program = stats_program; + Mf_chanpressure = stats_pressure; + Mf_sysex = no_op2; + Mf_metamisc = no_op3; + Mf_seqnum = no_op1; + Mf_eot = stats_eot; + Mf_timesig = stats_timesig; + Mf_smpte = no_op5; + Mf_tempo = stats_tempo; + Mf_keysig = stats_keysig; + Mf_seqspecific = no_op3; + Mf_text = stats_metatext; + Mf_arbitrary = no_op2; +} + + +int readnum(num) +/* read a number from a string */ +/* used for processing command line */ +char *num; +{ + int t; + char *p; + int neg; + + t = 0; + neg = 1; + p = num; + if (*p == '-') { + p = p + 1; + neg = -1; + }; + /* [JA] 2021-05-25 */ + while (((int)*p >= '0') && ((int)*p <= '9') && (t < (INT_MAX-9)/10)) { + t = t * 10 + (int) *p - '0'; + p = p + 1; + }; + return neg*t; +} + + +int readnump(p) +/* read a number from a string (subtly different) */ +/* used for processing command line */ +char **p; +{ + int t; + + t = 0; + /* [JA] 2021-05-25 */ + while (((int)**p >= '0') && ((int)**p <= '9') && (t < (INT_MAX-9)/10)) { + t = t * 10 + (int) **p - '0'; + *p = *p + 1; + }; + /* advance over any spurious extra digits */ + while (isdigit(**p)) { + *p = *p + 1; + } + return t; +} + + +int getarg(option, argc, argv) +/* extract arguments from command line */ +char *option; +char *argv[]; +int argc; +{ + int j, place; + + place = -1; + for (j=0; j\n"); + printf(" -ver version number\n"); + printf(" -d debug parameter\n"); + printf(" The input filename is assumed to be any string not\n"); + printf(" beginning with a - (hyphen). It may be placed anywhere.\n"); + exit(0); + }; + return arg; +} + + + +void midistats(argc,argv) +char *argv[]; +int argc; +{ +initfunc_for_stats(); +Mf_getc = filegetc; +mfread(); +stats_finish(); +} + + + +int main(argc,argv) +char *argv[]; +int argc; +{ + FILE *efopen(); + int arg; + + arg = process_command_line_arguments(argc,argv); + if(stats == 1) midistats(argc,argv); + return 0; +}