|
@@ -3744,3 +3744,135 @@ struct cmDspClass_str* cmReflectCalcClassCons( cmDspCtx_t* ctx )
|
3744
|
3744
|
|
3745
|
3745
|
return &_cmReflectCalcDC;
|
3746
|
3746
|
}
|
|
3747
|
+
|
|
3748
|
+
|
|
3749
|
+//==========================================================================================================================================
|
|
3750
|
+enum
|
|
3751
|
+{
|
|
3752
|
+ kMuEcId,
|
|
3753
|
+ kImpRespN_EcId,
|
|
3754
|
+ kDelayN_EcId,
|
|
3755
|
+ kUnfiltInEcId,
|
|
3756
|
+ kFiltInEcId,
|
|
3757
|
+ kOutEcId
|
|
3758
|
+};
|
|
3759
|
+
|
|
3760
|
+cmDspClass_t _cmEchoCancelDC;
|
|
3761
|
+
|
|
3762
|
+typedef struct
|
|
3763
|
+{
|
|
3764
|
+ cmDspInst_t inst;
|
|
3765
|
+ cmNlmsEc_t* r;
|
|
3766
|
+} cmDspEchoCancel_t;
|
|
3767
|
+
|
|
3768
|
+
|
|
3769
|
+cmDspInst_t* _cmDspEchoCancelAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
|
|
3770
|
+{
|
|
3771
|
+
|
|
3772
|
+ /*
|
|
3773
|
+ if( va_cnt !=3 )
|
|
3774
|
+ {
|
|
3775
|
+ cmDspClassErr(ctx,classPtr,kVarArgParseFailDspRC,"The 'EchoCancel' constructor must have two arguments: a channel count and frequency array.");
|
|
3776
|
+ return NULL;
|
|
3777
|
+ }
|
|
3778
|
+ */
|
|
3779
|
+
|
|
3780
|
+ cmDspEchoCancel_t* p = cmDspInstAllocV(cmDspEchoCancel_t,ctx,classPtr,instSymId,id,storeSymId,va_cnt,vl,
|
|
3781
|
+ 1, "mu", kMuEcId, 0,0, kInDsvFl | kDoubleDsvFl, "NLSM mu coefficient.",
|
|
3782
|
+ 1, "irN", kImpRespN_EcId, 0,0, kInDsvFl | kUIntDsvFl, "Filter impulse response length in samples.",
|
|
3783
|
+ 1, "delayN", kDelayN_EcId, 0,0, kInDsvFl | kUIntDsvFl, "Fixed feedback delay in samples.",
|
|
3784
|
+ 1, "uf_in", kUnfiltInEcId, 0,1, kInDsvFl | kAudioBufDsvFl,"Unfiltered audio input",
|
|
3785
|
+ 1, "f_in", kFiltInEcId, 0,1, kInDsvFl | kAudioBufDsvFl,"Filtered audio input",
|
|
3786
|
+ 1, "out", kOutEcId, 0,1, kOutDsvFl | kAudioBufDsvFl,"Audio output",
|
|
3787
|
+ 0 );
|
|
3788
|
+
|
|
3789
|
+
|
|
3790
|
+ p->r = cmNlmsEcAlloc(ctx->cmProcCtx, NULL, 0,0,0 );
|
|
3791
|
+
|
|
3792
|
+ cmDspSetDefaultDouble( ctx, &p->inst, kMuEcId, 0, 0.1);
|
|
3793
|
+ cmDspSetDefaultUInt( ctx, &p->inst, kImpRespN_EcId, 0, 256);
|
|
3794
|
+ cmDspSetDefaultUInt( ctx, &p->inst, kDelayN_EcId, 0, 2048);
|
|
3795
|
+
|
|
3796
|
+ return &p->inst;
|
|
3797
|
+}
|
|
3798
|
+
|
|
3799
|
+cmDspRC_t _cmDspEchoCancelSetup( cmDspCtx_t* ctx, cmDspInst_t* inst )
|
|
3800
|
+{
|
|
3801
|
+ cmDspRC_t rc = kOkDspRC;
|
|
3802
|
+ cmDspEchoCancel_t* p = (cmDspEchoCancel_t*)inst;
|
|
3803
|
+ double mu = cmDspDouble(inst,kMuEcId);
|
|
3804
|
+ unsigned hN = cmDspUInt(inst,kImpRespN_EcId);
|
|
3805
|
+ unsigned delayN = cmDspUInt(inst,kDelayN_EcId);
|
|
3806
|
+
|
|
3807
|
+ if( cmNlmsEcInit(p->r,mu,hN,delayN) != cmOkRC )
|
|
3808
|
+ rc = cmErrMsg(&inst->classPtr->err, kSubSysFailDspRC, "Unable to initialize the internal echo canceller.");
|
|
3809
|
+
|
|
3810
|
+ return rc;
|
|
3811
|
+}
|
|
3812
|
+
|
|
3813
|
+cmDspRC_t _cmDspEchoCancelFree(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
|
|
3814
|
+{
|
|
3815
|
+ cmDspRC_t rc = kOkDspRC;
|
|
3816
|
+ cmDspEchoCancel_t* p = (cmDspEchoCancel_t*)inst;
|
|
3817
|
+
|
|
3818
|
+ cmNlmsEcFree(&p->r);
|
|
3819
|
+
|
|
3820
|
+ return rc;
|
|
3821
|
+}
|
|
3822
|
+
|
|
3823
|
+cmDspRC_t _cmDspEchoCancelReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
|
|
3824
|
+{
|
|
3825
|
+//cmDspEchoCancel_t* p = (cmDspEchoCancel_t*)inst;
|
|
3826
|
+
|
|
3827
|
+ cmDspApplyAllDefaults(ctx,inst);
|
|
3828
|
+
|
|
3829
|
+ return _cmDspEchoCancelSetup(ctx, inst );
|
|
3830
|
+}
|
|
3831
|
+
|
|
3832
|
+cmDspRC_t _cmDspEchoCancelExec(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
|
|
3833
|
+{
|
|
3834
|
+ cmDspRC_t rc = kOkDspRC;
|
|
3835
|
+ cmDspEchoCancel_t* p = (cmDspEchoCancel_t*)inst;
|
|
3836
|
+
|
|
3837
|
+ const cmSample_t* fV = cmDspAudioBuf(ctx,inst,kFiltInEcId,0);
|
|
3838
|
+ unsigned fN = cmDspAudioBufSmpCount(ctx,inst,kFiltInEcId,0);
|
|
3839
|
+
|
|
3840
|
+ const cmSample_t* uV = cmDspAudioBuf(ctx,inst,kUnfiltInEcId,0);
|
|
3841
|
+ unsigned uN = cmDspAudioBufSmpCount(ctx,inst,kUnfiltInEcId,0);
|
|
3842
|
+
|
|
3843
|
+ cmSample_t* yV = cmDspAudioBuf(ctx,inst,kOutEcId,0);
|
|
3844
|
+ unsigned yN = cmDspAudioBufSmpCount(ctx,inst,kOutEcId,0);
|
|
3845
|
+
|
|
3846
|
+ if( fV !=NULL && uV != NULL && yV != NULL )
|
|
3847
|
+ {
|
|
3848
|
+ assert( uN == yN && fN == yN );
|
|
3849
|
+ cmNlmsEcExec(p->r,uV,fV,yV,yN);
|
|
3850
|
+ }
|
|
3851
|
+
|
|
3852
|
+ return rc;
|
|
3853
|
+}
|
|
3854
|
+
|
|
3855
|
+cmDspRC_t _cmDspEchoCancelRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
|
|
3856
|
+{
|
|
3857
|
+//cmDspEchoCancel_t* p = (cmDspEchoCancel_t*)inst;
|
|
3858
|
+
|
|
3859
|
+ cmDspSetEvent(ctx,inst,evt);
|
|
3860
|
+
|
|
3861
|
+ return kOkDspRC;
|
|
3862
|
+}
|
|
3863
|
+
|
|
3864
|
+struct cmDspClass_str* cmEchoCancelClassCons( cmDspCtx_t* ctx )
|
|
3865
|
+{
|
|
3866
|
+ cmDspClassSetup(&_cmEchoCancelDC,ctx,"EchoCancel",
|
|
3867
|
+ NULL,
|
|
3868
|
+ _cmDspEchoCancelAlloc,
|
|
3869
|
+ _cmDspEchoCancelFree,
|
|
3870
|
+ _cmDspEchoCancelReset,
|
|
3871
|
+ _cmDspEchoCancelExec,
|
|
3872
|
+ _cmDspEchoCancelRecv,
|
|
3873
|
+ NULL,
|
|
3874
|
+ NULL,
|
|
3875
|
+ "Echo canceller");
|
|
3876
|
+
|
|
3877
|
+ return &_cmEchoCancelDC;
|
|
3878
|
+}
|