2eb327056d
- midiExtractor.js: extractSelectedMIDIContext with note name conversion - aiGateway.js: REARRANGE_TOOL_SPEC + buildRearrangeMessage - dawCommandDispatcher.js: register REARRANGE_MIDI_MELODY command - app.jsx: handleAISend detects selected MIDI item → rearrange flow - rearrangeMidiMelody handler places A/B track below source track
61 lines
2.1 KiB
JavaScript
61 lines
2.1 KiB
JavaScript
const SonicMidiExtractor = (function() {
|
|
const NOTE_NAMES = ['C','C#','D','D#','E','F','F#','G','G#','A','A#','B'];
|
|
|
|
function midiPitchToNoteName(pitch) {
|
|
const note = NOTE_NAMES[pitch % 12];
|
|
const octave = Math.floor(pitch / 12) - 1;
|
|
return note + octave;
|
|
}
|
|
|
|
function extractSelectedMIDIContext(tracks, selectedItemId, bpm) {
|
|
let targetItem = null;
|
|
let targetTrack = null;
|
|
|
|
for (const track of tracks) {
|
|
const items = track.midiItems || [];
|
|
const item = items.find(i => i.id === selectedItemId);
|
|
if (item) { targetItem = item; targetTrack = track; break; }
|
|
}
|
|
|
|
if (!targetItem) {
|
|
throw new Error('Please select a MIDI Item on the Timeline before requesting a Rearrangement!');
|
|
}
|
|
|
|
const notes = targetItem.notes || [];
|
|
if (notes.length === 0) {
|
|
throw new Error('Selected MIDI item has no notes to rearrange.');
|
|
}
|
|
|
|
const compactNotes = notes.map(n => ({
|
|
pitch: n.pitch,
|
|
note_name: midiPitchToNoteName(n.pitch),
|
|
start_beat: parseFloat((n.start_beat || 0).toFixed(2)),
|
|
duration_beats: parseFloat((n.duration_beats || 1).toFixed(2)),
|
|
velocity: parseFloat((n.velocity || 0.8).toFixed(2))
|
|
}));
|
|
|
|
const totalDurationBeats = compactNotes.reduce((max, n) => Math.max(max, n.start_beat + n.duration_beats), 0);
|
|
|
|
return {
|
|
track_name: targetTrack.name,
|
|
track_id: targetTrack.id,
|
|
item_id: targetItem.id,
|
|
item_name: targetItem.name,
|
|
duration_bars: targetItem.length_bars || Math.ceil(totalDurationBeats / 4),
|
|
total_beats: Math.ceil(totalDurationBeats),
|
|
bpm: parseInt(bpm || '120'),
|
|
total_notes: compactNotes.length,
|
|
notes: compactNotes,
|
|
instrument: targetTrack.synth_engine ? {
|
|
soundfont_id: targetTrack.synth_engine.soundfont_id || '',
|
|
soundfont_bank: targetTrack.synth_engine.soundfont_bank ?? 0,
|
|
soundfont_program: targetTrack.synth_engine.soundfont_program ?? 0
|
|
} : null
|
|
};
|
|
}
|
|
|
|
return { extractSelectedMIDIContext, midiPitchToNoteName };
|
|
})();
|
|
|
|
window.SonicMidiExtractor = SonicMidiExtractor;
|