@onjmin/dtm 2.1.3 → 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 +772 -141
- package/dist/index.mjs +766 -140
- 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],
|
|
@@ -17794,8 +18248,10 @@ var createRenderer = (mountTarget, width = 800, height = 450, config) => {
|
|
|
17794
18248
|
const getXY = (e) => {
|
|
17795
18249
|
const { clientX, clientY } = e;
|
|
17796
18250
|
const rect = g_grid_canvas.getBoundingClientRect();
|
|
17797
|
-
const
|
|
17798
|
-
const
|
|
18251
|
+
const scaleX = rect.width > 0 ? g_grid_canvas.width / rect.width : 1;
|
|
18252
|
+
const scaleY = rect.height > 0 ? g_grid_canvas.height / rect.height : 1;
|
|
18253
|
+
const x2 = Math.floor((clientX - rect.left) * scaleX);
|
|
18254
|
+
const y = Math.floor((clientY - rect.top) * scaleY);
|
|
17799
18255
|
return [x2, y, e.buttons];
|
|
17800
18256
|
};
|
|
17801
18257
|
const getGridPosition = (e) => {
|
|
@@ -17829,7 +18285,7 @@ var createRenderer = (mountTarget, width = 800, height = 450, config) => {
|
|
|
17829
18285
|
const absoluteY = y + g_draw_offset_y;
|
|
17830
18286
|
const yIndex = Math.floor(absoluteY / keyHeight);
|
|
17831
18287
|
const pitch = units(pitchRangeStart + (keyCount - 1 - yIndex) * upr);
|
|
17832
|
-
if (pitch >= pitchRangeStart && pitch < pitchRangeStart + keyCount) {
|
|
18288
|
+
if (pitch >= pitchRangeStart && pitch < pitchRangeStart + keyCount * upr) {
|
|
17833
18289
|
requestAnimationFrame(() => callback(step, pitch));
|
|
17834
18290
|
}
|
|
17835
18291
|
},
|
|
@@ -18468,12 +18924,15 @@ var pickComposeVocal = (exclude) => {
|
|
|
18468
18924
|
var ADVANCED_COMPOSE_LAYOUT = [
|
|
18469
18925
|
{ index: 0, part: "melody", octave: 0, volume: 104 },
|
|
18470
18926
|
{ index: 1, part: "melody", octave: 1, volume: 62 },
|
|
18471
|
-
{ index: 2, part: "
|
|
18472
|
-
{ index: 3, part: "
|
|
18473
|
-
{ index: 4, part: "bass", octave:
|
|
18474
|
-
{ index: 5, part: "
|
|
18475
|
-
{ index: 6, part: "
|
|
18476
|
-
{ 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 }
|
|
18477
18936
|
];
|
|
18478
18937
|
var LYRIC_MODEL_CATEGORIES = [
|
|
18479
18938
|
{
|
|
@@ -18763,6 +19222,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
18763
19222
|
options.onDrumFontChange?.(font);
|
|
18764
19223
|
};
|
|
18765
19224
|
let currentInstrument = "";
|
|
19225
|
+
let autoComposeInstrument = null;
|
|
18766
19226
|
let activeTrackId = options.initialActiveTrack ?? trackConfigs[0].id;
|
|
18767
19227
|
let trackFxAdvancedOpen = readPanelOpen("track-fx-advanced") ?? false;
|
|
18768
19228
|
let lyricAdvancedOpen = readPanelOpen("lyric-advanced") ?? false;
|
|
@@ -19285,7 +19745,9 @@ var mountDAW = (target, options = {}) => {
|
|
|
19285
19745
|
unitsPerRow: upr = UNITS_PER_SEMITONE
|
|
19286
19746
|
} = renderConfig;
|
|
19287
19747
|
const offset = renderer.getDrawOffset();
|
|
19288
|
-
|
|
19748
|
+
const notes = active.core.getNotes();
|
|
19749
|
+
for (let i2 = notes.length - 1; i2 >= 0; i2--) {
|
|
19750
|
+
const note = notes[i2];
|
|
19289
19751
|
const logicalX = note.startStep * stepWidth;
|
|
19290
19752
|
const yIndex = keyCount - 1 - (note.pitchUnits - pitchRangeStart) / upr;
|
|
19291
19753
|
const logicalY = yIndex * keyHeight;
|
|
@@ -19361,14 +19823,18 @@ var mountDAW = (target, options = {}) => {
|
|
|
19361
19823
|
return;
|
|
19362
19824
|
}
|
|
19363
19825
|
hasDragged = false;
|
|
19364
|
-
const
|
|
19826
|
+
const hitMargin = event.pointerType === "mouse" ? 0 : Math.min(
|
|
19827
|
+
TOUCH_HIT_MARGIN,
|
|
19828
|
+
Math.max(0, Math.floor(renderConfig.keyHeight * 0.25))
|
|
19829
|
+
);
|
|
19830
|
+
const existing = findActiveNoteAt(x2, y, hitMargin);
|
|
19365
19831
|
if (existing) {
|
|
19366
19832
|
playPreview(existing.pitchUnits);
|
|
19367
19833
|
const { stepWidth } = renderConfig;
|
|
19368
19834
|
const offset = renderer.getDrawOffset();
|
|
19369
19835
|
const renderX = existing.startStep * stepWidth - offset.x;
|
|
19370
19836
|
const w = existing.durationSteps * stepWidth;
|
|
19371
|
-
if (x2 >= renderX + w - resizeHandleWidth && x2 <= renderX + w) {
|
|
19837
|
+
if (x2 >= renderX + w - resizeHandleWidth && x2 <= renderX + w + hitMargin) {
|
|
19372
19838
|
dragState = {
|
|
19373
19839
|
noteId: existing.id,
|
|
19374
19840
|
mode: "resize",
|
|
@@ -19383,7 +19849,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
19383
19849
|
noteId: existing.id,
|
|
19384
19850
|
mode: "move",
|
|
19385
19851
|
dragOffsetStep: step - existing.startStep,
|
|
19386
|
-
dragOffsetPitch:
|
|
19852
|
+
dragOffsetPitch: 0,
|
|
19387
19853
|
startStep: existing.startStep,
|
|
19388
19854
|
durationSteps: existing.durationSteps,
|
|
19389
19855
|
lastPreviewPitch: existing.pitchUnits
|
|
@@ -19498,7 +19964,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
19498
19964
|
const orig = selectedOriginal.find((o) => o.id === grab.id);
|
|
19499
19965
|
if (orig) {
|
|
19500
19966
|
const newGrab = units(orig.pitch + deltaPitch);
|
|
19501
|
-
if (newGrab !== lastMultiPreviewPitch && newGrab >=
|
|
19967
|
+
if (newGrab !== lastMultiPreviewPitch && newGrab >= PITCH_RANGE_START && newGrab <= PITCH_RANGE_END) {
|
|
19502
19968
|
lastMultiPreviewPitch = newGrab;
|
|
19503
19969
|
playPreview(newGrab);
|
|
19504
19970
|
}
|
|
@@ -19647,11 +20113,9 @@ var mountDAW = (target, options = {}) => {
|
|
|
19647
20113
|
gridCanvas.addEventListener("dblclick", (event) => {
|
|
19648
20114
|
event.preventDefault();
|
|
19649
20115
|
if (isActiveLocked()) return;
|
|
19650
|
-
const {
|
|
20116
|
+
const { x: x2, y } = renderer.getGridPosition(event);
|
|
19651
20117
|
const active = getActive();
|
|
19652
|
-
const note =
|
|
19653
|
-
(n) => n.pitchUnits === pitch && step >= n.startStep && step < n.startStep + n.durationSteps
|
|
19654
|
-
);
|
|
20118
|
+
const note = findActiveNoteAt(x2, y);
|
|
19655
20119
|
if (note) active.core.deleteNoteById(note.id);
|
|
19656
20120
|
});
|
|
19657
20121
|
gridCanvas.addEventListener(
|
|
@@ -19796,8 +20260,8 @@ var mountDAW = (target, options = {}) => {
|
|
|
19796
20260
|
redrawAll();
|
|
19797
20261
|
},
|
|
19798
20262
|
onEnd: (interrupted) => {
|
|
19799
|
-
options.onScheduleFade?.(null);
|
|
19800
20263
|
if (interrupted) {
|
|
20264
|
+
options.onScheduleFade?.(null);
|
|
19801
20265
|
playbackState = "paused";
|
|
19802
20266
|
pausedPlayStep = currentPlayStep;
|
|
19803
20267
|
} else {
|
|
@@ -21929,6 +22393,10 @@ var mountDAW = (target, options = {}) => {
|
|
|
21929
22393
|
}
|
|
21930
22394
|
return ADVANCED_COMPOSE_LAYOUT.filter((l) => l.part === "bass").map((l) => trackStates[l.index]).filter((t) => !!t);
|
|
21931
22395
|
};
|
|
22396
|
+
const selectedComposeTemplate = () => {
|
|
22397
|
+
const val = refs.composeTemplate?.value;
|
|
22398
|
+
return val && val !== "custom" ? val : void 0;
|
|
22399
|
+
};
|
|
21932
22400
|
const selectedComposeSections = () => {
|
|
21933
22401
|
const boxes = [
|
|
21934
22402
|
...refs.composeSections.querySelectorAll(
|
|
@@ -21939,11 +22407,97 @@ var mountDAW = (target, options = {}) => {
|
|
|
21939
22407
|
return picked.length > 0 ? picked : DEFAULT_SECTIONS;
|
|
21940
22408
|
};
|
|
21941
22409
|
const updateComposeSectionsLen = () => {
|
|
21942
|
-
const
|
|
22410
|
+
const tmpl = selectedComposeTemplate();
|
|
22411
|
+
const plan = buildSectionPlan(selectedComposeSections(), tmpl);
|
|
21943
22412
|
const bars = plan.reduce((sum, x2) => sum + x2.bars, 0);
|
|
21944
22413
|
refs.composeSectionsLen.textContent = `${bars}\u5C0F\u7BC0`;
|
|
21945
22414
|
};
|
|
21946
|
-
|
|
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
|
+
}
|
|
21947
22501
|
updateComposeSectionsLen();
|
|
21948
22502
|
const updateComposeKeyHint = () => {
|
|
21949
22503
|
if (!refs.composeKey || !refs.composeKeyHint) return;
|
|
@@ -21951,17 +22505,33 @@ var mountDAW = (target, options = {}) => {
|
|
|
21951
22505
|
refs.composeKeyHint.textContent = desc;
|
|
21952
22506
|
refs.composeKeyHint.title = desc;
|
|
21953
22507
|
};
|
|
21954
|
-
|
|
21955
|
-
|
|
22508
|
+
const composeKey = refs.composeKey;
|
|
22509
|
+
if (composeKey) {
|
|
22510
|
+
composeKey.addEventListener("change", () => {
|
|
22511
|
+
writeMacroSetting("key", composeKey.value);
|
|
22512
|
+
updateComposeKeyHint();
|
|
22513
|
+
});
|
|
21956
22514
|
updateComposeKeyHint();
|
|
21957
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
|
+
}
|
|
21958
22526
|
const runCompose = (withVocal) => {
|
|
21959
22527
|
stop();
|
|
21960
22528
|
overlayDuring(() => {
|
|
22529
|
+
const tmpl = selectedComposeTemplate();
|
|
21961
22530
|
const song = composeSong({
|
|
21962
22531
|
stepsPerBar: renderConfig.stepsPerBar,
|
|
21963
22532
|
edo: renderConfig.edo,
|
|
21964
22533
|
sections: selectedComposeSections(),
|
|
22534
|
+
template: tmpl,
|
|
21965
22535
|
baseKey: refs.composeKey?.value ?? "any",
|
|
21966
22536
|
// 直近に作った曲の特徴を渡すと、それらから離れた候補に加点される。
|
|
21967
22537
|
// 「作曲」を続けて押したときに似た曲が並ぶのを防ぐ。
|
|
@@ -22000,7 +22570,19 @@ var mountDAW = (target, options = {}) => {
|
|
|
22000
22570
|
for (const layer of ADVANCED_COMPOSE_LAYOUT) {
|
|
22001
22571
|
const track = trackStates[layer.index];
|
|
22002
22572
|
if (!track) continue;
|
|
22003
|
-
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({
|
|
22004
22586
|
edo: renderConfig.edo,
|
|
22005
22587
|
chordStr: song.chordProgression,
|
|
22006
22588
|
patternType: layer.part,
|
|
@@ -22039,6 +22621,12 @@ var mountDAW = (target, options = {}) => {
|
|
|
22039
22621
|
refs.drumSelect.value = song.drum;
|
|
22040
22622
|
options.onDrumChange?.(song.drum);
|
|
22041
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
|
+
}
|
|
22042
22630
|
for (const t of bassTracksForCompose()) {
|
|
22043
22631
|
t.trackCompression = AUTO_ROLE_MIX.bass.compression;
|
|
22044
22632
|
options.onTrackCompressionChange?.(t.config.id, t.trackCompression);
|
|
@@ -23549,7 +24137,7 @@ var createPianoRoll = (options, handlers) => {
|
|
|
23549
24137
|
const h = keyHeight;
|
|
23550
24138
|
const renderX = logicalX - offset.x;
|
|
23551
24139
|
const renderY = logicalY - offset.y;
|
|
23552
|
-
if (x2 >= renderX && x2
|
|
24140
|
+
if (x2 >= renderX && x2 < renderX + w && y >= renderY && y < renderY + h) {
|
|
23553
24141
|
return note;
|
|
23554
24142
|
}
|
|
23555
24143
|
}
|
|
@@ -24312,6 +24900,8 @@ var createDtmStudio = async (options = {}) => {
|
|
|
24312
24900
|
if (fadeOutStartAt !== void 0 && fadeOutEndAt !== void 0) {
|
|
24313
24901
|
fadeGain.gain.setValueAtTime(1, fadeOutStartAt);
|
|
24314
24902
|
fadeGain.gain.linearRampToValueAtTime(0, fadeOutEndAt);
|
|
24903
|
+
fadeGain.gain.setValueAtTime(0, fadeOutEndAt + 2);
|
|
24904
|
+
fadeGain.gain.setValueAtTime(1, fadeOutEndAt + 2);
|
|
24315
24905
|
}
|
|
24316
24906
|
};
|
|
24317
24907
|
const clipMeter = createClipMeter(audioCtx, glueMakeup);
|
|
@@ -24539,13 +25129,17 @@ var createDtmStudio = async (options = {}) => {
|
|
|
24539
25129
|
}
|
|
24540
25130
|
const select = doc.createElement("select");
|
|
24541
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);
|
|
24542
25136
|
for (const [key, p] of Object.entries(INSTRUMENT_PRESETS)) {
|
|
24543
25137
|
const o = doc.createElement("option");
|
|
24544
25138
|
o.value = key;
|
|
24545
25139
|
o.textContent = p.displayName;
|
|
24546
25140
|
select.appendChild(o);
|
|
24547
25141
|
}
|
|
24548
|
-
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;
|
|
24549
25143
|
wrapper.appendChild(select);
|
|
24550
25144
|
let busy = false;
|
|
24551
25145
|
const onChange = async () => {
|
|
@@ -24554,6 +25148,10 @@ var createDtmStudio = async (options = {}) => {
|
|
|
24554
25148
|
busy = true;
|
|
24555
25149
|
const key = select.value;
|
|
24556
25150
|
opts.onChange?.(key);
|
|
25151
|
+
if (key === "auto") {
|
|
25152
|
+
busy = false;
|
|
25153
|
+
return;
|
|
25154
|
+
}
|
|
24557
25155
|
const trackIds = opts.getTrackIds?.() ?? [...TRACK_ROLES];
|
|
24558
25156
|
const isAdvanced = trackIds.includes("t0");
|
|
24559
25157
|
const mode = isAdvanced ? "advanced" : "simple";
|
|
@@ -24571,7 +25169,7 @@ var createDtmStudio = async (options = {}) => {
|
|
|
24571
25169
|
element: wrapper,
|
|
24572
25170
|
select,
|
|
24573
25171
|
setValue: (k) => {
|
|
24574
|
-
if (INSTRUMENT_PRESETS[k]) select.value = k;
|
|
25172
|
+
if (k === "auto" || INSTRUMENT_PRESETS[k]) select.value = k;
|
|
24575
25173
|
},
|
|
24576
25174
|
getValue: () => select.value,
|
|
24577
25175
|
destroy: () => {
|
|
@@ -24583,8 +25181,15 @@ var createDtmStudio = async (options = {}) => {
|
|
|
24583
25181
|
await listReady;
|
|
24584
25182
|
nameToKey = await buildNameToKeyMapping();
|
|
24585
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
|
+
};
|
|
24586
25190
|
const playDrum = (e) => {
|
|
24587
25191
|
if (!sfDrum.font) return;
|
|
25192
|
+
if (e.when === 0) restoreFadeGainIfMuted();
|
|
24588
25193
|
if (KICK_PITCHES.has(e.pitch)) duckBassForKick(e.when);
|
|
24589
25194
|
sfDrum.play({
|
|
24590
25195
|
ctx: audioCtx,
|
|
@@ -24628,6 +25233,7 @@ var createDtmStudio = async (options = {}) => {
|
|
|
24628
25233
|
}
|
|
24629
25234
|
}
|
|
24630
25235
|
const playNote4 = (e) => {
|
|
25236
|
+
if (e.when === 0) restoreFadeGainIfMuted();
|
|
24631
25237
|
const { trackIdx, role } = resolveTrackIdxAndRole(e.trackId);
|
|
24632
25238
|
const overrideKey = trackIdx >= 0 ? trackInstOverrides.get(trackIdx) : void 0;
|
|
24633
25239
|
let sfInst;
|
|
@@ -24653,12 +25259,33 @@ var createDtmStudio = async (options = {}) => {
|
|
|
24653
25259
|
duration: e.duration
|
|
24654
25260
|
});
|
|
24655
25261
|
};
|
|
25262
|
+
let daw;
|
|
24656
25263
|
let presetSelect = null;
|
|
24657
25264
|
const handleInstrumentChange = (key) => {
|
|
25265
|
+
if (key === "auto") {
|
|
25266
|
+
if (presetSelect) {
|
|
25267
|
+
presetSelect.setValue("auto");
|
|
25268
|
+
}
|
|
25269
|
+
onInstrumentChange?.("auto");
|
|
25270
|
+
return;
|
|
25271
|
+
}
|
|
24658
25272
|
editorPreset = key;
|
|
24659
25273
|
if (presetSelect) {
|
|
24660
25274
|
presetSelect.setValue(key);
|
|
24661
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
|
+
}
|
|
24662
25289
|
onInstrumentChange?.(key);
|
|
24663
25290
|
};
|
|
24664
25291
|
const handleTrackInstrumentChange = async (trackIndex, instrumentName) => {
|
|
@@ -24672,7 +25299,6 @@ var createDtmStudio = async (options = {}) => {
|
|
|
24672
25299
|
trackInstOverrides.set(trackIndex, key);
|
|
24673
25300
|
await loadInstrument(key);
|
|
24674
25301
|
};
|
|
24675
|
-
let daw;
|
|
24676
25302
|
const base = {
|
|
24677
25303
|
getAudioTime: () => audioCtx.currentTime,
|
|
24678
25304
|
onResumeAudio: async () => {
|
|
@@ -25431,6 +26057,7 @@ var createDtmStudio = async (options = {}) => {
|
|
|
25431
26057
|
KOE_VOICEBANK_LABELS,
|
|
25432
26058
|
KOE_VOICEBANK_TERMS,
|
|
25433
26059
|
LinkedList,
|
|
26060
|
+
MACRO_STORAGE_KEYS,
|
|
25434
26061
|
MAJOR_KEY_IDS,
|
|
25435
26062
|
MAX_VOCAL_VOLUME,
|
|
25436
26063
|
MICRO_STEP,
|
|
@@ -25533,6 +26160,8 @@ var createDtmStudio = async (options = {}) => {
|
|
|
25533
26160
|
playNote,
|
|
25534
26161
|
playPlacements,
|
|
25535
26162
|
playSingingMML,
|
|
26163
|
+
readMacroSections,
|
|
26164
|
+
readMacroSetting,
|
|
25536
26165
|
resolveComposeKey,
|
|
25537
26166
|
resolveDrumPattern,
|
|
25538
26167
|
resolveLoopPoint,
|
|
@@ -25555,5 +26184,7 @@ var createDtmStudio = async (options = {}) => {
|
|
|
25555
26184
|
unitsToMidi,
|
|
25556
26185
|
unitsToMidiDetune,
|
|
25557
26186
|
unitsToPitchV1,
|
|
25558
|
-
vocalVolumeToGain
|
|
26187
|
+
vocalVolumeToGain,
|
|
26188
|
+
writeMacroSections,
|
|
26189
|
+
writeMacroSetting
|
|
25559
26190
|
});
|