From 766c9f0d98f0ba6b892a026907800e89fbd6d9b0 Mon Sep 17 00:00:00 2001 From: Brad Anderson Date: Fri, 9 Oct 2026 17:17:02 -0700 Subject: [PATCH] tests: replace copyrighted lyrics with placeholder text The align, transcribe, lyrics and notes tests quoted lines from published songs, and the UltraStar parser fixtures were complete community charts of commercial songs. Replace them with counting words and two hand-written charts that keep what the parser tests rely on: CRLF line endings, Latin-1 bytes, a decimal-comma BPM, freestyle/golden/rap notes, negative pitch and a two-number line break. --- tests/fixtures/chart_crlf.txt | 36 +++ tests/fixtures/chart_latin1.txt | 21 ++ tests/fixtures/sanctuary.txt | 472 ------------------------------ tests/fixtures/sweet_child.txt | 494 -------------------------------- tests/test_align.py | 34 +-- tests/test_lyrics.py | 14 +- tests/test_notes.py | 18 +- tests/test_transcribe.py | 24 +- tests/test_ultrastar.py | 10 +- 9 files changed, 107 insertions(+), 1016 deletions(-) create mode 100644 tests/fixtures/chart_crlf.txt create mode 100644 tests/fixtures/chart_latin1.txt delete mode 100755 tests/fixtures/sanctuary.txt delete mode 100755 tests/fixtures/sweet_child.txt diff --git a/tests/fixtures/chart_crlf.txt b/tests/fixtures/chart_crlf.txt new file mode 100644 index 0000000..731297a --- /dev/null +++ b/tests/fixtures/chart_crlf.txt @@ -0,0 +1,36 @@ +#TITLE:Placeholder Chart +#ARTIST:Test Artist +#LANGUAGE:English +#YEAR:2000 +#CREATOR:songtrace tests +#GENRE:Test +#COVER:Test Artist - Placeholder Chart [CO].jpg +#MP3:Test Artist - Placeholder Chart.mp3 +#VIDEO:Test Artist - Placeholder Chart.mp4 +#BPM:217,98 +#GAP:4880 +#MEDLEYSTARTBEAT:113 +#MEDLEYENDBEAT:240 +: 0 3 16 ah +: 5 3 20 ah +: 11 3 23 la +: 17 3 16 la +: 22 28 15 ah +: 51 2 16 doo +: 54 31 16 ~ +- 95 +F 113 3 18 la +F 117 3 21 la +F 121 3 21 la +* 125 3 21 doo +* 129 12 19 ~ +- 150 +: 155 4 12 Na +R 160 4 0 na +G 165 4 0 na +: 170 6 14 la +- 190 +: 194 3 16 La +: 198 3 18 la +* 202 10 20 ah +E diff --git a/tests/fixtures/chart_latin1.txt b/tests/fixtures/chart_latin1.txt new file mode 100644 index 0000000..19a0c03 --- /dev/null +++ b/tests/fixtures/chart_latin1.txt @@ -0,0 +1,21 @@ +#TITLE:Café Placeholder +#ARTIST:Tést Artist +#LANGUAGE:English +#GENRE:Test +#YEAR:2000 +#MP3:Tést Artist - Café Placeholder.mp3 +#CREATOR:songtrace tests +#BPM:256 +#GAP:49673 +: 0 4 2 Doo +: 6 4 4 doo +: 12 8 5 laé +- 28 30 +: 32 4 0 Na +: 38 4 -2 na +* 44 12 -9 ah +- 64 +F 70 4 3 La +: 76 6 -5 la +: 84 10 -9 ~ +E diff --git a/tests/fixtures/sanctuary.txt b/tests/fixtures/sanctuary.txt deleted file mode 100755 index b90e0c5..0000000 --- a/tests/fixtures/sanctuary.txt +++ /dev/null @@ -1,472 +0,0 @@ -#TITLE:Sanctuary -#ARTIST:Utada Hikaru -#LANGUAGE:English -#YEAR:2009 -#CREATOR:Subkei -#GENRE:J-Pop -#COVER:Utada Hikaru - Sanctuary [CO].jpg -#MP3:Utada Hikaru - Sanctuary.mp3 -#VIDEO:Utada Hikaru - Sanctuary.mp4 -#BPM:217,98 -#GAP:4880 -#MEDLEYSTARTBEAT:2471 -#MEDLEYENDBEAT:2990 -: 0 3 16 ah -: 5 3 20 ah -: 11 3 23 ah -: 17 3 16 ah -: 22 28 15 ah -: 51 2 16 ah -: 54 31 16 ~ -- 95 -F 113 3 18 wonk -F 117 3 21 uoy -F 121 3 21 naht -F 125 3 21 snoit -F 129 3 21 cef -F 133 3 18 fa -F 137 3 18 erom -F 144 2 18 deen -F 147 4 18 I -- 180 -: 425 3 16 In -: 429 3 21 you -: 433 2 20 ~ -: 436 4 16 ~ -: 441 2 18 and -: 445 4 20 I -: 451 4 18 ~ -- 459 -: 461 3 16 there's -: 465 3 16 a -: 469 5 20 new -: 475 4 23 land -: 481 4 16 ~ -: 487 27 15 ~ -: 515 4 16 ~ -: 521 17 16 ~ -: 539 1 18 ~ -: 541 3 20 ~ -- 547 -: 549 1 16 An -: 551 2 18 ~ -: 556 3 18 gels -: 560 4 18 in -: 565 7 20 flight -: 573 2 18 ~ -- 576 -F 578 2 18 wonk -F 581 3 21 uoy -F 585 3 21 naht -F 589 3 21 snoit -F 593 3 21 cef -F 597 3 18 fa -F 601 3 18 erom -F 608 2 18 deen -F 611 3 18 I -- 615 -: 617 1 16 My -: 620 1 21 sanc -: 624 2 20 tu -: 628 4 16 a -: 634 8 18 ry -- 646 -: 648 3 16 my -: 653 1 21 sanc -: 657 2 20 tu -: 661 3 16 a -: 665 4 16 ry -: 670 2 18 ~ -F 674 4 13 yeah -- 680 -: 682 2 16 Where -: 686 1 21 fears -: 689 1 20 ~ -: 691 5 16 ~ -: 697 1 18 and -* 701 4 20 lies -* 707 4 18 ~ -- 715 -: 717 3 16 melt -: 721 3 16 a -: 725 4 20 way -: 732 4 23 ~ -: 737 3 16 ~ -: 742 28 15 ~ -: 771 3 16 ~ -: 775 19 16 ~ -: 795 1 18 ~ -: 797 3 20 ~ -- 804 -: 806 1 16 Mu -: 808 2 18 ~ -: 812 3 18 sic -: 817 3 18 will -: 822 7 20 tie -: 830 2 18 ~ -- 833 -F 835 1 18 wonk -F 837 3 21 uoy -F 841 3 21 naht -F 845 3 21 snoit -F 849 3 21 cef -F 853 3 18 fa -F 857 3 18 erom -F 864 2 18 deen -F 867 3 18 I -- 871 -: 873 2 16 What's -: 877 1 21 left -: 881 1 20 of -: 884 3 16 me -: 888 1 16 ~ -: 890 7 18 ~ -- 903 -: 905 2 16 What's -: 909 1 21 left -: 913 1 20 of -: 916 3 16 me -: 921 2 16 ~ -: 925 3 18 ~ -: 933 24 13 now? -- 986 -: 1069 3 13 I -: 1074 6 16 watch -: 1082 3 16 you -: 1087 9 18 ~ -- 1102 -: 1105 3 18 fast -: 1109 3 20 ~ -* 1117 2 13 a -* 1122 5 16 sleep -: 1129 3 18 ~ -: 1133 15 16 ~ -- 1162 -: 1189 3 20 All -: 1193 6 21 ~ -: 1201 3 18 I -: 1205 6 20 ~ -: 1213 5 16 fear -: 1220 20 13 ~ -- 1246 -: 1249 2 11 means -: 1255 7 13 no -: 1266 5 18 thing -: 1273 41 20 ~ -- 1319 -: 1321 2 16 In -: 1325 2 21 you -: 1328 2 20 ~ -: 1332 3 16 ~ -: 1337 2 18 and -: 1341 4 20 I -: 1347 4 18 ~ -- 1355 -: 1357 3 16 there's -: 1361 3 16 a -* 1365 5 20 new -: 1371 4 23 land -: 1377 4 16 ~ -: 1383 27 15 ~ -: 1411 4 16 ~ -: 1417 17 16 ~ -: 1435 1 18 ~ -: 1437 3 20 ~ -- 1442 -: 1444 1 16 An -: 1446 2 18 ~ -: 1452 3 18 gels -: 1457 3 18 in -: 1462 6 20 flight -: 1469 2 18 ~ -- 1472 -F 1474 1 18 wonk -F 1476 3 21 uoy -F 1480 3 21 naht -F 1484 3 21 snoit -F 1488 3 21 cef -F 1492 3 18 fa -F 1496 3 18 erom -F 1503 2 18 deen -F 1506 3 18 I -- 1511 -: 1513 1 16 My -: 1516 1 21 sanc -: 1520 2 20 tu -: 1524 4 16 a -: 1530 8 18 ry -- 1541 -: 1543 3 16 my -: 1548 1 21 sanc -: 1552 2 20 tu -: 1556 3 16 a -: 1560 4 16 ry -: 1565 2 18 ~ -F 1570 3 13 yeah -- 1575 -: 1577 2 16 Where -* 1581 1 21 fears -* 1584 1 20 ~ -: 1586 5 16 ~ -: 1592 1 18 and -: 1596 4 20 lies -: 1602 4 18 ~ -- 1611 -: 1613 3 16 melt -: 1617 3 16 a -: 1621 4 20 way -: 1628 4 23 ~ -: 1633 3 16 ~ -: 1638 27 15 ~ -: 1666 4 16 ~ -: 1672 18 16 ~ -: 1691 1 18 ~ -: 1693 3 20 ~ -- 1699 -: 1701 1 16 Mu -: 1703 2 18 ~ -: 1707 3 18 sic -: 1712 3 18 will -: 1717 7 20 tie -: 1725 2 18 ~ -- 1728 -F 1730 2 18 wonk -F 1733 3 21 uoy -F 1737 3 21 naht -F 1741 3 21 snoit -F 1745 3 21 cef -F 1749 3 18 fa -F 1753 3 18 erom -F 1760 2 18 deen -F 1763 3 18 I -- 1767 -: 1769 2 16 What's -: 1773 1 21 left -: 1777 1 20 of -: 1780 3 16 me -: 1785 1 16 ~ -: 1787 7 18 ~ -- 1798 -: 1800 2 16 What's -: 1804 1 21 left -* 1808 1 20 of -* 1811 3 16 me -: 1815 1 16 ~ -: 1817 7 18 ~ -- 1831 -F 1834 2 21 snwod -F 1837 2 20 dna -F 1841 3 18 spu -F 1845 3 20 y -F 1849 3 20 nam -F 1853 3 18 os -- 1870 -: 1897 3 20 My -* 1901 2 20 heart's -: 1904 1 18 a -: 1906 3 20 bat -: 1910 3 21 tle -: 1914 5 21 ground -- 1926 -F 1929 2 16 snoit -F 1932 6 16 om -F 1941 2 18 e -F 1945 2 18 ~ -F 1948 2 18 eurt -F 1952 2 18 deen -F 1955 2 16 I -- 1971 -F 1987 3 18 wonk -F 1991 3 21 uoy -F 1995 3 21 naht -F 1999 3 21 snoit -F 2003 3 21 cef -F 2007 3 18 fa -F 2011 3 18 erom -F 2018 2 18 deen -F 2021 3 18 I -- 2038 -F 2059 2 16 snoit -F 2062 6 16 om -F 2070 3 18 e -F 2075 2 18 ~ -F 2078 2 18 eurt -F 2082 2 18 deen -F 2085 2 16 I -- 2116 -: 2219 3 13 You -: 2224 6 16 show -: 2232 3 16 me -: 2237 7 18 ~ -- 2252 -: 2255 3 18 how -: 2259 3 20 ~ -: 2267 2 13 to -: 2272 5 16 see -- 2282 -* 2284 3 13 That -* 2289 6 16 no -* 2297 3 16 thing -* 2302 5 18 ~ -- 2313 -: 2316 3 13 is -: 2321 3 16 whole -: 2325 2 15 ~ -: 2328 2 13 and -: 2331 1 13 ~ -: 2333 2 15 ~ -- 2338 -: 2340 3 20 no -: 2344 6 21 ~ -: 2352 3 18 ~ -: 2356 6 20 ~ -: 2364 5 16 thing -: 2371 12 13 ~ -- 2395 -: 2399 2 11 is -: 2403 9 13 bro -: 2416 5 18 ken -: 2423 41 20 ~ -- 2470 -: 2472 2 16 In -* 2476 2 21 you -* 2479 2 20 ~ -* 2483 3 16 ~ -: 2488 2 18 and -: 2492 4 20 I -: 2499 3 18 ~ -- 2506 -: 2508 3 16 There's -: 2512 3 16 a -: 2516 5 20 new -: 2522 4 23 land -: 2528 4 16 ~ -: 2534 27 15 ~ -: 2562 4 16 ~ -: 2568 17 16 ~ -: 2586 1 18 ~ -: 2588 3 20 ~ -- 2593 -: 2595 1 16 An -: 2597 2 18 ~ -: 2603 3 18 gels -: 2608 3 18 in -: 2613 6 20 flight -: 2620 2 18 ~ -- 2623 -F 2625 2 18 wonk -F 2628 3 21 uoy -F 2632 3 21 naht -F 2636 3 21 snoit -F 2640 3 21 cef -F 2644 3 18 fa -F 2648 3 18 erom -F 2655 2 18 deen -F 2658 2 18 I -- 2661 -: 2663 2 16 My -: 2668 1 21 sanc -: 2672 1 20 tu -: 2675 4 16 a -: 2681 7 18 ry -- 2693 -: 2695 3 16 My -: 2700 1 21 sanc -: 2704 2 20 tu -: 2708 3 16 a -: 2712 4 16 ry -: 2717 2 18 ~ -F 2721 4 13 yeah -- 2726 -: 2728 2 16 Where -: 2732 1 21 fears -: 2735 1 20 ~ -: 2737 5 16 ~ -: 2743 1 18 and -: 2747 4 20 lies -: 2754 3 18 ~ -- 2761 -: 2763 3 16 melt -: 2767 3 16 a -: 2771 4 20 way -: 2778 4 23 ~ -: 2783 4 16 ~ -: 2789 27 15 ~ -: 2817 4 16 ~ -: 2823 17 16 ~ -: 2841 1 18 ~ -: 2843 3 20 ~ -- 2849 -: 2851 1 16 Mu -: 2853 2 18 ~ -: 2857 3 18 sic -* 2862 3 18 will -* 2868 7 20 tie -: 2877 2 18 ~ -- 2880 -F 2882 1 18 wonk -F 2884 3 21 uoy -F 2888 3 21 naht -F 2892 3 21 snoit -F 2896 3 21 cef -F 2900 3 18 fa -F 2904 3 18 erom -F 2911 2 18 deen -F 2914 2 18 I -- 2917 -: 2919 2 16 What's -: 2923 1 21 left -: 2927 1 20 of -: 2930 3 16 me -: 2935 1 16 ~ -: 2937 7 18 ~ -- 2949 -: 2951 2 16 What's -: 2955 1 21 left -* 2959 1 20 of -* 2962 3 16 me -* 2967 2 16 ~ -: 2971 3 18 ~ -: 2979 12 13 now? -- 3005 -: 3026 2 11 uh -: 3029 2 13 ~ -: 3032 3 16 ~ -: 3036 8 15 ~ -: 3045 4 18 ~ -: 3051 4 16 ~ -: 3056 3 15 ~ -: 3060 3 13 ~ -- 3066 -: 3068 1 16 My -: 3070 2 18 ~ -: 3074 12 18 fears -- 3096 -: 3100 1 16 my -: 3102 2 18 ~ -: 3107 3 18 lies -: 3111 2 16 ~ -: 3114 1 13 ~ -- 3129 -* 3164 3 16 melt -* 3169 3 16 a -* 3173 4 20 way -* 3179 4 23 ~ -* 3185 3 16 ~ -* 3190 27 15 ~ -* 3218 3 16 ~ -* 3223 19 16 ~ -- 3248 -: 3250 4 18 ah -: 3256 126 20 ~ -- 3392 -F 3410 1 18 wonk -F 3412 3 21 uoy -F 3416 3 21 naht -F 3420 3 21 snoit -F 3424 3 21 cef -F 3428 3 18 fa -F 3432 3 18 erom -F 3439 2 18 deen -F 3442 3 18 I -E diff --git a/tests/fixtures/sweet_child.txt b/tests/fixtures/sweet_child.txt deleted file mode 100755 index 8133924..0000000 --- a/tests/fixtures/sweet_child.txt +++ /dev/null @@ -1,494 +0,0 @@ -#TITLE:Sweet Child O´Mine -#ARTIST:Guns N' Roses -#LANGUAGE:English -#GENRE:Rock -#YEAR:1987 -#MP3:Guns N' Roses - Sweet Child O´Mine.mp3 -#COVER:Guns N' Roses - Sweet Child O´Mine.jpg -#VIDEO:Guns N' Roses - Sweet Child O´Mine.webm -#CREATOR:sanicsip -#FIXER:Pacayaka -#BPM:256 -#GAP:49673 -#VIDEOGAP:0,3 -#START:13 -#MEDLEYSTARTBEAT:1564 -#MEDLEYENDBEAT:2057 -: 0 3 8 She's -: 5 2 8 got -: 8 1 8 a -: 13 2 6 smile -: 16 8 8 ~ -: 25 1 6 that -: 27 2 5 it -: 32 7 6 seems -: 41 1 8 to -: 45 1 5 me -: 47 5 4 ~ -: 53 1 3 ~ -- 55 -: 57 1 1 re -: 60 7 6 minds -: 69 2 5 me -: 73 1 1 of -: 76 1 1 child -: 79 9 6 ~ -: 91 5 6 hood -- 99 -: 101 3 6 mem -: 105 4 5 o -: 111 6 3 ries -: 118 1 1 ~ -- 120 -: 122 3 1 where -: 126 2 4 eve -: 129 5 6 ~ -: 135 2 5 ~ -: 138 1 1 ry -: 142 2 4 thing -: 145 4 6 ~ -: 150 2 5 was -: 154 1 1 as -: 158 2 5 fresh -: 161 4 6 ~ -: 166 3 5 as -: 171 1 1 the -: 174 5 6 bright -: 181 5 6 blue -: 190 8 6 sky -: 200 5 5 ~ -- 222 -: 258 4 8 Now -: 264 4 8 and -: 271 10 8 then -: 283 2 6 when -: 287 2 5 I -: 291 3 6 see -: 295 1 5 her -: 297 1 6 ~ -: 299 2 8 ~ -: 304 8 5 face -- 313 -: 315 3 6 she -: 319 3 8 ~ -: 324 3 6 takes -: 330 2 5 me -: 334 1 1 a -: 338 2 3 way -: 341 3 6 ~ -: 345 2 5 to -: 349 3 1 that -- 354 -: 356 3 6 spe -: 360 3 6 cial -: 364 2 8 ~ -: 369 1 6 place -: 371 4 5 ~ -: 377 2 5 and -: 381 1 6 if -: 384 2 5 I -: 389 3 6 stare -: 393 2 5 ~ -: 398 3 6 too -: 402 2 5 ~ -: 405 4 6 long -: 410 1 5 ~ -- 415 -: 417 1 1 I'd -: 420 1 1 prob -: 423 1 6 a -: 425 2 6 bly -: 429 5 6 break -: 436 5 6 down -: 442 2 6 and -* 445 1 8 ~ -: 450 7 6 cry -: 458 8 5 ~ -- 483 -: 512 3 6 Whoah -: 517 24 8 ~ -: 543 3 10 oh -: 548 2 8 ooh -: 551 3 8 whoah -: 555 1 6 ~ -: 559 3 6 sweet -: 563 1 5 ~ -: 567 2 5 child -: 570 3 6 ~ -: 575 1 6 o' -: 578 8 6 mine -: 587 12 5 ~ -- 616 -: 643 1 6 Whoah -: 645 11 8 ~ -: 659 7 6 oh -: 668 7 5 oh -: 677 2 5 oh -: 680 3 6 ~ -: 684 3 5 ~ -: 689 5 1 sweet -: 697 7 3 love -: 706 2 5 of -: 711 26 1 mine -- 771 -: 1041 5 8 She's -: 1048 6 8 got -: 1056 2 6 eyes -: 1059 7 8 ~ -: 1068 3 6 of -: 1073 1 5 the -: 1076 3 6 blu -: 1080 3 6 est -: 1084 2 8 ~ -: 1089 11 3 skies -: 1102 5 1 as -: 1110 5 6 if -: 1118 7 6 they -- 1128 -: 1130 4 6 thought -: 1135 2 5 of -: 1140 2 5 rain -: 1143 4 6 ~ -: 1148 4 5 ~ -- 1162 -* 1171 4 8 I -: 1176 2 5 hate -: 1179 3 6 ~ -: 1184 2 6 to -: 1187 3 5 ~ -: 1192 2 6 look -: 1196 10 6 in -: 1208 3 6 to -: 1213 6 5 those -: 1221 2 5 eyes -: 1224 7 6 ~ -: 1233 4 6 and -- 1239 -: 1241 4 6 see -: 1246 1 5 ~ -: 1249 3 1 an -: 1253 1 3 ounce -: 1256 5 6 ~ -: 1262 1 5 ~ -: 1265 2 1 of -: 1269 15 1 pain -- 1294 -: 1301 3 6 Her -: 1305 2 6 hair -: 1308 5 8 ~ -: 1314 2 8 re -: 1318 6 8 minds -: 1326 4 8 me -: 1331 3 6 of -: 1335 2 5 a -: 1339 6 6 warm -: 1347 2 6 safe -: 1350 3 8 ~ -: 1355 6 5 place -- 1362 -: 1364 6 1 where -: 1372 3 6 as -: 1376 2 5 ~ -: 1380 2 1 a -: 1384 2 5 child -: 1387 7 6 ~ -* 1395 3 8 I'd -: 1399 5 6 hide -: 1405 1 5 ~ -: 1408 11 1 ~ -- 1428 -: 1431 1 6 and -: 1433 2 8 ~ -: 1437 2 5 pray -: 1440 3 6 ~ -: 1445 3 6 for -: 1449 2 5 the -: 1453 7 6 thun -: 1461 6 6 der -- 1471 -: 1473 4 6 and -: 1478 2 5 the -: 1482 1 5 rain -: 1484 6 6 ~ -- 1491 -: 1493 1 5 to -: 1496 8 6 qui -: 1505 2 5 et -: 1509 2 1 ly -: 1514 1 5 pass -: 1516 6 6 ~ -* 1526 2 8 me -: 1529 5 6 by -: 1535 1 5 ~ -: 1538 10 1 ~ -- 1558 -: 1566 3 6 Whoah -: 1570 19 8 ~ -: 1591 3 10 oh -: 1595 3 8 ooh -: 1600 2 8 whoah -: 1603 1 6 ~ -: 1607 4 6 sweet -: 1612 1 5 ~ -: 1615 3 5 child -: 1620 2 6 ~ -: 1623 1 6 o' -: 1629 7 6 mine -: 1637 11 5 ~ -- 1658 -: 1675 2 12 Whoah -: 1678 20 13 ~ -: 1699 1 12 ~ -: 1701 5 13 ~ -: 1711 1 8 oh -: 1713 4 10 ~ -: 1719 7 8 oh -: 1727 3 8 oh -: 1731 3 10 ~ -: 1736 1 8 ~ -- 1737 -: 1739 3 6 Sweet -: 1743 1 5 ~ -: 1748 7 6 love -* 1757 2 8 of -: 1761 4 6 mine -: 1766 1 5 ~ -: 1770 16 1 ~ -- 1803 -* 1829 8 8 Oh -* 1842 4 10 oh -* 1850 4 13 oh -* 1858 2 13 oh -* 1861 5 15 ~ -* 1867 1 13 ~ -- 1869 -: 1871 3 13 Sweet -: 1875 1 10 ~ -: 1880 1 10 child -: 1882 3 13 ~ -: 1886 1 10 ~ -: 1888 2 8 o' -: 1892 2 8 mine -: 1895 5 10 ~ -: 1901 2 13 ~ -: 1905 2 10 ~ -: 1909 9 8 ~ -- 1924 -: 1926 2 8 Ooh -: 1929 4 10 ~ -: 1934 2 8 ~ -: 1937 3 5 ~ -: 1942 3 8 yeah -: 1951 1 8 yeah -: 1953 5 10 ~ -: 1959 2 8 ~ -- 1962 -: 1964 1 8 Ooh -: 1966 7 10 ~ -: 1974 7 8 ~ -: 1982 7 6 ~ -: 1991 2 5 ooh -: 1994 4 6 ~ -: 1999 1 5 ~ -- 2002 -: 2004 3 1 sweet -: 2010 9 3 love -: 2021 1 5 of -: 2025 1 3 mine -: 2027 1 5 ~ -: 2029 2 3 ~ -: 2032 25 1 ~ -- 2091 -: 3176 4 3 Where -: 3181 3 1 do -: 3185 2 -2 we -: 3190 8 -4 go? -- 3204 -: 3207 1 1 Where -: 3209 4 3 ~ -: 3214 2 1 do -: 3217 2 -2 we -: 3221 6 -4 go -: 3229 8 -6 now? -- 3239 -: 3241 3 3 Where -: 3245 3 1 do -: 3249 2 -2 we -: 3253 11 -4 go? -- 3274 -: 3282 1 -4 Ooh -: 3284 4 -2 ~ -: 3289 3 -4 oh -: 3293 3 -2 ~ -: 3297 3 -4 oh -: 3301 1 -6 ~ -- 3304 -: 3306 2 -2 Where -: 3309 2 -4 do -: 3312 2 -6 we -: 3316 4 -2 go -: 3321 4 -4 ~ -: 3326 6 -2 ~? -- 3342 -: 3355 5 -4 Oh -: 3362 7 -2 ~ -: 3370 2 -2 where -: 3373 2 -2 do -: 3376 2 -2 we -: 3380 3 -4 go -: 3384 1 -6 ~ -: 3387 13 -9 now? -- 3410 -: 3430 1 -6 Where -: 3433 1 -2 ~ -: 3435 2 -2 do -: 3439 2 1 we -: 3443 3 -4 go -: 3447 8 -2 ~? -- 3465 -: 3474 7 3 Ooh -: 3483 12 1 oh -: 3497 2 3 where -: 3500 2 1 do -: 3503 2 -2 we -: 3507 6 -4 go -: 3514 13 -6 now? -- 3537 -: 3558 1 -4 ay -: 3560 6 -2 ~ -: 3567 1 -4 ay -: 3569 5 -2 ~ -: 3575 1 -4 ay -: 3577 5 -2 ~ -: 3583 1 -4 ay -: 3585 5 -2 ~ -: 3591 1 -4 ay -: 3593 6 -2 ~ -: 3600 1 -4 ay -: 3602 5 -2 ~ -: 3608 2 -4 ay -: 3611 2 -2 ~ -- 3614 -: 3616 4 10 Oh -: 3623 1 13 where -: 3625 1 15 ~ -: 3627 3 13 do -: 3631 3 10 we -: 3635 6 8 go -: 3643 5 6 now? -- 3649 -* 3651 2 6 ah -* 3655 2 10 ah -* 3659 2 13 ah -* 3663 2 10 ah -* 3666 1 8 ah -* 3668 2 10 ah -* 3673 2 8 ah -* 3676 2 6 oh -* 3680 2 8 ah -* 3683 1 6 oh -- 3684 -: 3686 1 8 where -: 3688 2 10 ~ -: 3691 2 8 do -: 3695 2 6 we -: 3699 1 8 go -: 3701 11 10 ~? -- 3719 -* 3722 2 13 ah -* 3725 12 15 ~ -* 3738 8 13 ~ -* 3748 1 10 oh -* 3752 2 15 where -* 3756 2 13 do -* 3760 2 10 we -* 3764 7 8 go -* 3772 10 6 now? -- 3792 -: 3816 3 10 Where -: 3821 2 10 do -: 3825 2 13 we -: 3829 1 8 go -: 3831 4 10 ~ -: 3837 1 13 ~ -: 3841 2 10 ~ -: 3845 1 13 ~ -: 3849 1 10 ~ -: 3851 1 8 ~ -: 3853 1 10 ~ -: 3855 1 8 ~ -: 3857 1 10 ~ -: 3859 1 8 ~ -: 3861 2 10 ~ -: 3865 2 8 ~ -: 3868 3 6 ~ -: 3872 3 8 ~ -: 3876 2 6 ~? -- 3879 -: 3881 2 10 where -: 3884 1 8 do -: 3886 1 10 ~ -: 3888 2 10 we -: 3892 3 8 go -: 3897 1 6 ~ -: 3901 11 3 now? -- 3922 -: 3943 1 8 Where -: 3945 2 10 ~ -: 3949 2 8 do -: 3953 2 6 we -: 3957 2 10 go -: 3960 2 8 ~ -: 3963 10 10 ~? -- 3983 -: 3990 8 10 Whoah -: 4000 3 13 ~ -: 4004 3 10 ~ -: 4008 3 10 where -: 4012 3 13 do -: 4017 2 10 we -: 4021 5 8 go -: 4028 10 6 now? -- 4039 -* 4041 3 15 no -* 4046 3 13 no -* 4051 4 10 no -* 4057 3 9 no -* 4062 3 8 no -* 4067 3 6 no -* 4072 9 3 no -- 4087 -: 4090 3 8 sweet -: 4094 2 10 ~ -: 4101 3 8 child -: 4105 2 6 ~ -: 4109 7 3 ~ -- 4122 -: 4124 3 10 sweet -: 4128 1 8 ~ -: 4130 3 10 ~ -: 4137 3 10 child -: 4142 2 13 ~ -: 4145 4 10 ~ -: 4150 2 13 ~ -: 4153 4 10 ~ -: 4158 1 8 ~ -: 4160 2 10 ~ -: 4163 2 8 ~ -: 4166 3 6 ~ -: 4171 2 10 ~ -: 4175 2 13 ~ -: 4179 3 10 ~ -: 4183 4 13 ~ -: 4188 4 15 ~ -: 4194 2 13 ~ -: 4199 1 10 ~ -- 4200 -: 4202 1 8 o' -: 4204 2 10 ~ -: 4208 2 8 mine -: 4211 2 6 ~ -: 4214 46 3 ~ -: 4262 33 1 ~ -: 4297 49 3 ~ -E diff --git a/tests/test_align.py b/tests/test_align.py index c362510..f7016a3 100644 --- a/tests/test_align.py +++ b/tests/test_align.py @@ -7,7 +7,7 @@ from songtrace.lyrics import normalize_lyrics from songtrace.pipeline import Ctx, PipelineError, SongInput from songtrace.stages import align -LYRICS = "she's got a smile\nthat it seems to me" +LYRICS = "it's one two three\nfour five six seven eight" def make_ctx(tmp_path, lyrics=LYRICS, transcript=None): @@ -15,7 +15,7 @@ def make_ctx(tmp_path, lyrics=LYRICS, transcript=None): work.mkdir(exist_ok=True) if transcript is None: transcript = [{"start": 1.0, "end": 4.0, - "text": "she's got a smile that it seems to me"}] + "text": "it's one two three four five six seven eight"}] (work / "transcript.json").write_text(json.dumps(transcript)) inp = SongInput(title="T", artist="A", lyrics_text=lyrics) return Ctx(inp=inp, cfg=Config(whisper_url="u", device="cpu"), @@ -49,7 +49,7 @@ def check_invariants(rows, lyrics): def test_alignment_covers_all_words(tmp_path, monkeypatch): rows = run_align(tmp_path, monkeypatch) assert [r["word"] for r in rows] == \ - ["she's", "got", "a", "smile", "that", "it", "seems", "to", "me"] + ["it's", "one", "two", "three", "four", "five", "six", "seven", "eight"] assert rows[0]["line_index"] == 0 and rows[-1]["line_index"] == 1 starts = [r["start"] for r in rows] assert starts == sorted(starts) @@ -63,18 +63,18 @@ def test_mismatched_lyrics_fail(tmp_path, monkeypatch): def test_unalignable_word_interpolated(tmp_path, monkeypatch): - lyrics = "she's got ... smile\nthat it seems to me" + lyrics = "it's one ... three\nfour five six seven eight" rows = run_align(tmp_path, monkeypatch, lyrics) dots = next(r for r in rows if r["word"] == "...") assert dots["score"] == 0.0 - prev = next(r for r in rows if r["word"] == "got") - nxt = next(r for r in rows if r["word"] == "smile") + prev = next(r for r in rows if r["word"] == "one") + nxt = next(r for r in rows if r["word"] == "three") assert prev["end"] <= dots["start"] <= dots["end"] <= nxt["start"] + 1e-6 check_invariants(rows, lyrics) def test_leading_unalignable_word(tmp_path, monkeypatch): - lyrics = "... got a smile\nthat it seems to me" + lyrics = "... one two three\nfour five six seven eight" rows = run_align(tmp_path, monkeypatch, lyrics) assert rows[0]["word"] == "..." and rows[0]["score"] == 0.0 assert rows[0]["start"] >= 0.0 @@ -83,7 +83,7 @@ def test_leading_unalignable_word(tmp_path, monkeypatch): def test_trailing_unalignable_word(tmp_path, monkeypatch): - lyrics = "she's got a smile\nthat it seems to ..." + lyrics = "it's one two three\nfour five six seven ..." rows = run_align(tmp_path, monkeypatch, lyrics) assert rows[-1]["word"] == "..." and rows[-1]["score"] == 0.0 assert rows[-2]["end"] <= rows[-1]["start"] @@ -91,7 +91,7 @@ def test_trailing_unalignable_word(tmp_path, monkeypatch): def test_consecutive_unalignable_words(tmp_path, monkeypatch): - lyrics = "she's got ... ... smile\nthat it seems to me" + lyrics = "it's one ... ... three\nfour five six seven eight" rows = run_align(tmp_path, monkeypatch, lyrics) dots = [r for r in rows if r["word"] == "..."] assert len(dots) == 2 @@ -113,8 +113,8 @@ def test_all_words_unalignable_in_section(tmp_path, monkeypatch): def test_non_chronological_transcript(tmp_path, monkeypatch): - transcript = [{"start": 30.0, "end": 33.0, "text": "that it seems to me"}, - {"start": 1.0, "end": 4.0, "text": "she's got a smile"}] + transcript = [{"start": 30.0, "end": 33.0, "text": "four five six seven eight"}, + {"start": 1.0, "end": 4.0, "text": "it's one two three"}] rows = run_align(tmp_path, monkeypatch, transcript=transcript) check_invariants(rows, LYRICS) assert len({r["start"] for r in rows}) == len(rows) @@ -131,8 +131,8 @@ def test_inverted_section_does_not_collapse(tmp_path, monkeypatch): def test_words_split_across_sections(tmp_path, monkeypatch): - transcript = [{"start": 1.0, "end": 4.0, "text": "she's got a smile"}, - {"start": 30.0, "end": 33.0, "text": "that it seems to me"}] + transcript = [{"start": 1.0, "end": 4.0, "text": "it's one two three"}, + {"start": 30.0, "end": 33.0, "text": "four five six seven eight"}] rows = run_align(tmp_path, monkeypatch, transcript=transcript) check_invariants(rows, LYRICS) assert rows[3]["end"] <= 5.0 @@ -140,9 +140,9 @@ def test_words_split_across_sections(tmp_path, monkeypatch): def test_align_drops_lines_never_sung(tmp_path, monkeypatch): - lyrics = "she's got a smile\nthat it seems to me\nbut then it fades away" + lyrics = "it's one two three\nfour five six seven eight\nnine ten eleven twelve" transcript = [{"start": 1.0, "end": 4.0, - "text": "she's got a smile that it seems to me"}] + "text": "it's one two three four five six seven eight"}] rows = run_align(tmp_path, monkeypatch, lyrics, transcript) assert {r["line_index"] for r in rows} == {0, 1} meta = json.loads((tmp_path / "w" / "align_meta.json").read_text()) @@ -151,9 +151,9 @@ def test_align_drops_lines_never_sung(tmp_path, monkeypatch): def test_align_flags_missing_span_for_unmatched_singing(tmp_path, monkeypatch): - lyrics = "she's got a smile\nthat it seems to me" + lyrics = "it's one two three\nfour five six seven eight" transcript = [ - {"start": 1.0, "end": 4.0, "text": "she's got a smile that it seems to me"}, + {"start": 1.0, "end": 4.0, "text": "it's one two three four five six seven eight"}, {"start": 20.0, "end": 23.0, "text": "completely unrelated ad lib bridge"}, ] run_align(tmp_path, monkeypatch, lyrics, transcript) diff --git a/tests/test_lyrics.py b/tests/test_lyrics.py index b9f05dd..716c759 100644 --- a/tests/test_lyrics.py +++ b/tests/test_lyrics.py @@ -1,22 +1,22 @@ from songtrace.lyrics import normalize_lyrics, alignment_token RAW = """[Verse 1] -She's got a smile +It's one two three [Chorus] -Whoa, sweet child o' mine -Take me down to 7 streets +Whoa, la la o' la +Count me up to 7 times """ def test_normalize_strips_sections_and_blanks(): ref = normalize_lyrics(RAW) assert ref.lines == [ - ["She's", "got", "a", "smile"], - ["Whoa,", "sweet", "child", "o'", "mine"], - ["Take", "me", "down", "to", "7", "streets"], + ["It's", "one", "two", "three"], + ["Whoa,", "la", "la", "o'", "la"], + ["Count", "me", "up", "to", "7", "times"], ] - assert ref.words[0] == "She's" + assert ref.words[0] == "It's" assert ref.word_line_index == [0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2] diff --git a/tests/test_notes.py b/tests/test_notes.py index 1e556f4..1e33cc0 100644 --- a/tests/test_notes.py +++ b/tests/test_notes.py @@ -78,7 +78,7 @@ def test_syllabify(): assert syllabify("reminds", "English") == ["re", "minds"] assert syllabify("a", "English") == ["a"] assert syllabify("xyzzy", None) == ["xyzzy"] - assert syllabify("She's", "English") == ["She's"] + assert syllabify("It's", "English") == ["It's"] def test_syllabify_preserves_word_characters(): @@ -96,12 +96,12 @@ def test_syllabify_language_without_pyphen_dict_is_not_mishandled_as_english(): def test_build_notes_basic_line(): times, f0, conf = flat_pitch() rows = [ - {"word": "She's", "start": 1.0, "end": 1.5, "score": 0.9, "line_index": 0}, + {"word": "It's", "start": 1.0, "end": 1.5, "score": 0.9, "line_index": 0}, {"word": "got", "start": 1.6, "end": 2.0, "score": 0.9, "line_index": 0}, {"word": "Now", "start": 5.0, "end": 5.5, "score": 0.9, "line_index": 1}, ] notes, breaks, warnings = build_notes(rows, times, f0, conf, "English") - assert notes[0].text == "She's" # line-initial: no leading space + assert notes[0].text == "It's" # line-initial: no leading space assert notes[1].text == " got" # mid-line: leading space assert notes[2].text == "Now" # new line: no leading space assert len(breaks) == 1 and 2.0 <= breaks[0] <= 5.0 @@ -225,8 +225,8 @@ def test_build_notes_short_multisyllable_word_does_not_overlap(): def test_build_notes_never_overlaps_on_dense_input(): rng = np.random.default_rng(11) times = np.arange(0, 40.0, 0.01) - words = ["She's", "got", "a", "beautiful", "smile", "reminds", "me", - "everything", "I", "lost", "yesterday", "oh"] + words = ["We", "count", "a", "beautiful", "number", "reminds", "us", + "everything", "we", "listed", "yesterday", "oh"] for _ in range(8): f0 = 220.0 * 2 ** (rng.integers(0, 12, len(times)) // 3 / 12.0) conf = np.where(rng.random(len(times)) < 0.9, 0.9, 0.1) @@ -244,8 +244,8 @@ def test_build_notes_starts_are_non_decreasing(): times = np.arange(0, 12.0, 0.01) f0 = 220.0 * 2 ** (np.floor(times * 2) % 5 / 12.0) # stepped melody conf = np.where((times % 3.0) < 2.6, 0.9, 0.1) # unvoiced gaps - words = ["She's", "got", "a", "beautiful", "smile", "that", - "reminds", "me", "of", "everything", "I", "lost"] + words = ["We", "count", "a", "beautiful", "number", "that", + "reminds", "us", "of", "everything", "we", "list"] rows = [] for i, w in enumerate(words): dur = 0.8 if i % 3 else 0.07 # every third word sung very fast @@ -278,7 +278,7 @@ def test_notes_stage_writes_json(tmp_path): times, f0, conf = flat_pitch() np.savez(work / "pitch.npz", times=times, f0=f0, conf=conf) (work / "alignment.json").write_text(json.dumps([ - {"word": "She's", "start": 1.0, "end": 1.5, "score": 0.9, "line_index": 0}, + {"word": "It's", "start": 1.0, "end": 1.5, "score": 0.9, "line_index": 0}, {"word": "gone", "start": 3.0, "end": 3.5, "score": 0.9, "line_index": 1}, ])) ctx = Ctx(inp=SongInput(title="T", artist="A", lyrics_text="x", language="English"), @@ -287,7 +287,7 @@ def test_notes_stage_writes_json(tmp_path): assert stage.outputs(ctx) == [work / "notes_sec.json"] stage.run(ctx) data = json.loads((work / "notes_sec.json").read_text()) - assert [n["text"] for n in data["notes"]] == ["She's", "gone"] + assert [n["text"] for n in data["notes"]] == ["It's", "gone"] assert data["breaks"] == [2.25] assert data["warnings"] == [] assert TimedNote(**data["notes"][0]).pitch == 0 diff --git a/tests/test_transcribe.py b/tests/test_transcribe.py index 5947706..9ac80e4 100644 --- a/tests/test_transcribe.py +++ b/tests/test_transcribe.py @@ -18,35 +18,35 @@ def test_vocal_sections_keeps_contained_segment(): assert sections == [(0.0, 11.0)] def test_similarity_high_for_matching_lyrics(): - ref = normalize_lyrics("she's got a smile\nthat it seems to me") - segs = [seg(0, 2, "She's got a smile"), seg(2, 4, "that it seems to me")] + ref = normalize_lyrics("it's one two three\nfour five six seven eight") + segs = [seg(0, 2, "It's one two three"), seg(2, 4, "four five six seven eight")] assert lyrics_similarity(segs, ref) > 0.9 def test_similarity_low_for_wrong_lyrics(): ref = normalize_lyrics("completely different words here entirely") - segs = [seg(0, 2, "she's got a smile that it seems to me")] + segs = [seg(0, 2, "it's one two three four five six seven eight")] assert lyrics_similarity(segs, ref) < 0.4 def test_classify_lyrics_match_flags_extra_reference_line(): - ref = normalize_lyrics("she's got a smile\nthat it seems to me\nbut then it fades") - segs = [seg(1, 4, "she's got a smile that it seems to me")] + ref = normalize_lyrics("it's one two three\nfour five six seven eight\nnine ten eleven") + segs = [seg(1, 4, "it's one two three four five six seven eight")] dropped, missing = classify_lyrics_match(segs, ref) assert dropped == [2] assert missing == [] def test_classify_lyrics_match_flags_unmatched_singing(): - ref = normalize_lyrics("she's got a smile\nthat it seems to me") - segs = [seg(1, 4, "she's got a smile that it seems to me"), + ref = normalize_lyrics("it's one two three\nfour five six seven eight") + segs = [seg(1, 4, "it's one two three four five six seven eight"), seg(20, 23, "completely unrelated ad lib bridge")] dropped, missing = classify_lyrics_match(segs, ref) assert dropped == [] assert missing == [(19.0, 24.0)] def test_classify_lyrics_match_keeps_partially_matched_lines(): - ref = normalize_lyrics("she's got a smile\nthat it seems to me") - # line 1 heard with one word garbled ("it" -> "bit"): still a replace/equal + ref = normalize_lyrics("it's one two three\nfour five six seven eight") + # line 1 heard with one word garbled ("five" -> "fife"): still a replace/equal # match, so the line stays matched rather than dropped - segs = [seg(1, 4, "she's got a smile that bit seems to me")] + segs = [seg(1, 4, "it's one two three four fife six seven eight")] dropped, _ = classify_lyrics_match(segs, ref) assert dropped == [] @@ -54,8 +54,8 @@ def test_classify_lyrics_match_scopes_missing_span_to_adlib_not_whole_section(): # matched line and an unmatched ad-lib close enough together that # vocal_sections would merge them into one section; missing_spans must # stay tight around the ad-lib so the review marks the right place. - ref = normalize_lyrics("she's got a smile\nthat it seems to me") - segs = [seg(1, 4, "she's got a smile that it seems to me"), + ref = normalize_lyrics("it's one two three\nfour five six seven eight") + segs = [seg(1, 4, "it's one two three four five six seven eight"), seg(6, 8, "completely unrelated ad lib")] sections = vocal_sections(segs) assert sections == [(0.0, 9.0)] # confirms the two segments do merge diff --git a/tests/test_ultrastar.py b/tests/test_ultrastar.py index b523cc3..b4fadac 100644 --- a/tests/test_ultrastar.py +++ b/tests/test_ultrastar.py @@ -10,8 +10,8 @@ def load(name): return (FIXTURES / name).read_text(encoding="utf-8", errors="replace") def test_parse_headers_and_notes(): - song = parse_ultrastar(load("sanctuary.txt")) - assert get_header(song, "artist") == "Utada Hikaru" + song = parse_ultrastar(load("chart_crlf.txt")) + assert get_header(song, "artist") == "Test Artist" assert parse_bpm(get_header(song, "BPM")) == 217.98 first = song.body[0] assert first == Note(kind=":", beat=0, length=3, pitch=16, text="ah") @@ -19,16 +19,16 @@ def test_parse_headers_and_notes(): assert any(n.kind == "F" for n in song.body if isinstance(n, Note)) def test_note_text_keeps_leading_space(): - song = parse_ultrastar(load("sanctuary.txt")) + song = parse_ultrastar(load("chart_crlf.txt")) notes = [n for n in song.body if isinstance(n, Note)] assert notes[1].text == " ah" def test_negative_pitch(): - song = parse_ultrastar(load("sweet_child.txt")) + song = parse_ultrastar(load("chart_latin1.txt")) assert any(n.pitch == -9 for n in song.body if isinstance(n, Note)) def test_round_trip(): - for name in ("sweet_child.txt", "sanctuary.txt"): + for name in ("chart_latin1.txt", "chart_crlf.txt"): song = parse_ultrastar(load(name)) again = parse_ultrastar(serialize_ultrastar(song)) assert again == song