|
@@ -3733,6 +3733,7 @@ enum
|
3733
|
3733
|
kEndLnId,
|
3734
|
3734
|
kDurLnId,
|
3735
|
3735
|
kCmdLnId,
|
|
3736
|
+ kRateLnId,
|
3736
|
3737
|
kOutLnId,
|
3737
|
3738
|
};
|
3738
|
3739
|
|
|
@@ -3752,6 +3753,7 @@ typedef struct
|
3752
|
3753
|
unsigned offSymId;
|
3753
|
3754
|
unsigned resetSymId;
|
3754
|
3755
|
unsigned curSmpIdx;
|
|
3756
|
+ double phase;
|
3755
|
3757
|
bool onFl;
|
3756
|
3758
|
} cmDspLine_t;
|
3757
|
3759
|
|
|
@@ -3762,6 +3764,7 @@ cmDspInst_t* _cmDspLineAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned
|
3762
|
3764
|
1, "end", kEndLnId, 0, 0, kInDsvFl | kDoubleDsvFl | kReqArgDsvFl, "End value.",
|
3763
|
3765
|
1, "dur", kDurLnId, 0, 0, kInDsvFl | kDoubleDsvFl | kReqArgDsvFl, "Duration (ms)",
|
3764
|
3766
|
1, "cmd", kCmdLnId, 0, 0, kInDsvFl | kSymDsvFl | kOptArgDsvFl, "Command: on | off | reset",
|
|
3767
|
+ 1, "rate", kRateLnId, 0, 0, kInDsvFl | kDoubleDsvFl | kOptArgDsvFl, "Output messages per second",
|
3765
|
3768
|
1, "out", kOutLnId, 0, 0, kOutDsvFl | kDoubleDsvFl, "Output",
|
3766
|
3769
|
0 );
|
3767
|
3770
|
|
|
@@ -3769,10 +3772,12 @@ cmDspInst_t* _cmDspLineAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned
|
3769
|
3772
|
return NULL;
|
3770
|
3773
|
|
3771
|
3774
|
cmDspSetDefaultDouble( ctx, &p->inst, kOutLnId, 0.0, cmDspDefaultDouble(&p->inst,kBegLnId) );
|
|
3775
|
+ cmDspSetDefaultDouble( ctx, &p->inst, kRateLnId, 0.0, 0.0 );
|
3772
|
3776
|
|
3773
|
3777
|
p->onSymId = cmSymTblRegisterStaticSymbol(ctx->stH,"on");
|
3774
|
3778
|
p->offSymId = cmSymTblRegisterStaticSymbol(ctx->stH,"off");
|
3775
|
3779
|
p->resetSymId = cmSymTblRegisterStaticSymbol(ctx->stH,"reset");
|
|
3780
|
+
|
3776
|
3781
|
|
3777
|
3782
|
return &p->inst;
|
3778
|
3783
|
}
|
|
@@ -3788,6 +3793,7 @@ cmDspRC_t _cmDspLineReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t*
|
3788
|
3793
|
cmDspLine_t* p = (cmDspLine_t*)inst;
|
3789
|
3794
|
p->curSmpIdx = 0;
|
3790
|
3795
|
p->onFl = false;
|
|
3796
|
+ p->phase = 0;
|
3791
|
3797
|
return cmDspApplyAllDefaults(ctx,inst);
|
3792
|
3798
|
}
|
3793
|
3799
|
|
|
@@ -3799,12 +3805,21 @@ cmDspRC_t _cmDspLineExec( cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t*
|
3799
|
3805
|
if( p->onFl == false )
|
3800
|
3806
|
return kOkDspRC;
|
3801
|
3807
|
|
|
3808
|
+ unsigned sPc = cmDspSamplesPerCycle(ctx);
|
3802
|
3809
|
double beg = cmDspDouble(inst,kBegLnId);
|
3803
|
3810
|
double end = cmDspDouble(inst,kEndLnId);
|
|
3811
|
+ double rate = cmDspDouble(inst,kRateLnId);
|
3804
|
3812
|
double ms = cmDspDouble(inst,kDurLnId);
|
3805
|
3813
|
double durSmpCnt = floor(ms * cmDspSampleRate(ctx) / 1000);
|
3806
|
3814
|
double out = beg + (end - beg) * p->curSmpIdx / durSmpCnt;
|
3807
|
|
-
|
|
3815
|
+ double phsMax = rate==0 ? sPc : cmDspSampleRate(ctx) / rate;
|
|
3816
|
+
|
|
3817
|
+ // we can never output with a period shorter than
|
|
3818
|
+ // the length of one audio buffer
|
|
3819
|
+ if( phsMax < sPc )
|
|
3820
|
+ phsMax = sPc;
|
|
3821
|
+
|
|
3822
|
+
|
3808
|
3823
|
if( beg < end )
|
3809
|
3824
|
{
|
3810
|
3825
|
if( out >= end )
|
|
@@ -3822,9 +3837,15 @@ cmDspRC_t _cmDspLineExec( cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t*
|
3822
|
3837
|
}
|
3823
|
3838
|
}
|
3824
|
3839
|
|
3825
|
|
- cmDspSetDouble(ctx,inst,kOutLnId,out);
|
|
3840
|
+ p->phase += sPc;
|
|
3841
|
+
|
|
3842
|
+ if( p->phase >= sPc )
|
|
3843
|
+ {
|
|
3844
|
+ cmDspSetDouble(ctx,inst,kOutLnId,out);
|
|
3845
|
+ p->phase -= sPc;
|
|
3846
|
+ }
|
3826
|
3847
|
|
3827
|
|
- p->curSmpIdx += cmDspSamplesPerCycle(ctx);
|
|
3848
|
+ p->curSmpIdx += sPc;
|
3828
|
3849
|
|
3829
|
3850
|
return rc;
|
3830
|
3851
|
}
|