@onjmin/dtm 2.1.4 → 2.1.5
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 +85 -9
- package/dist/index.d.ts +85 -9
- package/dist/index.js +753 -128
- package/dist/index.mjs +747 -127
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -52,6 +52,7 @@ __export(index_exports, {
|
|
|
52
52
|
KOE_VOICEBANK_LABELS: () => KOE_VOICEBANK_LABELS,
|
|
53
53
|
KOE_VOICEBANK_TERMS: () => KOE_VOICEBANK_TERMS,
|
|
54
54
|
LinkedList: () => LinkedList,
|
|
55
|
+
MACRO_STORAGE_KEYS: () => MACRO_STORAGE_KEYS,
|
|
55
56
|
MAJOR_KEY_IDS: () => MAJOR_KEY_IDS,
|
|
56
57
|
MAX_VOCAL_VOLUME: () => MAX_VOCAL_VOLUME,
|
|
57
58
|
MICRO_STEP: () => MICRO_STEP,
|
|
@@ -154,6 +155,8 @@ __export(index_exports, {
|
|
|
154
155
|
playNote: () => playNote,
|
|
155
156
|
playPlacements: () => playPlacements,
|
|
156
157
|
playSingingMML: () => playSingingMML,
|
|
158
|
+
readMacroSections: () => readMacroSections,
|
|
159
|
+
readMacroSetting: () => readMacroSetting,
|
|
157
160
|
resolveComposeKey: () => resolveComposeKey,
|
|
158
161
|
resolveDrumPattern: () => resolveDrumPattern,
|
|
159
162
|
resolveLoopPoint: () => resolveLoopPoint,
|
|
@@ -176,7 +179,9 @@ __export(index_exports, {
|
|
|
176
179
|
unitsToMidi: () => unitsToMidi,
|
|
177
180
|
unitsToMidiDetune: () => unitsToMidiDetune,
|
|
178
181
|
unitsToPitchV1: () => unitsToPitchV1,
|
|
179
|
-
vocalVolumeToGain: () => vocalVolumeToGain
|
|
182
|
+
vocalVolumeToGain: () => vocalVolumeToGain,
|
|
183
|
+
writeMacroSections: () => writeMacroSections,
|
|
184
|
+
writeMacroSetting: () => writeMacroSetting
|
|
180
185
|
});
|
|
181
186
|
module.exports = __toCommonJS(index_exports);
|
|
182
187
|
|
|
@@ -4910,6 +4915,7 @@ var createSequencer = (options) => {
|
|
|
4910
4915
|
let drumCursor = 0;
|
|
4911
4916
|
let lastDrumStep = Number.NEGATIVE_INFINITY;
|
|
4912
4917
|
let lastPlayStep = 0;
|
|
4918
|
+
let maxTimelineEndSec = 0;
|
|
4913
4919
|
const secondsPerStep = () => 60 / options.getBpm() / STEPS_PER_BEAT;
|
|
4914
4920
|
const getWrappedPlayStep = (time, sps) => {
|
|
4915
4921
|
if (!isLooping || loopDurationSec <= 0 || time < loopEndSec) {
|
|
@@ -4936,6 +4942,7 @@ var createSequencer = (options) => {
|
|
|
4936
4942
|
}
|
|
4937
4943
|
const startLimit = isLooping ? Math.min(fromStep, loopStartStep) : fromStep;
|
|
4938
4944
|
let maxEndStep = 0;
|
|
4945
|
+
maxTimelineEndSec = 0;
|
|
4939
4946
|
for (const track of options.getTracks()) {
|
|
4940
4947
|
trackVolumeMap.set(track.id, track.volume);
|
|
4941
4948
|
for (const note of track.notes) {
|
|
@@ -4944,6 +4951,7 @@ var createSequencer = (options) => {
|
|
|
4944
4951
|
const when = relativeStart * sps;
|
|
4945
4952
|
const duration = note.durationSteps * sps;
|
|
4946
4953
|
maxEndStep = Math.max(maxEndStep, note.startStep + note.durationSteps);
|
|
4954
|
+
maxTimelineEndSec = Math.max(maxTimelineEndSec, when + duration);
|
|
4947
4955
|
timeline.push({
|
|
4948
4956
|
trackId: track.id,
|
|
4949
4957
|
pitch: note.pitchUnits,
|
|
@@ -5069,10 +5077,7 @@ var createSequencer = (options) => {
|
|
|
5069
5077
|
lastPlayStep = currentStep2;
|
|
5070
5078
|
}
|
|
5071
5079
|
if (!isLooping) {
|
|
5072
|
-
|
|
5073
|
-
const lastWhen = last?.when ?? 0;
|
|
5074
|
-
const lastDuration = last?.duration ?? 0;
|
|
5075
|
-
if (nowIndex >= timeline.length && time > lastWhen + lastDuration + 0.1) {
|
|
5080
|
+
if (nowIndex >= timeline.length && time > maxTimelineEndSec + 0.1) {
|
|
5076
5081
|
stop();
|
|
5077
5082
|
options.onEnd(false);
|
|
5078
5083
|
}
|
|
@@ -8404,6 +8409,21 @@ var DAW_CSS = `
|
|
|
8404
8409
|
.dtm-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
|
|
8405
8410
|
.dtm-track-body { display: flex; flex-direction: column; gap: 10px; }
|
|
8406
8411
|
|
|
8412
|
+
/* \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 */
|
|
8413
|
+
.dtm-compose-container {
|
|
8414
|
+
background: var(--dtm-deep);
|
|
8415
|
+
border: 2px solid var(--c-black);
|
|
8416
|
+
box-shadow:
|
|
8417
|
+
inset 0 0 0 1px var(--dtm-border2),
|
|
8418
|
+
0 0 0 1px var(--dtm-success),
|
|
8419
|
+
3px 3px 0 var(--c-black);
|
|
8420
|
+
padding: 10px 12px 12px;
|
|
8421
|
+
display: flex;
|
|
8422
|
+
flex-direction: column;
|
|
8423
|
+
gap: 10px;
|
|
8424
|
+
margin-bottom: 6px;
|
|
8425
|
+
}
|
|
8426
|
+
|
|
8407
8427
|
/* \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 */
|
|
8408
8428
|
.dtm-panel--track > summary::before,
|
|
8409
8429
|
.dtm-panel--track[open] > summary::before {
|
|
@@ -13198,11 +13218,25 @@ var densityFeatures = (notes, opts) => {
|
|
|
13198
13218
|
shortNoteRatio: short / notes.length
|
|
13199
13219
|
};
|
|
13200
13220
|
};
|
|
13201
|
-
var tensionFeatures = (barTension) => {
|
|
13202
|
-
if (barTension.length <
|
|
13221
|
+
var tensionFeatures = (barTension, opts) => {
|
|
13222
|
+
if (barTension.length < 8) return { rise: 0, resolve: 0 };
|
|
13203
13223
|
const mean2 = (xs) => xs.reduce((a2, b2) => a2 + b2, 0) / Math.max(1, xs.length);
|
|
13204
|
-
|
|
13205
|
-
|
|
13224
|
+
let a;
|
|
13225
|
+
let b;
|
|
13226
|
+
if (opts?.verseBars && opts?.chorusBars && opts.verseBars.length > 0 && opts.chorusBars.length > 0) {
|
|
13227
|
+
a = mean2(opts.verseBars.map((i2) => barTension[i2] ?? 0));
|
|
13228
|
+
b = mean2(opts.chorusBars.map((i2) => barTension[i2] ?? 0));
|
|
13229
|
+
} else if (barTension.length >= 16 && barTension.length <= 24) {
|
|
13230
|
+
a = mean2(barTension.slice(0, 4));
|
|
13231
|
+
b = mean2(barTension.slice(8, 12));
|
|
13232
|
+
} else {
|
|
13233
|
+
const q1Start = Math.floor(barTension.length * 0.15);
|
|
13234
|
+
const q1End = Math.max(q1Start + 2, Math.floor(barTension.length * 0.35));
|
|
13235
|
+
const q3Start = Math.floor(barTension.length * 0.55);
|
|
13236
|
+
const q3End = Math.max(q3Start + 2, Math.floor(barTension.length * 0.75));
|
|
13237
|
+
a = mean2(barTension.slice(q1Start, q1End));
|
|
13238
|
+
b = mean2(barTension.slice(q3Start, q3End));
|
|
13239
|
+
}
|
|
13206
13240
|
const all = mean2(barTension);
|
|
13207
13241
|
const last = barTension[barTension.length - 1];
|
|
13208
13242
|
const rise = Math.max(0, Math.min(1, (b - a) / 0.5));
|
|
@@ -13249,6 +13283,8 @@ var SECTION_LABELS = {
|
|
|
13249
13283
|
verse: "A\u30E1\u30ED",
|
|
13250
13284
|
prechorus: "B\u30E1\u30ED",
|
|
13251
13285
|
chorus: "\u30B5\u30D3",
|
|
13286
|
+
bridge: "C\u30E1\u30ED",
|
|
13287
|
+
drop_chorus: "\u843D\u3061\u30B5\u30D3",
|
|
13252
13288
|
interlude: "\u9593\u594F",
|
|
13253
13289
|
outro: "\u30A2\u30A6\u30C8\u30ED"
|
|
13254
13290
|
};
|
|
@@ -13257,6 +13293,8 @@ var SECTION_ORDER = [
|
|
|
13257
13293
|
"verse",
|
|
13258
13294
|
"prechorus",
|
|
13259
13295
|
"chorus",
|
|
13296
|
+
"bridge",
|
|
13297
|
+
"drop_chorus",
|
|
13260
13298
|
"interlude",
|
|
13261
13299
|
"outro"
|
|
13262
13300
|
];
|
|
@@ -13308,6 +13346,35 @@ var SECTION_SPECS = {
|
|
|
13308
13346
|
// 主音へ全終止
|
|
13309
13347
|
progression: "b"
|
|
13310
13348
|
},
|
|
13349
|
+
// Cメロ。Verse/Pre chorusとは違うメロディで、ラストのサビ前に緊張感を持たせる。
|
|
13350
|
+
// 2番のサビの後に来ることが多い(参考: ONLIVE Studio blog)。
|
|
13351
|
+
// 専用のコード進行 "c" を持ち、AメロともBメロとも雰囲気が違う。
|
|
13352
|
+
bridge: {
|
|
13353
|
+
bars: 4,
|
|
13354
|
+
melody: true,
|
|
13355
|
+
registerShift: 2,
|
|
13356
|
+
density: 0.9,
|
|
13357
|
+
drumLevel: 1,
|
|
13358
|
+
landing: 1,
|
|
13359
|
+
// 解決しない音で止めてラスサビへ渡す
|
|
13360
|
+
progression: "c"
|
|
13361
|
+
},
|
|
13362
|
+
// 落ちサビ。サビのメロディを伴奏控えめに歌う。J-POPの王道パターン。
|
|
13363
|
+
// density と drumLevel だけ下げ、メロディはサビと同じものを使う。
|
|
13364
|
+
drop_chorus: {
|
|
13365
|
+
bars: 4,
|
|
13366
|
+
melody: true,
|
|
13367
|
+
registerShift: 4,
|
|
13368
|
+
// サビと同じ高さ
|
|
13369
|
+
density: 0.6,
|
|
13370
|
+
// 薄い(ここが「落ち」の実体)
|
|
13371
|
+
drumLevel: 0,
|
|
13372
|
+
// ドラム控えめ
|
|
13373
|
+
landing: 0,
|
|
13374
|
+
// 主音へ全終止
|
|
13375
|
+
progression: "b"
|
|
13376
|
+
// サビと同じ進行
|
|
13377
|
+
},
|
|
13311
13378
|
interlude: {
|
|
13312
13379
|
bars: 4,
|
|
13313
13380
|
melody: false,
|
|
@@ -13327,18 +13394,120 @@ var SECTION_SPECS = {
|
|
|
13327
13394
|
progression: "a"
|
|
13328
13395
|
}
|
|
13329
13396
|
};
|
|
13330
|
-
var
|
|
13331
|
-
|
|
13332
|
-
|
|
13397
|
+
var STRUCTURE_TEMPLATES = [
|
|
13398
|
+
// 1コーラス(現行デフォルト、短い曲・初心者向け)
|
|
13399
|
+
{
|
|
13400
|
+
name: "1chorus",
|
|
13401
|
+
label: "1\u30B3\u30FC\u30E9\u30B9",
|
|
13402
|
+
plan: ["intro", "verse", "prechorus", "chorus"]
|
|
13403
|
+
},
|
|
13404
|
+
// JPOP王道(マリーゴールド型)
|
|
13405
|
+
// イントロ→Aメロ→Aメロ→Bメロ→サビ→Aメロ→Bメロ→サビ→Cメロ→間奏→サビ→アウトロ
|
|
13406
|
+
{
|
|
13407
|
+
name: "jpop_standard",
|
|
13408
|
+
label: "JPOP\u738B\u9053",
|
|
13409
|
+
plan: [
|
|
13410
|
+
"intro",
|
|
13411
|
+
"verse",
|
|
13412
|
+
"verse",
|
|
13413
|
+
"prechorus",
|
|
13414
|
+
"chorus",
|
|
13415
|
+
"verse",
|
|
13416
|
+
"prechorus",
|
|
13417
|
+
"chorus",
|
|
13418
|
+
"bridge",
|
|
13419
|
+
"interlude",
|
|
13420
|
+
"chorus",
|
|
13421
|
+
"outro"
|
|
13422
|
+
]
|
|
13423
|
+
},
|
|
13424
|
+
// 落ちサビ入り(J-POP王道の変形。ラスサビ前に落ちサビ)
|
|
13425
|
+
{
|
|
13426
|
+
name: "jpop_drop",
|
|
13427
|
+
label: "\u843D\u3061\u30B5\u30D3\u5165\u308A",
|
|
13428
|
+
plan: [
|
|
13429
|
+
"intro",
|
|
13430
|
+
"verse",
|
|
13431
|
+
"verse",
|
|
13432
|
+
"prechorus",
|
|
13433
|
+
"chorus",
|
|
13434
|
+
"verse",
|
|
13435
|
+
"prechorus",
|
|
13436
|
+
"chorus",
|
|
13437
|
+
"bridge",
|
|
13438
|
+
"drop_chorus",
|
|
13439
|
+
"chorus",
|
|
13440
|
+
"outro"
|
|
13441
|
+
]
|
|
13442
|
+
},
|
|
13443
|
+
// ボカロ王道(短め高速、Aメロ繰り返しなし)
|
|
13444
|
+
{
|
|
13445
|
+
name: "vocaloid",
|
|
13446
|
+
label: "\u30DC\u30AB\u30ED\u738B\u9053",
|
|
13447
|
+
plan: [
|
|
13448
|
+
"intro",
|
|
13449
|
+
"verse",
|
|
13450
|
+
"prechorus",
|
|
13451
|
+
"chorus",
|
|
13452
|
+
"verse",
|
|
13453
|
+
"prechorus",
|
|
13454
|
+
"chorus",
|
|
13455
|
+
"bridge",
|
|
13456
|
+
"chorus",
|
|
13457
|
+
"outro"
|
|
13458
|
+
]
|
|
13459
|
+
},
|
|
13460
|
+
// Verse-Chorus形式(Bメロなし、洋楽的)
|
|
13461
|
+
{
|
|
13462
|
+
name: "verse_chorus",
|
|
13463
|
+
label: "Verse-Chorus",
|
|
13464
|
+
plan: [
|
|
13465
|
+
"intro",
|
|
13466
|
+
"verse",
|
|
13467
|
+
"chorus",
|
|
13468
|
+
"verse",
|
|
13469
|
+
"chorus",
|
|
13470
|
+
"bridge",
|
|
13471
|
+
"chorus",
|
|
13472
|
+
"outro"
|
|
13473
|
+
]
|
|
13474
|
+
}
|
|
13475
|
+
];
|
|
13476
|
+
var buildSectionPlan = (kinds, templateName) => {
|
|
13477
|
+
let ordered;
|
|
13478
|
+
if (templateName) {
|
|
13479
|
+
const tmpl = STRUCTURE_TEMPLATES.find((t) => t.name === templateName);
|
|
13480
|
+
ordered = tmpl ? tmpl.plan : DEFAULT_SECTIONS;
|
|
13481
|
+
} else {
|
|
13482
|
+
const wanted = kinds.length > 0 ? kinds : DEFAULT_SECTIONS;
|
|
13483
|
+
ordered = SECTION_ORDER.filter((k) => wanted.includes(k));
|
|
13484
|
+
}
|
|
13333
13485
|
const plan = [];
|
|
13334
13486
|
let bar = 0;
|
|
13487
|
+
const seen = /* @__PURE__ */ new Map();
|
|
13335
13488
|
for (const kind of ordered) {
|
|
13336
13489
|
const spec = SECTION_SPECS[kind];
|
|
13337
|
-
|
|
13490
|
+
const count = seen.get(kind) ?? 0;
|
|
13491
|
+
plan.push({
|
|
13492
|
+
kind,
|
|
13493
|
+
startBar: bar,
|
|
13494
|
+
bars: spec.bars,
|
|
13495
|
+
spec,
|
|
13496
|
+
keyShift: 0,
|
|
13497
|
+
restatement: count > 0
|
|
13498
|
+
});
|
|
13499
|
+
seen.set(kind, count + 1);
|
|
13338
13500
|
bar += spec.bars;
|
|
13339
13501
|
}
|
|
13340
13502
|
return plan;
|
|
13341
13503
|
};
|
|
13504
|
+
var sectionAt = (plan, bar) => {
|
|
13505
|
+
for (const section of plan) {
|
|
13506
|
+
if (bar >= section.startBar && bar < section.startBar + section.bars)
|
|
13507
|
+
return section;
|
|
13508
|
+
}
|
|
13509
|
+
return plan[plan.length - 1];
|
|
13510
|
+
};
|
|
13342
13511
|
|
|
13343
13512
|
// src/compose.ts
|
|
13344
13513
|
var STEP_SEMITONES = 2;
|
|
@@ -13624,6 +13793,16 @@ var SECTION_A_PROGRESSIONS = [
|
|
|
13624
13793
|
["Am", "Dm7", "Bb", "E7"]
|
|
13625
13794
|
// bVI からドミナントへ
|
|
13626
13795
|
];
|
|
13796
|
+
var SECTION_C_PROGRESSIONS = [
|
|
13797
|
+
["Am", "Em", "F", "C"],
|
|
13798
|
+
["Dm7", "Em7", "FM7", "G7"],
|
|
13799
|
+
["Am7", "Dm7", "G7", "CM7"],
|
|
13800
|
+
["F", "G", "Am", "G"],
|
|
13801
|
+
["Dm7", "G7", "Em7", "Am"],
|
|
13802
|
+
["FM7", "Em7", "Am7", "Dm7"],
|
|
13803
|
+
["Am", "G", "FM7", "E7"],
|
|
13804
|
+
["C", "Am", "FM7", "G7"]
|
|
13805
|
+
];
|
|
13627
13806
|
var SECTION_B_PROGRESSIONS = [
|
|
13628
13807
|
["F", "G", "Em7", "Am"],
|
|
13629
13808
|
["Dm7", "G7", "CM7", "A7"],
|
|
@@ -13850,10 +14029,9 @@ var HALF_BAR_FIGURES = [
|
|
|
13850
14029
|
[EIGHTH, EIGHTH, EIGHTH, EIGHTH],
|
|
13851
14030
|
// タタタタ
|
|
13852
14031
|
[EIGHTH, EIGHTH, EIGHTH, EIGHTH],
|
|
13853
|
-
[EIGHTH, EIGHTH, EIGHTH, EIGHTH],
|
|
13854
|
-
[EIGHTH, EIGHTH, EIGHTH, EIGHTH],
|
|
13855
14032
|
[QUARTER, EIGHTH, EIGHTH],
|
|
13856
14033
|
// ター・タタ
|
|
14034
|
+
[QUARTER, EIGHTH, EIGHTH],
|
|
13857
14035
|
[EIGHTH, EIGHTH, QUARTER],
|
|
13858
14036
|
// タタ・ター
|
|
13859
14037
|
[DOT_QUARTER, EIGHTH],
|
|
@@ -13861,8 +14039,24 @@ var HALF_BAR_FIGURES = [
|
|
|
13861
14039
|
[DOT_QUARTER, EIGHTH],
|
|
13862
14040
|
[EIGHTH, QUARTER, EIGHTH],
|
|
13863
14041
|
// 頭抜き
|
|
14042
|
+
// 4分音符主体・ロングトーン(J-POPの歌い上げるバラード〜ミドル向け。音数過多を是正)
|
|
14043
|
+
[QUARTER, QUARTER],
|
|
14044
|
+
// ター・ター
|
|
14045
|
+
[QUARTER, QUARTER],
|
|
13864
14046
|
[HALF],
|
|
13865
|
-
//
|
|
14047
|
+
// ターーー
|
|
14048
|
+
[HALF],
|
|
14049
|
+
[-QUARTER, QUARTER],
|
|
14050
|
+
// 休・ター
|
|
14051
|
+
[QUARTER, -QUARTER],
|
|
14052
|
+
// ター・休
|
|
14053
|
+
// 弱起(アウフタクト)パターン:末尾から次へ飛び込む言い回し
|
|
14054
|
+
[-DOT_QUARTER, EIGHTH],
|
|
14055
|
+
// 3拍半休みからの裏拍アウフタクト
|
|
14056
|
+
[-QUARTER, EIGHTH, EIGHTH],
|
|
14057
|
+
// 2拍目裏からのアウフタクト(タタ)
|
|
14058
|
+
[QUARTER, -EIGHTH, EIGHTH],
|
|
14059
|
+
// ター・休タ(8分裏弱起)
|
|
13866
14060
|
// 付点8分+16分(タッカ)。歌モノで非常に多用される跳ね・推進力の型。
|
|
13867
14061
|
[DOT_EIGHTH, SIXTEENTH, EIGHTH, EIGHTH],
|
|
13868
14062
|
[EIGHTH, EIGHTH, DOT_EIGHTH, SIXTEENTH],
|
|
@@ -14531,7 +14725,10 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14531
14725
|
};
|
|
14532
14726
|
const quarterSteps = scaleStep(QUARTER);
|
|
14533
14727
|
const strongStep = Math.max(1, Math.round(stepsPerBar / 2));
|
|
14534
|
-
const sectionPlan = buildSectionPlan(
|
|
14728
|
+
const sectionPlan = buildSectionPlan(
|
|
14729
|
+
options.sections ?? DEFAULT_SECTIONS,
|
|
14730
|
+
options.template
|
|
14731
|
+
);
|
|
14535
14732
|
const totalBars = sectionPlan.reduce((sum, s) => sum + s.bars, 0);
|
|
14536
14733
|
if (rnd() < 0.35) {
|
|
14537
14734
|
const modType = pick(
|
|
@@ -14568,12 +14765,18 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14568
14765
|
(p) => p.join("|") !== progA.join("|")
|
|
14569
14766
|
);
|
|
14570
14767
|
const progB = pick(progBPool, rnd);
|
|
14768
|
+
const progC = pick(
|
|
14769
|
+
SECTION_C_PROGRESSIONS.filter(
|
|
14770
|
+
(p) => p.join("|") !== progA.join("|") && p.join("|") !== progB.join("|")
|
|
14771
|
+
),
|
|
14772
|
+
rnd
|
|
14773
|
+
);
|
|
14571
14774
|
const tonic = progA[0].startsWith("Am") ? "Am" : "C";
|
|
14572
14775
|
const progHalf = pick(SECTION_A2_DERIVATIONS, rnd)(progA);
|
|
14573
14776
|
const progFull = pick(SECTION_A3_DERIVATIONS, rnd)(progA, tonic);
|
|
14574
14777
|
const progression = [];
|
|
14575
14778
|
for (const section of sectionPlan) {
|
|
14576
|
-
const base = section.spec.progression === "b" ? progB : progA;
|
|
14779
|
+
const base = section.spec.progression === "c" ? progC : section.spec.progression === "b" ? progB : progA;
|
|
14577
14780
|
for (let i2 = 0; i2 < section.bars; i2 += 4) {
|
|
14578
14781
|
const isLastPhrase = i2 + 4 >= section.bars;
|
|
14579
14782
|
if (!isLastPhrase) {
|
|
@@ -14591,7 +14794,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14591
14794
|
const chordPattern = pick(CHORD_PATTERNS, rnd);
|
|
14592
14795
|
const rootShift = resolvedKey.rootShift;
|
|
14593
14796
|
const bpm = pick(BPM_CHOICES, rnd);
|
|
14594
|
-
const sourceOf = (kind) => kind === "chorus" || kind === "interlude" ? "b" : kind === "prechorus" ? "a2" : "a";
|
|
14797
|
+
const sourceOf = (kind) => kind === "chorus" || kind === "interlude" || kind === "drop_chorus" ? "b" : kind === "prechorus" ? "a2" : kind === "bridge" ? "c" : "a";
|
|
14595
14798
|
const units2 = [];
|
|
14596
14799
|
for (const section of sectionPlan) {
|
|
14597
14800
|
const unitCount = Math.max(1, Math.round(section.bars / 2));
|
|
@@ -14628,6 +14831,19 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14628
14831
|
const barInUnit = (bar) => bar % 2;
|
|
14629
14832
|
const unitOf = (bar) => Math.floor(bar / 2);
|
|
14630
14833
|
const restatementOf = (bar) => {
|
|
14834
|
+
const curSec = sectionAt(sectionPlan, bar);
|
|
14835
|
+
if (!curSec.spec.melody) return null;
|
|
14836
|
+
if (curSec.restatement) {
|
|
14837
|
+
const firstSec = sectionPlan.find(
|
|
14838
|
+
(s) => s.kind === curSec.kind && !s.restatement
|
|
14839
|
+
);
|
|
14840
|
+
if (firstSec) {
|
|
14841
|
+
const offset = bar - curSec.startBar;
|
|
14842
|
+
if (offset < firstSec.bars) {
|
|
14843
|
+
return firstSec.startBar + offset;
|
|
14844
|
+
}
|
|
14845
|
+
}
|
|
14846
|
+
}
|
|
14631
14847
|
const u = unitOf(bar);
|
|
14632
14848
|
if (units2[u].source === "silent") return null;
|
|
14633
14849
|
for (let v = 0; v < u; v++) {
|
|
@@ -14657,10 +14873,9 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14657
14873
|
),
|
|
14658
14874
|
// 人間の曲の跳躍率は p25〜p75 で 0.40〜0.55。上限が低いとその帯へ届かない。
|
|
14659
14875
|
leapAffinity: 0.08 + rnd() * 0.3,
|
|
14660
|
-
//
|
|
14661
|
-
|
|
14662
|
-
|
|
14663
|
-
barHeadWeight: rnd() < 0.65 ? 3 : 2,
|
|
14876
|
+
// 界隈曲らしさ:調の外の音(クロマチック)や微小な逸脱を積極的に許容する。
|
|
14877
|
+
chromaticAffinity: rnd() < 0.1 ? 0 : 0.3 + rnd() * 0.6,
|
|
14878
|
+
barHeadWeight: rnd() < 0.5 ? 3 : 2,
|
|
14664
14879
|
bassStyle: pick(
|
|
14665
14880
|
[
|
|
14666
14881
|
"quarter",
|
|
@@ -14686,7 +14901,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14686
14901
|
subInterval: pick([3, 4, 8, 9], rnd)
|
|
14687
14902
|
};
|
|
14688
14903
|
const motifPool = groovyCells(MOTIF_CELLS, style.groove, rnd);
|
|
14689
|
-
const targetNotesPerBar =
|
|
14904
|
+
const targetNotesPerBar = 4 + rnd() * 4;
|
|
14690
14905
|
const targetRestRatio = 0.02 + rnd() * 0.1;
|
|
14691
14906
|
const cellNotes = (c) => c.value.filter((v) => v > 0).length;
|
|
14692
14907
|
const cellRest = (c) => {
|
|
@@ -14698,27 +14913,49 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14698
14913
|
}
|
|
14699
14914
|
return total === 0 ? 0 : rest / total;
|
|
14700
14915
|
};
|
|
14701
|
-
const cellDistance = (c) => Math.abs(cellNotes(c) - targetNotesPerBar) + Math.abs(cellRest(c) - targetRestRatio) * 8;
|
|
14702
|
-
const pickCell = (pool) => {
|
|
14916
|
+
const cellDistance = (c, densityMul = 1) => Math.abs(cellNotes(c) - targetNotesPerBar * densityMul) + Math.abs(cellRest(c) - targetRestRatio / Math.max(0.5, densityMul)) * 8;
|
|
14917
|
+
const pickCell = (pool, densityMul = 1) => {
|
|
14703
14918
|
let best = pick(pool, rnd);
|
|
14704
14919
|
for (let i2 = 0; i2 < 2; i2++) {
|
|
14705
14920
|
const c = pick(pool, rnd);
|
|
14706
|
-
if (cellDistance(c) < cellDistance(best))
|
|
14921
|
+
if (cellDistance(c, densityMul) < cellDistance(best, densityMul))
|
|
14922
|
+
best = c;
|
|
14707
14923
|
}
|
|
14708
14924
|
return best;
|
|
14709
14925
|
};
|
|
14710
|
-
const motifCell = pickCell(motifPool);
|
|
14711
|
-
const motifCell2 = rnd() < 0.45 ? motifCell : pickCell(
|
|
14926
|
+
const motifCell = pickCell(motifPool, 0.85);
|
|
14927
|
+
const motifCell2 = rnd() < 0.45 ? motifCell : pickCell(
|
|
14928
|
+
motifPool.filter((c) => c !== motifCell),
|
|
14929
|
+
0.85
|
|
14930
|
+
);
|
|
14712
14931
|
const motifB = pickCell(
|
|
14713
|
-
motifPool.filter((c) => c !== motifCell && c !== motifCell2)
|
|
14932
|
+
motifPool.filter((c) => c !== motifCell && c !== motifCell2),
|
|
14933
|
+
1.2
|
|
14934
|
+
);
|
|
14935
|
+
const motifB2 = pickCell(
|
|
14936
|
+
motifPool.filter((c) => c !== motifB),
|
|
14937
|
+
1.2
|
|
14714
14938
|
);
|
|
14715
|
-
const motifB2 = pickCell(motifPool.filter((c) => c !== motifB));
|
|
14716
14939
|
const motifA2 = pickCell(
|
|
14717
14940
|
motifPool.filter(
|
|
14718
14941
|
(c) => c !== motifCell && c !== motifCell2 && c !== motifB
|
|
14719
|
-
)
|
|
14942
|
+
),
|
|
14943
|
+
1.1
|
|
14944
|
+
);
|
|
14945
|
+
const motifA22 = rnd() < 0.45 ? motifA2 : pickCell(
|
|
14946
|
+
motifPool.filter((c) => c !== motifA2),
|
|
14947
|
+
1.1
|
|
14948
|
+
);
|
|
14949
|
+
const motifC = pickCell(
|
|
14950
|
+
motifPool.filter(
|
|
14951
|
+
(c) => c !== motifCell && c !== motifCell2 && c !== motifB && c !== motifA2
|
|
14952
|
+
),
|
|
14953
|
+
0.9
|
|
14954
|
+
);
|
|
14955
|
+
const motifC2 = rnd() < 0.45 ? motifC : pickCell(
|
|
14956
|
+
motifPool.filter((c) => c !== motifC),
|
|
14957
|
+
0.9
|
|
14720
14958
|
);
|
|
14721
|
-
const motifA22 = rnd() < 0.45 ? motifA2 : pickCell(motifPool.filter((c) => c !== motifA2));
|
|
14722
14959
|
const motifVar = pickCell(
|
|
14723
14960
|
motifPool.filter((c) => c !== motifCell && c !== motifCell2)
|
|
14724
14961
|
);
|
|
@@ -14771,12 +15008,13 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14771
15008
|
}
|
|
14772
15009
|
const isB = units2[u].source === "b";
|
|
14773
15010
|
const isA2 = units2[u].source === "a2";
|
|
15011
|
+
const isC = units2[u].source === "c";
|
|
14774
15012
|
const isPrechorusEnd = units2[u].section.kind === "prechorus" && bar === units2[u].section.startBar + units2[u].section.bars - 1;
|
|
14775
15013
|
if (isPrechorusEnd) {
|
|
14776
15014
|
barRhythms.push(scaleCell(buildUpCell.value));
|
|
14777
15015
|
continue;
|
|
14778
15016
|
}
|
|
14779
|
-
const pair = () => isB ? [motifB, motifB2] : isA2 ? [motifA2, motifA22] : [motifCell, motifCell2];
|
|
15017
|
+
const pair = () => isB ? [motifB, motifB2] : isA2 ? [motifA2, motifA22] : isC ? [motifC, motifC2] : [motifCell, motifCell2];
|
|
14780
15018
|
let cell;
|
|
14781
15019
|
if (units2[u].source === "answer") {
|
|
14782
15020
|
const isPeriodEnd = units2[u].landing !== null;
|
|
@@ -14807,6 +15045,8 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14807
15045
|
const melody = [];
|
|
14808
15046
|
const submelody = [];
|
|
14809
15047
|
const bass = [];
|
|
15048
|
+
const harmony = [];
|
|
15049
|
+
const pad = [];
|
|
14810
15050
|
const melodyDurations = [];
|
|
14811
15051
|
const barTension = new Array(totalBars).fill(0);
|
|
14812
15052
|
let restSteps = 0;
|
|
@@ -14853,13 +15093,22 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
14853
15093
|
(bar + style.arcPhase) / style.arcPeriod * Math.PI * 2
|
|
14854
15094
|
);
|
|
14855
15095
|
const arcCenter = MELODY_CENTER + arc * style.arcAmp;
|
|
14856
|
-
const
|
|
14857
|
-
|
|
14858
|
-
|
|
14859
|
-
tones,
|
|
14860
|
-
|
|
14861
|
-
|
|
14862
|
-
|
|
15096
|
+
const inUnit = barInUnit(bar);
|
|
15097
|
+
let headSemi;
|
|
15098
|
+
if (inUnit === 1 && bar > 0) {
|
|
15099
|
+
headSemi = nearestChordTone(prevSemi, tones, headWeight, isSectionB).semi;
|
|
15100
|
+
if (Math.abs(headSemi - prevSemi) > 4) {
|
|
15101
|
+
headSemi = nearestChordTone(prevSemi, tones, 1, isSectionB).semi;
|
|
15102
|
+
}
|
|
15103
|
+
} else {
|
|
15104
|
+
const headTarget = prevSemi + (arcCenter - prevSemi) * 0.5;
|
|
15105
|
+
headSemi = nearestChordTone(
|
|
15106
|
+
headTarget,
|
|
15107
|
+
tones,
|
|
15108
|
+
headWeight,
|
|
15109
|
+
isSectionB
|
|
15110
|
+
).semi;
|
|
15111
|
+
}
|
|
14863
15112
|
const contourOffset = barInUnit(bar) === 0 ? 0 : barRhythms[bar - 1].filter((v) => v > 0).length;
|
|
14864
15113
|
const prevRole = bar > 0 ? barRoles[bar - 1] : null;
|
|
14865
15114
|
const repeatShift = role === "motif" && (prevRole === "motif" || prevRole === "sequence" || prevRole === "climax") ? pick([-2, -1, 1, 2], rnd) : 0;
|
|
@@ -15039,6 +15288,48 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15039
15288
|
} else {
|
|
15040
15289
|
pushSub(scaleStep(QUARTER), scaleStep(DOT_HALF), subSemi);
|
|
15041
15290
|
}
|
|
15291
|
+
const barSec = sectionAt(sectionPlan, bar);
|
|
15292
|
+
if (!silent && (barSec.kind === "chorus" || barSec.kind === "drop_chorus")) {
|
|
15293
|
+
for (let i2 = 0; i2 < slots.length; i2++) {
|
|
15294
|
+
const hSemi = pitches[i2] + 3;
|
|
15295
|
+
const hTone = nearestChordTone(hSemi, tones, 2);
|
|
15296
|
+
const hClamped = clampSemi(hTone.semi, MELODY_LOW, MELODY_HIGH);
|
|
15297
|
+
const k = barKeyShift[bar];
|
|
15298
|
+
const fifthShift = k === 0 ? 0 : SEMITONE_TO_FIFTH_SHIFT[(k % 12 + 12) % 12];
|
|
15299
|
+
harmony.push({
|
|
15300
|
+
startStep: barStart + slots[i2].at,
|
|
15301
|
+
pitchUnits: spelledToUnits(
|
|
15302
|
+
hClamped + k,
|
|
15303
|
+
hTone.fifth + fifthShift,
|
|
15304
|
+
edo
|
|
15305
|
+
),
|
|
15306
|
+
durationSteps: slots[i2].value,
|
|
15307
|
+
velocity: slots[i2].at === 0 ? 82 : 76
|
|
15308
|
+
});
|
|
15309
|
+
}
|
|
15310
|
+
}
|
|
15311
|
+
if (barSec.kind === "prechorus" || barSec.kind === "chorus" || barSec.kind === "bridge" || barSec.kind === "drop_chorus") {
|
|
15312
|
+
const padTone = nearestChordTone(
|
|
15313
|
+
MELODY_HIGH + 2,
|
|
15314
|
+
// メロディの上の音域
|
|
15315
|
+
tones,
|
|
15316
|
+
2
|
|
15317
|
+
);
|
|
15318
|
+
const padSemi = clampSemi(padTone.semi, MELODY_HIGH - 4, MELODY_HIGH + 8);
|
|
15319
|
+
const k = barKeyShift[bar];
|
|
15320
|
+
const fifthShift = k === 0 ? 0 : SEMITONE_TO_FIFTH_SHIFT[(k % 12 + 12) % 12];
|
|
15321
|
+
pad.push({
|
|
15322
|
+
startStep: barStart,
|
|
15323
|
+
pitchUnits: spelledToUnits(
|
|
15324
|
+
padSemi + k,
|
|
15325
|
+
padTone.fifth + fifthShift,
|
|
15326
|
+
edo
|
|
15327
|
+
),
|
|
15328
|
+
durationSteps: stepsPerBar,
|
|
15329
|
+
// 小節全体を伸ばす
|
|
15330
|
+
velocity: barSec.kind === "drop_chorus" ? 50 : 62
|
|
15331
|
+
});
|
|
15332
|
+
}
|
|
15042
15333
|
const rootTone = tones[0];
|
|
15043
15334
|
const fifthTone = tones.find((t) => t.weight === 3 && t !== rootTone);
|
|
15044
15335
|
const thirdTone = tones.find((t) => t.weight === 2);
|
|
@@ -15145,6 +15436,69 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15145
15436
|
}
|
|
15146
15437
|
for (const n of barBass) bass.push(n);
|
|
15147
15438
|
}
|
|
15439
|
+
const eighthSteps = scaleStep(EIGHTH);
|
|
15440
|
+
for (let i2 = 0; i2 < melody.length - 1; i2++) {
|
|
15441
|
+
const cur = melody[i2];
|
|
15442
|
+
const nxt = melody[i2 + 1];
|
|
15443
|
+
const curEnd = cur.startStep + cur.durationSteps;
|
|
15444
|
+
const atBarBoundary = curEnd % stepsPerBar === 0 && nxt.startStep === curEnd;
|
|
15445
|
+
if (!atBarBoundary) continue;
|
|
15446
|
+
if (cur.durationSteps > eighthSteps) continue;
|
|
15447
|
+
const barIdx = Math.floor(curEnd / stepsPerBar);
|
|
15448
|
+
if (barIdx >= totalBars) continue;
|
|
15449
|
+
if (i2 + 1 >= melody.length - 1) continue;
|
|
15450
|
+
const curSec = sectionAt(sectionPlan, barIdx - 1);
|
|
15451
|
+
const nextSec = sectionAt(sectionPlan, barIdx);
|
|
15452
|
+
if (!nextSec.spec.melody || curSec !== nextSec) continue;
|
|
15453
|
+
const curSemi = Math.round(cur.pitchUnits / UNITS_PER_SEMITONE);
|
|
15454
|
+
const nxtSemi = Math.round(nxt.pitchUnits / UNITS_PER_SEMITONE);
|
|
15455
|
+
if (Math.abs(nxtSemi - curSemi) > 3) continue;
|
|
15456
|
+
const nextRole = barRoles[barIdx];
|
|
15457
|
+
let tieProb = 0.4;
|
|
15458
|
+
if (nextRole === "motif") tieProb = 0.05;
|
|
15459
|
+
else if (nextRole === "sequence") tieProb = 0.75;
|
|
15460
|
+
else if (nextRole === "climax") tieProb = 0.9;
|
|
15461
|
+
else if (nextRole === "cadence") tieProb = 0.1;
|
|
15462
|
+
if (rnd() < tieProb) {
|
|
15463
|
+
cur.durationSteps += nxt.durationSteps;
|
|
15464
|
+
melody.splice(i2 + 1, 1);
|
|
15465
|
+
if (i2 < melodyDurations.length - 1) {
|
|
15466
|
+
melodyDurations[i2] += melodyDurations[i2 + 1];
|
|
15467
|
+
melodyDurations.splice(i2 + 1, 1);
|
|
15468
|
+
}
|
|
15469
|
+
const hCurIdx = harmony.findIndex((h) => h.startStep === cur.startStep);
|
|
15470
|
+
const hNxtIdx = harmony.findIndex((h) => h.startStep === nxt.startStep);
|
|
15471
|
+
if (hCurIdx >= 0 && hNxtIdx >= 0) {
|
|
15472
|
+
harmony[hCurIdx].durationSteps += harmony[hNxtIdx].durationSteps;
|
|
15473
|
+
harmony.splice(hNxtIdx, 1);
|
|
15474
|
+
}
|
|
15475
|
+
i2--;
|
|
15476
|
+
}
|
|
15477
|
+
}
|
|
15478
|
+
for (let i2 = 0; i2 < melody.length; i2++) {
|
|
15479
|
+
const barIdx = Math.floor(melody[i2].startStep / stepsPerBar);
|
|
15480
|
+
if (barIdx >= totalBars) continue;
|
|
15481
|
+
const role = barRoles[barIdx];
|
|
15482
|
+
let splitProb = 0.15;
|
|
15483
|
+
if (role === "motif" || role === "sequence") splitProb = 0;
|
|
15484
|
+
else if (role === "climax") splitProb = 0.6;
|
|
15485
|
+
else if (role === "cadence") splitProb = 0;
|
|
15486
|
+
if (rnd() < splitProb && melody[i2].durationSteps === quarterSteps) {
|
|
15487
|
+
const half = scaleStep(EIGHTH);
|
|
15488
|
+
const newNote = {
|
|
15489
|
+
...melody[i2],
|
|
15490
|
+
startStep: melody[i2].startStep + half,
|
|
15491
|
+
durationSteps: half
|
|
15492
|
+
};
|
|
15493
|
+
melody[i2].durationSteps = half;
|
|
15494
|
+
melody.splice(i2 + 1, 0, newNote);
|
|
15495
|
+
if (i2 < melodyDurations.length) {
|
|
15496
|
+
melodyDurations[i2] = half;
|
|
15497
|
+
melodyDurations.splice(i2 + 1, 0, half);
|
|
15498
|
+
}
|
|
15499
|
+
i2++;
|
|
15500
|
+
}
|
|
15501
|
+
}
|
|
15148
15502
|
const range = (notes) => {
|
|
15149
15503
|
if (notes.length === 0) return 0;
|
|
15150
15504
|
const us = notes.map((n) => n.pitchUnits);
|
|
@@ -15152,7 +15506,7 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15152
15506
|
};
|
|
15153
15507
|
const shiftUnits = semitonesToUnits(rootShift, edo);
|
|
15154
15508
|
if (shiftUnits !== 0)
|
|
15155
|
-
for (const list of [melody, submelody, bass])
|
|
15509
|
+
for (const list of [melody, submelody, bass, harmony, pad])
|
|
15156
15510
|
for (const n of list) n.pitchUnits = n.pitchUnits + shiftUnits;
|
|
15157
15511
|
return {
|
|
15158
15512
|
chordProgression,
|
|
@@ -15167,6 +15521,8 @@ var draw = (options, resolvedKey, rnd) => {
|
|
|
15167
15521
|
melody,
|
|
15168
15522
|
submelody,
|
|
15169
15523
|
bass,
|
|
15524
|
+
harmony,
|
|
15525
|
+
pad,
|
|
15170
15526
|
melodyDurations,
|
|
15171
15527
|
restSteps,
|
|
15172
15528
|
totalSteps: Math.max(1, sungBars) * stepsPerBar,
|
|
@@ -15202,7 +15558,16 @@ var evaluate = (d, recent) => {
|
|
|
15202
15558
|
fromMelody(toMetricNotes(d.submelody)),
|
|
15203
15559
|
opts
|
|
15204
15560
|
);
|
|
15205
|
-
const
|
|
15561
|
+
const verseBars = [];
|
|
15562
|
+
const chorusBars = [];
|
|
15563
|
+
for (const s of d.sections) {
|
|
15564
|
+
for (let b = s.startBar; b < s.startBar + s.bars; b++) {
|
|
15565
|
+
if (s.kind === "verse") verseBars.push(b);
|
|
15566
|
+
else if (s.kind === "chorus" || s.kind === "drop_chorus")
|
|
15567
|
+
chorusBars.push(b);
|
|
15568
|
+
}
|
|
15569
|
+
}
|
|
15570
|
+
const tension = tensionFeatures(d.barTension, { verseBars, chorusBars });
|
|
15206
15571
|
const density = densityFeatures(melodyFrom, opts);
|
|
15207
15572
|
const fingerprint = featureVector({
|
|
15208
15573
|
entropy,
|
|
@@ -15218,6 +15583,7 @@ var evaluate = (d, recent) => {
|
|
|
15218
15583
|
);
|
|
15219
15584
|
const at = (b, v) => band(v, b[0], b[1], b[2], b[3]);
|
|
15220
15585
|
const atc = (key, v) => centeredBand(v, CORPUS_BANDS[key], CORPUS_MEDIANS[key]);
|
|
15586
|
+
const peakBand = d.bars > 24 ? [0, 1, Math.round(d.bars / 16), Math.round(d.bars / 8) + 2] : HAND_BANDS.climaxPeaks;
|
|
15221
15587
|
const scoreBreakdown = {
|
|
15222
15588
|
entropy: atc("entropy", entropy),
|
|
15223
15589
|
valueKinds: atc("valueKinds", valueKinds),
|
|
@@ -15235,7 +15601,7 @@ var evaluate = (d, recent) => {
|
|
|
15235
15601
|
sim8: atc("sim8", structure.sim8),
|
|
15236
15602
|
phraseBreath: atc("phraseBreath", structure.phraseBreath),
|
|
15237
15603
|
climaxPosition: atc("climaxPosition", structure.climaxPosition),
|
|
15238
|
-
climaxPeaks: at(
|
|
15604
|
+
climaxPeaks: at(peakBand, structure.climaxPeaks),
|
|
15239
15605
|
complementarity: at(HAND_BANDS.complementarity, structure.complementarity),
|
|
15240
15606
|
subDensity: at(HAND_BANDS.subDensity, d.submelody.length / d.bars),
|
|
15241
15607
|
tensionRise: tension.rise,
|
|
@@ -15289,9 +15655,10 @@ var composeSong = (options) => {
|
|
|
15289
15655
|
bestScore = stats.score;
|
|
15290
15656
|
bestIsValid = ok;
|
|
15291
15657
|
best = {
|
|
15292
|
-
//
|
|
15658
|
+
// ドラム・楽器は勝った候補にだけ後から付ける(メロディに依存しないので
|
|
15293
15659
|
// 候補ごとに引いても採点は動かず、40本ぶん無駄になる)。
|
|
15294
15660
|
drum: "",
|
|
15661
|
+
instrument: "",
|
|
15295
15662
|
chordProgression: d.chordProgression,
|
|
15296
15663
|
chordPattern: d.chordPattern,
|
|
15297
15664
|
rootShift: d.rootShift,
|
|
@@ -15304,6 +15671,8 @@ var composeSong = (options) => {
|
|
|
15304
15671
|
melody: d.melody,
|
|
15305
15672
|
submelody: d.submelody,
|
|
15306
15673
|
bass: d.bass,
|
|
15674
|
+
harmony: d.harmony,
|
|
15675
|
+
pad: d.pad,
|
|
15307
15676
|
stats: { ...stats, attempts: attempt, rejected }
|
|
15308
15677
|
};
|
|
15309
15678
|
}
|
|
@@ -15311,6 +15680,7 @@ var composeSong = (options) => {
|
|
|
15311
15680
|
result.stats.attempts = count;
|
|
15312
15681
|
result.stats.rejected = rejected;
|
|
15313
15682
|
result.drum = pickBuiltinDrum(result, rnd);
|
|
15683
|
+
result.instrument = pickBuiltinInstrument(result, rnd);
|
|
15314
15684
|
return result;
|
|
15315
15685
|
};
|
|
15316
15686
|
var pickBuiltinDrum = (song, rnd) => {
|
|
@@ -15319,6 +15689,35 @@ var pickBuiltinDrum = (song, rnd) => {
|
|
|
15319
15689
|
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"];
|
|
15320
15690
|
return pick(pool, rnd);
|
|
15321
15691
|
};
|
|
15692
|
+
var pickBuiltinInstrument = (song, rnd) => {
|
|
15693
|
+
const eighth = BASE_STEPS_PER_BAR / 8;
|
|
15694
|
+
const short = song.melody.filter((n) => n.durationSteps <= eighth).length / Math.max(1, song.melody.length);
|
|
15695
|
+
if (rnd() < 0.06) {
|
|
15696
|
+
return pick(["japanese_wa", "arabic_exotic"], rnd);
|
|
15697
|
+
}
|
|
15698
|
+
let pool;
|
|
15699
|
+
if (song.drum === "dance" || song.drum === "disco") {
|
|
15700
|
+
pool = song.bpm >= 150 ? ["cyber_punk", "synth_pop", "retro_game"] : ["synth_pop", "retro_game", "rock", "piano"];
|
|
15701
|
+
} else if (song.drum === "bossa") {
|
|
15702
|
+
pool = ["jazz_night", "acoustic", "piano"];
|
|
15703
|
+
} else if (song.bpm <= 105 && short < 0.4) {
|
|
15704
|
+
pool = ["ambient_cloud", "acoustic", "orchestra", "piano", "fantasy_rpg"];
|
|
15705
|
+
} else if (song.bpm >= 145) {
|
|
15706
|
+
pool = ["rock", "synth_pop", "cyber_punk", "retro_game", "piano"];
|
|
15707
|
+
} else if (song.stats.leapRatio >= 0.45) {
|
|
15708
|
+
pool = ["fantasy_rpg", "orchestra", "acoustic", "piano"];
|
|
15709
|
+
} else {
|
|
15710
|
+
pool = [
|
|
15711
|
+
"piano",
|
|
15712
|
+
"acoustic",
|
|
15713
|
+
"synth_pop",
|
|
15714
|
+
"rock",
|
|
15715
|
+
"jazz_night",
|
|
15716
|
+
"fantasy_rpg"
|
|
15717
|
+
];
|
|
15718
|
+
}
|
|
15719
|
+
return pick(pool, rnd);
|
|
15720
|
+
};
|
|
15322
15721
|
var LYRIC_WORDS = [
|
|
15323
15722
|
"\u3042\u3055",
|
|
15324
15723
|
"\u3072\u304B\u308A",
|
|
@@ -15720,74 +16119,89 @@ var buildUI = (target, options) => {
|
|
|
15720
16119
|
<details class="dtm-panel" data-dtm-acc="macro">
|
|
15721
16120
|
<summary>\u30DE\u30AF\u30ED</summary>
|
|
15722
16121
|
<div class="dtm-panel-body">
|
|
15723
|
-
<div class="dtm-
|
|
15724
|
-
<
|
|
15725
|
-
|
|
15726
|
-
|
|
15727
|
-
|
|
15728
|
-
|
|
15729
|
-
|
|
15730
|
-
<
|
|
15731
|
-
|
|
15732
|
-
<
|
|
15733
|
-
|
|
15734
|
-
|
|
15735
|
-
|
|
15736
|
-
|
|
15737
|
-
|
|
16122
|
+
<div class="dtm-compose-container ${showCompose ? "" : "dtm-hidden"}" data-dtm="compose-container">
|
|
16123
|
+
<div class="dtm-row" data-dtm="compose-row">
|
|
16124
|
+
<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>
|
|
16125
|
+
<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>
|
|
16126
|
+
<button class="dtm-infobtn" data-dtm="macro-compose-info" title="\u4F5C\u66F2\u306E\u89E3\u8AAC">${icon("info", 12)}</button>
|
|
16127
|
+
<span class="dtm-grow"></span>
|
|
16128
|
+
</div>
|
|
16129
|
+
<div class="dtm-row" data-dtm="compose-template-row">
|
|
16130
|
+
<span class="dtm-label">\u69CB\u6210</span>
|
|
16131
|
+
<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">
|
|
16132
|
+
<option value="custom">\u81EA\u7531\u9078\u629E\uFF08\u4E0B\u8A18\u30C1\u30A7\u30C3\u30AF\uFF09</option>
|
|
16133
|
+
<option value="1chorus">1\u30B3\u30FC\u30E9\u30B9\uFF08\u77ED\u3081\u30FB\u521D\u5FC3\u8005\u5411\u3051\uFF09</option>
|
|
16134
|
+
<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>
|
|
16135
|
+
<option value="jpop_drop">\u843D\u3061\u30B5\u30D3\u5165\u308A\uFF08JPOP\u738B\u9053 + \u30E9\u30B9\u30B5\u30D3\u524D\u843D\u3061\u30B5\u30D3\uFF09</option>
|
|
16136
|
+
<option value="vocaloid">\u30DC\u30AB\u30ED\u738B\u9053\uFF08\u75BE\u8D70\u30FB2\u756A/C\u30E1\u30ED/\u30E9\u30B9\u30B5\u30D3\uFF09</option>
|
|
16137
|
+
<option value="verse_chorus">Verse-Chorus\uFF08B\u30E1\u30ED\u306A\u3057\u30FB\u6D0B\u697D\u98A8\uFF09</option>
|
|
16138
|
+
</select>
|
|
16139
|
+
</div>
|
|
16140
|
+
<div class="dtm-row" data-dtm="compose-sections-row">
|
|
16141
|
+
<span class="dtm-label">\u4F5C\u308B\u90E8\u5206</span>
|
|
16142
|
+
<div class="dtm-checks" data-dtm="compose-sections">
|
|
16143
|
+
<label class="dtm-check"><input type="checkbox" value="intro" checked>\u30A4\u30F3\u30C8\u30ED</label>
|
|
16144
|
+
<label class="dtm-check"><input type="checkbox" value="verse" checked>A\u30E1\u30ED</label>
|
|
16145
|
+
<label class="dtm-check"><input type="checkbox" value="prechorus" checked>B\u30E1\u30ED</label>
|
|
16146
|
+
<label class="dtm-check"><input type="checkbox" value="chorus" checked>\u30B5\u30D3</label>
|
|
16147
|
+
<label class="dtm-check"><input type="checkbox" value="bridge">C\u30E1\u30ED</label>
|
|
16148
|
+
<label class="dtm-check"><input type="checkbox" value="drop_chorus">\u843D\u3061\u30B5\u30D3</label>
|
|
16149
|
+
<label class="dtm-check"><input type="checkbox" value="interlude">\u9593\u594F</label>
|
|
16150
|
+
<label class="dtm-check"><input type="checkbox" value="outro">\u30A2\u30A6\u30C8\u30ED</label>
|
|
16151
|
+
</div>
|
|
16152
|
+
<span class="dtm-grow"></span>
|
|
16153
|
+
<span class="dtm-hint" data-dtm="compose-sections-len"></span>
|
|
16154
|
+
</div>
|
|
16155
|
+
<div class="dtm-row" data-dtm="compose-key-row">
|
|
16156
|
+
<span class="dtm-label">\u30D9\u30FC\u30B9\u8ABF</span>
|
|
16157
|
+
<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">
|
|
16158
|
+
<option value="any" title="\u516824\u8ABF\u304B\u3089\u30E9\u30F3\u30C0\u30E0\u306B\u6C7A\u5B9A\u3057\u307E\u3059">\u5E0C\u671B\u306A\u3057</option>
|
|
16159
|
+
<optgroup label="\u57FA\u672C">
|
|
16160
|
+
<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>
|
|
16161
|
+
<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>
|
|
16162
|
+
</optgroup>
|
|
16163
|
+
<optgroup label="\u96F0\u56F2\u6C17\u304B\u3089\u9078\u3076\uFF08\u62BD\u9078\uFF09">
|
|
16164
|
+
<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>
|
|
16165
|
+
<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>
|
|
16166
|
+
<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>
|
|
16167
|
+
<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>
|
|
16168
|
+
<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>
|
|
16169
|
+
<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>
|
|
16170
|
+
<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>
|
|
16171
|
+
<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>
|
|
16172
|
+
</optgroup>
|
|
16173
|
+
<optgroup label="\u9577\u8ABF\uFF08\u500B\u5225\u6307\u5B9A\uFF09">
|
|
16174
|
+
<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>
|
|
16175
|
+
<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>
|
|
16176
|
+
<option value="key_D" title="\u610F\u6C17\u63DA\u3005\u3068\u3057\u305F\u3001\u52DD\u5229\u306E\u3001\u558A\u58F0">\u30CB\u9577\u8ABF (D)</option>
|
|
16177
|
+
<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>
|
|
16178
|
+
<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>
|
|
16179
|
+
<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>
|
|
16180
|
+
<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>
|
|
16181
|
+
<option value="key_G" title="\u53B3\u7C9B\u306A\u3001\u5D07\u9AD8\u306A\u3001\u5E7B\u60F3\u3001\u8AA0\u5B9F">\u30C8\u9577\u8ABF (G)</option>
|
|
16182
|
+
<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>
|
|
16183
|
+
<option value="key_A" title="\u3046\u308C\u3057\u3044\u3001\u7267\u6B4C\u7684\u306A\u3001\u611B\u306E\u544A\u767D">\u30A4\u9577\u8ABF (A)</option>
|
|
16184
|
+
<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>
|
|
16185
|
+
<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>
|
|
16186
|
+
</optgroup>
|
|
16187
|
+
<optgroup label="\u77ED\u8ABF\uFF08\u500B\u5225\u6307\u5B9A\uFF09">
|
|
16188
|
+
<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>
|
|
16189
|
+
<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>
|
|
16190
|
+
<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>
|
|
16191
|
+
<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>
|
|
16192
|
+
<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>
|
|
16193
|
+
<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>
|
|
16194
|
+
<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>
|
|
16195
|
+
<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>
|
|
16196
|
+
<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>
|
|
16197
|
+
<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>
|
|
16198
|
+
<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>
|
|
16199
|
+
<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>
|
|
16200
|
+
</optgroup>
|
|
16201
|
+
</select>
|
|
16202
|
+
<span class="dtm-grow"></span>
|
|
16203
|
+
<span class="dtm-hint" data-dtm="compose-key-hint"></span>
|
|
15738
16204
|
</div>
|
|
15739
|
-
<span class="dtm-grow"></span>
|
|
15740
|
-
<span class="dtm-hint" data-dtm="compose-sections-len"></span>
|
|
15741
|
-
</div>
|
|
15742
|
-
<div class="dtm-row ${showCompose ? "" : "dtm-hidden"}" data-dtm="compose-key-row">
|
|
15743
|
-
<span class="dtm-label">\u30D9\u30FC\u30B9\u8ABF</span>
|
|
15744
|
-
<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">
|
|
15745
|
-
<option value="any" title="\u516824\u8ABF\u304B\u3089\u30E9\u30F3\u30C0\u30E0\u306B\u6C7A\u5B9A\u3057\u307E\u3059">\u5E0C\u671B\u306A\u3057</option>
|
|
15746
|
-
<optgroup label="\u57FA\u672C">
|
|
15747
|
-
<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>
|
|
15748
|
-
<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>
|
|
15749
|
-
</optgroup>
|
|
15750
|
-
<optgroup label="\u96F0\u56F2\u6C17\u304B\u3089\u9078\u3076\uFF08\u62BD\u9078\uFF09">
|
|
15751
|
-
<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>
|
|
15752
|
-
<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>
|
|
15753
|
-
<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>
|
|
15754
|
-
<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>
|
|
15755
|
-
<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>
|
|
15756
|
-
<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>
|
|
15757
|
-
<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>
|
|
15758
|
-
<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>
|
|
15759
|
-
</optgroup>
|
|
15760
|
-
<optgroup label="\u9577\u8ABF\uFF08\u500B\u5225\u6307\u5B9A\uFF09">
|
|
15761
|
-
<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>
|
|
15762
|
-
<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>
|
|
15763
|
-
<option value="key_D" title="\u610F\u6C17\u63DA\u3005\u3068\u3057\u305F\u3001\u52DD\u5229\u306E\u3001\u558A\u58F0">\u30CB\u9577\u8ABF (D)</option>
|
|
15764
|
-
<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>
|
|
15765
|
-
<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>
|
|
15766
|
-
<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>
|
|
15767
|
-
<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>
|
|
15768
|
-
<option value="key_G" title="\u53B3\u7C9B\u306A\u3001\u5D07\u9AD8\u306A\u3001\u5E7B\u60F3\u3001\u8AA0\u5B9F">\u30C8\u9577\u8ABF (G)</option>
|
|
15769
|
-
<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>
|
|
15770
|
-
<option value="key_A" title="\u3046\u308C\u3057\u3044\u3001\u7267\u6B4C\u7684\u306A\u3001\u611B\u306E\u544A\u767D">\u30A4\u9577\u8ABF (A)</option>
|
|
15771
|
-
<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>
|
|
15772
|
-
<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>
|
|
15773
|
-
</optgroup>
|
|
15774
|
-
<optgroup label="\u77ED\u8ABF\uFF08\u500B\u5225\u6307\u5B9A\uFF09">
|
|
15775
|
-
<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>
|
|
15776
|
-
<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>
|
|
15777
|
-
<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>
|
|
15778
|
-
<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>
|
|
15779
|
-
<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>
|
|
15780
|
-
<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>
|
|
15781
|
-
<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>
|
|
15782
|
-
<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>
|
|
15783
|
-
<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>
|
|
15784
|
-
<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>
|
|
15785
|
-
<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>
|
|
15786
|
-
<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>
|
|
15787
|
-
</optgroup>
|
|
15788
|
-
</select>
|
|
15789
|
-
<span class="dtm-grow"></span>
|
|
15790
|
-
<span class="dtm-hint" data-dtm="compose-key-hint"></span>
|
|
15791
16205
|
</div>
|
|
15792
16206
|
<div class="dtm-row">
|
|
15793
16207
|
<span class="dtm-label">\u5168\u4F53\u30B7\u30D5\u30C8</span>
|
|
@@ -15985,6 +16399,7 @@ var buildUI = (target, options) => {
|
|
|
15985
16399
|
transposeApplyBtn: sel("transpose-apply"),
|
|
15986
16400
|
transposeInfoBtn: sel("transpose-info"),
|
|
15987
16401
|
macroCompose: sel("macro-compose"),
|
|
16402
|
+
composeTemplate: sel("compose-template"),
|
|
15988
16403
|
composeSections: sel("compose-sections"),
|
|
15989
16404
|
composeSectionsLen: sel("compose-sections-len"),
|
|
15990
16405
|
composeKey: sel("compose-key"),
|
|
@@ -16127,6 +16542,45 @@ var INSTRUMENT_PRESETS = {
|
|
|
16127
16542
|
}
|
|
16128
16543
|
};
|
|
16129
16544
|
|
|
16545
|
+
// src/macro-state.ts
|
|
16546
|
+
var MACRO_STORAGE_KEYS = {
|
|
16547
|
+
template: "dtm-macro:template",
|
|
16548
|
+
sections: "dtm-macro:sections",
|
|
16549
|
+
key: "dtm-macro:key",
|
|
16550
|
+
shift: "dtm-macro:shift",
|
|
16551
|
+
transpose: "dtm-macro:transpose"
|
|
16552
|
+
};
|
|
16553
|
+
var readMacroSetting = (key) => {
|
|
16554
|
+
try {
|
|
16555
|
+
if (typeof localStorage === "undefined" || !localStorage) return null;
|
|
16556
|
+
return localStorage.getItem(MACRO_STORAGE_KEYS[key]);
|
|
16557
|
+
} catch (_) {
|
|
16558
|
+
return null;
|
|
16559
|
+
}
|
|
16560
|
+
};
|
|
16561
|
+
var writeMacroSetting = (key, value) => {
|
|
16562
|
+
try {
|
|
16563
|
+
if (typeof localStorage === "undefined" || !localStorage) return;
|
|
16564
|
+
localStorage.setItem(MACRO_STORAGE_KEYS[key], value);
|
|
16565
|
+
} catch (_) {
|
|
16566
|
+
}
|
|
16567
|
+
};
|
|
16568
|
+
var readMacroSections = () => {
|
|
16569
|
+
const raw = readMacroSetting("sections");
|
|
16570
|
+
if (!raw) return null;
|
|
16571
|
+
try {
|
|
16572
|
+
const parsed = JSON.parse(raw);
|
|
16573
|
+
if (Array.isArray(parsed) && parsed.every((x2) => typeof x2 === "string")) {
|
|
16574
|
+
return parsed;
|
|
16575
|
+
}
|
|
16576
|
+
} catch (_) {
|
|
16577
|
+
}
|
|
16578
|
+
return null;
|
|
16579
|
+
};
|
|
16580
|
+
var writeMacroSections = (sections) => {
|
|
16581
|
+
writeMacroSetting("sections", JSON.stringify(sections));
|
|
16582
|
+
};
|
|
16583
|
+
|
|
16130
16584
|
// src/macros.ts
|
|
16131
16585
|
var SCALES = [
|
|
16132
16586
|
[0, 2, 4, 5, 7, 9, 11],
|
|
@@ -18470,12 +18924,15 @@ var pickComposeVocal = (exclude) => {
|
|
|
18470
18924
|
var ADVANCED_COMPOSE_LAYOUT = [
|
|
18471
18925
|
{ index: 0, part: "melody", octave: 0, volume: 104 },
|
|
18472
18926
|
{ index: 1, part: "melody", octave: 1, volume: 62 },
|
|
18473
|
-
{ index: 2, part: "
|
|
18474
|
-
{ index: 3, part: "
|
|
18475
|
-
{ index: 4, part: "bass", octave:
|
|
18476
|
-
{ index: 5, part: "
|
|
18477
|
-
{ index: 6, part: "
|
|
18478
|
-
{ index: 7, part: "
|
|
18927
|
+
{ index: 2, part: "harmony", octave: 0, volume: 82 },
|
|
18928
|
+
{ index: 3, part: "submelody", octave: 0, volume: 86 },
|
|
18929
|
+
{ index: 4, part: "bass", octave: 0, volume: 92 },
|
|
18930
|
+
{ index: 5, part: "bass", octave: -1, volume: 58 },
|
|
18931
|
+
{ index: 6, part: "pad", octave: 0, volume: 64 },
|
|
18932
|
+
{ index: 7, part: "block", octave: 0, volume: 62 },
|
|
18933
|
+
{ index: 8, part: "arpeggio", octave: 0, volume: 54 },
|
|
18934
|
+
{ index: 9, part: "offbeat", octave: 0, volume: 50 },
|
|
18935
|
+
{ index: 10, part: "uwamono", octave: 1, volume: 56 }
|
|
18479
18936
|
];
|
|
18480
18937
|
var LYRIC_MODEL_CATEGORIES = [
|
|
18481
18938
|
{
|
|
@@ -18765,6 +19222,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
18765
19222
|
options.onDrumFontChange?.(font);
|
|
18766
19223
|
};
|
|
18767
19224
|
let currentInstrument = "";
|
|
19225
|
+
let autoComposeInstrument = null;
|
|
18768
19226
|
let activeTrackId = options.initialActiveTrack ?? trackConfigs[0].id;
|
|
18769
19227
|
let trackFxAdvancedOpen = readPanelOpen("track-fx-advanced") ?? false;
|
|
18770
19228
|
let lyricAdvancedOpen = readPanelOpen("lyric-advanced") ?? false;
|
|
@@ -19802,8 +20260,8 @@ var mountDAW = (target, options = {}) => {
|
|
|
19802
20260
|
redrawAll();
|
|
19803
20261
|
},
|
|
19804
20262
|
onEnd: (interrupted) => {
|
|
19805
|
-
options.onScheduleFade?.(null);
|
|
19806
20263
|
if (interrupted) {
|
|
20264
|
+
options.onScheduleFade?.(null);
|
|
19807
20265
|
playbackState = "paused";
|
|
19808
20266
|
pausedPlayStep = currentPlayStep;
|
|
19809
20267
|
} else {
|
|
@@ -21935,6 +22393,10 @@ var mountDAW = (target, options = {}) => {
|
|
|
21935
22393
|
}
|
|
21936
22394
|
return ADVANCED_COMPOSE_LAYOUT.filter((l) => l.part === "bass").map((l) => trackStates[l.index]).filter((t) => !!t);
|
|
21937
22395
|
};
|
|
22396
|
+
const selectedComposeTemplate = () => {
|
|
22397
|
+
const val = refs.composeTemplate?.value;
|
|
22398
|
+
return val && val !== "custom" ? val : void 0;
|
|
22399
|
+
};
|
|
21938
22400
|
const selectedComposeSections = () => {
|
|
21939
22401
|
const boxes = [
|
|
21940
22402
|
...refs.composeSections.querySelectorAll(
|
|
@@ -21945,11 +22407,97 @@ var mountDAW = (target, options = {}) => {
|
|
|
21945
22407
|
return picked.length > 0 ? picked : DEFAULT_SECTIONS;
|
|
21946
22408
|
};
|
|
21947
22409
|
const updateComposeSectionsLen = () => {
|
|
21948
|
-
const
|
|
22410
|
+
const tmpl = selectedComposeTemplate();
|
|
22411
|
+
const plan = buildSectionPlan(selectedComposeSections(), tmpl);
|
|
21949
22412
|
const bars = plan.reduce((sum, x2) => sum + x2.bars, 0);
|
|
21950
22413
|
refs.composeSectionsLen.textContent = `${bars}\u5C0F\u7BC0`;
|
|
21951
22414
|
};
|
|
21952
|
-
|
|
22415
|
+
const savedTemplate = readMacroSetting("template");
|
|
22416
|
+
if (savedTemplate && refs.composeTemplate) {
|
|
22417
|
+
const hasOption = Array.from(refs.composeTemplate.options).some(
|
|
22418
|
+
(opt) => opt.value === savedTemplate
|
|
22419
|
+
);
|
|
22420
|
+
if (hasOption) {
|
|
22421
|
+
refs.composeTemplate.value = savedTemplate;
|
|
22422
|
+
}
|
|
22423
|
+
}
|
|
22424
|
+
const savedSections = readMacroSections();
|
|
22425
|
+
if (savedSections && refs.composeSections) {
|
|
22426
|
+
const boxes = refs.composeSections.querySelectorAll(
|
|
22427
|
+
'input[type="checkbox"]'
|
|
22428
|
+
);
|
|
22429
|
+
const validValues = new Set(savedSections);
|
|
22430
|
+
for (const box of boxes) {
|
|
22431
|
+
box.checked = validValues.has(box.value);
|
|
22432
|
+
}
|
|
22433
|
+
} else if (savedTemplate && savedTemplate !== "custom" && refs.composeSections) {
|
|
22434
|
+
const tmpl = STRUCTURE_TEMPLATES.find((t) => t.name === savedTemplate);
|
|
22435
|
+
if (tmpl) {
|
|
22436
|
+
const planSet = new Set(tmpl.plan);
|
|
22437
|
+
const boxes = refs.composeSections.querySelectorAll(
|
|
22438
|
+
'input[type="checkbox"]'
|
|
22439
|
+
);
|
|
22440
|
+
for (const box of boxes) {
|
|
22441
|
+
box.checked = planSet.has(box.value);
|
|
22442
|
+
}
|
|
22443
|
+
}
|
|
22444
|
+
}
|
|
22445
|
+
const savedKey = readMacroSetting("key");
|
|
22446
|
+
if (savedKey && refs.composeKey) {
|
|
22447
|
+
const hasOption = Array.from(refs.composeKey.options).some(
|
|
22448
|
+
(opt) => opt.value === savedKey
|
|
22449
|
+
);
|
|
22450
|
+
if (hasOption) {
|
|
22451
|
+
refs.composeKey.value = savedKey;
|
|
22452
|
+
}
|
|
22453
|
+
}
|
|
22454
|
+
const savedShift = readMacroSetting("shift");
|
|
22455
|
+
if (savedShift && refs.shiftSelect) {
|
|
22456
|
+
const hasOption = Array.from(refs.shiftSelect.options).some(
|
|
22457
|
+
(opt) => opt.value === savedShift
|
|
22458
|
+
);
|
|
22459
|
+
if (hasOption) {
|
|
22460
|
+
refs.shiftSelect.value = savedShift;
|
|
22461
|
+
}
|
|
22462
|
+
}
|
|
22463
|
+
const savedTranspose = readMacroSetting("transpose");
|
|
22464
|
+
if (savedTranspose && refs.transposeSelect) {
|
|
22465
|
+
const hasOption = Array.from(refs.transposeSelect.options).some(
|
|
22466
|
+
(opt) => opt.value === savedTranspose
|
|
22467
|
+
);
|
|
22468
|
+
if (hasOption) {
|
|
22469
|
+
refs.transposeSelect.value = savedTranspose;
|
|
22470
|
+
}
|
|
22471
|
+
}
|
|
22472
|
+
refs.composeSections.addEventListener("change", () => {
|
|
22473
|
+
if (refs.composeTemplate) {
|
|
22474
|
+
refs.composeTemplate.value = "custom";
|
|
22475
|
+
writeMacroSetting("template", "custom");
|
|
22476
|
+
}
|
|
22477
|
+
writeMacroSections(selectedComposeSections());
|
|
22478
|
+
updateComposeSectionsLen();
|
|
22479
|
+
});
|
|
22480
|
+
const composeTemplate = refs.composeTemplate;
|
|
22481
|
+
if (composeTemplate) {
|
|
22482
|
+
composeTemplate.addEventListener("change", () => {
|
|
22483
|
+
writeMacroSetting("template", composeTemplate.value);
|
|
22484
|
+
const tmplName = selectedComposeTemplate();
|
|
22485
|
+
if (tmplName) {
|
|
22486
|
+
const tmpl = STRUCTURE_TEMPLATES.find((t) => t.name === tmplName);
|
|
22487
|
+
if (tmpl) {
|
|
22488
|
+
const planSet = new Set(tmpl.plan);
|
|
22489
|
+
const boxes = refs.composeSections.querySelectorAll(
|
|
22490
|
+
'input[type="checkbox"]'
|
|
22491
|
+
);
|
|
22492
|
+
for (const box of boxes) {
|
|
22493
|
+
box.checked = planSet.has(box.value);
|
|
22494
|
+
}
|
|
22495
|
+
}
|
|
22496
|
+
}
|
|
22497
|
+
writeMacroSections(selectedComposeSections());
|
|
22498
|
+
updateComposeSectionsLen();
|
|
22499
|
+
});
|
|
22500
|
+
}
|
|
21953
22501
|
updateComposeSectionsLen();
|
|
21954
22502
|
const updateComposeKeyHint = () => {
|
|
21955
22503
|
if (!refs.composeKey || !refs.composeKeyHint) return;
|
|
@@ -21957,17 +22505,33 @@ var mountDAW = (target, options = {}) => {
|
|
|
21957
22505
|
refs.composeKeyHint.textContent = desc;
|
|
21958
22506
|
refs.composeKeyHint.title = desc;
|
|
21959
22507
|
};
|
|
21960
|
-
|
|
21961
|
-
|
|
22508
|
+
const composeKey = refs.composeKey;
|
|
22509
|
+
if (composeKey) {
|
|
22510
|
+
composeKey.addEventListener("change", () => {
|
|
22511
|
+
writeMacroSetting("key", composeKey.value);
|
|
22512
|
+
updateComposeKeyHint();
|
|
22513
|
+
});
|
|
21962
22514
|
updateComposeKeyHint();
|
|
21963
22515
|
}
|
|
22516
|
+
if (refs.shiftSelect) {
|
|
22517
|
+
refs.shiftSelect.addEventListener("change", () => {
|
|
22518
|
+
writeMacroSetting("shift", refs.shiftSelect.value);
|
|
22519
|
+
});
|
|
22520
|
+
}
|
|
22521
|
+
if (refs.transposeSelect) {
|
|
22522
|
+
refs.transposeSelect.addEventListener("change", () => {
|
|
22523
|
+
writeMacroSetting("transpose", refs.transposeSelect.value);
|
|
22524
|
+
});
|
|
22525
|
+
}
|
|
21964
22526
|
const runCompose = (withVocal) => {
|
|
21965
22527
|
stop();
|
|
21966
22528
|
overlayDuring(() => {
|
|
22529
|
+
const tmpl = selectedComposeTemplate();
|
|
21967
22530
|
const song = composeSong({
|
|
21968
22531
|
stepsPerBar: renderConfig.stepsPerBar,
|
|
21969
22532
|
edo: renderConfig.edo,
|
|
21970
22533
|
sections: selectedComposeSections(),
|
|
22534
|
+
template: tmpl,
|
|
21971
22535
|
baseKey: refs.composeKey?.value ?? "any",
|
|
21972
22536
|
// 直近に作った曲の特徴を渡すと、それらから離れた候補に加点される。
|
|
21973
22537
|
// 「作曲」を続けて押したときに似た曲が並ぶのを防ぐ。
|
|
@@ -22006,7 +22570,19 @@ var mountDAW = (target, options = {}) => {
|
|
|
22006
22570
|
for (const layer of ADVANCED_COMPOSE_LAYOUT) {
|
|
22007
22571
|
const track = trackStates[layer.index];
|
|
22008
22572
|
if (!track) continue;
|
|
22009
|
-
const notes = layer.part === "melody" ? song.melody : layer.part === "submelody" ? song.submelody : layer.part === "bass" ? song.bass : buildChordPlacements({
|
|
22573
|
+
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({
|
|
22574
|
+
edo: renderConfig.edo,
|
|
22575
|
+
chordStr: song.chordProgression,
|
|
22576
|
+
patternType: "arpeggio",
|
|
22577
|
+
rootShift: song.rootShift,
|
|
22578
|
+
bpm: song.bpm,
|
|
22579
|
+
stepsPerBar: renderConfig.stepsPerBar
|
|
22580
|
+
}).map((p) => ({
|
|
22581
|
+
startStep: p.startStep,
|
|
22582
|
+
pitchUnits: p.pitchUnits,
|
|
22583
|
+
durationSteps: p.durationSteps,
|
|
22584
|
+
velocity: Math.max(30, p.velocity - 14)
|
|
22585
|
+
})) : buildChordPlacements({
|
|
22010
22586
|
edo: renderConfig.edo,
|
|
22011
22587
|
chordStr: song.chordProgression,
|
|
22012
22588
|
patternType: layer.part,
|
|
@@ -22045,6 +22621,12 @@ var mountDAW = (target, options = {}) => {
|
|
|
22045
22621
|
refs.drumSelect.value = song.drum;
|
|
22046
22622
|
options.onDrumChange?.(song.drum);
|
|
22047
22623
|
applyDrumPatternFont(song.drum);
|
|
22624
|
+
const shouldAutoInstrument = !currentInstrument || currentInstrument === "auto" || currentInstrument === autoComposeInstrument;
|
|
22625
|
+
if (shouldAutoInstrument && song.instrument) {
|
|
22626
|
+
currentInstrument = song.instrument;
|
|
22627
|
+
autoComposeInstrument = song.instrument;
|
|
22628
|
+
options.onInstrumentChange?.(song.instrument);
|
|
22629
|
+
}
|
|
22048
22630
|
for (const t of bassTracksForCompose()) {
|
|
22049
22631
|
t.trackCompression = AUTO_ROLE_MIX.bass.compression;
|
|
22050
22632
|
options.onTrackCompressionChange?.(t.config.id, t.trackCompression);
|
|
@@ -24318,6 +24900,8 @@ var createDtmStudio = async (options = {}) => {
|
|
|
24318
24900
|
if (fadeOutStartAt !== void 0 && fadeOutEndAt !== void 0) {
|
|
24319
24901
|
fadeGain.gain.setValueAtTime(1, fadeOutStartAt);
|
|
24320
24902
|
fadeGain.gain.linearRampToValueAtTime(0, fadeOutEndAt);
|
|
24903
|
+
fadeGain.gain.setValueAtTime(0, fadeOutEndAt + 2);
|
|
24904
|
+
fadeGain.gain.setValueAtTime(1, fadeOutEndAt + 2);
|
|
24321
24905
|
}
|
|
24322
24906
|
};
|
|
24323
24907
|
const clipMeter = createClipMeter(audioCtx, glueMakeup);
|
|
@@ -24545,13 +25129,17 @@ var createDtmStudio = async (options = {}) => {
|
|
|
24545
25129
|
}
|
|
24546
25130
|
const select = doc.createElement("select");
|
|
24547
25131
|
select.className = "dtm-select dtm-grow";
|
|
25132
|
+
const autoOpt = doc.createElement("option");
|
|
25133
|
+
autoOpt.value = "auto";
|
|
25134
|
+
autoOpt.textContent = "\u2728 \u81EA\u52D5\uFF08\u66F2\u8ABF\u9023\u52D5\uFF09";
|
|
25135
|
+
select.appendChild(autoOpt);
|
|
24548
25136
|
for (const [key, p] of Object.entries(INSTRUMENT_PRESETS)) {
|
|
24549
25137
|
const o = doc.createElement("option");
|
|
24550
25138
|
o.value = key;
|
|
24551
25139
|
o.textContent = p.displayName;
|
|
24552
25140
|
select.appendChild(o);
|
|
24553
25141
|
}
|
|
24554
|
-
select.value = opts.value && INSTRUMENT_PRESETS[opts.value] ? opts.value : defaultPreset;
|
|
25142
|
+
select.value = opts.value === "auto" || opts.value && INSTRUMENT_PRESETS[opts.value] ? opts.value : defaultPreset;
|
|
24555
25143
|
wrapper.appendChild(select);
|
|
24556
25144
|
let busy = false;
|
|
24557
25145
|
const onChange = async () => {
|
|
@@ -24560,6 +25148,10 @@ var createDtmStudio = async (options = {}) => {
|
|
|
24560
25148
|
busy = true;
|
|
24561
25149
|
const key = select.value;
|
|
24562
25150
|
opts.onChange?.(key);
|
|
25151
|
+
if (key === "auto") {
|
|
25152
|
+
busy = false;
|
|
25153
|
+
return;
|
|
25154
|
+
}
|
|
24563
25155
|
const trackIds = opts.getTrackIds?.() ?? [...TRACK_ROLES];
|
|
24564
25156
|
const isAdvanced = trackIds.includes("t0");
|
|
24565
25157
|
const mode = isAdvanced ? "advanced" : "simple";
|
|
@@ -24577,7 +25169,7 @@ var createDtmStudio = async (options = {}) => {
|
|
|
24577
25169
|
element: wrapper,
|
|
24578
25170
|
select,
|
|
24579
25171
|
setValue: (k) => {
|
|
24580
|
-
if (INSTRUMENT_PRESETS[k]) select.value = k;
|
|
25172
|
+
if (k === "auto" || INSTRUMENT_PRESETS[k]) select.value = k;
|
|
24581
25173
|
},
|
|
24582
25174
|
getValue: () => select.value,
|
|
24583
25175
|
destroy: () => {
|
|
@@ -24589,8 +25181,15 @@ var createDtmStudio = async (options = {}) => {
|
|
|
24589
25181
|
await listReady;
|
|
24590
25182
|
nameToKey = await buildNameToKeyMapping();
|
|
24591
25183
|
await Promise.all([drumReady, loadPreset(defaultPreset)]);
|
|
25184
|
+
const restoreFadeGainIfMuted = () => {
|
|
25185
|
+
if (fadeGain.gain.value < 1) {
|
|
25186
|
+
fadeGain.gain.cancelScheduledValues(audioCtx.currentTime);
|
|
25187
|
+
fadeGain.gain.setValueAtTime(1, audioCtx.currentTime);
|
|
25188
|
+
}
|
|
25189
|
+
};
|
|
24592
25190
|
const playDrum = (e) => {
|
|
24593
25191
|
if (!sfDrum.font) return;
|
|
25192
|
+
if (e.when === 0) restoreFadeGainIfMuted();
|
|
24594
25193
|
if (KICK_PITCHES.has(e.pitch)) duckBassForKick(e.when);
|
|
24595
25194
|
sfDrum.play({
|
|
24596
25195
|
ctx: audioCtx,
|
|
@@ -24634,6 +25233,7 @@ var createDtmStudio = async (options = {}) => {
|
|
|
24634
25233
|
}
|
|
24635
25234
|
}
|
|
24636
25235
|
const playNote4 = (e) => {
|
|
25236
|
+
if (e.when === 0) restoreFadeGainIfMuted();
|
|
24637
25237
|
const { trackIdx, role } = resolveTrackIdxAndRole(e.trackId);
|
|
24638
25238
|
const overrideKey = trackIdx >= 0 ? trackInstOverrides.get(trackIdx) : void 0;
|
|
24639
25239
|
let sfInst;
|
|
@@ -24659,12 +25259,33 @@ var createDtmStudio = async (options = {}) => {
|
|
|
24659
25259
|
duration: e.duration
|
|
24660
25260
|
});
|
|
24661
25261
|
};
|
|
25262
|
+
let daw;
|
|
24662
25263
|
let presetSelect = null;
|
|
24663
25264
|
const handleInstrumentChange = (key) => {
|
|
25265
|
+
if (key === "auto") {
|
|
25266
|
+
if (presetSelect) {
|
|
25267
|
+
presetSelect.setValue("auto");
|
|
25268
|
+
}
|
|
25269
|
+
onInstrumentChange?.("auto");
|
|
25270
|
+
return;
|
|
25271
|
+
}
|
|
24664
25272
|
editorPreset = key;
|
|
24665
25273
|
if (presetSelect) {
|
|
24666
25274
|
presetSelect.setValue(key);
|
|
24667
25275
|
}
|
|
25276
|
+
if (INSTRUMENT_PRESETS[key]) {
|
|
25277
|
+
const wasPlaying = daw?.getPlaybackState() === "playing";
|
|
25278
|
+
if (wasPlaying) daw.pause();
|
|
25279
|
+
daw?.setLoading?.(true);
|
|
25280
|
+
void loadPreset(
|
|
25281
|
+
key,
|
|
25282
|
+
trackIds,
|
|
25283
|
+
isAdvancedMode ? "advanced" : "simple"
|
|
25284
|
+
).finally(() => {
|
|
25285
|
+
daw?.setLoading?.(false);
|
|
25286
|
+
if (wasPlaying) daw?.play();
|
|
25287
|
+
});
|
|
25288
|
+
}
|
|
24668
25289
|
onInstrumentChange?.(key);
|
|
24669
25290
|
};
|
|
24670
25291
|
const handleTrackInstrumentChange = async (trackIndex, instrumentName) => {
|
|
@@ -24678,7 +25299,6 @@ var createDtmStudio = async (options = {}) => {
|
|
|
24678
25299
|
trackInstOverrides.set(trackIndex, key);
|
|
24679
25300
|
await loadInstrument(key);
|
|
24680
25301
|
};
|
|
24681
|
-
let daw;
|
|
24682
25302
|
const base = {
|
|
24683
25303
|
getAudioTime: () => audioCtx.currentTime,
|
|
24684
25304
|
onResumeAudio: async () => {
|
|
@@ -25437,6 +26057,7 @@ var createDtmStudio = async (options = {}) => {
|
|
|
25437
26057
|
KOE_VOICEBANK_LABELS,
|
|
25438
26058
|
KOE_VOICEBANK_TERMS,
|
|
25439
26059
|
LinkedList,
|
|
26060
|
+
MACRO_STORAGE_KEYS,
|
|
25440
26061
|
MAJOR_KEY_IDS,
|
|
25441
26062
|
MAX_VOCAL_VOLUME,
|
|
25442
26063
|
MICRO_STEP,
|
|
@@ -25539,6 +26160,8 @@ var createDtmStudio = async (options = {}) => {
|
|
|
25539
26160
|
playNote,
|
|
25540
26161
|
playPlacements,
|
|
25541
26162
|
playSingingMML,
|
|
26163
|
+
readMacroSections,
|
|
26164
|
+
readMacroSetting,
|
|
25542
26165
|
resolveComposeKey,
|
|
25543
26166
|
resolveDrumPattern,
|
|
25544
26167
|
resolveLoopPoint,
|
|
@@ -25561,5 +26184,7 @@ var createDtmStudio = async (options = {}) => {
|
|
|
25561
26184
|
unitsToMidi,
|
|
25562
26185
|
unitsToMidiDetune,
|
|
25563
26186
|
unitsToPitchV1,
|
|
25564
|
-
vocalVolumeToGain
|
|
26187
|
+
vocalVolumeToGain,
|
|
26188
|
+
writeMacroSections,
|
|
26189
|
+
writeMacroSetting
|
|
25565
26190
|
});
|