@onjmin/dtm 0.1.12 → 0.1.14
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 +32 -0
- package/dist/index.d.mts +23 -3
- package/dist/index.d.ts +23 -3
- package/dist/index.js +61 -20
- package/dist/index.mjs +61 -20
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -30,6 +30,38 @@ const daw = studio.mountEditor(document.getElementById("editor"), {
|
|
|
30
30
|
studio.mountPlayer(document.getElementById("player"), daw.getMML().full);
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
+
## モード(`simple` / `advanced`)
|
|
34
|
+
|
|
35
|
+
トラック構成と MIDI の取り込み方が異なる 2 つのモードがあります。`mode` オプションで切り替え、
|
|
36
|
+
合わせて `tracks` に対応するトラック構成(`TRACKS_SIMPLE` / `TRACKS_ADVANCED`)を渡します。
|
|
37
|
+
|
|
38
|
+
| モード | トラック | MIDI 取り込み | 伴奏(コード進行)UI |
|
|
39
|
+
| --- | --- | --- | --- |
|
|
40
|
+
| `simple` | メロディー / サブメロ / ベース / 伴奏 の 4 本 | 各トラックの特徴から役割へ**自動分類** | `chord` トラックに表示(歌詞欄の代わり) |
|
|
41
|
+
| `advanced` | TRACK 01〜16 の 16 本 | MIDI トラックを**1:1 マッピング** | なし(全トラックが通常のノート+歌詞トラック) |
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
import {
|
|
45
|
+
createDtmStudio,
|
|
46
|
+
TRACKS_SIMPLE,
|
|
47
|
+
TRACKS_ADVANCED,
|
|
48
|
+
} from "@onjmin/dtm";
|
|
49
|
+
|
|
50
|
+
const studio = await createDtmStudio();
|
|
51
|
+
|
|
52
|
+
// シンプルモード(既定)
|
|
53
|
+
studio.mountEditor(editorEl, { mode: "simple", tracks: TRACKS_SIMPLE });
|
|
54
|
+
|
|
55
|
+
// アドバンスモード
|
|
56
|
+
studio.mountEditor(editorEl, { mode: "advanced", tracks: TRACKS_ADVANCED });
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
- `mode` を省略すると `tracks` の本数から推論します(4 本以下→`simple` / 5 本以上→`advanced`)。
|
|
60
|
+
4 トラックでも 1:1 で取り込みたい等、意図がトラック数とずれる場合は `mode` を明示してください。
|
|
61
|
+
- `tracks` には任意の独自構成も渡せます(`mode` と組み合わせて挙動を決めます)。
|
|
62
|
+
- MIDI のドラム(ch10)はピアノロールで編集できないため、取り込み時の**トラック選択 UI には出ません**。
|
|
63
|
+
- `mode` / `tracks` は低レベル API の `mountDAW` でも同じく指定できます。
|
|
64
|
+
|
|
33
65
|
## 低レベル API(`mountDAW` / 注入式)
|
|
34
66
|
|
|
35
67
|
本体は音を持たない設計で、`onPlayNote` / `onPlayDrum` に自前のシンセを繋ぐ
|
package/dist/index.d.mts
CHANGED
|
@@ -537,6 +537,13 @@ type DawViewState = {
|
|
|
537
537
|
/** 和音分解時に和音伴奏トラックを分解対象から除外するフラグ */
|
|
538
538
|
ignoreChordHeavy: boolean;
|
|
539
539
|
};
|
|
540
|
+
/**
|
|
541
|
+
* DAWの動作モード。
|
|
542
|
+
* - `simple`: 4トラック(メロディー/サブメロ/ベース/伴奏)。MIDIは役割別に自動分類して取り込み、
|
|
543
|
+
* id `chord` のトラックには歌詞欄の代わりに伴奏(コード進行)UIを出す。
|
|
544
|
+
* - `advanced`: MIDIトラックを1:1でマッピング。全トラックが通常のノートトラックとして振る舞う。
|
|
545
|
+
*/
|
|
546
|
+
type DawMode = "simple" | "advanced";
|
|
540
547
|
type DawOptions = {
|
|
541
548
|
/** メロディックトラックのノート発音要求 */
|
|
542
549
|
onPlayNote?: (e: PlayNoteEvent) => void;
|
|
@@ -559,6 +566,12 @@ type DawOptions = {
|
|
|
559
566
|
*/
|
|
560
567
|
onViewStateChange?: (state: DawViewState) => void;
|
|
561
568
|
parseMidi?: ParseMidiFn;
|
|
569
|
+
/**
|
|
570
|
+
* 動作モード({@link DawMode})。
|
|
571
|
+
* 未指定のときは後方互換のため `tracks` の本数から推論する(4本以下→simple / 5本以上→advanced)。
|
|
572
|
+
* 4トラック構成でも1:1取り込みをしたい等、トラック数と意図がずれる場合は明示指定する。
|
|
573
|
+
*/
|
|
574
|
+
mode?: DawMode;
|
|
562
575
|
/** トラック構成。既定は melody/submelody/bass/chord の4本 */
|
|
563
576
|
tracks?: TrackConfig[];
|
|
564
577
|
/** ドラムパターン辞書。既定は DRUM_PATTERNS */
|
|
@@ -836,6 +849,8 @@ type MidiExtraction = {
|
|
|
836
849
|
};
|
|
837
850
|
/**
|
|
838
851
|
* MIDIの各トラックを走査し、ノート数などの概要を返す(トラック選択UI用)。
|
|
852
|
+
* ノート数はピアノロールで編集可能なノートのみを数える(ドラム ch10 は除外)。
|
|
853
|
+
* ドラム(ch10)だけで構成されたトラックは編集できないため、結果に含めない。
|
|
839
854
|
*/
|
|
840
855
|
declare const analyzeMidiTracks: (midi: unknown) => MidiTrackAnalysis[];
|
|
841
856
|
/** MIDIメタイベントからBPMを取得(無ければ120)。 */
|
|
@@ -846,8 +861,13 @@ declare const getMidiBPM: (midi: unknown) => number;
|
|
|
846
861
|
*/
|
|
847
862
|
declare const extractMidiPlacements: (midi: unknown, selectedTrackIndices: number[]) => MidiExtraction;
|
|
848
863
|
/**
|
|
849
|
-
*
|
|
850
|
-
*
|
|
864
|
+
* advancedモード用:選択された MIDI トラックを選択順に DAW トラックへ上から詰める
|
|
865
|
+
* (k番目に選んだトラック → trackIds[k])。自動分類なし。
|
|
866
|
+
*
|
|
867
|
+
* MIDIの実トラック番号ではなく「選択順の位置」で割り当てるため、先頭のテンポ/コンダクタ
|
|
868
|
+
* トラックや、空・ドラムだけのトラックが混ざっていても DAW レーンがずれない
|
|
869
|
+
* (これらは選択リストに出ない/選ばれないので位置を消費しない)。
|
|
870
|
+
* ドラム(ch10 = channel 9)のノートはスキップする。
|
|
851
871
|
*/
|
|
852
872
|
declare const extractMidiPlacementsByTrack: (midi: unknown, selectedIndices: number[], trackIds: string[]) => MidiExtraction;
|
|
853
873
|
type ExportMidiOptions = {
|
|
@@ -1266,4 +1286,4 @@ declare const DAW_CSS = "\n@font-face {\n font-family: 'k8x12';\n src: url('ht
|
|
|
1266
1286
|
*/
|
|
1267
1287
|
declare const injectStyles: (doc?: Document) => void;
|
|
1268
1288
|
|
|
1269
|
-
export { type AddNoteOptions, type ApplyChordOptions, type ChordPatternType, type ChordPlacement, type ConsumedSyllable, type CoreEventHandlers, DAW_CSS, DEFAULT_BPM, DEFAULT_GATE, DEFAULT_PAN, DEFAULT_PLAYBACK_VELOCITY, DEFAULT_STEPS_PER_BAR, DEFAULT_VELOCITY, DEFAULT_VOCAL_VOLUME, DRUM_FONT, DRUM_KEYS, DRUM_PATTERNS, type DawInstance, type DawOptions, type DawViewState, type DrumPattern, type DtmStudio, type DtmStudioEngines, type DtmStudioOptions, type ExportMidiOptions, INSTRUMENT_PRESETS, type InstrumentPreset, KOE_BASE_URL, KOE_VOICEBANKS, KOE_VOICEBANK_LABELS, KOE_VOICEBANK_TERMS, type KoeVoiceOptions, LinkedList, type LyricSyllable, type LyricTrack, type LyricsConductor, MAX_VOCAL_VOLUME, MMLCore, type MMLDisplayToken, type MMLNotePlacement, MML_END_MARKER, type MidiExtraction, type MidiNotePlacement, type MidiTrackAnalysis, type MmlMeta, type MmlPlayerInstance, type MmlPlayerOptions, type MountEditorOptions, type MountPlayerOptions, type Note, PITCH_MAP, PREWARM_NOTES, type ParseMMLOptions, type ParseMidiFn, type ParsedMML, type PianoRollInstance, type PianoRollOptions, type PitchToken, type PlayDrumEvent, type PlayNoteEvent, type PlaybackState, type PreviewSoundCallback, type RenderConfig, type Sequencer, type SequencerOptions, type SequencerTrack, type SingingVoices, type SingingVoicesOptions, type StreamPlaybackOptions, type StreamVoiceNote, type StreamVoiceTrack, TRACKS_ADVANCED, TRACKS_SIMPLE, type ToolMode, type TrackConfig, VOICE_IMAGE_KEY, type VoiceModel, type VoiceRegistry, analyzeMidiTracks, applyHarmonicFilter, applyMonophonic, buildChordPlacements, buildNameToKeyMapping, collectPitchTokens, createAudioContext, createDtmStudio, createKlattVoice, createKoeVoice, createLyricsConductor, createPianoRoll, createSequencer, createSingingVoices, createVoiceRegistry, decomposeToMonophonic, drawGrid, drawHeader, drawKeyboard, drawNotes, drawSelectedNotes, drawSelectionRect, exportMIDI, extractMidiPlacements, extractMidiPlacementsByTrack, fetchSoundFontList, formatMmlMeta, generateRandomPattern, getDrawOffset, getGridCanvas, getGridContext, getGridPosition, getHeaderCanvas, getMidiBPM, getRenderConfig, getXY, icon, init, injectStyles, isChordHeavyTrack, koeUrl, mountDAW, mountMmlPlayer, normalizeLyrics, onClick, panToStereo, parseLyrics, parseMML, parseMmlMeta, setDrawOffset, setupRecorder, shiftNotes, stripLyrics, stripMmlMeta, vocalVolumeToGain };
|
|
1289
|
+
export { type AddNoteOptions, type ApplyChordOptions, type ChordPatternType, type ChordPlacement, type ConsumedSyllable, type CoreEventHandlers, DAW_CSS, DEFAULT_BPM, DEFAULT_GATE, DEFAULT_PAN, DEFAULT_PLAYBACK_VELOCITY, DEFAULT_STEPS_PER_BAR, DEFAULT_VELOCITY, DEFAULT_VOCAL_VOLUME, DRUM_FONT, DRUM_KEYS, DRUM_PATTERNS, type DawInstance, type DawMode, type DawOptions, type DawViewState, type DrumPattern, type DtmStudio, type DtmStudioEngines, type DtmStudioOptions, type ExportMidiOptions, INSTRUMENT_PRESETS, type InstrumentPreset, KOE_BASE_URL, KOE_VOICEBANKS, KOE_VOICEBANK_LABELS, KOE_VOICEBANK_TERMS, type KoeVoiceOptions, LinkedList, type LyricSyllable, type LyricTrack, type LyricsConductor, MAX_VOCAL_VOLUME, MMLCore, type MMLDisplayToken, type MMLNotePlacement, MML_END_MARKER, type MidiExtraction, type MidiNotePlacement, type MidiTrackAnalysis, type MmlMeta, type MmlPlayerInstance, type MmlPlayerOptions, type MountEditorOptions, type MountPlayerOptions, type Note, PITCH_MAP, PREWARM_NOTES, type ParseMMLOptions, type ParseMidiFn, type ParsedMML, type PianoRollInstance, type PianoRollOptions, type PitchToken, type PlayDrumEvent, type PlayNoteEvent, type PlaybackState, type PreviewSoundCallback, type RenderConfig, type Sequencer, type SequencerOptions, type SequencerTrack, type SingingVoices, type SingingVoicesOptions, type StreamPlaybackOptions, type StreamVoiceNote, type StreamVoiceTrack, TRACKS_ADVANCED, TRACKS_SIMPLE, type ToolMode, type TrackConfig, VOICE_IMAGE_KEY, type VoiceModel, type VoiceRegistry, analyzeMidiTracks, applyHarmonicFilter, applyMonophonic, buildChordPlacements, buildNameToKeyMapping, collectPitchTokens, createAudioContext, createDtmStudio, createKlattVoice, createKoeVoice, createLyricsConductor, createPianoRoll, createSequencer, createSingingVoices, createVoiceRegistry, decomposeToMonophonic, drawGrid, drawHeader, drawKeyboard, drawNotes, drawSelectedNotes, drawSelectionRect, exportMIDI, extractMidiPlacements, extractMidiPlacementsByTrack, fetchSoundFontList, formatMmlMeta, generateRandomPattern, getDrawOffset, getGridCanvas, getGridContext, getGridPosition, getHeaderCanvas, getMidiBPM, getRenderConfig, getXY, icon, init, injectStyles, isChordHeavyTrack, koeUrl, mountDAW, mountMmlPlayer, normalizeLyrics, onClick, panToStereo, parseLyrics, parseMML, parseMmlMeta, setDrawOffset, setupRecorder, shiftNotes, stripLyrics, stripMmlMeta, vocalVolumeToGain };
|
package/dist/index.d.ts
CHANGED
|
@@ -537,6 +537,13 @@ type DawViewState = {
|
|
|
537
537
|
/** 和音分解時に和音伴奏トラックを分解対象から除外するフラグ */
|
|
538
538
|
ignoreChordHeavy: boolean;
|
|
539
539
|
};
|
|
540
|
+
/**
|
|
541
|
+
* DAWの動作モード。
|
|
542
|
+
* - `simple`: 4トラック(メロディー/サブメロ/ベース/伴奏)。MIDIは役割別に自動分類して取り込み、
|
|
543
|
+
* id `chord` のトラックには歌詞欄の代わりに伴奏(コード進行)UIを出す。
|
|
544
|
+
* - `advanced`: MIDIトラックを1:1でマッピング。全トラックが通常のノートトラックとして振る舞う。
|
|
545
|
+
*/
|
|
546
|
+
type DawMode = "simple" | "advanced";
|
|
540
547
|
type DawOptions = {
|
|
541
548
|
/** メロディックトラックのノート発音要求 */
|
|
542
549
|
onPlayNote?: (e: PlayNoteEvent) => void;
|
|
@@ -559,6 +566,12 @@ type DawOptions = {
|
|
|
559
566
|
*/
|
|
560
567
|
onViewStateChange?: (state: DawViewState) => void;
|
|
561
568
|
parseMidi?: ParseMidiFn;
|
|
569
|
+
/**
|
|
570
|
+
* 動作モード({@link DawMode})。
|
|
571
|
+
* 未指定のときは後方互換のため `tracks` の本数から推論する(4本以下→simple / 5本以上→advanced)。
|
|
572
|
+
* 4トラック構成でも1:1取り込みをしたい等、トラック数と意図がずれる場合は明示指定する。
|
|
573
|
+
*/
|
|
574
|
+
mode?: DawMode;
|
|
562
575
|
/** トラック構成。既定は melody/submelody/bass/chord の4本 */
|
|
563
576
|
tracks?: TrackConfig[];
|
|
564
577
|
/** ドラムパターン辞書。既定は DRUM_PATTERNS */
|
|
@@ -836,6 +849,8 @@ type MidiExtraction = {
|
|
|
836
849
|
};
|
|
837
850
|
/**
|
|
838
851
|
* MIDIの各トラックを走査し、ノート数などの概要を返す(トラック選択UI用)。
|
|
852
|
+
* ノート数はピアノロールで編集可能なノートのみを数える(ドラム ch10 は除外)。
|
|
853
|
+
* ドラム(ch10)だけで構成されたトラックは編集できないため、結果に含めない。
|
|
839
854
|
*/
|
|
840
855
|
declare const analyzeMidiTracks: (midi: unknown) => MidiTrackAnalysis[];
|
|
841
856
|
/** MIDIメタイベントからBPMを取得(無ければ120)。 */
|
|
@@ -846,8 +861,13 @@ declare const getMidiBPM: (midi: unknown) => number;
|
|
|
846
861
|
*/
|
|
847
862
|
declare const extractMidiPlacements: (midi: unknown, selectedTrackIndices: number[]) => MidiExtraction;
|
|
848
863
|
/**
|
|
849
|
-
*
|
|
850
|
-
*
|
|
864
|
+
* advancedモード用:選択された MIDI トラックを選択順に DAW トラックへ上から詰める
|
|
865
|
+
* (k番目に選んだトラック → trackIds[k])。自動分類なし。
|
|
866
|
+
*
|
|
867
|
+
* MIDIの実トラック番号ではなく「選択順の位置」で割り当てるため、先頭のテンポ/コンダクタ
|
|
868
|
+
* トラックや、空・ドラムだけのトラックが混ざっていても DAW レーンがずれない
|
|
869
|
+
* (これらは選択リストに出ない/選ばれないので位置を消費しない)。
|
|
870
|
+
* ドラム(ch10 = channel 9)のノートはスキップする。
|
|
851
871
|
*/
|
|
852
872
|
declare const extractMidiPlacementsByTrack: (midi: unknown, selectedIndices: number[], trackIds: string[]) => MidiExtraction;
|
|
853
873
|
type ExportMidiOptions = {
|
|
@@ -1266,4 +1286,4 @@ declare const DAW_CSS = "\n@font-face {\n font-family: 'k8x12';\n src: url('ht
|
|
|
1266
1286
|
*/
|
|
1267
1287
|
declare const injectStyles: (doc?: Document) => void;
|
|
1268
1288
|
|
|
1269
|
-
export { type AddNoteOptions, type ApplyChordOptions, type ChordPatternType, type ChordPlacement, type ConsumedSyllable, type CoreEventHandlers, DAW_CSS, DEFAULT_BPM, DEFAULT_GATE, DEFAULT_PAN, DEFAULT_PLAYBACK_VELOCITY, DEFAULT_STEPS_PER_BAR, DEFAULT_VELOCITY, DEFAULT_VOCAL_VOLUME, DRUM_FONT, DRUM_KEYS, DRUM_PATTERNS, type DawInstance, type DawOptions, type DawViewState, type DrumPattern, type DtmStudio, type DtmStudioEngines, type DtmStudioOptions, type ExportMidiOptions, INSTRUMENT_PRESETS, type InstrumentPreset, KOE_BASE_URL, KOE_VOICEBANKS, KOE_VOICEBANK_LABELS, KOE_VOICEBANK_TERMS, type KoeVoiceOptions, LinkedList, type LyricSyllable, type LyricTrack, type LyricsConductor, MAX_VOCAL_VOLUME, MMLCore, type MMLDisplayToken, type MMLNotePlacement, MML_END_MARKER, type MidiExtraction, type MidiNotePlacement, type MidiTrackAnalysis, type MmlMeta, type MmlPlayerInstance, type MmlPlayerOptions, type MountEditorOptions, type MountPlayerOptions, type Note, PITCH_MAP, PREWARM_NOTES, type ParseMMLOptions, type ParseMidiFn, type ParsedMML, type PianoRollInstance, type PianoRollOptions, type PitchToken, type PlayDrumEvent, type PlayNoteEvent, type PlaybackState, type PreviewSoundCallback, type RenderConfig, type Sequencer, type SequencerOptions, type SequencerTrack, type SingingVoices, type SingingVoicesOptions, type StreamPlaybackOptions, type StreamVoiceNote, type StreamVoiceTrack, TRACKS_ADVANCED, TRACKS_SIMPLE, type ToolMode, type TrackConfig, VOICE_IMAGE_KEY, type VoiceModel, type VoiceRegistry, analyzeMidiTracks, applyHarmonicFilter, applyMonophonic, buildChordPlacements, buildNameToKeyMapping, collectPitchTokens, createAudioContext, createDtmStudio, createKlattVoice, createKoeVoice, createLyricsConductor, createPianoRoll, createSequencer, createSingingVoices, createVoiceRegistry, decomposeToMonophonic, drawGrid, drawHeader, drawKeyboard, drawNotes, drawSelectedNotes, drawSelectionRect, exportMIDI, extractMidiPlacements, extractMidiPlacementsByTrack, fetchSoundFontList, formatMmlMeta, generateRandomPattern, getDrawOffset, getGridCanvas, getGridContext, getGridPosition, getHeaderCanvas, getMidiBPM, getRenderConfig, getXY, icon, init, injectStyles, isChordHeavyTrack, koeUrl, mountDAW, mountMmlPlayer, normalizeLyrics, onClick, panToStereo, parseLyrics, parseMML, parseMmlMeta, setDrawOffset, setupRecorder, shiftNotes, stripLyrics, stripMmlMeta, vocalVolumeToGain };
|
|
1289
|
+
export { type AddNoteOptions, type ApplyChordOptions, type ChordPatternType, type ChordPlacement, type ConsumedSyllable, type CoreEventHandlers, DAW_CSS, DEFAULT_BPM, DEFAULT_GATE, DEFAULT_PAN, DEFAULT_PLAYBACK_VELOCITY, DEFAULT_STEPS_PER_BAR, DEFAULT_VELOCITY, DEFAULT_VOCAL_VOLUME, DRUM_FONT, DRUM_KEYS, DRUM_PATTERNS, type DawInstance, type DawMode, type DawOptions, type DawViewState, type DrumPattern, type DtmStudio, type DtmStudioEngines, type DtmStudioOptions, type ExportMidiOptions, INSTRUMENT_PRESETS, type InstrumentPreset, KOE_BASE_URL, KOE_VOICEBANKS, KOE_VOICEBANK_LABELS, KOE_VOICEBANK_TERMS, type KoeVoiceOptions, LinkedList, type LyricSyllable, type LyricTrack, type LyricsConductor, MAX_VOCAL_VOLUME, MMLCore, type MMLDisplayToken, type MMLNotePlacement, MML_END_MARKER, type MidiExtraction, type MidiNotePlacement, type MidiTrackAnalysis, type MmlMeta, type MmlPlayerInstance, type MmlPlayerOptions, type MountEditorOptions, type MountPlayerOptions, type Note, PITCH_MAP, PREWARM_NOTES, type ParseMMLOptions, type ParseMidiFn, type ParsedMML, type PianoRollInstance, type PianoRollOptions, type PitchToken, type PlayDrumEvent, type PlayNoteEvent, type PlaybackState, type PreviewSoundCallback, type RenderConfig, type Sequencer, type SequencerOptions, type SequencerTrack, type SingingVoices, type SingingVoicesOptions, type StreamPlaybackOptions, type StreamVoiceNote, type StreamVoiceTrack, TRACKS_ADVANCED, TRACKS_SIMPLE, type ToolMode, type TrackConfig, VOICE_IMAGE_KEY, type VoiceModel, type VoiceRegistry, analyzeMidiTracks, applyHarmonicFilter, applyMonophonic, buildChordPlacements, buildNameToKeyMapping, collectPitchTokens, createAudioContext, createDtmStudio, createKlattVoice, createKoeVoice, createLyricsConductor, createPianoRoll, createSequencer, createSingingVoices, createVoiceRegistry, decomposeToMonophonic, drawGrid, drawHeader, drawKeyboard, drawNotes, drawSelectedNotes, drawSelectionRect, exportMIDI, extractMidiPlacements, extractMidiPlacementsByTrack, fetchSoundFontList, formatMmlMeta, generateRandomPattern, getDrawOffset, getGridCanvas, getGridContext, getGridPosition, getHeaderCanvas, getMidiBPM, getRenderConfig, getXY, icon, init, injectStyles, isChordHeavyTrack, koeUrl, mountDAW, mountMmlPlayer, normalizeLyrics, onClick, panToStereo, parseLyrics, parseMML, parseMmlMeta, setDrawOffset, setupRecorder, shiftNotes, stripLyrics, stripMmlMeta, vocalVolumeToGain };
|
package/dist/index.js
CHANGED
|
@@ -1322,7 +1322,10 @@ var buildUI = (target, options) => {
|
|
|
1322
1322
|
<summary>MIDI / MML \u5165\u529B</summary>
|
|
1323
1323
|
<div class="dtm-panel-body">
|
|
1324
1324
|
<div class="dtm-row">
|
|
1325
|
-
<
|
|
1325
|
+
<div style="display: inline-flex; flex-direction: column; align-items: center; gap: 4px; justify-content: center; min-width: 48px;">
|
|
1326
|
+
<span class="dtm-label" style="line-height: 1;">MIDI</span>
|
|
1327
|
+
<button class="dtm-infobtn" data-dtm="midi-info" title="MIDI\u306E\u8AAD\u307F\u8FBC\u307F\u89E3\u8AAC">${icon("info", 12)}</button>
|
|
1328
|
+
</div>
|
|
1326
1329
|
<input type="file" class="dtm-input dtm-grow" accept=".mid,.midi" data-dtm="midi-input">
|
|
1327
1330
|
<button class="dtm-btn dtm-btn--success" data-dtm="midi-load">\u8AAD\u8FBC</button>
|
|
1328
1331
|
</div>
|
|
@@ -1455,6 +1458,7 @@ var buildUI = (target, options) => {
|
|
|
1455
1458
|
drumVolumeLabel: sel("drum-volume-label"),
|
|
1456
1459
|
midiInput: sel("midi-input"),
|
|
1457
1460
|
midiLoadBtn: sel("midi-load"),
|
|
1461
|
+
midiInfoBtn: sel("midi-info"),
|
|
1458
1462
|
midiTrackSelection: sel("midi-track-selection"),
|
|
1459
1463
|
midiPanel: sel("midi-panel"),
|
|
1460
1464
|
mmlInput: sel("mml-input"),
|
|
@@ -2888,7 +2892,7 @@ var analyzeMidiTracks = (midi) => {
|
|
|
2888
2892
|
currentTime += event.deltaTime;
|
|
2889
2893
|
const data = event.data;
|
|
2890
2894
|
if (event.type === 9 && data && data[1]) {
|
|
2891
|
-
notes.push({ pitch: data[0] });
|
|
2895
|
+
notes.push({ pitch: data[0], channel: event.channel ?? 0 });
|
|
2892
2896
|
} else if (event.type === 8) {
|
|
2893
2897
|
for (let k = notes.length - 1; k >= 0; k--) {
|
|
2894
2898
|
if (notes[k].pitch === data[0] && notes[k].end === void 0) {
|
|
@@ -2899,11 +2903,13 @@ var analyzeMidiTracks = (midi) => {
|
|
|
2899
2903
|
}
|
|
2900
2904
|
}
|
|
2901
2905
|
const validNotes = notes.filter((n) => n.end !== void 0);
|
|
2906
|
+
const editableNotes = validNotes.filter((n) => n.channel !== 9);
|
|
2907
|
+
if (validNotes.length > 0 && editableNotes.length === 0) continue;
|
|
2902
2908
|
result.push({
|
|
2903
2909
|
index: i,
|
|
2904
2910
|
name: `Ch${i + 1}`,
|
|
2905
|
-
noteCount:
|
|
2906
|
-
selected:
|
|
2911
|
+
noteCount: editableNotes.length,
|
|
2912
|
+
selected: editableNotes.length > 0
|
|
2907
2913
|
});
|
|
2908
2914
|
}
|
|
2909
2915
|
return result;
|
|
@@ -3071,13 +3077,11 @@ var extractMidiPlacementsByTrack = (midi, selectedIndices, trackIds) => {
|
|
|
3071
3077
|
const bpm = getMidiBPM(midi);
|
|
3072
3078
|
const ticksPerStep = ticksPerBeat / STEPS_PER_BEAT;
|
|
3073
3079
|
const placements = [];
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
if (!selectedSet.has(midiIdx)) continue;
|
|
3077
|
-
if (midiIdx >= trackIds.length) continue;
|
|
3078
|
-
const trackId = trackIds[midiIdx];
|
|
3080
|
+
selectedIndices.forEach((midiIdx, lane) => {
|
|
3081
|
+
if (lane >= trackIds.length) return;
|
|
3079
3082
|
const trackData = track[midiIdx];
|
|
3080
|
-
if (!trackData)
|
|
3083
|
+
if (!trackData) return;
|
|
3084
|
+
const trackId = trackIds[lane];
|
|
3081
3085
|
const active = [];
|
|
3082
3086
|
let currentTime = 0;
|
|
3083
3087
|
for (const event of trackData.event) {
|
|
@@ -3112,7 +3116,7 @@ var extractMidiPlacementsByTrack = (midi, selectedIndices, trackIds) => {
|
|
|
3112
3116
|
velocity: note.velocity
|
|
3113
3117
|
});
|
|
3114
3118
|
}
|
|
3115
|
-
}
|
|
3119
|
+
});
|
|
3116
3120
|
return { placements, bpm };
|
|
3117
3121
|
};
|
|
3118
3122
|
var to2byte = (n) => [(n & 65280) >> 8, n & 255];
|
|
@@ -3153,6 +3157,7 @@ var exportMIDI = (options) => {
|
|
|
3153
3157
|
const midiTracks = [];
|
|
3154
3158
|
tracks.forEach((track, ch) => {
|
|
3155
3159
|
if (track.notes.length === 0) return;
|
|
3160
|
+
const channel = ch < 9 ? ch : ch + 1 & 15;
|
|
3156
3161
|
const events = [];
|
|
3157
3162
|
for (const n of track.notes) {
|
|
3158
3163
|
const startTick = Math.round(n.startStep * tickPerStep);
|
|
@@ -3162,8 +3167,8 @@ var exportMIDI = (options) => {
|
|
|
3162
3167
|
const vel = Math.round(
|
|
3163
3168
|
(n.velocity ?? DEFAULT_VELOCITY) * (track.volume ?? 100) / 100
|
|
3164
3169
|
);
|
|
3165
|
-
events.push({ t: startTick, m: [144 |
|
|
3166
|
-
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] });
|
|
3167
3172
|
}
|
|
3168
3173
|
events.sort((a, b) => a.t - b.t);
|
|
3169
3174
|
midiTracks.push(events);
|
|
@@ -5280,6 +5285,7 @@ var CHORD_INFO_HTML = `
|
|
|
5280
5285
|
<h4>1. \u57FA\u672C\u306E\u66F8\u304D\u65B9</h4>
|
|
5281
5286
|
<p>\u30B3\u30FC\u30C9\u540D\uFF08\u548C\u97F3\u8A18\u53F7\uFF09\u3092\u7E26\u7DDA <code>|</code>\u3001\u30B9\u30DA\u30FC\u30B9\u3001\u307E\u305F\u306F\u30AB\u30F3\u30DE\u3067\u533A\u5207\u3063\u3066\u5165\u529B\u3057\u307E\u3059\u3002\u7E26\u7DDA\u3067\u533A\u5207\u308B\u30681\u5C0F\u7BC0\u3054\u3068\u306E\u914D\u7F6E\u306B\u306A\u308A\u307E\u3059\u3002</p>
|
|
5282
5287
|
<pre>\u4F8B: C | G | Am | F</pre>
|
|
5288
|
+
<p style="margin-top:4px;"><small>\u30B3\u30FC\u30C9\u9032\u884C\u3092\u81EA\u5206\u3067\u8003\u3048\u308B\u306E\u304C\u96E3\u3057\u3044\u3068\u304D\u306F\u3001\u30B3\u30FC\u30C9\u9032\u884C\u306E\u5171\u6709\u30B5\u30A4\u30C8\uFF08\u4F8B: <a href="https://rechord.cc/scores" target="_blank" rel="noopener">rechord.cc</a>\uFF09\u304B\u3089\u597D\u304D\u306A\u9032\u884C\u3092\u63A2\u3057\u3066\u30B3\u30D4\u30DA\u3059\u308B\u306E\u3082\u624B\u3067\u3059\u3002\u533A\u5207\u308A\u6587\u5B57\uFF08<code>|</code> / \u30B9\u30DA\u30FC\u30B9 / \u30AB\u30F3\u30DE\uFF09\u3060\u3051\u4E0A\u306E\u5F62\u5F0F\u306B\u5408\u308F\u305B\u308C\u3070\u3001\u305D\u306E\u307E\u307E\u4F7F\u3048\u307E\u3059\u3002</small></p>
|
|
5283
5289
|
|
|
5284
5290
|
<h4>2. 1\u5C0F\u7BC0\u306B\u8907\u6570\u30B3\u30FC\u30C9\u3092\u5165\u308C\u308B</h4>
|
|
5285
5291
|
<p>\u5C0F\u7BC0\u306E\u533A\u5207\u308A\uFF08\u7E26\u7DDA <code>|</code>\uFF09\u306E\u4E2D\u306B\u3001\u30B9\u30DA\u30FC\u30B9\u533A\u5207\u308A\u3067\u30B3\u30FC\u30C9\u3092\u4E26\u3079\u307E\u3059\u3002\u7B49\u9593\u9694\u306B\u914D\u7F6E\u3055\u308C\u307E\u3059\u3002</p>
|
|
@@ -5354,6 +5360,38 @@ var MML_INFO_HTML = `
|
|
|
5354
5360
|
<p style="margin-top:4px;"><small>\uFF08\u97F3\u6E90\u540D\u306F <code>klatt</code> \u3084 <code>roze</code>, <code>teto</code> \u306A\u3069\u306E\u97F3\u58F0\u30E2\u30C7\u30EB\u3092\u6307\u5B9A\u3067\u304D\u307E\u3059\uFF09</small></p>
|
|
5355
5361
|
</div>
|
|
5356
5362
|
`;
|
|
5363
|
+
var MIDI_INFO_HTML = `
|
|
5364
|
+
<div class="dtm-modal-body-content">
|
|
5365
|
+
<h4>1. MIDI\u30D5\u30A1\u30A4\u30EB\u3068\u306F</h4>
|
|
5366
|
+
<p>\u300C\u3069\u306E\u97F3\u3092\u30FB\u3044\u3064\u30FB\u3069\u306E\u304F\u3089\u3044\u306E\u9577\u3055\u3067\u9CF4\u3089\u3059\u304B\u300D\u3092\u8A18\u9332\u3057\u305F\u3001\u6F14\u594F\u30C7\u30FC\u30BF\u306E\u30D5\u30A1\u30A4\u30EB\uFF08\u62E1\u5F35\u5B50 <code>.mid</code> / <code>.midi</code>\uFF09\u3067\u3059\u3002\u97F3\u305D\u306E\u3082\u306E\u3067\u306F\u306A\u304F\u697D\u8B5C\u306B\u8FD1\u3044\u30C7\u30FC\u30BF\u306A\u306E\u3067\u3001\u8AAD\u307F\u8FBC\u3093\u3067\u305D\u306E\u307E\u307E\u7DE8\u96C6\u3067\u304D\u307E\u3059\u3002</p>
|
|
5367
|
+
|
|
5368
|
+
<h4>2. \u8AAD\u307F\u8FBC\u307F\u306E\u3057\u304B\u305F</h4>
|
|
5369
|
+
<ul>
|
|
5370
|
+
<li>\u300C\u30D5\u30A1\u30A4\u30EB\u3092\u9078\u629E\u300D\u304B\u3089 <code>.mid</code> \u30D5\u30A1\u30A4\u30EB\u3092\u9078\u3073\u307E\u3059\u3002</li>
|
|
5371
|
+
<li>\u30D5\u30A1\u30A4\u30EB\u5185\u306E\u30C8\u30E9\u30C3\u30AF\u4E00\u89A7\u304C\u51FA\u308B\u306E\u3067\u3001\u53D6\u308A\u8FBC\u307F\u305F\u3044\u30C8\u30E9\u30C3\u30AF\u3092\u9078\u3073\u307E\u3059\u3002</li>
|
|
5372
|
+
<li>\u300C\u8AAD\u8FBC\u300D\u3092\u62BC\u3059\u3068\u53CD\u6620\u3055\u308C\u307E\u3059\u3002</li>
|
|
5373
|
+
</ul>
|
|
5374
|
+
|
|
5375
|
+
<h4>3. \u30E2\u30FC\u30C9\u306B\u3088\u308B\u53D6\u308A\u8FBC\u307F\u65B9\u306E\u9055\u3044</h4>
|
|
5376
|
+
<ul>
|
|
5377
|
+
<li><strong>SIMPLE</strong>: \u5404\u30C8\u30E9\u30C3\u30AF\u306E\u7279\u5FB4\u304B\u3089\u3001\u30E1\u30ED\u30C7\u30A3\u30FC\u30FB\u30B5\u30D6\u30E1\u30ED\u30FB\u30D9\u30FC\u30B9\u30FB\u4F34\u594F\u306E4\u3064\u306E\u5F79\u5272\u306B\u81EA\u52D5\u3067\u632F\u308A\u5206\u3051\u3089\u308C\u307E\u3059\u3002</li>
|
|
5378
|
+
<li><strong>ADVANCED</strong>: MIDI\u306E\u30C8\u30E9\u30C3\u30AF\u69CB\u6210\u304C\u305D\u306E\u307E\u307E\u53CD\u6620\u3055\u308C\u307E\u3059\uFF081\u5BFE1\uFF09\u3002</li>
|
|
5379
|
+
</ul>
|
|
5380
|
+
|
|
5381
|
+
<h4>4. MIDI\u30D5\u30A1\u30A4\u30EB\u3092\u624B\u306B\u5165\u308C\u308B</h4>
|
|
5382
|
+
<p>\u624B\u5143\u306BMIDI\u304C\u7121\u3044\u3068\u304D\u306F\u3001\u300C<code>\u66F2\u540D midi</code>\u300D\u306A\u3069\u3067\u691C\u7D22\u3059\u308C\u3070\u3001\u7121\u6599\u3067\u914D\u5E03\u3057\u3066\u3044\u308B\u30B5\u30A4\u30C8\u304C\u898B\u3064\u304B\u308A\u307E\u3059\u3002</p>
|
|
5383
|
+
<p style="margin-top:4px;"><small>\u307F\u3093\u306A\u304CMIDI\u3092\u6295\u7A3F\u3067\u304D\u308B\u6295\u7A3F\u578B\u30D7\u30E9\u30C3\u30C8\u30D5\u30A9\u30FC\u30E0: <a href="http://picotune.me/" target="_blank" rel="noopener">picotune.me</a>\uFF08\u3044\u308D\u3093\u306A\u30B8\u30E3\u30F3\u30EB\u306EMIDI\u3092\u7121\u6599\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9\u3067\u304D\u307E\u3059\u3002\u30B5\u30A4\u30C8\u4E0A\u3067\u306F\u30C1\u30C3\u30D7\u30C1\u30E5\u30FC\u30F3\u98A8\u306B\u518D\u751F\u3055\u308C\u307E\u3059\uFF09</small></p>
|
|
5384
|
+
<p style="margin-top:4px;"><small>\u203B\u691C\u7D22\u3067\u898B\u3064\u304B\u308B\u914D\u5E03\u30B5\u30A4\u30C8\u306F\u3001\u500B\u4EBA\u904B\u55B6\u306E\u3082\u306E\u304B\u3089\u6A29\u5229\u7684\u306B\u30B0\u30EC\u30FC\u306A\u3082\u306E\u307E\u3067\u69D8\u3005\u3067\u3059\u3002\u305D\u306E\u305F\u3081\u3001\u305D\u308C\u3089\u3078\u306E\u76F4\u63A5\u30EA\u30F3\u30AF\u306F\u8F09\u305B\u3066\u3044\u307E\u305B\u3093\u3002\u5229\u7528\u306E\u969B\u306F\u914D\u5E03\u5143\u3084\u6A29\u5229\u95A2\u4FC2\u3092\u3054\u81EA\u8EAB\u3067\u3054\u78BA\u8A8D\u304F\u3060\u3055\u3044\u3002</small></p>
|
|
5385
|
+
|
|
5386
|
+
<h4>5. UST\uFF08UTAU\uFF09\u306E\u6B4C\u8A5E\u3092\u4F7F\u3046</h4>
|
|
5387
|
+
<p>UTAU\u306EUST\u30D5\u30A1\u30A4\u30EB\u304B\u3089\u6B4C\u8A5E\u3060\u3051\u3092\u53D6\u308A\u51FA\u3057\u3066\u3001\u6B4C\u308F\u305B\u308B\u3053\u3068\u3082\u3067\u304D\u307E\u3059\u3002</p>
|
|
5388
|
+
<ul>
|
|
5389
|
+
<li>\u97F3\u7B26: UTAU\u306A\u3069\u3067UST\u3092MIDI\u306B\u66F8\u304D\u51FA\u3057\u3001\u4E0A\u306E\u624B\u9806\u3067\u8AAD\u307F\u8FBC\u307F\u307E\u3059\u3002</li>
|
|
5390
|
+
<li>\u6B4C\u8A5E: \u4E0B\u8A18\u30B5\u30A4\u30C8\u3067UST\u304B\u3089\u6B4C\u8A5E\u30C6\u30AD\u30B9\u30C8\u3092\u629C\u304D\u51FA\u3057\u3001MML/\u6B4C\u8A5E\u5165\u529B\u6B04\u306E <code>@@</code> \u69CB\u6587\u306B\u8CBC\u308A\u4ED8\u3051\u307E\u3059\u3002</li>
|
|
5391
|
+
</ul>
|
|
5392
|
+
<p style="margin-top:4px;"><small>\u6B4C\u8A5E\u306E\u62BD\u51FA: <a href="https://rpgen3.github.io/ust2txt/" target="_blank" rel="noopener">ust2txt</a></small></p>
|
|
5393
|
+
</div>
|
|
5394
|
+
`;
|
|
5357
5395
|
var BASE_STEP_WIDTH = 0.5;
|
|
5358
5396
|
var BASE_KEY_HEIGHT = 15;
|
|
5359
5397
|
var TRACKS_SIMPLE = [
|
|
@@ -5512,9 +5550,11 @@ var mountDAW = (target, options = {}) => {
|
|
|
5512
5550
|
injectStyles();
|
|
5513
5551
|
const getAudioTime = options.getAudioTime ?? (() => performance.now() / 1e3);
|
|
5514
5552
|
const trackConfigs = options.tracks ?? DEFAULT_TRACKS;
|
|
5553
|
+
const mode = options.mode ?? (trackConfigs.length > TRACKS_SIMPLE.length ? "advanced" : "simple");
|
|
5554
|
+
const isAdvanced = mode === "advanced";
|
|
5515
5555
|
const drumPatterns = options.drumPatterns ?? DRUM_PATTERNS;
|
|
5516
5556
|
const showMidi = !!options.parseMidi;
|
|
5517
|
-
const showChord =
|
|
5557
|
+
const showChord = !isAdvanced;
|
|
5518
5558
|
const refs = buildUI(target, {
|
|
5519
5559
|
tracks: trackConfigs,
|
|
5520
5560
|
drumPatternNames: Object.keys(drumPatterns),
|
|
@@ -6299,7 +6339,6 @@ var mountDAW = (target, options = {}) => {
|
|
|
6299
6339
|
active.core.setVolume(active.volume);
|
|
6300
6340
|
volLabel.textContent = String(active.volume);
|
|
6301
6341
|
});
|
|
6302
|
-
const isAdvanced = trackStates.length > TRACKS_SIMPLE.length;
|
|
6303
6342
|
if (isAdvanced || active.config.id !== "chord") {
|
|
6304
6343
|
const lyricDiv = document.createElement("div");
|
|
6305
6344
|
lyricDiv.className = "dtm-row";
|
|
@@ -6507,16 +6546,16 @@ var mountDAW = (target, options = {}) => {
|
|
|
6507
6546
|
updateUndoRedo();
|
|
6508
6547
|
redrawAll();
|
|
6509
6548
|
};
|
|
6510
|
-
const setToolMode = (
|
|
6511
|
-
activeToolMode =
|
|
6549
|
+
const setToolMode = (mode2) => {
|
|
6550
|
+
activeToolMode = mode2;
|
|
6512
6551
|
for (const [btn, m] of [
|
|
6513
6552
|
[refs.toolPen, "pen"],
|
|
6514
6553
|
[refs.toolSelect, "select"],
|
|
6515
6554
|
[refs.toolEraser, "eraser"]
|
|
6516
6555
|
]) {
|
|
6517
|
-
btn.classList.toggle("dtm-segbtn--active", m ===
|
|
6556
|
+
btn.classList.toggle("dtm-segbtn--active", m === mode2);
|
|
6518
6557
|
}
|
|
6519
|
-
if (
|
|
6558
|
+
if (mode2 !== "select") {
|
|
6520
6559
|
selectionRect = null;
|
|
6521
6560
|
selectedNotes = [];
|
|
6522
6561
|
}
|
|
@@ -6750,7 +6789,6 @@ var mountDAW = (target, options = {}) => {
|
|
|
6750
6789
|
const applyMidiSelection = (midi, selectedIndices) => {
|
|
6751
6790
|
clearAll();
|
|
6752
6791
|
for (const t of trackStates) t.core.setLoadMode(true);
|
|
6753
|
-
const isAdvanced = trackStates.length > TRACKS_SIMPLE.length;
|
|
6754
6792
|
const { placements, bpm: parsedBpm } = isAdvanced ? extractMidiPlacementsByTrack(
|
|
6755
6793
|
midi,
|
|
6756
6794
|
selectedIndices,
|
|
@@ -6948,6 +6986,9 @@ var mountDAW = (target, options = {}) => {
|
|
|
6948
6986
|
refs.mmlInfoBtn.addEventListener("click", () => {
|
|
6949
6987
|
showModal("MML\u306E\u66F8\u304D\u65B9\u89E3\u8AAC", MML_INFO_HTML);
|
|
6950
6988
|
});
|
|
6989
|
+
refs.midiInfoBtn.addEventListener("click", () => {
|
|
6990
|
+
showModal("MIDI\u306E\u8AAD\u307F\u8FBC\u307F\u89E3\u8AAC", MIDI_INFO_HTML);
|
|
6991
|
+
});
|
|
6951
6992
|
refs.shiftApplyBtn.addEventListener(
|
|
6952
6993
|
"click",
|
|
6953
6994
|
() => overlayDuring(() => {
|
package/dist/index.mjs
CHANGED
|
@@ -1217,7 +1217,10 @@ var buildUI = (target, options) => {
|
|
|
1217
1217
|
<summary>MIDI / MML \u5165\u529B</summary>
|
|
1218
1218
|
<div class="dtm-panel-body">
|
|
1219
1219
|
<div class="dtm-row">
|
|
1220
|
-
<
|
|
1220
|
+
<div style="display: inline-flex; flex-direction: column; align-items: center; gap: 4px; justify-content: center; min-width: 48px;">
|
|
1221
|
+
<span class="dtm-label" style="line-height: 1;">MIDI</span>
|
|
1222
|
+
<button class="dtm-infobtn" data-dtm="midi-info" title="MIDI\u306E\u8AAD\u307F\u8FBC\u307F\u89E3\u8AAC">${icon("info", 12)}</button>
|
|
1223
|
+
</div>
|
|
1221
1224
|
<input type="file" class="dtm-input dtm-grow" accept=".mid,.midi" data-dtm="midi-input">
|
|
1222
1225
|
<button class="dtm-btn dtm-btn--success" data-dtm="midi-load">\u8AAD\u8FBC</button>
|
|
1223
1226
|
</div>
|
|
@@ -1350,6 +1353,7 @@ var buildUI = (target, options) => {
|
|
|
1350
1353
|
drumVolumeLabel: sel("drum-volume-label"),
|
|
1351
1354
|
midiInput: sel("midi-input"),
|
|
1352
1355
|
midiLoadBtn: sel("midi-load"),
|
|
1356
|
+
midiInfoBtn: sel("midi-info"),
|
|
1353
1357
|
midiTrackSelection: sel("midi-track-selection"),
|
|
1354
1358
|
midiPanel: sel("midi-panel"),
|
|
1355
1359
|
mmlInput: sel("mml-input"),
|
|
@@ -2783,7 +2787,7 @@ var analyzeMidiTracks = (midi) => {
|
|
|
2783
2787
|
currentTime += event.deltaTime;
|
|
2784
2788
|
const data = event.data;
|
|
2785
2789
|
if (event.type === 9 && data && data[1]) {
|
|
2786
|
-
notes.push({ pitch: data[0] });
|
|
2790
|
+
notes.push({ pitch: data[0], channel: event.channel ?? 0 });
|
|
2787
2791
|
} else if (event.type === 8) {
|
|
2788
2792
|
for (let k = notes.length - 1; k >= 0; k--) {
|
|
2789
2793
|
if (notes[k].pitch === data[0] && notes[k].end === void 0) {
|
|
@@ -2794,11 +2798,13 @@ var analyzeMidiTracks = (midi) => {
|
|
|
2794
2798
|
}
|
|
2795
2799
|
}
|
|
2796
2800
|
const validNotes = notes.filter((n) => n.end !== void 0);
|
|
2801
|
+
const editableNotes = validNotes.filter((n) => n.channel !== 9);
|
|
2802
|
+
if (validNotes.length > 0 && editableNotes.length === 0) continue;
|
|
2797
2803
|
result.push({
|
|
2798
2804
|
index: i,
|
|
2799
2805
|
name: `Ch${i + 1}`,
|
|
2800
|
-
noteCount:
|
|
2801
|
-
selected:
|
|
2806
|
+
noteCount: editableNotes.length,
|
|
2807
|
+
selected: editableNotes.length > 0
|
|
2802
2808
|
});
|
|
2803
2809
|
}
|
|
2804
2810
|
return result;
|
|
@@ -2966,13 +2972,11 @@ var extractMidiPlacementsByTrack = (midi, selectedIndices, trackIds) => {
|
|
|
2966
2972
|
const bpm = getMidiBPM(midi);
|
|
2967
2973
|
const ticksPerStep = ticksPerBeat / STEPS_PER_BEAT;
|
|
2968
2974
|
const placements = [];
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
if (!selectedSet.has(midiIdx)) continue;
|
|
2972
|
-
if (midiIdx >= trackIds.length) continue;
|
|
2973
|
-
const trackId = trackIds[midiIdx];
|
|
2975
|
+
selectedIndices.forEach((midiIdx, lane) => {
|
|
2976
|
+
if (lane >= trackIds.length) return;
|
|
2974
2977
|
const trackData = track[midiIdx];
|
|
2975
|
-
if (!trackData)
|
|
2978
|
+
if (!trackData) return;
|
|
2979
|
+
const trackId = trackIds[lane];
|
|
2976
2980
|
const active = [];
|
|
2977
2981
|
let currentTime = 0;
|
|
2978
2982
|
for (const event of trackData.event) {
|
|
@@ -3007,7 +3011,7 @@ var extractMidiPlacementsByTrack = (midi, selectedIndices, trackIds) => {
|
|
|
3007
3011
|
velocity: note.velocity
|
|
3008
3012
|
});
|
|
3009
3013
|
}
|
|
3010
|
-
}
|
|
3014
|
+
});
|
|
3011
3015
|
return { placements, bpm };
|
|
3012
3016
|
};
|
|
3013
3017
|
var to2byte = (n) => [(n & 65280) >> 8, n & 255];
|
|
@@ -3048,6 +3052,7 @@ var exportMIDI = (options) => {
|
|
|
3048
3052
|
const midiTracks = [];
|
|
3049
3053
|
tracks.forEach((track, ch) => {
|
|
3050
3054
|
if (track.notes.length === 0) return;
|
|
3055
|
+
const channel = ch < 9 ? ch : ch + 1 & 15;
|
|
3051
3056
|
const events = [];
|
|
3052
3057
|
for (const n of track.notes) {
|
|
3053
3058
|
const startTick = Math.round(n.startStep * tickPerStep);
|
|
@@ -3057,8 +3062,8 @@ var exportMIDI = (options) => {
|
|
|
3057
3062
|
const vel = Math.round(
|
|
3058
3063
|
(n.velocity ?? DEFAULT_VELOCITY) * (track.volume ?? 100) / 100
|
|
3059
3064
|
);
|
|
3060
|
-
events.push({ t: startTick, m: [144 |
|
|
3061
|
-
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] });
|
|
3062
3067
|
}
|
|
3063
3068
|
events.sort((a, b) => a.t - b.t);
|
|
3064
3069
|
midiTracks.push(events);
|
|
@@ -5175,6 +5180,7 @@ var CHORD_INFO_HTML = `
|
|
|
5175
5180
|
<h4>1. \u57FA\u672C\u306E\u66F8\u304D\u65B9</h4>
|
|
5176
5181
|
<p>\u30B3\u30FC\u30C9\u540D\uFF08\u548C\u97F3\u8A18\u53F7\uFF09\u3092\u7E26\u7DDA <code>|</code>\u3001\u30B9\u30DA\u30FC\u30B9\u3001\u307E\u305F\u306F\u30AB\u30F3\u30DE\u3067\u533A\u5207\u3063\u3066\u5165\u529B\u3057\u307E\u3059\u3002\u7E26\u7DDA\u3067\u533A\u5207\u308B\u30681\u5C0F\u7BC0\u3054\u3068\u306E\u914D\u7F6E\u306B\u306A\u308A\u307E\u3059\u3002</p>
|
|
5177
5182
|
<pre>\u4F8B: C | G | Am | F</pre>
|
|
5183
|
+
<p style="margin-top:4px;"><small>\u30B3\u30FC\u30C9\u9032\u884C\u3092\u81EA\u5206\u3067\u8003\u3048\u308B\u306E\u304C\u96E3\u3057\u3044\u3068\u304D\u306F\u3001\u30B3\u30FC\u30C9\u9032\u884C\u306E\u5171\u6709\u30B5\u30A4\u30C8\uFF08\u4F8B: <a href="https://rechord.cc/scores" target="_blank" rel="noopener">rechord.cc</a>\uFF09\u304B\u3089\u597D\u304D\u306A\u9032\u884C\u3092\u63A2\u3057\u3066\u30B3\u30D4\u30DA\u3059\u308B\u306E\u3082\u624B\u3067\u3059\u3002\u533A\u5207\u308A\u6587\u5B57\uFF08<code>|</code> / \u30B9\u30DA\u30FC\u30B9 / \u30AB\u30F3\u30DE\uFF09\u3060\u3051\u4E0A\u306E\u5F62\u5F0F\u306B\u5408\u308F\u305B\u308C\u3070\u3001\u305D\u306E\u307E\u307E\u4F7F\u3048\u307E\u3059\u3002</small></p>
|
|
5178
5184
|
|
|
5179
5185
|
<h4>2. 1\u5C0F\u7BC0\u306B\u8907\u6570\u30B3\u30FC\u30C9\u3092\u5165\u308C\u308B</h4>
|
|
5180
5186
|
<p>\u5C0F\u7BC0\u306E\u533A\u5207\u308A\uFF08\u7E26\u7DDA <code>|</code>\uFF09\u306E\u4E2D\u306B\u3001\u30B9\u30DA\u30FC\u30B9\u533A\u5207\u308A\u3067\u30B3\u30FC\u30C9\u3092\u4E26\u3079\u307E\u3059\u3002\u7B49\u9593\u9694\u306B\u914D\u7F6E\u3055\u308C\u307E\u3059\u3002</p>
|
|
@@ -5249,6 +5255,38 @@ var MML_INFO_HTML = `
|
|
|
5249
5255
|
<p style="margin-top:4px;"><small>\uFF08\u97F3\u6E90\u540D\u306F <code>klatt</code> \u3084 <code>roze</code>, <code>teto</code> \u306A\u3069\u306E\u97F3\u58F0\u30E2\u30C7\u30EB\u3092\u6307\u5B9A\u3067\u304D\u307E\u3059\uFF09</small></p>
|
|
5250
5256
|
</div>
|
|
5251
5257
|
`;
|
|
5258
|
+
var MIDI_INFO_HTML = `
|
|
5259
|
+
<div class="dtm-modal-body-content">
|
|
5260
|
+
<h4>1. MIDI\u30D5\u30A1\u30A4\u30EB\u3068\u306F</h4>
|
|
5261
|
+
<p>\u300C\u3069\u306E\u97F3\u3092\u30FB\u3044\u3064\u30FB\u3069\u306E\u304F\u3089\u3044\u306E\u9577\u3055\u3067\u9CF4\u3089\u3059\u304B\u300D\u3092\u8A18\u9332\u3057\u305F\u3001\u6F14\u594F\u30C7\u30FC\u30BF\u306E\u30D5\u30A1\u30A4\u30EB\uFF08\u62E1\u5F35\u5B50 <code>.mid</code> / <code>.midi</code>\uFF09\u3067\u3059\u3002\u97F3\u305D\u306E\u3082\u306E\u3067\u306F\u306A\u304F\u697D\u8B5C\u306B\u8FD1\u3044\u30C7\u30FC\u30BF\u306A\u306E\u3067\u3001\u8AAD\u307F\u8FBC\u3093\u3067\u305D\u306E\u307E\u307E\u7DE8\u96C6\u3067\u304D\u307E\u3059\u3002</p>
|
|
5262
|
+
|
|
5263
|
+
<h4>2. \u8AAD\u307F\u8FBC\u307F\u306E\u3057\u304B\u305F</h4>
|
|
5264
|
+
<ul>
|
|
5265
|
+
<li>\u300C\u30D5\u30A1\u30A4\u30EB\u3092\u9078\u629E\u300D\u304B\u3089 <code>.mid</code> \u30D5\u30A1\u30A4\u30EB\u3092\u9078\u3073\u307E\u3059\u3002</li>
|
|
5266
|
+
<li>\u30D5\u30A1\u30A4\u30EB\u5185\u306E\u30C8\u30E9\u30C3\u30AF\u4E00\u89A7\u304C\u51FA\u308B\u306E\u3067\u3001\u53D6\u308A\u8FBC\u307F\u305F\u3044\u30C8\u30E9\u30C3\u30AF\u3092\u9078\u3073\u307E\u3059\u3002</li>
|
|
5267
|
+
<li>\u300C\u8AAD\u8FBC\u300D\u3092\u62BC\u3059\u3068\u53CD\u6620\u3055\u308C\u307E\u3059\u3002</li>
|
|
5268
|
+
</ul>
|
|
5269
|
+
|
|
5270
|
+
<h4>3. \u30E2\u30FC\u30C9\u306B\u3088\u308B\u53D6\u308A\u8FBC\u307F\u65B9\u306E\u9055\u3044</h4>
|
|
5271
|
+
<ul>
|
|
5272
|
+
<li><strong>SIMPLE</strong>: \u5404\u30C8\u30E9\u30C3\u30AF\u306E\u7279\u5FB4\u304B\u3089\u3001\u30E1\u30ED\u30C7\u30A3\u30FC\u30FB\u30B5\u30D6\u30E1\u30ED\u30FB\u30D9\u30FC\u30B9\u30FB\u4F34\u594F\u306E4\u3064\u306E\u5F79\u5272\u306B\u81EA\u52D5\u3067\u632F\u308A\u5206\u3051\u3089\u308C\u307E\u3059\u3002</li>
|
|
5273
|
+
<li><strong>ADVANCED</strong>: MIDI\u306E\u30C8\u30E9\u30C3\u30AF\u69CB\u6210\u304C\u305D\u306E\u307E\u307E\u53CD\u6620\u3055\u308C\u307E\u3059\uFF081\u5BFE1\uFF09\u3002</li>
|
|
5274
|
+
</ul>
|
|
5275
|
+
|
|
5276
|
+
<h4>4. MIDI\u30D5\u30A1\u30A4\u30EB\u3092\u624B\u306B\u5165\u308C\u308B</h4>
|
|
5277
|
+
<p>\u624B\u5143\u306BMIDI\u304C\u7121\u3044\u3068\u304D\u306F\u3001\u300C<code>\u66F2\u540D midi</code>\u300D\u306A\u3069\u3067\u691C\u7D22\u3059\u308C\u3070\u3001\u7121\u6599\u3067\u914D\u5E03\u3057\u3066\u3044\u308B\u30B5\u30A4\u30C8\u304C\u898B\u3064\u304B\u308A\u307E\u3059\u3002</p>
|
|
5278
|
+
<p style="margin-top:4px;"><small>\u307F\u3093\u306A\u304CMIDI\u3092\u6295\u7A3F\u3067\u304D\u308B\u6295\u7A3F\u578B\u30D7\u30E9\u30C3\u30C8\u30D5\u30A9\u30FC\u30E0: <a href="http://picotune.me/" target="_blank" rel="noopener">picotune.me</a>\uFF08\u3044\u308D\u3093\u306A\u30B8\u30E3\u30F3\u30EB\u306EMIDI\u3092\u7121\u6599\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9\u3067\u304D\u307E\u3059\u3002\u30B5\u30A4\u30C8\u4E0A\u3067\u306F\u30C1\u30C3\u30D7\u30C1\u30E5\u30FC\u30F3\u98A8\u306B\u518D\u751F\u3055\u308C\u307E\u3059\uFF09</small></p>
|
|
5279
|
+
<p style="margin-top:4px;"><small>\u203B\u691C\u7D22\u3067\u898B\u3064\u304B\u308B\u914D\u5E03\u30B5\u30A4\u30C8\u306F\u3001\u500B\u4EBA\u904B\u55B6\u306E\u3082\u306E\u304B\u3089\u6A29\u5229\u7684\u306B\u30B0\u30EC\u30FC\u306A\u3082\u306E\u307E\u3067\u69D8\u3005\u3067\u3059\u3002\u305D\u306E\u305F\u3081\u3001\u305D\u308C\u3089\u3078\u306E\u76F4\u63A5\u30EA\u30F3\u30AF\u306F\u8F09\u305B\u3066\u3044\u307E\u305B\u3093\u3002\u5229\u7528\u306E\u969B\u306F\u914D\u5E03\u5143\u3084\u6A29\u5229\u95A2\u4FC2\u3092\u3054\u81EA\u8EAB\u3067\u3054\u78BA\u8A8D\u304F\u3060\u3055\u3044\u3002</small></p>
|
|
5280
|
+
|
|
5281
|
+
<h4>5. UST\uFF08UTAU\uFF09\u306E\u6B4C\u8A5E\u3092\u4F7F\u3046</h4>
|
|
5282
|
+
<p>UTAU\u306EUST\u30D5\u30A1\u30A4\u30EB\u304B\u3089\u6B4C\u8A5E\u3060\u3051\u3092\u53D6\u308A\u51FA\u3057\u3066\u3001\u6B4C\u308F\u305B\u308B\u3053\u3068\u3082\u3067\u304D\u307E\u3059\u3002</p>
|
|
5283
|
+
<ul>
|
|
5284
|
+
<li>\u97F3\u7B26: UTAU\u306A\u3069\u3067UST\u3092MIDI\u306B\u66F8\u304D\u51FA\u3057\u3001\u4E0A\u306E\u624B\u9806\u3067\u8AAD\u307F\u8FBC\u307F\u307E\u3059\u3002</li>
|
|
5285
|
+
<li>\u6B4C\u8A5E: \u4E0B\u8A18\u30B5\u30A4\u30C8\u3067UST\u304B\u3089\u6B4C\u8A5E\u30C6\u30AD\u30B9\u30C8\u3092\u629C\u304D\u51FA\u3057\u3001MML/\u6B4C\u8A5E\u5165\u529B\u6B04\u306E <code>@@</code> \u69CB\u6587\u306B\u8CBC\u308A\u4ED8\u3051\u307E\u3059\u3002</li>
|
|
5286
|
+
</ul>
|
|
5287
|
+
<p style="margin-top:4px;"><small>\u6B4C\u8A5E\u306E\u62BD\u51FA: <a href="https://rpgen3.github.io/ust2txt/" target="_blank" rel="noopener">ust2txt</a></small></p>
|
|
5288
|
+
</div>
|
|
5289
|
+
`;
|
|
5252
5290
|
var BASE_STEP_WIDTH = 0.5;
|
|
5253
5291
|
var BASE_KEY_HEIGHT = 15;
|
|
5254
5292
|
var TRACKS_SIMPLE = [
|
|
@@ -5407,9 +5445,11 @@ var mountDAW = (target, options = {}) => {
|
|
|
5407
5445
|
injectStyles();
|
|
5408
5446
|
const getAudioTime = options.getAudioTime ?? (() => performance.now() / 1e3);
|
|
5409
5447
|
const trackConfigs = options.tracks ?? DEFAULT_TRACKS;
|
|
5448
|
+
const mode = options.mode ?? (trackConfigs.length > TRACKS_SIMPLE.length ? "advanced" : "simple");
|
|
5449
|
+
const isAdvanced = mode === "advanced";
|
|
5410
5450
|
const drumPatterns = options.drumPatterns ?? DRUM_PATTERNS;
|
|
5411
5451
|
const showMidi = !!options.parseMidi;
|
|
5412
|
-
const showChord =
|
|
5452
|
+
const showChord = !isAdvanced;
|
|
5413
5453
|
const refs = buildUI(target, {
|
|
5414
5454
|
tracks: trackConfigs,
|
|
5415
5455
|
drumPatternNames: Object.keys(drumPatterns),
|
|
@@ -6194,7 +6234,6 @@ var mountDAW = (target, options = {}) => {
|
|
|
6194
6234
|
active.core.setVolume(active.volume);
|
|
6195
6235
|
volLabel.textContent = String(active.volume);
|
|
6196
6236
|
});
|
|
6197
|
-
const isAdvanced = trackStates.length > TRACKS_SIMPLE.length;
|
|
6198
6237
|
if (isAdvanced || active.config.id !== "chord") {
|
|
6199
6238
|
const lyricDiv = document.createElement("div");
|
|
6200
6239
|
lyricDiv.className = "dtm-row";
|
|
@@ -6402,16 +6441,16 @@ var mountDAW = (target, options = {}) => {
|
|
|
6402
6441
|
updateUndoRedo();
|
|
6403
6442
|
redrawAll();
|
|
6404
6443
|
};
|
|
6405
|
-
const setToolMode = (
|
|
6406
|
-
activeToolMode =
|
|
6444
|
+
const setToolMode = (mode2) => {
|
|
6445
|
+
activeToolMode = mode2;
|
|
6407
6446
|
for (const [btn, m] of [
|
|
6408
6447
|
[refs.toolPen, "pen"],
|
|
6409
6448
|
[refs.toolSelect, "select"],
|
|
6410
6449
|
[refs.toolEraser, "eraser"]
|
|
6411
6450
|
]) {
|
|
6412
|
-
btn.classList.toggle("dtm-segbtn--active", m ===
|
|
6451
|
+
btn.classList.toggle("dtm-segbtn--active", m === mode2);
|
|
6413
6452
|
}
|
|
6414
|
-
if (
|
|
6453
|
+
if (mode2 !== "select") {
|
|
6415
6454
|
selectionRect = null;
|
|
6416
6455
|
selectedNotes = [];
|
|
6417
6456
|
}
|
|
@@ -6645,7 +6684,6 @@ var mountDAW = (target, options = {}) => {
|
|
|
6645
6684
|
const applyMidiSelection = (midi, selectedIndices) => {
|
|
6646
6685
|
clearAll();
|
|
6647
6686
|
for (const t of trackStates) t.core.setLoadMode(true);
|
|
6648
|
-
const isAdvanced = trackStates.length > TRACKS_SIMPLE.length;
|
|
6649
6687
|
const { placements, bpm: parsedBpm } = isAdvanced ? extractMidiPlacementsByTrack(
|
|
6650
6688
|
midi,
|
|
6651
6689
|
selectedIndices,
|
|
@@ -6843,6 +6881,9 @@ var mountDAW = (target, options = {}) => {
|
|
|
6843
6881
|
refs.mmlInfoBtn.addEventListener("click", () => {
|
|
6844
6882
|
showModal("MML\u306E\u66F8\u304D\u65B9\u89E3\u8AAC", MML_INFO_HTML);
|
|
6845
6883
|
});
|
|
6884
|
+
refs.midiInfoBtn.addEventListener("click", () => {
|
|
6885
|
+
showModal("MIDI\u306E\u8AAD\u307F\u8FBC\u307F\u89E3\u8AAC", MIDI_INFO_HTML);
|
|
6886
|
+
});
|
|
6846
6887
|
refs.shiftApplyBtn.addEventListener(
|
|
6847
6888
|
"click",
|
|
6848
6889
|
() => overlayDuring(() => {
|
package/package.json
CHANGED