*/}}
Prechádzať zdrojové kódy

Noise generator and osc improvements

YimingWu 1 rok pred
rodič
commit
dc6a3b429b
3 zmenil súbory, kde vykonal 120 pridanie a 23 odobranie
  1. 71 8
      la_audio.c
  2. 11 0
      la_interface.h
  3. 38 15
      resources/la_widgets.c

+ 71 - 8
la_audio.c

@@ -29,11 +29,13 @@ laNodeCategory* LA_NODE_CATEGORY_SYSTEM_SOUND;
 
 laBaseNodeType LA_IDN_FM;
 laBaseNodeType LA_IDN_VCA;
+laBaseNodeType LA_IDN_NOISE;
 laBaseNodeType LA_IDN_OUTPUT;
 laBaseNodeType LA_IDN_SCOPE;
 
 laPropContainer* LA_PC_IDN_FM;
 laPropContainer* LA_PC_IDN_VCA;
+laPropContainer* LA_PC_IDN_NOISE;
 laPropContainer* LA_PC_IDN_OUTPUT;
 laPropContainer* LA_PC_IDN_SCOPE;
 
@@ -63,6 +65,7 @@ void IDN_FMDestroy(laSynthNodeFM* n){
     laDestroyInSocket(n->InFrequency); laDestroyOutSocket(n->Out); strSafeDestroy(&n->Base.Name); memFree(n->OutSamples);
 }
 int IDN_FMVisit(laSynthNodeFM* n, laNodeVisitInfo* vi){
+    LA_GUARD_THIS_NODE(n,vi);
     if(LA_SRC_AND_PARENT(n->InFrequency)){ laBaseNode*bn=n->InFrequency->Source->Parent; LA_VISIT_NODE(bn,vi); }
     LA_ADD_THIS_NODE(n,vi);
     return LA_DAG_FLAG_PERM;
@@ -107,6 +110,7 @@ void IDN_VCADestroy(laSynthNodeVCA* n){
     laDestroyOutSocket(n->Out); strSafeDestroy(&n->Base.Name); memFree(n->OutSamples);
 }
 int IDN_VCAVisit(laSynthNodeVCA* n, laNodeVisitInfo* vi){
+    LA_GUARD_THIS_NODE(n,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);
@@ -141,13 +145,65 @@ void laui_VCANode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *
     laEndRow(uil,b);
 }
 
+void IDN_NoiseInit(laSynthNodeNoise* n, int NoCreate){
+    INITPACKET(n->OutWhiteSamples); INITPACKET(n->OutPinkSamples);
+    n->PinkA[0]=0.02109238; n->PinkA[1]=0.07113478; n->PinkA[2]=0.68873558;
+    n->PinkP[0]=0.3190; n->PinkP[1]=0.7756; n->PinkP[2]=0.9613;
+    if(NoCreate){ return; }
+    n->OutWhite=laCreateOutSocket(n,"WHITE",LA_PROP_FLOAT|LA_PROP_ARRAY);
+    n->OutPink=laCreateOutSocket(n,"PINK",LA_PROP_FLOAT|LA_PROP_ARRAY);
+    strSafeSet(&n->Base.Name,"Noise");
+}
+void IDN_NoiseDestroy(laSynthNodeNoise* n){
+    laDestroyOutSocket(n->OutWhite); laDestroyOutSocket(n->OutPink); strSafeDestroy(&n->Base.Name);
+    memFree(n->OutWhiteSamples); memFree(n->OutPinkSamples);
+}
+int IDN_NoiseVisit(laSynthNodeNoise* n, laNodeVisitInfo* vi){
+    LA_GUARD_THIS_NODE(n,vi); LA_ADD_THIS_NODE(n,vi);
+    return LA_DAG_FLAG_PERM;
+}
+int IDN_NoiseEval(laSynthNodeNoise* n){
+    real RMI2 = 2.0 / (real)RAND_MAX; // + 1.0; // change for range [0,1)
+    real offset = n->PinkA[0] + n->PinkA[1] + n->PinkA[2];
+    for(int i=0;i<LA_SYNTH_PLEN;i++){
+        real R1=(real)rand()/(real)RAND_MAX;
+        real R2=(real)rand()/(real)RAND_MAX;
+        real X=(real)sqrt(-2.0f*log(R1))*cos(2.0f*TNS_PI*R2);
+        n->OutWhiteSamples[i]=X*2.5;
+
+        real temp; for(int i=0;i<3;i++){ temp=(real)rand();
+            n->PinkStates[i] = n->PinkP[i] * (n->PinkStates[i] - temp) + temp;
+        }
+        n->OutPinkSamples[i]=(n->PinkA[0]*n->PinkStates[0]+
+                              n->PinkA[1]*n->PinkStates[1]+
+                              n->PinkA[2]*n->PinkStates[2])*RMI2-offset;
+        n->OutPinkSamples[i]*=40;
+    }
+    n->OutWhite->Data=n->OutWhiteSamples; n->OutWhite->ArrLen=LA_SYNTH_PLEN;
+    n->OutPink->Data=n->OutPinkSamples; n->OutPink->ArrLen=LA_SYNTH_PLEN;
+    return 1;
+}
+void IDN_NoiseCopy(laSynthNodeNoise* new, laSynthNodeNoise* old, int DoRematch){
+    if(DoRematch){ return; }
+    LA_IDN_OLD_DUPL(OutWhite);
+}
+void laui_NoiseNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
+    laColumn* c=laFirstColumn(uil); laSynthNodeNoise*n=This->EndInstance;
+    LA_BASE_NODE_HEADER(uil,c,This);
+
+    laUiItem* b=laBeginRow(uil,c,0,0);
+    laShowNodeSocket(uil,c,This,"out_white",0)->Flags|=LA_UI_SOCKET_LABEL_N;
+    laShowNodeSocket(uil,c,This,"out_pink",0)->Flags|=LA_UI_SOCKET_LABEL_N;
+    laEndRow(uil,b);
+}
+
 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;
+    strSafeSet(&n->Base.Name,"SCOPE"); n->Time=5; n->Brightness1=0.7f; n->Brightness2=0.4f;
     n->Gain1=1; n->Gain2=1;
 }
 void IDN_ScopeDestroy(laSynthNodeScope* n){
@@ -156,6 +212,7 @@ void IDN_ScopeDestroy(laSynthNodeScope* n){
     pthread_spin_destroy(&n->Lock);
 }
 int IDN_ScopeVisit(laSynthNodeScope* n, laNodeVisitInfo* vi){
+    LA_GUARD_THIS_NODE(n,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);
@@ -197,13 +254,13 @@ void laui_ScopeNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn
     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;
+    laShowNodeSocket(uil,c,This,"in1",0)->Flags|=LA_UI_SOCKET_LABEL_W;
     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;
+    laShowNodeSocket(uil,c,This,"in2",0)->Flags|=LA_UI_SOCKET_LABEL_W;
     laEndRow(uil,b);
 
     laShowItem(uil,c,This,"scope")->Extra->HeightCoeff=6;
@@ -508,6 +565,12 @@ void laInitAudio(){
     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_noise", "Noise Node", "Noise node",0,laui_NoiseNode,sizeof(laSynthNodeFM),lapost_Node,0,1);
+    LA_PC_IDN_NOISE=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_white", "White","White noise output","la_out_socket",0,0,0,offsetof(laSynthNodeNoise,OutWhite),0,0,0,0,0,0,0,LA_UDF_SINGLE);
+    laAddSubGroup(pc,"out_pink", "Pink","Pinknoise output","la_out_socket",0,0,0,offsetof(laSynthNodeNoise,OutPink),0,0,0,0,0,0,0,LA_UDF_SINGLE);
+
     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);
@@ -522,9 +585,10 @@ void laInitAudio(){
 #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)
+#define ADD_GAIN_S(a,s) laAddEnumItemAs(p,"GAIN"_STR(a),s,"^"s" gain",a,0);
+    ADD_GAIN_S(-1,"¼") ADD_GAIN_S(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)
+    ADD_GAIN_S(-1,"¼") ADD_GAIN_S(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);
@@ -538,14 +602,13 @@ void laInitAudio(){
 
     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);
     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_SYNTHESIZER, &LA_IDN_FM,&LA_IDN_VCA,&LA_IDN_NOISE,&LA_IDN_SCOPE,0);
     laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_SYSTEM_SOUND, &LA_IDN_OUTPUT,0);
 }

+ 11 - 0
la_interface.h

@@ -1685,6 +1685,17 @@ STRUCTURE(laSynthNodeFM){
     real* OutSamples;
 };
 
+STRUCTURE(laSynthNodeNoise){
+    laBaseNode Base;
+    laNodeOutSocket* OutWhite;
+    laNodeOutSocket* OutPink;
+    real* OutWhiteSamples;
+    real* OutPinkSamples;
+    //runtime
+    real PinkStates[3];
+    real PinkA[3],PinkP[3];
+};
+
 STRUCTURE(laSynthNodeVCA){
     laBaseNode Base;
     real Amp;

+ 38 - 15
resources/la_widgets.c

@@ -1558,48 +1558,71 @@ void la_ScopeDraw(laUiItem *ui, int h){
     if(!s) return;
     real* lcolor=laAccentColor(LA_BT_TEXT); int plen=LA_SYNTH_PLEN;
     int cl=ui->L, cr=ui->R, cu=ui->U, cb=ui->B; real cc=(real)(cu+cb)/2;
-    real yfac1=1<<(s->Gain1-1), yfac2=1<<(s->Gain2-1); yfac1/=10; yfac2/=10;
-    pthread_spin_lock(&s->Lock);
+    real yfac1=(real)(1<<(s->Gain1+1))/4.0f, yfac2=(real)(1<<(s->Gain2+1))/4.0f; yfac1/=10; yfac2/=10;
+    real off1=s->Offset1/20*(cb-cu), off2=s->Offset2/20*(cb-cu);
     real arrx[LA_SYNTH_PLEN];
     real arru1[LA_SYNTH_PLEN],arrb1[LA_SYNTH_PLEN];
     real arru2[LA_SYNTH_PLEN],arrb2[LA_SYNTH_PLEN];
 
-    tnsUseNoTexture(); tnsLineWidth(3.0);
+    tnsFlush(); tnsUseNoTexture();
+    
+    tnsColor4d(0,0,0,0.8);
+    tnsVertex2d(ui->L,ui->U); tnsVertex2d(ui->R,ui->U);
+    tnsVertex2d(ui->R,ui->B); tnsVertex2d(ui->L,ui->B);
+    tnsPackAs(GL_TRIANGLE_FAN);
+
+    tnsFlush(); tnsLineWidth(3.0);
+
+    int sx,sy,sw,sh,vl,vr,vu,vb;
+    la_DoUiScissor(ui,&sx,&sy,&sw,&sh,&vl,&vr,&vu,&vb);
+
+    pthread_spin_lock(&s->Lock);
+
+    real b1=s->Brightness1, b2=s->Brightness2; real hcy[3]; tnsRGB2HCY(lcolor,hcy); hcy[2]=0.75;
+    real c1[3]; tnsHCY2RGB(hcy,c1);
 
     for(int i=0;i<plen;i++){
         arrx[i]=tnsInterpolate(cl,cr,((real)i)/plen);
-        arru1[i]=tnsInterpolate(cc,cb,yfac1*s->Display1[i]);
-        arrb1[i]=tnsInterpolate(cc,cb,yfac1*s->Display1[i+plen]);
+        arru1[i]=tnsInterpolate(cc,cb,yfac1*s->Display1[i])-off1;
+        arrb1[i]=tnsInterpolate(cc,cb,yfac1*s->Display1[i+plen])-off1;
         tnsVertex2d(arrx[i],arru1[i]); tnsVertex2d(arrx[i],arrb1[i]);
     }
-    tnsColor4d(LA_COLOR3(lcolor),s->Brightness1*0.5);
+    tnsColor4d(LA_COLOR3(c1),b1*0.4);
     tnsPackAs(GL_TRIANGLE_STRIP); tnsFlush();
 
     for(int i=0;i<plen;i++){
-        arru2[i]=tnsInterpolate(cc,cb,yfac2*s->Display2[i]);
-        arrb2[i]=tnsInterpolate(cc,cb,yfac2*s->Display2[i+plen]);
+        arru2[i]=tnsInterpolate(cc,cb,yfac2*s->Display2[i])-off2;
+        arrb2[i]=tnsInterpolate(cc,cb,yfac2*s->Display2[i+plen])-off2;
         tnsVertex2d(arrx[i],arru2[i]); tnsVertex2d(arrx[i],arrb2[i]);
     }
-    tnsColor4d(LA_COLOR3(lcolor),s->Brightness2*0.5);
+    tnsColor4d(LA_COLOR3(c1),b2*0.6);
     tnsPackAs(GL_TRIANGLE_STRIP); tnsFlush();
 
     for(int i=0;i<plen;i++){ tnsVertex2d(arrx[i],arru1[i]); }
-    tnsColor4d(LA_COLOR3(lcolor),s->Brightness1);
+    tnsColor4d(LA_COLOR3(c1),b1);
     tnsPackAs(GL_LINE_STRIP);
     for(int i=0;i<plen;i++){ tnsVertex2d(arrx[i],arrb1[i]); }
-    tnsColor4d(LA_COLOR3(lcolor),s->Brightness1);
+    tnsColor4d(LA_COLOR3(c1),b1);
     tnsPackAs(GL_LINE_STRIP);
 
     for(int i=0;i<plen;i++){ tnsVertex2d(arrx[i],arru2[i]); }
-    tnsColor4d(LA_COLOR3(lcolor),s->Brightness2);
+    tnsColor4d(LA_COLOR3(c1),b2);
     tnsPackAs(GL_LINE_STRIP);
     for(int i=0;i<plen;i++){ tnsVertex2d(arrx[i],arrb2[i]); }
-    tnsColor4d(LA_COLOR3(lcolor),s->Brightness2);
+    tnsColor4d(LA_COLOR3(c1),b2);
     tnsPackAs(GL_LINE_STRIP);
 
+    pthread_spin_unlock(&s->Lock);
+
     tnsFlush(); tnsLineWidth(1.0);
 
-    pthread_spin_unlock(&s->Lock);
+    tnsViewportWithScissor(sx,sy,sw,sh);
+    tnsOrtho(vl,vr,vb,vu,-100,100);
+
+    tnsColor4dv(laThemeColor(bt,LA_BT_BORDER));
+    tnsVertex2d(ui->L,ui->U); tnsVertex2d(ui->R,ui->U);
+    tnsVertex2d(ui->R,ui->B); tnsVertex2d(ui->L,ui->B);
+    tnsPackAs(GL_LINE_LOOP);
 
     if(s->FromSynth && laget_SynthPlaying(s->FromSynth)){ laDeferredRedraw(MAIN.CurrentPanel); }
 }
@@ -1778,7 +1801,7 @@ void la_RegisterUiTypesBasic(){
     _LA_UI_IMAGE->GetMinWidth=la_ImageGetMinWidth;
 
     LA_WIDGET_SCOPE->Type=
-    _LA_UI_SCOPE = la_RegisterUiType("LA_scope_default", 0, "LA_synth_scope", &_LA_THEME_COLLECTION_GROUP, la_ScopeDraw, la_ColorPickerGetHeight, la_GeneralUiInit, la_GeneralUiDestroy);
+    _LA_UI_SCOPE = la_RegisterUiType("LA_scope_default", 0, "LA_synth_scope", &_LA_THEME_BUTTON, la_ScopeDraw, la_ColorPickerGetHeight, la_GeneralUiInit, la_GeneralUiDestroy);
 
     _LA_UI_INVISIBLE.Theme=&_LA_THEME_BUTTON;
     _LA_UI_ROW_BEGIN.Theme=&_LA_THEME_BUTTON;