@onjmin/dtm 0.1.13 → 0.1.15
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/README.md +21 -1
- package/dist/index.d.mts +14 -3
- package/dist/index.d.ts +14 -3
- package/dist/index.js +8 -16
- package/dist/index.mjs +8 -16
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -38,7 +38,7 @@ studio.mountPlayer(document.getElementById("player"), daw.getMML().full);
|
|
|
38
38
|
| モード | トラック | MIDI 取り込み | 伴奏(コード進行)UI |
|
|
39
39
|
| --- | --- | --- | --- |
|
|
40
40
|
| `simple` | メロディー / サブメロ / ベース / 伴奏 の 4 本 | 各トラックの特徴から役割へ**自動分類** | `chord` トラックに表示(歌詞欄の代わり) |
|
|
41
|
-
| `advanced` | TRACK 01〜
|
|
41
|
+
| `advanced` | TRACK 01〜15 の 15 本(フラットな連番) | MIDI トラックを**1:1 マッピング** | なし(全トラックが通常のノート+歌詞トラック) |
|
|
42
42
|
|
|
43
43
|
```ts
|
|
44
44
|
import {
|
|
@@ -62,6 +62,26 @@ studio.mountEditor(editorEl, { mode: "advanced", tracks: TRACKS_ADVANCED });
|
|
|
62
62
|
- MIDI のドラム(ch10)はピアノロールで編集できないため、取り込み時の**トラック選択 UI には出ません**。
|
|
63
63
|
- `mode` / `tracks` は低レベル API の `mountDAW` でも同じく指定できます。
|
|
64
64
|
|
|
65
|
+
### 備考: トラック採番と MIDI チャンネルの対応(暫定仕様)
|
|
66
|
+
|
|
67
|
+
`advanced` の `@n` / タブ名は **MML 仕様に合わせたフラットな連番**(`@0`〜`@14` / TRACK 01〜15、欠番なし)です。
|
|
68
|
+
「ch10 = ドラム」という MIDI の慣習は内部モデルには持ち込まず、**MIDI 入出力の変換時にだけ**扱います。
|
|
69
|
+
|
|
70
|
+
- **出力**: レーン index → MIDI チャンネルに変換する際、打楽器ch(内部 `channel 9` = 1始まり ch10)を避けます。
|
|
71
|
+
結果、TRACK 01〜09 → ch1〜9 / **TRACK 10〜15 → ch11〜16** に書き出されます(タブ番号と MIDI ch は
|
|
72
|
+
10 番以降ズレますが、これは出力時の変換詳細です)。15 レーン ⇄ 15 個の非打楽器ch がちょうど 1:1 で、
|
|
73
|
+
チャンネル衝突は起きません。
|
|
74
|
+
- **入力**: `channel 9`(ドラム)のノートは取り込まず、ドラムだけのトラックは選択 UI にも出しません。
|
|
75
|
+
選択したトラックは**選択順に上から**レーンへ詰めます(MIDI の実トラック番号やテンポトラックの有無に
|
|
76
|
+
左右されません)。
|
|
77
|
+
- ドラム自体はノートレーンではなく、別系統の**ドラム設定**で編集します。
|
|
78
|
+
|
|
79
|
+
> 経緯: 当初は「タブ番号 = MIDI チャンネル番号」に揃え、ドラムの ch10 をタブの欠番にする案も検討しましたが、
|
|
80
|
+
> このアプリの正規フォーマットは MML(0 始まり・フラット・ドラムch非依存)であり、MIDI は境界の交換
|
|
81
|
+
> フォーマットに過ぎません。MIDI の慣習を内部採番に漏らすと MML の一貫性が崩れる(モード間で採番が割れる、
|
|
82
|
+
> 永続化される MML に欠番が残る等)ため、**内部は MML 仕様に寄せ、ch10=ドラムの面倒は変換層に閉じ込める**
|
|
83
|
+
> 方針に決めました。
|
|
84
|
+
|
|
65
85
|
## 低レベル API(`mountDAW` / 注入式)
|
|
66
86
|
|
|
67
87
|
本体は音を持たない設計で、`onPlayNote` / `onPlayDrum` に自前のシンセを繋ぐ
|
package/dist/index.d.mts
CHANGED
|
@@ -621,7 +621,13 @@ type DawInstance = {
|
|
|
621
621
|
|
|
622
622
|
/** シンプルモード(4トラック)— 役割別に自動分類してMIDIを読み込む */
|
|
623
623
|
declare const TRACKS_SIMPLE: TrackConfig[];
|
|
624
|
-
/**
|
|
624
|
+
/**
|
|
625
|
+
* advancedモード(15トラック)— MIDIトラックを1:1で扱う。
|
|
626
|
+
* 採番はMML仕様に合わせてフラットな連番(@0〜@14 / TRACK 01〜15、欠番なし)。
|
|
627
|
+
* MIDIの「ch10=ドラム」の慣習は内部モデルに持ち込まず、MIDI入出力の変換時にだけ扱う:
|
|
628
|
+
* 出力は打楽器ch(内部 channel 9)を避けて割り当て(TRACK 10以降は ch11〜16 へ)、
|
|
629
|
+
* 入力は channel 9 のドラムを除外する。ドラム自体は別系統の「ドラム設定」で編集する。
|
|
630
|
+
*/
|
|
625
631
|
declare const TRACKS_ADVANCED: TrackConfig[];
|
|
626
632
|
/**
|
|
627
633
|
* DAWコンポーネントをマウントする。
|
|
@@ -861,8 +867,13 @@ declare const getMidiBPM: (midi: unknown) => number;
|
|
|
861
867
|
*/
|
|
862
868
|
declare const extractMidiPlacements: (midi: unknown, selectedTrackIndices: number[]) => MidiExtraction;
|
|
863
869
|
/**
|
|
864
|
-
*
|
|
865
|
-
*
|
|
870
|
+
* advancedモード用:選択された MIDI トラックを選択順に DAW トラックへ上から詰める
|
|
871
|
+
* (k番目に選んだトラック → trackIds[k])。自動分類なし。
|
|
872
|
+
*
|
|
873
|
+
* MIDIの実トラック番号ではなく「選択順の位置」で割り当てるため、先頭のテンポ/コンダクタ
|
|
874
|
+
* トラックや、空・ドラムだけのトラックが混ざっていても DAW レーンがずれない
|
|
875
|
+
* (これらは選択リストに出ない/選ばれないので位置を消費しない)。
|
|
876
|
+
* ドラム(ch10 = channel 9)のノートはスキップする。
|
|
866
877
|
*/
|
|
867
878
|
declare const extractMidiPlacementsByTrack: (midi: unknown, selectedIndices: number[], trackIds: string[]) => MidiExtraction;
|
|
868
879
|
type ExportMidiOptions = {
|
package/dist/index.d.ts
CHANGED
|
@@ -621,7 +621,13 @@ type DawInstance = {
|
|
|
621
621
|
|
|
622
622
|
/** シンプルモード(4トラック)— 役割別に自動分類してMIDIを読み込む */
|
|
623
623
|
declare const TRACKS_SIMPLE: TrackConfig[];
|
|
624
|
-
/**
|
|
624
|
+
/**
|
|
625
|
+
* advancedモード(15トラック)— MIDIトラックを1:1で扱う。
|
|
626
|
+
* 採番はMML仕様に合わせてフラットな連番(@0〜@14 / TRACK 01〜15、欠番なし)。
|
|
627
|
+
* MIDIの「ch10=ドラム」の慣習は内部モデルに持ち込まず、MIDI入出力の変換時にだけ扱う:
|
|
628
|
+
* 出力は打楽器ch(内部 channel 9)を避けて割り当て(TRACK 10以降は ch11〜16 へ)、
|
|
629
|
+
* 入力は channel 9 のドラムを除外する。ドラム自体は別系統の「ドラム設定」で編集する。
|
|
630
|
+
*/
|
|
625
631
|
declare const TRACKS_ADVANCED: TrackConfig[];
|
|
626
632
|
/**
|
|
627
633
|
* DAWコンポーネントをマウントする。
|
|
@@ -861,8 +867,13 @@ declare const getMidiBPM: (midi: unknown) => number;
|
|
|
861
867
|
*/
|
|
862
868
|
declare const extractMidiPlacements: (midi: unknown, selectedTrackIndices: number[]) => MidiExtraction;
|
|
863
869
|
/**
|
|
864
|
-
*
|
|
865
|
-
*
|
|
870
|
+
* advancedモード用:選択された MIDI トラックを選択順に DAW トラックへ上から詰める
|
|
871
|
+
* (k番目に選んだトラック → trackIds[k])。自動分類なし。
|
|
872
|
+
*
|
|
873
|
+
* MIDIの実トラック番号ではなく「選択順の位置」で割り当てるため、先頭のテンポ/コンダクタ
|
|
874
|
+
* トラックや、空・ドラムだけのトラックが混ざっていても DAW レーンがずれない
|
|
875
|
+
* (これらは選択リストに出ない/選ばれないので位置を消費しない)。
|
|
876
|
+
* ドラム(ch10 = channel 9)のノートはスキップする。
|
|
866
877
|
*/
|
|
867
878
|
declare const extractMidiPlacementsByTrack: (midi: unknown, selectedIndices: number[], trackIds: string[]) => MidiExtraction;
|
|
868
879
|
type ExportMidiOptions = {
|
package/dist/index.js
CHANGED
|
@@ -3077,13 +3077,11 @@ var extractMidiPlacementsByTrack = (midi, selectedIndices, trackIds) => {
|
|
|
3077
3077
|
const bpm = getMidiBPM(midi);
|
|
3078
3078
|
const ticksPerStep = ticksPerBeat / STEPS_PER_BEAT;
|
|
3079
3079
|
const placements = [];
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
if (!selectedSet.has(midiIdx)) continue;
|
|
3083
|
-
if (midiIdx >= trackIds.length) continue;
|
|
3084
|
-
const trackId = trackIds[midiIdx];
|
|
3080
|
+
selectedIndices.forEach((midiIdx, lane) => {
|
|
3081
|
+
if (lane >= trackIds.length) return;
|
|
3085
3082
|
const trackData = track[midiIdx];
|
|
3086
|
-
if (!trackData)
|
|
3083
|
+
if (!trackData) return;
|
|
3084
|
+
const trackId = trackIds[lane];
|
|
3087
3085
|
const active = [];
|
|
3088
3086
|
let currentTime = 0;
|
|
3089
3087
|
for (const event of trackData.event) {
|
|
@@ -3118,7 +3116,7 @@ var extractMidiPlacementsByTrack = (midi, selectedIndices, trackIds) => {
|
|
|
3118
3116
|
velocity: note.velocity
|
|
3119
3117
|
});
|
|
3120
3118
|
}
|
|
3121
|
-
}
|
|
3119
|
+
});
|
|
3122
3120
|
return { placements, bpm };
|
|
3123
3121
|
};
|
|
3124
3122
|
var to2byte = (n) => [(n & 65280) >> 8, n & 255];
|
|
@@ -3159,6 +3157,7 @@ var exportMIDI = (options) => {
|
|
|
3159
3157
|
const midiTracks = [];
|
|
3160
3158
|
tracks.forEach((track, ch) => {
|
|
3161
3159
|
if (track.notes.length === 0) return;
|
|
3160
|
+
const channel = ch < 9 ? ch : ch + 1 & 15;
|
|
3162
3161
|
const events = [];
|
|
3163
3162
|
for (const n of track.notes) {
|
|
3164
3163
|
const startTick = Math.round(n.startStep * tickPerStep);
|
|
@@ -3168,8 +3167,8 @@ var exportMIDI = (options) => {
|
|
|
3168
3167
|
const vel = Math.round(
|
|
3169
3168
|
(n.velocity ?? DEFAULT_VELOCITY) * (track.volume ?? 100) / 100
|
|
3170
3169
|
);
|
|
3171
|
-
events.push({ t: startTick, m: [144 |
|
|
3172
|
-
events.push({ t: endTick, m: [144 |
|
|
3170
|
+
events.push({ t: startTick, m: [144 | channel, n.pitch, vel] });
|
|
3171
|
+
events.push({ t: endTick, m: [144 | channel, n.pitch, 0] });
|
|
3173
3172
|
}
|
|
3174
3173
|
events.sort((a, b) => a.t - b.t);
|
|
3175
3174
|
midiTracks.push(events);
|
|
@@ -5530,13 +5529,6 @@ var TRACKS_ADVANCED = [
|
|
|
5530
5529
|
color: [100, 255, 160],
|
|
5531
5530
|
instrument: 14,
|
|
5532
5531
|
volume: 100
|
|
5533
|
-
},
|
|
5534
|
-
{
|
|
5535
|
-
id: "t15",
|
|
5536
|
-
name: "TRACK 16",
|
|
5537
|
-
color: [255, 150, 200],
|
|
5538
|
-
instrument: 15,
|
|
5539
|
-
volume: 100
|
|
5540
5532
|
}
|
|
5541
5533
|
];
|
|
5542
5534
|
var DEFAULT_TRACKS = TRACKS_SIMPLE;
|
package/dist/index.mjs
CHANGED
|
@@ -2972,13 +2972,11 @@ var extractMidiPlacementsByTrack = (midi, selectedIndices, trackIds) => {
|
|
|
2972
2972
|
const bpm = getMidiBPM(midi);
|
|
2973
2973
|
const ticksPerStep = ticksPerBeat / STEPS_PER_BEAT;
|
|
2974
2974
|
const placements = [];
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
if (!selectedSet.has(midiIdx)) continue;
|
|
2978
|
-
if (midiIdx >= trackIds.length) continue;
|
|
2979
|
-
const trackId = trackIds[midiIdx];
|
|
2975
|
+
selectedIndices.forEach((midiIdx, lane) => {
|
|
2976
|
+
if (lane >= trackIds.length) return;
|
|
2980
2977
|
const trackData = track[midiIdx];
|
|
2981
|
-
if (!trackData)
|
|
2978
|
+
if (!trackData) return;
|
|
2979
|
+
const trackId = trackIds[lane];
|
|
2982
2980
|
const active = [];
|
|
2983
2981
|
let currentTime = 0;
|
|
2984
2982
|
for (const event of trackData.event) {
|
|
@@ -3013,7 +3011,7 @@ var extractMidiPlacementsByTrack = (midi, selectedIndices, trackIds) => {
|
|
|
3013
3011
|
velocity: note.velocity
|
|
3014
3012
|
});
|
|
3015
3013
|
}
|
|
3016
|
-
}
|
|
3014
|
+
});
|
|
3017
3015
|
return { placements, bpm };
|
|
3018
3016
|
};
|
|
3019
3017
|
var to2byte = (n) => [(n & 65280) >> 8, n & 255];
|
|
@@ -3054,6 +3052,7 @@ var exportMIDI = (options) => {
|
|
|
3054
3052
|
const midiTracks = [];
|
|
3055
3053
|
tracks.forEach((track, ch) => {
|
|
3056
3054
|
if (track.notes.length === 0) return;
|
|
3055
|
+
const channel = ch < 9 ? ch : ch + 1 & 15;
|
|
3057
3056
|
const events = [];
|
|
3058
3057
|
for (const n of track.notes) {
|
|
3059
3058
|
const startTick = Math.round(n.startStep * tickPerStep);
|
|
@@ -3063,8 +3062,8 @@ var exportMIDI = (options) => {
|
|
|
3063
3062
|
const vel = Math.round(
|
|
3064
3063
|
(n.velocity ?? DEFAULT_VELOCITY) * (track.volume ?? 100) / 100
|
|
3065
3064
|
);
|
|
3066
|
-
events.push({ t: startTick, m: [144 |
|
|
3067
|
-
events.push({ t: endTick, m: [144 |
|
|
3065
|
+
events.push({ t: startTick, m: [144 | channel, n.pitch, vel] });
|
|
3066
|
+
events.push({ t: endTick, m: [144 | channel, n.pitch, 0] });
|
|
3068
3067
|
}
|
|
3069
3068
|
events.sort((a, b) => a.t - b.t);
|
|
3070
3069
|
midiTracks.push(events);
|
|
@@ -5425,13 +5424,6 @@ var TRACKS_ADVANCED = [
|
|
|
5425
5424
|
color: [100, 255, 160],
|
|
5426
5425
|
instrument: 14,
|
|
5427
5426
|
volume: 100
|
|
5428
|
-
},
|
|
5429
|
-
{
|
|
5430
|
-
id: "t15",
|
|
5431
|
-
name: "TRACK 16",
|
|
5432
|
-
color: [255, 150, 200],
|
|
5433
|
-
instrument: 15,
|
|
5434
|
-
volume: 100
|
|
5435
5427
|
}
|
|
5436
5428
|
];
|
|
5437
5429
|
var DEFAULT_TRACKS = TRACKS_SIMPLE;
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"author": "onjmin",
|
|
3
3
|
"license": "MIT",
|
|
4
4
|
"name": "@onjmin/dtm",
|
|
5
|
-
"version": "0.1.
|
|
5
|
+
"version": "0.1.15",
|
|
6
6
|
"description": "MMLを中間言語に用いた、モバイルファーストなDAW / ピアノロール打ち込みコンポーネント",
|
|
7
7
|
"homepage": "https://onjmin.github.io/dtm",
|
|
8
8
|
"repository": {
|
|
@@ -53,6 +53,7 @@
|
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
55
|
"@onjmin/chord-parser": "1.0.2",
|
|
56
|
+
"@onjmin/dtm": "0.1.14",
|
|
56
57
|
"@onjmin/koe": "1.0.3"
|
|
57
58
|
},
|
|
58
59
|
"scripts": {
|