@onjmin/dtm 2.1.9 → 2.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +351 -3
- package/dist/index.d.ts +351 -3
- package/dist/index.js +1333 -227
- package/dist/index.mjs +1319 -227
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -8121,6 +8121,22 @@ var DAW_CSS = `
|
|
|
8121
8121
|
opacity: 0.85;
|
|
8122
8122
|
}
|
|
8123
8123
|
.dtm-pill:not(.dtm-pill--active):active { transform: translate(1px,1px); box-shadow: none; }
|
|
8124
|
+
/* \u30DC\u30FC\u30AB\u30EB\u304C\u9078\u629E\u3055\u308C\u3066\u3044\u308B\u30C8\u30E9\u30C3\u30AF\u306E\u30BF\u30D6\u306B\u3001\u3046\u3063\u3059\u3089\u58F0\u306E\u30A2\u30A4\u30B3\u30F3\u3092\u91CD\u306D\u308B\uFF08\u80CC\u666F\u8272\u30FB\u30B5\u30A4\u30BA\u306F\u5909\u3048\u306A\u3044\uFF09 */
|
|
8125
|
+
.dtm-pill--vocal::after {
|
|
8126
|
+
content: '';
|
|
8127
|
+
position: absolute;
|
|
8128
|
+
inset: 0;
|
|
8129
|
+
background-image: var(--dtm-pill-icon);
|
|
8130
|
+
background-size: contain;
|
|
8131
|
+
background-repeat: no-repeat;
|
|
8132
|
+
background-position: right center;
|
|
8133
|
+
opacity: 0.4;
|
|
8134
|
+
pointer-events: none;
|
|
8135
|
+
}
|
|
8136
|
+
.dtm-pill__label {
|
|
8137
|
+
position: relative;
|
|
8138
|
+
z-index: 1;
|
|
8139
|
+
}
|
|
8124
8140
|
/* \u518D\u751F\u4E2D\u3001\u5B9F\u969B\u306B\u767A\u97F3\u3057\u305F\u77AC\u9593\u3060\u3051\u70B9\u706F\uFF08\u3069\u306E\u30BF\u30D6\u304C\u4ECA\u9CF4\u3063\u3066\u3044\u308B\u304B\u8996\u899A\u7684\u306B\u5206\u304B\u308B\u3088\u3046\u306B\uFF09 */
|
|
8125
8141
|
.dtm-pill--sounding {
|
|
8126
8142
|
filter: brightness(1.6);
|
|
@@ -13460,6 +13476,650 @@ var featureDistance = (a, b) => {
|
|
|
13460
13476
|
return Math.sqrt(sum);
|
|
13461
13477
|
};
|
|
13462
13478
|
|
|
13479
|
+
// src/compose-scales.ts
|
|
13480
|
+
var MAJOR_SCALE2 = [
|
|
13481
|
+
{ semi: 0, fifth: 0 },
|
|
13482
|
+
// C
|
|
13483
|
+
{ semi: 2, fifth: 2 },
|
|
13484
|
+
// D
|
|
13485
|
+
{ semi: 4, fifth: 4 },
|
|
13486
|
+
// E
|
|
13487
|
+
{ semi: 5, fifth: -1 },
|
|
13488
|
+
// F
|
|
13489
|
+
{ semi: 7, fifth: 1 },
|
|
13490
|
+
// G
|
|
13491
|
+
{ semi: 9, fifth: 3 },
|
|
13492
|
+
// A
|
|
13493
|
+
{ semi: 11, fifth: 5 }
|
|
13494
|
+
// B
|
|
13495
|
+
];
|
|
13496
|
+
var HARMONIC_MINOR_SCALE = [
|
|
13497
|
+
{ semi: 0, fifth: 0 },
|
|
13498
|
+
// C
|
|
13499
|
+
{ semi: 2, fifth: 2 },
|
|
13500
|
+
// D
|
|
13501
|
+
{ semi: 4, fifth: 4 },
|
|
13502
|
+
// E
|
|
13503
|
+
{ semi: 5, fifth: -1 },
|
|
13504
|
+
// F
|
|
13505
|
+
{ semi: 8, fifth: 8 },
|
|
13506
|
+
// G#
|
|
13507
|
+
{ semi: 9, fifth: 3 },
|
|
13508
|
+
// A
|
|
13509
|
+
{ semi: 11, fifth: 5 }
|
|
13510
|
+
// B
|
|
13511
|
+
];
|
|
13512
|
+
var HUNGARIAN_SCALE = [
|
|
13513
|
+
{ semi: 0, fifth: 0 },
|
|
13514
|
+
// C
|
|
13515
|
+
{ semi: 3, fifth: 9 },
|
|
13516
|
+
// D#
|
|
13517
|
+
{ semi: 4, fifth: 4 },
|
|
13518
|
+
// E
|
|
13519
|
+
{ semi: 5, fifth: -1 },
|
|
13520
|
+
// F
|
|
13521
|
+
{ semi: 8, fifth: 8 },
|
|
13522
|
+
// G#
|
|
13523
|
+
{ semi: 9, fifth: 3 },
|
|
13524
|
+
// A
|
|
13525
|
+
{ semi: 11, fifth: 5 }
|
|
13526
|
+
// B
|
|
13527
|
+
];
|
|
13528
|
+
var BLUES_SCALE = [
|
|
13529
|
+
{ semi: 0, fifth: 0 },
|
|
13530
|
+
// C
|
|
13531
|
+
{ semi: 3, fifth: -3 },
|
|
13532
|
+
// Eb
|
|
13533
|
+
{ semi: 5, fifth: -1 },
|
|
13534
|
+
// F
|
|
13535
|
+
{ semi: 6, fifth: -6 },
|
|
13536
|
+
// Gb(ブルーノート)
|
|
13537
|
+
{ semi: 7, fifth: 1 },
|
|
13538
|
+
// G
|
|
13539
|
+
{ semi: 10, fifth: -2 }
|
|
13540
|
+
// Bb
|
|
13541
|
+
];
|
|
13542
|
+
var RYUKYU_CENTER = {
|
|
13543
|
+
tonic: "C",
|
|
13544
|
+
half: "G",
|
|
13545
|
+
deceptive: "Em",
|
|
13546
|
+
tonicPattern: /^C(?![#b]|m)/,
|
|
13547
|
+
a: [
|
|
13548
|
+
["C", "F", "G", "C"],
|
|
13549
|
+
["C", "C", "F", "G"],
|
|
13550
|
+
["F", "G", "C", "C"],
|
|
13551
|
+
["C", "G", "F", "G"],
|
|
13552
|
+
["CM7", "F", "G", "C"],
|
|
13553
|
+
["C", "F", "C", "G"],
|
|
13554
|
+
["C", "Em", "F", "G"],
|
|
13555
|
+
["F", "C", "G", "C"]
|
|
13556
|
+
],
|
|
13557
|
+
b: [
|
|
13558
|
+
["F", "G", "Em", "C"],
|
|
13559
|
+
["F", "G", "C", "G"],
|
|
13560
|
+
["G", "F", "C", "C"],
|
|
13561
|
+
["FM7", "G", "Em", "F"],
|
|
13562
|
+
["C", "G", "F", "C"],
|
|
13563
|
+
["F", "Em", "F", "G"]
|
|
13564
|
+
],
|
|
13565
|
+
c: [
|
|
13566
|
+
["Em", "F", "G", "C"],
|
|
13567
|
+
["F", "C", "G", "Em"],
|
|
13568
|
+
["C", "Em", "F", "G"]
|
|
13569
|
+
]
|
|
13570
|
+
};
|
|
13571
|
+
var MIYAKOBUSHI_CENTER = {
|
|
13572
|
+
tonic: "Em",
|
|
13573
|
+
half: "Am",
|
|
13574
|
+
deceptive: "F",
|
|
13575
|
+
tonicPattern: /^E(?:m|sus)/,
|
|
13576
|
+
a: [
|
|
13577
|
+
["Em", "F", "Em", "Em"],
|
|
13578
|
+
["Esus4", "F", "Esus4", "Em"],
|
|
13579
|
+
["Em", "Am", "F", "Em"],
|
|
13580
|
+
["Am", "Em", "F", "Em"],
|
|
13581
|
+
["Em", "F", "Am", "Em"],
|
|
13582
|
+
["Em", "Em", "F", "F"],
|
|
13583
|
+
["Am", "F", "Em", "Em"],
|
|
13584
|
+
["Em", "FM7", "Am", "Em"]
|
|
13585
|
+
],
|
|
13586
|
+
b: [
|
|
13587
|
+
["F", "Am", "Em", "Em"],
|
|
13588
|
+
["Am", "F", "Em", "Em"],
|
|
13589
|
+
["F", "Em", "Am", "Em"],
|
|
13590
|
+
["FM7", "Am", "F", "Em"],
|
|
13591
|
+
["Am", "Em", "F", "Am"],
|
|
13592
|
+
["F", "Am", "F", "Em"]
|
|
13593
|
+
],
|
|
13594
|
+
c: [
|
|
13595
|
+
["Am", "Em", "F", "Am"],
|
|
13596
|
+
["F", "Am", "Esus4", "Em"],
|
|
13597
|
+
["Am", "F", "Em", "Em"]
|
|
13598
|
+
]
|
|
13599
|
+
};
|
|
13600
|
+
var RITSU_CENTER = {
|
|
13601
|
+
tonic: "Dsus4",
|
|
13602
|
+
half: "G",
|
|
13603
|
+
deceptive: "Em",
|
|
13604
|
+
tonicPattern: /^Dsus/,
|
|
13605
|
+
a: [
|
|
13606
|
+
["Dsus4", "G", "Dsus4", "Dsus4"],
|
|
13607
|
+
["Dsus4", "Em", "G", "Dsus4"],
|
|
13608
|
+
["G", "Dsus4", "Em", "Dsus4"],
|
|
13609
|
+
["Dsus4", "G", "Em", "G"],
|
|
13610
|
+
["Em", "G", "Dsus4", "Dsus4"],
|
|
13611
|
+
["Dsus4", "Em7", "G", "Dsus4"],
|
|
13612
|
+
["G", "Em", "Dsus4", "G"],
|
|
13613
|
+
["Dsus4", "Am", "G", "Dsus4"]
|
|
13614
|
+
],
|
|
13615
|
+
b: [
|
|
13616
|
+
["G", "Em", "Dsus4", "Dsus4"],
|
|
13617
|
+
["Em", "G", "Em", "Dsus4"],
|
|
13618
|
+
["G", "Am", "Em", "Dsus4"],
|
|
13619
|
+
["Em7", "G", "Dsus4", "Dsus4"],
|
|
13620
|
+
["Am", "G", "Em", "Dsus4"],
|
|
13621
|
+
["Dsus4", "Em", "G", "Em"]
|
|
13622
|
+
],
|
|
13623
|
+
c: [
|
|
13624
|
+
["Em", "Dsus4", "G", "Em"],
|
|
13625
|
+
["G", "Em7", "Am", "G"],
|
|
13626
|
+
["Am", "G", "Em", "Dsus4"]
|
|
13627
|
+
]
|
|
13628
|
+
};
|
|
13629
|
+
var HARMONIC_MINOR_CENTER = {
|
|
13630
|
+
tonic: "Am",
|
|
13631
|
+
half: "E7",
|
|
13632
|
+
deceptive: "F",
|
|
13633
|
+
tonicPattern: /^Am/,
|
|
13634
|
+
a: [
|
|
13635
|
+
["Am", "Dm", "E7", "Am"],
|
|
13636
|
+
// i-iv-V7-i。和声的短音階の基本形
|
|
13637
|
+
["Am", "F", "E7", "Am"],
|
|
13638
|
+
["Am", "E7", "Am", "Am"],
|
|
13639
|
+
["Dm", "E7", "Am", "Am"],
|
|
13640
|
+
["Am", "AmM7", "Dm", "E7"],
|
|
13641
|
+
// 主和音に導音を重ねたクリシェ
|
|
13642
|
+
["Am", "F", "Dm", "E7"],
|
|
13643
|
+
["F", "E7", "Am", "Am"],
|
|
13644
|
+
["Am", "Bm7-5", "E7", "Am"]
|
|
13645
|
+
],
|
|
13646
|
+
b: [
|
|
13647
|
+
["Dm", "E7", "Am", "Am"],
|
|
13648
|
+
["F", "E7", "Am", "E7"],
|
|
13649
|
+
["Dm7", "G#dim", "Am", "E7"],
|
|
13650
|
+
["F", "Dm", "E7", "Am"],
|
|
13651
|
+
["Am", "Dm", "Bm7-5", "E7"],
|
|
13652
|
+
["FM7", "E7", "Am", "Am"]
|
|
13653
|
+
],
|
|
13654
|
+
c: [
|
|
13655
|
+
["Dm", "Am", "Bm7-5", "E7"],
|
|
13656
|
+
["F", "C+", "Dm", "E7"],
|
|
13657
|
+
["Am", "F", "Dm", "E7"]
|
|
13658
|
+
]
|
|
13659
|
+
};
|
|
13660
|
+
var HIJAZ_CENTER = {
|
|
13661
|
+
tonic: "E",
|
|
13662
|
+
half: "F",
|
|
13663
|
+
deceptive: "Am",
|
|
13664
|
+
tonicPattern: /^E(?![#b]|m)/,
|
|
13665
|
+
a: [
|
|
13666
|
+
["E", "F", "E", "E"],
|
|
13667
|
+
// I-♭II。ヒジャーズの顔
|
|
13668
|
+
["E7", "F", "E", "E"],
|
|
13669
|
+
["Am", "F", "E", "E"],
|
|
13670
|
+
["E", "F", "Dm", "E"],
|
|
13671
|
+
["F", "E", "F", "E"],
|
|
13672
|
+
["Dm", "E", "F", "E"],
|
|
13673
|
+
["E7", "Am", "F", "E"],
|
|
13674
|
+
["E", "Dm", "F", "E"]
|
|
13675
|
+
],
|
|
13676
|
+
b: [
|
|
13677
|
+
["F", "E", "Am", "E"],
|
|
13678
|
+
["Dm", "C+", "F", "E"],
|
|
13679
|
+
["Am", "Dm", "F", "E"],
|
|
13680
|
+
["F", "Dm", "E", "E"],
|
|
13681
|
+
["E7", "F", "Dm", "E"],
|
|
13682
|
+
["Bm7-5", "E7", "Am", "E"]
|
|
13683
|
+
],
|
|
13684
|
+
c: [
|
|
13685
|
+
["Am", "Dm", "F", "E"],
|
|
13686
|
+
["Dm", "Am", "F", "E7"],
|
|
13687
|
+
["F", "C+", "Dm", "E"]
|
|
13688
|
+
]
|
|
13689
|
+
};
|
|
13690
|
+
var HUNGARIAN_CENTER = {
|
|
13691
|
+
tonic: "Am",
|
|
13692
|
+
half: "E",
|
|
13693
|
+
deceptive: "F",
|
|
13694
|
+
tonicPattern: /^Am/,
|
|
13695
|
+
a: [
|
|
13696
|
+
["Am", "E", "Am", "Am"],
|
|
13697
|
+
["Am", "F", "E", "Am"],
|
|
13698
|
+
["Am", "AmM7", "F", "E"],
|
|
13699
|
+
["F", "E", "Am", "Am"],
|
|
13700
|
+
["Am", "Fm", "E", "Am"],
|
|
13701
|
+
// ♭VIm。増2度を和音の側でも鳴らす
|
|
13702
|
+
["Am", "E", "F", "E"],
|
|
13703
|
+
["FM7", "E", "Am", "Am"],
|
|
13704
|
+
["Am", "C+", "F", "E"]
|
|
13705
|
+
],
|
|
13706
|
+
b: [
|
|
13707
|
+
["F", "E", "Am", "E"],
|
|
13708
|
+
["Fm", "E", "Am", "Am"],
|
|
13709
|
+
["Am", "F", "C+", "E"],
|
|
13710
|
+
["FM7", "Am", "F", "E"],
|
|
13711
|
+
["E", "F", "E", "Am"],
|
|
13712
|
+
["Am", "AmM7", "Fm", "E"]
|
|
13713
|
+
],
|
|
13714
|
+
c: [
|
|
13715
|
+
["F", "Am", "Fm", "E"],
|
|
13716
|
+
["C+", "F", "Am", "E"],
|
|
13717
|
+
["Am", "Fm", "F", "E"]
|
|
13718
|
+
]
|
|
13719
|
+
};
|
|
13720
|
+
var BLUES_CENTER = {
|
|
13721
|
+
tonic: "C7",
|
|
13722
|
+
half: "G7",
|
|
13723
|
+
deceptive: "F7",
|
|
13724
|
+
tonicPattern: /^C7/,
|
|
13725
|
+
a: [
|
|
13726
|
+
["C7", "C7", "C7", "C7"],
|
|
13727
|
+
// 12小節ブルースの1〜4小節
|
|
13728
|
+
["C7", "F7", "C7", "C7"],
|
|
13729
|
+
["C7", "C7", "F7", "F7"],
|
|
13730
|
+
["F7", "F7", "C7", "C7"],
|
|
13731
|
+
// 5〜8小節
|
|
13732
|
+
["C7", "F7", "C7", "G7"],
|
|
13733
|
+
["C7", "C7", "G7", "F7"],
|
|
13734
|
+
["C7", "F7", "G7", "C7"],
|
|
13735
|
+
["F7", "C7", "G7", "C7"]
|
|
13736
|
+
],
|
|
13737
|
+
b: [
|
|
13738
|
+
["F7", "F7", "C7", "C7"],
|
|
13739
|
+
["G7", "F7", "C7", "C7"],
|
|
13740
|
+
// 9〜12小節(ターンアラウンド)
|
|
13741
|
+
["F7", "G7", "C7", "C7"],
|
|
13742
|
+
["C7", "F7", "G7", "C7"],
|
|
13743
|
+
["F7", "C7", "G7", "F7"],
|
|
13744
|
+
["G7", "G7", "F7", "C7"]
|
|
13745
|
+
],
|
|
13746
|
+
c: [
|
|
13747
|
+
["G7", "F7", "C7", "G7"],
|
|
13748
|
+
["F7", "F7", "G7", "G7"],
|
|
13749
|
+
["C7", "C7", "F7", "G7"]
|
|
13750
|
+
]
|
|
13751
|
+
};
|
|
13752
|
+
var COMPOSE_SCALES = {
|
|
13753
|
+
yo: {
|
|
13754
|
+
id: "yo",
|
|
13755
|
+
label: "\u967D\u97F3\u968E\uFF08\u9577\u8ABF\u30DA\u30F3\u30BF\u30C8\u30CB\u30C3\u30AF\uFF09",
|
|
13756
|
+
tonic: 0,
|
|
13757
|
+
core: [0, 1, 2, 4, 5],
|
|
13758
|
+
// ド レ ミ ソ ラ
|
|
13759
|
+
minorish: false,
|
|
13760
|
+
strict: false,
|
|
13761
|
+
description: "J-POP\u306E\u6A19\u6E96\u3002\u660E\u308B\u304F\u7D20\u76F4\u3067\u6B4C\u3044\u3084\u3059\u3044\u3002\u5F93\u6765\u306E\u9577\u8ABF\u3068\u540C\u3058"
|
|
13762
|
+
},
|
|
13763
|
+
minyo: {
|
|
13764
|
+
id: "minyo",
|
|
13765
|
+
label: "\u6C11\u8B21\u97F3\u968E\uFF08\u77ED\u8ABF\u30DA\u30F3\u30BF\u30C8\u30CB\u30C3\u30AF\uFF09",
|
|
13766
|
+
tonic: 5,
|
|
13767
|
+
core: [5, 0, 1, 2, 4],
|
|
13768
|
+
// ラ ド レ ミ ソ
|
|
13769
|
+
minorish: true,
|
|
13770
|
+
strict: false,
|
|
13771
|
+
description: "\u308F\u3089\u3079\u6B4C\u30FB\u6C11\u8B21\u306E\u97F3\u968E\u3002\u7FF3\u308A\u304C\u3042\u308B\u304C\u6697\u3059\u304E\u306A\u3044\u3002\u5F93\u6765\u306E\u77ED\u8ABF\u3068\u540C\u3058"
|
|
13772
|
+
},
|
|
13773
|
+
ritsu: {
|
|
13774
|
+
id: "ritsu",
|
|
13775
|
+
label: "\u5F8B\u97F3\u968E",
|
|
13776
|
+
tonic: 1,
|
|
13777
|
+
core: [1, 2, 4, 5, 6],
|
|
13778
|
+
// レ ミ ソ ラ シ
|
|
13779
|
+
minorish: true,
|
|
13780
|
+
strict: true,
|
|
13781
|
+
center: RITSU_CENTER,
|
|
13782
|
+
description: "\u96C5\u697D\u30FB\u58F0\u660E\u306E\u97F3\u968E\u3002\u534A\u97F3\u3092\u542B\u307E\u305A\u3001\u5E73\u3089\u3067\u8358\u91CD\u306B\u6D41\u308C\u308B"
|
|
13783
|
+
},
|
|
13784
|
+
miyakobushi: {
|
|
13785
|
+
id: "miyakobushi",
|
|
13786
|
+
label: "\u90FD\u7BC0\u97F3\u968E\uFF08\u9670\u97F3\u968E\uFF09",
|
|
13787
|
+
tonic: 2,
|
|
13788
|
+
core: [2, 3, 5, 6, 0],
|
|
13789
|
+
// ミ ファ ラ シ ド
|
|
13790
|
+
minorish: true,
|
|
13791
|
+
strict: true,
|
|
13792
|
+
center: MIYAKOBUSHI_CENTER,
|
|
13793
|
+
description: "\u300E\u3055\u304F\u3089\u3055\u304F\u3089\u300F\u306E\u97F3\u968E\u3002\u4E3B\u97F3\u306E\u3059\u3050\u4E0A\u304C\u534A\u97F3\u3067\u3001\u7FF3\u308A\u304C\u6FC3\u3044"
|
|
13794
|
+
},
|
|
13795
|
+
ryukyu: {
|
|
13796
|
+
id: "ryukyu",
|
|
13797
|
+
label: "\u7409\u7403\u97F3\u968E",
|
|
13798
|
+
tonic: 0,
|
|
13799
|
+
core: [0, 2, 3, 4, 6],
|
|
13800
|
+
// ド ミ ファ ソ シ
|
|
13801
|
+
minorish: false,
|
|
13802
|
+
strict: true,
|
|
13803
|
+
center: RYUKYU_CENTER,
|
|
13804
|
+
description: "\u6C96\u7E04\u97F3\u968E\u3002\u30EC\u3068\u30E9\u3092\u629C\u304D\u3001\u30D5\u30A1\u3068\u30B7\u3092\u67F1\u306B\u3059\u308B\u3002\u660E\u308B\u304F\u8DF3\u306D\u308B"
|
|
13805
|
+
},
|
|
13806
|
+
dorian: {
|
|
13807
|
+
id: "dorian",
|
|
13808
|
+
label: "\u30C9\u30EA\u30A2\u30F3",
|
|
13809
|
+
tonic: 1,
|
|
13810
|
+
core: [1, 3, 4, 5, 0],
|
|
13811
|
+
// レ ファ ソ ラ ド
|
|
13812
|
+
minorish: true,
|
|
13813
|
+
strict: false,
|
|
13814
|
+
description: "\u77ED\u8ABF\u3060\u304C6\u5EA6\u304C\u660E\u308B\u3044\u3002\u30B1\u30EB\u30C8\u30FB\u30ED\u30C3\u30AF\u30FB\u30B7\u30C6\u30A3\u30DD\u30C3\u30D7"
|
|
13815
|
+
},
|
|
13816
|
+
phrygian: {
|
|
13817
|
+
id: "phrygian",
|
|
13818
|
+
label: "\u30D5\u30EA\u30B8\u30A2\u30F3",
|
|
13819
|
+
tonic: 2,
|
|
13820
|
+
core: [2, 3, 5, 6, 1],
|
|
13821
|
+
// ミ ファ ラ シ レ
|
|
13822
|
+
minorish: true,
|
|
13823
|
+
strict: false,
|
|
13824
|
+
description: "\u4E3B\u97F3\u306E\u4E0A\u304C\u534A\u97F3\u3002\u30B9\u30D1\u30CB\u30C3\u30B7\u30E5\uFF0F\u30E1\u30BF\u30EB\u306E\u7DCA\u8FEB\u3057\u305F\u97FF\u304D"
|
|
13825
|
+
},
|
|
13826
|
+
lydian: {
|
|
13827
|
+
id: "lydian",
|
|
13828
|
+
label: "\u30EA\u30C7\u30A3\u30A2\u30F3",
|
|
13829
|
+
tonic: 3,
|
|
13830
|
+
core: [3, 4, 6, 0, 2],
|
|
13831
|
+
// ファ ソ シ ド ミ
|
|
13832
|
+
minorish: false,
|
|
13833
|
+
strict: false,
|
|
13834
|
+
description: "4\u5EA6\u304C\u9AD8\u304F\u3001\u6D6E\u904A\u3057\u3066\u5E83\u304C\u308B\u3002\u6620\u753B\u97F3\u697D\u30FB\u30B2\u30FC\u30E0\u306E\u7A7A\u306E\u8272"
|
|
13835
|
+
},
|
|
13836
|
+
mixolydian: {
|
|
13837
|
+
id: "mixolydian",
|
|
13838
|
+
label: "\u30DF\u30AF\u30BD\u30EA\u30C7\u30A3\u30A2\u30F3",
|
|
13839
|
+
tonic: 4,
|
|
13840
|
+
core: [4, 5, 0, 1, 3],
|
|
13841
|
+
// ソ ラ ド レ ファ
|
|
13842
|
+
minorish: false,
|
|
13843
|
+
strict: false,
|
|
13844
|
+
description: "\u9577\u8ABF\u3060\u304C7\u5EA6\u304C\u4F4E\u3044\u3002\u30D6\u30EB\u30FC\u30B9\u30ED\u30C3\u30AF\u30FB\u6C11\u65CF\u97F3\u697D\u306E\u571F\u304F\u3055\u3055"
|
|
13845
|
+
},
|
|
13846
|
+
harmonic_minor: {
|
|
13847
|
+
id: "harmonic_minor",
|
|
13848
|
+
label: "\u548C\u58F0\u7684\u77ED\u97F3\u968E",
|
|
13849
|
+
tonic: 5,
|
|
13850
|
+
parent: HARMONIC_MINOR_SCALE,
|
|
13851
|
+
core: [5, 0, 1, 2, 4],
|
|
13852
|
+
// ラ ド レ ミ ソ♯
|
|
13853
|
+
minorish: true,
|
|
13854
|
+
strict: false,
|
|
13855
|
+
center: HARMONIC_MINOR_CENTER,
|
|
13856
|
+
description: "\u5C0E\u97F3\u30BD\u266F\u3092\u6301\u3064\u77ED\u8ABF\u3002\u58972\u5EA6\u304C\u6CE3\u304D\u3092\u4F5C\u308B\u3002\u30AF\u30E9\u30B7\u30C3\u30AF\u30FBV\u7CFB\u30FB\u5287\u4F34"
|
|
13857
|
+
},
|
|
13858
|
+
hijaz: {
|
|
13859
|
+
id: "hijaz",
|
|
13860
|
+
label: "\u30D2\u30B8\u30E3\u30FC\u30BA\uFF08\u30D5\u30EA\u30B8\u30A2\u30F3\u30FB\u30C9\u30DF\u30CA\u30F3\u30C8\uFF09",
|
|
13861
|
+
tonic: 2,
|
|
13862
|
+
parent: HARMONIC_MINOR_SCALE,
|
|
13863
|
+
core: [2, 3, 4, 5, 6],
|
|
13864
|
+
// ミ ファ ソ♯ ラ シ
|
|
13865
|
+
minorish: false,
|
|
13866
|
+
strict: false,
|
|
13867
|
+
center: HIJAZ_CENTER,
|
|
13868
|
+
description: "\u4E3B\u97F3\u306E\u4E0A\u304C\u534A\u97F3\u3001\u4E3B\u548C\u97F3\u306F\u9577\u4E09\u548C\u97F3\u3002\u4E2D\u6771\u30FB\u30B9\u30D1\u30CB\u30C3\u30B7\u30E5\u30FB\u30E1\u30BF\u30EB"
|
|
13869
|
+
},
|
|
13870
|
+
hungarian: {
|
|
13871
|
+
id: "hungarian",
|
|
13872
|
+
label: "\u30CF\u30F3\u30AC\u30EA\u30A2\u30F3\u30FB\u30DE\u30A4\u30CA\u30FC\uFF08\u30B8\u30D7\u30B7\u30FC\uFF09",
|
|
13873
|
+
tonic: 5,
|
|
13874
|
+
parent: HUNGARIAN_SCALE,
|
|
13875
|
+
core: [5, 0, 1, 2, 4],
|
|
13876
|
+
// ラ ド レ♯ ミ ソ♯
|
|
13877
|
+
minorish: true,
|
|
13878
|
+
strict: false,
|
|
13879
|
+
center: HUNGARIAN_CENTER,
|
|
13880
|
+
description: "\u58972\u5EA6\u304C2\u304B\u6240\u3002\u97F3\u968E\u306E\u4E2D\u3067\u3044\u3061\u3070\u3093\u8DF3\u306D\u305F\u3001\u7570\u56FD\u3081\u3044\u305F\u97FF\u304D"
|
|
13881
|
+
},
|
|
13882
|
+
blues: {
|
|
13883
|
+
id: "blues",
|
|
13884
|
+
label: "\u30D6\u30EB\u30FC\u30B9\u97F3\u968E",
|
|
13885
|
+
tonic: 0,
|
|
13886
|
+
parent: BLUES_SCALE,
|
|
13887
|
+
core: [0, 1, 2, 4, 5],
|
|
13888
|
+
// ド ミ♭ ファ ソ シ♭
|
|
13889
|
+
minorish: true,
|
|
13890
|
+
strict: true,
|
|
13891
|
+
center: BLUES_CENTER,
|
|
13892
|
+
description: "\u30D6\u30EB\u30FC\u30CE\u30FC\u30C8\u5165\u308A\u306E6\u97F3\u97F3\u968E\u3002\u77ED3\u5EA6\u3067\u6B4C\u3044\u3001\u4F34\u594F\u306F\u95773\u5EA6\u3067\u9CF4\u308B"
|
|
13893
|
+
}
|
|
13894
|
+
};
|
|
13895
|
+
var COMPOSE_SCALE_IDS = Object.keys(
|
|
13896
|
+
COMPOSE_SCALES
|
|
13897
|
+
);
|
|
13898
|
+
var TONIC_CENTERS = {
|
|
13899
|
+
// --- レ(律・ドリアン) ---
|
|
13900
|
+
1: {
|
|
13901
|
+
tonic: "Dm",
|
|
13902
|
+
half: "G",
|
|
13903
|
+
deceptive: "F",
|
|
13904
|
+
tonicPattern: /^Dm/,
|
|
13905
|
+
a: [
|
|
13906
|
+
["Dm", "G", "Dm", "Dm"],
|
|
13907
|
+
// i-IV の往復。ドリアンの顔
|
|
13908
|
+
["Dm", "Am", "G", "Dm"],
|
|
13909
|
+
["Dm", "C", "G", "Dm"],
|
|
13910
|
+
["Dm7", "G", "Dm7", "C"],
|
|
13911
|
+
["Dm", "F", "C", "G"],
|
|
13912
|
+
["Dm", "Em", "F", "G"],
|
|
13913
|
+
["Dm", "G", "F", "C"],
|
|
13914
|
+
["Dm7", "Em7", "FM7", "G"]
|
|
13915
|
+
],
|
|
13916
|
+
b: [
|
|
13917
|
+
["F", "G", "Am", "Dm"],
|
|
13918
|
+
["C", "G", "Dm", "Dm"],
|
|
13919
|
+
["G", "F", "C", "Dm"],
|
|
13920
|
+
["Am", "G", "F", "Dm"],
|
|
13921
|
+
["FM7", "G", "Em7", "Dm7"],
|
|
13922
|
+
["Dm", "G", "C", "Am"]
|
|
13923
|
+
],
|
|
13924
|
+
c: [
|
|
13925
|
+
["Am", "Dm", "G", "C"],
|
|
13926
|
+
["F", "Em", "Dm", "G"],
|
|
13927
|
+
["Dm", "Am", "Em", "G"]
|
|
13928
|
+
]
|
|
13929
|
+
},
|
|
13930
|
+
// --- ミ(都節・フリジアン) ---
|
|
13931
|
+
2: {
|
|
13932
|
+
tonic: "Em",
|
|
13933
|
+
half: "Am",
|
|
13934
|
+
deceptive: "C",
|
|
13935
|
+
tonicPattern: /^Em/,
|
|
13936
|
+
a: [
|
|
13937
|
+
["Em", "F", "Em", "Em"],
|
|
13938
|
+
// i-♭II。フリジアン/都節の顔
|
|
13939
|
+
["Em", "Am", "F", "Em"],
|
|
13940
|
+
["Am", "Em", "F", "Em"],
|
|
13941
|
+
["Em", "F", "G", "Em"],
|
|
13942
|
+
["Em", "Em", "F", "F"],
|
|
13943
|
+
["Em", "C", "F", "Em"],
|
|
13944
|
+
["Am", "F", "Em", "Em"],
|
|
13945
|
+
["Em7", "FM7", "Em7", "Am7"]
|
|
13946
|
+
],
|
|
13947
|
+
b: [
|
|
13948
|
+
["F", "G", "Am", "Em"],
|
|
13949
|
+
["Am", "G", "F", "Em"],
|
|
13950
|
+
["F", "Em", "Am", "Em"],
|
|
13951
|
+
["C", "F", "Em", "Em"],
|
|
13952
|
+
["FM7", "G", "Em7", "Am"],
|
|
13953
|
+
["Am", "Em", "F", "G"]
|
|
13954
|
+
],
|
|
13955
|
+
c: [
|
|
13956
|
+
["Am", "Em", "F", "C"],
|
|
13957
|
+
["C", "G", "Am", "Em"],
|
|
13958
|
+
["F", "C", "Am", "Em"]
|
|
13959
|
+
]
|
|
13960
|
+
},
|
|
13961
|
+
// --- ファ(リディアン) ---
|
|
13962
|
+
3: {
|
|
13963
|
+
tonic: "FM7",
|
|
13964
|
+
half: "C",
|
|
13965
|
+
deceptive: "Dm",
|
|
13966
|
+
tonicPattern: /^F(?![#b]|m)/,
|
|
13967
|
+
a: [
|
|
13968
|
+
["FM7", "G", "FM7", "FM7"],
|
|
13969
|
+
// I-II。リディアンの顔(♯4 が G の3度に居る)
|
|
13970
|
+
["FM7", "G", "Em", "Am"],
|
|
13971
|
+
["F", "G", "C", "F"],
|
|
13972
|
+
["FM7", "G", "Am", "F"],
|
|
13973
|
+
["F", "C", "G", "F"],
|
|
13974
|
+
["FM7", "Em7", "Dm7", "G"],
|
|
13975
|
+
["F", "G", "F", "C"],
|
|
13976
|
+
["FM7", "G", "Dm7", "F"]
|
|
13977
|
+
],
|
|
13978
|
+
b: [
|
|
13979
|
+
["G", "F", "C", "F"],
|
|
13980
|
+
["Am", "G", "FM7", "FM7"],
|
|
13981
|
+
["C", "G", "Am", "F"],
|
|
13982
|
+
["G", "Em", "Am", "F"],
|
|
13983
|
+
["Dm7", "G", "FM7", "FM7"],
|
|
13984
|
+
["FM7", "G", "Em7", "F"]
|
|
13985
|
+
],
|
|
13986
|
+
c: [
|
|
13987
|
+
["Dm", "Am", "F", "G"],
|
|
13988
|
+
["Am", "Em", "F", "G"],
|
|
13989
|
+
["C", "Am", "Dm", "F"]
|
|
13990
|
+
]
|
|
13991
|
+
},
|
|
13992
|
+
// --- ソ(ミクソリディアン) ---
|
|
13993
|
+
4: {
|
|
13994
|
+
tonic: "G",
|
|
13995
|
+
half: "Dm",
|
|
13996
|
+
deceptive: "Em",
|
|
13997
|
+
tonicPattern: /^G(?![#b]|m)/,
|
|
13998
|
+
a: [
|
|
13999
|
+
["G", "F", "C", "G"],
|
|
14000
|
+
// I-♭VII-IV。ミクソリディアンの顔
|
|
14001
|
+
["G", "C", "F", "G"],
|
|
14002
|
+
["G", "F", "G", "G"],
|
|
14003
|
+
["C", "G", "F", "G"],
|
|
14004
|
+
["G", "Dm", "F", "G"],
|
|
14005
|
+
["G", "Am", "F", "G"],
|
|
14006
|
+
["G", "F", "Dm", "C"],
|
|
14007
|
+
["G", "C", "G", "F"]
|
|
14008
|
+
],
|
|
14009
|
+
b: [
|
|
14010
|
+
["F", "C", "G", "G"],
|
|
14011
|
+
["Am", "F", "C", "G"],
|
|
14012
|
+
["C", "Dm", "F", "G"],
|
|
14013
|
+
["Em", "F", "C", "G"],
|
|
14014
|
+
["F", "G", "Am", "G"],
|
|
14015
|
+
["Dm7", "F", "C", "G"]
|
|
14016
|
+
],
|
|
14017
|
+
c: [
|
|
14018
|
+
["Am", "Em", "F", "G"],
|
|
14019
|
+
["C", "Am", "Dm", "G"],
|
|
14020
|
+
["Em", "Am", "F", "C"]
|
|
14021
|
+
]
|
|
14022
|
+
}
|
|
14023
|
+
};
|
|
14024
|
+
var scaleDegrees = (scale) => scale.parent ?? MAJOR_SCALE2;
|
|
14025
|
+
var scaleSize = (scale) => scaleDegrees(scale).length;
|
|
14026
|
+
var degreeToPitch = (scale, degree) => {
|
|
14027
|
+
const list = scaleDegrees(scale);
|
|
14028
|
+
const size = list.length;
|
|
14029
|
+
const index = (degree % size + size) % size;
|
|
14030
|
+
const octave = Math.floor(degree / size);
|
|
14031
|
+
const d = list[index];
|
|
14032
|
+
return { semi: d.semi + octave * 12, fifth: d.fifth };
|
|
14033
|
+
};
|
|
14034
|
+
var semitoneToDegree = (scale, semi) => {
|
|
14035
|
+
const list = scaleDegrees(scale);
|
|
14036
|
+
const octave = Math.floor(semi / 12);
|
|
14037
|
+
const within = semi - octave * 12;
|
|
14038
|
+
let best = 0;
|
|
14039
|
+
let bestDist = Number.POSITIVE_INFINITY;
|
|
14040
|
+
for (let i2 = 0; i2 < list.length; i2++) {
|
|
14041
|
+
const dist = Math.abs(list[i2].semi - within);
|
|
14042
|
+
if (dist < bestDist) {
|
|
14043
|
+
bestDist = dist;
|
|
14044
|
+
best = i2;
|
|
14045
|
+
}
|
|
14046
|
+
}
|
|
14047
|
+
return octave * list.length + best;
|
|
14048
|
+
};
|
|
14049
|
+
var walk = (scale, semi, delta) => degreeToPitch(scale, semitoneToDegree(scale, semi) + delta).semi;
|
|
14050
|
+
var scaleFifth = (scale, semi) => degreeToPitch(scale, semitoneToDegree(scale, semi)).fifth;
|
|
14051
|
+
var SCALE_PCS = /* @__PURE__ */ new Map();
|
|
14052
|
+
var scalePcs = (scale) => {
|
|
14053
|
+
const hit = SCALE_PCS.get(scale.id);
|
|
14054
|
+
if (hit) return hit;
|
|
14055
|
+
const set = new Set(
|
|
14056
|
+
scaleDegrees(scale).map((d) => (d.semi % 12 + 12) % 12)
|
|
14057
|
+
);
|
|
14058
|
+
SCALE_PCS.set(scale.id, set);
|
|
14059
|
+
return set;
|
|
14060
|
+
};
|
|
14061
|
+
var CORE_SORTED = /* @__PURE__ */ new Map();
|
|
14062
|
+
var sortedCore = (scale) => {
|
|
14063
|
+
const hit = CORE_SORTED.get(scale.id);
|
|
14064
|
+
if (hit) return hit;
|
|
14065
|
+
const sorted = [...scale.core].sort((a, b) => a - b);
|
|
14066
|
+
CORE_SORTED.set(scale.id, sorted);
|
|
14067
|
+
return sorted;
|
|
14068
|
+
};
|
|
14069
|
+
var CORE_PCS = /* @__PURE__ */ new Map();
|
|
14070
|
+
var corePcs = (scale) => {
|
|
14071
|
+
const hit = CORE_PCS.get(scale.id);
|
|
14072
|
+
if (hit) return hit;
|
|
14073
|
+
const list = scaleDegrees(scale);
|
|
14074
|
+
const set = new Set(scale.core.map((d) => (list[d].semi % 12 + 12) % 12));
|
|
14075
|
+
CORE_PCS.set(scale.id, set);
|
|
14076
|
+
return set;
|
|
14077
|
+
};
|
|
14078
|
+
var isCoreDegree = (scale, degree) => {
|
|
14079
|
+
const size = scaleSize(scale);
|
|
14080
|
+
return sortedCore(scale).includes((degree % size + size) % size);
|
|
14081
|
+
};
|
|
14082
|
+
var coreToDegree = (scale, step) => {
|
|
14083
|
+
const sorted = sortedCore(scale);
|
|
14084
|
+
const n = sorted.length;
|
|
14085
|
+
const index = (step % n + n) % n;
|
|
14086
|
+
const octave = Math.floor(step / n);
|
|
14087
|
+
return sorted[index] + octave * scaleSize(scale);
|
|
14088
|
+
};
|
|
14089
|
+
var degreeToCore = (scale, degree) => {
|
|
14090
|
+
const sorted = sortedCore(scale);
|
|
14091
|
+
const size = scaleSize(scale);
|
|
14092
|
+
const index = (degree % size + size) % size;
|
|
14093
|
+
const octave = Math.floor(degree / size);
|
|
14094
|
+
let best = 0;
|
|
14095
|
+
let bestDist = Number.POSITIVE_INFINITY;
|
|
14096
|
+
for (let i2 = 0; i2 < sorted.length; i2++) {
|
|
14097
|
+
const dist = Math.abs(sorted[i2] - index);
|
|
14098
|
+
if (dist < bestDist) {
|
|
14099
|
+
bestDist = dist;
|
|
14100
|
+
best = i2;
|
|
14101
|
+
}
|
|
14102
|
+
}
|
|
14103
|
+
return octave * sorted.length + best;
|
|
14104
|
+
};
|
|
14105
|
+
var isOutsideCore = (scale, semi) => scale.strict ? !corePcs(scale).has((semi % 12 + 12) % 12) : !isCoreDegree(scale, semitoneToDegree(scale, semi));
|
|
14106
|
+
var resolveComposeScale = (choice, minorKey, rnd = Math.random) => {
|
|
14107
|
+
const c = (choice ?? "").trim() || "auto";
|
|
14108
|
+
const hit = COMPOSE_SCALES[c];
|
|
14109
|
+
if (hit) return hit;
|
|
14110
|
+
if (c === "any")
|
|
14111
|
+
return COMPOSE_SCALES[COMPOSE_SCALE_IDS[Math.floor(rnd() * COMPOSE_SCALE_IDS.length)] ?? "yo"];
|
|
14112
|
+
return COMPOSE_SCALES[minorKey ? "minyo" : "yo"];
|
|
14113
|
+
};
|
|
14114
|
+
var getComposeScaleDescription = (choice) => {
|
|
14115
|
+
const hit = COMPOSE_SCALES[choice];
|
|
14116
|
+
if (hit) return hit.description;
|
|
14117
|
+
if (choice === "any")
|
|
14118
|
+
return `${COMPOSE_SCALE_IDS.length}\u3064\u306E\u97F3\u968E\u304B\u3089\u30E9\u30F3\u30C0\u30E0\u306B\u62BD\u9078\u3057\u307E\u3059`;
|
|
14119
|
+
return "\u30D9\u30FC\u30B9\u8ABF\u306E\u9577\u77ED\u306B\u5408\u308F\u305B\u3066\u3001\u967D\u97F3\u968E\uFF08\u9577\u8ABF\uFF09\u304B\u6C11\u8B21\u97F3\u968E\uFF08\u77ED\u8ABF\uFF09\u3092\u4F7F\u3044\u307E\u3059";
|
|
14120
|
+
};
|
|
14121
|
+
var resolveCenter = (scale) => scale.center ?? TONIC_CENTERS[scale.tonic] ?? null;
|
|
14122
|
+
|
|
13463
14123
|
// src/compose-sections.ts
|
|
13464
14124
|
var SECTION_LABELS = {
|
|
13465
14125
|
intro: "\u30A4\u30F3\u30C8\u30ED",
|
|
@@ -13884,65 +14544,6 @@ var BPM_CHOICES = [
|
|
|
13884
14544
|
180,
|
|
13885
14545
|
185
|
|
13886
14546
|
];
|
|
13887
|
-
var MAJOR_SCALE2 = [
|
|
13888
|
-
{ semi: 0, fifth: 0 },
|
|
13889
|
-
// C
|
|
13890
|
-
{ semi: 2, fifth: 2 },
|
|
13891
|
-
// D
|
|
13892
|
-
{ semi: 4, fifth: 4 },
|
|
13893
|
-
// E
|
|
13894
|
-
{ semi: 5, fifth: -1 },
|
|
13895
|
-
// F
|
|
13896
|
-
{ semi: 7, fifth: 1 },
|
|
13897
|
-
// G
|
|
13898
|
-
{ semi: 9, fifth: 3 },
|
|
13899
|
-
// A
|
|
13900
|
-
{ semi: 11, fifth: 5 }
|
|
13901
|
-
// B
|
|
13902
|
-
];
|
|
13903
|
-
var degreeToPitch = (degree) => {
|
|
13904
|
-
const index = (degree % 7 + 7) % 7;
|
|
13905
|
-
const octave = Math.floor(degree / 7);
|
|
13906
|
-
const d = MAJOR_SCALE2[index];
|
|
13907
|
-
return { semi: d.semi + octave * 12, fifth: d.fifth };
|
|
13908
|
-
};
|
|
13909
|
-
var semitoneToDegree = (semi) => {
|
|
13910
|
-
const octave = Math.floor(semi / 12);
|
|
13911
|
-
const within = semi - octave * 12;
|
|
13912
|
-
let best = 0;
|
|
13913
|
-
let bestDist = Number.POSITIVE_INFINITY;
|
|
13914
|
-
for (let i2 = 0; i2 < MAJOR_SCALE2.length; i2++) {
|
|
13915
|
-
const dist = Math.abs(MAJOR_SCALE2[i2].semi - within);
|
|
13916
|
-
if (dist < bestDist) {
|
|
13917
|
-
bestDist = dist;
|
|
13918
|
-
best = i2;
|
|
13919
|
-
}
|
|
13920
|
-
}
|
|
13921
|
-
return octave * 7 + best;
|
|
13922
|
-
};
|
|
13923
|
-
var walk = (semi, delta) => degreeToPitch(semitoneToDegree(semi) + delta).semi;
|
|
13924
|
-
var NON_PENTATONIC_DEGREES = /* @__PURE__ */ new Set([3, 6]);
|
|
13925
|
-
var isNonPentatonic = (semi) => NON_PENTATONIC_DEGREES.has((semitoneToDegree(semi) % 7 + 7) % 7);
|
|
13926
|
-
var PENTATONIC_DEGREES = [0, 1, 2, 4, 5];
|
|
13927
|
-
var pentaToDegree = (penta) => {
|
|
13928
|
-
const index = (penta % 5 + 5) % 5;
|
|
13929
|
-
const octave = Math.floor(penta / 5);
|
|
13930
|
-
return PENTATONIC_DEGREES[index] + octave * 7;
|
|
13931
|
-
};
|
|
13932
|
-
var degreeToPenta = (degree) => {
|
|
13933
|
-
const index = (degree % 7 + 7) % 7;
|
|
13934
|
-
const octave = Math.floor(degree / 7);
|
|
13935
|
-
let best = 0;
|
|
13936
|
-
let bestDist = Number.POSITIVE_INFINITY;
|
|
13937
|
-
for (let i2 = 0; i2 < PENTATONIC_DEGREES.length; i2++) {
|
|
13938
|
-
const dist = Math.abs(PENTATONIC_DEGREES[i2] - index);
|
|
13939
|
-
if (dist < bestDist) {
|
|
13940
|
-
bestDist = dist;
|
|
13941
|
-
best = i2;
|
|
13942
|
-
}
|
|
13943
|
-
}
|
|
13944
|
-
return octave * 5 + best;
|
|
13945
|
-
};
|
|
13946
14547
|
var SECTION_A_PROGRESSIONS = [
|
|
13947
14548
|
["C", "G", "Am", "Em7"],
|
|
13948
14549
|
// カノン進行の前半
|
|
@@ -14061,6 +14662,22 @@ var SECTION_DECEPTIVE_DERIVATIONS = [
|
|
|
14061
14662
|
(a, t) => [a[0], "Dm7", "G7", t === "Am" ? "FM7" : "Am7"],
|
|
14062
14663
|
(a, t) => [a[0], "F", "G7", t === "Am" ? "F" : "Am7"]
|
|
14063
14664
|
];
|
|
14665
|
+
var MODAL_FULL_DERIVATIONS = [
|
|
14666
|
+
(a, c) => [a[0], a[1], c.half, c.tonic],
|
|
14667
|
+
(a, c) => [a[0], c.half, a[2], c.tonic],
|
|
14668
|
+
(a, c) => [a[0], a[1], a[2], c.tonic],
|
|
14669
|
+
(a, c) => [c.tonic, c.half, a[2], c.tonic]
|
|
14670
|
+
];
|
|
14671
|
+
var MODAL_HALF_DERIVATIONS = [
|
|
14672
|
+
(a, c) => [a[0], a[1], a[2], c.half],
|
|
14673
|
+
(a, c) => [a[0], a[1], c.tonic, c.half],
|
|
14674
|
+
(a, c) => [a[0], c.tonic, a[2], c.half]
|
|
14675
|
+
];
|
|
14676
|
+
var MODAL_DECEPTIVE_DERIVATIONS = [
|
|
14677
|
+
(a, c) => [a[0], a[1], c.half, c.deceptive],
|
|
14678
|
+
(a, c) => [a[0], c.half, a[2], c.deceptive],
|
|
14679
|
+
(a, c) => [a[0], a[1], a[2], c.deceptive]
|
|
14680
|
+
];
|
|
14064
14681
|
var MODAL_BORROW = {
|
|
14065
14682
|
F: "Fm",
|
|
14066
14683
|
// IV → IVm(サブドミナントマイナー。いちばん定番)
|
|
@@ -14651,7 +15268,7 @@ var nearestChordTone = (targetSemi, tones, minWeight, preferColor = false) => {
|
|
|
14651
15268
|
var MELODY_LOW = 60;
|
|
14652
15269
|
var MELODY_HIGH = 81;
|
|
14653
15270
|
var MELODY_CENTER = (MELODY_LOW + MELODY_HIGH) / 2;
|
|
14654
|
-
var harmonyPitch = (melodySemi, tones, prevHarmony, offset, parallel, against) => {
|
|
15271
|
+
var harmonyPitch = (scale, melodySemi, tones, prevHarmony, offset, parallel, against) => {
|
|
14655
15272
|
const lo = Math.max(-12, Math.min(offset, 0) - 7);
|
|
14656
15273
|
const hi = Math.min(12, Math.max(offset, 0) + 7);
|
|
14657
15274
|
let best = null;
|
|
@@ -14669,7 +15286,8 @@ var harmonyPitch = (melodySemi, tones, prevHarmony, offset, parallel, against) =
|
|
|
14669
15286
|
const g = Math.abs(semi - against) % 12;
|
|
14670
15287
|
clash = g === 3 || g === 4 || g === 8 || g === 9 || g === 7 ? 0 : g === 0 ? 0.5 : 1.2;
|
|
14671
15288
|
}
|
|
14672
|
-
const
|
|
15289
|
+
const offCore = scale.strict && isOutsideCore(scale, semi) ? 1.5 : 0;
|
|
15290
|
+
const cost = stay + clash + offCore + Math.abs(delta - offset) * (parallel ? 1.4 : 0.7) + (3 - tone.weight) * 0.4;
|
|
14673
15291
|
if (cost < bestCost) {
|
|
14674
15292
|
bestCost = cost;
|
|
14675
15293
|
best = { semi, fifth: tone.fifth };
|
|
@@ -14714,40 +15332,43 @@ var leapTarget = (from, tones, rnd) => {
|
|
|
14714
15332
|
];
|
|
14715
15333
|
return pick(weighted.length > 0 ? weighted : candidates, rnd);
|
|
14716
15334
|
};
|
|
14717
|
-
var landOn = (degrees, scaleIndex) => {
|
|
15335
|
+
var landOn = (scale, degrees, scaleIndex) => {
|
|
14718
15336
|
if (degrees.length === 0) return;
|
|
15337
|
+
const size = scaleSize(scale);
|
|
14719
15338
|
const last = degrees[degrees.length - 1];
|
|
14720
|
-
const index = (last %
|
|
15339
|
+
const index = (last % size + size) % size;
|
|
14721
15340
|
let delta = scaleIndex - index;
|
|
14722
|
-
if (delta >
|
|
14723
|
-
if (delta < -
|
|
15341
|
+
if (delta > size / 2) delta -= size;
|
|
15342
|
+
if (delta < -size / 2) delta += size;
|
|
14724
15343
|
degrees[degrees.length - 1] = last + delta;
|
|
14725
15344
|
};
|
|
14726
|
-
var landPitch = (pitches, scaleIndex) => {
|
|
15345
|
+
var landPitch = (scale, pitches, scaleIndex) => {
|
|
14727
15346
|
if (pitches.length === 0) return;
|
|
15347
|
+
const size = scaleSize(scale);
|
|
14728
15348
|
const last = pitches[pitches.length - 1];
|
|
14729
|
-
const degree = semitoneToDegree(last);
|
|
14730
|
-
const index = (degree %
|
|
15349
|
+
const degree = semitoneToDegree(scale, last);
|
|
15350
|
+
const index = (degree % size + size) % size;
|
|
14731
15351
|
let delta = scaleIndex - index;
|
|
14732
|
-
if (delta >
|
|
14733
|
-
if (delta < -
|
|
15352
|
+
if (delta > size / 2) delta -= size;
|
|
15353
|
+
if (delta < -size / 2) delta += size;
|
|
14734
15354
|
pitches[pitches.length - 1] = clampSemi(
|
|
14735
|
-
degreeToPitch(degree + delta).semi,
|
|
15355
|
+
degreeToPitch(scale, degree + delta).semi,
|
|
14736
15356
|
MELODY_LOW,
|
|
14737
15357
|
MELODY_HIGH
|
|
14738
15358
|
);
|
|
14739
15359
|
};
|
|
14740
|
-
var barDegrees = (role, slots, tones, style, motifContour, startDegree, contourOffset, repeatShift, barHeadWeight, preferColor, quarterSteps, rnd) => {
|
|
15360
|
+
var barDegrees = (role, slots, tones, style, scale, motifContour, startDegree, contourOffset, repeatShift, barHeadWeight, preferColor, quarterSteps, rnd) => {
|
|
14741
15361
|
const noteCount = slots.length;
|
|
14742
15362
|
const out = [];
|
|
14743
15363
|
if (role === "motif" || role === "sequence" || role === "climax" || role === "answer") {
|
|
14744
15364
|
const shift = (role === "sequence" ? pick([-2, -1, 1, 2], rnd) : role === "climax" ? 5 : 0) + repeatShift;
|
|
14745
15365
|
if (style.pentatonicMotif) {
|
|
14746
|
-
const
|
|
15366
|
+
const startCore = degreeToCore(scale, startDegree);
|
|
14747
15367
|
for (let i2 = 0; i2 < noteCount; i2++)
|
|
14748
15368
|
out.push(
|
|
14749
|
-
|
|
14750
|
-
|
|
15369
|
+
coreToDegree(
|
|
15370
|
+
scale,
|
|
15371
|
+
startCore + shift + motifContour[(contourOffset + i2) % motifContour.length]
|
|
14751
15372
|
)
|
|
14752
15373
|
);
|
|
14753
15374
|
} else {
|
|
@@ -14767,9 +15388,9 @@ var barDegrees = (role, slots, tones, style, motifContour, startDegree, contourO
|
|
|
14767
15388
|
for (let i2 = 0; i2 < noteCount; i2++)
|
|
14768
15389
|
out.push(startDegree + dir2 * (i2 < peak ? i2 : peak * 2 - i2 - 1));
|
|
14769
15390
|
} else if (style.runShape === "broken") {
|
|
14770
|
-
const arp = tones.map((t) => semitoneToDegree(clampSemi(t.semi, 60, 71))).sort((a, b) => a - b);
|
|
15391
|
+
const arp = tones.map((t) => semitoneToDegree(scale, clampSemi(t.semi, 60, 71))).sort((a, b) => a - b);
|
|
14771
15392
|
for (let i2 = 0; i2 < noteCount; i2++) {
|
|
14772
|
-
const oct = Math.floor(i2 / arp.length) *
|
|
15393
|
+
const oct = Math.floor(i2 / arp.length) * scaleSize(scale);
|
|
14773
15394
|
const idx = dir2 > 0 ? i2 % arp.length : arp.length - 1 - i2 % arp.length;
|
|
14774
15395
|
out.push(arp[idx] + dir2 * oct);
|
|
14775
15396
|
}
|
|
@@ -14792,7 +15413,10 @@ var barDegrees = (role, slots, tones, style, motifContour, startDegree, contourO
|
|
|
14792
15413
|
return out;
|
|
14793
15414
|
}
|
|
14794
15415
|
if (role === "cadence") {
|
|
14795
|
-
const tonic = semitoneToDegree(
|
|
15416
|
+
const tonic = semitoneToDegree(
|
|
15417
|
+
scale,
|
|
15418
|
+
clampSemi(72, MELODY_LOW, MELODY_HIGH)
|
|
15419
|
+
);
|
|
14796
15420
|
for (let i2 = 0; i2 < noteCount; i2++) {
|
|
14797
15421
|
if (style.cadenceShape === "descend") {
|
|
14798
15422
|
out.push(tonic + noteCount - 1 - i2);
|
|
@@ -14800,7 +15424,9 @@ var barDegrees = (role, slots, tones, style, motifContour, startDegree, contourO
|
|
|
14800
15424
|
const shape = [4, 2, 0];
|
|
14801
15425
|
out.push(tonic + shape[Math.min(i2, shape.length - 1)]);
|
|
14802
15426
|
} else if (style.cadenceShape === "leap-up") {
|
|
14803
|
-
out.push(
|
|
15427
|
+
out.push(
|
|
15428
|
+
i2 === noteCount - 1 ? tonic : tonic - scaleSize(scale) + Math.min(i2, 4)
|
|
15429
|
+
);
|
|
14804
15430
|
} else {
|
|
14805
15431
|
out.push(i2 === 0 && noteCount > 1 ? tonic + 1 : tonic);
|
|
14806
15432
|
}
|
|
@@ -14835,8 +15461,9 @@ var barDegrees = (role, slots, tones, style, motifContour, startDegree, contourO
|
|
|
14835
15461
|
for (let i2 = 0; i2 < out.length; i2++) {
|
|
14836
15462
|
if (!slots[i2].isStrong) continue;
|
|
14837
15463
|
out[i2] = semitoneToDegree(
|
|
15464
|
+
scale,
|
|
14838
15465
|
nearestChordTone(
|
|
14839
|
-
degreeToPitch(out[i2]).semi,
|
|
15466
|
+
degreeToPitch(scale, out[i2]).semi,
|
|
14840
15467
|
tones,
|
|
14841
15468
|
barHeadWeight,
|
|
14842
15469
|
preferColor
|
|
@@ -14847,9 +15474,9 @@ var barDegrees = (role, slots, tones, style, motifContour, startDegree, contourO
|
|
|
14847
15474
|
if (slots[i2].isStrong) continue;
|
|
14848
15475
|
if (slots[i2].value >= quarterSteps) {
|
|
14849
15476
|
if (rnd() < style.leapAffinity) {
|
|
14850
|
-
const from = degreeToPitch(out[i2 - 1]).semi;
|
|
15477
|
+
const from = degreeToPitch(scale, out[i2 - 1]).semi;
|
|
14851
15478
|
const target = leapTarget(from, tones, rnd);
|
|
14852
|
-
if (target !== null) out[i2] = semitoneToDegree(target);
|
|
15479
|
+
if (target !== null) out[i2] = semitoneToDegree(scale, target);
|
|
14853
15480
|
}
|
|
14854
15481
|
continue;
|
|
14855
15482
|
}
|
|
@@ -14859,7 +15486,7 @@ var barDegrees = (role, slots, tones, style, motifContour, startDegree, contourO
|
|
|
14859
15486
|
}
|
|
14860
15487
|
return out;
|
|
14861
15488
|
};
|
|
14862
|
-
var fitMotif = (degrees, slots, tones, prevSemi, quarterSteps, pentatonic, preferShift) => {
|
|
15489
|
+
var fitMotif = (degrees, slots, tones, prevSemi, quarterSteps, scale, pentatonic, preferShift) => {
|
|
14863
15490
|
let best = degrees;
|
|
14864
15491
|
let bestShift = 0;
|
|
14865
15492
|
let bestScore = Number.NEGATIVE_INFINITY;
|
|
@@ -14867,12 +15494,12 @@ var fitMotif = (degrees, slots, tones, prevSemi, quarterSteps, pentatonic, prefe
|
|
|
14867
15494
|
let preferMoved = null;
|
|
14868
15495
|
for (let shift = -3; shift <= 3; shift++) {
|
|
14869
15496
|
const moved = degrees.map(
|
|
14870
|
-
(d) => pentatonic ?
|
|
15497
|
+
(d) => pentatonic ? coreToDegree(scale, degreeToCore(scale, d) + shift) : d + shift
|
|
14871
15498
|
);
|
|
14872
15499
|
let score = 0;
|
|
14873
15500
|
for (let i2 = 0; i2 < moved.length; i2++) {
|
|
14874
15501
|
const semi = clampSemi(
|
|
14875
|
-
degreeToPitch(moved[i2]).semi,
|
|
15502
|
+
degreeToPitch(scale, moved[i2]).semi,
|
|
14876
15503
|
MELODY_LOW,
|
|
14877
15504
|
MELODY_HIGH
|
|
14878
15505
|
);
|
|
@@ -14881,7 +15508,7 @@ var fitMotif = (degrees, slots, tones, prevSemi, quarterSteps, pentatonic, prefe
|
|
|
14881
15508
|
score += important ? w * 3 : w;
|
|
14882
15509
|
}
|
|
14883
15510
|
const head = clampSemi(
|
|
14884
|
-
degreeToPitch(moved[0]).semi,
|
|
15511
|
+
degreeToPitch(scale, moved[0]).semi,
|
|
14885
15512
|
MELODY_LOW,
|
|
14886
15513
|
MELODY_HIGH
|
|
14887
15514
|
);
|
|
@@ -14904,7 +15531,7 @@ var shapeBar = (degrees, slots, tones, prevSemi, opts) => {
|
|
|
14904
15531
|
const out = [];
|
|
14905
15532
|
let prev = prevSemi;
|
|
14906
15533
|
if (opts.preserveContour) {
|
|
14907
|
-
const raw = degrees.map((d) => degreeToPitch(d).semi);
|
|
15534
|
+
const raw = degrees.map((d) => degreeToPitch(opts.scale, d).semi);
|
|
14908
15535
|
const lo = Math.min(...raw);
|
|
14909
15536
|
const hi = Math.max(...raw);
|
|
14910
15537
|
let shift = 0;
|
|
@@ -14918,30 +15545,42 @@ var shapeBar = (degrees, slots, tones, prevSemi, opts) => {
|
|
|
14918
15545
|
}
|
|
14919
15546
|
for (let i2 = 0; i2 < degrees.length; i2++) {
|
|
14920
15547
|
let semi = clampSemi(
|
|
14921
|
-
degreeToPitch(degrees[i2]).semi,
|
|
15548
|
+
degreeToPitch(opts.scale, degrees[i2]).semi,
|
|
14922
15549
|
MELODY_LOW,
|
|
14923
15550
|
MELODY_HIGH
|
|
14924
15551
|
);
|
|
14925
15552
|
const limit = i2 === 0 ? MAX_BAR_LEAP_SEMITONES : MAX_LEAP_SEMITONES;
|
|
14926
15553
|
if (!opts.allowLeap && Math.abs(semi - prev) > limit) {
|
|
14927
15554
|
semi = clampSemi(
|
|
14928
|
-
walk(prev, Math.sign(semi - prev) * 3),
|
|
15555
|
+
walk(opts.scale, prev, Math.sign(semi - prev) * 3),
|
|
14929
15556
|
MELODY_LOW,
|
|
14930
15557
|
MELODY_HIGH
|
|
14931
15558
|
);
|
|
14932
15559
|
}
|
|
14933
15560
|
if (!opts.allowArpeggio && i2 >= 2 && Math.abs(out[i2 - 1] - out[i2 - 2]) > STEP_SEMITONES) {
|
|
14934
15561
|
const back = -Math.sign(out[i2 - 1] - out[i2 - 2]);
|
|
14935
|
-
semi = clampSemi(
|
|
15562
|
+
semi = clampSemi(
|
|
15563
|
+
walk(opts.scale, out[i2 - 1], back),
|
|
15564
|
+
MELODY_LOW,
|
|
15565
|
+
MELODY_HIGH
|
|
15566
|
+
);
|
|
14936
15567
|
}
|
|
14937
15568
|
if (toneWeight(semi, tones) === 0 && (slots[i2].isStrong || slots[i2].value >= opts.quarterSteps)) {
|
|
14938
15569
|
const resolved = semi + 1;
|
|
14939
|
-
const useResolved = resolved <= MELODY_HIGH && !
|
|
15570
|
+
const useResolved = resolved <= MELODY_HIGH && !scalePcs(opts.scale).has(pitchClass(resolved)) && toneWeight(resolved, tones) >= 2 && resolved !== prev && opts.rnd() < opts.chromaticAffinity;
|
|
14940
15571
|
if (useResolved) {
|
|
14941
15572
|
semi = resolved;
|
|
14942
15573
|
} else {
|
|
14943
|
-
const up = clampSemi(
|
|
14944
|
-
|
|
15574
|
+
const up = clampSemi(
|
|
15575
|
+
walk(opts.scale, semi, 1),
|
|
15576
|
+
MELODY_LOW,
|
|
15577
|
+
MELODY_HIGH
|
|
15578
|
+
);
|
|
15579
|
+
const down = clampSemi(
|
|
15580
|
+
walk(opts.scale, semi, -1),
|
|
15581
|
+
MELODY_LOW,
|
|
15582
|
+
MELODY_HIGH
|
|
15583
|
+
);
|
|
14945
15584
|
const score = (s) => toneWeight(s, tones) * 2 + (i2 > 0 && s === prev ? -3 : 0);
|
|
14946
15585
|
semi = score(down) >= score(up) ? down : up;
|
|
14947
15586
|
}
|
|
@@ -14949,7 +15588,14 @@ var shapeBar = (degrees, slots, tones, prevSemi, opts) => {
|
|
|
14949
15588
|
out.push(semi);
|
|
14950
15589
|
prev = semi;
|
|
14951
15590
|
}
|
|
14952
|
-
applyPentatonic(
|
|
15591
|
+
applyPentatonic(
|
|
15592
|
+
out,
|
|
15593
|
+
slots,
|
|
15594
|
+
tones,
|
|
15595
|
+
prevSemi,
|
|
15596
|
+
opts.quarterSteps / 2,
|
|
15597
|
+
opts.scale
|
|
15598
|
+
);
|
|
14953
15599
|
applyOctaveJumps(out, slots, opts.octaveAffinity, opts.rnd);
|
|
14954
15600
|
return out;
|
|
14955
15601
|
};
|
|
@@ -14966,27 +15612,27 @@ var applyOctaveJumps = (out, slots, affinity, rnd) => {
|
|
|
14966
15612
|
out[i2] = canUp && (!canDown || rnd() < 0.5) ? up : down;
|
|
14967
15613
|
}
|
|
14968
15614
|
};
|
|
14969
|
-
var applyPentatonic = (out, slots, tones, prevSemi, shortSteps) => {
|
|
15615
|
+
var applyPentatonic = (out, slots, tones, prevSemi, shortSteps, scale) => {
|
|
14970
15616
|
for (let i2 = 0; i2 < out.length; i2++) {
|
|
14971
15617
|
const semi = out[i2];
|
|
14972
|
-
if (!
|
|
14973
|
-
if (tones.some((t) => pitchClass(t.semi) === pitchClass(semi)))
|
|
15618
|
+
if (!isOutsideCore(scale, semi)) continue;
|
|
15619
|
+
if (!scale.strict && tones.some((t) => pitchClass(t.semi) === pitchClass(semi)))
|
|
15620
|
+
continue;
|
|
14974
15621
|
const before = i2 === 0 ? prevSemi : out[i2 - 1];
|
|
14975
15622
|
const after = i2 + 1 < out.length ? out[i2 + 1] : null;
|
|
14976
15623
|
const inByStep = Math.abs(semi - before) <= STEP_SEMITONES;
|
|
14977
15624
|
const outByStep = after !== null && Math.abs(after - semi) <= STEP_SEMITONES;
|
|
14978
|
-
if (inByStep || outByStep) continue;
|
|
14979
|
-
if (!slots[i2].isStrong && slots[i2].value <= shortSteps)
|
|
14980
|
-
|
|
14981
|
-
const
|
|
14982
|
-
const
|
|
15625
|
+
if (scale.strict ? inByStep && outByStep : inByStep || outByStep) continue;
|
|
15626
|
+
if (!scale.strict && !slots[i2].isStrong && slots[i2].value <= shortSteps)
|
|
15627
|
+
continue;
|
|
15628
|
+
const up = clampSemi(walk(scale, semi, 1), MELODY_LOW, MELODY_HIGH);
|
|
15629
|
+
const down = clampSemi(walk(scale, semi, -1), MELODY_LOW, MELODY_HIGH);
|
|
15630
|
+
const score = (s) => (isOutsideCore(scale, s) ? -4 : 0) + toneWeight(s, tones) + (s === before ? -3 : 0) + (after !== null ? -Math.abs(after - s) / 12 : 0);
|
|
14983
15631
|
out[i2] = score(down) >= score(up) ? down : up;
|
|
14984
15632
|
}
|
|
14985
15633
|
};
|
|
14986
|
-
var DIATONIC_PCS = new Set(MAJOR_SCALE2.map((d) => d.semi));
|
|
14987
15634
|
var SHARP_FIFTHS = [0, 7, 2, 9, 4, -1, 6, 1, 8, 3, 10, 5];
|
|
14988
15635
|
var FLAT_FIFTHS = [0, -5, 2, -3, 4, -1, -6, 1, -4, 3, -2, 5];
|
|
14989
|
-
var diatonicFifth = (semi) => degreeToPitch(semitoneToDegree(semi)).fifth;
|
|
14990
15636
|
var nearestOctaveOf = (near, semi) => {
|
|
14991
15637
|
const pc = pitchClass(semi);
|
|
14992
15638
|
let best = pc;
|
|
@@ -15001,7 +15647,7 @@ var nearestOctaveOf = (near, semi) => {
|
|
|
15001
15647
|
}
|
|
15002
15648
|
return best;
|
|
15003
15649
|
};
|
|
15004
|
-
var applyChromatic = (pitches, fifths, slots, tones, opts) => {
|
|
15650
|
+
var applyChromatic = (scale, pitches, fifths, slots, tones, opts) => {
|
|
15005
15651
|
const last = pitches.length - 1;
|
|
15006
15652
|
for (let i2 = 0; i2 < pitches.length; i2++) {
|
|
15007
15653
|
const tone = tones.find(
|
|
@@ -15009,7 +15655,8 @@ var applyChromatic = (pitches, fifths, slots, tones, opts) => {
|
|
|
15009
15655
|
);
|
|
15010
15656
|
if (tone) fifths[i2] = tone.fifth;
|
|
15011
15657
|
}
|
|
15012
|
-
const
|
|
15658
|
+
const pcs = scalePcs(scale);
|
|
15659
|
+
const altered = tones.filter((t) => !pcs.has(pitchClass(t.semi)));
|
|
15013
15660
|
for (let i2 = 0; i2 < pitches.length; i2++) {
|
|
15014
15661
|
if (opts.keepLast && i2 === last) continue;
|
|
15015
15662
|
if (!slots[i2].isStrong && slots[i2].value < opts.quarterSteps) continue;
|
|
@@ -15037,7 +15684,7 @@ var applyChromatic = (pitches, fifths, slots, tones, opts) => {
|
|
|
15037
15684
|
const span = Math.abs(after - before);
|
|
15038
15685
|
const target = span === 2 ? before + dir : span === 3 ? after - dir : null;
|
|
15039
15686
|
if (target === null) continue;
|
|
15040
|
-
if (
|
|
15687
|
+
if (pcs.has(pitchClass(target))) continue;
|
|
15041
15688
|
if (target === before || target === after) continue;
|
|
15042
15689
|
if (target < MELODY_LOW || target > MELODY_HIGH) continue;
|
|
15043
15690
|
pitches[i2] = target;
|
|
@@ -15045,7 +15692,8 @@ var applyChromatic = (pitches, fifths, slots, tones, opts) => {
|
|
|
15045
15692
|
lastAltered = i2;
|
|
15046
15693
|
}
|
|
15047
15694
|
};
|
|
15048
|
-
var draw = (options, resolvedKey, rnd) => {
|
|
15695
|
+
var draw = (options, resolvedKey, scale, rnd) => {
|
|
15696
|
+
const center = resolveCenter(scale);
|
|
15049
15697
|
const stepsPerBar = options.stepsPerBar;
|
|
15050
15698
|
const edo = options.edo === 31 ? 31 : 12;
|
|
15051
15699
|
const scaleStep = (v) => Math.max(1, Math.round(Math.abs(v) * stepsPerBar / BASE_STEPS_PER_BAR)) * Math.sign(v);
|
|
@@ -15073,7 +15721,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15073
15721
|
const totalBars = sectionPlan.reduce((sum, s) => sum + s.bars, 0);
|
|
15074
15722
|
const relativeKinds = /* @__PURE__ */ new Set();
|
|
15075
15723
|
let relativeShift = 0;
|
|
15076
|
-
if (rnd() < 0.25) {
|
|
15724
|
+
if (rnd() < 0.25 && !center) {
|
|
15077
15725
|
for (const kind of pick(
|
|
15078
15726
|
[["prechorus"], ["bridge"], ["prechorus", "bridge"]],
|
|
15079
15727
|
rnd
|
|
@@ -15183,42 +15831,42 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15183
15831
|
barKeyShift[b] = s.keyShift;
|
|
15184
15832
|
}
|
|
15185
15833
|
}
|
|
15186
|
-
const progAPool = resolvedKey.mode === "major" ? SECTION_A_PROGRESSIONS.filter((p) => !p[0].startsWith("Am")) : resolvedKey.mode === "minor" ? SECTION_A_PROGRESSIONS.filter((p) => p[0].startsWith("Am")) : SECTION_A_PROGRESSIONS;
|
|
15834
|
+
const progAPool = center ? center.a : resolvedKey.mode === "major" ? SECTION_A_PROGRESSIONS.filter((p) => !p[0].startsWith("Am")) : resolvedKey.mode === "minor" ? SECTION_A_PROGRESSIONS.filter((p) => p[0].startsWith("Am")) : SECTION_A_PROGRESSIONS;
|
|
15187
15835
|
const withoutTonic = (pool, root) => {
|
|
15188
|
-
const isTonic = (c) => root === "Am" ? /^Am/.test(c) : /^C(?![#b]|m)/.test(c);
|
|
15836
|
+
const isTonic = (c) => center ? center.tonicPattern.test(c) : root === "Am" ? /^Am/.test(c) : /^C(?![#b]|m)/.test(c);
|
|
15189
15837
|
const out = pool.filter((p) => !p.some(isTonic));
|
|
15190
15838
|
return out.length > 0 ? out : pool;
|
|
15191
15839
|
};
|
|
15192
|
-
const homeRoot = resolvedKey.mode === "minor" ? "Am" : "C";
|
|
15840
|
+
const homeRoot = center ? center.tonic : resolvedKey.mode === "minor" ? "Am" : "C";
|
|
15193
15841
|
const progA = pick(
|
|
15194
15842
|
floating ? withoutTonic(progAPool, homeRoot) : progAPool,
|
|
15195
15843
|
rnd
|
|
15196
15844
|
);
|
|
15197
|
-
const progBPool = SECTION_B_PROGRESSIONS.filter(
|
|
15845
|
+
const progBPool = (center ? center.b : SECTION_B_PROGRESSIONS).filter(
|
|
15198
15846
|
(p) => p.join("|") !== progA.join("|")
|
|
15199
15847
|
);
|
|
15200
15848
|
const progB = pick(
|
|
15201
15849
|
floating ? withoutTonic(progBPool, homeRoot) : progBPool,
|
|
15202
15850
|
rnd
|
|
15203
15851
|
);
|
|
15204
|
-
const progRelativePool = SECTION_A_PROGRESSIONS.filter(
|
|
15852
|
+
const progRelativePool = center ? center.a : SECTION_A_PROGRESSIONS.filter(
|
|
15205
15853
|
(p) => resolvedKey.mode === "minor" ? !p[0].startsWith("Am") : p[0].startsWith("Am")
|
|
15206
15854
|
);
|
|
15207
15855
|
const progRelative = pick(
|
|
15208
15856
|
floating ? withoutTonic(progRelativePool, homeRoot) : progRelativePool,
|
|
15209
15857
|
rnd
|
|
15210
15858
|
);
|
|
15211
|
-
const progCPool = SECTION_C_PROGRESSIONS.filter(
|
|
15859
|
+
const progCPool = (center ? center.c : SECTION_C_PROGRESSIONS).filter(
|
|
15212
15860
|
(p) => p.join("|") !== progA.join("|") && p.join("|") !== progB.join("|")
|
|
15213
15861
|
);
|
|
15214
15862
|
const progC = pick(
|
|
15215
15863
|
floating ? withoutTonic(progCPool, homeRoot) : progCPool,
|
|
15216
15864
|
rnd
|
|
15217
15865
|
);
|
|
15218
|
-
const tonic = progA[0].startsWith("Am") ? "Am" : "C";
|
|
15219
|
-
const progHalf = pick(SECTION_A2_DERIVATIONS, rnd)(progA);
|
|
15220
|
-
const progFull = pick(SECTION_A3_DERIVATIONS, rnd)(progA, tonic);
|
|
15221
|
-
const progDeceptive = pick(SECTION_DECEPTIVE_DERIVATIONS, rnd)(progA, tonic);
|
|
15866
|
+
const tonic = center ? center.tonic : progA[0].startsWith("Am") ? "Am" : "C";
|
|
15867
|
+
const progHalf = center ? pick(MODAL_HALF_DERIVATIONS, rnd)(progA, center) : pick(SECTION_A2_DERIVATIONS, rnd)(progA);
|
|
15868
|
+
const progFull = center ? pick(MODAL_FULL_DERIVATIONS, rnd)(progA, center) : pick(SECTION_A3_DERIVATIONS, rnd)(progA, tonic);
|
|
15869
|
+
const progDeceptive = center ? pick(MODAL_DECEPTIVE_DERIVATIONS, rnd)(progA, center) : pick(SECTION_DECEPTIVE_DERIVATIONS, rnd)(progA, tonic);
|
|
15222
15870
|
let lastChorusBar = -1;
|
|
15223
15871
|
for (const section of sectionPlan)
|
|
15224
15872
|
if (section.kind === "chorus" || section.kind === "outro")
|
|
@@ -15265,7 +15913,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15265
15913
|
progression[bar - 1] = transposeChordName("G7", shift - prev);
|
|
15266
15914
|
}
|
|
15267
15915
|
}
|
|
15268
|
-
if (rnd() < 0.3) {
|
|
15916
|
+
if (rnd() < 0.3 && !center) {
|
|
15269
15917
|
const tonicNames = tonic === "Am" ? ["Am", "Am7"] : ["C", "CM7"];
|
|
15270
15918
|
const spots = [];
|
|
15271
15919
|
for (let bar = 0; bar + 1 < totalBars; bar++) {
|
|
@@ -15286,10 +15934,12 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15286
15934
|
const sourceOf = (kind) => kind === "chorus" || kind === "interlude" || kind === "drop_chorus" ? "b" : kind === "prechorus" ? "a2" : kind === "bridge" ? "c" : "a";
|
|
15287
15935
|
const landingOf = (section) => {
|
|
15288
15936
|
if (section.spec.landing === null) return null;
|
|
15289
|
-
const
|
|
15290
|
-
|
|
15291
|
-
|
|
15292
|
-
|
|
15937
|
+
const relativeHere = relativeKinds.has(section.kind);
|
|
15938
|
+
const tonicDegree = relativeHere ? scale.tonic === 5 ? 0 : 5 : scale.tonic;
|
|
15939
|
+
const size = scaleSize(scale);
|
|
15940
|
+
let landing = (section.spec.landing + tonicDegree) % size;
|
|
15941
|
+
if (floating && landing === tonicDegree)
|
|
15942
|
+
landing = (landing + pick([2, 4], rnd)) % size;
|
|
15293
15943
|
return landing;
|
|
15294
15944
|
};
|
|
15295
15945
|
const units2 = [];
|
|
@@ -15298,9 +15948,12 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15298
15948
|
const src = sourceOf(section.kind);
|
|
15299
15949
|
for (let u = 0; u < unitCount; u++) {
|
|
15300
15950
|
if (!section.spec.melody) {
|
|
15951
|
+
const solo2 = section.kind === "interlude";
|
|
15301
15952
|
units2.push({
|
|
15302
|
-
|
|
15303
|
-
|
|
15953
|
+
// 見せ場なので走句と山を交互に置く。`hold` のままだと
|
|
15954
|
+
// リズム型が最も薄いものになり、ソロにならない。
|
|
15955
|
+
role: solo2 ? u % 2 === 0 ? "run" : "climax" : "hold",
|
|
15956
|
+
source: solo2 ? "solo" : "silent",
|
|
15304
15957
|
landing: null,
|
|
15305
15958
|
section
|
|
15306
15959
|
});
|
|
@@ -15364,7 +16017,10 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15364
16017
|
arcAmp: 2 + rnd() * 3,
|
|
15365
16018
|
// オクターブ跳躍は参考曲では音程の1.0%しかない。上げすぎると音域が広がる。
|
|
15366
16019
|
octaveAffinity: 0.06 + rnd() * 0.12,
|
|
15367
|
-
|
|
16020
|
+
// **音階を厳しく締める曲は必ず中核音の歩数で組む。** ダイアトニックの度数で輪郭を
|
|
16021
|
+
// 作ると、琉球音階なのにレやラが輪郭の中に入り込む。ファ・シを自由に使う
|
|
16022
|
+
// 陽・民謡だけが、曲ごとに掛けたり掛けなかったりする({@link ComposeScale.strict})。
|
|
16023
|
+
pentatonicMotif: rnd() < 0.55 || scale.strict,
|
|
15368
16024
|
runShape: pick(["scale", "turn", "broken", "zigzag"], rnd),
|
|
15369
16025
|
stepShape: pick(
|
|
15370
16026
|
["arch", "valley", "ascend", "descend", "wave", "pivot"],
|
|
@@ -15382,7 +16038,11 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15382
16038
|
// 界隈曲らしさ:調の外の音(クロマチック)や微小な逸脱を積極的に許容する。
|
|
15383
16039
|
// 刻みを細かくすると経過音の置き場所が増えるので、同じ係数でも変化音は増える。
|
|
15384
16040
|
// 参考曲の1.75倍まで伸びていたぶんを引く。
|
|
15385
|
-
|
|
16041
|
+
// **音階を厳しく締める曲は変化音を控える。** 半音の経過音は長調・短調の泣きメロの
|
|
16042
|
+
// 芯だが、琉球・都節・律ではその半音が音階の外にしか無く、入れたぶんだけ
|
|
16043
|
+
// 音階の色が薄まる(実測で嬰ヘが3%出て、音階内のラ2%より多いという逆転が
|
|
16044
|
+
// 起きていた)。0 にはしない——民族音階の実際の曲にも装飾の半音は出る。
|
|
16045
|
+
chromaticAffinity: (rnd() < 0.2 ? 0 : 0.12 + rnd() * 0.33) * (scale.strict ? 0.4 : 1),
|
|
15386
16046
|
barHeadWeight: rnd() < 0.5 ? 3 : 2,
|
|
15387
16047
|
bassStyle: pick(
|
|
15388
16048
|
[
|
|
@@ -15537,7 +16197,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15537
16197
|
if (breathBars.has(source)) breathBars.add(bar);
|
|
15538
16198
|
continue;
|
|
15539
16199
|
}
|
|
15540
|
-
const isB = units2[u].source === "b";
|
|
16200
|
+
const isB = units2[u].source === "b" || units2[u].source === "solo";
|
|
15541
16201
|
const isA2 = units2[u].source === "a2";
|
|
15542
16202
|
const isC = units2[u].source === "c";
|
|
15543
16203
|
const isPrechorusEnd = units2[u].section.kind === "prechorus" && bar === units2[u].section.startBar + units2[u].section.bars - 1;
|
|
@@ -15587,6 +16247,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15587
16247
|
const harmony = [];
|
|
15588
16248
|
const harmony2 = [];
|
|
15589
16249
|
const pad = [];
|
|
16250
|
+
const solo = [];
|
|
15590
16251
|
const melodyDurations = [];
|
|
15591
16252
|
const barTension = new Array(totalBars).fill(0);
|
|
15592
16253
|
let restSteps = 0;
|
|
@@ -15597,9 +16258,9 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15597
16258
|
let chromaticNotes = 0;
|
|
15598
16259
|
let sungBars = 0;
|
|
15599
16260
|
let prevSemi = pick([60, 64, 65, 67, 69, 72, 74, 76], rnd);
|
|
15600
|
-
const pickFigure = (gapSteps,
|
|
16261
|
+
const pickFigure = (gapSteps, scale2) => {
|
|
15601
16262
|
const fits = ANSWER_FIGURES.filter(
|
|
15602
|
-
(f) => f.reduce((sum, v) => sum +
|
|
16263
|
+
(f) => f.reduce((sum, v) => sum + scale2(Math.abs(v)), 0) <= gapSteps
|
|
15603
16264
|
);
|
|
15604
16265
|
return fits.length === 0 ? null : pick(fits, rnd);
|
|
15605
16266
|
};
|
|
@@ -15657,8 +16318,9 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15657
16318
|
slots,
|
|
15658
16319
|
tones,
|
|
15659
16320
|
style,
|
|
16321
|
+
scale,
|
|
15660
16322
|
motifContour,
|
|
15661
|
-
semitoneToDegree(headSemi),
|
|
16323
|
+
semitoneToDegree(scale, headSemi),
|
|
15662
16324
|
contourOffset,
|
|
15663
16325
|
repeatShift,
|
|
15664
16326
|
headWeight,
|
|
@@ -15674,7 +16336,8 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15674
16336
|
...plannedDegrees[source]
|
|
15675
16337
|
);
|
|
15676
16338
|
const landing = units2[unitOf(bar)].landing;
|
|
15677
|
-
if (landing !== null && barInUnit(bar) === 1)
|
|
16339
|
+
if (landing !== null && barInUnit(bar) === 1)
|
|
16340
|
+
landOn(scale, degrees, landing);
|
|
15678
16341
|
plannedDegrees[bar] = [...degrees];
|
|
15679
16342
|
const isMotifBar = source !== null || role === "motif" || role === "sequence" || role === "climax" || role === "answer";
|
|
15680
16343
|
let fitted = degrees;
|
|
@@ -15686,6 +16349,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15686
16349
|
tones,
|
|
15687
16350
|
prevSemi,
|
|
15688
16351
|
quarterSteps,
|
|
16352
|
+
scale,
|
|
15689
16353
|
style.pentatonicMotif,
|
|
15690
16354
|
motifShiftMemo.get(shiftKey) ?? null
|
|
15691
16355
|
);
|
|
@@ -15693,6 +16357,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15693
16357
|
motifShiftMemo.set(shiftKey, r.shift);
|
|
15694
16358
|
}
|
|
15695
16359
|
const pitches = shapeBar(fitted, slots, tones, prevSemi, {
|
|
16360
|
+
scale,
|
|
15696
16361
|
allowLeap: role === "climax",
|
|
15697
16362
|
allowArpeggio: role === "climax" || role === "run" && style.runShape === "broken" || role === "cadence" && style.cadenceShape !== "descend",
|
|
15698
16363
|
quarterSteps,
|
|
@@ -15707,16 +16372,19 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15707
16372
|
rnd,
|
|
15708
16373
|
preserveContour: isMotifBar
|
|
15709
16374
|
});
|
|
15710
|
-
if (landing !== null && barInUnit(bar) === 1)
|
|
15711
|
-
|
|
15712
|
-
|
|
16375
|
+
if (landing !== null && barInUnit(bar) === 1)
|
|
16376
|
+
landPitch(scale, pitches, landing);
|
|
16377
|
+
const fifths = pitches.map((semi) => scaleFifth(scale, semi));
|
|
16378
|
+
applyChromatic(scale, pitches, fifths, slots, tones, {
|
|
15713
16379
|
affinity: style.chromaticAffinity,
|
|
15714
16380
|
quarterSteps,
|
|
15715
16381
|
shortSteps: scaleStep(EIGHTH),
|
|
15716
16382
|
keepLast: landing !== null && barInUnit(bar) === 1,
|
|
15717
16383
|
rnd
|
|
15718
16384
|
});
|
|
15719
|
-
const
|
|
16385
|
+
const unitSource = units2[unitOf(bar)].source;
|
|
16386
|
+
const isSolo = unitSource === "solo";
|
|
16387
|
+
const silent = unitSource === "silent" || isSolo;
|
|
15720
16388
|
const barHead = pitches[0];
|
|
15721
16389
|
let tensionSum = 0;
|
|
15722
16390
|
let tensionSteps = 0;
|
|
@@ -15724,7 +16392,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15724
16392
|
const semi = pitches[i2];
|
|
15725
16393
|
tensionSum += (3 - toneWeight(semi, tones)) / 3 * slots[i2].value;
|
|
15726
16394
|
tensionSteps += slots[i2].value;
|
|
15727
|
-
if (role !== "climax") {
|
|
16395
|
+
if (!silent && role !== "climax") {
|
|
15728
16396
|
const gap = Math.abs(semi - prevSemi);
|
|
15729
16397
|
maxLeap = Math.max(maxLeap, gap);
|
|
15730
16398
|
intervals++;
|
|
@@ -15733,10 +16401,25 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15733
16401
|
}
|
|
15734
16402
|
const slot = slots[i2];
|
|
15735
16403
|
if (silent) {
|
|
16404
|
+
if (isSolo) {
|
|
16405
|
+
const ks = barKeyShift[bar];
|
|
16406
|
+
const fifthShiftSolo = ks === 0 ? 0 : SEMITONE_TO_FIFTH_SHIFT[(ks % 12 + 12) % 12];
|
|
16407
|
+
solo.push({
|
|
16408
|
+
startStep: barStart + slot.at,
|
|
16409
|
+
pitchUnits: spelledToUnits(
|
|
16410
|
+
semi + ks,
|
|
16411
|
+
fifths[i2] + fifthShiftSolo,
|
|
16412
|
+
edo
|
|
16413
|
+
),
|
|
16414
|
+
durationSteps: slot.value,
|
|
16415
|
+
// ソロは前に出る声部なので、歌メロより気持ち強く弾く。
|
|
16416
|
+
velocity: slot.at === 0 ? 116 : slot.value <= scaleStep(SIXTEENTH) ? 96 : 106
|
|
16417
|
+
});
|
|
16418
|
+
}
|
|
15736
16419
|
prevSemi = semi;
|
|
15737
16420
|
continue;
|
|
15738
16421
|
}
|
|
15739
|
-
if (!
|
|
16422
|
+
if (!scalePcs(scale).has(pitchClass(semi))) chromaticNotes++;
|
|
15740
16423
|
const k = barKeyShift[bar];
|
|
15741
16424
|
const fifthShift = k === 0 ? 0 : SEMITONE_TO_FIFTH_SHIFT[(k % 12 + 12) % 12];
|
|
15742
16425
|
melody.push({
|
|
@@ -15790,7 +16473,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15790
16473
|
subSemi = pushSub(
|
|
15791
16474
|
cursor,
|
|
15792
16475
|
step,
|
|
15793
|
-
i2 === 0 ? subSemi : walk(subSemi, subDir)
|
|
16476
|
+
i2 === 0 ? subSemi : walk(scale, subSemi, subDir)
|
|
15794
16477
|
);
|
|
15795
16478
|
placed++;
|
|
15796
16479
|
}
|
|
@@ -15814,7 +16497,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15814
16497
|
subSemi = pushSub(
|
|
15815
16498
|
cursor,
|
|
15816
16499
|
step,
|
|
15817
|
-
index === 0 ? subSemi : walk(subSemi, subDir * (index % 2 === 0 ? 1 : -1))
|
|
16500
|
+
index === 0 ? subSemi : walk(scale, subSemi, subDir * (index % 2 === 0 ? 1 : -1))
|
|
15818
16501
|
);
|
|
15819
16502
|
index++;
|
|
15820
16503
|
}
|
|
@@ -15824,7 +16507,11 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15824
16507
|
pushSub(0, stepsPerBar, subSemi);
|
|
15825
16508
|
} else if (subStyle === "long-short") {
|
|
15826
16509
|
subSemi = pushSub(0, scaleStep(DOT_HALF), subSemi);
|
|
15827
|
-
pushSub(
|
|
16510
|
+
pushSub(
|
|
16511
|
+
scaleStep(DOT_HALF),
|
|
16512
|
+
scaleStep(QUARTER),
|
|
16513
|
+
walk(scale, subSemi, subDir)
|
|
16514
|
+
);
|
|
15828
16515
|
} else if (role === "cadence") {
|
|
15829
16516
|
pushSub(0, stepsPerBar, subSemi);
|
|
15830
16517
|
} else {
|
|
@@ -15839,6 +16526,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15839
16526
|
const written = [];
|
|
15840
16527
|
for (let i2 = 0; i2 < slots.length; i2++) {
|
|
15841
16528
|
const hTone = harmonyPitch(
|
|
16529
|
+
scale,
|
|
15842
16530
|
pitches[i2],
|
|
15843
16531
|
tones,
|
|
15844
16532
|
last,
|
|
@@ -15909,6 +16597,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15909
16597
|
const nextTones = chordTones(progression[(bar + 1) % totalBars]);
|
|
15910
16598
|
const A = clampSemi(
|
|
15911
16599
|
walk(
|
|
16600
|
+
scale,
|
|
15912
16601
|
nextTones[0] ? clampSemi(nextTones[0].semi, BASS_LOW, BASS_HIGH) : R,
|
|
15913
16602
|
-1
|
|
15914
16603
|
),
|
|
@@ -15965,7 +16654,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15965
16654
|
let bassCursor = 0;
|
|
15966
16655
|
for (const [semi, value] of bassCell) {
|
|
15967
16656
|
const len = scaleStep(value);
|
|
15968
|
-
const fifth = semi === R || semi === O ? rootTone.fifth : semi === F ? fifthTone?.fifth ?? rootTone.fifth : semi === T ? thirdTone?.fifth ?? rootTone.fifth :
|
|
16657
|
+
const fifth = semi === R || semi === O ? rootTone.fifth : semi === F ? fifthTone?.fifth ?? rootTone.fifth : semi === T ? thirdTone?.fifth ?? rootTone.fifth : scaleFifth(scale, semi);
|
|
15969
16658
|
const k = barKeyShift[bar];
|
|
15970
16659
|
const fifthShift = k === 0 ? 0 : SEMITONE_TO_FIFTH_SHIFT[(k % 12 + 12) % 12];
|
|
15971
16660
|
barBass.push({
|
|
@@ -16027,7 +16716,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
16027
16716
|
const after = melody[i2 + 2];
|
|
16028
16717
|
if (after && Math.floor(after.startStep / stepsPerBar) === barIdx) {
|
|
16029
16718
|
const afterSemi = Math.round(after.pitchUnits / UNITS_PER_SEMITONE) - (barKeyShift[barIdx] ?? 0);
|
|
16030
|
-
if (!
|
|
16719
|
+
if (!scalePcs(scale).has(pitchClass(afterSemi))) continue;
|
|
16031
16720
|
}
|
|
16032
16721
|
const nextRole = barRoles[barIdx];
|
|
16033
16722
|
let tieProb = 0.3;
|
|
@@ -16048,11 +16737,13 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
16048
16737
|
melodyDurations[i2] += melodyDurations[i2 + 1];
|
|
16049
16738
|
melodyDurations.splice(i2 + 1, 1);
|
|
16050
16739
|
}
|
|
16051
|
-
const
|
|
16052
|
-
|
|
16053
|
-
|
|
16054
|
-
|
|
16055
|
-
|
|
16740
|
+
for (const voice of [harmony, harmony2]) {
|
|
16741
|
+
const nxtIdx = voice.findIndex((h) => h.startStep === nxt.startStep);
|
|
16742
|
+
if (nxtIdx < 0) continue;
|
|
16743
|
+
const curIdx = voice.findIndex((h) => h.startStep === cur.startStep);
|
|
16744
|
+
if (curIdx >= 0)
|
|
16745
|
+
voice[curIdx].durationSteps += voice[nxtIdx].durationSteps;
|
|
16746
|
+
voice.splice(nxtIdx, 1);
|
|
16056
16747
|
}
|
|
16057
16748
|
i2--;
|
|
16058
16749
|
}
|
|
@@ -16106,7 +16797,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
16106
16797
|
};
|
|
16107
16798
|
const shiftUnits = semitonesToUnits(rootShift, edo);
|
|
16108
16799
|
if (shiftUnits !== 0)
|
|
16109
|
-
for (const list of [melody, submelody, bass, harmony, harmony2, pad])
|
|
16800
|
+
for (const list of [melody, submelody, bass, harmony, harmony2, pad, solo])
|
|
16110
16801
|
for (const n of list) n.pitchUnits = n.pitchUnits + shiftUnits;
|
|
16111
16802
|
const octave = useOctaveLayer ? melody.filter(
|
|
16112
16803
|
(n) => n.durationSteps >= quarterSteps || rnd() < octaveCoverage
|
|
@@ -16117,6 +16808,8 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
16117
16808
|
rootShift,
|
|
16118
16809
|
keyName: resolvedKey.keyName,
|
|
16119
16810
|
keyLabel: resolvedKey.keyLabel,
|
|
16811
|
+
scaleId: scale.id,
|
|
16812
|
+
scaleLabel: scale.label,
|
|
16120
16813
|
moodLabel: resolvedKey.moodLabel,
|
|
16121
16814
|
bpm,
|
|
16122
16815
|
sections: sectionPlan,
|
|
@@ -16136,6 +16829,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
16136
16829
|
harmony2,
|
|
16137
16830
|
octave,
|
|
16138
16831
|
pad,
|
|
16832
|
+
solo,
|
|
16139
16833
|
melodyDurations,
|
|
16140
16834
|
restSteps,
|
|
16141
16835
|
totalSteps: Math.max(1, sungBars) * stepsPerBar,
|
|
@@ -16265,12 +16959,17 @@ var composeSong = (options) => {
|
|
|
16265
16959
|
const recent = options.recent ?? [];
|
|
16266
16960
|
const count = Math.max(1, options.drawCount ?? DRAW_COUNT);
|
|
16267
16961
|
const resolvedKey = resolveComposeKey(options.baseKey, rnd);
|
|
16962
|
+
const scale = resolveComposeScale(
|
|
16963
|
+
options.scale,
|
|
16964
|
+
resolvedKey.mode === "minor",
|
|
16965
|
+
rnd
|
|
16966
|
+
);
|
|
16268
16967
|
let best = null;
|
|
16269
16968
|
let bestScore = Number.NEGATIVE_INFINITY;
|
|
16270
16969
|
let bestIsValid = false;
|
|
16271
16970
|
let rejected = 0;
|
|
16272
16971
|
for (let attempt = 1; attempt <= count; attempt++) {
|
|
16273
|
-
const d = draw(options, resolvedKey, rnd);
|
|
16972
|
+
const d = draw(options, resolvedKey, scale, rnd);
|
|
16274
16973
|
const { stats, ok } = evaluate(d, recent);
|
|
16275
16974
|
if (!ok) rejected++;
|
|
16276
16975
|
const better = ok === bestIsValid ? stats.score > bestScore : ok;
|
|
@@ -16278,15 +16977,18 @@ var composeSong = (options) => {
|
|
|
16278
16977
|
bestScore = stats.score;
|
|
16279
16978
|
bestIsValid = ok;
|
|
16280
16979
|
best = {
|
|
16281
|
-
//
|
|
16282
|
-
//
|
|
16980
|
+
// ドラム・楽器・編曲プランは勝った候補にだけ後から付ける(メロディに
|
|
16981
|
+
// 依存しないので候補ごとに引いても採点は動かず、40本ぶん無駄になる)。
|
|
16283
16982
|
drum: "",
|
|
16284
16983
|
instrument: "",
|
|
16984
|
+
arrange: EMPTY_ARRANGE,
|
|
16285
16985
|
chordProgression: d.chordProgression,
|
|
16286
16986
|
chordPattern: d.chordPattern,
|
|
16287
16987
|
rootShift: d.rootShift,
|
|
16288
16988
|
keyName: d.keyName,
|
|
16289
16989
|
keyLabel: d.keyLabel,
|
|
16990
|
+
scaleId: scale.id,
|
|
16991
|
+
scaleLabel: scale.label,
|
|
16290
16992
|
moodLabel: d.moodLabel,
|
|
16291
16993
|
bpm: d.bpm,
|
|
16292
16994
|
sections: d.sections,
|
|
@@ -16300,6 +17002,7 @@ var composeSong = (options) => {
|
|
|
16300
17002
|
harmony2: d.harmony2,
|
|
16301
17003
|
octave: d.octave,
|
|
16302
17004
|
pad: d.pad,
|
|
17005
|
+
solo: d.solo,
|
|
16303
17006
|
stats: { ...stats, attempts: attempt, rejected }
|
|
16304
17007
|
};
|
|
16305
17008
|
}
|
|
@@ -16308,6 +17011,7 @@ var composeSong = (options) => {
|
|
|
16308
17011
|
result.stats.rejected = rejected;
|
|
16309
17012
|
result.drum = pickBuiltinDrum(result, rnd);
|
|
16310
17013
|
result.instrument = pickBuiltinInstrument(result, rnd);
|
|
17014
|
+
result.arrange = buildArrangePlan(result, rnd);
|
|
16311
17015
|
return result;
|
|
16312
17016
|
};
|
|
16313
17017
|
var pickBuiltinDrum = (song, rnd) => {
|
|
@@ -16319,6 +17023,80 @@ var pickBuiltinDrum = (song, rnd) => {
|
|
|
16319
17023
|
const pool = dotted >= 0.08 ? ["shuffle", "8beat", "16beat"] : song.bpm >= 150 ? ["4beat", "dance", "16beat", "disco"] : short >= 0.85 ? ["16beat", "dance", "disco"] : song.bpm <= 115 ? ["bossa", "8beat", "shuffle", "4beat"] : ["8beat", "4beat", "16beat", "dance"];
|
|
16320
17024
|
return pick(pool, rnd);
|
|
16321
17025
|
};
|
|
17026
|
+
var EMPTY_ARRANGE = {
|
|
17027
|
+
backing: [],
|
|
17028
|
+
sparkle: null,
|
|
17029
|
+
padSections: [],
|
|
17030
|
+
lead: null,
|
|
17031
|
+
bassLayer: null
|
|
17032
|
+
};
|
|
17033
|
+
var LOUD_KINDS = ["prechorus", "chorus", "bridge"];
|
|
17034
|
+
var QUIET_KINDS = [
|
|
17035
|
+
"intro",
|
|
17036
|
+
"verse",
|
|
17037
|
+
"interlude",
|
|
17038
|
+
"drop_chorus",
|
|
17039
|
+
"outro"
|
|
17040
|
+
];
|
|
17041
|
+
var CHORUS_KINDS = ["chorus", "drop_chorus"];
|
|
17042
|
+
var buildArrangePlan = (song, rnd) => {
|
|
17043
|
+
const present = new Set(song.sections.map((s) => s.kind));
|
|
17044
|
+
const narrow = (kinds) => {
|
|
17045
|
+
const hit = kinds.filter((k) => present.has(k));
|
|
17046
|
+
return hit.length === 0 ? null : hit;
|
|
17047
|
+
};
|
|
17048
|
+
const base = {
|
|
17049
|
+
pattern: song.chordPattern,
|
|
17050
|
+
sections: null,
|
|
17051
|
+
octave: 0
|
|
17052
|
+
};
|
|
17053
|
+
const others = chordPatternPool(song.bpm).filter((p) => p !== base.pattern);
|
|
17054
|
+
const backing = [base];
|
|
17055
|
+
const addKinds = pick(
|
|
17056
|
+
[LOUD_KINDS, CHORUS_KINDS, LOUD_KINDS, QUIET_KINDS],
|
|
17057
|
+
rnd
|
|
17058
|
+
);
|
|
17059
|
+
const second = pick(others, rnd);
|
|
17060
|
+
backing.push({
|
|
17061
|
+
pattern: second,
|
|
17062
|
+
sections: narrow(addKinds),
|
|
17063
|
+
octave: 0
|
|
17064
|
+
});
|
|
17065
|
+
if (rnd() < 0.55) {
|
|
17066
|
+
const rest = others.filter((p) => p !== second);
|
|
17067
|
+
backing.push({
|
|
17068
|
+
pattern: pick(rest.length > 0 ? rest : others, rnd),
|
|
17069
|
+
// 2本目と逆側へ置く(両方サビに寄せると、サビだけ団子になる)。
|
|
17070
|
+
sections: narrow(addKinds === QUIET_KINDS ? LOUD_KINDS : QUIET_KINDS),
|
|
17071
|
+
octave: 0
|
|
17072
|
+
});
|
|
17073
|
+
}
|
|
17074
|
+
const sparklePool = chordPatternPool(song.bpm).filter(
|
|
17075
|
+
(p) => p !== "block" && !backing.some((b) => b.pattern === p)
|
|
17076
|
+
);
|
|
17077
|
+
const sparkle = sparklePool.length > 0 && rnd() < 0.7 ? {
|
|
17078
|
+
pattern: pick(sparklePool, rnd),
|
|
17079
|
+
sections: narrow(pick([LOUD_KINDS, CHORUS_KINDS], rnd)) ?? CHORUS_KINDS,
|
|
17080
|
+
octave: 1
|
|
17081
|
+
} : null;
|
|
17082
|
+
const padSections = narrow(
|
|
17083
|
+
pick(
|
|
17084
|
+
[
|
|
17085
|
+
["prechorus", "chorus", "bridge", "drop_chorus"],
|
|
17086
|
+
["chorus", "drop_chorus"],
|
|
17087
|
+
["prechorus", "chorus", "bridge", "drop_chorus"],
|
|
17088
|
+
["bridge", "chorus"]
|
|
17089
|
+
],
|
|
17090
|
+
rnd
|
|
17091
|
+
)
|
|
17092
|
+
) ?? [];
|
|
17093
|
+
const lead = rnd() < 0.75 ? {
|
|
17094
|
+
sections: narrow(pick([CHORUS_KINDS, LOUD_KINDS], rnd)) ?? CHORUS_KINDS,
|
|
17095
|
+
octave: rnd() < 0.5 ? 0 : 1
|
|
17096
|
+
} : null;
|
|
17097
|
+
const bassLayer = rnd() < 0.25 ? { sections: narrow(CHORUS_KINDS) ?? CHORUS_KINDS, octave: 1 } : null;
|
|
17098
|
+
return { backing, sparkle, padSections, lead, bassLayer };
|
|
17099
|
+
};
|
|
16322
17100
|
var pickBuiltinInstrument = (song, rnd) => {
|
|
16323
17101
|
const eighth = BASE_STEPS_PER_BAR / 8;
|
|
16324
17102
|
const short = song.melody.filter((n) => n.durationSteps <= eighth).length / Math.max(1, song.melody.length);
|
|
@@ -16849,6 +17627,34 @@ var buildUI = (target, options) => {
|
|
|
16849
17627
|
<span class="dtm-grow"></span>
|
|
16850
17628
|
<span class="dtm-hint" data-dtm="compose-key-hint"></span>
|
|
16851
17629
|
</div>
|
|
17630
|
+
<div class="dtm-row" data-dtm="compose-scale-row">
|
|
17631
|
+
<span class="dtm-label">\u97F3\u968E</span>
|
|
17632
|
+
<select class="dtm-select" data-dtm="compose-scale" title="\u65CB\u5F8B\u304C\u4F7F\u3046\u97F3\u968E\u3092\u9078\u3073\u307E\u3059\u3002\u30D9\u30FC\u30B9\u8ABF\uFF08\u4E3B\u97F3\u306E\u9AD8\u3055\uFF09\u3068\u306F\u72EC\u7ACB\u3057\u305F\u8A2D\u5B9A\u3067\u3059">
|
|
17633
|
+
<option value="auto" title="\u30D9\u30FC\u30B9\u8ABF\u306E\u9577\u77ED\u306B\u5408\u308F\u305B\u3066\u3001\u967D\u97F3\u968E\uFF08\u9577\u8ABF\uFF09\u304B\u6C11\u8B21\u97F3\u968E\uFF08\u77ED\u8ABF\uFF09\u3092\u4F7F\u3044\u307E\u3059">\u304A\u307E\u304B\u305B\uFF08\u5F93\u6765\u3069\u304A\u308A\uFF09</option>
|
|
17634
|
+
<option value="any" title="9\u3064\u306E\u97F3\u968E\u304B\u3089\u30E9\u30F3\u30C0\u30E0\u306B\u62BD\u9078\u3057\u307E\u3059">\u5E0C\u671B\u306A\u3057\uFF08\u5168\u97F3\u968E\u304B\u3089\u62BD\u9078\uFF09</option>
|
|
17635
|
+
<optgroup label="\u30DA\u30F3\u30BF\u30C8\u30CB\u30C3\u30AF\uFF085\u97F3\u97F3\u968E\uFF09">
|
|
17636
|
+
<option value="yo" title="J-POP\u306E\u6A19\u6E96\u3002\u660E\u308B\u304F\u7D20\u76F4\u3067\u6B4C\u3044\u3084\u3059\u3044\u3002\u5F93\u6765\u306E\u9577\u8ABF\u3068\u540C\u3058">\u967D\u97F3\u968E\uFF08\u9577\u8ABF\u30DA\u30F3\u30BF\uFF09</option>
|
|
17637
|
+
<option value="minyo" title="\u308F\u3089\u3079\u6B4C\u30FB\u6C11\u8B21\u306E\u97F3\u968E\u3002\u7FF3\u308A\u304C\u3042\u308B\u304C\u6697\u3059\u304E\u306A\u3044\u3002\u5F93\u6765\u306E\u77ED\u8ABF\u3068\u540C\u3058">\u6C11\u8B21\u97F3\u968E\uFF08\u77ED\u8ABF\u30DA\u30F3\u30BF\uFF09</option>
|
|
17638
|
+
<option value="ryukyu" title="\u6C96\u7E04\u97F3\u968E\u3002\u30EC\u3068\u30E9\u3092\u629C\u304D\u3001\u30D5\u30A1\u3068\u30B7\u3092\u67F1\u306B\u3059\u308B\u3002\u660E\u308B\u304F\u8DF3\u306D\u308B">\u7409\u7403\u97F3\u968E\uFF08\u6C96\u7E04\uFF09</option>
|
|
17639
|
+
<option value="miyakobushi" title="\u300E\u3055\u304F\u3089\u3055\u304F\u3089\u300F\u306E\u97F3\u968E\u3002\u4E3B\u97F3\u306E\u3059\u3050\u4E0A\u304C\u534A\u97F3\u3067\u3001\u7FF3\u308A\u304C\u6FC3\u3044">\u90FD\u7BC0\u97F3\u968E\uFF08\u9670\u97F3\u968E\uFF09</option>
|
|
17640
|
+
<option value="ritsu" title="\u96C5\u697D\u30FB\u58F0\u660E\u306E\u97F3\u968E\u3002\u534A\u97F3\u3092\u542B\u307E\u305A\u3001\u5E73\u3089\u3067\u8358\u91CD\u306B\u6D41\u308C\u308B">\u5F8B\u97F3\u968E\uFF08\u96C5\u697D\uFF09</option>
|
|
17641
|
+
</optgroup>
|
|
17642
|
+
<optgroup label="\u30C1\u30E3\u30FC\u30C1\u30E2\u30FC\u30C9\uFF087\u97F3\u97F3\u968E\uFF09">
|
|
17643
|
+
<option value="dorian" title="\u77ED\u8ABF\u3060\u304C6\u5EA6\u304C\u660E\u308B\u3044\u3002\u30B1\u30EB\u30C8\u30FB\u30ED\u30C3\u30AF\u30FB\u30B7\u30C6\u30A3\u30DD\u30C3\u30D7">\u30C9\u30EA\u30A2\u30F3</option>
|
|
17644
|
+
<option value="phrygian" title="\u4E3B\u97F3\u306E\u4E0A\u304C\u534A\u97F3\u3002\u30B9\u30D1\u30CB\u30C3\u30B7\u30E5\uFF0F\u30E1\u30BF\u30EB\u306E\u7DCA\u8FEB\u3057\u305F\u97FF\u304D">\u30D5\u30EA\u30B8\u30A2\u30F3</option>
|
|
17645
|
+
<option value="lydian" title="4\u5EA6\u304C\u9AD8\u304F\u3001\u6D6E\u904A\u3057\u3066\u5E83\u304C\u308B\u3002\u6620\u753B\u97F3\u697D\u30FB\u30B2\u30FC\u30E0\u306E\u7A7A\u306E\u8272">\u30EA\u30C7\u30A3\u30A2\u30F3</option>
|
|
17646
|
+
<option value="mixolydian" title="\u9577\u8ABF\u3060\u304C7\u5EA6\u304C\u4F4E\u3044\u3002\u30D6\u30EB\u30FC\u30B9\u30ED\u30C3\u30AF\u30FB\u6C11\u65CF\u97F3\u697D\u306E\u571F\u304F\u3055\u3055">\u30DF\u30AF\u30BD\u30EA\u30C7\u30A3\u30A2\u30F3</option>
|
|
17647
|
+
</optgroup>
|
|
17648
|
+
<optgroup label="\u7279\u6B8A\u97F3\u968E\uFF08\u97F3\u7A0B\u96C6\u5408\u3054\u3068\u5165\u308C\u66FF\u308F\u308B\uFF09">
|
|
17649
|
+
<option value="harmonic_minor" title="\u5C0E\u97F3\u30BD\u266F\u3092\u6301\u3064\u77ED\u8ABF\u3002\u58972\u5EA6\u304C\u6CE3\u304D\u3092\u4F5C\u308B\u3002\u30AF\u30E9\u30B7\u30C3\u30AF\u30FBV\u7CFB\u30FB\u5287\u4F34">\u548C\u58F0\u7684\u77ED\u97F3\u968E</option>
|
|
17650
|
+
<option value="hijaz" title="\u4E3B\u97F3\u306E\u4E0A\u304C\u534A\u97F3\u3001\u4E3B\u548C\u97F3\u306F\u9577\u4E09\u548C\u97F3\u3002\u4E2D\u6771\u30FB\u30B9\u30D1\u30CB\u30C3\u30B7\u30E5\u30FB\u30E1\u30BF\u30EB">\u30D2\u30B8\u30E3\u30FC\u30BA\uFF08\u30D5\u30EA\u30B8\u30A2\u30F3\u30FB\u30C9\u30DF\u30CA\u30F3\u30C8\uFF09</option>
|
|
17651
|
+
<option value="hungarian" title="\u58972\u5EA6\u304C2\u304B\u6240\u3002\u97F3\u968E\u306E\u4E2D\u3067\u3044\u3061\u3070\u3093\u8DF3\u306D\u305F\u3001\u7570\u56FD\u3081\u3044\u305F\u97FF\u304D">\u30CF\u30F3\u30AC\u30EA\u30A2\u30F3\u30FB\u30DE\u30A4\u30CA\u30FC\uFF08\u30B8\u30D7\u30B7\u30FC\uFF09</option>
|
|
17652
|
+
<option value="blues" title="\u30D6\u30EB\u30FC\u30CE\u30FC\u30C8\u5165\u308A\u306E6\u97F3\u97F3\u968E\u3002\u77ED3\u5EA6\u3067\u6B4C\u3044\u3001\u4F34\u594F\u306F\u95773\u5EA6\u3067\u9CF4\u308B">\u30D6\u30EB\u30FC\u30B9\u97F3\u968E</option>
|
|
17653
|
+
</optgroup>
|
|
17654
|
+
</select>
|
|
17655
|
+
<span class="dtm-grow"></span>
|
|
17656
|
+
<span class="dtm-hint" data-dtm="compose-scale-hint"></span>
|
|
17657
|
+
</div>
|
|
16852
17658
|
</div>
|
|
16853
17659
|
<div class="dtm-row">
|
|
16854
17660
|
<span class="dtm-label">\u5168\u4F53\u30B7\u30D5\u30C8</span>
|
|
@@ -17051,6 +17857,8 @@ var buildUI = (target, options) => {
|
|
|
17051
17857
|
composeSectionsLen: sel("compose-sections-len"),
|
|
17052
17858
|
composeKey: sel("compose-key"),
|
|
17053
17859
|
composeKeyHint: sel("compose-key-hint"),
|
|
17860
|
+
composeScale: sel("compose-scale"),
|
|
17861
|
+
composeScaleHint: sel("compose-scale-hint"),
|
|
17054
17862
|
macroComposeVocal: sel("macro-compose-vocal"),
|
|
17055
17863
|
macroComposeInfo: sel("macro-compose-info"),
|
|
17056
17864
|
macroClear: sel("macro-clear"),
|
|
@@ -17094,7 +17902,12 @@ var INSTRUMENT_PRESETS = {
|
|
|
17094
17902
|
melody: "Acoustic Grand Piano",
|
|
17095
17903
|
submelody: "Vibraphone",
|
|
17096
17904
|
bass: "Electric Bass (finger)",
|
|
17097
|
-
chord: "Pad 2 (warm)"
|
|
17905
|
+
chord: "Pad 2 (warm)",
|
|
17906
|
+
solo: "Electric Guitar (clean)",
|
|
17907
|
+
// グロッケンは実物の音域が G5(79)〜 の高音楽器で、旋律の音域へそのまま置くと
|
|
17908
|
+
// 金切り音になる。**外すのではなくオクターブで下げて使う**
|
|
17909
|
+
// ({@link GM_BRIGHT_CEILING} / {@link fitInstrumentOctave})。
|
|
17910
|
+
chorusLead: "Glockenspiel"
|
|
17098
17911
|
},
|
|
17099
17912
|
acoustic: {
|
|
17100
17913
|
displayName: "\u30A2\u30B3\u30FC\u30B9\u30C6\u30A3\u30C3\u30AF",
|
|
@@ -17102,7 +17915,9 @@ var INSTRUMENT_PRESETS = {
|
|
|
17102
17915
|
melody: "Acoustic Guitar (steel)",
|
|
17103
17916
|
submelody: "Harmonica",
|
|
17104
17917
|
bass: "Acoustic Bass",
|
|
17105
|
-
chord: "Acoustic Guitar (nylon)"
|
|
17918
|
+
chord: "Acoustic Guitar (nylon)",
|
|
17919
|
+
solo: "Overdriven Guitar",
|
|
17920
|
+
chorusLead: "String Ensemble 1"
|
|
17106
17921
|
},
|
|
17107
17922
|
jazz_night: {
|
|
17108
17923
|
displayName: "\u30B8\u30E3\u30BA\u30FB\u30CA\u30A4\u30C8",
|
|
@@ -17110,7 +17925,9 @@ var INSTRUMENT_PRESETS = {
|
|
|
17110
17925
|
melody: "Electric Piano 1",
|
|
17111
17926
|
submelody: "Flute",
|
|
17112
17927
|
bass: "Acoustic Bass",
|
|
17113
|
-
chord: "Electric Guitar (jazz)"
|
|
17928
|
+
chord: "Electric Guitar (jazz)",
|
|
17929
|
+
solo: "Tenor Sax",
|
|
17930
|
+
chorusLead: "Muted Trumpet"
|
|
17114
17931
|
},
|
|
17115
17932
|
// --- MODERN & VIBE: エッジの効いた現代的な響き ---
|
|
17116
17933
|
synth_pop: {
|
|
@@ -17119,7 +17936,9 @@ var INSTRUMENT_PRESETS = {
|
|
|
17119
17936
|
melody: "Lead 2 (sawtooth)",
|
|
17120
17937
|
submelody: "Lead 4 (chiff)",
|
|
17121
17938
|
bass: "Synth Bass 2",
|
|
17122
|
-
chord: "Pad 3 (polysynth)"
|
|
17939
|
+
chord: "Pad 3 (polysynth)",
|
|
17940
|
+
solo: "Distortion Guitar",
|
|
17941
|
+
chorusLead: "Synth Brass 1"
|
|
17123
17942
|
},
|
|
17124
17943
|
cyber_punk: {
|
|
17125
17944
|
displayName: "\u30B5\u30A4\u30D0\u30FC\u30D1\u30F3\u30AF",
|
|
@@ -17127,7 +17946,9 @@ var INSTRUMENT_PRESETS = {
|
|
|
17127
17946
|
melody: "Lead 8 (bass + lead)",
|
|
17128
17947
|
submelody: "Lead 5 (charang)",
|
|
17129
17948
|
bass: "Synth Bass 2",
|
|
17130
|
-
chord: "Pad 8 (sweep)"
|
|
17949
|
+
chord: "Pad 8 (sweep)",
|
|
17950
|
+
solo: "Distortion Guitar",
|
|
17951
|
+
chorusLead: "Lead 7 (fifths)"
|
|
17131
17952
|
},
|
|
17132
17953
|
rock: {
|
|
17133
17954
|
displayName: "\u30CF\u30FC\u30C9\u30ED\u30C3\u30AF",
|
|
@@ -17135,7 +17956,9 @@ var INSTRUMENT_PRESETS = {
|
|
|
17135
17956
|
melody: "Distortion Guitar",
|
|
17136
17957
|
submelody: "Rock Organ",
|
|
17137
17958
|
bass: "Electric Bass (pick)",
|
|
17138
|
-
chord: "Overdriven Guitar"
|
|
17959
|
+
chord: "Overdriven Guitar",
|
|
17960
|
+
solo: "Distortion Guitar",
|
|
17961
|
+
chorusLead: "Brass Section"
|
|
17139
17962
|
},
|
|
17140
17963
|
// --- WORLD & CLASSIC: 特定のジャンル・地域 ---
|
|
17141
17964
|
orchestra: {
|
|
@@ -17144,7 +17967,9 @@ var INSTRUMENT_PRESETS = {
|
|
|
17144
17967
|
melody: "French Horn",
|
|
17145
17968
|
submelody: "Pizzicato Strings",
|
|
17146
17969
|
bass: "Cello",
|
|
17147
|
-
chord: "Tremolo Strings"
|
|
17970
|
+
chord: "Tremolo Strings",
|
|
17971
|
+
solo: "Violin",
|
|
17972
|
+
chorusLead: "Trumpet"
|
|
17148
17973
|
},
|
|
17149
17974
|
japanese_wa: {
|
|
17150
17975
|
displayName: "\u548C\u98A8\u30FB\u96C5",
|
|
@@ -17152,7 +17977,9 @@ var INSTRUMENT_PRESETS = {
|
|
|
17152
17977
|
melody: "Koto",
|
|
17153
17978
|
submelody: "Shamisen",
|
|
17154
17979
|
bass: "Taiko Drum",
|
|
17155
|
-
chord: "Shakuhachi"
|
|
17980
|
+
chord: "Shakuhachi",
|
|
17981
|
+
solo: "Shakuhachi",
|
|
17982
|
+
chorusLead: "Glockenspiel"
|
|
17156
17983
|
},
|
|
17157
17984
|
arabic_exotic: {
|
|
17158
17985
|
displayName: "\u30A8\u30AD\u30BE\u30C1\u30C3\u30AF",
|
|
@@ -17160,7 +17987,9 @@ var INSTRUMENT_PRESETS = {
|
|
|
17160
17987
|
melody: "Sitar",
|
|
17161
17988
|
submelody: "Bagpipe",
|
|
17162
17989
|
bass: "Fretless Bass",
|
|
17163
|
-
chord: "Kalimba"
|
|
17990
|
+
chord: "Kalimba",
|
|
17991
|
+
solo: "Shanai",
|
|
17992
|
+
chorusLead: "Steel Drums"
|
|
17164
17993
|
},
|
|
17165
17994
|
// --- FANTASY & ATMOSPHERE: 雰囲気と余韻 ---
|
|
17166
17995
|
fantasy_rpg: {
|
|
@@ -17169,7 +17998,9 @@ var INSTRUMENT_PRESETS = {
|
|
|
17169
17998
|
melody: "Ocarina",
|
|
17170
17999
|
submelody: "Celesta",
|
|
17171
18000
|
bass: "Timpani",
|
|
17172
|
-
chord: "Orchestral Harp"
|
|
18001
|
+
chord: "Orchestral Harp",
|
|
18002
|
+
solo: "Pan Flute",
|
|
18003
|
+
chorusLead: "Choir Aahs"
|
|
17173
18004
|
},
|
|
17174
18005
|
ambient_cloud: {
|
|
17175
18006
|
displayName: "\u30A2\u30F3\u30D3\u30A8\u30F3\u30C8",
|
|
@@ -17177,7 +18008,9 @@ var INSTRUMENT_PRESETS = {
|
|
|
17177
18008
|
melody: "Lead 6 (voice)",
|
|
17178
18009
|
submelody: "Music Box",
|
|
17179
18010
|
bass: "Synth Bass 1",
|
|
17180
|
-
chord: "Pad 7 (halo)"
|
|
18011
|
+
chord: "Pad 7 (halo)",
|
|
18012
|
+
solo: "Lead 3 (calliope)",
|
|
18013
|
+
chorusLead: "Synth Choir"
|
|
17181
18014
|
},
|
|
17182
18015
|
retro_game: {
|
|
17183
18016
|
displayName: "8-bit \u30EC\u30C8\u30ED",
|
|
@@ -17185,8 +18018,99 @@ var INSTRUMENT_PRESETS = {
|
|
|
17185
18018
|
melody: "Lead 1 (square)",
|
|
17186
18019
|
submelody: "Lead 2 (sawtooth)",
|
|
17187
18020
|
bass: "Synth Bass 1",
|
|
17188
|
-
chord: "Clavinet"
|
|
17189
|
-
|
|
18021
|
+
chord: "Clavinet",
|
|
18022
|
+
solo: "Lead 8 (bass + lead)",
|
|
18023
|
+
chorusLead: "Lead 4 (chiff)"
|
|
18024
|
+
}
|
|
18025
|
+
};
|
|
18026
|
+
var GM_INSTRUMENT_RANGE = {
|
|
18027
|
+
// 鍵盤・音板
|
|
18028
|
+
"Acoustic Grand Piano": [21, 108],
|
|
18029
|
+
"Electric Piano 1": [28, 103],
|
|
18030
|
+
Clavinet: [36, 96],
|
|
18031
|
+
Celesta: [60, 108],
|
|
18032
|
+
Glockenspiel: [79, 108],
|
|
18033
|
+
"Music Box": [72, 108],
|
|
18034
|
+
Vibraphone: [53, 89],
|
|
18035
|
+
Kalimba: [60, 84],
|
|
18036
|
+
"Orchestral Harp": [23, 104],
|
|
18037
|
+
// 弦・撥弦
|
|
18038
|
+
"Acoustic Guitar (steel)": [40, 83],
|
|
18039
|
+
"Acoustic Guitar (nylon)": [40, 83],
|
|
18040
|
+
"Electric Guitar (clean)": [40, 86],
|
|
18041
|
+
"Electric Guitar (jazz)": [40, 86],
|
|
18042
|
+
"Overdriven Guitar": [40, 88],
|
|
18043
|
+
"Distortion Guitar": [40, 88],
|
|
18044
|
+
Violin: [55, 103],
|
|
18045
|
+
Cello: [36, 76],
|
|
18046
|
+
"String Ensemble 1": [28, 100],
|
|
18047
|
+
"Tremolo Strings": [28, 100],
|
|
18048
|
+
"Pizzicato Strings": [28, 96],
|
|
18049
|
+
Sitar: [48, 79],
|
|
18050
|
+
Shamisen: [48, 84],
|
|
18051
|
+
Koto: [41, 77],
|
|
18052
|
+
// ベース
|
|
18053
|
+
"Acoustic Bass": [28, 60],
|
|
18054
|
+
"Electric Bass (finger)": [28, 67],
|
|
18055
|
+
"Electric Bass (pick)": [28, 67],
|
|
18056
|
+
"Fretless Bass": [28, 67],
|
|
18057
|
+
"Synth Bass 1": [24, 72],
|
|
18058
|
+
"Synth Bass 2": [24, 72],
|
|
18059
|
+
// 管
|
|
18060
|
+
Flute: [60, 96],
|
|
18061
|
+
"Pan Flute": [60, 91],
|
|
18062
|
+
Shakuhachi: [62, 86],
|
|
18063
|
+
Ocarina: [60, 84],
|
|
18064
|
+
Harmonica: [60, 96],
|
|
18065
|
+
Bagpipe: [62, 86],
|
|
18066
|
+
Shanai: [60, 86],
|
|
18067
|
+
"Tenor Sax": [44, 75],
|
|
18068
|
+
Trumpet: [55, 82],
|
|
18069
|
+
"Muted Trumpet": [55, 82],
|
|
18070
|
+
"French Horn": [41, 77],
|
|
18071
|
+
"Brass Section": [41, 84],
|
|
18072
|
+
// 声・打・オルガン
|
|
18073
|
+
"Choir Aahs": [43, 84],
|
|
18074
|
+
"Synth Choir": [43, 84],
|
|
18075
|
+
"Steel Drums": [55, 86],
|
|
18076
|
+
"Taiko Drum": [30, 60],
|
|
18077
|
+
Timpani: [36, 57],
|
|
18078
|
+
"Rock Organ": [36, 96],
|
|
18079
|
+
// シンセ(実物が無いので一般的な使用域)
|
|
18080
|
+
"Synth Brass 1": [36, 96],
|
|
18081
|
+
"Lead 1 (square)": [36, 96],
|
|
18082
|
+
"Lead 2 (sawtooth)": [36, 96],
|
|
18083
|
+
"Lead 3 (calliope)": [48, 96],
|
|
18084
|
+
"Lead 4 (chiff)": [48, 96],
|
|
18085
|
+
"Lead 5 (charang)": [40, 96],
|
|
18086
|
+
"Lead 6 (voice)": [43, 91],
|
|
18087
|
+
"Lead 7 (fifths)": [36, 84],
|
|
18088
|
+
"Lead 8 (bass + lead)": [28, 91],
|
|
18089
|
+
"Pad 2 (warm)": [24, 96],
|
|
18090
|
+
"Pad 3 (polysynth)": [24, 96],
|
|
18091
|
+
"Pad 7 (halo)": [24, 96],
|
|
18092
|
+
"Pad 8 (sweep)": [24, 96]
|
|
18093
|
+
};
|
|
18094
|
+
var GM_BRIGHT_CEILING = {
|
|
18095
|
+
Glockenspiel: 72,
|
|
18096
|
+
"Tinkle Bell": 72,
|
|
18097
|
+
"Music Box": 79,
|
|
18098
|
+
Celesta: 84,
|
|
18099
|
+
Kalimba: 79,
|
|
18100
|
+
"Steel Drums": 84,
|
|
18101
|
+
"FX 3 (crystal)": 79
|
|
18102
|
+
};
|
|
18103
|
+
var OCTAVE_FIT_TOLERANCE = 3;
|
|
18104
|
+
var fitInstrumentOctave = (semitoneRange, instrument, wanted) => {
|
|
18105
|
+
const range = GM_INSTRUMENT_RANGE[instrument];
|
|
18106
|
+
if (!range || !semitoneRange) return wanted;
|
|
18107
|
+
const hi = Math.min(range[1], GM_BRIGHT_CEILING[instrument] ?? range[1]);
|
|
18108
|
+
let octave = wanted;
|
|
18109
|
+
while (octave > wanted - 2) {
|
|
18110
|
+
if (semitoneRange[1] + octave * 12 <= hi + OCTAVE_FIT_TOLERANCE) break;
|
|
18111
|
+
octave--;
|
|
18112
|
+
}
|
|
18113
|
+
return octave;
|
|
17190
18114
|
};
|
|
17191
18115
|
|
|
17192
18116
|
// src/macro-state.ts
|
|
@@ -17194,6 +18118,7 @@ var MACRO_STORAGE_KEYS = {
|
|
|
17194
18118
|
template: "dtm-macro:template",
|
|
17195
18119
|
sections: "dtm-macro:sections",
|
|
17196
18120
|
key: "dtm-macro:key",
|
|
18121
|
+
scale: "dtm-macro:scale",
|
|
17197
18122
|
shift: "dtm-macro:shift",
|
|
17198
18123
|
transpose: "dtm-macro:transpose"
|
|
17199
18124
|
};
|
|
@@ -19353,6 +20278,7 @@ var COMPOSE_INFO_HTML = `
|
|
|
19353
20278
|
<li><strong>\u30E1\u30ED\u30C7\u30A3\u306E\u66F8\u6CD5</strong>\u2014\u2014\u8D70\u53E5\u306E\u5F62\uFF08\u97F3\u968E\uFF0F\u6298\u308A\u8FD4\u3057\uFF0F\u5206\u6563\u548C\u97F3\uFF0F\u30B8\u30B0\u30B6\u30B0\uFF09\u3001\u3064\u306A\u304E\u306E\u5F62\uFF08\u5C71\u306A\u308A\uFF0F\u8C37\uFF0F\u4E0A\u884C\uFF0F\u4E0B\u884C\uFF0F\u3046\u306D\u308A\uFF0F\u8EF8\u97F3\u307E\u308F\u308A\uFF09\u3001\u7D42\u6B62\u306E\u5F62\uFF08\u9806\u6B21\u4E0B\u964D\uFF0F\u30BD\u30DF\u30C9\uFF0F\u8DF3\u306D\u4E0A\u304C\u308A\uFF0F\u30ED\u30F3\u30B0\u30C8\u30FC\u30F3\uFF09\u3001\u30E2\u30C1\u30FC\u30D5\u306E\u539F\u578B\u3001\u8DF3\u8E8D\u306E\u6DF7\u305C\u5177\u5408\u3001\u958B\u59CB\u97F3\u3001\u57FA\u6E96\u306E\u523B\u307F\uFF088\u5206\uFF0F16\u5206\uFF0F\u4E09\u9023\uFF09\u3001\u30B9\u30A6\u30A3\u30F3\u30B0\u91CF</li>
|
|
19354
20279
|
<li><strong>\u30D9\u30FC\u30B9\u306E\u594F\u6CD5</strong>\uFF084\u5206\u6253\u3061\uFF0F\u30AA\u30EB\u30BF\u30CD\u30A4\u30C8\uFF0F2\u5206\uFF0F8\u5206\u30C9\u30E9\u30A4\u30D6\uFF0F\u30B7\u30F3\u30B3\u30DA\uFF0F\u30A6\u30A9\u30FC\u30AD\u30F3\u30B0\uFF0F\u30AA\u30AF\u30BF\u30FC\u30D6\uFF09</li>
|
|
19355
20280
|
<li><strong>\u30B5\u30D6\u30E1\u30ED\u306E\u66F8\u304D\u65B9</strong>\u2014\u2014\u5408\u3044\u306E\u624B\uFF08\u30E1\u30ED\u30C7\u30A3\u304C\u4F11\u3093\u3060\u9699\u9593\u306B\u3060\u3051\u5165\u308B\uFF09\u3001\u30CF\u30E2\u30EA\uFF08\u30E1\u30ED\u30C7\u30A3\u306E\u30EA\u30BA\u30E0\u3092\u306A\u305E\u3063\u30663\u5EA6\u30FB6\u5EA6\u4E0B\u3092\u6B4C\u3046\uFF09\u3001\u5BFE\u65CB\u5F8B\uFF088\u5206\u3067\u30E1\u30ED\u30C7\u30A3\u3068\u53CD\u884C\u3059\u308B\uFF09\u3001\u4FDD\u7D9A\u97F3\uFF08\u540C\u3058\u97F3\u3092\u4F38\u3070\u3057\u7D9A\u3051\u308B\uFF09\u3001\u30D1\u30C3\u30C9\u3002\u5C0F\u7BC0\u3054\u3068\u306B\u3001\u30E1\u30ED\u30C7\u30A3\u304C\u606F\u7D99\u304E\u3057\u3066\u3044\u308B\u5834\u6240\u3067\u306F\u81EA\u52D5\u3067\u5408\u3044\u306E\u624B\u306B\u5207\u308A\u66FF\u308F\u308A\u307E\u3059\u3002</li>
|
|
20281
|
+
<li><strong>\u7DE8\u66F2\u30D7\u30E9\u30F3</strong>\uFF08\u4E0A\u7D1A\u8005\u30E2\u30FC\u30C9\u306E\u307F\uFF09\u2014\u2014\u4F34\u594F\u3092\u4F55\u5C64\u306B\u3059\u308B\u304B\u3001\u305D\u308C\u305E\u308C\u3069\u306E\u594F\u6CD5\u3067\u3069\u306E\u30BB\u30AF\u30B7\u30E7\u30F3\u3092\u9CF4\u3089\u3059\u304B\u3001\u30B5\u30D3\u306E\u91CD\u306D\u3092\u51FA\u3059\u304B\u30FB\u30E6\u30CB\u30BE\u30F3\u304B\u30AA\u30AF\u30BF\u30FC\u30D6\u4E0A\u304B\u3001\u88C5\u98FE\u3092\u3069\u3053\u306B\u7F6E\u304F\u304B\u3002400\u66F2\u5F15\u304F\u3068392\u901A\u308A\u306E\u578B\u304C\u51FA\u307E\u3059\u3002</li>
|
|
19356
20282
|
</ul>
|
|
19357
20283
|
<p>\u3055\u3089\u306B\u3001\u76F4\u524D\u306B\u4F5C\u3063\u305F5\u66F2\u3068\u7279\u5FB4\u304C\u4F3C\u3066\u3044\u308B\u5019\u88DC\u306B\u306F\u6E1B\u70B9\u3057\u3066\u3044\u307E\u3059\u3002\u7D9A\u3051\u3066\u62BC\u3057\u305F\u3068\u304D\u306B\u4F3C\u305F\u66F2\u304C\u4E26\u3070\u306A\u3044\u3088\u3046\u306B\u3059\u308B\u305F\u3081\u3067\u3059\u3002</p>
|
|
19358
20284
|
<h4>\u3067\u304D\u3042\u304C\u308A\u306E\u9078\u3073\u65B9</h4>
|
|
@@ -19371,6 +20297,18 @@ var COMPOSE_INFO_HTML = `
|
|
|
19371
20297
|
<li><strong>\u639B\u3051\u5408\u3044\uFF08\u30C7\u30E5\u30A8\u30C3\u30C8\uFF09</strong> \u2014 4\u5272\u307B\u3069\u306E\u66F2\u304C2\u4EBA\u6B4C\u3044\u306B\u306A\u308A\u307E\u3059\u3002\u30BB\u30AF\u30B7\u30E7\u30F3\u3054\u3068\uFF0FA\u30E1\u30ED\u30672\u5C0F\u7BC0\u3054\u3068\uFF0F\u639B\u3051\u5408\u3044\u30B5\u30D3\uFF0FA\u30E1\u30ED\u3060\u3051\u3001\u306E4\u901A\u308A\u3002<strong>\u53D7\u3051\u6E21\u3057\u306F\u5C0F\u7BC0\u7DDA\u3074\u3063\u305F\u308A\u3067\u306F\u306A\u304F\u3001\u6B21\u306E\u4EBA\u304C\u624B\u524D\u304B\u3089\u98DF\u3044\u6C17\u5473\u306B\u5165\u308A\u307E\u3059\u3002</strong>\u4E00\u7DD2\u306B\u6B4C\u3046\u30B5\u30D3\u3067\u306F\u76F8\u65B9\u304C\u30CF\u30E2\u30EA\u3078\u56DE\u308A\u307E\u3059\uFF08\u540C\u3058\u97F3\u3092\u306A\u305E\u308B\u30E6\u30CB\u30BE\u30F3\u306B\u306F\u3057\u307E\u305B\u3093\uFF09\u3002</li>
|
|
19372
20298
|
</ul>
|
|
19373
20299
|
<p>\u30B7\u30F3\u30D7\u30EB\u30E2\u30FC\u30C9\uFF084\u30C8\u30E9\u30C3\u30AF\uFF09\u306F\u72EC\u5531\u3067\u3059\u30024\u672C\u304C\u57CB\u307E\u3063\u3066\u3044\u3066\u30CF\u30E2\u30EA\u306E\u7F6E\u304D\u5834\u6240\u304C\u7121\u3044\u305F\u3081\u3067\u3059\u3002</p>
|
|
20300
|
+
<h4>\u30BB\u30AF\u30B7\u30E7\u30F3\u3067\u697D\u5668\u30FB\u4F34\u594F\u304C\u5909\u308F\u308B\uFF08\u4E0A\u7D1A\u8005\u30E2\u30FC\u30C9\u306E\u307F\uFF09</h4>
|
|
20301
|
+
<p>1\u672C\u306E\u30C8\u30E9\u30C3\u30AF\u306F\u3001\u66F2\u306E\u6700\u521D\u304B\u3089\u6700\u5F8C\u307E\u30671\u3064\u306E\u697D\u5668\u3067\u9CF4\u308A\u307E\u3059\u3002\u3064\u307E\u308A<strong>\u300C\u30B5\u30D3\u3060\u3051\u5225\u306E\u697D\u5668\u306B\u3059\u308B\u300D\u306F\u30011\u672C\u306E\u30C8\u30E9\u30C3\u30AF\u306E\u4E2D\u3067\u306F\u4F5C\u308C\u307E\u305B\u3093</strong>\u3002\u4F5C\u308C\u308B\u306E\u306F\u3001\u9CF4\u3089\u3057\u305F\u3044\u533A\u9593\u3092\u5225\u306E\u30C8\u30E9\u30C3\u30AF\u3078\u66F8\u304D\u5206\u3051\u305F\u3068\u304D\u3060\u3051\u3067\u3059\u3002\u4E0A\u7D1A\u8005\u30E2\u30FC\u30C9\uFF0815\u30C8\u30E9\u30C3\u30AF\uFF09\u304C15\u672C\u3042\u308B\u306E\u306F\u305D\u306E\u305F\u3081\u3067\u3001\u300C\u4F5C\u66F2\u300D\u306F\u5834\u6240\u3054\u3068\u306B\u30C8\u30E9\u30C3\u30AF\u3092\u5206\u3051\u307E\u3059\u3002</p>
|
|
20302
|
+
<ul>
|
|
20303
|
+
<li><strong>\u4F34\u594F\u306E\u624B\u89E6\u308A\u304C\u30BB\u30AF\u30B7\u30E7\u30F3\u3067\u5909\u308F\u308B</strong> \u2014 \u540C\u3058\u30B3\u30FC\u30C9\u9032\u884C\u3092\u3001\u30D6\u30ED\u30C3\u30AF\u30FB\u30A2\u30EB\u30DA\u30B8\u30AA\u30FB\u88CF\u62CD\u30FB\u516B\u5206\u98DF\u3044\u30FB\u5206\u6563\u306E\u4E2D\u304B\u3089<strong>\u5225\u3005\u306E\u594F\u6CD5</strong>\u30671\u301C3\u5C64\u306B\u91CD\u306D\u307E\u3059\u3002\u3069\u306E\u594F\u6CD5\u3092\u3069\u306E\u30BB\u30AF\u30B7\u30E7\u30F3\u3067\u9CF4\u3089\u3059\u304B\u306F\u66F2\u3054\u3068\u306B\u5F15\u304F\u306E\u3067\u3001A\u30E1\u30ED\u3068\u30B5\u30D3\u3067\u4F34\u594F\u306E\u523B\u307F\u65B9\u305D\u306E\u3082\u306E\u304C\u5909\u308F\u308A\u307E\u3059\u3002\u66F2\u5168\u4F53\u3092\u901A\u308B\u300C\u5730\u300D\u306E\u5C64\u304C1\u3064\u3042\u308A\u3001\u6B8B\u308A\u306F\u8DB3\u3059\u5834\u6240\u3092\u7D5E\u308A\u307E\u3059\u3002</li>
|
|
20304
|
+
<li><strong>\u30B5\u30D3\u306E\u91CD\u306D</strong> \u2014 \u4E3B\u65CB\u5F8B\u3092\u3082\u30461\u672C\u306E\u5225\u697D\u5668\uFF08\u30D7\u30EA\u30BB\u30C3\u30C8\u306B\u3088\u3063\u3066\u30D6\u30E9\u30B9\u30FB\u30B9\u30C8\u30EA\u30F3\u30B0\u30B9\u30FB\u30B0\u30ED\u30C3\u30B1\u30F3\u306A\u3069\uFF09\u3067\u91CD\u306D\u307E\u3059\u3002<strong>\u30AA\u30AF\u30BF\u30FC\u30D6\u4E0A\u3068\u30E6\u30CB\u30BE\u30F3\u306E\u4E21\u65B9\u3092\u5F15\u304D\u307E\u3059</strong>\u2014\u2014\u540C\u3058\u9AD8\u3055\u3092\u5225\u306E\u697D\u5668\u3067\u91CD\u306D\u308B\u30682\u3064\u306E\u97F3\u8272\u304C\u6EB6\u3051\u3066\u5225\u306E\u97F3\u8272\u306B\u306A\u308B\u306E\u3067\u3001\u30AA\u30AF\u30BF\u30FC\u30D6\u4E0A\u3052\u308B\u3088\u308A\u60C5\u5831\u91CF\u304C\u591A\u3044\u3053\u3068\u304C\u3042\u308A\u307E\u3059\u3002\u91CD\u306D\u306A\u3044\u66F2\u3082\u3042\u308A\u307E\u3059\u3002</li>
|
|
20305
|
+
<li><strong>\u9593\u594F\u306E\u30BD\u30ED</strong> \u2014 \u9593\u594F\u306F\u6B4C\u304C\u4F11\u3080\u5834\u6240\u3067\u3042\u3063\u3066\u3001\u97F3\u697D\u304C\u4F11\u3080\u5834\u6240\u3067\u306F\u3042\u308A\u307E\u305B\u3093\u3002\u6B4C\u30E1\u30ED\u306E\u4EE3\u308F\u308A\u306B\u5668\u697D\u306E\u30BD\u30ED\u3092\u66F8\u304D\u3001\u5C02\u7528\u306E\u30C8\u30E9\u30C3\u30AF\u3067\u9CF4\u3089\u3057\u307E\u3059\u3002\u30D7\u30EA\u30BB\u30C3\u30C8\u306B\u3088\u3063\u3066\u6B6A\u307F\u30AE\u30BF\u30FC\u30FB\u30B5\u30C3\u30AF\u30B9\u30FB\u5C3A\u516B\u306A\u3069\u306B\u5909\u308F\u308A\u307E\u3059\u3002\u7D20\u6750\u306F\u30B5\u30D3\u3068\u540C\u3058\u306A\u306E\u3067\u3001\u9593\u594F\u304C\u30B5\u30D3\u306E\u4E3B\u984C\u3092\u5F3E\u304F\u5F62\u306B\u306A\u308A\u307E\u3059\u3002</li>
|
|
20306
|
+
<li><strong>\u30A6\u30EF\u30E2\u30CE</strong> \u2014 \u304D\u3089\u3073\u3084\u304B\u306A\u88C5\u98FE\u3092\u3001\u76DB\u308A\u4E0A\u304C\u308B\u30BB\u30AF\u30B7\u30E7\u30F3\u306B\u3060\u3051\u30AA\u30AF\u30BF\u30FC\u30D6\u4E0A\u3067\u8DB3\u3057\u307E\u3059\u3002<strong>\u5730\u306E\u4F34\u594F\u3068\u540C\u3058\u594F\u6CD5\u306F\u4F7F\u3044\u307E\u305B\u3093</strong>\u2014\u2014\u540C\u3058\u3082\u306E\u3092\u30AA\u30AF\u30BF\u30FC\u30D6\u4E0A\u3052\u305F\u3060\u3051\u306E\u5C64\u306F\u88C5\u98FE\u3067\u306F\u306A\u304F\u5199\u3057\u3060\u304B\u3089\u3067\u3059\u3002\u30D6\u30ED\u30C3\u30AF\u3082\u5916\u3057\u307E\u3059\uFF08\u548C\u97F3\u3092\u4E38\u3054\u3068\u30AA\u30AF\u30BF\u30FC\u30D6\u4E0A\u3067\u9CF4\u3089\u3059\u306E\u306F\u88C5\u98FE\u3067\u306F\u306A\u304F\u58C1\u306B\u306A\u308A\u307E\u3059\uFF09\u3002</li>
|
|
20307
|
+
</ul>
|
|
20308
|
+
<p><strong>\u697D\u5668\u306E\u97F3\u57DF\u306B\u5408\u308F\u305B\u3066\u30AA\u30AF\u30BF\u30FC\u30D6\u3092\u4E0B\u3052\u307E\u3059\u3002</strong>1\u30C8\u30E9\u30C3\u30AF1\u697D\u5668\u3067\u3001\u3057\u304B\u3082\u5C64\u3054\u3068\u306B\u30AA\u30AF\u30BF\u30FC\u30D6\u3092\u5909\u3048\u308B\u306E\u3067\u3001\u6C7A\u3081\u305F\u30AA\u30AF\u30BF\u30FC\u30D6\u304C\u305D\u306E\u697D\u5668\u306E\u51FA\u305B\u306A\u3044\u9AD8\u3055\u306B\u306A\u308B\u3053\u3068\u304C\u3042\u308A\u307E\u3059\u3002\u5B9F\u6E2C\u3059\u308B\u3068\u3001\u30B5\u30D3\u306E\u91CD\u306D\u30921\u30AA\u30AF\u30BF\u30FC\u30D6\u4E0A\u3052\u308B\u6307\u5B9A\u306F\u30DF\u30E5\u30FC\u30C8\u30C8\u30E9\u30F3\u30DA\u30C3\u30C8\u3084\u30C8\u30E9\u30F3\u30DA\u30C3\u30C8\u306714\u534A\u97F3\u3076\u3093\u3001\u30B3\u30FC\u30C9\u30D1\u30C3\u30C9\uFF08\u5B9F\u97F377\u301C93\uFF09\u306F\u30CA\u30A4\u30ED\u30F3\u30AE\u30BF\u30FC\u306710\u534A\u97F3\u30FB\u30AB\u30EA\u30F3\u30D0\u30679\u534A\u97F3\u3076\u3093\u97F3\u57DF\u3092\u7A81\u304D\u629C\u3051\u3066\u3044\u307E\u3057\u305F\u3002\u30B5\u30F3\u30D7\u30EB\u304C\u5F15\u304D\u4F38\u3070\u3055\u308C\u3066<strong>\u91D1\u5207\u308A\u97F3</strong>\u306B\u306A\u308A\u3001\u8074\u304D\u624B\u306B\u306F\u300C\u8033\u304C\u75DB\u3044\u300D\u3068\u3057\u304B\u611F\u3058\u3089\u308C\u307E\u305B\u3093\u3002\u305D\u3053\u3067\u3001\u9CF4\u3089\u3059\u97F3\u57DF\u304C\u305D\u306E\u697D\u5668\u306E\u5B9F\u7528\u4E0A\u9650\u306B\u53CE\u307E\u308B\u3068\u3053\u308D\u307E\u3067<strong>\u30AA\u30AF\u30BF\u30FC\u30D6\u3092\u4E0B\u3052\u3066\u304B\u3089</strong>\u7F6E\u304D\u307E\u3059\uFF08\u30C8\u30E9\u30C3\u30AF\u306E\u30AA\u30AF\u30BF\u30FC\u30D6\u8A2D\u5B9A\u306F\u3001\u307E\u3055\u306B\u3053\u3046\u3044\u3046\u300C\u5F97\u610F\u306A\u97F3\u57DF\u304C\u504F\u3063\u305F\u97F3\u6E90\u300D\u3092\u4F7F\u3048\u308B\u3088\u3046\u306B\u3059\u308B\u305F\u3081\u306B\u5728\u308B\u3082\u306E\u3067\u3059\uFF09\u3002<strong>\u4E0B\u3052\u308B\u65B9\u5411\u306B\u3057\u304B\u52D5\u304B\u3057\u307E\u305B\u3093</strong>\u2014\u2014\u4E0A\u3052\u308B\u5074\u304C\u75DB\u307F\u3092\u4F5C\u308B\u5074\u306A\u306E\u3067\u3002</p>
|
|
20309
|
+
<p>\u5B9F\u7269\u306E\u97F3\u57DF\u306B\u53CE\u307E\u3063\u3066\u3044\u3066\u3082\u75DB\u304F\u306A\u308B\u97F3\u8272\u304C\u3042\u308A\u307E\u3059\u3002\u30B0\u30ED\u30C3\u30B1\u30F3\u306F\u5B9F\u7269\u306E\u97F3\u57DF\u304CG5\u301CC8\u306A\u306E\u3067\u3001\u65CB\u5F8B\u306E\u97F3\u57DF\uFF08\u301CC6\uFF09\u306F\u300C\u4F59\u88D5\u3067\u7BC4\u56F2\u5185\u300D\u3067\u3059\u304C\u3001\u91D1\u5C5E\u4F53\u306E\u500D\u97F3\u306F\u4EBA\u306E\u8033\u304C\u3044\u3061\u3070\u3093\u654F\u611F\u306A2\u301C4kHz\u306B\u96C6\u307E\u308B\u305F\u3081\u3001\u305D\u306E\u9AD8\u3055\u3067\u9CF4\u3089\u3057\u7D9A\u3051\u308B\u3068\u523A\u3055\u308A\u307E\u3059\u3002\u3053\u3046\u3044\u3046\u97F3\u8272\u306B\u306F\u97F3\u57DF\u3068\u306F\u5225\u306B<strong>\u660E\u308B\u3055\u306E\u4E0A\u9650</strong>\u3092\u6301\u305F\u305B\u3066\u3042\u308A\u3001\u30B0\u30ED\u30C3\u30B1\u30F3\u306A\u3089C5\u3088\u308A\u4E0A\u3067\u9CF4\u3089\u306A\u3044\u3068\u3053\u308D\u307E\u3067\u4E0B\u3052\u307E\u3059\u3002<strong>\u5019\u88DC\u304B\u3089\u5916\u3059\u306E\u3067\u306F\u306A\u304F\u7F6E\u304D\u5834\u6240\u3092\u5909\u3048\u307E\u3059</strong>\u2014\u2014\u5916\u3059\u3068\u97F3\u8272\u306E\u5E45\u304C\u305D\u306E\u3076\u3093\u6E1B\u308B\u3060\u3051\u3067\u3001\u4F4E\u304F\u9CF4\u3089\u3057\u305F\u30B0\u30ED\u30C3\u30B1\u30F3\u306F\u30DD\u30C3\u30D7\u30B9\u3067\u666E\u901A\u306B\u4F7F\u308F\u308C\u308B\u67D4\u3089\u304B\u3044\u97F3\u3067\u3059\u3002</p>
|
|
20310
|
+
<p><strong>\u30AA\u30AF\u30BF\u30FC\u30D6\u306E\u91CD\u306D\u3092\u4E3B\u5F79\u306B\u3057\u3066\u3044\u307E\u305B\u3093\u3002</strong>\u300C\u65E2\u306B\u3042\u308B\u30C8\u30E9\u30C3\u30AF\u30921\u30AA\u30AF\u30BF\u30FC\u30D6\u52D5\u304B\u3057\u3066\u5225\u30C8\u30E9\u30C3\u30AF\u3078\u5199\u3059\u300D\u5C64\u306F\u3001\u97F3\u697D\u7684\u306A\u4FA1\u5024\u304C\u9AD8\u304F\u3042\u308A\u307E\u305B\u3093\u3002\u4EBA\u306E\u8033\u306F\u30AA\u30AF\u30BF\u30FC\u30D6\u9055\u3044\u3092<strong>\u540C\u3058\u97F3</strong>\u3068\u3057\u3066\u805E\u304F\u306E\u3067\uFF08\u30AA\u30AF\u30BF\u30FC\u30D6\u7B49\u4FA1\uFF09\u3001\u5199\u3057\u305F\u5C64\u306F\u65B0\u3057\u3044\u58F0\u90E8\u306B\u306A\u3089\u305A\u3001\u97F3\u91CF\u3068\u97F3\u8272\u304C\u308F\u305A\u304B\u306B\u5909\u308F\u308B\u3060\u3051\u3067\u3059\u3002\u5F37\u8ABF\u3068\u3057\u3066\u306E\u610F\u5473\u306F\u3042\u308B\u306E\u3067\u4F7F\u3044\u306F\u3057\u307E\u3059\u304C\u3001\u5E38\u8A2D\u306B\u306F\u3057\u307E\u305B\u3093\u3002\u30D9\u30FC\u30B9\u306E\u30AA\u30AF\u30BF\u30FC\u30D6\u4E0B\u306E\u91CD\u306D\u306F\u7279\u306B\u300130Hz\u524D\u5F8C\u307E\u3067\u843D\u3061\u3066\u8F2A\u90ED\u304C\u6FC1\u308B\u306E\u3067\u65E2\u5B9A\u3067\u306F\u51FA\u3057\u307E\u305B\u3093\uFF08\u51FA\u3059\u3068\u304D\u3082\u4E0A\u306E\u30AA\u30AF\u30BF\u30FC\u30D6\u3078\u3001\u76DB\u308A\u4E0A\u304C\u308B\u5834\u6240\u3060\u3051\u306B\u7F6E\u304D\u307E\u3059\uFF09\u3002</p>
|
|
20311
|
+
<p>\u300C\u4F5C\u66F2\u300D\u304C\u6C7A\u3081\u305F\u3053\u308C\u3089\u306E\u697D\u5668\u306F\u3001\u304A\u307E\u304B\u305B\u30DE\u30B9\u30BF\u30EA\u30F3\u30B0\u306E\u5F79\u5272\u63A8\u5B9A\u3088\u308A\u512A\u5148\u3055\u308C\u307E\u3059\uFF08\u6F14\u594F\u5185\u5BB9\u3060\u3051\u3092\u898B\u308B\u3068\u3001\u9593\u594F\u306E\u30BD\u30ED\u3082\u30B5\u30D3\u306E\u91CD\u306D\u3082\u300C\u97F3\u306E\u5C11\u306A\u3044\u5358\u65CB\u5F8B\u300D\u3067\u3001\u4E3B\u65CB\u5F8B\u3068\u533A\u5225\u304C\u4ED8\u304B\u306A\u3044\u305F\u3081\u3067\u3059\uFF09\u3002\u697D\u5668\u3092\u624B\u3067\u9078\u3073\u76F4\u3057\u305F\u30C8\u30E9\u30C3\u30AF\u306F\u3001\u4EE5\u5F8C\u3069\u3061\u3089\u306B\u3082\u4E0A\u66F8\u304D\u3055\u308C\u307E\u305B\u3093\u3002</p>
|
|
19374
20312
|
<h4>\u305D\u306E\u307B\u304B</h4>
|
|
19375
20313
|
<ul>
|
|
19376
20314
|
<li><strong>\u66F2\u306E\u9014\u4E2D\u3067\u8EE2\u8ABF\u3057\u307E\u3059</strong>\uFF08\u304A\u3088\u305D\u534A\u5206\u306E\u66F2\uFF09\u3002\u4E94\u5EA6\u570F\u3067\u8FD1\u3044\u5C5E\u8ABF\u30FB\u4E0B\u5C5E\u8ABF\u3078\u306F\u5171\u901A\u3059\u308B\u548C\u97F3\uFF08\u30D4\u30DC\u30C3\u30C8\u30B3\u30FC\u30C9\uFF09\u304B\u65B0\u3057\u3044\u8ABF\u306E\u30C9\u30DF\u30CA\u30F3\u30C8\u3067\u6A4B\u6E21\u3057\u3057\u3001\u30E9\u30B9\u30B5\u30D3\u306E\u534A\u97F3\u4E0A\u3052\u306F\u6E96\u5099\u306A\u3057\u306E\u76F4\u63A5\u8EE2\u8ABF\u306B\u3057\u307E\u3059\u3002\u8ABF\u53F7\u3092\u5909\u3048\u305A\u306B\u660E\u6697\u3060\u3051\u5165\u308C\u66FF\u3048\u308B<strong>\u5E73\u884C\u8ABF</strong>\uFF08\u30CF\u9577\u8ABF\u2194\u30A4\u77ED\u8ABF\uFF09\u3068\u3001\u4E3B\u97F3\u3092\u4FDD\u3063\u305F\u307E\u307E\u6697\u304F\u3059\u308B<strong>\u540C\u4E3B\u8ABF</strong>\uFF08\u30CF\u9577\u8ABF\u2192\u30CF\u77ED\u8ABF\uFF09\u3082\u5F15\u304D\u307E\u3059\u30021\u5272\u5F37\u306E\u66F2\u306F\u4E3B\u548C\u97F3\u3092\u907F\u3051\u3066\u300C\u660E\u308B\u3044\u306E\u304B\u6697\u3044\u306E\u304B\u5206\u304B\u3089\u306A\u3044\u300D\u6D6E\u904A\u611F\u3067\u901A\u3057\u307E\u3059\u3002</li>
|
|
@@ -19637,26 +20575,128 @@ var pickComposeVocal = (exclude) => {
|
|
|
19637
20575
|
const list = pool.length > 0 ? pool : COMPOSE_VOCAL_POOL;
|
|
19638
20576
|
return list[Math.floor(Math.random() * list.length)] ?? "klatt";
|
|
19639
20577
|
};
|
|
19640
|
-
var
|
|
19641
|
-
{
|
|
19642
|
-
|
|
19643
|
-
|
|
19644
|
-
|
|
19645
|
-
|
|
19646
|
-
|
|
19647
|
-
|
|
19648
|
-
|
|
19649
|
-
|
|
19650
|
-
|
|
19651
|
-
|
|
19652
|
-
|
|
19653
|
-
|
|
19654
|
-
|
|
19655
|
-
|
|
19656
|
-
|
|
19657
|
-
|
|
19658
|
-
|
|
19659
|
-
|
|
20578
|
+
var buildAdvancedLayers = (song, config) => {
|
|
20579
|
+
const { edo, stepsPerBar, preset } = config;
|
|
20580
|
+
const semitoneRange = (notes) => {
|
|
20581
|
+
if (notes.length === 0) return null;
|
|
20582
|
+
let lo = Number.POSITIVE_INFINITY;
|
|
20583
|
+
let hi = Number.NEGATIVE_INFINITY;
|
|
20584
|
+
for (const n of notes) {
|
|
20585
|
+
const semi = n.pitchUnits / UNITS_PER_SEMITONE;
|
|
20586
|
+
if (semi < lo) lo = semi;
|
|
20587
|
+
if (semi > hi) hi = semi;
|
|
20588
|
+
}
|
|
20589
|
+
return [Math.round(lo), Math.round(hi)];
|
|
20590
|
+
};
|
|
20591
|
+
const fit = (notes, slot, wanted) => fitInstrumentOctave(semitoneRange(notes), preset[slot], wanted);
|
|
20592
|
+
const kindAtBar = (bar) => song.sections.find(
|
|
20593
|
+
(sec) => bar >= sec.startBar && bar < sec.startBar + sec.bars
|
|
20594
|
+
)?.kind ?? null;
|
|
20595
|
+
const onlyIn = (notes, kinds) => {
|
|
20596
|
+
if (!kinds) return notes;
|
|
20597
|
+
const want = new Set(kinds);
|
|
20598
|
+
return notes.filter((n) => {
|
|
20599
|
+
const kind = kindAtBar(Math.floor(n.startStep / stepsPerBar));
|
|
20600
|
+
return kind !== null && want.has(kind);
|
|
20601
|
+
});
|
|
20602
|
+
};
|
|
20603
|
+
const chordNotes = (pattern, velocityShift = 0) => buildChordPlacements({
|
|
20604
|
+
edo,
|
|
20605
|
+
chordStr: song.chordProgression,
|
|
20606
|
+
patternType: pattern,
|
|
20607
|
+
rootShift: song.rootShift,
|
|
20608
|
+
bpm: song.bpm,
|
|
20609
|
+
stepsPerBar
|
|
20610
|
+
}).map((p) => ({
|
|
20611
|
+
startStep: p.startStep,
|
|
20612
|
+
pitchUnits: p.pitchUnits,
|
|
20613
|
+
durationSteps: p.durationSteps,
|
|
20614
|
+
velocity: Math.max(30, p.velocity + velocityShift)
|
|
20615
|
+
}));
|
|
20616
|
+
const plan = song.arrange;
|
|
20617
|
+
const leadNotes = plan.lead ? onlyIn(song.melody, plan.lead.sections) : [];
|
|
20618
|
+
const leadOctave = fit(leadNotes, "chorusLead", plan.lead?.octave ?? 0);
|
|
20619
|
+
const leadLayer = {
|
|
20620
|
+
index: 1,
|
|
20621
|
+
notes: leadNotes,
|
|
20622
|
+
octave: leadOctave,
|
|
20623
|
+
// ユニゾンで重ねるときは、オクターブ上より前に出やすいので少し引く。
|
|
20624
|
+
volume: leadOctave === 0 ? 54 : 62,
|
|
20625
|
+
slot: "chorusLead"
|
|
20626
|
+
};
|
|
20627
|
+
const bassNotes = plan.bassLayer ? onlyIn(song.bass, plan.bassLayer.sections) : [];
|
|
20628
|
+
const bassOctave = fit(bassNotes, "bass", plan.bassLayer?.octave ?? 0);
|
|
20629
|
+
const bassLayer = {
|
|
20630
|
+
index: 5,
|
|
20631
|
+
notes: bassOctave === 0 ? [] : bassNotes,
|
|
20632
|
+
octave: bassOctave,
|
|
20633
|
+
volume: 58,
|
|
20634
|
+
slot: "bass"
|
|
20635
|
+
};
|
|
20636
|
+
const padNotes = onlyIn(song.pad, plan.padSections);
|
|
20637
|
+
const layers = [
|
|
20638
|
+
{ index: 0, notes: song.melody, octave: 0, volume: 104, slot: "melody" },
|
|
20639
|
+
leadLayer,
|
|
20640
|
+
{ index: 2, notes: song.harmony, octave: 0, volume: 82 },
|
|
20641
|
+
{
|
|
20642
|
+
index: 3,
|
|
20643
|
+
notes: song.submelody,
|
|
20644
|
+
octave: 0,
|
|
20645
|
+
volume: 86,
|
|
20646
|
+
slot: "submelody"
|
|
20647
|
+
},
|
|
20648
|
+
{ index: 4, notes: song.bass, octave: 0, volume: 92, slot: "bass" },
|
|
20649
|
+
bassLayer,
|
|
20650
|
+
// **パッドは伴奏用の楽器で、伴奏より1.5オクターブ高いところを鳴らす。**
|
|
20651
|
+
// そのまま置くとナイロンギターで10半音、カリンバで9半音、尺八で7半音ぶん
|
|
20652
|
+
// 音域を突き抜ける。楽器に合わせて下げる。
|
|
20653
|
+
{
|
|
20654
|
+
index: 6,
|
|
20655
|
+
notes: padNotes,
|
|
20656
|
+
octave: fit(padNotes, "chord", 0),
|
|
20657
|
+
volume: 64,
|
|
20658
|
+
slot: "chord"
|
|
20659
|
+
}
|
|
20660
|
+
];
|
|
20661
|
+
const backingVolumes = [62, 54, 50];
|
|
20662
|
+
for (let i2 = 0; i2 < 3; i2++) {
|
|
20663
|
+
const layer = plan.backing[i2];
|
|
20664
|
+
layers.push({
|
|
20665
|
+
index: 7 + i2,
|
|
20666
|
+
notes: layer ? onlyIn(chordNotes(layer.pattern), layer.sections) : [],
|
|
20667
|
+
octave: layer?.octave ?? 0,
|
|
20668
|
+
volume: backingVolumes[i2],
|
|
20669
|
+
slot: "chord"
|
|
20670
|
+
});
|
|
20671
|
+
}
|
|
20672
|
+
const sparkleNotes = plan.sparkle ? onlyIn(chordNotes(plan.sparkle.pattern, -14), plan.sparkle.sections) : [];
|
|
20673
|
+
layers.push(
|
|
20674
|
+
{
|
|
20675
|
+
index: 10,
|
|
20676
|
+
notes: sparkleNotes,
|
|
20677
|
+
octave: fit(sparkleNotes, "chord", plan.sparkle?.octave ?? 0),
|
|
20678
|
+
volume: 56,
|
|
20679
|
+
slot: "chord"
|
|
20680
|
+
},
|
|
20681
|
+
// 掛け合い(デュエット)の相手。**歌入り作曲のときだけ**中身が入る。
|
|
20682
|
+
{ index: 11, notes: [], octave: 0, volume: 104, slot: "melody" },
|
|
20683
|
+
// 2声目のハモリ(主旋律を上下から挟む3声)と、主旋律のオクターブ下の重ね。
|
|
20684
|
+
// どちらも曲ごとに出るかどうかが決まる(`song.vocal`)。
|
|
20685
|
+
{ index: 12, notes: song.harmony2, octave: 0, volume: 74 },
|
|
20686
|
+
{ index: 13, notes: song.octave, octave: -1, volume: 56, slot: "melody" },
|
|
20687
|
+
// **間奏のソロ。** 音が入るのは間奏の小節だけなので、この1本だけを
|
|
20688
|
+
// 別の楽器にしても他のセクションの鳴りは変わらない。歌の音域をそのまま
|
|
20689
|
+
// 渡すと管楽器が上へ抜ける(テナーサックスで10半音)ので、ここも合わせる。
|
|
20690
|
+
{
|
|
20691
|
+
index: 14,
|
|
20692
|
+
notes: song.solo,
|
|
20693
|
+
octave: fit(song.solo, "solo", 0),
|
|
20694
|
+
volume: 100,
|
|
20695
|
+
slot: "solo"
|
|
20696
|
+
}
|
|
20697
|
+
);
|
|
20698
|
+
return layers;
|
|
20699
|
+
};
|
|
19660
20700
|
var LYRIC_MODEL_CATEGORIES = [
|
|
19661
20701
|
{
|
|
19662
20702
|
label: "kusa\u30D7\u30EA\u30BB\u30C3\u30C8",
|
|
@@ -19812,7 +20852,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
19812
20852
|
showChord,
|
|
19813
20853
|
showMidiSearch,
|
|
19814
20854
|
// 「作曲」は simple では役割固定の4トラックへ、advanced では15トラックへ
|
|
19815
|
-
// 編曲を展開する({@link
|
|
20855
|
+
// 編曲を展開する({@link buildAdvancedLayers})。どちらでも出す。
|
|
19816
20856
|
showCompose: true
|
|
19817
20857
|
});
|
|
19818
20858
|
refs.masterVolume.value = String(options.masterVolume ?? 50);
|
|
@@ -20006,6 +21046,14 @@ var mountDAW = (target, options = {}) => {
|
|
|
20006
21046
|
while (customVocalsMap.has(`custom${n}`)) n++;
|
|
20007
21047
|
return `custom${n}`;
|
|
20008
21048
|
};
|
|
21049
|
+
const getVocalIconSrc = (lyricModel) => {
|
|
21050
|
+
if (!lyricModel) return void 0;
|
|
21051
|
+
const customDef = customVocalsMap.get(lyricModel);
|
|
21052
|
+
if (customDef !== void 0)
|
|
21053
|
+
return customDef.iconUrl || FALLBACK_VOCAL_ICON;
|
|
21054
|
+
const imgKey = VOICE_IMAGE_KEY[lyricModel.toLowerCase()];
|
|
21055
|
+
return imgKey ? VOICE_IMAGES[imgKey] : void 0;
|
|
21056
|
+
};
|
|
20009
21057
|
let selectedNotes = [];
|
|
20010
21058
|
let selectionRect = null;
|
|
20011
21059
|
let copiedNotes = [];
|
|
@@ -20139,6 +21187,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
20139
21187
|
vocalTension: t1?.vocalTension ?? 50,
|
|
20140
21188
|
vocalOctaveUnison: t1?.vocalOctaveUnison ?? "none",
|
|
20141
21189
|
trackInstrument: t1?.trackInstrument ?? "",
|
|
21190
|
+
composeSlot: null,
|
|
20142
21191
|
trackCompression: t1?.trackCompression ?? 0,
|
|
20143
21192
|
trackWidth: t1?.trackWidth ?? 100,
|
|
20144
21193
|
trackReverbSend: t1?.trackReverbSend ?? 0,
|
|
@@ -21190,25 +22239,38 @@ var mountDAW = (target, options = {}) => {
|
|
|
21190
22239
|
refs.undoBtn.disabled = !core.canUndo();
|
|
21191
22240
|
refs.redoBtn.disabled = !core.canRedo();
|
|
21192
22241
|
};
|
|
21193
|
-
const
|
|
22242
|
+
const updateTrackTabs = () => {
|
|
21194
22243
|
refs.trackTabs.innerHTML = "";
|
|
21195
22244
|
trackPillEls.clear();
|
|
21196
22245
|
for (const [i2, t] of trackStates.entries()) {
|
|
21197
22246
|
const [r, g, b] = t.config.color;
|
|
21198
22247
|
const isActive = t.config.id === activeTrackId;
|
|
21199
22248
|
const btn = document.createElement("button");
|
|
21200
|
-
|
|
22249
|
+
const vocalIconSrc = getVocalIconSrc(t.lyricModel);
|
|
22250
|
+
btn.className = `dtm-pill ${isActive ? "dtm-pill--active" : ""} ${vocalIconSrc ? "dtm-pill--vocal" : ""}`;
|
|
21201
22251
|
btn.style.setProperty("--dtm-pill-color", `rgb(${r},${g},${b})`);
|
|
22252
|
+
if (vocalIconSrc) {
|
|
22253
|
+
btn.style.setProperty(
|
|
22254
|
+
"--dtm-pill-icon",
|
|
22255
|
+
`url(${JSON.stringify(vocalIconSrc)})`
|
|
22256
|
+
);
|
|
22257
|
+
}
|
|
21202
22258
|
btn.title = `Track ${i2 + 1}: ${t.config.name}`;
|
|
21203
22259
|
btn.setAttribute(
|
|
21204
22260
|
"aria-label",
|
|
21205
|
-
`Track ${i2 + 1}: ${t.config.name}${isActive ? " (\u9078\u629E\u4E2D)" : ""}`
|
|
22261
|
+
`Track ${i2 + 1}: ${t.config.name}${isActive ? " (\u9078\u629E\u4E2D)" : ""}${vocalIconSrc ? "\uFF08\u30DC\u30FC\u30AB\u30EB\u9078\u629E\u4E2D\uFF09" : ""}`
|
|
21206
22262
|
);
|
|
21207
|
-
|
|
22263
|
+
const labelEl = document.createElement("span");
|
|
22264
|
+
labelEl.className = "dtm-pill__label";
|
|
22265
|
+
labelEl.textContent = String(i2 + 1);
|
|
22266
|
+
btn.appendChild(labelEl);
|
|
21208
22267
|
btn.addEventListener("click", () => switchTrack(t.config.id));
|
|
21209
22268
|
refs.trackTabs.appendChild(btn);
|
|
21210
22269
|
trackPillEls.set(t.config.id, btn);
|
|
21211
22270
|
}
|
|
22271
|
+
};
|
|
22272
|
+
const updateTrackPanel = () => {
|
|
22273
|
+
updateTrackTabs();
|
|
21212
22274
|
const active = getActive();
|
|
21213
22275
|
const activeIndex = trackStates.findIndex(
|
|
21214
22276
|
(t) => t.config.id === activeTrackId
|
|
@@ -21525,6 +22587,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
21525
22587
|
syncInstDisabled();
|
|
21526
22588
|
instSel.addEventListener("change", () => {
|
|
21527
22589
|
active.trackInstrument = instSel.value;
|
|
22590
|
+
active.composeSlot = null;
|
|
21528
22591
|
const trackIndex = trackStates.indexOf(active);
|
|
21529
22592
|
options.onTrackInstrumentChange?.(trackIndex, active.trackInstrument);
|
|
21530
22593
|
persistTrack1(active);
|
|
@@ -21928,6 +22991,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
21928
22991
|
redrawAll();
|
|
21929
22992
|
fireLyricsChange(active);
|
|
21930
22993
|
reloadVoicesForModel(active.lyricModel);
|
|
22994
|
+
updateTrackTabs();
|
|
21931
22995
|
});
|
|
21932
22996
|
lyricCustomGuide.addEventListener("click", () => {
|
|
21933
22997
|
showModal("\u30AB\u30B9\u30BF\u30E0\u97F3\u58F0(.koe)\u306E\u4F7F\u3044\u65B9", KOE_INFO_HTML);
|
|
@@ -22461,6 +23525,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
22461
23525
|
}
|
|
22462
23526
|
trackStates.forEach((t, i2) => {
|
|
22463
23527
|
if (applyActiveOnly && i2 !== activeTrackIndex) return;
|
|
23528
|
+
t.composeSlot = null;
|
|
22464
23529
|
const name = normalizeInstrumentName(meta.trackInstruments?.[i2] ?? "");
|
|
22465
23530
|
if (t.trackInstrument !== name) {
|
|
22466
23531
|
t.trackInstrument = name;
|
|
@@ -22712,7 +23777,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
22712
23777
|
const p = programOfInstrumentName(t.trackInstrument);
|
|
22713
23778
|
if (p !== null) program = p;
|
|
22714
23779
|
} else if (!t.lyricModel) {
|
|
22715
|
-
const role = DECLARED_ROLE[t.config.id] ?? "melody";
|
|
23780
|
+
const role = t.composeSlot ?? DECLARED_ROLE[t.config.id] ?? "melody";
|
|
22716
23781
|
const instName = autoPreset[role] ?? autoPreset.melody;
|
|
22717
23782
|
const p = programOfInstrumentName(instName);
|
|
22718
23783
|
if (p !== null) program = p;
|
|
@@ -23081,7 +24146,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
23081
24146
|
if (!stats) continue;
|
|
23082
24147
|
const role = DECLARED_ROLE[t.config.id] ?? classifyTrackRole(stats, t.config.id === topSingleVoiceId);
|
|
23083
24148
|
roleByTrackId.set(t.config.id, role);
|
|
23084
|
-
const instName = autoPreset[role];
|
|
24149
|
+
const instName = autoPreset[t.composeSlot ?? role] ?? autoPreset[role];
|
|
23085
24150
|
t.trackInstrument = instName;
|
|
23086
24151
|
const trackIndex = trackStates.indexOf(t);
|
|
23087
24152
|
options.onTrackInstrumentChange?.(trackIndex, instName);
|
|
@@ -23232,6 +24297,15 @@ var mountDAW = (target, options = {}) => {
|
|
|
23232
24297
|
refs.composeKey.value = savedKey;
|
|
23233
24298
|
}
|
|
23234
24299
|
}
|
|
24300
|
+
const savedScale = readMacroSetting("scale");
|
|
24301
|
+
if (savedScale && refs.composeScale) {
|
|
24302
|
+
const hasOption = Array.from(refs.composeScale.options).some(
|
|
24303
|
+
(opt) => opt.value === savedScale
|
|
24304
|
+
);
|
|
24305
|
+
if (hasOption) {
|
|
24306
|
+
refs.composeScale.value = savedScale;
|
|
24307
|
+
}
|
|
24308
|
+
}
|
|
23235
24309
|
const savedShift = readMacroSetting("shift");
|
|
23236
24310
|
if (savedShift && refs.shiftSelect) {
|
|
23237
24311
|
const hasOption = Array.from(refs.shiftSelect.options).some(
|
|
@@ -23294,6 +24368,20 @@ var mountDAW = (target, options = {}) => {
|
|
|
23294
24368
|
});
|
|
23295
24369
|
updateComposeKeyHint();
|
|
23296
24370
|
}
|
|
24371
|
+
const updateComposeScaleHint = () => {
|
|
24372
|
+
if (!refs.composeScale || !refs.composeScaleHint) return;
|
|
24373
|
+
const desc = getComposeScaleDescription(refs.composeScale.value);
|
|
24374
|
+
refs.composeScaleHint.textContent = desc;
|
|
24375
|
+
refs.composeScaleHint.title = desc;
|
|
24376
|
+
};
|
|
24377
|
+
const composeScale = refs.composeScale;
|
|
24378
|
+
if (composeScale) {
|
|
24379
|
+
composeScale.addEventListener("change", () => {
|
|
24380
|
+
writeMacroSetting("scale", composeScale.value);
|
|
24381
|
+
updateComposeScaleHint();
|
|
24382
|
+
});
|
|
24383
|
+
updateComposeScaleHint();
|
|
24384
|
+
}
|
|
23297
24385
|
if (refs.shiftSelect) {
|
|
23298
24386
|
refs.shiftSelect.addEventListener("change", () => {
|
|
23299
24387
|
writeMacroSetting("shift", refs.shiftSelect.value);
|
|
@@ -23314,6 +24402,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
23314
24402
|
sections: selectedComposeSections(),
|
|
23315
24403
|
template: tmpl,
|
|
23316
24404
|
baseKey: refs.composeKey?.value ?? "any",
|
|
24405
|
+
scale: refs.composeScale?.value ?? "auto",
|
|
23317
24406
|
// 直近に作った曲の特徴を渡すと、それらから離れた候補に加点される。
|
|
23318
24407
|
// 「作曲」を続けて押したときに似た曲が並ぶのを防ぐ。
|
|
23319
24408
|
recent: recentComposeFingerprints
|
|
@@ -23347,45 +24436,39 @@ var mountDAW = (target, options = {}) => {
|
|
|
23347
24436
|
}
|
|
23348
24437
|
track.core.endBatch();
|
|
23349
24438
|
};
|
|
24439
|
+
const shouldAutoInstrument = !currentInstrument || currentInstrument === "auto" || currentInstrument === autoComposeInstrument;
|
|
24440
|
+
if (shouldAutoInstrument && song.instrument) {
|
|
24441
|
+
currentInstrument = song.instrument;
|
|
24442
|
+
autoComposeInstrument = song.instrument;
|
|
24443
|
+
options.onInstrumentChange?.(song.instrument);
|
|
24444
|
+
}
|
|
23350
24445
|
if (isAdvanced) {
|
|
23351
|
-
|
|
24446
|
+
const layers = buildAdvancedLayers(song, {
|
|
24447
|
+
edo: renderConfig.edo,
|
|
24448
|
+
stepsPerBar: renderConfig.stepsPerBar,
|
|
24449
|
+
preset: INSTRUMENT_PRESETS[currentInstrument] ?? INSTRUMENT_PRESETS.piano
|
|
24450
|
+
});
|
|
24451
|
+
for (const layer of layers) {
|
|
23352
24452
|
const track = trackStates[layer.index];
|
|
23353
24453
|
if (!track) continue;
|
|
23354
|
-
|
|
23355
|
-
edo: renderConfig.edo,
|
|
23356
|
-
chordStr: song.chordProgression,
|
|
23357
|
-
patternType: "arpeggio",
|
|
23358
|
-
rootShift: song.rootShift,
|
|
23359
|
-
bpm: song.bpm,
|
|
23360
|
-
stepsPerBar: renderConfig.stepsPerBar
|
|
23361
|
-
}).map((p) => ({
|
|
23362
|
-
startStep: p.startStep,
|
|
23363
|
-
pitchUnits: p.pitchUnits,
|
|
23364
|
-
durationSteps: p.durationSteps,
|
|
23365
|
-
velocity: Math.max(30, p.velocity - 14)
|
|
23366
|
-
})) : buildChordPlacements({
|
|
23367
|
-
edo: renderConfig.edo,
|
|
23368
|
-
chordStr: song.chordProgression,
|
|
23369
|
-
patternType: layer.part,
|
|
23370
|
-
rootShift: song.rootShift,
|
|
23371
|
-
bpm: song.bpm,
|
|
23372
|
-
stepsPerBar: renderConfig.stepsPerBar
|
|
23373
|
-
}).map((p) => ({
|
|
23374
|
-
startStep: p.startStep,
|
|
23375
|
-
pitchUnits: p.pitchUnits,
|
|
23376
|
-
durationSteps: p.durationSteps,
|
|
23377
|
-
velocity: p.velocity
|
|
23378
|
-
}));
|
|
23379
|
-
writeTrackAt(layer.index, notes);
|
|
24454
|
+
writeTrackAt(layer.index, layer.notes);
|
|
23380
24455
|
track.trackOctave = layer.octave;
|
|
23381
24456
|
track.volume = layer.volume;
|
|
23382
24457
|
track.core.setVolume(layer.volume);
|
|
24458
|
+
track.composeSlot = layer.notes.length > 0 ? layer.slot ?? null : null;
|
|
24459
|
+
if (layer.notes.length === 0 && track.trackInstrument) {
|
|
24460
|
+
track.trackInstrument = "";
|
|
24461
|
+
options.onTrackInstrumentChange?.(layer.index, "");
|
|
24462
|
+
}
|
|
23383
24463
|
}
|
|
23384
24464
|
for (let i2 = 0; i2 < trackStates.length; i2++) {
|
|
23385
|
-
if (
|
|
24465
|
+
if (layers.some((l) => l.index === i2)) continue;
|
|
23386
24466
|
writeTrackAt(i2, []);
|
|
24467
|
+
const t = trackStates[i2];
|
|
24468
|
+
if (t) t.composeSlot = null;
|
|
23387
24469
|
}
|
|
23388
24470
|
} else {
|
|
24471
|
+
for (const t of trackStates) t.composeSlot = null;
|
|
23389
24472
|
writeTrack("melody", song.melody);
|
|
23390
24473
|
writeTrack("submelody", song.submelody);
|
|
23391
24474
|
writeTrack("bass", song.bass);
|
|
@@ -23402,12 +24485,6 @@ var mountDAW = (target, options = {}) => {
|
|
|
23402
24485
|
refs.drumSelect.value = song.drum;
|
|
23403
24486
|
options.onDrumChange?.(song.drum);
|
|
23404
24487
|
applyDrumPatternFont(song.drum);
|
|
23405
|
-
const shouldAutoInstrument = !currentInstrument || currentInstrument === "auto" || currentInstrument === autoComposeInstrument;
|
|
23406
|
-
if (shouldAutoInstrument && song.instrument) {
|
|
23407
|
-
currentInstrument = song.instrument;
|
|
23408
|
-
autoComposeInstrument = song.instrument;
|
|
23409
|
-
options.onInstrumentChange?.(song.instrument);
|
|
23410
|
-
}
|
|
23411
24488
|
if (withVocal) {
|
|
23412
24489
|
autoComposeVocalTracks.clear();
|
|
23413
24490
|
const melodyTrack = isAdvanced ? trackStates[0] : trackStates.find((t) => t.config.id === "melody");
|
|
@@ -24644,6 +25721,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
24644
25721
|
if (!t) return;
|
|
24645
25722
|
const name = normalizeInstrumentName(instrumentName);
|
|
24646
25723
|
t.trackInstrument = name;
|
|
25724
|
+
t.composeSlot = null;
|
|
24647
25725
|
if (t.config.id === activeTrackId) updateTrackPanel();
|
|
24648
25726
|
},
|
|
24649
25727
|
noteToCanvas: (step, pitch) => {
|
|
@@ -26911,10 +27989,13 @@ var createDtmStudio = async (options = {}) => {
|
|
|
26911
27989
|
export {
|
|
26912
27990
|
A4_HZ,
|
|
26913
27991
|
A4_UNITS,
|
|
27992
|
+
BLUES_SCALE,
|
|
26914
27993
|
BREATH_MARK,
|
|
26915
27994
|
CENTS_PER_UNIT,
|
|
26916
27995
|
COMPOSE_KEYS,
|
|
26917
27996
|
COMPOSE_MOOD_GROUPS,
|
|
27997
|
+
COMPOSE_SCALES,
|
|
27998
|
+
COMPOSE_SCALE_IDS,
|
|
26918
27999
|
CORPUS_BANDS,
|
|
26919
28000
|
CORPUS_SIZE,
|
|
26920
28001
|
DAW_CSS,
|
|
@@ -26934,7 +28015,11 @@ export {
|
|
|
26934
28015
|
FADE_IN_MARK,
|
|
26935
28016
|
FADE_OUT_MARK,
|
|
26936
28017
|
GLOBAL_STORAGE_KEYS,
|
|
28018
|
+
GM_BRIGHT_CEILING,
|
|
26937
28019
|
GM_INSTRUMENT_NAMES,
|
|
28020
|
+
GM_INSTRUMENT_RANGE,
|
|
28021
|
+
HARMONIC_MINOR_SCALE,
|
|
28022
|
+
HUNGARIAN_SCALE,
|
|
26938
28023
|
INSTRUMENT_PRESETS,
|
|
26939
28024
|
KEY_COUNT,
|
|
26940
28025
|
KOE_BASE_URL,
|
|
@@ -26944,6 +28029,7 @@ export {
|
|
|
26944
28029
|
LinkedList,
|
|
26945
28030
|
MACRO_STORAGE_KEYS,
|
|
26946
28031
|
MAJOR_KEY_IDS,
|
|
28032
|
+
MAJOR_SCALE2 as MAJOR_SCALE,
|
|
26947
28033
|
MAX_VOCAL_VOLUME,
|
|
26948
28034
|
MICRO_STEP,
|
|
26949
28035
|
MINOR_KEY_IDS,
|
|
@@ -27012,10 +28098,12 @@ export {
|
|
|
27012
28098
|
featureVector,
|
|
27013
28099
|
fifthToStep,
|
|
27014
28100
|
fifthToUnits,
|
|
28101
|
+
fitInstrumentOctave,
|
|
27015
28102
|
formatMmlMeta,
|
|
27016
28103
|
freqFromPitch,
|
|
27017
28104
|
generateRandomPattern,
|
|
27018
28105
|
getComposeKeyDescription,
|
|
28106
|
+
getComposeScaleDescription,
|
|
27019
28107
|
getDrumPatternKeys,
|
|
27020
28108
|
getMidiBPM,
|
|
27021
28109
|
icon,
|
|
@@ -27051,9 +28139,13 @@ export {
|
|
|
27051
28139
|
readGlobalSetting,
|
|
27052
28140
|
readMacroSections,
|
|
27053
28141
|
readMacroSetting,
|
|
28142
|
+
resolveCenter,
|
|
27054
28143
|
resolveComposeKey,
|
|
28144
|
+
resolveComposeScale,
|
|
27055
28145
|
resolveDrumPattern,
|
|
27056
28146
|
resolveLoopPoint,
|
|
28147
|
+
scaleDegrees,
|
|
28148
|
+
scaleSize,
|
|
27057
28149
|
semitonesToUnits,
|
|
27058
28150
|
shiftNotes,
|
|
27059
28151
|
showLoadingOverlay,
|