From 67551075be1ebbb7c2ec7e25d97938b2782d0626 Mon Sep 17 00:00:00 2001 From: 3dtours Date: Tue, 28 Jul 2026 09:39:18 +0700 Subject: [PATCH] =?UTF-8?q?fix:=20s=E1=BB=ADa=20l=E1=BB=97i=20loaded=20ins?= =?UTF-8?q?trument=20=E1=BB=9F=20SECTION-TAB=20nh=C6=B0ng=20kh=C3=B4ng=20p?= =?UTF-8?q?lay=20=C4=91=C6=B0=E1=BB=A3c=20=E1=BB=9F=20MAIN=20SESSION?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/static/js/app.jsx | 3 ++- app/static/js/app.precompiled.js | 2 +- app/storage/sonicforge.db | Bin 110592 -> 110592 bytes 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/static/js/app.jsx b/app/static/js/app.jsx index 433249b..0c5ac7c 100644 --- a/app/static/js/app.jsx +++ b/app/static/js/app.jsx @@ -10331,7 +10331,8 @@ const App = () => { const secStart = sec.start || 0; const secEnd = secStart + (sec.duration || 0); - const secTracks = sec.tracks || []; + const openTab = sessionTabsRef.current ? sessionTabsRef.current.find(st => st.sectionId === sec.sectionId || st.sectionId === sec.id) : null; + const secTracks = openTab ? openTab.tracks : (sec.tracks || []); const hasSubSolo = secTracks.some(st => st.solo); secTracks.forEach((subTrack, subIdx) => { diff --git a/app/static/js/app.precompiled.js b/app/static/js/app.precompiled.js index 0ec78a2..a3530e8 100644 --- a/app/static/js/app.precompiled.js +++ b/app/static/js/app.precompiled.js @@ -303,7 +303,7 @@ const noteDurSec=(note.duration_beats||1)*secondsPerBeat;const noteEndSec=noteSt if(track.instrumentId&&midiItems.length===0&&track.buffer){// Play audio normally (the buffer has the audio data) // This block is intentionally empty - audio clips already play above }// SECTION items playback -const sections=track.sections||[];if(activeTab==='main'&§ions.length>0){const bpmVal=parseInt(bpm)||120;const secondsPerBeat=60.0/bpmVal;const secondsPerBar=secondsPerBeat*4;sections.forEach(sec=>{const secStart=sec.start||0;const secEnd=secStart+(sec.duration||0);const secTracks=sec.tracks||[];const hasSubSolo=secTracks.some(st=>st.solo);secTracks.forEach((subTrack,subIdx)=>{const isSubPlayable=hasSubSolo?subTrack.solo:!subTrack.muted;if(!isSubPlayable)return;const subNode=getOrCreateSubTrackNode(track,subTrack,context);if(!subNode)return;// 1. Play clips in subTrack +const sections=track.sections||[];if(activeTab==='main'&§ions.length>0){const bpmVal=parseInt(bpm)||120;const secondsPerBeat=60.0/bpmVal;const secondsPerBar=secondsPerBeat*4;sections.forEach(sec=>{const secStart=sec.start||0;const secEnd=secStart+(sec.duration||0);const openTab=sessionTabsRef.current?sessionTabsRef.current.find(st=>st.sectionId===sec.sectionId||st.sectionId===sec.id):null;const secTracks=openTab?openTab.tracks:sec.tracks||[];const hasSubSolo=secTracks.some(st=>st.solo);secTracks.forEach((subTrack,subIdx)=>{const isSubPlayable=hasSubSolo?subTrack.solo:!subTrack.muted;if(!isSubPlayable)return;const subNode=getOrCreateSubTrackNode(track,subTrack,context);if(!subNode)return;// 1. Play clips in subTrack const subClips=subTrack.clips||[];subClips.forEach(clip=>{if(!clip.buffer)return;const clipStartLocal=clip.startTime||0;const clipDurLocal=clip.buffer.duration/(clip.speed||1.0);const clipStartMain=secStart+clipStartLocal;const clipEndMain=clipStartMain+clipDurLocal;// Only play within the bounds of [secStart, secEnd] const activeStart=Math.max(clipStartMain,secStart);const activeEnd=Math.min(clipEndMain,secEnd);if(activeStart0){subMidiItems.forEach(item=>{const notes=item.notes||[];notes.forEach(note=>{const noteStartSecLocal=item.startTime+(note.start_beat||0)*secondsPerBeat;const noteDurSec=(note.duration_beats||1)*secondsPerBeat;const noteStartMain=secStart+noteStartSecLocal;const noteEndMain=noteStartMain+noteDurSec;// Only play if the note starts inside the Section item bounds and hasn't finished yet diff --git a/app/storage/sonicforge.db b/app/storage/sonicforge.db index 98fec64097e9cedb491b1fe8796c9eb113aa9809..8671c8918d89b4ca9272637d1d34da84be5b6c2e 100644 GIT binary patch delta 3694 zcmeHKU2GLa6z-JDKlI*Ku-q0)S0WHE+nt%6*`4AK^(O`eM1>%UWZCxq|L?uq`$shR zZcOV1Mv91u(I=x(5=kH}2@i%RV~7vN_)z1k54=mFGkY&|_ex)V>Liogo85EHcg~*k z%{S+k)}C8hJ3GAPc27^wu-H$Cy^w& z3*zN?1`Ni-om9<0K!}%9B^c6JSuKRl=FiWAq5gmkZrkja(J3S)7;_75 zb=rc&7aey+mwphxei4wCu`t3nad2R)^F@`3vr0OqOemGOaAKGQX`LrL$-$4U(83-7 zIT#0n81@=y`l#b6`cwFjX^m)3I+!?6$T5hQ?Ky-o@Mx$!^z9uoc-HH$7U&hLC z!=7IgC9<^0nq_QJ{?9Ckh#Z+`^xrXRC&(DB*-j&$s#}IH!LBJnY7hvOBeE@|`@vCa zdbRfaGDzyxJgyb1u4OL!rCrm4R2uAguW%vcryR!Ge!UDCMn$`z8)mj7$Yu00h=hSz7s1LJd~zPV=(Uch46&OtB(J3c zJVd)%600N#TcUVrK;(}#NKid76-y9Z5|CtQ5i$5Fsqb}+D#bL?+^QqEM^bZS0INnY zN!>#z%ZoJ=Ii+eQTbn9akowBo)l*nCy&$p(SYs@MnoY+oHboJRTmd`#y9Zq2m%W9d z7|M9D-l!&+1%1ucO~tyZ1whKi*v_w91jGFIt01!VsV^sgn}6)X(ZAjn=U2G3`_`}g z?3>_8uFQflal9Fj5z1ei1*hd7$!q)@@npT2Nt5VE;eTHOBdd%SU1c=C-dJTc!HTPl z_CGV)8y)3#Vp+Kf;+>u;m*WN3a??_biOwXNkL8&-F{X>TVp*9e%;a+KMLY7)ujdeg zI?_B6+$nUZW>W9GwA*g&DN71UY26`1AyoyFmte`MEfYTxXYV^;Oxz|ABz{JIpv{Dp zh*M*(o~cgPd0`HW^lIt~>R;jz_XTL@S+ZV;mo1+dr%(#Xr~A8)K6%Xudv=u68#8&W zk)5%0DIXrF{YOebPkIYQS}at|cur$}twy`V0`%~13u7&?P+KgtgEKSLbSqBNsR(r@ zw8Dcc&Q^a>gkF%h6VC!eVo#-OrK+u423Jpsn*v%v&9&dhu$;=KlewB^ncVyo?DVup zD5wNF0;W$Ea|26wP%K7bgyWj*|jOP@K1-YH;SxojWrx3rbtHSyZY(RoPV!ha}iRiIdm{ zVG7EsYf}_PLaGEps#FQ}D+?AZ*mYYXv4SqL>=ua?n|A!11gic5Bo;?cGk509nRDmp zZSJNwchl|hp$9!ZJ>wonJO*x_F!12F^FRL5m+cwMZs&v4VCJW4DieSG(ay^DUyr`( zeUB|F6nINNo^y+7IC<;Q<8WYaGQ57>-I#$JZY6+PpC=r<54*wdPx{1mu={fI=9xp^ z|JwhszX++*A7p&_sKSp9l5S@bKFlW!R z5?MhkwNjR}G*Wg+6#a*T-Ms=#CnQQxMB0?Eh)S$n_6Ur5A>L+5X!f}rehGzPQBo`< zqqPxgYcxl%r6?&{Vtv_^*Bddr+>n?i=Iifd6NLLps^H(_WTf1AR`j7K#9rzpyP*Ps$Z;Ms+v|UzMX^PIe|u#pGS+N zMPkKhKt>5><(q^C3E%Kj8KG7xmoF_hF}Chn3MO)rS&%W7$S@&y6pZHfhstVHT5j#^ zS?QOutZ%TyN*uXYet*E!-Pv7=T&Of`D@NgppZR7` zNgo)Vm~lG;?`MVb_D3qxQsUO1P&$=tH-gt}bD_FEA0vj-;aatEp%Ts-o(}7c@Owdh z))z0t==&nYUd6rag+E;T6Da