Implement basic testing infrastructure (#19)

* Add configuration for CMake build system alongside autoconf

- Add a modern CMake build system (`CMakeLists.txt`, `CMakePresets.json`) that coexists with the legacy
autoconf/Makefile build
- Shared source files (`midifile.c`, `parseabc.c`, `music_utils.c`, `parser2.c`) are compiled once via OBJECT
libraries and linked into the 8 binaries
- Three presets: `default` (Release), `debug`, `sanitize` (ASan + UBSan)
- Generates `compile_commands.json` for clangd/LSP editor support
- Install rules match the legacy Makefile (binaries, doc files, man pages)
- Pinned to `-std=gnu89` because the codebase mixes K&R `()` and ANSI typed prototypes — in C23/gnu23 (GCC 15+
default), `()` means `(void)`, making these a hard error. Note: **the existing autoconf build is also broken with
GCC 15** for the same reason

```sh
cmake --preset debug
cmake --build --preset debug
cmake --install build/debug --prefix /usr/local

Documentation

- README.md: added Building section with both autoconf and CMake instructions
- doc/readme.txt: added build instructions in the existing preamble
- doc/CHANGES: added changelog entry

Test plan

- All 3 presets configure and build with GCC 15
- Smoke test: abc2midi samples/coleraine.abc produces valid MIDI through mftext
- Sanitizer build (--preset sanitize) runs clean on sample files
- Install layout verified: 8 binaries, 10 doc files, 8 man pages in correct paths
- Build on macOS (untested, should work with AppleClang)

* Implement basic testing infrastructure

The CMake build includes a test suite covering all 8 programs:

- **Smoke tests** verify each binary runs cleanly with `-ver`.
- **Golden-file tests** run each program on a sample input and compare the
  (normalized) output to a checked-in reference. Binary MIDI outputs are
  piped through `mftext` to produce diffable text. Volatile lines (version
  banners, dates, temporary paths) are stripped before comparison.

```sh
ctest --preset debug

ctest --preset debug -L golden
ctest --preset debug -L smoke
```

To regenerate the golden files after an intentional behavioural change,
review the diff, then commit:

```sh
cmake --build build/debug --target update-golden
git diff tests/golden/
```

* Factorize more the test CMake code
This commit is contained in:
Ronan Keryell
2026-04-22 04:42:29 -07:00
committed by GitHub
parent c7f4015945
commit 1d766a85d2
18 changed files with 8421 additions and 0 deletions

83
tests/CMakeLists.txt Normal file
View File

@@ -0,0 +1,83 @@
# abcmidi test suite
#
# Two layers of tests:
#
# 1. Smoke tests - every binary runs with -ver and exits cleanly.
# Catches link errors, missing libraries, trivial crashes.
#
# 2. Golden tests - each program is run on a sample input and its output
# is compared with a checked-in reference file. Binary
# MIDI outputs are first piped through mftext to produce
# diffable text. Volatile lines (version banners, dates,
# tmpdir paths) are stripped before comparison.
#
# To regenerate golden files after an intentional change:
#
# ABCMIDI_UPDATE_GOLDEN=1 ctest --preset debug
#
# Then review the diff and commit the updated tests/golden/*.txt files.
set(SAMPLES_DIR "${PROJECT_SOURCE_DIR}/samples")
set(GOLDEN_DIR "${CMAKE_CURRENT_SOURCE_DIR}/golden")
set(TEST_TMPDIR "${CMAKE_CURRENT_BINARY_DIR}/tmp")
# --- Smoke tests: -ver on every binary ---
foreach(bin IN LISTS ABCMIDI_BINARIES)
add_test(NAME "smoke_${bin}_ver" COMMAND $<TARGET_FILE:${bin}> -ver)
set_tests_properties("smoke_${bin}_ver" PROPERTIES LABELS "smoke")
endforeach()
# --- Golden tests ---
# Build a list of "-D<BIN>=$<TARGET_FILE:bin>" args, one per binary, so that
# run_test.cmake receives all binary paths uniformly.
set(BINARY_DEFS)
foreach(bin IN LISTS ABCMIDI_BINARIES)
string(TOUPPER "${bin}" BIN_UPPER)
list(APPEND BINARY_DEFS "-D${BIN_UPPER}=$<TARGET_FILE:${bin}>")
endforeach()
# Helper: register a golden test for one program against one sample
function(add_golden_test)
cmake_parse_arguments(T "" "TYPE;SAMPLE" "" ${ARGN})
get_filename_component(stem "${T_SAMPLE}" NAME_WE)
set(test_name "${T_TYPE}_${stem}")
add_test(
NAME "${test_name}"
COMMAND "${CMAKE_COMMAND}"
-DTYPE=${T_TYPE}
-DSAMPLE=${SAMPLES_DIR}/${T_SAMPLE}
-DGOLDEN=${GOLDEN_DIR}/${test_name}.txt
-DTMPDIR=${TEST_TMPDIR}
${BINARY_DEFS}
-P "${CMAKE_CURRENT_SOURCE_DIR}/run_test.cmake"
)
set_tests_properties("${test_name}" PROPERTIES LABELS "golden")
endfunction()
# One golden test per program against coleraine.abc
foreach(type IN ITEMS abc2midi abc2abc midi2abc midistats mftext yaps midicopy abcmatch)
add_golden_test(TYPE ${type} SAMPLE coleraine.abc)
endforeach()
# A few extra coverage points on different samples
add_golden_test(TYPE abc2midi SAMPLE demo.abc)
add_golden_test(TYPE abc2abc SAMPLE demo.abc)
# --- Regenerate-golden convenience target ---
#
# Usage: cmake --build build/debug --target update-golden
#
# Equivalent to setting ABCMIDI_UPDATE_GOLDEN=1 and running ctest, but easier
# to discover via cmake --build --target.
add_custom_target(update-golden
COMMAND ${CMAKE_COMMAND} -E env ABCMIDI_UPDATE_GOLDEN=1
${CMAKE_CTEST_COMMAND} -L golden --output-on-failure
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
COMMENT "Regenerating golden test references"
USES_TERMINAL
)

View File

@@ -0,0 +1,54 @@
X:8
%%MIDI channel 1
%%MIDI chordprog 3
%%MIDI bassprog 3
%%MIDI program 26
%%MIDI beat 110 100 90 4
%%MIDI ratio 2 1
%%MIDI chordvol 64
%%MIDI bassvol 65
%%MIDI transpose 0
%%MIDI gracedivider 4
Q:1/4=142
T:Coleraine
B:Kerr's Violin IV
Z:John Chambers <jc@eddie.mit.edu> http://eddie.mit.edu/~jc/music/
R:jig
M:6/8
L:1/8
K:Am
%%MIDI drum d2z2ddd2d2d2 65 66 66 50 66 66 90 70 70 90 70 70
%%MIDI drumon
V:1
%%MIDI program 72
%%MIDI control 7 115
%%MIDI control 10 67
%%MIDI beat 110 100 90 4
|: "E7"E
%Error : Bar 1 is 1/8 not 6/8
| "Am"E>AA ABc | "E7"B>ee e2d | "Am"c>AA ABc | "E7"B^GE E2E | \
| "Am"E>AA ABc | "E7"B>ee e2d | "Am"c>BA "E7"B^GE | "Am"A3- A2 :|
|: "G7"B | "C"c2c cdc | "G"Bdg "(E)"g2^g | "Am"a>ed cBA | "E7"^GBG E^FG | \
| "Am"A^GA "E7"BAB | "Am"cde "Dm"fed | "Am"c>BA "E7"B^GE | "Am"A3- A2 :|
V:drum
M:6/8
L:1/16
%%MIDI channel 10
|: z2|G,,3A,,G,,2 A,,G,,A,,2A,,2 |
G,,3A,,G,,2 A,,2G,,A,,G,,2 |
G,,3A,,G,,2 A,,G,,A,,2A,,2 |
G,,3A,,G,,2 A,,2G,,A,,G,,2 |
G,,3A,,G,,2 A,,G,,A,,2A,,2 |
G,,3A,,G,,2 A,,2G,,A,,G,,2 |
G,,3A,,G,,2 A,,G,,A,,2A,,2 |
G,,3A,,G,,2 A,,2G,,A,, :|
%
|:z2| G,,3A,,G,,2 A,,G,,A,,2A,,2 |
G,,3A,,G,,2 A,,2G,,A,,G,,2 |
G,,3A,,G,,2 A,,G,,A,,2A,,2 |
G,,3A,,G,,2 A,,2G,,A,,G,,2 |
G,,2G,,2G,,2 z6 |
G,,2G,,2G,,2 z6 |
G,,2G,,2G,,2 z6 |
G,,6 z4 :|

View File

@@ -0,0 +1,294 @@
% Example tunes for abc2midi.
% Illustrating various aspects of the abc notation language
%
%
% A French tune using an in-body key change
%
X:1
T:Horses Branle
M:4/4
L:1/8
Q:1/4=127
C:Trad
K:G
P:A
|: G>A BB cBAc|BAGF E2D2|G>A BB cBAc|BGAF G2 G2
P:B
:: d c/2B/2 AB c B/2A/2 GB|AGFG A>B A2|\
d c/2B/2 AB c B/2A/2 GB|AGGF G2 G2 ::
P:C
K:F
B/2A/2 G B/2A/2 G FG A2|DEFG ABAG | \
B/2A/2 G B/2A/2 G FG A2|DEFG GF G2 :|
% A hornpipe using triplets, accidentals and broken rhythm
%
X:2
T:Trumpet Hornpipe
T:Captain Pugwash Theme
C:Trad
M:4/4
L:1/8
Q:1/4=140
R:hornpipe
K:G
|: (3GGG G2 (3GGG G>d|B>GB>d g>dB>G|\
(3DDD D2 (3DDD D>A|F>DF>A c>AF>A|
(3GGG G2 (3GGG G>d|B>G B>d g2 g2|\
f>ag>f e>gf>e |1 d>^cd>e d>=cB>A :|2 d>^cd>e d2 B>=c |:
(3ddd d2 (3ddd d2|e>fg>f e>dc>B|\
c>de>d c>BA>G|F>GA>G F>DE>F|
(3GGG G2 (3=FFF F2|(3EEE E2 (3^DDD D2| \
=D>gf>e d>cB>A|1 G2B2G2 B>c :|2 G2B2G4 ||
% Using ties to create non-standard length notes.
%
X:3
T:Smash the Windows
T:Roaring Jelly
S:One Thousand English Country Dance Tunes, Michael Raven
C:Trad
M:6/8
L:1/8
Q:1/8=400
K:D
|:A
%Error : Bar 1 is 1/8 not 6/8
|DED F2A|d2f ecA|G2B F2A|E2F GFE|DED F2A|d2f ecA|Bgf edc|d3-d2:|
a|a2f d2f|A2a agf|g2e c2e|A2g gfe|f2d g2e|a2f bag|fed edc|d3-d2a|
agf fed|Adf agf|gfe ecA|Ace gfe|fed gfe|agf bag|fed edc|d3-d2z||
% Four-part arrangement using V: for multiple voices
%
X:4
T:Candlemas Eve
S:Hymn 126 Arr. R. Herrick from an old church-gallery book
M:4/4
L:1/8
Q:1/8=400
N:from an old church-gallery book
H:The old church-gallery book was discovered by the Rev. L.J.T. Darwall.
H:The source has a 4-part harmony.
O:English
R:Reel
K:G
V:1
% soprano
D2 |\
G2 G2 B2 G2 | E2 F2 G2 Bd | c2 B2 A2 G2 | A6 Bc |
d2 B2 G2 AB | c2 A2 F2 GA | B2 G2 E2 F2 | G6 Bc |
d2 d2 d2 B2 | e2 c2 A2 Bd | c2 B2 A2 G2 | d6 B2 |
e2 d2 c2 B2 | A2 G2 F2 GA | B2 G2 E2 F2 | G6 z2 ||
V:2
% alto
D2
%Error : Bar 17 is 1/4 not 4/4
|\
D2 C2 B,2 D2 | C2 C2 D2 D2 | G2 G2 E2 E2 | F6 G2 |
G2 F2 E2 D2 | C2 E2 D2 E2 | D2 D2 C2 C2 | D6 G2 |
G2 G2 G2 G2 | G2 G2 F2 D2 | G2 G2 E2 G2 | F6 D2 |
C2 D2 EF G2 | E2 E2 D2 E2 | D2 B,2 C2 D2 | D6 z2 ||
V:3
% tenor
D,2
%Error : Bar 34 is 1/4 not 4/4
|\
G,2 G,2 G,2 G,2 | G,2 A,2 B,2 B,2 | E2 D2 C2 B,2 | D6 D2 |
D2 D2 B,2 G,2 | E,2 A,2 A,2 C2 | G,2 G,2 G,2 A,2 | B,6 DC |
B,2 D2 B,2 D2 | C2 E2 D2 B,2 | C2 D2 C2 G,2 | A,6 G,2 |
G,2 G,2 C2 D2 | CD CB, A,2 C2 | G,2 G,2 A,2 A,2 | B,6 z2 ||
V:4
% bass up one octave
D2
%Error : Bar 51 is 1/4 not 4/4
|\
B,2 A,2 G,2 B,2 | C2 A,2 G,2 G2 | E2 G2 A2 E2 | D6 GA |
B,2 D2 E2 E2 | A,2 C2 D2 C2 | B,2 A,B, C2 A,2 | G,6 G,2 |
G2 B2 G2 G2 | c2 C2 D2 G2 | E2 G2 C2 E2 | D6 G2 |
C2 B,2 A,2 G,2 | A,2 C2 D2 C2 | B,2 E2 A,2 D2 | G,6 z2 ||
% Using the w: field and part notation to create a karaoke file.
% There are a lot more verses to this song than the 3 shown here.
%
X:5
T:Oh You New York Girls
C:Trad
M:4/4
L:1/8
Q:1/4=200
P:(AB)3
K:C % 0 sharps
%%MIDI gchord fz
%%MIDI chordvol 90
P:A
g2|e2g2g3g|f2a2a3a|g2g2f2g2|e6
w:As I walked out on So-uth Street, a fair maid I did meet
w:I said, "My dear young la-dy, I'm a stran-ger here in town
w:I took her out to Tiff-an-y's, I spared her no ex-pense
g2|c'3c'c'2g2|b2 a2a3a|g3 gf2d2|c4
w:Who asked me please to see her home, she lived on Blee-cker Street
w:I left my ship just yes-ter-day, from Liver-pool I was bound."
w:I bought her two gold ea-r-rings, they cost me fif-teen cents.
P:B
e2f2|g6e2|f2 a6|b4 a4|a2g4 z2|
w:And a-way, you John-ny, my dear hon-ey
c'6b2|b2a2 a4|g3g f2B2|d2c4
w:Oh you New York girls, can you dance the pol-ka?
% Using "guitar chords" to generate an accompaniment.
% Also uses R:hornpipe to generate broken rhythm.
%
X:6
T:The Friendly Visit
R:hornpipe
S:Nottingham Music Database
M:4/4
L:1/8
Q:1/4=200
K:G
|: BA
%Error : Bar 1 is 1/4 not 4/4
|\
"G"(3GFG DG BGBd|"C"(3cBc AB "D7"cdef|"G"g2df "C"ecAG|"Am"FGAB "D7"cAFD|
"G"(3GFG DG BGBd|"C"(3cBc AB "D7"cdef|"G"gdBG "D7"FAdc|"G"B2G2 G2::
(3GBd|\
"G"g2dB GBdg|"Am"e2cA FGAg|"D"f2ed "A7"^cdeg|"D7"(3fgf (3efe dcBA|
"G"(3GFG DG BGBd|"C"(3cBc AB "D7"cdef|"G"gdBG "D7"FAdc|"G"B2G2 G2:|z2||
% Using drone commands for bagpipe music
X:7
T:The First Slip "Arranged by Terry Tully"
M:C
L:1/8
Q:1/4=80
C:Traditional Irish
S:Reel
Z:The Brussels Caledonian Corneymusers Pipe Band
Z:http://membres.lycos.fr/corneymusers/Tunes.html
K:HP
%%MIDI program 109
%%MIDI drone 70 45 33 90 90
%%MIDI droneon
|: {g}eA{gAGAG}A2{gef}e2{g}dB|
{g}eA{gAGAG}A2{g}GB{gBeBG}B2|
{g}eA{gAGAG}A2{gef}e2{g}fa| !
ge{gde}dB{G}ABcd:||:
{g}ea{g}ag{ef}e2{A}ef|
{g}dB{gBeBG}B2{g}GB{gBeBG}B2| !
{g}ea{g}ag{ef}e2{A}ef|
{a}ge{gde}dB{G}ABcd:|
%%MIDI droneoff
% Using extended gchord codes for playing arpeggios
X:8
T:Roddy McCawley
% Nottingham Music Database
S:Saen Smith, via PR
M:4/4
L:1/4
K:G
%%MIDI program 73
%%MIDI chordprog 0
%%MIDI bassprog 1
%%MIDI gchord ghhi
GA |B2 AB|D2 GA|"G"B3/2c/2 BA|G2 D2|"C"E2 G2|G2 A2|"G"G4-|
B2 Bc|"G"d2 d2|d2 Bd|"C"e2 e2|"G"d2 BA|"Em"G2 E2|"Am"c2 B2|"D"A4-|
A2 Bc|"G"d2 d2|d2 Bd|"C"e2 e2|"G"d2 BA|"Em"G2 E2|"Am"c2 B2|"D"A4-|A2 GA|
"G"B2 AB|D2 GA|"G"B3/2c/2 BA|G2 D2|"C"E2 G2|G2 A2|"G"G4-|G4||
% uses microtones
X:9
T:Daramad of Shur
L:1/8
% adapted from http://anamnese.online.fr/iran/persianm.abc
% see http://anamnese.online.fr/iran/persian_music.html for more info
Q:1/4=135
M:4/4
K:C
%%MIDI program 111
d e g f e d c _B A G A d2 {c}_B2 {A}G2 |
G A c _B A G F E D E F G A c {_B} A2 {G} F4
%Error : Bar 1 is 5/2 not 4/4
|
FFF A2 G2 {F} EEE G2 F2 {E} DDDF2 E2
%Error : Bar 2 is 21/8 not 4/4
|
%using the %%MIDI trim command to distinguish slurs
X:10
T:Heights of Alma
% Nottingham Music Database
S:KCC p3, via EF
M:4/4
L:1/4
K:A
%%MIDI trim 1/5
%%MIDI program 74
%%MIDI beat 89 79 69 4
%%MIDI chordprog 45
%%MIDI bassprog 45
%%MIDI chordvol 77
%%MIDI bassvol 73
P:A
(e/2d/2)|"A"cA AE|"A"(A/2B/2c/2d/2) e2|"A"(f/2e/2d/2c/2) eA|\
"G"(d/2=c/2B/2A/2) =Ge/2d/2|
"A"cA AE|"A"A/2B/2c/2d/2 e2|"A"(f/2e/2d/2c/2) "E7"(e/2f/2e/2d/2)|
%Warning : Missing repeat at start ? Unexpected :| found
"A"cA A:|
P:B
c/2d/2|"A"ea ca|"A"e/2f/2e/2c/2 AB/2=c/2|"G"d=g Bg|"G"d/2e/2d/2B/2 =Gc/2d/2|
"A"ea ca|"A"e/2f/2e/2c/2 AB/2c/2|"E7"(d/2c/2B/2A/2) (G/2B/2e/2d/2)|
%Warning : Unexpected :| found
"A"cA A:|
X:11
T:Linear Temperament
M:4/4
L:1/4
Q:1/4=35
% %MIDI temperamentlinear 1200.0 694.736842 % 19-EDO
% %MIDI temperamentlinear 1200.0 709.090909 % 22-EDO
% %MIDI temperamentlinear 1200.0 696.774194 % 31-EDO
% %MIDI temperamentlinear 1200.0 698.0 % fifth=698 cents
% %MIDI temperamentlinear 1200.0 696.57843 % 1/4-comma meantone
%%MIDI temperamentlinear 1200.0 701.955001 % Pythagorean
% %MIDI temperamentnormal % 12-EDO
K:C
V:1
%%MIDI program 16
c2 B2 | c3/2z/2 ^A2 |
V:2
%%MIDI program 16
G2 G2 | G3/2z/2 G2 |
V:3
%%MIDI program 16
(3E_E^D (3=DF_F | =E3/2z/2 E2 |
V:4
%%MIDI program 16
C2 G,2 | C3/2z/2 C2 |
X:12
T:Cuckoo's Nest
% Nottingham Music Database
% drum line added by Seymour
S:Song
M:4/4
L:1/8
R:Hornpipe
Q:1/4=144
K:Dm
V:1
"Dm"D2DE DCA,C|"Dm"DCDE F2"C7"FA|"F"c2cd A2GF|"C"ECCC C2"A7"FE|
"Dm"D2DE DCA,C|"Dm"DCDE F2"C7"FG|"F"ABcA "A7"GFEF|"Dm"E2"Gm"D2 "Dm"D2
%Error : Bar 7 is 3/4 not 4/4
||
V:2
%%MIDI channel 10
%%MIDI chordattack 50
[^F,,E,,]/2[^F,,E,,]/2[D,,^F,,]/2[D,,^F,,]/2 ^F,,F,, z4|^F,,E,,E,,^F,,z4|\
[^F,,E,,]/2[^F,,E,,]/2[D,,^F,,]/2[D,,^F,,]/2 ^F,,F,, z4|D,,D,,D,,^F,,z4|
[^F,,E,,]/2[^F,,E,,]/2[D,,^F,,]/2[D,,^F,,]/2 ^F,,F,, z4|^F,,D,,D,,^F,,z4|\
[^F,,E,,]/2[^F,,E,,]/2[D,,^F,,]/2[D,,^F,,]/2 ^F,,E,, z4|E,,^F,,B,,,4
%Error : Bar 15 is 3/4 not 4/4
|

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,389 @@
Header format=0 ntrks=1 division=480
Track start
Time=0 Meta Text, type=0x01 (Text Event) leng=10
Text = <note track>
Time=0 Tempo, microseconds-per-MIDI-quarter-note=472440
Time=0 Key signature, sharp/flats=1 minor=0
Time=0 Time signature=4/4 MIDI-clocks/click=48 32nd-notes/24-MIDI-clocks=8
Time=0 Meta Text, type=0x03 (Sequence/Track Name) leng=13
Text = <Horses Branle>
Time=1 Note on, chan=1 pitch=67 vol=105
Time=360 Note off, chan=1 pitch=67 vol=0
Time=361 Note on, chan=1 pitch=69 vol=80
Time=480 Note off, chan=1 pitch=69 vol=0
Time=481 Note on, chan=1 pitch=71 vol=80
Time=720 Note off, chan=1 pitch=71 vol=0
Time=721 Note on, chan=1 pitch=71 vol=80
Time=960 Note off, chan=1 pitch=71 vol=0
Time=961 Note on, chan=1 pitch=72 vol=95
Time=1200 Note off, chan=1 pitch=72 vol=0
Time=1201 Note on, chan=1 pitch=71 vol=80
Time=1440 Note off, chan=1 pitch=71 vol=0
Time=1441 Note on, chan=1 pitch=69 vol=80
Time=1680 Note off, chan=1 pitch=69 vol=0
Time=1681 Note on, chan=1 pitch=72 vol=80
Time=1920 Note off, chan=1 pitch=72 vol=0
Time=1921 Note on, chan=1 pitch=71 vol=105
Time=2160 Note off, chan=1 pitch=71 vol=0
Time=2161 Note on, chan=1 pitch=69 vol=80
Time=2400 Note off, chan=1 pitch=69 vol=0
Time=2401 Note on, chan=1 pitch=67 vol=80
Time=2640 Note off, chan=1 pitch=67 vol=0
Time=2641 Note on, chan=1 pitch=66 vol=80
Time=2880 Note off, chan=1 pitch=66 vol=0
Time=2881 Note on, chan=1 pitch=64 vol=95
Time=3360 Note off, chan=1 pitch=64 vol=0
Time=3361 Note on, chan=1 pitch=62 vol=80
Time=3840 Note off, chan=1 pitch=62 vol=0
Time=3841 Note on, chan=1 pitch=67 vol=105
Time=4200 Note off, chan=1 pitch=67 vol=0
Time=4201 Note on, chan=1 pitch=69 vol=80
Time=4320 Note off, chan=1 pitch=69 vol=0
Time=4321 Note on, chan=1 pitch=71 vol=80
Time=4560 Note off, chan=1 pitch=71 vol=0
Time=4561 Note on, chan=1 pitch=71 vol=80
Time=4800 Note off, chan=1 pitch=71 vol=0
Time=4801 Note on, chan=1 pitch=72 vol=95
Time=5040 Note off, chan=1 pitch=72 vol=0
Time=5041 Note on, chan=1 pitch=71 vol=80
Time=5280 Note off, chan=1 pitch=71 vol=0
Time=5281 Note on, chan=1 pitch=69 vol=80
Time=5520 Note off, chan=1 pitch=69 vol=0
Time=5521 Note on, chan=1 pitch=72 vol=80
Time=5760 Note off, chan=1 pitch=72 vol=0
Time=5761 Note on, chan=1 pitch=71 vol=105
Time=6000 Note off, chan=1 pitch=71 vol=0
Time=6001 Note on, chan=1 pitch=67 vol=80
Time=6240 Note off, chan=1 pitch=67 vol=0
Time=6241 Note on, chan=1 pitch=69 vol=80
Time=6480 Note off, chan=1 pitch=69 vol=0
Time=6481 Note on, chan=1 pitch=66 vol=80
Time=6720 Note off, chan=1 pitch=66 vol=0
Time=6721 Note on, chan=1 pitch=67 vol=95
Time=7200 Note off, chan=1 pitch=67 vol=0
Time=7201 Note on, chan=1 pitch=67 vol=80
Time=7680 Note off, chan=1 pitch=67 vol=0
Time=7681 Note on, chan=1 pitch=67 vol=105
Time=8040 Note off, chan=1 pitch=67 vol=0
Time=8041 Note on, chan=1 pitch=69 vol=80
Time=8160 Note off, chan=1 pitch=69 vol=0
Time=8161 Note on, chan=1 pitch=71 vol=80
Time=8400 Note off, chan=1 pitch=71 vol=0
Time=8401 Note on, chan=1 pitch=71 vol=80
Time=8640 Note off, chan=1 pitch=71 vol=0
Time=8641 Note on, chan=1 pitch=72 vol=95
Time=8880 Note off, chan=1 pitch=72 vol=0
Time=8881 Note on, chan=1 pitch=71 vol=80
Time=9120 Note off, chan=1 pitch=71 vol=0
Time=9121 Note on, chan=1 pitch=69 vol=80
Time=9360 Note off, chan=1 pitch=69 vol=0
Time=9361 Note on, chan=1 pitch=72 vol=80
Time=9600 Note off, chan=1 pitch=72 vol=0
Time=9601 Note on, chan=1 pitch=71 vol=105
Time=9840 Note off, chan=1 pitch=71 vol=0
Time=9841 Note on, chan=1 pitch=69 vol=80
Time=10080 Note off, chan=1 pitch=69 vol=0
Time=10081 Note on, chan=1 pitch=67 vol=80
Time=10320 Note off, chan=1 pitch=67 vol=0
Time=10321 Note on, chan=1 pitch=66 vol=80
Time=10560 Note off, chan=1 pitch=66 vol=0
Time=10561 Note on, chan=1 pitch=64 vol=95
Time=11040 Note off, chan=1 pitch=64 vol=0
Time=11041 Note on, chan=1 pitch=62 vol=80
Time=11520 Note off, chan=1 pitch=62 vol=0
Time=11521 Note on, chan=1 pitch=67 vol=105
Time=11880 Note off, chan=1 pitch=67 vol=0
Time=11881 Note on, chan=1 pitch=69 vol=80
Time=12000 Note off, chan=1 pitch=69 vol=0
Time=12001 Note on, chan=1 pitch=71 vol=80
Time=12240 Note off, chan=1 pitch=71 vol=0
Time=12241 Note on, chan=1 pitch=71 vol=80
Time=12480 Note off, chan=1 pitch=71 vol=0
Time=12481 Note on, chan=1 pitch=72 vol=95
Time=12720 Note off, chan=1 pitch=72 vol=0
Time=12721 Note on, chan=1 pitch=71 vol=80
Time=12960 Note off, chan=1 pitch=71 vol=0
Time=12961 Note on, chan=1 pitch=69 vol=80
Time=13200 Note off, chan=1 pitch=69 vol=0
Time=13201 Note on, chan=1 pitch=72 vol=80
Time=13440 Note off, chan=1 pitch=72 vol=0
Time=13441 Note on, chan=1 pitch=71 vol=105
Time=13680 Note off, chan=1 pitch=71 vol=0
Time=13681 Note on, chan=1 pitch=67 vol=80
Time=13920 Note off, chan=1 pitch=67 vol=0
Time=13921 Note on, chan=1 pitch=69 vol=80
Time=14160 Note off, chan=1 pitch=69 vol=0
Time=14161 Note on, chan=1 pitch=66 vol=80
Time=14400 Note off, chan=1 pitch=66 vol=0
Time=14401 Note on, chan=1 pitch=67 vol=95
Time=14880 Note off, chan=1 pitch=67 vol=0
Time=14881 Note on, chan=1 pitch=67 vol=80
Time=15360 Note off, chan=1 pitch=67 vol=0
Time=15361 Note on, chan=1 pitch=74 vol=105
Time=15600 Note off, chan=1 pitch=74 vol=0
Time=15601 Note on, chan=1 pitch=72 vol=80
Time=15720 Note off, chan=1 pitch=72 vol=0
Time=15721 Note on, chan=1 pitch=71 vol=80
Time=15840 Note off, chan=1 pitch=71 vol=0
Time=15841 Note on, chan=1 pitch=69 vol=80
Time=16080 Note off, chan=1 pitch=69 vol=0
Time=16081 Note on, chan=1 pitch=71 vol=80
Time=16320 Note off, chan=1 pitch=71 vol=0
Time=16321 Note on, chan=1 pitch=72 vol=95
Time=16560 Note off, chan=1 pitch=72 vol=0
Time=16561 Note on, chan=1 pitch=71 vol=80
Time=16680 Note off, chan=1 pitch=71 vol=0
Time=16681 Note on, chan=1 pitch=69 vol=80
Time=16800 Note off, chan=1 pitch=69 vol=0
Time=16801 Note on, chan=1 pitch=67 vol=80
Time=17040 Note off, chan=1 pitch=67 vol=0
Time=17041 Note on, chan=1 pitch=71 vol=80
Time=17280 Note off, chan=1 pitch=71 vol=0
Time=17281 Note on, chan=1 pitch=69 vol=105
Time=17520 Note off, chan=1 pitch=69 vol=0
Time=17521 Note on, chan=1 pitch=67 vol=80
Time=17760 Note off, chan=1 pitch=67 vol=0
Time=17761 Note on, chan=1 pitch=66 vol=80
Time=18000 Note off, chan=1 pitch=66 vol=0
Time=18001 Note on, chan=1 pitch=67 vol=80
Time=18240 Note off, chan=1 pitch=67 vol=0
Time=18241 Note on, chan=1 pitch=69 vol=95
Time=18600 Note off, chan=1 pitch=69 vol=0
Time=18601 Note on, chan=1 pitch=71 vol=80
Time=18720 Note off, chan=1 pitch=71 vol=0
Time=18721 Note on, chan=1 pitch=69 vol=80
Time=19200 Note off, chan=1 pitch=69 vol=0
Time=19201 Note on, chan=1 pitch=74 vol=105
Time=19440 Note off, chan=1 pitch=74 vol=0
Time=19441 Note on, chan=1 pitch=72 vol=80
Time=19560 Note off, chan=1 pitch=72 vol=0
Time=19561 Note on, chan=1 pitch=71 vol=80
Time=19680 Note off, chan=1 pitch=71 vol=0
Time=19681 Note on, chan=1 pitch=69 vol=80
Time=19920 Note off, chan=1 pitch=69 vol=0
Time=19921 Note on, chan=1 pitch=71 vol=80
Time=20160 Note off, chan=1 pitch=71 vol=0
Time=20161 Note on, chan=1 pitch=72 vol=95
Time=20400 Note off, chan=1 pitch=72 vol=0
Time=20401 Note on, chan=1 pitch=71 vol=80
Time=20520 Note off, chan=1 pitch=71 vol=0
Time=20521 Note on, chan=1 pitch=69 vol=80
Time=20640 Note off, chan=1 pitch=69 vol=0
Time=20641 Note on, chan=1 pitch=67 vol=80
Time=20880 Note off, chan=1 pitch=67 vol=0
Time=20881 Note on, chan=1 pitch=71 vol=80
Time=21120 Note off, chan=1 pitch=71 vol=0
Time=21121 Note on, chan=1 pitch=69 vol=105
Time=21360 Note off, chan=1 pitch=69 vol=0
Time=21361 Note on, chan=1 pitch=67 vol=80
Time=21600 Note off, chan=1 pitch=67 vol=0
Time=21601 Note on, chan=1 pitch=67 vol=80
Time=21840 Note off, chan=1 pitch=67 vol=0
Time=21841 Note on, chan=1 pitch=66 vol=80
Time=22080 Note off, chan=1 pitch=66 vol=0
Time=22081 Note on, chan=1 pitch=67 vol=95
Time=22560 Note off, chan=1 pitch=67 vol=0
Time=22561 Note on, chan=1 pitch=67 vol=80
Time=23040 Note off, chan=1 pitch=67 vol=0
Time=23041 Note on, chan=1 pitch=74 vol=105
Time=23280 Note off, chan=1 pitch=74 vol=0
Time=23281 Note on, chan=1 pitch=72 vol=80
Time=23400 Note off, chan=1 pitch=72 vol=0
Time=23401 Note on, chan=1 pitch=71 vol=80
Time=23520 Note off, chan=1 pitch=71 vol=0
Time=23521 Note on, chan=1 pitch=69 vol=80
Time=23760 Note off, chan=1 pitch=69 vol=0
Time=23761 Note on, chan=1 pitch=71 vol=80
Time=24000 Note off, chan=1 pitch=71 vol=0
Time=24001 Note on, chan=1 pitch=72 vol=95
Time=24240 Note off, chan=1 pitch=72 vol=0
Time=24241 Note on, chan=1 pitch=71 vol=80
Time=24360 Note off, chan=1 pitch=71 vol=0
Time=24361 Note on, chan=1 pitch=69 vol=80
Time=24480 Note off, chan=1 pitch=69 vol=0
Time=24481 Note on, chan=1 pitch=67 vol=80
Time=24720 Note off, chan=1 pitch=67 vol=0
Time=24721 Note on, chan=1 pitch=71 vol=80
Time=24960 Note off, chan=1 pitch=71 vol=0
Time=24961 Note on, chan=1 pitch=69 vol=105
Time=25200 Note off, chan=1 pitch=69 vol=0
Time=25201 Note on, chan=1 pitch=67 vol=80
Time=25440 Note off, chan=1 pitch=67 vol=0
Time=25441 Note on, chan=1 pitch=66 vol=80
Time=25680 Note off, chan=1 pitch=66 vol=0
Time=25681 Note on, chan=1 pitch=67 vol=80
Time=25920 Note off, chan=1 pitch=67 vol=0
Time=25921 Note on, chan=1 pitch=69 vol=95
Time=26280 Note off, chan=1 pitch=69 vol=0
Time=26281 Note on, chan=1 pitch=71 vol=80
Time=26400 Note off, chan=1 pitch=71 vol=0
Time=26401 Note on, chan=1 pitch=69 vol=80
Time=26880 Note off, chan=1 pitch=69 vol=0
Time=26881 Note on, chan=1 pitch=74 vol=105
Time=27120 Note off, chan=1 pitch=74 vol=0
Time=27121 Note on, chan=1 pitch=72 vol=80
Time=27240 Note off, chan=1 pitch=72 vol=0
Time=27241 Note on, chan=1 pitch=71 vol=80
Time=27360 Note off, chan=1 pitch=71 vol=0
Time=27361 Note on, chan=1 pitch=69 vol=80
Time=27600 Note off, chan=1 pitch=69 vol=0
Time=27601 Note on, chan=1 pitch=71 vol=80
Time=27840 Note off, chan=1 pitch=71 vol=0
Time=27841 Note on, chan=1 pitch=72 vol=95
Time=28080 Note off, chan=1 pitch=72 vol=0
Time=28081 Note on, chan=1 pitch=71 vol=80
Time=28200 Note off, chan=1 pitch=71 vol=0
Time=28201 Note on, chan=1 pitch=69 vol=80
Time=28320 Note off, chan=1 pitch=69 vol=0
Time=28321 Note on, chan=1 pitch=67 vol=80
Time=28560 Note off, chan=1 pitch=67 vol=0
Time=28561 Note on, chan=1 pitch=71 vol=80
Time=28800 Note off, chan=1 pitch=71 vol=0
Time=28801 Note on, chan=1 pitch=69 vol=105
Time=29040 Note off, chan=1 pitch=69 vol=0
Time=29041 Note on, chan=1 pitch=67 vol=80
Time=29280 Note off, chan=1 pitch=67 vol=0
Time=29281 Note on, chan=1 pitch=67 vol=80
Time=29520 Note off, chan=1 pitch=67 vol=0
Time=29521 Note on, chan=1 pitch=66 vol=80
Time=29760 Note off, chan=1 pitch=66 vol=0
Time=29761 Note on, chan=1 pitch=67 vol=95
Time=30240 Note off, chan=1 pitch=67 vol=0
Time=30241 Note on, chan=1 pitch=67 vol=80
Time=30720 Note off, chan=1 pitch=67 vol=0
Time=30720 Key signature, sharp/flats=-1 minor=0
Time=30721 Note on, chan=1 pitch=70 vol=105
Time=30840 Note off, chan=1 pitch=70 vol=0
Time=30841 Note on, chan=1 pitch=69 vol=80
Time=30960 Note off, chan=1 pitch=69 vol=0
Time=30961 Note on, chan=1 pitch=67 vol=80
Time=31200 Note off, chan=1 pitch=67 vol=0
Time=31201 Note on, chan=1 pitch=70 vol=80
Time=31320 Note off, chan=1 pitch=70 vol=0
Time=31321 Note on, chan=1 pitch=69 vol=80
Time=31440 Note off, chan=1 pitch=69 vol=0
Time=31441 Note on, chan=1 pitch=67 vol=80
Time=31680 Note off, chan=1 pitch=67 vol=0
Time=31681 Note on, chan=1 pitch=65 vol=95
Time=31920 Note off, chan=1 pitch=65 vol=0
Time=31921 Note on, chan=1 pitch=67 vol=80
Time=32160 Note off, chan=1 pitch=67 vol=0
Time=32161 Note on, chan=1 pitch=69 vol=80
Time=32640 Note off, chan=1 pitch=69 vol=0
Time=32641 Note on, chan=1 pitch=62 vol=105
Time=32880 Note off, chan=1 pitch=62 vol=0
Time=32881 Note on, chan=1 pitch=64 vol=80
Time=33120 Note off, chan=1 pitch=64 vol=0
Time=33121 Note on, chan=1 pitch=65 vol=80
Time=33360 Note off, chan=1 pitch=65 vol=0
Time=33361 Note on, chan=1 pitch=67 vol=80
Time=33600 Note off, chan=1 pitch=67 vol=0
Time=33601 Note on, chan=1 pitch=69 vol=95
Time=33840 Note off, chan=1 pitch=69 vol=0
Time=33841 Note on, chan=1 pitch=70 vol=80
Time=34080 Note off, chan=1 pitch=70 vol=0
Time=34081 Note on, chan=1 pitch=69 vol=80
Time=34320 Note off, chan=1 pitch=69 vol=0
Time=34321 Note on, chan=1 pitch=67 vol=80
Time=34560 Note off, chan=1 pitch=67 vol=0
Time=34561 Note on, chan=1 pitch=70 vol=105
Time=34680 Note off, chan=1 pitch=70 vol=0
Time=34681 Note on, chan=1 pitch=69 vol=80
Time=34800 Note off, chan=1 pitch=69 vol=0
Time=34801 Note on, chan=1 pitch=67 vol=80
Time=35040 Note off, chan=1 pitch=67 vol=0
Time=35041 Note on, chan=1 pitch=70 vol=80
Time=35160 Note off, chan=1 pitch=70 vol=0
Time=35161 Note on, chan=1 pitch=69 vol=80
Time=35280 Note off, chan=1 pitch=69 vol=0
Time=35281 Note on, chan=1 pitch=67 vol=80
Time=35520 Note off, chan=1 pitch=67 vol=0
Time=35521 Note on, chan=1 pitch=65 vol=95
Time=35760 Note off, chan=1 pitch=65 vol=0
Time=35761 Note on, chan=1 pitch=67 vol=80
Time=36000 Note off, chan=1 pitch=67 vol=0
Time=36001 Note on, chan=1 pitch=69 vol=80
Time=36480 Note off, chan=1 pitch=69 vol=0
Time=36481 Note on, chan=1 pitch=62 vol=105
Time=36720 Note off, chan=1 pitch=62 vol=0
Time=36721 Note on, chan=1 pitch=64 vol=80
Time=36960 Note off, chan=1 pitch=64 vol=0
Time=36961 Note on, chan=1 pitch=65 vol=80
Time=37200 Note off, chan=1 pitch=65 vol=0
Time=37201 Note on, chan=1 pitch=67 vol=80
Time=37440 Note off, chan=1 pitch=67 vol=0
Time=37441 Note on, chan=1 pitch=67 vol=95
Time=37680 Note off, chan=1 pitch=67 vol=0
Time=37681 Note on, chan=1 pitch=65 vol=80
Time=37920 Note off, chan=1 pitch=65 vol=0
Time=37921 Note on, chan=1 pitch=67 vol=80
Time=38400 Note off, chan=1 pitch=67 vol=0
Time=38400 Key signature, sharp/flats=-1 minor=0
Time=38401 Note on, chan=1 pitch=70 vol=105
Time=38520 Note off, chan=1 pitch=70 vol=0
Time=38521 Note on, chan=1 pitch=69 vol=80
Time=38640 Note off, chan=1 pitch=69 vol=0
Time=38641 Note on, chan=1 pitch=67 vol=80
Time=38880 Note off, chan=1 pitch=67 vol=0
Time=38881 Note on, chan=1 pitch=70 vol=80
Time=39000 Note off, chan=1 pitch=70 vol=0
Time=39001 Note on, chan=1 pitch=69 vol=80
Time=39120 Note off, chan=1 pitch=69 vol=0
Time=39121 Note on, chan=1 pitch=67 vol=80
Time=39360 Note off, chan=1 pitch=67 vol=0
Time=39361 Note on, chan=1 pitch=65 vol=95
Time=39600 Note off, chan=1 pitch=65 vol=0
Time=39601 Note on, chan=1 pitch=67 vol=80
Time=39840 Note off, chan=1 pitch=67 vol=0
Time=39841 Note on, chan=1 pitch=69 vol=80
Time=40320 Note off, chan=1 pitch=69 vol=0
Time=40321 Note on, chan=1 pitch=62 vol=105
Time=40560 Note off, chan=1 pitch=62 vol=0
Time=40561 Note on, chan=1 pitch=64 vol=80
Time=40800 Note off, chan=1 pitch=64 vol=0
Time=40801 Note on, chan=1 pitch=65 vol=80
Time=41040 Note off, chan=1 pitch=65 vol=0
Time=41041 Note on, chan=1 pitch=67 vol=80
Time=41280 Note off, chan=1 pitch=67 vol=0
Time=41281 Note on, chan=1 pitch=69 vol=95
Time=41520 Note off, chan=1 pitch=69 vol=0
Time=41521 Note on, chan=1 pitch=70 vol=80
Time=41760 Note off, chan=1 pitch=70 vol=0
Time=41761 Note on, chan=1 pitch=69 vol=80
Time=42000 Note off, chan=1 pitch=69 vol=0
Time=42001 Note on, chan=1 pitch=67 vol=80
Time=42240 Note off, chan=1 pitch=67 vol=0
Time=42241 Note on, chan=1 pitch=70 vol=105
Time=42360 Note off, chan=1 pitch=70 vol=0
Time=42361 Note on, chan=1 pitch=69 vol=80
Time=42480 Note off, chan=1 pitch=69 vol=0
Time=42481 Note on, chan=1 pitch=67 vol=80
Time=42720 Note off, chan=1 pitch=67 vol=0
Time=42721 Note on, chan=1 pitch=70 vol=80
Time=42840 Note off, chan=1 pitch=70 vol=0
Time=42841 Note on, chan=1 pitch=69 vol=80
Time=42960 Note off, chan=1 pitch=69 vol=0
Time=42961 Note on, chan=1 pitch=67 vol=80
Time=43200 Note off, chan=1 pitch=67 vol=0
Time=43201 Note on, chan=1 pitch=65 vol=95
Time=43440 Note off, chan=1 pitch=65 vol=0
Time=43441 Note on, chan=1 pitch=67 vol=80
Time=43680 Note off, chan=1 pitch=67 vol=0
Time=43681 Note on, chan=1 pitch=69 vol=80
Time=44160 Note off, chan=1 pitch=69 vol=0
Time=44161 Note on, chan=1 pitch=62 vol=105
Time=44400 Note off, chan=1 pitch=62 vol=0
Time=44401 Note on, chan=1 pitch=64 vol=80
Time=44640 Note off, chan=1 pitch=64 vol=0
Time=44641 Note on, chan=1 pitch=65 vol=80
Time=44880 Note off, chan=1 pitch=65 vol=0
Time=44881 Note on, chan=1 pitch=67 vol=80
Time=45120 Note off, chan=1 pitch=67 vol=0
Time=45121 Note on, chan=1 pitch=67 vol=95
Time=45360 Note off, chan=1 pitch=67 vol=0
Time=45361 Note on, chan=1 pitch=65 vol=80
Time=45600 Note off, chan=1 pitch=65 vol=0
Time=45601 Note on, chan=1 pitch=67 vol=80
Time=46080 Note off, chan=1 pitch=67 vol=0
Time=46106 Meta event, end of track
Track end

View File

@@ -0,0 +1,15 @@
pitch_histogram
43 51
45 42
64 9
66 1
68 7
69 19
71 16
72 12
74 7
76 9
77 1
79 2
80 1
81 1

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,148 @@
calling midi2abc
X: 1
T: from midi2abc_coleraine.mid
M: 6/8
L: 1/8
Q:1/4=142
K:C % 0 sharps
V:1
%%MIDI program 26
%%MIDI program 72
EE>A AAB| \
cB>e ee2| \
dc>A AAB| \
cB^G EE2|
EE>A AAB| \
cB>e ee2| \
dc>B AB^G| \
EA4-A|
EE>A AAB| \
cB>e ee2| \
dc>A AAB| \
cB^G EE2|
EE>A AAB| \
cB>e ee2| \
dc>B AB^G| \
EA4-A|
Bc2 ccd| \
cBd gg2| \
^ga>e dcB| \
A^GB GE^F|
^GAG ABA| \
Bcd efe| \
dc>B AB^G| \
EA4-A|
Bc2 ccd| \
cBd gg2| \
^ga>e dcB| \
A^GB GE^F|
^GAG ABA| \
Bcd efe| \
dc>B AB^G| \
EA4-A|
V:2
%%MIDI program 3
%%MIDI program 3
E,,A,,z [ECA,]A,,z| \
[ECA,]E,,z [DB,^G,E,]E,,z| \
[DB,^G,E,]A,,z [ECA,]A,,z| \
[ECA,]E,,z [DB,^G,E,]E,,z|
[DB,^G,E,]A,,z [ECA,]A,,z| \
[ECA,]E,,z [DB,^G,E,]E,,z| \
[DB,^G,E,]A,,z [ECA,]E,,z| \
[DB,^G,E,]A,,z [ECA,]A,,z|
[DB,^G,E,]A,,z [ECA,]A,,z| \
[ECA,]E,,z [DB,^G,E,]E,,z| \
[DB,^G,E,]A,,z [ECA,]A,,z| \
[ECA,]E,,z [DB,^G,E,]E,,z|
[DB,^G,E,]A,,z [ECA,]A,,z| \
[ECA,]E,,z [DB,^G,E,]E,,z| \
[DB,^G,E,]A,,z [ECA,]E,,z| \
[DB,^G,E,]A,,z [ECA,]A,,z|
[FDB,G,]C,,z [G,E,C,]C,,z| \
[G,E,C,]G,,z [DB,G,]E,,z| \
[B,^G,E,]A,,z [ECA,]A,,z| \
[ECA,]E,,z [DB,^G,E,]E,,z|
[DB,^G,E,]A,,z [ECA,]E,,z| \
[DB,^G,E,]A,,z [ECA,]D,,z| \
[A,F,D,]A,,z [ECA,]E,,z| \
[DB,^G,E,]A,,z [ECA,]A,,z|
[FDB,G,]C,,z [G,E,C,]C,,z| \
[G,E,C,]G,,z [DB,G,]E,,z| \
[B,^G,E,]A,,z [ECA,]A,,z| \
[ECA,]E,,z [DB,^G,E,]E,,z|
[DB,^G,E,]A,,z [ECA,]E,,z| \
[DB,^G,E,]A,,z [ECA,]D,,z| \
[A,F,D,]A,,z [ECA,]E,,z| \
[DB,^G,E,]A,,z [ECA,]A,,
V:3
%%MIDI channel 10
%%clef bass
FFz ^F/2F/2D,F| \
^F=Fz ^F/2F/2D,F| \
^F=Fz ^F/2F/2D,F| \
^F=Fz ^F/2F/2D,F|
^F=Fz ^F/2F/2D,F| \
^F=Fz ^F/2F/2D,F| \
^F=Fz ^F/2F/2D,F| \
^F=Fz ^F/2F/2D,F|
^F=Fz ^F/2F/2D,F| \
^F=Fz ^F/2F/2D,F| \
^F=Fz ^F/2F/2D,F| \
^F=Fz ^F/2F/2D,F|
^F=Fz ^F/2F/2D,F| \
^F=Fz ^F/2F/2D,F| \
^F=Fz ^F/2F/2D,F| \
^F=Fz ^F/2F/2D,F|
^F=Fz ^F/2F/2D,F| \
^F=Fz ^F/2F/2D,F| \
^F=Fz ^F/2F/2D,F| \
^F=Fz ^F/2F/2D,F|
^F=Fz ^F/2F/2D,F| \
^F=Fz ^F/2F/2D,F| \
^F=Fz ^F/2F/2D,F| \
^F=Fz ^F/2F/2D,F|
^F=Fz ^F/2F/2D,F| \
^F=Fz ^F/2F/2D,F| \
^F=Fz ^F/2F/2D,F| \
^F=Fz ^F/2F/2D,F|
^F=Fz ^F/2F/2D,F| \
^F=Fz ^F/2F/2D,F| \
^F=Fz ^F/2F/2D,F| \
^F=Fz ^F/2F/2D,F|
V:4
%%MIDI channel 10
zG,,3/2A,,/2 G,,A,,/2G,,/2A,,| \
A,,G,,3/2A,,/2 G,,A,,G,,/2A,,/2| \
G,,G,,3/2A,,/2 G,,A,,/2G,,/2A,,| \
A,,G,,3/2A,,/2 G,,A,,G,,/2A,,/2|
G,,G,,3/2A,,/2 G,,A,,/2G,,/2A,,| \
A,,G,,3/2A,,/2 G,,A,,G,,/2A,,/2| \
G,,G,,3/2A,,/2 G,,A,,/2G,,/2A,,| \
A,,G,,3/2A,,/2 G,,A,,G,,/2A,,/2|
zG,,3/2A,,/2 G,,A,,/2G,,/2A,,| \
A,,G,,3/2A,,/2 G,,A,,G,,/2A,,/2| \
G,,G,,3/2A,,/2 G,,A,,/2G,,/2A,,| \
A,,G,,3/2A,,/2 G,,A,,G,,/2A,,/2|
G,,G,,3/2A,,/2 G,,A,,/2G,,/2A,,| \
A,,G,,3/2A,,/2 G,,A,,G,,/2A,,/2| \
G,,G,,3/2A,,/2 G,,A,,/2G,,/2A,,| \
A,,G,,3/2A,,/2 G,,A,,G,,/2A,,/2|
z
K:F# % 6 sharps
=G,,3/2=A,,/2 G,,A,,/2G,,/2A,,| \
=A,,=G,,3/2A,,/2 G,,A,,G,,/2A,,/2| \
=G,,G,,3/2=A,,/2 G,,A,,/2G,,/2A,,| \
=A,,=G,,3/2A,,/2 G,,A,,G,,/2A,,/2|
=G,,G,,G,, G,,z2| \
z=G,,G,, G,,z2| \
z=G,,G,, G,,z2| \
z=G,,3z2|
z=G,,3/2=A,,/2 G,,A,,/2G,,/2A,,| \
=A,,=G,,3/2A,,/2 G,,A,,G,,/2A,,/2| \
=G,,G,,3/2=A,,/2 G,,A,,/2G,,/2A,,| \
=A,,=G,,3/2A,,/2 G,,A,,G,,/2A,,/2|
=G,,G,,G,, G,,z2| \
z=G,,G,, G,,z2| \
z=G,,G,, G,,z2| \
z=G,,3

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,56 @@
ntrks 5
ppqn 480
trk 1
tempo 142.00 bpm
keysig Amin 0 1 0.00
timesig 6/8 0.00
metatext 3 Coleraine
trk 2
program 1 26
metatext 3 Coleraine
cprogram 1 72 0
trkinfo 1 26 165 1 11778 45914 0 2 0 26 8 64 81 159 1199 0 5.665032 16 45 25 95 8
trk 3
program 3 3
program 2 3
trkinfo 2 3 64 1 2746 15535 0 0 0 266 4 36 45 239 239 0 3.010735 22 2 38 65 0
trkinfo 3 3 63 151 12443 51146 0 0 0 506 4 48 65 239 239 0 5.702527 18 33 10 64 0
trk 4
trkinfo 10 0 191 1 -1 0 0 0 0 26 0 -1 0
trk 5
timesig 6/8 0.00
trkinfo 10 0 186 0 -1 0 0 0 0 506 0 -1 0
npulses 46106
tempocmds 1
pitchbends 0
programcmd 1
ntimesig 2
progs 3 26
progsact 66681 45914
progcolor 1.45 0.00 0.00 0.00 1.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
drums 43 45 50 65 66
drumhits 102 84 32 33 127
pitches 60 0 45 0 118 6 2 14 41 98 0 61
key Amin 0 0.609575
rmaj 0.305 -0.394 0.316 -0.360 0.354 0.157 -0.476 0.264 -0.368 0.530 -0.225 -0.105
rmin -0.201 0.058 0.322 -0.480 0.522 -0.315 0.071 -0.111 -0.152 0.610 -0.469 0.144
pitchact 0.33 0.00 0.23 0.00 0.64 0.03 0.01 0.08 0.21 0.58 0.00 0.32
chanvol 115 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
chnact 0.996 0.337 1.109 0.000 0.000 0.000 0.000 0.000 0.000 1.689 0.000 0.000 0.000 0.000 0.000 0.000
trkact 0 0 166 279 192 186
pitchperplexity 6.420275
pitchentropy 2.682635
totalrhythmpatterns =16
collisions = 0
clean_quantization
programs: 26 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0
cnotes: 332 130 428 0 0 0 0 0 0 756 0 0 0 0 0 0
nnotes: 87 63 63 0 0 0 0 0 0 0 0 0 0 0 0 0
nzeros: 16 22 18 0 0 0 0 0 0 0 0 0 0 0 0 0
nsteps: 45 2 33 0 0 0 0 0 0 0 0 0 0 0 0 0
njumps: 25 38 10 0 0 0 0 0 0 0 0 0 0 0 0 0
rpats: 8 4 4 0 0 0 0 0 0 0 0 0 0 0 0 0
pavg: 70 41 53 0 0 0 0 0 0 0 0 0 0 0 0 0
spread: 99 99 98 0 0 0 0 0 0 98 0 0 0 0 0 0

File diff suppressed because it is too large Load Diff

177
tests/run_test.cmake Normal file
View File

@@ -0,0 +1,177 @@
# Generic test runner for abcmidi golden-file tests.
#
# Required variables (passed via -D on the cmake command line):
# TYPE - one of: abc2midi, abc2abc, midi2abc, midistats, mftext,
# yaps, midicopy, abcmatch
# SAMPLE - path to the input ABC sample file
# GOLDEN - path to the golden reference file
# TMPDIR - working directory for temporary outputs
#
# ABC2MIDI, ABC2ABC, MIDI2ABC, MIDISTATS, MFTEXT, YAPS, MIDICOPY, ABCMATCH
# - absolute paths to the binaries (only those needed for TYPE)
#
# Behaviour:
# - Runs the requested binary (and any pipeline steps required to make the
# output diffable, e.g. mftext for binary MIDI output).
# - Strips non-deterministic lines (version banners, dates) from the output.
# - If the environment variable ABCMIDI_UPDATE_GOLDEN is set, the filtered
# output is written to GOLDEN (used to regenerate references after an
# intentional behavioural change).
# - Otherwise, the filtered output is compared with GOLDEN; on mismatch, a
# unified diff is printed and the test fails.
cmake_minimum_required(VERSION 3.14)
if(NOT TYPE OR NOT SAMPLE OR NOT GOLDEN OR NOT TMPDIR)
message(FATAL_ERROR "run_test.cmake: TYPE, SAMPLE, GOLDEN, TMPDIR are required")
endif()
file(MAKE_DIRECTORY "${TMPDIR}")
get_filename_component(stem "${SAMPLE}" NAME_WE)
set(raw "${TMPDIR}/${TYPE}_${stem}.raw")
set(out "${TMPDIR}/${TYPE}_${stem}.out")
set(midfile "${TMPDIR}/${TYPE}_${stem}.mid")
# --- Command helpers ---------------------------------------------------------
# Run a command; abort with a detailed message on non-zero exit.
function(run_or_die)
execute_process(
COMMAND ${ARGN}
RESULT_VARIABLE rc
OUTPUT_VARIABLE captured_out
ERROR_VARIABLE captured_err
)
if(NOT rc EQUAL 0)
message(FATAL_ERROR
"Command failed (rc=${rc}):\n ${ARGN}\n"
"--- stdout ---\n${captured_out}\n"
"--- stderr ---\n${captured_err}")
endif()
endfunction()
# Run a command and capture its stdout into a file.
function(run_to_file outfile)
execute_process(
COMMAND ${ARGN}
OUTPUT_FILE "${outfile}"
RESULT_VARIABLE rc
ERROR_VARIABLE captured_err
)
if(NOT rc EQUAL 0)
message(FATAL_ERROR
"Command failed (rc=${rc}):\n ${ARGN}\n--- stderr ---\n${captured_err}")
endif()
endfunction()
# Convert ${SAMPLE} to MIDI, then run ${bin} on the resulting MIDI file and
# capture its stdout. Any extra arguments are inserted BEFORE the MIDI path
# (needed e.g. for "midi2abc -f <file>").
function(run_via_mid outfile bin)
run_or_die("${ABC2MIDI}" "${SAMPLE}" -o "${midfile}" -quiet -silent)
run_to_file("${outfile}" "${bin}" ${ARGN} "${midfile}")
endfunction()
# Run ${bin} directly on ${SAMPLE} and capture its stdout. Extra arguments
# are appended after the sample path.
function(run_on_sample outfile bin)
run_to_file("${outfile}" "${bin}" "${SAMPLE}" ${ARGN})
endfunction()
# --- Dispatch: populate ${raw} based on TYPE ---------------------------------
#
# The binary path is derived from TYPE via TOUPPER + double-dereference:
# for TYPE=midistats, ${bin} resolves to ${MIDISTATS}. The only exception is
# abc2midi, where we render the MIDI output through mftext for diffing — it
# is therefore an alias for the mftext test.
string(TOUPPER "${TYPE}" TYPE_UPPER)
if(TYPE STREQUAL "abc2midi")
set(bin "${MFTEXT}")
else()
set(bin "${${TYPE_UPPER}}")
endif()
if(TYPE MATCHES "^(abc2midi|mftext|midistats)$")
run_via_mid("${raw}" "${bin}")
elseif(TYPE STREQUAL "midi2abc")
run_via_mid("${raw}" "${bin}" -f)
elseif(TYPE STREQUAL "abc2abc")
run_on_sample("${raw}" "${bin}")
elseif(TYPE STREQUAL "abcmatch")
# -pitch_hist gives a short, deterministic, useful summary of the tune.
run_on_sample("${raw}" "${bin}" -pitch_hist)
elseif(TYPE STREQUAL "yaps")
set(psfile "${TMPDIR}/yaps_${stem}.ps")
run_or_die("${bin}" "${SAMPLE}" -o "${psfile}")
configure_file("${psfile}" "${raw}" COPYONLY)
elseif(TYPE STREQUAL "midicopy")
# ABC -> MIDI -> midicopy -> mftext
set(copied "${TMPDIR}/midicopy_${stem}_out.mid")
run_or_die("${ABC2MIDI}" "${SAMPLE}" -o "${midfile}" -quiet -silent)
run_or_die("${bin}" "${midfile}" "${copied}")
run_to_file("${raw}" "${MFTEXT}" "${copied}")
else()
message(FATAL_ERROR "Unknown TYPE: ${TYPE}")
endif()
# --- Normalize: strip non-deterministic lines --------------------------------
#
# Each program prints a version line as the first line of stdout. yaps
# PostScript output contains a CreationDate. Filenames embedded in output
# (e.g. yaps "%%Title: /tmp/...") are also volatile and stripped.
file(READ "${raw}" content)
# Strip program version banners (e.g. "5.02 February 16 2025 abc2midi")
string(REGEX REPLACE "[0-9]+\\.[0-9]+ +[A-Za-z]+ +[0-9]+ +[0-9]+ +[a-z2]+\n" "" content "${content}")
# Strip yaps PostScript volatile headers
string(REGEX REPLACE "%%Title:[^\n]*\n" "%%Title: <stripped>\n" content "${content}")
string(REGEX REPLACE "%%CreationDate:[^\n]*\n" "%%CreationDate: <stripped>\n" content "${content}")
# Strip absolute paths to TMPDIR (filenames embedded in some outputs)
string(REPLACE "${TMPDIR}/" "" content "${content}")
file(WRITE "${out}" "${content}")
# --- Update or compare -------------------------------------------------------
if(DEFINED ENV{ABCMIDI_UPDATE_GOLDEN})
get_filename_component(golden_dir "${GOLDEN}" DIRECTORY)
file(MAKE_DIRECTORY "${golden_dir}")
file(WRITE "${GOLDEN}" "${content}")
message(STATUS "Updated golden: ${GOLDEN}")
return()
endif()
if(NOT EXISTS "${GOLDEN}")
message(FATAL_ERROR
"Golden file does not exist: ${GOLDEN}\n"
"Run 'ABCMIDI_UPDATE_GOLDEN=1 ctest ...' to generate it.")
endif()
execute_process(
COMMAND "${CMAKE_COMMAND}" -E compare_files "${out}" "${GOLDEN}"
RESULT_VARIABLE diff_rc
OUTPUT_QUIET
ERROR_QUIET
)
if(NOT diff_rc EQUAL 0)
execute_process(
COMMAND diff -u "${GOLDEN}" "${out}"
OUTPUT_VARIABLE diff_text
)
message(FATAL_ERROR
"Output differs from golden ${GOLDEN}\n"
"To accept the new output: ABCMIDI_UPDATE_GOLDEN=1 ctest ...\n"
"${diff_text}")
endif()