| 
					
				 | 
			
			
				@@ -28,10 +28,14 @@ laNodeCategory* LA_NODE_CATEGORY_SYNTHESIZER; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 laNodeCategory* LA_NODE_CATEGORY_SYSTEM_SOUND; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 laBaseNodeType LA_IDN_FM; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+laBaseNodeType LA_IDN_VCA; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 laBaseNodeType LA_IDN_OUTPUT; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+laBaseNodeType LA_IDN_SCOPE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 laPropContainer* LA_PC_IDN_FM; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+laPropContainer* LA_PC_IDN_VCA; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 laPropContainer* LA_PC_IDN_OUTPUT; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+laPropContainer* LA_PC_IDN_SCOPE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #define _2PI 6.283185307 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -50,13 +54,13 @@ laPropContainer* LA_PC_IDN_OUTPUT; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 void IDN_FMInit(laSynthNodeFM* n, int NoCreate){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    INITPACKET(n->OutSamples); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if(NoCreate){ return; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     n->InFrequency=laCreateInSocket("FREQ",0); n->Out=laCreateOutSocket(n,"OUT",LA_PROP_FLOAT|LA_PROP_ARRAY); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     strSafeSet(&n->Base.Name,"FM"); n->Frequency=4; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    INITPACKET(n->OutSamples); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 void IDN_FMDestroy(laSynthNodeFM* n){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    laDestroyInSocket(n->InFrequency); laDestroyOutSocket(n->Out); strSafeDestroy(&n->Base.Name); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    laDestroyInSocket(n->InFrequency); laDestroyOutSocket(n->Out); strSafeDestroy(&n->Base.Name); memFree(n->OutSamples); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 int IDN_FMVisit(laSynthNodeFM* n, laNodeVisitInfo* vi){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if(LA_SRC_AND_PARENT(n->InFrequency)){ laBaseNode*bn=n->InFrequency->Source->Parent; LA_VISIT_NODE(bn,vi); } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -67,7 +71,7 @@ int IDN_FMEval(laSynthNodeFM* n){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     real f=n->Frequency, constf=0; real* inputf; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     INPUTPACKET(inputf,n->InFrequency); LA_GET_SRC_AS_VALUE(constf,n->InFrequency);  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     for(int i=0;i<LA_SYNTH_PLEN;i++){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        real useF=inputf?(inputf[i]+f):(f+constf); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        real useF=inputf?(inputf[i]+f):(f+constf); if(n->Slow) useF-=10; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         n->Phase+=MAIN.Audio->AudioFrameInterval*VAL2FREQ(useF)*_2PI; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         WRAPPHASE(n->Phase); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         n->OutSamples[i]=sin(n->Phase)*10; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -77,22 +81,139 @@ int IDN_FMEval(laSynthNodeFM* n){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 void IDN_FMCopy(laSynthNodeFM* new, laSynthNodeFM* old, int DoRematch){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if(DoRematch){ LA_IDN_NEW_LINK(InFrequency) return; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    LA_IDN_OLD_DUPL(Out); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    LA_IDN_OLD_DUPL(Out); new->Frequency=old->Frequency; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void la_FMNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void laui_FMNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     laColumn* c=laFirstColumn(uil); laSynthNodeFM*n=This->EndInstance; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     LA_BASE_NODE_HEADER(uil,c,This); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    laColumn* cl,*cr; laSplitColumn(uil,c,0.3); cl=laLeftColumn(c,0); cr=laRightColumn(c,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     laUiItem* b=laBeginRow(uil,c,0,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     laShowNodeSocket(uil,c,This,"in_frequency",0)->Flags|=LA_UI_SOCKET_LABEL_E; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    laShowItem(uil,c,This,"slow"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     laShowItem(uil,c,This,"frequency")->Expand=1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    laShowNodeSocket(uil,c,This,"out",0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    laEndRow(uil,b); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void IDN_VCAInit(laSynthNodeVCA* n, int NoCreate){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    INITPACKET(n->OutSamples); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if(NoCreate){ return; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    n->InAmp=laCreateInSocket("AMP",0); n->In=laCreateInSocket("IN",0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    n->Out=laCreateOutSocket(n,"OUT",LA_PROP_FLOAT|LA_PROP_ARRAY); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    strSafeSet(&n->Base.Name,"FM"); n->Amp=10; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void IDN_VCADestroy(laSynthNodeVCA* n){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    laDestroyInSocket(n->InAmp); laDestroyInSocket(n->In); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    laDestroyOutSocket(n->Out); strSafeDestroy(&n->Base.Name); memFree(n->OutSamples); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+int IDN_VCAVisit(laSynthNodeVCA* n, laNodeVisitInfo* vi){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if(LA_SRC_AND_PARENT(n->In)){ laBaseNode*bn=n->In->Source->Parent; LA_VISIT_NODE(bn,vi); } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if(LA_SRC_AND_PARENT(n->InAmp)){ laBaseNode*bn=n->InAmp->Source->Parent; LA_VISIT_NODE(bn,vi); } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    LA_ADD_THIS_NODE(n,vi); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return LA_DAG_FLAG_PERM; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+int IDN_VCAEval(laSynthNodeVCA* n){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    real amp=n->Amp, constamp=amp; real* inputamp=0,*input=0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    INPUTPACKET(input,n->In); INPUTPACKET(inputamp,n->InAmp); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if(!inputamp) LA_GET_SRC_AS_VALUE(constamp,n->InAmp); constamp/=10; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    n->Out->Data=n->OutSamples; n->Out->ArrLen=LA_SYNTH_PLEN; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if(!input){ memset(n->OutSamples,0,sizeof(real)*LA_SYNTH_PLEN); return 0; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for(int i=0;i<LA_SYNTH_PLEN;i++){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        real useA=(inputamp?(inputamp[i]/10):1)*constamp; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        n->OutSamples[i]= input[i]*useA; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void IDN_VCACopy(laSynthNodeVCA* new, laSynthNodeVCA* old, int DoRematch){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if(DoRematch){ LA_IDN_NEW_LINK(InAmp) LA_IDN_NEW_LINK(In) return; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    LA_IDN_OLD_DUPL(Out); new->Amp=old->Amp; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void laui_VCANode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    laColumn* c=laFirstColumn(uil); laSynthNodeVCA*n=This->EndInstance; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    LA_BASE_NODE_HEADER(uil,c,This); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    laColumn* cl,*cr; laSplitColumn(uil,c,0.3); cl=laLeftColumn(c,0); cr=laRightColumn(c,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    laUiItem* b=laBeginRow(uil,c,0,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    laShowNodeSocket(uil,c,This,"in",0)->Flags|=LA_UI_SOCKET_LABEL_E; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    laShowNodeSocket(uil,c,This,"in_amp",0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    laShowItem(uil,c,This,"amp")->Expand=1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    laShowNodeSocket(uil,cr,This,"out",0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     laEndRow(uil,b); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    b=laBeginRow(uil,cr,0,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    laShowSeparator(uil,cr)->Expand=1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    laShowNodeSocket(uil,cr,This,"out",0)->Flags|=LA_UI_SOCKET_LABEL_W; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void IDN_ScopeInit(laSynthNodeScope* n, int NoCreate){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if(!n->Display1){ n->Display1=memAcquireSimple(sizeof(real)*LA_SYNTH_PLEN*2); } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if(!n->Display2){ n->Display2=memAcquireSimple(sizeof(real)*LA_SYNTH_PLEN*2); } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    pthread_spin_init(&n->Lock,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if(NoCreate){ return; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    n->In1=laCreateInSocket("CH1",0); n->In2=laCreateInSocket("CH2",0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    strSafeSet(&n->Base.Name,"SCOPE"); n->Time=5; n->Brightness1=1.0f; n->Brightness2=0.5f; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    n->Gain1=1; n->Gain2=1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void IDN_ScopeDestroy(laSynthNodeScope* n){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    laDestroyInSocket(n->In1); laDestroyOutSocket(n->In2); strSafeDestroy(&n->Base.Name); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    memFree(n->Display1); memFree(n->Display2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    pthread_spin_destroy(&n->Lock); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+int IDN_ScopeVisit(laSynthNodeScope* n, laNodeVisitInfo* vi){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if(LA_SRC_AND_PARENT(n->In1)){ laBaseNode*bn=n->In1->Source->Parent; LA_VISIT_NODE(bn,vi); } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if(LA_SRC_AND_PARENT(n->In2)){ laBaseNode*bn=n->In2->Source->Parent; LA_VISIT_NODE(bn,vi); } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    LA_ADD_THIS_NODE(n,vi); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return LA_DAG_FLAG_PERM; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+int IDN_ScopeEval(laSynthNodeScope* n){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if(!n->Display1){ n->Display1=memAcquireSimple(sizeof(real)*LA_SYNTH_PLEN*2); } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if(!n->Display2){ n->Display2=memAcquireSimple(sizeof(real)*LA_SYNTH_PLEN*2); } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    real* ch1,*ch2; INPUTPACKET(ch1,n->In1); INPUTPACKET(ch2,n->In2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    int Frame=1<<(n->Time-1); TNS_CLAMP(Frame,1,LA_SYNTH_PLEN); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    int Times=LA_SYNTH_PLEN/Frame; int sp=0; pthread_spin_lock(&n->Lock); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for(int t=0;t<Times;t++){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        real smin1=FLT_MAX,smax1=-FLT_MAX,smin2=FLT_MAX,smax2=-FLT_MAX; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for(int i=0;i<Frame;i++){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if(ch1){ smin1=TNS_MIN2(smin1,ch1[sp]); smax1=TNS_MAX2(smax1,ch1[sp]); } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if(ch2){ smin2=TNS_MIN2(smin2,ch2[sp]); smax2=TNS_MAX2(smax2,ch2[sp]); } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            sp++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if(!ch1){smin1=smax1=0;} if(!ch2){smin2=smax2=0;} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        int ns=n->NextSample; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        n->Display1[ns]=smin1; n->Display1[ns+LA_SYNTH_PLEN]=smax1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        n->Display2[ns]=smin2; n->Display2[ns+LA_SYNTH_PLEN]=smax2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        n->NextSample++; if(n->NextSample>=LA_SYNTH_PLEN) n->NextSample=0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    n->FromSynth=MAIN.Audio->AudioEvalSynth; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    pthread_spin_unlock(&n->Lock); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void IDN_ScopeCopy(laSynthNodeScope* new, laSynthNodeScope* old, int DoRematch){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if(DoRematch){ LA_IDN_NEW_LINK(In1)  LA_IDN_NEW_LINK(In2) return; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    new->Brightness1=old->Brightness1; new->Brightness2=old->Brightness2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    new->Gain1=old->Gain1; new->Gain2=old->Gain2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    new->Offset1=old->Offset1; new->Offset2=old->Offset2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    new->Time=old->Time; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void laui_ScopeNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    laColumn* c=laFirstColumn(uil); laSynthNodeScope*n=This->EndInstance; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    LA_BASE_NODE_HEADER(uil,c,This); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    laColumn* cl,*cr; laSplitColumn(uil,c,0.5); cl=laLeftColumn(c,0); cr=laRightColumn(c,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    laUiItem* b=laBeginRow(uil,c,0,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    laShowNodeSocket(uil,c,This,"in1",0)->Flags|=LA_UI_SOCKET_LABEL_E; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    laUiItem* u=laShowItem(uil,c,This,"gain1");u->Flags|=LA_UI_FLAGS_EXPAND; u->Expand=1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     laEndRow(uil,b); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    b=laBeginRow(uil,c,0,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    laShowNodeSocket(uil,c,This,"in2",0)->Flags|=LA_UI_SOCKET_LABEL_E; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    u=laShowItem(uil,c,This,"gain2");u->Flags|=LA_UI_FLAGS_EXPAND; u->Expand=1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    laEndRow(uil,b); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    laShowItem(uil,c,This,"scope")->Extra->HeightCoeff=6; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    laShowLabel(uil,cl,"CH1",0,0)->Flags|=LA_TEXT_ALIGN_CENTER; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    laShowItem(uil,cl,This,"bright1"); laShowItem(uil,cl,This,"offset1"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    laShowLabel(uil,cr,"CH2",0,0)->Flags|=LA_TEXT_ALIGN_CENTER; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    laShowItem(uil,cr,This,"bright2"); laShowItem(uil,cr,This,"offset2"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    laShowItem(uil,c,This,"time")->Flags|=LA_UI_FLAGS_EXPAND; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 void IDN_OutputInit(laSynthNodeOutput* n, int NoCreate){ 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -116,7 +237,7 @@ int IDN_OutputEval(laSynthNodeOutput* n){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 void IDN_OutputCopy(laSynthNodeOutput* new, laSynthNodeOutput* old, int DoRematch){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if(DoRematch){ LA_IDN_NEW_LINK(In) return; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void la_OutputNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void laui_OutputNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     laColumn* c=laFirstColumn(uil); laSynthNodeOutput*n=This->EndInstance; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     LA_BASE_NODE_HEADER(uil,c,This); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     laColumn* cl,*cr; laSplitColumn(uil,c,0.3); cl=laLeftColumn(c,0); cr=laRightColumn(c,0); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -327,7 +448,7 @@ void* laget_FirstSynth(void* unused1,void* unused2){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 void lapost_Synth(laSynth* ss){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     pthread_spin_init(&ss->Lock,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-int laget_Playing(laSynth* ss){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+int laget_SynthPlaying(laSynth* ss){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     int play=0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     pthread_spin_lock(&ss->Lock); play=ss->Playing; pthread_spin_unlock(&ss->Lock); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return play; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -362,31 +483,69 @@ void laInitAudio(){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         LA_PC_SYNTH=pc; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         laAddStringProperty(pc,"name","Name","Name of the synthesizer",0,0,0,0,1,offsetof(laSynth,Name),0,0,0,0,LA_AS_IDENTIFIER); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         laAddSubGroup(pc, "page", "Page", "Rack page","la_rack_page",0,0,0,offsetof(laSynth,Page),0,0,0,0,0,0,0,LA_UDF_SINGLE|LA_HIDE_IN_SAVE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        p=laAddEnumProperty(pc,"playing","Playing","Synth is playing",0,0,0,0,0,-1,laget_Playing,0,0,0,0,0,0,0,0,LA_READ_ONLY); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        p=laAddEnumProperty(pc,"playing","Playing","Synth is playing",0,0,0,0,0,-1,laget_SynthPlaying,0,0,0,0,0,0,0,0,LA_READ_ONLY); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         laAddEnumItemAs(p,"IDLE","Idle","Synth is not playing",0,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         laAddEnumItemAs(p,"PLAYING","Playing","Synth is playing",1,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         laAddOperatorProperty(pc,"remove_synth","Remove Synth", "Remove synth", "LA_remove_synth", L'🗴', 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         laAddOperatorProperty(pc,"play","Play Synth", "Play synth", "LA_synth_play", 0, 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    pc=laAddPropertyContainer("la_node_synth_fm", "FM OSC Node", "Osilliator node with frequency modulation",0,la_FMNode,sizeof(laSynthNodeFM),lapost_Node,0,1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    pc=laAddPropertyContainer("la_node_synth_fm", "FM OSC Node", "Osilliator node with frequency modulation",0,laui_FMNode,sizeof(laSynthNodeFM),lapost_Node,0,1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     LA_PC_IDN_FM=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_frequency", "In Frequency","Input frequency","la_in_socket",0,0,0,offsetof(laSynthNodeFM,InFrequency),0,0,0,0,0,0,0,LA_UDF_SINGLE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     laAddSubGroup(pc,"out", "Out","Output","la_out_socket",0,0,0,offsetof(laSynthNodeFM,Out),0,0,0,0,0,0,0,LA_UDF_SINGLE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     laAddFloatProperty(pc,"frequency","Frequency","Frequency of the oscilliator",0,0,0,10,0,0.1,0,0,offsetof(laSynthNodeFM,Frequency),0,0,0,0,0,0,0,0,0,0,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    p=laAddEnumProperty(pc,"slow","Slow","Low frequency oscilliator",LA_WIDGET_ENUM_HIGHLIGHT,0,0,0,0,offsetof(laSynthNodeFM,Slow),0,0,0,0,0,0,0,0,0,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    laAddEnumItemAs(p,"NONE","None","Regular frequency range",0,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    laAddEnumItemAs(p,"SLOW","Slow","Slow frequency range",1,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    pc=laAddPropertyContainer("la_node_synth_output", "Output Node", "Sound output to system",0,la_OutputNode,sizeof(laSynthNodeOutput),lapost_Node,0,1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    pc=laAddPropertyContainer("la_node_synth_vca", "VCA Node", "Voltage controlled amplifier",0,laui_VCANode,sizeof(laSynthNodeVCA),lapost_Node,0,1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    LA_PC_IDN_VCA=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_amp", "In Amptitude","Input amptitude","la_in_socket",0,0,0,offsetof(laSynthNodeVCA,InAmp),0,0,0,0,0,0,0,LA_UDF_SINGLE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    laAddSubGroup(pc,"in", "Input","Input","la_in_socket",0,0,0,offsetof(laSynthNodeVCA,In),0,0,0,0,0,0,0,LA_UDF_SINGLE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    laAddSubGroup(pc,"out", "Out","Output","la_out_socket",0,0,0,offsetof(laSynthNodeVCA,Out),0,0,0,0,0,0,0,LA_UDF_SINGLE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    laAddFloatProperty(pc,"amp","Amptitude","Amptitude of the output signal",0,0,0,10,0,0.1,0,0,offsetof(laSynthNodeVCA,Amp),0,0,0,0,0,0,0,0,0,0,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    pc=laAddPropertyContainer("la_node_synth_scope", "Scope Node", "Scope for synthesizer",0,laui_ScopeNode,sizeof(laSynthNodeScope),lapost_Node,0,1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    LA_PC_IDN_SCOPE=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,"scope", "Scope","Synth scope","la_node_synth_scope",0,LA_WIDGET_SCOPE,0,-1,0,laget_InstanceSelf,0,0,0,0,0,LA_UDF_REFER|LA_UDF_IGNORE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    laAddSubGroup(pc,"in1", "In 1","Input Channel 1","la_in_socket",0,0,0,offsetof(laSynthNodeScope,In1),0,0,0,0,0,0,0,LA_UDF_SINGLE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    laAddSubGroup(pc,"in2", "In 2","Input Channel 2","la_in_socket",0,0,0,offsetof(laSynthNodeScope,In2),0,0,0,0,0,0,0,LA_UDF_SINGLE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    p=laAddEnumProperty(pc,"time","Time","Time factor of the scope",0,0,0,5,0,offsetof(laSynthNodeScope,Time),0,0,0,0,0,0,0,0,0,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define _STR(a) #a 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define ADD_TIME_FACTOR(a) laAddEnumItemAs(p,"FAC"_STR(a),_STR(a),"^"_STR(a)" time",a,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ADD_TIME_FACTOR(1) ADD_TIME_FACTOR(2) ADD_TIME_FACTOR(3) ADD_TIME_FACTOR(4) ADD_TIME_FACTOR(5) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ADD_TIME_FACTOR(6) ADD_TIME_FACTOR(7) ADD_TIME_FACTOR(8) ADD_TIME_FACTOR(9) ADD_TIME_FACTOR(10) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#undef ADD_TIME_FACTOR 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    p=laAddEnumProperty(pc,"gain1","Gain 1","Channel 1 Gain",0,0,0,5,0,offsetof(laSynthNodeScope,Gain1),0,0,0,0,0,0,0,0,0,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define ADD_GAIN(a) laAddEnumItemAs(p,"GAIN"_STR(a),_STR(a),"^"_STR(a)" gain",a,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ADD_GAIN(1) ADD_GAIN(2) ADD_GAIN(3) ADD_GAIN(4) ADD_GAIN(5) ADD_GAIN(6) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    p=laAddEnumProperty(pc,"gain2","Gain 2","Channel 2 Gain",0,0,0,5,0,offsetof(laSynthNodeScope,Gain2),0,0,0,0,0,0,0,0,0,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ADD_GAIN(1) ADD_GAIN(2) ADD_GAIN(3) ADD_GAIN(4) ADD_GAIN(5) ADD_GAIN(6) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#undef ADD_GAIN 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    laAddFloatProperty(pc,"offset1","Offset 1","Channel 1 offset",0,0,0,10,-10,0.1,0,0,offsetof(laSynthNodeScope,Offset1),0,0,0,0,0,0,0,0,0,0,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    laAddFloatProperty(pc,"offset2","Offset 2","Channel 2 offset",0,0,0,10,-10,0.1,0,0,offsetof(laSynthNodeScope,Offset2),0,0,0,0,0,0,0,0,0,0,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    laAddFloatProperty(pc,"bright1","Brightness 1","Channel 1 brightness",0,0,0,1,0,0.1,0,0,offsetof(laSynthNodeScope,Brightness1),0,0,0,0,0,0,0,0,0,0,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    laAddFloatProperty(pc,"bright2","Brightness 2","Channel 2 brightness",0,0,0,1,0,0.1,0,0,offsetof(laSynthNodeScope,Brightness2),0,0,0,0,0,0,0,0,0,0,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    pc=laAddPropertyContainer("la_node_synth_output", "Output Node", "Sound output to system",0,laui_OutputNode,sizeof(laSynthNodeOutput),lapost_Node,0,1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     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); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     LA_IDN_REGISTER("VCO",'f',LA_IDN_FM, LA_PC_IDN_FM, IDN_FM, laSynthNodeFM); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    LA_IDN_REGISTER("VCA",'a',LA_IDN_VCA, LA_PC_IDN_VCA, IDN_VCA, laSynthNodeVCA); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    LA_IDN_REGISTER("Scope",'s',LA_IDN_SCOPE, LA_PC_IDN_SCOPE, IDN_Scope, laSynthNodeScope); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     LA_IDN_REGISTER("Sound Output",U'🕪',LA_IDN_OUTPUT, LA_PC_IDN_OUTPUT, IDN_Output, laSynthNodeOutput); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     LA_NODE_CATEGORY_SYNTHESIZER=laAddNodeCategory("OSC",0,LA_RACK_TYPE_AUDIO); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     LA_NODE_CATEGORY_SYSTEM_SOUND=laAddNodeCategory("System",0,LA_RACK_TYPE_AUDIO); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_SYNTHESIZER, &LA_IDN_FM,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_SYNTHESIZER, &LA_IDN_VCA,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_SYNTHESIZER, &LA_IDN_SCOPE,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_SYSTEM_SOUND, &LA_IDN_OUTPUT,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 |