diff --git a/app/core/native_render.py b/app/core/native_render.py index 71417e2..188857a 100644 --- a/app/core/native_render.py +++ b/app/core/native_render.py @@ -175,7 +175,7 @@ def bridge_state_preset_b64(channel=None, plugin_path=None) -> str: return "" -EXPRESSION_CC = 7 # TEST: CC7 thay CC11 de kiem tra VSTi nhan CC (revert 11 khi xong) +EXPRESSION_CC = 11 # CC11 expression def _expression_events(notes, bpm, sample_rate, grid=64): """Sinh CC11 events sample-accurate từ expression_curve mỗi note. diff --git a/app/static/js/app.jsx b/app/static/js/app.jsx index dc74d14..a383f3e 100644 --- a/app/static/js/app.jsx +++ b/app/static/js/app.jsx @@ -746,7 +746,7 @@ const _cc11ValueAt = (curve, ratio) => { }; // ponytail: duplicate interp cc11ValueAt (component) — consolidate khi curve // thành field track-level. -const EXPRESSION_CC = 7; // TEST: CC7 thay CC11 de kiem tra VSTi nhan CC (revert 11 khi xong) +const EXPRESSION_CC = 11; // CC11 expression — TEST 7 da xong, revert 11 const scheduleNoteExpressionCC11 = (track, note, ch, startWallTime, startSec, durSec) => { try { const curve = Array.isArray(note && note.expression_curve) ? note.expression_curve : []; diff --git a/app/static/js/app.precompiled.js b/app/static/js/app.precompiled.js index 0521aef..8987830 100644 --- a/app/static/js/app.precompiled.js +++ b/app/static/js/app.precompiled.js @@ -143,7 +143,7 @@ function sendMidiVolumeCC7(t,list,audible){const volDb=typeof t.volumeDb==='numb // chống timer stale sau stop/loop restart (pattern scheduleMidiNoteDispatch). let _cc11Timers=new Set();const clearAllCC11Timers=()=>{_cc11Timers.forEach(t=>{try{clearTimeout(t);}catch(e){}});_cc11Timers.clear();};const _cc11ValueAt=(curve,ratio)=>{if(!curve||!curve.length)return 127;if(curve.length===1)return curve[0].value;const pts=curve.slice().sort((a,b)=>a.position_ratio-b.position_ratio);if(ratio<=pts[0].position_ratio)return pts[0].value;if(ratio>=pts[pts.length-1].position_ratio)return pts[pts.length-1].value;for(let i=1;i{try{const curve=Array.isArray(note&¬e.expression_curve)?note.expression_curve:[];if(!curve||!curve.length)return;const epoch=_nativePlayEpoch;const isPerc=!!(track&&track.synth_engine&&track.synth_engine.soundfont_bank===128)||!!(track&&track.is_percussion);const ctx=getAudioContext();const GRID_MS=16;const n=Math.max(1,Math.ceil(durSec*1000/GRID_MS));const stepMs=durSec*1000/n;for(let i=0;i<=n;i++){const ratio=Math.min(1,i/n);const wallMs=(startWallTime+startSec)*1000+i*stepMs;const delayMs=Math.max(0,wallMs-ctx.currentTime*1000);const val=_cc11ValueAt(curve,ratio);const timer=setTimeout(()=>{if(epoch!==_nativePlayEpoch)return;if(window.SonicMidiRouter&&window.SonicMidiRouter.isBridgeActive&&window.SonicMidiRouter.isBridgeActive()){window.SonicMidiRouter.pushEvent({cmd:'CC',channel:track?track.id:0,pitch:EXPRESSION_CC,velocity:0,data2:val,percussion:isPerc});return;}if(window.SonicSF&&typeof window.SonicSF.controllerChange==='function'){window.SonicSF.controllerChange(ch,EXPRESSION_CC,val);}},delayMs);_cc11Timers.add(timer);}}catch(e){console.warn('[CC11] schedule error:',e);}};// MAIN SESSION end-time (seconds): endtime of the items ON the session's own // tracks only — audio clips, MIDI items, and section-item bounds. Section-TAB // content is deliberately IGNORED here: when played inside the main session the diff --git a/app/templates/index.html b/app/templates/index.html index 960ac3b..dba9630 100644 --- a/app/templates/index.html +++ b/app/templates/index.html @@ -51,7 +51,7 @@ - +