@onjmin/dtm 0.1.6 → 0.1.8

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 CHANGED
@@ -263,6 +263,11 @@ type StreamVoiceNote = {
263
263
  };
264
264
  /** ストリーミング再生する歌詞トラック1本。 */
265
265
  type StreamVoiceTrack = {
266
+ /**
267
+ * 呼び出し側がソロ/ミュート判定に使う識別子(演奏トラックの config.id 等)。
268
+ * {@link StreamPlaybackOptions.isAudible} で参照する。省略時は常に可聴。
269
+ */
270
+ id?: string;
266
271
  /** 歌唱モデル名(koe音源キーワード or "klatt")。 */
267
272
  model: string;
268
273
  /** 最終ゲイン(声量×マスタ等を適用済み。1=等倍)。 */
@@ -272,6 +277,17 @@ type StreamVoiceTrack = {
272
277
  /** 発音順(startSec昇順)の歌唱ノート列。 */
273
278
  notes: StreamVoiceNote[];
274
279
  };
280
+ /** {@link SingingVoices.startStream} の任意オプション。 */
281
+ type StreamPlaybackOptions = {
282
+ /**
283
+ * そのトラックを今この瞬間に発音してよいか(ソロ/ミュート判定)。
284
+ * 各ノートを合成・スケジュールする直前にライブで評価するため、再生中に
285
+ * ソロを切り替えると先読み地平(最大 {@link STREAM_LOOKAHEAD_SEC} 秒)以降のノートへ反映される。
286
+ * 既にスケジュール済みのノートは鳴り切る(楽器側のミュート挙動と同じ)。
287
+ * 省略時は全トラック可聴。
288
+ */
289
+ isAudible?: (track: StreamVoiceTrack) => boolean;
290
+ };
275
291
  /**
276
292
  * 歌唱モデルをまとめて管理し、koeデモ式の「先読みストリーミング合成」で歌わせる高レベルヘルパ。
277
293
  *
@@ -298,7 +314,7 @@ type SingingVoices = {
298
314
  * AudioContextクロック秒(=シーケンサの開始時刻と一致させること)。
299
315
  * 即座に return し、合成は裏で先回り進行する。
300
316
  */
301
- startStream: (tracks: StreamVoiceTrack[], anchorTime: number) => void;
317
+ startStream: (tracks: StreamVoiceTrack[], anchorTime: number, opts?: StreamPlaybackOptions) => void;
302
318
  /** 進行中のストリームを中断し、スケジュール済みの発音をすべて止める(停止・一時停止・シーク)。 */
303
319
  stopStream: () => void;
304
320
  /** ストリーム停止+各モデルの内部状態を初期化する。 */
@@ -1266,4 +1282,4 @@ declare const DAW_CSS = "\n@font-face {\n font-family: 'k8x12';\n src: url('ht
1266
1282
  */
1267
1283
  declare const injectStyles: (doc?: Document) => void;
1268
1284
 
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, type MidiExtraction, type MidiNotePlacement, type MidiTrackAnalysis, type MmlMeta, type MmlPlayerInstance, type MmlPlayerOptions, type MountEditorOptions, type MountPlayerOptions, type Note, PITCH_MAP, PREWARM_NOTES, type ParseChordFn, type ParseChordsFn, 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 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 };
1285
+ 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, type MidiExtraction, type MidiNotePlacement, type MidiTrackAnalysis, type MmlMeta, type MmlPlayerInstance, type MmlPlayerOptions, type MountEditorOptions, type MountPlayerOptions, type Note, PITCH_MAP, PREWARM_NOTES, type ParseChordFn, type ParseChordsFn, 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
@@ -263,6 +263,11 @@ type StreamVoiceNote = {
263
263
  };
264
264
  /** ストリーミング再生する歌詞トラック1本。 */
265
265
  type StreamVoiceTrack = {
266
+ /**
267
+ * 呼び出し側がソロ/ミュート判定に使う識別子(演奏トラックの config.id 等)。
268
+ * {@link StreamPlaybackOptions.isAudible} で参照する。省略時は常に可聴。
269
+ */
270
+ id?: string;
266
271
  /** 歌唱モデル名(koe音源キーワード or "klatt")。 */
267
272
  model: string;
268
273
  /** 最終ゲイン(声量×マスタ等を適用済み。1=等倍)。 */
@@ -272,6 +277,17 @@ type StreamVoiceTrack = {
272
277
  /** 発音順(startSec昇順)の歌唱ノート列。 */
273
278
  notes: StreamVoiceNote[];
274
279
  };
280
+ /** {@link SingingVoices.startStream} の任意オプション。 */
281
+ type StreamPlaybackOptions = {
282
+ /**
283
+ * そのトラックを今この瞬間に発音してよいか(ソロ/ミュート判定)。
284
+ * 各ノートを合成・スケジュールする直前にライブで評価するため、再生中に
285
+ * ソロを切り替えると先読み地平(最大 {@link STREAM_LOOKAHEAD_SEC} 秒)以降のノートへ反映される。
286
+ * 既にスケジュール済みのノートは鳴り切る(楽器側のミュート挙動と同じ)。
287
+ * 省略時は全トラック可聴。
288
+ */
289
+ isAudible?: (track: StreamVoiceTrack) => boolean;
290
+ };
275
291
  /**
276
292
  * 歌唱モデルをまとめて管理し、koeデモ式の「先読みストリーミング合成」で歌わせる高レベルヘルパ。
277
293
  *
@@ -298,7 +314,7 @@ type SingingVoices = {
298
314
  * AudioContextクロック秒(=シーケンサの開始時刻と一致させること)。
299
315
  * 即座に return し、合成は裏で先回り進行する。
300
316
  */
301
- startStream: (tracks: StreamVoiceTrack[], anchorTime: number) => void;
317
+ startStream: (tracks: StreamVoiceTrack[], anchorTime: number, opts?: StreamPlaybackOptions) => void;
302
318
  /** 進行中のストリームを中断し、スケジュール済みの発音をすべて止める(停止・一時停止・シーク)。 */
303
319
  stopStream: () => void;
304
320
  /** ストリーム停止+各モデルの内部状態を初期化する。 */
@@ -1266,4 +1282,4 @@ declare const DAW_CSS = "\n@font-face {\n font-family: 'k8x12';\n src: url('ht
1266
1282
  */
1267
1283
  declare const injectStyles: (doc?: Document) => void;
1268
1284
 
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, type MidiExtraction, type MidiNotePlacement, type MidiTrackAnalysis, type MmlMeta, type MmlPlayerInstance, type MmlPlayerOptions, type MountEditorOptions, type MountPlayerOptions, type Note, PITCH_MAP, PREWARM_NOTES, type ParseChordFn, type ParseChordsFn, 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 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 };
1285
+ 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, type MidiExtraction, type MidiNotePlacement, type MidiTrackAnalysis, type MmlMeta, type MmlPlayerInstance, type MmlPlayerOptions, type MountEditorOptions, type MountPlayerOptions, type Note, PITCH_MAP, PREWARM_NOTES, type ParseChordFn, type ParseChordsFn, 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
@@ -1789,42 +1789,33 @@ var createSingingVoices = (ctx, destination, options = {}) => {
1789
1789
  }
1790
1790
  await Promise.all(promises);
1791
1791
  };
1792
- const startStream = (tracks, anchorTime) => {
1792
+ const startStream = (tracks, anchorTime, opts) => {
1793
1793
  const session = ++streamSession;
1794
- const items = [];
1795
- for (const track of tracks) {
1794
+ const runTrack = async (track) => {
1796
1795
  const model = loaded.get(track.model.toLowerCase());
1797
- if (!model) continue;
1796
+ if (!model) return;
1797
+ const items = [];
1798
1798
  forEachSungNote(track, (note, prevVowel) => {
1799
- items.push({
1800
- model,
1801
- note,
1802
- prevVowel,
1803
- volume: track.volume,
1804
- pan: track.pan
1805
- });
1799
+ items.push({ note, prevVowel });
1806
1800
  });
1807
- }
1808
- items.sort((a, b) => a.note.startSec - b.note.startSec);
1809
- void (async () => {
1810
- for (const item of items) {
1801
+ const peak = Math.max(1e-4, track.volume);
1802
+ for (const { note, prevVowel } of items) {
1811
1803
  if (session !== streamSession) return;
1812
- while (item.note.startSec - (ctx.currentTime - anchorTime) > STREAM_LOOKAHEAD_SEC) {
1804
+ while (note.startSec - (ctx.currentTime - anchorTime) > STREAM_LOOKAHEAD_SEC) {
1813
1805
  await new Promise((resolve) => setTimeout(resolve, STREAM_POLL_MS));
1814
1806
  if (session !== streamSession) return;
1815
1807
  }
1816
- const t0 = anchorTime + item.note.startSec;
1817
- const peak = Math.max(1e-4, item.volume);
1818
- const { model, note } = item;
1808
+ if (opts?.isAudible && !opts.isAudible(track)) continue;
1809
+ const t0 = anchorTime + note.startSec;
1819
1810
  if (model.renderToCache && model.scheduleCached) {
1820
1811
  const key = await model.renderToCache(
1821
1812
  note.syllable,
1822
- item.prevVowel,
1813
+ prevVowel,
1823
1814
  note.pitch,
1824
1815
  note.durationSec * 1e3
1825
1816
  );
1826
1817
  if (session !== streamSession) return;
1827
- if (key) model.scheduleCached(key, t0, peak, item.pan);
1818
+ if (key) model.scheduleCached(key, t0, peak, track.pan);
1828
1819
  } else {
1829
1820
  const when = t0 - ctx.currentTime;
1830
1821
  model(note.syllable, {
@@ -1834,12 +1825,13 @@ var createSingingVoices = (ctx, destination, options = {}) => {
1834
1825
  volume: peak,
1835
1826
  when,
1836
1827
  duration: note.durationSec,
1837
- pan: item.pan
1828
+ pan: track.pan
1838
1829
  });
1830
+ await new Promise((resolve) => setTimeout(resolve, 0));
1839
1831
  }
1840
- await new Promise((resolve) => setTimeout(resolve, 0));
1841
1832
  }
1842
- })();
1833
+ };
1834
+ for (const track of tracks) void runTrack(track);
1843
1835
  };
1844
1836
  const stopStream = () => {
1845
1837
  streamSession++;
@@ -3379,13 +3371,10 @@ var createSequencer = (options) => {
3379
3371
  }
3380
3372
  while (nowIndex < timeline.length) {
3381
3373
  const ev = timeline[nowIndex];
3382
- if (soloId && ev.trackId !== soloId) {
3383
- nowIndex++;
3384
- continue;
3385
- }
3386
3374
  const _when = ev.when - time;
3387
3375
  if (_when > PLAN_TIME) break;
3388
3376
  nowIndex++;
3377
+ if (soloId && ev.trackId !== soloId) continue;
3389
3378
  const velocityVolume = ev.velocity / 127;
3390
3379
  const currentVolume = (trackVolumeMap.get(ev.trackId) ?? ev.volume * 100) / 100;
3391
3380
  options.onPlayNote({
@@ -5080,6 +5069,7 @@ var mountDAW = (target, options = {}) => {
5080
5069
  });
5081
5070
  }
5082
5071
  return {
5072
+ id: trackState?.config.id,
5083
5073
  model: lt.model,
5084
5074
  volume: vocalVolumeToGain(lt.volume ?? DEFAULT_VOCAL_VOLUME) * (masterVolume / 100),
5085
5075
  pan: panToStereo(lt.pan ?? DEFAULT_PAN),
@@ -5110,7 +5100,9 @@ var mountDAW = (target, options = {}) => {
5110
5100
  playbackState = "playing";
5111
5101
  sequencer.start(fromStep);
5112
5102
  if (streaming && voices) {
5113
- voices.startStream(streamTracks, sequencer.getStartTime());
5103
+ voices.startStream(streamTracks, sequencer.getStartTime(), {
5104
+ isAudible: (t) => !isSolo || t.id === activeTrackId
5105
+ });
5114
5106
  }
5115
5107
  updateTransport();
5116
5108
  };
package/dist/index.mjs CHANGED
@@ -1685,42 +1685,33 @@ var createSingingVoices = (ctx, destination, options = {}) => {
1685
1685
  }
1686
1686
  await Promise.all(promises);
1687
1687
  };
1688
- const startStream = (tracks, anchorTime) => {
1688
+ const startStream = (tracks, anchorTime, opts) => {
1689
1689
  const session = ++streamSession;
1690
- const items = [];
1691
- for (const track of tracks) {
1690
+ const runTrack = async (track) => {
1692
1691
  const model = loaded.get(track.model.toLowerCase());
1693
- if (!model) continue;
1692
+ if (!model) return;
1693
+ const items = [];
1694
1694
  forEachSungNote(track, (note, prevVowel) => {
1695
- items.push({
1696
- model,
1697
- note,
1698
- prevVowel,
1699
- volume: track.volume,
1700
- pan: track.pan
1701
- });
1695
+ items.push({ note, prevVowel });
1702
1696
  });
1703
- }
1704
- items.sort((a, b) => a.note.startSec - b.note.startSec);
1705
- void (async () => {
1706
- for (const item of items) {
1697
+ const peak = Math.max(1e-4, track.volume);
1698
+ for (const { note, prevVowel } of items) {
1707
1699
  if (session !== streamSession) return;
1708
- while (item.note.startSec - (ctx.currentTime - anchorTime) > STREAM_LOOKAHEAD_SEC) {
1700
+ while (note.startSec - (ctx.currentTime - anchorTime) > STREAM_LOOKAHEAD_SEC) {
1709
1701
  await new Promise((resolve) => setTimeout(resolve, STREAM_POLL_MS));
1710
1702
  if (session !== streamSession) return;
1711
1703
  }
1712
- const t0 = anchorTime + item.note.startSec;
1713
- const peak = Math.max(1e-4, item.volume);
1714
- const { model, note } = item;
1704
+ if (opts?.isAudible && !opts.isAudible(track)) continue;
1705
+ const t0 = anchorTime + note.startSec;
1715
1706
  if (model.renderToCache && model.scheduleCached) {
1716
1707
  const key = await model.renderToCache(
1717
1708
  note.syllable,
1718
- item.prevVowel,
1709
+ prevVowel,
1719
1710
  note.pitch,
1720
1711
  note.durationSec * 1e3
1721
1712
  );
1722
1713
  if (session !== streamSession) return;
1723
- if (key) model.scheduleCached(key, t0, peak, item.pan);
1714
+ if (key) model.scheduleCached(key, t0, peak, track.pan);
1724
1715
  } else {
1725
1716
  const when = t0 - ctx.currentTime;
1726
1717
  model(note.syllable, {
@@ -1730,12 +1721,13 @@ var createSingingVoices = (ctx, destination, options = {}) => {
1730
1721
  volume: peak,
1731
1722
  when,
1732
1723
  duration: note.durationSec,
1733
- pan: item.pan
1724
+ pan: track.pan
1734
1725
  });
1726
+ await new Promise((resolve) => setTimeout(resolve, 0));
1735
1727
  }
1736
- await new Promise((resolve) => setTimeout(resolve, 0));
1737
1728
  }
1738
- })();
1729
+ };
1730
+ for (const track of tracks) void runTrack(track);
1739
1731
  };
1740
1732
  const stopStream = () => {
1741
1733
  streamSession++;
@@ -3275,13 +3267,10 @@ var createSequencer = (options) => {
3275
3267
  }
3276
3268
  while (nowIndex < timeline.length) {
3277
3269
  const ev = timeline[nowIndex];
3278
- if (soloId && ev.trackId !== soloId) {
3279
- nowIndex++;
3280
- continue;
3281
- }
3282
3270
  const _when = ev.when - time;
3283
3271
  if (_when > PLAN_TIME) break;
3284
3272
  nowIndex++;
3273
+ if (soloId && ev.trackId !== soloId) continue;
3285
3274
  const velocityVolume = ev.velocity / 127;
3286
3275
  const currentVolume = (trackVolumeMap.get(ev.trackId) ?? ev.volume * 100) / 100;
3287
3276
  options.onPlayNote({
@@ -4976,6 +4965,7 @@ var mountDAW = (target, options = {}) => {
4976
4965
  });
4977
4966
  }
4978
4967
  return {
4968
+ id: trackState?.config.id,
4979
4969
  model: lt.model,
4980
4970
  volume: vocalVolumeToGain(lt.volume ?? DEFAULT_VOCAL_VOLUME) * (masterVolume / 100),
4981
4971
  pan: panToStereo(lt.pan ?? DEFAULT_PAN),
@@ -5006,7 +4996,9 @@ var mountDAW = (target, options = {}) => {
5006
4996
  playbackState = "playing";
5007
4997
  sequencer.start(fromStep);
5008
4998
  if (streaming && voices) {
5009
- voices.startStream(streamTracks, sequencer.getStartTime());
4999
+ voices.startStream(streamTracks, sequencer.getStartTime(), {
5000
+ isAudible: (t) => !isSolo || t.id === activeTrackId
5001
+ });
5010
5002
  }
5011
5003
  updateTransport();
5012
5004
  };
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.6",
5
+ "version": "0.1.8",
6
6
  "description": "MMLを中間言語に用いた、モバイルファーストなDAW / ピアノロール打ち込みコンポーネント",
7
7
  "homepage": "https://onjmin.github.io/dtm",
8
8
  "repository": {