@onjmin/dtm 2.1.6 → 2.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +131 -133
- package/dist/index.d.ts +131 -133
- package/dist/index.js +1275 -221
- package/dist/index.mjs +1274 -221
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -156,6 +156,7 @@ __export(index_exports, {
|
|
|
156
156
|
playNote: () => playNote,
|
|
157
157
|
playPlacements: () => playPlacements,
|
|
158
158
|
playSingingMML: () => playSingingMML,
|
|
159
|
+
programOfInstrumentName: () => programOfInstrumentName,
|
|
159
160
|
readGlobalBool: () => readGlobalBool,
|
|
160
161
|
readGlobalNumber: () => readGlobalNumber,
|
|
161
162
|
readGlobalSetting: () => readGlobalSetting,
|
|
@@ -339,6 +340,14 @@ async function buildNameToKeyMapping() {
|
|
|
339
340
|
return nameToKey;
|
|
340
341
|
}
|
|
341
342
|
var GM_INSTRUMENT_NAMES = FONT_NAME_SURIKOV.trim().split("\n").map((line) => line.slice(line.indexOf(" ") + 1));
|
|
343
|
+
var programOfInstrumentName = (name) => {
|
|
344
|
+
if (!name) return null;
|
|
345
|
+
const stripped = name.replace(/\s+/g, "").toLowerCase();
|
|
346
|
+
const idx = GM_INSTRUMENT_NAMES.findIndex(
|
|
347
|
+
(n) => n.replace(/\s+/g, "").toLowerCase() === stripped
|
|
348
|
+
);
|
|
349
|
+
return idx >= 0 ? idx : null;
|
|
350
|
+
};
|
|
342
351
|
|
|
343
352
|
// node_modules/.pnpm/@onjmin+chord-parser@1.1.1/node_modules/@onjmin/chord-parser/dist/index.mjs
|
|
344
353
|
var SHARP_NAMES = [
|
|
@@ -12702,44 +12711,365 @@ var mountChordPlayer = (target, chords, options = {}) => {
|
|
|
12702
12711
|
// src/compose-corpus.ts
|
|
12703
12712
|
var CORPUS_SIZE = 91;
|
|
12704
12713
|
var CORPUS_BANDS = {
|
|
12705
|
-
entropy: [0.
|
|
12706
|
-
valueKinds: [2, 3,
|
|
12707
|
-
restRatio: [
|
|
12708
|
-
leapRatio: [0.
|
|
12709
|
-
stepRatio: [0.
|
|
12710
|
-
chromaticRatio: [0, 0.
|
|
12711
|
-
maxLeap: [
|
|
12712
|
-
melodyRange: [
|
|
12713
|
-
notesPerBar: [
|
|
12714
|
-
shortNoteRatio: [0.
|
|
12715
|
-
|
|
12716
|
-
|
|
12717
|
-
|
|
12718
|
-
|
|
12719
|
-
|
|
12720
|
-
|
|
12721
|
-
|
|
12722
|
-
|
|
12714
|
+
entropy: [0.25, 0.711, 1.237, 1.754],
|
|
12715
|
+
valueKinds: [2, 3, 6, 7],
|
|
12716
|
+
restRatio: [0.016, 0.091, 0.223, 0.464],
|
|
12717
|
+
leapRatio: [0.202, 0.28, 0.412, 0.71],
|
|
12718
|
+
stepRatio: [0.188, 0.438, 0.617, 0.693],
|
|
12719
|
+
chromaticRatio: [0, 0.017, 0.121, 0.242],
|
|
12720
|
+
maxLeap: [5, 8, 12, 16],
|
|
12721
|
+
melodyRange: [8, 17, 22, 28],
|
|
12722
|
+
notesPerBar: [2.743, 4.77, 6.473, 11.995],
|
|
12723
|
+
shortNoteRatio: [0.055, 0.753, 0.91, 1],
|
|
12724
|
+
barDensityCv: [0.148, 0.206, 0.328, 0.451],
|
|
12725
|
+
densityCliff: [0, 0, 0.043, 0.125],
|
|
12726
|
+
sim1: [0.345, 0.465, 0.598, 0.803],
|
|
12727
|
+
sim2: [0.389, 0.5, 0.647, 0.845],
|
|
12728
|
+
sim4: [0.437, 0.549, 0.723, 0.882],
|
|
12729
|
+
sim8: [0.063, 0.561, 0.771, 0.972],
|
|
12730
|
+
phraseBreath: [0, 0.115, 0.323, 0.884],
|
|
12731
|
+
turnRatio: [0.4, 0.478, 0.556, 0.769],
|
|
12732
|
+
climaxPosition: [0.016, 0.14, 0.655, 0.92],
|
|
12733
|
+
climaxPeaks: [1, 2, 13.5, 26],
|
|
12734
|
+
complementarity: [0, 0.026, 0.179, 0.405]
|
|
12723
12735
|
};
|
|
12724
12736
|
var CORPUS_MEDIANS = {
|
|
12725
|
-
entropy: 0.
|
|
12737
|
+
entropy: 0.907,
|
|
12726
12738
|
valueKinds: 4,
|
|
12727
|
-
restRatio: 0.
|
|
12728
|
-
leapRatio: 0.
|
|
12729
|
-
stepRatio: 0.
|
|
12730
|
-
chromaticRatio: 0.
|
|
12739
|
+
restRatio: 0.149,
|
|
12740
|
+
leapRatio: 0.339,
|
|
12741
|
+
stepRatio: 0.538,
|
|
12742
|
+
chromaticRatio: 0.052,
|
|
12731
12743
|
maxLeap: 12,
|
|
12732
|
-
melodyRange:
|
|
12733
|
-
notesPerBar: 5.
|
|
12734
|
-
shortNoteRatio: 0.
|
|
12735
|
-
|
|
12736
|
-
|
|
12737
|
-
|
|
12738
|
-
|
|
12739
|
-
|
|
12744
|
+
melodyRange: 20,
|
|
12745
|
+
notesPerBar: 5.511,
|
|
12746
|
+
shortNoteRatio: 0.816,
|
|
12747
|
+
barDensityCv: 0.279,
|
|
12748
|
+
densityCliff: 0.026,
|
|
12749
|
+
sim1: 0.518,
|
|
12750
|
+
sim2: 0.552,
|
|
12751
|
+
sim4: 0.616,
|
|
12752
|
+
sim8: 0.676,
|
|
12753
|
+
phraseBreath: 0.227,
|
|
12754
|
+
turnRatio: 0.519,
|
|
12740
12755
|
climaxPosition: 0.273,
|
|
12741
|
-
climaxPeaks:
|
|
12742
|
-
complementarity: 0.
|
|
12756
|
+
climaxPeaks: 6,
|
|
12757
|
+
complementarity: 0.075
|
|
12758
|
+
};
|
|
12759
|
+
var CORPUS_CELL_WEIGHTS = {
|
|
12760
|
+
"0,2,4,6,8,10,12,14": 584,
|
|
12761
|
+
"0,2,4,6,8,12,14": 512,
|
|
12762
|
+
"0,4,6,8,10,12,14": 246,
|
|
12763
|
+
"0,8": 187,
|
|
12764
|
+
"0,4,8,10,12,14": 158,
|
|
12765
|
+
"0,6,8,10,12,14": 153,
|
|
12766
|
+
"2,5,10,13": 128,
|
|
12767
|
+
"0,12,14": 123,
|
|
12768
|
+
"0,4,6,8,12,14": 114,
|
|
12769
|
+
"0,4,8,12": 110,
|
|
12770
|
+
"0": 105,
|
|
12771
|
+
"0,2,4,6,8,12": 103,
|
|
12772
|
+
"0,4,8,12,14": 102,
|
|
12773
|
+
"0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15": 89,
|
|
12774
|
+
"0,2,4,6,8": 76,
|
|
12775
|
+
"0,6,8,12,14": 58,
|
|
12776
|
+
"0,6,8,14": 48,
|
|
12777
|
+
"0,4,6,8,12": 44,
|
|
12778
|
+
"0,4,8,14": 44,
|
|
12779
|
+
"0,2,4,5,6,8,9,10,12,13,14,15": 44,
|
|
12780
|
+
"2,6,10,14": 42,
|
|
12781
|
+
"0,8,12": 40,
|
|
12782
|
+
"0,2,4,6,8,10,12": 39,
|
|
12783
|
+
"0,3,9,10,11,12,13,14,15": 36,
|
|
12784
|
+
"0,3,6,8,11,14": 32,
|
|
12785
|
+
"0,2,4,6,7,9,10,12,14": 32,
|
|
12786
|
+
"0,2,4,6,10,12,14": 31,
|
|
12787
|
+
"0,10,12,14": 28,
|
|
12788
|
+
"12,14": 27,
|
|
12789
|
+
"0,2,4,6,8,14": 27,
|
|
12790
|
+
"0,6,8,12": 25,
|
|
12791
|
+
"0,4,6,8,10,12": 24,
|
|
12792
|
+
"0,1,2,4,5,6,7,8,9,10,11,12,13,14,15": 24,
|
|
12793
|
+
"2,4,6,8,10,12,14": 22,
|
|
12794
|
+
"0,6,8": 19,
|
|
12795
|
+
"0,12": 19,
|
|
12796
|
+
"8,12": 17,
|
|
12797
|
+
"0,2,4,8,12,14": 16,
|
|
12798
|
+
"0,3,5,6,7,8,11,13,14,15": 16,
|
|
12799
|
+
"0,3,4,5,6,7,8,10,12,14": 16,
|
|
12800
|
+
"0,14": 15,
|
|
12801
|
+
"0,4,8": 15,
|
|
12802
|
+
"0,4,6,8,14": 14,
|
|
12803
|
+
"0,4,6,8,10,11,12,14": 14,
|
|
12804
|
+
"2,4,6,8": 13,
|
|
12805
|
+
"0,4,6,10,12,14": 13,
|
|
12806
|
+
"0,4,6,8": 13,
|
|
12807
|
+
"0,2,4,8,9,11,14,15": 12,
|
|
12808
|
+
"0,4,8,10,11,12,14": 12,
|
|
12809
|
+
"0,2,4,6,8,9,12,14": 12,
|
|
12810
|
+
"0,3,4,6,8,12,14": 12,
|
|
12811
|
+
"0,2,4,6,8,11,14": 12,
|
|
12812
|
+
"0,2,4,5,6,7,8,9,10,11,12,14": 12,
|
|
12813
|
+
"2,4,6,8,12,14": 11,
|
|
12814
|
+
"0,2,4,8,10,12": 11,
|
|
12815
|
+
"0,1,2,3,4,5,6,7,8,9,10,11,12": 11,
|
|
12816
|
+
"0,2,4,6,8,10,11,12,14": 10,
|
|
12817
|
+
"0,4,6,7,8,14,15": 10,
|
|
12818
|
+
"0,8,10,12,14": 10,
|
|
12819
|
+
"0,3,4,6,8,10,12,14": 9,
|
|
12820
|
+
"0,2,3,4,6,8,12,14": 9,
|
|
12821
|
+
"0,2,4,5,6,8,12,14": 9,
|
|
12822
|
+
"0,3,4,6,8,9,10,11,12": 9,
|
|
12823
|
+
"0,3,4,6,8,9,10,11,12,14,15": 9,
|
|
12824
|
+
"0,3,4,6,7,8,10,12,14,15": 9,
|
|
12825
|
+
"0,2,4,5,6,7,8,9,10,12,13,14,15": 9,
|
|
12826
|
+
"0,2,4,8,10,12,14": 8,
|
|
12827
|
+
"0,2,4,6,8,10,12,14,15": 8,
|
|
12828
|
+
"1,2,3,4,5,6,7,8,9,10,11,12,13,14,15": 8,
|
|
12829
|
+
"0,3,6,8,12,14": 7,
|
|
12830
|
+
"0,1,2,3,4,5,6,7,8": 7,
|
|
12831
|
+
"0,4,8,10,12": 7,
|
|
12832
|
+
"0,2,3,4,5,6,7,8": 7,
|
|
12833
|
+
"0,3,4,6,8,12": 6,
|
|
12834
|
+
"0,2,4,6,10,14": 6,
|
|
12835
|
+
"4,12": 6,
|
|
12836
|
+
"0,6,8,10,14": 6,
|
|
12837
|
+
"0,2,3,4,5,6,7,8,9,10,11,12": 6,
|
|
12838
|
+
"0,1,2,3,4,6,7,8,10,12,14,15": 6,
|
|
12839
|
+
"0,3,6,8,12": 6,
|
|
12840
|
+
"2,4,6,8,10,11,12,14": 6,
|
|
12841
|
+
"6,8,10,12,14": 5,
|
|
12842
|
+
"2,6,8,10,12,14": 5,
|
|
12843
|
+
"0,8,12,14": 5,
|
|
12844
|
+
"0,3,4,6,8": 5,
|
|
12845
|
+
"0,8,11,14": 5,
|
|
12846
|
+
"0,3,4,6,8,10,11,12,14": 5,
|
|
12847
|
+
"0,3,6,8": 5,
|
|
12848
|
+
"0,1,4,8,9,12,13": 5,
|
|
12849
|
+
"10,12,14": 5,
|
|
12850
|
+
"0,4,6,8,10,11,12,13,14": 5,
|
|
12851
|
+
"12,13,14,15": 5,
|
|
12852
|
+
"0,2,4,7,8,14,15": 5,
|
|
12853
|
+
"0,4,8,9,10,11,12,13,14,15": 5,
|
|
12854
|
+
"0,4,7,8,14,15": 5,
|
|
12855
|
+
"0,4,8,9,10,11,12": 5,
|
|
12856
|
+
"0,2,6,8,10,12,14": 5,
|
|
12857
|
+
"2,4,6,12,14": 4,
|
|
12858
|
+
"0,2,4,6,7,8,10,12,14": 4,
|
|
12859
|
+
"4,5,7,8,10,12,13,14": 4,
|
|
12860
|
+
"0,2,3,4,5,8,9,12,13": 4,
|
|
12861
|
+
"2,3,4,6,8,12,13,14": 4,
|
|
12862
|
+
"0,1,2,3,4,5,6,7,8,9,10,11,12,13,14": 4,
|
|
12863
|
+
"0,2,4,8,12": 4,
|
|
12864
|
+
"4,6,8,10,12": 4,
|
|
12865
|
+
"0,2,4,5,6,8,12,13,14,15": 4,
|
|
12866
|
+
"0,2,3,4,6,8": 4,
|
|
12867
|
+
"0,4,6,8,10,12,13,14": 4,
|
|
12868
|
+
"0,6,8,12,14,15": 4,
|
|
12869
|
+
"0,4,8,9,10,12,14": 4,
|
|
12870
|
+
"0,3,4,7,8,9,10,11,12": 4,
|
|
12871
|
+
"0,1,2,3,4,5,7,8,9,10,11,12": 4,
|
|
12872
|
+
"2,4,8,12": 4,
|
|
12873
|
+
"0,2,4,6,10,12": 4,
|
|
12874
|
+
"0,3,4,6,7,8,9,10,12,14": 4,
|
|
12875
|
+
"0,3,6,9,11,12": 4,
|
|
12876
|
+
"0,1,4,6,8,12,14": 4,
|
|
12877
|
+
"4,8,12": 4,
|
|
12878
|
+
"2,4,6,14": 3,
|
|
12879
|
+
"0,3,4,8": 3,
|
|
12880
|
+
"0,2,4,12,14": 3,
|
|
12881
|
+
"14": 3,
|
|
12882
|
+
"0,4,6,12,14": 3,
|
|
12883
|
+
"0,6,10,12,14": 3,
|
|
12884
|
+
"4,8,9,11,14": 3,
|
|
12885
|
+
"0,2,4,8,9,11,14": 3,
|
|
12886
|
+
"0,4,8,9,11,14": 3,
|
|
12887
|
+
"0,2,4,5,7,9,11,12": 3,
|
|
12888
|
+
"0,3,6,8,10,12,14": 3,
|
|
12889
|
+
"0,3,4,6,8,11,12,14": 3,
|
|
12890
|
+
"0,1,4,5,8,9,12,13": 3,
|
|
12891
|
+
"0,2,4,5,8,9": 3,
|
|
12892
|
+
"2,3,4,6,8,9,12,14": 3,
|
|
12893
|
+
"0,2,4,8": 3,
|
|
12894
|
+
"0,2,3,4,5,6,8,9": 3,
|
|
12895
|
+
"2,3,4,6,8,10,12,13": 3,
|
|
12896
|
+
"12,14,15": 3,
|
|
12897
|
+
"0,2,3,4,6,7,8,10,12": 3,
|
|
12898
|
+
"0,2,3,4,5,6,7,8,9,10,12": 3,
|
|
12899
|
+
"0,1,2,3,4,5,6,7,8,9,10,11,12,14": 3,
|
|
12900
|
+
"0,2,3,4,6,7,8,9,10,11,12": 3,
|
|
12901
|
+
"0,4,6,12": 3,
|
|
12902
|
+
"0,2,3,6,8,11,14": 3,
|
|
12903
|
+
"0,2,6,8,12,14": 3,
|
|
12904
|
+
"2,4,6,8,14,15": 3,
|
|
12905
|
+
"0,2,4,6,12,14": 2,
|
|
12906
|
+
"2,4,6,10,12,14": 2,
|
|
12907
|
+
"4,6,10,12,14": 2,
|
|
12908
|
+
"0,8,14": 2,
|
|
12909
|
+
"2,4,8,10,12,14": 2,
|
|
12910
|
+
"8": 2,
|
|
12911
|
+
"0,2,4,6,8,9,10,11,12,14": 2,
|
|
12912
|
+
"0,2,4,6,8,12,13,14": 2,
|
|
12913
|
+
"0,6,8,11,12,14": 2,
|
|
12914
|
+
"0,1,2,3,4,5,6,7,8,9,11,12,13,14,15": 2,
|
|
12915
|
+
"0,1,3,4,5,6,7,8,9,10,11,12,13,14,15": 2,
|
|
12916
|
+
"0,6,7,8,10,12": 2,
|
|
12917
|
+
"0,3,6,7,8,10,12": 2,
|
|
12918
|
+
"1,2,3,4,6,8,10,12,13": 2,
|
|
12919
|
+
"0,2,8,10,12,14": 2,
|
|
12920
|
+
"0,2,7,8,9,10": 2,
|
|
12921
|
+
"4,8,9,10,12,13": 2,
|
|
12922
|
+
"0,2,4,7,8,9,10": 2,
|
|
12923
|
+
"2,4,7,8,12,15": 2,
|
|
12924
|
+
"0,4,7,8,10": 2,
|
|
12925
|
+
"0,4,8,9,12,13": 2,
|
|
12926
|
+
"0,2,4,5,6,8,9": 2,
|
|
12927
|
+
"0,1,4": 2,
|
|
12928
|
+
"0,4": 2,
|
|
12929
|
+
"0,3,6,10,12,14": 2,
|
|
12930
|
+
"0,2,6,10,12,14": 2,
|
|
12931
|
+
"0,2,3,4,6,8,14,15": 2,
|
|
12932
|
+
"2,4,6,8,12,14,15": 2,
|
|
12933
|
+
"0,2,4,6,8,9,10,12": 2,
|
|
12934
|
+
"0,3,6,8,10,12": 2,
|
|
12935
|
+
"0,3,4,6,8,10,14": 2,
|
|
12936
|
+
"0,4,8,11,12,14": 2,
|
|
12937
|
+
"0,2,4,6,8,9,10,11,12,13,14": 2,
|
|
12938
|
+
"0,2,4,5,6,7,8,9,10,12": 2,
|
|
12939
|
+
"0,1,2,3,4,6,7,8,9,10,12,14": 2,
|
|
12940
|
+
"0,1,2,4,5,6,8,9,10,11,12,13,14": 2,
|
|
12941
|
+
"0,1,2,3,4,6,7,8,9,10,11,12,13,14": 2,
|
|
12942
|
+
"0,1,2,3,4,6,7,8,9,10,11,12,13,14,15": 2,
|
|
12943
|
+
"0,1,2,4,6,8,9,10,11,12,13,14": 2,
|
|
12944
|
+
"0,1,2,3,4,5,6,8,9,10,11,12,13,14": 2,
|
|
12945
|
+
"0,1,2,3,4,6,7,8,9,10,12,13,14,15": 2,
|
|
12946
|
+
"0,2,4,6,8,9,10,11,12,13,14,15": 2,
|
|
12947
|
+
"0,2,3,4,5,6,8,10,12": 2,
|
|
12948
|
+
"0,2,3,4,5,6,7,8,10,11,12": 2,
|
|
12949
|
+
"0,2,3,4,6,7,8,9,10,12": 2,
|
|
12950
|
+
"0,1,2,3,4,6,7,8,9,10,11,12": 2,
|
|
12951
|
+
"0,4,5,8,12,13": 2,
|
|
12952
|
+
"0,3,4,5,8,11,12,13": 2,
|
|
12953
|
+
"0,2,4,7,8,9": 2,
|
|
12954
|
+
"0,4,6,7,8,12": 2,
|
|
12955
|
+
"0,2,3,4,6,7,8,10,11,12,14": 2,
|
|
12956
|
+
"0,2,3,4,5,6,7,8,10,11,12,13": 2,
|
|
12957
|
+
"12": 2,
|
|
12958
|
+
"0,2,4,6,8,13": 2,
|
|
12959
|
+
"2,4,6,8,11,14": 2,
|
|
12960
|
+
"0,5,8,13": 2,
|
|
12961
|
+
"0,2,4,6,8,10,11,12,13,14": 2,
|
|
12962
|
+
"0,4,6,8,10,11,12,13,14,15": 2,
|
|
12963
|
+
"0,5,8,12": 2,
|
|
12964
|
+
"2,4,6,8,14": 1,
|
|
12965
|
+
"0,6,7,8,14": 1,
|
|
12966
|
+
"0,6,8,14,15": 1,
|
|
12967
|
+
"0,6,7,8,10,11,12,13": 1,
|
|
12968
|
+
"0,6,7,8,9,10,11,12,14": 1,
|
|
12969
|
+
"0,1,2,4,6,7,8,10,11,12,13,14,15": 1,
|
|
12970
|
+
"0,4,8,10,11,12": 1,
|
|
12971
|
+
"0,6,7,8,11,14": 1,
|
|
12972
|
+
"0,2,5,8,11,14": 1,
|
|
12973
|
+
"0,2,4,6,8,10,11,12": 1,
|
|
12974
|
+
"0,11,14": 1,
|
|
12975
|
+
"0,8,11,12,13,14,15": 1,
|
|
12976
|
+
"0,1,12": 1,
|
|
12977
|
+
"0,3,5,8,12": 1,
|
|
12978
|
+
"0,4,8,11,14": 1,
|
|
12979
|
+
"2,6,8,11,14": 1,
|
|
12980
|
+
"0,2,3,4,6,8,12": 1,
|
|
12981
|
+
"0,4,6,8,11,12,14": 1,
|
|
12982
|
+
"0,1,12,14": 1,
|
|
12983
|
+
"0,9,12": 1,
|
|
12984
|
+
"0,3": 1,
|
|
12985
|
+
"0,1": 1,
|
|
12986
|
+
"4,6,8,14": 1,
|
|
12987
|
+
"2,12,14": 1,
|
|
12988
|
+
"2,8,12": 1,
|
|
12989
|
+
"0,3,6,8,11": 1,
|
|
12990
|
+
"10,12,14,15": 1,
|
|
12991
|
+
"0,2,3,6,8,9,11,14": 1,
|
|
12992
|
+
"0,2,4,8,10,11": 1,
|
|
12993
|
+
"0,2,4,6,7,8,10,12,13": 1,
|
|
12994
|
+
"2,3,4,5,8,10,12,13,15": 1,
|
|
12995
|
+
"0,2,3,4,5,6,8,10,11,12": 1,
|
|
12996
|
+
"4,6,8,10,11,12": 1,
|
|
12997
|
+
"0,1,2,3,4,6,8,9,10,13,15": 1,
|
|
12998
|
+
"0,1,2,3,4,10,11,12": 1,
|
|
12999
|
+
"0,3,6,7,8,9,11": 1,
|
|
13000
|
+
"0,2,4,5,8,10,11,15": 1,
|
|
13001
|
+
"0,2,4,6,7,8,9,12,13": 1,
|
|
13002
|
+
"0,1,2,4,5,8,10,12,13": 1,
|
|
13003
|
+
"0,2,3,4,5,6,8,10,11,12,13": 1,
|
|
13004
|
+
"4,6,8,10,11,12,13": 1,
|
|
13005
|
+
"0,3,8,12,14": 1,
|
|
13006
|
+
"0,3,4,5,7,8,9,10,12,14,15": 1,
|
|
13007
|
+
"0,2,4,6,8,9,11": 1,
|
|
13008
|
+
"10,14": 1,
|
|
13009
|
+
"0,2,4,6,9,10,12,14": 1,
|
|
13010
|
+
"0,2,4,6,7,9,10,12": 1,
|
|
13011
|
+
"0,2,3,5,8,10,12,13,14": 1,
|
|
13012
|
+
"0,1,2,3,5,6,7,8,9,10,12,13,14": 1,
|
|
13013
|
+
"2,3,4,6,7,8,12,13,14": 1,
|
|
13014
|
+
"0,1,2,3,6,7,8,10,12,13,14": 1,
|
|
13015
|
+
"2,3,4,5,6,8,9,10,11,12,13,14": 1,
|
|
13016
|
+
"0,2,3,4,5,6,7,8,9,10,11,12,13,14": 1,
|
|
13017
|
+
"2,3,4,6,8,9,10,11,12,13,14,15": 1,
|
|
13018
|
+
"0,3,4,7,8,11,12": 1,
|
|
13019
|
+
"0,4,10,12,14": 1,
|
|
13020
|
+
"0,3,4,7,8,11,12,15": 1,
|
|
13021
|
+
"0,4,12,14": 1,
|
|
13022
|
+
"0,4,12": 1,
|
|
13023
|
+
"0,4,7,8,10,11,12,14": 1,
|
|
13024
|
+
"2,6,8,12": 1,
|
|
13025
|
+
"0,2,4,5,6,8": 1,
|
|
13026
|
+
"2,6,8,10,12": 1,
|
|
13027
|
+
"0,2,4,6,8,12,13,14,15": 1,
|
|
13028
|
+
"0,4,6,8,10,11,12": 1,
|
|
13029
|
+
"0,4,8,10,11,12,13,14": 1,
|
|
13030
|
+
"0,2,3,4,6,7,8,9,10,12,13,14,15": 1,
|
|
13031
|
+
"0,2,4,5,6,8,9,10,11,12,13,14": 1,
|
|
13032
|
+
"0,3,4,7,8,9,10,12,13": 1,
|
|
13033
|
+
"0,1,2,4,6,7,8,9,10,12,13,14,15": 1,
|
|
13034
|
+
"0,2,3,4,5,6,8,9,10,11,12,13,14": 1,
|
|
13035
|
+
"0,4,6,7,8,10,12,14,15": 1,
|
|
13036
|
+
"0,2,4,6,7,8,10,12,14,15": 1,
|
|
13037
|
+
"0,1,2,3,4,5,7,8,10,11,12": 1,
|
|
13038
|
+
"0,2,4,6,7,8,9,10,11,12,14": 1,
|
|
13039
|
+
"0,1,2,4,5,6,7,8,10,12,14,15": 1,
|
|
13040
|
+
"0,2,3,4,5,7,8,9,10,11,12": 1,
|
|
13041
|
+
"0,2,3,4,6,7,8,10,11,12": 1,
|
|
13042
|
+
"0,8,9,10,11,12,13,14,15": 1,
|
|
13043
|
+
"14,15": 1,
|
|
13044
|
+
"2,4,6,8,12": 1,
|
|
13045
|
+
"2,4,8,10,12": 1,
|
|
13046
|
+
"0,2,4,8,9,12,14": 1,
|
|
13047
|
+
"0,4,5,8,9,12": 1,
|
|
13048
|
+
"0,4,8,10,14": 1,
|
|
13049
|
+
"0,6,7,12": 1,
|
|
13050
|
+
"0,4,5,8,11,12,13": 1,
|
|
13051
|
+
"0,2,4,8,9": 1,
|
|
13052
|
+
"2,4,7,8,11,12": 1,
|
|
13053
|
+
"0,4,7,8,11": 1,
|
|
13054
|
+
"0,4,8,12,14,15": 1,
|
|
13055
|
+
"0,1,2,4,5,6,7,8,9,10,12": 1,
|
|
13056
|
+
"0,1,2,3,4,5,6,7,8,9,10,12": 1,
|
|
13057
|
+
"0,2,3,4,5,6,7,8,9,10,12,13,14,15": 1,
|
|
13058
|
+
"0,3,4,7,8,9,11,12": 1,
|
|
13059
|
+
"0,1,2,3,4,5,6,7,8,10,11,12,13": 1,
|
|
13060
|
+
"0,6,8,10,12": 1,
|
|
13061
|
+
"0,2,3,4,6,8,10,11,12,14": 1,
|
|
13062
|
+
"0,2,4,6,8,10,13": 1,
|
|
13063
|
+
"2,6,8": 1,
|
|
13064
|
+
"0,2,3,4,6,7,8,12,14": 1,
|
|
13065
|
+
"2,4,6,8,10,14": 1,
|
|
13066
|
+
"0,2,4": 1,
|
|
13067
|
+
"0,2,4,5,6,7,8,9,10": 1,
|
|
13068
|
+
"0,2,4,5,6,7,8,9,10,12,13,14": 1,
|
|
13069
|
+
"0,3,6,10,14": 1,
|
|
13070
|
+
"0,14,15": 1,
|
|
13071
|
+
"0,6,7,12,14": 1,
|
|
13072
|
+
"0,6,8,10,11,12,14": 1
|
|
12743
13073
|
};
|
|
12744
13074
|
|
|
12745
13075
|
// src/compose-keys.ts
|
|
@@ -13074,8 +13404,7 @@ var resolveComposeKey = (choice, rnd = Math.random) => {
|
|
|
13074
13404
|
const target = COMPOSE_KEYS[pickedKeyId];
|
|
13075
13405
|
const targetMood = COMPOSE_MOOD_GROUPS.find((m) => m.id === target.moodId);
|
|
13076
13406
|
return {
|
|
13077
|
-
mode:
|
|
13078
|
-
// コード進行の長短制約は掛けず従来通りランダム
|
|
13407
|
+
mode: target.mode,
|
|
13079
13408
|
rootShift: target.rootShift,
|
|
13080
13409
|
keyName: target.name,
|
|
13081
13410
|
keyLabel: target.label,
|
|
@@ -13202,9 +13531,24 @@ var complementarity = (melody, submelody, opts) => {
|
|
|
13202
13531
|
}
|
|
13203
13532
|
return free / submelody.length;
|
|
13204
13533
|
};
|
|
13534
|
+
var turnRatio = (notes) => {
|
|
13535
|
+
const sorted = [...notes].sort((a, b) => a.startStep - b.startStep);
|
|
13536
|
+
let turns = 0;
|
|
13537
|
+
let intervals = 0;
|
|
13538
|
+
let prevDir = 0;
|
|
13539
|
+
for (let i2 = 1; i2 < sorted.length; i2++) {
|
|
13540
|
+
const dir = Math.sign(sorted[i2].pitchSemi - sorted[i2 - 1].pitchSemi);
|
|
13541
|
+
if (dir === 0) continue;
|
|
13542
|
+
intervals++;
|
|
13543
|
+
if (prevDir !== 0 && dir !== prevDir) turns++;
|
|
13544
|
+
prevDir = dir;
|
|
13545
|
+
}
|
|
13546
|
+
return intervals === 0 ? 0 : turns / intervals;
|
|
13547
|
+
};
|
|
13205
13548
|
var structureFeatures = (melody, submelody, opts) => {
|
|
13206
13549
|
const sigs = barSignatures(melody, opts);
|
|
13207
13550
|
return {
|
|
13551
|
+
turnRatio: turnRatio(melody),
|
|
13208
13552
|
sim1: selfSimilarity(sigs, 1),
|
|
13209
13553
|
sim2: selfSimilarity(sigs, 2),
|
|
13210
13554
|
sim4: selfSimilarity(sigs, 4),
|
|
@@ -13214,13 +13558,40 @@ var structureFeatures = (melody, submelody, opts) => {
|
|
|
13214
13558
|
complementarity: complementarity(melody, submelody, opts)
|
|
13215
13559
|
};
|
|
13216
13560
|
};
|
|
13561
|
+
var barNoteCounts = (notes, opts) => {
|
|
13562
|
+
const out = new Array(Math.max(1, opts.bars)).fill(0);
|
|
13563
|
+
for (const n of notes) {
|
|
13564
|
+
const bar = Math.floor(n.startStep / opts.stepsPerBar);
|
|
13565
|
+
if (bar >= 0 && bar < out.length) out[bar]++;
|
|
13566
|
+
}
|
|
13567
|
+
return out;
|
|
13568
|
+
};
|
|
13217
13569
|
var densityFeatures = (notes, opts) => {
|
|
13218
|
-
if (notes.length === 0)
|
|
13570
|
+
if (notes.length === 0)
|
|
13571
|
+
return {
|
|
13572
|
+
notesPerBar: 0,
|
|
13573
|
+
shortNoteRatio: 0,
|
|
13574
|
+
barDensityCv: 0,
|
|
13575
|
+
densityCliff: 0
|
|
13576
|
+
};
|
|
13219
13577
|
const eighth = opts.stepsPerBar / 8;
|
|
13220
13578
|
const short = notes.filter((n) => n.durationSteps <= eighth).length;
|
|
13579
|
+
const counts = barNoteCounts(notes, opts);
|
|
13580
|
+
const sung = counts.filter((c) => c > 0);
|
|
13581
|
+
const mean2 = sung.reduce((a, b) => a + b, 0) / Math.max(1, sung.length);
|
|
13582
|
+
const variance = sung.reduce((a, b) => a + (b - mean2) ** 2, 0) / Math.max(1, sung.length);
|
|
13583
|
+
let cliffs = 0;
|
|
13584
|
+
let pairs = 0;
|
|
13585
|
+
for (let i2 = 1; i2 < counts.length; i2++) {
|
|
13586
|
+
if (counts[i2 - 1] < 3 || counts[i2] === 0) continue;
|
|
13587
|
+
pairs++;
|
|
13588
|
+
if (counts[i2] <= counts[i2 - 1] * 0.3) cliffs++;
|
|
13589
|
+
}
|
|
13221
13590
|
return {
|
|
13222
13591
|
notesPerBar: notes.length / Math.max(1, opts.bars),
|
|
13223
|
-
shortNoteRatio: short / notes.length
|
|
13592
|
+
shortNoteRatio: short / notes.length,
|
|
13593
|
+
barDensityCv: mean2 === 0 ? 0 : Math.sqrt(variance) / mean2,
|
|
13594
|
+
densityCliff: pairs === 0 ? 0 : cliffs / pairs
|
|
13224
13595
|
};
|
|
13225
13596
|
};
|
|
13226
13597
|
var tensionFeatures = (barTension, opts) => {
|
|
@@ -13516,8 +13887,8 @@ var sectionAt = (plan, bar) => {
|
|
|
13516
13887
|
|
|
13517
13888
|
// src/compose.ts
|
|
13518
13889
|
var STEP_SEMITONES = 2;
|
|
13519
|
-
var MAX_LEAP_SEMITONES =
|
|
13520
|
-
var MAX_BAR_LEAP_SEMITONES =
|
|
13890
|
+
var MAX_LEAP_SEMITONES = 10;
|
|
13891
|
+
var MAX_BAR_LEAP_SEMITONES = 10;
|
|
13521
13892
|
var HARD = {
|
|
13522
13893
|
/** メロディが1音も無い、音域が半音未満(同じ音を並べただけ)。 */
|
|
13523
13894
|
minMelodyRange: 3,
|
|
@@ -13543,6 +13914,9 @@ var WEIGHTS = {
|
|
|
13543
13914
|
*/
|
|
13544
13915
|
notesPerBar: 0.8,
|
|
13545
13916
|
shortNoteRatio: 0.6,
|
|
13917
|
+
/** 小節ごとの音数のばらつきと崖。平均だけを見ていて見逃していた偏り。 */
|
|
13918
|
+
barDensityCv: 0.6,
|
|
13919
|
+
densityCliff: 1,
|
|
13546
13920
|
/** 順次進行の比率。跳躍率だけを見ていると、跳躍の帯の上端に張り付く。 */
|
|
13547
13921
|
stepRatio: 0.8,
|
|
13548
13922
|
/** 調の外の音。0のままだと全曲が同じ音階をなぞるだけになる。 */
|
|
@@ -13555,10 +13929,15 @@ var WEIGHTS = {
|
|
|
13555
13929
|
sim4: 1.4,
|
|
13556
13930
|
sim8: 1.4,
|
|
13557
13931
|
phraseBreath: 1,
|
|
13932
|
+
/** 折り返しの多さ。跳躍率・順次進行率が揃っていても、これは別に足りなくなる。 */
|
|
13933
|
+
turnRatio: 0.8,
|
|
13558
13934
|
climaxPosition: 1,
|
|
13559
13935
|
climaxPeaks: 1,
|
|
13560
13936
|
/** メロディとサブメロが呼応しているか。 */
|
|
13561
13937
|
complementarity: 1,
|
|
13938
|
+
/** サブメロの音数と、その崖。メロディと同じ物差しで見る。 */
|
|
13939
|
+
subDensity: 0.6,
|
|
13940
|
+
subDensityCliff: 0.5,
|
|
13562
13941
|
// --- 和声(コードが要るのでコーパスからは較正できない) ---
|
|
13563
13942
|
/** B部でテンションが上がるか。 */
|
|
13564
13943
|
tensionRise: 1,
|
|
@@ -13634,6 +14013,10 @@ var FLAT_NOTE_NAMES = [
|
|
|
13634
14013
|
"Bb",
|
|
13635
14014
|
"B"
|
|
13636
14015
|
];
|
|
14016
|
+
var fifthsDistance = (semitones) => {
|
|
14017
|
+
const steps = (semitones * 7 % 12 + 12) % 12;
|
|
14018
|
+
return Math.min(steps, 12 - steps);
|
|
14019
|
+
};
|
|
13637
14020
|
var SEMITONE_TO_FIFTH_SHIFT = [
|
|
13638
14021
|
0,
|
|
13639
14022
|
// 0: C
|
|
@@ -13786,6 +14169,22 @@ var SECTION_A_PROGRESSIONS = [
|
|
|
13786
14169
|
// ジャズ寄りの2-5-1
|
|
13787
14170
|
["Dm7", "G7", "Em7", "Am7"],
|
|
13788
14171
|
// 2-5-3-6
|
|
14172
|
+
// --- ライン・クリシェ(内声が半音ずつ動く) ---
|
|
14173
|
+
// 和音の1声だけを半音で動かして、和音記号は変わるのに響きは繋がったまま進む。
|
|
14174
|
+
// J-POPのサビ後半やAメロの定番。
|
|
14175
|
+
["Am", "AmM7", "Am7", "Am6"],
|
|
14176
|
+
// ラ→ソ#→ソ→ファ# の下行
|
|
14177
|
+
["C", "CM7", "C7", "F"],
|
|
14178
|
+
// ド→シ→シb→ラ
|
|
14179
|
+
["Am", "AmM7", "Am7", "D7"],
|
|
14180
|
+
// クリシェからドリアンのIVへ
|
|
14181
|
+
["F", "Fm", "CM7", "Am7"],
|
|
14182
|
+
// サブドミナントマイナーのクリシェ
|
|
14183
|
+
// --- ペダルポイント(ベースを保続する) ---
|
|
14184
|
+
// ベースだけ動かさずに上の和音を変える。緊張感が出る。分数和音のルートを
|
|
14185
|
+
// {@link chordTones} が先頭で返すので、ベースは自然に保続音になる。
|
|
14186
|
+
["C", "Am/C", "F/C", "G/C"],
|
|
14187
|
+
["Am", "Em/A", "F/A", "G/A"],
|
|
13789
14188
|
// --- 借用和音(同主短調・ミクソリディアンから借りる) ---
|
|
13790
14189
|
// **調の外の和音を進行そのものに持たせる。** ここまでの候補は全部ハ長調/イ短調の
|
|
13791
14190
|
// ダイアトニックで、セカンダリドミナント以外に調の外の音が出てこなかった。
|
|
@@ -13842,10 +14241,34 @@ var SECTION_A2_DERIVATIONS = [
|
|
|
13842
14241
|
var SECTION_A3_DERIVATIONS = [
|
|
13843
14242
|
(a, t) => [a[0], a[1], "G7", t],
|
|
13844
14243
|
(a, t) => [a[0], "Dm7", "G7", t],
|
|
13845
|
-
(a, t) => [a[0], "F", "G7", t],
|
|
13846
14244
|
(a, t) => [a[0], a[1], "Em7", t],
|
|
13847
|
-
|
|
14245
|
+
// アーメン終止(IV→I)
|
|
14246
|
+
(a, t) => [a[0], "G7", "F", t],
|
|
14247
|
+
(a, t) => [a[0], "Dm7", "FM7", t],
|
|
14248
|
+
// サブドミナントマイナー終止(IVm→I)
|
|
14249
|
+
(a, t) => [a[0], "G7", "Fm", t],
|
|
14250
|
+
(a, t) => [a[0], "F", "Fm", t]
|
|
13848
14251
|
];
|
|
14252
|
+
var SECTION_DECEPTIVE_DERIVATIONS = [
|
|
14253
|
+
(a, t) => [a[0], a[1], "G7", t === "Am" ? "F" : "Am"],
|
|
14254
|
+
(a, t) => [a[0], "Dm7", "G7", t === "Am" ? "FM7" : "Am7"],
|
|
14255
|
+
(a, t) => [a[0], "F", "G7", t === "Am" ? "F" : "Am7"]
|
|
14256
|
+
];
|
|
14257
|
+
var MODAL_BORROW = {
|
|
14258
|
+
F: "Fm",
|
|
14259
|
+
// IV → IVm(サブドミナントマイナー。いちばん定番)
|
|
14260
|
+
FM7: "Fm7",
|
|
14261
|
+
Am: "Ab",
|
|
14262
|
+
// VIm → ♭VI
|
|
14263
|
+
Am7: "Ab",
|
|
14264
|
+
G: "Bb",
|
|
14265
|
+
// V → ♭VII(ミクソリディアン)
|
|
14266
|
+
G7: "Bb",
|
|
14267
|
+
Em7: "Eb",
|
|
14268
|
+
// IIIm → ♭III
|
|
14269
|
+
Dm7: "Dm7-5"
|
|
14270
|
+
// IIm7 → IIm7♭5(エオリアン)
|
|
14271
|
+
};
|
|
13849
14272
|
var CHORD_PATTERNS = [
|
|
13850
14273
|
"block",
|
|
13851
14274
|
"arpeggio",
|
|
@@ -13853,6 +14276,7 @@ var CHORD_PATTERNS = [
|
|
|
13853
14276
|
"yatsume",
|
|
13854
14277
|
"alternating"
|
|
13855
14278
|
];
|
|
14279
|
+
var chordPatternPool = (bpm) => bpm <= 130 ? [...CHORD_PATTERNS, "arpeggio-fast"] : CHORD_PATTERNS;
|
|
13856
14280
|
var CHORD_TONE_WEIGHT = {
|
|
13857
14281
|
0: 3,
|
|
13858
14282
|
// ルート
|
|
@@ -14030,6 +14454,54 @@ var RHYTHM_CELLS = [
|
|
|
14030
14454
|
density: "dense"
|
|
14031
14455
|
}
|
|
14032
14456
|
];
|
|
14457
|
+
var PHRASE_END_CELLS = [
|
|
14458
|
+
// 白玉で受けてから息を継ぐ(いちばん歌らしい終わり方)。
|
|
14459
|
+
{ value: [HALF, QUARTER, -QUARTER], density: "sparse" },
|
|
14460
|
+
{ value: [DOT_QUARTER, EIGHTH, HALF], density: "sparse" },
|
|
14461
|
+
{ value: [QUARTER, DOT_QUARTER, EIGHTH, -QUARTER], density: "sparse" },
|
|
14462
|
+
// 2音で降りてから息を継ぐ。
|
|
14463
|
+
{ value: [QUARTER, QUARTER, -HALF], density: "sparse" },
|
|
14464
|
+
{ value: [DOT_QUARTER, EIGHTH, -HALF], density: "sparse" },
|
|
14465
|
+
{ value: [HALF, -QUARTER, QUARTER], density: "sparse" },
|
|
14466
|
+
// 3音で言い切ってから息を継ぐ。
|
|
14467
|
+
{ value: [EIGHTH, EIGHTH, QUARTER, -HALF], density: "sparse" },
|
|
14468
|
+
{ value: [QUARTER, EIGHTH, EIGHTH, -HALF], density: "sparse" },
|
|
14469
|
+
{ value: [QUARTER, QUARTER, QUARTER, -QUARTER], density: "sparse" },
|
|
14470
|
+
{ value: [HALF, EIGHTH, EIGHTH, -QUARTER], density: "sparse" },
|
|
14471
|
+
// 4音で言い切ってから息を継ぐ。周りが7音前後の曲では、2音まで落とすと崖になる。
|
|
14472
|
+
{ value: [EIGHTH, EIGHTH, EIGHTH, EIGHTH, -HALF], density: "sparse" },
|
|
14473
|
+
{ value: [QUARTER, EIGHTH, EIGHTH, QUARTER, -QUARTER], density: "sparse" },
|
|
14474
|
+
{ value: [EIGHTH, EIGHTH, QUARTER, QUARTER, -QUARTER], density: "sparse" }
|
|
14475
|
+
];
|
|
14476
|
+
var MID_BREATH_CELLS = [
|
|
14477
|
+
{ value: [QUARTER, EIGHTH, EIGHTH, QUARTER, -QUARTER], density: "medium" },
|
|
14478
|
+
{ value: [EIGHTH, EIGHTH, QUARTER, QUARTER, -QUARTER], density: "medium" },
|
|
14479
|
+
{ value: [DOT_QUARTER, EIGHTH, QUARTER, QUARTER], density: "medium" },
|
|
14480
|
+
{ value: [QUARTER, QUARTER, EIGHTH, EIGHTH, -QUARTER], density: "medium" },
|
|
14481
|
+
{ value: [EIGHTH, EIGHTH, EIGHTH, EIGHTH, HALF], density: "medium" },
|
|
14482
|
+
{ value: [QUARTER, EIGHTH, EIGHTH, DOT_QUARTER, EIGHTH], density: "medium" }
|
|
14483
|
+
];
|
|
14484
|
+
var CELL_GRID = BASE_STEPS_PER_BAR / 16;
|
|
14485
|
+
var onsetKeyOf = (value) => {
|
|
14486
|
+
const on = [];
|
|
14487
|
+
let at = 0;
|
|
14488
|
+
for (const v of value) {
|
|
14489
|
+
if (v > 0) on.push(Math.round(at / CELL_GRID));
|
|
14490
|
+
at += Math.abs(v);
|
|
14491
|
+
}
|
|
14492
|
+
return on.join(",");
|
|
14493
|
+
};
|
|
14494
|
+
var UNSEEN_CELL_WEIGHT = 0.5;
|
|
14495
|
+
var cellEntryCount = /* @__PURE__ */ new Map();
|
|
14496
|
+
var cellWeightCache = /* @__PURE__ */ new Map();
|
|
14497
|
+
var cellWeight = (c) => {
|
|
14498
|
+
const cached = cellWeightCache.get(c.value);
|
|
14499
|
+
if (cached !== void 0) return cached;
|
|
14500
|
+
const key = onsetKeyOf(c.value);
|
|
14501
|
+
const w = (CORPUS_CELL_WEIGHTS[key] ?? UNSEEN_CELL_WEIGHT) / Math.max(1, cellEntryCount.get(key) ?? 1);
|
|
14502
|
+
cellWeightCache.set(c.value, w);
|
|
14503
|
+
return w;
|
|
14504
|
+
};
|
|
14033
14505
|
var HALF_BAR_FIGURES = [
|
|
14034
14506
|
[EIGHTH, EIGHTH, EIGHTH, EIGHTH],
|
|
14035
14507
|
// タタタタ
|
|
@@ -14062,6 +14534,14 @@ var HALF_BAR_FIGURES = [
|
|
|
14062
14534
|
// 2拍目裏からのアウフタクト(タタ)
|
|
14063
14535
|
[QUARTER, -EIGHTH, EIGHTH],
|
|
14064
14536
|
// ター・休タ(8分裏弱起)
|
|
14537
|
+
// **3+3+2(トレシーヨ)。** 参考曲91本で最も多かった「語彙に無い形」で、
|
|
14538
|
+
// 174小節ぶんの穴が空いていた(`scripts/compare-vocabulary.ts` の①)。
|
|
14539
|
+
// 付点8分が `[DOT_EIGHTH, SIXTEENTH]` の対でしか入っておらず、
|
|
14540
|
+
// 付点8分を2つ並べる形が作れなかった。界隈曲・ボカロの推進力の中心。
|
|
14541
|
+
[DOT_EIGHTH, DOT_EIGHTH, EIGHTH],
|
|
14542
|
+
[DOT_EIGHTH, DOT_EIGHTH, EIGHTH],
|
|
14543
|
+
// 4分音符が全部8分裏に来る形(食い)。参考曲で67小節ぶん取りこぼしていた。
|
|
14544
|
+
[-EIGHTH, QUARTER, EIGHTH],
|
|
14065
14545
|
// 付点8分+16分(タッカ)。歌モノで非常に多用される跳ね・推進力の型。
|
|
14066
14546
|
[DOT_EIGHTH, SIXTEENTH, EIGHTH, EIGHTH],
|
|
14067
14547
|
[EIGHTH, EIGHTH, DOT_EIGHTH, SIXTEENTH],
|
|
@@ -14227,9 +14707,21 @@ var MOTIF_CELLS = [
|
|
|
14227
14707
|
...buildMotifCells(),
|
|
14228
14708
|
...HAND_MOTIF_CELLS
|
|
14229
14709
|
];
|
|
14710
|
+
for (const c of [...MOTIF_CELLS, ...RHYTHM_CELLS]) {
|
|
14711
|
+
const key = onsetKeyOf(c.value);
|
|
14712
|
+
cellEntryCount.set(key, (cellEntryCount.get(key) ?? 0) + 1);
|
|
14713
|
+
}
|
|
14230
14714
|
var groovyCells = (cells, groove, rnd) => {
|
|
14231
14715
|
const hasSixteenth = (c) => c.value.some((v) => Math.abs(v) <= SIXTEENTH);
|
|
14232
|
-
if (groove === "eighth")
|
|
14716
|
+
if (groove === "eighth") {
|
|
14717
|
+
const plain = cells.filter((c) => !hasSixteenth(c));
|
|
14718
|
+
const spiced = cells.filter(hasSixteenth);
|
|
14719
|
+
if (spiced.length === 0) return plain;
|
|
14720
|
+
const out = [...plain];
|
|
14721
|
+
const take = Math.max(1, Math.round(plain.length * 0.1));
|
|
14722
|
+
for (let i2 = 0; i2 < take; i2++) out.push(pick(spiced, rnd));
|
|
14723
|
+
return out;
|
|
14724
|
+
}
|
|
14233
14725
|
const withSixteenth = cells.filter(hasSixteenth);
|
|
14234
14726
|
return withSixteenth.length > 0 && rnd() < 0.75 ? withSixteenth : cells;
|
|
14235
14727
|
};
|
|
@@ -14350,8 +14842,35 @@ var nearestChordTone = (targetSemi, tones, minWeight, preferColor = false) => {
|
|
|
14350
14842
|
return best;
|
|
14351
14843
|
};
|
|
14352
14844
|
var MELODY_LOW = 60;
|
|
14353
|
-
var MELODY_HIGH =
|
|
14845
|
+
var MELODY_HIGH = 81;
|
|
14354
14846
|
var MELODY_CENTER = (MELODY_LOW + MELODY_HIGH) / 2;
|
|
14847
|
+
var harmonyPitch = (melodySemi, tones, prevHarmony, offset, parallel, against) => {
|
|
14848
|
+
const lo = Math.max(-12, Math.min(offset, 0) - 7);
|
|
14849
|
+
const hi = Math.min(12, Math.max(offset, 0) + 7);
|
|
14850
|
+
let best = null;
|
|
14851
|
+
let bestCost = Number.POSITIVE_INFINITY;
|
|
14852
|
+
for (const tone of tones) {
|
|
14853
|
+
const pc = pitchClass(tone.semi);
|
|
14854
|
+
for (let oct = 0; oct <= 10; oct++) {
|
|
14855
|
+
const semi = pc + oct * 12;
|
|
14856
|
+
const delta = semi - melodySemi;
|
|
14857
|
+
if (delta > hi || delta < lo) continue;
|
|
14858
|
+
const move = prevHarmony === null ? 0 : Math.abs(semi - prevHarmony);
|
|
14859
|
+
const stay = parallel ? move * 0.06 : move <= 2 ? move * 0.04 : 0.1 + (move - 2) * 0.9;
|
|
14860
|
+
let clash = 0;
|
|
14861
|
+
if (against !== null) {
|
|
14862
|
+
const g = Math.abs(semi - against) % 12;
|
|
14863
|
+
clash = g === 3 || g === 4 || g === 8 || g === 9 || g === 7 ? 0 : g === 0 ? 0.5 : 1.2;
|
|
14864
|
+
}
|
|
14865
|
+
const cost = stay + clash + Math.abs(delta - offset) * (parallel ? 1.4 : 0.7) + (3 - tone.weight) * 0.4;
|
|
14866
|
+
if (cost < bestCost) {
|
|
14867
|
+
bestCost = cost;
|
|
14868
|
+
best = { semi, fifth: tone.fifth };
|
|
14869
|
+
}
|
|
14870
|
+
}
|
|
14871
|
+
}
|
|
14872
|
+
return best ?? nearestChordTone(melodySemi + offset, tones, 2);
|
|
14873
|
+
};
|
|
14355
14874
|
var SUBMELODY_LOW = 55;
|
|
14356
14875
|
var SUBMELODY_HIGH = 74;
|
|
14357
14876
|
var BASS_LOW = 33;
|
|
@@ -14533,9 +15052,12 @@ var barDegrees = (role, slots, tones, style, motifContour, startDegree, contourO
|
|
|
14533
15052
|
}
|
|
14534
15053
|
return out;
|
|
14535
15054
|
};
|
|
14536
|
-
var fitMotif = (degrees, slots, tones, prevSemi, quarterSteps, pentatonic) => {
|
|
15055
|
+
var fitMotif = (degrees, slots, tones, prevSemi, quarterSteps, pentatonic, preferShift) => {
|
|
14537
15056
|
let best = degrees;
|
|
15057
|
+
let bestShift = 0;
|
|
14538
15058
|
let bestScore = Number.NEGATIVE_INFINITY;
|
|
15059
|
+
let preferScore = Number.NEGATIVE_INFINITY;
|
|
15060
|
+
let preferMoved = null;
|
|
14539
15061
|
for (let shift = -3; shift <= 3; shift++) {
|
|
14540
15062
|
const moved = degrees.map(
|
|
14541
15063
|
(d) => pentatonic ? pentaToDegree(degreeToPenta(d) + shift) : d + shift
|
|
@@ -14557,12 +15079,19 @@ var fitMotif = (degrees, slots, tones, prevSemi, quarterSteps, pentatonic) => {
|
|
|
14557
15079
|
MELODY_HIGH
|
|
14558
15080
|
);
|
|
14559
15081
|
score -= Math.max(0, Math.abs(head - prevSemi) - MAX_BAR_LEAP_SEMITONES);
|
|
15082
|
+
if (shift === preferShift) {
|
|
15083
|
+
preferScore = score;
|
|
15084
|
+
preferMoved = moved;
|
|
15085
|
+
}
|
|
14560
15086
|
if (score > bestScore) {
|
|
14561
15087
|
bestScore = score;
|
|
15088
|
+
bestShift = shift;
|
|
14562
15089
|
best = moved;
|
|
14563
15090
|
}
|
|
14564
15091
|
}
|
|
14565
|
-
|
|
15092
|
+
if (preferMoved !== null && preferScore >= bestScore - 3)
|
|
15093
|
+
return { degrees: preferMoved, shift: preferShift };
|
|
15094
|
+
return { degrees: best, shift: bestShift };
|
|
14566
15095
|
};
|
|
14567
15096
|
var shapeBar = (degrees, slots, tones, prevSemi, opts) => {
|
|
14568
15097
|
const out = [];
|
|
@@ -14735,9 +15264,24 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14735
15264
|
options.template
|
|
14736
15265
|
);
|
|
14737
15266
|
const totalBars = sectionPlan.reduce((sum, s) => sum + s.bars, 0);
|
|
14738
|
-
|
|
15267
|
+
const relativeKinds = /* @__PURE__ */ new Set();
|
|
15268
|
+
let relativeShift = 0;
|
|
15269
|
+
if (rnd() < 0.25) {
|
|
15270
|
+
for (const kind of pick(
|
|
15271
|
+
[["prechorus"], ["bridge"], ["prechorus", "bridge"]],
|
|
15272
|
+
rnd
|
|
15273
|
+
))
|
|
15274
|
+
relativeKinds.add(kind);
|
|
15275
|
+
if (rnd() < 0.33) relativeShift = resolvedKey.mode === "minor" ? -3 : 3;
|
|
15276
|
+
}
|
|
15277
|
+
const floating = rnd() < 0.12;
|
|
15278
|
+
if (relativeKinds.size > 0 && relativeShift !== 0) {
|
|
15279
|
+
for (const s of sectionPlan)
|
|
15280
|
+
if (relativeKinds.has(s.kind)) s.keyShift = relativeShift;
|
|
15281
|
+
}
|
|
15282
|
+
if (relativeKinds.size === 0 && !floating && rnd() < 0.32) {
|
|
14739
15283
|
const modType = pick(
|
|
14740
|
-
["chorus_up", "chorus_up", "
|
|
15284
|
+
["chorus_up", "chorus_up", "color", "dominant", "subdominant"],
|
|
14741
15285
|
rnd
|
|
14742
15286
|
);
|
|
14743
15287
|
if (modType === "chorus_up") {
|
|
@@ -14746,15 +15290,83 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14746
15290
|
for (let i2 = 0; i2 < sectionPlan.length; i2++) {
|
|
14747
15291
|
if (sectionPlan[i2].kind === "chorus") lastChorusIdx = i2;
|
|
14748
15292
|
}
|
|
14749
|
-
if (lastChorusIdx >= 0)
|
|
14750
|
-
for (let i2 = lastChorusIdx; i2 < sectionPlan.length; i2++)
|
|
15293
|
+
if (lastChorusIdx >= 0)
|
|
15294
|
+
for (let i2 = lastChorusIdx; i2 < sectionPlan.length; i2++)
|
|
14751
15295
|
sectionPlan[i2].keyShift = shift;
|
|
14752
|
-
}
|
|
14753
|
-
}
|
|
14754
15296
|
} else {
|
|
14755
|
-
const shift = pick([-2, 3], rnd);
|
|
14756
|
-
|
|
14757
|
-
|
|
15297
|
+
const shift = modType === "dominant" ? 7 : modType === "subdominant" ? 5 : pick([-2, 3], rnd);
|
|
15298
|
+
const kinds = pick(
|
|
15299
|
+
[["prechorus"], ["bridge"], ["prechorus", "bridge"]],
|
|
15300
|
+
rnd
|
|
15301
|
+
);
|
|
15302
|
+
for (const s of sectionPlan)
|
|
15303
|
+
if (kinds.includes(s.kind)) s.keyShift = shift;
|
|
15304
|
+
}
|
|
15305
|
+
}
|
|
15306
|
+
const harmonyFrom = pick(
|
|
15307
|
+
["chorus", "chorus", "prechorus"],
|
|
15308
|
+
rnd
|
|
15309
|
+
);
|
|
15310
|
+
const harmonyParallel = rnd() < 0.45;
|
|
15311
|
+
const harmonyCoverage = 0.7 + rnd() * 0.3;
|
|
15312
|
+
const useHarmony2 = rnd() < 0.3;
|
|
15313
|
+
const useOctaveLayer = !useHarmony2 && rnd() < 0.25;
|
|
15314
|
+
const octaveCoverage = 0.3 + rnd() * 0.3;
|
|
15315
|
+
const harmonyOffset = useHarmony2 ? (
|
|
15316
|
+
// 3声のときは1声目を下〜ユニゾン側へ寄せ、2声目を上へ回して主旋律を挟む
|
|
15317
|
+
// (参考: チョウチン少女 ch12/ch11/ch13)。
|
|
15318
|
+
pick([-5, -3, 0, 0, 3], rnd)
|
|
15319
|
+
) : harmonyParallel ? pick([3, 4, 5, 9, 7, 0, -5], rnd) : pick([3, 4, 5, 0, -5, -4, -7], rnd);
|
|
15320
|
+
let prevHarmony = null;
|
|
15321
|
+
let prevHarmony2 = null;
|
|
15322
|
+
const harmony2Offset = harmonyOffset + pick([9, 9, 9, 8, 7], rnd);
|
|
15323
|
+
const harmonyKinds = harmonyFrom === "prechorus" ? ["prechorus", "chorus", "bridge"] : ["chorus"];
|
|
15324
|
+
const duetStyle = pick(
|
|
15325
|
+
[
|
|
15326
|
+
"none",
|
|
15327
|
+
"none",
|
|
15328
|
+
"none",
|
|
15329
|
+
"none",
|
|
15330
|
+
"none",
|
|
15331
|
+
"section",
|
|
15332
|
+
"phrase",
|
|
15333
|
+
"chorus",
|
|
15334
|
+
"verse"
|
|
15335
|
+
],
|
|
15336
|
+
rnd
|
|
15337
|
+
);
|
|
15338
|
+
const duetOwner = new Array(totalBars).fill(false);
|
|
15339
|
+
if (duetStyle !== "none") {
|
|
15340
|
+
let melodySection = 0;
|
|
15341
|
+
for (const section of sectionPlan) {
|
|
15342
|
+
if (!section.spec.melody) continue;
|
|
15343
|
+
const isChorus = section.kind === "chorus" || section.kind === "drop_chorus";
|
|
15344
|
+
const isVerse = section.kind === "verse";
|
|
15345
|
+
const takeSection = melodySection % 2 === 1;
|
|
15346
|
+
melodySection++;
|
|
15347
|
+
const alternate = duetStyle === "phrase" ? !isChorus : duetStyle === "chorus" ? isChorus : duetStyle === "verse" ? isVerse : false;
|
|
15348
|
+
if (!alternate && !(duetStyle === "section" && takeSection && !isChorus))
|
|
15349
|
+
continue;
|
|
15350
|
+
for (let b = section.startBar; b < section.startBar + section.bars; b++) {
|
|
15351
|
+
if (alternate) {
|
|
15352
|
+
if (Math.floor((b - section.startBar) / 2) % 2 === 1)
|
|
15353
|
+
duetOwner[b] = true;
|
|
15354
|
+
} else duetOwner[b] = true;
|
|
15355
|
+
}
|
|
15356
|
+
}
|
|
15357
|
+
}
|
|
15358
|
+
const duetSpans = [];
|
|
15359
|
+
{
|
|
15360
|
+
let from = -1;
|
|
15361
|
+
for (let b = 0; b <= totalBars; b++) {
|
|
15362
|
+
const owned = b < totalBars && duetOwner[b];
|
|
15363
|
+
if (owned && from < 0) from = b;
|
|
15364
|
+
if (!owned && from >= 0) {
|
|
15365
|
+
const lead = from === 0 ? 0 : scaleStep(
|
|
15366
|
+
pick([0, 0, EIGHTH, EIGHTH, QUARTER, DOT_QUARTER], rnd)
|
|
15367
|
+
);
|
|
15368
|
+
duetSpans.push([from * stepsPerBar - lead, b * stepsPerBar]);
|
|
15369
|
+
from = -1;
|
|
14758
15370
|
}
|
|
14759
15371
|
}
|
|
14760
15372
|
}
|
|
@@ -14765,41 +15377,114 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14765
15377
|
}
|
|
14766
15378
|
}
|
|
14767
15379
|
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;
|
|
14768
|
-
const
|
|
15380
|
+
const withoutTonic = (pool, root) => {
|
|
15381
|
+
const isTonic = (c) => root === "Am" ? /^Am/.test(c) : /^C(?![#b]|m)/.test(c);
|
|
15382
|
+
const out = pool.filter((p) => !p.some(isTonic));
|
|
15383
|
+
return out.length > 0 ? out : pool;
|
|
15384
|
+
};
|
|
15385
|
+
const homeRoot = resolvedKey.mode === "minor" ? "Am" : "C";
|
|
15386
|
+
const progA = pick(
|
|
15387
|
+
floating ? withoutTonic(progAPool, homeRoot) : progAPool,
|
|
15388
|
+
rnd
|
|
15389
|
+
);
|
|
14769
15390
|
const progBPool = SECTION_B_PROGRESSIONS.filter(
|
|
14770
15391
|
(p) => p.join("|") !== progA.join("|")
|
|
14771
15392
|
);
|
|
14772
|
-
const progB = pick(
|
|
15393
|
+
const progB = pick(
|
|
15394
|
+
floating ? withoutTonic(progBPool, homeRoot) : progBPool,
|
|
15395
|
+
rnd
|
|
15396
|
+
);
|
|
15397
|
+
const progRelativePool = SECTION_A_PROGRESSIONS.filter(
|
|
15398
|
+
(p) => resolvedKey.mode === "minor" ? !p[0].startsWith("Am") : p[0].startsWith("Am")
|
|
15399
|
+
);
|
|
15400
|
+
const progRelative = pick(
|
|
15401
|
+
floating ? withoutTonic(progRelativePool, homeRoot) : progRelativePool,
|
|
15402
|
+
rnd
|
|
15403
|
+
);
|
|
15404
|
+
const progCPool = SECTION_C_PROGRESSIONS.filter(
|
|
15405
|
+
(p) => p.join("|") !== progA.join("|") && p.join("|") !== progB.join("|")
|
|
15406
|
+
);
|
|
14773
15407
|
const progC = pick(
|
|
14774
|
-
|
|
14775
|
-
(p) => p.join("|") !== progA.join("|") && p.join("|") !== progB.join("|")
|
|
14776
|
-
),
|
|
15408
|
+
floating ? withoutTonic(progCPool, homeRoot) : progCPool,
|
|
14777
15409
|
rnd
|
|
14778
15410
|
);
|
|
14779
15411
|
const tonic = progA[0].startsWith("Am") ? "Am" : "C";
|
|
14780
15412
|
const progHalf = pick(SECTION_A2_DERIVATIONS, rnd)(progA);
|
|
14781
15413
|
const progFull = pick(SECTION_A3_DERIVATIONS, rnd)(progA, tonic);
|
|
15414
|
+
const progDeceptive = pick(SECTION_DECEPTIVE_DERIVATIONS, rnd)(progA, tonic);
|
|
15415
|
+
let lastChorusBar = -1;
|
|
15416
|
+
for (const section of sectionPlan)
|
|
15417
|
+
if (section.kind === "chorus" || section.kind === "outro")
|
|
15418
|
+
lastChorusBar = section.startBar;
|
|
14782
15419
|
const progression = [];
|
|
14783
15420
|
for (const section of sectionPlan) {
|
|
14784
|
-
const base = section.spec.progression === "c" ? progC : section.spec.progression === "b" ? progB : progA;
|
|
15421
|
+
const base = relativeKinds.has(section.kind) ? progRelative : section.spec.progression === "c" ? progC : section.spec.progression === "b" ? progB : progA;
|
|
14785
15422
|
for (let i2 = 0; i2 < section.bars; i2 += 4) {
|
|
14786
15423
|
const isLastPhrase = i2 + 4 >= section.bars;
|
|
14787
15424
|
if (!isLastPhrase) {
|
|
14788
15425
|
progression.push(...base);
|
|
14789
15426
|
continue;
|
|
14790
15427
|
}
|
|
14791
|
-
if (section.kind
|
|
15428
|
+
if (relativeKinds.has(section.kind)) progression.push(...base);
|
|
15429
|
+
else if (section.kind === "prechorus") progression.push(...progHalf);
|
|
14792
15430
|
else if (section.kind === "chorus" || section.kind === "outro")
|
|
14793
|
-
progression.push(
|
|
15431
|
+
progression.push(
|
|
15432
|
+
...floating ? progHalf : section.startBar === lastChorusBar ? progFull : progDeceptive
|
|
15433
|
+
);
|
|
14794
15434
|
else progression.push(...base);
|
|
14795
15435
|
}
|
|
14796
15436
|
}
|
|
14797
15437
|
progression.length = totalBars;
|
|
15438
|
+
const PIVOT_CHORDS = {
|
|
15439
|
+
7: ["C", "Em7", "G", "Am"],
|
|
15440
|
+
// 属調(ト長調)と共通
|
|
15441
|
+
5: ["C", "Dm7", "F", "Am"]
|
|
15442
|
+
// 下属調(ヘ長調)と共通
|
|
15443
|
+
};
|
|
15444
|
+
for (let bar = 1; bar < totalBars; bar++) {
|
|
15445
|
+
const shift = barKeyShift[bar];
|
|
15446
|
+
const prev = barKeyShift[bar - 1];
|
|
15447
|
+
if (shift === prev) continue;
|
|
15448
|
+
const distance = fifthsDistance(shift - prev);
|
|
15449
|
+
if (distance >= 4) continue;
|
|
15450
|
+
const prevSec = sectionAt(sectionPlan, bar - 1);
|
|
15451
|
+
if (prevSec.kind === "prechorus" || prevSec.kind === "chorus" || prevSec.kind === "outro")
|
|
15452
|
+
continue;
|
|
15453
|
+
if (rnd() < 0.35) continue;
|
|
15454
|
+
const pivots = PIVOT_CHORDS[((shift - prev) % 12 + 12) % 12];
|
|
15455
|
+
if (distance <= 1 && pivots && rnd() < 0.6) {
|
|
15456
|
+
progression[bar - 1] = pick(pivots, rnd);
|
|
15457
|
+
} else {
|
|
15458
|
+
progression[bar - 1] = transposeChordName("G7", shift - prev);
|
|
15459
|
+
}
|
|
15460
|
+
}
|
|
15461
|
+
if (rnd() < 0.3) {
|
|
15462
|
+
const tonicNames = tonic === "Am" ? ["Am", "Am7"] : ["C", "CM7"];
|
|
15463
|
+
const spots = [];
|
|
15464
|
+
for (let bar = 0; bar + 1 < totalBars; bar++) {
|
|
15465
|
+
if (barKeyShift[bar] !== barKeyShift[bar + 1]) continue;
|
|
15466
|
+
if (!MODAL_BORROW[progression[bar]]) continue;
|
|
15467
|
+
if (!tonicNames.includes(progression[bar + 1])) continue;
|
|
15468
|
+
spots.push(bar);
|
|
15469
|
+
}
|
|
15470
|
+
if (spots.length > 0) {
|
|
15471
|
+
const at = pick(spots, rnd);
|
|
15472
|
+
progression[at] = MODAL_BORROW[progression[at]];
|
|
15473
|
+
}
|
|
15474
|
+
}
|
|
14798
15475
|
const chordProgression = progression.map((chord, bar) => transposeChordName(chord, barKeyShift[bar])).join("|");
|
|
14799
|
-
const chordPattern = pick(CHORD_PATTERNS, rnd);
|
|
14800
15476
|
const rootShift = resolvedKey.rootShift;
|
|
14801
15477
|
const bpm = pick(BPM_CHOICES, rnd);
|
|
15478
|
+
const chordPattern = pick(chordPatternPool(bpm), rnd);
|
|
14802
15479
|
const sourceOf = (kind) => kind === "chorus" || kind === "interlude" || kind === "drop_chorus" ? "b" : kind === "prechorus" ? "a2" : kind === "bridge" ? "c" : "a";
|
|
15480
|
+
const landingOf = (section) => {
|
|
15481
|
+
if (section.spec.landing === null) return null;
|
|
15482
|
+
const minorHere = resolvedKey.mode === "minor" !== relativeKinds.has(section.kind);
|
|
15483
|
+
let landing = (section.spec.landing + (minorHere ? 5 : 0)) % 7;
|
|
15484
|
+
if (floating && landing === (minorHere ? 5 : 0))
|
|
15485
|
+
landing = (landing + pick([2, 4], rnd)) % 7;
|
|
15486
|
+
return landing;
|
|
15487
|
+
};
|
|
14803
15488
|
const units2 = [];
|
|
14804
15489
|
for (const section of sectionPlan) {
|
|
14805
15490
|
const unitCount = Math.max(1, Math.round(section.bars / 2));
|
|
@@ -14817,22 +15502,28 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14817
15502
|
const isLast = u === unitCount - 1;
|
|
14818
15503
|
if (u % 2 === 0) {
|
|
14819
15504
|
units2.push({
|
|
14820
|
-
role: section.kind === "chorus" ? "climax" : src === "a2" || u > 0 ? "sequence" : "motif",
|
|
15505
|
+
role: section.kind === "bridge" ? "step" : section.kind === "chorus" ? "climax" : src === "a2" || u > 0 ? "sequence" : "motif",
|
|
14821
15506
|
source: src,
|
|
14822
15507
|
landing: null,
|
|
14823
15508
|
section
|
|
14824
15509
|
});
|
|
14825
15510
|
} else {
|
|
15511
|
+
const landing = landingOf(section);
|
|
14826
15512
|
units2.push({
|
|
14827
|
-
role: isLast &&
|
|
15513
|
+
role: isLast && landing === 0 ? "cadence" : "answer",
|
|
14828
15514
|
source: "answer",
|
|
14829
|
-
landing: isLast ?
|
|
15515
|
+
landing: isLast ? landing : null,
|
|
14830
15516
|
section
|
|
14831
15517
|
});
|
|
14832
15518
|
}
|
|
14833
15519
|
}
|
|
14834
15520
|
}
|
|
14835
15521
|
const barRoles = units2.flatMap((u) => [u.role, u.role]);
|
|
15522
|
+
for (const section of sectionPlan) {
|
|
15523
|
+
if (section.kind !== "prechorus") continue;
|
|
15524
|
+
const last = section.startBar + section.bars - 1;
|
|
15525
|
+
if (last < barRoles.length) barRoles[last] = "run";
|
|
15526
|
+
}
|
|
14836
15527
|
const barInUnit = (bar) => bar % 2;
|
|
14837
15528
|
const unitOf = (bar) => Math.floor(bar / 2);
|
|
14838
15529
|
const restatementOf = (bar) => {
|
|
@@ -14863,8 +15554,9 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14863
15554
|
groove: pick(["eighth", "sixteenth"], rnd),
|
|
14864
15555
|
arcPeriod: pick([4, 8, 8, 16], rnd),
|
|
14865
15556
|
arcPhase: pick([0, 1, 2], rnd),
|
|
14866
|
-
arcAmp:
|
|
14867
|
-
|
|
15557
|
+
arcAmp: 2 + rnd() * 3,
|
|
15558
|
+
// オクターブ跳躍は参考曲では音程の1.0%しかない。上げすぎると音域が広がる。
|
|
15559
|
+
octaveAffinity: 0.06 + rnd() * 0.12,
|
|
14868
15560
|
pentatonicMotif: rnd() < 0.55,
|
|
14869
15561
|
runShape: pick(["scale", "turn", "broken", "zigzag"], rnd),
|
|
14870
15562
|
stepShape: pick(
|
|
@@ -14876,10 +15568,14 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14876
15568
|
["descend", "five-three-one", "leap-up", "hold-tonic"],
|
|
14877
15569
|
rnd
|
|
14878
15570
|
),
|
|
14879
|
-
//
|
|
14880
|
-
|
|
15571
|
+
// 参考曲の跳躍率は p25〜p75 で 0.28〜0.41、最大跳躍の中央値は9半音。
|
|
15572
|
+
// 2声を交互に書いたチャンネルを主旋律と誤検出していた頃は 0.31〜0.65 に
|
|
15573
|
+
// 見えており、それに合わせて上限を高く取っていた。
|
|
15574
|
+
leapAffinity: 0.05 + rnd() * 0.2,
|
|
14881
15575
|
// 界隈曲らしさ:調の外の音(クロマチック)や微小な逸脱を積極的に許容する。
|
|
14882
|
-
|
|
15576
|
+
// 刻みを細かくすると経過音の置き場所が増えるので、同じ係数でも変化音は増える。
|
|
15577
|
+
// 参考曲の1.75倍まで伸びていたぶんを引く。
|
|
15578
|
+
chromaticAffinity: rnd() < 0.2 ? 0 : 0.12 + rnd() * 0.33,
|
|
14883
15579
|
barHeadWeight: rnd() < 0.5 ? 3 : 2,
|
|
14884
15580
|
bassStyle: pick(
|
|
14885
15581
|
[
|
|
@@ -14906,7 +15602,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14906
15602
|
subInterval: pick([3, 4, 8, 9], rnd)
|
|
14907
15603
|
};
|
|
14908
15604
|
const motifPool = groovyCells(MOTIF_CELLS, style.groove, rnd);
|
|
14909
|
-
const targetNotesPerBar = 4 + rnd() * 4;
|
|
15605
|
+
const targetNotesPerBar = 4.5 + rnd() * 4.5;
|
|
14910
15606
|
const targetRestRatio = 0.02 + rnd() * 0.1;
|
|
14911
15607
|
const cellNotes = (c) => c.value.filter((v) => v > 0).length;
|
|
14912
15608
|
const cellRest = (c) => {
|
|
@@ -14919,17 +15615,27 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14919
15615
|
return total === 0 ? 0 : rest / total;
|
|
14920
15616
|
};
|
|
14921
15617
|
const cellDistance = (c, densityMul = 1) => Math.abs(cellNotes(c) - targetNotesPerBar * densityMul) + Math.abs(cellRest(c) - targetRestRatio / Math.max(0.5, densityMul)) * 8;
|
|
15618
|
+
const weightedPick = (pool) => {
|
|
15619
|
+
let total = 0;
|
|
15620
|
+
for (const c of pool) total += cellWeight(c);
|
|
15621
|
+
let r = rnd() * total;
|
|
15622
|
+
for (const c of pool) {
|
|
15623
|
+
r -= cellWeight(c);
|
|
15624
|
+
if (r <= 0) return c;
|
|
15625
|
+
}
|
|
15626
|
+
return pool[pool.length - 1];
|
|
15627
|
+
};
|
|
14922
15628
|
const pickCell = (pool, densityMul = 1) => {
|
|
14923
|
-
let best =
|
|
15629
|
+
let best = weightedPick(pool);
|
|
14924
15630
|
for (let i2 = 0; i2 < 2; i2++) {
|
|
14925
|
-
const c =
|
|
15631
|
+
const c = weightedPick(pool);
|
|
14926
15632
|
if (cellDistance(c, densityMul) < cellDistance(best, densityMul))
|
|
14927
15633
|
best = c;
|
|
14928
15634
|
}
|
|
14929
15635
|
return best;
|
|
14930
15636
|
};
|
|
14931
15637
|
const motifCell = pickCell(motifPool, 0.85);
|
|
14932
|
-
const motifCell2 = rnd() < 0.
|
|
15638
|
+
const motifCell2 = rnd() < 0.72 ? motifCell : pickCell(
|
|
14933
15639
|
motifPool.filter((c) => c !== motifCell),
|
|
14934
15640
|
0.85
|
|
14935
15641
|
);
|
|
@@ -14947,7 +15653,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14947
15653
|
),
|
|
14948
15654
|
1.1
|
|
14949
15655
|
);
|
|
14950
|
-
const motifA22 = rnd() < 0.
|
|
15656
|
+
const motifA22 = rnd() < 0.72 ? motifA2 : pickCell(
|
|
14951
15657
|
motifPool.filter((c) => c !== motifA2),
|
|
14952
15658
|
1.1
|
|
14953
15659
|
);
|
|
@@ -14957,7 +15663,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14957
15663
|
),
|
|
14958
15664
|
0.9
|
|
14959
15665
|
);
|
|
14960
|
-
const motifC2 = rnd() < 0.
|
|
15666
|
+
const motifC2 = rnd() < 0.72 ? motifC : pickCell(
|
|
14961
15667
|
motifPool.filter((c) => c !== motifC),
|
|
14962
15668
|
0.9
|
|
14963
15669
|
);
|
|
@@ -14996,12 +15702,24 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14996
15702
|
),
|
|
14997
15703
|
rnd
|
|
14998
15704
|
).value;
|
|
14999
|
-
const
|
|
15000
|
-
|
|
15001
|
-
|
|
15002
|
-
)
|
|
15003
|
-
|
|
15004
|
-
|
|
15705
|
+
const breathBySection = /* @__PURE__ */ new Map();
|
|
15706
|
+
{
|
|
15707
|
+
let prev = null;
|
|
15708
|
+
for (const section of sectionPlan) {
|
|
15709
|
+
if (!section.spec.melody) continue;
|
|
15710
|
+
const pool = PHRASE_END_CELLS.filter((c) => c !== prev);
|
|
15711
|
+
const cell = pick(pool.length > 0 ? pool : PHRASE_END_CELLS, rnd);
|
|
15712
|
+
breathBySection.set(section.startBar, cell);
|
|
15713
|
+
prev = cell;
|
|
15714
|
+
}
|
|
15715
|
+
}
|
|
15716
|
+
const midBreathCell = pick(MID_BREATH_CELLS, rnd);
|
|
15717
|
+
const breathBars = /* @__PURE__ */ new Set();
|
|
15718
|
+
const phraseEndBars = /* @__PURE__ */ new Set();
|
|
15719
|
+
for (const section of sectionPlan) {
|
|
15720
|
+
if (!section.spec.melody) continue;
|
|
15721
|
+
phraseEndBars.add(section.startBar + section.bars - 1);
|
|
15722
|
+
}
|
|
15005
15723
|
const barRhythms = [];
|
|
15006
15724
|
for (let bar = 0; bar < totalBars; bar++) {
|
|
15007
15725
|
const u = unitOf(bar);
|
|
@@ -15009,6 +15727,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15009
15727
|
const source = restatementOf(bar);
|
|
15010
15728
|
if (source !== null) {
|
|
15011
15729
|
barRhythms.push(barRhythms[source]);
|
|
15730
|
+
if (breathBars.has(source)) breathBars.add(bar);
|
|
15012
15731
|
continue;
|
|
15013
15732
|
}
|
|
15014
15733
|
const isB = units2[u].source === "b";
|
|
@@ -15026,7 +15745,14 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15026
15745
|
const prevSource = units2[u - 1]?.source;
|
|
15027
15746
|
const [head, tail] = prevSource === "b" ? [motifB, motifB2] : prevSource === "a2" ? [motifA2, motifA22] : [motifCell, motifCell2];
|
|
15028
15747
|
const answerVar = prevSource === "b" ? motifBVar : motifVar;
|
|
15029
|
-
|
|
15748
|
+
if (half === 0) {
|
|
15749
|
+
cell = rnd() < 0.15 ? answerVar : head;
|
|
15750
|
+
} else if (isPeriodEnd) {
|
|
15751
|
+
cell = breathBySection.get(units2[u].section.startBar) ?? tail;
|
|
15752
|
+
breathBars.add(bar);
|
|
15753
|
+
} else {
|
|
15754
|
+
cell = rnd() < 0.28 ? midBreathCell : rnd() < 0.12 ? answerVar : tail;
|
|
15755
|
+
}
|
|
15030
15756
|
} else {
|
|
15031
15757
|
const [head, tail] = pair();
|
|
15032
15758
|
cell = half === 0 ? head : tail;
|
|
@@ -15047,10 +15773,12 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15047
15773
|
motifContour.push(baseDegree + archetype[idx]);
|
|
15048
15774
|
}
|
|
15049
15775
|
const plannedDegrees = new Array(totalBars).fill(null);
|
|
15776
|
+
const motifShiftMemo = /* @__PURE__ */ new Map();
|
|
15050
15777
|
const melody = [];
|
|
15051
15778
|
const submelody = [];
|
|
15052
15779
|
const bass = [];
|
|
15053
15780
|
const harmony = [];
|
|
15781
|
+
const harmony2 = [];
|
|
15054
15782
|
const pad = [];
|
|
15055
15783
|
const melodyDurations = [];
|
|
15056
15784
|
const barTension = new Array(totalBars).fill(0);
|
|
@@ -15142,34 +15870,36 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15142
15870
|
if (landing !== null && barInUnit(bar) === 1) landOn(degrees, landing);
|
|
15143
15871
|
plannedDegrees[bar] = [...degrees];
|
|
15144
15872
|
const isMotifBar = source !== null || role === "motif" || role === "sequence" || role === "climax" || role === "answer";
|
|
15145
|
-
|
|
15146
|
-
|
|
15873
|
+
let fitted = degrees;
|
|
15874
|
+
if (isMotifBar) {
|
|
15875
|
+
const shiftKey = degrees.join(",");
|
|
15876
|
+
const r = fitMotif(
|
|
15147
15877
|
degrees,
|
|
15148
15878
|
slots,
|
|
15149
15879
|
tones,
|
|
15150
15880
|
prevSemi,
|
|
15151
15881
|
quarterSteps,
|
|
15152
|
-
style.pentatonicMotif
|
|
15153
|
-
|
|
15154
|
-
|
|
15155
|
-
|
|
15156
|
-
|
|
15157
|
-
|
|
15158
|
-
|
|
15159
|
-
|
|
15160
|
-
|
|
15161
|
-
|
|
15162
|
-
|
|
15163
|
-
|
|
15164
|
-
|
|
15165
|
-
|
|
15166
|
-
|
|
15167
|
-
|
|
15168
|
-
|
|
15169
|
-
|
|
15170
|
-
|
|
15171
|
-
|
|
15172
|
-
);
|
|
15882
|
+
style.pentatonicMotif,
|
|
15883
|
+
motifShiftMemo.get(shiftKey) ?? null
|
|
15884
|
+
);
|
|
15885
|
+
fitted = r.degrees;
|
|
15886
|
+
motifShiftMemo.set(shiftKey, r.shift);
|
|
15887
|
+
}
|
|
15888
|
+
const pitches = shapeBar(fitted, slots, tones, prevSemi, {
|
|
15889
|
+
allowLeap: role === "climax",
|
|
15890
|
+
allowArpeggio: role === "climax" || role === "run" && style.runShape === "broken" || role === "cadence" && style.cadenceShape !== "descend",
|
|
15891
|
+
quarterSteps,
|
|
15892
|
+
// モチーフの小節はオクターブ移動を入れない。モチーフは輪郭が命なので、
|
|
15893
|
+
// 後から音を1つ跳ばすと「同じフレーズが返ってきた」と分からなくなる。
|
|
15894
|
+
// モチーフ側は {@link MOTIF_ARCHETYPES} が自前でオクターブを持つ。
|
|
15895
|
+
// モチーフ・セクエンツ・サビの小節はオクターブ移動を入れない
|
|
15896
|
+
// (輪郭が命なので、後から音を1つ跳ばすと同じフレーズと分からなくなる)。
|
|
15897
|
+
// 答えの小節は輪郭を借りているだけなので許す。
|
|
15898
|
+
octaveAffinity: role === "motif" || role === "sequence" || role === "climax" ? 0 : style.octaveAffinity,
|
|
15899
|
+
chromaticAffinity: style.chromaticAffinity,
|
|
15900
|
+
rnd,
|
|
15901
|
+
preserveContour: isMotifBar
|
|
15902
|
+
});
|
|
15173
15903
|
if (landing !== null && barInUnit(bar) === 1) landPitch(pitches, landing);
|
|
15174
15904
|
const fifths = pitches.map(diatonicFifth);
|
|
15175
15905
|
applyChromatic(pitches, fifths, slots, tones, {
|
|
@@ -15294,23 +16024,50 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15294
16024
|
pushSub(scaleStep(QUARTER), scaleStep(DOT_HALF), subSemi);
|
|
15295
16025
|
}
|
|
15296
16026
|
const barSec = sectionAt(sectionPlan, bar);
|
|
15297
|
-
if (!silent && (barSec.kind
|
|
15298
|
-
|
|
15299
|
-
|
|
15300
|
-
|
|
15301
|
-
|
|
15302
|
-
const
|
|
15303
|
-
|
|
15304
|
-
|
|
15305
|
-
|
|
15306
|
-
|
|
15307
|
-
|
|
15308
|
-
|
|
15309
|
-
|
|
15310
|
-
|
|
15311
|
-
|
|
15312
|
-
|
|
15313
|
-
|
|
16027
|
+
if (!silent && harmonyKinds.includes(barSec.kind)) {
|
|
16028
|
+
const k = barKeyShift[bar];
|
|
16029
|
+
const fifthShift = k === 0 ? 0 : SEMITONE_TO_FIFTH_SHIFT[(k % 12 + 12) % 12];
|
|
16030
|
+
const writeHarmony = (out, prev, offset, against) => {
|
|
16031
|
+
let last = prev;
|
|
16032
|
+
const written = [];
|
|
16033
|
+
for (let i2 = 0; i2 < slots.length; i2++) {
|
|
16034
|
+
const hTone = harmonyPitch(
|
|
16035
|
+
pitches[i2],
|
|
16036
|
+
tones,
|
|
16037
|
+
last,
|
|
16038
|
+
offset,
|
|
16039
|
+
harmonyParallel,
|
|
16040
|
+
against?.[i2] ?? null
|
|
16041
|
+
);
|
|
16042
|
+
let hClamped = clampSemi(
|
|
16043
|
+
hTone.semi,
|
|
16044
|
+
MELODY_LOW - 12,
|
|
16045
|
+
MELODY_HIGH + 7
|
|
16046
|
+
);
|
|
16047
|
+
while (hClamped - pitches[i2] > 12) hClamped -= 12;
|
|
16048
|
+
while (hClamped - pitches[i2] < -12) hClamped += 12;
|
|
16049
|
+
last = hClamped;
|
|
16050
|
+
written.push(hClamped);
|
|
16051
|
+
const keep = slots[i2].isStrong || slots[i2].value >= quarterSteps || rnd() < harmonyCoverage;
|
|
16052
|
+
if (!keep) continue;
|
|
16053
|
+
out.push({
|
|
16054
|
+
startStep: barStart + slots[i2].at,
|
|
16055
|
+
pitchUnits: spelledToUnits(
|
|
16056
|
+
hClamped + k,
|
|
16057
|
+
hTone.fifth + fifthShift,
|
|
16058
|
+
edo
|
|
16059
|
+
),
|
|
16060
|
+
durationSteps: slots[i2].value,
|
|
16061
|
+
velocity: slots[i2].at === 0 ? 82 : 76
|
|
16062
|
+
});
|
|
16063
|
+
}
|
|
16064
|
+
return written;
|
|
16065
|
+
};
|
|
16066
|
+
const h1 = writeHarmony(harmony, prevHarmony, harmonyOffset, null);
|
|
16067
|
+
prevHarmony = h1[h1.length - 1] ?? prevHarmony;
|
|
16068
|
+
if (useHarmony2) {
|
|
16069
|
+
const h2 = writeHarmony(harmony2, prevHarmony2, harmony2Offset, h1);
|
|
16070
|
+
prevHarmony2 = h2[h2.length - 1] ?? prevHarmony2;
|
|
15314
16071
|
}
|
|
15315
16072
|
}
|
|
15316
16073
|
if (barSec.kind === "prechorus" || barSec.kind === "chorus" || barSec.kind === "bridge" || barSec.kind === "drop_chorus") {
|
|
@@ -15442,6 +16199,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15442
16199
|
for (const n of barBass) bass.push(n);
|
|
15443
16200
|
}
|
|
15444
16201
|
const eighthSteps = scaleStep(EIGHTH);
|
|
16202
|
+
const tieMemo = /* @__PURE__ */ new Map();
|
|
15445
16203
|
for (let i2 = 0; i2 < melody.length - 1; i2++) {
|
|
15446
16204
|
const cur = melody[i2];
|
|
15447
16205
|
const nxt = melody[i2 + 1];
|
|
@@ -15455,16 +16213,28 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15455
16213
|
const curSec = sectionAt(sectionPlan, barIdx - 1);
|
|
15456
16214
|
const nextSec = sectionAt(sectionPlan, barIdx);
|
|
15457
16215
|
if (!nextSec.spec.melody || curSec !== nextSec) continue;
|
|
16216
|
+
if (breathBars.has(barIdx)) continue;
|
|
15458
16217
|
const curSemi = Math.round(cur.pitchUnits / UNITS_PER_SEMITONE);
|
|
15459
16218
|
const nxtSemi = Math.round(nxt.pitchUnits / UNITS_PER_SEMITONE);
|
|
15460
16219
|
if (Math.abs(nxtSemi - curSemi) > 3) continue;
|
|
16220
|
+
const after = melody[i2 + 2];
|
|
16221
|
+
if (after && Math.floor(after.startStep / stepsPerBar) === barIdx) {
|
|
16222
|
+
const afterSemi = Math.round(after.pitchUnits / UNITS_PER_SEMITONE) - (barKeyShift[barIdx] ?? 0);
|
|
16223
|
+
if (!DIATONIC_PCS.has(pitchClass(afterSemi))) continue;
|
|
16224
|
+
}
|
|
15461
16225
|
const nextRole = barRoles[barIdx];
|
|
15462
|
-
let tieProb = 0.
|
|
15463
|
-
if (nextRole === "motif") tieProb = 0.
|
|
15464
|
-
else if (nextRole === "sequence") tieProb = 0.
|
|
15465
|
-
else if (nextRole === "climax") tieProb = 0.
|
|
16226
|
+
let tieProb = 0.3;
|
|
16227
|
+
if (nextRole === "motif") tieProb = 0.1;
|
|
16228
|
+
else if (nextRole === "sequence") tieProb = 0.35;
|
|
16229
|
+
else if (nextRole === "climax") tieProb = 0.45;
|
|
15466
16230
|
else if (nextRole === "cadence") tieProb = 0.1;
|
|
15467
|
-
|
|
16231
|
+
const tieKey = `${barRhythms[barIdx].join(",")}|${barInUnit(barIdx)}`;
|
|
16232
|
+
let tie = tieMemo.get(tieKey);
|
|
16233
|
+
if (tie === void 0) {
|
|
16234
|
+
tie = rnd() < tieProb;
|
|
16235
|
+
tieMemo.set(tieKey, tie);
|
|
16236
|
+
}
|
|
16237
|
+
if (tie) {
|
|
15468
16238
|
cur.durationSteps += nxt.durationSteps;
|
|
15469
16239
|
melody.splice(i2 + 1, 1);
|
|
15470
16240
|
if (i2 < melodyDurations.length - 1) {
|
|
@@ -15480,15 +16250,32 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15480
16250
|
i2--;
|
|
15481
16251
|
}
|
|
15482
16252
|
}
|
|
16253
|
+
const splitMemo = /* @__PURE__ */ new Map();
|
|
16254
|
+
let splitLastBar = -1;
|
|
16255
|
+
let splitIdxInBar = 0;
|
|
15483
16256
|
for (let i2 = 0; i2 < melody.length; i2++) {
|
|
15484
16257
|
const barIdx = Math.floor(melody[i2].startStep / stepsPerBar);
|
|
16258
|
+
if (barIdx !== splitLastBar) {
|
|
16259
|
+
splitLastBar = barIdx;
|
|
16260
|
+
splitIdxInBar = 0;
|
|
16261
|
+
} else splitIdxInBar++;
|
|
15485
16262
|
if (barIdx >= totalBars) continue;
|
|
16263
|
+
if (phraseEndBars.has(barIdx)) continue;
|
|
15486
16264
|
const role = barRoles[barIdx];
|
|
15487
|
-
let splitProb = 0.
|
|
16265
|
+
let splitProb = 0.08;
|
|
15488
16266
|
if (role === "motif" || role === "sequence") splitProb = 0;
|
|
15489
|
-
else if (role === "climax") splitProb = 0.
|
|
16267
|
+
else if (role === "climax") splitProb = 0.3;
|
|
15490
16268
|
else if (role === "cadence") splitProb = 0;
|
|
15491
|
-
|
|
16269
|
+
let doSplit = false;
|
|
16270
|
+
if (melody[i2].durationSteps === quarterSteps) {
|
|
16271
|
+
const key = `${barRhythms[barIdx].join(",")}|${barInUnit(barIdx)}|${role}|${splitIdxInBar}`;
|
|
16272
|
+
const memo = splitMemo.get(key);
|
|
16273
|
+
if (memo === void 0) {
|
|
16274
|
+
doSplit = rnd() < splitProb;
|
|
16275
|
+
splitMemo.set(key, doSplit);
|
|
16276
|
+
} else doSplit = memo;
|
|
16277
|
+
}
|
|
16278
|
+
if (doSplit) {
|
|
15492
16279
|
const half = scaleStep(EIGHTH);
|
|
15493
16280
|
const newNote = {
|
|
15494
16281
|
...melody[i2],
|
|
@@ -15502,6 +16289,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15502
16289
|
melodyDurations.splice(i2 + 1, 0, half);
|
|
15503
16290
|
}
|
|
15504
16291
|
i2++;
|
|
16292
|
+
splitIdxInBar++;
|
|
15505
16293
|
}
|
|
15506
16294
|
}
|
|
15507
16295
|
const range = (notes) => {
|
|
@@ -15511,8 +16299,11 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15511
16299
|
};
|
|
15512
16300
|
const shiftUnits = semitonesToUnits(rootShift, edo);
|
|
15513
16301
|
if (shiftUnits !== 0)
|
|
15514
|
-
for (const list of [melody, submelody, bass, harmony, pad])
|
|
16302
|
+
for (const list of [melody, submelody, bass, harmony, harmony2, pad])
|
|
15515
16303
|
for (const n of list) n.pitchUnits = n.pitchUnits + shiftUnits;
|
|
16304
|
+
const octave = useOctaveLayer ? melody.filter(
|
|
16305
|
+
(n) => n.durationSteps >= quarterSteps || rnd() < octaveCoverage
|
|
16306
|
+
).map((n) => ({ ...n, velocity: Math.max(40, n.velocity - 26) })) : [];
|
|
15516
16307
|
return {
|
|
15517
16308
|
chordProgression,
|
|
15518
16309
|
chordPattern,
|
|
@@ -15523,10 +16314,20 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15523
16314
|
bpm,
|
|
15524
16315
|
sections: sectionPlan,
|
|
15525
16316
|
bars: totalBars,
|
|
16317
|
+
vocal: {
|
|
16318
|
+
duetSpans,
|
|
16319
|
+
duetStyle,
|
|
16320
|
+
harmonyKinds,
|
|
16321
|
+
harmony2: useHarmony2,
|
|
16322
|
+
octaveLayer: useOctaveLayer
|
|
16323
|
+
},
|
|
16324
|
+
tonal: { relativeKinds: [...relativeKinds], relativeShift, floating },
|
|
15526
16325
|
melody,
|
|
15527
16326
|
submelody,
|
|
15528
16327
|
bass,
|
|
15529
16328
|
harmony,
|
|
16329
|
+
harmony2,
|
|
16330
|
+
octave,
|
|
15530
16331
|
pad,
|
|
15531
16332
|
melodyDurations,
|
|
15532
16333
|
restSteps,
|
|
@@ -15598,6 +16399,8 @@ var evaluate = (d, recent) => {
|
|
|
15598
16399
|
melodyRange: atc("melodyRange", d.melodyRange),
|
|
15599
16400
|
notesPerBar: atc("notesPerBar", density.notesPerBar),
|
|
15600
16401
|
shortNoteRatio: atc("shortNoteRatio", density.shortNoteRatio),
|
|
16402
|
+
barDensityCv: atc("barDensityCv", density.barDensityCv),
|
|
16403
|
+
densityCliff: atc("densityCliff", density.densityCliff),
|
|
15601
16404
|
stepRatio: atc("stepRatio", d.stepRatio),
|
|
15602
16405
|
chromaticRatio: atc("chromaticRatio", d.chromaticRatio),
|
|
15603
16406
|
sim1: atc("sim1", structure.sim1),
|
|
@@ -15605,12 +16408,20 @@ var evaluate = (d, recent) => {
|
|
|
15605
16408
|
sim4: atc("sim4", structure.sim4),
|
|
15606
16409
|
sim8: atc("sim8", structure.sim8),
|
|
15607
16410
|
phraseBreath: atc("phraseBreath", structure.phraseBreath),
|
|
16411
|
+
turnRatio: atc("turnRatio", structure.turnRatio),
|
|
15608
16412
|
climaxPosition: atc("climaxPosition", structure.climaxPosition),
|
|
15609
16413
|
climaxPeaks: at(peakBand, structure.climaxPeaks),
|
|
15610
16414
|
complementarity: at(HAND_BANDS.complementarity, structure.complementarity),
|
|
15611
16415
|
subDensity: at(HAND_BANDS.subDensity, d.submelody.length / d.bars),
|
|
16416
|
+
// サブメロにも同じ崖の物差しを当てる。帯はメロディから採ったものを流用する。
|
|
16417
|
+
subDensityCliff: atc(
|
|
16418
|
+
"densityCliff",
|
|
16419
|
+
densityFeatures(fromMelody(toMetricNotes(d.submelody)), opts).densityCliff
|
|
16420
|
+
),
|
|
15612
16421
|
tensionRise: tension.rise,
|
|
15613
|
-
|
|
16422
|
+
// **浮遊感の曲に「終止で解決しろ」は要求しない。** 解決しないことが狙いなので、
|
|
16423
|
+
// この項目で減点すると候補40本の選抜で必ず負けて、狙って引いた曲が出てこない。
|
|
16424
|
+
tensionResolve: d.tonal.floating ? 1 : tension.resolve,
|
|
15614
16425
|
novelty
|
|
15615
16426
|
};
|
|
15616
16427
|
let weighted = 0;
|
|
@@ -15673,10 +16484,14 @@ var composeSong = (options) => {
|
|
|
15673
16484
|
bpm: d.bpm,
|
|
15674
16485
|
sections: d.sections,
|
|
15675
16486
|
bars: d.bars,
|
|
16487
|
+
vocal: d.vocal,
|
|
16488
|
+
tonal: d.tonal,
|
|
15676
16489
|
melody: d.melody,
|
|
15677
16490
|
submelody: d.submelody,
|
|
15678
16491
|
bass: d.bass,
|
|
15679
16492
|
harmony: d.harmony,
|
|
16493
|
+
harmony2: d.harmony2,
|
|
16494
|
+
octave: d.octave,
|
|
15680
16495
|
pad: d.pad,
|
|
15681
16496
|
stats: { ...stats, attempts: attempt, rejected }
|
|
15682
16497
|
};
|
|
@@ -15691,7 +16506,10 @@ var composeSong = (options) => {
|
|
|
15691
16506
|
var pickBuiltinDrum = (song, rnd) => {
|
|
15692
16507
|
const eighth = BASE_STEPS_PER_BAR / 8;
|
|
15693
16508
|
const short = song.melody.filter((n) => n.durationSteps <= eighth).length / Math.max(1, song.melody.length);
|
|
15694
|
-
const
|
|
16509
|
+
const dotted = song.melody.filter(
|
|
16510
|
+
(n) => n.durationSteps === Math.round(BASE_STEPS_PER_BAR * 3 / 16)
|
|
16511
|
+
).length / Math.max(1, song.melody.length);
|
|
16512
|
+
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"];
|
|
15695
16513
|
return pick(pool, rnd);
|
|
15696
16514
|
};
|
|
15697
16515
|
var pickBuiltinInstrument = (song, rnd) => {
|
|
@@ -15705,7 +16523,7 @@ var pickBuiltinInstrument = (song, rnd) => {
|
|
|
15705
16523
|
pool = song.bpm >= 150 ? ["cyber_punk", "synth_pop", "retro_game"] : ["synth_pop", "retro_game", "rock", "piano"];
|
|
15706
16524
|
} else if (song.drum === "bossa") {
|
|
15707
16525
|
pool = ["jazz_night", "acoustic", "piano"];
|
|
15708
|
-
} else if (song.bpm <=
|
|
16526
|
+
} else if (song.bpm <= 115) {
|
|
15709
16527
|
pool = ["ambient_cloud", "acoustic", "orchestra", "piano", "fantasy_rpg"];
|
|
15710
16528
|
} else if (song.bpm >= 145) {
|
|
15711
16529
|
pool = ["rock", "synth_pop", "cyber_punk", "retro_game", "piano"];
|
|
@@ -15761,6 +16579,23 @@ var LYRIC_WORDS = [
|
|
|
15761
16579
|
"\u305B\u304B\u3044",
|
|
15762
16580
|
"\u304D\u305B\u3064"
|
|
15763
16581
|
];
|
|
16582
|
+
var alignLyrics = (source, lyrics, target, options) => {
|
|
16583
|
+
const sorted = [...source].sort((a, b) => a.startStep - b.startStep);
|
|
16584
|
+
const kana = [...lyrics].filter((c) => c !== "\u3001");
|
|
16585
|
+
const at = /* @__PURE__ */ new Map();
|
|
16586
|
+
for (let i2 = 0; i2 < sorted.length && i2 < kana.length; i2++)
|
|
16587
|
+
at.set(sorted[i2].startStep, kana[i2]);
|
|
16588
|
+
const { stepsPerBar } = options;
|
|
16589
|
+
const tgt = [...target].sort((a, b) => a.startStep - b.startStep);
|
|
16590
|
+
const out = [];
|
|
16591
|
+
for (let i2 = 0; i2 < tgt.length; i2++) {
|
|
16592
|
+
out.push(at.get(tgt[i2].startStep) ?? "\u30FC");
|
|
16593
|
+
const next = tgt[i2 + 1];
|
|
16594
|
+
if (next && Math.floor(tgt[i2].startStep / (stepsPerBar * 4)) !== Math.floor(next.startStep / (stepsPerBar * 4)))
|
|
16595
|
+
out.push("\u3001");
|
|
16596
|
+
}
|
|
16597
|
+
return out.join("");
|
|
16598
|
+
};
|
|
15764
16599
|
var composeLyrics = (melody, options) => {
|
|
15765
16600
|
const rnd = options.random ?? Math.random;
|
|
15766
16601
|
const { stepsPerBar } = options;
|
|
@@ -17055,56 +17890,95 @@ var exportMIDI = (options) => {
|
|
|
17055
17890
|
const div = 480;
|
|
17056
17891
|
const tickPerStep = div / STEPS_PER_BEAT3;
|
|
17057
17892
|
const midiTracks = [];
|
|
17058
|
-
const NOTE_CHANNELS = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15];
|
|
17059
|
-
const BEND_RANGE_SEMITONES = 2;
|
|
17060
17893
|
const bendKey = (cents) => Math.round(cents * 100);
|
|
17061
|
-
const
|
|
17062
|
-
|
|
17063
|
-
for (const n of track.notes) {
|
|
17894
|
+
const hasMicrotones = tracks.some(
|
|
17895
|
+
(track) => track.notes.some((n) => {
|
|
17064
17896
|
const { detuneCents } = unitsToMidiDetune(n.pitchUnits);
|
|
17065
|
-
|
|
17066
|
-
|
|
17067
|
-
|
|
17068
|
-
}
|
|
17069
|
-
const bendChannel = /* @__PURE__ */ new Map();
|
|
17070
|
-
const ordered = [...bendUse.entries()].sort((a, b) => b[1] - a[1]);
|
|
17071
|
-
for (const [k] of ordered) {
|
|
17072
|
-
if (bendChannel.size >= NOTE_CHANNELS.length) break;
|
|
17073
|
-
bendChannel.set(k, NOTE_CHANNELS[bendChannel.size]);
|
|
17074
|
-
}
|
|
17075
|
-
tracks.forEach((track) => {
|
|
17076
|
-
if (track.notes.length === 0) return;
|
|
17077
|
-
const events = [];
|
|
17078
|
-
for (const n of track.notes) {
|
|
17079
|
-
const { midi, detuneCents } = unitsToMidiDetune(n.pitchUnits);
|
|
17080
|
-
const k = bendKey(detuneCents);
|
|
17081
|
-
const channel = bendChannel.get(k) ?? bendChannel.get(0) ?? 0;
|
|
17082
|
-
const note = Math.max(0, Math.min(127, midi));
|
|
17083
|
-
const startTick = Math.round(n.startStep * tickPerStep);
|
|
17084
|
-
const endTick = Math.round(
|
|
17085
|
-
(n.startStep + (n.durationSteps || 1)) * tickPerStep
|
|
17086
|
-
);
|
|
17087
|
-
const vel = Math.round(
|
|
17088
|
-
(n.velocity ?? DEFAULT_VELOCITY) * (track.volume ?? 100) / 100
|
|
17089
|
-
);
|
|
17090
|
-
events.push({ t: startTick, m: [144 | channel, note, vel] });
|
|
17091
|
-
events.push({ t: endTick, m: [144 | channel, note, 0] });
|
|
17092
|
-
}
|
|
17093
|
-
events.sort((a, b) => a.t - b.t);
|
|
17094
|
-
midiTracks.push(events);
|
|
17095
|
-
});
|
|
17897
|
+
return bendKey(detuneCents) !== 0;
|
|
17898
|
+
})
|
|
17899
|
+
);
|
|
17096
17900
|
const bendSetup = [];
|
|
17097
|
-
|
|
17098
|
-
const
|
|
17099
|
-
|
|
17100
|
-
|
|
17101
|
-
|
|
17102
|
-
|
|
17103
|
-
|
|
17104
|
-
|
|
17105
|
-
|
|
17106
|
-
|
|
17107
|
-
|
|
17901
|
+
if (hasMicrotones) {
|
|
17902
|
+
const NOTE_CHANNELS = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15];
|
|
17903
|
+
const BEND_RANGE_SEMITONES = 2;
|
|
17904
|
+
const bendUse = /* @__PURE__ */ new Map();
|
|
17905
|
+
for (const track of tracks) {
|
|
17906
|
+
for (const n of track.notes) {
|
|
17907
|
+
const { detuneCents } = unitsToMidiDetune(n.pitchUnits);
|
|
17908
|
+
const k = bendKey(detuneCents);
|
|
17909
|
+
bendUse.set(k, (bendUse.get(k) ?? 0) + 1);
|
|
17910
|
+
}
|
|
17911
|
+
}
|
|
17912
|
+
const bendChannel = /* @__PURE__ */ new Map();
|
|
17913
|
+
const ordered = [...bendUse.entries()].sort((a, b) => b[1] - a[1]);
|
|
17914
|
+
for (const [k] of ordered) {
|
|
17915
|
+
if (bendChannel.size >= NOTE_CHANNELS.length) break;
|
|
17916
|
+
bendChannel.set(k, NOTE_CHANNELS[bendChannel.size]);
|
|
17917
|
+
}
|
|
17918
|
+
tracks.forEach((track) => {
|
|
17919
|
+
if (track.notes.length === 0) return;
|
|
17920
|
+
const events = [];
|
|
17921
|
+
for (const n of track.notes) {
|
|
17922
|
+
const { midi, detuneCents } = unitsToMidiDetune(n.pitchUnits);
|
|
17923
|
+
const k = bendKey(detuneCents);
|
|
17924
|
+
const channel = bendChannel.get(k) ?? bendChannel.get(0) ?? 0;
|
|
17925
|
+
const note = Math.max(0, Math.min(127, midi));
|
|
17926
|
+
const startTick = Math.round(n.startStep * tickPerStep);
|
|
17927
|
+
const endTick = Math.round(
|
|
17928
|
+
(n.startStep + (n.durationSteps || 1)) * tickPerStep
|
|
17929
|
+
);
|
|
17930
|
+
const vel = Math.round(
|
|
17931
|
+
(n.velocity ?? DEFAULT_VELOCITY) * (track.volume ?? 100) / 100
|
|
17932
|
+
);
|
|
17933
|
+
events.push({ t: startTick, m: [144 | channel, note, vel] });
|
|
17934
|
+
events.push({ t: endTick, m: [144 | channel, note, 0] });
|
|
17935
|
+
}
|
|
17936
|
+
events.sort((a, b) => a.t - b.t);
|
|
17937
|
+
midiTracks.push(events);
|
|
17938
|
+
});
|
|
17939
|
+
for (const [k, channel] of bendChannel) {
|
|
17940
|
+
const cents = k / 100;
|
|
17941
|
+
bendSetup.push({ t: 0, m: [176 | channel, 101, 0] });
|
|
17942
|
+
bendSetup.push({ t: 0, m: [176 | channel, 100, 0] });
|
|
17943
|
+
bendSetup.push({ t: 0, m: [176 | channel, 6, BEND_RANGE_SEMITONES] });
|
|
17944
|
+
bendSetup.push({ t: 0, m: [176 | channel, 38, 0] });
|
|
17945
|
+
bendSetup.push({ t: 0, m: [176 | channel, 101, 127] });
|
|
17946
|
+
bendSetup.push({ t: 0, m: [176 | channel, 100, 127] });
|
|
17947
|
+
const raw = 8192 + Math.round(cents / (BEND_RANGE_SEMITONES * 100) * 8192);
|
|
17948
|
+
const v = Math.max(0, Math.min(16383, raw));
|
|
17949
|
+
bendSetup.push({ t: 0, m: [224 | channel, v & 127, v >> 7 & 127] });
|
|
17950
|
+
}
|
|
17951
|
+
} else {
|
|
17952
|
+
tracks.forEach((track, trIdx) => {
|
|
17953
|
+
if (track.notes.length === 0) return;
|
|
17954
|
+
const channel = trIdx < 9 ? trIdx : trIdx + 1 & 15;
|
|
17955
|
+
const events = [];
|
|
17956
|
+
if (track.program !== void 0 && track.program >= 0 && track.program <= 127) {
|
|
17957
|
+
events.push({ t: 0, m: [192 | channel, track.program] });
|
|
17958
|
+
}
|
|
17959
|
+
for (const n of track.notes) {
|
|
17960
|
+
const { midi } = unitsToMidiDetune(n.pitchUnits);
|
|
17961
|
+
const note = Math.max(0, Math.min(127, midi));
|
|
17962
|
+
const startTick = Math.round(n.startStep * tickPerStep);
|
|
17963
|
+
const endTick = Math.round(
|
|
17964
|
+
(n.startStep + (n.durationSteps || 1)) * tickPerStep
|
|
17965
|
+
);
|
|
17966
|
+
const vel = Math.round(
|
|
17967
|
+
(n.velocity ?? DEFAULT_VELOCITY) * (track.volume ?? 100) / 100
|
|
17968
|
+
);
|
|
17969
|
+
events.push({ t: startTick, m: [144 | channel, note, vel] });
|
|
17970
|
+
events.push({ t: endTick, m: [144 | channel, note, 0] });
|
|
17971
|
+
}
|
|
17972
|
+
events.sort((a, b) => {
|
|
17973
|
+
if (a.t !== b.t) return a.t - b.t;
|
|
17974
|
+
const typeA = a.m[0] & 240;
|
|
17975
|
+
const typeB = b.m[0] & 240;
|
|
17976
|
+
if (typeA === 192 && typeB !== 192) return -1;
|
|
17977
|
+
if (typeB === 192 && typeA !== 192) return 1;
|
|
17978
|
+
return 0;
|
|
17979
|
+
});
|
|
17980
|
+
midiTracks.push(events);
|
|
17981
|
+
});
|
|
17108
17982
|
}
|
|
17109
17983
|
const maxStep = Math.max(
|
|
17110
17984
|
...tracks.filter((t) => t.notes.length > 0).map(
|
|
@@ -18329,6 +19203,28 @@ var createRenderer = (mountTarget, width = 800, height = 450, config) => {
|
|
|
18329
19203
|
};
|
|
18330
19204
|
};
|
|
18331
19205
|
|
|
19206
|
+
// src/track1-state.ts
|
|
19207
|
+
var TRACK1_STORAGE_KEY = "dtm-track1:settings";
|
|
19208
|
+
var readTrack1Settings = () => {
|
|
19209
|
+
try {
|
|
19210
|
+
if (typeof localStorage === "undefined" || !localStorage) return null;
|
|
19211
|
+
const raw = localStorage.getItem(TRACK1_STORAGE_KEY);
|
|
19212
|
+
if (!raw) return null;
|
|
19213
|
+
const parsed = JSON.parse(raw);
|
|
19214
|
+
if (!parsed || typeof parsed !== "object") return null;
|
|
19215
|
+
return parsed;
|
|
19216
|
+
} catch (_) {
|
|
19217
|
+
return null;
|
|
19218
|
+
}
|
|
19219
|
+
};
|
|
19220
|
+
var writeTrack1Settings = (settings) => {
|
|
19221
|
+
try {
|
|
19222
|
+
if (typeof localStorage === "undefined" || !localStorage) return;
|
|
19223
|
+
localStorage.setItem(TRACK1_STORAGE_KEY, JSON.stringify(settings));
|
|
19224
|
+
} catch (_) {
|
|
19225
|
+
}
|
|
19226
|
+
};
|
|
19227
|
+
|
|
18332
19228
|
// src/daw.ts
|
|
18333
19229
|
var CHORD_INFO_HTML2 = `
|
|
18334
19230
|
<div class="dtm-modal-body-content">
|
|
@@ -18661,8 +19557,16 @@ var COMPOSE_INFO_HTML = `
|
|
|
18661
19557
|
<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>
|
|
18662
19558
|
</ul>
|
|
18663
19559
|
<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>
|
|
19560
|
+
<h4>\u6B4C\u5165\u308A\u4F5C\u66F2\u306E\u30DC\u30FC\u30AB\u30EB</h4>
|
|
19561
|
+
<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>
|
|
19562
|
+
<ul>
|
|
19563
|
+
<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>
|
|
19564
|
+
<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>
|
|
19565
|
+
</ul>
|
|
19566
|
+
<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>
|
|
18664
19567
|
<h4>\u305D\u306E\u307B\u304B</h4>
|
|
18665
19568
|
<ul>
|
|
19569
|
+
<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>
|
|
18666
19570
|
<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>
|
|
18667
19571
|
<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>
|
|
18668
19572
|
<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>
|
|
@@ -18937,7 +19841,14 @@ var ADVANCED_COMPOSE_LAYOUT = [
|
|
|
18937
19841
|
{ index: 7, part: "block", octave: 0, volume: 62 },
|
|
18938
19842
|
{ index: 8, part: "arpeggio", octave: 0, volume: 54 },
|
|
18939
19843
|
{ index: 9, part: "offbeat", octave: 0, volume: 50 },
|
|
18940
|
-
{ index: 10, part: "uwamono", octave: 1, volume: 56 }
|
|
19844
|
+
{ index: 10, part: "uwamono", octave: 1, volume: 56 },
|
|
19845
|
+
// 掛け合い(デュエット)の相手。**歌入り作曲のときだけ**中身が入る。
|
|
19846
|
+
// 作曲だけならメロディは t0 が全部持つので、ここは空のまま。
|
|
19847
|
+
{ index: 11, part: "duet", octave: 0, volume: 104 },
|
|
19848
|
+
// 2声目のハモリ(主旋律を上下から挟む3声)と、主旋律のオクターブ下の重ね。
|
|
19849
|
+
// どちらも曲ごとに出るかどうかが決まる(`song.vocal`)。
|
|
19850
|
+
{ index: 12, part: "harmony2", octave: 0, volume: 74 },
|
|
19851
|
+
{ index: 13, part: "melody", octave: -1, volume: 56 }
|
|
18941
19852
|
];
|
|
18942
19853
|
var LYRIC_MODEL_CATEGORIES = [
|
|
18943
19854
|
{
|
|
@@ -19217,6 +20128,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
19217
20128
|
let currentDrumPattern = refs.drumSelect.value;
|
|
19218
20129
|
const recentComposeFingerprints = [];
|
|
19219
20130
|
let autoComposeVocal = null;
|
|
20131
|
+
const autoComposeVocalTracks = /* @__PURE__ */ new Map();
|
|
19220
20132
|
let currentDrumFont = options.drumFont ?? "FluidR3_GM_sf2_file:0";
|
|
19221
20133
|
refs.drumFontSelect.value = currentDrumFont;
|
|
19222
20134
|
const applyDrumPatternFont = (name) => {
|
|
@@ -19293,7 +20205,38 @@ var mountDAW = (target, options = {}) => {
|
|
|
19293
20205
|
let trackStates = [];
|
|
19294
20206
|
let suppressPatch = false;
|
|
19295
20207
|
let lyricsDebounceTimer = null;
|
|
20208
|
+
const persistTrack1 = (t) => {
|
|
20209
|
+
if (trackStates.indexOf(t) !== 0) return;
|
|
20210
|
+
const settings = {
|
|
20211
|
+
volume: t.volume,
|
|
20212
|
+
trackInstrument: t.trackInstrument,
|
|
20213
|
+
trackOctave: t.trackOctave,
|
|
20214
|
+
trackOctaveUnison: t.trackOctaveUnison,
|
|
20215
|
+
trackCompression: t.trackCompression,
|
|
20216
|
+
trackWidth: t.trackWidth,
|
|
20217
|
+
trackReverbSend: t.trackReverbSend,
|
|
20218
|
+
trackEqLow: t.trackEqLow,
|
|
20219
|
+
trackEqMid: t.trackEqMid,
|
|
20220
|
+
trackEqHigh: t.trackEqHigh,
|
|
20221
|
+
trackPan: t.trackPan,
|
|
20222
|
+
trackDelaySend: t.trackDelaySend,
|
|
20223
|
+
lyricModel: t.lyricModel,
|
|
20224
|
+
vocalVolume: t.vocalVolume,
|
|
20225
|
+
vocalGate: t.vocalGate,
|
|
20226
|
+
vocalPan: t.vocalPan,
|
|
20227
|
+
vocalOctave: t.vocalOctave,
|
|
20228
|
+
vocalVibrato: t.vocalVibrato,
|
|
20229
|
+
vocalReverb: t.vocalReverb,
|
|
20230
|
+
vocalDelay: t.vocalDelay,
|
|
20231
|
+
vocalGender: t.vocalGender,
|
|
20232
|
+
vocalBreathiness: t.vocalBreathiness,
|
|
20233
|
+
vocalTension: t.vocalTension,
|
|
20234
|
+
vocalOctaveUnison: t.vocalOctaveUnison
|
|
20235
|
+
};
|
|
20236
|
+
writeTrack1Settings(settings);
|
|
20237
|
+
};
|
|
19296
20238
|
const fireLyricsChange = (t) => {
|
|
20239
|
+
persistTrack1(t);
|
|
19297
20240
|
if (!options.onLyricsChange) return;
|
|
19298
20241
|
const trackId = t.config.id;
|
|
19299
20242
|
const data = {
|
|
@@ -19319,9 +20262,11 @@ var mountDAW = (target, options = {}) => {
|
|
|
19319
20262
|
};
|
|
19320
20263
|
const hiddenTracks = /* @__PURE__ */ new Set();
|
|
19321
20264
|
const audioMutedTracks = /* @__PURE__ */ new Set();
|
|
20265
|
+
const savedTrack1 = readTrack1Settings();
|
|
19322
20266
|
const createTrackStates = () => {
|
|
19323
|
-
trackStates = trackConfigs.map((config) => {
|
|
20267
|
+
trackStates = trackConfigs.map((config, index) => {
|
|
19324
20268
|
let prevNotes = [];
|
|
20269
|
+
const t1 = index === 0 ? savedTrack1 : null;
|
|
19325
20270
|
return {
|
|
19326
20271
|
config,
|
|
19327
20272
|
core: new MMLCore(
|
|
@@ -19366,35 +20311,35 @@ var mountDAW = (target, options = {}) => {
|
|
|
19366
20311
|
config.volume,
|
|
19367
20312
|
() => renderConfig
|
|
19368
20313
|
),
|
|
19369
|
-
volume: config.volume,
|
|
20314
|
+
volume: t1?.volume ?? config.volume,
|
|
19370
20315
|
savedChordInput: "",
|
|
19371
20316
|
savedChordPattern: "block",
|
|
19372
20317
|
savedChordRoot: 0,
|
|
19373
20318
|
lyrics: "",
|
|
19374
|
-
lyricModel: "",
|
|
20319
|
+
lyricModel: t1?.lyricModel ?? "",
|
|
19375
20320
|
// 既定は「なし」(歌わない)
|
|
19376
|
-
vocalVolume: DEFAULT_VOCAL_VOLUME,
|
|
19377
|
-
vocalGate: 100,
|
|
19378
|
-
vocalPan: 64,
|
|
19379
|
-
trackOctave: 0,
|
|
19380
|
-
trackOctaveUnison: "none",
|
|
19381
|
-
vocalOctave: 0,
|
|
19382
|
-
vocalVibrato: false,
|
|
19383
|
-
vocalReverb: 0,
|
|
19384
|
-
vocalDelay: 0,
|
|
19385
|
-
vocalGender: 50,
|
|
19386
|
-
vocalBreathiness: 50,
|
|
19387
|
-
vocalTension: 50,
|
|
19388
|
-
vocalOctaveUnison: "none",
|
|
19389
|
-
trackInstrument: "",
|
|
19390
|
-
trackCompression: 0,
|
|
19391
|
-
trackWidth: 100,
|
|
19392
|
-
trackReverbSend: 0,
|
|
19393
|
-
trackEqLow: 0,
|
|
19394
|
-
trackEqMid: 0,
|
|
19395
|
-
trackEqHigh: 0,
|
|
19396
|
-
trackPan: 64,
|
|
19397
|
-
trackDelaySend: 0
|
|
20321
|
+
vocalVolume: t1?.vocalVolume ?? DEFAULT_VOCAL_VOLUME,
|
|
20322
|
+
vocalGate: t1?.vocalGate ?? 100,
|
|
20323
|
+
vocalPan: t1?.vocalPan ?? 64,
|
|
20324
|
+
trackOctave: t1?.trackOctave ?? 0,
|
|
20325
|
+
trackOctaveUnison: t1?.trackOctaveUnison ?? "none",
|
|
20326
|
+
vocalOctave: t1?.vocalOctave ?? 0,
|
|
20327
|
+
vocalVibrato: t1?.vocalVibrato ?? false,
|
|
20328
|
+
vocalReverb: t1?.vocalReverb ?? 0,
|
|
20329
|
+
vocalDelay: t1?.vocalDelay ?? 0,
|
|
20330
|
+
vocalGender: t1?.vocalGender ?? 50,
|
|
20331
|
+
vocalBreathiness: t1?.vocalBreathiness ?? 50,
|
|
20332
|
+
vocalTension: t1?.vocalTension ?? 50,
|
|
20333
|
+
vocalOctaveUnison: t1?.vocalOctaveUnison ?? "none",
|
|
20334
|
+
trackInstrument: t1?.trackInstrument ?? "",
|
|
20335
|
+
trackCompression: t1?.trackCompression ?? 0,
|
|
20336
|
+
trackWidth: t1?.trackWidth ?? 100,
|
|
20337
|
+
trackReverbSend: t1?.trackReverbSend ?? 0,
|
|
20338
|
+
trackEqLow: t1?.trackEqLow ?? 0,
|
|
20339
|
+
trackEqMid: t1?.trackEqMid ?? 0,
|
|
20340
|
+
trackEqHigh: t1?.trackEqHigh ?? 0,
|
|
20341
|
+
trackPan: t1?.trackPan ?? 64,
|
|
20342
|
+
trackDelaySend: t1?.trackDelaySend ?? 0
|
|
19398
20343
|
};
|
|
19399
20344
|
});
|
|
19400
20345
|
};
|
|
@@ -20562,6 +21507,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
20562
21507
|
active.volume = Number.parseInt(volInput.value, 10);
|
|
20563
21508
|
active.core.setVolume(active.volume);
|
|
20564
21509
|
volLabel.textContent = String(active.volume);
|
|
21510
|
+
persistTrack1(active);
|
|
20565
21511
|
});
|
|
20566
21512
|
const syncVelocityDisabled = () => {
|
|
20567
21513
|
volInput.disabled = !!active.lyricModel;
|
|
@@ -20600,16 +21546,19 @@ var mountDAW = (target, options = {}) => {
|
|
|
20600
21546
|
active.trackEqLow = Number.parseInt(trackEqLowInput.value, 10);
|
|
20601
21547
|
trackEqLowLabel.textContent = fmtDb(active.trackEqLow);
|
|
20602
21548
|
options.onTrackEqLowChange?.(active.config.id, active.trackEqLow);
|
|
21549
|
+
persistTrack1(active);
|
|
20603
21550
|
});
|
|
20604
21551
|
trackEqMidInput.addEventListener("input", () => {
|
|
20605
21552
|
active.trackEqMid = Number.parseInt(trackEqMidInput.value, 10);
|
|
20606
21553
|
trackEqMidLabel.textContent = fmtDb(active.trackEqMid);
|
|
20607
21554
|
options.onTrackEqMidChange?.(active.config.id, active.trackEqMid);
|
|
21555
|
+
persistTrack1(active);
|
|
20608
21556
|
});
|
|
20609
21557
|
trackEqHighInput.addEventListener("input", () => {
|
|
20610
21558
|
active.trackEqHigh = Number.parseInt(trackEqHighInput.value, 10);
|
|
20611
21559
|
trackEqHighLabel.textContent = fmtDb(active.trackEqHigh);
|
|
20612
21560
|
options.onTrackEqHighChange?.(active.config.id, active.trackEqHigh);
|
|
21561
|
+
persistTrack1(active);
|
|
20613
21562
|
});
|
|
20614
21563
|
trackEqInfo.addEventListener("click", () => {
|
|
20615
21564
|
showModal("EQ\uFF08\u30A4\u30B3\u30E9\u30A4\u30B6\u30FC\uFF09\u306E\u89E3\u8AAC", TRACK_EQ_INFO_HTML);
|
|
@@ -20643,11 +21592,13 @@ var mountDAW = (target, options = {}) => {
|
|
|
20643
21592
|
active.config.id,
|
|
20644
21593
|
active.trackCompression
|
|
20645
21594
|
);
|
|
21595
|
+
persistTrack1(active);
|
|
20646
21596
|
});
|
|
20647
21597
|
trackWidthInput.addEventListener("input", () => {
|
|
20648
21598
|
active.trackWidth = Number.parseInt(trackWidthInput.value, 10);
|
|
20649
21599
|
trackWidthLabel.textContent = `${active.trackWidth}%`;
|
|
20650
21600
|
options.onTrackWidthChange?.(active.config.id, active.trackWidth);
|
|
21601
|
+
persistTrack1(active);
|
|
20651
21602
|
});
|
|
20652
21603
|
trackCompInfo.addEventListener("click", () => {
|
|
20653
21604
|
showModal("\u97F3\u5727\u5F37\u5316\u306E\u89E3\u8AAC", TRACK_COMPRESSION_INFO_HTML);
|
|
@@ -20671,6 +21622,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
20671
21622
|
active.trackPan = Number.parseInt(trackPanInput.value, 10);
|
|
20672
21623
|
trackPanLabel.textContent = fmtTrackPan(active.trackPan);
|
|
20673
21624
|
options.onTrackPanChange?.(active.config.id, active.trackPan);
|
|
21625
|
+
persistTrack1(active);
|
|
20674
21626
|
});
|
|
20675
21627
|
trackPanInfo.addEventListener("click", () => {
|
|
20676
21628
|
showModal("\u5B9A\u4F4D\u306E\u89E3\u8AAC", TRACK_PAN_INFO_HTML);
|
|
@@ -20693,6 +21645,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
20693
21645
|
active.config.id,
|
|
20694
21646
|
active.trackReverbSend
|
|
20695
21647
|
);
|
|
21648
|
+
persistTrack1(active);
|
|
20696
21649
|
});
|
|
20697
21650
|
trackReverbSendInfo.addEventListener("click", () => {
|
|
20698
21651
|
showModal("\u30EA\u30D0\u30FC\u30D6\u9001\u308A\u306E\u89E3\u8AAC", TRACK_REVERBSEND_INFO_HTML);
|
|
@@ -20712,6 +21665,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
20712
21665
|
active.trackDelaySend = Number.parseInt(trackDelaySendInput.value, 10);
|
|
20713
21666
|
trackDelaySendLabel.textContent = `${active.trackDelaySend}%`;
|
|
20714
21667
|
options.onTrackDelaySendChange?.(active.config.id, active.trackDelaySend);
|
|
21668
|
+
persistTrack1(active);
|
|
20715
21669
|
});
|
|
20716
21670
|
trackDelaySendInfo.addEventListener("click", () => {
|
|
20717
21671
|
showModal("\u30C7\u30A3\u30EC\u30A4\u9001\u308A\u306E\u89E3\u8AAC", TRACK_DELAYSEND_INFO_HTML);
|
|
@@ -20766,6 +21720,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
20766
21720
|
active.trackInstrument = instSel.value;
|
|
20767
21721
|
const trackIndex = trackStates.indexOf(active);
|
|
20768
21722
|
options.onTrackInstrumentChange?.(trackIndex, active.trackInstrument);
|
|
21723
|
+
persistTrack1(active);
|
|
20769
21724
|
});
|
|
20770
21725
|
refs.trackBody.querySelector('[data-dtm="track-vol-row"]').prepend(instLabel, instSel);
|
|
20771
21726
|
const octaveRow = refs.trackBody.querySelector(
|
|
@@ -20781,6 +21736,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
20781
21736
|
syncOctaveVisibility();
|
|
20782
21737
|
octaveSel.addEventListener("change", () => {
|
|
20783
21738
|
active.trackOctave = Number.parseInt(octaveSel.value, 10) || 0;
|
|
21739
|
+
persistTrack1(active);
|
|
20784
21740
|
});
|
|
20785
21741
|
const unisonSel = refs.trackBody.querySelector(
|
|
20786
21742
|
'[data-dtm="track-octave-unison"]'
|
|
@@ -20788,6 +21744,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
20788
21744
|
unisonSel.value = active.trackOctaveUnison;
|
|
20789
21745
|
unisonSel.addEventListener("change", () => {
|
|
20790
21746
|
active.trackOctaveUnison = unisonSel.value;
|
|
21747
|
+
persistTrack1(active);
|
|
20791
21748
|
});
|
|
20792
21749
|
if (isAdvanced || active.config.id !== "chord") {
|
|
20793
21750
|
const lyricDiv = document.createElement("div");
|
|
@@ -21939,16 +22896,32 @@ var mountDAW = (target, options = {}) => {
|
|
|
21939
22896
|
updateTrackPanel();
|
|
21940
22897
|
updateUndoRedo();
|
|
21941
22898
|
};
|
|
21942
|
-
const exportMIDI2 = () =>
|
|
21943
|
-
|
|
21944
|
-
|
|
21945
|
-
|
|
21946
|
-
|
|
21947
|
-
|
|
21948
|
-
|
|
21949
|
-
|
|
21950
|
-
|
|
21951
|
-
|
|
22899
|
+
const exportMIDI2 = () => {
|
|
22900
|
+
const autoPreset = INSTRUMENT_PRESETS[currentInstrument] ?? INSTRUMENT_PRESETS.piano;
|
|
22901
|
+
return exportMIDI({
|
|
22902
|
+
tracks: trackStates.map((t) => {
|
|
22903
|
+
let program;
|
|
22904
|
+
if (t.trackInstrument) {
|
|
22905
|
+
const p = programOfInstrumentName(t.trackInstrument);
|
|
22906
|
+
if (p !== null) program = p;
|
|
22907
|
+
} else if (!t.lyricModel) {
|
|
22908
|
+
const role = DECLARED_ROLE[t.config.id] ?? "melody";
|
|
22909
|
+
const instName = autoPreset[role] ?? autoPreset.melody;
|
|
22910
|
+
const p = programOfInstrumentName(instName);
|
|
22911
|
+
if (p !== null) program = p;
|
|
22912
|
+
}
|
|
22913
|
+
return {
|
|
22914
|
+
notes: playableNotes(t),
|
|
22915
|
+
volume: t.volume,
|
|
22916
|
+
program
|
|
22917
|
+
};
|
|
22918
|
+
}),
|
|
22919
|
+
getDrumPattern: (currentBar) => resolveDrumPattern(currentDrumPattern, drumPatterns, currentBar),
|
|
22920
|
+
drumVolume,
|
|
22921
|
+
bpm,
|
|
22922
|
+
stepsPerBar: renderConfig.stepsPerBar
|
|
22923
|
+
});
|
|
22924
|
+
};
|
|
21952
22925
|
const setBpm = (value) => {
|
|
21953
22926
|
bpm = value;
|
|
21954
22927
|
refs.bpmInput.value = String(value);
|
|
@@ -22571,7 +23544,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
22571
23544
|
for (const layer of ADVANCED_COMPOSE_LAYOUT) {
|
|
22572
23545
|
const track = trackStates[layer.index];
|
|
22573
23546
|
if (!track) continue;
|
|
22574
|
-
const notes = layer.part === "melody" ? song.melody : layer.part === "harmony" ? song.harmony : layer.part === "submelody" ? song.submelody : layer.part === "bass" ? song.bass : layer.part === "pad" ? song.pad : layer.part === "uwamono" ? buildChordPlacements({
|
|
23547
|
+
const notes = layer.part === "duet" ? [] : layer.part === "harmony2" ? song.harmony2 : layer.index === 13 ? song.octave : layer.part === "melody" ? song.melody : layer.part === "harmony" ? song.harmony : layer.part === "submelody" ? song.submelody : layer.part === "bass" ? song.bass : layer.part === "pad" ? song.pad : layer.part === "uwamono" ? buildChordPlacements({
|
|
22575
23548
|
edo: renderConfig.edo,
|
|
22576
23549
|
chordStr: song.chordProgression,
|
|
22577
23550
|
patternType: "arpeggio",
|
|
@@ -22629,18 +23602,95 @@ var mountDAW = (target, options = {}) => {
|
|
|
22629
23602
|
options.onInstrumentChange?.(song.instrument);
|
|
22630
23603
|
}
|
|
22631
23604
|
if (withVocal) {
|
|
23605
|
+
autoComposeVocalTracks.clear();
|
|
22632
23606
|
const melodyTrack = isAdvanced ? trackStates[0] : trackStates.find((t) => t.config.id === "melody");
|
|
22633
23607
|
if (melodyTrack) {
|
|
22634
23608
|
const current = melodyTrack.lyricModel.trim();
|
|
22635
23609
|
if (!current || current === autoComposeVocal) {
|
|
23610
|
+
if (!current && melodyTrack.vocalOctave === 0) {
|
|
23611
|
+
melodyTrack.vocalOctave = -1;
|
|
23612
|
+
}
|
|
22636
23613
|
melodyTrack.lyricModel = pickComposeVocal(autoComposeVocal);
|
|
22637
23614
|
autoComposeVocal = melodyTrack.lyricModel;
|
|
23615
|
+
autoComposeVocalTracks.set(melodyTrack, melodyTrack.lyricModel);
|
|
22638
23616
|
}
|
|
22639
23617
|
melodyTrack.lyrics = composeLyrics(song.melody, {
|
|
22640
23618
|
stepsPerBar: renderConfig.stepsPerBar
|
|
22641
23619
|
});
|
|
22642
23620
|
fireLyricsChange(melodyTrack);
|
|
22643
23621
|
}
|
|
23622
|
+
if (isAdvanced && melodyTrack) {
|
|
23623
|
+
const stepsPerBar = renderConfig.stepsPerBar;
|
|
23624
|
+
const spans = song.vocal.duetSpans;
|
|
23625
|
+
const inDuet = (n) => spans.some(([a, b]) => n.startStep >= a && n.startStep < b);
|
|
23626
|
+
const sing = (track, lyrics, voice) => {
|
|
23627
|
+
if (!track) return;
|
|
23628
|
+
track.lyricModel = voice;
|
|
23629
|
+
autoComposeVocalTracks.set(track, voice);
|
|
23630
|
+
if (track.vocalOctave === 0) track.vocalOctave = -1;
|
|
23631
|
+
track.lyrics = lyrics;
|
|
23632
|
+
fireLyricsChange(track);
|
|
23633
|
+
};
|
|
23634
|
+
const partnerVoice = pickComposeVocal(melodyTrack.lyricModel);
|
|
23635
|
+
const duetting = spans.length > 0;
|
|
23636
|
+
if (duetting) {
|
|
23637
|
+
const mine = song.melody.filter((n) => !inDuet(n));
|
|
23638
|
+
const yours = song.melody.filter((n) => inDuet(n));
|
|
23639
|
+
writeTrackAt(0, mine);
|
|
23640
|
+
writeTrackAt(11, yours);
|
|
23641
|
+
const full = melodyTrack.lyrics;
|
|
23642
|
+
sing(
|
|
23643
|
+
melodyTrack,
|
|
23644
|
+
alignLyrics(song.melody, full, mine, { stepsPerBar }),
|
|
23645
|
+
melodyTrack.lyricModel
|
|
23646
|
+
);
|
|
23647
|
+
sing(
|
|
23648
|
+
trackStates[11],
|
|
23649
|
+
alignLyrics(song.melody, full, yours, { stepsPerBar }),
|
|
23650
|
+
partnerVoice
|
|
23651
|
+
);
|
|
23652
|
+
}
|
|
23653
|
+
const harmonyTrack = trackStates[2];
|
|
23654
|
+
if (song.harmony.length > 0 && harmonyTrack) {
|
|
23655
|
+
sing(
|
|
23656
|
+
harmonyTrack,
|
|
23657
|
+
alignLyrics(song.melody, melodyTrack.lyrics, song.harmony, {
|
|
23658
|
+
stepsPerBar
|
|
23659
|
+
}),
|
|
23660
|
+
duetting ? partnerVoice : melodyTrack.lyricModel
|
|
23661
|
+
);
|
|
23662
|
+
}
|
|
23663
|
+
if (!duetting) {
|
|
23664
|
+
if (song.harmony2.length > 0)
|
|
23665
|
+
sing(
|
|
23666
|
+
trackStates[12],
|
|
23667
|
+
alignLyrics(song.melody, melodyTrack.lyrics, song.harmony2, {
|
|
23668
|
+
stepsPerBar
|
|
23669
|
+
}),
|
|
23670
|
+
melodyTrack.lyricModel
|
|
23671
|
+
);
|
|
23672
|
+
const octaveTrack = trackStates[13];
|
|
23673
|
+
if (song.octave.length > 0 && octaveTrack) {
|
|
23674
|
+
sing(
|
|
23675
|
+
octaveTrack,
|
|
23676
|
+
alignLyrics(song.melody, melodyTrack.lyrics, song.octave, {
|
|
23677
|
+
stepsPerBar
|
|
23678
|
+
}),
|
|
23679
|
+
melodyTrack.lyricModel
|
|
23680
|
+
);
|
|
23681
|
+
octaveTrack.vocalOctave = -2;
|
|
23682
|
+
}
|
|
23683
|
+
}
|
|
23684
|
+
}
|
|
23685
|
+
} else {
|
|
23686
|
+
for (const [track, voice] of autoComposeVocalTracks) {
|
|
23687
|
+
if (track.lyricModel === voice) {
|
|
23688
|
+
track.lyrics = "";
|
|
23689
|
+
track.lyricModel = "";
|
|
23690
|
+
fireLyricsChange(track);
|
|
23691
|
+
}
|
|
23692
|
+
}
|
|
23693
|
+
autoComposeVocalTracks.clear();
|
|
22644
23694
|
}
|
|
22645
23695
|
applyAutoMastering();
|
|
22646
23696
|
if (refs.composeKeyHint) {
|
|
@@ -23777,7 +24827,10 @@ var mountDAW = (target, options = {}) => {
|
|
|
23777
24827
|
t.vocalBreathiness = data.vocalBreathiness ?? 50;
|
|
23778
24828
|
t.vocalTension = data.vocalTension ?? 50;
|
|
23779
24829
|
t.vocalOctaveUnison = data.vocalOctaveUnison ?? "none";
|
|
23780
|
-
if (t.config.id === activeTrackId)
|
|
24830
|
+
if (t.config.id === activeTrackId) {
|
|
24831
|
+
updateTrackPanel();
|
|
24832
|
+
redrawAll();
|
|
24833
|
+
}
|
|
23781
24834
|
},
|
|
23782
24835
|
applyTrackInstrument: (trackIndex, instrumentName) => {
|
|
23783
24836
|
const t = trackStates[trackIndex];
|
|
@@ -26187,6 +27240,7 @@ var createDtmStudio = async (options = {}) => {
|
|
|
26187
27240
|
playNote,
|
|
26188
27241
|
playPlacements,
|
|
26189
27242
|
playSingingMML,
|
|
27243
|
+
programOfInstrumentName,
|
|
26190
27244
|
readGlobalBool,
|
|
26191
27245
|
readGlobalNumber,
|
|
26192
27246
|
readGlobalSetting,
|