@onjmin/dtm 2.1.8 → 2.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +131 -133
- package/dist/index.d.ts +131 -133
- package/dist/index.js +1198 -217
- package/dist/index.mjs +1197 -217
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -147,6 +147,14 @@ async function buildNameToKeyMapping() {
|
|
|
147
147
|
return nameToKey;
|
|
148
148
|
}
|
|
149
149
|
var GM_INSTRUMENT_NAMES = FONT_NAME_SURIKOV.trim().split("\n").map((line) => line.slice(line.indexOf(" ") + 1));
|
|
150
|
+
var programOfInstrumentName = (name) => {
|
|
151
|
+
if (!name) return null;
|
|
152
|
+
const stripped = name.replace(/\s+/g, "").toLowerCase();
|
|
153
|
+
const idx = GM_INSTRUMENT_NAMES.findIndex(
|
|
154
|
+
(n) => n.replace(/\s+/g, "").toLowerCase() === stripped
|
|
155
|
+
);
|
|
156
|
+
return idx >= 0 ? idx : null;
|
|
157
|
+
};
|
|
150
158
|
|
|
151
159
|
// node_modules/.pnpm/@onjmin+chord-parser@1.1.1/node_modules/@onjmin/chord-parser/dist/index.mjs
|
|
152
160
|
var SHARP_NAMES = [
|
|
@@ -12510,44 +12518,365 @@ var mountChordPlayer = (target, chords, options = {}) => {
|
|
|
12510
12518
|
// src/compose-corpus.ts
|
|
12511
12519
|
var CORPUS_SIZE = 91;
|
|
12512
12520
|
var CORPUS_BANDS = {
|
|
12513
|
-
entropy: [0.
|
|
12514
|
-
valueKinds: [2, 3,
|
|
12515
|
-
restRatio: [
|
|
12516
|
-
leapRatio: [0.
|
|
12517
|
-
stepRatio: [0.
|
|
12518
|
-
chromaticRatio: [0, 0.
|
|
12519
|
-
maxLeap: [
|
|
12520
|
-
melodyRange: [
|
|
12521
|
-
notesPerBar: [
|
|
12522
|
-
shortNoteRatio: [0.
|
|
12523
|
-
|
|
12524
|
-
|
|
12525
|
-
|
|
12526
|
-
|
|
12527
|
-
|
|
12528
|
-
|
|
12529
|
-
|
|
12530
|
-
|
|
12521
|
+
entropy: [0.25, 0.711, 1.237, 1.754],
|
|
12522
|
+
valueKinds: [2, 3, 6, 7],
|
|
12523
|
+
restRatio: [0.016, 0.091, 0.223, 0.464],
|
|
12524
|
+
leapRatio: [0.202, 0.28, 0.412, 0.71],
|
|
12525
|
+
stepRatio: [0.188, 0.438, 0.617, 0.693],
|
|
12526
|
+
chromaticRatio: [0, 0.017, 0.121, 0.242],
|
|
12527
|
+
maxLeap: [5, 8, 12, 16],
|
|
12528
|
+
melodyRange: [8, 17, 22, 28],
|
|
12529
|
+
notesPerBar: [2.743, 4.77, 6.473, 11.995],
|
|
12530
|
+
shortNoteRatio: [0.055, 0.753, 0.91, 1],
|
|
12531
|
+
barDensityCv: [0.148, 0.206, 0.328, 0.451],
|
|
12532
|
+
densityCliff: [0, 0, 0.043, 0.125],
|
|
12533
|
+
sim1: [0.345, 0.465, 0.598, 0.803],
|
|
12534
|
+
sim2: [0.389, 0.5, 0.647, 0.845],
|
|
12535
|
+
sim4: [0.437, 0.549, 0.723, 0.882],
|
|
12536
|
+
sim8: [0.063, 0.561, 0.771, 0.972],
|
|
12537
|
+
phraseBreath: [0, 0.115, 0.323, 0.884],
|
|
12538
|
+
turnRatio: [0.4, 0.478, 0.556, 0.769],
|
|
12539
|
+
climaxPosition: [0.016, 0.14, 0.655, 0.92],
|
|
12540
|
+
climaxPeaks: [1, 2, 13.5, 26],
|
|
12541
|
+
complementarity: [0, 0.026, 0.179, 0.405]
|
|
12531
12542
|
};
|
|
12532
12543
|
var CORPUS_MEDIANS = {
|
|
12533
|
-
entropy: 0.
|
|
12544
|
+
entropy: 0.907,
|
|
12534
12545
|
valueKinds: 4,
|
|
12535
|
-
restRatio: 0.
|
|
12536
|
-
leapRatio: 0.
|
|
12537
|
-
stepRatio: 0.
|
|
12538
|
-
chromaticRatio: 0.
|
|
12546
|
+
restRatio: 0.149,
|
|
12547
|
+
leapRatio: 0.339,
|
|
12548
|
+
stepRatio: 0.538,
|
|
12549
|
+
chromaticRatio: 0.052,
|
|
12539
12550
|
maxLeap: 12,
|
|
12540
|
-
melodyRange:
|
|
12541
|
-
notesPerBar: 5.
|
|
12542
|
-
shortNoteRatio: 0.
|
|
12543
|
-
|
|
12544
|
-
|
|
12545
|
-
|
|
12546
|
-
|
|
12547
|
-
|
|
12551
|
+
melodyRange: 20,
|
|
12552
|
+
notesPerBar: 5.511,
|
|
12553
|
+
shortNoteRatio: 0.816,
|
|
12554
|
+
barDensityCv: 0.279,
|
|
12555
|
+
densityCliff: 0.026,
|
|
12556
|
+
sim1: 0.518,
|
|
12557
|
+
sim2: 0.552,
|
|
12558
|
+
sim4: 0.616,
|
|
12559
|
+
sim8: 0.676,
|
|
12560
|
+
phraseBreath: 0.227,
|
|
12561
|
+
turnRatio: 0.519,
|
|
12548
12562
|
climaxPosition: 0.273,
|
|
12549
|
-
climaxPeaks:
|
|
12550
|
-
complementarity: 0.
|
|
12563
|
+
climaxPeaks: 6,
|
|
12564
|
+
complementarity: 0.075
|
|
12565
|
+
};
|
|
12566
|
+
var CORPUS_CELL_WEIGHTS = {
|
|
12567
|
+
"0,2,4,6,8,10,12,14": 584,
|
|
12568
|
+
"0,2,4,6,8,12,14": 512,
|
|
12569
|
+
"0,4,6,8,10,12,14": 246,
|
|
12570
|
+
"0,8": 187,
|
|
12571
|
+
"0,4,8,10,12,14": 158,
|
|
12572
|
+
"0,6,8,10,12,14": 153,
|
|
12573
|
+
"2,5,10,13": 128,
|
|
12574
|
+
"0,12,14": 123,
|
|
12575
|
+
"0,4,6,8,12,14": 114,
|
|
12576
|
+
"0,4,8,12": 110,
|
|
12577
|
+
"0": 105,
|
|
12578
|
+
"0,2,4,6,8,12": 103,
|
|
12579
|
+
"0,4,8,12,14": 102,
|
|
12580
|
+
"0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15": 89,
|
|
12581
|
+
"0,2,4,6,8": 76,
|
|
12582
|
+
"0,6,8,12,14": 58,
|
|
12583
|
+
"0,6,8,14": 48,
|
|
12584
|
+
"0,4,6,8,12": 44,
|
|
12585
|
+
"0,4,8,14": 44,
|
|
12586
|
+
"0,2,4,5,6,8,9,10,12,13,14,15": 44,
|
|
12587
|
+
"2,6,10,14": 42,
|
|
12588
|
+
"0,8,12": 40,
|
|
12589
|
+
"0,2,4,6,8,10,12": 39,
|
|
12590
|
+
"0,3,9,10,11,12,13,14,15": 36,
|
|
12591
|
+
"0,3,6,8,11,14": 32,
|
|
12592
|
+
"0,2,4,6,7,9,10,12,14": 32,
|
|
12593
|
+
"0,2,4,6,10,12,14": 31,
|
|
12594
|
+
"0,10,12,14": 28,
|
|
12595
|
+
"12,14": 27,
|
|
12596
|
+
"0,2,4,6,8,14": 27,
|
|
12597
|
+
"0,6,8,12": 25,
|
|
12598
|
+
"0,4,6,8,10,12": 24,
|
|
12599
|
+
"0,1,2,4,5,6,7,8,9,10,11,12,13,14,15": 24,
|
|
12600
|
+
"2,4,6,8,10,12,14": 22,
|
|
12601
|
+
"0,6,8": 19,
|
|
12602
|
+
"0,12": 19,
|
|
12603
|
+
"8,12": 17,
|
|
12604
|
+
"0,2,4,8,12,14": 16,
|
|
12605
|
+
"0,3,5,6,7,8,11,13,14,15": 16,
|
|
12606
|
+
"0,3,4,5,6,7,8,10,12,14": 16,
|
|
12607
|
+
"0,14": 15,
|
|
12608
|
+
"0,4,8": 15,
|
|
12609
|
+
"0,4,6,8,14": 14,
|
|
12610
|
+
"0,4,6,8,10,11,12,14": 14,
|
|
12611
|
+
"2,4,6,8": 13,
|
|
12612
|
+
"0,4,6,10,12,14": 13,
|
|
12613
|
+
"0,4,6,8": 13,
|
|
12614
|
+
"0,2,4,8,9,11,14,15": 12,
|
|
12615
|
+
"0,4,8,10,11,12,14": 12,
|
|
12616
|
+
"0,2,4,6,8,9,12,14": 12,
|
|
12617
|
+
"0,3,4,6,8,12,14": 12,
|
|
12618
|
+
"0,2,4,6,8,11,14": 12,
|
|
12619
|
+
"0,2,4,5,6,7,8,9,10,11,12,14": 12,
|
|
12620
|
+
"2,4,6,8,12,14": 11,
|
|
12621
|
+
"0,2,4,8,10,12": 11,
|
|
12622
|
+
"0,1,2,3,4,5,6,7,8,9,10,11,12": 11,
|
|
12623
|
+
"0,2,4,6,8,10,11,12,14": 10,
|
|
12624
|
+
"0,4,6,7,8,14,15": 10,
|
|
12625
|
+
"0,8,10,12,14": 10,
|
|
12626
|
+
"0,3,4,6,8,10,12,14": 9,
|
|
12627
|
+
"0,2,3,4,6,8,12,14": 9,
|
|
12628
|
+
"0,2,4,5,6,8,12,14": 9,
|
|
12629
|
+
"0,3,4,6,8,9,10,11,12": 9,
|
|
12630
|
+
"0,3,4,6,8,9,10,11,12,14,15": 9,
|
|
12631
|
+
"0,3,4,6,7,8,10,12,14,15": 9,
|
|
12632
|
+
"0,2,4,5,6,7,8,9,10,12,13,14,15": 9,
|
|
12633
|
+
"0,2,4,8,10,12,14": 8,
|
|
12634
|
+
"0,2,4,6,8,10,12,14,15": 8,
|
|
12635
|
+
"1,2,3,4,5,6,7,8,9,10,11,12,13,14,15": 8,
|
|
12636
|
+
"0,3,6,8,12,14": 7,
|
|
12637
|
+
"0,1,2,3,4,5,6,7,8": 7,
|
|
12638
|
+
"0,4,8,10,12": 7,
|
|
12639
|
+
"0,2,3,4,5,6,7,8": 7,
|
|
12640
|
+
"0,3,4,6,8,12": 6,
|
|
12641
|
+
"0,2,4,6,10,14": 6,
|
|
12642
|
+
"4,12": 6,
|
|
12643
|
+
"0,6,8,10,14": 6,
|
|
12644
|
+
"0,2,3,4,5,6,7,8,9,10,11,12": 6,
|
|
12645
|
+
"0,1,2,3,4,6,7,8,10,12,14,15": 6,
|
|
12646
|
+
"0,3,6,8,12": 6,
|
|
12647
|
+
"2,4,6,8,10,11,12,14": 6,
|
|
12648
|
+
"6,8,10,12,14": 5,
|
|
12649
|
+
"2,6,8,10,12,14": 5,
|
|
12650
|
+
"0,8,12,14": 5,
|
|
12651
|
+
"0,3,4,6,8": 5,
|
|
12652
|
+
"0,8,11,14": 5,
|
|
12653
|
+
"0,3,4,6,8,10,11,12,14": 5,
|
|
12654
|
+
"0,3,6,8": 5,
|
|
12655
|
+
"0,1,4,8,9,12,13": 5,
|
|
12656
|
+
"10,12,14": 5,
|
|
12657
|
+
"0,4,6,8,10,11,12,13,14": 5,
|
|
12658
|
+
"12,13,14,15": 5,
|
|
12659
|
+
"0,2,4,7,8,14,15": 5,
|
|
12660
|
+
"0,4,8,9,10,11,12,13,14,15": 5,
|
|
12661
|
+
"0,4,7,8,14,15": 5,
|
|
12662
|
+
"0,4,8,9,10,11,12": 5,
|
|
12663
|
+
"0,2,6,8,10,12,14": 5,
|
|
12664
|
+
"2,4,6,12,14": 4,
|
|
12665
|
+
"0,2,4,6,7,8,10,12,14": 4,
|
|
12666
|
+
"4,5,7,8,10,12,13,14": 4,
|
|
12667
|
+
"0,2,3,4,5,8,9,12,13": 4,
|
|
12668
|
+
"2,3,4,6,8,12,13,14": 4,
|
|
12669
|
+
"0,1,2,3,4,5,6,7,8,9,10,11,12,13,14": 4,
|
|
12670
|
+
"0,2,4,8,12": 4,
|
|
12671
|
+
"4,6,8,10,12": 4,
|
|
12672
|
+
"0,2,4,5,6,8,12,13,14,15": 4,
|
|
12673
|
+
"0,2,3,4,6,8": 4,
|
|
12674
|
+
"0,4,6,8,10,12,13,14": 4,
|
|
12675
|
+
"0,6,8,12,14,15": 4,
|
|
12676
|
+
"0,4,8,9,10,12,14": 4,
|
|
12677
|
+
"0,3,4,7,8,9,10,11,12": 4,
|
|
12678
|
+
"0,1,2,3,4,5,7,8,9,10,11,12": 4,
|
|
12679
|
+
"2,4,8,12": 4,
|
|
12680
|
+
"0,2,4,6,10,12": 4,
|
|
12681
|
+
"0,3,4,6,7,8,9,10,12,14": 4,
|
|
12682
|
+
"0,3,6,9,11,12": 4,
|
|
12683
|
+
"0,1,4,6,8,12,14": 4,
|
|
12684
|
+
"4,8,12": 4,
|
|
12685
|
+
"2,4,6,14": 3,
|
|
12686
|
+
"0,3,4,8": 3,
|
|
12687
|
+
"0,2,4,12,14": 3,
|
|
12688
|
+
"14": 3,
|
|
12689
|
+
"0,4,6,12,14": 3,
|
|
12690
|
+
"0,6,10,12,14": 3,
|
|
12691
|
+
"4,8,9,11,14": 3,
|
|
12692
|
+
"0,2,4,8,9,11,14": 3,
|
|
12693
|
+
"0,4,8,9,11,14": 3,
|
|
12694
|
+
"0,2,4,5,7,9,11,12": 3,
|
|
12695
|
+
"0,3,6,8,10,12,14": 3,
|
|
12696
|
+
"0,3,4,6,8,11,12,14": 3,
|
|
12697
|
+
"0,1,4,5,8,9,12,13": 3,
|
|
12698
|
+
"0,2,4,5,8,9": 3,
|
|
12699
|
+
"2,3,4,6,8,9,12,14": 3,
|
|
12700
|
+
"0,2,4,8": 3,
|
|
12701
|
+
"0,2,3,4,5,6,8,9": 3,
|
|
12702
|
+
"2,3,4,6,8,10,12,13": 3,
|
|
12703
|
+
"12,14,15": 3,
|
|
12704
|
+
"0,2,3,4,6,7,8,10,12": 3,
|
|
12705
|
+
"0,2,3,4,5,6,7,8,9,10,12": 3,
|
|
12706
|
+
"0,1,2,3,4,5,6,7,8,9,10,11,12,14": 3,
|
|
12707
|
+
"0,2,3,4,6,7,8,9,10,11,12": 3,
|
|
12708
|
+
"0,4,6,12": 3,
|
|
12709
|
+
"0,2,3,6,8,11,14": 3,
|
|
12710
|
+
"0,2,6,8,12,14": 3,
|
|
12711
|
+
"2,4,6,8,14,15": 3,
|
|
12712
|
+
"0,2,4,6,12,14": 2,
|
|
12713
|
+
"2,4,6,10,12,14": 2,
|
|
12714
|
+
"4,6,10,12,14": 2,
|
|
12715
|
+
"0,8,14": 2,
|
|
12716
|
+
"2,4,8,10,12,14": 2,
|
|
12717
|
+
"8": 2,
|
|
12718
|
+
"0,2,4,6,8,9,10,11,12,14": 2,
|
|
12719
|
+
"0,2,4,6,8,12,13,14": 2,
|
|
12720
|
+
"0,6,8,11,12,14": 2,
|
|
12721
|
+
"0,1,2,3,4,5,6,7,8,9,11,12,13,14,15": 2,
|
|
12722
|
+
"0,1,3,4,5,6,7,8,9,10,11,12,13,14,15": 2,
|
|
12723
|
+
"0,6,7,8,10,12": 2,
|
|
12724
|
+
"0,3,6,7,8,10,12": 2,
|
|
12725
|
+
"1,2,3,4,6,8,10,12,13": 2,
|
|
12726
|
+
"0,2,8,10,12,14": 2,
|
|
12727
|
+
"0,2,7,8,9,10": 2,
|
|
12728
|
+
"4,8,9,10,12,13": 2,
|
|
12729
|
+
"0,2,4,7,8,9,10": 2,
|
|
12730
|
+
"2,4,7,8,12,15": 2,
|
|
12731
|
+
"0,4,7,8,10": 2,
|
|
12732
|
+
"0,4,8,9,12,13": 2,
|
|
12733
|
+
"0,2,4,5,6,8,9": 2,
|
|
12734
|
+
"0,1,4": 2,
|
|
12735
|
+
"0,4": 2,
|
|
12736
|
+
"0,3,6,10,12,14": 2,
|
|
12737
|
+
"0,2,6,10,12,14": 2,
|
|
12738
|
+
"0,2,3,4,6,8,14,15": 2,
|
|
12739
|
+
"2,4,6,8,12,14,15": 2,
|
|
12740
|
+
"0,2,4,6,8,9,10,12": 2,
|
|
12741
|
+
"0,3,6,8,10,12": 2,
|
|
12742
|
+
"0,3,4,6,8,10,14": 2,
|
|
12743
|
+
"0,4,8,11,12,14": 2,
|
|
12744
|
+
"0,2,4,6,8,9,10,11,12,13,14": 2,
|
|
12745
|
+
"0,2,4,5,6,7,8,9,10,12": 2,
|
|
12746
|
+
"0,1,2,3,4,6,7,8,9,10,12,14": 2,
|
|
12747
|
+
"0,1,2,4,5,6,8,9,10,11,12,13,14": 2,
|
|
12748
|
+
"0,1,2,3,4,6,7,8,9,10,11,12,13,14": 2,
|
|
12749
|
+
"0,1,2,3,4,6,7,8,9,10,11,12,13,14,15": 2,
|
|
12750
|
+
"0,1,2,4,6,8,9,10,11,12,13,14": 2,
|
|
12751
|
+
"0,1,2,3,4,5,6,8,9,10,11,12,13,14": 2,
|
|
12752
|
+
"0,1,2,3,4,6,7,8,9,10,12,13,14,15": 2,
|
|
12753
|
+
"0,2,4,6,8,9,10,11,12,13,14,15": 2,
|
|
12754
|
+
"0,2,3,4,5,6,8,10,12": 2,
|
|
12755
|
+
"0,2,3,4,5,6,7,8,10,11,12": 2,
|
|
12756
|
+
"0,2,3,4,6,7,8,9,10,12": 2,
|
|
12757
|
+
"0,1,2,3,4,6,7,8,9,10,11,12": 2,
|
|
12758
|
+
"0,4,5,8,12,13": 2,
|
|
12759
|
+
"0,3,4,5,8,11,12,13": 2,
|
|
12760
|
+
"0,2,4,7,8,9": 2,
|
|
12761
|
+
"0,4,6,7,8,12": 2,
|
|
12762
|
+
"0,2,3,4,6,7,8,10,11,12,14": 2,
|
|
12763
|
+
"0,2,3,4,5,6,7,8,10,11,12,13": 2,
|
|
12764
|
+
"12": 2,
|
|
12765
|
+
"0,2,4,6,8,13": 2,
|
|
12766
|
+
"2,4,6,8,11,14": 2,
|
|
12767
|
+
"0,5,8,13": 2,
|
|
12768
|
+
"0,2,4,6,8,10,11,12,13,14": 2,
|
|
12769
|
+
"0,4,6,8,10,11,12,13,14,15": 2,
|
|
12770
|
+
"0,5,8,12": 2,
|
|
12771
|
+
"2,4,6,8,14": 1,
|
|
12772
|
+
"0,6,7,8,14": 1,
|
|
12773
|
+
"0,6,8,14,15": 1,
|
|
12774
|
+
"0,6,7,8,10,11,12,13": 1,
|
|
12775
|
+
"0,6,7,8,9,10,11,12,14": 1,
|
|
12776
|
+
"0,1,2,4,6,7,8,10,11,12,13,14,15": 1,
|
|
12777
|
+
"0,4,8,10,11,12": 1,
|
|
12778
|
+
"0,6,7,8,11,14": 1,
|
|
12779
|
+
"0,2,5,8,11,14": 1,
|
|
12780
|
+
"0,2,4,6,8,10,11,12": 1,
|
|
12781
|
+
"0,11,14": 1,
|
|
12782
|
+
"0,8,11,12,13,14,15": 1,
|
|
12783
|
+
"0,1,12": 1,
|
|
12784
|
+
"0,3,5,8,12": 1,
|
|
12785
|
+
"0,4,8,11,14": 1,
|
|
12786
|
+
"2,6,8,11,14": 1,
|
|
12787
|
+
"0,2,3,4,6,8,12": 1,
|
|
12788
|
+
"0,4,6,8,11,12,14": 1,
|
|
12789
|
+
"0,1,12,14": 1,
|
|
12790
|
+
"0,9,12": 1,
|
|
12791
|
+
"0,3": 1,
|
|
12792
|
+
"0,1": 1,
|
|
12793
|
+
"4,6,8,14": 1,
|
|
12794
|
+
"2,12,14": 1,
|
|
12795
|
+
"2,8,12": 1,
|
|
12796
|
+
"0,3,6,8,11": 1,
|
|
12797
|
+
"10,12,14,15": 1,
|
|
12798
|
+
"0,2,3,6,8,9,11,14": 1,
|
|
12799
|
+
"0,2,4,8,10,11": 1,
|
|
12800
|
+
"0,2,4,6,7,8,10,12,13": 1,
|
|
12801
|
+
"2,3,4,5,8,10,12,13,15": 1,
|
|
12802
|
+
"0,2,3,4,5,6,8,10,11,12": 1,
|
|
12803
|
+
"4,6,8,10,11,12": 1,
|
|
12804
|
+
"0,1,2,3,4,6,8,9,10,13,15": 1,
|
|
12805
|
+
"0,1,2,3,4,10,11,12": 1,
|
|
12806
|
+
"0,3,6,7,8,9,11": 1,
|
|
12807
|
+
"0,2,4,5,8,10,11,15": 1,
|
|
12808
|
+
"0,2,4,6,7,8,9,12,13": 1,
|
|
12809
|
+
"0,1,2,4,5,8,10,12,13": 1,
|
|
12810
|
+
"0,2,3,4,5,6,8,10,11,12,13": 1,
|
|
12811
|
+
"4,6,8,10,11,12,13": 1,
|
|
12812
|
+
"0,3,8,12,14": 1,
|
|
12813
|
+
"0,3,4,5,7,8,9,10,12,14,15": 1,
|
|
12814
|
+
"0,2,4,6,8,9,11": 1,
|
|
12815
|
+
"10,14": 1,
|
|
12816
|
+
"0,2,4,6,9,10,12,14": 1,
|
|
12817
|
+
"0,2,4,6,7,9,10,12": 1,
|
|
12818
|
+
"0,2,3,5,8,10,12,13,14": 1,
|
|
12819
|
+
"0,1,2,3,5,6,7,8,9,10,12,13,14": 1,
|
|
12820
|
+
"2,3,4,6,7,8,12,13,14": 1,
|
|
12821
|
+
"0,1,2,3,6,7,8,10,12,13,14": 1,
|
|
12822
|
+
"2,3,4,5,6,8,9,10,11,12,13,14": 1,
|
|
12823
|
+
"0,2,3,4,5,6,7,8,9,10,11,12,13,14": 1,
|
|
12824
|
+
"2,3,4,6,8,9,10,11,12,13,14,15": 1,
|
|
12825
|
+
"0,3,4,7,8,11,12": 1,
|
|
12826
|
+
"0,4,10,12,14": 1,
|
|
12827
|
+
"0,3,4,7,8,11,12,15": 1,
|
|
12828
|
+
"0,4,12,14": 1,
|
|
12829
|
+
"0,4,12": 1,
|
|
12830
|
+
"0,4,7,8,10,11,12,14": 1,
|
|
12831
|
+
"2,6,8,12": 1,
|
|
12832
|
+
"0,2,4,5,6,8": 1,
|
|
12833
|
+
"2,6,8,10,12": 1,
|
|
12834
|
+
"0,2,4,6,8,12,13,14,15": 1,
|
|
12835
|
+
"0,4,6,8,10,11,12": 1,
|
|
12836
|
+
"0,4,8,10,11,12,13,14": 1,
|
|
12837
|
+
"0,2,3,4,6,7,8,9,10,12,13,14,15": 1,
|
|
12838
|
+
"0,2,4,5,6,8,9,10,11,12,13,14": 1,
|
|
12839
|
+
"0,3,4,7,8,9,10,12,13": 1,
|
|
12840
|
+
"0,1,2,4,6,7,8,9,10,12,13,14,15": 1,
|
|
12841
|
+
"0,2,3,4,5,6,8,9,10,11,12,13,14": 1,
|
|
12842
|
+
"0,4,6,7,8,10,12,14,15": 1,
|
|
12843
|
+
"0,2,4,6,7,8,10,12,14,15": 1,
|
|
12844
|
+
"0,1,2,3,4,5,7,8,10,11,12": 1,
|
|
12845
|
+
"0,2,4,6,7,8,9,10,11,12,14": 1,
|
|
12846
|
+
"0,1,2,4,5,6,7,8,10,12,14,15": 1,
|
|
12847
|
+
"0,2,3,4,5,7,8,9,10,11,12": 1,
|
|
12848
|
+
"0,2,3,4,6,7,8,10,11,12": 1,
|
|
12849
|
+
"0,8,9,10,11,12,13,14,15": 1,
|
|
12850
|
+
"14,15": 1,
|
|
12851
|
+
"2,4,6,8,12": 1,
|
|
12852
|
+
"2,4,8,10,12": 1,
|
|
12853
|
+
"0,2,4,8,9,12,14": 1,
|
|
12854
|
+
"0,4,5,8,9,12": 1,
|
|
12855
|
+
"0,4,8,10,14": 1,
|
|
12856
|
+
"0,6,7,12": 1,
|
|
12857
|
+
"0,4,5,8,11,12,13": 1,
|
|
12858
|
+
"0,2,4,8,9": 1,
|
|
12859
|
+
"2,4,7,8,11,12": 1,
|
|
12860
|
+
"0,4,7,8,11": 1,
|
|
12861
|
+
"0,4,8,12,14,15": 1,
|
|
12862
|
+
"0,1,2,4,5,6,7,8,9,10,12": 1,
|
|
12863
|
+
"0,1,2,3,4,5,6,7,8,9,10,12": 1,
|
|
12864
|
+
"0,2,3,4,5,6,7,8,9,10,12,13,14,15": 1,
|
|
12865
|
+
"0,3,4,7,8,9,11,12": 1,
|
|
12866
|
+
"0,1,2,3,4,5,6,7,8,10,11,12,13": 1,
|
|
12867
|
+
"0,6,8,10,12": 1,
|
|
12868
|
+
"0,2,3,4,6,8,10,11,12,14": 1,
|
|
12869
|
+
"0,2,4,6,8,10,13": 1,
|
|
12870
|
+
"2,6,8": 1,
|
|
12871
|
+
"0,2,3,4,6,7,8,12,14": 1,
|
|
12872
|
+
"2,4,6,8,10,14": 1,
|
|
12873
|
+
"0,2,4": 1,
|
|
12874
|
+
"0,2,4,5,6,7,8,9,10": 1,
|
|
12875
|
+
"0,2,4,5,6,7,8,9,10,12,13,14": 1,
|
|
12876
|
+
"0,3,6,10,14": 1,
|
|
12877
|
+
"0,14,15": 1,
|
|
12878
|
+
"0,6,7,12,14": 1,
|
|
12879
|
+
"0,6,8,10,11,12,14": 1
|
|
12551
12880
|
};
|
|
12552
12881
|
|
|
12553
12882
|
// src/compose-keys.ts
|
|
@@ -12882,8 +13211,7 @@ var resolveComposeKey = (choice, rnd = Math.random) => {
|
|
|
12882
13211
|
const target = COMPOSE_KEYS[pickedKeyId];
|
|
12883
13212
|
const targetMood = COMPOSE_MOOD_GROUPS.find((m) => m.id === target.moodId);
|
|
12884
13213
|
return {
|
|
12885
|
-
mode:
|
|
12886
|
-
// コード進行の長短制約は掛けず従来通りランダム
|
|
13214
|
+
mode: target.mode,
|
|
12887
13215
|
rootShift: target.rootShift,
|
|
12888
13216
|
keyName: target.name,
|
|
12889
13217
|
keyLabel: target.label,
|
|
@@ -13010,9 +13338,24 @@ var complementarity = (melody, submelody, opts) => {
|
|
|
13010
13338
|
}
|
|
13011
13339
|
return free / submelody.length;
|
|
13012
13340
|
};
|
|
13341
|
+
var turnRatio = (notes) => {
|
|
13342
|
+
const sorted = [...notes].sort((a, b) => a.startStep - b.startStep);
|
|
13343
|
+
let turns = 0;
|
|
13344
|
+
let intervals = 0;
|
|
13345
|
+
let prevDir = 0;
|
|
13346
|
+
for (let i2 = 1; i2 < sorted.length; i2++) {
|
|
13347
|
+
const dir = Math.sign(sorted[i2].pitchSemi - sorted[i2 - 1].pitchSemi);
|
|
13348
|
+
if (dir === 0) continue;
|
|
13349
|
+
intervals++;
|
|
13350
|
+
if (prevDir !== 0 && dir !== prevDir) turns++;
|
|
13351
|
+
prevDir = dir;
|
|
13352
|
+
}
|
|
13353
|
+
return intervals === 0 ? 0 : turns / intervals;
|
|
13354
|
+
};
|
|
13013
13355
|
var structureFeatures = (melody, submelody, opts) => {
|
|
13014
13356
|
const sigs = barSignatures(melody, opts);
|
|
13015
13357
|
return {
|
|
13358
|
+
turnRatio: turnRatio(melody),
|
|
13016
13359
|
sim1: selfSimilarity(sigs, 1),
|
|
13017
13360
|
sim2: selfSimilarity(sigs, 2),
|
|
13018
13361
|
sim4: selfSimilarity(sigs, 4),
|
|
@@ -13022,13 +13365,40 @@ var structureFeatures = (melody, submelody, opts) => {
|
|
|
13022
13365
|
complementarity: complementarity(melody, submelody, opts)
|
|
13023
13366
|
};
|
|
13024
13367
|
};
|
|
13368
|
+
var barNoteCounts = (notes, opts) => {
|
|
13369
|
+
const out = new Array(Math.max(1, opts.bars)).fill(0);
|
|
13370
|
+
for (const n of notes) {
|
|
13371
|
+
const bar = Math.floor(n.startStep / opts.stepsPerBar);
|
|
13372
|
+
if (bar >= 0 && bar < out.length) out[bar]++;
|
|
13373
|
+
}
|
|
13374
|
+
return out;
|
|
13375
|
+
};
|
|
13025
13376
|
var densityFeatures = (notes, opts) => {
|
|
13026
|
-
if (notes.length === 0)
|
|
13377
|
+
if (notes.length === 0)
|
|
13378
|
+
return {
|
|
13379
|
+
notesPerBar: 0,
|
|
13380
|
+
shortNoteRatio: 0,
|
|
13381
|
+
barDensityCv: 0,
|
|
13382
|
+
densityCliff: 0
|
|
13383
|
+
};
|
|
13027
13384
|
const eighth = opts.stepsPerBar / 8;
|
|
13028
13385
|
const short = notes.filter((n) => n.durationSteps <= eighth).length;
|
|
13386
|
+
const counts = barNoteCounts(notes, opts);
|
|
13387
|
+
const sung = counts.filter((c) => c > 0);
|
|
13388
|
+
const mean2 = sung.reduce((a, b) => a + b, 0) / Math.max(1, sung.length);
|
|
13389
|
+
const variance = sung.reduce((a, b) => a + (b - mean2) ** 2, 0) / Math.max(1, sung.length);
|
|
13390
|
+
let cliffs = 0;
|
|
13391
|
+
let pairs = 0;
|
|
13392
|
+
for (let i2 = 1; i2 < counts.length; i2++) {
|
|
13393
|
+
if (counts[i2 - 1] < 3 || counts[i2] === 0) continue;
|
|
13394
|
+
pairs++;
|
|
13395
|
+
if (counts[i2] <= counts[i2 - 1] * 0.3) cliffs++;
|
|
13396
|
+
}
|
|
13029
13397
|
return {
|
|
13030
13398
|
notesPerBar: notes.length / Math.max(1, opts.bars),
|
|
13031
|
-
shortNoteRatio: short / notes.length
|
|
13399
|
+
shortNoteRatio: short / notes.length,
|
|
13400
|
+
barDensityCv: mean2 === 0 ? 0 : Math.sqrt(variance) / mean2,
|
|
13401
|
+
densityCliff: pairs === 0 ? 0 : cliffs / pairs
|
|
13032
13402
|
};
|
|
13033
13403
|
};
|
|
13034
13404
|
var tensionFeatures = (barTension, opts) => {
|
|
@@ -13324,8 +13694,8 @@ var sectionAt = (plan, bar) => {
|
|
|
13324
13694
|
|
|
13325
13695
|
// src/compose.ts
|
|
13326
13696
|
var STEP_SEMITONES = 2;
|
|
13327
|
-
var MAX_LEAP_SEMITONES =
|
|
13328
|
-
var MAX_BAR_LEAP_SEMITONES =
|
|
13697
|
+
var MAX_LEAP_SEMITONES = 10;
|
|
13698
|
+
var MAX_BAR_LEAP_SEMITONES = 10;
|
|
13329
13699
|
var HARD = {
|
|
13330
13700
|
/** メロディが1音も無い、音域が半音未満(同じ音を並べただけ)。 */
|
|
13331
13701
|
minMelodyRange: 3,
|
|
@@ -13351,6 +13721,9 @@ var WEIGHTS = {
|
|
|
13351
13721
|
*/
|
|
13352
13722
|
notesPerBar: 0.8,
|
|
13353
13723
|
shortNoteRatio: 0.6,
|
|
13724
|
+
/** 小節ごとの音数のばらつきと崖。平均だけを見ていて見逃していた偏り。 */
|
|
13725
|
+
barDensityCv: 0.6,
|
|
13726
|
+
densityCliff: 1,
|
|
13354
13727
|
/** 順次進行の比率。跳躍率だけを見ていると、跳躍の帯の上端に張り付く。 */
|
|
13355
13728
|
stepRatio: 0.8,
|
|
13356
13729
|
/** 調の外の音。0のままだと全曲が同じ音階をなぞるだけになる。 */
|
|
@@ -13363,10 +13736,15 @@ var WEIGHTS = {
|
|
|
13363
13736
|
sim4: 1.4,
|
|
13364
13737
|
sim8: 1.4,
|
|
13365
13738
|
phraseBreath: 1,
|
|
13739
|
+
/** 折り返しの多さ。跳躍率・順次進行率が揃っていても、これは別に足りなくなる。 */
|
|
13740
|
+
turnRatio: 0.8,
|
|
13366
13741
|
climaxPosition: 1,
|
|
13367
13742
|
climaxPeaks: 1,
|
|
13368
13743
|
/** メロディとサブメロが呼応しているか。 */
|
|
13369
13744
|
complementarity: 1,
|
|
13745
|
+
/** サブメロの音数と、その崖。メロディと同じ物差しで見る。 */
|
|
13746
|
+
subDensity: 0.6,
|
|
13747
|
+
subDensityCliff: 0.5,
|
|
13370
13748
|
// --- 和声(コードが要るのでコーパスからは較正できない) ---
|
|
13371
13749
|
/** B部でテンションが上がるか。 */
|
|
13372
13750
|
tensionRise: 1,
|
|
@@ -13442,6 +13820,10 @@ var FLAT_NOTE_NAMES = [
|
|
|
13442
13820
|
"Bb",
|
|
13443
13821
|
"B"
|
|
13444
13822
|
];
|
|
13823
|
+
var fifthsDistance = (semitones) => {
|
|
13824
|
+
const steps = (semitones * 7 % 12 + 12) % 12;
|
|
13825
|
+
return Math.min(steps, 12 - steps);
|
|
13826
|
+
};
|
|
13445
13827
|
var SEMITONE_TO_FIFTH_SHIFT = [
|
|
13446
13828
|
0,
|
|
13447
13829
|
// 0: C
|
|
@@ -13594,6 +13976,22 @@ var SECTION_A_PROGRESSIONS = [
|
|
|
13594
13976
|
// ジャズ寄りの2-5-1
|
|
13595
13977
|
["Dm7", "G7", "Em7", "Am7"],
|
|
13596
13978
|
// 2-5-3-6
|
|
13979
|
+
// --- ライン・クリシェ(内声が半音ずつ動く) ---
|
|
13980
|
+
// 和音の1声だけを半音で動かして、和音記号は変わるのに響きは繋がったまま進む。
|
|
13981
|
+
// J-POPのサビ後半やAメロの定番。
|
|
13982
|
+
["Am", "AmM7", "Am7", "Am6"],
|
|
13983
|
+
// ラ→ソ#→ソ→ファ# の下行
|
|
13984
|
+
["C", "CM7", "C7", "F"],
|
|
13985
|
+
// ド→シ→シb→ラ
|
|
13986
|
+
["Am", "AmM7", "Am7", "D7"],
|
|
13987
|
+
// クリシェからドリアンのIVへ
|
|
13988
|
+
["F", "Fm", "CM7", "Am7"],
|
|
13989
|
+
// サブドミナントマイナーのクリシェ
|
|
13990
|
+
// --- ペダルポイント(ベースを保続する) ---
|
|
13991
|
+
// ベースだけ動かさずに上の和音を変える。緊張感が出る。分数和音のルートを
|
|
13992
|
+
// {@link chordTones} が先頭で返すので、ベースは自然に保続音になる。
|
|
13993
|
+
["C", "Am/C", "F/C", "G/C"],
|
|
13994
|
+
["Am", "Em/A", "F/A", "G/A"],
|
|
13597
13995
|
// --- 借用和音(同主短調・ミクソリディアンから借りる) ---
|
|
13598
13996
|
// **調の外の和音を進行そのものに持たせる。** ここまでの候補は全部ハ長調/イ短調の
|
|
13599
13997
|
// ダイアトニックで、セカンダリドミナント以外に調の外の音が出てこなかった。
|
|
@@ -13650,10 +14048,34 @@ var SECTION_A2_DERIVATIONS = [
|
|
|
13650
14048
|
var SECTION_A3_DERIVATIONS = [
|
|
13651
14049
|
(a, t) => [a[0], a[1], "G7", t],
|
|
13652
14050
|
(a, t) => [a[0], "Dm7", "G7", t],
|
|
13653
|
-
(a, t) => [a[0], "F", "G7", t],
|
|
13654
14051
|
(a, t) => [a[0], a[1], "Em7", t],
|
|
13655
|
-
|
|
14052
|
+
// アーメン終止(IV→I)
|
|
14053
|
+
(a, t) => [a[0], "G7", "F", t],
|
|
14054
|
+
(a, t) => [a[0], "Dm7", "FM7", t],
|
|
14055
|
+
// サブドミナントマイナー終止(IVm→I)
|
|
14056
|
+
(a, t) => [a[0], "G7", "Fm", t],
|
|
14057
|
+
(a, t) => [a[0], "F", "Fm", t]
|
|
14058
|
+
];
|
|
14059
|
+
var SECTION_DECEPTIVE_DERIVATIONS = [
|
|
14060
|
+
(a, t) => [a[0], a[1], "G7", t === "Am" ? "F" : "Am"],
|
|
14061
|
+
(a, t) => [a[0], "Dm7", "G7", t === "Am" ? "FM7" : "Am7"],
|
|
14062
|
+
(a, t) => [a[0], "F", "G7", t === "Am" ? "F" : "Am7"]
|
|
13656
14063
|
];
|
|
14064
|
+
var MODAL_BORROW = {
|
|
14065
|
+
F: "Fm",
|
|
14066
|
+
// IV → IVm(サブドミナントマイナー。いちばん定番)
|
|
14067
|
+
FM7: "Fm7",
|
|
14068
|
+
Am: "Ab",
|
|
14069
|
+
// VIm → ♭VI
|
|
14070
|
+
Am7: "Ab",
|
|
14071
|
+
G: "Bb",
|
|
14072
|
+
// V → ♭VII(ミクソリディアン)
|
|
14073
|
+
G7: "Bb",
|
|
14074
|
+
Em7: "Eb",
|
|
14075
|
+
// IIIm → ♭III
|
|
14076
|
+
Dm7: "Dm7-5"
|
|
14077
|
+
// IIm7 → IIm7♭5(エオリアン)
|
|
14078
|
+
};
|
|
13657
14079
|
var CHORD_PATTERNS = [
|
|
13658
14080
|
"block",
|
|
13659
14081
|
"arpeggio",
|
|
@@ -13661,6 +14083,7 @@ var CHORD_PATTERNS = [
|
|
|
13661
14083
|
"yatsume",
|
|
13662
14084
|
"alternating"
|
|
13663
14085
|
];
|
|
14086
|
+
var chordPatternPool = (bpm) => bpm <= 130 ? [...CHORD_PATTERNS, "arpeggio-fast"] : CHORD_PATTERNS;
|
|
13664
14087
|
var CHORD_TONE_WEIGHT = {
|
|
13665
14088
|
0: 3,
|
|
13666
14089
|
// ルート
|
|
@@ -13838,6 +14261,54 @@ var RHYTHM_CELLS = [
|
|
|
13838
14261
|
density: "dense"
|
|
13839
14262
|
}
|
|
13840
14263
|
];
|
|
14264
|
+
var PHRASE_END_CELLS = [
|
|
14265
|
+
// 白玉で受けてから息を継ぐ(いちばん歌らしい終わり方)。
|
|
14266
|
+
{ value: [HALF, QUARTER, -QUARTER], density: "sparse" },
|
|
14267
|
+
{ value: [DOT_QUARTER, EIGHTH, HALF], density: "sparse" },
|
|
14268
|
+
{ value: [QUARTER, DOT_QUARTER, EIGHTH, -QUARTER], density: "sparse" },
|
|
14269
|
+
// 2音で降りてから息を継ぐ。
|
|
14270
|
+
{ value: [QUARTER, QUARTER, -HALF], density: "sparse" },
|
|
14271
|
+
{ value: [DOT_QUARTER, EIGHTH, -HALF], density: "sparse" },
|
|
14272
|
+
{ value: [HALF, -QUARTER, QUARTER], density: "sparse" },
|
|
14273
|
+
// 3音で言い切ってから息を継ぐ。
|
|
14274
|
+
{ value: [EIGHTH, EIGHTH, QUARTER, -HALF], density: "sparse" },
|
|
14275
|
+
{ value: [QUARTER, EIGHTH, EIGHTH, -HALF], density: "sparse" },
|
|
14276
|
+
{ value: [QUARTER, QUARTER, QUARTER, -QUARTER], density: "sparse" },
|
|
14277
|
+
{ value: [HALF, EIGHTH, EIGHTH, -QUARTER], density: "sparse" },
|
|
14278
|
+
// 4音で言い切ってから息を継ぐ。周りが7音前後の曲では、2音まで落とすと崖になる。
|
|
14279
|
+
{ value: [EIGHTH, EIGHTH, EIGHTH, EIGHTH, -HALF], density: "sparse" },
|
|
14280
|
+
{ value: [QUARTER, EIGHTH, EIGHTH, QUARTER, -QUARTER], density: "sparse" },
|
|
14281
|
+
{ value: [EIGHTH, EIGHTH, QUARTER, QUARTER, -QUARTER], density: "sparse" }
|
|
14282
|
+
];
|
|
14283
|
+
var MID_BREATH_CELLS = [
|
|
14284
|
+
{ value: [QUARTER, EIGHTH, EIGHTH, QUARTER, -QUARTER], density: "medium" },
|
|
14285
|
+
{ value: [EIGHTH, EIGHTH, QUARTER, QUARTER, -QUARTER], density: "medium" },
|
|
14286
|
+
{ value: [DOT_QUARTER, EIGHTH, QUARTER, QUARTER], density: "medium" },
|
|
14287
|
+
{ value: [QUARTER, QUARTER, EIGHTH, EIGHTH, -QUARTER], density: "medium" },
|
|
14288
|
+
{ value: [EIGHTH, EIGHTH, EIGHTH, EIGHTH, HALF], density: "medium" },
|
|
14289
|
+
{ value: [QUARTER, EIGHTH, EIGHTH, DOT_QUARTER, EIGHTH], density: "medium" }
|
|
14290
|
+
];
|
|
14291
|
+
var CELL_GRID = BASE_STEPS_PER_BAR / 16;
|
|
14292
|
+
var onsetKeyOf = (value) => {
|
|
14293
|
+
const on = [];
|
|
14294
|
+
let at = 0;
|
|
14295
|
+
for (const v of value) {
|
|
14296
|
+
if (v > 0) on.push(Math.round(at / CELL_GRID));
|
|
14297
|
+
at += Math.abs(v);
|
|
14298
|
+
}
|
|
14299
|
+
return on.join(",");
|
|
14300
|
+
};
|
|
14301
|
+
var UNSEEN_CELL_WEIGHT = 0.5;
|
|
14302
|
+
var cellEntryCount = /* @__PURE__ */ new Map();
|
|
14303
|
+
var cellWeightCache = /* @__PURE__ */ new Map();
|
|
14304
|
+
var cellWeight = (c) => {
|
|
14305
|
+
const cached = cellWeightCache.get(c.value);
|
|
14306
|
+
if (cached !== void 0) return cached;
|
|
14307
|
+
const key = onsetKeyOf(c.value);
|
|
14308
|
+
const w = (CORPUS_CELL_WEIGHTS[key] ?? UNSEEN_CELL_WEIGHT) / Math.max(1, cellEntryCount.get(key) ?? 1);
|
|
14309
|
+
cellWeightCache.set(c.value, w);
|
|
14310
|
+
return w;
|
|
14311
|
+
};
|
|
13841
14312
|
var HALF_BAR_FIGURES = [
|
|
13842
14313
|
[EIGHTH, EIGHTH, EIGHTH, EIGHTH],
|
|
13843
14314
|
// タタタタ
|
|
@@ -13870,6 +14341,14 @@ var HALF_BAR_FIGURES = [
|
|
|
13870
14341
|
// 2拍目裏からのアウフタクト(タタ)
|
|
13871
14342
|
[QUARTER, -EIGHTH, EIGHTH],
|
|
13872
14343
|
// ター・休タ(8分裏弱起)
|
|
14344
|
+
// **3+3+2(トレシーヨ)。** 参考曲91本で最も多かった「語彙に無い形」で、
|
|
14345
|
+
// 174小節ぶんの穴が空いていた(`scripts/compare-vocabulary.ts` の①)。
|
|
14346
|
+
// 付点8分が `[DOT_EIGHTH, SIXTEENTH]` の対でしか入っておらず、
|
|
14347
|
+
// 付点8分を2つ並べる形が作れなかった。界隈曲・ボカロの推進力の中心。
|
|
14348
|
+
[DOT_EIGHTH, DOT_EIGHTH, EIGHTH],
|
|
14349
|
+
[DOT_EIGHTH, DOT_EIGHTH, EIGHTH],
|
|
14350
|
+
// 4分音符が全部8分裏に来る形(食い)。参考曲で67小節ぶん取りこぼしていた。
|
|
14351
|
+
[-EIGHTH, QUARTER, EIGHTH],
|
|
13873
14352
|
// 付点8分+16分(タッカ)。歌モノで非常に多用される跳ね・推進力の型。
|
|
13874
14353
|
[DOT_EIGHTH, SIXTEENTH, EIGHTH, EIGHTH],
|
|
13875
14354
|
[EIGHTH, EIGHTH, DOT_EIGHTH, SIXTEENTH],
|
|
@@ -14035,9 +14514,21 @@ var MOTIF_CELLS = [
|
|
|
14035
14514
|
...buildMotifCells(),
|
|
14036
14515
|
...HAND_MOTIF_CELLS
|
|
14037
14516
|
];
|
|
14517
|
+
for (const c of [...MOTIF_CELLS, ...RHYTHM_CELLS]) {
|
|
14518
|
+
const key = onsetKeyOf(c.value);
|
|
14519
|
+
cellEntryCount.set(key, (cellEntryCount.get(key) ?? 0) + 1);
|
|
14520
|
+
}
|
|
14038
14521
|
var groovyCells = (cells, groove, rnd) => {
|
|
14039
14522
|
const hasSixteenth = (c) => c.value.some((v) => Math.abs(v) <= SIXTEENTH);
|
|
14040
|
-
if (groove === "eighth")
|
|
14523
|
+
if (groove === "eighth") {
|
|
14524
|
+
const plain = cells.filter((c) => !hasSixteenth(c));
|
|
14525
|
+
const spiced = cells.filter(hasSixteenth);
|
|
14526
|
+
if (spiced.length === 0) return plain;
|
|
14527
|
+
const out = [...plain];
|
|
14528
|
+
const take = Math.max(1, Math.round(plain.length * 0.1));
|
|
14529
|
+
for (let i2 = 0; i2 < take; i2++) out.push(pick(spiced, rnd));
|
|
14530
|
+
return out;
|
|
14531
|
+
}
|
|
14041
14532
|
const withSixteenth = cells.filter(hasSixteenth);
|
|
14042
14533
|
return withSixteenth.length > 0 && rnd() < 0.75 ? withSixteenth : cells;
|
|
14043
14534
|
};
|
|
@@ -14158,8 +14649,35 @@ var nearestChordTone = (targetSemi, tones, minWeight, preferColor = false) => {
|
|
|
14158
14649
|
return best;
|
|
14159
14650
|
};
|
|
14160
14651
|
var MELODY_LOW = 60;
|
|
14161
|
-
var MELODY_HIGH =
|
|
14652
|
+
var MELODY_HIGH = 81;
|
|
14162
14653
|
var MELODY_CENTER = (MELODY_LOW + MELODY_HIGH) / 2;
|
|
14654
|
+
var harmonyPitch = (melodySemi, tones, prevHarmony, offset, parallel, against) => {
|
|
14655
|
+
const lo = Math.max(-12, Math.min(offset, 0) - 7);
|
|
14656
|
+
const hi = Math.min(12, Math.max(offset, 0) + 7);
|
|
14657
|
+
let best = null;
|
|
14658
|
+
let bestCost = Number.POSITIVE_INFINITY;
|
|
14659
|
+
for (const tone of tones) {
|
|
14660
|
+
const pc = pitchClass(tone.semi);
|
|
14661
|
+
for (let oct = 0; oct <= 10; oct++) {
|
|
14662
|
+
const semi = pc + oct * 12;
|
|
14663
|
+
const delta = semi - melodySemi;
|
|
14664
|
+
if (delta > hi || delta < lo) continue;
|
|
14665
|
+
const move = prevHarmony === null ? 0 : Math.abs(semi - prevHarmony);
|
|
14666
|
+
const stay = parallel ? move * 0.06 : move <= 2 ? move * 0.04 : 0.1 + (move - 2) * 0.9;
|
|
14667
|
+
let clash = 0;
|
|
14668
|
+
if (against !== null) {
|
|
14669
|
+
const g = Math.abs(semi - against) % 12;
|
|
14670
|
+
clash = g === 3 || g === 4 || g === 8 || g === 9 || g === 7 ? 0 : g === 0 ? 0.5 : 1.2;
|
|
14671
|
+
}
|
|
14672
|
+
const cost = stay + clash + Math.abs(delta - offset) * (parallel ? 1.4 : 0.7) + (3 - tone.weight) * 0.4;
|
|
14673
|
+
if (cost < bestCost) {
|
|
14674
|
+
bestCost = cost;
|
|
14675
|
+
best = { semi, fifth: tone.fifth };
|
|
14676
|
+
}
|
|
14677
|
+
}
|
|
14678
|
+
}
|
|
14679
|
+
return best ?? nearestChordTone(melodySemi + offset, tones, 2);
|
|
14680
|
+
};
|
|
14163
14681
|
var SUBMELODY_LOW = 55;
|
|
14164
14682
|
var SUBMELODY_HIGH = 74;
|
|
14165
14683
|
var BASS_LOW = 33;
|
|
@@ -14341,9 +14859,12 @@ var barDegrees = (role, slots, tones, style, motifContour, startDegree, contourO
|
|
|
14341
14859
|
}
|
|
14342
14860
|
return out;
|
|
14343
14861
|
};
|
|
14344
|
-
var fitMotif = (degrees, slots, tones, prevSemi, quarterSteps, pentatonic) => {
|
|
14862
|
+
var fitMotif = (degrees, slots, tones, prevSemi, quarterSteps, pentatonic, preferShift) => {
|
|
14345
14863
|
let best = degrees;
|
|
14864
|
+
let bestShift = 0;
|
|
14346
14865
|
let bestScore = Number.NEGATIVE_INFINITY;
|
|
14866
|
+
let preferScore = Number.NEGATIVE_INFINITY;
|
|
14867
|
+
let preferMoved = null;
|
|
14347
14868
|
for (let shift = -3; shift <= 3; shift++) {
|
|
14348
14869
|
const moved = degrees.map(
|
|
14349
14870
|
(d) => pentatonic ? pentaToDegree(degreeToPenta(d) + shift) : d + shift
|
|
@@ -14365,12 +14886,19 @@ var fitMotif = (degrees, slots, tones, prevSemi, quarterSteps, pentatonic) => {
|
|
|
14365
14886
|
MELODY_HIGH
|
|
14366
14887
|
);
|
|
14367
14888
|
score -= Math.max(0, Math.abs(head - prevSemi) - MAX_BAR_LEAP_SEMITONES);
|
|
14889
|
+
if (shift === preferShift) {
|
|
14890
|
+
preferScore = score;
|
|
14891
|
+
preferMoved = moved;
|
|
14892
|
+
}
|
|
14368
14893
|
if (score > bestScore) {
|
|
14369
14894
|
bestScore = score;
|
|
14895
|
+
bestShift = shift;
|
|
14370
14896
|
best = moved;
|
|
14371
14897
|
}
|
|
14372
14898
|
}
|
|
14373
|
-
|
|
14899
|
+
if (preferMoved !== null && preferScore >= bestScore - 3)
|
|
14900
|
+
return { degrees: preferMoved, shift: preferShift };
|
|
14901
|
+
return { degrees: best, shift: bestShift };
|
|
14374
14902
|
};
|
|
14375
14903
|
var shapeBar = (degrees, slots, tones, prevSemi, opts) => {
|
|
14376
14904
|
const out = [];
|
|
@@ -14543,9 +15071,24 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14543
15071
|
options.template
|
|
14544
15072
|
);
|
|
14545
15073
|
const totalBars = sectionPlan.reduce((sum, s) => sum + s.bars, 0);
|
|
14546
|
-
|
|
15074
|
+
const relativeKinds = /* @__PURE__ */ new Set();
|
|
15075
|
+
let relativeShift = 0;
|
|
15076
|
+
if (rnd() < 0.25) {
|
|
15077
|
+
for (const kind of pick(
|
|
15078
|
+
[["prechorus"], ["bridge"], ["prechorus", "bridge"]],
|
|
15079
|
+
rnd
|
|
15080
|
+
))
|
|
15081
|
+
relativeKinds.add(kind);
|
|
15082
|
+
if (rnd() < 0.33) relativeShift = resolvedKey.mode === "minor" ? -3 : 3;
|
|
15083
|
+
}
|
|
15084
|
+
const floating = rnd() < 0.12;
|
|
15085
|
+
if (relativeKinds.size > 0 && relativeShift !== 0) {
|
|
15086
|
+
for (const s of sectionPlan)
|
|
15087
|
+
if (relativeKinds.has(s.kind)) s.keyShift = relativeShift;
|
|
15088
|
+
}
|
|
15089
|
+
if (relativeKinds.size === 0 && !floating && rnd() < 0.32) {
|
|
14547
15090
|
const modType = pick(
|
|
14548
|
-
["chorus_up", "chorus_up", "
|
|
15091
|
+
["chorus_up", "chorus_up", "color", "dominant", "subdominant"],
|
|
14549
15092
|
rnd
|
|
14550
15093
|
);
|
|
14551
15094
|
if (modType === "chorus_up") {
|
|
@@ -14554,15 +15097,83 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14554
15097
|
for (let i2 = 0; i2 < sectionPlan.length; i2++) {
|
|
14555
15098
|
if (sectionPlan[i2].kind === "chorus") lastChorusIdx = i2;
|
|
14556
15099
|
}
|
|
14557
|
-
if (lastChorusIdx >= 0)
|
|
14558
|
-
for (let i2 = lastChorusIdx; i2 < sectionPlan.length; i2++)
|
|
15100
|
+
if (lastChorusIdx >= 0)
|
|
15101
|
+
for (let i2 = lastChorusIdx; i2 < sectionPlan.length; i2++)
|
|
14559
15102
|
sectionPlan[i2].keyShift = shift;
|
|
14560
|
-
}
|
|
14561
|
-
}
|
|
14562
15103
|
} else {
|
|
14563
|
-
const shift = pick([-2, 3], rnd);
|
|
14564
|
-
|
|
14565
|
-
|
|
15104
|
+
const shift = modType === "dominant" ? 7 : modType === "subdominant" ? 5 : pick([-2, 3], rnd);
|
|
15105
|
+
const kinds = pick(
|
|
15106
|
+
[["prechorus"], ["bridge"], ["prechorus", "bridge"]],
|
|
15107
|
+
rnd
|
|
15108
|
+
);
|
|
15109
|
+
for (const s of sectionPlan)
|
|
15110
|
+
if (kinds.includes(s.kind)) s.keyShift = shift;
|
|
15111
|
+
}
|
|
15112
|
+
}
|
|
15113
|
+
const harmonyFrom = pick(
|
|
15114
|
+
["chorus", "chorus", "prechorus"],
|
|
15115
|
+
rnd
|
|
15116
|
+
);
|
|
15117
|
+
const harmonyParallel = rnd() < 0.45;
|
|
15118
|
+
const harmonyCoverage = 0.7 + rnd() * 0.3;
|
|
15119
|
+
const useHarmony2 = rnd() < 0.3;
|
|
15120
|
+
const useOctaveLayer = !useHarmony2 && rnd() < 0.25;
|
|
15121
|
+
const octaveCoverage = 0.3 + rnd() * 0.3;
|
|
15122
|
+
const harmonyOffset = useHarmony2 ? (
|
|
15123
|
+
// 3声のときは1声目を下〜ユニゾン側へ寄せ、2声目を上へ回して主旋律を挟む
|
|
15124
|
+
// (参考: チョウチン少女 ch12/ch11/ch13)。
|
|
15125
|
+
pick([-5, -3, 0, 0, 3], rnd)
|
|
15126
|
+
) : harmonyParallel ? pick([3, 4, 5, 9, 7, 0, -5], rnd) : pick([3, 4, 5, 0, -5, -4, -7], rnd);
|
|
15127
|
+
let prevHarmony = null;
|
|
15128
|
+
let prevHarmony2 = null;
|
|
15129
|
+
const harmony2Offset = harmonyOffset + pick([9, 9, 9, 8, 7], rnd);
|
|
15130
|
+
const harmonyKinds = harmonyFrom === "prechorus" ? ["prechorus", "chorus", "bridge"] : ["chorus"];
|
|
15131
|
+
const duetStyle = pick(
|
|
15132
|
+
[
|
|
15133
|
+
"none",
|
|
15134
|
+
"none",
|
|
15135
|
+
"none",
|
|
15136
|
+
"none",
|
|
15137
|
+
"none",
|
|
15138
|
+
"section",
|
|
15139
|
+
"phrase",
|
|
15140
|
+
"chorus",
|
|
15141
|
+
"verse"
|
|
15142
|
+
],
|
|
15143
|
+
rnd
|
|
15144
|
+
);
|
|
15145
|
+
const duetOwner = new Array(totalBars).fill(false);
|
|
15146
|
+
if (duetStyle !== "none") {
|
|
15147
|
+
let melodySection = 0;
|
|
15148
|
+
for (const section of sectionPlan) {
|
|
15149
|
+
if (!section.spec.melody) continue;
|
|
15150
|
+
const isChorus = section.kind === "chorus" || section.kind === "drop_chorus";
|
|
15151
|
+
const isVerse = section.kind === "verse";
|
|
15152
|
+
const takeSection = melodySection % 2 === 1;
|
|
15153
|
+
melodySection++;
|
|
15154
|
+
const alternate = duetStyle === "phrase" ? !isChorus : duetStyle === "chorus" ? isChorus : duetStyle === "verse" ? isVerse : false;
|
|
15155
|
+
if (!alternate && !(duetStyle === "section" && takeSection && !isChorus))
|
|
15156
|
+
continue;
|
|
15157
|
+
for (let b = section.startBar; b < section.startBar + section.bars; b++) {
|
|
15158
|
+
if (alternate) {
|
|
15159
|
+
if (Math.floor((b - section.startBar) / 2) % 2 === 1)
|
|
15160
|
+
duetOwner[b] = true;
|
|
15161
|
+
} else duetOwner[b] = true;
|
|
15162
|
+
}
|
|
15163
|
+
}
|
|
15164
|
+
}
|
|
15165
|
+
const duetSpans = [];
|
|
15166
|
+
{
|
|
15167
|
+
let from = -1;
|
|
15168
|
+
for (let b = 0; b <= totalBars; b++) {
|
|
15169
|
+
const owned = b < totalBars && duetOwner[b];
|
|
15170
|
+
if (owned && from < 0) from = b;
|
|
15171
|
+
if (!owned && from >= 0) {
|
|
15172
|
+
const lead = from === 0 ? 0 : scaleStep(
|
|
15173
|
+
pick([0, 0, EIGHTH, EIGHTH, QUARTER, DOT_QUARTER], rnd)
|
|
15174
|
+
);
|
|
15175
|
+
duetSpans.push([from * stepsPerBar - lead, b * stepsPerBar]);
|
|
15176
|
+
from = -1;
|
|
14566
15177
|
}
|
|
14567
15178
|
}
|
|
14568
15179
|
}
|
|
@@ -14573,41 +15184,114 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14573
15184
|
}
|
|
14574
15185
|
}
|
|
14575
15186
|
const progAPool = resolvedKey.mode === "major" ? SECTION_A_PROGRESSIONS.filter((p) => !p[0].startsWith("Am")) : resolvedKey.mode === "minor" ? SECTION_A_PROGRESSIONS.filter((p) => p[0].startsWith("Am")) : SECTION_A_PROGRESSIONS;
|
|
14576
|
-
const
|
|
15187
|
+
const withoutTonic = (pool, root) => {
|
|
15188
|
+
const isTonic = (c) => root === "Am" ? /^Am/.test(c) : /^C(?![#b]|m)/.test(c);
|
|
15189
|
+
const out = pool.filter((p) => !p.some(isTonic));
|
|
15190
|
+
return out.length > 0 ? out : pool;
|
|
15191
|
+
};
|
|
15192
|
+
const homeRoot = resolvedKey.mode === "minor" ? "Am" : "C";
|
|
15193
|
+
const progA = pick(
|
|
15194
|
+
floating ? withoutTonic(progAPool, homeRoot) : progAPool,
|
|
15195
|
+
rnd
|
|
15196
|
+
);
|
|
14577
15197
|
const progBPool = SECTION_B_PROGRESSIONS.filter(
|
|
14578
15198
|
(p) => p.join("|") !== progA.join("|")
|
|
14579
15199
|
);
|
|
14580
|
-
const progB = pick(
|
|
15200
|
+
const progB = pick(
|
|
15201
|
+
floating ? withoutTonic(progBPool, homeRoot) : progBPool,
|
|
15202
|
+
rnd
|
|
15203
|
+
);
|
|
15204
|
+
const progRelativePool = SECTION_A_PROGRESSIONS.filter(
|
|
15205
|
+
(p) => resolvedKey.mode === "minor" ? !p[0].startsWith("Am") : p[0].startsWith("Am")
|
|
15206
|
+
);
|
|
15207
|
+
const progRelative = pick(
|
|
15208
|
+
floating ? withoutTonic(progRelativePool, homeRoot) : progRelativePool,
|
|
15209
|
+
rnd
|
|
15210
|
+
);
|
|
15211
|
+
const progCPool = SECTION_C_PROGRESSIONS.filter(
|
|
15212
|
+
(p) => p.join("|") !== progA.join("|") && p.join("|") !== progB.join("|")
|
|
15213
|
+
);
|
|
14581
15214
|
const progC = pick(
|
|
14582
|
-
|
|
14583
|
-
(p) => p.join("|") !== progA.join("|") && p.join("|") !== progB.join("|")
|
|
14584
|
-
),
|
|
15215
|
+
floating ? withoutTonic(progCPool, homeRoot) : progCPool,
|
|
14585
15216
|
rnd
|
|
14586
15217
|
);
|
|
14587
15218
|
const tonic = progA[0].startsWith("Am") ? "Am" : "C";
|
|
14588
15219
|
const progHalf = pick(SECTION_A2_DERIVATIONS, rnd)(progA);
|
|
14589
15220
|
const progFull = pick(SECTION_A3_DERIVATIONS, rnd)(progA, tonic);
|
|
15221
|
+
const progDeceptive = pick(SECTION_DECEPTIVE_DERIVATIONS, rnd)(progA, tonic);
|
|
15222
|
+
let lastChorusBar = -1;
|
|
15223
|
+
for (const section of sectionPlan)
|
|
15224
|
+
if (section.kind === "chorus" || section.kind === "outro")
|
|
15225
|
+
lastChorusBar = section.startBar;
|
|
14590
15226
|
const progression = [];
|
|
14591
15227
|
for (const section of sectionPlan) {
|
|
14592
|
-
const base = section.spec.progression === "c" ? progC : section.spec.progression === "b" ? progB : progA;
|
|
15228
|
+
const base = relativeKinds.has(section.kind) ? progRelative : section.spec.progression === "c" ? progC : section.spec.progression === "b" ? progB : progA;
|
|
14593
15229
|
for (let i2 = 0; i2 < section.bars; i2 += 4) {
|
|
14594
15230
|
const isLastPhrase = i2 + 4 >= section.bars;
|
|
14595
15231
|
if (!isLastPhrase) {
|
|
14596
15232
|
progression.push(...base);
|
|
14597
15233
|
continue;
|
|
14598
15234
|
}
|
|
14599
|
-
if (section.kind
|
|
15235
|
+
if (relativeKinds.has(section.kind)) progression.push(...base);
|
|
15236
|
+
else if (section.kind === "prechorus") progression.push(...progHalf);
|
|
14600
15237
|
else if (section.kind === "chorus" || section.kind === "outro")
|
|
14601
|
-
progression.push(
|
|
15238
|
+
progression.push(
|
|
15239
|
+
...floating ? progHalf : section.startBar === lastChorusBar ? progFull : progDeceptive
|
|
15240
|
+
);
|
|
14602
15241
|
else progression.push(...base);
|
|
14603
15242
|
}
|
|
14604
15243
|
}
|
|
14605
15244
|
progression.length = totalBars;
|
|
15245
|
+
const PIVOT_CHORDS = {
|
|
15246
|
+
7: ["C", "Em7", "G", "Am"],
|
|
15247
|
+
// 属調(ト長調)と共通
|
|
15248
|
+
5: ["C", "Dm7", "F", "Am"]
|
|
15249
|
+
// 下属調(ヘ長調)と共通
|
|
15250
|
+
};
|
|
15251
|
+
for (let bar = 1; bar < totalBars; bar++) {
|
|
15252
|
+
const shift = barKeyShift[bar];
|
|
15253
|
+
const prev = barKeyShift[bar - 1];
|
|
15254
|
+
if (shift === prev) continue;
|
|
15255
|
+
const distance = fifthsDistance(shift - prev);
|
|
15256
|
+
if (distance >= 4) continue;
|
|
15257
|
+
const prevSec = sectionAt(sectionPlan, bar - 1);
|
|
15258
|
+
if (prevSec.kind === "prechorus" || prevSec.kind === "chorus" || prevSec.kind === "outro")
|
|
15259
|
+
continue;
|
|
15260
|
+
if (rnd() < 0.35) continue;
|
|
15261
|
+
const pivots = PIVOT_CHORDS[((shift - prev) % 12 + 12) % 12];
|
|
15262
|
+
if (distance <= 1 && pivots && rnd() < 0.6) {
|
|
15263
|
+
progression[bar - 1] = pick(pivots, rnd);
|
|
15264
|
+
} else {
|
|
15265
|
+
progression[bar - 1] = transposeChordName("G7", shift - prev);
|
|
15266
|
+
}
|
|
15267
|
+
}
|
|
15268
|
+
if (rnd() < 0.3) {
|
|
15269
|
+
const tonicNames = tonic === "Am" ? ["Am", "Am7"] : ["C", "CM7"];
|
|
15270
|
+
const spots = [];
|
|
15271
|
+
for (let bar = 0; bar + 1 < totalBars; bar++) {
|
|
15272
|
+
if (barKeyShift[bar] !== barKeyShift[bar + 1]) continue;
|
|
15273
|
+
if (!MODAL_BORROW[progression[bar]]) continue;
|
|
15274
|
+
if (!tonicNames.includes(progression[bar + 1])) continue;
|
|
15275
|
+
spots.push(bar);
|
|
15276
|
+
}
|
|
15277
|
+
if (spots.length > 0) {
|
|
15278
|
+
const at = pick(spots, rnd);
|
|
15279
|
+
progression[at] = MODAL_BORROW[progression[at]];
|
|
15280
|
+
}
|
|
15281
|
+
}
|
|
14606
15282
|
const chordProgression = progression.map((chord, bar) => transposeChordName(chord, barKeyShift[bar])).join("|");
|
|
14607
|
-
const chordPattern = pick(CHORD_PATTERNS, rnd);
|
|
14608
15283
|
const rootShift = resolvedKey.rootShift;
|
|
14609
15284
|
const bpm = pick(BPM_CHOICES, rnd);
|
|
15285
|
+
const chordPattern = pick(chordPatternPool(bpm), rnd);
|
|
14610
15286
|
const sourceOf = (kind) => kind === "chorus" || kind === "interlude" || kind === "drop_chorus" ? "b" : kind === "prechorus" ? "a2" : kind === "bridge" ? "c" : "a";
|
|
15287
|
+
const landingOf = (section) => {
|
|
15288
|
+
if (section.spec.landing === null) return null;
|
|
15289
|
+
const minorHere = resolvedKey.mode === "minor" !== relativeKinds.has(section.kind);
|
|
15290
|
+
let landing = (section.spec.landing + (minorHere ? 5 : 0)) % 7;
|
|
15291
|
+
if (floating && landing === (minorHere ? 5 : 0))
|
|
15292
|
+
landing = (landing + pick([2, 4], rnd)) % 7;
|
|
15293
|
+
return landing;
|
|
15294
|
+
};
|
|
14611
15295
|
const units2 = [];
|
|
14612
15296
|
for (const section of sectionPlan) {
|
|
14613
15297
|
const unitCount = Math.max(1, Math.round(section.bars / 2));
|
|
@@ -14625,22 +15309,28 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14625
15309
|
const isLast = u === unitCount - 1;
|
|
14626
15310
|
if (u % 2 === 0) {
|
|
14627
15311
|
units2.push({
|
|
14628
|
-
role: section.kind === "chorus" ? "climax" : src === "a2" || u > 0 ? "sequence" : "motif",
|
|
15312
|
+
role: section.kind === "bridge" ? "step" : section.kind === "chorus" ? "climax" : src === "a2" || u > 0 ? "sequence" : "motif",
|
|
14629
15313
|
source: src,
|
|
14630
15314
|
landing: null,
|
|
14631
15315
|
section
|
|
14632
15316
|
});
|
|
14633
15317
|
} else {
|
|
15318
|
+
const landing = landingOf(section);
|
|
14634
15319
|
units2.push({
|
|
14635
|
-
role: isLast &&
|
|
15320
|
+
role: isLast && landing === 0 ? "cadence" : "answer",
|
|
14636
15321
|
source: "answer",
|
|
14637
|
-
landing: isLast ?
|
|
15322
|
+
landing: isLast ? landing : null,
|
|
14638
15323
|
section
|
|
14639
15324
|
});
|
|
14640
15325
|
}
|
|
14641
15326
|
}
|
|
14642
15327
|
}
|
|
14643
15328
|
const barRoles = units2.flatMap((u) => [u.role, u.role]);
|
|
15329
|
+
for (const section of sectionPlan) {
|
|
15330
|
+
if (section.kind !== "prechorus") continue;
|
|
15331
|
+
const last = section.startBar + section.bars - 1;
|
|
15332
|
+
if (last < barRoles.length) barRoles[last] = "run";
|
|
15333
|
+
}
|
|
14644
15334
|
const barInUnit = (bar) => bar % 2;
|
|
14645
15335
|
const unitOf = (bar) => Math.floor(bar / 2);
|
|
14646
15336
|
const restatementOf = (bar) => {
|
|
@@ -14671,8 +15361,9 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14671
15361
|
groove: pick(["eighth", "sixteenth"], rnd),
|
|
14672
15362
|
arcPeriod: pick([4, 8, 8, 16], rnd),
|
|
14673
15363
|
arcPhase: pick([0, 1, 2], rnd),
|
|
14674
|
-
arcAmp:
|
|
14675
|
-
|
|
15364
|
+
arcAmp: 2 + rnd() * 3,
|
|
15365
|
+
// オクターブ跳躍は参考曲では音程の1.0%しかない。上げすぎると音域が広がる。
|
|
15366
|
+
octaveAffinity: 0.06 + rnd() * 0.12,
|
|
14676
15367
|
pentatonicMotif: rnd() < 0.55,
|
|
14677
15368
|
runShape: pick(["scale", "turn", "broken", "zigzag"], rnd),
|
|
14678
15369
|
stepShape: pick(
|
|
@@ -14684,10 +15375,14 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14684
15375
|
["descend", "five-three-one", "leap-up", "hold-tonic"],
|
|
14685
15376
|
rnd
|
|
14686
15377
|
),
|
|
14687
|
-
//
|
|
14688
|
-
|
|
15378
|
+
// 参考曲の跳躍率は p25〜p75 で 0.28〜0.41、最大跳躍の中央値は9半音。
|
|
15379
|
+
// 2声を交互に書いたチャンネルを主旋律と誤検出していた頃は 0.31〜0.65 に
|
|
15380
|
+
// 見えており、それに合わせて上限を高く取っていた。
|
|
15381
|
+
leapAffinity: 0.05 + rnd() * 0.2,
|
|
14689
15382
|
// 界隈曲らしさ:調の外の音(クロマチック)や微小な逸脱を積極的に許容する。
|
|
14690
|
-
|
|
15383
|
+
// 刻みを細かくすると経過音の置き場所が増えるので、同じ係数でも変化音は増える。
|
|
15384
|
+
// 参考曲の1.75倍まで伸びていたぶんを引く。
|
|
15385
|
+
chromaticAffinity: rnd() < 0.2 ? 0 : 0.12 + rnd() * 0.33,
|
|
14691
15386
|
barHeadWeight: rnd() < 0.5 ? 3 : 2,
|
|
14692
15387
|
bassStyle: pick(
|
|
14693
15388
|
[
|
|
@@ -14714,7 +15409,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14714
15409
|
subInterval: pick([3, 4, 8, 9], rnd)
|
|
14715
15410
|
};
|
|
14716
15411
|
const motifPool = groovyCells(MOTIF_CELLS, style.groove, rnd);
|
|
14717
|
-
const targetNotesPerBar = 4 + rnd() * 4;
|
|
15412
|
+
const targetNotesPerBar = 4.5 + rnd() * 4.5;
|
|
14718
15413
|
const targetRestRatio = 0.02 + rnd() * 0.1;
|
|
14719
15414
|
const cellNotes = (c) => c.value.filter((v) => v > 0).length;
|
|
14720
15415
|
const cellRest = (c) => {
|
|
@@ -14727,17 +15422,27 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14727
15422
|
return total === 0 ? 0 : rest / total;
|
|
14728
15423
|
};
|
|
14729
15424
|
const cellDistance = (c, densityMul = 1) => Math.abs(cellNotes(c) - targetNotesPerBar * densityMul) + Math.abs(cellRest(c) - targetRestRatio / Math.max(0.5, densityMul)) * 8;
|
|
15425
|
+
const weightedPick = (pool) => {
|
|
15426
|
+
let total = 0;
|
|
15427
|
+
for (const c of pool) total += cellWeight(c);
|
|
15428
|
+
let r = rnd() * total;
|
|
15429
|
+
for (const c of pool) {
|
|
15430
|
+
r -= cellWeight(c);
|
|
15431
|
+
if (r <= 0) return c;
|
|
15432
|
+
}
|
|
15433
|
+
return pool[pool.length - 1];
|
|
15434
|
+
};
|
|
14730
15435
|
const pickCell = (pool, densityMul = 1) => {
|
|
14731
|
-
let best =
|
|
15436
|
+
let best = weightedPick(pool);
|
|
14732
15437
|
for (let i2 = 0; i2 < 2; i2++) {
|
|
14733
|
-
const c =
|
|
15438
|
+
const c = weightedPick(pool);
|
|
14734
15439
|
if (cellDistance(c, densityMul) < cellDistance(best, densityMul))
|
|
14735
15440
|
best = c;
|
|
14736
15441
|
}
|
|
14737
15442
|
return best;
|
|
14738
15443
|
};
|
|
14739
15444
|
const motifCell = pickCell(motifPool, 0.85);
|
|
14740
|
-
const motifCell2 = rnd() < 0.
|
|
15445
|
+
const motifCell2 = rnd() < 0.72 ? motifCell : pickCell(
|
|
14741
15446
|
motifPool.filter((c) => c !== motifCell),
|
|
14742
15447
|
0.85
|
|
14743
15448
|
);
|
|
@@ -14755,7 +15460,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14755
15460
|
),
|
|
14756
15461
|
1.1
|
|
14757
15462
|
);
|
|
14758
|
-
const motifA22 = rnd() < 0.
|
|
15463
|
+
const motifA22 = rnd() < 0.72 ? motifA2 : pickCell(
|
|
14759
15464
|
motifPool.filter((c) => c !== motifA2),
|
|
14760
15465
|
1.1
|
|
14761
15466
|
);
|
|
@@ -14765,7 +15470,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14765
15470
|
),
|
|
14766
15471
|
0.9
|
|
14767
15472
|
);
|
|
14768
|
-
const motifC2 = rnd() < 0.
|
|
15473
|
+
const motifC2 = rnd() < 0.72 ? motifC : pickCell(
|
|
14769
15474
|
motifPool.filter((c) => c !== motifC),
|
|
14770
15475
|
0.9
|
|
14771
15476
|
);
|
|
@@ -14804,12 +15509,24 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14804
15509
|
),
|
|
14805
15510
|
rnd
|
|
14806
15511
|
).value;
|
|
14807
|
-
const
|
|
14808
|
-
|
|
14809
|
-
|
|
14810
|
-
)
|
|
14811
|
-
|
|
14812
|
-
|
|
15512
|
+
const breathBySection = /* @__PURE__ */ new Map();
|
|
15513
|
+
{
|
|
15514
|
+
let prev = null;
|
|
15515
|
+
for (const section of sectionPlan) {
|
|
15516
|
+
if (!section.spec.melody) continue;
|
|
15517
|
+
const pool = PHRASE_END_CELLS.filter((c) => c !== prev);
|
|
15518
|
+
const cell = pick(pool.length > 0 ? pool : PHRASE_END_CELLS, rnd);
|
|
15519
|
+
breathBySection.set(section.startBar, cell);
|
|
15520
|
+
prev = cell;
|
|
15521
|
+
}
|
|
15522
|
+
}
|
|
15523
|
+
const midBreathCell = pick(MID_BREATH_CELLS, rnd);
|
|
15524
|
+
const breathBars = /* @__PURE__ */ new Set();
|
|
15525
|
+
const phraseEndBars = /* @__PURE__ */ new Set();
|
|
15526
|
+
for (const section of sectionPlan) {
|
|
15527
|
+
if (!section.spec.melody) continue;
|
|
15528
|
+
phraseEndBars.add(section.startBar + section.bars - 1);
|
|
15529
|
+
}
|
|
14813
15530
|
const barRhythms = [];
|
|
14814
15531
|
for (let bar = 0; bar < totalBars; bar++) {
|
|
14815
15532
|
const u = unitOf(bar);
|
|
@@ -14817,6 +15534,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14817
15534
|
const source = restatementOf(bar);
|
|
14818
15535
|
if (source !== null) {
|
|
14819
15536
|
barRhythms.push(barRhythms[source]);
|
|
15537
|
+
if (breathBars.has(source)) breathBars.add(bar);
|
|
14820
15538
|
continue;
|
|
14821
15539
|
}
|
|
14822
15540
|
const isB = units2[u].source === "b";
|
|
@@ -14834,7 +15552,14 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14834
15552
|
const prevSource = units2[u - 1]?.source;
|
|
14835
15553
|
const [head, tail] = prevSource === "b" ? [motifB, motifB2] : prevSource === "a2" ? [motifA2, motifA22] : [motifCell, motifCell2];
|
|
14836
15554
|
const answerVar = prevSource === "b" ? motifBVar : motifVar;
|
|
14837
|
-
|
|
15555
|
+
if (half === 0) {
|
|
15556
|
+
cell = rnd() < 0.15 ? answerVar : head;
|
|
15557
|
+
} else if (isPeriodEnd) {
|
|
15558
|
+
cell = breathBySection.get(units2[u].section.startBar) ?? tail;
|
|
15559
|
+
breathBars.add(bar);
|
|
15560
|
+
} else {
|
|
15561
|
+
cell = rnd() < 0.28 ? midBreathCell : rnd() < 0.12 ? answerVar : tail;
|
|
15562
|
+
}
|
|
14838
15563
|
} else {
|
|
14839
15564
|
const [head, tail] = pair();
|
|
14840
15565
|
cell = half === 0 ? head : tail;
|
|
@@ -14855,10 +15580,12 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14855
15580
|
motifContour.push(baseDegree + archetype[idx]);
|
|
14856
15581
|
}
|
|
14857
15582
|
const plannedDegrees = new Array(totalBars).fill(null);
|
|
15583
|
+
const motifShiftMemo = /* @__PURE__ */ new Map();
|
|
14858
15584
|
const melody = [];
|
|
14859
15585
|
const submelody = [];
|
|
14860
15586
|
const bass = [];
|
|
14861
15587
|
const harmony = [];
|
|
15588
|
+
const harmony2 = [];
|
|
14862
15589
|
const pad = [];
|
|
14863
15590
|
const melodyDurations = [];
|
|
14864
15591
|
const barTension = new Array(totalBars).fill(0);
|
|
@@ -14950,34 +15677,36 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14950
15677
|
if (landing !== null && barInUnit(bar) === 1) landOn(degrees, landing);
|
|
14951
15678
|
plannedDegrees[bar] = [...degrees];
|
|
14952
15679
|
const isMotifBar = source !== null || role === "motif" || role === "sequence" || role === "climax" || role === "answer";
|
|
14953
|
-
|
|
14954
|
-
|
|
15680
|
+
let fitted = degrees;
|
|
15681
|
+
if (isMotifBar) {
|
|
15682
|
+
const shiftKey = degrees.join(",");
|
|
15683
|
+
const r = fitMotif(
|
|
14955
15684
|
degrees,
|
|
14956
15685
|
slots,
|
|
14957
15686
|
tones,
|
|
14958
15687
|
prevSemi,
|
|
14959
15688
|
quarterSteps,
|
|
14960
|
-
style.pentatonicMotif
|
|
14961
|
-
|
|
14962
|
-
|
|
14963
|
-
|
|
14964
|
-
|
|
14965
|
-
|
|
14966
|
-
|
|
14967
|
-
|
|
14968
|
-
|
|
14969
|
-
|
|
14970
|
-
|
|
14971
|
-
|
|
14972
|
-
|
|
14973
|
-
|
|
14974
|
-
|
|
14975
|
-
|
|
14976
|
-
|
|
14977
|
-
|
|
14978
|
-
|
|
14979
|
-
|
|
14980
|
-
);
|
|
15689
|
+
style.pentatonicMotif,
|
|
15690
|
+
motifShiftMemo.get(shiftKey) ?? null
|
|
15691
|
+
);
|
|
15692
|
+
fitted = r.degrees;
|
|
15693
|
+
motifShiftMemo.set(shiftKey, r.shift);
|
|
15694
|
+
}
|
|
15695
|
+
const pitches = shapeBar(fitted, slots, tones, prevSemi, {
|
|
15696
|
+
allowLeap: role === "climax",
|
|
15697
|
+
allowArpeggio: role === "climax" || role === "run" && style.runShape === "broken" || role === "cadence" && style.cadenceShape !== "descend",
|
|
15698
|
+
quarterSteps,
|
|
15699
|
+
// モチーフの小節はオクターブ移動を入れない。モチーフは輪郭が命なので、
|
|
15700
|
+
// 後から音を1つ跳ばすと「同じフレーズが返ってきた」と分からなくなる。
|
|
15701
|
+
// モチーフ側は {@link MOTIF_ARCHETYPES} が自前でオクターブを持つ。
|
|
15702
|
+
// モチーフ・セクエンツ・サビの小節はオクターブ移動を入れない
|
|
15703
|
+
// (輪郭が命なので、後から音を1つ跳ばすと同じフレーズと分からなくなる)。
|
|
15704
|
+
// 答えの小節は輪郭を借りているだけなので許す。
|
|
15705
|
+
octaveAffinity: role === "motif" || role === "sequence" || role === "climax" ? 0 : style.octaveAffinity,
|
|
15706
|
+
chromaticAffinity: style.chromaticAffinity,
|
|
15707
|
+
rnd,
|
|
15708
|
+
preserveContour: isMotifBar
|
|
15709
|
+
});
|
|
14981
15710
|
if (landing !== null && barInUnit(bar) === 1) landPitch(pitches, landing);
|
|
14982
15711
|
const fifths = pitches.map(diatonicFifth);
|
|
14983
15712
|
applyChromatic(pitches, fifths, slots, tones, {
|
|
@@ -15102,23 +15831,50 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15102
15831
|
pushSub(scaleStep(QUARTER), scaleStep(DOT_HALF), subSemi);
|
|
15103
15832
|
}
|
|
15104
15833
|
const barSec = sectionAt(sectionPlan, bar);
|
|
15105
|
-
if (!silent && (barSec.kind
|
|
15106
|
-
|
|
15107
|
-
|
|
15108
|
-
|
|
15109
|
-
|
|
15110
|
-
const
|
|
15111
|
-
|
|
15112
|
-
|
|
15113
|
-
|
|
15114
|
-
|
|
15115
|
-
|
|
15116
|
-
|
|
15117
|
-
|
|
15118
|
-
|
|
15119
|
-
|
|
15120
|
-
|
|
15121
|
-
|
|
15834
|
+
if (!silent && harmonyKinds.includes(barSec.kind)) {
|
|
15835
|
+
const k = barKeyShift[bar];
|
|
15836
|
+
const fifthShift = k === 0 ? 0 : SEMITONE_TO_FIFTH_SHIFT[(k % 12 + 12) % 12];
|
|
15837
|
+
const writeHarmony = (out, prev, offset, against) => {
|
|
15838
|
+
let last = prev;
|
|
15839
|
+
const written = [];
|
|
15840
|
+
for (let i2 = 0; i2 < slots.length; i2++) {
|
|
15841
|
+
const hTone = harmonyPitch(
|
|
15842
|
+
pitches[i2],
|
|
15843
|
+
tones,
|
|
15844
|
+
last,
|
|
15845
|
+
offset,
|
|
15846
|
+
harmonyParallel,
|
|
15847
|
+
against?.[i2] ?? null
|
|
15848
|
+
);
|
|
15849
|
+
let hClamped = clampSemi(
|
|
15850
|
+
hTone.semi,
|
|
15851
|
+
MELODY_LOW - 12,
|
|
15852
|
+
MELODY_HIGH + 7
|
|
15853
|
+
);
|
|
15854
|
+
while (hClamped - pitches[i2] > 12) hClamped -= 12;
|
|
15855
|
+
while (hClamped - pitches[i2] < -12) hClamped += 12;
|
|
15856
|
+
last = hClamped;
|
|
15857
|
+
written.push(hClamped);
|
|
15858
|
+
const keep = slots[i2].isStrong || slots[i2].value >= quarterSteps || rnd() < harmonyCoverage;
|
|
15859
|
+
if (!keep) continue;
|
|
15860
|
+
out.push({
|
|
15861
|
+
startStep: barStart + slots[i2].at,
|
|
15862
|
+
pitchUnits: spelledToUnits(
|
|
15863
|
+
hClamped + k,
|
|
15864
|
+
hTone.fifth + fifthShift,
|
|
15865
|
+
edo
|
|
15866
|
+
),
|
|
15867
|
+
durationSteps: slots[i2].value,
|
|
15868
|
+
velocity: slots[i2].at === 0 ? 82 : 76
|
|
15869
|
+
});
|
|
15870
|
+
}
|
|
15871
|
+
return written;
|
|
15872
|
+
};
|
|
15873
|
+
const h1 = writeHarmony(harmony, prevHarmony, harmonyOffset, null);
|
|
15874
|
+
prevHarmony = h1[h1.length - 1] ?? prevHarmony;
|
|
15875
|
+
if (useHarmony2) {
|
|
15876
|
+
const h2 = writeHarmony(harmony2, prevHarmony2, harmony2Offset, h1);
|
|
15877
|
+
prevHarmony2 = h2[h2.length - 1] ?? prevHarmony2;
|
|
15122
15878
|
}
|
|
15123
15879
|
}
|
|
15124
15880
|
if (barSec.kind === "prechorus" || barSec.kind === "chorus" || barSec.kind === "bridge" || barSec.kind === "drop_chorus") {
|
|
@@ -15250,6 +16006,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15250
16006
|
for (const n of barBass) bass.push(n);
|
|
15251
16007
|
}
|
|
15252
16008
|
const eighthSteps = scaleStep(EIGHTH);
|
|
16009
|
+
const tieMemo = /* @__PURE__ */ new Map();
|
|
15253
16010
|
for (let i2 = 0; i2 < melody.length - 1; i2++) {
|
|
15254
16011
|
const cur = melody[i2];
|
|
15255
16012
|
const nxt = melody[i2 + 1];
|
|
@@ -15263,16 +16020,28 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15263
16020
|
const curSec = sectionAt(sectionPlan, barIdx - 1);
|
|
15264
16021
|
const nextSec = sectionAt(sectionPlan, barIdx);
|
|
15265
16022
|
if (!nextSec.spec.melody || curSec !== nextSec) continue;
|
|
16023
|
+
if (breathBars.has(barIdx)) continue;
|
|
15266
16024
|
const curSemi = Math.round(cur.pitchUnits / UNITS_PER_SEMITONE);
|
|
15267
16025
|
const nxtSemi = Math.round(nxt.pitchUnits / UNITS_PER_SEMITONE);
|
|
15268
16026
|
if (Math.abs(nxtSemi - curSemi) > 3) continue;
|
|
16027
|
+
const after = melody[i2 + 2];
|
|
16028
|
+
if (after && Math.floor(after.startStep / stepsPerBar) === barIdx) {
|
|
16029
|
+
const afterSemi = Math.round(after.pitchUnits / UNITS_PER_SEMITONE) - (barKeyShift[barIdx] ?? 0);
|
|
16030
|
+
if (!DIATONIC_PCS.has(pitchClass(afterSemi))) continue;
|
|
16031
|
+
}
|
|
15269
16032
|
const nextRole = barRoles[barIdx];
|
|
15270
|
-
let tieProb = 0.
|
|
15271
|
-
if (nextRole === "motif") tieProb = 0.
|
|
15272
|
-
else if (nextRole === "sequence") tieProb = 0.
|
|
15273
|
-
else if (nextRole === "climax") tieProb = 0.
|
|
16033
|
+
let tieProb = 0.3;
|
|
16034
|
+
if (nextRole === "motif") tieProb = 0.1;
|
|
16035
|
+
else if (nextRole === "sequence") tieProb = 0.35;
|
|
16036
|
+
else if (nextRole === "climax") tieProb = 0.45;
|
|
15274
16037
|
else if (nextRole === "cadence") tieProb = 0.1;
|
|
15275
|
-
|
|
16038
|
+
const tieKey = `${barRhythms[barIdx].join(",")}|${barInUnit(barIdx)}`;
|
|
16039
|
+
let tie = tieMemo.get(tieKey);
|
|
16040
|
+
if (tie === void 0) {
|
|
16041
|
+
tie = rnd() < tieProb;
|
|
16042
|
+
tieMemo.set(tieKey, tie);
|
|
16043
|
+
}
|
|
16044
|
+
if (tie) {
|
|
15276
16045
|
cur.durationSteps += nxt.durationSteps;
|
|
15277
16046
|
melody.splice(i2 + 1, 1);
|
|
15278
16047
|
if (i2 < melodyDurations.length - 1) {
|
|
@@ -15288,15 +16057,32 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15288
16057
|
i2--;
|
|
15289
16058
|
}
|
|
15290
16059
|
}
|
|
16060
|
+
const splitMemo = /* @__PURE__ */ new Map();
|
|
16061
|
+
let splitLastBar = -1;
|
|
16062
|
+
let splitIdxInBar = 0;
|
|
15291
16063
|
for (let i2 = 0; i2 < melody.length; i2++) {
|
|
15292
16064
|
const barIdx = Math.floor(melody[i2].startStep / stepsPerBar);
|
|
16065
|
+
if (barIdx !== splitLastBar) {
|
|
16066
|
+
splitLastBar = barIdx;
|
|
16067
|
+
splitIdxInBar = 0;
|
|
16068
|
+
} else splitIdxInBar++;
|
|
15293
16069
|
if (barIdx >= totalBars) continue;
|
|
16070
|
+
if (phraseEndBars.has(barIdx)) continue;
|
|
15294
16071
|
const role = barRoles[barIdx];
|
|
15295
|
-
let splitProb = 0.
|
|
16072
|
+
let splitProb = 0.08;
|
|
15296
16073
|
if (role === "motif" || role === "sequence") splitProb = 0;
|
|
15297
|
-
else if (role === "climax") splitProb = 0.
|
|
16074
|
+
else if (role === "climax") splitProb = 0.3;
|
|
15298
16075
|
else if (role === "cadence") splitProb = 0;
|
|
15299
|
-
|
|
16076
|
+
let doSplit = false;
|
|
16077
|
+
if (melody[i2].durationSteps === quarterSteps) {
|
|
16078
|
+
const key = `${barRhythms[barIdx].join(",")}|${barInUnit(barIdx)}|${role}|${splitIdxInBar}`;
|
|
16079
|
+
const memo = splitMemo.get(key);
|
|
16080
|
+
if (memo === void 0) {
|
|
16081
|
+
doSplit = rnd() < splitProb;
|
|
16082
|
+
splitMemo.set(key, doSplit);
|
|
16083
|
+
} else doSplit = memo;
|
|
16084
|
+
}
|
|
16085
|
+
if (doSplit) {
|
|
15300
16086
|
const half = scaleStep(EIGHTH);
|
|
15301
16087
|
const newNote = {
|
|
15302
16088
|
...melody[i2],
|
|
@@ -15310,6 +16096,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15310
16096
|
melodyDurations.splice(i2 + 1, 0, half);
|
|
15311
16097
|
}
|
|
15312
16098
|
i2++;
|
|
16099
|
+
splitIdxInBar++;
|
|
15313
16100
|
}
|
|
15314
16101
|
}
|
|
15315
16102
|
const range = (notes) => {
|
|
@@ -15319,8 +16106,11 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15319
16106
|
};
|
|
15320
16107
|
const shiftUnits = semitonesToUnits(rootShift, edo);
|
|
15321
16108
|
if (shiftUnits !== 0)
|
|
15322
|
-
for (const list of [melody, submelody, bass, harmony, pad])
|
|
16109
|
+
for (const list of [melody, submelody, bass, harmony, harmony2, pad])
|
|
15323
16110
|
for (const n of list) n.pitchUnits = n.pitchUnits + shiftUnits;
|
|
16111
|
+
const octave = useOctaveLayer ? melody.filter(
|
|
16112
|
+
(n) => n.durationSteps >= quarterSteps || rnd() < octaveCoverage
|
|
16113
|
+
).map((n) => ({ ...n, velocity: Math.max(40, n.velocity - 26) })) : [];
|
|
15324
16114
|
return {
|
|
15325
16115
|
chordProgression,
|
|
15326
16116
|
chordPattern,
|
|
@@ -15331,10 +16121,20 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15331
16121
|
bpm,
|
|
15332
16122
|
sections: sectionPlan,
|
|
15333
16123
|
bars: totalBars,
|
|
16124
|
+
vocal: {
|
|
16125
|
+
duetSpans,
|
|
16126
|
+
duetStyle,
|
|
16127
|
+
harmonyKinds,
|
|
16128
|
+
harmony2: useHarmony2,
|
|
16129
|
+
octaveLayer: useOctaveLayer
|
|
16130
|
+
},
|
|
16131
|
+
tonal: { relativeKinds: [...relativeKinds], relativeShift, floating },
|
|
15334
16132
|
melody,
|
|
15335
16133
|
submelody,
|
|
15336
16134
|
bass,
|
|
15337
16135
|
harmony,
|
|
16136
|
+
harmony2,
|
|
16137
|
+
octave,
|
|
15338
16138
|
pad,
|
|
15339
16139
|
melodyDurations,
|
|
15340
16140
|
restSteps,
|
|
@@ -15406,6 +16206,8 @@ var evaluate = (d, recent) => {
|
|
|
15406
16206
|
melodyRange: atc("melodyRange", d.melodyRange),
|
|
15407
16207
|
notesPerBar: atc("notesPerBar", density.notesPerBar),
|
|
15408
16208
|
shortNoteRatio: atc("shortNoteRatio", density.shortNoteRatio),
|
|
16209
|
+
barDensityCv: atc("barDensityCv", density.barDensityCv),
|
|
16210
|
+
densityCliff: atc("densityCliff", density.densityCliff),
|
|
15409
16211
|
stepRatio: atc("stepRatio", d.stepRatio),
|
|
15410
16212
|
chromaticRatio: atc("chromaticRatio", d.chromaticRatio),
|
|
15411
16213
|
sim1: atc("sim1", structure.sim1),
|
|
@@ -15413,12 +16215,20 @@ var evaluate = (d, recent) => {
|
|
|
15413
16215
|
sim4: atc("sim4", structure.sim4),
|
|
15414
16216
|
sim8: atc("sim8", structure.sim8),
|
|
15415
16217
|
phraseBreath: atc("phraseBreath", structure.phraseBreath),
|
|
16218
|
+
turnRatio: atc("turnRatio", structure.turnRatio),
|
|
15416
16219
|
climaxPosition: atc("climaxPosition", structure.climaxPosition),
|
|
15417
16220
|
climaxPeaks: at(peakBand, structure.climaxPeaks),
|
|
15418
16221
|
complementarity: at(HAND_BANDS.complementarity, structure.complementarity),
|
|
15419
16222
|
subDensity: at(HAND_BANDS.subDensity, d.submelody.length / d.bars),
|
|
16223
|
+
// サブメロにも同じ崖の物差しを当てる。帯はメロディから採ったものを流用する。
|
|
16224
|
+
subDensityCliff: atc(
|
|
16225
|
+
"densityCliff",
|
|
16226
|
+
densityFeatures(fromMelody(toMetricNotes(d.submelody)), opts).densityCliff
|
|
16227
|
+
),
|
|
15420
16228
|
tensionRise: tension.rise,
|
|
15421
|
-
|
|
16229
|
+
// **浮遊感の曲に「終止で解決しろ」は要求しない。** 解決しないことが狙いなので、
|
|
16230
|
+
// この項目で減点すると候補40本の選抜で必ず負けて、狙って引いた曲が出てこない。
|
|
16231
|
+
tensionResolve: d.tonal.floating ? 1 : tension.resolve,
|
|
15422
16232
|
novelty
|
|
15423
16233
|
};
|
|
15424
16234
|
let weighted = 0;
|
|
@@ -15481,10 +16291,14 @@ var composeSong = (options) => {
|
|
|
15481
16291
|
bpm: d.bpm,
|
|
15482
16292
|
sections: d.sections,
|
|
15483
16293
|
bars: d.bars,
|
|
16294
|
+
vocal: d.vocal,
|
|
16295
|
+
tonal: d.tonal,
|
|
15484
16296
|
melody: d.melody,
|
|
15485
16297
|
submelody: d.submelody,
|
|
15486
16298
|
bass: d.bass,
|
|
15487
16299
|
harmony: d.harmony,
|
|
16300
|
+
harmony2: d.harmony2,
|
|
16301
|
+
octave: d.octave,
|
|
15488
16302
|
pad: d.pad,
|
|
15489
16303
|
stats: { ...stats, attempts: attempt, rejected }
|
|
15490
16304
|
};
|
|
@@ -15499,7 +16313,10 @@ var composeSong = (options) => {
|
|
|
15499
16313
|
var pickBuiltinDrum = (song, rnd) => {
|
|
15500
16314
|
const eighth = BASE_STEPS_PER_BAR / 8;
|
|
15501
16315
|
const short = song.melody.filter((n) => n.durationSteps <= eighth).length / Math.max(1, song.melody.length);
|
|
15502
|
-
const
|
|
16316
|
+
const dotted = song.melody.filter(
|
|
16317
|
+
(n) => n.durationSteps === Math.round(BASE_STEPS_PER_BAR * 3 / 16)
|
|
16318
|
+
).length / Math.max(1, song.melody.length);
|
|
16319
|
+
const pool = dotted >= 0.08 ? ["shuffle", "8beat", "16beat"] : song.bpm >= 150 ? ["4beat", "dance", "16beat", "disco"] : short >= 0.85 ? ["16beat", "dance", "disco"] : song.bpm <= 115 ? ["bossa", "8beat", "shuffle", "4beat"] : ["8beat", "4beat", "16beat", "dance"];
|
|
15503
16320
|
return pick(pool, rnd);
|
|
15504
16321
|
};
|
|
15505
16322
|
var pickBuiltinInstrument = (song, rnd) => {
|
|
@@ -15513,7 +16330,7 @@ var pickBuiltinInstrument = (song, rnd) => {
|
|
|
15513
16330
|
pool = song.bpm >= 150 ? ["cyber_punk", "synth_pop", "retro_game"] : ["synth_pop", "retro_game", "rock", "piano"];
|
|
15514
16331
|
} else if (song.drum === "bossa") {
|
|
15515
16332
|
pool = ["jazz_night", "acoustic", "piano"];
|
|
15516
|
-
} else if (song.bpm <=
|
|
16333
|
+
} else if (song.bpm <= 115) {
|
|
15517
16334
|
pool = ["ambient_cloud", "acoustic", "orchestra", "piano", "fantasy_rpg"];
|
|
15518
16335
|
} else if (song.bpm >= 145) {
|
|
15519
16336
|
pool = ["rock", "synth_pop", "cyber_punk", "retro_game", "piano"];
|
|
@@ -15569,6 +16386,23 @@ var LYRIC_WORDS = [
|
|
|
15569
16386
|
"\u305B\u304B\u3044",
|
|
15570
16387
|
"\u304D\u305B\u3064"
|
|
15571
16388
|
];
|
|
16389
|
+
var alignLyrics = (source, lyrics, target, options) => {
|
|
16390
|
+
const sorted = [...source].sort((a, b) => a.startStep - b.startStep);
|
|
16391
|
+
const kana = [...lyrics].filter((c) => c !== "\u3001");
|
|
16392
|
+
const at = /* @__PURE__ */ new Map();
|
|
16393
|
+
for (let i2 = 0; i2 < sorted.length && i2 < kana.length; i2++)
|
|
16394
|
+
at.set(sorted[i2].startStep, kana[i2]);
|
|
16395
|
+
const { stepsPerBar } = options;
|
|
16396
|
+
const tgt = [...target].sort((a, b) => a.startStep - b.startStep);
|
|
16397
|
+
const out = [];
|
|
16398
|
+
for (let i2 = 0; i2 < tgt.length; i2++) {
|
|
16399
|
+
out.push(at.get(tgt[i2].startStep) ?? "\u30FC");
|
|
16400
|
+
const next = tgt[i2 + 1];
|
|
16401
|
+
if (next && Math.floor(tgt[i2].startStep / (stepsPerBar * 4)) !== Math.floor(next.startStep / (stepsPerBar * 4)))
|
|
16402
|
+
out.push("\u3001");
|
|
16403
|
+
}
|
|
16404
|
+
return out.join("");
|
|
16405
|
+
};
|
|
15572
16406
|
var composeLyrics = (melody, options) => {
|
|
15573
16407
|
const rnd = options.random ?? Math.random;
|
|
15574
16408
|
const { stepsPerBar } = options;
|
|
@@ -16863,56 +17697,95 @@ var exportMIDI = (options) => {
|
|
|
16863
17697
|
const div = 480;
|
|
16864
17698
|
const tickPerStep = div / STEPS_PER_BEAT3;
|
|
16865
17699
|
const midiTracks = [];
|
|
16866
|
-
const NOTE_CHANNELS = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15];
|
|
16867
|
-
const BEND_RANGE_SEMITONES = 2;
|
|
16868
17700
|
const bendKey = (cents) => Math.round(cents * 100);
|
|
16869
|
-
const
|
|
16870
|
-
|
|
16871
|
-
for (const n of track.notes) {
|
|
17701
|
+
const hasMicrotones = tracks.some(
|
|
17702
|
+
(track) => track.notes.some((n) => {
|
|
16872
17703
|
const { detuneCents } = unitsToMidiDetune(n.pitchUnits);
|
|
16873
|
-
|
|
16874
|
-
|
|
16875
|
-
|
|
16876
|
-
}
|
|
16877
|
-
const bendChannel = /* @__PURE__ */ new Map();
|
|
16878
|
-
const ordered = [...bendUse.entries()].sort((a, b) => b[1] - a[1]);
|
|
16879
|
-
for (const [k] of ordered) {
|
|
16880
|
-
if (bendChannel.size >= NOTE_CHANNELS.length) break;
|
|
16881
|
-
bendChannel.set(k, NOTE_CHANNELS[bendChannel.size]);
|
|
16882
|
-
}
|
|
16883
|
-
tracks.forEach((track) => {
|
|
16884
|
-
if (track.notes.length === 0) return;
|
|
16885
|
-
const events = [];
|
|
16886
|
-
for (const n of track.notes) {
|
|
16887
|
-
const { midi, detuneCents } = unitsToMidiDetune(n.pitchUnits);
|
|
16888
|
-
const k = bendKey(detuneCents);
|
|
16889
|
-
const channel = bendChannel.get(k) ?? bendChannel.get(0) ?? 0;
|
|
16890
|
-
const note = Math.max(0, Math.min(127, midi));
|
|
16891
|
-
const startTick = Math.round(n.startStep * tickPerStep);
|
|
16892
|
-
const endTick = Math.round(
|
|
16893
|
-
(n.startStep + (n.durationSteps || 1)) * tickPerStep
|
|
16894
|
-
);
|
|
16895
|
-
const vel = Math.round(
|
|
16896
|
-
(n.velocity ?? DEFAULT_VELOCITY) * (track.volume ?? 100) / 100
|
|
16897
|
-
);
|
|
16898
|
-
events.push({ t: startTick, m: [144 | channel, note, vel] });
|
|
16899
|
-
events.push({ t: endTick, m: [144 | channel, note, 0] });
|
|
16900
|
-
}
|
|
16901
|
-
events.sort((a, b) => a.t - b.t);
|
|
16902
|
-
midiTracks.push(events);
|
|
16903
|
-
});
|
|
17704
|
+
return bendKey(detuneCents) !== 0;
|
|
17705
|
+
})
|
|
17706
|
+
);
|
|
16904
17707
|
const bendSetup = [];
|
|
16905
|
-
|
|
16906
|
-
const
|
|
16907
|
-
|
|
16908
|
-
|
|
16909
|
-
|
|
16910
|
-
|
|
16911
|
-
|
|
16912
|
-
|
|
16913
|
-
|
|
16914
|
-
|
|
16915
|
-
|
|
17708
|
+
if (hasMicrotones) {
|
|
17709
|
+
const NOTE_CHANNELS = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15];
|
|
17710
|
+
const BEND_RANGE_SEMITONES = 2;
|
|
17711
|
+
const bendUse = /* @__PURE__ */ new Map();
|
|
17712
|
+
for (const track of tracks) {
|
|
17713
|
+
for (const n of track.notes) {
|
|
17714
|
+
const { detuneCents } = unitsToMidiDetune(n.pitchUnits);
|
|
17715
|
+
const k = bendKey(detuneCents);
|
|
17716
|
+
bendUse.set(k, (bendUse.get(k) ?? 0) + 1);
|
|
17717
|
+
}
|
|
17718
|
+
}
|
|
17719
|
+
const bendChannel = /* @__PURE__ */ new Map();
|
|
17720
|
+
const ordered = [...bendUse.entries()].sort((a, b) => b[1] - a[1]);
|
|
17721
|
+
for (const [k] of ordered) {
|
|
17722
|
+
if (bendChannel.size >= NOTE_CHANNELS.length) break;
|
|
17723
|
+
bendChannel.set(k, NOTE_CHANNELS[bendChannel.size]);
|
|
17724
|
+
}
|
|
17725
|
+
tracks.forEach((track) => {
|
|
17726
|
+
if (track.notes.length === 0) return;
|
|
17727
|
+
const events = [];
|
|
17728
|
+
for (const n of track.notes) {
|
|
17729
|
+
const { midi, detuneCents } = unitsToMidiDetune(n.pitchUnits);
|
|
17730
|
+
const k = bendKey(detuneCents);
|
|
17731
|
+
const channel = bendChannel.get(k) ?? bendChannel.get(0) ?? 0;
|
|
17732
|
+
const note = Math.max(0, Math.min(127, midi));
|
|
17733
|
+
const startTick = Math.round(n.startStep * tickPerStep);
|
|
17734
|
+
const endTick = Math.round(
|
|
17735
|
+
(n.startStep + (n.durationSteps || 1)) * tickPerStep
|
|
17736
|
+
);
|
|
17737
|
+
const vel = Math.round(
|
|
17738
|
+
(n.velocity ?? DEFAULT_VELOCITY) * (track.volume ?? 100) / 100
|
|
17739
|
+
);
|
|
17740
|
+
events.push({ t: startTick, m: [144 | channel, note, vel] });
|
|
17741
|
+
events.push({ t: endTick, m: [144 | channel, note, 0] });
|
|
17742
|
+
}
|
|
17743
|
+
events.sort((a, b) => a.t - b.t);
|
|
17744
|
+
midiTracks.push(events);
|
|
17745
|
+
});
|
|
17746
|
+
for (const [k, channel] of bendChannel) {
|
|
17747
|
+
const cents = k / 100;
|
|
17748
|
+
bendSetup.push({ t: 0, m: [176 | channel, 101, 0] });
|
|
17749
|
+
bendSetup.push({ t: 0, m: [176 | channel, 100, 0] });
|
|
17750
|
+
bendSetup.push({ t: 0, m: [176 | channel, 6, BEND_RANGE_SEMITONES] });
|
|
17751
|
+
bendSetup.push({ t: 0, m: [176 | channel, 38, 0] });
|
|
17752
|
+
bendSetup.push({ t: 0, m: [176 | channel, 101, 127] });
|
|
17753
|
+
bendSetup.push({ t: 0, m: [176 | channel, 100, 127] });
|
|
17754
|
+
const raw = 8192 + Math.round(cents / (BEND_RANGE_SEMITONES * 100) * 8192);
|
|
17755
|
+
const v = Math.max(0, Math.min(16383, raw));
|
|
17756
|
+
bendSetup.push({ t: 0, m: [224 | channel, v & 127, v >> 7 & 127] });
|
|
17757
|
+
}
|
|
17758
|
+
} else {
|
|
17759
|
+
tracks.forEach((track, trIdx) => {
|
|
17760
|
+
if (track.notes.length === 0) return;
|
|
17761
|
+
const channel = trIdx < 9 ? trIdx : trIdx + 1 & 15;
|
|
17762
|
+
const events = [];
|
|
17763
|
+
if (track.program !== void 0 && track.program >= 0 && track.program <= 127) {
|
|
17764
|
+
events.push({ t: 0, m: [192 | channel, track.program] });
|
|
17765
|
+
}
|
|
17766
|
+
for (const n of track.notes) {
|
|
17767
|
+
const { midi } = unitsToMidiDetune(n.pitchUnits);
|
|
17768
|
+
const note = Math.max(0, Math.min(127, midi));
|
|
17769
|
+
const startTick = Math.round(n.startStep * tickPerStep);
|
|
17770
|
+
const endTick = Math.round(
|
|
17771
|
+
(n.startStep + (n.durationSteps || 1)) * tickPerStep
|
|
17772
|
+
);
|
|
17773
|
+
const vel = Math.round(
|
|
17774
|
+
(n.velocity ?? DEFAULT_VELOCITY) * (track.volume ?? 100) / 100
|
|
17775
|
+
);
|
|
17776
|
+
events.push({ t: startTick, m: [144 | channel, note, vel] });
|
|
17777
|
+
events.push({ t: endTick, m: [144 | channel, note, 0] });
|
|
17778
|
+
}
|
|
17779
|
+
events.sort((a, b) => {
|
|
17780
|
+
if (a.t !== b.t) return a.t - b.t;
|
|
17781
|
+
const typeA = a.m[0] & 240;
|
|
17782
|
+
const typeB = b.m[0] & 240;
|
|
17783
|
+
if (typeA === 192 && typeB !== 192) return -1;
|
|
17784
|
+
if (typeB === 192 && typeA !== 192) return 1;
|
|
17785
|
+
return 0;
|
|
17786
|
+
});
|
|
17787
|
+
midiTracks.push(events);
|
|
17788
|
+
});
|
|
16916
17789
|
}
|
|
16917
17790
|
const maxStep = Math.max(
|
|
16918
17791
|
...tracks.filter((t) => t.notes.length > 0).map(
|
|
@@ -17648,28 +18521,6 @@ var isChordHeavyTrack = (notes, threshold = 0.6) => {
|
|
|
17648
18521
|
return chordNotes / notes.length >= threshold;
|
|
17649
18522
|
};
|
|
17650
18523
|
|
|
17651
|
-
// src/track1-state.ts
|
|
17652
|
-
var TRACK1_STORAGE_KEY = "dtm-track1:settings";
|
|
17653
|
-
var readTrack1Settings = () => {
|
|
17654
|
-
try {
|
|
17655
|
-
if (typeof localStorage === "undefined" || !localStorage) return null;
|
|
17656
|
-
const raw = localStorage.getItem(TRACK1_STORAGE_KEY);
|
|
17657
|
-
if (!raw) return null;
|
|
17658
|
-
const parsed = JSON.parse(raw);
|
|
17659
|
-
if (!parsed || typeof parsed !== "object") return null;
|
|
17660
|
-
return parsed;
|
|
17661
|
-
} catch (_) {
|
|
17662
|
-
return null;
|
|
17663
|
-
}
|
|
17664
|
-
};
|
|
17665
|
-
var writeTrack1Settings = (settings) => {
|
|
17666
|
-
try {
|
|
17667
|
-
if (typeof localStorage === "undefined" || !localStorage) return;
|
|
17668
|
-
localStorage.setItem(TRACK1_STORAGE_KEY, JSON.stringify(settings));
|
|
17669
|
-
} catch (_) {
|
|
17670
|
-
}
|
|
17671
|
-
};
|
|
17672
|
-
|
|
17673
18524
|
// src/renderer.ts
|
|
17674
18525
|
var KEYBOARD_WIDTH = 60;
|
|
17675
18526
|
var HEADER_HEIGHT = 20;
|
|
@@ -18159,6 +19010,28 @@ var createRenderer = (mountTarget, width = 800, height = 450, config) => {
|
|
|
18159
19010
|
};
|
|
18160
19011
|
};
|
|
18161
19012
|
|
|
19013
|
+
// src/track1-state.ts
|
|
19014
|
+
var TRACK1_STORAGE_KEY = "dtm-track1:settings";
|
|
19015
|
+
var readTrack1Settings = () => {
|
|
19016
|
+
try {
|
|
19017
|
+
if (typeof localStorage === "undefined" || !localStorage) return null;
|
|
19018
|
+
const raw = localStorage.getItem(TRACK1_STORAGE_KEY);
|
|
19019
|
+
if (!raw) return null;
|
|
19020
|
+
const parsed = JSON.parse(raw);
|
|
19021
|
+
if (!parsed || typeof parsed !== "object") return null;
|
|
19022
|
+
return parsed;
|
|
19023
|
+
} catch (_) {
|
|
19024
|
+
return null;
|
|
19025
|
+
}
|
|
19026
|
+
};
|
|
19027
|
+
var writeTrack1Settings = (settings) => {
|
|
19028
|
+
try {
|
|
19029
|
+
if (typeof localStorage === "undefined" || !localStorage) return;
|
|
19030
|
+
localStorage.setItem(TRACK1_STORAGE_KEY, JSON.stringify(settings));
|
|
19031
|
+
} catch (_) {
|
|
19032
|
+
}
|
|
19033
|
+
};
|
|
19034
|
+
|
|
18162
19035
|
// src/daw.ts
|
|
18163
19036
|
var CHORD_INFO_HTML2 = `
|
|
18164
19037
|
<div class="dtm-modal-body-content">
|
|
@@ -18491,8 +19364,16 @@ var COMPOSE_INFO_HTML = `
|
|
|
18491
19364
|
<li><strong>\u97F3\u306E\u5206\u5E03</strong>\u2014\u2014\u97F3\u4FA1\u306E\u3070\u3089\u3064\u304D\u30FB\u4F11\u7B26\u306E\u5272\u5408\u30FB\u8DF3\u8E8D\u306E\u5927\u304D\u3055\u3068\u6BD4\u7387\u30FB\u4F7F\u3063\u3066\u3044\u308B\u97F3\u57DF\u3002</li>
|
|
18492
19365
|
</ul>
|
|
18493
19366
|
<p>\u5404\u9805\u76EE\u306E\u5408\u683C\u30E9\u30A4\u30F3\u306F\u52D8\u3067\u6C7A\u3081\u305F\u3082\u306E\u3067\u306F\u306A\u304F\u3001<strong>\u4EBA\u9593\u304C\u66F8\u3044\u305FMIDI\u3092\u5B9F\u969B\u306B\u6E2C\u3063\u3066\u3001\u305D\u306E\u5206\u5E03\u306E\u771F\u3093\u4E2D\u3042\u305F\u308A\u3092\u6E80\u70B9\u306B\u3057\u3066\u3044\u307E\u3059</strong>\u3002\u305F\u3068\u3048\u3070\u4E3B\u65CB\u5F8B\u306E\u4F11\u7B26\u306F\u3001\u4EBA\u304C\u66F8\u3044\u305F\u66F2\u3067\u306F\u5168\u4F53\u306E15\u301C43%\u3092\u5360\u3081\u3066\u3044\u307E\u3057\u305F\u3002</p>
|
|
19367
|
+
<h4>\u6B4C\u5165\u308A\u4F5C\u66F2\u306E\u30DC\u30FC\u30AB\u30EB</h4>
|
|
19368
|
+
<p>\u4E3B\u65CB\u5F8B\u306B\u6B4C\u8A5E\u3092\u4ED8\u3051\u3066\u6B4C\u308F\u305B\u307E\u3059\u3002\u6B4C\u8A5E\u306B\u610F\u5473\u306F\u3042\u308A\u307E\u305B\u3093\uFF08\u30E1\u30ED\u30C7\u30A3\u306B\u6B63\u3057\u304F\u4E57\u308B\u3001\u767A\u97F3\u3067\u304D\u308B\u97F3\u306E\u4E26\u3073\u3060\u3051\u3092\u4F5C\u3063\u3066\u3044\u307E\u3059\uFF09\u3002<strong>\u4E0A\u7D1A\u8005\u30E2\u30FC\u30C9\uFF0815\u30C8\u30E9\u30C3\u30AF\uFF09\u3067\u306F\u3001\u3055\u3089\u306B\u30DC\u30FC\u30AB\u30EB\u30A2\u30EC\u30F3\u30B8\u307E\u3067\u5C55\u958B\u3057\u307E\u3059\u3002</strong>\u3069\u3053\u3067\u4F55\u3092\u3059\u308B\u304B\u306F\u66F2\u3054\u3068\u306B\u81EA\u52D5\u3067\u6C7A\u307E\u308B\u306E\u3067\u3001\u8A2D\u5B9A\u9805\u76EE\u306F\u3042\u308A\u307E\u305B\u3093\u3002</p>
|
|
19369
|
+
<ul>
|
|
19370
|
+
<li><strong>\u30CF\u30E2\u30EA</strong> \u2014 \u30B5\u30D3\u304B\u3089\u3001\u66F2\u306B\u3088\u3063\u3066\u306FB\u30E1\u30ED\u304B\u3089\u5165\u308A\u307E\u3059\u3002<strong>\u4E3B\u65CB\u5F8B\u3068\u540C\u3058\u58F0\u30FB\u540C\u3058\u6B4C\u8A5E\u3067\u9055\u3046\u9AD8\u3055\u3092\u91CD\u306D\u308B</strong>\u306E\u3067\u3001\u305D\u306E\u30D1\u30FC\u30C8\u304B\u3089\u58F0\u304C\u539A\u304F\u306A\u3063\u3066\u8C6A\u83EF\u306B\u805E\u3053\u3048\u307E\u3059\u30023\u5EA6\u304B6\u5EA6\u304C\u57FA\u672C\u3067\u3001\u6D6E\u3044\u3066\u805E\u3053\u3048\u308B\u5B8C\u51685\u5EA6\u306F\u907F\u3051\u307E\u3059\u3002\u4E3B\u65CB\u5F8B\u304C\u30C6\u30F3\u30B7\u30E7\u30F3\u97F3\uFF089th\u30FB11th \u306A\u3069\uFF09\u306B\u4E57\u3063\u3066\u3044\u308B\u3068\u3053\u308D\u3060\u30514\u5EA6\u3067\u5F53\u3066\u307E\u3059\u2014\u2014\u305D\u3053\u3067\u306F3\u5EA6\u30826\u5EA6\u3082\u548C\u97F3\u306E\u69CB\u6210\u97F3\u3078\u5C4A\u304B\u306A\u3044\u305F\u3081\u3067\u3059\u3002\u843D\u3061\u30B5\u30D3\u306F\u58F0\u3060\u3051\u3092\u805E\u304B\u305B\u308B\u5834\u6240\u306A\u306E\u3067\u5916\u3057\u307E\u3059\u3002</li>
|
|
19371
|
+
<li><strong>\u639B\u3051\u5408\u3044\uFF08\u30C7\u30E5\u30A8\u30C3\u30C8\uFF09</strong> \u2014 4\u5272\u307B\u3069\u306E\u66F2\u304C2\u4EBA\u6B4C\u3044\u306B\u306A\u308A\u307E\u3059\u3002\u30BB\u30AF\u30B7\u30E7\u30F3\u3054\u3068\uFF0FA\u30E1\u30ED\u30672\u5C0F\u7BC0\u3054\u3068\uFF0F\u639B\u3051\u5408\u3044\u30B5\u30D3\uFF0FA\u30E1\u30ED\u3060\u3051\u3001\u306E4\u901A\u308A\u3002<strong>\u53D7\u3051\u6E21\u3057\u306F\u5C0F\u7BC0\u7DDA\u3074\u3063\u305F\u308A\u3067\u306F\u306A\u304F\u3001\u6B21\u306E\u4EBA\u304C\u624B\u524D\u304B\u3089\u98DF\u3044\u6C17\u5473\u306B\u5165\u308A\u307E\u3059\u3002</strong>\u4E00\u7DD2\u306B\u6B4C\u3046\u30B5\u30D3\u3067\u306F\u76F8\u65B9\u304C\u30CF\u30E2\u30EA\u3078\u56DE\u308A\u307E\u3059\uFF08\u540C\u3058\u97F3\u3092\u306A\u305E\u308B\u30E6\u30CB\u30BE\u30F3\u306B\u306F\u3057\u307E\u305B\u3093\uFF09\u3002</li>
|
|
19372
|
+
</ul>
|
|
19373
|
+
<p>\u30B7\u30F3\u30D7\u30EB\u30E2\u30FC\u30C9\uFF084\u30C8\u30E9\u30C3\u30AF\uFF09\u306F\u72EC\u5531\u3067\u3059\u30024\u672C\u304C\u57CB\u307E\u3063\u3066\u3044\u3066\u30CF\u30E2\u30EA\u306E\u7F6E\u304D\u5834\u6240\u304C\u7121\u3044\u305F\u3081\u3067\u3059\u3002</p>
|
|
18494
19374
|
<h4>\u305D\u306E\u307B\u304B</h4>
|
|
18495
19375
|
<ul>
|
|
19376
|
+
<li><strong>\u66F2\u306E\u9014\u4E2D\u3067\u8EE2\u8ABF\u3057\u307E\u3059</strong>\uFF08\u304A\u3088\u305D\u534A\u5206\u306E\u66F2\uFF09\u3002\u4E94\u5EA6\u570F\u3067\u8FD1\u3044\u5C5E\u8ABF\u30FB\u4E0B\u5C5E\u8ABF\u3078\u306F\u5171\u901A\u3059\u308B\u548C\u97F3\uFF08\u30D4\u30DC\u30C3\u30C8\u30B3\u30FC\u30C9\uFF09\u304B\u65B0\u3057\u3044\u8ABF\u306E\u30C9\u30DF\u30CA\u30F3\u30C8\u3067\u6A4B\u6E21\u3057\u3057\u3001\u30E9\u30B9\u30B5\u30D3\u306E\u534A\u97F3\u4E0A\u3052\u306F\u6E96\u5099\u306A\u3057\u306E\u76F4\u63A5\u8EE2\u8ABF\u306B\u3057\u307E\u3059\u3002\u8ABF\u53F7\u3092\u5909\u3048\u305A\u306B\u660E\u6697\u3060\u3051\u5165\u308C\u66FF\u3048\u308B<strong>\u5E73\u884C\u8ABF</strong>\uFF08\u30CF\u9577\u8ABF\u2194\u30A4\u77ED\u8ABF\uFF09\u3068\u3001\u4E3B\u97F3\u3092\u4FDD\u3063\u305F\u307E\u307E\u6697\u304F\u3059\u308B<strong>\u540C\u4E3B\u8ABF</strong>\uFF08\u30CF\u9577\u8ABF\u2192\u30CF\u77ED\u8ABF\uFF09\u3082\u5F15\u304D\u307E\u3059\u30021\u5272\u5F37\u306E\u66F2\u306F\u4E3B\u548C\u97F3\u3092\u907F\u3051\u3066\u300C\u660E\u308B\u3044\u306E\u304B\u6697\u3044\u306E\u304B\u5206\u304B\u3089\u306A\u3044\u300D\u6D6E\u904A\u611F\u3067\u901A\u3057\u307E\u3059\u3002</li>
|
|
18496
19377
|
<li>\u8ABF\u306F\u30CF\u9577\u8ABF\uFF08\u307E\u305F\u306F\u30A4\u77ED\u8ABF\uFF09\u3067\u56FA\u5B9A\u3067\u3059\u3002\u5225\u306E\u8ABF\u306B\u3057\u305F\u3044\u3068\u304D\u306F\u3001\u3053\u306E\u4E0B\u306E\u300C\u79FB\u8ABF\u300D\u3067\u52D5\u304B\u3057\u3066\u304F\u3060\u3055\u3044\u3002</li>
|
|
18497
19378
|
<li>31\u5E73\u5747\u5F8B\u306E\u66F2\u3067\u3082\u4F7F\u3048\u307E\u3059\u3002\u548C\u97F3\u30FB\u30E1\u30ED\u30C7\u30A3\u3068\u308231\u5E73\u5747\u5F8B\u306E\u683C\u5B50\u306B\u4E57\u305B\u3066\u751F\u6210\u3057\u307E\u3059\u3002</li>
|
|
18498
19379
|
<li><strong>\u30C9\u30E9\u30E0\u3082\u66F2\u306B\u5408\u308F\u305B\u3066\u7D44\u307F\u7ACB\u3066\u307E\u3059</strong>\u3002\u30C6\u30F3\u30DD\u3068\u30E1\u30ED\u30C7\u30A3\u306E\u523B\u307F\u304B\u30898\u30D3\u30FC\u30C8\uFF0F16\u30D3\u30FC\u30C8\uFF0F4\u3064\u6253\u3061\uFF0F\u30B7\u30E3\u30C3\u30D5\u30EB\uFF0F\u30D0\u30E9\u30FC\u30C9\uFF0F\u30ED\u30C3\u30AF\u306E\u3069\u308C\u304B\u3092\u9078\u3073\u3001A\u30FBA'\u30FB\u30B5\u30D3\u30FBA'' \u3067\u523B\u307F\u306E\u5F37\u3055\u3092\u5909\u3048\u30014\u5C0F\u7BC0\u3054\u3068\u306B\u30D5\u30A3\u30EB\u3001\u30BB\u30AF\u30B7\u30E7\u30F3\u306E\u982D\u306B\u30AF\u30E9\u30C3\u30B7\u30E5\u3092\u7F6E\u304D\u307E\u3059\u3002\u6C17\u306B\u5165\u3089\u306A\u3051\u308C\u3070\u300C\u30C9\u30E9\u30E0\u8A2D\u5B9A\u300D\u304B\u3089\u4ED6\u306E\u30EA\u30BA\u30E0\u3078\u5207\u308A\u66FF\u3048\u3089\u308C\u307E\u3059\u3002</li>
|
|
@@ -18767,7 +19648,14 @@ var ADVANCED_COMPOSE_LAYOUT = [
|
|
|
18767
19648
|
{ index: 7, part: "block", octave: 0, volume: 62 },
|
|
18768
19649
|
{ index: 8, part: "arpeggio", octave: 0, volume: 54 },
|
|
18769
19650
|
{ index: 9, part: "offbeat", octave: 0, volume: 50 },
|
|
18770
|
-
{ index: 10, part: "uwamono", octave: 1, volume: 56 }
|
|
19651
|
+
{ index: 10, part: "uwamono", octave: 1, volume: 56 },
|
|
19652
|
+
// 掛け合い(デュエット)の相手。**歌入り作曲のときだけ**中身が入る。
|
|
19653
|
+
// 作曲だけならメロディは t0 が全部持つので、ここは空のまま。
|
|
19654
|
+
{ index: 11, part: "duet", octave: 0, volume: 104 },
|
|
19655
|
+
// 2声目のハモリ(主旋律を上下から挟む3声)と、主旋律のオクターブ下の重ね。
|
|
19656
|
+
// どちらも曲ごとに出るかどうかが決まる(`song.vocal`)。
|
|
19657
|
+
{ index: 12, part: "harmony2", octave: 0, volume: 74 },
|
|
19658
|
+
{ index: 13, part: "melody", octave: -1, volume: 56 }
|
|
18771
19659
|
];
|
|
18772
19660
|
var LYRIC_MODEL_CATEGORIES = [
|
|
18773
19661
|
{
|
|
@@ -19047,6 +19935,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
19047
19935
|
let currentDrumPattern = refs.drumSelect.value;
|
|
19048
19936
|
const recentComposeFingerprints = [];
|
|
19049
19937
|
let autoComposeVocal = null;
|
|
19938
|
+
const autoComposeVocalTracks = /* @__PURE__ */ new Map();
|
|
19050
19939
|
let currentDrumFont = options.drumFont ?? "FluidR3_GM_sf2_file:0";
|
|
19051
19940
|
refs.drumFontSelect.value = currentDrumFont;
|
|
19052
19941
|
const applyDrumPatternFont = (name) => {
|
|
@@ -21814,16 +22703,32 @@ var mountDAW = (target, options = {}) => {
|
|
|
21814
22703
|
updateTrackPanel();
|
|
21815
22704
|
updateUndoRedo();
|
|
21816
22705
|
};
|
|
21817
|
-
const exportMIDI2 = () =>
|
|
21818
|
-
|
|
21819
|
-
|
|
21820
|
-
|
|
21821
|
-
|
|
21822
|
-
|
|
21823
|
-
|
|
21824
|
-
|
|
21825
|
-
|
|
21826
|
-
|
|
22706
|
+
const exportMIDI2 = () => {
|
|
22707
|
+
const autoPreset = INSTRUMENT_PRESETS[currentInstrument] ?? INSTRUMENT_PRESETS.piano;
|
|
22708
|
+
return exportMIDI({
|
|
22709
|
+
tracks: trackStates.map((t) => {
|
|
22710
|
+
let program;
|
|
22711
|
+
if (t.trackInstrument) {
|
|
22712
|
+
const p = programOfInstrumentName(t.trackInstrument);
|
|
22713
|
+
if (p !== null) program = p;
|
|
22714
|
+
} else if (!t.lyricModel) {
|
|
22715
|
+
const role = DECLARED_ROLE[t.config.id] ?? "melody";
|
|
22716
|
+
const instName = autoPreset[role] ?? autoPreset.melody;
|
|
22717
|
+
const p = programOfInstrumentName(instName);
|
|
22718
|
+
if (p !== null) program = p;
|
|
22719
|
+
}
|
|
22720
|
+
return {
|
|
22721
|
+
notes: playableNotes(t),
|
|
22722
|
+
volume: t.volume,
|
|
22723
|
+
program
|
|
22724
|
+
};
|
|
22725
|
+
}),
|
|
22726
|
+
getDrumPattern: (currentBar) => resolveDrumPattern(currentDrumPattern, drumPatterns, currentBar),
|
|
22727
|
+
drumVolume,
|
|
22728
|
+
bpm,
|
|
22729
|
+
stepsPerBar: renderConfig.stepsPerBar
|
|
22730
|
+
});
|
|
22731
|
+
};
|
|
21827
22732
|
const setBpm = (value) => {
|
|
21828
22733
|
bpm = value;
|
|
21829
22734
|
refs.bpmInput.value = String(value);
|
|
@@ -22446,7 +23351,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
22446
23351
|
for (const layer of ADVANCED_COMPOSE_LAYOUT) {
|
|
22447
23352
|
const track = trackStates[layer.index];
|
|
22448
23353
|
if (!track) continue;
|
|
22449
|
-
const notes = layer.part === "melody" ? song.melody : layer.part === "harmony" ? song.harmony : layer.part === "submelody" ? song.submelody : layer.part === "bass" ? song.bass : layer.part === "pad" ? song.pad : layer.part === "uwamono" ? buildChordPlacements({
|
|
23354
|
+
const notes = layer.part === "duet" ? [] : layer.part === "harmony2" ? song.harmony2 : layer.index === 13 ? song.octave : layer.part === "melody" ? song.melody : layer.part === "harmony" ? song.harmony : layer.part === "submelody" ? song.submelody : layer.part === "bass" ? song.bass : layer.part === "pad" ? song.pad : layer.part === "uwamono" ? buildChordPlacements({
|
|
22450
23355
|
edo: renderConfig.edo,
|
|
22451
23356
|
chordStr: song.chordProgression,
|
|
22452
23357
|
patternType: "arpeggio",
|
|
@@ -22504,6 +23409,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
22504
23409
|
options.onInstrumentChange?.(song.instrument);
|
|
22505
23410
|
}
|
|
22506
23411
|
if (withVocal) {
|
|
23412
|
+
autoComposeVocalTracks.clear();
|
|
22507
23413
|
const melodyTrack = isAdvanced ? trackStates[0] : trackStates.find((t) => t.config.id === "melody");
|
|
22508
23414
|
if (melodyTrack) {
|
|
22509
23415
|
const current = melodyTrack.lyricModel.trim();
|
|
@@ -22513,12 +23419,85 @@ var mountDAW = (target, options = {}) => {
|
|
|
22513
23419
|
}
|
|
22514
23420
|
melodyTrack.lyricModel = pickComposeVocal(autoComposeVocal);
|
|
22515
23421
|
autoComposeVocal = melodyTrack.lyricModel;
|
|
23422
|
+
autoComposeVocalTracks.set(melodyTrack, melodyTrack.lyricModel);
|
|
22516
23423
|
}
|
|
22517
23424
|
melodyTrack.lyrics = composeLyrics(song.melody, {
|
|
22518
23425
|
stepsPerBar: renderConfig.stepsPerBar
|
|
22519
23426
|
});
|
|
22520
23427
|
fireLyricsChange(melodyTrack);
|
|
22521
23428
|
}
|
|
23429
|
+
if (isAdvanced && melodyTrack) {
|
|
23430
|
+
const stepsPerBar = renderConfig.stepsPerBar;
|
|
23431
|
+
const spans = song.vocal.duetSpans;
|
|
23432
|
+
const inDuet = (n) => spans.some(([a, b]) => n.startStep >= a && n.startStep < b);
|
|
23433
|
+
const sing = (track, lyrics, voice) => {
|
|
23434
|
+
if (!track) return;
|
|
23435
|
+
track.lyricModel = voice;
|
|
23436
|
+
autoComposeVocalTracks.set(track, voice);
|
|
23437
|
+
if (track.vocalOctave === 0) track.vocalOctave = -1;
|
|
23438
|
+
track.lyrics = lyrics;
|
|
23439
|
+
fireLyricsChange(track);
|
|
23440
|
+
};
|
|
23441
|
+
const partnerVoice = pickComposeVocal(melodyTrack.lyricModel);
|
|
23442
|
+
const duetting = spans.length > 0;
|
|
23443
|
+
if (duetting) {
|
|
23444
|
+
const mine = song.melody.filter((n) => !inDuet(n));
|
|
23445
|
+
const yours = song.melody.filter((n) => inDuet(n));
|
|
23446
|
+
writeTrackAt(0, mine);
|
|
23447
|
+
writeTrackAt(11, yours);
|
|
23448
|
+
const full = melodyTrack.lyrics;
|
|
23449
|
+
sing(
|
|
23450
|
+
melodyTrack,
|
|
23451
|
+
alignLyrics(song.melody, full, mine, { stepsPerBar }),
|
|
23452
|
+
melodyTrack.lyricModel
|
|
23453
|
+
);
|
|
23454
|
+
sing(
|
|
23455
|
+
trackStates[11],
|
|
23456
|
+
alignLyrics(song.melody, full, yours, { stepsPerBar }),
|
|
23457
|
+
partnerVoice
|
|
23458
|
+
);
|
|
23459
|
+
}
|
|
23460
|
+
const harmonyTrack = trackStates[2];
|
|
23461
|
+
if (song.harmony.length > 0 && harmonyTrack) {
|
|
23462
|
+
sing(
|
|
23463
|
+
harmonyTrack,
|
|
23464
|
+
alignLyrics(song.melody, melodyTrack.lyrics, song.harmony, {
|
|
23465
|
+
stepsPerBar
|
|
23466
|
+
}),
|
|
23467
|
+
duetting ? partnerVoice : melodyTrack.lyricModel
|
|
23468
|
+
);
|
|
23469
|
+
}
|
|
23470
|
+
if (!duetting) {
|
|
23471
|
+
if (song.harmony2.length > 0)
|
|
23472
|
+
sing(
|
|
23473
|
+
trackStates[12],
|
|
23474
|
+
alignLyrics(song.melody, melodyTrack.lyrics, song.harmony2, {
|
|
23475
|
+
stepsPerBar
|
|
23476
|
+
}),
|
|
23477
|
+
melodyTrack.lyricModel
|
|
23478
|
+
);
|
|
23479
|
+
const octaveTrack = trackStates[13];
|
|
23480
|
+
if (song.octave.length > 0 && octaveTrack) {
|
|
23481
|
+
sing(
|
|
23482
|
+
octaveTrack,
|
|
23483
|
+
alignLyrics(song.melody, melodyTrack.lyrics, song.octave, {
|
|
23484
|
+
stepsPerBar
|
|
23485
|
+
}),
|
|
23486
|
+
melodyTrack.lyricModel
|
|
23487
|
+
);
|
|
23488
|
+
octaveTrack.vocalOctave = -2;
|
|
23489
|
+
}
|
|
23490
|
+
}
|
|
23491
|
+
}
|
|
23492
|
+
} else {
|
|
23493
|
+
for (const [track, voice] of autoComposeVocalTracks) {
|
|
23494
|
+
if (track.lyricModel === voice) {
|
|
23495
|
+
track.lyrics = "";
|
|
23496
|
+
track.lyricModel = "";
|
|
23497
|
+
fireLyricsChange(track);
|
|
23498
|
+
}
|
|
23499
|
+
}
|
|
23500
|
+
autoComposeVocalTracks.clear();
|
|
22522
23501
|
}
|
|
22523
23502
|
applyAutoMastering();
|
|
22524
23503
|
if (refs.composeKeyHint) {
|
|
@@ -26066,6 +27045,7 @@ export {
|
|
|
26066
27045
|
playNote,
|
|
26067
27046
|
playPlacements,
|
|
26068
27047
|
playSingingMML,
|
|
27048
|
+
programOfInstrumentName,
|
|
26069
27049
|
readGlobalBool,
|
|
26070
27050
|
readGlobalNumber,
|
|
26071
27051
|
readGlobalSetting,
|