|  | @@ -30,6 +30,7 @@ laNodeCategory* LA_NODE_CATEGORY_SYNTHESIZER;
 | 
	
		
			
				|  |  |  laNodeCategory* LA_NODE_CATEGORY_SYSTEM_SOUND;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  laBaseNodeType LA_IDN_INPUT;
 | 
	
		
			
				|  |  | +laBaseNodeType LA_IDN_PULSE;
 | 
	
		
			
				|  |  |  laBaseNodeType LA_IDN_FM;
 | 
	
		
			
				|  |  |  laBaseNodeType LA_IDN_VCA;
 | 
	
		
			
				|  |  |  laBaseNodeType LA_IDN_NOISE;
 | 
	
	
		
			
				|  | @@ -40,6 +41,7 @@ laBaseNodeType LA_IDN_QUANTIZE;
 | 
	
		
			
				|  |  |  laBaseNodeType LA_IDN_SYNTH_DRIVER;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  laPropContainer* LA_PC_IDN_INPUT;
 | 
	
		
			
				|  |  | +laPropContainer* LA_PC_IDN_PULSE;
 | 
	
		
			
				|  |  |  laPropContainer* LA_PC_IDN_FM;
 | 
	
		
			
				|  |  |  laPropContainer* LA_PC_IDN_VCA;
 | 
	
		
			
				|  |  |  laPropContainer* LA_PC_IDN_NOISE;
 | 
	
	
		
			
				|  | @@ -114,6 +116,73 @@ void laui_InputNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn
 | 
	
		
			
				|  |  |      laEndRow(uil,b);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +void IDN_PulseInit(laSynthNodePulse* n, int NoCreate){
 | 
	
		
			
				|  |  | +    INITPACKET(n->rOut);
 | 
	
		
			
				|  |  | +    if(NoCreate){ return; }
 | 
	
		
			
				|  |  | +    n->InTrigger = laCreateInSocket("TRIGGER",0);
 | 
	
		
			
				|  |  | +    n->InWidth = laCreateInSocket("WIDTH",0);
 | 
	
		
			
				|  |  | +    n->InGate = laCreateInSocket("GATE",0);
 | 
	
		
			
				|  |  | +    n->Out=laCreateOutSocket(n,"OUT",LA_PROP_FLOAT|LA_PROP_ARRAY);
 | 
	
		
			
				|  |  | +    strSafeSet(&n->Base.Name,"Pulse");
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void IDN_PulseDestroy(laSynthNodePulse* n){
 | 
	
		
			
				|  |  | +    laDestroyOutSocket(n->Out); laDestroyInSocket(n->InWidth); laDestroyInSocket(n->InTrigger); laDestroyInSocket(n->InGate);
 | 
	
		
			
				|  |  | +    strSafeDestroy(&n->Base.Name); memFree(n->rOut);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +int IDN_PulseVisit(laSynthNodePulse* n, laNodeVisitInfo* vi){
 | 
	
		
			
				|  |  | +    LA_GUARD_THIS_NODE(n,vi);
 | 
	
		
			
				|  |  | +    if(LA_SRC_AND_PARENT(n->InTrigger)){ laBaseNode*bn=n->InTrigger->Source->Parent; LA_VISIT_NODE(bn,vi); }
 | 
	
		
			
				|  |  | +    if(LA_SRC_AND_PARENT(n->InWidth)){ laBaseNode*bn=n->InWidth->Source->Parent; LA_VISIT_NODE(bn,vi); }
 | 
	
		
			
				|  |  | +    if(LA_SRC_AND_PARENT(n->InGate)){ laBaseNode*bn=n->InGate->Source->Parent; LA_VISIT_NODE(bn,vi); }
 | 
	
		
			
				|  |  | +    n->Out->Data = n->rOut; n->Out->ArrLen=LA_SYNTH_PLEN;
 | 
	
		
			
				|  |  | +    LA_ADD_THIS_NODE(n,vi);
 | 
	
		
			
				|  |  | +    return LA_DAG_FLAG_PERM;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +int IDN_PulseEval(laSynthNodePulse* n){
 | 
	
		
			
				|  |  | +    laSynth*ss=MAIN.Audio->AudioEvalSynth;
 | 
	
		
			
				|  |  | +    real* trigger=0; real trig=n->iTrigger?100:-100; INPUTPACKET(trigger,n->InTrigger); LA_GET_SRC_AS_VALUE(trig,n->InTrigger);
 | 
	
		
			
				|  |  | +    real* gate=0; real gt=n->rGate; INPUTPACKET(gate,n->InGate); LA_GET_SRC_AS_VALUE(gt,n->InGate);
 | 
	
		
			
				|  |  | +    real* width=0; real w=n->rWidth; INPUTPACKET(width,n->InWidth);
 | 
	
		
			
				|  |  | +    real wi=0; LA_GET_SRC_AS_VALUE(wi,n->InWidth); if(!width){ w=n->rWidth+wi*n->rInfluence; }
 | 
	
		
			
				|  |  | +    for(int i=0;i<LA_SYNTH_PLEN;i++){
 | 
	
		
			
				|  |  | +        if(trigger){ trig=trigger[i]; } if(gate){ gt=gate[i]; } if(width){ w=n->rWidth+width[i]*n->rInfluence; }
 | 
	
		
			
				|  |  | +        if(!n->Triggered){ if(trig>gt){ n->Triggered=1; n->EvalSamples=1; } }
 | 
	
		
			
				|  |  | +        else{ if(trig<=gt){ n->Triggered=0; } }
 | 
	
		
			
				|  |  | +        int totalsamples=w*MAIN.Audio->AudioSampleRate;
 | 
	
		
			
				|  |  | +        if(n->EvalSamples) n->EvalSamples++;
 | 
	
		
			
				|  |  | +        n->rOut[i]= (n->Triggered || (n->EvalSamples > 0 && n->EvalSamples < totalsamples)) ? 10.0f : 0.0f;
 | 
	
		
			
				|  |  | +        if(n->EvalSamples > totalsamples && !n->Triggered){ n->EvalSamples=0; }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    return 1;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void IDN_PulseCopy(laSynthNodePulse* new, laSynthNodePulse* old, int DoRematch){
 | 
	
		
			
				|  |  | +    if(DoRematch){  LA_IDN_NEW_LINK(InTrigger); LA_IDN_NEW_LINK(InWidth); LA_IDN_NEW_LINK(InGate);  return; }
 | 
	
		
			
				|  |  | +    LA_IDN_OLD_DUPL(Out); new->rGate = old->rGate; new->rInfluence=old->rInfluence; new->rWidth=old->rWidth;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void laui_PulseNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
 | 
	
		
			
				|  |  | +    laColumn* c=laFirstColumn(uil); laSynthNodePulse*n=This->EndInstance;
 | 
	
		
			
				|  |  | +    LA_BASE_NODE_HEADER(uil,c,This);
 | 
	
		
			
				|  |  | +    laUiItem* b;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    b=laBeginRow(uil,c,0,0);
 | 
	
		
			
				|  |  | +    laShowNodeSocket(uil,c,This,"in_width",0)->Flags|=LA_UI_SOCKET_LABEL_W;
 | 
	
		
			
				|  |  | +    laShowItem(uil,c,This,"influence");
 | 
	
		
			
				|  |  | +    laShowItem(uil,c,This,"width")->Expand=1;
 | 
	
		
			
				|  |  | +    laEndRow(uil,b);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    b=laBeginRow(uil,c,0,0);
 | 
	
		
			
				|  |  | +    laShowItem(uil,c,This,"gate")->Expand=1;
 | 
	
		
			
				|  |  | +    laShowNodeSocket(uil,c,This,"in_gate",0)->Flags|=LA_UI_SOCKET_LABEL_W;
 | 
	
		
			
				|  |  | +    laShowNodeSocket(uil,c,This,"in_trigger",0)->Flags|=LA_UI_SOCKET_LABEL_E;
 | 
	
		
			
				|  |  | +    laEndRow(uil,b);
 | 
	
		
			
				|  |  | +    b=laBeginRow(uil,c,0,0);
 | 
	
		
			
				|  |  | +    laShowSeparator(uil,c)->Expand=1; 
 | 
	
		
			
				|  |  | +    laShowItem(uil,c,This,"trigger")->Flags|=LA_UI_FLAGS_MOMENTARY|LA_UI_FLAGS_HIGHLIGHT;
 | 
	
		
			
				|  |  | +    laShowItem(uil,c,This,"out")->Flags|=LA_UI_SOCKET_LABEL_W;
 | 
	
		
			
				|  |  | +    laEndRow(uil,b);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  void IDN_FMInit(laSynthNodeFM* n, int NoCreate){
 | 
	
		
			
				|  |  |      INITPACKET(n->OutSamples);
 | 
	
		
			
				|  |  |      if(NoCreate){ return; }
 | 
	
	
		
			
				|  | @@ -1107,6 +1176,20 @@ void laInitAudio(){
 | 
	
		
			
				|  |  |      laAddSubGroup(pc,"out_time", "Out Time","Time output","la_out_socket",0,0,0,offsetof(laSynthNodeInput,OutTime),0,0,0,0,0,0,0,LA_UDF_SINGLE);
 | 
	
		
			
				|  |  |      laAddSubGroup(pc,"out_trigger", "Out Trigger","Trigger output","la_out_socket",0,0,0,offsetof(laSynthNodeInput,OutTrigger),0,0,0,0,0,0,0,LA_UDF_SINGLE);
 | 
	
		
			
				|  |  |      
 | 
	
		
			
				|  |  | +    pc=laAddPropertyContainer("la_node_synth_pulse", "Synth Pulse Node", "Pulse generate node for synth",0,laui_PulseNode,sizeof(laSynthNodePulse),lapost_Node,0,1);
 | 
	
		
			
				|  |  | +    LA_PC_IDN_PULSE=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,"out", "Out","Pulse output","la_out_socket",0,0,0,offsetof(laSynthNodePulse,Out),0,0,0,0,0,0,0,LA_UDF_SINGLE);
 | 
	
		
			
				|  |  | +    laAddSubGroup(pc,"in_trigger", "In Trigger","Trigger input","la_in_socket",0,0,0,offsetof(laSynthNodePulse,InTrigger),0,0,0,0,0,0,0,LA_UDF_SINGLE);
 | 
	
		
			
				|  |  | +    laAddSubGroup(pc,"in_width", "In Width","Width input","la_in_socket",0,0,0,offsetof(laSynthNodePulse,InWidth),0,0,0,0,0,0,0,LA_UDF_SINGLE);
 | 
	
		
			
				|  |  | +    laAddSubGroup(pc,"in_gate", "In Gate","Gate input","la_in_socket",0,0,0,offsetof(laSynthNodePulse,InGate),0,0,0,0,0,0,0,LA_UDF_SINGLE);
 | 
	
		
			
				|  |  | +    laAddFloatProperty(pc,"influence","Influence","Influence of the width input",LA_WIDGET_KNOB,0,0,1,-1,0.01,0,0,offsetof(laSynthNodePulse,rInfluence),0,0,0,0,0,0,0,0,0,0,0);
 | 
	
		
			
				|  |  | +    laAddFloatProperty(pc,"width","Width","Width of the pulse",0,0,0,10,0,0.1,0,0,offsetof(laSynthNodePulse,rWidth),0,0,0,0,0,0,0,0,0,0,0);
 | 
	
		
			
				|  |  | +    laAddFloatProperty(pc,"gate","Gate","Gate of the trigger",0,0,0,10,-10,0.1,0,0,offsetof(laSynthNodePulse,rGate),0,0,0,0,0,0,0,0,0,0,0);
 | 
	
		
			
				|  |  | +    p=laAddEnumProperty(pc,"trigger","Trigger","Trigger the envelope",LA_WIDGET_ENUM_CYCLE,0,0,0,0,offsetof(laSynthNodePulse,iTrigger),0,0,0,0,0,0,0,0,0,0);
 | 
	
		
			
				|  |  | +    laAddEnumItemAs(p,"IDLE","Idle","Trigger idle",0,0);
 | 
	
		
			
				|  |  | +    laAddEnumItemAs(p,"TRIG","Trigger","Trigger active",1,0);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      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);
 | 
	
	
		
			
				|  | @@ -1189,7 +1272,6 @@ void laInitAudio(){
 | 
	
		
			
				|  |  |      laAddEnumItemAs(p,"IDLE","Idle","Trigger idle",0,0);
 | 
	
		
			
				|  |  |      laAddEnumItemAs(p,"TRIG","Trigger","Trigger active",1,0);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |      pc=laAddPropertyContainer("la_node_synth_driver", "Synth Driver Node", "Control playing status of the synth",0,laui_SynthDriverNode,sizeof(laSynthNodeDriver),lapost_Node,0,1);
 | 
	
		
			
				|  |  |      LA_PC_IDN_DRIVER=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);
 | 
	
	
		
			
				|  | @@ -1216,6 +1298,7 @@ void laInitAudio(){
 | 
	
		
			
				|  |  |      laAddEnumItemAs(p,"OUTPUT","Outputting","Key is Outputting",3,U'🌑');
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      LA_IDN_REGISTER("Inputs",U'🔌',LA_IDN_INPUT, LA_PC_IDN_INPUT, IDN_Input, laSynthNodeInput);
 | 
	
		
			
				|  |  | +    LA_IDN_REGISTER("Pulse",U'⎍',LA_IDN_PULSE, LA_PC_IDN_PULSE, IDN_Pulse, laSynthNodePulse);
 | 
	
		
			
				|  |  |      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("Noise",'~',LA_IDN_NOISE, LA_PC_IDN_NOISE, IDN_Noise, laSynthNodeNoise);
 | 
	
	
		
			
				|  | @@ -1228,13 +1311,10 @@ void laInitAudio(){
 | 
	
		
			
				|  |  |      LA_NODE_CATEGORY_SYNTHESIZER=laEnsureNodeCategory("OSC",0,LA_RACK_TYPE_AUDIO);
 | 
	
		
			
				|  |  |      LA_NODE_CATEGORY_SYSTEM_SOUND=laEnsureNodeCategory("System",0,LA_RACK_TYPE_AUDIO);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_SYNTHESIZER, &LA_IDN_INPUT,&LA_IDN_FM,&LA_IDN_NOISE,&LA_IDN_VCA,&LA_IDN_ENVELOPE,&LA_IDN_QUANTIZE,&LA_IDN_SCOPE,0);
 | 
	
		
			
				|  |  | +    laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_SYNTHESIZER,
 | 
	
		
			
				|  |  | +        &LA_IDN_INPUT,&LA_IDN_PULSE,&LA_IDN_FM,&LA_IDN_NOISE,&LA_IDN_VCA,&LA_IDN_ENVELOPE,&LA_IDN_QUANTIZE,&LA_IDN_SCOPE,0);
 | 
	
		
			
				|  |  |      laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_SYSTEM_SOUND, &LA_IDN_OUTPUT,0);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      LA_NODE_CATEGORY_DRIVER=laEnsureNodeCategory("Driver",0,LA_RACK_TYPE_DRIVER);
 | 
	
		
			
				|  |  |      laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_DRIVER, &LA_IDN_SYNTH_DRIVER,0);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -void laAudioDummy(){
 | 
	
		
			
				|  |  | -    return 0;
 | 
	
		
			
				|  |  | -}
 |