@onjmin/dtm 2.1.4 → 2.1.6
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 +127 -9
- package/dist/index.d.ts +127 -9
- package/dist/index.js +793 -137
- package/dist/index.mjs +782 -136
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -4728,6 +4728,7 @@ var createSequencer = (options) => {
|
|
|
4728
4728
|
let drumCursor = 0;
|
|
4729
4729
|
let lastDrumStep = Number.NEGATIVE_INFINITY;
|
|
4730
4730
|
let lastPlayStep = 0;
|
|
4731
|
+
let maxTimelineEndSec = 0;
|
|
4731
4732
|
const secondsPerStep = () => 60 / options.getBpm() / STEPS_PER_BEAT;
|
|
4732
4733
|
const getWrappedPlayStep = (time, sps) => {
|
|
4733
4734
|
if (!isLooping || loopDurationSec <= 0 || time < loopEndSec) {
|
|
@@ -4754,6 +4755,7 @@ var createSequencer = (options) => {
|
|
|
4754
4755
|
}
|
|
4755
4756
|
const startLimit = isLooping ? Math.min(fromStep, loopStartStep) : fromStep;
|
|
4756
4757
|
let maxEndStep = 0;
|
|
4758
|
+
maxTimelineEndSec = 0;
|
|
4757
4759
|
for (const track of options.getTracks()) {
|
|
4758
4760
|
trackVolumeMap.set(track.id, track.volume);
|
|
4759
4761
|
for (const note of track.notes) {
|
|
@@ -4762,6 +4764,7 @@ var createSequencer = (options) => {
|
|
|
4762
4764
|
const when = relativeStart * sps;
|
|
4763
4765
|
const duration = note.durationSteps * sps;
|
|
4764
4766
|
maxEndStep = Math.max(maxEndStep, note.startStep + note.durationSteps);
|
|
4767
|
+
maxTimelineEndSec = Math.max(maxTimelineEndSec, when + duration);
|
|
4765
4768
|
timeline.push({
|
|
4766
4769
|
trackId: track.id,
|
|
4767
4770
|
pitch: note.pitchUnits,
|
|
@@ -4887,10 +4890,7 @@ var createSequencer = (options) => {
|
|
|
4887
4890
|
lastPlayStep = currentStep2;
|
|
4888
4891
|
}
|
|
4889
4892
|
if (!isLooping) {
|
|
4890
|
-
|
|
4891
|
-
const lastWhen = last?.when ?? 0;
|
|
4892
|
-
const lastDuration = last?.duration ?? 0;
|
|
4893
|
-
if (nowIndex >= timeline.length && time > lastWhen + lastDuration + 0.1) {
|
|
4893
|
+
if (nowIndex >= timeline.length && time > maxTimelineEndSec + 0.1) {
|
|
4894
4894
|
stop();
|
|
4895
4895
|
options.onEnd(false);
|
|
4896
4896
|
}
|
|
@@ -8222,6 +8222,21 @@ var DAW_CSS = `
|
|
|
8222
8222
|
.dtm-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
|
|
8223
8223
|
.dtm-track-body { display: flex; flex-direction: column; gap: 10px; }
|
|
8224
8224
|
|
|
8225
|
+
/* \u2500\u2500\u2500 \u81EA\u52D5\u4F5C\u66F2\u30B3\u30F3\u30C6\u30CA\uFF08\u30DE\u30AF\u30ED\u30D1\u30CD\u30EB\u5185\u306E\u5C02\u7528\u30AB\u30FC\u30C9\u98A8\u30B0\u30EB\u30FC\u30D7\u67A0\uFF09 \u2500\u2500\u2500 */
|
|
8226
|
+
.dtm-compose-container {
|
|
8227
|
+
background: var(--dtm-deep);
|
|
8228
|
+
border: 2px solid var(--c-black);
|
|
8229
|
+
box-shadow:
|
|
8230
|
+
inset 0 0 0 1px var(--dtm-border2),
|
|
8231
|
+
0 0 0 1px var(--dtm-success),
|
|
8232
|
+
3px 3px 0 var(--c-black);
|
|
8233
|
+
padding: 10px 12px 12px;
|
|
8234
|
+
display: flex;
|
|
8235
|
+
flex-direction: column;
|
|
8236
|
+
gap: 10px;
|
|
8237
|
+
margin-bottom: 6px;
|
|
8238
|
+
}
|
|
8239
|
+
|
|
8225
8240
|
/* \u2500\u2500\u2500 \u30A2\u30AF\u30C6\u30A3\u30D6\u30C8\u30E9\u30C3\u30AF\u8272\uFF08\u500B\u5225\u30C8\u30E9\u30C3\u30AF\u8A2D\u5B9A\u30D1\u30CD\u30EB\u306E\u5DE6\u7AEF\u30E9\u30A4\u30F3\uFF09 \u2500\u2500\u2500 */
|
|
8226
8241
|
.dtm-panel--track > summary::before,
|
|
8227
8242
|
.dtm-panel--track[open] > summary::before {
|
|
@@ -13016,11 +13031,25 @@ var densityFeatures = (notes, opts) => {
|
|
|
13016
13031
|
shortNoteRatio: short / notes.length
|
|
13017
13032
|
};
|
|
13018
13033
|
};
|
|
13019
|
-
var tensionFeatures = (barTension) => {
|
|
13020
|
-
if (barTension.length <
|
|
13034
|
+
var tensionFeatures = (barTension, opts) => {
|
|
13035
|
+
if (barTension.length < 8) return { rise: 0, resolve: 0 };
|
|
13021
13036
|
const mean2 = (xs) => xs.reduce((a2, b2) => a2 + b2, 0) / Math.max(1, xs.length);
|
|
13022
|
-
|
|
13023
|
-
|
|
13037
|
+
let a;
|
|
13038
|
+
let b;
|
|
13039
|
+
if (opts?.verseBars && opts?.chorusBars && opts.verseBars.length > 0 && opts.chorusBars.length > 0) {
|
|
13040
|
+
a = mean2(opts.verseBars.map((i2) => barTension[i2] ?? 0));
|
|
13041
|
+
b = mean2(opts.chorusBars.map((i2) => barTension[i2] ?? 0));
|
|
13042
|
+
} else if (barTension.length >= 16 && barTension.length <= 24) {
|
|
13043
|
+
a = mean2(barTension.slice(0, 4));
|
|
13044
|
+
b = mean2(barTension.slice(8, 12));
|
|
13045
|
+
} else {
|
|
13046
|
+
const q1Start = Math.floor(barTension.length * 0.15);
|
|
13047
|
+
const q1End = Math.max(q1Start + 2, Math.floor(barTension.length * 0.35));
|
|
13048
|
+
const q3Start = Math.floor(barTension.length * 0.55);
|
|
13049
|
+
const q3End = Math.max(q3Start + 2, Math.floor(barTension.length * 0.75));
|
|
13050
|
+
a = mean2(barTension.slice(q1Start, q1End));
|
|
13051
|
+
b = mean2(barTension.slice(q3Start, q3End));
|
|
13052
|
+
}
|
|
13024
13053
|
const all = mean2(barTension);
|
|
13025
13054
|
const last = barTension[barTension.length - 1];
|
|
13026
13055
|
const rise = Math.max(0, Math.min(1, (b - a) / 0.5));
|
|
@@ -13067,6 +13096,8 @@ var SECTION_LABELS = {
|
|
|
13067
13096
|
verse: "A\u30E1\u30ED",
|
|
13068
13097
|
prechorus: "B\u30E1\u30ED",
|
|
13069
13098
|
chorus: "\u30B5\u30D3",
|
|
13099
|
+
bridge: "C\u30E1\u30ED",
|
|
13100
|
+
drop_chorus: "\u843D\u3061\u30B5\u30D3",
|
|
13070
13101
|
interlude: "\u9593\u594F",
|
|
13071
13102
|
outro: "\u30A2\u30A6\u30C8\u30ED"
|
|
13072
13103
|
};
|
|
@@ -13075,6 +13106,8 @@ var SECTION_ORDER = [
|
|
|
13075
13106
|
"verse",
|
|
13076
13107
|
"prechorus",
|
|
13077
13108
|
"chorus",
|
|
13109
|
+
"bridge",
|
|
13110
|
+
"drop_chorus",
|
|
13078
13111
|
"interlude",
|
|
13079
13112
|
"outro"
|
|
13080
13113
|
];
|
|
@@ -13126,6 +13159,35 @@ var SECTION_SPECS = {
|
|
|
13126
13159
|
// 主音へ全終止
|
|
13127
13160
|
progression: "b"
|
|
13128
13161
|
},
|
|
13162
|
+
// Cメロ。Verse/Pre chorusとは違うメロディで、ラストのサビ前に緊張感を持たせる。
|
|
13163
|
+
// 2番のサビの後に来ることが多い(参考: ONLIVE Studio blog)。
|
|
13164
|
+
// 専用のコード進行 "c" を持ち、AメロともBメロとも雰囲気が違う。
|
|
13165
|
+
bridge: {
|
|
13166
|
+
bars: 4,
|
|
13167
|
+
melody: true,
|
|
13168
|
+
registerShift: 2,
|
|
13169
|
+
density: 0.9,
|
|
13170
|
+
drumLevel: 1,
|
|
13171
|
+
landing: 1,
|
|
13172
|
+
// 解決しない音で止めてラスサビへ渡す
|
|
13173
|
+
progression: "c"
|
|
13174
|
+
},
|
|
13175
|
+
// 落ちサビ。サビのメロディを伴奏控えめに歌う。J-POPの王道パターン。
|
|
13176
|
+
// density と drumLevel だけ下げ、メロディはサビと同じものを使う。
|
|
13177
|
+
drop_chorus: {
|
|
13178
|
+
bars: 4,
|
|
13179
|
+
melody: true,
|
|
13180
|
+
registerShift: 4,
|
|
13181
|
+
// サビと同じ高さ
|
|
13182
|
+
density: 0.6,
|
|
13183
|
+
// 薄い(ここが「落ち」の実体)
|
|
13184
|
+
drumLevel: 0,
|
|
13185
|
+
// ドラム控えめ
|
|
13186
|
+
landing: 0,
|
|
13187
|
+
// 主音へ全終止
|
|
13188
|
+
progression: "b"
|
|
13189
|
+
// サビと同じ進行
|
|
13190
|
+
},
|
|
13129
13191
|
interlude: {
|
|
13130
13192
|
bars: 4,
|
|
13131
13193
|
melody: false,
|
|
@@ -13145,18 +13207,120 @@ var SECTION_SPECS = {
|
|
|
13145
13207
|
progression: "a"
|
|
13146
13208
|
}
|
|
13147
13209
|
};
|
|
13148
|
-
var
|
|
13149
|
-
|
|
13150
|
-
|
|
13210
|
+
var STRUCTURE_TEMPLATES = [
|
|
13211
|
+
// 1コーラス(現行デフォルト、短い曲・初心者向け)
|
|
13212
|
+
{
|
|
13213
|
+
name: "1chorus",
|
|
13214
|
+
label: "1\u30B3\u30FC\u30E9\u30B9",
|
|
13215
|
+
plan: ["intro", "verse", "prechorus", "chorus"]
|
|
13216
|
+
},
|
|
13217
|
+
// JPOP王道(マリーゴールド型)
|
|
13218
|
+
// イントロ→Aメロ→Aメロ→Bメロ→サビ→Aメロ→Bメロ→サビ→Cメロ→間奏→サビ→アウトロ
|
|
13219
|
+
{
|
|
13220
|
+
name: "jpop_standard",
|
|
13221
|
+
label: "JPOP\u738B\u9053",
|
|
13222
|
+
plan: [
|
|
13223
|
+
"intro",
|
|
13224
|
+
"verse",
|
|
13225
|
+
"verse",
|
|
13226
|
+
"prechorus",
|
|
13227
|
+
"chorus",
|
|
13228
|
+
"verse",
|
|
13229
|
+
"prechorus",
|
|
13230
|
+
"chorus",
|
|
13231
|
+
"bridge",
|
|
13232
|
+
"interlude",
|
|
13233
|
+
"chorus",
|
|
13234
|
+
"outro"
|
|
13235
|
+
]
|
|
13236
|
+
},
|
|
13237
|
+
// 落ちサビ入り(J-POP王道の変形。ラスサビ前に落ちサビ)
|
|
13238
|
+
{
|
|
13239
|
+
name: "jpop_drop",
|
|
13240
|
+
label: "\u843D\u3061\u30B5\u30D3\u5165\u308A",
|
|
13241
|
+
plan: [
|
|
13242
|
+
"intro",
|
|
13243
|
+
"verse",
|
|
13244
|
+
"verse",
|
|
13245
|
+
"prechorus",
|
|
13246
|
+
"chorus",
|
|
13247
|
+
"verse",
|
|
13248
|
+
"prechorus",
|
|
13249
|
+
"chorus",
|
|
13250
|
+
"bridge",
|
|
13251
|
+
"drop_chorus",
|
|
13252
|
+
"chorus",
|
|
13253
|
+
"outro"
|
|
13254
|
+
]
|
|
13255
|
+
},
|
|
13256
|
+
// ボカロ王道(短め高速、Aメロ繰り返しなし)
|
|
13257
|
+
{
|
|
13258
|
+
name: "vocaloid",
|
|
13259
|
+
label: "\u30DC\u30AB\u30ED\u738B\u9053",
|
|
13260
|
+
plan: [
|
|
13261
|
+
"intro",
|
|
13262
|
+
"verse",
|
|
13263
|
+
"prechorus",
|
|
13264
|
+
"chorus",
|
|
13265
|
+
"verse",
|
|
13266
|
+
"prechorus",
|
|
13267
|
+
"chorus",
|
|
13268
|
+
"bridge",
|
|
13269
|
+
"chorus",
|
|
13270
|
+
"outro"
|
|
13271
|
+
]
|
|
13272
|
+
},
|
|
13273
|
+
// Verse-Chorus形式(Bメロなし、洋楽的)
|
|
13274
|
+
{
|
|
13275
|
+
name: "verse_chorus",
|
|
13276
|
+
label: "Verse-Chorus",
|
|
13277
|
+
plan: [
|
|
13278
|
+
"intro",
|
|
13279
|
+
"verse",
|
|
13280
|
+
"chorus",
|
|
13281
|
+
"verse",
|
|
13282
|
+
"chorus",
|
|
13283
|
+
"bridge",
|
|
13284
|
+
"chorus",
|
|
13285
|
+
"outro"
|
|
13286
|
+
]
|
|
13287
|
+
}
|
|
13288
|
+
];
|
|
13289
|
+
var buildSectionPlan = (kinds, templateName) => {
|
|
13290
|
+
let ordered;
|
|
13291
|
+
if (templateName) {
|
|
13292
|
+
const tmpl = STRUCTURE_TEMPLATES.find((t) => t.name === templateName);
|
|
13293
|
+
ordered = tmpl ? tmpl.plan : DEFAULT_SECTIONS;
|
|
13294
|
+
} else {
|
|
13295
|
+
const wanted = kinds.length > 0 ? kinds : DEFAULT_SECTIONS;
|
|
13296
|
+
ordered = SECTION_ORDER.filter((k) => wanted.includes(k));
|
|
13297
|
+
}
|
|
13151
13298
|
const plan = [];
|
|
13152
13299
|
let bar = 0;
|
|
13300
|
+
const seen = /* @__PURE__ */ new Map();
|
|
13153
13301
|
for (const kind of ordered) {
|
|
13154
13302
|
const spec = SECTION_SPECS[kind];
|
|
13155
|
-
|
|
13303
|
+
const count = seen.get(kind) ?? 0;
|
|
13304
|
+
plan.push({
|
|
13305
|
+
kind,
|
|
13306
|
+
startBar: bar,
|
|
13307
|
+
bars: spec.bars,
|
|
13308
|
+
spec,
|
|
13309
|
+
keyShift: 0,
|
|
13310
|
+
restatement: count > 0
|
|
13311
|
+
});
|
|
13312
|
+
seen.set(kind, count + 1);
|
|
13156
13313
|
bar += spec.bars;
|
|
13157
13314
|
}
|
|
13158
13315
|
return plan;
|
|
13159
13316
|
};
|
|
13317
|
+
var sectionAt = (plan, bar) => {
|
|
13318
|
+
for (const section of plan) {
|
|
13319
|
+
if (bar >= section.startBar && bar < section.startBar + section.bars)
|
|
13320
|
+
return section;
|
|
13321
|
+
}
|
|
13322
|
+
return plan[plan.length - 1];
|
|
13323
|
+
};
|
|
13160
13324
|
|
|
13161
13325
|
// src/compose.ts
|
|
13162
13326
|
var STEP_SEMITONES = 2;
|
|
@@ -13442,6 +13606,16 @@ var SECTION_A_PROGRESSIONS = [
|
|
|
13442
13606
|
["Am", "Dm7", "Bb", "E7"]
|
|
13443
13607
|
// bVI からドミナントへ
|
|
13444
13608
|
];
|
|
13609
|
+
var SECTION_C_PROGRESSIONS = [
|
|
13610
|
+
["Am", "Em", "F", "C"],
|
|
13611
|
+
["Dm7", "Em7", "FM7", "G7"],
|
|
13612
|
+
["Am7", "Dm7", "G7", "CM7"],
|
|
13613
|
+
["F", "G", "Am", "G"],
|
|
13614
|
+
["Dm7", "G7", "Em7", "Am"],
|
|
13615
|
+
["FM7", "Em7", "Am7", "Dm7"],
|
|
13616
|
+
["Am", "G", "FM7", "E7"],
|
|
13617
|
+
["C", "Am", "FM7", "G7"]
|
|
13618
|
+
];
|
|
13445
13619
|
var SECTION_B_PROGRESSIONS = [
|
|
13446
13620
|
["F", "G", "Em7", "Am"],
|
|
13447
13621
|
["Dm7", "G7", "CM7", "A7"],
|
|
@@ -13668,10 +13842,9 @@ var HALF_BAR_FIGURES = [
|
|
|
13668
13842
|
[EIGHTH, EIGHTH, EIGHTH, EIGHTH],
|
|
13669
13843
|
// タタタタ
|
|
13670
13844
|
[EIGHTH, EIGHTH, EIGHTH, EIGHTH],
|
|
13671
|
-
[EIGHTH, EIGHTH, EIGHTH, EIGHTH],
|
|
13672
|
-
[EIGHTH, EIGHTH, EIGHTH, EIGHTH],
|
|
13673
13845
|
[QUARTER, EIGHTH, EIGHTH],
|
|
13674
13846
|
// ター・タタ
|
|
13847
|
+
[QUARTER, EIGHTH, EIGHTH],
|
|
13675
13848
|
[EIGHTH, EIGHTH, QUARTER],
|
|
13676
13849
|
// タタ・ター
|
|
13677
13850
|
[DOT_QUARTER, EIGHTH],
|
|
@@ -13679,8 +13852,24 @@ var HALF_BAR_FIGURES = [
|
|
|
13679
13852
|
[DOT_QUARTER, EIGHTH],
|
|
13680
13853
|
[EIGHTH, QUARTER, EIGHTH],
|
|
13681
13854
|
// 頭抜き
|
|
13855
|
+
// 4分音符主体・ロングトーン(J-POPの歌い上げるバラード〜ミドル向け。音数過多を是正)
|
|
13856
|
+
[QUARTER, QUARTER],
|
|
13857
|
+
// ター・ター
|
|
13858
|
+
[QUARTER, QUARTER],
|
|
13859
|
+
[HALF],
|
|
13860
|
+
// ターーー
|
|
13682
13861
|
[HALF],
|
|
13683
|
-
|
|
13862
|
+
[-QUARTER, QUARTER],
|
|
13863
|
+
// 休・ター
|
|
13864
|
+
[QUARTER, -QUARTER],
|
|
13865
|
+
// ター・休
|
|
13866
|
+
// 弱起(アウフタクト)パターン:末尾から次へ飛び込む言い回し
|
|
13867
|
+
[-DOT_QUARTER, EIGHTH],
|
|
13868
|
+
// 3拍半休みからの裏拍アウフタクト
|
|
13869
|
+
[-QUARTER, EIGHTH, EIGHTH],
|
|
13870
|
+
// 2拍目裏からのアウフタクト(タタ)
|
|
13871
|
+
[QUARTER, -EIGHTH, EIGHTH],
|
|
13872
|
+
// ター・休タ(8分裏弱起)
|
|
13684
13873
|
// 付点8分+16分(タッカ)。歌モノで非常に多用される跳ね・推進力の型。
|
|
13685
13874
|
[DOT_EIGHTH, SIXTEENTH, EIGHTH, EIGHTH],
|
|
13686
13875
|
[EIGHTH, EIGHTH, DOT_EIGHTH, SIXTEENTH],
|
|
@@ -14349,7 +14538,10 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14349
14538
|
};
|
|
14350
14539
|
const quarterSteps = scaleStep(QUARTER);
|
|
14351
14540
|
const strongStep = Math.max(1, Math.round(stepsPerBar / 2));
|
|
14352
|
-
const sectionPlan = buildSectionPlan(
|
|
14541
|
+
const sectionPlan = buildSectionPlan(
|
|
14542
|
+
options.sections ?? DEFAULT_SECTIONS,
|
|
14543
|
+
options.template
|
|
14544
|
+
);
|
|
14353
14545
|
const totalBars = sectionPlan.reduce((sum, s) => sum + s.bars, 0);
|
|
14354
14546
|
if (rnd() < 0.35) {
|
|
14355
14547
|
const modType = pick(
|
|
@@ -14386,12 +14578,18 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14386
14578
|
(p) => p.join("|") !== progA.join("|")
|
|
14387
14579
|
);
|
|
14388
14580
|
const progB = pick(progBPool, rnd);
|
|
14581
|
+
const progC = pick(
|
|
14582
|
+
SECTION_C_PROGRESSIONS.filter(
|
|
14583
|
+
(p) => p.join("|") !== progA.join("|") && p.join("|") !== progB.join("|")
|
|
14584
|
+
),
|
|
14585
|
+
rnd
|
|
14586
|
+
);
|
|
14389
14587
|
const tonic = progA[0].startsWith("Am") ? "Am" : "C";
|
|
14390
14588
|
const progHalf = pick(SECTION_A2_DERIVATIONS, rnd)(progA);
|
|
14391
14589
|
const progFull = pick(SECTION_A3_DERIVATIONS, rnd)(progA, tonic);
|
|
14392
14590
|
const progression = [];
|
|
14393
14591
|
for (const section of sectionPlan) {
|
|
14394
|
-
const base = section.spec.progression === "b" ? progB : progA;
|
|
14592
|
+
const base = section.spec.progression === "c" ? progC : section.spec.progression === "b" ? progB : progA;
|
|
14395
14593
|
for (let i2 = 0; i2 < section.bars; i2 += 4) {
|
|
14396
14594
|
const isLastPhrase = i2 + 4 >= section.bars;
|
|
14397
14595
|
if (!isLastPhrase) {
|
|
@@ -14409,7 +14607,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14409
14607
|
const chordPattern = pick(CHORD_PATTERNS, rnd);
|
|
14410
14608
|
const rootShift = resolvedKey.rootShift;
|
|
14411
14609
|
const bpm = pick(BPM_CHOICES, rnd);
|
|
14412
|
-
const sourceOf = (kind) => kind === "chorus" || kind === "interlude" ? "b" : kind === "prechorus" ? "a2" : "a";
|
|
14610
|
+
const sourceOf = (kind) => kind === "chorus" || kind === "interlude" || kind === "drop_chorus" ? "b" : kind === "prechorus" ? "a2" : kind === "bridge" ? "c" : "a";
|
|
14413
14611
|
const units2 = [];
|
|
14414
14612
|
for (const section of sectionPlan) {
|
|
14415
14613
|
const unitCount = Math.max(1, Math.round(section.bars / 2));
|
|
@@ -14446,6 +14644,19 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14446
14644
|
const barInUnit = (bar) => bar % 2;
|
|
14447
14645
|
const unitOf = (bar) => Math.floor(bar / 2);
|
|
14448
14646
|
const restatementOf = (bar) => {
|
|
14647
|
+
const curSec = sectionAt(sectionPlan, bar);
|
|
14648
|
+
if (!curSec.spec.melody) return null;
|
|
14649
|
+
if (curSec.restatement) {
|
|
14650
|
+
const firstSec = sectionPlan.find(
|
|
14651
|
+
(s) => s.kind === curSec.kind && !s.restatement
|
|
14652
|
+
);
|
|
14653
|
+
if (firstSec) {
|
|
14654
|
+
const offset = bar - curSec.startBar;
|
|
14655
|
+
if (offset < firstSec.bars) {
|
|
14656
|
+
return firstSec.startBar + offset;
|
|
14657
|
+
}
|
|
14658
|
+
}
|
|
14659
|
+
}
|
|
14449
14660
|
const u = unitOf(bar);
|
|
14450
14661
|
if (units2[u].source === "silent") return null;
|
|
14451
14662
|
for (let v = 0; v < u; v++) {
|
|
@@ -14475,10 +14686,9 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14475
14686
|
),
|
|
14476
14687
|
// 人間の曲の跳躍率は p25〜p75 で 0.40〜0.55。上限が低いとその帯へ届かない。
|
|
14477
14688
|
leapAffinity: 0.08 + rnd() * 0.3,
|
|
14478
|
-
//
|
|
14479
|
-
|
|
14480
|
-
|
|
14481
|
-
barHeadWeight: rnd() < 0.65 ? 3 : 2,
|
|
14689
|
+
// 界隈曲らしさ:調の外の音(クロマチック)や微小な逸脱を積極的に許容する。
|
|
14690
|
+
chromaticAffinity: rnd() < 0.1 ? 0 : 0.3 + rnd() * 0.6,
|
|
14691
|
+
barHeadWeight: rnd() < 0.5 ? 3 : 2,
|
|
14482
14692
|
bassStyle: pick(
|
|
14483
14693
|
[
|
|
14484
14694
|
"quarter",
|
|
@@ -14504,7 +14714,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14504
14714
|
subInterval: pick([3, 4, 8, 9], rnd)
|
|
14505
14715
|
};
|
|
14506
14716
|
const motifPool = groovyCells(MOTIF_CELLS, style.groove, rnd);
|
|
14507
|
-
const targetNotesPerBar =
|
|
14717
|
+
const targetNotesPerBar = 4 + rnd() * 4;
|
|
14508
14718
|
const targetRestRatio = 0.02 + rnd() * 0.1;
|
|
14509
14719
|
const cellNotes = (c) => c.value.filter((v) => v > 0).length;
|
|
14510
14720
|
const cellRest = (c) => {
|
|
@@ -14516,27 +14726,49 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14516
14726
|
}
|
|
14517
14727
|
return total === 0 ? 0 : rest / total;
|
|
14518
14728
|
};
|
|
14519
|
-
const cellDistance = (c) => Math.abs(cellNotes(c) - targetNotesPerBar) + Math.abs(cellRest(c) - targetRestRatio) * 8;
|
|
14520
|
-
const pickCell = (pool) => {
|
|
14729
|
+
const cellDistance = (c, densityMul = 1) => Math.abs(cellNotes(c) - targetNotesPerBar * densityMul) + Math.abs(cellRest(c) - targetRestRatio / Math.max(0.5, densityMul)) * 8;
|
|
14730
|
+
const pickCell = (pool, densityMul = 1) => {
|
|
14521
14731
|
let best = pick(pool, rnd);
|
|
14522
14732
|
for (let i2 = 0; i2 < 2; i2++) {
|
|
14523
14733
|
const c = pick(pool, rnd);
|
|
14524
|
-
if (cellDistance(c) < cellDistance(best))
|
|
14734
|
+
if (cellDistance(c, densityMul) < cellDistance(best, densityMul))
|
|
14735
|
+
best = c;
|
|
14525
14736
|
}
|
|
14526
14737
|
return best;
|
|
14527
14738
|
};
|
|
14528
|
-
const motifCell = pickCell(motifPool);
|
|
14529
|
-
const motifCell2 = rnd() < 0.45 ? motifCell : pickCell(
|
|
14739
|
+
const motifCell = pickCell(motifPool, 0.85);
|
|
14740
|
+
const motifCell2 = rnd() < 0.45 ? motifCell : pickCell(
|
|
14741
|
+
motifPool.filter((c) => c !== motifCell),
|
|
14742
|
+
0.85
|
|
14743
|
+
);
|
|
14530
14744
|
const motifB = pickCell(
|
|
14531
|
-
motifPool.filter((c) => c !== motifCell && c !== motifCell2)
|
|
14745
|
+
motifPool.filter((c) => c !== motifCell && c !== motifCell2),
|
|
14746
|
+
1.2
|
|
14747
|
+
);
|
|
14748
|
+
const motifB2 = pickCell(
|
|
14749
|
+
motifPool.filter((c) => c !== motifB),
|
|
14750
|
+
1.2
|
|
14532
14751
|
);
|
|
14533
|
-
const motifB2 = pickCell(motifPool.filter((c) => c !== motifB));
|
|
14534
14752
|
const motifA2 = pickCell(
|
|
14535
14753
|
motifPool.filter(
|
|
14536
14754
|
(c) => c !== motifCell && c !== motifCell2 && c !== motifB
|
|
14537
|
-
)
|
|
14755
|
+
),
|
|
14756
|
+
1.1
|
|
14757
|
+
);
|
|
14758
|
+
const motifA22 = rnd() < 0.45 ? motifA2 : pickCell(
|
|
14759
|
+
motifPool.filter((c) => c !== motifA2),
|
|
14760
|
+
1.1
|
|
14761
|
+
);
|
|
14762
|
+
const motifC = pickCell(
|
|
14763
|
+
motifPool.filter(
|
|
14764
|
+
(c) => c !== motifCell && c !== motifCell2 && c !== motifB && c !== motifA2
|
|
14765
|
+
),
|
|
14766
|
+
0.9
|
|
14767
|
+
);
|
|
14768
|
+
const motifC2 = rnd() < 0.45 ? motifC : pickCell(
|
|
14769
|
+
motifPool.filter((c) => c !== motifC),
|
|
14770
|
+
0.9
|
|
14538
14771
|
);
|
|
14539
|
-
const motifA22 = rnd() < 0.45 ? motifA2 : pickCell(motifPool.filter((c) => c !== motifA2));
|
|
14540
14772
|
const motifVar = pickCell(
|
|
14541
14773
|
motifPool.filter((c) => c !== motifCell && c !== motifCell2)
|
|
14542
14774
|
);
|
|
@@ -14589,12 +14821,13 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14589
14821
|
}
|
|
14590
14822
|
const isB = units2[u].source === "b";
|
|
14591
14823
|
const isA2 = units2[u].source === "a2";
|
|
14824
|
+
const isC = units2[u].source === "c";
|
|
14592
14825
|
const isPrechorusEnd = units2[u].section.kind === "prechorus" && bar === units2[u].section.startBar + units2[u].section.bars - 1;
|
|
14593
14826
|
if (isPrechorusEnd) {
|
|
14594
14827
|
barRhythms.push(scaleCell(buildUpCell.value));
|
|
14595
14828
|
continue;
|
|
14596
14829
|
}
|
|
14597
|
-
const pair = () => isB ? [motifB, motifB2] : isA2 ? [motifA2, motifA22] : [motifCell, motifCell2];
|
|
14830
|
+
const pair = () => isB ? [motifB, motifB2] : isA2 ? [motifA2, motifA22] : isC ? [motifC, motifC2] : [motifCell, motifCell2];
|
|
14598
14831
|
let cell;
|
|
14599
14832
|
if (units2[u].source === "answer") {
|
|
14600
14833
|
const isPeriodEnd = units2[u].landing !== null;
|
|
@@ -14625,6 +14858,8 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14625
14858
|
const melody = [];
|
|
14626
14859
|
const submelody = [];
|
|
14627
14860
|
const bass = [];
|
|
14861
|
+
const harmony = [];
|
|
14862
|
+
const pad = [];
|
|
14628
14863
|
const melodyDurations = [];
|
|
14629
14864
|
const barTension = new Array(totalBars).fill(0);
|
|
14630
14865
|
let restSteps = 0;
|
|
@@ -14671,13 +14906,22 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14671
14906
|
(bar + style.arcPhase) / style.arcPeriod * Math.PI * 2
|
|
14672
14907
|
);
|
|
14673
14908
|
const arcCenter = MELODY_CENTER + arc * style.arcAmp;
|
|
14674
|
-
const
|
|
14675
|
-
|
|
14676
|
-
|
|
14677
|
-
tones,
|
|
14678
|
-
|
|
14679
|
-
|
|
14680
|
-
|
|
14909
|
+
const inUnit = barInUnit(bar);
|
|
14910
|
+
let headSemi;
|
|
14911
|
+
if (inUnit === 1 && bar > 0) {
|
|
14912
|
+
headSemi = nearestChordTone(prevSemi, tones, headWeight, isSectionB).semi;
|
|
14913
|
+
if (Math.abs(headSemi - prevSemi) > 4) {
|
|
14914
|
+
headSemi = nearestChordTone(prevSemi, tones, 1, isSectionB).semi;
|
|
14915
|
+
}
|
|
14916
|
+
} else {
|
|
14917
|
+
const headTarget = prevSemi + (arcCenter - prevSemi) * 0.5;
|
|
14918
|
+
headSemi = nearestChordTone(
|
|
14919
|
+
headTarget,
|
|
14920
|
+
tones,
|
|
14921
|
+
headWeight,
|
|
14922
|
+
isSectionB
|
|
14923
|
+
).semi;
|
|
14924
|
+
}
|
|
14681
14925
|
const contourOffset = barInUnit(bar) === 0 ? 0 : barRhythms[bar - 1].filter((v) => v > 0).length;
|
|
14682
14926
|
const prevRole = bar > 0 ? barRoles[bar - 1] : null;
|
|
14683
14927
|
const repeatShift = role === "motif" && (prevRole === "motif" || prevRole === "sequence" || prevRole === "climax") ? pick([-2, -1, 1, 2], rnd) : 0;
|
|
@@ -14857,6 +15101,48 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14857
15101
|
} else {
|
|
14858
15102
|
pushSub(scaleStep(QUARTER), scaleStep(DOT_HALF), subSemi);
|
|
14859
15103
|
}
|
|
15104
|
+
const barSec = sectionAt(sectionPlan, bar);
|
|
15105
|
+
if (!silent && (barSec.kind === "chorus" || barSec.kind === "drop_chorus")) {
|
|
15106
|
+
for (let i2 = 0; i2 < slots.length; i2++) {
|
|
15107
|
+
const hSemi = pitches[i2] + 3;
|
|
15108
|
+
const hTone = nearestChordTone(hSemi, tones, 2);
|
|
15109
|
+
const hClamped = clampSemi(hTone.semi, MELODY_LOW, MELODY_HIGH);
|
|
15110
|
+
const k = barKeyShift[bar];
|
|
15111
|
+
const fifthShift = k === 0 ? 0 : SEMITONE_TO_FIFTH_SHIFT[(k % 12 + 12) % 12];
|
|
15112
|
+
harmony.push({
|
|
15113
|
+
startStep: barStart + slots[i2].at,
|
|
15114
|
+
pitchUnits: spelledToUnits(
|
|
15115
|
+
hClamped + k,
|
|
15116
|
+
hTone.fifth + fifthShift,
|
|
15117
|
+
edo
|
|
15118
|
+
),
|
|
15119
|
+
durationSteps: slots[i2].value,
|
|
15120
|
+
velocity: slots[i2].at === 0 ? 82 : 76
|
|
15121
|
+
});
|
|
15122
|
+
}
|
|
15123
|
+
}
|
|
15124
|
+
if (barSec.kind === "prechorus" || barSec.kind === "chorus" || barSec.kind === "bridge" || barSec.kind === "drop_chorus") {
|
|
15125
|
+
const padTone = nearestChordTone(
|
|
15126
|
+
MELODY_HIGH + 2,
|
|
15127
|
+
// メロディの上の音域
|
|
15128
|
+
tones,
|
|
15129
|
+
2
|
|
15130
|
+
);
|
|
15131
|
+
const padSemi = clampSemi(padTone.semi, MELODY_HIGH - 4, MELODY_HIGH + 8);
|
|
15132
|
+
const k = barKeyShift[bar];
|
|
15133
|
+
const fifthShift = k === 0 ? 0 : SEMITONE_TO_FIFTH_SHIFT[(k % 12 + 12) % 12];
|
|
15134
|
+
pad.push({
|
|
15135
|
+
startStep: barStart,
|
|
15136
|
+
pitchUnits: spelledToUnits(
|
|
15137
|
+
padSemi + k,
|
|
15138
|
+
padTone.fifth + fifthShift,
|
|
15139
|
+
edo
|
|
15140
|
+
),
|
|
15141
|
+
durationSteps: stepsPerBar,
|
|
15142
|
+
// 小節全体を伸ばす
|
|
15143
|
+
velocity: barSec.kind === "drop_chorus" ? 50 : 62
|
|
15144
|
+
});
|
|
15145
|
+
}
|
|
14860
15146
|
const rootTone = tones[0];
|
|
14861
15147
|
const fifthTone = tones.find((t) => t.weight === 3 && t !== rootTone);
|
|
14862
15148
|
const thirdTone = tones.find((t) => t.weight === 2);
|
|
@@ -14963,6 +15249,69 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14963
15249
|
}
|
|
14964
15250
|
for (const n of barBass) bass.push(n);
|
|
14965
15251
|
}
|
|
15252
|
+
const eighthSteps = scaleStep(EIGHTH);
|
|
15253
|
+
for (let i2 = 0; i2 < melody.length - 1; i2++) {
|
|
15254
|
+
const cur = melody[i2];
|
|
15255
|
+
const nxt = melody[i2 + 1];
|
|
15256
|
+
const curEnd = cur.startStep + cur.durationSteps;
|
|
15257
|
+
const atBarBoundary = curEnd % stepsPerBar === 0 && nxt.startStep === curEnd;
|
|
15258
|
+
if (!atBarBoundary) continue;
|
|
15259
|
+
if (cur.durationSteps > eighthSteps) continue;
|
|
15260
|
+
const barIdx = Math.floor(curEnd / stepsPerBar);
|
|
15261
|
+
if (barIdx >= totalBars) continue;
|
|
15262
|
+
if (i2 + 1 >= melody.length - 1) continue;
|
|
15263
|
+
const curSec = sectionAt(sectionPlan, barIdx - 1);
|
|
15264
|
+
const nextSec = sectionAt(sectionPlan, barIdx);
|
|
15265
|
+
if (!nextSec.spec.melody || curSec !== nextSec) continue;
|
|
15266
|
+
const curSemi = Math.round(cur.pitchUnits / UNITS_PER_SEMITONE);
|
|
15267
|
+
const nxtSemi = Math.round(nxt.pitchUnits / UNITS_PER_SEMITONE);
|
|
15268
|
+
if (Math.abs(nxtSemi - curSemi) > 3) continue;
|
|
15269
|
+
const nextRole = barRoles[barIdx];
|
|
15270
|
+
let tieProb = 0.4;
|
|
15271
|
+
if (nextRole === "motif") tieProb = 0.05;
|
|
15272
|
+
else if (nextRole === "sequence") tieProb = 0.75;
|
|
15273
|
+
else if (nextRole === "climax") tieProb = 0.9;
|
|
15274
|
+
else if (nextRole === "cadence") tieProb = 0.1;
|
|
15275
|
+
if (rnd() < tieProb) {
|
|
15276
|
+
cur.durationSteps += nxt.durationSteps;
|
|
15277
|
+
melody.splice(i2 + 1, 1);
|
|
15278
|
+
if (i2 < melodyDurations.length - 1) {
|
|
15279
|
+
melodyDurations[i2] += melodyDurations[i2 + 1];
|
|
15280
|
+
melodyDurations.splice(i2 + 1, 1);
|
|
15281
|
+
}
|
|
15282
|
+
const hCurIdx = harmony.findIndex((h) => h.startStep === cur.startStep);
|
|
15283
|
+
const hNxtIdx = harmony.findIndex((h) => h.startStep === nxt.startStep);
|
|
15284
|
+
if (hCurIdx >= 0 && hNxtIdx >= 0) {
|
|
15285
|
+
harmony[hCurIdx].durationSteps += harmony[hNxtIdx].durationSteps;
|
|
15286
|
+
harmony.splice(hNxtIdx, 1);
|
|
15287
|
+
}
|
|
15288
|
+
i2--;
|
|
15289
|
+
}
|
|
15290
|
+
}
|
|
15291
|
+
for (let i2 = 0; i2 < melody.length; i2++) {
|
|
15292
|
+
const barIdx = Math.floor(melody[i2].startStep / stepsPerBar);
|
|
15293
|
+
if (barIdx >= totalBars) continue;
|
|
15294
|
+
const role = barRoles[barIdx];
|
|
15295
|
+
let splitProb = 0.15;
|
|
15296
|
+
if (role === "motif" || role === "sequence") splitProb = 0;
|
|
15297
|
+
else if (role === "climax") splitProb = 0.6;
|
|
15298
|
+
else if (role === "cadence") splitProb = 0;
|
|
15299
|
+
if (rnd() < splitProb && melody[i2].durationSteps === quarterSteps) {
|
|
15300
|
+
const half = scaleStep(EIGHTH);
|
|
15301
|
+
const newNote = {
|
|
15302
|
+
...melody[i2],
|
|
15303
|
+
startStep: melody[i2].startStep + half,
|
|
15304
|
+
durationSteps: half
|
|
15305
|
+
};
|
|
15306
|
+
melody[i2].durationSteps = half;
|
|
15307
|
+
melody.splice(i2 + 1, 0, newNote);
|
|
15308
|
+
if (i2 < melodyDurations.length) {
|
|
15309
|
+
melodyDurations[i2] = half;
|
|
15310
|
+
melodyDurations.splice(i2 + 1, 0, half);
|
|
15311
|
+
}
|
|
15312
|
+
i2++;
|
|
15313
|
+
}
|
|
15314
|
+
}
|
|
14966
15315
|
const range = (notes) => {
|
|
14967
15316
|
if (notes.length === 0) return 0;
|
|
14968
15317
|
const us = notes.map((n) => n.pitchUnits);
|
|
@@ -14970,7 +15319,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14970
15319
|
};
|
|
14971
15320
|
const shiftUnits = semitonesToUnits(rootShift, edo);
|
|
14972
15321
|
if (shiftUnits !== 0)
|
|
14973
|
-
for (const list of [melody, submelody, bass])
|
|
15322
|
+
for (const list of [melody, submelody, bass, harmony, pad])
|
|
14974
15323
|
for (const n of list) n.pitchUnits = n.pitchUnits + shiftUnits;
|
|
14975
15324
|
return {
|
|
14976
15325
|
chordProgression,
|
|
@@ -14985,6 +15334,8 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14985
15334
|
melody,
|
|
14986
15335
|
submelody,
|
|
14987
15336
|
bass,
|
|
15337
|
+
harmony,
|
|
15338
|
+
pad,
|
|
14988
15339
|
melodyDurations,
|
|
14989
15340
|
restSteps,
|
|
14990
15341
|
totalSteps: Math.max(1, sungBars) * stepsPerBar,
|
|
@@ -15020,7 +15371,16 @@ var evaluate = (d, recent) => {
|
|
|
15020
15371
|
fromMelody(toMetricNotes(d.submelody)),
|
|
15021
15372
|
opts
|
|
15022
15373
|
);
|
|
15023
|
-
const
|
|
15374
|
+
const verseBars = [];
|
|
15375
|
+
const chorusBars = [];
|
|
15376
|
+
for (const s of d.sections) {
|
|
15377
|
+
for (let b = s.startBar; b < s.startBar + s.bars; b++) {
|
|
15378
|
+
if (s.kind === "verse") verseBars.push(b);
|
|
15379
|
+
else if (s.kind === "chorus" || s.kind === "drop_chorus")
|
|
15380
|
+
chorusBars.push(b);
|
|
15381
|
+
}
|
|
15382
|
+
}
|
|
15383
|
+
const tension = tensionFeatures(d.barTension, { verseBars, chorusBars });
|
|
15024
15384
|
const density = densityFeatures(melodyFrom, opts);
|
|
15025
15385
|
const fingerprint = featureVector({
|
|
15026
15386
|
entropy,
|
|
@@ -15036,6 +15396,7 @@ var evaluate = (d, recent) => {
|
|
|
15036
15396
|
);
|
|
15037
15397
|
const at = (b, v) => band(v, b[0], b[1], b[2], b[3]);
|
|
15038
15398
|
const atc = (key, v) => centeredBand(v, CORPUS_BANDS[key], CORPUS_MEDIANS[key]);
|
|
15399
|
+
const peakBand = d.bars > 24 ? [0, 1, Math.round(d.bars / 16), Math.round(d.bars / 8) + 2] : HAND_BANDS.climaxPeaks;
|
|
15039
15400
|
const scoreBreakdown = {
|
|
15040
15401
|
entropy: atc("entropy", entropy),
|
|
15041
15402
|
valueKinds: atc("valueKinds", valueKinds),
|
|
@@ -15053,7 +15414,7 @@ var evaluate = (d, recent) => {
|
|
|
15053
15414
|
sim8: atc("sim8", structure.sim8),
|
|
15054
15415
|
phraseBreath: atc("phraseBreath", structure.phraseBreath),
|
|
15055
15416
|
climaxPosition: atc("climaxPosition", structure.climaxPosition),
|
|
15056
|
-
climaxPeaks: at(
|
|
15417
|
+
climaxPeaks: at(peakBand, structure.climaxPeaks),
|
|
15057
15418
|
complementarity: at(HAND_BANDS.complementarity, structure.complementarity),
|
|
15058
15419
|
subDensity: at(HAND_BANDS.subDensity, d.submelody.length / d.bars),
|
|
15059
15420
|
tensionRise: tension.rise,
|
|
@@ -15107,9 +15468,10 @@ var composeSong = (options) => {
|
|
|
15107
15468
|
bestScore = stats.score;
|
|
15108
15469
|
bestIsValid = ok;
|
|
15109
15470
|
best = {
|
|
15110
|
-
//
|
|
15471
|
+
// ドラム・楽器は勝った候補にだけ後から付ける(メロディに依存しないので
|
|
15111
15472
|
// 候補ごとに引いても採点は動かず、40本ぶん無駄になる)。
|
|
15112
15473
|
drum: "",
|
|
15474
|
+
instrument: "",
|
|
15113
15475
|
chordProgression: d.chordProgression,
|
|
15114
15476
|
chordPattern: d.chordPattern,
|
|
15115
15477
|
rootShift: d.rootShift,
|
|
@@ -15122,6 +15484,8 @@ var composeSong = (options) => {
|
|
|
15122
15484
|
melody: d.melody,
|
|
15123
15485
|
submelody: d.submelody,
|
|
15124
15486
|
bass: d.bass,
|
|
15487
|
+
harmony: d.harmony,
|
|
15488
|
+
pad: d.pad,
|
|
15125
15489
|
stats: { ...stats, attempts: attempt, rejected }
|
|
15126
15490
|
};
|
|
15127
15491
|
}
|
|
@@ -15129,6 +15493,7 @@ var composeSong = (options) => {
|
|
|
15129
15493
|
result.stats.attempts = count;
|
|
15130
15494
|
result.stats.rejected = rejected;
|
|
15131
15495
|
result.drum = pickBuiltinDrum(result, rnd);
|
|
15496
|
+
result.instrument = pickBuiltinInstrument(result, rnd);
|
|
15132
15497
|
return result;
|
|
15133
15498
|
};
|
|
15134
15499
|
var pickBuiltinDrum = (song, rnd) => {
|
|
@@ -15137,6 +15502,35 @@ var pickBuiltinDrum = (song, rnd) => {
|
|
|
15137
15502
|
const pool = song.bpm >= 150 ? ["4beat", "dance", "16beat", "disco"] : short >= 0.6 ? ["16beat", "dance", "4beat", "disco"] : song.bpm <= 110 && short < 0.4 ? ["bossa", "8beat"] : ["8beat", "4beat", "16beat"];
|
|
15138
15503
|
return pick(pool, rnd);
|
|
15139
15504
|
};
|
|
15505
|
+
var pickBuiltinInstrument = (song, rnd) => {
|
|
15506
|
+
const eighth = BASE_STEPS_PER_BAR / 8;
|
|
15507
|
+
const short = song.melody.filter((n) => n.durationSteps <= eighth).length / Math.max(1, song.melody.length);
|
|
15508
|
+
if (rnd() < 0.06) {
|
|
15509
|
+
return pick(["japanese_wa", "arabic_exotic"], rnd);
|
|
15510
|
+
}
|
|
15511
|
+
let pool;
|
|
15512
|
+
if (song.drum === "dance" || song.drum === "disco") {
|
|
15513
|
+
pool = song.bpm >= 150 ? ["cyber_punk", "synth_pop", "retro_game"] : ["synth_pop", "retro_game", "rock", "piano"];
|
|
15514
|
+
} else if (song.drum === "bossa") {
|
|
15515
|
+
pool = ["jazz_night", "acoustic", "piano"];
|
|
15516
|
+
} else if (song.bpm <= 105 && short < 0.4) {
|
|
15517
|
+
pool = ["ambient_cloud", "acoustic", "orchestra", "piano", "fantasy_rpg"];
|
|
15518
|
+
} else if (song.bpm >= 145) {
|
|
15519
|
+
pool = ["rock", "synth_pop", "cyber_punk", "retro_game", "piano"];
|
|
15520
|
+
} else if (song.stats.leapRatio >= 0.45) {
|
|
15521
|
+
pool = ["fantasy_rpg", "orchestra", "acoustic", "piano"];
|
|
15522
|
+
} else {
|
|
15523
|
+
pool = [
|
|
15524
|
+
"piano",
|
|
15525
|
+
"acoustic",
|
|
15526
|
+
"synth_pop",
|
|
15527
|
+
"rock",
|
|
15528
|
+
"jazz_night",
|
|
15529
|
+
"fantasy_rpg"
|
|
15530
|
+
];
|
|
15531
|
+
}
|
|
15532
|
+
return pick(pool, rnd);
|
|
15533
|
+
};
|
|
15140
15534
|
var LYRIC_WORDS = [
|
|
15141
15535
|
"\u3042\u3055",
|
|
15142
15536
|
"\u3072\u304B\u308A",
|
|
@@ -15538,74 +15932,89 @@ var buildUI = (target, options) => {
|
|
|
15538
15932
|
<details class="dtm-panel" data-dtm-acc="macro">
|
|
15539
15933
|
<summary>\u30DE\u30AF\u30ED</summary>
|
|
15540
15934
|
<div class="dtm-panel-body">
|
|
15541
|
-
<div class="dtm-
|
|
15542
|
-
<
|
|
15543
|
-
|
|
15544
|
-
|
|
15545
|
-
|
|
15546
|
-
|
|
15547
|
-
|
|
15548
|
-
<
|
|
15549
|
-
|
|
15550
|
-
<
|
|
15551
|
-
|
|
15552
|
-
|
|
15553
|
-
|
|
15554
|
-
|
|
15555
|
-
|
|
15935
|
+
<div class="dtm-compose-container ${showCompose ? "" : "dtm-hidden"}" data-dtm="compose-container">
|
|
15936
|
+
<div class="dtm-row" data-dtm="compose-row">
|
|
15937
|
+
<button class="dtm-btn dtm-btn--success" data-dtm="macro-compose" title="\u30B3\u30FC\u30C9\u9032\u884C\u30FB\u30E1\u30ED\u30C7\u30A3\u30FB\u30B5\u30D6\u30E1\u30ED\u30FB\u30D9\u30FC\u30B9\u30FB\u4F34\u594F\u30FB\u30C9\u30E9\u30E0\u3092\u81EA\u52D5\u3067\u4F5C\u308A\u307E\u3059">\u4F5C\u66F2</button>
|
|
15938
|
+
<button class="dtm-btn dtm-btn--success" data-dtm="macro-compose-vocal" title="\u4F5C\u66F2\u3057\u305F\u3046\u3048\u3067\u3001\u30E1\u30ED\u30C7\u30A3\u306B\u6B4C\u8A5E\u3092\u4ED8\u3051\u3066\u6B4C\u308F\u305B\u307E\u3059">\u6B4C\u5165\u308A\u4F5C\u66F2</button>
|
|
15939
|
+
<button class="dtm-infobtn" data-dtm="macro-compose-info" title="\u4F5C\u66F2\u306E\u89E3\u8AAC">${icon("info", 12)}</button>
|
|
15940
|
+
<span class="dtm-grow"></span>
|
|
15941
|
+
</div>
|
|
15942
|
+
<div class="dtm-row" data-dtm="compose-template-row">
|
|
15943
|
+
<span class="dtm-label">\u69CB\u6210</span>
|
|
15944
|
+
<select class="dtm-select" data-dtm="compose-template" title="J-POP\u738B\u9053\u306A\u3069\u306E\u30D7\u30EA\u30BB\u30C3\u30C8\u69CB\u6210\u3092\u9078\u3073\u307E\u3059">
|
|
15945
|
+
<option value="custom">\u81EA\u7531\u9078\u629E\uFF08\u4E0B\u8A18\u30C1\u30A7\u30C3\u30AF\uFF09</option>
|
|
15946
|
+
<option value="1chorus">1\u30B3\u30FC\u30E9\u30B9\uFF08\u77ED\u3081\u30FB\u521D\u5FC3\u8005\u5411\u3051\uFF09</option>
|
|
15947
|
+
<option value="jpop_standard">JPOP\u738B\u9053\uFF08\u30DE\u30EA\u30FC\u30B4\u30FC\u30EB\u30C9\u578B 2\u756A/C\u30E1\u30ED/\u30E9\u30B9\u30B5\u30D3\uFF09</option>
|
|
15948
|
+
<option value="jpop_drop">\u843D\u3061\u30B5\u30D3\u5165\u308A\uFF08JPOP\u738B\u9053 + \u30E9\u30B9\u30B5\u30D3\u524D\u843D\u3061\u30B5\u30D3\uFF09</option>
|
|
15949
|
+
<option value="vocaloid">\u30DC\u30AB\u30ED\u738B\u9053\uFF08\u75BE\u8D70\u30FB2\u756A/C\u30E1\u30ED/\u30E9\u30B9\u30B5\u30D3\uFF09</option>
|
|
15950
|
+
<option value="verse_chorus">Verse-Chorus\uFF08B\u30E1\u30ED\u306A\u3057\u30FB\u6D0B\u697D\u98A8\uFF09</option>
|
|
15951
|
+
</select>
|
|
15952
|
+
</div>
|
|
15953
|
+
<div class="dtm-row" data-dtm="compose-sections-row">
|
|
15954
|
+
<span class="dtm-label">\u4F5C\u308B\u90E8\u5206</span>
|
|
15955
|
+
<div class="dtm-checks" data-dtm="compose-sections">
|
|
15956
|
+
<label class="dtm-check"><input type="checkbox" value="intro" checked>\u30A4\u30F3\u30C8\u30ED</label>
|
|
15957
|
+
<label class="dtm-check"><input type="checkbox" value="verse" checked>A\u30E1\u30ED</label>
|
|
15958
|
+
<label class="dtm-check"><input type="checkbox" value="prechorus" checked>B\u30E1\u30ED</label>
|
|
15959
|
+
<label class="dtm-check"><input type="checkbox" value="chorus" checked>\u30B5\u30D3</label>
|
|
15960
|
+
<label class="dtm-check"><input type="checkbox" value="bridge">C\u30E1\u30ED</label>
|
|
15961
|
+
<label class="dtm-check"><input type="checkbox" value="drop_chorus">\u843D\u3061\u30B5\u30D3</label>
|
|
15962
|
+
<label class="dtm-check"><input type="checkbox" value="interlude">\u9593\u594F</label>
|
|
15963
|
+
<label class="dtm-check"><input type="checkbox" value="outro">\u30A2\u30A6\u30C8\u30ED</label>
|
|
15964
|
+
</div>
|
|
15965
|
+
<span class="dtm-grow"></span>
|
|
15966
|
+
<span class="dtm-hint" data-dtm="compose-sections-len"></span>
|
|
15967
|
+
</div>
|
|
15968
|
+
<div class="dtm-row" data-dtm="compose-key-row">
|
|
15969
|
+
<span class="dtm-label">\u30D9\u30FC\u30B9\u8ABF</span>
|
|
15970
|
+
<select class="dtm-select" data-dtm="compose-key" title="\u81EA\u52D5\u4F5C\u66F2\u306E\u30D9\u30FC\u30B9\u3068\u306A\u308B\u8ABF\u3084\u96F0\u56F2\u6C17\u3092\u9078\u3073\u307E\u3059">
|
|
15971
|
+
<option value="any" title="\u516824\u8ABF\u304B\u3089\u30E9\u30F3\u30C0\u30E0\u306B\u6C7A\u5B9A\u3057\u307E\u3059">\u5E0C\u671B\u306A\u3057</option>
|
|
15972
|
+
<optgroup label="\u57FA\u672C">
|
|
15973
|
+
<option value="major" title="12\u306E\u9577\u8ABF\u306E\u4E2D\u304B\u3089\u30E9\u30F3\u30C0\u30E0\u306B\u62BD\u9078\u3057\u307E\u3059">\u9577\u8ABF</option>
|
|
15974
|
+
<option value="minor" title="12\u306E\u77ED\u8ABF\u306E\u4E2D\u304B\u3089\u30E9\u30F3\u30C0\u30E0\u306B\u62BD\u9078\u3057\u307E\u3059">\u77ED\u8ABF</option>
|
|
15975
|
+
</optgroup>
|
|
15976
|
+
<optgroup label="\u96F0\u56F2\u6C17\u304B\u3089\u9078\u3076\uFF08\u62BD\u9078\uFF09">
|
|
15977
|
+
<option value="mood_happy" title="\u30CF\u9577\u8ABF\u30FB\u30A4\u9577\u8ABF\u30FB\u5909\u30ED\u9577\u8ABF\u304B\u3089\u62BD\u9078\uFF08\u7121\u57A2\u306B\u559C\u3070\u3057\u3044\u3001\u7267\u6B4C\u7684\u3001\u967D\u6C17\uFF09">\u559C\u3070\u3057\u3044\u30FB\u967D\u6C17\u306A\u66F2</option>
|
|
15978
|
+
<option value="mood_triumphant" title="\u30CB\u9577\u8ABF\u30FB\u5909\u30C8\u9577\u8ABF\u304B\u3089\u62BD\u9078\uFF08\u610F\u6C17\u63DA\u3005\u3001\u52DD\u5229\u306E\u558A\u58F0\u3001\u56F0\u96E3\u6253\u7834\u3001\u5B89\u5835\uFF09">\u52DD\u5229\u30FB\u529B\u5F37\u3044\u66F2</option>
|
|
15979
|
+
<option value="mood_fierce" title="\u30DB\u9577\u8ABF\u30FB\u30D8\u9577\u8ABF\u30FB\u30ED\u9577\u8ABF\u304B\u3089\u62BD\u9078\uFF08\u3051\u3093\u304B\u3063\u65E9\u3044\u3001\u6012\u308A\u72C2\u3063\u305F\u8352\u3005\u3057\u3055\u3001\u3069\u304E\u3064\u304F\u731B\u70C8\uFF09">\u6FC0\u3057\u3044\u30FB\u8352\u3005\u3057\u3044\u66F2</option>
|
|
15980
|
+
<option value="mood_solemn" title="\u30C8\u9577\u8ABF\u30FB\u30CB\u77ED\u8ABF\u30FB\u30A4\u77ED\u8ABF\u304B\u3089\u62BD\u9078\uFF08\u53B3\u7C9B\u3001\u5D07\u9AD8\u3001\u5E7B\u60F3\u3001\u656C\u8654\u3001\u601D\u7D22\u7684\uFF09">\u53B3\u7C9B\u30FB\u5E7B\u60F3\u7684\u306A\u66F2</option>
|
|
15981
|
+
<option value="mood_plaintive" title="\u30CF\u77ED\u8ABF\u30FB\u30DB\u77ED\u8ABF\u30FB\u30D8\u77ED\u8ABF\u304B\u3089\u62BD\u9078\uFF08\u7D14\u7C8B\u306B\u60B2\u3057\u3052\u3001\u604B\u308F\u305A\u3089\u3044\u3001\u843D\u3061\u7740\u304D\u306E\u306A\u3044\u3001\u7269\u60B2\u3057\u3044\u54C0\u6101\uFF09">\u7269\u60B2\u3057\u3044\u30FB\u54C0\u6101\u306E\u66F2</option>
|
|
15982
|
+
<option value="mood_melancholy" title="\u5909\u30CB\u9577\u8ABF\u30FB\u30ED\u77ED\u8ABF\u30FB\u5B30\u30CF\u77ED\u8ABF\u304B\u3089\u62BD\u9078\uFF08\u60B2\u3057\u307F\u3001\u6182\u9B31\u3001\u5B64\u72EC\u3001\u5FCD\u8010\u3001\u843D\u80C6\u3001\u60B2\u6D99\uFF09">\u6182\u9B31\u30FB\u5B64\u72EC\u306A\u66F2</option>
|
|
15983
|
+
<option value="mood_anxious" title="\u30C8\u77ED\u8ABF\u30FB\u5909\u30DB\u77ED\u8ABF\u30FB\u5B30\u30D8\u77ED\u8ABF\u30FB\u5909\u30A4\u77ED\u8ABF\u304B\u3089\u62BD\u9078\uFF08\u4E0D\u6E80\u3001\u4E0D\u5B89\u3001\u6DF1\u3044\u82E6\u60A9\u3001\u9670\u6C17\u306A\u61A4\u308A\uFF09">\u4E0D\u5B89\u30FB\u82E6\u60A9\u306A\u66F2</option>
|
|
15984
|
+
<option value="mood_dark" title="\u5909\u30DB\u9577\u8ABF\u30FB\u5909\u30A4\u9577\u8ABF\u30FB\u5909\u30ED\u77ED\u8ABF\u304B\u3089\u62BD\u9078\uFF08\u53B3\u3057\u3044\u611B\u3001\u6B7B\u3001\u6C38\u9060\u3001\u88C1\u304D\u3001\u6697\u95C7\u3001\u6050\u308D\u3057\u3044\u5632\u308A\uFF09">\u6697\u95C7\u30FB\u91CD\u539A\u306A\u66F2</option>
|
|
15985
|
+
</optgroup>
|
|
15986
|
+
<optgroup label="\u9577\u8ABF\uFF08\u500B\u5225\u6307\u5B9A\uFF09">
|
|
15987
|
+
<option value="key_C" title="\u7121\u57A2\u306B\u559C\u3070\u3057\u3044\u3001\u7D14\u7C8B\u3001\u7D20\u6734\u3001\u51FA\u767A">\u30CF\u9577\u8ABF (C)</option>
|
|
15988
|
+
<option value="key_Db" title="\u60B2\u3057\u307F\u3001\u6182\u9B31\u306A\u3001\u7518\u7F8E\u306A\u611F\u50B7">\u5909\u30CB\u9577\u8ABF (D\u266D)</option>
|
|
15989
|
+
<option value="key_D" title="\u610F\u6C17\u63DA\u3005\u3068\u3057\u305F\u3001\u52DD\u5229\u306E\u3001\u558A\u58F0">\u30CB\u9577\u8ABF (D)</option>
|
|
15990
|
+
<option value="key_Eb" title="\u53B3\u3057\u3044\u3001\u304D\u3064\u3044\u3001\u305D\u308C\u3067\u3044\u3066\u611B\u306B\u6E80\u3061\u305F">\u5909\u30DB\u9577\u8ABF (E\u266D)</option>
|
|
15991
|
+
<option value="key_E" title="\u3051\u3093\u304B\u3063\u65E9\u3044\u3001\u8352\u3005\u3057\u3044\u3001\u8F1D\u304B\u3057\u3044\u60C5\u71B1">\u30DB\u9577\u8ABF (E)</option>
|
|
15992
|
+
<option value="key_F" title="\u6012\u308A\u72C2\u3063\u305F\u3001\u6C17\u6027\u306E\u8352\u3044\u3001\u4E00\u6642\u7684\u306A\u60B2\u5606">\u30D8\u9577\u8ABF (F)</option>
|
|
15993
|
+
<option value="key_Gb" title="\u56F0\u96E3\u306E\u6253\u7834\u3001\u5B89\u5835\u306E\u305F\u3081\u606F\u3001\u51F1\u65CB">\u5909\u30C8\u9577\u8ABF (G\u266D)</option>
|
|
15994
|
+
<option value="key_G" title="\u53B3\u7C9B\u306A\u3001\u5D07\u9AD8\u306A\u3001\u5E7B\u60F3\u3001\u8AA0\u5B9F">\u30C8\u9577\u8ABF (G)</option>
|
|
15995
|
+
<option value="key_Ab" title="\u6B7B\u3001\u6C38\u9060\u3001\u88C1\u304D\u3001\u6DF1\u9060\u306A\u7791\u60F3">\u5909\u30A4\u9577\u8ABF (A\u266D)</option>
|
|
15996
|
+
<option value="key_A" title="\u3046\u308C\u3057\u3044\u3001\u7267\u6B4C\u7684\u306A\u3001\u611B\u306E\u544A\u767D">\u30A4\u9577\u8ABF (A)</option>
|
|
15997
|
+
<option value="key_Bb" title="\u559C\u3070\u3057\u3044\u3001\u98A8\u5909\u308F\u308A\u306A\u3001\u967D\u6C17\u306A\u3001\u8EFD\u5FEB">\u5909\u30ED\u9577\u8ABF (B\u266D)</option>
|
|
15998
|
+
<option value="key_B" title="\u3069\u304E\u3064\u3044\u3001\u5F37\u70C8\u306A\u3001\u8352\u3063\u307D\u3044\u3001\u731B\u70C8">\u30ED\u9577\u8ABF (B)</option>
|
|
15999
|
+
</optgroup>
|
|
16000
|
+
<optgroup label="\u77ED\u8ABF\uFF08\u500B\u5225\u6307\u5B9A\uFF09">
|
|
16001
|
+
<option value="key_Am" title="\u67D4\u3089\u304B\u306A\u3001\u7269\u60B2\u3057\u3044\u3001\u656C\u8654\u306A\u3001\u7D20\u6734\u306A\u54C0\u6101">\u30A4\u77ED\u8ABF (Am)</option>
|
|
16002
|
+
<option value="key_Bbm" title="\u6050\u308D\u3057\u3044\u3001\u6697\u95C7\u3001\u5632\u308B\u3088\u3046\u306A\u3001\u4E0D\u6C17\u5473">\u5909\u30ED\u77ED\u8ABF (B\u266Dm)</option>
|
|
16003
|
+
<option value="key_Bm" title="\u5B64\u72EC\u306A\u3001\u6182\u9B31\u306A\u3001\u5FCD\u8010\u3001\u9759\u304B\u306A\u8AE6\u5FF5">\u30ED\u77ED\u8ABF (Bm)</option>
|
|
16004
|
+
<option value="key_Cm" title="\u7D14\u7C8B\u306B\u60B2\u3057\u3052\u306A\u3001\u604B\u308F\u305A\u3089\u3044\u306E\u3001\u60B2\u5287\u7684">\u30CF\u77ED\u8ABF (Cm)</option>
|
|
16005
|
+
<option value="key_Csm" title="\u843D\u80C6\u3001\u6CE3\u304D\u53EB\u3093\u3060\u3001\u60B2\u6D99\u306E\u3001\u6DF1\u3044\u5606\u304D">\u5B30\u30CF\u77ED\u8ABF (C\u266Fm)</option>
|
|
16006
|
+
<option value="key_Dm" title="\u53B3\u7C9B\u306A\u3001\u656C\u8654\u306A\u3001\u601D\u7D22\u7684\u306A\u3001\u91CD\u539A\u306A\u7948\u308A">\u30CB\u77ED\u8ABF (Dm)</option>
|
|
16007
|
+
<option value="key_Ebm" title="\u6DF1\u3044\u82E6\u60A9\u3001\u5B9F\u5B58\u7684\u306A\u4E0D\u5B89\u3001\u6226\u6144">\u5909\u30DB\u77ED\u8ABF (E\u266Dm)</option>
|
|
16008
|
+
<option value="key_Em" title="\u5F31\u3005\u3057\u3044\u3001\u306A\u307E\u3081\u304B\u3057\u3044\u3001\u843D\u3061\u7740\u304D\u306E\u306A\u3044">\u30DB\u77ED\u8ABF (Em)</option>
|
|
16009
|
+
<option value="key_Fm" title="\u307C\u3093\u3084\u308A\u3057\u305F\u3001\u7269\u60B2\u3057\u3044\u3001\u3057\u3081\u3084\u304B\u306A\u3001\u846C\u9001">\u30D8\u77ED\u8ABF (Fm)</option>
|
|
16010
|
+
<option value="key_Fsm" title="\u9670\u6C17\u306A\u3001\u6FC0\u3057\u3044\u61A4\u308A\u3001\u6697\u3044\u60C5\u5FF5">\u5B30\u30D8\u77ED\u8ABF (F\u266Fm)</option>
|
|
16011
|
+
<option value="key_Gm" title="\u4E0D\u6E80\u3001\u4E0D\u5B89\u3001\u3084\u308B\u305B\u306A\u3055\u3001\u60B2\u75DB\u306A\u53EB\u3073">\u30C8\u77ED\u8ABF (Gm)</option>
|
|
16012
|
+
<option value="key_Abm" title="\u4E0D\u670D\u306A\u3001\u5606\u304D\u306E\u3001\u6CE3\u304D\u53EB\u3093\u3060">\u5909\u30A4\u77ED\u8ABF (A\u266Dm)</option>
|
|
16013
|
+
</optgroup>
|
|
16014
|
+
</select>
|
|
16015
|
+
<span class="dtm-grow"></span>
|
|
16016
|
+
<span class="dtm-hint" data-dtm="compose-key-hint"></span>
|
|
15556
16017
|
</div>
|
|
15557
|
-
<span class="dtm-grow"></span>
|
|
15558
|
-
<span class="dtm-hint" data-dtm="compose-sections-len"></span>
|
|
15559
|
-
</div>
|
|
15560
|
-
<div class="dtm-row ${showCompose ? "" : "dtm-hidden"}" data-dtm="compose-key-row">
|
|
15561
|
-
<span class="dtm-label">\u30D9\u30FC\u30B9\u8ABF</span>
|
|
15562
|
-
<select class="dtm-select" data-dtm="compose-key" title="\u81EA\u52D5\u4F5C\u66F2\u306E\u30D9\u30FC\u30B9\u3068\u306A\u308B\u8ABF\u3084\u96F0\u56F2\u6C17\u3092\u9078\u3073\u307E\u3059">
|
|
15563
|
-
<option value="any" title="\u516824\u8ABF\u304B\u3089\u30E9\u30F3\u30C0\u30E0\u306B\u6C7A\u5B9A\u3057\u307E\u3059">\u5E0C\u671B\u306A\u3057</option>
|
|
15564
|
-
<optgroup label="\u57FA\u672C">
|
|
15565
|
-
<option value="major" title="12\u306E\u9577\u8ABF\u306E\u4E2D\u304B\u3089\u30E9\u30F3\u30C0\u30E0\u306B\u62BD\u9078\u3057\u307E\u3059">\u9577\u8ABF</option>
|
|
15566
|
-
<option value="minor" title="12\u306E\u77ED\u8ABF\u306E\u4E2D\u304B\u3089\u30E9\u30F3\u30C0\u30E0\u306B\u62BD\u9078\u3057\u307E\u3059">\u77ED\u8ABF</option>
|
|
15567
|
-
</optgroup>
|
|
15568
|
-
<optgroup label="\u96F0\u56F2\u6C17\u304B\u3089\u9078\u3076\uFF08\u62BD\u9078\uFF09">
|
|
15569
|
-
<option value="mood_happy" title="\u30CF\u9577\u8ABF\u30FB\u30A4\u9577\u8ABF\u30FB\u5909\u30ED\u9577\u8ABF\u304B\u3089\u62BD\u9078\uFF08\u7121\u57A2\u306B\u559C\u3070\u3057\u3044\u3001\u7267\u6B4C\u7684\u3001\u967D\u6C17\uFF09">\u559C\u3070\u3057\u3044\u30FB\u967D\u6C17\u306A\u66F2</option>
|
|
15570
|
-
<option value="mood_triumphant" title="\u30CB\u9577\u8ABF\u30FB\u5909\u30C8\u9577\u8ABF\u304B\u3089\u62BD\u9078\uFF08\u610F\u6C17\u63DA\u3005\u3001\u52DD\u5229\u306E\u558A\u58F0\u3001\u56F0\u96E3\u6253\u7834\u3001\u5B89\u5835\uFF09">\u52DD\u5229\u30FB\u529B\u5F37\u3044\u66F2</option>
|
|
15571
|
-
<option value="mood_fierce" title="\u30DB\u9577\u8ABF\u30FB\u30D8\u9577\u8ABF\u30FB\u30ED\u9577\u8ABF\u304B\u3089\u62BD\u9078\uFF08\u3051\u3093\u304B\u3063\u65E9\u3044\u3001\u6012\u308A\u72C2\u3063\u305F\u8352\u3005\u3057\u3055\u3001\u3069\u304E\u3064\u304F\u731B\u70C8\uFF09">\u6FC0\u3057\u3044\u30FB\u8352\u3005\u3057\u3044\u66F2</option>
|
|
15572
|
-
<option value="mood_solemn" title="\u30C8\u9577\u8ABF\u30FB\u30CB\u77ED\u8ABF\u30FB\u30A4\u77ED\u8ABF\u304B\u3089\u62BD\u9078\uFF08\u53B3\u7C9B\u3001\u5D07\u9AD8\u3001\u5E7B\u60F3\u3001\u656C\u8654\u3001\u601D\u7D22\u7684\uFF09">\u53B3\u7C9B\u30FB\u5E7B\u60F3\u7684\u306A\u66F2</option>
|
|
15573
|
-
<option value="mood_plaintive" title="\u30CF\u77ED\u8ABF\u30FB\u30DB\u77ED\u8ABF\u30FB\u30D8\u77ED\u8ABF\u304B\u3089\u62BD\u9078\uFF08\u7D14\u7C8B\u306B\u60B2\u3057\u3052\u3001\u604B\u308F\u305A\u3089\u3044\u3001\u843D\u3061\u7740\u304D\u306E\u306A\u3044\u3001\u7269\u60B2\u3057\u3044\u54C0\u6101\uFF09">\u7269\u60B2\u3057\u3044\u30FB\u54C0\u6101\u306E\u66F2</option>
|
|
15574
|
-
<option value="mood_melancholy" title="\u5909\u30CB\u9577\u8ABF\u30FB\u30ED\u77ED\u8ABF\u30FB\u5B30\u30CF\u77ED\u8ABF\u304B\u3089\u62BD\u9078\uFF08\u60B2\u3057\u307F\u3001\u6182\u9B31\u3001\u5B64\u72EC\u3001\u5FCD\u8010\u3001\u843D\u80C6\u3001\u60B2\u6D99\uFF09">\u6182\u9B31\u30FB\u5B64\u72EC\u306A\u66F2</option>
|
|
15575
|
-
<option value="mood_anxious" title="\u30C8\u77ED\u8ABF\u30FB\u5909\u30DB\u77ED\u8ABF\u30FB\u5B30\u30D8\u77ED\u8ABF\u30FB\u5909\u30A4\u77ED\u8ABF\u304B\u3089\u62BD\u9078\uFF08\u4E0D\u6E80\u3001\u4E0D\u5B89\u3001\u6DF1\u3044\u82E6\u60A9\u3001\u9670\u6C17\u306A\u61A4\u308A\uFF09">\u4E0D\u5B89\u30FB\u82E6\u60A9\u306A\u66F2</option>
|
|
15576
|
-
<option value="mood_dark" title="\u5909\u30DB\u9577\u8ABF\u30FB\u5909\u30A4\u9577\u8ABF\u30FB\u5909\u30ED\u77ED\u8ABF\u304B\u3089\u62BD\u9078\uFF08\u53B3\u3057\u3044\u611B\u3001\u6B7B\u3001\u6C38\u9060\u3001\u88C1\u304D\u3001\u6697\u95C7\u3001\u6050\u308D\u3057\u3044\u5632\u308A\uFF09">\u6697\u95C7\u30FB\u91CD\u539A\u306A\u66F2</option>
|
|
15577
|
-
</optgroup>
|
|
15578
|
-
<optgroup label="\u9577\u8ABF\uFF08\u500B\u5225\u6307\u5B9A\uFF09">
|
|
15579
|
-
<option value="key_C" title="\u7121\u57A2\u306B\u559C\u3070\u3057\u3044\u3001\u7D14\u7C8B\u3001\u7D20\u6734\u3001\u51FA\u767A">\u30CF\u9577\u8ABF (C)</option>
|
|
15580
|
-
<option value="key_Db" title="\u60B2\u3057\u307F\u3001\u6182\u9B31\u306A\u3001\u7518\u7F8E\u306A\u611F\u50B7">\u5909\u30CB\u9577\u8ABF (D\u266D)</option>
|
|
15581
|
-
<option value="key_D" title="\u610F\u6C17\u63DA\u3005\u3068\u3057\u305F\u3001\u52DD\u5229\u306E\u3001\u558A\u58F0">\u30CB\u9577\u8ABF (D)</option>
|
|
15582
|
-
<option value="key_Eb" title="\u53B3\u3057\u3044\u3001\u304D\u3064\u3044\u3001\u305D\u308C\u3067\u3044\u3066\u611B\u306B\u6E80\u3061\u305F">\u5909\u30DB\u9577\u8ABF (E\u266D)</option>
|
|
15583
|
-
<option value="key_E" title="\u3051\u3093\u304B\u3063\u65E9\u3044\u3001\u8352\u3005\u3057\u3044\u3001\u8F1D\u304B\u3057\u3044\u60C5\u71B1">\u30DB\u9577\u8ABF (E)</option>
|
|
15584
|
-
<option value="key_F" title="\u6012\u308A\u72C2\u3063\u305F\u3001\u6C17\u6027\u306E\u8352\u3044\u3001\u4E00\u6642\u7684\u306A\u60B2\u5606">\u30D8\u9577\u8ABF (F)</option>
|
|
15585
|
-
<option value="key_Gb" title="\u56F0\u96E3\u306E\u6253\u7834\u3001\u5B89\u5835\u306E\u305F\u3081\u606F\u3001\u51F1\u65CB">\u5909\u30C8\u9577\u8ABF (G\u266D)</option>
|
|
15586
|
-
<option value="key_G" title="\u53B3\u7C9B\u306A\u3001\u5D07\u9AD8\u306A\u3001\u5E7B\u60F3\u3001\u8AA0\u5B9F">\u30C8\u9577\u8ABF (G)</option>
|
|
15587
|
-
<option value="key_Ab" title="\u6B7B\u3001\u6C38\u9060\u3001\u88C1\u304D\u3001\u6DF1\u9060\u306A\u7791\u60F3">\u5909\u30A4\u9577\u8ABF (A\u266D)</option>
|
|
15588
|
-
<option value="key_A" title="\u3046\u308C\u3057\u3044\u3001\u7267\u6B4C\u7684\u306A\u3001\u611B\u306E\u544A\u767D">\u30A4\u9577\u8ABF (A)</option>
|
|
15589
|
-
<option value="key_Bb" title="\u559C\u3070\u3057\u3044\u3001\u98A8\u5909\u308F\u308A\u306A\u3001\u967D\u6C17\u306A\u3001\u8EFD\u5FEB">\u5909\u30ED\u9577\u8ABF (B\u266D)</option>
|
|
15590
|
-
<option value="key_B" title="\u3069\u304E\u3064\u3044\u3001\u5F37\u70C8\u306A\u3001\u8352\u3063\u307D\u3044\u3001\u731B\u70C8">\u30ED\u9577\u8ABF (B)</option>
|
|
15591
|
-
</optgroup>
|
|
15592
|
-
<optgroup label="\u77ED\u8ABF\uFF08\u500B\u5225\u6307\u5B9A\uFF09">
|
|
15593
|
-
<option value="key_Am" title="\u67D4\u3089\u304B\u306A\u3001\u7269\u60B2\u3057\u3044\u3001\u656C\u8654\u306A\u3001\u7D20\u6734\u306A\u54C0\u6101">\u30A4\u77ED\u8ABF (Am)</option>
|
|
15594
|
-
<option value="key_Bbm" title="\u6050\u308D\u3057\u3044\u3001\u6697\u95C7\u3001\u5632\u308B\u3088\u3046\u306A\u3001\u4E0D\u6C17\u5473">\u5909\u30ED\u77ED\u8ABF (B\u266Dm)</option>
|
|
15595
|
-
<option value="key_Bm" title="\u5B64\u72EC\u306A\u3001\u6182\u9B31\u306A\u3001\u5FCD\u8010\u3001\u9759\u304B\u306A\u8AE6\u5FF5">\u30ED\u77ED\u8ABF (Bm)</option>
|
|
15596
|
-
<option value="key_Cm" title="\u7D14\u7C8B\u306B\u60B2\u3057\u3052\u306A\u3001\u604B\u308F\u305A\u3089\u3044\u306E\u3001\u60B2\u5287\u7684">\u30CF\u77ED\u8ABF (Cm)</option>
|
|
15597
|
-
<option value="key_Csm" title="\u843D\u80C6\u3001\u6CE3\u304D\u53EB\u3093\u3060\u3001\u60B2\u6D99\u306E\u3001\u6DF1\u3044\u5606\u304D">\u5B30\u30CF\u77ED\u8ABF (C\u266Fm)</option>
|
|
15598
|
-
<option value="key_Dm" title="\u53B3\u7C9B\u306A\u3001\u656C\u8654\u306A\u3001\u601D\u7D22\u7684\u306A\u3001\u91CD\u539A\u306A\u7948\u308A">\u30CB\u77ED\u8ABF (Dm)</option>
|
|
15599
|
-
<option value="key_Ebm" title="\u6DF1\u3044\u82E6\u60A9\u3001\u5B9F\u5B58\u7684\u306A\u4E0D\u5B89\u3001\u6226\u6144">\u5909\u30DB\u77ED\u8ABF (E\u266Dm)</option>
|
|
15600
|
-
<option value="key_Em" title="\u5F31\u3005\u3057\u3044\u3001\u306A\u307E\u3081\u304B\u3057\u3044\u3001\u843D\u3061\u7740\u304D\u306E\u306A\u3044">\u30DB\u77ED\u8ABF (Em)</option>
|
|
15601
|
-
<option value="key_Fm" title="\u307C\u3093\u3084\u308A\u3057\u305F\u3001\u7269\u60B2\u3057\u3044\u3001\u3057\u3081\u3084\u304B\u306A\u3001\u846C\u9001">\u30D8\u77ED\u8ABF (Fm)</option>
|
|
15602
|
-
<option value="key_Fsm" title="\u9670\u6C17\u306A\u3001\u6FC0\u3057\u3044\u61A4\u308A\u3001\u6697\u3044\u60C5\u5FF5">\u5B30\u30D8\u77ED\u8ABF (F\u266Fm)</option>
|
|
15603
|
-
<option value="key_Gm" title="\u4E0D\u6E80\u3001\u4E0D\u5B89\u3001\u3084\u308B\u305B\u306A\u3055\u3001\u60B2\u75DB\u306A\u53EB\u3073">\u30C8\u77ED\u8ABF (Gm)</option>
|
|
15604
|
-
<option value="key_Abm" title="\u4E0D\u670D\u306A\u3001\u5606\u304D\u306E\u3001\u6CE3\u304D\u53EB\u3093\u3060">\u5909\u30A4\u77ED\u8ABF (A\u266Dm)</option>
|
|
15605
|
-
</optgroup>
|
|
15606
|
-
</select>
|
|
15607
|
-
<span class="dtm-grow"></span>
|
|
15608
|
-
<span class="dtm-hint" data-dtm="compose-key-hint"></span>
|
|
15609
16018
|
</div>
|
|
15610
16019
|
<div class="dtm-row">
|
|
15611
16020
|
<span class="dtm-label">\u5168\u4F53\u30B7\u30D5\u30C8</span>
|
|
@@ -15803,6 +16212,7 @@ var buildUI = (target, options) => {
|
|
|
15803
16212
|
transposeApplyBtn: sel("transpose-apply"),
|
|
15804
16213
|
transposeInfoBtn: sel("transpose-info"),
|
|
15805
16214
|
macroCompose: sel("macro-compose"),
|
|
16215
|
+
composeTemplate: sel("compose-template"),
|
|
15806
16216
|
composeSections: sel("compose-sections"),
|
|
15807
16217
|
composeSectionsLen: sel("compose-sections-len"),
|
|
15808
16218
|
composeKey: sel("compose-key"),
|
|
@@ -15945,6 +16355,45 @@ var INSTRUMENT_PRESETS = {
|
|
|
15945
16355
|
}
|
|
15946
16356
|
};
|
|
15947
16357
|
|
|
16358
|
+
// src/macro-state.ts
|
|
16359
|
+
var MACRO_STORAGE_KEYS = {
|
|
16360
|
+
template: "dtm-macro:template",
|
|
16361
|
+
sections: "dtm-macro:sections",
|
|
16362
|
+
key: "dtm-macro:key",
|
|
16363
|
+
shift: "dtm-macro:shift",
|
|
16364
|
+
transpose: "dtm-macro:transpose"
|
|
16365
|
+
};
|
|
16366
|
+
var readMacroSetting = (key) => {
|
|
16367
|
+
try {
|
|
16368
|
+
if (typeof localStorage === "undefined" || !localStorage) return null;
|
|
16369
|
+
return localStorage.getItem(MACRO_STORAGE_KEYS[key]);
|
|
16370
|
+
} catch (_) {
|
|
16371
|
+
return null;
|
|
16372
|
+
}
|
|
16373
|
+
};
|
|
16374
|
+
var writeMacroSetting = (key, value) => {
|
|
16375
|
+
try {
|
|
16376
|
+
if (typeof localStorage === "undefined" || !localStorage) return;
|
|
16377
|
+
localStorage.setItem(MACRO_STORAGE_KEYS[key], value);
|
|
16378
|
+
} catch (_) {
|
|
16379
|
+
}
|
|
16380
|
+
};
|
|
16381
|
+
var readMacroSections = () => {
|
|
16382
|
+
const raw = readMacroSetting("sections");
|
|
16383
|
+
if (!raw) return null;
|
|
16384
|
+
try {
|
|
16385
|
+
const parsed = JSON.parse(raw);
|
|
16386
|
+
if (Array.isArray(parsed) && parsed.every((x2) => typeof x2 === "string")) {
|
|
16387
|
+
return parsed;
|
|
16388
|
+
}
|
|
16389
|
+
} catch (_) {
|
|
16390
|
+
}
|
|
16391
|
+
return null;
|
|
16392
|
+
};
|
|
16393
|
+
var writeMacroSections = (sections) => {
|
|
16394
|
+
writeMacroSetting("sections", JSON.stringify(sections));
|
|
16395
|
+
};
|
|
16396
|
+
|
|
15948
16397
|
// src/macros.ts
|
|
15949
16398
|
var SCALES = [
|
|
15950
16399
|
[0, 2, 4, 5, 7, 9, 11],
|
|
@@ -17980,7 +18429,7 @@ var COMPOSE_INFO_HTML = `
|
|
|
17980
18429
|
<tr><td>\u30A2\u30A6\u30C8\u30ED</td><td>\u6709\u308A</td><td>\u4F4E\u3081</td><td>\u8584\u3044</td><td>\u4E3B\u97F3\u3078\u7740\u5730</td></tr>
|
|
17981
18430
|
</table>
|
|
17982
18431
|
<p>\u30A4\u30F3\u30C8\u30ED\u3068\u9593\u594F\u306F\u30E1\u30ED\u30C7\u30A3\u3092\u66F8\u304D\u307E\u305B\u3093\uFF08\u4F34\u594F\u30FB\u30D9\u30FC\u30B9\u30FB\u30C9\u30E9\u30E0\u30FB\u30B5\u30D6\u30E1\u30ED\u3060\u3051\u304C\u9CF4\u308A\u307E\u3059\uFF09\u3002\u3053\u3053\u306B\u6B4C\u30E1\u30ED\u3092\u7F6E\u304F\u3068\u3001\u3069\u306E\u30BB\u30AF\u30B7\u30E7\u30F3\u3082\u540C\u3058\u9854\u306B\u306A\u3063\u3066\u300C\u305A\u3063\u3068\u6B4C\u3063\u3066\u3044\u308B\u66F2\u300D\u306B\u306A\u3063\u3066\u3057\u307E\u3046\u305F\u3081\u3067\u3059\u3002\u30BB\u30AF\u30B7\u30E7\u30F3\u306E\u982D\u3067\u306F\u30C9\u30E9\u30E0\u304C\u30AF\u30E9\u30C3\u30B7\u30E5\u3092\u53E9\u304D\u3001\u7D42\u308F\u308A\u306E1\u3064\u624B\u524D\u3067\u30D5\u30A3\u30EB\u304C\u5165\u308A\u307E\u3059\u3002</p>
|
|
17983
|
-
<p>\u30CE\u30FC\u30C8\
|
|
18432
|
+
<p>\u30CE\u30FC\u30C8\u306E\u914D\u7F6E\u306B\u52A0\u3048\u3066\u3001\u30C6\u30F3\u30DD\u30FB\u30C9\u30E9\u30E0\u30FB\u697D\u5668\u30FB<strong>\u304A\u307E\u304B\u305B\u30DE\u30B9\u30BF\u30EA\u30F3\u30B0</strong>\uFF08\u5404\u30C8\u30E9\u30C3\u30AF\u306E\u97F3\u91CF\u30D0\u30E9\u30F3\u30B9\u30FB\u5B9A\u4F4D\u30FBEQ\u30FB\u30B3\u30F3\u30D7\u30EC\u30C3\u30B5\u30FC\u30FB\u30EA\u30D0\u30FC\u30D6\u30FB\u30DE\u30B9\u30BF\u8A2D\u5B9A\uFF09\u3082\u81EA\u52D5\u3067\u4E00\u62EC\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002\u3067\u304D\u305F\u5F8C\u306B\u5FAE\u8ABF\u6574\u3057\u305F\u3044\u3068\u304D\u306F\u3001\u5404\u30C8\u30E9\u30C3\u30AF\u306E\u8A2D\u5B9A\u3084\u300C\u5168\u4F53\u30C8\u30E9\u30C3\u30AF\u8A2D\u5B9A\u300D\u304B\u3089\u81EA\u7531\u306B\u5909\u66F4\u3067\u304D\u307E\u3059\u3002</p>
|
|
17984
18433
|
<h4>\u66F2\u306E\u7D44\u307F\u7ACB\u3066\u65B9</h4>
|
|
17985
18434
|
<p>\u5358\u7D14\u306B\u30E9\u30F3\u30C0\u30E0\u306A\u97F3\u3092\u4E26\u3079\u3066\u3044\u308B\u308F\u3051\u3067\u306F\u3042\u308A\u307E\u305B\u3093\u3002\u6B21\u306E\u9806\u756A\u3067\u7D44\u307F\u7ACB\u3066\u3066\u3044\u307E\u3059\u3002</p>
|
|
17986
18435
|
<ol>
|
|
@@ -18288,12 +18737,15 @@ var pickComposeVocal = (exclude) => {
|
|
|
18288
18737
|
var ADVANCED_COMPOSE_LAYOUT = [
|
|
18289
18738
|
{ index: 0, part: "melody", octave: 0, volume: 104 },
|
|
18290
18739
|
{ index: 1, part: "melody", octave: 1, volume: 62 },
|
|
18291
|
-
{ index: 2, part: "
|
|
18292
|
-
{ index: 3, part: "
|
|
18293
|
-
{ index: 4, part: "bass", octave:
|
|
18294
|
-
{ index: 5, part: "
|
|
18295
|
-
{ index: 6, part: "
|
|
18296
|
-
{ index: 7, part: "
|
|
18740
|
+
{ index: 2, part: "harmony", octave: 0, volume: 82 },
|
|
18741
|
+
{ index: 3, part: "submelody", octave: 0, volume: 86 },
|
|
18742
|
+
{ index: 4, part: "bass", octave: 0, volume: 92 },
|
|
18743
|
+
{ index: 5, part: "bass", octave: -1, volume: 58 },
|
|
18744
|
+
{ index: 6, part: "pad", octave: 0, volume: 64 },
|
|
18745
|
+
{ index: 7, part: "block", octave: 0, volume: 62 },
|
|
18746
|
+
{ index: 8, part: "arpeggio", octave: 0, volume: 54 },
|
|
18747
|
+
{ index: 9, part: "offbeat", octave: 0, volume: 50 },
|
|
18748
|
+
{ index: 10, part: "uwamono", octave: 1, volume: 56 }
|
|
18297
18749
|
];
|
|
18298
18750
|
var LYRIC_MODEL_CATEGORIES = [
|
|
18299
18751
|
{
|
|
@@ -18583,6 +19035,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
18583
19035
|
options.onDrumFontChange?.(font);
|
|
18584
19036
|
};
|
|
18585
19037
|
let currentInstrument = "";
|
|
19038
|
+
let autoComposeInstrument = null;
|
|
18586
19039
|
let activeTrackId = options.initialActiveTrack ?? trackConfigs[0].id;
|
|
18587
19040
|
let trackFxAdvancedOpen = readPanelOpen("track-fx-advanced") ?? false;
|
|
18588
19041
|
let lyricAdvancedOpen = readPanelOpen("lyric-advanced") ?? false;
|
|
@@ -19620,8 +20073,8 @@ var mountDAW = (target, options = {}) => {
|
|
|
19620
20073
|
redrawAll();
|
|
19621
20074
|
},
|
|
19622
20075
|
onEnd: (interrupted) => {
|
|
19623
|
-
options.onScheduleFade?.(null);
|
|
19624
20076
|
if (interrupted) {
|
|
20077
|
+
options.onScheduleFade?.(null);
|
|
19625
20078
|
playbackState = "paused";
|
|
19626
20079
|
pausedPlayStep = currentPlayStep;
|
|
19627
20080
|
} else {
|
|
@@ -21576,7 +22029,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
21576
22029
|
refs.autoMasterInfoBtn.addEventListener("click", () => {
|
|
21577
22030
|
showModal("\u304A\u307E\u304B\u305B\u30DE\u30B9\u30BF\u30EA\u30F3\u30B0\u89E3\u8AAC", AUTO_MASTER_INFO_HTML);
|
|
21578
22031
|
});
|
|
21579
|
-
|
|
22032
|
+
const applyAutoMastering = () => {
|
|
21580
22033
|
if (observedPlayMs >= PEAK_SAMPLE_MIN_PLAY_MS && observedPeakMax > 0) {
|
|
21581
22034
|
const targetPeak = 0.5;
|
|
21582
22035
|
const scale = targetPeak / observedPeakMax;
|
|
@@ -21729,6 +22182,9 @@ var mountDAW = (target, options = {}) => {
|
|
|
21729
22182
|
}
|
|
21730
22183
|
}
|
|
21731
22184
|
updateTrackPanel();
|
|
22185
|
+
};
|
|
22186
|
+
refs.autoMasterBtn.addEventListener("click", () => {
|
|
22187
|
+
applyAutoMastering();
|
|
21732
22188
|
});
|
|
21733
22189
|
refs.drumSelect.addEventListener("change", () => {
|
|
21734
22190
|
currentDrumPattern = refs.drumSelect.value;
|
|
@@ -21746,12 +22202,9 @@ var mountDAW = (target, options = {}) => {
|
|
|
21746
22202
|
refs.macroComposeInfo.addEventListener("click", () => {
|
|
21747
22203
|
showModal("\u4F5C\u66F2\u306E\u89E3\u8AAC", COMPOSE_INFO_HTML);
|
|
21748
22204
|
});
|
|
21749
|
-
const
|
|
21750
|
-
|
|
21751
|
-
|
|
21752
|
-
return t ? [t] : [];
|
|
21753
|
-
}
|
|
21754
|
-
return ADVANCED_COMPOSE_LAYOUT.filter((l) => l.part === "bass").map((l) => trackStates[l.index]).filter((t) => !!t);
|
|
22205
|
+
const selectedComposeTemplate = () => {
|
|
22206
|
+
const val = refs.composeTemplate?.value;
|
|
22207
|
+
return val && val !== "custom" ? val : void 0;
|
|
21755
22208
|
};
|
|
21756
22209
|
const selectedComposeSections = () => {
|
|
21757
22210
|
const boxes = [
|
|
@@ -21763,11 +22216,97 @@ var mountDAW = (target, options = {}) => {
|
|
|
21763
22216
|
return picked.length > 0 ? picked : DEFAULT_SECTIONS;
|
|
21764
22217
|
};
|
|
21765
22218
|
const updateComposeSectionsLen = () => {
|
|
21766
|
-
const
|
|
22219
|
+
const tmpl = selectedComposeTemplate();
|
|
22220
|
+
const plan = buildSectionPlan(selectedComposeSections(), tmpl);
|
|
21767
22221
|
const bars = plan.reduce((sum, x2) => sum + x2.bars, 0);
|
|
21768
22222
|
refs.composeSectionsLen.textContent = `${bars}\u5C0F\u7BC0`;
|
|
21769
22223
|
};
|
|
21770
|
-
|
|
22224
|
+
const savedTemplate = readMacroSetting("template");
|
|
22225
|
+
if (savedTemplate && refs.composeTemplate) {
|
|
22226
|
+
const hasOption = Array.from(refs.composeTemplate.options).some(
|
|
22227
|
+
(opt) => opt.value === savedTemplate
|
|
22228
|
+
);
|
|
22229
|
+
if (hasOption) {
|
|
22230
|
+
refs.composeTemplate.value = savedTemplate;
|
|
22231
|
+
}
|
|
22232
|
+
}
|
|
22233
|
+
const savedSections = readMacroSections();
|
|
22234
|
+
if (savedSections && refs.composeSections) {
|
|
22235
|
+
const boxes = refs.composeSections.querySelectorAll(
|
|
22236
|
+
'input[type="checkbox"]'
|
|
22237
|
+
);
|
|
22238
|
+
const validValues = new Set(savedSections);
|
|
22239
|
+
for (const box of boxes) {
|
|
22240
|
+
box.checked = validValues.has(box.value);
|
|
22241
|
+
}
|
|
22242
|
+
} else if (savedTemplate && savedTemplate !== "custom" && refs.composeSections) {
|
|
22243
|
+
const tmpl = STRUCTURE_TEMPLATES.find((t) => t.name === savedTemplate);
|
|
22244
|
+
if (tmpl) {
|
|
22245
|
+
const planSet = new Set(tmpl.plan);
|
|
22246
|
+
const boxes = refs.composeSections.querySelectorAll(
|
|
22247
|
+
'input[type="checkbox"]'
|
|
22248
|
+
);
|
|
22249
|
+
for (const box of boxes) {
|
|
22250
|
+
box.checked = planSet.has(box.value);
|
|
22251
|
+
}
|
|
22252
|
+
}
|
|
22253
|
+
}
|
|
22254
|
+
const savedKey = readMacroSetting("key");
|
|
22255
|
+
if (savedKey && refs.composeKey) {
|
|
22256
|
+
const hasOption = Array.from(refs.composeKey.options).some(
|
|
22257
|
+
(opt) => opt.value === savedKey
|
|
22258
|
+
);
|
|
22259
|
+
if (hasOption) {
|
|
22260
|
+
refs.composeKey.value = savedKey;
|
|
22261
|
+
}
|
|
22262
|
+
}
|
|
22263
|
+
const savedShift = readMacroSetting("shift");
|
|
22264
|
+
if (savedShift && refs.shiftSelect) {
|
|
22265
|
+
const hasOption = Array.from(refs.shiftSelect.options).some(
|
|
22266
|
+
(opt) => opt.value === savedShift
|
|
22267
|
+
);
|
|
22268
|
+
if (hasOption) {
|
|
22269
|
+
refs.shiftSelect.value = savedShift;
|
|
22270
|
+
}
|
|
22271
|
+
}
|
|
22272
|
+
const savedTranspose = readMacroSetting("transpose");
|
|
22273
|
+
if (savedTranspose && refs.transposeSelect) {
|
|
22274
|
+
const hasOption = Array.from(refs.transposeSelect.options).some(
|
|
22275
|
+
(opt) => opt.value === savedTranspose
|
|
22276
|
+
);
|
|
22277
|
+
if (hasOption) {
|
|
22278
|
+
refs.transposeSelect.value = savedTranspose;
|
|
22279
|
+
}
|
|
22280
|
+
}
|
|
22281
|
+
refs.composeSections.addEventListener("change", () => {
|
|
22282
|
+
if (refs.composeTemplate) {
|
|
22283
|
+
refs.composeTemplate.value = "custom";
|
|
22284
|
+
writeMacroSetting("template", "custom");
|
|
22285
|
+
}
|
|
22286
|
+
writeMacroSections(selectedComposeSections());
|
|
22287
|
+
updateComposeSectionsLen();
|
|
22288
|
+
});
|
|
22289
|
+
const composeTemplate = refs.composeTemplate;
|
|
22290
|
+
if (composeTemplate) {
|
|
22291
|
+
composeTemplate.addEventListener("change", () => {
|
|
22292
|
+
writeMacroSetting("template", composeTemplate.value);
|
|
22293
|
+
const tmplName = selectedComposeTemplate();
|
|
22294
|
+
if (tmplName) {
|
|
22295
|
+
const tmpl = STRUCTURE_TEMPLATES.find((t) => t.name === tmplName);
|
|
22296
|
+
if (tmpl) {
|
|
22297
|
+
const planSet = new Set(tmpl.plan);
|
|
22298
|
+
const boxes = refs.composeSections.querySelectorAll(
|
|
22299
|
+
'input[type="checkbox"]'
|
|
22300
|
+
);
|
|
22301
|
+
for (const box of boxes) {
|
|
22302
|
+
box.checked = planSet.has(box.value);
|
|
22303
|
+
}
|
|
22304
|
+
}
|
|
22305
|
+
}
|
|
22306
|
+
writeMacroSections(selectedComposeSections());
|
|
22307
|
+
updateComposeSectionsLen();
|
|
22308
|
+
});
|
|
22309
|
+
}
|
|
21771
22310
|
updateComposeSectionsLen();
|
|
21772
22311
|
const updateComposeKeyHint = () => {
|
|
21773
22312
|
if (!refs.composeKey || !refs.composeKeyHint) return;
|
|
@@ -21775,17 +22314,33 @@ var mountDAW = (target, options = {}) => {
|
|
|
21775
22314
|
refs.composeKeyHint.textContent = desc;
|
|
21776
22315
|
refs.composeKeyHint.title = desc;
|
|
21777
22316
|
};
|
|
21778
|
-
|
|
21779
|
-
|
|
22317
|
+
const composeKey = refs.composeKey;
|
|
22318
|
+
if (composeKey) {
|
|
22319
|
+
composeKey.addEventListener("change", () => {
|
|
22320
|
+
writeMacroSetting("key", composeKey.value);
|
|
22321
|
+
updateComposeKeyHint();
|
|
22322
|
+
});
|
|
21780
22323
|
updateComposeKeyHint();
|
|
21781
22324
|
}
|
|
22325
|
+
if (refs.shiftSelect) {
|
|
22326
|
+
refs.shiftSelect.addEventListener("change", () => {
|
|
22327
|
+
writeMacroSetting("shift", refs.shiftSelect.value);
|
|
22328
|
+
});
|
|
22329
|
+
}
|
|
22330
|
+
if (refs.transposeSelect) {
|
|
22331
|
+
refs.transposeSelect.addEventListener("change", () => {
|
|
22332
|
+
writeMacroSetting("transpose", refs.transposeSelect.value);
|
|
22333
|
+
});
|
|
22334
|
+
}
|
|
21782
22335
|
const runCompose = (withVocal) => {
|
|
21783
22336
|
stop();
|
|
21784
22337
|
overlayDuring(() => {
|
|
22338
|
+
const tmpl = selectedComposeTemplate();
|
|
21785
22339
|
const song = composeSong({
|
|
21786
22340
|
stepsPerBar: renderConfig.stepsPerBar,
|
|
21787
22341
|
edo: renderConfig.edo,
|
|
21788
22342
|
sections: selectedComposeSections(),
|
|
22343
|
+
template: tmpl,
|
|
21789
22344
|
baseKey: refs.composeKey?.value ?? "any",
|
|
21790
22345
|
// 直近に作った曲の特徴を渡すと、それらから離れた候補に加点される。
|
|
21791
22346
|
// 「作曲」を続けて押したときに似た曲が並ぶのを防ぐ。
|
|
@@ -21824,7 +22379,19 @@ var mountDAW = (target, options = {}) => {
|
|
|
21824
22379
|
for (const layer of ADVANCED_COMPOSE_LAYOUT) {
|
|
21825
22380
|
const track = trackStates[layer.index];
|
|
21826
22381
|
if (!track) continue;
|
|
21827
|
-
const notes = layer.part === "melody" ? song.melody : layer.part === "submelody" ? song.submelody : layer.part === "bass" ? song.bass : buildChordPlacements({
|
|
22382
|
+
const notes = layer.part === "melody" ? song.melody : layer.part === "harmony" ? song.harmony : layer.part === "submelody" ? song.submelody : layer.part === "bass" ? song.bass : layer.part === "pad" ? song.pad : layer.part === "uwamono" ? buildChordPlacements({
|
|
22383
|
+
edo: renderConfig.edo,
|
|
22384
|
+
chordStr: song.chordProgression,
|
|
22385
|
+
patternType: "arpeggio",
|
|
22386
|
+
rootShift: song.rootShift,
|
|
22387
|
+
bpm: song.bpm,
|
|
22388
|
+
stepsPerBar: renderConfig.stepsPerBar
|
|
22389
|
+
}).map((p) => ({
|
|
22390
|
+
startStep: p.startStep,
|
|
22391
|
+
pitchUnits: p.pitchUnits,
|
|
22392
|
+
durationSteps: p.durationSteps,
|
|
22393
|
+
velocity: Math.max(30, p.velocity - 14)
|
|
22394
|
+
})) : buildChordPlacements({
|
|
21828
22395
|
edo: renderConfig.edo,
|
|
21829
22396
|
chordStr: song.chordProgression,
|
|
21830
22397
|
patternType: layer.part,
|
|
@@ -21863,9 +22430,11 @@ var mountDAW = (target, options = {}) => {
|
|
|
21863
22430
|
refs.drumSelect.value = song.drum;
|
|
21864
22431
|
options.onDrumChange?.(song.drum);
|
|
21865
22432
|
applyDrumPatternFont(song.drum);
|
|
21866
|
-
|
|
21867
|
-
|
|
21868
|
-
|
|
22433
|
+
const shouldAutoInstrument = !currentInstrument || currentInstrument === "auto" || currentInstrument === autoComposeInstrument;
|
|
22434
|
+
if (shouldAutoInstrument && song.instrument) {
|
|
22435
|
+
currentInstrument = song.instrument;
|
|
22436
|
+
autoComposeInstrument = song.instrument;
|
|
22437
|
+
options.onInstrumentChange?.(song.instrument);
|
|
21869
22438
|
}
|
|
21870
22439
|
if (withVocal) {
|
|
21871
22440
|
const melodyTrack = isAdvanced ? trackStates[0] : trackStates.find((t) => t.config.id === "melody");
|
|
@@ -21881,6 +22450,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
21881
22450
|
fireLyricsChange(melodyTrack);
|
|
21882
22451
|
}
|
|
21883
22452
|
}
|
|
22453
|
+
applyAutoMastering();
|
|
21884
22454
|
if (refs.composeKeyHint) {
|
|
21885
22455
|
refs.composeKeyHint.textContent = `${song.keyLabel} \u3067\u4F5C\u6210`;
|
|
21886
22456
|
refs.composeKeyHint.title = `${song.keyLabel}${song.moodLabel ? `\uFF08${song.moodLabel}\uFF09` : ""}`;
|
|
@@ -23052,6 +23622,49 @@ var mountDAW = (target, options = {}) => {
|
|
|
23052
23622
|
};
|
|
23053
23623
|
};
|
|
23054
23624
|
|
|
23625
|
+
// src/global-state.ts
|
|
23626
|
+
var GLOBAL_STORAGE_KEYS = {
|
|
23627
|
+
edo: "dtm-global:edo",
|
|
23628
|
+
loop: "dtm-global:loop",
|
|
23629
|
+
masterVolume: "dtm-global:master-volume",
|
|
23630
|
+
masterComp: "dtm-global:master-comp",
|
|
23631
|
+
reverbAmount: "dtm-global:reverb-amount",
|
|
23632
|
+
reverbDecay: "dtm-global:reverb-decay",
|
|
23633
|
+
reverbPreDelay: "dtm-global:reverb-predelay",
|
|
23634
|
+
delayAmount: "dtm-global:delay-amount",
|
|
23635
|
+
delayDivision: "dtm-global:delay-division",
|
|
23636
|
+
fadeIn: "dtm-global:fade-in",
|
|
23637
|
+
fadeOut: "dtm-global:fade-out"
|
|
23638
|
+
};
|
|
23639
|
+
var readGlobalSetting = (key) => {
|
|
23640
|
+
try {
|
|
23641
|
+
if (typeof localStorage === "undefined" || !localStorage) return null;
|
|
23642
|
+
return localStorage.getItem(GLOBAL_STORAGE_KEYS[key]);
|
|
23643
|
+
} catch (_) {
|
|
23644
|
+
return null;
|
|
23645
|
+
}
|
|
23646
|
+
};
|
|
23647
|
+
var writeGlobalSetting = (key, value) => {
|
|
23648
|
+
try {
|
|
23649
|
+
if (typeof localStorage === "undefined" || !localStorage) return;
|
|
23650
|
+
localStorage.setItem(GLOBAL_STORAGE_KEYS[key], value);
|
|
23651
|
+
} catch (_) {
|
|
23652
|
+
}
|
|
23653
|
+
};
|
|
23654
|
+
var readGlobalNumber = (key, min, max) => {
|
|
23655
|
+
const raw = readGlobalSetting(key);
|
|
23656
|
+
if (raw === null) return null;
|
|
23657
|
+
const n = Number.parseFloat(raw);
|
|
23658
|
+
if (Number.isNaN(n)) return null;
|
|
23659
|
+
return Math.max(min, Math.min(max, n));
|
|
23660
|
+
};
|
|
23661
|
+
var readGlobalBool = (key) => {
|
|
23662
|
+
const raw = readGlobalSetting(key);
|
|
23663
|
+
if (raw === "1" || raw === "true") return true;
|
|
23664
|
+
if (raw === "0" || raw === "false") return false;
|
|
23665
|
+
return null;
|
|
23666
|
+
};
|
|
23667
|
+
|
|
23055
23668
|
// src/headless-singing-player.ts
|
|
23056
23669
|
var STEPS_PER_BEAT4 = 48;
|
|
23057
23670
|
var STEPS_PER_BAR3 = 192;
|
|
@@ -24135,6 +24748,8 @@ var createDtmStudio = async (options = {}) => {
|
|
|
24135
24748
|
if (fadeOutStartAt !== void 0 && fadeOutEndAt !== void 0) {
|
|
24136
24749
|
fadeGain.gain.setValueAtTime(1, fadeOutStartAt);
|
|
24137
24750
|
fadeGain.gain.linearRampToValueAtTime(0, fadeOutEndAt);
|
|
24751
|
+
fadeGain.gain.setValueAtTime(0, fadeOutEndAt + 2);
|
|
24752
|
+
fadeGain.gain.setValueAtTime(1, fadeOutEndAt + 2);
|
|
24138
24753
|
}
|
|
24139
24754
|
};
|
|
24140
24755
|
const clipMeter = createClipMeter(audioCtx, glueMakeup);
|
|
@@ -24406,8 +25021,15 @@ var createDtmStudio = async (options = {}) => {
|
|
|
24406
25021
|
await listReady;
|
|
24407
25022
|
nameToKey = await buildNameToKeyMapping();
|
|
24408
25023
|
await Promise.all([drumReady, loadPreset(defaultPreset)]);
|
|
25024
|
+
const restoreFadeGainIfMuted = () => {
|
|
25025
|
+
if (fadeGain.gain.value < 1) {
|
|
25026
|
+
fadeGain.gain.cancelScheduledValues(audioCtx.currentTime);
|
|
25027
|
+
fadeGain.gain.setValueAtTime(1, audioCtx.currentTime);
|
|
25028
|
+
}
|
|
25029
|
+
};
|
|
24409
25030
|
const playDrum = (e) => {
|
|
24410
25031
|
if (!sfDrum.font) return;
|
|
25032
|
+
if (e.when === 0) restoreFadeGainIfMuted();
|
|
24411
25033
|
if (KICK_PITCHES.has(e.pitch)) duckBassForKick(e.when);
|
|
24412
25034
|
sfDrum.play({
|
|
24413
25035
|
ctx: audioCtx,
|
|
@@ -24451,6 +25073,7 @@ var createDtmStudio = async (options = {}) => {
|
|
|
24451
25073
|
}
|
|
24452
25074
|
}
|
|
24453
25075
|
const playNote4 = (e) => {
|
|
25076
|
+
if (e.when === 0) restoreFadeGainIfMuted();
|
|
24454
25077
|
const { trackIdx, role } = resolveTrackIdxAndRole(e.trackId);
|
|
24455
25078
|
const overrideKey = trackIdx >= 0 ? trackInstOverrides.get(trackIdx) : void 0;
|
|
24456
25079
|
let sfInst;
|
|
@@ -24476,12 +25099,26 @@ var createDtmStudio = async (options = {}) => {
|
|
|
24476
25099
|
duration: e.duration
|
|
24477
25100
|
});
|
|
24478
25101
|
};
|
|
25102
|
+
let daw;
|
|
24479
25103
|
let presetSelect = null;
|
|
24480
25104
|
const handleInstrumentChange = (key) => {
|
|
24481
25105
|
editorPreset = key;
|
|
24482
25106
|
if (presetSelect) {
|
|
24483
25107
|
presetSelect.setValue(key);
|
|
24484
25108
|
}
|
|
25109
|
+
if (INSTRUMENT_PRESETS[key]) {
|
|
25110
|
+
const wasPlaying = daw?.getPlaybackState() === "playing";
|
|
25111
|
+
if (wasPlaying) daw.pause();
|
|
25112
|
+
daw?.setLoading?.(true);
|
|
25113
|
+
void loadPreset(
|
|
25114
|
+
key,
|
|
25115
|
+
trackIds,
|
|
25116
|
+
isAdvancedMode ? "advanced" : "simple"
|
|
25117
|
+
).finally(() => {
|
|
25118
|
+
daw?.setLoading?.(false);
|
|
25119
|
+
if (wasPlaying) daw?.play();
|
|
25120
|
+
});
|
|
25121
|
+
}
|
|
24485
25122
|
onInstrumentChange?.(key);
|
|
24486
25123
|
};
|
|
24487
25124
|
const handleTrackInstrumentChange = async (trackIndex, instrumentName) => {
|
|
@@ -24495,7 +25132,6 @@ var createDtmStudio = async (options = {}) => {
|
|
|
24495
25132
|
trackInstOverrides.set(trackIndex, key);
|
|
24496
25133
|
await loadInstrument(key);
|
|
24497
25134
|
};
|
|
24498
|
-
let daw;
|
|
24499
25135
|
const base = {
|
|
24500
25136
|
getAudioTime: () => audioCtx.currentTime,
|
|
24501
25137
|
onResumeAudio: async () => {
|
|
@@ -25245,6 +25881,7 @@ export {
|
|
|
25245
25881
|
EDO31_NAMES,
|
|
25246
25882
|
FADE_IN_MARK,
|
|
25247
25883
|
FADE_OUT_MARK,
|
|
25884
|
+
GLOBAL_STORAGE_KEYS,
|
|
25248
25885
|
GM_INSTRUMENT_NAMES,
|
|
25249
25886
|
INSTRUMENT_PRESETS,
|
|
25250
25887
|
KEY_COUNT,
|
|
@@ -25253,6 +25890,7 @@ export {
|
|
|
25253
25890
|
KOE_VOICEBANK_LABELS,
|
|
25254
25891
|
KOE_VOICEBANK_TERMS,
|
|
25255
25892
|
LinkedList,
|
|
25893
|
+
MACRO_STORAGE_KEYS,
|
|
25256
25894
|
MAJOR_KEY_IDS,
|
|
25257
25895
|
MAX_VOCAL_VOLUME,
|
|
25258
25896
|
MICRO_STEP,
|
|
@@ -25355,6 +25993,11 @@ export {
|
|
|
25355
25993
|
playNote,
|
|
25356
25994
|
playPlacements,
|
|
25357
25995
|
playSingingMML,
|
|
25996
|
+
readGlobalBool,
|
|
25997
|
+
readGlobalNumber,
|
|
25998
|
+
readGlobalSetting,
|
|
25999
|
+
readMacroSections,
|
|
26000
|
+
readMacroSetting,
|
|
25358
26001
|
resolveComposeKey,
|
|
25359
26002
|
resolveDrumPattern,
|
|
25360
26003
|
resolveLoopPoint,
|
|
@@ -25377,5 +26020,8 @@ export {
|
|
|
25377
26020
|
unitsToMidi,
|
|
25378
26021
|
unitsToMidiDetune,
|
|
25379
26022
|
unitsToPitchV1,
|
|
25380
|
-
vocalVolumeToGain
|
|
26023
|
+
vocalVolumeToGain,
|
|
26024
|
+
writeGlobalSetting,
|
|
26025
|
+
writeMacroSections,
|
|
26026
|
+
writeMacroSetting
|
|
25381
26027
|
};
|