*/}}
瀏覽代碼

Separated audio channels

YimingWu 1 年之前
父節點
當前提交
088d8bbe49
共有 2 個文件被更改,包括 51 次插入37 次删除
  1. 40 32
      la_audio.c
  2. 11 5
      la_interface.h

+ 40 - 32
la_audio.c

@@ -300,12 +300,17 @@ void IDN_OutputDestroy(laSynthNodeOutput* n){
 int IDN_OutputVisit(laSynthNodeOutput* n, laNodeVisitInfo* vi){
     if(LA_SRC_AND_PARENT(n->In)){ laBaseNode*bn=n->In->Source->Parent; LA_VISIT_NODE(bn,vi); }
     LA_ADD_THIS_NODE(n,vi);
+    laAudioChannel* outchannel = laGetAudioChannel(SSTR(n->SendName));
+    memAssignRef(n,&n->Send,outchannel);
     return LA_DAG_FLAG_PERM;
 }
 int IDN_OutputEval(laSynthNodeOutput* n){
-    real* input; INPUTPACKET(input,n->In);
-    if(input) memcpy(MAIN.Audio->AudioEvalSynth->AudioSamples,input,sizeof(real)*LA_SYNTH_PLEN);
-    else memset(MAIN.Audio->AudioEvalSynth->AudioSamples,0,sizeof(real)*LA_SYNTH_PLEN);
+    if(!n->Send)return 1;
+    real* input; INPUTPACKET(input,n->In); if(!input) return 1;
+    real Samples[LA_SYNTH_PLEN];
+    for(int i=0;i<LA_SYNTH_PLEN;i++){
+        n->Send->Samples[i] += input[i];
+    }
     return 1;
 }
 void IDN_OutputCopy(laSynthNodeOutput* new, laSynthNodeOutput* old, int DoRematch){
@@ -319,6 +324,8 @@ void laui_OutputNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColum
     laUiItem* b=laBeginRow(uil,c,0,0);
     laShowNodeSocket(uil,c,This,"in",0)->Flags|=LA_UI_SOCKET_LABEL_E;
     laShowLabel(uil,c,"🕪",0,0);
+    laShowItemFull(uil,c,This,"send_channel_selector",LA_WIDGET_COLLECTION_SELECTOR,0,laui_IdentifierOnly,0)->Flags|=LA_UI_COLLECTION_SIMPLE_SELECTOR;
+    laShowItem(uil,c,This,"send_channel_name")->Expand = 1;
     laEndRow(uil,b);
 }
 
@@ -499,16 +506,22 @@ void laRebuildSynthGraphs(){
 int laEvalSynthGraphs(){
     laSynth* ss; int any=0;
     memset(MAIN.Audio->AudioSamples,0,sizeof(real)*LA_SYNTH_PLEN);
+    for(laAudioChannel* ac=MAIN.Audio->Channels.pFirst;ac;ac=ac->Item.pNext){
+        memset(ac->Samples,0,sizeof(real)*LA_SYNTH_PLEN);
+    }
     for(ss=MAIN.Audio->Synths.pFirst;ss;ss=ss->Item.pNext){
         laSpinLock(&ss->Lock);
         if(!ss->Playing){ laSpinUnlock(&ss->Lock); continue; }
-        MAIN.Audio->AudioEvalSynth=ss; MAIN.Audio->AudioEvalTime=0; INITPACKET(ss->AudioSamples);
+        MAIN.Audio->AudioEvalSynth=ss; MAIN.Audio->AudioEvalTime=0;
         laRunPage(ss->Page,1);
         laSpinUnlock(&ss->Lock);
+        any=1;
+    }
+
+    for(laAudioChannel* ac=MAIN.Audio->Channels.pFirst;ac;ac=ac->Item.pNext){
         for(int i=0;i<LA_SYNTH_PLEN;i++){
-            MAIN.Audio->AudioSamples[i]+=ss->AudioSamples[i];
+            MAIN.Audio->AudioSamples[i] += ac->Samples[i]*(ac->Volume/10);
         }
-        any=1;
     }
     return any;
 }
@@ -659,24 +672,20 @@ int OPINV_laSynthPlay(laOperator* a, laEvent* e){
     return LA_FINISHED;
 }
 
-void laAudioEnsureChannelPtr(){
-    for(laAudioChannel* iac=MAIN.Audio->Channels.pFirst;iac;iac=iac->Item.pNext){
-        TNS_CLAMP(iac->ID,0,31);
-        MAIN.Audio->ChannelPtr[iac->ID]=iac;
-    }
-}
 laAudioChannel* laNewAudioChannel(char* Name){
     laAudioChannel* ac=memAcquireHyper(sizeof(laAudioChannel)); lstAppendItem(&MAIN.Audio->Channels,ac);
-    strSafeSet(&ac->Name,Name); int has=0,i;
-    for(i=0;i<64;i++){
-        for(laAudioChannel* iac=MAIN.Audio->Channels.pFirst;iac;iac=iac->Item.pNext){ if(iac->ID==i){ has=1; break; } }
-    }
-    if(!has){ac->ID = i;}else{ac->ID=0;}
-    ac->Volume = 10.0f; laAudioEnsureChannelPtr();
+    strSafeSet(&ac->Name,Name); 
+    ac->Volume = 10.0f;
 }
 void laRemoveAudioChannel(laAudioChannel* ac){
     lstRemoveItem(&MAIN.Audio->Channels,ac); strSafeDestroy(&ac->Name);
-    memFree(ac); laAudioEnsureChannelPtr();
+    memFree(ac);
+}
+laAudioChannel* laGetAudioChannel(char* Name){
+    for(laAudioChannel* ac=MAIN.Audio->Channels.pFirst;ac;ac=ac->Item.pNext){
+        if(strSame(SSTR(ac->Name),Name)) return ac;
+    }
+    return 0;
 }
 
 int OPCHK_IslaAudioChannel(laPropPack *This, laStringSplitor *ss){
@@ -685,7 +694,7 @@ int OPCHK_IslaAudioChannel(laPropPack *This, laStringSplitor *ss){
 }
 int OPINV_ShedNewAudioChannel(laOperator* a, laEvent* e){
     laNewAudioChannel("Output");
-    laNotifyInstanceUsers(MAIN.Audio); laRecordAndPush(0,"la.audio","New channel", 0); // TODO: hint for laAudioEnsureChannelPtr
+    laNotifyInstanceUsers(MAIN.Audio); laRecordAndPush(0,"la.audio","New channel", 0);
     return LA_FINISHED;
 }
 int OPINV_ShedRemoveAudioChannel(laOperator* a, laEvent* e){
@@ -754,9 +763,9 @@ void laui_AudioChannel(laUiList *uil, laPropPack *This, laPropPack *Extra, laCol
     
     laShowHeightAdjuster(uil,c1,This,"__move",0);
 
-    laShowItem(uil,c2,This,"name");
     b=laBeginRow(uil,c2,0,0);
-    laShowItem(uil,c2,This,"id")->Expand=1; laShowItem(uil,c,This,"remove")->Flags|=LA_UI_FLAGS_ICON;
+    laShowItem(uil,c2,This,"name")->Expand=1;
+    laShowItem(uil,c,This,"remove")->Flags|=LA_UI_FLAGS_ICON;
     laEndRow(uil,b);
     laShowItem(uil,c2,This,"volume");
 
@@ -782,6 +791,9 @@ void* laget_FirstAudioDevice(void* unused1,void* unused2){
 void* laget_FirstSynth(void* unused1,void* unused2){
     return MAIN.Audio->Synths.pFirst;
 }
+void* laget_FirstAudioChannel(void* unused1, void* unused2){
+    return MAIN.Audio->Channels.pFirst;
+}
 void lapost_Synth(laSynth* ss){
     laSpinInit(&ss->Lock);
 }
@@ -796,17 +808,15 @@ void laset_CurrentSynth(laAudio* a,laSynth* s){
 void laset_CurrentAudioDevice(laAudio* a,laAudioDevice* ad){
     la_SelectAudioDevice(ad);
 }
-void laget_OutputSendChannelName(laSynthNodeOutput* n, char* str, char** target){
-    if(!MAIN.Audio||!MAIN.Audio->ChannelPtr[n->Send]) *target="-";
-    *target = SSTR(MAIN.Audio->ChannelPtr[n->Send]->Name);
+void laset_OutputSendChannel(laSynthNodeOutput* n,laAudioChannel* ac){
+    if(ac){ strSafeSet(&n->SendName, SSTR(ac->Name)); } else { strSafeSet(&n->SendName,""); }
+    laAudioChannel* outchannel = laGetAudioChannel(SSTR(n->SendName));
+    memAssignRef(n,&n->Send,outchannel);
 }
 void laset_QuantizeEnabledKeys(laSynthNodeQuantize* n, int index, int val_UNUSED){
     if(n->EnabledBits[index] & 0x1){ n->EnabledBits[index]=0; }
     else{ n->EnabledBits[index]=1; }
 }
-void laset_AudioChannelID(laAudioChannel* ac, int id){
-    ac->ID=id; laAudioEnsureChannelPtr();
-}
 void laset_AudioChannelMove(laAudioChannel* ac, int move){
     if(move<0 && ac->Item.pPrev){ lstMoveUp(&MAIN.Audio->Channels, ac); laNotifyUsers("la.audio"); }
     elif(move>0 && ac->Item.pNext){ lstMoveDown(&MAIN.Audio->Channels, ac); laNotifyUsers("la.audio"); }
@@ -858,8 +868,6 @@ void laInitAudio(){
     pc = laAddPropertyContainer("la_audio_channel", "LaGUI Audio Channel", "LaGUI Audio Channel", 0,0,sizeof(laAudioChannel),0,0,2);{
         LA_PC_CHANNEL=pc;
         laAddStringProperty(pc,"name","Name","Name of the synthesizer",0,0,0,0,1,offsetof(laAudioChannel,Name),0,0,0,0,LA_AS_IDENTIFIER);
-        laAddIntProperty(pc,"id","ID","Identifier of this channel",0,0,0,31,0,0,0,0,offsetof(laAudioChannel,ID),0,laset_AudioChannelID,0,0,0,0,0,0,0,0,0);
-        //laAddIntProperty(pc,"id","ID","Identifier of this channel",0,0,0,31,0,0,0,0,offsetof(laAudioChannel,ID),0,laset_AudioChannelID,0,0,0,0,0,0,0,0,0);
         laAddFloatProperty(pc,"volume","Volume","Volume of this channel",0,0,0,15,0,0.05,0,0,offsetof(laAudioChannel,Volume),0,0,0,0,0,0,0,0,0,0,0);
         laAddOperatorProperty(pc,"remove","Remove Channel", "Remove this channel", "LA_remove_channel", L'🗴', 0);
         laAddIntProperty(pc,"__move","Move Slider","Move Slider",LA_WIDGET_HEIGHT_ADJUSTER,0,0,0,0,0,0,0,0,0,laset_AudioChannelMove,0,0,0,0,0,0,0,0,LA_UDF_IGNORE);
@@ -920,8 +928,8 @@ void laInitAudio(){
     LA_PC_IDN_OUTPUT=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);
     laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
     laAddSubGroup(pc,"in", "Input","Input sound","la_in_socket",0,0,0,offsetof(laSynthNodeOutput,In),0,0,0,0,0,0,0,LA_UDF_SINGLE);
-    laAddIntProperty(pc,"send","Send","Send to channel",0,0,0,128,0,0,0,0,offsetof(laSynthNodeOutput,Send),0,0,0,0,0,0,0,0,0,0,0);
-    laAddStringProperty(pc,"send_channel_name","Channel Name","Channel name of this send target",0,0,0,0,0,-1,0,laget_OutputSendChannelName,0,0,LA_READ_ONLY|LA_UDF_IGNORE);
+    laAddStringProperty(pc,"send_channel_name","Channel Name","Channel name of this send target",0,0,0,0,1,offsetof(laSynthNodeOutput,SendName),0,0,0,0,0);
+    laAddSubGroup(pc,"send_channel_selector","Send","Send to channel","la_audio_channel",0,0,0,-1,laget_FirstAudioChannel,0,laget_ListNext,laset_OutputSendChannel,0,0,0,0);
 
     pc=laAddPropertyContainer("la_node_synth_envelope", "Envelope Node", "Sound envelope",0,laui_EnvelopeNode,sizeof(laSynthNodeEnvelope),lapost_Node,0,1);
     LA_PC_IDN_ENVELOPE=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);

+ 11 - 5
la_interface.h

@@ -1799,7 +1799,6 @@ STRUCTURE(laSynth){
     SYSLOCK Lock;
     int Playing;
     real AudioEvalTime;
-    real* AudioSamples;
 };
 
 STRUCTURE(laSynthNodeFM){
@@ -1847,10 +1846,14 @@ STRUCTURE(laSynthNodeScope){
     laSynth* FromSynth;
 };
 
+NEED_STRUCTURE(laAudioChannel);
+
 STRUCTURE(laSynthNodeOutput){
     laBaseNode Base;
     laNodeInSocket* In;
-    int Send;
+    laSafeString* SendName;
+    /* Runtime */
+    laAudioChannel* Send;
 };
 
 STRUCTURE(laSynthNodeEnvelope){
@@ -1879,8 +1882,8 @@ STRUCTURE(laAudioChannel){
     laListItem Item;
     laSafeString* Name;
     real Volume;
-    int ID;
-    int OutputChannel;
+    laSafeString* OutputChannel;
+    real Samples[LA_SYNTH_PLEN];
 };
 
 STRUCTURE(laAudioDevice){
@@ -1896,7 +1899,6 @@ STRUCTURE(laAudio){
     laSynth* CurrentSynth;
 
     laListHandle Channels;
-    laAudioChannel* ChannelPtr[32];
 
     SYSLOCK AudioStatusLock;
     ma_context MiniAudioContext;
@@ -1916,6 +1918,10 @@ void* laget_FirstSynth(void* unused1,void* unused2);
 void laset_CurrentSynth(laAudio* a,laSynth* s);
 void laset_CurrentAudioDevice(laAudio* a,laAudioDevice* ad);
 
+void laRemoveAudioChannel(laAudioChannel* ac);
+laAudioChannel* laNewAudioChannel(char* Name);
+laAudioChannel* laGetAudioChannel(char* Name);
+
 void la_AudioPreFrame();
 
 void laRebuildSynthGraphs();