@onjmin/dtm 2.1.8 → 2.1.10
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 +481 -135
- package/dist/index.d.ts +481 -135
- package/dist/index.js +2504 -417
- package/dist/index.mjs +2489 -417
- package/package.json +2 -2
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 = [
|
|
@@ -8113,6 +8121,22 @@ var DAW_CSS = `
|
|
|
8113
8121
|
opacity: 0.85;
|
|
8114
8122
|
}
|
|
8115
8123
|
.dtm-pill:not(.dtm-pill--active):active { transform: translate(1px,1px); box-shadow: none; }
|
|
8124
|
+
/* \u30DC\u30FC\u30AB\u30EB\u304C\u9078\u629E\u3055\u308C\u3066\u3044\u308B\u30C8\u30E9\u30C3\u30AF\u306E\u30BF\u30D6\u306B\u3001\u3046\u3063\u3059\u3089\u58F0\u306E\u30A2\u30A4\u30B3\u30F3\u3092\u91CD\u306D\u308B\uFF08\u80CC\u666F\u8272\u30FB\u30B5\u30A4\u30BA\u306F\u5909\u3048\u306A\u3044\uFF09 */
|
|
8125
|
+
.dtm-pill--vocal::after {
|
|
8126
|
+
content: '';
|
|
8127
|
+
position: absolute;
|
|
8128
|
+
inset: 0;
|
|
8129
|
+
background-image: var(--dtm-pill-icon);
|
|
8130
|
+
background-size: contain;
|
|
8131
|
+
background-repeat: no-repeat;
|
|
8132
|
+
background-position: right center;
|
|
8133
|
+
opacity: 0.4;
|
|
8134
|
+
pointer-events: none;
|
|
8135
|
+
}
|
|
8136
|
+
.dtm-pill__label {
|
|
8137
|
+
position: relative;
|
|
8138
|
+
z-index: 1;
|
|
8139
|
+
}
|
|
8116
8140
|
/* \u518D\u751F\u4E2D\u3001\u5B9F\u969B\u306B\u767A\u97F3\u3057\u305F\u77AC\u9593\u3060\u3051\u70B9\u706F\uFF08\u3069\u306E\u30BF\u30D6\u304C\u4ECA\u9CF4\u3063\u3066\u3044\u308B\u304B\u8996\u899A\u7684\u306B\u5206\u304B\u308B\u3088\u3046\u306B\uFF09 */
|
|
8117
8141
|
.dtm-pill--sounding {
|
|
8118
8142
|
filter: brightness(1.6);
|
|
@@ -12510,44 +12534,365 @@ var mountChordPlayer = (target, chords, options = {}) => {
|
|
|
12510
12534
|
// src/compose-corpus.ts
|
|
12511
12535
|
var CORPUS_SIZE = 91;
|
|
12512
12536
|
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
|
-
|
|
12537
|
+
entropy: [0.25, 0.711, 1.237, 1.754],
|
|
12538
|
+
valueKinds: [2, 3, 6, 7],
|
|
12539
|
+
restRatio: [0.016, 0.091, 0.223, 0.464],
|
|
12540
|
+
leapRatio: [0.202, 0.28, 0.412, 0.71],
|
|
12541
|
+
stepRatio: [0.188, 0.438, 0.617, 0.693],
|
|
12542
|
+
chromaticRatio: [0, 0.017, 0.121, 0.242],
|
|
12543
|
+
maxLeap: [5, 8, 12, 16],
|
|
12544
|
+
melodyRange: [8, 17, 22, 28],
|
|
12545
|
+
notesPerBar: [2.743, 4.77, 6.473, 11.995],
|
|
12546
|
+
shortNoteRatio: [0.055, 0.753, 0.91, 1],
|
|
12547
|
+
barDensityCv: [0.148, 0.206, 0.328, 0.451],
|
|
12548
|
+
densityCliff: [0, 0, 0.043, 0.125],
|
|
12549
|
+
sim1: [0.345, 0.465, 0.598, 0.803],
|
|
12550
|
+
sim2: [0.389, 0.5, 0.647, 0.845],
|
|
12551
|
+
sim4: [0.437, 0.549, 0.723, 0.882],
|
|
12552
|
+
sim8: [0.063, 0.561, 0.771, 0.972],
|
|
12553
|
+
phraseBreath: [0, 0.115, 0.323, 0.884],
|
|
12554
|
+
turnRatio: [0.4, 0.478, 0.556, 0.769],
|
|
12555
|
+
climaxPosition: [0.016, 0.14, 0.655, 0.92],
|
|
12556
|
+
climaxPeaks: [1, 2, 13.5, 26],
|
|
12557
|
+
complementarity: [0, 0.026, 0.179, 0.405]
|
|
12531
12558
|
};
|
|
12532
12559
|
var CORPUS_MEDIANS = {
|
|
12533
|
-
entropy: 0.
|
|
12560
|
+
entropy: 0.907,
|
|
12534
12561
|
valueKinds: 4,
|
|
12535
|
-
restRatio: 0.
|
|
12536
|
-
leapRatio: 0.
|
|
12537
|
-
stepRatio: 0.
|
|
12538
|
-
chromaticRatio: 0.
|
|
12562
|
+
restRatio: 0.149,
|
|
12563
|
+
leapRatio: 0.339,
|
|
12564
|
+
stepRatio: 0.538,
|
|
12565
|
+
chromaticRatio: 0.052,
|
|
12539
12566
|
maxLeap: 12,
|
|
12540
|
-
melodyRange:
|
|
12541
|
-
notesPerBar: 5.
|
|
12542
|
-
shortNoteRatio: 0.
|
|
12543
|
-
|
|
12544
|
-
|
|
12545
|
-
|
|
12546
|
-
|
|
12547
|
-
|
|
12567
|
+
melodyRange: 20,
|
|
12568
|
+
notesPerBar: 5.511,
|
|
12569
|
+
shortNoteRatio: 0.816,
|
|
12570
|
+
barDensityCv: 0.279,
|
|
12571
|
+
densityCliff: 0.026,
|
|
12572
|
+
sim1: 0.518,
|
|
12573
|
+
sim2: 0.552,
|
|
12574
|
+
sim4: 0.616,
|
|
12575
|
+
sim8: 0.676,
|
|
12576
|
+
phraseBreath: 0.227,
|
|
12577
|
+
turnRatio: 0.519,
|
|
12548
12578
|
climaxPosition: 0.273,
|
|
12549
|
-
climaxPeaks:
|
|
12550
|
-
complementarity: 0.
|
|
12579
|
+
climaxPeaks: 6,
|
|
12580
|
+
complementarity: 0.075
|
|
12581
|
+
};
|
|
12582
|
+
var CORPUS_CELL_WEIGHTS = {
|
|
12583
|
+
"0,2,4,6,8,10,12,14": 584,
|
|
12584
|
+
"0,2,4,6,8,12,14": 512,
|
|
12585
|
+
"0,4,6,8,10,12,14": 246,
|
|
12586
|
+
"0,8": 187,
|
|
12587
|
+
"0,4,8,10,12,14": 158,
|
|
12588
|
+
"0,6,8,10,12,14": 153,
|
|
12589
|
+
"2,5,10,13": 128,
|
|
12590
|
+
"0,12,14": 123,
|
|
12591
|
+
"0,4,6,8,12,14": 114,
|
|
12592
|
+
"0,4,8,12": 110,
|
|
12593
|
+
"0": 105,
|
|
12594
|
+
"0,2,4,6,8,12": 103,
|
|
12595
|
+
"0,4,8,12,14": 102,
|
|
12596
|
+
"0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15": 89,
|
|
12597
|
+
"0,2,4,6,8": 76,
|
|
12598
|
+
"0,6,8,12,14": 58,
|
|
12599
|
+
"0,6,8,14": 48,
|
|
12600
|
+
"0,4,6,8,12": 44,
|
|
12601
|
+
"0,4,8,14": 44,
|
|
12602
|
+
"0,2,4,5,6,8,9,10,12,13,14,15": 44,
|
|
12603
|
+
"2,6,10,14": 42,
|
|
12604
|
+
"0,8,12": 40,
|
|
12605
|
+
"0,2,4,6,8,10,12": 39,
|
|
12606
|
+
"0,3,9,10,11,12,13,14,15": 36,
|
|
12607
|
+
"0,3,6,8,11,14": 32,
|
|
12608
|
+
"0,2,4,6,7,9,10,12,14": 32,
|
|
12609
|
+
"0,2,4,6,10,12,14": 31,
|
|
12610
|
+
"0,10,12,14": 28,
|
|
12611
|
+
"12,14": 27,
|
|
12612
|
+
"0,2,4,6,8,14": 27,
|
|
12613
|
+
"0,6,8,12": 25,
|
|
12614
|
+
"0,4,6,8,10,12": 24,
|
|
12615
|
+
"0,1,2,4,5,6,7,8,9,10,11,12,13,14,15": 24,
|
|
12616
|
+
"2,4,6,8,10,12,14": 22,
|
|
12617
|
+
"0,6,8": 19,
|
|
12618
|
+
"0,12": 19,
|
|
12619
|
+
"8,12": 17,
|
|
12620
|
+
"0,2,4,8,12,14": 16,
|
|
12621
|
+
"0,3,5,6,7,8,11,13,14,15": 16,
|
|
12622
|
+
"0,3,4,5,6,7,8,10,12,14": 16,
|
|
12623
|
+
"0,14": 15,
|
|
12624
|
+
"0,4,8": 15,
|
|
12625
|
+
"0,4,6,8,14": 14,
|
|
12626
|
+
"0,4,6,8,10,11,12,14": 14,
|
|
12627
|
+
"2,4,6,8": 13,
|
|
12628
|
+
"0,4,6,10,12,14": 13,
|
|
12629
|
+
"0,4,6,8": 13,
|
|
12630
|
+
"0,2,4,8,9,11,14,15": 12,
|
|
12631
|
+
"0,4,8,10,11,12,14": 12,
|
|
12632
|
+
"0,2,4,6,8,9,12,14": 12,
|
|
12633
|
+
"0,3,4,6,8,12,14": 12,
|
|
12634
|
+
"0,2,4,6,8,11,14": 12,
|
|
12635
|
+
"0,2,4,5,6,7,8,9,10,11,12,14": 12,
|
|
12636
|
+
"2,4,6,8,12,14": 11,
|
|
12637
|
+
"0,2,4,8,10,12": 11,
|
|
12638
|
+
"0,1,2,3,4,5,6,7,8,9,10,11,12": 11,
|
|
12639
|
+
"0,2,4,6,8,10,11,12,14": 10,
|
|
12640
|
+
"0,4,6,7,8,14,15": 10,
|
|
12641
|
+
"0,8,10,12,14": 10,
|
|
12642
|
+
"0,3,4,6,8,10,12,14": 9,
|
|
12643
|
+
"0,2,3,4,6,8,12,14": 9,
|
|
12644
|
+
"0,2,4,5,6,8,12,14": 9,
|
|
12645
|
+
"0,3,4,6,8,9,10,11,12": 9,
|
|
12646
|
+
"0,3,4,6,8,9,10,11,12,14,15": 9,
|
|
12647
|
+
"0,3,4,6,7,8,10,12,14,15": 9,
|
|
12648
|
+
"0,2,4,5,6,7,8,9,10,12,13,14,15": 9,
|
|
12649
|
+
"0,2,4,8,10,12,14": 8,
|
|
12650
|
+
"0,2,4,6,8,10,12,14,15": 8,
|
|
12651
|
+
"1,2,3,4,5,6,7,8,9,10,11,12,13,14,15": 8,
|
|
12652
|
+
"0,3,6,8,12,14": 7,
|
|
12653
|
+
"0,1,2,3,4,5,6,7,8": 7,
|
|
12654
|
+
"0,4,8,10,12": 7,
|
|
12655
|
+
"0,2,3,4,5,6,7,8": 7,
|
|
12656
|
+
"0,3,4,6,8,12": 6,
|
|
12657
|
+
"0,2,4,6,10,14": 6,
|
|
12658
|
+
"4,12": 6,
|
|
12659
|
+
"0,6,8,10,14": 6,
|
|
12660
|
+
"0,2,3,4,5,6,7,8,9,10,11,12": 6,
|
|
12661
|
+
"0,1,2,3,4,6,7,8,10,12,14,15": 6,
|
|
12662
|
+
"0,3,6,8,12": 6,
|
|
12663
|
+
"2,4,6,8,10,11,12,14": 6,
|
|
12664
|
+
"6,8,10,12,14": 5,
|
|
12665
|
+
"2,6,8,10,12,14": 5,
|
|
12666
|
+
"0,8,12,14": 5,
|
|
12667
|
+
"0,3,4,6,8": 5,
|
|
12668
|
+
"0,8,11,14": 5,
|
|
12669
|
+
"0,3,4,6,8,10,11,12,14": 5,
|
|
12670
|
+
"0,3,6,8": 5,
|
|
12671
|
+
"0,1,4,8,9,12,13": 5,
|
|
12672
|
+
"10,12,14": 5,
|
|
12673
|
+
"0,4,6,8,10,11,12,13,14": 5,
|
|
12674
|
+
"12,13,14,15": 5,
|
|
12675
|
+
"0,2,4,7,8,14,15": 5,
|
|
12676
|
+
"0,4,8,9,10,11,12,13,14,15": 5,
|
|
12677
|
+
"0,4,7,8,14,15": 5,
|
|
12678
|
+
"0,4,8,9,10,11,12": 5,
|
|
12679
|
+
"0,2,6,8,10,12,14": 5,
|
|
12680
|
+
"2,4,6,12,14": 4,
|
|
12681
|
+
"0,2,4,6,7,8,10,12,14": 4,
|
|
12682
|
+
"4,5,7,8,10,12,13,14": 4,
|
|
12683
|
+
"0,2,3,4,5,8,9,12,13": 4,
|
|
12684
|
+
"2,3,4,6,8,12,13,14": 4,
|
|
12685
|
+
"0,1,2,3,4,5,6,7,8,9,10,11,12,13,14": 4,
|
|
12686
|
+
"0,2,4,8,12": 4,
|
|
12687
|
+
"4,6,8,10,12": 4,
|
|
12688
|
+
"0,2,4,5,6,8,12,13,14,15": 4,
|
|
12689
|
+
"0,2,3,4,6,8": 4,
|
|
12690
|
+
"0,4,6,8,10,12,13,14": 4,
|
|
12691
|
+
"0,6,8,12,14,15": 4,
|
|
12692
|
+
"0,4,8,9,10,12,14": 4,
|
|
12693
|
+
"0,3,4,7,8,9,10,11,12": 4,
|
|
12694
|
+
"0,1,2,3,4,5,7,8,9,10,11,12": 4,
|
|
12695
|
+
"2,4,8,12": 4,
|
|
12696
|
+
"0,2,4,6,10,12": 4,
|
|
12697
|
+
"0,3,4,6,7,8,9,10,12,14": 4,
|
|
12698
|
+
"0,3,6,9,11,12": 4,
|
|
12699
|
+
"0,1,4,6,8,12,14": 4,
|
|
12700
|
+
"4,8,12": 4,
|
|
12701
|
+
"2,4,6,14": 3,
|
|
12702
|
+
"0,3,4,8": 3,
|
|
12703
|
+
"0,2,4,12,14": 3,
|
|
12704
|
+
"14": 3,
|
|
12705
|
+
"0,4,6,12,14": 3,
|
|
12706
|
+
"0,6,10,12,14": 3,
|
|
12707
|
+
"4,8,9,11,14": 3,
|
|
12708
|
+
"0,2,4,8,9,11,14": 3,
|
|
12709
|
+
"0,4,8,9,11,14": 3,
|
|
12710
|
+
"0,2,4,5,7,9,11,12": 3,
|
|
12711
|
+
"0,3,6,8,10,12,14": 3,
|
|
12712
|
+
"0,3,4,6,8,11,12,14": 3,
|
|
12713
|
+
"0,1,4,5,8,9,12,13": 3,
|
|
12714
|
+
"0,2,4,5,8,9": 3,
|
|
12715
|
+
"2,3,4,6,8,9,12,14": 3,
|
|
12716
|
+
"0,2,4,8": 3,
|
|
12717
|
+
"0,2,3,4,5,6,8,9": 3,
|
|
12718
|
+
"2,3,4,6,8,10,12,13": 3,
|
|
12719
|
+
"12,14,15": 3,
|
|
12720
|
+
"0,2,3,4,6,7,8,10,12": 3,
|
|
12721
|
+
"0,2,3,4,5,6,7,8,9,10,12": 3,
|
|
12722
|
+
"0,1,2,3,4,5,6,7,8,9,10,11,12,14": 3,
|
|
12723
|
+
"0,2,3,4,6,7,8,9,10,11,12": 3,
|
|
12724
|
+
"0,4,6,12": 3,
|
|
12725
|
+
"0,2,3,6,8,11,14": 3,
|
|
12726
|
+
"0,2,6,8,12,14": 3,
|
|
12727
|
+
"2,4,6,8,14,15": 3,
|
|
12728
|
+
"0,2,4,6,12,14": 2,
|
|
12729
|
+
"2,4,6,10,12,14": 2,
|
|
12730
|
+
"4,6,10,12,14": 2,
|
|
12731
|
+
"0,8,14": 2,
|
|
12732
|
+
"2,4,8,10,12,14": 2,
|
|
12733
|
+
"8": 2,
|
|
12734
|
+
"0,2,4,6,8,9,10,11,12,14": 2,
|
|
12735
|
+
"0,2,4,6,8,12,13,14": 2,
|
|
12736
|
+
"0,6,8,11,12,14": 2,
|
|
12737
|
+
"0,1,2,3,4,5,6,7,8,9,11,12,13,14,15": 2,
|
|
12738
|
+
"0,1,3,4,5,6,7,8,9,10,11,12,13,14,15": 2,
|
|
12739
|
+
"0,6,7,8,10,12": 2,
|
|
12740
|
+
"0,3,6,7,8,10,12": 2,
|
|
12741
|
+
"1,2,3,4,6,8,10,12,13": 2,
|
|
12742
|
+
"0,2,8,10,12,14": 2,
|
|
12743
|
+
"0,2,7,8,9,10": 2,
|
|
12744
|
+
"4,8,9,10,12,13": 2,
|
|
12745
|
+
"0,2,4,7,8,9,10": 2,
|
|
12746
|
+
"2,4,7,8,12,15": 2,
|
|
12747
|
+
"0,4,7,8,10": 2,
|
|
12748
|
+
"0,4,8,9,12,13": 2,
|
|
12749
|
+
"0,2,4,5,6,8,9": 2,
|
|
12750
|
+
"0,1,4": 2,
|
|
12751
|
+
"0,4": 2,
|
|
12752
|
+
"0,3,6,10,12,14": 2,
|
|
12753
|
+
"0,2,6,10,12,14": 2,
|
|
12754
|
+
"0,2,3,4,6,8,14,15": 2,
|
|
12755
|
+
"2,4,6,8,12,14,15": 2,
|
|
12756
|
+
"0,2,4,6,8,9,10,12": 2,
|
|
12757
|
+
"0,3,6,8,10,12": 2,
|
|
12758
|
+
"0,3,4,6,8,10,14": 2,
|
|
12759
|
+
"0,4,8,11,12,14": 2,
|
|
12760
|
+
"0,2,4,6,8,9,10,11,12,13,14": 2,
|
|
12761
|
+
"0,2,4,5,6,7,8,9,10,12": 2,
|
|
12762
|
+
"0,1,2,3,4,6,7,8,9,10,12,14": 2,
|
|
12763
|
+
"0,1,2,4,5,6,8,9,10,11,12,13,14": 2,
|
|
12764
|
+
"0,1,2,3,4,6,7,8,9,10,11,12,13,14": 2,
|
|
12765
|
+
"0,1,2,3,4,6,7,8,9,10,11,12,13,14,15": 2,
|
|
12766
|
+
"0,1,2,4,6,8,9,10,11,12,13,14": 2,
|
|
12767
|
+
"0,1,2,3,4,5,6,8,9,10,11,12,13,14": 2,
|
|
12768
|
+
"0,1,2,3,4,6,7,8,9,10,12,13,14,15": 2,
|
|
12769
|
+
"0,2,4,6,8,9,10,11,12,13,14,15": 2,
|
|
12770
|
+
"0,2,3,4,5,6,8,10,12": 2,
|
|
12771
|
+
"0,2,3,4,5,6,7,8,10,11,12": 2,
|
|
12772
|
+
"0,2,3,4,6,7,8,9,10,12": 2,
|
|
12773
|
+
"0,1,2,3,4,6,7,8,9,10,11,12": 2,
|
|
12774
|
+
"0,4,5,8,12,13": 2,
|
|
12775
|
+
"0,3,4,5,8,11,12,13": 2,
|
|
12776
|
+
"0,2,4,7,8,9": 2,
|
|
12777
|
+
"0,4,6,7,8,12": 2,
|
|
12778
|
+
"0,2,3,4,6,7,8,10,11,12,14": 2,
|
|
12779
|
+
"0,2,3,4,5,6,7,8,10,11,12,13": 2,
|
|
12780
|
+
"12": 2,
|
|
12781
|
+
"0,2,4,6,8,13": 2,
|
|
12782
|
+
"2,4,6,8,11,14": 2,
|
|
12783
|
+
"0,5,8,13": 2,
|
|
12784
|
+
"0,2,4,6,8,10,11,12,13,14": 2,
|
|
12785
|
+
"0,4,6,8,10,11,12,13,14,15": 2,
|
|
12786
|
+
"0,5,8,12": 2,
|
|
12787
|
+
"2,4,6,8,14": 1,
|
|
12788
|
+
"0,6,7,8,14": 1,
|
|
12789
|
+
"0,6,8,14,15": 1,
|
|
12790
|
+
"0,6,7,8,10,11,12,13": 1,
|
|
12791
|
+
"0,6,7,8,9,10,11,12,14": 1,
|
|
12792
|
+
"0,1,2,4,6,7,8,10,11,12,13,14,15": 1,
|
|
12793
|
+
"0,4,8,10,11,12": 1,
|
|
12794
|
+
"0,6,7,8,11,14": 1,
|
|
12795
|
+
"0,2,5,8,11,14": 1,
|
|
12796
|
+
"0,2,4,6,8,10,11,12": 1,
|
|
12797
|
+
"0,11,14": 1,
|
|
12798
|
+
"0,8,11,12,13,14,15": 1,
|
|
12799
|
+
"0,1,12": 1,
|
|
12800
|
+
"0,3,5,8,12": 1,
|
|
12801
|
+
"0,4,8,11,14": 1,
|
|
12802
|
+
"2,6,8,11,14": 1,
|
|
12803
|
+
"0,2,3,4,6,8,12": 1,
|
|
12804
|
+
"0,4,6,8,11,12,14": 1,
|
|
12805
|
+
"0,1,12,14": 1,
|
|
12806
|
+
"0,9,12": 1,
|
|
12807
|
+
"0,3": 1,
|
|
12808
|
+
"0,1": 1,
|
|
12809
|
+
"4,6,8,14": 1,
|
|
12810
|
+
"2,12,14": 1,
|
|
12811
|
+
"2,8,12": 1,
|
|
12812
|
+
"0,3,6,8,11": 1,
|
|
12813
|
+
"10,12,14,15": 1,
|
|
12814
|
+
"0,2,3,6,8,9,11,14": 1,
|
|
12815
|
+
"0,2,4,8,10,11": 1,
|
|
12816
|
+
"0,2,4,6,7,8,10,12,13": 1,
|
|
12817
|
+
"2,3,4,5,8,10,12,13,15": 1,
|
|
12818
|
+
"0,2,3,4,5,6,8,10,11,12": 1,
|
|
12819
|
+
"4,6,8,10,11,12": 1,
|
|
12820
|
+
"0,1,2,3,4,6,8,9,10,13,15": 1,
|
|
12821
|
+
"0,1,2,3,4,10,11,12": 1,
|
|
12822
|
+
"0,3,6,7,8,9,11": 1,
|
|
12823
|
+
"0,2,4,5,8,10,11,15": 1,
|
|
12824
|
+
"0,2,4,6,7,8,9,12,13": 1,
|
|
12825
|
+
"0,1,2,4,5,8,10,12,13": 1,
|
|
12826
|
+
"0,2,3,4,5,6,8,10,11,12,13": 1,
|
|
12827
|
+
"4,6,8,10,11,12,13": 1,
|
|
12828
|
+
"0,3,8,12,14": 1,
|
|
12829
|
+
"0,3,4,5,7,8,9,10,12,14,15": 1,
|
|
12830
|
+
"0,2,4,6,8,9,11": 1,
|
|
12831
|
+
"10,14": 1,
|
|
12832
|
+
"0,2,4,6,9,10,12,14": 1,
|
|
12833
|
+
"0,2,4,6,7,9,10,12": 1,
|
|
12834
|
+
"0,2,3,5,8,10,12,13,14": 1,
|
|
12835
|
+
"0,1,2,3,5,6,7,8,9,10,12,13,14": 1,
|
|
12836
|
+
"2,3,4,6,7,8,12,13,14": 1,
|
|
12837
|
+
"0,1,2,3,6,7,8,10,12,13,14": 1,
|
|
12838
|
+
"2,3,4,5,6,8,9,10,11,12,13,14": 1,
|
|
12839
|
+
"0,2,3,4,5,6,7,8,9,10,11,12,13,14": 1,
|
|
12840
|
+
"2,3,4,6,8,9,10,11,12,13,14,15": 1,
|
|
12841
|
+
"0,3,4,7,8,11,12": 1,
|
|
12842
|
+
"0,4,10,12,14": 1,
|
|
12843
|
+
"0,3,4,7,8,11,12,15": 1,
|
|
12844
|
+
"0,4,12,14": 1,
|
|
12845
|
+
"0,4,12": 1,
|
|
12846
|
+
"0,4,7,8,10,11,12,14": 1,
|
|
12847
|
+
"2,6,8,12": 1,
|
|
12848
|
+
"0,2,4,5,6,8": 1,
|
|
12849
|
+
"2,6,8,10,12": 1,
|
|
12850
|
+
"0,2,4,6,8,12,13,14,15": 1,
|
|
12851
|
+
"0,4,6,8,10,11,12": 1,
|
|
12852
|
+
"0,4,8,10,11,12,13,14": 1,
|
|
12853
|
+
"0,2,3,4,6,7,8,9,10,12,13,14,15": 1,
|
|
12854
|
+
"0,2,4,5,6,8,9,10,11,12,13,14": 1,
|
|
12855
|
+
"0,3,4,7,8,9,10,12,13": 1,
|
|
12856
|
+
"0,1,2,4,6,7,8,9,10,12,13,14,15": 1,
|
|
12857
|
+
"0,2,3,4,5,6,8,9,10,11,12,13,14": 1,
|
|
12858
|
+
"0,4,6,7,8,10,12,14,15": 1,
|
|
12859
|
+
"0,2,4,6,7,8,10,12,14,15": 1,
|
|
12860
|
+
"0,1,2,3,4,5,7,8,10,11,12": 1,
|
|
12861
|
+
"0,2,4,6,7,8,9,10,11,12,14": 1,
|
|
12862
|
+
"0,1,2,4,5,6,7,8,10,12,14,15": 1,
|
|
12863
|
+
"0,2,3,4,5,7,8,9,10,11,12": 1,
|
|
12864
|
+
"0,2,3,4,6,7,8,10,11,12": 1,
|
|
12865
|
+
"0,8,9,10,11,12,13,14,15": 1,
|
|
12866
|
+
"14,15": 1,
|
|
12867
|
+
"2,4,6,8,12": 1,
|
|
12868
|
+
"2,4,8,10,12": 1,
|
|
12869
|
+
"0,2,4,8,9,12,14": 1,
|
|
12870
|
+
"0,4,5,8,9,12": 1,
|
|
12871
|
+
"0,4,8,10,14": 1,
|
|
12872
|
+
"0,6,7,12": 1,
|
|
12873
|
+
"0,4,5,8,11,12,13": 1,
|
|
12874
|
+
"0,2,4,8,9": 1,
|
|
12875
|
+
"2,4,7,8,11,12": 1,
|
|
12876
|
+
"0,4,7,8,11": 1,
|
|
12877
|
+
"0,4,8,12,14,15": 1,
|
|
12878
|
+
"0,1,2,4,5,6,7,8,9,10,12": 1,
|
|
12879
|
+
"0,1,2,3,4,5,6,7,8,9,10,12": 1,
|
|
12880
|
+
"0,2,3,4,5,6,7,8,9,10,12,13,14,15": 1,
|
|
12881
|
+
"0,3,4,7,8,9,11,12": 1,
|
|
12882
|
+
"0,1,2,3,4,5,6,7,8,10,11,12,13": 1,
|
|
12883
|
+
"0,6,8,10,12": 1,
|
|
12884
|
+
"0,2,3,4,6,8,10,11,12,14": 1,
|
|
12885
|
+
"0,2,4,6,8,10,13": 1,
|
|
12886
|
+
"2,6,8": 1,
|
|
12887
|
+
"0,2,3,4,6,7,8,12,14": 1,
|
|
12888
|
+
"2,4,6,8,10,14": 1,
|
|
12889
|
+
"0,2,4": 1,
|
|
12890
|
+
"0,2,4,5,6,7,8,9,10": 1,
|
|
12891
|
+
"0,2,4,5,6,7,8,9,10,12,13,14": 1,
|
|
12892
|
+
"0,3,6,10,14": 1,
|
|
12893
|
+
"0,14,15": 1,
|
|
12894
|
+
"0,6,7,12,14": 1,
|
|
12895
|
+
"0,6,8,10,11,12,14": 1
|
|
12551
12896
|
};
|
|
12552
12897
|
|
|
12553
12898
|
// src/compose-keys.ts
|
|
@@ -12882,8 +13227,7 @@ var resolveComposeKey = (choice, rnd = Math.random) => {
|
|
|
12882
13227
|
const target = COMPOSE_KEYS[pickedKeyId];
|
|
12883
13228
|
const targetMood = COMPOSE_MOOD_GROUPS.find((m) => m.id === target.moodId);
|
|
12884
13229
|
return {
|
|
12885
|
-
mode:
|
|
12886
|
-
// コード進行の長短制約は掛けず従来通りランダム
|
|
13230
|
+
mode: target.mode,
|
|
12887
13231
|
rootShift: target.rootShift,
|
|
12888
13232
|
keyName: target.name,
|
|
12889
13233
|
keyLabel: target.label,
|
|
@@ -13010,9 +13354,24 @@ var complementarity = (melody, submelody, opts) => {
|
|
|
13010
13354
|
}
|
|
13011
13355
|
return free / submelody.length;
|
|
13012
13356
|
};
|
|
13357
|
+
var turnRatio = (notes) => {
|
|
13358
|
+
const sorted = [...notes].sort((a, b) => a.startStep - b.startStep);
|
|
13359
|
+
let turns = 0;
|
|
13360
|
+
let intervals = 0;
|
|
13361
|
+
let prevDir = 0;
|
|
13362
|
+
for (let i2 = 1; i2 < sorted.length; i2++) {
|
|
13363
|
+
const dir = Math.sign(sorted[i2].pitchSemi - sorted[i2 - 1].pitchSemi);
|
|
13364
|
+
if (dir === 0) continue;
|
|
13365
|
+
intervals++;
|
|
13366
|
+
if (prevDir !== 0 && dir !== prevDir) turns++;
|
|
13367
|
+
prevDir = dir;
|
|
13368
|
+
}
|
|
13369
|
+
return intervals === 0 ? 0 : turns / intervals;
|
|
13370
|
+
};
|
|
13013
13371
|
var structureFeatures = (melody, submelody, opts) => {
|
|
13014
13372
|
const sigs = barSignatures(melody, opts);
|
|
13015
13373
|
return {
|
|
13374
|
+
turnRatio: turnRatio(melody),
|
|
13016
13375
|
sim1: selfSimilarity(sigs, 1),
|
|
13017
13376
|
sim2: selfSimilarity(sigs, 2),
|
|
13018
13377
|
sim4: selfSimilarity(sigs, 4),
|
|
@@ -13022,13 +13381,40 @@ var structureFeatures = (melody, submelody, opts) => {
|
|
|
13022
13381
|
complementarity: complementarity(melody, submelody, opts)
|
|
13023
13382
|
};
|
|
13024
13383
|
};
|
|
13384
|
+
var barNoteCounts = (notes, opts) => {
|
|
13385
|
+
const out = new Array(Math.max(1, opts.bars)).fill(0);
|
|
13386
|
+
for (const n of notes) {
|
|
13387
|
+
const bar = Math.floor(n.startStep / opts.stepsPerBar);
|
|
13388
|
+
if (bar >= 0 && bar < out.length) out[bar]++;
|
|
13389
|
+
}
|
|
13390
|
+
return out;
|
|
13391
|
+
};
|
|
13025
13392
|
var densityFeatures = (notes, opts) => {
|
|
13026
|
-
if (notes.length === 0)
|
|
13393
|
+
if (notes.length === 0)
|
|
13394
|
+
return {
|
|
13395
|
+
notesPerBar: 0,
|
|
13396
|
+
shortNoteRatio: 0,
|
|
13397
|
+
barDensityCv: 0,
|
|
13398
|
+
densityCliff: 0
|
|
13399
|
+
};
|
|
13027
13400
|
const eighth = opts.stepsPerBar / 8;
|
|
13028
13401
|
const short = notes.filter((n) => n.durationSteps <= eighth).length;
|
|
13402
|
+
const counts = barNoteCounts(notes, opts);
|
|
13403
|
+
const sung = counts.filter((c) => c > 0);
|
|
13404
|
+
const mean2 = sung.reduce((a, b) => a + b, 0) / Math.max(1, sung.length);
|
|
13405
|
+
const variance = sung.reduce((a, b) => a + (b - mean2) ** 2, 0) / Math.max(1, sung.length);
|
|
13406
|
+
let cliffs = 0;
|
|
13407
|
+
let pairs = 0;
|
|
13408
|
+
for (let i2 = 1; i2 < counts.length; i2++) {
|
|
13409
|
+
if (counts[i2 - 1] < 3 || counts[i2] === 0) continue;
|
|
13410
|
+
pairs++;
|
|
13411
|
+
if (counts[i2] <= counts[i2 - 1] * 0.3) cliffs++;
|
|
13412
|
+
}
|
|
13029
13413
|
return {
|
|
13030
13414
|
notesPerBar: notes.length / Math.max(1, opts.bars),
|
|
13031
|
-
shortNoteRatio: short / notes.length
|
|
13415
|
+
shortNoteRatio: short / notes.length,
|
|
13416
|
+
barDensityCv: mean2 === 0 ? 0 : Math.sqrt(variance) / mean2,
|
|
13417
|
+
densityCliff: pairs === 0 ? 0 : cliffs / pairs
|
|
13032
13418
|
};
|
|
13033
13419
|
};
|
|
13034
13420
|
var tensionFeatures = (barTension, opts) => {
|
|
@@ -13090,6 +13476,650 @@ var featureDistance = (a, b) => {
|
|
|
13090
13476
|
return Math.sqrt(sum);
|
|
13091
13477
|
};
|
|
13092
13478
|
|
|
13479
|
+
// src/compose-scales.ts
|
|
13480
|
+
var MAJOR_SCALE2 = [
|
|
13481
|
+
{ semi: 0, fifth: 0 },
|
|
13482
|
+
// C
|
|
13483
|
+
{ semi: 2, fifth: 2 },
|
|
13484
|
+
// D
|
|
13485
|
+
{ semi: 4, fifth: 4 },
|
|
13486
|
+
// E
|
|
13487
|
+
{ semi: 5, fifth: -1 },
|
|
13488
|
+
// F
|
|
13489
|
+
{ semi: 7, fifth: 1 },
|
|
13490
|
+
// G
|
|
13491
|
+
{ semi: 9, fifth: 3 },
|
|
13492
|
+
// A
|
|
13493
|
+
{ semi: 11, fifth: 5 }
|
|
13494
|
+
// B
|
|
13495
|
+
];
|
|
13496
|
+
var HARMONIC_MINOR_SCALE = [
|
|
13497
|
+
{ semi: 0, fifth: 0 },
|
|
13498
|
+
// C
|
|
13499
|
+
{ semi: 2, fifth: 2 },
|
|
13500
|
+
// D
|
|
13501
|
+
{ semi: 4, fifth: 4 },
|
|
13502
|
+
// E
|
|
13503
|
+
{ semi: 5, fifth: -1 },
|
|
13504
|
+
// F
|
|
13505
|
+
{ semi: 8, fifth: 8 },
|
|
13506
|
+
// G#
|
|
13507
|
+
{ semi: 9, fifth: 3 },
|
|
13508
|
+
// A
|
|
13509
|
+
{ semi: 11, fifth: 5 }
|
|
13510
|
+
// B
|
|
13511
|
+
];
|
|
13512
|
+
var HUNGARIAN_SCALE = [
|
|
13513
|
+
{ semi: 0, fifth: 0 },
|
|
13514
|
+
// C
|
|
13515
|
+
{ semi: 3, fifth: 9 },
|
|
13516
|
+
// D#
|
|
13517
|
+
{ semi: 4, fifth: 4 },
|
|
13518
|
+
// E
|
|
13519
|
+
{ semi: 5, fifth: -1 },
|
|
13520
|
+
// F
|
|
13521
|
+
{ semi: 8, fifth: 8 },
|
|
13522
|
+
// G#
|
|
13523
|
+
{ semi: 9, fifth: 3 },
|
|
13524
|
+
// A
|
|
13525
|
+
{ semi: 11, fifth: 5 }
|
|
13526
|
+
// B
|
|
13527
|
+
];
|
|
13528
|
+
var BLUES_SCALE = [
|
|
13529
|
+
{ semi: 0, fifth: 0 },
|
|
13530
|
+
// C
|
|
13531
|
+
{ semi: 3, fifth: -3 },
|
|
13532
|
+
// Eb
|
|
13533
|
+
{ semi: 5, fifth: -1 },
|
|
13534
|
+
// F
|
|
13535
|
+
{ semi: 6, fifth: -6 },
|
|
13536
|
+
// Gb(ブルーノート)
|
|
13537
|
+
{ semi: 7, fifth: 1 },
|
|
13538
|
+
// G
|
|
13539
|
+
{ semi: 10, fifth: -2 }
|
|
13540
|
+
// Bb
|
|
13541
|
+
];
|
|
13542
|
+
var RYUKYU_CENTER = {
|
|
13543
|
+
tonic: "C",
|
|
13544
|
+
half: "G",
|
|
13545
|
+
deceptive: "Em",
|
|
13546
|
+
tonicPattern: /^C(?![#b]|m)/,
|
|
13547
|
+
a: [
|
|
13548
|
+
["C", "F", "G", "C"],
|
|
13549
|
+
["C", "C", "F", "G"],
|
|
13550
|
+
["F", "G", "C", "C"],
|
|
13551
|
+
["C", "G", "F", "G"],
|
|
13552
|
+
["CM7", "F", "G", "C"],
|
|
13553
|
+
["C", "F", "C", "G"],
|
|
13554
|
+
["C", "Em", "F", "G"],
|
|
13555
|
+
["F", "C", "G", "C"]
|
|
13556
|
+
],
|
|
13557
|
+
b: [
|
|
13558
|
+
["F", "G", "Em", "C"],
|
|
13559
|
+
["F", "G", "C", "G"],
|
|
13560
|
+
["G", "F", "C", "C"],
|
|
13561
|
+
["FM7", "G", "Em", "F"],
|
|
13562
|
+
["C", "G", "F", "C"],
|
|
13563
|
+
["F", "Em", "F", "G"]
|
|
13564
|
+
],
|
|
13565
|
+
c: [
|
|
13566
|
+
["Em", "F", "G", "C"],
|
|
13567
|
+
["F", "C", "G", "Em"],
|
|
13568
|
+
["C", "Em", "F", "G"]
|
|
13569
|
+
]
|
|
13570
|
+
};
|
|
13571
|
+
var MIYAKOBUSHI_CENTER = {
|
|
13572
|
+
tonic: "Em",
|
|
13573
|
+
half: "Am",
|
|
13574
|
+
deceptive: "F",
|
|
13575
|
+
tonicPattern: /^E(?:m|sus)/,
|
|
13576
|
+
a: [
|
|
13577
|
+
["Em", "F", "Em", "Em"],
|
|
13578
|
+
["Esus4", "F", "Esus4", "Em"],
|
|
13579
|
+
["Em", "Am", "F", "Em"],
|
|
13580
|
+
["Am", "Em", "F", "Em"],
|
|
13581
|
+
["Em", "F", "Am", "Em"],
|
|
13582
|
+
["Em", "Em", "F", "F"],
|
|
13583
|
+
["Am", "F", "Em", "Em"],
|
|
13584
|
+
["Em", "FM7", "Am", "Em"]
|
|
13585
|
+
],
|
|
13586
|
+
b: [
|
|
13587
|
+
["F", "Am", "Em", "Em"],
|
|
13588
|
+
["Am", "F", "Em", "Em"],
|
|
13589
|
+
["F", "Em", "Am", "Em"],
|
|
13590
|
+
["FM7", "Am", "F", "Em"],
|
|
13591
|
+
["Am", "Em", "F", "Am"],
|
|
13592
|
+
["F", "Am", "F", "Em"]
|
|
13593
|
+
],
|
|
13594
|
+
c: [
|
|
13595
|
+
["Am", "Em", "F", "Am"],
|
|
13596
|
+
["F", "Am", "Esus4", "Em"],
|
|
13597
|
+
["Am", "F", "Em", "Em"]
|
|
13598
|
+
]
|
|
13599
|
+
};
|
|
13600
|
+
var RITSU_CENTER = {
|
|
13601
|
+
tonic: "Dsus4",
|
|
13602
|
+
half: "G",
|
|
13603
|
+
deceptive: "Em",
|
|
13604
|
+
tonicPattern: /^Dsus/,
|
|
13605
|
+
a: [
|
|
13606
|
+
["Dsus4", "G", "Dsus4", "Dsus4"],
|
|
13607
|
+
["Dsus4", "Em", "G", "Dsus4"],
|
|
13608
|
+
["G", "Dsus4", "Em", "Dsus4"],
|
|
13609
|
+
["Dsus4", "G", "Em", "G"],
|
|
13610
|
+
["Em", "G", "Dsus4", "Dsus4"],
|
|
13611
|
+
["Dsus4", "Em7", "G", "Dsus4"],
|
|
13612
|
+
["G", "Em", "Dsus4", "G"],
|
|
13613
|
+
["Dsus4", "Am", "G", "Dsus4"]
|
|
13614
|
+
],
|
|
13615
|
+
b: [
|
|
13616
|
+
["G", "Em", "Dsus4", "Dsus4"],
|
|
13617
|
+
["Em", "G", "Em", "Dsus4"],
|
|
13618
|
+
["G", "Am", "Em", "Dsus4"],
|
|
13619
|
+
["Em7", "G", "Dsus4", "Dsus4"],
|
|
13620
|
+
["Am", "G", "Em", "Dsus4"],
|
|
13621
|
+
["Dsus4", "Em", "G", "Em"]
|
|
13622
|
+
],
|
|
13623
|
+
c: [
|
|
13624
|
+
["Em", "Dsus4", "G", "Em"],
|
|
13625
|
+
["G", "Em7", "Am", "G"],
|
|
13626
|
+
["Am", "G", "Em", "Dsus4"]
|
|
13627
|
+
]
|
|
13628
|
+
};
|
|
13629
|
+
var HARMONIC_MINOR_CENTER = {
|
|
13630
|
+
tonic: "Am",
|
|
13631
|
+
half: "E7",
|
|
13632
|
+
deceptive: "F",
|
|
13633
|
+
tonicPattern: /^Am/,
|
|
13634
|
+
a: [
|
|
13635
|
+
["Am", "Dm", "E7", "Am"],
|
|
13636
|
+
// i-iv-V7-i。和声的短音階の基本形
|
|
13637
|
+
["Am", "F", "E7", "Am"],
|
|
13638
|
+
["Am", "E7", "Am", "Am"],
|
|
13639
|
+
["Dm", "E7", "Am", "Am"],
|
|
13640
|
+
["Am", "AmM7", "Dm", "E7"],
|
|
13641
|
+
// 主和音に導音を重ねたクリシェ
|
|
13642
|
+
["Am", "F", "Dm", "E7"],
|
|
13643
|
+
["F", "E7", "Am", "Am"],
|
|
13644
|
+
["Am", "Bm7-5", "E7", "Am"]
|
|
13645
|
+
],
|
|
13646
|
+
b: [
|
|
13647
|
+
["Dm", "E7", "Am", "Am"],
|
|
13648
|
+
["F", "E7", "Am", "E7"],
|
|
13649
|
+
["Dm7", "G#dim", "Am", "E7"],
|
|
13650
|
+
["F", "Dm", "E7", "Am"],
|
|
13651
|
+
["Am", "Dm", "Bm7-5", "E7"],
|
|
13652
|
+
["FM7", "E7", "Am", "Am"]
|
|
13653
|
+
],
|
|
13654
|
+
c: [
|
|
13655
|
+
["Dm", "Am", "Bm7-5", "E7"],
|
|
13656
|
+
["F", "C+", "Dm", "E7"],
|
|
13657
|
+
["Am", "F", "Dm", "E7"]
|
|
13658
|
+
]
|
|
13659
|
+
};
|
|
13660
|
+
var HIJAZ_CENTER = {
|
|
13661
|
+
tonic: "E",
|
|
13662
|
+
half: "F",
|
|
13663
|
+
deceptive: "Am",
|
|
13664
|
+
tonicPattern: /^E(?![#b]|m)/,
|
|
13665
|
+
a: [
|
|
13666
|
+
["E", "F", "E", "E"],
|
|
13667
|
+
// I-♭II。ヒジャーズの顔
|
|
13668
|
+
["E7", "F", "E", "E"],
|
|
13669
|
+
["Am", "F", "E", "E"],
|
|
13670
|
+
["E", "F", "Dm", "E"],
|
|
13671
|
+
["F", "E", "F", "E"],
|
|
13672
|
+
["Dm", "E", "F", "E"],
|
|
13673
|
+
["E7", "Am", "F", "E"],
|
|
13674
|
+
["E", "Dm", "F", "E"]
|
|
13675
|
+
],
|
|
13676
|
+
b: [
|
|
13677
|
+
["F", "E", "Am", "E"],
|
|
13678
|
+
["Dm", "C+", "F", "E"],
|
|
13679
|
+
["Am", "Dm", "F", "E"],
|
|
13680
|
+
["F", "Dm", "E", "E"],
|
|
13681
|
+
["E7", "F", "Dm", "E"],
|
|
13682
|
+
["Bm7-5", "E7", "Am", "E"]
|
|
13683
|
+
],
|
|
13684
|
+
c: [
|
|
13685
|
+
["Am", "Dm", "F", "E"],
|
|
13686
|
+
["Dm", "Am", "F", "E7"],
|
|
13687
|
+
["F", "C+", "Dm", "E"]
|
|
13688
|
+
]
|
|
13689
|
+
};
|
|
13690
|
+
var HUNGARIAN_CENTER = {
|
|
13691
|
+
tonic: "Am",
|
|
13692
|
+
half: "E",
|
|
13693
|
+
deceptive: "F",
|
|
13694
|
+
tonicPattern: /^Am/,
|
|
13695
|
+
a: [
|
|
13696
|
+
["Am", "E", "Am", "Am"],
|
|
13697
|
+
["Am", "F", "E", "Am"],
|
|
13698
|
+
["Am", "AmM7", "F", "E"],
|
|
13699
|
+
["F", "E", "Am", "Am"],
|
|
13700
|
+
["Am", "Fm", "E", "Am"],
|
|
13701
|
+
// ♭VIm。増2度を和音の側でも鳴らす
|
|
13702
|
+
["Am", "E", "F", "E"],
|
|
13703
|
+
["FM7", "E", "Am", "Am"],
|
|
13704
|
+
["Am", "C+", "F", "E"]
|
|
13705
|
+
],
|
|
13706
|
+
b: [
|
|
13707
|
+
["F", "E", "Am", "E"],
|
|
13708
|
+
["Fm", "E", "Am", "Am"],
|
|
13709
|
+
["Am", "F", "C+", "E"],
|
|
13710
|
+
["FM7", "Am", "F", "E"],
|
|
13711
|
+
["E", "F", "E", "Am"],
|
|
13712
|
+
["Am", "AmM7", "Fm", "E"]
|
|
13713
|
+
],
|
|
13714
|
+
c: [
|
|
13715
|
+
["F", "Am", "Fm", "E"],
|
|
13716
|
+
["C+", "F", "Am", "E"],
|
|
13717
|
+
["Am", "Fm", "F", "E"]
|
|
13718
|
+
]
|
|
13719
|
+
};
|
|
13720
|
+
var BLUES_CENTER = {
|
|
13721
|
+
tonic: "C7",
|
|
13722
|
+
half: "G7",
|
|
13723
|
+
deceptive: "F7",
|
|
13724
|
+
tonicPattern: /^C7/,
|
|
13725
|
+
a: [
|
|
13726
|
+
["C7", "C7", "C7", "C7"],
|
|
13727
|
+
// 12小節ブルースの1〜4小節
|
|
13728
|
+
["C7", "F7", "C7", "C7"],
|
|
13729
|
+
["C7", "C7", "F7", "F7"],
|
|
13730
|
+
["F7", "F7", "C7", "C7"],
|
|
13731
|
+
// 5〜8小節
|
|
13732
|
+
["C7", "F7", "C7", "G7"],
|
|
13733
|
+
["C7", "C7", "G7", "F7"],
|
|
13734
|
+
["C7", "F7", "G7", "C7"],
|
|
13735
|
+
["F7", "C7", "G7", "C7"]
|
|
13736
|
+
],
|
|
13737
|
+
b: [
|
|
13738
|
+
["F7", "F7", "C7", "C7"],
|
|
13739
|
+
["G7", "F7", "C7", "C7"],
|
|
13740
|
+
// 9〜12小節(ターンアラウンド)
|
|
13741
|
+
["F7", "G7", "C7", "C7"],
|
|
13742
|
+
["C7", "F7", "G7", "C7"],
|
|
13743
|
+
["F7", "C7", "G7", "F7"],
|
|
13744
|
+
["G7", "G7", "F7", "C7"]
|
|
13745
|
+
],
|
|
13746
|
+
c: [
|
|
13747
|
+
["G7", "F7", "C7", "G7"],
|
|
13748
|
+
["F7", "F7", "G7", "G7"],
|
|
13749
|
+
["C7", "C7", "F7", "G7"]
|
|
13750
|
+
]
|
|
13751
|
+
};
|
|
13752
|
+
var COMPOSE_SCALES = {
|
|
13753
|
+
yo: {
|
|
13754
|
+
id: "yo",
|
|
13755
|
+
label: "\u967D\u97F3\u968E\uFF08\u9577\u8ABF\u30DA\u30F3\u30BF\u30C8\u30CB\u30C3\u30AF\uFF09",
|
|
13756
|
+
tonic: 0,
|
|
13757
|
+
core: [0, 1, 2, 4, 5],
|
|
13758
|
+
// ド レ ミ ソ ラ
|
|
13759
|
+
minorish: false,
|
|
13760
|
+
strict: false,
|
|
13761
|
+
description: "J-POP\u306E\u6A19\u6E96\u3002\u660E\u308B\u304F\u7D20\u76F4\u3067\u6B4C\u3044\u3084\u3059\u3044\u3002\u5F93\u6765\u306E\u9577\u8ABF\u3068\u540C\u3058"
|
|
13762
|
+
},
|
|
13763
|
+
minyo: {
|
|
13764
|
+
id: "minyo",
|
|
13765
|
+
label: "\u6C11\u8B21\u97F3\u968E\uFF08\u77ED\u8ABF\u30DA\u30F3\u30BF\u30C8\u30CB\u30C3\u30AF\uFF09",
|
|
13766
|
+
tonic: 5,
|
|
13767
|
+
core: [5, 0, 1, 2, 4],
|
|
13768
|
+
// ラ ド レ ミ ソ
|
|
13769
|
+
minorish: true,
|
|
13770
|
+
strict: false,
|
|
13771
|
+
description: "\u308F\u3089\u3079\u6B4C\u30FB\u6C11\u8B21\u306E\u97F3\u968E\u3002\u7FF3\u308A\u304C\u3042\u308B\u304C\u6697\u3059\u304E\u306A\u3044\u3002\u5F93\u6765\u306E\u77ED\u8ABF\u3068\u540C\u3058"
|
|
13772
|
+
},
|
|
13773
|
+
ritsu: {
|
|
13774
|
+
id: "ritsu",
|
|
13775
|
+
label: "\u5F8B\u97F3\u968E",
|
|
13776
|
+
tonic: 1,
|
|
13777
|
+
core: [1, 2, 4, 5, 6],
|
|
13778
|
+
// レ ミ ソ ラ シ
|
|
13779
|
+
minorish: true,
|
|
13780
|
+
strict: true,
|
|
13781
|
+
center: RITSU_CENTER,
|
|
13782
|
+
description: "\u96C5\u697D\u30FB\u58F0\u660E\u306E\u97F3\u968E\u3002\u534A\u97F3\u3092\u542B\u307E\u305A\u3001\u5E73\u3089\u3067\u8358\u91CD\u306B\u6D41\u308C\u308B"
|
|
13783
|
+
},
|
|
13784
|
+
miyakobushi: {
|
|
13785
|
+
id: "miyakobushi",
|
|
13786
|
+
label: "\u90FD\u7BC0\u97F3\u968E\uFF08\u9670\u97F3\u968E\uFF09",
|
|
13787
|
+
tonic: 2,
|
|
13788
|
+
core: [2, 3, 5, 6, 0],
|
|
13789
|
+
// ミ ファ ラ シ ド
|
|
13790
|
+
minorish: true,
|
|
13791
|
+
strict: true,
|
|
13792
|
+
center: MIYAKOBUSHI_CENTER,
|
|
13793
|
+
description: "\u300E\u3055\u304F\u3089\u3055\u304F\u3089\u300F\u306E\u97F3\u968E\u3002\u4E3B\u97F3\u306E\u3059\u3050\u4E0A\u304C\u534A\u97F3\u3067\u3001\u7FF3\u308A\u304C\u6FC3\u3044"
|
|
13794
|
+
},
|
|
13795
|
+
ryukyu: {
|
|
13796
|
+
id: "ryukyu",
|
|
13797
|
+
label: "\u7409\u7403\u97F3\u968E",
|
|
13798
|
+
tonic: 0,
|
|
13799
|
+
core: [0, 2, 3, 4, 6],
|
|
13800
|
+
// ド ミ ファ ソ シ
|
|
13801
|
+
minorish: false,
|
|
13802
|
+
strict: true,
|
|
13803
|
+
center: RYUKYU_CENTER,
|
|
13804
|
+
description: "\u6C96\u7E04\u97F3\u968E\u3002\u30EC\u3068\u30E9\u3092\u629C\u304D\u3001\u30D5\u30A1\u3068\u30B7\u3092\u67F1\u306B\u3059\u308B\u3002\u660E\u308B\u304F\u8DF3\u306D\u308B"
|
|
13805
|
+
},
|
|
13806
|
+
dorian: {
|
|
13807
|
+
id: "dorian",
|
|
13808
|
+
label: "\u30C9\u30EA\u30A2\u30F3",
|
|
13809
|
+
tonic: 1,
|
|
13810
|
+
core: [1, 3, 4, 5, 0],
|
|
13811
|
+
// レ ファ ソ ラ ド
|
|
13812
|
+
minorish: true,
|
|
13813
|
+
strict: false,
|
|
13814
|
+
description: "\u77ED\u8ABF\u3060\u304C6\u5EA6\u304C\u660E\u308B\u3044\u3002\u30B1\u30EB\u30C8\u30FB\u30ED\u30C3\u30AF\u30FB\u30B7\u30C6\u30A3\u30DD\u30C3\u30D7"
|
|
13815
|
+
},
|
|
13816
|
+
phrygian: {
|
|
13817
|
+
id: "phrygian",
|
|
13818
|
+
label: "\u30D5\u30EA\u30B8\u30A2\u30F3",
|
|
13819
|
+
tonic: 2,
|
|
13820
|
+
core: [2, 3, 5, 6, 1],
|
|
13821
|
+
// ミ ファ ラ シ レ
|
|
13822
|
+
minorish: true,
|
|
13823
|
+
strict: false,
|
|
13824
|
+
description: "\u4E3B\u97F3\u306E\u4E0A\u304C\u534A\u97F3\u3002\u30B9\u30D1\u30CB\u30C3\u30B7\u30E5\uFF0F\u30E1\u30BF\u30EB\u306E\u7DCA\u8FEB\u3057\u305F\u97FF\u304D"
|
|
13825
|
+
},
|
|
13826
|
+
lydian: {
|
|
13827
|
+
id: "lydian",
|
|
13828
|
+
label: "\u30EA\u30C7\u30A3\u30A2\u30F3",
|
|
13829
|
+
tonic: 3,
|
|
13830
|
+
core: [3, 4, 6, 0, 2],
|
|
13831
|
+
// ファ ソ シ ド ミ
|
|
13832
|
+
minorish: false,
|
|
13833
|
+
strict: false,
|
|
13834
|
+
description: "4\u5EA6\u304C\u9AD8\u304F\u3001\u6D6E\u904A\u3057\u3066\u5E83\u304C\u308B\u3002\u6620\u753B\u97F3\u697D\u30FB\u30B2\u30FC\u30E0\u306E\u7A7A\u306E\u8272"
|
|
13835
|
+
},
|
|
13836
|
+
mixolydian: {
|
|
13837
|
+
id: "mixolydian",
|
|
13838
|
+
label: "\u30DF\u30AF\u30BD\u30EA\u30C7\u30A3\u30A2\u30F3",
|
|
13839
|
+
tonic: 4,
|
|
13840
|
+
core: [4, 5, 0, 1, 3],
|
|
13841
|
+
// ソ ラ ド レ ファ
|
|
13842
|
+
minorish: false,
|
|
13843
|
+
strict: false,
|
|
13844
|
+
description: "\u9577\u8ABF\u3060\u304C7\u5EA6\u304C\u4F4E\u3044\u3002\u30D6\u30EB\u30FC\u30B9\u30ED\u30C3\u30AF\u30FB\u6C11\u65CF\u97F3\u697D\u306E\u571F\u304F\u3055\u3055"
|
|
13845
|
+
},
|
|
13846
|
+
harmonic_minor: {
|
|
13847
|
+
id: "harmonic_minor",
|
|
13848
|
+
label: "\u548C\u58F0\u7684\u77ED\u97F3\u968E",
|
|
13849
|
+
tonic: 5,
|
|
13850
|
+
parent: HARMONIC_MINOR_SCALE,
|
|
13851
|
+
core: [5, 0, 1, 2, 4],
|
|
13852
|
+
// ラ ド レ ミ ソ♯
|
|
13853
|
+
minorish: true,
|
|
13854
|
+
strict: false,
|
|
13855
|
+
center: HARMONIC_MINOR_CENTER,
|
|
13856
|
+
description: "\u5C0E\u97F3\u30BD\u266F\u3092\u6301\u3064\u77ED\u8ABF\u3002\u58972\u5EA6\u304C\u6CE3\u304D\u3092\u4F5C\u308B\u3002\u30AF\u30E9\u30B7\u30C3\u30AF\u30FBV\u7CFB\u30FB\u5287\u4F34"
|
|
13857
|
+
},
|
|
13858
|
+
hijaz: {
|
|
13859
|
+
id: "hijaz",
|
|
13860
|
+
label: "\u30D2\u30B8\u30E3\u30FC\u30BA\uFF08\u30D5\u30EA\u30B8\u30A2\u30F3\u30FB\u30C9\u30DF\u30CA\u30F3\u30C8\uFF09",
|
|
13861
|
+
tonic: 2,
|
|
13862
|
+
parent: HARMONIC_MINOR_SCALE,
|
|
13863
|
+
core: [2, 3, 4, 5, 6],
|
|
13864
|
+
// ミ ファ ソ♯ ラ シ
|
|
13865
|
+
minorish: false,
|
|
13866
|
+
strict: false,
|
|
13867
|
+
center: HIJAZ_CENTER,
|
|
13868
|
+
description: "\u4E3B\u97F3\u306E\u4E0A\u304C\u534A\u97F3\u3001\u4E3B\u548C\u97F3\u306F\u9577\u4E09\u548C\u97F3\u3002\u4E2D\u6771\u30FB\u30B9\u30D1\u30CB\u30C3\u30B7\u30E5\u30FB\u30E1\u30BF\u30EB"
|
|
13869
|
+
},
|
|
13870
|
+
hungarian: {
|
|
13871
|
+
id: "hungarian",
|
|
13872
|
+
label: "\u30CF\u30F3\u30AC\u30EA\u30A2\u30F3\u30FB\u30DE\u30A4\u30CA\u30FC\uFF08\u30B8\u30D7\u30B7\u30FC\uFF09",
|
|
13873
|
+
tonic: 5,
|
|
13874
|
+
parent: HUNGARIAN_SCALE,
|
|
13875
|
+
core: [5, 0, 1, 2, 4],
|
|
13876
|
+
// ラ ド レ♯ ミ ソ♯
|
|
13877
|
+
minorish: true,
|
|
13878
|
+
strict: false,
|
|
13879
|
+
center: HUNGARIAN_CENTER,
|
|
13880
|
+
description: "\u58972\u5EA6\u304C2\u304B\u6240\u3002\u97F3\u968E\u306E\u4E2D\u3067\u3044\u3061\u3070\u3093\u8DF3\u306D\u305F\u3001\u7570\u56FD\u3081\u3044\u305F\u97FF\u304D"
|
|
13881
|
+
},
|
|
13882
|
+
blues: {
|
|
13883
|
+
id: "blues",
|
|
13884
|
+
label: "\u30D6\u30EB\u30FC\u30B9\u97F3\u968E",
|
|
13885
|
+
tonic: 0,
|
|
13886
|
+
parent: BLUES_SCALE,
|
|
13887
|
+
core: [0, 1, 2, 4, 5],
|
|
13888
|
+
// ド ミ♭ ファ ソ シ♭
|
|
13889
|
+
minorish: true,
|
|
13890
|
+
strict: true,
|
|
13891
|
+
center: BLUES_CENTER,
|
|
13892
|
+
description: "\u30D6\u30EB\u30FC\u30CE\u30FC\u30C8\u5165\u308A\u306E6\u97F3\u97F3\u968E\u3002\u77ED3\u5EA6\u3067\u6B4C\u3044\u3001\u4F34\u594F\u306F\u95773\u5EA6\u3067\u9CF4\u308B"
|
|
13893
|
+
}
|
|
13894
|
+
};
|
|
13895
|
+
var COMPOSE_SCALE_IDS = Object.keys(
|
|
13896
|
+
COMPOSE_SCALES
|
|
13897
|
+
);
|
|
13898
|
+
var TONIC_CENTERS = {
|
|
13899
|
+
// --- レ(律・ドリアン) ---
|
|
13900
|
+
1: {
|
|
13901
|
+
tonic: "Dm",
|
|
13902
|
+
half: "G",
|
|
13903
|
+
deceptive: "F",
|
|
13904
|
+
tonicPattern: /^Dm/,
|
|
13905
|
+
a: [
|
|
13906
|
+
["Dm", "G", "Dm", "Dm"],
|
|
13907
|
+
// i-IV の往復。ドリアンの顔
|
|
13908
|
+
["Dm", "Am", "G", "Dm"],
|
|
13909
|
+
["Dm", "C", "G", "Dm"],
|
|
13910
|
+
["Dm7", "G", "Dm7", "C"],
|
|
13911
|
+
["Dm", "F", "C", "G"],
|
|
13912
|
+
["Dm", "Em", "F", "G"],
|
|
13913
|
+
["Dm", "G", "F", "C"],
|
|
13914
|
+
["Dm7", "Em7", "FM7", "G"]
|
|
13915
|
+
],
|
|
13916
|
+
b: [
|
|
13917
|
+
["F", "G", "Am", "Dm"],
|
|
13918
|
+
["C", "G", "Dm", "Dm"],
|
|
13919
|
+
["G", "F", "C", "Dm"],
|
|
13920
|
+
["Am", "G", "F", "Dm"],
|
|
13921
|
+
["FM7", "G", "Em7", "Dm7"],
|
|
13922
|
+
["Dm", "G", "C", "Am"]
|
|
13923
|
+
],
|
|
13924
|
+
c: [
|
|
13925
|
+
["Am", "Dm", "G", "C"],
|
|
13926
|
+
["F", "Em", "Dm", "G"],
|
|
13927
|
+
["Dm", "Am", "Em", "G"]
|
|
13928
|
+
]
|
|
13929
|
+
},
|
|
13930
|
+
// --- ミ(都節・フリジアン) ---
|
|
13931
|
+
2: {
|
|
13932
|
+
tonic: "Em",
|
|
13933
|
+
half: "Am",
|
|
13934
|
+
deceptive: "C",
|
|
13935
|
+
tonicPattern: /^Em/,
|
|
13936
|
+
a: [
|
|
13937
|
+
["Em", "F", "Em", "Em"],
|
|
13938
|
+
// i-♭II。フリジアン/都節の顔
|
|
13939
|
+
["Em", "Am", "F", "Em"],
|
|
13940
|
+
["Am", "Em", "F", "Em"],
|
|
13941
|
+
["Em", "F", "G", "Em"],
|
|
13942
|
+
["Em", "Em", "F", "F"],
|
|
13943
|
+
["Em", "C", "F", "Em"],
|
|
13944
|
+
["Am", "F", "Em", "Em"],
|
|
13945
|
+
["Em7", "FM7", "Em7", "Am7"]
|
|
13946
|
+
],
|
|
13947
|
+
b: [
|
|
13948
|
+
["F", "G", "Am", "Em"],
|
|
13949
|
+
["Am", "G", "F", "Em"],
|
|
13950
|
+
["F", "Em", "Am", "Em"],
|
|
13951
|
+
["C", "F", "Em", "Em"],
|
|
13952
|
+
["FM7", "G", "Em7", "Am"],
|
|
13953
|
+
["Am", "Em", "F", "G"]
|
|
13954
|
+
],
|
|
13955
|
+
c: [
|
|
13956
|
+
["Am", "Em", "F", "C"],
|
|
13957
|
+
["C", "G", "Am", "Em"],
|
|
13958
|
+
["F", "C", "Am", "Em"]
|
|
13959
|
+
]
|
|
13960
|
+
},
|
|
13961
|
+
// --- ファ(リディアン) ---
|
|
13962
|
+
3: {
|
|
13963
|
+
tonic: "FM7",
|
|
13964
|
+
half: "C",
|
|
13965
|
+
deceptive: "Dm",
|
|
13966
|
+
tonicPattern: /^F(?![#b]|m)/,
|
|
13967
|
+
a: [
|
|
13968
|
+
["FM7", "G", "FM7", "FM7"],
|
|
13969
|
+
// I-II。リディアンの顔(♯4 が G の3度に居る)
|
|
13970
|
+
["FM7", "G", "Em", "Am"],
|
|
13971
|
+
["F", "G", "C", "F"],
|
|
13972
|
+
["FM7", "G", "Am", "F"],
|
|
13973
|
+
["F", "C", "G", "F"],
|
|
13974
|
+
["FM7", "Em7", "Dm7", "G"],
|
|
13975
|
+
["F", "G", "F", "C"],
|
|
13976
|
+
["FM7", "G", "Dm7", "F"]
|
|
13977
|
+
],
|
|
13978
|
+
b: [
|
|
13979
|
+
["G", "F", "C", "F"],
|
|
13980
|
+
["Am", "G", "FM7", "FM7"],
|
|
13981
|
+
["C", "G", "Am", "F"],
|
|
13982
|
+
["G", "Em", "Am", "F"],
|
|
13983
|
+
["Dm7", "G", "FM7", "FM7"],
|
|
13984
|
+
["FM7", "G", "Em7", "F"]
|
|
13985
|
+
],
|
|
13986
|
+
c: [
|
|
13987
|
+
["Dm", "Am", "F", "G"],
|
|
13988
|
+
["Am", "Em", "F", "G"],
|
|
13989
|
+
["C", "Am", "Dm", "F"]
|
|
13990
|
+
]
|
|
13991
|
+
},
|
|
13992
|
+
// --- ソ(ミクソリディアン) ---
|
|
13993
|
+
4: {
|
|
13994
|
+
tonic: "G",
|
|
13995
|
+
half: "Dm",
|
|
13996
|
+
deceptive: "Em",
|
|
13997
|
+
tonicPattern: /^G(?![#b]|m)/,
|
|
13998
|
+
a: [
|
|
13999
|
+
["G", "F", "C", "G"],
|
|
14000
|
+
// I-♭VII-IV。ミクソリディアンの顔
|
|
14001
|
+
["G", "C", "F", "G"],
|
|
14002
|
+
["G", "F", "G", "G"],
|
|
14003
|
+
["C", "G", "F", "G"],
|
|
14004
|
+
["G", "Dm", "F", "G"],
|
|
14005
|
+
["G", "Am", "F", "G"],
|
|
14006
|
+
["G", "F", "Dm", "C"],
|
|
14007
|
+
["G", "C", "G", "F"]
|
|
14008
|
+
],
|
|
14009
|
+
b: [
|
|
14010
|
+
["F", "C", "G", "G"],
|
|
14011
|
+
["Am", "F", "C", "G"],
|
|
14012
|
+
["C", "Dm", "F", "G"],
|
|
14013
|
+
["Em", "F", "C", "G"],
|
|
14014
|
+
["F", "G", "Am", "G"],
|
|
14015
|
+
["Dm7", "F", "C", "G"]
|
|
14016
|
+
],
|
|
14017
|
+
c: [
|
|
14018
|
+
["Am", "Em", "F", "G"],
|
|
14019
|
+
["C", "Am", "Dm", "G"],
|
|
14020
|
+
["Em", "Am", "F", "C"]
|
|
14021
|
+
]
|
|
14022
|
+
}
|
|
14023
|
+
};
|
|
14024
|
+
var scaleDegrees = (scale) => scale.parent ?? MAJOR_SCALE2;
|
|
14025
|
+
var scaleSize = (scale) => scaleDegrees(scale).length;
|
|
14026
|
+
var degreeToPitch = (scale, degree) => {
|
|
14027
|
+
const list = scaleDegrees(scale);
|
|
14028
|
+
const size = list.length;
|
|
14029
|
+
const index = (degree % size + size) % size;
|
|
14030
|
+
const octave = Math.floor(degree / size);
|
|
14031
|
+
const d = list[index];
|
|
14032
|
+
return { semi: d.semi + octave * 12, fifth: d.fifth };
|
|
14033
|
+
};
|
|
14034
|
+
var semitoneToDegree = (scale, semi) => {
|
|
14035
|
+
const list = scaleDegrees(scale);
|
|
14036
|
+
const octave = Math.floor(semi / 12);
|
|
14037
|
+
const within = semi - octave * 12;
|
|
14038
|
+
let best = 0;
|
|
14039
|
+
let bestDist = Number.POSITIVE_INFINITY;
|
|
14040
|
+
for (let i2 = 0; i2 < list.length; i2++) {
|
|
14041
|
+
const dist = Math.abs(list[i2].semi - within);
|
|
14042
|
+
if (dist < bestDist) {
|
|
14043
|
+
bestDist = dist;
|
|
14044
|
+
best = i2;
|
|
14045
|
+
}
|
|
14046
|
+
}
|
|
14047
|
+
return octave * list.length + best;
|
|
14048
|
+
};
|
|
14049
|
+
var walk = (scale, semi, delta) => degreeToPitch(scale, semitoneToDegree(scale, semi) + delta).semi;
|
|
14050
|
+
var scaleFifth = (scale, semi) => degreeToPitch(scale, semitoneToDegree(scale, semi)).fifth;
|
|
14051
|
+
var SCALE_PCS = /* @__PURE__ */ new Map();
|
|
14052
|
+
var scalePcs = (scale) => {
|
|
14053
|
+
const hit = SCALE_PCS.get(scale.id);
|
|
14054
|
+
if (hit) return hit;
|
|
14055
|
+
const set = new Set(
|
|
14056
|
+
scaleDegrees(scale).map((d) => (d.semi % 12 + 12) % 12)
|
|
14057
|
+
);
|
|
14058
|
+
SCALE_PCS.set(scale.id, set);
|
|
14059
|
+
return set;
|
|
14060
|
+
};
|
|
14061
|
+
var CORE_SORTED = /* @__PURE__ */ new Map();
|
|
14062
|
+
var sortedCore = (scale) => {
|
|
14063
|
+
const hit = CORE_SORTED.get(scale.id);
|
|
14064
|
+
if (hit) return hit;
|
|
14065
|
+
const sorted = [...scale.core].sort((a, b) => a - b);
|
|
14066
|
+
CORE_SORTED.set(scale.id, sorted);
|
|
14067
|
+
return sorted;
|
|
14068
|
+
};
|
|
14069
|
+
var CORE_PCS = /* @__PURE__ */ new Map();
|
|
14070
|
+
var corePcs = (scale) => {
|
|
14071
|
+
const hit = CORE_PCS.get(scale.id);
|
|
14072
|
+
if (hit) return hit;
|
|
14073
|
+
const list = scaleDegrees(scale);
|
|
14074
|
+
const set = new Set(scale.core.map((d) => (list[d].semi % 12 + 12) % 12));
|
|
14075
|
+
CORE_PCS.set(scale.id, set);
|
|
14076
|
+
return set;
|
|
14077
|
+
};
|
|
14078
|
+
var isCoreDegree = (scale, degree) => {
|
|
14079
|
+
const size = scaleSize(scale);
|
|
14080
|
+
return sortedCore(scale).includes((degree % size + size) % size);
|
|
14081
|
+
};
|
|
14082
|
+
var coreToDegree = (scale, step) => {
|
|
14083
|
+
const sorted = sortedCore(scale);
|
|
14084
|
+
const n = sorted.length;
|
|
14085
|
+
const index = (step % n + n) % n;
|
|
14086
|
+
const octave = Math.floor(step / n);
|
|
14087
|
+
return sorted[index] + octave * scaleSize(scale);
|
|
14088
|
+
};
|
|
14089
|
+
var degreeToCore = (scale, degree) => {
|
|
14090
|
+
const sorted = sortedCore(scale);
|
|
14091
|
+
const size = scaleSize(scale);
|
|
14092
|
+
const index = (degree % size + size) % size;
|
|
14093
|
+
const octave = Math.floor(degree / size);
|
|
14094
|
+
let best = 0;
|
|
14095
|
+
let bestDist = Number.POSITIVE_INFINITY;
|
|
14096
|
+
for (let i2 = 0; i2 < sorted.length; i2++) {
|
|
14097
|
+
const dist = Math.abs(sorted[i2] - index);
|
|
14098
|
+
if (dist < bestDist) {
|
|
14099
|
+
bestDist = dist;
|
|
14100
|
+
best = i2;
|
|
14101
|
+
}
|
|
14102
|
+
}
|
|
14103
|
+
return octave * sorted.length + best;
|
|
14104
|
+
};
|
|
14105
|
+
var isOutsideCore = (scale, semi) => scale.strict ? !corePcs(scale).has((semi % 12 + 12) % 12) : !isCoreDegree(scale, semitoneToDegree(scale, semi));
|
|
14106
|
+
var resolveComposeScale = (choice, minorKey, rnd = Math.random) => {
|
|
14107
|
+
const c = (choice ?? "").trim() || "auto";
|
|
14108
|
+
const hit = COMPOSE_SCALES[c];
|
|
14109
|
+
if (hit) return hit;
|
|
14110
|
+
if (c === "any")
|
|
14111
|
+
return COMPOSE_SCALES[COMPOSE_SCALE_IDS[Math.floor(rnd() * COMPOSE_SCALE_IDS.length)] ?? "yo"];
|
|
14112
|
+
return COMPOSE_SCALES[minorKey ? "minyo" : "yo"];
|
|
14113
|
+
};
|
|
14114
|
+
var getComposeScaleDescription = (choice) => {
|
|
14115
|
+
const hit = COMPOSE_SCALES[choice];
|
|
14116
|
+
if (hit) return hit.description;
|
|
14117
|
+
if (choice === "any")
|
|
14118
|
+
return `${COMPOSE_SCALE_IDS.length}\u3064\u306E\u97F3\u968E\u304B\u3089\u30E9\u30F3\u30C0\u30E0\u306B\u62BD\u9078\u3057\u307E\u3059`;
|
|
14119
|
+
return "\u30D9\u30FC\u30B9\u8ABF\u306E\u9577\u77ED\u306B\u5408\u308F\u305B\u3066\u3001\u967D\u97F3\u968E\uFF08\u9577\u8ABF\uFF09\u304B\u6C11\u8B21\u97F3\u968E\uFF08\u77ED\u8ABF\uFF09\u3092\u4F7F\u3044\u307E\u3059";
|
|
14120
|
+
};
|
|
14121
|
+
var resolveCenter = (scale) => scale.center ?? TONIC_CENTERS[scale.tonic] ?? null;
|
|
14122
|
+
|
|
13093
14123
|
// src/compose-sections.ts
|
|
13094
14124
|
var SECTION_LABELS = {
|
|
13095
14125
|
intro: "\u30A4\u30F3\u30C8\u30ED",
|
|
@@ -13324,8 +14354,8 @@ var sectionAt = (plan, bar) => {
|
|
|
13324
14354
|
|
|
13325
14355
|
// src/compose.ts
|
|
13326
14356
|
var STEP_SEMITONES = 2;
|
|
13327
|
-
var MAX_LEAP_SEMITONES =
|
|
13328
|
-
var MAX_BAR_LEAP_SEMITONES =
|
|
14357
|
+
var MAX_LEAP_SEMITONES = 10;
|
|
14358
|
+
var MAX_BAR_LEAP_SEMITONES = 10;
|
|
13329
14359
|
var HARD = {
|
|
13330
14360
|
/** メロディが1音も無い、音域が半音未満(同じ音を並べただけ)。 */
|
|
13331
14361
|
minMelodyRange: 3,
|
|
@@ -13351,6 +14381,9 @@ var WEIGHTS = {
|
|
|
13351
14381
|
*/
|
|
13352
14382
|
notesPerBar: 0.8,
|
|
13353
14383
|
shortNoteRatio: 0.6,
|
|
14384
|
+
/** 小節ごとの音数のばらつきと崖。平均だけを見ていて見逃していた偏り。 */
|
|
14385
|
+
barDensityCv: 0.6,
|
|
14386
|
+
densityCliff: 1,
|
|
13354
14387
|
/** 順次進行の比率。跳躍率だけを見ていると、跳躍の帯の上端に張り付く。 */
|
|
13355
14388
|
stepRatio: 0.8,
|
|
13356
14389
|
/** 調の外の音。0のままだと全曲が同じ音階をなぞるだけになる。 */
|
|
@@ -13363,10 +14396,15 @@ var WEIGHTS = {
|
|
|
13363
14396
|
sim4: 1.4,
|
|
13364
14397
|
sim8: 1.4,
|
|
13365
14398
|
phraseBreath: 1,
|
|
14399
|
+
/** 折り返しの多さ。跳躍率・順次進行率が揃っていても、これは別に足りなくなる。 */
|
|
14400
|
+
turnRatio: 0.8,
|
|
13366
14401
|
climaxPosition: 1,
|
|
13367
14402
|
climaxPeaks: 1,
|
|
13368
14403
|
/** メロディとサブメロが呼応しているか。 */
|
|
13369
14404
|
complementarity: 1,
|
|
14405
|
+
/** サブメロの音数と、その崖。メロディと同じ物差しで見る。 */
|
|
14406
|
+
subDensity: 0.6,
|
|
14407
|
+
subDensityCliff: 0.5,
|
|
13370
14408
|
// --- 和声(コードが要るのでコーパスからは較正できない) ---
|
|
13371
14409
|
/** B部でテンションが上がるか。 */
|
|
13372
14410
|
tensionRise: 1,
|
|
@@ -13442,6 +14480,10 @@ var FLAT_NOTE_NAMES = [
|
|
|
13442
14480
|
"Bb",
|
|
13443
14481
|
"B"
|
|
13444
14482
|
];
|
|
14483
|
+
var fifthsDistance = (semitones) => {
|
|
14484
|
+
const steps = (semitones * 7 % 12 + 12) % 12;
|
|
14485
|
+
return Math.min(steps, 12 - steps);
|
|
14486
|
+
};
|
|
13445
14487
|
var SEMITONE_TO_FIFTH_SHIFT = [
|
|
13446
14488
|
0,
|
|
13447
14489
|
// 0: C
|
|
@@ -13502,65 +14544,6 @@ var BPM_CHOICES = [
|
|
|
13502
14544
|
180,
|
|
13503
14545
|
185
|
|
13504
14546
|
];
|
|
13505
|
-
var MAJOR_SCALE2 = [
|
|
13506
|
-
{ semi: 0, fifth: 0 },
|
|
13507
|
-
// C
|
|
13508
|
-
{ semi: 2, fifth: 2 },
|
|
13509
|
-
// D
|
|
13510
|
-
{ semi: 4, fifth: 4 },
|
|
13511
|
-
// E
|
|
13512
|
-
{ semi: 5, fifth: -1 },
|
|
13513
|
-
// F
|
|
13514
|
-
{ semi: 7, fifth: 1 },
|
|
13515
|
-
// G
|
|
13516
|
-
{ semi: 9, fifth: 3 },
|
|
13517
|
-
// A
|
|
13518
|
-
{ semi: 11, fifth: 5 }
|
|
13519
|
-
// B
|
|
13520
|
-
];
|
|
13521
|
-
var degreeToPitch = (degree) => {
|
|
13522
|
-
const index = (degree % 7 + 7) % 7;
|
|
13523
|
-
const octave = Math.floor(degree / 7);
|
|
13524
|
-
const d = MAJOR_SCALE2[index];
|
|
13525
|
-
return { semi: d.semi + octave * 12, fifth: d.fifth };
|
|
13526
|
-
};
|
|
13527
|
-
var semitoneToDegree = (semi) => {
|
|
13528
|
-
const octave = Math.floor(semi / 12);
|
|
13529
|
-
const within = semi - octave * 12;
|
|
13530
|
-
let best = 0;
|
|
13531
|
-
let bestDist = Number.POSITIVE_INFINITY;
|
|
13532
|
-
for (let i2 = 0; i2 < MAJOR_SCALE2.length; i2++) {
|
|
13533
|
-
const dist = Math.abs(MAJOR_SCALE2[i2].semi - within);
|
|
13534
|
-
if (dist < bestDist) {
|
|
13535
|
-
bestDist = dist;
|
|
13536
|
-
best = i2;
|
|
13537
|
-
}
|
|
13538
|
-
}
|
|
13539
|
-
return octave * 7 + best;
|
|
13540
|
-
};
|
|
13541
|
-
var walk = (semi, delta) => degreeToPitch(semitoneToDegree(semi) + delta).semi;
|
|
13542
|
-
var NON_PENTATONIC_DEGREES = /* @__PURE__ */ new Set([3, 6]);
|
|
13543
|
-
var isNonPentatonic = (semi) => NON_PENTATONIC_DEGREES.has((semitoneToDegree(semi) % 7 + 7) % 7);
|
|
13544
|
-
var PENTATONIC_DEGREES = [0, 1, 2, 4, 5];
|
|
13545
|
-
var pentaToDegree = (penta) => {
|
|
13546
|
-
const index = (penta % 5 + 5) % 5;
|
|
13547
|
-
const octave = Math.floor(penta / 5);
|
|
13548
|
-
return PENTATONIC_DEGREES[index] + octave * 7;
|
|
13549
|
-
};
|
|
13550
|
-
var degreeToPenta = (degree) => {
|
|
13551
|
-
const index = (degree % 7 + 7) % 7;
|
|
13552
|
-
const octave = Math.floor(degree / 7);
|
|
13553
|
-
let best = 0;
|
|
13554
|
-
let bestDist = Number.POSITIVE_INFINITY;
|
|
13555
|
-
for (let i2 = 0; i2 < PENTATONIC_DEGREES.length; i2++) {
|
|
13556
|
-
const dist = Math.abs(PENTATONIC_DEGREES[i2] - index);
|
|
13557
|
-
if (dist < bestDist) {
|
|
13558
|
-
bestDist = dist;
|
|
13559
|
-
best = i2;
|
|
13560
|
-
}
|
|
13561
|
-
}
|
|
13562
|
-
return octave * 5 + best;
|
|
13563
|
-
};
|
|
13564
14547
|
var SECTION_A_PROGRESSIONS = [
|
|
13565
14548
|
["C", "G", "Am", "Em7"],
|
|
13566
14549
|
// カノン進行の前半
|
|
@@ -13594,6 +14577,22 @@ var SECTION_A_PROGRESSIONS = [
|
|
|
13594
14577
|
// ジャズ寄りの2-5-1
|
|
13595
14578
|
["Dm7", "G7", "Em7", "Am7"],
|
|
13596
14579
|
// 2-5-3-6
|
|
14580
|
+
// --- ライン・クリシェ(内声が半音ずつ動く) ---
|
|
14581
|
+
// 和音の1声だけを半音で動かして、和音記号は変わるのに響きは繋がったまま進む。
|
|
14582
|
+
// J-POPのサビ後半やAメロの定番。
|
|
14583
|
+
["Am", "AmM7", "Am7", "Am6"],
|
|
14584
|
+
// ラ→ソ#→ソ→ファ# の下行
|
|
14585
|
+
["C", "CM7", "C7", "F"],
|
|
14586
|
+
// ド→シ→シb→ラ
|
|
14587
|
+
["Am", "AmM7", "Am7", "D7"],
|
|
14588
|
+
// クリシェからドリアンのIVへ
|
|
14589
|
+
["F", "Fm", "CM7", "Am7"],
|
|
14590
|
+
// サブドミナントマイナーのクリシェ
|
|
14591
|
+
// --- ペダルポイント(ベースを保続する) ---
|
|
14592
|
+
// ベースだけ動かさずに上の和音を変える。緊張感が出る。分数和音のルートを
|
|
14593
|
+
// {@link chordTones} が先頭で返すので、ベースは自然に保続音になる。
|
|
14594
|
+
["C", "Am/C", "F/C", "G/C"],
|
|
14595
|
+
["Am", "Em/A", "F/A", "G/A"],
|
|
13597
14596
|
// --- 借用和音(同主短調・ミクソリディアンから借りる) ---
|
|
13598
14597
|
// **調の外の和音を進行そのものに持たせる。** ここまでの候補は全部ハ長調/イ短調の
|
|
13599
14598
|
// ダイアトニックで、セカンダリドミナント以外に調の外の音が出てこなかった。
|
|
@@ -13650,10 +14649,50 @@ var SECTION_A2_DERIVATIONS = [
|
|
|
13650
14649
|
var SECTION_A3_DERIVATIONS = [
|
|
13651
14650
|
(a, t) => [a[0], a[1], "G7", t],
|
|
13652
14651
|
(a, t) => [a[0], "Dm7", "G7", t],
|
|
13653
|
-
(a, t) => [a[0], "F", "G7", t],
|
|
13654
14652
|
(a, t) => [a[0], a[1], "Em7", t],
|
|
13655
|
-
|
|
14653
|
+
// アーメン終止(IV→I)
|
|
14654
|
+
(a, t) => [a[0], "G7", "F", t],
|
|
14655
|
+
(a, t) => [a[0], "Dm7", "FM7", t],
|
|
14656
|
+
// サブドミナントマイナー終止(IVm→I)
|
|
14657
|
+
(a, t) => [a[0], "G7", "Fm", t],
|
|
14658
|
+
(a, t) => [a[0], "F", "Fm", t]
|
|
13656
14659
|
];
|
|
14660
|
+
var SECTION_DECEPTIVE_DERIVATIONS = [
|
|
14661
|
+
(a, t) => [a[0], a[1], "G7", t === "Am" ? "F" : "Am"],
|
|
14662
|
+
(a, t) => [a[0], "Dm7", "G7", t === "Am" ? "FM7" : "Am7"],
|
|
14663
|
+
(a, t) => [a[0], "F", "G7", t === "Am" ? "F" : "Am7"]
|
|
14664
|
+
];
|
|
14665
|
+
var MODAL_FULL_DERIVATIONS = [
|
|
14666
|
+
(a, c) => [a[0], a[1], c.half, c.tonic],
|
|
14667
|
+
(a, c) => [a[0], c.half, a[2], c.tonic],
|
|
14668
|
+
(a, c) => [a[0], a[1], a[2], c.tonic],
|
|
14669
|
+
(a, c) => [c.tonic, c.half, a[2], c.tonic]
|
|
14670
|
+
];
|
|
14671
|
+
var MODAL_HALF_DERIVATIONS = [
|
|
14672
|
+
(a, c) => [a[0], a[1], a[2], c.half],
|
|
14673
|
+
(a, c) => [a[0], a[1], c.tonic, c.half],
|
|
14674
|
+
(a, c) => [a[0], c.tonic, a[2], c.half]
|
|
14675
|
+
];
|
|
14676
|
+
var MODAL_DECEPTIVE_DERIVATIONS = [
|
|
14677
|
+
(a, c) => [a[0], a[1], c.half, c.deceptive],
|
|
14678
|
+
(a, c) => [a[0], c.half, a[2], c.deceptive],
|
|
14679
|
+
(a, c) => [a[0], a[1], a[2], c.deceptive]
|
|
14680
|
+
];
|
|
14681
|
+
var MODAL_BORROW = {
|
|
14682
|
+
F: "Fm",
|
|
14683
|
+
// IV → IVm(サブドミナントマイナー。いちばん定番)
|
|
14684
|
+
FM7: "Fm7",
|
|
14685
|
+
Am: "Ab",
|
|
14686
|
+
// VIm → ♭VI
|
|
14687
|
+
Am7: "Ab",
|
|
14688
|
+
G: "Bb",
|
|
14689
|
+
// V → ♭VII(ミクソリディアン)
|
|
14690
|
+
G7: "Bb",
|
|
14691
|
+
Em7: "Eb",
|
|
14692
|
+
// IIIm → ♭III
|
|
14693
|
+
Dm7: "Dm7-5"
|
|
14694
|
+
// IIm7 → IIm7♭5(エオリアン)
|
|
14695
|
+
};
|
|
13657
14696
|
var CHORD_PATTERNS = [
|
|
13658
14697
|
"block",
|
|
13659
14698
|
"arpeggio",
|
|
@@ -13661,6 +14700,7 @@ var CHORD_PATTERNS = [
|
|
|
13661
14700
|
"yatsume",
|
|
13662
14701
|
"alternating"
|
|
13663
14702
|
];
|
|
14703
|
+
var chordPatternPool = (bpm) => bpm <= 130 ? [...CHORD_PATTERNS, "arpeggio-fast"] : CHORD_PATTERNS;
|
|
13664
14704
|
var CHORD_TONE_WEIGHT = {
|
|
13665
14705
|
0: 3,
|
|
13666
14706
|
// ルート
|
|
@@ -13838,6 +14878,54 @@ var RHYTHM_CELLS = [
|
|
|
13838
14878
|
density: "dense"
|
|
13839
14879
|
}
|
|
13840
14880
|
];
|
|
14881
|
+
var PHRASE_END_CELLS = [
|
|
14882
|
+
// 白玉で受けてから息を継ぐ(いちばん歌らしい終わり方)。
|
|
14883
|
+
{ value: [HALF, QUARTER, -QUARTER], density: "sparse" },
|
|
14884
|
+
{ value: [DOT_QUARTER, EIGHTH, HALF], density: "sparse" },
|
|
14885
|
+
{ value: [QUARTER, DOT_QUARTER, EIGHTH, -QUARTER], density: "sparse" },
|
|
14886
|
+
// 2音で降りてから息を継ぐ。
|
|
14887
|
+
{ value: [QUARTER, QUARTER, -HALF], density: "sparse" },
|
|
14888
|
+
{ value: [DOT_QUARTER, EIGHTH, -HALF], density: "sparse" },
|
|
14889
|
+
{ value: [HALF, -QUARTER, QUARTER], density: "sparse" },
|
|
14890
|
+
// 3音で言い切ってから息を継ぐ。
|
|
14891
|
+
{ value: [EIGHTH, EIGHTH, QUARTER, -HALF], density: "sparse" },
|
|
14892
|
+
{ value: [QUARTER, EIGHTH, EIGHTH, -HALF], density: "sparse" },
|
|
14893
|
+
{ value: [QUARTER, QUARTER, QUARTER, -QUARTER], density: "sparse" },
|
|
14894
|
+
{ value: [HALF, EIGHTH, EIGHTH, -QUARTER], density: "sparse" },
|
|
14895
|
+
// 4音で言い切ってから息を継ぐ。周りが7音前後の曲では、2音まで落とすと崖になる。
|
|
14896
|
+
{ value: [EIGHTH, EIGHTH, EIGHTH, EIGHTH, -HALF], density: "sparse" },
|
|
14897
|
+
{ value: [QUARTER, EIGHTH, EIGHTH, QUARTER, -QUARTER], density: "sparse" },
|
|
14898
|
+
{ value: [EIGHTH, EIGHTH, QUARTER, QUARTER, -QUARTER], density: "sparse" }
|
|
14899
|
+
];
|
|
14900
|
+
var MID_BREATH_CELLS = [
|
|
14901
|
+
{ value: [QUARTER, EIGHTH, EIGHTH, QUARTER, -QUARTER], density: "medium" },
|
|
14902
|
+
{ value: [EIGHTH, EIGHTH, QUARTER, QUARTER, -QUARTER], density: "medium" },
|
|
14903
|
+
{ value: [DOT_QUARTER, EIGHTH, QUARTER, QUARTER], density: "medium" },
|
|
14904
|
+
{ value: [QUARTER, QUARTER, EIGHTH, EIGHTH, -QUARTER], density: "medium" },
|
|
14905
|
+
{ value: [EIGHTH, EIGHTH, EIGHTH, EIGHTH, HALF], density: "medium" },
|
|
14906
|
+
{ value: [QUARTER, EIGHTH, EIGHTH, DOT_QUARTER, EIGHTH], density: "medium" }
|
|
14907
|
+
];
|
|
14908
|
+
var CELL_GRID = BASE_STEPS_PER_BAR / 16;
|
|
14909
|
+
var onsetKeyOf = (value) => {
|
|
14910
|
+
const on = [];
|
|
14911
|
+
let at = 0;
|
|
14912
|
+
for (const v of value) {
|
|
14913
|
+
if (v > 0) on.push(Math.round(at / CELL_GRID));
|
|
14914
|
+
at += Math.abs(v);
|
|
14915
|
+
}
|
|
14916
|
+
return on.join(",");
|
|
14917
|
+
};
|
|
14918
|
+
var UNSEEN_CELL_WEIGHT = 0.5;
|
|
14919
|
+
var cellEntryCount = /* @__PURE__ */ new Map();
|
|
14920
|
+
var cellWeightCache = /* @__PURE__ */ new Map();
|
|
14921
|
+
var cellWeight = (c) => {
|
|
14922
|
+
const cached = cellWeightCache.get(c.value);
|
|
14923
|
+
if (cached !== void 0) return cached;
|
|
14924
|
+
const key = onsetKeyOf(c.value);
|
|
14925
|
+
const w = (CORPUS_CELL_WEIGHTS[key] ?? UNSEEN_CELL_WEIGHT) / Math.max(1, cellEntryCount.get(key) ?? 1);
|
|
14926
|
+
cellWeightCache.set(c.value, w);
|
|
14927
|
+
return w;
|
|
14928
|
+
};
|
|
13841
14929
|
var HALF_BAR_FIGURES = [
|
|
13842
14930
|
[EIGHTH, EIGHTH, EIGHTH, EIGHTH],
|
|
13843
14931
|
// タタタタ
|
|
@@ -13870,6 +14958,14 @@ var HALF_BAR_FIGURES = [
|
|
|
13870
14958
|
// 2拍目裏からのアウフタクト(タタ)
|
|
13871
14959
|
[QUARTER, -EIGHTH, EIGHTH],
|
|
13872
14960
|
// ター・休タ(8分裏弱起)
|
|
14961
|
+
// **3+3+2(トレシーヨ)。** 参考曲91本で最も多かった「語彙に無い形」で、
|
|
14962
|
+
// 174小節ぶんの穴が空いていた(`scripts/compare-vocabulary.ts` の①)。
|
|
14963
|
+
// 付点8分が `[DOT_EIGHTH, SIXTEENTH]` の対でしか入っておらず、
|
|
14964
|
+
// 付点8分を2つ並べる形が作れなかった。界隈曲・ボカロの推進力の中心。
|
|
14965
|
+
[DOT_EIGHTH, DOT_EIGHTH, EIGHTH],
|
|
14966
|
+
[DOT_EIGHTH, DOT_EIGHTH, EIGHTH],
|
|
14967
|
+
// 4分音符が全部8分裏に来る形(食い)。参考曲で67小節ぶん取りこぼしていた。
|
|
14968
|
+
[-EIGHTH, QUARTER, EIGHTH],
|
|
13873
14969
|
// 付点8分+16分(タッカ)。歌モノで非常に多用される跳ね・推進力の型。
|
|
13874
14970
|
[DOT_EIGHTH, SIXTEENTH, EIGHTH, EIGHTH],
|
|
13875
14971
|
[EIGHTH, EIGHTH, DOT_EIGHTH, SIXTEENTH],
|
|
@@ -14035,9 +15131,21 @@ var MOTIF_CELLS = [
|
|
|
14035
15131
|
...buildMotifCells(),
|
|
14036
15132
|
...HAND_MOTIF_CELLS
|
|
14037
15133
|
];
|
|
15134
|
+
for (const c of [...MOTIF_CELLS, ...RHYTHM_CELLS]) {
|
|
15135
|
+
const key = onsetKeyOf(c.value);
|
|
15136
|
+
cellEntryCount.set(key, (cellEntryCount.get(key) ?? 0) + 1);
|
|
15137
|
+
}
|
|
14038
15138
|
var groovyCells = (cells, groove, rnd) => {
|
|
14039
15139
|
const hasSixteenth = (c) => c.value.some((v) => Math.abs(v) <= SIXTEENTH);
|
|
14040
|
-
if (groove === "eighth")
|
|
15140
|
+
if (groove === "eighth") {
|
|
15141
|
+
const plain = cells.filter((c) => !hasSixteenth(c));
|
|
15142
|
+
const spiced = cells.filter(hasSixteenth);
|
|
15143
|
+
if (spiced.length === 0) return plain;
|
|
15144
|
+
const out = [...plain];
|
|
15145
|
+
const take = Math.max(1, Math.round(plain.length * 0.1));
|
|
15146
|
+
for (let i2 = 0; i2 < take; i2++) out.push(pick(spiced, rnd));
|
|
15147
|
+
return out;
|
|
15148
|
+
}
|
|
14041
15149
|
const withSixteenth = cells.filter(hasSixteenth);
|
|
14042
15150
|
return withSixteenth.length > 0 && rnd() < 0.75 ? withSixteenth : cells;
|
|
14043
15151
|
};
|
|
@@ -14158,8 +15266,36 @@ var nearestChordTone = (targetSemi, tones, minWeight, preferColor = false) => {
|
|
|
14158
15266
|
return best;
|
|
14159
15267
|
};
|
|
14160
15268
|
var MELODY_LOW = 60;
|
|
14161
|
-
var MELODY_HIGH =
|
|
15269
|
+
var MELODY_HIGH = 81;
|
|
14162
15270
|
var MELODY_CENTER = (MELODY_LOW + MELODY_HIGH) / 2;
|
|
15271
|
+
var harmonyPitch = (scale, melodySemi, tones, prevHarmony, offset, parallel, against) => {
|
|
15272
|
+
const lo = Math.max(-12, Math.min(offset, 0) - 7);
|
|
15273
|
+
const hi = Math.min(12, Math.max(offset, 0) + 7);
|
|
15274
|
+
let best = null;
|
|
15275
|
+
let bestCost = Number.POSITIVE_INFINITY;
|
|
15276
|
+
for (const tone of tones) {
|
|
15277
|
+
const pc = pitchClass(tone.semi);
|
|
15278
|
+
for (let oct = 0; oct <= 10; oct++) {
|
|
15279
|
+
const semi = pc + oct * 12;
|
|
15280
|
+
const delta = semi - melodySemi;
|
|
15281
|
+
if (delta > hi || delta < lo) continue;
|
|
15282
|
+
const move = prevHarmony === null ? 0 : Math.abs(semi - prevHarmony);
|
|
15283
|
+
const stay = parallel ? move * 0.06 : move <= 2 ? move * 0.04 : 0.1 + (move - 2) * 0.9;
|
|
15284
|
+
let clash = 0;
|
|
15285
|
+
if (against !== null) {
|
|
15286
|
+
const g = Math.abs(semi - against) % 12;
|
|
15287
|
+
clash = g === 3 || g === 4 || g === 8 || g === 9 || g === 7 ? 0 : g === 0 ? 0.5 : 1.2;
|
|
15288
|
+
}
|
|
15289
|
+
const offCore = scale.strict && isOutsideCore(scale, semi) ? 1.5 : 0;
|
|
15290
|
+
const cost = stay + clash + offCore + Math.abs(delta - offset) * (parallel ? 1.4 : 0.7) + (3 - tone.weight) * 0.4;
|
|
15291
|
+
if (cost < bestCost) {
|
|
15292
|
+
bestCost = cost;
|
|
15293
|
+
best = { semi, fifth: tone.fifth };
|
|
15294
|
+
}
|
|
15295
|
+
}
|
|
15296
|
+
}
|
|
15297
|
+
return best ?? nearestChordTone(melodySemi + offset, tones, 2);
|
|
15298
|
+
};
|
|
14163
15299
|
var SUBMELODY_LOW = 55;
|
|
14164
15300
|
var SUBMELODY_HIGH = 74;
|
|
14165
15301
|
var BASS_LOW = 33;
|
|
@@ -14196,40 +15332,43 @@ var leapTarget = (from, tones, rnd) => {
|
|
|
14196
15332
|
];
|
|
14197
15333
|
return pick(weighted.length > 0 ? weighted : candidates, rnd);
|
|
14198
15334
|
};
|
|
14199
|
-
var landOn = (degrees, scaleIndex) => {
|
|
15335
|
+
var landOn = (scale, degrees, scaleIndex) => {
|
|
14200
15336
|
if (degrees.length === 0) return;
|
|
15337
|
+
const size = scaleSize(scale);
|
|
14201
15338
|
const last = degrees[degrees.length - 1];
|
|
14202
|
-
const index = (last %
|
|
15339
|
+
const index = (last % size + size) % size;
|
|
14203
15340
|
let delta = scaleIndex - index;
|
|
14204
|
-
if (delta >
|
|
14205
|
-
if (delta < -
|
|
15341
|
+
if (delta > size / 2) delta -= size;
|
|
15342
|
+
if (delta < -size / 2) delta += size;
|
|
14206
15343
|
degrees[degrees.length - 1] = last + delta;
|
|
14207
15344
|
};
|
|
14208
|
-
var landPitch = (pitches, scaleIndex) => {
|
|
15345
|
+
var landPitch = (scale, pitches, scaleIndex) => {
|
|
14209
15346
|
if (pitches.length === 0) return;
|
|
15347
|
+
const size = scaleSize(scale);
|
|
14210
15348
|
const last = pitches[pitches.length - 1];
|
|
14211
|
-
const degree = semitoneToDegree(last);
|
|
14212
|
-
const index = (degree %
|
|
15349
|
+
const degree = semitoneToDegree(scale, last);
|
|
15350
|
+
const index = (degree % size + size) % size;
|
|
14213
15351
|
let delta = scaleIndex - index;
|
|
14214
|
-
if (delta >
|
|
14215
|
-
if (delta < -
|
|
15352
|
+
if (delta > size / 2) delta -= size;
|
|
15353
|
+
if (delta < -size / 2) delta += size;
|
|
14216
15354
|
pitches[pitches.length - 1] = clampSemi(
|
|
14217
|
-
degreeToPitch(degree + delta).semi,
|
|
15355
|
+
degreeToPitch(scale, degree + delta).semi,
|
|
14218
15356
|
MELODY_LOW,
|
|
14219
15357
|
MELODY_HIGH
|
|
14220
15358
|
);
|
|
14221
15359
|
};
|
|
14222
|
-
var barDegrees = (role, slots, tones, style, motifContour, startDegree, contourOffset, repeatShift, barHeadWeight, preferColor, quarterSteps, rnd) => {
|
|
15360
|
+
var barDegrees = (role, slots, tones, style, scale, motifContour, startDegree, contourOffset, repeatShift, barHeadWeight, preferColor, quarterSteps, rnd) => {
|
|
14223
15361
|
const noteCount = slots.length;
|
|
14224
15362
|
const out = [];
|
|
14225
15363
|
if (role === "motif" || role === "sequence" || role === "climax" || role === "answer") {
|
|
14226
15364
|
const shift = (role === "sequence" ? pick([-2, -1, 1, 2], rnd) : role === "climax" ? 5 : 0) + repeatShift;
|
|
14227
15365
|
if (style.pentatonicMotif) {
|
|
14228
|
-
const
|
|
15366
|
+
const startCore = degreeToCore(scale, startDegree);
|
|
14229
15367
|
for (let i2 = 0; i2 < noteCount; i2++)
|
|
14230
15368
|
out.push(
|
|
14231
|
-
|
|
14232
|
-
|
|
15369
|
+
coreToDegree(
|
|
15370
|
+
scale,
|
|
15371
|
+
startCore + shift + motifContour[(contourOffset + i2) % motifContour.length]
|
|
14233
15372
|
)
|
|
14234
15373
|
);
|
|
14235
15374
|
} else {
|
|
@@ -14249,9 +15388,9 @@ var barDegrees = (role, slots, tones, style, motifContour, startDegree, contourO
|
|
|
14249
15388
|
for (let i2 = 0; i2 < noteCount; i2++)
|
|
14250
15389
|
out.push(startDegree + dir2 * (i2 < peak ? i2 : peak * 2 - i2 - 1));
|
|
14251
15390
|
} else if (style.runShape === "broken") {
|
|
14252
|
-
const arp = tones.map((t) => semitoneToDegree(clampSemi(t.semi, 60, 71))).sort((a, b) => a - b);
|
|
15391
|
+
const arp = tones.map((t) => semitoneToDegree(scale, clampSemi(t.semi, 60, 71))).sort((a, b) => a - b);
|
|
14253
15392
|
for (let i2 = 0; i2 < noteCount; i2++) {
|
|
14254
|
-
const oct = Math.floor(i2 / arp.length) *
|
|
15393
|
+
const oct = Math.floor(i2 / arp.length) * scaleSize(scale);
|
|
14255
15394
|
const idx = dir2 > 0 ? i2 % arp.length : arp.length - 1 - i2 % arp.length;
|
|
14256
15395
|
out.push(arp[idx] + dir2 * oct);
|
|
14257
15396
|
}
|
|
@@ -14274,7 +15413,10 @@ var barDegrees = (role, slots, tones, style, motifContour, startDegree, contourO
|
|
|
14274
15413
|
return out;
|
|
14275
15414
|
}
|
|
14276
15415
|
if (role === "cadence") {
|
|
14277
|
-
const tonic = semitoneToDegree(
|
|
15416
|
+
const tonic = semitoneToDegree(
|
|
15417
|
+
scale,
|
|
15418
|
+
clampSemi(72, MELODY_LOW, MELODY_HIGH)
|
|
15419
|
+
);
|
|
14278
15420
|
for (let i2 = 0; i2 < noteCount; i2++) {
|
|
14279
15421
|
if (style.cadenceShape === "descend") {
|
|
14280
15422
|
out.push(tonic + noteCount - 1 - i2);
|
|
@@ -14282,7 +15424,9 @@ var barDegrees = (role, slots, tones, style, motifContour, startDegree, contourO
|
|
|
14282
15424
|
const shape = [4, 2, 0];
|
|
14283
15425
|
out.push(tonic + shape[Math.min(i2, shape.length - 1)]);
|
|
14284
15426
|
} else if (style.cadenceShape === "leap-up") {
|
|
14285
|
-
out.push(
|
|
15427
|
+
out.push(
|
|
15428
|
+
i2 === noteCount - 1 ? tonic : tonic - scaleSize(scale) + Math.min(i2, 4)
|
|
15429
|
+
);
|
|
14286
15430
|
} else {
|
|
14287
15431
|
out.push(i2 === 0 && noteCount > 1 ? tonic + 1 : tonic);
|
|
14288
15432
|
}
|
|
@@ -14317,8 +15461,9 @@ var barDegrees = (role, slots, tones, style, motifContour, startDegree, contourO
|
|
|
14317
15461
|
for (let i2 = 0; i2 < out.length; i2++) {
|
|
14318
15462
|
if (!slots[i2].isStrong) continue;
|
|
14319
15463
|
out[i2] = semitoneToDegree(
|
|
15464
|
+
scale,
|
|
14320
15465
|
nearestChordTone(
|
|
14321
|
-
degreeToPitch(out[i2]).semi,
|
|
15466
|
+
degreeToPitch(scale, out[i2]).semi,
|
|
14322
15467
|
tones,
|
|
14323
15468
|
barHeadWeight,
|
|
14324
15469
|
preferColor
|
|
@@ -14329,9 +15474,9 @@ var barDegrees = (role, slots, tones, style, motifContour, startDegree, contourO
|
|
|
14329
15474
|
if (slots[i2].isStrong) continue;
|
|
14330
15475
|
if (slots[i2].value >= quarterSteps) {
|
|
14331
15476
|
if (rnd() < style.leapAffinity) {
|
|
14332
|
-
const from = degreeToPitch(out[i2 - 1]).semi;
|
|
15477
|
+
const from = degreeToPitch(scale, out[i2 - 1]).semi;
|
|
14333
15478
|
const target = leapTarget(from, tones, rnd);
|
|
14334
|
-
if (target !== null) out[i2] = semitoneToDegree(target);
|
|
15479
|
+
if (target !== null) out[i2] = semitoneToDegree(scale, target);
|
|
14335
15480
|
}
|
|
14336
15481
|
continue;
|
|
14337
15482
|
}
|
|
@@ -14341,17 +15486,20 @@ var barDegrees = (role, slots, tones, style, motifContour, startDegree, contourO
|
|
|
14341
15486
|
}
|
|
14342
15487
|
return out;
|
|
14343
15488
|
};
|
|
14344
|
-
var fitMotif = (degrees, slots, tones, prevSemi, quarterSteps, pentatonic) => {
|
|
15489
|
+
var fitMotif = (degrees, slots, tones, prevSemi, quarterSteps, scale, pentatonic, preferShift) => {
|
|
14345
15490
|
let best = degrees;
|
|
15491
|
+
let bestShift = 0;
|
|
14346
15492
|
let bestScore = Number.NEGATIVE_INFINITY;
|
|
15493
|
+
let preferScore = Number.NEGATIVE_INFINITY;
|
|
15494
|
+
let preferMoved = null;
|
|
14347
15495
|
for (let shift = -3; shift <= 3; shift++) {
|
|
14348
15496
|
const moved = degrees.map(
|
|
14349
|
-
(d) => pentatonic ?
|
|
15497
|
+
(d) => pentatonic ? coreToDegree(scale, degreeToCore(scale, d) + shift) : d + shift
|
|
14350
15498
|
);
|
|
14351
15499
|
let score = 0;
|
|
14352
15500
|
for (let i2 = 0; i2 < moved.length; i2++) {
|
|
14353
15501
|
const semi = clampSemi(
|
|
14354
|
-
degreeToPitch(moved[i2]).semi,
|
|
15502
|
+
degreeToPitch(scale, moved[i2]).semi,
|
|
14355
15503
|
MELODY_LOW,
|
|
14356
15504
|
MELODY_HIGH
|
|
14357
15505
|
);
|
|
@@ -14360,23 +15508,30 @@ var fitMotif = (degrees, slots, tones, prevSemi, quarterSteps, pentatonic) => {
|
|
|
14360
15508
|
score += important ? w * 3 : w;
|
|
14361
15509
|
}
|
|
14362
15510
|
const head = clampSemi(
|
|
14363
|
-
degreeToPitch(moved[0]).semi,
|
|
15511
|
+
degreeToPitch(scale, moved[0]).semi,
|
|
14364
15512
|
MELODY_LOW,
|
|
14365
15513
|
MELODY_HIGH
|
|
14366
15514
|
);
|
|
14367
15515
|
score -= Math.max(0, Math.abs(head - prevSemi) - MAX_BAR_LEAP_SEMITONES);
|
|
15516
|
+
if (shift === preferShift) {
|
|
15517
|
+
preferScore = score;
|
|
15518
|
+
preferMoved = moved;
|
|
15519
|
+
}
|
|
14368
15520
|
if (score > bestScore) {
|
|
14369
15521
|
bestScore = score;
|
|
15522
|
+
bestShift = shift;
|
|
14370
15523
|
best = moved;
|
|
14371
15524
|
}
|
|
14372
15525
|
}
|
|
14373
|
-
|
|
15526
|
+
if (preferMoved !== null && preferScore >= bestScore - 3)
|
|
15527
|
+
return { degrees: preferMoved, shift: preferShift };
|
|
15528
|
+
return { degrees: best, shift: bestShift };
|
|
14374
15529
|
};
|
|
14375
15530
|
var shapeBar = (degrees, slots, tones, prevSemi, opts) => {
|
|
14376
15531
|
const out = [];
|
|
14377
15532
|
let prev = prevSemi;
|
|
14378
15533
|
if (opts.preserveContour) {
|
|
14379
|
-
const raw = degrees.map((d) => degreeToPitch(d).semi);
|
|
15534
|
+
const raw = degrees.map((d) => degreeToPitch(opts.scale, d).semi);
|
|
14380
15535
|
const lo = Math.min(...raw);
|
|
14381
15536
|
const hi = Math.max(...raw);
|
|
14382
15537
|
let shift = 0;
|
|
@@ -14390,30 +15545,42 @@ var shapeBar = (degrees, slots, tones, prevSemi, opts) => {
|
|
|
14390
15545
|
}
|
|
14391
15546
|
for (let i2 = 0; i2 < degrees.length; i2++) {
|
|
14392
15547
|
let semi = clampSemi(
|
|
14393
|
-
degreeToPitch(degrees[i2]).semi,
|
|
15548
|
+
degreeToPitch(opts.scale, degrees[i2]).semi,
|
|
14394
15549
|
MELODY_LOW,
|
|
14395
15550
|
MELODY_HIGH
|
|
14396
15551
|
);
|
|
14397
15552
|
const limit = i2 === 0 ? MAX_BAR_LEAP_SEMITONES : MAX_LEAP_SEMITONES;
|
|
14398
15553
|
if (!opts.allowLeap && Math.abs(semi - prev) > limit) {
|
|
14399
15554
|
semi = clampSemi(
|
|
14400
|
-
walk(prev, Math.sign(semi - prev) * 3),
|
|
15555
|
+
walk(opts.scale, prev, Math.sign(semi - prev) * 3),
|
|
14401
15556
|
MELODY_LOW,
|
|
14402
15557
|
MELODY_HIGH
|
|
14403
15558
|
);
|
|
14404
15559
|
}
|
|
14405
15560
|
if (!opts.allowArpeggio && i2 >= 2 && Math.abs(out[i2 - 1] - out[i2 - 2]) > STEP_SEMITONES) {
|
|
14406
15561
|
const back = -Math.sign(out[i2 - 1] - out[i2 - 2]);
|
|
14407
|
-
semi = clampSemi(
|
|
15562
|
+
semi = clampSemi(
|
|
15563
|
+
walk(opts.scale, out[i2 - 1], back),
|
|
15564
|
+
MELODY_LOW,
|
|
15565
|
+
MELODY_HIGH
|
|
15566
|
+
);
|
|
14408
15567
|
}
|
|
14409
15568
|
if (toneWeight(semi, tones) === 0 && (slots[i2].isStrong || slots[i2].value >= opts.quarterSteps)) {
|
|
14410
15569
|
const resolved = semi + 1;
|
|
14411
|
-
const useResolved = resolved <= MELODY_HIGH && !
|
|
15570
|
+
const useResolved = resolved <= MELODY_HIGH && !scalePcs(opts.scale).has(pitchClass(resolved)) && toneWeight(resolved, tones) >= 2 && resolved !== prev && opts.rnd() < opts.chromaticAffinity;
|
|
14412
15571
|
if (useResolved) {
|
|
14413
15572
|
semi = resolved;
|
|
14414
15573
|
} else {
|
|
14415
|
-
const up = clampSemi(
|
|
14416
|
-
|
|
15574
|
+
const up = clampSemi(
|
|
15575
|
+
walk(opts.scale, semi, 1),
|
|
15576
|
+
MELODY_LOW,
|
|
15577
|
+
MELODY_HIGH
|
|
15578
|
+
);
|
|
15579
|
+
const down = clampSemi(
|
|
15580
|
+
walk(opts.scale, semi, -1),
|
|
15581
|
+
MELODY_LOW,
|
|
15582
|
+
MELODY_HIGH
|
|
15583
|
+
);
|
|
14417
15584
|
const score = (s) => toneWeight(s, tones) * 2 + (i2 > 0 && s === prev ? -3 : 0);
|
|
14418
15585
|
semi = score(down) >= score(up) ? down : up;
|
|
14419
15586
|
}
|
|
@@ -14421,7 +15588,14 @@ var shapeBar = (degrees, slots, tones, prevSemi, opts) => {
|
|
|
14421
15588
|
out.push(semi);
|
|
14422
15589
|
prev = semi;
|
|
14423
15590
|
}
|
|
14424
|
-
applyPentatonic(
|
|
15591
|
+
applyPentatonic(
|
|
15592
|
+
out,
|
|
15593
|
+
slots,
|
|
15594
|
+
tones,
|
|
15595
|
+
prevSemi,
|
|
15596
|
+
opts.quarterSteps / 2,
|
|
15597
|
+
opts.scale
|
|
15598
|
+
);
|
|
14425
15599
|
applyOctaveJumps(out, slots, opts.octaveAffinity, opts.rnd);
|
|
14426
15600
|
return out;
|
|
14427
15601
|
};
|
|
@@ -14438,27 +15612,27 @@ var applyOctaveJumps = (out, slots, affinity, rnd) => {
|
|
|
14438
15612
|
out[i2] = canUp && (!canDown || rnd() < 0.5) ? up : down;
|
|
14439
15613
|
}
|
|
14440
15614
|
};
|
|
14441
|
-
var applyPentatonic = (out, slots, tones, prevSemi, shortSteps) => {
|
|
15615
|
+
var applyPentatonic = (out, slots, tones, prevSemi, shortSteps, scale) => {
|
|
14442
15616
|
for (let i2 = 0; i2 < out.length; i2++) {
|
|
14443
15617
|
const semi = out[i2];
|
|
14444
|
-
if (!
|
|
14445
|
-
if (tones.some((t) => pitchClass(t.semi) === pitchClass(semi)))
|
|
15618
|
+
if (!isOutsideCore(scale, semi)) continue;
|
|
15619
|
+
if (!scale.strict && tones.some((t) => pitchClass(t.semi) === pitchClass(semi)))
|
|
15620
|
+
continue;
|
|
14446
15621
|
const before = i2 === 0 ? prevSemi : out[i2 - 1];
|
|
14447
15622
|
const after = i2 + 1 < out.length ? out[i2 + 1] : null;
|
|
14448
15623
|
const inByStep = Math.abs(semi - before) <= STEP_SEMITONES;
|
|
14449
15624
|
const outByStep = after !== null && Math.abs(after - semi) <= STEP_SEMITONES;
|
|
14450
|
-
if (inByStep || outByStep) continue;
|
|
14451
|
-
if (!slots[i2].isStrong && slots[i2].value <= shortSteps)
|
|
14452
|
-
|
|
14453
|
-
const
|
|
14454
|
-
const
|
|
15625
|
+
if (scale.strict ? inByStep && outByStep : inByStep || outByStep) continue;
|
|
15626
|
+
if (!scale.strict && !slots[i2].isStrong && slots[i2].value <= shortSteps)
|
|
15627
|
+
continue;
|
|
15628
|
+
const up = clampSemi(walk(scale, semi, 1), MELODY_LOW, MELODY_HIGH);
|
|
15629
|
+
const down = clampSemi(walk(scale, semi, -1), MELODY_LOW, MELODY_HIGH);
|
|
15630
|
+
const score = (s) => (isOutsideCore(scale, s) ? -4 : 0) + toneWeight(s, tones) + (s === before ? -3 : 0) + (after !== null ? -Math.abs(after - s) / 12 : 0);
|
|
14455
15631
|
out[i2] = score(down) >= score(up) ? down : up;
|
|
14456
15632
|
}
|
|
14457
15633
|
};
|
|
14458
|
-
var DIATONIC_PCS = new Set(MAJOR_SCALE2.map((d) => d.semi));
|
|
14459
15634
|
var SHARP_FIFTHS = [0, 7, 2, 9, 4, -1, 6, 1, 8, 3, 10, 5];
|
|
14460
15635
|
var FLAT_FIFTHS = [0, -5, 2, -3, 4, -1, -6, 1, -4, 3, -2, 5];
|
|
14461
|
-
var diatonicFifth = (semi) => degreeToPitch(semitoneToDegree(semi)).fifth;
|
|
14462
15636
|
var nearestOctaveOf = (near, semi) => {
|
|
14463
15637
|
const pc = pitchClass(semi);
|
|
14464
15638
|
let best = pc;
|
|
@@ -14473,7 +15647,7 @@ var nearestOctaveOf = (near, semi) => {
|
|
|
14473
15647
|
}
|
|
14474
15648
|
return best;
|
|
14475
15649
|
};
|
|
14476
|
-
var applyChromatic = (pitches, fifths, slots, tones, opts) => {
|
|
15650
|
+
var applyChromatic = (scale, pitches, fifths, slots, tones, opts) => {
|
|
14477
15651
|
const last = pitches.length - 1;
|
|
14478
15652
|
for (let i2 = 0; i2 < pitches.length; i2++) {
|
|
14479
15653
|
const tone = tones.find(
|
|
@@ -14481,7 +15655,8 @@ var applyChromatic = (pitches, fifths, slots, tones, opts) => {
|
|
|
14481
15655
|
);
|
|
14482
15656
|
if (tone) fifths[i2] = tone.fifth;
|
|
14483
15657
|
}
|
|
14484
|
-
const
|
|
15658
|
+
const pcs = scalePcs(scale);
|
|
15659
|
+
const altered = tones.filter((t) => !pcs.has(pitchClass(t.semi)));
|
|
14485
15660
|
for (let i2 = 0; i2 < pitches.length; i2++) {
|
|
14486
15661
|
if (opts.keepLast && i2 === last) continue;
|
|
14487
15662
|
if (!slots[i2].isStrong && slots[i2].value < opts.quarterSteps) continue;
|
|
@@ -14509,7 +15684,7 @@ var applyChromatic = (pitches, fifths, slots, tones, opts) => {
|
|
|
14509
15684
|
const span = Math.abs(after - before);
|
|
14510
15685
|
const target = span === 2 ? before + dir : span === 3 ? after - dir : null;
|
|
14511
15686
|
if (target === null) continue;
|
|
14512
|
-
if (
|
|
15687
|
+
if (pcs.has(pitchClass(target))) continue;
|
|
14513
15688
|
if (target === before || target === after) continue;
|
|
14514
15689
|
if (target < MELODY_LOW || target > MELODY_HIGH) continue;
|
|
14515
15690
|
pitches[i2] = target;
|
|
@@ -14517,7 +15692,8 @@ var applyChromatic = (pitches, fifths, slots, tones, opts) => {
|
|
|
14517
15692
|
lastAltered = i2;
|
|
14518
15693
|
}
|
|
14519
15694
|
};
|
|
14520
|
-
var draw = (options, resolvedKey, rnd) => {
|
|
15695
|
+
var draw = (options, resolvedKey, scale, rnd) => {
|
|
15696
|
+
const center = resolveCenter(scale);
|
|
14521
15697
|
const stepsPerBar = options.stepsPerBar;
|
|
14522
15698
|
const edo = options.edo === 31 ? 31 : 12;
|
|
14523
15699
|
const scaleStep = (v) => Math.max(1, Math.round(Math.abs(v) * stepsPerBar / BASE_STEPS_PER_BAR)) * Math.sign(v);
|
|
@@ -14543,9 +15719,24 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14543
15719
|
options.template
|
|
14544
15720
|
);
|
|
14545
15721
|
const totalBars = sectionPlan.reduce((sum, s) => sum + s.bars, 0);
|
|
14546
|
-
|
|
15722
|
+
const relativeKinds = /* @__PURE__ */ new Set();
|
|
15723
|
+
let relativeShift = 0;
|
|
15724
|
+
if (rnd() < 0.25 && !center) {
|
|
15725
|
+
for (const kind of pick(
|
|
15726
|
+
[["prechorus"], ["bridge"], ["prechorus", "bridge"]],
|
|
15727
|
+
rnd
|
|
15728
|
+
))
|
|
15729
|
+
relativeKinds.add(kind);
|
|
15730
|
+
if (rnd() < 0.33) relativeShift = resolvedKey.mode === "minor" ? -3 : 3;
|
|
15731
|
+
}
|
|
15732
|
+
const floating = rnd() < 0.12;
|
|
15733
|
+
if (relativeKinds.size > 0 && relativeShift !== 0) {
|
|
15734
|
+
for (const s of sectionPlan)
|
|
15735
|
+
if (relativeKinds.has(s.kind)) s.keyShift = relativeShift;
|
|
15736
|
+
}
|
|
15737
|
+
if (relativeKinds.size === 0 && !floating && rnd() < 0.32) {
|
|
14547
15738
|
const modType = pick(
|
|
14548
|
-
["chorus_up", "chorus_up", "
|
|
15739
|
+
["chorus_up", "chorus_up", "color", "dominant", "subdominant"],
|
|
14549
15740
|
rnd
|
|
14550
15741
|
);
|
|
14551
15742
|
if (modType === "chorus_up") {
|
|
@@ -14554,15 +15745,83 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14554
15745
|
for (let i2 = 0; i2 < sectionPlan.length; i2++) {
|
|
14555
15746
|
if (sectionPlan[i2].kind === "chorus") lastChorusIdx = i2;
|
|
14556
15747
|
}
|
|
14557
|
-
if (lastChorusIdx >= 0)
|
|
14558
|
-
for (let i2 = lastChorusIdx; i2 < sectionPlan.length; i2++)
|
|
15748
|
+
if (lastChorusIdx >= 0)
|
|
15749
|
+
for (let i2 = lastChorusIdx; i2 < sectionPlan.length; i2++)
|
|
14559
15750
|
sectionPlan[i2].keyShift = shift;
|
|
14560
|
-
}
|
|
14561
|
-
}
|
|
14562
15751
|
} else {
|
|
14563
|
-
const shift = pick([-2, 3], rnd);
|
|
14564
|
-
|
|
14565
|
-
|
|
15752
|
+
const shift = modType === "dominant" ? 7 : modType === "subdominant" ? 5 : pick([-2, 3], rnd);
|
|
15753
|
+
const kinds = pick(
|
|
15754
|
+
[["prechorus"], ["bridge"], ["prechorus", "bridge"]],
|
|
15755
|
+
rnd
|
|
15756
|
+
);
|
|
15757
|
+
for (const s of sectionPlan)
|
|
15758
|
+
if (kinds.includes(s.kind)) s.keyShift = shift;
|
|
15759
|
+
}
|
|
15760
|
+
}
|
|
15761
|
+
const harmonyFrom = pick(
|
|
15762
|
+
["chorus", "chorus", "prechorus"],
|
|
15763
|
+
rnd
|
|
15764
|
+
);
|
|
15765
|
+
const harmonyParallel = rnd() < 0.45;
|
|
15766
|
+
const harmonyCoverage = 0.7 + rnd() * 0.3;
|
|
15767
|
+
const useHarmony2 = rnd() < 0.3;
|
|
15768
|
+
const useOctaveLayer = !useHarmony2 && rnd() < 0.25;
|
|
15769
|
+
const octaveCoverage = 0.3 + rnd() * 0.3;
|
|
15770
|
+
const harmonyOffset = useHarmony2 ? (
|
|
15771
|
+
// 3声のときは1声目を下〜ユニゾン側へ寄せ、2声目を上へ回して主旋律を挟む
|
|
15772
|
+
// (参考: チョウチン少女 ch12/ch11/ch13)。
|
|
15773
|
+
pick([-5, -3, 0, 0, 3], rnd)
|
|
15774
|
+
) : harmonyParallel ? pick([3, 4, 5, 9, 7, 0, -5], rnd) : pick([3, 4, 5, 0, -5, -4, -7], rnd);
|
|
15775
|
+
let prevHarmony = null;
|
|
15776
|
+
let prevHarmony2 = null;
|
|
15777
|
+
const harmony2Offset = harmonyOffset + pick([9, 9, 9, 8, 7], rnd);
|
|
15778
|
+
const harmonyKinds = harmonyFrom === "prechorus" ? ["prechorus", "chorus", "bridge"] : ["chorus"];
|
|
15779
|
+
const duetStyle = pick(
|
|
15780
|
+
[
|
|
15781
|
+
"none",
|
|
15782
|
+
"none",
|
|
15783
|
+
"none",
|
|
15784
|
+
"none",
|
|
15785
|
+
"none",
|
|
15786
|
+
"section",
|
|
15787
|
+
"phrase",
|
|
15788
|
+
"chorus",
|
|
15789
|
+
"verse"
|
|
15790
|
+
],
|
|
15791
|
+
rnd
|
|
15792
|
+
);
|
|
15793
|
+
const duetOwner = new Array(totalBars).fill(false);
|
|
15794
|
+
if (duetStyle !== "none") {
|
|
15795
|
+
let melodySection = 0;
|
|
15796
|
+
for (const section of sectionPlan) {
|
|
15797
|
+
if (!section.spec.melody) continue;
|
|
15798
|
+
const isChorus = section.kind === "chorus" || section.kind === "drop_chorus";
|
|
15799
|
+
const isVerse = section.kind === "verse";
|
|
15800
|
+
const takeSection = melodySection % 2 === 1;
|
|
15801
|
+
melodySection++;
|
|
15802
|
+
const alternate = duetStyle === "phrase" ? !isChorus : duetStyle === "chorus" ? isChorus : duetStyle === "verse" ? isVerse : false;
|
|
15803
|
+
if (!alternate && !(duetStyle === "section" && takeSection && !isChorus))
|
|
15804
|
+
continue;
|
|
15805
|
+
for (let b = section.startBar; b < section.startBar + section.bars; b++) {
|
|
15806
|
+
if (alternate) {
|
|
15807
|
+
if (Math.floor((b - section.startBar) / 2) % 2 === 1)
|
|
15808
|
+
duetOwner[b] = true;
|
|
15809
|
+
} else duetOwner[b] = true;
|
|
15810
|
+
}
|
|
15811
|
+
}
|
|
15812
|
+
}
|
|
15813
|
+
const duetSpans = [];
|
|
15814
|
+
{
|
|
15815
|
+
let from = -1;
|
|
15816
|
+
for (let b = 0; b <= totalBars; b++) {
|
|
15817
|
+
const owned = b < totalBars && duetOwner[b];
|
|
15818
|
+
if (owned && from < 0) from = b;
|
|
15819
|
+
if (!owned && from >= 0) {
|
|
15820
|
+
const lead = from === 0 ? 0 : scaleStep(
|
|
15821
|
+
pick([0, 0, EIGHTH, EIGHTH, QUARTER, DOT_QUARTER], rnd)
|
|
15822
|
+
);
|
|
15823
|
+
duetSpans.push([from * stepsPerBar - lead, b * stepsPerBar]);
|
|
15824
|
+
from = -1;
|
|
14566
15825
|
}
|
|
14567
15826
|
}
|
|
14568
15827
|
}
|
|
@@ -14572,51 +15831,129 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14572
15831
|
barKeyShift[b] = s.keyShift;
|
|
14573
15832
|
}
|
|
14574
15833
|
}
|
|
14575
|
-
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
|
|
14577
|
-
|
|
15834
|
+
const progAPool = center ? center.a : 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;
|
|
15835
|
+
const withoutTonic = (pool, root) => {
|
|
15836
|
+
const isTonic = (c) => center ? center.tonicPattern.test(c) : root === "Am" ? /^Am/.test(c) : /^C(?![#b]|m)/.test(c);
|
|
15837
|
+
const out = pool.filter((p) => !p.some(isTonic));
|
|
15838
|
+
return out.length > 0 ? out : pool;
|
|
15839
|
+
};
|
|
15840
|
+
const homeRoot = center ? center.tonic : resolvedKey.mode === "minor" ? "Am" : "C";
|
|
15841
|
+
const progA = pick(
|
|
15842
|
+
floating ? withoutTonic(progAPool, homeRoot) : progAPool,
|
|
15843
|
+
rnd
|
|
15844
|
+
);
|
|
15845
|
+
const progBPool = (center ? center.b : SECTION_B_PROGRESSIONS).filter(
|
|
14578
15846
|
(p) => p.join("|") !== progA.join("|")
|
|
14579
15847
|
);
|
|
14580
|
-
const progB = pick(
|
|
15848
|
+
const progB = pick(
|
|
15849
|
+
floating ? withoutTonic(progBPool, homeRoot) : progBPool,
|
|
15850
|
+
rnd
|
|
15851
|
+
);
|
|
15852
|
+
const progRelativePool = center ? center.a : SECTION_A_PROGRESSIONS.filter(
|
|
15853
|
+
(p) => resolvedKey.mode === "minor" ? !p[0].startsWith("Am") : p[0].startsWith("Am")
|
|
15854
|
+
);
|
|
15855
|
+
const progRelative = pick(
|
|
15856
|
+
floating ? withoutTonic(progRelativePool, homeRoot) : progRelativePool,
|
|
15857
|
+
rnd
|
|
15858
|
+
);
|
|
15859
|
+
const progCPool = (center ? center.c : SECTION_C_PROGRESSIONS).filter(
|
|
15860
|
+
(p) => p.join("|") !== progA.join("|") && p.join("|") !== progB.join("|")
|
|
15861
|
+
);
|
|
14581
15862
|
const progC = pick(
|
|
14582
|
-
|
|
14583
|
-
(p) => p.join("|") !== progA.join("|") && p.join("|") !== progB.join("|")
|
|
14584
|
-
),
|
|
15863
|
+
floating ? withoutTonic(progCPool, homeRoot) : progCPool,
|
|
14585
15864
|
rnd
|
|
14586
15865
|
);
|
|
14587
|
-
const tonic = progA[0].startsWith("Am") ? "Am" : "C";
|
|
14588
|
-
const progHalf = pick(SECTION_A2_DERIVATIONS, rnd)(progA);
|
|
14589
|
-
const progFull = pick(SECTION_A3_DERIVATIONS, rnd)(progA, tonic);
|
|
15866
|
+
const tonic = center ? center.tonic : progA[0].startsWith("Am") ? "Am" : "C";
|
|
15867
|
+
const progHalf = center ? pick(MODAL_HALF_DERIVATIONS, rnd)(progA, center) : pick(SECTION_A2_DERIVATIONS, rnd)(progA);
|
|
15868
|
+
const progFull = center ? pick(MODAL_FULL_DERIVATIONS, rnd)(progA, center) : pick(SECTION_A3_DERIVATIONS, rnd)(progA, tonic);
|
|
15869
|
+
const progDeceptive = center ? pick(MODAL_DECEPTIVE_DERIVATIONS, rnd)(progA, center) : pick(SECTION_DECEPTIVE_DERIVATIONS, rnd)(progA, tonic);
|
|
15870
|
+
let lastChorusBar = -1;
|
|
15871
|
+
for (const section of sectionPlan)
|
|
15872
|
+
if (section.kind === "chorus" || section.kind === "outro")
|
|
15873
|
+
lastChorusBar = section.startBar;
|
|
14590
15874
|
const progression = [];
|
|
14591
15875
|
for (const section of sectionPlan) {
|
|
14592
|
-
const base = section.spec.progression === "c" ? progC : section.spec.progression === "b" ? progB : progA;
|
|
15876
|
+
const base = relativeKinds.has(section.kind) ? progRelative : section.spec.progression === "c" ? progC : section.spec.progression === "b" ? progB : progA;
|
|
14593
15877
|
for (let i2 = 0; i2 < section.bars; i2 += 4) {
|
|
14594
15878
|
const isLastPhrase = i2 + 4 >= section.bars;
|
|
14595
15879
|
if (!isLastPhrase) {
|
|
14596
15880
|
progression.push(...base);
|
|
14597
15881
|
continue;
|
|
14598
15882
|
}
|
|
14599
|
-
if (section.kind
|
|
15883
|
+
if (relativeKinds.has(section.kind)) progression.push(...base);
|
|
15884
|
+
else if (section.kind === "prechorus") progression.push(...progHalf);
|
|
14600
15885
|
else if (section.kind === "chorus" || section.kind === "outro")
|
|
14601
|
-
progression.push(
|
|
15886
|
+
progression.push(
|
|
15887
|
+
...floating ? progHalf : section.startBar === lastChorusBar ? progFull : progDeceptive
|
|
15888
|
+
);
|
|
14602
15889
|
else progression.push(...base);
|
|
14603
15890
|
}
|
|
14604
15891
|
}
|
|
14605
15892
|
progression.length = totalBars;
|
|
15893
|
+
const PIVOT_CHORDS = {
|
|
15894
|
+
7: ["C", "Em7", "G", "Am"],
|
|
15895
|
+
// 属調(ト長調)と共通
|
|
15896
|
+
5: ["C", "Dm7", "F", "Am"]
|
|
15897
|
+
// 下属調(ヘ長調)と共通
|
|
15898
|
+
};
|
|
15899
|
+
for (let bar = 1; bar < totalBars; bar++) {
|
|
15900
|
+
const shift = barKeyShift[bar];
|
|
15901
|
+
const prev = barKeyShift[bar - 1];
|
|
15902
|
+
if (shift === prev) continue;
|
|
15903
|
+
const distance = fifthsDistance(shift - prev);
|
|
15904
|
+
if (distance >= 4) continue;
|
|
15905
|
+
const prevSec = sectionAt(sectionPlan, bar - 1);
|
|
15906
|
+
if (prevSec.kind === "prechorus" || prevSec.kind === "chorus" || prevSec.kind === "outro")
|
|
15907
|
+
continue;
|
|
15908
|
+
if (rnd() < 0.35) continue;
|
|
15909
|
+
const pivots = PIVOT_CHORDS[((shift - prev) % 12 + 12) % 12];
|
|
15910
|
+
if (distance <= 1 && pivots && rnd() < 0.6) {
|
|
15911
|
+
progression[bar - 1] = pick(pivots, rnd);
|
|
15912
|
+
} else {
|
|
15913
|
+
progression[bar - 1] = transposeChordName("G7", shift - prev);
|
|
15914
|
+
}
|
|
15915
|
+
}
|
|
15916
|
+
if (rnd() < 0.3 && !center) {
|
|
15917
|
+
const tonicNames = tonic === "Am" ? ["Am", "Am7"] : ["C", "CM7"];
|
|
15918
|
+
const spots = [];
|
|
15919
|
+
for (let bar = 0; bar + 1 < totalBars; bar++) {
|
|
15920
|
+
if (barKeyShift[bar] !== barKeyShift[bar + 1]) continue;
|
|
15921
|
+
if (!MODAL_BORROW[progression[bar]]) continue;
|
|
15922
|
+
if (!tonicNames.includes(progression[bar + 1])) continue;
|
|
15923
|
+
spots.push(bar);
|
|
15924
|
+
}
|
|
15925
|
+
if (spots.length > 0) {
|
|
15926
|
+
const at = pick(spots, rnd);
|
|
15927
|
+
progression[at] = MODAL_BORROW[progression[at]];
|
|
15928
|
+
}
|
|
15929
|
+
}
|
|
14606
15930
|
const chordProgression = progression.map((chord, bar) => transposeChordName(chord, barKeyShift[bar])).join("|");
|
|
14607
|
-
const chordPattern = pick(CHORD_PATTERNS, rnd);
|
|
14608
15931
|
const rootShift = resolvedKey.rootShift;
|
|
14609
15932
|
const bpm = pick(BPM_CHOICES, rnd);
|
|
15933
|
+
const chordPattern = pick(chordPatternPool(bpm), rnd);
|
|
14610
15934
|
const sourceOf = (kind) => kind === "chorus" || kind === "interlude" || kind === "drop_chorus" ? "b" : kind === "prechorus" ? "a2" : kind === "bridge" ? "c" : "a";
|
|
15935
|
+
const landingOf = (section) => {
|
|
15936
|
+
if (section.spec.landing === null) return null;
|
|
15937
|
+
const relativeHere = relativeKinds.has(section.kind);
|
|
15938
|
+
const tonicDegree = relativeHere ? scale.tonic === 5 ? 0 : 5 : scale.tonic;
|
|
15939
|
+
const size = scaleSize(scale);
|
|
15940
|
+
let landing = (section.spec.landing + tonicDegree) % size;
|
|
15941
|
+
if (floating && landing === tonicDegree)
|
|
15942
|
+
landing = (landing + pick([2, 4], rnd)) % size;
|
|
15943
|
+
return landing;
|
|
15944
|
+
};
|
|
14611
15945
|
const units2 = [];
|
|
14612
15946
|
for (const section of sectionPlan) {
|
|
14613
15947
|
const unitCount = Math.max(1, Math.round(section.bars / 2));
|
|
14614
15948
|
const src = sourceOf(section.kind);
|
|
14615
15949
|
for (let u = 0; u < unitCount; u++) {
|
|
14616
15950
|
if (!section.spec.melody) {
|
|
15951
|
+
const solo2 = section.kind === "interlude";
|
|
14617
15952
|
units2.push({
|
|
14618
|
-
|
|
14619
|
-
|
|
15953
|
+
// 見せ場なので走句と山を交互に置く。`hold` のままだと
|
|
15954
|
+
// リズム型が最も薄いものになり、ソロにならない。
|
|
15955
|
+
role: solo2 ? u % 2 === 0 ? "run" : "climax" : "hold",
|
|
15956
|
+
source: solo2 ? "solo" : "silent",
|
|
14620
15957
|
landing: null,
|
|
14621
15958
|
section
|
|
14622
15959
|
});
|
|
@@ -14625,22 +15962,28 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14625
15962
|
const isLast = u === unitCount - 1;
|
|
14626
15963
|
if (u % 2 === 0) {
|
|
14627
15964
|
units2.push({
|
|
14628
|
-
role: section.kind === "chorus" ? "climax" : src === "a2" || u > 0 ? "sequence" : "motif",
|
|
15965
|
+
role: section.kind === "bridge" ? "step" : section.kind === "chorus" ? "climax" : src === "a2" || u > 0 ? "sequence" : "motif",
|
|
14629
15966
|
source: src,
|
|
14630
15967
|
landing: null,
|
|
14631
15968
|
section
|
|
14632
15969
|
});
|
|
14633
15970
|
} else {
|
|
15971
|
+
const landing = landingOf(section);
|
|
14634
15972
|
units2.push({
|
|
14635
|
-
role: isLast &&
|
|
15973
|
+
role: isLast && landing === 0 ? "cadence" : "answer",
|
|
14636
15974
|
source: "answer",
|
|
14637
|
-
landing: isLast ?
|
|
15975
|
+
landing: isLast ? landing : null,
|
|
14638
15976
|
section
|
|
14639
15977
|
});
|
|
14640
15978
|
}
|
|
14641
15979
|
}
|
|
14642
15980
|
}
|
|
14643
15981
|
const barRoles = units2.flatMap((u) => [u.role, u.role]);
|
|
15982
|
+
for (const section of sectionPlan) {
|
|
15983
|
+
if (section.kind !== "prechorus") continue;
|
|
15984
|
+
const last = section.startBar + section.bars - 1;
|
|
15985
|
+
if (last < barRoles.length) barRoles[last] = "run";
|
|
15986
|
+
}
|
|
14644
15987
|
const barInUnit = (bar) => bar % 2;
|
|
14645
15988
|
const unitOf = (bar) => Math.floor(bar / 2);
|
|
14646
15989
|
const restatementOf = (bar) => {
|
|
@@ -14671,9 +16014,13 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14671
16014
|
groove: pick(["eighth", "sixteenth"], rnd),
|
|
14672
16015
|
arcPeriod: pick([4, 8, 8, 16], rnd),
|
|
14673
16016
|
arcPhase: pick([0, 1, 2], rnd),
|
|
14674
|
-
arcAmp:
|
|
14675
|
-
|
|
14676
|
-
|
|
16017
|
+
arcAmp: 2 + rnd() * 3,
|
|
16018
|
+
// オクターブ跳躍は参考曲では音程の1.0%しかない。上げすぎると音域が広がる。
|
|
16019
|
+
octaveAffinity: 0.06 + rnd() * 0.12,
|
|
16020
|
+
// **音階を厳しく締める曲は必ず中核音の歩数で組む。** ダイアトニックの度数で輪郭を
|
|
16021
|
+
// 作ると、琉球音階なのにレやラが輪郭の中に入り込む。ファ・シを自由に使う
|
|
16022
|
+
// 陽・民謡だけが、曲ごとに掛けたり掛けなかったりする({@link ComposeScale.strict})。
|
|
16023
|
+
pentatonicMotif: rnd() < 0.55 || scale.strict,
|
|
14677
16024
|
runShape: pick(["scale", "turn", "broken", "zigzag"], rnd),
|
|
14678
16025
|
stepShape: pick(
|
|
14679
16026
|
["arch", "valley", "ascend", "descend", "wave", "pivot"],
|
|
@@ -14684,10 +16031,18 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14684
16031
|
["descend", "five-three-one", "leap-up", "hold-tonic"],
|
|
14685
16032
|
rnd
|
|
14686
16033
|
),
|
|
14687
|
-
//
|
|
14688
|
-
|
|
16034
|
+
// 参考曲の跳躍率は p25〜p75 で 0.28〜0.41、最大跳躍の中央値は9半音。
|
|
16035
|
+
// 2声を交互に書いたチャンネルを主旋律と誤検出していた頃は 0.31〜0.65 に
|
|
16036
|
+
// 見えており、それに合わせて上限を高く取っていた。
|
|
16037
|
+
leapAffinity: 0.05 + rnd() * 0.2,
|
|
14689
16038
|
// 界隈曲らしさ:調の外の音(クロマチック)や微小な逸脱を積極的に許容する。
|
|
14690
|
-
|
|
16039
|
+
// 刻みを細かくすると経過音の置き場所が増えるので、同じ係数でも変化音は増える。
|
|
16040
|
+
// 参考曲の1.75倍まで伸びていたぶんを引く。
|
|
16041
|
+
// **音階を厳しく締める曲は変化音を控える。** 半音の経過音は長調・短調の泣きメロの
|
|
16042
|
+
// 芯だが、琉球・都節・律ではその半音が音階の外にしか無く、入れたぶんだけ
|
|
16043
|
+
// 音階の色が薄まる(実測で嬰ヘが3%出て、音階内のラ2%より多いという逆転が
|
|
16044
|
+
// 起きていた)。0 にはしない——民族音階の実際の曲にも装飾の半音は出る。
|
|
16045
|
+
chromaticAffinity: (rnd() < 0.2 ? 0 : 0.12 + rnd() * 0.33) * (scale.strict ? 0.4 : 1),
|
|
14691
16046
|
barHeadWeight: rnd() < 0.5 ? 3 : 2,
|
|
14692
16047
|
bassStyle: pick(
|
|
14693
16048
|
[
|
|
@@ -14714,7 +16069,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14714
16069
|
subInterval: pick([3, 4, 8, 9], rnd)
|
|
14715
16070
|
};
|
|
14716
16071
|
const motifPool = groovyCells(MOTIF_CELLS, style.groove, rnd);
|
|
14717
|
-
const targetNotesPerBar = 4 + rnd() * 4;
|
|
16072
|
+
const targetNotesPerBar = 4.5 + rnd() * 4.5;
|
|
14718
16073
|
const targetRestRatio = 0.02 + rnd() * 0.1;
|
|
14719
16074
|
const cellNotes = (c) => c.value.filter((v) => v > 0).length;
|
|
14720
16075
|
const cellRest = (c) => {
|
|
@@ -14727,17 +16082,27 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14727
16082
|
return total === 0 ? 0 : rest / total;
|
|
14728
16083
|
};
|
|
14729
16084
|
const cellDistance = (c, densityMul = 1) => Math.abs(cellNotes(c) - targetNotesPerBar * densityMul) + Math.abs(cellRest(c) - targetRestRatio / Math.max(0.5, densityMul)) * 8;
|
|
16085
|
+
const weightedPick = (pool) => {
|
|
16086
|
+
let total = 0;
|
|
16087
|
+
for (const c of pool) total += cellWeight(c);
|
|
16088
|
+
let r = rnd() * total;
|
|
16089
|
+
for (const c of pool) {
|
|
16090
|
+
r -= cellWeight(c);
|
|
16091
|
+
if (r <= 0) return c;
|
|
16092
|
+
}
|
|
16093
|
+
return pool[pool.length - 1];
|
|
16094
|
+
};
|
|
14730
16095
|
const pickCell = (pool, densityMul = 1) => {
|
|
14731
|
-
let best =
|
|
16096
|
+
let best = weightedPick(pool);
|
|
14732
16097
|
for (let i2 = 0; i2 < 2; i2++) {
|
|
14733
|
-
const c =
|
|
16098
|
+
const c = weightedPick(pool);
|
|
14734
16099
|
if (cellDistance(c, densityMul) < cellDistance(best, densityMul))
|
|
14735
16100
|
best = c;
|
|
14736
16101
|
}
|
|
14737
16102
|
return best;
|
|
14738
16103
|
};
|
|
14739
16104
|
const motifCell = pickCell(motifPool, 0.85);
|
|
14740
|
-
const motifCell2 = rnd() < 0.
|
|
16105
|
+
const motifCell2 = rnd() < 0.72 ? motifCell : pickCell(
|
|
14741
16106
|
motifPool.filter((c) => c !== motifCell),
|
|
14742
16107
|
0.85
|
|
14743
16108
|
);
|
|
@@ -14755,7 +16120,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14755
16120
|
),
|
|
14756
16121
|
1.1
|
|
14757
16122
|
);
|
|
14758
|
-
const motifA22 = rnd() < 0.
|
|
16123
|
+
const motifA22 = rnd() < 0.72 ? motifA2 : pickCell(
|
|
14759
16124
|
motifPool.filter((c) => c !== motifA2),
|
|
14760
16125
|
1.1
|
|
14761
16126
|
);
|
|
@@ -14765,7 +16130,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14765
16130
|
),
|
|
14766
16131
|
0.9
|
|
14767
16132
|
);
|
|
14768
|
-
const motifC2 = rnd() < 0.
|
|
16133
|
+
const motifC2 = rnd() < 0.72 ? motifC : pickCell(
|
|
14769
16134
|
motifPool.filter((c) => c !== motifC),
|
|
14770
16135
|
0.9
|
|
14771
16136
|
);
|
|
@@ -14804,12 +16169,24 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14804
16169
|
),
|
|
14805
16170
|
rnd
|
|
14806
16171
|
).value;
|
|
14807
|
-
const
|
|
14808
|
-
|
|
14809
|
-
|
|
14810
|
-
)
|
|
14811
|
-
|
|
14812
|
-
|
|
16172
|
+
const breathBySection = /* @__PURE__ */ new Map();
|
|
16173
|
+
{
|
|
16174
|
+
let prev = null;
|
|
16175
|
+
for (const section of sectionPlan) {
|
|
16176
|
+
if (!section.spec.melody) continue;
|
|
16177
|
+
const pool = PHRASE_END_CELLS.filter((c) => c !== prev);
|
|
16178
|
+
const cell = pick(pool.length > 0 ? pool : PHRASE_END_CELLS, rnd);
|
|
16179
|
+
breathBySection.set(section.startBar, cell);
|
|
16180
|
+
prev = cell;
|
|
16181
|
+
}
|
|
16182
|
+
}
|
|
16183
|
+
const midBreathCell = pick(MID_BREATH_CELLS, rnd);
|
|
16184
|
+
const breathBars = /* @__PURE__ */ new Set();
|
|
16185
|
+
const phraseEndBars = /* @__PURE__ */ new Set();
|
|
16186
|
+
for (const section of sectionPlan) {
|
|
16187
|
+
if (!section.spec.melody) continue;
|
|
16188
|
+
phraseEndBars.add(section.startBar + section.bars - 1);
|
|
16189
|
+
}
|
|
14813
16190
|
const barRhythms = [];
|
|
14814
16191
|
for (let bar = 0; bar < totalBars; bar++) {
|
|
14815
16192
|
const u = unitOf(bar);
|
|
@@ -14817,9 +16194,10 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14817
16194
|
const source = restatementOf(bar);
|
|
14818
16195
|
if (source !== null) {
|
|
14819
16196
|
barRhythms.push(barRhythms[source]);
|
|
16197
|
+
if (breathBars.has(source)) breathBars.add(bar);
|
|
14820
16198
|
continue;
|
|
14821
16199
|
}
|
|
14822
|
-
const isB = units2[u].source === "b";
|
|
16200
|
+
const isB = units2[u].source === "b" || units2[u].source === "solo";
|
|
14823
16201
|
const isA2 = units2[u].source === "a2";
|
|
14824
16202
|
const isC = units2[u].source === "c";
|
|
14825
16203
|
const isPrechorusEnd = units2[u].section.kind === "prechorus" && bar === units2[u].section.startBar + units2[u].section.bars - 1;
|
|
@@ -14834,7 +16212,14 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14834
16212
|
const prevSource = units2[u - 1]?.source;
|
|
14835
16213
|
const [head, tail] = prevSource === "b" ? [motifB, motifB2] : prevSource === "a2" ? [motifA2, motifA22] : [motifCell, motifCell2];
|
|
14836
16214
|
const answerVar = prevSource === "b" ? motifBVar : motifVar;
|
|
14837
|
-
|
|
16215
|
+
if (half === 0) {
|
|
16216
|
+
cell = rnd() < 0.15 ? answerVar : head;
|
|
16217
|
+
} else if (isPeriodEnd) {
|
|
16218
|
+
cell = breathBySection.get(units2[u].section.startBar) ?? tail;
|
|
16219
|
+
breathBars.add(bar);
|
|
16220
|
+
} else {
|
|
16221
|
+
cell = rnd() < 0.28 ? midBreathCell : rnd() < 0.12 ? answerVar : tail;
|
|
16222
|
+
}
|
|
14838
16223
|
} else {
|
|
14839
16224
|
const [head, tail] = pair();
|
|
14840
16225
|
cell = half === 0 ? head : tail;
|
|
@@ -14855,11 +16240,14 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14855
16240
|
motifContour.push(baseDegree + archetype[idx]);
|
|
14856
16241
|
}
|
|
14857
16242
|
const plannedDegrees = new Array(totalBars).fill(null);
|
|
16243
|
+
const motifShiftMemo = /* @__PURE__ */ new Map();
|
|
14858
16244
|
const melody = [];
|
|
14859
16245
|
const submelody = [];
|
|
14860
16246
|
const bass = [];
|
|
14861
16247
|
const harmony = [];
|
|
16248
|
+
const harmony2 = [];
|
|
14862
16249
|
const pad = [];
|
|
16250
|
+
const solo = [];
|
|
14863
16251
|
const melodyDurations = [];
|
|
14864
16252
|
const barTension = new Array(totalBars).fill(0);
|
|
14865
16253
|
let restSteps = 0;
|
|
@@ -14870,9 +16258,9 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14870
16258
|
let chromaticNotes = 0;
|
|
14871
16259
|
let sungBars = 0;
|
|
14872
16260
|
let prevSemi = pick([60, 64, 65, 67, 69, 72, 74, 76], rnd);
|
|
14873
|
-
const pickFigure = (gapSteps,
|
|
16261
|
+
const pickFigure = (gapSteps, scale2) => {
|
|
14874
16262
|
const fits = ANSWER_FIGURES.filter(
|
|
14875
|
-
(f) => f.reduce((sum, v) => sum +
|
|
16263
|
+
(f) => f.reduce((sum, v) => sum + scale2(Math.abs(v)), 0) <= gapSteps
|
|
14876
16264
|
);
|
|
14877
16265
|
return fits.length === 0 ? null : pick(fits, rnd);
|
|
14878
16266
|
};
|
|
@@ -14930,8 +16318,9 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14930
16318
|
slots,
|
|
14931
16319
|
tones,
|
|
14932
16320
|
style,
|
|
16321
|
+
scale,
|
|
14933
16322
|
motifContour,
|
|
14934
|
-
semitoneToDegree(headSemi),
|
|
16323
|
+
semitoneToDegree(scale, headSemi),
|
|
14935
16324
|
contourOffset,
|
|
14936
16325
|
repeatShift,
|
|
14937
16326
|
headWeight,
|
|
@@ -14947,47 +16336,55 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14947
16336
|
...plannedDegrees[source]
|
|
14948
16337
|
);
|
|
14949
16338
|
const landing = units2[unitOf(bar)].landing;
|
|
14950
|
-
if (landing !== null && barInUnit(bar) === 1)
|
|
16339
|
+
if (landing !== null && barInUnit(bar) === 1)
|
|
16340
|
+
landOn(scale, degrees, landing);
|
|
14951
16341
|
plannedDegrees[bar] = [...degrees];
|
|
14952
16342
|
const isMotifBar = source !== null || role === "motif" || role === "sequence" || role === "climax" || role === "answer";
|
|
14953
|
-
|
|
14954
|
-
|
|
16343
|
+
let fitted = degrees;
|
|
16344
|
+
if (isMotifBar) {
|
|
16345
|
+
const shiftKey = degrees.join(",");
|
|
16346
|
+
const r = fitMotif(
|
|
14955
16347
|
degrees,
|
|
14956
16348
|
slots,
|
|
14957
16349
|
tones,
|
|
14958
16350
|
prevSemi,
|
|
14959
16351
|
quarterSteps,
|
|
14960
|
-
|
|
14961
|
-
|
|
14962
|
-
|
|
14963
|
-
|
|
14964
|
-
|
|
14965
|
-
|
|
14966
|
-
|
|
14967
|
-
|
|
14968
|
-
|
|
14969
|
-
|
|
14970
|
-
|
|
14971
|
-
|
|
14972
|
-
|
|
14973
|
-
|
|
14974
|
-
|
|
14975
|
-
|
|
14976
|
-
|
|
14977
|
-
|
|
14978
|
-
|
|
14979
|
-
|
|
14980
|
-
|
|
14981
|
-
|
|
14982
|
-
|
|
14983
|
-
|
|
16352
|
+
scale,
|
|
16353
|
+
style.pentatonicMotif,
|
|
16354
|
+
motifShiftMemo.get(shiftKey) ?? null
|
|
16355
|
+
);
|
|
16356
|
+
fitted = r.degrees;
|
|
16357
|
+
motifShiftMemo.set(shiftKey, r.shift);
|
|
16358
|
+
}
|
|
16359
|
+
const pitches = shapeBar(fitted, slots, tones, prevSemi, {
|
|
16360
|
+
scale,
|
|
16361
|
+
allowLeap: role === "climax",
|
|
16362
|
+
allowArpeggio: role === "climax" || role === "run" && style.runShape === "broken" || role === "cadence" && style.cadenceShape !== "descend",
|
|
16363
|
+
quarterSteps,
|
|
16364
|
+
// モチーフの小節はオクターブ移動を入れない。モチーフは輪郭が命なので、
|
|
16365
|
+
// 後から音を1つ跳ばすと「同じフレーズが返ってきた」と分からなくなる。
|
|
16366
|
+
// モチーフ側は {@link MOTIF_ARCHETYPES} が自前でオクターブを持つ。
|
|
16367
|
+
// モチーフ・セクエンツ・サビの小節はオクターブ移動を入れない
|
|
16368
|
+
// (輪郭が命なので、後から音を1つ跳ばすと同じフレーズと分からなくなる)。
|
|
16369
|
+
// 答えの小節は輪郭を借りているだけなので許す。
|
|
16370
|
+
octaveAffinity: role === "motif" || role === "sequence" || role === "climax" ? 0 : style.octaveAffinity,
|
|
16371
|
+
chromaticAffinity: style.chromaticAffinity,
|
|
16372
|
+
rnd,
|
|
16373
|
+
preserveContour: isMotifBar
|
|
16374
|
+
});
|
|
16375
|
+
if (landing !== null && barInUnit(bar) === 1)
|
|
16376
|
+
landPitch(scale, pitches, landing);
|
|
16377
|
+
const fifths = pitches.map((semi) => scaleFifth(scale, semi));
|
|
16378
|
+
applyChromatic(scale, pitches, fifths, slots, tones, {
|
|
14984
16379
|
affinity: style.chromaticAffinity,
|
|
14985
16380
|
quarterSteps,
|
|
14986
16381
|
shortSteps: scaleStep(EIGHTH),
|
|
14987
16382
|
keepLast: landing !== null && barInUnit(bar) === 1,
|
|
14988
16383
|
rnd
|
|
14989
16384
|
});
|
|
14990
|
-
const
|
|
16385
|
+
const unitSource = units2[unitOf(bar)].source;
|
|
16386
|
+
const isSolo = unitSource === "solo";
|
|
16387
|
+
const silent = unitSource === "silent" || isSolo;
|
|
14991
16388
|
const barHead = pitches[0];
|
|
14992
16389
|
let tensionSum = 0;
|
|
14993
16390
|
let tensionSteps = 0;
|
|
@@ -14995,7 +16392,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14995
16392
|
const semi = pitches[i2];
|
|
14996
16393
|
tensionSum += (3 - toneWeight(semi, tones)) / 3 * slots[i2].value;
|
|
14997
16394
|
tensionSteps += slots[i2].value;
|
|
14998
|
-
if (role !== "climax") {
|
|
16395
|
+
if (!silent && role !== "climax") {
|
|
14999
16396
|
const gap = Math.abs(semi - prevSemi);
|
|
15000
16397
|
maxLeap = Math.max(maxLeap, gap);
|
|
15001
16398
|
intervals++;
|
|
@@ -15004,10 +16401,25 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15004
16401
|
}
|
|
15005
16402
|
const slot = slots[i2];
|
|
15006
16403
|
if (silent) {
|
|
16404
|
+
if (isSolo) {
|
|
16405
|
+
const ks = barKeyShift[bar];
|
|
16406
|
+
const fifthShiftSolo = ks === 0 ? 0 : SEMITONE_TO_FIFTH_SHIFT[(ks % 12 + 12) % 12];
|
|
16407
|
+
solo.push({
|
|
16408
|
+
startStep: barStart + slot.at,
|
|
16409
|
+
pitchUnits: spelledToUnits(
|
|
16410
|
+
semi + ks,
|
|
16411
|
+
fifths[i2] + fifthShiftSolo,
|
|
16412
|
+
edo
|
|
16413
|
+
),
|
|
16414
|
+
durationSteps: slot.value,
|
|
16415
|
+
// ソロは前に出る声部なので、歌メロより気持ち強く弾く。
|
|
16416
|
+
velocity: slot.at === 0 ? 116 : slot.value <= scaleStep(SIXTEENTH) ? 96 : 106
|
|
16417
|
+
});
|
|
16418
|
+
}
|
|
15007
16419
|
prevSemi = semi;
|
|
15008
16420
|
continue;
|
|
15009
16421
|
}
|
|
15010
|
-
if (!
|
|
16422
|
+
if (!scalePcs(scale).has(pitchClass(semi))) chromaticNotes++;
|
|
15011
16423
|
const k = barKeyShift[bar];
|
|
15012
16424
|
const fifthShift = k === 0 ? 0 : SEMITONE_TO_FIFTH_SHIFT[(k % 12 + 12) % 12];
|
|
15013
16425
|
melody.push({
|
|
@@ -15061,7 +16473,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15061
16473
|
subSemi = pushSub(
|
|
15062
16474
|
cursor,
|
|
15063
16475
|
step,
|
|
15064
|
-
i2 === 0 ? subSemi : walk(subSemi, subDir)
|
|
16476
|
+
i2 === 0 ? subSemi : walk(scale, subSemi, subDir)
|
|
15065
16477
|
);
|
|
15066
16478
|
placed++;
|
|
15067
16479
|
}
|
|
@@ -15085,7 +16497,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15085
16497
|
subSemi = pushSub(
|
|
15086
16498
|
cursor,
|
|
15087
16499
|
step,
|
|
15088
|
-
index === 0 ? subSemi : walk(subSemi, subDir * (index % 2 === 0 ? 1 : -1))
|
|
16500
|
+
index === 0 ? subSemi : walk(scale, subSemi, subDir * (index % 2 === 0 ? 1 : -1))
|
|
15089
16501
|
);
|
|
15090
16502
|
index++;
|
|
15091
16503
|
}
|
|
@@ -15095,30 +16507,62 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15095
16507
|
pushSub(0, stepsPerBar, subSemi);
|
|
15096
16508
|
} else if (subStyle === "long-short") {
|
|
15097
16509
|
subSemi = pushSub(0, scaleStep(DOT_HALF), subSemi);
|
|
15098
|
-
pushSub(
|
|
16510
|
+
pushSub(
|
|
16511
|
+
scaleStep(DOT_HALF),
|
|
16512
|
+
scaleStep(QUARTER),
|
|
16513
|
+
walk(scale, subSemi, subDir)
|
|
16514
|
+
);
|
|
15099
16515
|
} else if (role === "cadence") {
|
|
15100
16516
|
pushSub(0, stepsPerBar, subSemi);
|
|
15101
16517
|
} else {
|
|
15102
16518
|
pushSub(scaleStep(QUARTER), scaleStep(DOT_HALF), subSemi);
|
|
15103
16519
|
}
|
|
15104
16520
|
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
|
-
|
|
16521
|
+
if (!silent && harmonyKinds.includes(barSec.kind)) {
|
|
16522
|
+
const k = barKeyShift[bar];
|
|
16523
|
+
const fifthShift = k === 0 ? 0 : SEMITONE_TO_FIFTH_SHIFT[(k % 12 + 12) % 12];
|
|
16524
|
+
const writeHarmony = (out, prev, offset, against) => {
|
|
16525
|
+
let last = prev;
|
|
16526
|
+
const written = [];
|
|
16527
|
+
for (let i2 = 0; i2 < slots.length; i2++) {
|
|
16528
|
+
const hTone = harmonyPitch(
|
|
16529
|
+
scale,
|
|
16530
|
+
pitches[i2],
|
|
16531
|
+
tones,
|
|
16532
|
+
last,
|
|
16533
|
+
offset,
|
|
16534
|
+
harmonyParallel,
|
|
16535
|
+
against?.[i2] ?? null
|
|
16536
|
+
);
|
|
16537
|
+
let hClamped = clampSemi(
|
|
16538
|
+
hTone.semi,
|
|
16539
|
+
MELODY_LOW - 12,
|
|
16540
|
+
MELODY_HIGH + 7
|
|
16541
|
+
);
|
|
16542
|
+
while (hClamped - pitches[i2] > 12) hClamped -= 12;
|
|
16543
|
+
while (hClamped - pitches[i2] < -12) hClamped += 12;
|
|
16544
|
+
last = hClamped;
|
|
16545
|
+
written.push(hClamped);
|
|
16546
|
+
const keep = slots[i2].isStrong || slots[i2].value >= quarterSteps || rnd() < harmonyCoverage;
|
|
16547
|
+
if (!keep) continue;
|
|
16548
|
+
out.push({
|
|
16549
|
+
startStep: barStart + slots[i2].at,
|
|
16550
|
+
pitchUnits: spelledToUnits(
|
|
16551
|
+
hClamped + k,
|
|
16552
|
+
hTone.fifth + fifthShift,
|
|
16553
|
+
edo
|
|
16554
|
+
),
|
|
16555
|
+
durationSteps: slots[i2].value,
|
|
16556
|
+
velocity: slots[i2].at === 0 ? 82 : 76
|
|
16557
|
+
});
|
|
16558
|
+
}
|
|
16559
|
+
return written;
|
|
16560
|
+
};
|
|
16561
|
+
const h1 = writeHarmony(harmony, prevHarmony, harmonyOffset, null);
|
|
16562
|
+
prevHarmony = h1[h1.length - 1] ?? prevHarmony;
|
|
16563
|
+
if (useHarmony2) {
|
|
16564
|
+
const h2 = writeHarmony(harmony2, prevHarmony2, harmony2Offset, h1);
|
|
16565
|
+
prevHarmony2 = h2[h2.length - 1] ?? prevHarmony2;
|
|
15122
16566
|
}
|
|
15123
16567
|
}
|
|
15124
16568
|
if (barSec.kind === "prechorus" || barSec.kind === "chorus" || barSec.kind === "bridge" || barSec.kind === "drop_chorus") {
|
|
@@ -15153,6 +16597,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15153
16597
|
const nextTones = chordTones(progression[(bar + 1) % totalBars]);
|
|
15154
16598
|
const A = clampSemi(
|
|
15155
16599
|
walk(
|
|
16600
|
+
scale,
|
|
15156
16601
|
nextTones[0] ? clampSemi(nextTones[0].semi, BASS_LOW, BASS_HIGH) : R,
|
|
15157
16602
|
-1
|
|
15158
16603
|
),
|
|
@@ -15209,7 +16654,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15209
16654
|
let bassCursor = 0;
|
|
15210
16655
|
for (const [semi, value] of bassCell) {
|
|
15211
16656
|
const len = scaleStep(value);
|
|
15212
|
-
const fifth = semi === R || semi === O ? rootTone.fifth : semi === F ? fifthTone?.fifth ?? rootTone.fifth : semi === T ? thirdTone?.fifth ?? rootTone.fifth :
|
|
16657
|
+
const fifth = semi === R || semi === O ? rootTone.fifth : semi === F ? fifthTone?.fifth ?? rootTone.fifth : semi === T ? thirdTone?.fifth ?? rootTone.fifth : scaleFifth(scale, semi);
|
|
15213
16658
|
const k = barKeyShift[bar];
|
|
15214
16659
|
const fifthShift = k === 0 ? 0 : SEMITONE_TO_FIFTH_SHIFT[(k % 12 + 12) % 12];
|
|
15215
16660
|
barBass.push({
|
|
@@ -15250,6 +16695,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15250
16695
|
for (const n of barBass) bass.push(n);
|
|
15251
16696
|
}
|
|
15252
16697
|
const eighthSteps = scaleStep(EIGHTH);
|
|
16698
|
+
const tieMemo = /* @__PURE__ */ new Map();
|
|
15253
16699
|
for (let i2 = 0; i2 < melody.length - 1; i2++) {
|
|
15254
16700
|
const cur = melody[i2];
|
|
15255
16701
|
const nxt = melody[i2 + 1];
|
|
@@ -15263,40 +16709,71 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15263
16709
|
const curSec = sectionAt(sectionPlan, barIdx - 1);
|
|
15264
16710
|
const nextSec = sectionAt(sectionPlan, barIdx);
|
|
15265
16711
|
if (!nextSec.spec.melody || curSec !== nextSec) continue;
|
|
16712
|
+
if (breathBars.has(barIdx)) continue;
|
|
15266
16713
|
const curSemi = Math.round(cur.pitchUnits / UNITS_PER_SEMITONE);
|
|
15267
16714
|
const nxtSemi = Math.round(nxt.pitchUnits / UNITS_PER_SEMITONE);
|
|
15268
16715
|
if (Math.abs(nxtSemi - curSemi) > 3) continue;
|
|
16716
|
+
const after = melody[i2 + 2];
|
|
16717
|
+
if (after && Math.floor(after.startStep / stepsPerBar) === barIdx) {
|
|
16718
|
+
const afterSemi = Math.round(after.pitchUnits / UNITS_PER_SEMITONE) - (barKeyShift[barIdx] ?? 0);
|
|
16719
|
+
if (!scalePcs(scale).has(pitchClass(afterSemi))) continue;
|
|
16720
|
+
}
|
|
15269
16721
|
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.
|
|
16722
|
+
let tieProb = 0.3;
|
|
16723
|
+
if (nextRole === "motif") tieProb = 0.1;
|
|
16724
|
+
else if (nextRole === "sequence") tieProb = 0.35;
|
|
16725
|
+
else if (nextRole === "climax") tieProb = 0.45;
|
|
15274
16726
|
else if (nextRole === "cadence") tieProb = 0.1;
|
|
15275
|
-
|
|
16727
|
+
const tieKey = `${barRhythms[barIdx].join(",")}|${barInUnit(barIdx)}`;
|
|
16728
|
+
let tie = tieMemo.get(tieKey);
|
|
16729
|
+
if (tie === void 0) {
|
|
16730
|
+
tie = rnd() < tieProb;
|
|
16731
|
+
tieMemo.set(tieKey, tie);
|
|
16732
|
+
}
|
|
16733
|
+
if (tie) {
|
|
15276
16734
|
cur.durationSteps += nxt.durationSteps;
|
|
15277
16735
|
melody.splice(i2 + 1, 1);
|
|
15278
16736
|
if (i2 < melodyDurations.length - 1) {
|
|
15279
16737
|
melodyDurations[i2] += melodyDurations[i2 + 1];
|
|
15280
16738
|
melodyDurations.splice(i2 + 1, 1);
|
|
15281
16739
|
}
|
|
15282
|
-
const
|
|
15283
|
-
|
|
15284
|
-
|
|
15285
|
-
|
|
15286
|
-
|
|
16740
|
+
for (const voice of [harmony, harmony2]) {
|
|
16741
|
+
const nxtIdx = voice.findIndex((h) => h.startStep === nxt.startStep);
|
|
16742
|
+
if (nxtIdx < 0) continue;
|
|
16743
|
+
const curIdx = voice.findIndex((h) => h.startStep === cur.startStep);
|
|
16744
|
+
if (curIdx >= 0)
|
|
16745
|
+
voice[curIdx].durationSteps += voice[nxtIdx].durationSteps;
|
|
16746
|
+
voice.splice(nxtIdx, 1);
|
|
15287
16747
|
}
|
|
15288
16748
|
i2--;
|
|
15289
16749
|
}
|
|
15290
16750
|
}
|
|
16751
|
+
const splitMemo = /* @__PURE__ */ new Map();
|
|
16752
|
+
let splitLastBar = -1;
|
|
16753
|
+
let splitIdxInBar = 0;
|
|
15291
16754
|
for (let i2 = 0; i2 < melody.length; i2++) {
|
|
15292
16755
|
const barIdx = Math.floor(melody[i2].startStep / stepsPerBar);
|
|
16756
|
+
if (barIdx !== splitLastBar) {
|
|
16757
|
+
splitLastBar = barIdx;
|
|
16758
|
+
splitIdxInBar = 0;
|
|
16759
|
+
} else splitIdxInBar++;
|
|
15293
16760
|
if (barIdx >= totalBars) continue;
|
|
16761
|
+
if (phraseEndBars.has(barIdx)) continue;
|
|
15294
16762
|
const role = barRoles[barIdx];
|
|
15295
|
-
let splitProb = 0.
|
|
16763
|
+
let splitProb = 0.08;
|
|
15296
16764
|
if (role === "motif" || role === "sequence") splitProb = 0;
|
|
15297
|
-
else if (role === "climax") splitProb = 0.
|
|
16765
|
+
else if (role === "climax") splitProb = 0.3;
|
|
15298
16766
|
else if (role === "cadence") splitProb = 0;
|
|
15299
|
-
|
|
16767
|
+
let doSplit = false;
|
|
16768
|
+
if (melody[i2].durationSteps === quarterSteps) {
|
|
16769
|
+
const key = `${barRhythms[barIdx].join(",")}|${barInUnit(barIdx)}|${role}|${splitIdxInBar}`;
|
|
16770
|
+
const memo = splitMemo.get(key);
|
|
16771
|
+
if (memo === void 0) {
|
|
16772
|
+
doSplit = rnd() < splitProb;
|
|
16773
|
+
splitMemo.set(key, doSplit);
|
|
16774
|
+
} else doSplit = memo;
|
|
16775
|
+
}
|
|
16776
|
+
if (doSplit) {
|
|
15300
16777
|
const half = scaleStep(EIGHTH);
|
|
15301
16778
|
const newNote = {
|
|
15302
16779
|
...melody[i2],
|
|
@@ -15310,6 +16787,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15310
16787
|
melodyDurations.splice(i2 + 1, 0, half);
|
|
15311
16788
|
}
|
|
15312
16789
|
i2++;
|
|
16790
|
+
splitIdxInBar++;
|
|
15313
16791
|
}
|
|
15314
16792
|
}
|
|
15315
16793
|
const range = (notes) => {
|
|
@@ -15319,23 +16797,39 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15319
16797
|
};
|
|
15320
16798
|
const shiftUnits = semitonesToUnits(rootShift, edo);
|
|
15321
16799
|
if (shiftUnits !== 0)
|
|
15322
|
-
for (const list of [melody, submelody, bass, harmony, pad])
|
|
16800
|
+
for (const list of [melody, submelody, bass, harmony, harmony2, pad, solo])
|
|
15323
16801
|
for (const n of list) n.pitchUnits = n.pitchUnits + shiftUnits;
|
|
16802
|
+
const octave = useOctaveLayer ? melody.filter(
|
|
16803
|
+
(n) => n.durationSteps >= quarterSteps || rnd() < octaveCoverage
|
|
16804
|
+
).map((n) => ({ ...n, velocity: Math.max(40, n.velocity - 26) })) : [];
|
|
15324
16805
|
return {
|
|
15325
16806
|
chordProgression,
|
|
15326
16807
|
chordPattern,
|
|
15327
16808
|
rootShift,
|
|
15328
16809
|
keyName: resolvedKey.keyName,
|
|
15329
16810
|
keyLabel: resolvedKey.keyLabel,
|
|
16811
|
+
scaleId: scale.id,
|
|
16812
|
+
scaleLabel: scale.label,
|
|
15330
16813
|
moodLabel: resolvedKey.moodLabel,
|
|
15331
16814
|
bpm,
|
|
15332
16815
|
sections: sectionPlan,
|
|
15333
16816
|
bars: totalBars,
|
|
16817
|
+
vocal: {
|
|
16818
|
+
duetSpans,
|
|
16819
|
+
duetStyle,
|
|
16820
|
+
harmonyKinds,
|
|
16821
|
+
harmony2: useHarmony2,
|
|
16822
|
+
octaveLayer: useOctaveLayer
|
|
16823
|
+
},
|
|
16824
|
+
tonal: { relativeKinds: [...relativeKinds], relativeShift, floating },
|
|
15334
16825
|
melody,
|
|
15335
16826
|
submelody,
|
|
15336
16827
|
bass,
|
|
15337
16828
|
harmony,
|
|
16829
|
+
harmony2,
|
|
16830
|
+
octave,
|
|
15338
16831
|
pad,
|
|
16832
|
+
solo,
|
|
15339
16833
|
melodyDurations,
|
|
15340
16834
|
restSteps,
|
|
15341
16835
|
totalSteps: Math.max(1, sungBars) * stepsPerBar,
|
|
@@ -15406,6 +16900,8 @@ var evaluate = (d, recent) => {
|
|
|
15406
16900
|
melodyRange: atc("melodyRange", d.melodyRange),
|
|
15407
16901
|
notesPerBar: atc("notesPerBar", density.notesPerBar),
|
|
15408
16902
|
shortNoteRatio: atc("shortNoteRatio", density.shortNoteRatio),
|
|
16903
|
+
barDensityCv: atc("barDensityCv", density.barDensityCv),
|
|
16904
|
+
densityCliff: atc("densityCliff", density.densityCliff),
|
|
15409
16905
|
stepRatio: atc("stepRatio", d.stepRatio),
|
|
15410
16906
|
chromaticRatio: atc("chromaticRatio", d.chromaticRatio),
|
|
15411
16907
|
sim1: atc("sim1", structure.sim1),
|
|
@@ -15413,12 +16909,20 @@ var evaluate = (d, recent) => {
|
|
|
15413
16909
|
sim4: atc("sim4", structure.sim4),
|
|
15414
16910
|
sim8: atc("sim8", structure.sim8),
|
|
15415
16911
|
phraseBreath: atc("phraseBreath", structure.phraseBreath),
|
|
16912
|
+
turnRatio: atc("turnRatio", structure.turnRatio),
|
|
15416
16913
|
climaxPosition: atc("climaxPosition", structure.climaxPosition),
|
|
15417
16914
|
climaxPeaks: at(peakBand, structure.climaxPeaks),
|
|
15418
16915
|
complementarity: at(HAND_BANDS.complementarity, structure.complementarity),
|
|
15419
16916
|
subDensity: at(HAND_BANDS.subDensity, d.submelody.length / d.bars),
|
|
16917
|
+
// サブメロにも同じ崖の物差しを当てる。帯はメロディから採ったものを流用する。
|
|
16918
|
+
subDensityCliff: atc(
|
|
16919
|
+
"densityCliff",
|
|
16920
|
+
densityFeatures(fromMelody(toMetricNotes(d.submelody)), opts).densityCliff
|
|
16921
|
+
),
|
|
15420
16922
|
tensionRise: tension.rise,
|
|
15421
|
-
|
|
16923
|
+
// **浮遊感の曲に「終止で解決しろ」は要求しない。** 解決しないことが狙いなので、
|
|
16924
|
+
// この項目で減点すると候補40本の選抜で必ず負けて、狙って引いた曲が出てこない。
|
|
16925
|
+
tensionResolve: d.tonal.floating ? 1 : tension.resolve,
|
|
15422
16926
|
novelty
|
|
15423
16927
|
};
|
|
15424
16928
|
let weighted = 0;
|
|
@@ -15455,12 +16959,17 @@ var composeSong = (options) => {
|
|
|
15455
16959
|
const recent = options.recent ?? [];
|
|
15456
16960
|
const count = Math.max(1, options.drawCount ?? DRAW_COUNT);
|
|
15457
16961
|
const resolvedKey = resolveComposeKey(options.baseKey, rnd);
|
|
16962
|
+
const scale = resolveComposeScale(
|
|
16963
|
+
options.scale,
|
|
16964
|
+
resolvedKey.mode === "minor",
|
|
16965
|
+
rnd
|
|
16966
|
+
);
|
|
15458
16967
|
let best = null;
|
|
15459
16968
|
let bestScore = Number.NEGATIVE_INFINITY;
|
|
15460
16969
|
let bestIsValid = false;
|
|
15461
16970
|
let rejected = 0;
|
|
15462
16971
|
for (let attempt = 1; attempt <= count; attempt++) {
|
|
15463
|
-
const d = draw(options, resolvedKey, rnd);
|
|
16972
|
+
const d = draw(options, resolvedKey, scale, rnd);
|
|
15464
16973
|
const { stats, ok } = evaluate(d, recent);
|
|
15465
16974
|
if (!ok) rejected++;
|
|
15466
16975
|
const better = ok === bestIsValid ? stats.score > bestScore : ok;
|
|
@@ -15468,24 +16977,32 @@ var composeSong = (options) => {
|
|
|
15468
16977
|
bestScore = stats.score;
|
|
15469
16978
|
bestIsValid = ok;
|
|
15470
16979
|
best = {
|
|
15471
|
-
//
|
|
15472
|
-
//
|
|
16980
|
+
// ドラム・楽器・編曲プランは勝った候補にだけ後から付ける(メロディに
|
|
16981
|
+
// 依存しないので候補ごとに引いても採点は動かず、40本ぶん無駄になる)。
|
|
15473
16982
|
drum: "",
|
|
15474
16983
|
instrument: "",
|
|
16984
|
+
arrange: EMPTY_ARRANGE,
|
|
15475
16985
|
chordProgression: d.chordProgression,
|
|
15476
16986
|
chordPattern: d.chordPattern,
|
|
15477
16987
|
rootShift: d.rootShift,
|
|
15478
16988
|
keyName: d.keyName,
|
|
15479
16989
|
keyLabel: d.keyLabel,
|
|
16990
|
+
scaleId: scale.id,
|
|
16991
|
+
scaleLabel: scale.label,
|
|
15480
16992
|
moodLabel: d.moodLabel,
|
|
15481
16993
|
bpm: d.bpm,
|
|
15482
16994
|
sections: d.sections,
|
|
15483
16995
|
bars: d.bars,
|
|
16996
|
+
vocal: d.vocal,
|
|
16997
|
+
tonal: d.tonal,
|
|
15484
16998
|
melody: d.melody,
|
|
15485
16999
|
submelody: d.submelody,
|
|
15486
17000
|
bass: d.bass,
|
|
15487
17001
|
harmony: d.harmony,
|
|
17002
|
+
harmony2: d.harmony2,
|
|
17003
|
+
octave: d.octave,
|
|
15488
17004
|
pad: d.pad,
|
|
17005
|
+
solo: d.solo,
|
|
15489
17006
|
stats: { ...stats, attempts: attempt, rejected }
|
|
15490
17007
|
};
|
|
15491
17008
|
}
|
|
@@ -15494,14 +17011,92 @@ var composeSong = (options) => {
|
|
|
15494
17011
|
result.stats.rejected = rejected;
|
|
15495
17012
|
result.drum = pickBuiltinDrum(result, rnd);
|
|
15496
17013
|
result.instrument = pickBuiltinInstrument(result, rnd);
|
|
17014
|
+
result.arrange = buildArrangePlan(result, rnd);
|
|
15497
17015
|
return result;
|
|
15498
17016
|
};
|
|
15499
17017
|
var pickBuiltinDrum = (song, rnd) => {
|
|
15500
17018
|
const eighth = BASE_STEPS_PER_BAR / 8;
|
|
15501
17019
|
const short = song.melody.filter((n) => n.durationSteps <= eighth).length / Math.max(1, song.melody.length);
|
|
15502
|
-
const
|
|
17020
|
+
const dotted = song.melody.filter(
|
|
17021
|
+
(n) => n.durationSteps === Math.round(BASE_STEPS_PER_BAR * 3 / 16)
|
|
17022
|
+
).length / Math.max(1, song.melody.length);
|
|
17023
|
+
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
17024
|
return pick(pool, rnd);
|
|
15504
17025
|
};
|
|
17026
|
+
var EMPTY_ARRANGE = {
|
|
17027
|
+
backing: [],
|
|
17028
|
+
sparkle: null,
|
|
17029
|
+
padSections: [],
|
|
17030
|
+
lead: null,
|
|
17031
|
+
bassLayer: null
|
|
17032
|
+
};
|
|
17033
|
+
var LOUD_KINDS = ["prechorus", "chorus", "bridge"];
|
|
17034
|
+
var QUIET_KINDS = [
|
|
17035
|
+
"intro",
|
|
17036
|
+
"verse",
|
|
17037
|
+
"interlude",
|
|
17038
|
+
"drop_chorus",
|
|
17039
|
+
"outro"
|
|
17040
|
+
];
|
|
17041
|
+
var CHORUS_KINDS = ["chorus", "drop_chorus"];
|
|
17042
|
+
var buildArrangePlan = (song, rnd) => {
|
|
17043
|
+
const present = new Set(song.sections.map((s) => s.kind));
|
|
17044
|
+
const narrow = (kinds) => {
|
|
17045
|
+
const hit = kinds.filter((k) => present.has(k));
|
|
17046
|
+
return hit.length === 0 ? null : hit;
|
|
17047
|
+
};
|
|
17048
|
+
const base = {
|
|
17049
|
+
pattern: song.chordPattern,
|
|
17050
|
+
sections: null,
|
|
17051
|
+
octave: 0
|
|
17052
|
+
};
|
|
17053
|
+
const others = chordPatternPool(song.bpm).filter((p) => p !== base.pattern);
|
|
17054
|
+
const backing = [base];
|
|
17055
|
+
const addKinds = pick(
|
|
17056
|
+
[LOUD_KINDS, CHORUS_KINDS, LOUD_KINDS, QUIET_KINDS],
|
|
17057
|
+
rnd
|
|
17058
|
+
);
|
|
17059
|
+
const second = pick(others, rnd);
|
|
17060
|
+
backing.push({
|
|
17061
|
+
pattern: second,
|
|
17062
|
+
sections: narrow(addKinds),
|
|
17063
|
+
octave: 0
|
|
17064
|
+
});
|
|
17065
|
+
if (rnd() < 0.55) {
|
|
17066
|
+
const rest = others.filter((p) => p !== second);
|
|
17067
|
+
backing.push({
|
|
17068
|
+
pattern: pick(rest.length > 0 ? rest : others, rnd),
|
|
17069
|
+
// 2本目と逆側へ置く(両方サビに寄せると、サビだけ団子になる)。
|
|
17070
|
+
sections: narrow(addKinds === QUIET_KINDS ? LOUD_KINDS : QUIET_KINDS),
|
|
17071
|
+
octave: 0
|
|
17072
|
+
});
|
|
17073
|
+
}
|
|
17074
|
+
const sparklePool = chordPatternPool(song.bpm).filter(
|
|
17075
|
+
(p) => p !== "block" && !backing.some((b) => b.pattern === p)
|
|
17076
|
+
);
|
|
17077
|
+
const sparkle = sparklePool.length > 0 && rnd() < 0.7 ? {
|
|
17078
|
+
pattern: pick(sparklePool, rnd),
|
|
17079
|
+
sections: narrow(pick([LOUD_KINDS, CHORUS_KINDS], rnd)) ?? CHORUS_KINDS,
|
|
17080
|
+
octave: 1
|
|
17081
|
+
} : null;
|
|
17082
|
+
const padSections = narrow(
|
|
17083
|
+
pick(
|
|
17084
|
+
[
|
|
17085
|
+
["prechorus", "chorus", "bridge", "drop_chorus"],
|
|
17086
|
+
["chorus", "drop_chorus"],
|
|
17087
|
+
["prechorus", "chorus", "bridge", "drop_chorus"],
|
|
17088
|
+
["bridge", "chorus"]
|
|
17089
|
+
],
|
|
17090
|
+
rnd
|
|
17091
|
+
)
|
|
17092
|
+
) ?? [];
|
|
17093
|
+
const lead = rnd() < 0.75 ? {
|
|
17094
|
+
sections: narrow(pick([CHORUS_KINDS, LOUD_KINDS], rnd)) ?? CHORUS_KINDS,
|
|
17095
|
+
octave: rnd() < 0.5 ? 0 : 1
|
|
17096
|
+
} : null;
|
|
17097
|
+
const bassLayer = rnd() < 0.25 ? { sections: narrow(CHORUS_KINDS) ?? CHORUS_KINDS, octave: 1 } : null;
|
|
17098
|
+
return { backing, sparkle, padSections, lead, bassLayer };
|
|
17099
|
+
};
|
|
15505
17100
|
var pickBuiltinInstrument = (song, rnd) => {
|
|
15506
17101
|
const eighth = BASE_STEPS_PER_BAR / 8;
|
|
15507
17102
|
const short = song.melody.filter((n) => n.durationSteps <= eighth).length / Math.max(1, song.melody.length);
|
|
@@ -15513,7 +17108,7 @@ var pickBuiltinInstrument = (song, rnd) => {
|
|
|
15513
17108
|
pool = song.bpm >= 150 ? ["cyber_punk", "synth_pop", "retro_game"] : ["synth_pop", "retro_game", "rock", "piano"];
|
|
15514
17109
|
} else if (song.drum === "bossa") {
|
|
15515
17110
|
pool = ["jazz_night", "acoustic", "piano"];
|
|
15516
|
-
} else if (song.bpm <=
|
|
17111
|
+
} else if (song.bpm <= 115) {
|
|
15517
17112
|
pool = ["ambient_cloud", "acoustic", "orchestra", "piano", "fantasy_rpg"];
|
|
15518
17113
|
} else if (song.bpm >= 145) {
|
|
15519
17114
|
pool = ["rock", "synth_pop", "cyber_punk", "retro_game", "piano"];
|
|
@@ -15569,6 +17164,23 @@ var LYRIC_WORDS = [
|
|
|
15569
17164
|
"\u305B\u304B\u3044",
|
|
15570
17165
|
"\u304D\u305B\u3064"
|
|
15571
17166
|
];
|
|
17167
|
+
var alignLyrics = (source, lyrics, target, options) => {
|
|
17168
|
+
const sorted = [...source].sort((a, b) => a.startStep - b.startStep);
|
|
17169
|
+
const kana = [...lyrics].filter((c) => c !== "\u3001");
|
|
17170
|
+
const at = /* @__PURE__ */ new Map();
|
|
17171
|
+
for (let i2 = 0; i2 < sorted.length && i2 < kana.length; i2++)
|
|
17172
|
+
at.set(sorted[i2].startStep, kana[i2]);
|
|
17173
|
+
const { stepsPerBar } = options;
|
|
17174
|
+
const tgt = [...target].sort((a, b) => a.startStep - b.startStep);
|
|
17175
|
+
const out = [];
|
|
17176
|
+
for (let i2 = 0; i2 < tgt.length; i2++) {
|
|
17177
|
+
out.push(at.get(tgt[i2].startStep) ?? "\u30FC");
|
|
17178
|
+
const next = tgt[i2 + 1];
|
|
17179
|
+
if (next && Math.floor(tgt[i2].startStep / (stepsPerBar * 4)) !== Math.floor(next.startStep / (stepsPerBar * 4)))
|
|
17180
|
+
out.push("\u3001");
|
|
17181
|
+
}
|
|
17182
|
+
return out.join("");
|
|
17183
|
+
};
|
|
15572
17184
|
var composeLyrics = (melody, options) => {
|
|
15573
17185
|
const rnd = options.random ?? Math.random;
|
|
15574
17186
|
const { stepsPerBar } = options;
|
|
@@ -16015,6 +17627,34 @@ var buildUI = (target, options) => {
|
|
|
16015
17627
|
<span class="dtm-grow"></span>
|
|
16016
17628
|
<span class="dtm-hint" data-dtm="compose-key-hint"></span>
|
|
16017
17629
|
</div>
|
|
17630
|
+
<div class="dtm-row" data-dtm="compose-scale-row">
|
|
17631
|
+
<span class="dtm-label">\u97F3\u968E</span>
|
|
17632
|
+
<select class="dtm-select" data-dtm="compose-scale" title="\u65CB\u5F8B\u304C\u4F7F\u3046\u97F3\u968E\u3092\u9078\u3073\u307E\u3059\u3002\u30D9\u30FC\u30B9\u8ABF\uFF08\u4E3B\u97F3\u306E\u9AD8\u3055\uFF09\u3068\u306F\u72EC\u7ACB\u3057\u305F\u8A2D\u5B9A\u3067\u3059">
|
|
17633
|
+
<option value="auto" title="\u30D9\u30FC\u30B9\u8ABF\u306E\u9577\u77ED\u306B\u5408\u308F\u305B\u3066\u3001\u967D\u97F3\u968E\uFF08\u9577\u8ABF\uFF09\u304B\u6C11\u8B21\u97F3\u968E\uFF08\u77ED\u8ABF\uFF09\u3092\u4F7F\u3044\u307E\u3059">\u304A\u307E\u304B\u305B\uFF08\u5F93\u6765\u3069\u304A\u308A\uFF09</option>
|
|
17634
|
+
<option value="any" title="9\u3064\u306E\u97F3\u968E\u304B\u3089\u30E9\u30F3\u30C0\u30E0\u306B\u62BD\u9078\u3057\u307E\u3059">\u5E0C\u671B\u306A\u3057\uFF08\u5168\u97F3\u968E\u304B\u3089\u62BD\u9078\uFF09</option>
|
|
17635
|
+
<optgroup label="\u30DA\u30F3\u30BF\u30C8\u30CB\u30C3\u30AF\uFF085\u97F3\u97F3\u968E\uFF09">
|
|
17636
|
+
<option value="yo" title="J-POP\u306E\u6A19\u6E96\u3002\u660E\u308B\u304F\u7D20\u76F4\u3067\u6B4C\u3044\u3084\u3059\u3044\u3002\u5F93\u6765\u306E\u9577\u8ABF\u3068\u540C\u3058">\u967D\u97F3\u968E\uFF08\u9577\u8ABF\u30DA\u30F3\u30BF\uFF09</option>
|
|
17637
|
+
<option value="minyo" title="\u308F\u3089\u3079\u6B4C\u30FB\u6C11\u8B21\u306E\u97F3\u968E\u3002\u7FF3\u308A\u304C\u3042\u308B\u304C\u6697\u3059\u304E\u306A\u3044\u3002\u5F93\u6765\u306E\u77ED\u8ABF\u3068\u540C\u3058">\u6C11\u8B21\u97F3\u968E\uFF08\u77ED\u8ABF\u30DA\u30F3\u30BF\uFF09</option>
|
|
17638
|
+
<option value="ryukyu" title="\u6C96\u7E04\u97F3\u968E\u3002\u30EC\u3068\u30E9\u3092\u629C\u304D\u3001\u30D5\u30A1\u3068\u30B7\u3092\u67F1\u306B\u3059\u308B\u3002\u660E\u308B\u304F\u8DF3\u306D\u308B">\u7409\u7403\u97F3\u968E\uFF08\u6C96\u7E04\uFF09</option>
|
|
17639
|
+
<option value="miyakobushi" title="\u300E\u3055\u304F\u3089\u3055\u304F\u3089\u300F\u306E\u97F3\u968E\u3002\u4E3B\u97F3\u306E\u3059\u3050\u4E0A\u304C\u534A\u97F3\u3067\u3001\u7FF3\u308A\u304C\u6FC3\u3044">\u90FD\u7BC0\u97F3\u968E\uFF08\u9670\u97F3\u968E\uFF09</option>
|
|
17640
|
+
<option value="ritsu" title="\u96C5\u697D\u30FB\u58F0\u660E\u306E\u97F3\u968E\u3002\u534A\u97F3\u3092\u542B\u307E\u305A\u3001\u5E73\u3089\u3067\u8358\u91CD\u306B\u6D41\u308C\u308B">\u5F8B\u97F3\u968E\uFF08\u96C5\u697D\uFF09</option>
|
|
17641
|
+
</optgroup>
|
|
17642
|
+
<optgroup label="\u30C1\u30E3\u30FC\u30C1\u30E2\u30FC\u30C9\uFF087\u97F3\u97F3\u968E\uFF09">
|
|
17643
|
+
<option value="dorian" title="\u77ED\u8ABF\u3060\u304C6\u5EA6\u304C\u660E\u308B\u3044\u3002\u30B1\u30EB\u30C8\u30FB\u30ED\u30C3\u30AF\u30FB\u30B7\u30C6\u30A3\u30DD\u30C3\u30D7">\u30C9\u30EA\u30A2\u30F3</option>
|
|
17644
|
+
<option value="phrygian" title="\u4E3B\u97F3\u306E\u4E0A\u304C\u534A\u97F3\u3002\u30B9\u30D1\u30CB\u30C3\u30B7\u30E5\uFF0F\u30E1\u30BF\u30EB\u306E\u7DCA\u8FEB\u3057\u305F\u97FF\u304D">\u30D5\u30EA\u30B8\u30A2\u30F3</option>
|
|
17645
|
+
<option value="lydian" title="4\u5EA6\u304C\u9AD8\u304F\u3001\u6D6E\u904A\u3057\u3066\u5E83\u304C\u308B\u3002\u6620\u753B\u97F3\u697D\u30FB\u30B2\u30FC\u30E0\u306E\u7A7A\u306E\u8272">\u30EA\u30C7\u30A3\u30A2\u30F3</option>
|
|
17646
|
+
<option value="mixolydian" title="\u9577\u8ABF\u3060\u304C7\u5EA6\u304C\u4F4E\u3044\u3002\u30D6\u30EB\u30FC\u30B9\u30ED\u30C3\u30AF\u30FB\u6C11\u65CF\u97F3\u697D\u306E\u571F\u304F\u3055\u3055">\u30DF\u30AF\u30BD\u30EA\u30C7\u30A3\u30A2\u30F3</option>
|
|
17647
|
+
</optgroup>
|
|
17648
|
+
<optgroup label="\u7279\u6B8A\u97F3\u968E\uFF08\u97F3\u7A0B\u96C6\u5408\u3054\u3068\u5165\u308C\u66FF\u308F\u308B\uFF09">
|
|
17649
|
+
<option value="harmonic_minor" title="\u5C0E\u97F3\u30BD\u266F\u3092\u6301\u3064\u77ED\u8ABF\u3002\u58972\u5EA6\u304C\u6CE3\u304D\u3092\u4F5C\u308B\u3002\u30AF\u30E9\u30B7\u30C3\u30AF\u30FBV\u7CFB\u30FB\u5287\u4F34">\u548C\u58F0\u7684\u77ED\u97F3\u968E</option>
|
|
17650
|
+
<option value="hijaz" title="\u4E3B\u97F3\u306E\u4E0A\u304C\u534A\u97F3\u3001\u4E3B\u548C\u97F3\u306F\u9577\u4E09\u548C\u97F3\u3002\u4E2D\u6771\u30FB\u30B9\u30D1\u30CB\u30C3\u30B7\u30E5\u30FB\u30E1\u30BF\u30EB">\u30D2\u30B8\u30E3\u30FC\u30BA\uFF08\u30D5\u30EA\u30B8\u30A2\u30F3\u30FB\u30C9\u30DF\u30CA\u30F3\u30C8\uFF09</option>
|
|
17651
|
+
<option value="hungarian" title="\u58972\u5EA6\u304C2\u304B\u6240\u3002\u97F3\u968E\u306E\u4E2D\u3067\u3044\u3061\u3070\u3093\u8DF3\u306D\u305F\u3001\u7570\u56FD\u3081\u3044\u305F\u97FF\u304D">\u30CF\u30F3\u30AC\u30EA\u30A2\u30F3\u30FB\u30DE\u30A4\u30CA\u30FC\uFF08\u30B8\u30D7\u30B7\u30FC\uFF09</option>
|
|
17652
|
+
<option value="blues" title="\u30D6\u30EB\u30FC\u30CE\u30FC\u30C8\u5165\u308A\u306E6\u97F3\u97F3\u968E\u3002\u77ED3\u5EA6\u3067\u6B4C\u3044\u3001\u4F34\u594F\u306F\u95773\u5EA6\u3067\u9CF4\u308B">\u30D6\u30EB\u30FC\u30B9\u97F3\u968E</option>
|
|
17653
|
+
</optgroup>
|
|
17654
|
+
</select>
|
|
17655
|
+
<span class="dtm-grow"></span>
|
|
17656
|
+
<span class="dtm-hint" data-dtm="compose-scale-hint"></span>
|
|
17657
|
+
</div>
|
|
16018
17658
|
</div>
|
|
16019
17659
|
<div class="dtm-row">
|
|
16020
17660
|
<span class="dtm-label">\u5168\u4F53\u30B7\u30D5\u30C8</span>
|
|
@@ -16217,6 +17857,8 @@ var buildUI = (target, options) => {
|
|
|
16217
17857
|
composeSectionsLen: sel("compose-sections-len"),
|
|
16218
17858
|
composeKey: sel("compose-key"),
|
|
16219
17859
|
composeKeyHint: sel("compose-key-hint"),
|
|
17860
|
+
composeScale: sel("compose-scale"),
|
|
17861
|
+
composeScaleHint: sel("compose-scale-hint"),
|
|
16220
17862
|
macroComposeVocal: sel("macro-compose-vocal"),
|
|
16221
17863
|
macroComposeInfo: sel("macro-compose-info"),
|
|
16222
17864
|
macroClear: sel("macro-clear"),
|
|
@@ -16260,7 +17902,12 @@ var INSTRUMENT_PRESETS = {
|
|
|
16260
17902
|
melody: "Acoustic Grand Piano",
|
|
16261
17903
|
submelody: "Vibraphone",
|
|
16262
17904
|
bass: "Electric Bass (finger)",
|
|
16263
|
-
chord: "Pad 2 (warm)"
|
|
17905
|
+
chord: "Pad 2 (warm)",
|
|
17906
|
+
solo: "Electric Guitar (clean)",
|
|
17907
|
+
// グロッケンは実物の音域が G5(79)〜 の高音楽器で、旋律の音域へそのまま置くと
|
|
17908
|
+
// 金切り音になる。**外すのではなくオクターブで下げて使う**
|
|
17909
|
+
// ({@link GM_BRIGHT_CEILING} / {@link fitInstrumentOctave})。
|
|
17910
|
+
chorusLead: "Glockenspiel"
|
|
16264
17911
|
},
|
|
16265
17912
|
acoustic: {
|
|
16266
17913
|
displayName: "\u30A2\u30B3\u30FC\u30B9\u30C6\u30A3\u30C3\u30AF",
|
|
@@ -16268,7 +17915,9 @@ var INSTRUMENT_PRESETS = {
|
|
|
16268
17915
|
melody: "Acoustic Guitar (steel)",
|
|
16269
17916
|
submelody: "Harmonica",
|
|
16270
17917
|
bass: "Acoustic Bass",
|
|
16271
|
-
chord: "Acoustic Guitar (nylon)"
|
|
17918
|
+
chord: "Acoustic Guitar (nylon)",
|
|
17919
|
+
solo: "Overdriven Guitar",
|
|
17920
|
+
chorusLead: "String Ensemble 1"
|
|
16272
17921
|
},
|
|
16273
17922
|
jazz_night: {
|
|
16274
17923
|
displayName: "\u30B8\u30E3\u30BA\u30FB\u30CA\u30A4\u30C8",
|
|
@@ -16276,7 +17925,9 @@ var INSTRUMENT_PRESETS = {
|
|
|
16276
17925
|
melody: "Electric Piano 1",
|
|
16277
17926
|
submelody: "Flute",
|
|
16278
17927
|
bass: "Acoustic Bass",
|
|
16279
|
-
chord: "Electric Guitar (jazz)"
|
|
17928
|
+
chord: "Electric Guitar (jazz)",
|
|
17929
|
+
solo: "Tenor Sax",
|
|
17930
|
+
chorusLead: "Muted Trumpet"
|
|
16280
17931
|
},
|
|
16281
17932
|
// --- MODERN & VIBE: エッジの効いた現代的な響き ---
|
|
16282
17933
|
synth_pop: {
|
|
@@ -16285,7 +17936,9 @@ var INSTRUMENT_PRESETS = {
|
|
|
16285
17936
|
melody: "Lead 2 (sawtooth)",
|
|
16286
17937
|
submelody: "Lead 4 (chiff)",
|
|
16287
17938
|
bass: "Synth Bass 2",
|
|
16288
|
-
chord: "Pad 3 (polysynth)"
|
|
17939
|
+
chord: "Pad 3 (polysynth)",
|
|
17940
|
+
solo: "Distortion Guitar",
|
|
17941
|
+
chorusLead: "Synth Brass 1"
|
|
16289
17942
|
},
|
|
16290
17943
|
cyber_punk: {
|
|
16291
17944
|
displayName: "\u30B5\u30A4\u30D0\u30FC\u30D1\u30F3\u30AF",
|
|
@@ -16293,7 +17946,9 @@ var INSTRUMENT_PRESETS = {
|
|
|
16293
17946
|
melody: "Lead 8 (bass + lead)",
|
|
16294
17947
|
submelody: "Lead 5 (charang)",
|
|
16295
17948
|
bass: "Synth Bass 2",
|
|
16296
|
-
chord: "Pad 8 (sweep)"
|
|
17949
|
+
chord: "Pad 8 (sweep)",
|
|
17950
|
+
solo: "Distortion Guitar",
|
|
17951
|
+
chorusLead: "Lead 7 (fifths)"
|
|
16297
17952
|
},
|
|
16298
17953
|
rock: {
|
|
16299
17954
|
displayName: "\u30CF\u30FC\u30C9\u30ED\u30C3\u30AF",
|
|
@@ -16301,7 +17956,9 @@ var INSTRUMENT_PRESETS = {
|
|
|
16301
17956
|
melody: "Distortion Guitar",
|
|
16302
17957
|
submelody: "Rock Organ",
|
|
16303
17958
|
bass: "Electric Bass (pick)",
|
|
16304
|
-
chord: "Overdriven Guitar"
|
|
17959
|
+
chord: "Overdriven Guitar",
|
|
17960
|
+
solo: "Distortion Guitar",
|
|
17961
|
+
chorusLead: "Brass Section"
|
|
16305
17962
|
},
|
|
16306
17963
|
// --- WORLD & CLASSIC: 特定のジャンル・地域 ---
|
|
16307
17964
|
orchestra: {
|
|
@@ -16310,7 +17967,9 @@ var INSTRUMENT_PRESETS = {
|
|
|
16310
17967
|
melody: "French Horn",
|
|
16311
17968
|
submelody: "Pizzicato Strings",
|
|
16312
17969
|
bass: "Cello",
|
|
16313
|
-
chord: "Tremolo Strings"
|
|
17970
|
+
chord: "Tremolo Strings",
|
|
17971
|
+
solo: "Violin",
|
|
17972
|
+
chorusLead: "Trumpet"
|
|
16314
17973
|
},
|
|
16315
17974
|
japanese_wa: {
|
|
16316
17975
|
displayName: "\u548C\u98A8\u30FB\u96C5",
|
|
@@ -16318,7 +17977,9 @@ var INSTRUMENT_PRESETS = {
|
|
|
16318
17977
|
melody: "Koto",
|
|
16319
17978
|
submelody: "Shamisen",
|
|
16320
17979
|
bass: "Taiko Drum",
|
|
16321
|
-
chord: "Shakuhachi"
|
|
17980
|
+
chord: "Shakuhachi",
|
|
17981
|
+
solo: "Shakuhachi",
|
|
17982
|
+
chorusLead: "Glockenspiel"
|
|
16322
17983
|
},
|
|
16323
17984
|
arabic_exotic: {
|
|
16324
17985
|
displayName: "\u30A8\u30AD\u30BE\u30C1\u30C3\u30AF",
|
|
@@ -16326,7 +17987,9 @@ var INSTRUMENT_PRESETS = {
|
|
|
16326
17987
|
melody: "Sitar",
|
|
16327
17988
|
submelody: "Bagpipe",
|
|
16328
17989
|
bass: "Fretless Bass",
|
|
16329
|
-
chord: "Kalimba"
|
|
17990
|
+
chord: "Kalimba",
|
|
17991
|
+
solo: "Shanai",
|
|
17992
|
+
chorusLead: "Steel Drums"
|
|
16330
17993
|
},
|
|
16331
17994
|
// --- FANTASY & ATMOSPHERE: 雰囲気と余韻 ---
|
|
16332
17995
|
fantasy_rpg: {
|
|
@@ -16335,7 +17998,9 @@ var INSTRUMENT_PRESETS = {
|
|
|
16335
17998
|
melody: "Ocarina",
|
|
16336
17999
|
submelody: "Celesta",
|
|
16337
18000
|
bass: "Timpani",
|
|
16338
|
-
chord: "Orchestral Harp"
|
|
18001
|
+
chord: "Orchestral Harp",
|
|
18002
|
+
solo: "Pan Flute",
|
|
18003
|
+
chorusLead: "Choir Aahs"
|
|
16339
18004
|
},
|
|
16340
18005
|
ambient_cloud: {
|
|
16341
18006
|
displayName: "\u30A2\u30F3\u30D3\u30A8\u30F3\u30C8",
|
|
@@ -16343,7 +18008,9 @@ var INSTRUMENT_PRESETS = {
|
|
|
16343
18008
|
melody: "Lead 6 (voice)",
|
|
16344
18009
|
submelody: "Music Box",
|
|
16345
18010
|
bass: "Synth Bass 1",
|
|
16346
|
-
chord: "Pad 7 (halo)"
|
|
18011
|
+
chord: "Pad 7 (halo)",
|
|
18012
|
+
solo: "Lead 3 (calliope)",
|
|
18013
|
+
chorusLead: "Synth Choir"
|
|
16347
18014
|
},
|
|
16348
18015
|
retro_game: {
|
|
16349
18016
|
displayName: "8-bit \u30EC\u30C8\u30ED",
|
|
@@ -16351,8 +18018,99 @@ var INSTRUMENT_PRESETS = {
|
|
|
16351
18018
|
melody: "Lead 1 (square)",
|
|
16352
18019
|
submelody: "Lead 2 (sawtooth)",
|
|
16353
18020
|
bass: "Synth Bass 1",
|
|
16354
|
-
chord: "Clavinet"
|
|
16355
|
-
|
|
18021
|
+
chord: "Clavinet",
|
|
18022
|
+
solo: "Lead 8 (bass + lead)",
|
|
18023
|
+
chorusLead: "Lead 4 (chiff)"
|
|
18024
|
+
}
|
|
18025
|
+
};
|
|
18026
|
+
var GM_INSTRUMENT_RANGE = {
|
|
18027
|
+
// 鍵盤・音板
|
|
18028
|
+
"Acoustic Grand Piano": [21, 108],
|
|
18029
|
+
"Electric Piano 1": [28, 103],
|
|
18030
|
+
Clavinet: [36, 96],
|
|
18031
|
+
Celesta: [60, 108],
|
|
18032
|
+
Glockenspiel: [79, 108],
|
|
18033
|
+
"Music Box": [72, 108],
|
|
18034
|
+
Vibraphone: [53, 89],
|
|
18035
|
+
Kalimba: [60, 84],
|
|
18036
|
+
"Orchestral Harp": [23, 104],
|
|
18037
|
+
// 弦・撥弦
|
|
18038
|
+
"Acoustic Guitar (steel)": [40, 83],
|
|
18039
|
+
"Acoustic Guitar (nylon)": [40, 83],
|
|
18040
|
+
"Electric Guitar (clean)": [40, 86],
|
|
18041
|
+
"Electric Guitar (jazz)": [40, 86],
|
|
18042
|
+
"Overdriven Guitar": [40, 88],
|
|
18043
|
+
"Distortion Guitar": [40, 88],
|
|
18044
|
+
Violin: [55, 103],
|
|
18045
|
+
Cello: [36, 76],
|
|
18046
|
+
"String Ensemble 1": [28, 100],
|
|
18047
|
+
"Tremolo Strings": [28, 100],
|
|
18048
|
+
"Pizzicato Strings": [28, 96],
|
|
18049
|
+
Sitar: [48, 79],
|
|
18050
|
+
Shamisen: [48, 84],
|
|
18051
|
+
Koto: [41, 77],
|
|
18052
|
+
// ベース
|
|
18053
|
+
"Acoustic Bass": [28, 60],
|
|
18054
|
+
"Electric Bass (finger)": [28, 67],
|
|
18055
|
+
"Electric Bass (pick)": [28, 67],
|
|
18056
|
+
"Fretless Bass": [28, 67],
|
|
18057
|
+
"Synth Bass 1": [24, 72],
|
|
18058
|
+
"Synth Bass 2": [24, 72],
|
|
18059
|
+
// 管
|
|
18060
|
+
Flute: [60, 96],
|
|
18061
|
+
"Pan Flute": [60, 91],
|
|
18062
|
+
Shakuhachi: [62, 86],
|
|
18063
|
+
Ocarina: [60, 84],
|
|
18064
|
+
Harmonica: [60, 96],
|
|
18065
|
+
Bagpipe: [62, 86],
|
|
18066
|
+
Shanai: [60, 86],
|
|
18067
|
+
"Tenor Sax": [44, 75],
|
|
18068
|
+
Trumpet: [55, 82],
|
|
18069
|
+
"Muted Trumpet": [55, 82],
|
|
18070
|
+
"French Horn": [41, 77],
|
|
18071
|
+
"Brass Section": [41, 84],
|
|
18072
|
+
// 声・打・オルガン
|
|
18073
|
+
"Choir Aahs": [43, 84],
|
|
18074
|
+
"Synth Choir": [43, 84],
|
|
18075
|
+
"Steel Drums": [55, 86],
|
|
18076
|
+
"Taiko Drum": [30, 60],
|
|
18077
|
+
Timpani: [36, 57],
|
|
18078
|
+
"Rock Organ": [36, 96],
|
|
18079
|
+
// シンセ(実物が無いので一般的な使用域)
|
|
18080
|
+
"Synth Brass 1": [36, 96],
|
|
18081
|
+
"Lead 1 (square)": [36, 96],
|
|
18082
|
+
"Lead 2 (sawtooth)": [36, 96],
|
|
18083
|
+
"Lead 3 (calliope)": [48, 96],
|
|
18084
|
+
"Lead 4 (chiff)": [48, 96],
|
|
18085
|
+
"Lead 5 (charang)": [40, 96],
|
|
18086
|
+
"Lead 6 (voice)": [43, 91],
|
|
18087
|
+
"Lead 7 (fifths)": [36, 84],
|
|
18088
|
+
"Lead 8 (bass + lead)": [28, 91],
|
|
18089
|
+
"Pad 2 (warm)": [24, 96],
|
|
18090
|
+
"Pad 3 (polysynth)": [24, 96],
|
|
18091
|
+
"Pad 7 (halo)": [24, 96],
|
|
18092
|
+
"Pad 8 (sweep)": [24, 96]
|
|
18093
|
+
};
|
|
18094
|
+
var GM_BRIGHT_CEILING = {
|
|
18095
|
+
Glockenspiel: 72,
|
|
18096
|
+
"Tinkle Bell": 72,
|
|
18097
|
+
"Music Box": 79,
|
|
18098
|
+
Celesta: 84,
|
|
18099
|
+
Kalimba: 79,
|
|
18100
|
+
"Steel Drums": 84,
|
|
18101
|
+
"FX 3 (crystal)": 79
|
|
18102
|
+
};
|
|
18103
|
+
var OCTAVE_FIT_TOLERANCE = 3;
|
|
18104
|
+
var fitInstrumentOctave = (semitoneRange, instrument, wanted) => {
|
|
18105
|
+
const range = GM_INSTRUMENT_RANGE[instrument];
|
|
18106
|
+
if (!range || !semitoneRange) return wanted;
|
|
18107
|
+
const hi = Math.min(range[1], GM_BRIGHT_CEILING[instrument] ?? range[1]);
|
|
18108
|
+
let octave = wanted;
|
|
18109
|
+
while (octave > wanted - 2) {
|
|
18110
|
+
if (semitoneRange[1] + octave * 12 <= hi + OCTAVE_FIT_TOLERANCE) break;
|
|
18111
|
+
octave--;
|
|
18112
|
+
}
|
|
18113
|
+
return octave;
|
|
16356
18114
|
};
|
|
16357
18115
|
|
|
16358
18116
|
// src/macro-state.ts
|
|
@@ -16360,6 +18118,7 @@ var MACRO_STORAGE_KEYS = {
|
|
|
16360
18118
|
template: "dtm-macro:template",
|
|
16361
18119
|
sections: "dtm-macro:sections",
|
|
16362
18120
|
key: "dtm-macro:key",
|
|
18121
|
+
scale: "dtm-macro:scale",
|
|
16363
18122
|
shift: "dtm-macro:shift",
|
|
16364
18123
|
transpose: "dtm-macro:transpose"
|
|
16365
18124
|
};
|
|
@@ -16863,56 +18622,95 @@ var exportMIDI = (options) => {
|
|
|
16863
18622
|
const div = 480;
|
|
16864
18623
|
const tickPerStep = div / STEPS_PER_BEAT3;
|
|
16865
18624
|
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
18625
|
const bendKey = (cents) => Math.round(cents * 100);
|
|
16869
|
-
const
|
|
16870
|
-
|
|
16871
|
-
for (const n of track.notes) {
|
|
18626
|
+
const hasMicrotones = tracks.some(
|
|
18627
|
+
(track) => track.notes.some((n) => {
|
|
16872
18628
|
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
|
-
});
|
|
18629
|
+
return bendKey(detuneCents) !== 0;
|
|
18630
|
+
})
|
|
18631
|
+
);
|
|
16904
18632
|
const bendSetup = [];
|
|
16905
|
-
|
|
16906
|
-
const
|
|
16907
|
-
|
|
16908
|
-
|
|
16909
|
-
|
|
16910
|
-
|
|
16911
|
-
|
|
16912
|
-
|
|
16913
|
-
|
|
16914
|
-
|
|
16915
|
-
|
|
18633
|
+
if (hasMicrotones) {
|
|
18634
|
+
const NOTE_CHANNELS = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15];
|
|
18635
|
+
const BEND_RANGE_SEMITONES = 2;
|
|
18636
|
+
const bendUse = /* @__PURE__ */ new Map();
|
|
18637
|
+
for (const track of tracks) {
|
|
18638
|
+
for (const n of track.notes) {
|
|
18639
|
+
const { detuneCents } = unitsToMidiDetune(n.pitchUnits);
|
|
18640
|
+
const k = bendKey(detuneCents);
|
|
18641
|
+
bendUse.set(k, (bendUse.get(k) ?? 0) + 1);
|
|
18642
|
+
}
|
|
18643
|
+
}
|
|
18644
|
+
const bendChannel = /* @__PURE__ */ new Map();
|
|
18645
|
+
const ordered = [...bendUse.entries()].sort((a, b) => b[1] - a[1]);
|
|
18646
|
+
for (const [k] of ordered) {
|
|
18647
|
+
if (bendChannel.size >= NOTE_CHANNELS.length) break;
|
|
18648
|
+
bendChannel.set(k, NOTE_CHANNELS[bendChannel.size]);
|
|
18649
|
+
}
|
|
18650
|
+
tracks.forEach((track) => {
|
|
18651
|
+
if (track.notes.length === 0) return;
|
|
18652
|
+
const events = [];
|
|
18653
|
+
for (const n of track.notes) {
|
|
18654
|
+
const { midi, detuneCents } = unitsToMidiDetune(n.pitchUnits);
|
|
18655
|
+
const k = bendKey(detuneCents);
|
|
18656
|
+
const channel = bendChannel.get(k) ?? bendChannel.get(0) ?? 0;
|
|
18657
|
+
const note = Math.max(0, Math.min(127, midi));
|
|
18658
|
+
const startTick = Math.round(n.startStep * tickPerStep);
|
|
18659
|
+
const endTick = Math.round(
|
|
18660
|
+
(n.startStep + (n.durationSteps || 1)) * tickPerStep
|
|
18661
|
+
);
|
|
18662
|
+
const vel = Math.round(
|
|
18663
|
+
(n.velocity ?? DEFAULT_VELOCITY) * (track.volume ?? 100) / 100
|
|
18664
|
+
);
|
|
18665
|
+
events.push({ t: startTick, m: [144 | channel, note, vel] });
|
|
18666
|
+
events.push({ t: endTick, m: [144 | channel, note, 0] });
|
|
18667
|
+
}
|
|
18668
|
+
events.sort((a, b) => a.t - b.t);
|
|
18669
|
+
midiTracks.push(events);
|
|
18670
|
+
});
|
|
18671
|
+
for (const [k, channel] of bendChannel) {
|
|
18672
|
+
const cents = k / 100;
|
|
18673
|
+
bendSetup.push({ t: 0, m: [176 | channel, 101, 0] });
|
|
18674
|
+
bendSetup.push({ t: 0, m: [176 | channel, 100, 0] });
|
|
18675
|
+
bendSetup.push({ t: 0, m: [176 | channel, 6, BEND_RANGE_SEMITONES] });
|
|
18676
|
+
bendSetup.push({ t: 0, m: [176 | channel, 38, 0] });
|
|
18677
|
+
bendSetup.push({ t: 0, m: [176 | channel, 101, 127] });
|
|
18678
|
+
bendSetup.push({ t: 0, m: [176 | channel, 100, 127] });
|
|
18679
|
+
const raw = 8192 + Math.round(cents / (BEND_RANGE_SEMITONES * 100) * 8192);
|
|
18680
|
+
const v = Math.max(0, Math.min(16383, raw));
|
|
18681
|
+
bendSetup.push({ t: 0, m: [224 | channel, v & 127, v >> 7 & 127] });
|
|
18682
|
+
}
|
|
18683
|
+
} else {
|
|
18684
|
+
tracks.forEach((track, trIdx) => {
|
|
18685
|
+
if (track.notes.length === 0) return;
|
|
18686
|
+
const channel = trIdx < 9 ? trIdx : trIdx + 1 & 15;
|
|
18687
|
+
const events = [];
|
|
18688
|
+
if (track.program !== void 0 && track.program >= 0 && track.program <= 127) {
|
|
18689
|
+
events.push({ t: 0, m: [192 | channel, track.program] });
|
|
18690
|
+
}
|
|
18691
|
+
for (const n of track.notes) {
|
|
18692
|
+
const { midi } = unitsToMidiDetune(n.pitchUnits);
|
|
18693
|
+
const note = Math.max(0, Math.min(127, midi));
|
|
18694
|
+
const startTick = Math.round(n.startStep * tickPerStep);
|
|
18695
|
+
const endTick = Math.round(
|
|
18696
|
+
(n.startStep + (n.durationSteps || 1)) * tickPerStep
|
|
18697
|
+
);
|
|
18698
|
+
const vel = Math.round(
|
|
18699
|
+
(n.velocity ?? DEFAULT_VELOCITY) * (track.volume ?? 100) / 100
|
|
18700
|
+
);
|
|
18701
|
+
events.push({ t: startTick, m: [144 | channel, note, vel] });
|
|
18702
|
+
events.push({ t: endTick, m: [144 | channel, note, 0] });
|
|
18703
|
+
}
|
|
18704
|
+
events.sort((a, b) => {
|
|
18705
|
+
if (a.t !== b.t) return a.t - b.t;
|
|
18706
|
+
const typeA = a.m[0] & 240;
|
|
18707
|
+
const typeB = b.m[0] & 240;
|
|
18708
|
+
if (typeA === 192 && typeB !== 192) return -1;
|
|
18709
|
+
if (typeB === 192 && typeA !== 192) return 1;
|
|
18710
|
+
return 0;
|
|
18711
|
+
});
|
|
18712
|
+
midiTracks.push(events);
|
|
18713
|
+
});
|
|
16916
18714
|
}
|
|
16917
18715
|
const maxStep = Math.max(
|
|
16918
18716
|
...tracks.filter((t) => t.notes.length > 0).map(
|
|
@@ -17648,28 +19446,6 @@ var isChordHeavyTrack = (notes, threshold = 0.6) => {
|
|
|
17648
19446
|
return chordNotes / notes.length >= threshold;
|
|
17649
19447
|
};
|
|
17650
19448
|
|
|
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
19449
|
// src/renderer.ts
|
|
17674
19450
|
var KEYBOARD_WIDTH = 60;
|
|
17675
19451
|
var HEADER_HEIGHT = 20;
|
|
@@ -18159,6 +19935,28 @@ var createRenderer = (mountTarget, width = 800, height = 450, config) => {
|
|
|
18159
19935
|
};
|
|
18160
19936
|
};
|
|
18161
19937
|
|
|
19938
|
+
// src/track1-state.ts
|
|
19939
|
+
var TRACK1_STORAGE_KEY = "dtm-track1:settings";
|
|
19940
|
+
var readTrack1Settings = () => {
|
|
19941
|
+
try {
|
|
19942
|
+
if (typeof localStorage === "undefined" || !localStorage) return null;
|
|
19943
|
+
const raw = localStorage.getItem(TRACK1_STORAGE_KEY);
|
|
19944
|
+
if (!raw) return null;
|
|
19945
|
+
const parsed = JSON.parse(raw);
|
|
19946
|
+
if (!parsed || typeof parsed !== "object") return null;
|
|
19947
|
+
return parsed;
|
|
19948
|
+
} catch (_) {
|
|
19949
|
+
return null;
|
|
19950
|
+
}
|
|
19951
|
+
};
|
|
19952
|
+
var writeTrack1Settings = (settings) => {
|
|
19953
|
+
try {
|
|
19954
|
+
if (typeof localStorage === "undefined" || !localStorage) return;
|
|
19955
|
+
localStorage.setItem(TRACK1_STORAGE_KEY, JSON.stringify(settings));
|
|
19956
|
+
} catch (_) {
|
|
19957
|
+
}
|
|
19958
|
+
};
|
|
19959
|
+
|
|
18162
19960
|
// src/daw.ts
|
|
18163
19961
|
var CHORD_INFO_HTML2 = `
|
|
18164
19962
|
<div class="dtm-modal-body-content">
|
|
@@ -18480,6 +20278,7 @@ var COMPOSE_INFO_HTML = `
|
|
|
18480
20278
|
<li><strong>\u30E1\u30ED\u30C7\u30A3\u306E\u66F8\u6CD5</strong>\u2014\u2014\u8D70\u53E5\u306E\u5F62\uFF08\u97F3\u968E\uFF0F\u6298\u308A\u8FD4\u3057\uFF0F\u5206\u6563\u548C\u97F3\uFF0F\u30B8\u30B0\u30B6\u30B0\uFF09\u3001\u3064\u306A\u304E\u306E\u5F62\uFF08\u5C71\u306A\u308A\uFF0F\u8C37\uFF0F\u4E0A\u884C\uFF0F\u4E0B\u884C\uFF0F\u3046\u306D\u308A\uFF0F\u8EF8\u97F3\u307E\u308F\u308A\uFF09\u3001\u7D42\u6B62\u306E\u5F62\uFF08\u9806\u6B21\u4E0B\u964D\uFF0F\u30BD\u30DF\u30C9\uFF0F\u8DF3\u306D\u4E0A\u304C\u308A\uFF0F\u30ED\u30F3\u30B0\u30C8\u30FC\u30F3\uFF09\u3001\u30E2\u30C1\u30FC\u30D5\u306E\u539F\u578B\u3001\u8DF3\u8E8D\u306E\u6DF7\u305C\u5177\u5408\u3001\u958B\u59CB\u97F3\u3001\u57FA\u6E96\u306E\u523B\u307F\uFF088\u5206\uFF0F16\u5206\uFF0F\u4E09\u9023\uFF09\u3001\u30B9\u30A6\u30A3\u30F3\u30B0\u91CF</li>
|
|
18481
20279
|
<li><strong>\u30D9\u30FC\u30B9\u306E\u594F\u6CD5</strong>\uFF084\u5206\u6253\u3061\uFF0F\u30AA\u30EB\u30BF\u30CD\u30A4\u30C8\uFF0F2\u5206\uFF0F8\u5206\u30C9\u30E9\u30A4\u30D6\uFF0F\u30B7\u30F3\u30B3\u30DA\uFF0F\u30A6\u30A9\u30FC\u30AD\u30F3\u30B0\uFF0F\u30AA\u30AF\u30BF\u30FC\u30D6\uFF09</li>
|
|
18482
20280
|
<li><strong>\u30B5\u30D6\u30E1\u30ED\u306E\u66F8\u304D\u65B9</strong>\u2014\u2014\u5408\u3044\u306E\u624B\uFF08\u30E1\u30ED\u30C7\u30A3\u304C\u4F11\u3093\u3060\u9699\u9593\u306B\u3060\u3051\u5165\u308B\uFF09\u3001\u30CF\u30E2\u30EA\uFF08\u30E1\u30ED\u30C7\u30A3\u306E\u30EA\u30BA\u30E0\u3092\u306A\u305E\u3063\u30663\u5EA6\u30FB6\u5EA6\u4E0B\u3092\u6B4C\u3046\uFF09\u3001\u5BFE\u65CB\u5F8B\uFF088\u5206\u3067\u30E1\u30ED\u30C7\u30A3\u3068\u53CD\u884C\u3059\u308B\uFF09\u3001\u4FDD\u7D9A\u97F3\uFF08\u540C\u3058\u97F3\u3092\u4F38\u3070\u3057\u7D9A\u3051\u308B\uFF09\u3001\u30D1\u30C3\u30C9\u3002\u5C0F\u7BC0\u3054\u3068\u306B\u3001\u30E1\u30ED\u30C7\u30A3\u304C\u606F\u7D99\u304E\u3057\u3066\u3044\u308B\u5834\u6240\u3067\u306F\u81EA\u52D5\u3067\u5408\u3044\u306E\u624B\u306B\u5207\u308A\u66FF\u308F\u308A\u307E\u3059\u3002</li>
|
|
20281
|
+
<li><strong>\u7DE8\u66F2\u30D7\u30E9\u30F3</strong>\uFF08\u4E0A\u7D1A\u8005\u30E2\u30FC\u30C9\u306E\u307F\uFF09\u2014\u2014\u4F34\u594F\u3092\u4F55\u5C64\u306B\u3059\u308B\u304B\u3001\u305D\u308C\u305E\u308C\u3069\u306E\u594F\u6CD5\u3067\u3069\u306E\u30BB\u30AF\u30B7\u30E7\u30F3\u3092\u9CF4\u3089\u3059\u304B\u3001\u30B5\u30D3\u306E\u91CD\u306D\u3092\u51FA\u3059\u304B\u30FB\u30E6\u30CB\u30BE\u30F3\u304B\u30AA\u30AF\u30BF\u30FC\u30D6\u4E0A\u304B\u3001\u88C5\u98FE\u3092\u3069\u3053\u306B\u7F6E\u304F\u304B\u3002400\u66F2\u5F15\u304F\u3068392\u901A\u308A\u306E\u578B\u304C\u51FA\u307E\u3059\u3002</li>
|
|
18483
20282
|
</ul>
|
|
18484
20283
|
<p>\u3055\u3089\u306B\u3001\u76F4\u524D\u306B\u4F5C\u3063\u305F5\u66F2\u3068\u7279\u5FB4\u304C\u4F3C\u3066\u3044\u308B\u5019\u88DC\u306B\u306F\u6E1B\u70B9\u3057\u3066\u3044\u307E\u3059\u3002\u7D9A\u3051\u3066\u62BC\u3057\u305F\u3068\u304D\u306B\u4F3C\u305F\u66F2\u304C\u4E26\u3070\u306A\u3044\u3088\u3046\u306B\u3059\u308B\u305F\u3081\u3067\u3059\u3002</p>
|
|
18485
20284
|
<h4>\u3067\u304D\u3042\u304C\u308A\u306E\u9078\u3073\u65B9</h4>
|
|
@@ -18491,8 +20290,28 @@ var COMPOSE_INFO_HTML = `
|
|
|
18491
20290
|
<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
20291
|
</ul>
|
|
18493
20292
|
<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>
|
|
20293
|
+
<h4>\u6B4C\u5165\u308A\u4F5C\u66F2\u306E\u30DC\u30FC\u30AB\u30EB</h4>
|
|
20294
|
+
<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>
|
|
20295
|
+
<ul>
|
|
20296
|
+
<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>
|
|
20297
|
+
<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>
|
|
20298
|
+
</ul>
|
|
20299
|
+
<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>
|
|
20300
|
+
<h4>\u30BB\u30AF\u30B7\u30E7\u30F3\u3067\u697D\u5668\u30FB\u4F34\u594F\u304C\u5909\u308F\u308B\uFF08\u4E0A\u7D1A\u8005\u30E2\u30FC\u30C9\u306E\u307F\uFF09</h4>
|
|
20301
|
+
<p>1\u672C\u306E\u30C8\u30E9\u30C3\u30AF\u306F\u3001\u66F2\u306E\u6700\u521D\u304B\u3089\u6700\u5F8C\u307E\u30671\u3064\u306E\u697D\u5668\u3067\u9CF4\u308A\u307E\u3059\u3002\u3064\u307E\u308A<strong>\u300C\u30B5\u30D3\u3060\u3051\u5225\u306E\u697D\u5668\u306B\u3059\u308B\u300D\u306F\u30011\u672C\u306E\u30C8\u30E9\u30C3\u30AF\u306E\u4E2D\u3067\u306F\u4F5C\u308C\u307E\u305B\u3093</strong>\u3002\u4F5C\u308C\u308B\u306E\u306F\u3001\u9CF4\u3089\u3057\u305F\u3044\u533A\u9593\u3092\u5225\u306E\u30C8\u30E9\u30C3\u30AF\u3078\u66F8\u304D\u5206\u3051\u305F\u3068\u304D\u3060\u3051\u3067\u3059\u3002\u4E0A\u7D1A\u8005\u30E2\u30FC\u30C9\uFF0815\u30C8\u30E9\u30C3\u30AF\uFF09\u304C15\u672C\u3042\u308B\u306E\u306F\u305D\u306E\u305F\u3081\u3067\u3001\u300C\u4F5C\u66F2\u300D\u306F\u5834\u6240\u3054\u3068\u306B\u30C8\u30E9\u30C3\u30AF\u3092\u5206\u3051\u307E\u3059\u3002</p>
|
|
20302
|
+
<ul>
|
|
20303
|
+
<li><strong>\u4F34\u594F\u306E\u624B\u89E6\u308A\u304C\u30BB\u30AF\u30B7\u30E7\u30F3\u3067\u5909\u308F\u308B</strong> \u2014 \u540C\u3058\u30B3\u30FC\u30C9\u9032\u884C\u3092\u3001\u30D6\u30ED\u30C3\u30AF\u30FB\u30A2\u30EB\u30DA\u30B8\u30AA\u30FB\u88CF\u62CD\u30FB\u516B\u5206\u98DF\u3044\u30FB\u5206\u6563\u306E\u4E2D\u304B\u3089<strong>\u5225\u3005\u306E\u594F\u6CD5</strong>\u30671\u301C3\u5C64\u306B\u91CD\u306D\u307E\u3059\u3002\u3069\u306E\u594F\u6CD5\u3092\u3069\u306E\u30BB\u30AF\u30B7\u30E7\u30F3\u3067\u9CF4\u3089\u3059\u304B\u306F\u66F2\u3054\u3068\u306B\u5F15\u304F\u306E\u3067\u3001A\u30E1\u30ED\u3068\u30B5\u30D3\u3067\u4F34\u594F\u306E\u523B\u307F\u65B9\u305D\u306E\u3082\u306E\u304C\u5909\u308F\u308A\u307E\u3059\u3002\u66F2\u5168\u4F53\u3092\u901A\u308B\u300C\u5730\u300D\u306E\u5C64\u304C1\u3064\u3042\u308A\u3001\u6B8B\u308A\u306F\u8DB3\u3059\u5834\u6240\u3092\u7D5E\u308A\u307E\u3059\u3002</li>
|
|
20304
|
+
<li><strong>\u30B5\u30D3\u306E\u91CD\u306D</strong> \u2014 \u4E3B\u65CB\u5F8B\u3092\u3082\u30461\u672C\u306E\u5225\u697D\u5668\uFF08\u30D7\u30EA\u30BB\u30C3\u30C8\u306B\u3088\u3063\u3066\u30D6\u30E9\u30B9\u30FB\u30B9\u30C8\u30EA\u30F3\u30B0\u30B9\u30FB\u30B0\u30ED\u30C3\u30B1\u30F3\u306A\u3069\uFF09\u3067\u91CD\u306D\u307E\u3059\u3002<strong>\u30AA\u30AF\u30BF\u30FC\u30D6\u4E0A\u3068\u30E6\u30CB\u30BE\u30F3\u306E\u4E21\u65B9\u3092\u5F15\u304D\u307E\u3059</strong>\u2014\u2014\u540C\u3058\u9AD8\u3055\u3092\u5225\u306E\u697D\u5668\u3067\u91CD\u306D\u308B\u30682\u3064\u306E\u97F3\u8272\u304C\u6EB6\u3051\u3066\u5225\u306E\u97F3\u8272\u306B\u306A\u308B\u306E\u3067\u3001\u30AA\u30AF\u30BF\u30FC\u30D6\u4E0A\u3052\u308B\u3088\u308A\u60C5\u5831\u91CF\u304C\u591A\u3044\u3053\u3068\u304C\u3042\u308A\u307E\u3059\u3002\u91CD\u306D\u306A\u3044\u66F2\u3082\u3042\u308A\u307E\u3059\u3002</li>
|
|
20305
|
+
<li><strong>\u9593\u594F\u306E\u30BD\u30ED</strong> \u2014 \u9593\u594F\u306F\u6B4C\u304C\u4F11\u3080\u5834\u6240\u3067\u3042\u3063\u3066\u3001\u97F3\u697D\u304C\u4F11\u3080\u5834\u6240\u3067\u306F\u3042\u308A\u307E\u305B\u3093\u3002\u6B4C\u30E1\u30ED\u306E\u4EE3\u308F\u308A\u306B\u5668\u697D\u306E\u30BD\u30ED\u3092\u66F8\u304D\u3001\u5C02\u7528\u306E\u30C8\u30E9\u30C3\u30AF\u3067\u9CF4\u3089\u3057\u307E\u3059\u3002\u30D7\u30EA\u30BB\u30C3\u30C8\u306B\u3088\u3063\u3066\u6B6A\u307F\u30AE\u30BF\u30FC\u30FB\u30B5\u30C3\u30AF\u30B9\u30FB\u5C3A\u516B\u306A\u3069\u306B\u5909\u308F\u308A\u307E\u3059\u3002\u7D20\u6750\u306F\u30B5\u30D3\u3068\u540C\u3058\u306A\u306E\u3067\u3001\u9593\u594F\u304C\u30B5\u30D3\u306E\u4E3B\u984C\u3092\u5F3E\u304F\u5F62\u306B\u306A\u308A\u307E\u3059\u3002</li>
|
|
20306
|
+
<li><strong>\u30A6\u30EF\u30E2\u30CE</strong> \u2014 \u304D\u3089\u3073\u3084\u304B\u306A\u88C5\u98FE\u3092\u3001\u76DB\u308A\u4E0A\u304C\u308B\u30BB\u30AF\u30B7\u30E7\u30F3\u306B\u3060\u3051\u30AA\u30AF\u30BF\u30FC\u30D6\u4E0A\u3067\u8DB3\u3057\u307E\u3059\u3002<strong>\u5730\u306E\u4F34\u594F\u3068\u540C\u3058\u594F\u6CD5\u306F\u4F7F\u3044\u307E\u305B\u3093</strong>\u2014\u2014\u540C\u3058\u3082\u306E\u3092\u30AA\u30AF\u30BF\u30FC\u30D6\u4E0A\u3052\u305F\u3060\u3051\u306E\u5C64\u306F\u88C5\u98FE\u3067\u306F\u306A\u304F\u5199\u3057\u3060\u304B\u3089\u3067\u3059\u3002\u30D6\u30ED\u30C3\u30AF\u3082\u5916\u3057\u307E\u3059\uFF08\u548C\u97F3\u3092\u4E38\u3054\u3068\u30AA\u30AF\u30BF\u30FC\u30D6\u4E0A\u3067\u9CF4\u3089\u3059\u306E\u306F\u88C5\u98FE\u3067\u306F\u306A\u304F\u58C1\u306B\u306A\u308A\u307E\u3059\uFF09\u3002</li>
|
|
20307
|
+
</ul>
|
|
20308
|
+
<p><strong>\u697D\u5668\u306E\u97F3\u57DF\u306B\u5408\u308F\u305B\u3066\u30AA\u30AF\u30BF\u30FC\u30D6\u3092\u4E0B\u3052\u307E\u3059\u3002</strong>1\u30C8\u30E9\u30C3\u30AF1\u697D\u5668\u3067\u3001\u3057\u304B\u3082\u5C64\u3054\u3068\u306B\u30AA\u30AF\u30BF\u30FC\u30D6\u3092\u5909\u3048\u308B\u306E\u3067\u3001\u6C7A\u3081\u305F\u30AA\u30AF\u30BF\u30FC\u30D6\u304C\u305D\u306E\u697D\u5668\u306E\u51FA\u305B\u306A\u3044\u9AD8\u3055\u306B\u306A\u308B\u3053\u3068\u304C\u3042\u308A\u307E\u3059\u3002\u5B9F\u6E2C\u3059\u308B\u3068\u3001\u30B5\u30D3\u306E\u91CD\u306D\u30921\u30AA\u30AF\u30BF\u30FC\u30D6\u4E0A\u3052\u308B\u6307\u5B9A\u306F\u30DF\u30E5\u30FC\u30C8\u30C8\u30E9\u30F3\u30DA\u30C3\u30C8\u3084\u30C8\u30E9\u30F3\u30DA\u30C3\u30C8\u306714\u534A\u97F3\u3076\u3093\u3001\u30B3\u30FC\u30C9\u30D1\u30C3\u30C9\uFF08\u5B9F\u97F377\u301C93\uFF09\u306F\u30CA\u30A4\u30ED\u30F3\u30AE\u30BF\u30FC\u306710\u534A\u97F3\u30FB\u30AB\u30EA\u30F3\u30D0\u30679\u534A\u97F3\u3076\u3093\u97F3\u57DF\u3092\u7A81\u304D\u629C\u3051\u3066\u3044\u307E\u3057\u305F\u3002\u30B5\u30F3\u30D7\u30EB\u304C\u5F15\u304D\u4F38\u3070\u3055\u308C\u3066<strong>\u91D1\u5207\u308A\u97F3</strong>\u306B\u306A\u308A\u3001\u8074\u304D\u624B\u306B\u306F\u300C\u8033\u304C\u75DB\u3044\u300D\u3068\u3057\u304B\u611F\u3058\u3089\u308C\u307E\u305B\u3093\u3002\u305D\u3053\u3067\u3001\u9CF4\u3089\u3059\u97F3\u57DF\u304C\u305D\u306E\u697D\u5668\u306E\u5B9F\u7528\u4E0A\u9650\u306B\u53CE\u307E\u308B\u3068\u3053\u308D\u307E\u3067<strong>\u30AA\u30AF\u30BF\u30FC\u30D6\u3092\u4E0B\u3052\u3066\u304B\u3089</strong>\u7F6E\u304D\u307E\u3059\uFF08\u30C8\u30E9\u30C3\u30AF\u306E\u30AA\u30AF\u30BF\u30FC\u30D6\u8A2D\u5B9A\u306F\u3001\u307E\u3055\u306B\u3053\u3046\u3044\u3046\u300C\u5F97\u610F\u306A\u97F3\u57DF\u304C\u504F\u3063\u305F\u97F3\u6E90\u300D\u3092\u4F7F\u3048\u308B\u3088\u3046\u306B\u3059\u308B\u305F\u3081\u306B\u5728\u308B\u3082\u306E\u3067\u3059\uFF09\u3002<strong>\u4E0B\u3052\u308B\u65B9\u5411\u306B\u3057\u304B\u52D5\u304B\u3057\u307E\u305B\u3093</strong>\u2014\u2014\u4E0A\u3052\u308B\u5074\u304C\u75DB\u307F\u3092\u4F5C\u308B\u5074\u306A\u306E\u3067\u3002</p>
|
|
20309
|
+
<p>\u5B9F\u7269\u306E\u97F3\u57DF\u306B\u53CE\u307E\u3063\u3066\u3044\u3066\u3082\u75DB\u304F\u306A\u308B\u97F3\u8272\u304C\u3042\u308A\u307E\u3059\u3002\u30B0\u30ED\u30C3\u30B1\u30F3\u306F\u5B9F\u7269\u306E\u97F3\u57DF\u304CG5\u301CC8\u306A\u306E\u3067\u3001\u65CB\u5F8B\u306E\u97F3\u57DF\uFF08\u301CC6\uFF09\u306F\u300C\u4F59\u88D5\u3067\u7BC4\u56F2\u5185\u300D\u3067\u3059\u304C\u3001\u91D1\u5C5E\u4F53\u306E\u500D\u97F3\u306F\u4EBA\u306E\u8033\u304C\u3044\u3061\u3070\u3093\u654F\u611F\u306A2\u301C4kHz\u306B\u96C6\u307E\u308B\u305F\u3081\u3001\u305D\u306E\u9AD8\u3055\u3067\u9CF4\u3089\u3057\u7D9A\u3051\u308B\u3068\u523A\u3055\u308A\u307E\u3059\u3002\u3053\u3046\u3044\u3046\u97F3\u8272\u306B\u306F\u97F3\u57DF\u3068\u306F\u5225\u306B<strong>\u660E\u308B\u3055\u306E\u4E0A\u9650</strong>\u3092\u6301\u305F\u305B\u3066\u3042\u308A\u3001\u30B0\u30ED\u30C3\u30B1\u30F3\u306A\u3089C5\u3088\u308A\u4E0A\u3067\u9CF4\u3089\u306A\u3044\u3068\u3053\u308D\u307E\u3067\u4E0B\u3052\u307E\u3059\u3002<strong>\u5019\u88DC\u304B\u3089\u5916\u3059\u306E\u3067\u306F\u306A\u304F\u7F6E\u304D\u5834\u6240\u3092\u5909\u3048\u307E\u3059</strong>\u2014\u2014\u5916\u3059\u3068\u97F3\u8272\u306E\u5E45\u304C\u305D\u306E\u3076\u3093\u6E1B\u308B\u3060\u3051\u3067\u3001\u4F4E\u304F\u9CF4\u3089\u3057\u305F\u30B0\u30ED\u30C3\u30B1\u30F3\u306F\u30DD\u30C3\u30D7\u30B9\u3067\u666E\u901A\u306B\u4F7F\u308F\u308C\u308B\u67D4\u3089\u304B\u3044\u97F3\u3067\u3059\u3002</p>
|
|
20310
|
+
<p><strong>\u30AA\u30AF\u30BF\u30FC\u30D6\u306E\u91CD\u306D\u3092\u4E3B\u5F79\u306B\u3057\u3066\u3044\u307E\u305B\u3093\u3002</strong>\u300C\u65E2\u306B\u3042\u308B\u30C8\u30E9\u30C3\u30AF\u30921\u30AA\u30AF\u30BF\u30FC\u30D6\u52D5\u304B\u3057\u3066\u5225\u30C8\u30E9\u30C3\u30AF\u3078\u5199\u3059\u300D\u5C64\u306F\u3001\u97F3\u697D\u7684\u306A\u4FA1\u5024\u304C\u9AD8\u304F\u3042\u308A\u307E\u305B\u3093\u3002\u4EBA\u306E\u8033\u306F\u30AA\u30AF\u30BF\u30FC\u30D6\u9055\u3044\u3092<strong>\u540C\u3058\u97F3</strong>\u3068\u3057\u3066\u805E\u304F\u306E\u3067\uFF08\u30AA\u30AF\u30BF\u30FC\u30D6\u7B49\u4FA1\uFF09\u3001\u5199\u3057\u305F\u5C64\u306F\u65B0\u3057\u3044\u58F0\u90E8\u306B\u306A\u3089\u305A\u3001\u97F3\u91CF\u3068\u97F3\u8272\u304C\u308F\u305A\u304B\u306B\u5909\u308F\u308B\u3060\u3051\u3067\u3059\u3002\u5F37\u8ABF\u3068\u3057\u3066\u306E\u610F\u5473\u306F\u3042\u308B\u306E\u3067\u4F7F\u3044\u306F\u3057\u307E\u3059\u304C\u3001\u5E38\u8A2D\u306B\u306F\u3057\u307E\u305B\u3093\u3002\u30D9\u30FC\u30B9\u306E\u30AA\u30AF\u30BF\u30FC\u30D6\u4E0B\u306E\u91CD\u306D\u306F\u7279\u306B\u300130Hz\u524D\u5F8C\u307E\u3067\u843D\u3061\u3066\u8F2A\u90ED\u304C\u6FC1\u308B\u306E\u3067\u65E2\u5B9A\u3067\u306F\u51FA\u3057\u307E\u305B\u3093\uFF08\u51FA\u3059\u3068\u304D\u3082\u4E0A\u306E\u30AA\u30AF\u30BF\u30FC\u30D6\u3078\u3001\u76DB\u308A\u4E0A\u304C\u308B\u5834\u6240\u3060\u3051\u306B\u7F6E\u304D\u307E\u3059\uFF09\u3002</p>
|
|
20311
|
+
<p>\u300C\u4F5C\u66F2\u300D\u304C\u6C7A\u3081\u305F\u3053\u308C\u3089\u306E\u697D\u5668\u306F\u3001\u304A\u307E\u304B\u305B\u30DE\u30B9\u30BF\u30EA\u30F3\u30B0\u306E\u5F79\u5272\u63A8\u5B9A\u3088\u308A\u512A\u5148\u3055\u308C\u307E\u3059\uFF08\u6F14\u594F\u5185\u5BB9\u3060\u3051\u3092\u898B\u308B\u3068\u3001\u9593\u594F\u306E\u30BD\u30ED\u3082\u30B5\u30D3\u306E\u91CD\u306D\u3082\u300C\u97F3\u306E\u5C11\u306A\u3044\u5358\u65CB\u5F8B\u300D\u3067\u3001\u4E3B\u65CB\u5F8B\u3068\u533A\u5225\u304C\u4ED8\u304B\u306A\u3044\u305F\u3081\u3067\u3059\uFF09\u3002\u697D\u5668\u3092\u624B\u3067\u9078\u3073\u76F4\u3057\u305F\u30C8\u30E9\u30C3\u30AF\u306F\u3001\u4EE5\u5F8C\u3069\u3061\u3089\u306B\u3082\u4E0A\u66F8\u304D\u3055\u308C\u307E\u305B\u3093\u3002</p>
|
|
18494
20312
|
<h4>\u305D\u306E\u307B\u304B</h4>
|
|
18495
20313
|
<ul>
|
|
20314
|
+
<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
20315
|
<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
20316
|
<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
20317
|
<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>
|
|
@@ -18756,19 +20575,128 @@ var pickComposeVocal = (exclude) => {
|
|
|
18756
20575
|
const list = pool.length > 0 ? pool : COMPOSE_VOCAL_POOL;
|
|
18757
20576
|
return list[Math.floor(Math.random() * list.length)] ?? "klatt";
|
|
18758
20577
|
};
|
|
18759
|
-
var
|
|
18760
|
-
{
|
|
18761
|
-
|
|
18762
|
-
|
|
18763
|
-
|
|
18764
|
-
|
|
18765
|
-
|
|
18766
|
-
|
|
18767
|
-
|
|
18768
|
-
|
|
18769
|
-
|
|
18770
|
-
|
|
18771
|
-
|
|
20578
|
+
var buildAdvancedLayers = (song, config) => {
|
|
20579
|
+
const { edo, stepsPerBar, preset } = config;
|
|
20580
|
+
const semitoneRange = (notes) => {
|
|
20581
|
+
if (notes.length === 0) return null;
|
|
20582
|
+
let lo = Number.POSITIVE_INFINITY;
|
|
20583
|
+
let hi = Number.NEGATIVE_INFINITY;
|
|
20584
|
+
for (const n of notes) {
|
|
20585
|
+
const semi = n.pitchUnits / UNITS_PER_SEMITONE;
|
|
20586
|
+
if (semi < lo) lo = semi;
|
|
20587
|
+
if (semi > hi) hi = semi;
|
|
20588
|
+
}
|
|
20589
|
+
return [Math.round(lo), Math.round(hi)];
|
|
20590
|
+
};
|
|
20591
|
+
const fit = (notes, slot, wanted) => fitInstrumentOctave(semitoneRange(notes), preset[slot], wanted);
|
|
20592
|
+
const kindAtBar = (bar) => song.sections.find(
|
|
20593
|
+
(sec) => bar >= sec.startBar && bar < sec.startBar + sec.bars
|
|
20594
|
+
)?.kind ?? null;
|
|
20595
|
+
const onlyIn = (notes, kinds) => {
|
|
20596
|
+
if (!kinds) return notes;
|
|
20597
|
+
const want = new Set(kinds);
|
|
20598
|
+
return notes.filter((n) => {
|
|
20599
|
+
const kind = kindAtBar(Math.floor(n.startStep / stepsPerBar));
|
|
20600
|
+
return kind !== null && want.has(kind);
|
|
20601
|
+
});
|
|
20602
|
+
};
|
|
20603
|
+
const chordNotes = (pattern, velocityShift = 0) => buildChordPlacements({
|
|
20604
|
+
edo,
|
|
20605
|
+
chordStr: song.chordProgression,
|
|
20606
|
+
patternType: pattern,
|
|
20607
|
+
rootShift: song.rootShift,
|
|
20608
|
+
bpm: song.bpm,
|
|
20609
|
+
stepsPerBar
|
|
20610
|
+
}).map((p) => ({
|
|
20611
|
+
startStep: p.startStep,
|
|
20612
|
+
pitchUnits: p.pitchUnits,
|
|
20613
|
+
durationSteps: p.durationSteps,
|
|
20614
|
+
velocity: Math.max(30, p.velocity + velocityShift)
|
|
20615
|
+
}));
|
|
20616
|
+
const plan = song.arrange;
|
|
20617
|
+
const leadNotes = plan.lead ? onlyIn(song.melody, plan.lead.sections) : [];
|
|
20618
|
+
const leadOctave = fit(leadNotes, "chorusLead", plan.lead?.octave ?? 0);
|
|
20619
|
+
const leadLayer = {
|
|
20620
|
+
index: 1,
|
|
20621
|
+
notes: leadNotes,
|
|
20622
|
+
octave: leadOctave,
|
|
20623
|
+
// ユニゾンで重ねるときは、オクターブ上より前に出やすいので少し引く。
|
|
20624
|
+
volume: leadOctave === 0 ? 54 : 62,
|
|
20625
|
+
slot: "chorusLead"
|
|
20626
|
+
};
|
|
20627
|
+
const bassNotes = plan.bassLayer ? onlyIn(song.bass, plan.bassLayer.sections) : [];
|
|
20628
|
+
const bassOctave = fit(bassNotes, "bass", plan.bassLayer?.octave ?? 0);
|
|
20629
|
+
const bassLayer = {
|
|
20630
|
+
index: 5,
|
|
20631
|
+
notes: bassOctave === 0 ? [] : bassNotes,
|
|
20632
|
+
octave: bassOctave,
|
|
20633
|
+
volume: 58,
|
|
20634
|
+
slot: "bass"
|
|
20635
|
+
};
|
|
20636
|
+
const padNotes = onlyIn(song.pad, plan.padSections);
|
|
20637
|
+
const layers = [
|
|
20638
|
+
{ index: 0, notes: song.melody, octave: 0, volume: 104, slot: "melody" },
|
|
20639
|
+
leadLayer,
|
|
20640
|
+
{ index: 2, notes: song.harmony, octave: 0, volume: 82 },
|
|
20641
|
+
{
|
|
20642
|
+
index: 3,
|
|
20643
|
+
notes: song.submelody,
|
|
20644
|
+
octave: 0,
|
|
20645
|
+
volume: 86,
|
|
20646
|
+
slot: "submelody"
|
|
20647
|
+
},
|
|
20648
|
+
{ index: 4, notes: song.bass, octave: 0, volume: 92, slot: "bass" },
|
|
20649
|
+
bassLayer,
|
|
20650
|
+
// **パッドは伴奏用の楽器で、伴奏より1.5オクターブ高いところを鳴らす。**
|
|
20651
|
+
// そのまま置くとナイロンギターで10半音、カリンバで9半音、尺八で7半音ぶん
|
|
20652
|
+
// 音域を突き抜ける。楽器に合わせて下げる。
|
|
20653
|
+
{
|
|
20654
|
+
index: 6,
|
|
20655
|
+
notes: padNotes,
|
|
20656
|
+
octave: fit(padNotes, "chord", 0),
|
|
20657
|
+
volume: 64,
|
|
20658
|
+
slot: "chord"
|
|
20659
|
+
}
|
|
20660
|
+
];
|
|
20661
|
+
const backingVolumes = [62, 54, 50];
|
|
20662
|
+
for (let i2 = 0; i2 < 3; i2++) {
|
|
20663
|
+
const layer = plan.backing[i2];
|
|
20664
|
+
layers.push({
|
|
20665
|
+
index: 7 + i2,
|
|
20666
|
+
notes: layer ? onlyIn(chordNotes(layer.pattern), layer.sections) : [],
|
|
20667
|
+
octave: layer?.octave ?? 0,
|
|
20668
|
+
volume: backingVolumes[i2],
|
|
20669
|
+
slot: "chord"
|
|
20670
|
+
});
|
|
20671
|
+
}
|
|
20672
|
+
const sparkleNotes = plan.sparkle ? onlyIn(chordNotes(plan.sparkle.pattern, -14), plan.sparkle.sections) : [];
|
|
20673
|
+
layers.push(
|
|
20674
|
+
{
|
|
20675
|
+
index: 10,
|
|
20676
|
+
notes: sparkleNotes,
|
|
20677
|
+
octave: fit(sparkleNotes, "chord", plan.sparkle?.octave ?? 0),
|
|
20678
|
+
volume: 56,
|
|
20679
|
+
slot: "chord"
|
|
20680
|
+
},
|
|
20681
|
+
// 掛け合い(デュエット)の相手。**歌入り作曲のときだけ**中身が入る。
|
|
20682
|
+
{ index: 11, notes: [], octave: 0, volume: 104, slot: "melody" },
|
|
20683
|
+
// 2声目のハモリ(主旋律を上下から挟む3声)と、主旋律のオクターブ下の重ね。
|
|
20684
|
+
// どちらも曲ごとに出るかどうかが決まる(`song.vocal`)。
|
|
20685
|
+
{ index: 12, notes: song.harmony2, octave: 0, volume: 74 },
|
|
20686
|
+
{ index: 13, notes: song.octave, octave: -1, volume: 56, slot: "melody" },
|
|
20687
|
+
// **間奏のソロ。** 音が入るのは間奏の小節だけなので、この1本だけを
|
|
20688
|
+
// 別の楽器にしても他のセクションの鳴りは変わらない。歌の音域をそのまま
|
|
20689
|
+
// 渡すと管楽器が上へ抜ける(テナーサックスで10半音)ので、ここも合わせる。
|
|
20690
|
+
{
|
|
20691
|
+
index: 14,
|
|
20692
|
+
notes: song.solo,
|
|
20693
|
+
octave: fit(song.solo, "solo", 0),
|
|
20694
|
+
volume: 100,
|
|
20695
|
+
slot: "solo"
|
|
20696
|
+
}
|
|
20697
|
+
);
|
|
20698
|
+
return layers;
|
|
20699
|
+
};
|
|
18772
20700
|
var LYRIC_MODEL_CATEGORIES = [
|
|
18773
20701
|
{
|
|
18774
20702
|
label: "kusa\u30D7\u30EA\u30BB\u30C3\u30C8",
|
|
@@ -18924,7 +20852,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
18924
20852
|
showChord,
|
|
18925
20853
|
showMidiSearch,
|
|
18926
20854
|
// 「作曲」は simple では役割固定の4トラックへ、advanced では15トラックへ
|
|
18927
|
-
// 編曲を展開する({@link
|
|
20855
|
+
// 編曲を展開する({@link buildAdvancedLayers})。どちらでも出す。
|
|
18928
20856
|
showCompose: true
|
|
18929
20857
|
});
|
|
18930
20858
|
refs.masterVolume.value = String(options.masterVolume ?? 50);
|
|
@@ -19047,6 +20975,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
19047
20975
|
let currentDrumPattern = refs.drumSelect.value;
|
|
19048
20976
|
const recentComposeFingerprints = [];
|
|
19049
20977
|
let autoComposeVocal = null;
|
|
20978
|
+
const autoComposeVocalTracks = /* @__PURE__ */ new Map();
|
|
19050
20979
|
let currentDrumFont = options.drumFont ?? "FluidR3_GM_sf2_file:0";
|
|
19051
20980
|
refs.drumFontSelect.value = currentDrumFont;
|
|
19052
20981
|
const applyDrumPatternFont = (name) => {
|
|
@@ -19117,6 +21046,14 @@ var mountDAW = (target, options = {}) => {
|
|
|
19117
21046
|
while (customVocalsMap.has(`custom${n}`)) n++;
|
|
19118
21047
|
return `custom${n}`;
|
|
19119
21048
|
};
|
|
21049
|
+
const getVocalIconSrc = (lyricModel) => {
|
|
21050
|
+
if (!lyricModel) return void 0;
|
|
21051
|
+
const customDef = customVocalsMap.get(lyricModel);
|
|
21052
|
+
if (customDef !== void 0)
|
|
21053
|
+
return customDef.iconUrl || FALLBACK_VOCAL_ICON;
|
|
21054
|
+
const imgKey = VOICE_IMAGE_KEY[lyricModel.toLowerCase()];
|
|
21055
|
+
return imgKey ? VOICE_IMAGES[imgKey] : void 0;
|
|
21056
|
+
};
|
|
19120
21057
|
let selectedNotes = [];
|
|
19121
21058
|
let selectionRect = null;
|
|
19122
21059
|
let copiedNotes = [];
|
|
@@ -19250,6 +21187,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
19250
21187
|
vocalTension: t1?.vocalTension ?? 50,
|
|
19251
21188
|
vocalOctaveUnison: t1?.vocalOctaveUnison ?? "none",
|
|
19252
21189
|
trackInstrument: t1?.trackInstrument ?? "",
|
|
21190
|
+
composeSlot: null,
|
|
19253
21191
|
trackCompression: t1?.trackCompression ?? 0,
|
|
19254
21192
|
trackWidth: t1?.trackWidth ?? 100,
|
|
19255
21193
|
trackReverbSend: t1?.trackReverbSend ?? 0,
|
|
@@ -20301,25 +22239,38 @@ var mountDAW = (target, options = {}) => {
|
|
|
20301
22239
|
refs.undoBtn.disabled = !core.canUndo();
|
|
20302
22240
|
refs.redoBtn.disabled = !core.canRedo();
|
|
20303
22241
|
};
|
|
20304
|
-
const
|
|
22242
|
+
const updateTrackTabs = () => {
|
|
20305
22243
|
refs.trackTabs.innerHTML = "";
|
|
20306
22244
|
trackPillEls.clear();
|
|
20307
22245
|
for (const [i2, t] of trackStates.entries()) {
|
|
20308
22246
|
const [r, g, b] = t.config.color;
|
|
20309
22247
|
const isActive = t.config.id === activeTrackId;
|
|
20310
22248
|
const btn = document.createElement("button");
|
|
20311
|
-
|
|
22249
|
+
const vocalIconSrc = getVocalIconSrc(t.lyricModel);
|
|
22250
|
+
btn.className = `dtm-pill ${isActive ? "dtm-pill--active" : ""} ${vocalIconSrc ? "dtm-pill--vocal" : ""}`;
|
|
20312
22251
|
btn.style.setProperty("--dtm-pill-color", `rgb(${r},${g},${b})`);
|
|
22252
|
+
if (vocalIconSrc) {
|
|
22253
|
+
btn.style.setProperty(
|
|
22254
|
+
"--dtm-pill-icon",
|
|
22255
|
+
`url(${JSON.stringify(vocalIconSrc)})`
|
|
22256
|
+
);
|
|
22257
|
+
}
|
|
20313
22258
|
btn.title = `Track ${i2 + 1}: ${t.config.name}`;
|
|
20314
22259
|
btn.setAttribute(
|
|
20315
22260
|
"aria-label",
|
|
20316
|
-
`Track ${i2 + 1}: ${t.config.name}${isActive ? " (\u9078\u629E\u4E2D)" : ""}`
|
|
22261
|
+
`Track ${i2 + 1}: ${t.config.name}${isActive ? " (\u9078\u629E\u4E2D)" : ""}${vocalIconSrc ? "\uFF08\u30DC\u30FC\u30AB\u30EB\u9078\u629E\u4E2D\uFF09" : ""}`
|
|
20317
22262
|
);
|
|
20318
|
-
|
|
22263
|
+
const labelEl = document.createElement("span");
|
|
22264
|
+
labelEl.className = "dtm-pill__label";
|
|
22265
|
+
labelEl.textContent = String(i2 + 1);
|
|
22266
|
+
btn.appendChild(labelEl);
|
|
20319
22267
|
btn.addEventListener("click", () => switchTrack(t.config.id));
|
|
20320
22268
|
refs.trackTabs.appendChild(btn);
|
|
20321
22269
|
trackPillEls.set(t.config.id, btn);
|
|
20322
22270
|
}
|
|
22271
|
+
};
|
|
22272
|
+
const updateTrackPanel = () => {
|
|
22273
|
+
updateTrackTabs();
|
|
20323
22274
|
const active = getActive();
|
|
20324
22275
|
const activeIndex = trackStates.findIndex(
|
|
20325
22276
|
(t) => t.config.id === activeTrackId
|
|
@@ -20636,6 +22587,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
20636
22587
|
syncInstDisabled();
|
|
20637
22588
|
instSel.addEventListener("change", () => {
|
|
20638
22589
|
active.trackInstrument = instSel.value;
|
|
22590
|
+
active.composeSlot = null;
|
|
20639
22591
|
const trackIndex = trackStates.indexOf(active);
|
|
20640
22592
|
options.onTrackInstrumentChange?.(trackIndex, active.trackInstrument);
|
|
20641
22593
|
persistTrack1(active);
|
|
@@ -21039,6 +22991,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
21039
22991
|
redrawAll();
|
|
21040
22992
|
fireLyricsChange(active);
|
|
21041
22993
|
reloadVoicesForModel(active.lyricModel);
|
|
22994
|
+
updateTrackTabs();
|
|
21042
22995
|
});
|
|
21043
22996
|
lyricCustomGuide.addEventListener("click", () => {
|
|
21044
22997
|
showModal("\u30AB\u30B9\u30BF\u30E0\u97F3\u58F0(.koe)\u306E\u4F7F\u3044\u65B9", KOE_INFO_HTML);
|
|
@@ -21572,6 +23525,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
21572
23525
|
}
|
|
21573
23526
|
trackStates.forEach((t, i2) => {
|
|
21574
23527
|
if (applyActiveOnly && i2 !== activeTrackIndex) return;
|
|
23528
|
+
t.composeSlot = null;
|
|
21575
23529
|
const name = normalizeInstrumentName(meta.trackInstruments?.[i2] ?? "");
|
|
21576
23530
|
if (t.trackInstrument !== name) {
|
|
21577
23531
|
t.trackInstrument = name;
|
|
@@ -21814,16 +23768,32 @@ var mountDAW = (target, options = {}) => {
|
|
|
21814
23768
|
updateTrackPanel();
|
|
21815
23769
|
updateUndoRedo();
|
|
21816
23770
|
};
|
|
21817
|
-
const exportMIDI2 = () =>
|
|
21818
|
-
|
|
21819
|
-
|
|
21820
|
-
|
|
21821
|
-
|
|
21822
|
-
|
|
21823
|
-
|
|
21824
|
-
|
|
21825
|
-
|
|
21826
|
-
|
|
23771
|
+
const exportMIDI2 = () => {
|
|
23772
|
+
const autoPreset = INSTRUMENT_PRESETS[currentInstrument] ?? INSTRUMENT_PRESETS.piano;
|
|
23773
|
+
return exportMIDI({
|
|
23774
|
+
tracks: trackStates.map((t) => {
|
|
23775
|
+
let program;
|
|
23776
|
+
if (t.trackInstrument) {
|
|
23777
|
+
const p = programOfInstrumentName(t.trackInstrument);
|
|
23778
|
+
if (p !== null) program = p;
|
|
23779
|
+
} else if (!t.lyricModel) {
|
|
23780
|
+
const role = t.composeSlot ?? DECLARED_ROLE[t.config.id] ?? "melody";
|
|
23781
|
+
const instName = autoPreset[role] ?? autoPreset.melody;
|
|
23782
|
+
const p = programOfInstrumentName(instName);
|
|
23783
|
+
if (p !== null) program = p;
|
|
23784
|
+
}
|
|
23785
|
+
return {
|
|
23786
|
+
notes: playableNotes(t),
|
|
23787
|
+
volume: t.volume,
|
|
23788
|
+
program
|
|
23789
|
+
};
|
|
23790
|
+
}),
|
|
23791
|
+
getDrumPattern: (currentBar) => resolveDrumPattern(currentDrumPattern, drumPatterns, currentBar),
|
|
23792
|
+
drumVolume,
|
|
23793
|
+
bpm,
|
|
23794
|
+
stepsPerBar: renderConfig.stepsPerBar
|
|
23795
|
+
});
|
|
23796
|
+
};
|
|
21827
23797
|
const setBpm = (value) => {
|
|
21828
23798
|
bpm = value;
|
|
21829
23799
|
refs.bpmInput.value = String(value);
|
|
@@ -22176,7 +24146,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
22176
24146
|
if (!stats) continue;
|
|
22177
24147
|
const role = DECLARED_ROLE[t.config.id] ?? classifyTrackRole(stats, t.config.id === topSingleVoiceId);
|
|
22178
24148
|
roleByTrackId.set(t.config.id, role);
|
|
22179
|
-
const instName = autoPreset[role];
|
|
24149
|
+
const instName = autoPreset[t.composeSlot ?? role] ?? autoPreset[role];
|
|
22180
24150
|
t.trackInstrument = instName;
|
|
22181
24151
|
const trackIndex = trackStates.indexOf(t);
|
|
22182
24152
|
options.onTrackInstrumentChange?.(trackIndex, instName);
|
|
@@ -22327,6 +24297,15 @@ var mountDAW = (target, options = {}) => {
|
|
|
22327
24297
|
refs.composeKey.value = savedKey;
|
|
22328
24298
|
}
|
|
22329
24299
|
}
|
|
24300
|
+
const savedScale = readMacroSetting("scale");
|
|
24301
|
+
if (savedScale && refs.composeScale) {
|
|
24302
|
+
const hasOption = Array.from(refs.composeScale.options).some(
|
|
24303
|
+
(opt) => opt.value === savedScale
|
|
24304
|
+
);
|
|
24305
|
+
if (hasOption) {
|
|
24306
|
+
refs.composeScale.value = savedScale;
|
|
24307
|
+
}
|
|
24308
|
+
}
|
|
22330
24309
|
const savedShift = readMacroSetting("shift");
|
|
22331
24310
|
if (savedShift && refs.shiftSelect) {
|
|
22332
24311
|
const hasOption = Array.from(refs.shiftSelect.options).some(
|
|
@@ -22389,6 +24368,20 @@ var mountDAW = (target, options = {}) => {
|
|
|
22389
24368
|
});
|
|
22390
24369
|
updateComposeKeyHint();
|
|
22391
24370
|
}
|
|
24371
|
+
const updateComposeScaleHint = () => {
|
|
24372
|
+
if (!refs.composeScale || !refs.composeScaleHint) return;
|
|
24373
|
+
const desc = getComposeScaleDescription(refs.composeScale.value);
|
|
24374
|
+
refs.composeScaleHint.textContent = desc;
|
|
24375
|
+
refs.composeScaleHint.title = desc;
|
|
24376
|
+
};
|
|
24377
|
+
const composeScale = refs.composeScale;
|
|
24378
|
+
if (composeScale) {
|
|
24379
|
+
composeScale.addEventListener("change", () => {
|
|
24380
|
+
writeMacroSetting("scale", composeScale.value);
|
|
24381
|
+
updateComposeScaleHint();
|
|
24382
|
+
});
|
|
24383
|
+
updateComposeScaleHint();
|
|
24384
|
+
}
|
|
22392
24385
|
if (refs.shiftSelect) {
|
|
22393
24386
|
refs.shiftSelect.addEventListener("change", () => {
|
|
22394
24387
|
writeMacroSetting("shift", refs.shiftSelect.value);
|
|
@@ -22409,6 +24402,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
22409
24402
|
sections: selectedComposeSections(),
|
|
22410
24403
|
template: tmpl,
|
|
22411
24404
|
baseKey: refs.composeKey?.value ?? "any",
|
|
24405
|
+
scale: refs.composeScale?.value ?? "auto",
|
|
22412
24406
|
// 直近に作った曲の特徴を渡すと、それらから離れた候補に加点される。
|
|
22413
24407
|
// 「作曲」を続けて押したときに似た曲が並ぶのを防ぐ。
|
|
22414
24408
|
recent: recentComposeFingerprints
|
|
@@ -22442,45 +24436,39 @@ var mountDAW = (target, options = {}) => {
|
|
|
22442
24436
|
}
|
|
22443
24437
|
track.core.endBatch();
|
|
22444
24438
|
};
|
|
24439
|
+
const shouldAutoInstrument = !currentInstrument || currentInstrument === "auto" || currentInstrument === autoComposeInstrument;
|
|
24440
|
+
if (shouldAutoInstrument && song.instrument) {
|
|
24441
|
+
currentInstrument = song.instrument;
|
|
24442
|
+
autoComposeInstrument = song.instrument;
|
|
24443
|
+
options.onInstrumentChange?.(song.instrument);
|
|
24444
|
+
}
|
|
22445
24445
|
if (isAdvanced) {
|
|
22446
|
-
|
|
24446
|
+
const layers = buildAdvancedLayers(song, {
|
|
24447
|
+
edo: renderConfig.edo,
|
|
24448
|
+
stepsPerBar: renderConfig.stepsPerBar,
|
|
24449
|
+
preset: INSTRUMENT_PRESETS[currentInstrument] ?? INSTRUMENT_PRESETS.piano
|
|
24450
|
+
});
|
|
24451
|
+
for (const layer of layers) {
|
|
22447
24452
|
const track = trackStates[layer.index];
|
|
22448
24453
|
if (!track) continue;
|
|
22449
|
-
|
|
22450
|
-
edo: renderConfig.edo,
|
|
22451
|
-
chordStr: song.chordProgression,
|
|
22452
|
-
patternType: "arpeggio",
|
|
22453
|
-
rootShift: song.rootShift,
|
|
22454
|
-
bpm: song.bpm,
|
|
22455
|
-
stepsPerBar: renderConfig.stepsPerBar
|
|
22456
|
-
}).map((p) => ({
|
|
22457
|
-
startStep: p.startStep,
|
|
22458
|
-
pitchUnits: p.pitchUnits,
|
|
22459
|
-
durationSteps: p.durationSteps,
|
|
22460
|
-
velocity: Math.max(30, p.velocity - 14)
|
|
22461
|
-
})) : buildChordPlacements({
|
|
22462
|
-
edo: renderConfig.edo,
|
|
22463
|
-
chordStr: song.chordProgression,
|
|
22464
|
-
patternType: layer.part,
|
|
22465
|
-
rootShift: song.rootShift,
|
|
22466
|
-
bpm: song.bpm,
|
|
22467
|
-
stepsPerBar: renderConfig.stepsPerBar
|
|
22468
|
-
}).map((p) => ({
|
|
22469
|
-
startStep: p.startStep,
|
|
22470
|
-
pitchUnits: p.pitchUnits,
|
|
22471
|
-
durationSteps: p.durationSteps,
|
|
22472
|
-
velocity: p.velocity
|
|
22473
|
-
}));
|
|
22474
|
-
writeTrackAt(layer.index, notes);
|
|
24454
|
+
writeTrackAt(layer.index, layer.notes);
|
|
22475
24455
|
track.trackOctave = layer.octave;
|
|
22476
24456
|
track.volume = layer.volume;
|
|
22477
24457
|
track.core.setVolume(layer.volume);
|
|
24458
|
+
track.composeSlot = layer.notes.length > 0 ? layer.slot ?? null : null;
|
|
24459
|
+
if (layer.notes.length === 0 && track.trackInstrument) {
|
|
24460
|
+
track.trackInstrument = "";
|
|
24461
|
+
options.onTrackInstrumentChange?.(layer.index, "");
|
|
24462
|
+
}
|
|
22478
24463
|
}
|
|
22479
24464
|
for (let i2 = 0; i2 < trackStates.length; i2++) {
|
|
22480
|
-
if (
|
|
24465
|
+
if (layers.some((l) => l.index === i2)) continue;
|
|
22481
24466
|
writeTrackAt(i2, []);
|
|
24467
|
+
const t = trackStates[i2];
|
|
24468
|
+
if (t) t.composeSlot = null;
|
|
22482
24469
|
}
|
|
22483
24470
|
} else {
|
|
24471
|
+
for (const t of trackStates) t.composeSlot = null;
|
|
22484
24472
|
writeTrack("melody", song.melody);
|
|
22485
24473
|
writeTrack("submelody", song.submelody);
|
|
22486
24474
|
writeTrack("bass", song.bass);
|
|
@@ -22497,13 +24485,8 @@ var mountDAW = (target, options = {}) => {
|
|
|
22497
24485
|
refs.drumSelect.value = song.drum;
|
|
22498
24486
|
options.onDrumChange?.(song.drum);
|
|
22499
24487
|
applyDrumPatternFont(song.drum);
|
|
22500
|
-
const shouldAutoInstrument = !currentInstrument || currentInstrument === "auto" || currentInstrument === autoComposeInstrument;
|
|
22501
|
-
if (shouldAutoInstrument && song.instrument) {
|
|
22502
|
-
currentInstrument = song.instrument;
|
|
22503
|
-
autoComposeInstrument = song.instrument;
|
|
22504
|
-
options.onInstrumentChange?.(song.instrument);
|
|
22505
|
-
}
|
|
22506
24488
|
if (withVocal) {
|
|
24489
|
+
autoComposeVocalTracks.clear();
|
|
22507
24490
|
const melodyTrack = isAdvanced ? trackStates[0] : trackStates.find((t) => t.config.id === "melody");
|
|
22508
24491
|
if (melodyTrack) {
|
|
22509
24492
|
const current = melodyTrack.lyricModel.trim();
|
|
@@ -22513,12 +24496,85 @@ var mountDAW = (target, options = {}) => {
|
|
|
22513
24496
|
}
|
|
22514
24497
|
melodyTrack.lyricModel = pickComposeVocal(autoComposeVocal);
|
|
22515
24498
|
autoComposeVocal = melodyTrack.lyricModel;
|
|
24499
|
+
autoComposeVocalTracks.set(melodyTrack, melodyTrack.lyricModel);
|
|
22516
24500
|
}
|
|
22517
24501
|
melodyTrack.lyrics = composeLyrics(song.melody, {
|
|
22518
24502
|
stepsPerBar: renderConfig.stepsPerBar
|
|
22519
24503
|
});
|
|
22520
24504
|
fireLyricsChange(melodyTrack);
|
|
22521
24505
|
}
|
|
24506
|
+
if (isAdvanced && melodyTrack) {
|
|
24507
|
+
const stepsPerBar = renderConfig.stepsPerBar;
|
|
24508
|
+
const spans = song.vocal.duetSpans;
|
|
24509
|
+
const inDuet = (n) => spans.some(([a, b]) => n.startStep >= a && n.startStep < b);
|
|
24510
|
+
const sing = (track, lyrics, voice) => {
|
|
24511
|
+
if (!track) return;
|
|
24512
|
+
track.lyricModel = voice;
|
|
24513
|
+
autoComposeVocalTracks.set(track, voice);
|
|
24514
|
+
if (track.vocalOctave === 0) track.vocalOctave = -1;
|
|
24515
|
+
track.lyrics = lyrics;
|
|
24516
|
+
fireLyricsChange(track);
|
|
24517
|
+
};
|
|
24518
|
+
const partnerVoice = pickComposeVocal(melodyTrack.lyricModel);
|
|
24519
|
+
const duetting = spans.length > 0;
|
|
24520
|
+
if (duetting) {
|
|
24521
|
+
const mine = song.melody.filter((n) => !inDuet(n));
|
|
24522
|
+
const yours = song.melody.filter((n) => inDuet(n));
|
|
24523
|
+
writeTrackAt(0, mine);
|
|
24524
|
+
writeTrackAt(11, yours);
|
|
24525
|
+
const full = melodyTrack.lyrics;
|
|
24526
|
+
sing(
|
|
24527
|
+
melodyTrack,
|
|
24528
|
+
alignLyrics(song.melody, full, mine, { stepsPerBar }),
|
|
24529
|
+
melodyTrack.lyricModel
|
|
24530
|
+
);
|
|
24531
|
+
sing(
|
|
24532
|
+
trackStates[11],
|
|
24533
|
+
alignLyrics(song.melody, full, yours, { stepsPerBar }),
|
|
24534
|
+
partnerVoice
|
|
24535
|
+
);
|
|
24536
|
+
}
|
|
24537
|
+
const harmonyTrack = trackStates[2];
|
|
24538
|
+
if (song.harmony.length > 0 && harmonyTrack) {
|
|
24539
|
+
sing(
|
|
24540
|
+
harmonyTrack,
|
|
24541
|
+
alignLyrics(song.melody, melodyTrack.lyrics, song.harmony, {
|
|
24542
|
+
stepsPerBar
|
|
24543
|
+
}),
|
|
24544
|
+
duetting ? partnerVoice : melodyTrack.lyricModel
|
|
24545
|
+
);
|
|
24546
|
+
}
|
|
24547
|
+
if (!duetting) {
|
|
24548
|
+
if (song.harmony2.length > 0)
|
|
24549
|
+
sing(
|
|
24550
|
+
trackStates[12],
|
|
24551
|
+
alignLyrics(song.melody, melodyTrack.lyrics, song.harmony2, {
|
|
24552
|
+
stepsPerBar
|
|
24553
|
+
}),
|
|
24554
|
+
melodyTrack.lyricModel
|
|
24555
|
+
);
|
|
24556
|
+
const octaveTrack = trackStates[13];
|
|
24557
|
+
if (song.octave.length > 0 && octaveTrack) {
|
|
24558
|
+
sing(
|
|
24559
|
+
octaveTrack,
|
|
24560
|
+
alignLyrics(song.melody, melodyTrack.lyrics, song.octave, {
|
|
24561
|
+
stepsPerBar
|
|
24562
|
+
}),
|
|
24563
|
+
melodyTrack.lyricModel
|
|
24564
|
+
);
|
|
24565
|
+
octaveTrack.vocalOctave = -2;
|
|
24566
|
+
}
|
|
24567
|
+
}
|
|
24568
|
+
}
|
|
24569
|
+
} else {
|
|
24570
|
+
for (const [track, voice] of autoComposeVocalTracks) {
|
|
24571
|
+
if (track.lyricModel === voice) {
|
|
24572
|
+
track.lyrics = "";
|
|
24573
|
+
track.lyricModel = "";
|
|
24574
|
+
fireLyricsChange(track);
|
|
24575
|
+
}
|
|
24576
|
+
}
|
|
24577
|
+
autoComposeVocalTracks.clear();
|
|
22522
24578
|
}
|
|
22523
24579
|
applyAutoMastering();
|
|
22524
24580
|
if (refs.composeKeyHint) {
|
|
@@ -23665,6 +25721,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
23665
25721
|
if (!t) return;
|
|
23666
25722
|
const name = normalizeInstrumentName(instrumentName);
|
|
23667
25723
|
t.trackInstrument = name;
|
|
25724
|
+
t.composeSlot = null;
|
|
23668
25725
|
if (t.config.id === activeTrackId) updateTrackPanel();
|
|
23669
25726
|
},
|
|
23670
25727
|
noteToCanvas: (step, pitch) => {
|
|
@@ -25932,10 +27989,13 @@ var createDtmStudio = async (options = {}) => {
|
|
|
25932
27989
|
export {
|
|
25933
27990
|
A4_HZ,
|
|
25934
27991
|
A4_UNITS,
|
|
27992
|
+
BLUES_SCALE,
|
|
25935
27993
|
BREATH_MARK,
|
|
25936
27994
|
CENTS_PER_UNIT,
|
|
25937
27995
|
COMPOSE_KEYS,
|
|
25938
27996
|
COMPOSE_MOOD_GROUPS,
|
|
27997
|
+
COMPOSE_SCALES,
|
|
27998
|
+
COMPOSE_SCALE_IDS,
|
|
25939
27999
|
CORPUS_BANDS,
|
|
25940
28000
|
CORPUS_SIZE,
|
|
25941
28001
|
DAW_CSS,
|
|
@@ -25955,7 +28015,11 @@ export {
|
|
|
25955
28015
|
FADE_IN_MARK,
|
|
25956
28016
|
FADE_OUT_MARK,
|
|
25957
28017
|
GLOBAL_STORAGE_KEYS,
|
|
28018
|
+
GM_BRIGHT_CEILING,
|
|
25958
28019
|
GM_INSTRUMENT_NAMES,
|
|
28020
|
+
GM_INSTRUMENT_RANGE,
|
|
28021
|
+
HARMONIC_MINOR_SCALE,
|
|
28022
|
+
HUNGARIAN_SCALE,
|
|
25959
28023
|
INSTRUMENT_PRESETS,
|
|
25960
28024
|
KEY_COUNT,
|
|
25961
28025
|
KOE_BASE_URL,
|
|
@@ -25965,6 +28029,7 @@ export {
|
|
|
25965
28029
|
LinkedList,
|
|
25966
28030
|
MACRO_STORAGE_KEYS,
|
|
25967
28031
|
MAJOR_KEY_IDS,
|
|
28032
|
+
MAJOR_SCALE2 as MAJOR_SCALE,
|
|
25968
28033
|
MAX_VOCAL_VOLUME,
|
|
25969
28034
|
MICRO_STEP,
|
|
25970
28035
|
MINOR_KEY_IDS,
|
|
@@ -26033,10 +28098,12 @@ export {
|
|
|
26033
28098
|
featureVector,
|
|
26034
28099
|
fifthToStep,
|
|
26035
28100
|
fifthToUnits,
|
|
28101
|
+
fitInstrumentOctave,
|
|
26036
28102
|
formatMmlMeta,
|
|
26037
28103
|
freqFromPitch,
|
|
26038
28104
|
generateRandomPattern,
|
|
26039
28105
|
getComposeKeyDescription,
|
|
28106
|
+
getComposeScaleDescription,
|
|
26040
28107
|
getDrumPatternKeys,
|
|
26041
28108
|
getMidiBPM,
|
|
26042
28109
|
icon,
|
|
@@ -26066,14 +28133,19 @@ export {
|
|
|
26066
28133
|
playNote,
|
|
26067
28134
|
playPlacements,
|
|
26068
28135
|
playSingingMML,
|
|
28136
|
+
programOfInstrumentName,
|
|
26069
28137
|
readGlobalBool,
|
|
26070
28138
|
readGlobalNumber,
|
|
26071
28139
|
readGlobalSetting,
|
|
26072
28140
|
readMacroSections,
|
|
26073
28141
|
readMacroSetting,
|
|
28142
|
+
resolveCenter,
|
|
26074
28143
|
resolveComposeKey,
|
|
28144
|
+
resolveComposeScale,
|
|
26075
28145
|
resolveDrumPattern,
|
|
26076
28146
|
resolveLoopPoint,
|
|
28147
|
+
scaleDegrees,
|
|
28148
|
+
scaleSize,
|
|
26077
28149
|
semitonesToUnits,
|
|
26078
28150
|
shiftNotes,
|
|
26079
28151
|
showLoadingOverlay,
|