feat: sustain (CC64), modulation (CC1), pitch bend for MIDI keyboard
- Add controllerChange forwarder for all CC messages (cmd 0xB) - Add pitchBend method to SonicSF + MIDI handler (cmd 0xE) - CCs routed to _synthInstance.controllerChange(ch, cc, val) - Pitch bend routed to _synthInstance.pitchBend(ch, 14bit-val)
This commit is contained in:
@@ -6758,6 +6758,7 @@ const App = () => {
|
|||||||
activeMidiPitchesRef.current.add(pitch);
|
activeMidiPitchesRef.current.add(pitch);
|
||||||
setActiveMidiPitches(new Set(activeMidiPitchesRef.current));
|
setActiveMidiPitches(new Set(activeMidiPitchesRef.current));
|
||||||
{ if (window.SonicSF) {
|
{ if (window.SonicSF) {
|
||||||
|
const ch = msg.data[0] & 0x0F;
|
||||||
const arSub = subTabsRef && subTabsRef.current && activeTabRef && subTabsRef.current.find(s => s.id === activeTabRef.current && s.type === 'PIANO_ROLL' && s.isArmed);
|
const arSub = subTabsRef && subTabsRef.current && activeTabRef && subTabsRef.current.find(s => s.id === activeTabRef.current && s.type === 'PIANO_ROLL' && s.isArmed);
|
||||||
if (arSub) {
|
if (arSub) {
|
||||||
window.SonicSF.playNote(pitch, velocity, 500, undefined, arSub.instrumentProgram, null, undefined, arSub.synth_engine);
|
window.SonicSF.playNote(pitch, velocity, 500, undefined, arSub.instrumentProgram, null, undefined, arSub.synth_engine);
|
||||||
@@ -6781,6 +6782,26 @@ const App = () => {
|
|||||||
setLastMidiNote(prev => prev && prev.pitch === pitch ? { ...prev, length: lenSec, time: Date.now() } : prev);
|
setLastMidiNote(prev => prev && prev.pitch === pitch ? { ...prev, length: lenSec, time: Date.now() } : prev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Sustain (CC64), Modulation (CC1), Pitch Bend ──
|
||||||
|
const midiCh = msg.data[0] & 0x0F;
|
||||||
|
if (cmd === 0xB) {
|
||||||
|
// Controller Change: forward all CCs to SpessaSynth
|
||||||
|
const cc = msg.data[1];
|
||||||
|
const val = msg.data[2];
|
||||||
|
if (window.SonicSF && window.SonicSF.controllerChange) {
|
||||||
|
window.SonicSF.controllerChange(midiCh, cc, val);
|
||||||
|
}
|
||||||
|
} else if (cmd === 0xE) {
|
||||||
|
// Pitch Bend: 14-bit value (LSB + MSB)
|
||||||
|
const lsb = msg.data[1];
|
||||||
|
const msb = msg.data[2];
|
||||||
|
const bendVal = (msb << 7) | lsb;
|
||||||
|
if (window.SonicSF && window.SonicSF.pitchBend) {
|
||||||
|
window.SonicSF.pitchBend(midiCh, bendVal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Forward to active MIDI recorders
|
// Forward to active MIDI recorders
|
||||||
if (activeMIDIRecordersRef.current) {
|
if (activeMIDIRecordersRef.current) {
|
||||||
|
|||||||
@@ -154,6 +154,13 @@
|
|||||||
return { ..._channels[channel] };
|
return { ..._channels[channel] };
|
||||||
},
|
},
|
||||||
|
|
||||||
|
pitchBend: function (channel, value) {
|
||||||
|
if (channel < 0 || channel > 15) return;
|
||||||
|
if (_initialized && _synthInstance) {
|
||||||
|
try { _synthInstance.pitchBend(channel, value); } catch (e) {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
playNote: function (note, velocity, durationMs, startTime, program, destinationNode, channel, synthEngine) {
|
playNote: function (note, velocity, durationMs, startTime, program, destinationNode, channel, synthEngine) {
|
||||||
if (_initialized && _synthInstance) {
|
if (_initialized && _synthInstance) {
|
||||||
this._playNoteSpessa(note, velocity, durationMs, startTime, program, channel, synthEngine);
|
this._playNoteSpessa(note, velocity, durationMs, startTime, program, channel, synthEngine);
|
||||||
|
|||||||
Reference in New Issue
Block a user