*/}}
YimingWu 9 mesi fa
parent
commit
fe356822c3
4 ha cambiato i file con 79 aggiunte e 10 eliminazioni
  1. 66 6
      la_audio.c
  2. 11 1
      la_interface.h
  3. 2 2
      la_kernel.c
  4. 0 1
      resources/la_tns_drivers.c

+ 66 - 6
la_audio.c

@@ -29,6 +29,7 @@ laPropContainer* LA_PC_CHANNEL;
 laNodeCategory* LA_NODE_CATEGORY_SYNTHESIZER;
 laNodeCategory* LA_NODE_CATEGORY_SYSTEM_SOUND;
 
+laBaseNodeType LA_IDN_INPUT;
 laBaseNodeType LA_IDN_FM;
 laBaseNodeType LA_IDN_VCA;
 laBaseNodeType LA_IDN_NOISE;
@@ -37,6 +38,7 @@ laBaseNodeType LA_IDN_SCOPE;
 laBaseNodeType LA_IDN_ENVELOPE;
 laBaseNodeType LA_IDN_QUANTIZE;
 
+laPropContainer* LA_PC_IDN_INPUT;
 laPropContainer* LA_PC_IDN_FM;
 laPropContainer* LA_PC_IDN_VCA;
 laPropContainer* LA_PC_IDN_NOISE;
@@ -69,6 +71,47 @@ laPropContainer* LA_PC_IDN_QUANTIZE;
 
 #define SAMPLE_RATE (MAIN.Audio->AudioSampleRate)
 
+void IDN_InputInit(laSynthNodeInput* n, int NoCreate){
+    INITPACKET(n->rTime); INITPACKET(n->rTrigger);
+    if(NoCreate){ return; }
+    n->OutTime=laCreateOutSocket(n,"TIME",LA_PROP_FLOAT|LA_PROP_ARRAY);
+    n->OutTrigger=laCreateOutSocket(n,"TRIGGER",LA_PROP_FLOAT|LA_PROP_ARRAY);
+    strSafeSet(&n->Base.Name,"Input");
+}
+void IDN_InputDestroy(laSynthNodeInput* n){
+    laDestroyOutSocket(n->OutTime); laDestroyOutSocket(n->OutTrigger); strSafeDestroy(&n->Base.Name); memFree(n->rTime); memFree(n->rTrigger);
+}
+int IDN_InputVisit(laSynthNodeInput* n, laNodeVisitInfo* vi){
+    LA_GUARD_THIS_NODE(n,vi);
+    LA_ADD_THIS_NODE(n,vi);
+    return LA_DAG_FLAG_PERM;
+}
+int IDN_InputEval(laSynthNodeInput* n){
+    laSynth*ss=MAIN.Audio->AudioEvalSynth;
+    real time=ss->EvalTime,target_time=time+(real)LA_SYNTH_PLEN/(real)MAIN.Audio->AudioSampleRate;
+    for(int i=0;i<LA_SYNTH_PLEN;i++){
+        real fac=(real)i/(real)LA_SYNTH_PLEN;
+        n->rTime[i] = tnsLinearItp(time,target_time,fac);
+    }
+    if(ss->EvalSamples==0){ n->rTrigger[0] = 10; }else{ n->rTrigger[0]=0; }
+    n->OutTime->Data=n->rTime; n->OutTrigger->Data=n->rTrigger; n->OutTime->ArrLen=LA_SYNTH_PLEN; n->OutTrigger->ArrLen=LA_SYNTH_PLEN;
+    return 1;
+}
+void IDN_InputCopy(laSynthNodeInput* new, laSynthNodeInput* old, int DoRematch){
+    if(DoRematch){ return; }
+    LA_IDN_OLD_DUPL(OutTime); LA_IDN_OLD_DUPL(OutTrigger);
+}
+void laui_InputNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
+    laColumn* c=laFirstColumn(uil); laSynthNodeInput*n=This->EndInstance;
+    LA_BASE_NODE_HEADER(uil,c,This);
+
+    laUiItem* b=laBeginRow(uil,c,0,0);
+    laUiItem* ui=laShowLabel(uil,c,"Synth",0,0); ui->Expand=1; ui->Flags|=LA_TEXT_ALIGN_RIGHT;
+    laShowNodeSocket(uil,c,This,"out_time",0)->Flags|=LA_UI_SOCKET_LABEL_E;
+    laShowNodeSocket(uil,c,This,"out_trigger",0)->Flags|=LA_UI_SOCKET_LABEL_E;
+    laEndRow(uil,b);
+}
+
 void IDN_FMInit(laSynthNodeFM* n, int NoCreate){
     INITPACKET(n->OutSamples);
     if(NoCreate){ return; }
@@ -138,7 +181,7 @@ int IDN_VCAEval(laSynthNodeVCA* n){
     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]*n->rInfluence/10):1)*constamp;
+        real useA= inputamp?tnsInterpolate(1.0f,inputamp[i]/10.0f,n->rInfluence)*constamp:constamp;
         n->OutSamples[i]= input[i]*useA;
     }
     return 1;
@@ -340,6 +383,7 @@ void IDN_EnvelopeInit(laSynthNodeEnvelope* n, int NoCreate){
         n->Time=20; n->rAttack=1; n->rDelay=5; n->rSustain=5; n->rRelease=7; n->rGate=5;
     }
     if(!n->Gate){ n->Gate=laCreateInSocket("GATE",0); }
+    if(!n->Restart){ n->Restart=laCreateInSocket("RESTART",0); }
     if(!n->OutSamples){ n->OutSamples=memAcquireSimple(sizeof(real)*LA_SYNTH_PLEN); }
     n->Out->Data = n->OutSamples; n->Out->DataType = LA_PROP_FLOAT|LA_PROP_ARRAY; n->Out->ArrLen=LA_SYNTH_PLEN;
 }
@@ -357,12 +401,14 @@ int IDN_EnvelopeVisit(laSynthNodeEnvelope* n, laNodeVisitInfo* vi){
     if(LA_SRC_AND_PARENT(n->Sustain)){ laBaseNode*bn=n->Sustain->Source->Parent; LA_VISIT_NODE(bn,vi); }
     if(LA_SRC_AND_PARENT(n->Release)){ laBaseNode*bn=n->Release->Source->Parent; LA_VISIT_NODE(bn,vi); }
     if(LA_SRC_AND_PARENT(n->Trigger)){ laBaseNode*bn=n->Trigger->Source->Parent; LA_VISIT_NODE(bn,vi); }
+    if(LA_SRC_AND_PARENT(n->Restart)){ laBaseNode*bn=n->Restart->Source->Parent; LA_VISIT_NODE(bn,vi); }
     LA_ADD_THIS_NODE(n,vi);
     return LA_DAG_FLAG_PERM;
 }
 int IDN_EnvelopeEval(laSynthNodeEnvelope* n){
-    int trigger_at=-1; real trig=n->bTrigger?n->bTrigger*100:-100;
+    int trigger_at=-1; real trig=n->bTrigger?n->bTrigger*100:-100; real res=0;
     real* trigger; INPUTPACKET(trigger,n->Trigger); if(!trigger){ LA_GET_SRC_AS_VALUE(trig,n->Trigger); }
+    real* restart; INPUTPACKET(restart,n->Restart); if(!restart){ LA_GET_SRC_AS_VALUE(res,n->Restart); }
     real *att,*del,*sus,*rel,*gat;
     real attack=n->rAttack,delay=n->rDelay,sustain=n->rSustain,release=n->rRelease;
     real gate = n->rGate; INPUTPACKET(gat,n->Gate); if(!gat) LA_GET_SRC_AS_VALUE(gate,n->Gate);
@@ -372,11 +418,12 @@ int IDN_EnvelopeEval(laSynthNodeEnvelope* n){
     INPUTPACKET(rel,n->Release); if(!rel) LA_GET_SRC_AS_VALUE(release,n->Release);
     attack=attack?pow(attack/10,2):0; delay=delay?pow(delay/10,2):0; release=release?pow(release/10,2):0;
     for(int i=0;i<LA_SYNTH_PLEN;i++){
-        if(trigger){ trig=trigger[i]; } if(gat){ gate=gat[i]; }
+        if(trigger){ trig=trigger[i]; } if(gat){ gate=gat[i]; } if(restart){ res=restart[i]; }
         if(att){ attack=att[i]*n->iAttack+n->rAttack; }
         if(del){ delay=del[i]*n->iDelay+n->rDelay; }
         if(sus){ sustain=sus[i]*n->iSustain+n->rSustain; }
         if(rel){ release=rel[i]*n->iRelease+n->rRelease; }
+        if(res){ n->Time=0; n->ReleaseTime=-10000; n->Triggered=0;}
         if(!n->Triggered){ if(trig > gate){ n->Triggered = 1; n->Time = 0; n->ReleaseTime=10000; n->AtLevel=0; } }
         else{ if(trig < gate-0.0001f){ n->Triggered = 0; n->ReleaseTime = n->Time; } }
         if(n->Time < n->ReleaseTime){
@@ -430,6 +477,7 @@ void laui_EnvelopeNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laCol
     laEndRow(uil,b);
     b=laBeginRow(uil,c,0,0);
     laShowSeparator(uil,c)->Expand=1; 
+    laShowItem(uil,c,This,"in_restart")->Flags|=LA_UI_SOCKET_LABEL_E;
     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);
@@ -521,8 +569,10 @@ int laEvalSynthGraphs(){
     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;
+        MAIN.Audio->AudioEvalSynth=ss;
         laRunPage(ss->Page,1);
+        ss->EvalSamples += LA_SYNTH_PLEN;
+        ss->EvalTime = (real)ss->EvalSamples/MAIN.Audio->AudioSampleRate;
         laSpinUnlock(&ss->Lock);
         any=1;
     }
@@ -677,7 +727,9 @@ int OPINV_laSynthPlay(laOperator* a, laEvent* e){
 
     laRebuildPageEval(ss->Page);
 
-    laSpinLock(&ss->Lock); ss->Playing=play; laSpinUnlock(&ss->Lock);
+    laSpinLock(&ss->Lock);
+    ss->Playing=play; if(!play){ ss->EvalSamples=0; ss->EvalTime=0; }
+    laSpinUnlock(&ss->Lock);
     
     ma_device_start(&MAIN.Audio->AudioDevice); laNotifyInstanceUsers(ss);
     return LA_FINISHED;
@@ -890,6 +942,12 @@ void laInitAudio(){
         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);
     }
 
+    pc=laAddPropertyContainer("la_node_synth_input", "Synth Input Node", "Synthesizer time and trigger input",0,laui_InputNode,sizeof(laSynthNodeInput),lapost_Node,0,1);
+    LA_PC_IDN_INPUT=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_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_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);
@@ -957,6 +1015,7 @@ void laInitAudio(){
     laAddSubGroup(pc,"in_sustain", "Sustain","Sustain input","la_in_socket",0,0,0,offsetof(laSynthNodeEnvelope,Sustain),0,0,0,0,0,0,0,LA_UDF_SINGLE);
     laAddSubGroup(pc,"in_release", "Release","Release input","la_in_socket",0,0,0,offsetof(laSynthNodeEnvelope,Release),0,0,0,0,0,0,0,LA_UDF_SINGLE);
     laAddSubGroup(pc,"in_trigger", "Trigger","Trigger input","la_in_socket",0,0,0,offsetof(laSynthNodeEnvelope,Trigger),0,0,0,0,0,0,0,LA_UDF_SINGLE);
+    laAddSubGroup(pc,"in_restart", "Restart","Restart input","la_in_socket",0,0,0,offsetof(laSynthNodeEnvelope,Restart),0,0,0,0,0,0,0,LA_UDF_SINGLE);
     laAddSubGroup(pc,"out", "Output","Envelope output","la_out_socket",0,0,0,offsetof(laSynthNodeEnvelope,Out),0,0,0,0,0,0,0,LA_UDF_SINGLE);
     laAddFloatProperty(pc,"gate","Gate","Gate for the trigger",0,0,0,10,-10,0.01,0,0,offsetof(laSynthNodeEnvelope,rGate),0,0,0,0,0,0,0,0,0,0,0);
     laAddFloatProperty(pc,"attack","Attack","Attack value",0,0,0,10,0,0.01,0,0,offsetof(laSynthNodeEnvelope,rAttack),0,0,0,0,0,0,0,0,0,0,0);
@@ -981,6 +1040,7 @@ void laInitAudio(){
     laAddEnumItemAs(p,"ENABLED","Enabled","Key is enabled",1,' ');
     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("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);
@@ -992,7 +1052,7 @@ void laInitAudio(){
     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,&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_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);
 }
 

+ 11 - 1
la_interface.h

@@ -1813,7 +1813,16 @@ STRUCTURE(laSynth){
 
     SYSLOCK Lock;
     int Playing;
-    real AudioEvalTime;
+    real EvalTime;
+    int EvalSamples;
+};
+
+STRUCTURE(laSynthNodeInput){
+    laBaseNode Base;
+    laNodeOutSocket* OutTime;
+    laNodeOutSocket* OutTrigger;
+    real* rTime;
+    real* rTrigger;
 };
 
 STRUCTURE(laSynthNodeFM){
@@ -1874,6 +1883,7 @@ STRUCTURE(laSynthNodeOutput){
 STRUCTURE(laSynthNodeEnvelope){
     laBaseNode Base;
     laNodeInSocket* Trigger,*Gate; real rGate; int bTrigger; int Triggered;
+    laNodeInSocket* Restart;
     laNodeInSocket* Attack;  real rAttack,iAttack;
     laNodeInSocket* Delay;   real rDelay,iDelay;
     laNodeInSocket* Sustain; real rSustain,iSustain;

+ 2 - 2
la_kernel.c

@@ -5926,8 +5926,8 @@ void la_SendWireVerts(real x1, real y1, real x2, real y2, real circle_r){
     v1[0]=x1; v1[1]=y1; v2[0]=x2; v2[1]=y2;
     tnsInterpolate2dv(v1,v2,0.5,vi);
     if(MAIN.WireSaggyness>0.01){ dist=tnsDist2dv(v1,v2); vi[1]+=dist*MAIN.WireSaggyness; }
-    tnsVectorMinus2d(v1s,vi,v1); tnsNormalizeSelf2d(v1s); tnsVectorMultiSelf2d(v1s,circle_r);
-    tnsVectorMinus2d(v2s,vi,v2); tnsNormalizeSelf2d(v2s); tnsVectorMultiSelf2d(v2s,circle_r);
+    tnsVectorMinus2d(v1s,vi,v1); if(tnsLength2d(v1s)<1e-3){ v1s[0]=-1; v1s[1]=0; }else{ tnsNormalizeSelf2d(v1s); } tnsVectorMultiSelf2d(v1s,circle_r);
+    tnsVectorMinus2d(v2s,vi,v2); if(tnsLength2d(v2s)<1e-3){ v2s[0]=1; v2s[1]=0; }else{ tnsNormalizeSelf2d(v2s); } tnsVectorMultiSelf2d(v2s,circle_r);
     tnsVectorAccum2d(v1, v1s); tnsVectorAccum2d(v2, v2s);
 
     if(MAIN.WireSaggyness<0.01){ tnsVertex2d(v1[0],v1[1]); tnsVertex2d(v2[0],v2[1]); return; }

+ 0 - 1
resources/la_tns_drivers.c

@@ -143,7 +143,6 @@ void tnsui_MakeTransformNode(laUiList *uil, laPropPack *This, laPropPack *Extra,
     laEndRow(uil,b);
 }
 
-
 void IDN_ActionPlayerInit(tnsActionPlayerNode* n, int NoCreate){
     if(NoCreate){ return; }
     strSafeSet(&n->Base.Name,"Make Transform");