2012-10-30 03:52:39 +00:00
# include "cmPrefix.h"
# include "cmGlobal.h"
# include "cmFloatTypes.h"
# include "cmComplexTypes.h"
# include "cmRpt.h"
# include "cmErr.h"
# include "cmCtx.h"
# include "cmMem.h"
# include "cmMallocDebug.h"
# include "cmLinkedHeap.h"
# include "cmText.h"
# include "cmMath.h"
# include "cmFile.h"
# include "cmFileSys.h"
# include "cmSymTbl.h"
# include "cmJson.h"
# include "cmPrefs.h"
# include "cmDspValue.h"
# include "cmMsgProtocol.h"
# include "cmThread.h"
# include "cmUdpPort.h"
# include "cmUdpNet.h"
2013-12-15 23:14:27 +00:00
# include "cmTime.h"
2012-10-30 03:52:39 +00:00
# include "cmAudioSys.h"
# include "cmProcObj.h"
# include "cmDspCtx.h"
# include "cmDspClass.h"
# include "cmDspUi.h"
# include "cmAudioFile.h"
# include "cmProcObj.h"
# include "cmProcTemplateMain.h"
# include "cmProc.h"
# include "cmMidi.h"
# include "cmProc2.h"
# include "cmProc3.h"
# include "cmVectOpsTemplateMain.h"
# include "app/cmPickup.h"
# include "cmDspSys.h"
//==========================================================================================================================================
enum
{
kBypassDyId ,
kTimeDyId ,
kFbDyId ,
kInDyId ,
kOutDyId
} ;
cmDspClass_t _cmDelayDC ;
typedef struct
{
cmDspInst_t inst ;
cmMDelay * delay ;
} cmDspDelay_t ;
cmDspInst_t * _cmDspDelayAlloc ( cmDspCtx_t * ctx , cmDspClass_t * classPtr , unsigned storeSymId , unsigned instSymId , unsigned id , unsigned va_cnt , va_list vl )
{
unsigned chs = 1 ;
cmDspVarArg_t args [ ] =
{
{ " bypass " , kBypassDyId , 0 , 0 , kInDsvFl | kBoolDsvFl | kOptArgDsvFl , " Bypass enable flag. " } ,
{ " time " , kTimeDyId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kOptArgDsvFl , " Max delay time in milliseconds " } ,
{ " fb " , kFbDyId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kOptArgDsvFl , " Feedback " } ,
{ " in " , kInDyId , 0 , 0 , kInDsvFl | kAudioBufDsvFl , " Audio input " } ,
{ " out " , kOutDyId , 0 , chs , kOutDsvFl | kAudioBufDsvFl , " Audio output. " } ,
{ NULL , 0 , 0 , 0 , 0 }
} ;
cmDspDelay_t * p = cmDspInstAlloc ( cmDspDelay_t , ctx , classPtr , args , instSymId , id , storeSymId , va_cnt , vl ) ;
// set default values for the parameters that were not explicitely set in the va_arg list
cmDspSetDefaultBool ( ctx , & p - > inst , kBypassDyId , 0 , 0 ) ;
cmDspSetDefaultUInt ( ctx , & p - > inst , kTimeDyId , 0 , 1000 ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kFbDyId , 0.0 , 0.0 ) ;
cmReal_t dtimeMs = cmDspDefaultUInt ( & p - > inst , kTimeDyId ) ;
cmReal_t fbCoeff = cmDspDefaultDouble ( & p - > inst , kFbDyId ) ;
p - > delay = cmMDelayAlloc ( ctx - > cmProcCtx , NULL , cmDspSamplesPerCycle ( ctx ) , cmDspSampleRate ( ctx ) , fbCoeff , 1 , & dtimeMs , NULL ) ;
return & p - > inst ;
}
cmDspRC_t _cmDspDelayFree ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspDelay_t * p = ( cmDspDelay_t * ) inst ;
cmMDelayFree ( & p - > delay ) ;
//cmCtxFree(&p->ctx);
return rc ;
}
cmDspRC_t _cmDspDelayReset ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
rc = cmDspApplyAllDefaults ( ctx , inst ) ;
return rc ;
}
cmDspRC_t _cmDspDelayExec ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspDelay_t * p = ( cmDspDelay_t * ) inst ;
cmDspRC_t rc = kOkDspRC ;
unsigned iChIdx = 0 ;
const cmSample_t * ip = cmDspAudioBuf ( ctx , inst , kInDyId , iChIdx ) ;
unsigned iSmpCnt = cmDspVarRows ( inst , kInDyId ) ;
unsigned oChIdx = 0 ;
cmSample_t * op = cmDspAudioBuf ( ctx , inst , kOutDyId , oChIdx ) ;
unsigned oSmpCnt = cmDspVarRows ( inst , kOutDyId ) ;
bool bypassFl = cmDspBool ( inst , kBypassDyId ) ;
cmMDelayExec ( p - > delay , ip , op , cmMin ( iSmpCnt , oSmpCnt ) , bypassFl ) ;
return rc ;
}
cmDspRC_t _cmDspDelayRecv ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspDelay_t * p = ( cmDspDelay_t * ) inst ;
cmDspRC_t rc = kOkDspRC ;
cmDspSetEvent ( ctx , inst , evt ) ;
switch ( evt - > dstVarId )
{
case kBypassDyId :
break ;
case kTimeDyId :
p - > delay - > delayArray [ 0 ] . delayMs = cmDspDouble ( inst , kTimeDyId ) ;
break ;
case kFbDyId :
p - > delay - > fbCoeff = cmDspDouble ( inst , kFbDyId ) ;
break ;
default :
{ assert ( 0 ) ; }
}
return rc ;
}
struct cmDspClass_str * cmDelayClassCons ( cmDspCtx_t * ctx )
{
cmDspClassSetup ( & _cmDelayDC , ctx , " Delay " ,
NULL ,
_cmDspDelayAlloc ,
_cmDspDelayFree ,
_cmDspDelayReset ,
_cmDspDelayExec ,
_cmDspDelayRecv ,
NULL , NULL ,
" Simple delay. " ) ;
return & _cmDelayDC ;
}
//==========================================================================================================================================
enum
{
kBypassMtId ,
kScaleMtId ,
kFbMtId ,
kInMtId ,
kOutMtId ,
kBaseMsMtId
} ;
cmDspClass_t _cmMtDelayDC ;
typedef struct
{
cmDspInst_t inst ;
cmMDelay * p ;
unsigned baseGainMtId ;
unsigned tapCnt ;
cmReal_t * msV ;
cmReal_t * gainV ;
unsigned printSymId ;
} cmDspMtDelay_t ;
// args: bypassFl, time_scale, feedback, tap_ms0, tap_gain0, tapms1, tap_gain1, ....
cmDspInst_t * _cmDspMtDelayAlloc ( cmDspCtx_t * ctx , cmDspClass_t * classPtr , unsigned storeSymId , unsigned instSymId , unsigned id , unsigned va_cnt , va_list vl )
{
va_list vl1 ;
cmDspVarArg_t args [ ] =
{
{ " bypass " , kBypassMtId , 0 , 0 , kInDsvFl | kBoolDsvFl | kReqArgDsvFl , " Bypass enable flag. " } ,
{ " scale " , kScaleMtId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kReqArgDsvFl , " Scale tap times. (0.0 - 1.0) " } ,
{ " fb " , kFbMtId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kReqArgDsvFl , " Feedback " } ,
{ " in " , kInMtId , 0 , 0 , kInDsvFl | kAudioBufDsvFl , " Audio input " } ,
{ " out " , kOutMtId , 0 , 1 , kOutDsvFl | kAudioBufDsvFl , " Audio output. " } ,
} ;
// verify that at least one var arg exists
if ( va_cnt < 5 | | cmIsEvenU ( va_cnt ) )
{
cmDspClassErr ( ctx , classPtr , kInvalidArgDspRC , " The 'multi-tap delay requires at least 5 arguments. Three fixed arguments and groups of two tap specification arguments. " ) ;
return NULL ;
}
2013-10-17 01:52:59 +00:00
va_copy ( vl1 , vl ) ;
2012-10-30 03:52:39 +00:00
unsigned reqArgCnt = 3 ;
unsigned fixArgCnt = sizeof ( args ) / sizeof ( args [ 0 ] ) ;
unsigned tapCnt = ( va_cnt - reqArgCnt ) / 2 ;
cmReal_t * msV = cmMemAllocZ ( cmReal_t , tapCnt ) ;
cmReal_t * gainV = cmMemAllocZ ( cmReal_t , tapCnt ) ;
unsigned argCnt = fixArgCnt + 2 * tapCnt ;
unsigned baseGainMtId = kBaseMsMtId + tapCnt ;
cmDspVarArg_t a [ argCnt + 1 ] ;
unsigned i ;
// Get the taps and gains
va_arg ( vl1 , int ) ; // enable
va_arg ( vl1 , double ) ; // time scale
va_arg ( vl1 , double ) ; // feedback
for ( i = 0 ; i < tapCnt ; + + i )
{
msV [ i ] = va_arg ( vl1 , double ) ;
gainV [ i ] = va_arg ( vl1 , double ) ;
}
// setup the output gain args
cmDspArgCopy ( a , argCnt , 0 , args , fixArgCnt ) ;
cmDspArgSetupN ( ctx , a , argCnt , kBaseMsMtId , tapCnt , " ms " , kBaseMsMtId , 0 , 0 , kInDsvFl | kDoubleDsvFl , " Tap delay times in milliseconds. " ) ;
cmDspArgSetupN ( ctx , a , argCnt , baseGainMtId , tapCnt , " gain " , baseGainMtId , 0 , 0 , kInDsvFl | kDoubleDsvFl , " Tap delay linear gain. " ) ;
cmDspArgSetupNull ( a + argCnt ) ; // set terminating arg. flag
cmDspMtDelay_t * p = cmDspInstAlloc ( cmDspMtDelay_t , ctx , classPtr , a , instSymId , id , storeSymId , reqArgCnt , vl1 ) ;
p - > p = cmMDelayAlloc ( ctx - > cmProcCtx , NULL , 0 , 0 , 0 , 0 , NULL , NULL ) ;
p - > baseGainMtId = baseGainMtId ;
p - > tapCnt = tapCnt ;
p - > msV = msV ;
p - > gainV = gainV ;
p - > printSymId = cmSymTblRegisterStaticSymbol ( ctx - > stH , " _print " ) ;
for ( i = 0 ; i < tapCnt ; + + i )
{
cmDspSetDefaultDouble ( ctx , & p - > inst , kBaseMsMtId + i , 0.0 , msV [ i ] ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , baseGainMtId + i , 0.0 , gainV [ i ] ) ;
}
2013-10-17 01:52:59 +00:00
va_end ( vl1 ) ;
2012-10-30 03:52:39 +00:00
return & p - > inst ;
}
cmDspRC_t _cmDspMtDelayFree ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspMtDelay_t * p = ( cmDspMtDelay_t * ) inst ;
cmMemFree ( p - > msV ) ;
cmMemFree ( p - > gainV ) ;
cmMDelayFree ( & p - > p ) ;
return rc ;
}
cmDspRC_t _cmDspMtDelayReset ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspMtDelay_t * p = ( cmDspMtDelay_t * ) inst ;
if ( ( rc = cmDspApplyAllDefaults ( ctx , inst ) ) = = kOkDspRC )
{
cmMDelayInit ( p - > p , cmDspSamplesPerCycle ( ctx ) , cmDspSampleRate ( ctx ) , cmDspDouble ( & p - > inst , kFbMtId ) , p - > tapCnt , p - > msV , p - > gainV ) ;
}
return rc ;
}
cmDspRC_t _cmDspMtDelayExec ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspMtDelay_t * p = ( cmDspMtDelay_t * ) inst ;
cmDspRC_t rc = kOkDspRC ;
unsigned iChIdx = 0 ;
const cmSample_t * ip = cmDspAudioBuf ( ctx , inst , kInMtId , iChIdx ) ;
unsigned iSmpCnt = cmDspVarRows ( inst , kInMtId ) ;
unsigned oChIdx = 0 ;
cmSample_t * op = cmDspAudioBuf ( ctx , inst , kOutMtId , oChIdx ) ;
unsigned oSmpCnt = cmDspVarRows ( inst , kOutMtId ) ;
bool bypassFl = cmDspBool ( inst , kBypassMtId ) ;
if ( ip ! = NULL )
cmMDelayExec ( p - > p , ip , op , cmMin ( iSmpCnt , oSmpCnt ) , bypassFl ) ;
return rc ;
}
cmDspRC_t _cmDspMtDelayRecv ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspMtDelay_t * p = ( cmDspMtDelay_t * ) inst ;
cmDspRC_t rc = kOkDspRC ;
cmDspSetEvent ( ctx , inst , evt ) ;
// set tap times
if ( kBaseMsMtId < = evt - > dstVarId & & evt - > dstVarId < kBaseMsMtId + p - > p - > delayCnt )
cmMDelaySetTapMs ( p - > p , evt - > dstVarId - kBaseMsMtId , cmDspDouble ( inst , evt - > dstVarId ) ) ;
else
// set tap gains
if ( p - > baseGainMtId < = evt - > dstVarId & & evt - > dstVarId < p - > baseGainMtId + p - > p - > delayCnt )
cmMDelaySetTapGain ( p - > p , evt - > dstVarId - p - > baseGainMtId , cmDspDouble ( inst , evt - > dstVarId ) ) ;
else
{
switch ( evt - > dstVarId )
{
case kScaleMtId :
//cmDspDouble(inst,kScaleMtId);
break ;
case kFbMtId :
p - > p - > fbCoeff = cmDspDouble ( inst , kFbMtId ) ;
break ;
}
}
return rc ;
}
cmDspRC_t _cmDspMtDelayRecvFunc ( cmDspCtx_t * ctx , struct cmDspInst_str * inst , unsigned attrSymId , const cmDspValue_t * value )
{
cmDspRC_t rc = kOkDspRC ;
cmDspMtDelay_t * p = ( cmDspMtDelay_t * ) inst ;
if ( cmDsvIsSymbol ( value ) & & ( cmDsvSymbol ( value ) = = p - > printSymId ) )
{
int i ;
cmRptPrintf ( ctx - > rpt , " taps:%i \n " , p - > tapCnt ) ;
for ( i = 0 ; i < p - > tapCnt ; + + i )
cmRptPrintf ( ctx - > rpt , " %f %f \n " , p - > msV [ i ] , p - > gainV [ i ] ) ;
cmMDelayReport ( p - > p , ctx - > rpt ) ;
}
return rc ;
}
struct cmDspClass_str * cmMtDelayClassCons ( cmDspCtx_t * ctx )
{
cmDspClassSetup ( & _cmMtDelayDC , ctx , " MtDelay " ,
NULL ,
_cmDspMtDelayAlloc ,
_cmDspMtDelayFree ,
_cmDspMtDelayReset ,
_cmDspMtDelayExec ,
_cmDspMtDelayRecv ,
NULL ,
_cmDspMtDelayRecvFunc ,
" Multi-tap delay. " ) ;
return & _cmMtDelayDC ;
}
//==========================================================================================================================================
enum
{
kBypassPsId ,
kRatioPsId ,
kInPsId ,
kOutPsId
} ;
cmDspClass_t _cmPShiftDC ;
typedef struct
{
cmDspInst_t inst ;
//cmCtx* ctx;
cmPitchShift * pshift ;
} cmDspPShift_t ;
cmDspInst_t * _cmDspPShiftAlloc ( cmDspCtx_t * ctx , cmDspClass_t * classPtr , unsigned storeSymId , unsigned instSymId , unsigned id , unsigned va_cnt , va_list vl )
{
unsigned chs = 1 ;
cmDspVarArg_t args [ ] =
{
{ " bypass " , kBypassPsId , 0 , 0 , kInDsvFl | kBoolDsvFl | kOptArgDsvFl , " Bypass enable flag. " } ,
{ " ratio " , kRatioPsId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kOptArgDsvFl , " Ratio " } ,
{ " in " , kInPsId , 0 , 0 , kInDsvFl | kAudioBufDsvFl , " Audio input " } ,
{ " out " , kOutPsId , 0 , chs , kOutDsvFl | kAudioBufDsvFl , " Audio output. " } ,
{ NULL , 0 , 0 , 0 , 0 }
} ;
cmDspPShift_t * p = cmDspInstAlloc ( cmDspPShift_t , ctx , classPtr , args , instSymId , id , storeSymId , va_cnt , vl ) ;
// set default values for the parameters that were not explicitely set in the va_arg list
cmDspSetDefaultBool ( ctx , & p - > inst , kBypassPsId , 0 , 0 ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kRatioPsId , 0.0 , 1.0 ) ;
p - > pshift = cmPitchShiftAlloc ( ctx - > cmProcCtx , NULL , cmDspSamplesPerCycle ( ctx ) , cmDspSampleRate ( ctx ) ) ;
return & p - > inst ;
}
cmDspRC_t _cmDspPShiftFree ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspPShift_t * p = ( cmDspPShift_t * ) inst ;
cmPitchShiftFree ( & p - > pshift ) ;
//cmCtxFree(&p->ctx);
return rc ;
}
cmDspRC_t _cmDspPShiftReset ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
rc = cmDspApplyAllDefaults ( ctx , inst ) ;
return rc ;
}
cmDspRC_t _cmDspPShiftExec ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspPShift_t * p = ( cmDspPShift_t * ) inst ;
cmDspRC_t rc = kOkDspRC ;
unsigned iChIdx = 0 ;
const cmSample_t * ip = cmDspAudioBuf ( ctx , inst , kInPsId , iChIdx ) ;
unsigned iSmpCnt = cmDspVarRows ( inst , kInPsId ) ;
unsigned oChIdx = 0 ;
cmSample_t * op = cmDspAudioBuf ( ctx , inst , kOutPsId , oChIdx ) ;
unsigned oSmpCnt = cmDspVarRows ( inst , kOutPsId ) ;
bool bypassFl = cmDspBool ( inst , kBypassPsId ) ;
cmPitchShiftExec ( p - > pshift , ip , op , cmMin ( iSmpCnt , oSmpCnt ) , cmDspDouble ( inst , kRatioPsId ) , bypassFl ) ;
return rc ;
}
cmDspRC_t _cmDspPShiftRecv ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
return cmDspSetEvent ( ctx , inst , evt ) ;
}
struct cmDspClass_str * cmPShiftClassCons ( cmDspCtx_t * ctx )
{
cmDspClassSetup ( & _cmPShiftDC , ctx , " PShift " ,
NULL ,
_cmDspPShiftAlloc ,
_cmDspPShiftFree ,
_cmDspPShiftReset ,
_cmDspPShiftExec ,
_cmDspPShiftRecv ,
NULL , NULL ,
" Pitch Shifter. " ) ;
return & _cmPShiftDC ;
}
//==========================================================================================================================================
enum
{
kTimeLrId ,
kPGainLrId ,
kRGainLrId ,
kBypassLrId ,
kPlayLrId ,
kRecdLrId ,
kRatioLrId ,
kInLrId ,
kOutLrId
} ;
cmDspClass_t _cmLoopRecdDC ;
typedef struct
{
cmDspInst_t inst ;
//cmCtx* ctx;
bool playFl ;
cmLoopRecord * lrp ;
} cmDspLoopRecd_t ;
cmDspInst_t * _cmDspLoopRecdAlloc ( cmDspCtx_t * ctx , cmDspClass_t * classPtr , unsigned storeSymId , unsigned instSymId , unsigned id , unsigned va_cnt , va_list vl )
{
unsigned chs = 1 ;
cmDspVarArg_t args [ ] =
{
{ " time " , kTimeLrId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kOptArgDsvFl , " Max record time in seconds " } ,
{ " pgain " , kPGainLrId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kOptArgDsvFl , " Pass-through gain. " } ,
{ " rgain " , kRGainLrId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kOptArgDsvFl , " Recorder out gain. " } ,
{ " bypass " , kBypassLrId , 0 , 0 , kInDsvFl | kBoolDsvFl , " Bypass flag " } ,
{ " play " , kPlayLrId , 0 , 0 , kInDsvFl | kBoolDsvFl , " Play gate flag " } ,
{ " recd " , kRecdLrId , 0 , 0 , kInDsvFl | kBoolDsvFl , " Recd gate flag " } ,
{ " ratio " , kRatioLrId , 0 , 0 , kInDsvFl | kDoubleDsvFl , " Playback speed ratio " } ,
{ " in " , kInLrId , 0 , 0 , kInDsvFl | kAudioBufDsvFl , " Audio input " } ,
{ " out " , kOutLrId , 0 , chs , kOutDsvFl | kAudioBufDsvFl , " Audio output. " } ,
{ NULL , 0 , 0 , 0 , 0 }
} ;
cmDspLoopRecd_t * p = cmDspInstAlloc ( cmDspLoopRecd_t , ctx , classPtr , args , instSymId , id , storeSymId , va_cnt , vl ) ;
// set default values for the parameters that were not explicitely set in the va_arg list
cmDspSetDefaultDouble ( ctx , & p - > inst , kTimeLrId , 0 , 10 ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kPGainLrId , 0 , 1.0 ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kRGainLrId , 0 , 1.0 ) ;
cmDspSetDefaultBool ( ctx , & p - > inst , kBypassLrId , 0 , 0 ) ;
cmDspSetDefaultBool ( ctx , & p - > inst , kPlayLrId , 0 , 0 ) ;
cmDspSetDefaultBool ( ctx , & p - > inst , kRecdLrId , 0 , 0 ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kRatioLrId , 0 , 1.0 ) ;
p - > lrp = cmLoopRecordAlloc ( ctx - > cmProcCtx , NULL , 0 , 0 , 0 ) ;
return & p - > inst ;
}
cmDspRC_t _cmDspLoopRecdFree ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspLoopRecd_t * p = ( cmDspLoopRecd_t * ) inst ;
cmLoopRecordFree ( & p - > lrp ) ;
//cmCtxFree(&p->ctx);
return rc ;
}
cmDspRC_t _cmDspLoopRecdReset ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspLoopRecd_t * p = ( cmDspLoopRecd_t * ) inst ;
rc = cmDspApplyAllDefaults ( ctx , inst ) ;
cmReal_t maxRecdTimeSecs = cmDspDefaultDouble ( & p - > inst , kTimeLrId ) ;
unsigned maxRecdTimeSmps = floor ( cmDspSampleRate ( ctx ) * maxRecdTimeSecs ) ;
unsigned xfadeTimeSmps = floor ( cmDspSampleRate ( ctx ) * 50.0 / 1000.0 ) ;
if ( maxRecdTimeSmps ! = p - > lrp - > maxRecdSmpCnt | | xfadeTimeSmps ! = p - > lrp - > xfadeSmpCnt )
cmLoopRecordInit ( p - > lrp , cmDspSamplesPerCycle ( ctx ) , maxRecdTimeSmps , xfadeTimeSmps ) ;
return rc ;
}
cmDspRC_t _cmDspLoopRecdExec ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspLoopRecd_t * p = ( cmDspLoopRecd_t * ) inst ;
cmDspRC_t rc = kOkDspRC ;
unsigned iChIdx = 0 ;
const cmSample_t * ip = cmDspAudioBuf ( ctx , inst , kInLrId , iChIdx ) ;
unsigned iSmpCnt = cmDspVarRows ( inst , kInLrId ) ;
unsigned oChIdx = 0 ;
cmSample_t * op = cmDspAudioBuf ( ctx , inst , kOutLrId , oChIdx ) ;
unsigned oSmpCnt = cmDspVarRows ( inst , kOutLrId ) ;
bool recdFl = cmDspBool ( inst , kRecdLrId ) ;
bool bypassFl = cmDspBool ( inst , kBypassLrId ) ;
double ratio = cmDspDouble ( inst , kRatioLrId ) ;
double rgain = cmDspDouble ( inst , kRGainLrId ) ; // recorder output gain
double pgain = cmDspDouble ( inst , kPGainLrId ) ; // pass through gain
if ( ip ! = NULL & & op ! = NULL )
cmLoopRecordExec ( p - > lrp , ip , op , cmMin ( iSmpCnt , oSmpCnt ) , bypassFl , recdFl , p - > playFl , ratio , pgain , rgain ) ;
p - > playFl = false ;
return rc ;
}
cmDspRC_t _cmDspLoopRecdRecv ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspLoopRecd_t * p = ( cmDspLoopRecd_t * ) inst ;
cmDspRC_t rc = cmDspSetEvent ( ctx , inst , evt ) ;
switch ( evt - > dstVarId )
{
case kPlayLrId :
p - > playFl = cmDspBool ( inst , kPlayLrId ) ;
break ;
}
return rc ;
}
struct cmDspClass_str * cmLoopRecdClassCons ( cmDspCtx_t * ctx )
{
cmDspClassSetup ( & _cmLoopRecdDC , ctx , " LoopRecd " ,
NULL ,
_cmDspLoopRecdAlloc ,
_cmDspLoopRecdFree ,
_cmDspLoopRecdReset ,
_cmDspLoopRecdExec ,
_cmDspLoopRecdRecv ,
NULL , NULL ,
" Loop recorder. " ) ;
return & _cmLoopRecdDC ;
}
//==========================================================================================================================================
enum
{
kBypassRcId ,
kCoeffRcId ,
kInRcId ,
kOutRcId
} ;
cmDspClass_t _cmRectifyDC ;
typedef struct
{
cmDspInst_t inst ;
} cmDspRectify_t ;
cmDspInst_t * _cmDspRectifyAlloc ( cmDspCtx_t * ctx , cmDspClass_t * classPtr , unsigned storeSymId , unsigned instSymId , unsigned id , unsigned va_cnt , va_list vl )
{
unsigned chs = 1 ;
cmDspVarArg_t args [ ] =
{
{ " bypass " , kBypassRcId , 0 , 0 , kInDsvFl | kBoolDsvFl | kOptArgDsvFl , " Bypass enable flag. " } ,
{ " coeff " , kCoeffRcId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kOptArgDsvFl , " Coefficient " } ,
{ " in " , kInRcId , 0 , 0 , kInDsvFl | kAudioBufDsvFl , " Audio input " } ,
{ " out " , kOutRcId , 0 , chs , kOutDsvFl | kAudioBufDsvFl , " Audio output. " } ,
{ NULL , 0 , 0 , 0 , 0 }
} ;
cmDspRectify_t * p = cmDspInstAlloc ( cmDspRectify_t , ctx , classPtr , args , instSymId , id , storeSymId , va_cnt , vl ) ;
// set default values for the parameters that were not explicitely set in the va_arg list
cmDspSetDefaultBool ( ctx , & p - > inst , kBypassRcId , 0 , 0 ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kCoeffRcId , 0 , 0.0 ) ;
return & p - > inst ;
}
cmDspRC_t _cmDspRectifyFree ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
return kOkDspRC ;
}
cmDspRC_t _cmDspRectifyReset ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
rc = cmDspApplyAllDefaults ( ctx , inst ) ;
return rc ;
}
cmDspRC_t _cmDspRectifyExec ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
unsigned iChIdx = 0 ;
const cmSample_t * ip = cmDspAudioBuf ( ctx , inst , kInRcId , iChIdx ) ;
unsigned iSmpCnt = cmDspVarRows ( inst , kInRcId ) ;
unsigned oChIdx = 0 ;
cmSample_t * op = cmDspAudioBuf ( ctx , inst , kOutRcId , oChIdx ) ;
unsigned oSmpCnt = cmDspVarRows ( inst , kOutRcId ) ;
bool bypassFl = cmDspBool ( inst , kBypassRcId ) ;
unsigned n = cmMin ( iSmpCnt , oSmpCnt ) ;
unsigned i ;
if ( bypassFl )
memcpy ( op , ip , n * sizeof ( cmSample_t ) ) ;
else
{
for ( i = 0 ; i < n ; + + i )
op [ i ] = ip [ i ] > 0 ? ip [ i ] : 0 ;
}
return kOkDspRC ;
}
cmDspRC_t _cmDspRectifyRecv ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
return cmDspSetEvent ( ctx , inst , evt ) ;
}
struct cmDspClass_str * cmRectifyClassCons ( cmDspCtx_t * ctx )
{
cmDspClassSetup ( & _cmRectifyDC , ctx , " Rectify " ,
NULL ,
_cmDspRectifyAlloc ,
_cmDspRectifyFree ,
_cmDspRectifyReset ,
_cmDspRectifyExec ,
_cmDspRectifyRecv ,
NULL , NULL ,
" Half-wave rectifier. " ) ;
return & _cmRectifyDC ;
}
//==========================================================================================================================================
enum
{
kWndMsGdId ,
kOnThreshPctGdId ,
kOnThreshDbGdId ,
kOffThreshDbGdId ,
kInGdId ,
kGateGdId ,
kRmsGdId ,
kMeanGdId
} ;
cmDspClass_t _cmGateDetectDC ;
typedef struct
{
cmDspInst_t inst ;
//cmCtx* ctx;
cmShiftBuf * sbp ;
cmGateDetect * gdp ;
} cmDspGateDetect_t ;
cmDspInst_t * _cmDspGateDetectAlloc ( cmDspCtx_t * ctx , cmDspClass_t * classPtr , unsigned storeSymId , unsigned instSymId , unsigned id , unsigned va_cnt , va_list vl )
{
cmDspVarArg_t args [ ] =
{
{ " wnd " , kWndMsGdId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kOptArgDsvFl , " Window length in milliseconds. " } ,
{ " onpct " , kOnThreshPctGdId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kOptArgDsvFl , " Onset slope threshold [0.0 - 1.0]. " } ,
{ " ondb " , kOnThreshDbGdId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kOptArgDsvFl , " Onset threshold dB [-Inf to 0] " } ,
{ " offdb " , kOffThreshDbGdId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kOptArgDsvFl , " Offset threshold dB [-Inf to 0] " } ,
{ " in " , kInGdId , 0 , 0 , kInDsvFl | kAudioBufDsvFl , " Audio input " } ,
{ " gate " , kGateGdId , 0 , 0 , kOutDsvFl | kBoolDsvFl , " Gate state output. " } ,
{ " rms " , kRmsGdId , 0 , 0 , kOutDsvFl | kDoubleDsvFl , " Signal level RMS " } ,
{ " mean " , kMeanGdId , 0 , 0 , kOutDsvFl | kDoubleDsvFl , " Derr mean. " } ,
{ NULL , 0 , 0 , 0 , 0 }
} ;
cmDspGateDetect_t * p = cmDspInstAlloc ( cmDspGateDetect_t , ctx , classPtr , args , instSymId , id , storeSymId , va_cnt , vl ) ;
p - > sbp = cmShiftBufAlloc ( ctx - > cmProcCtx , NULL , 0 , 0 , 0 ) ;
p - > gdp = cmGateDetectAlloc ( ctx - > cmProcCtx , NULL , 0 , 0 , 0 , 0 ) ;
// set default values for the parameters that were not explicitely set in the va_arg list
cmDspSetDefaultDouble ( ctx , & p - > inst , kWndMsGdId , 0 , 42 ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kOnThreshPctGdId , 0 , 0.8 ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kOnThreshDbGdId , 0 , - 30.0 ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kOffThreshDbGdId , 0 , - 60.0 ) ;
return & p - > inst ;
}
cmDspRC_t _cmDspGateDetectFree ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspGateDetect_t * p = ( cmDspGateDetect_t * ) inst ;
cmGateDetectFree ( & p - > gdp ) ;
cmShiftBufFree ( & p - > sbp ) ;
//cmCtxFree(&p->ctx);
return kOkDspRC ;
}
cmDspRC_t _cmDspGateDetectReset ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspGateDetect_t * p = ( cmDspGateDetect_t * ) inst ;
cmDspRC_t rc = kOkDspRC ;
if ( ( rc = cmDspApplyAllDefaults ( ctx , inst ) ) ! = kOkDspRC )
return rc ;
double wndMs = cmDspDouble ( inst , kWndMsGdId ) ;
double sr = cmDspSampleRate ( ctx ) ;
unsigned wndSmpCnt = floor ( wndMs * sr / 1000.0 ) ;
if ( cmShiftBufInit ( p - > sbp , cmDspSamplesPerCycle ( ctx ) , wndSmpCnt , wndSmpCnt / 4 ) ! = cmOkRC )
return cmErrMsg ( & ctx - > cmCtx - > err , kInstResetFailDspRC , " The gate detector shift buffer initialization failed. " ) ;
if ( cmGateDetectInit ( p - > gdp , cmDspSamplesPerCycle ( ctx ) , cmDspDouble ( inst , kOnThreshPctGdId ) , cmDspDouble ( inst , kOnThreshDbGdId ) , cmDspDouble ( inst , kOffThreshDbGdId ) ) ! = cmOkRC )
return cmErrMsg ( & ctx - > cmCtx - > err , kInstResetFailDspRC , " The gate detector shift buffer initialization failed. " ) ;
return rc ;
}
cmDspRC_t _cmDspGateDetectExec ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspGateDetect_t * p = ( cmDspGateDetect_t * ) inst ;
unsigned iChIdx = 0 ;
const cmSample_t * ip = cmDspAudioBuf ( ctx , inst , kInGdId , iChIdx ) ;
unsigned iSmpCnt = cmDspVarRows ( inst , kInGdId ) ;
while ( cmShiftBufExec ( p - > sbp , ip , iSmpCnt ) )
{
cmGateDetectExec ( p - > gdp , p - > sbp - > outV , p - > sbp - > outN ) ;
cmDspSetDouble ( ctx , inst , kRmsGdId , p - > gdp - > rms ) ;
cmDspSetDouble ( ctx , inst , kMeanGdId , p - > gdp - > mean ) ;
if ( p - > gdp - > deltaFl )
cmDspSetBool ( ctx , inst , kGateGdId , p - > gdp - > gateFl ) ;
}
return kOkDspRC ;
}
cmDspRC_t _cmDspGateDetectRecv ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc ;
if ( ( rc = cmDspSetEvent ( ctx , inst , evt ) ) ! = kOkDspRC )
return rc ;
switch ( evt - > dstVarId )
{
case kWndMsGdId :
break ;
case kOnThreshPctGdId :
break ;
case kOnThreshDbGdId :
break ;
case kOffThreshDbGdId :
break ;
case kInGdId :
break ;
}
return rc ;
}
struct cmDspClass_str * cmGateDetectClassCons ( cmDspCtx_t * ctx )
{
cmDspClassSetup ( & _cmGateDetectDC , ctx , " GateDetect " ,
NULL ,
_cmDspGateDetectAlloc ,
_cmDspGateDetectFree ,
_cmDspGateDetectReset ,
_cmDspGateDetectExec ,
_cmDspGateDetectRecv ,
NULL , NULL ,
" Gate detector. " ) ;
return & _cmGateDetectDC ;
}
//==========================================================================================================================================
/*
The purpose of this object is to calculate , store and retrieve gain coefficents
for a set of audio channels . The gain coefficients are designed to balance the
volume of each channel relative to the others . During gain calibration
a sample of each channel is taken and it ' s average volume is determined .
After an example of all channels has been received a new set of gain coefficients
is calculated which decreases the volume of loud channels and increases the
volume of quiet channels .
The gain coefficents are made available via a set of ' gain - # # # ' output ports .
This object acts as an interface to the cmAutoGain processor .
As input it takes a channel configuration JSON file of the form :
{
ch_array :
[ [ " ch " , " ssi " , " pitch " , " midi " , " gain " ]
[ 0 , 0 , " C4 " , 60 , 1.0 ]
. . . .
[ n 0 , " C5 " , 72 , 1.0 ]
]
}
Each array in ' ch_array ' gives the configuration of a channel .
It also requires a JSON resource object of the form
gdParms :
{
medCnt : 5
avgCnt : 9
suprCnt : 6
offCnt : 3
suprCoeff : 1.400000
onThreshDb : - 53.000000
offThreshDb : - 80.000000
}
These arguments are used to configure the cmAutoGain Proessor gate detector function .
During runtime the object accepts the following action selector symbol id ' s :
a . start - begin a new calibration session
b . proc - end a calibration session and calculate new gain coeff ' s
c . cancel - cancel a calibration session
d . write - write the channel configuration file
e . print - print the current auto gain calibration state
After a ' start ' msg the object accepts channel id ' s throught its ' id ' input port .
Each ' id ' identifies the channel which it will process next .
Upon reception of a channel id the object routes subsequent audio to its
internal cmAutoGain processor until it receives the next channel id
or a ' proc ' or ' cancel ' symbol .
*/
//==========================================================================================================================================
enum
{
kChCntAgId ,
kHopAgId ,
kMedNAgId ,
kAvgNAgId ,
kSupNAgId ,
kOffNAgId ,
kSupCoefAgId ,
kOnThrAgId ,
kOffThrAgId ,
kSelAgId ,
kIdAgId ,
kInBaseAgId
} ;
typedef struct
{
cmDspInst_t inst ;
cmAutoGain * agp ;
unsigned gainBaseAgId ;
unsigned chCnt ;
unsigned chIdx ;
unsigned startSymId ;
unsigned procSymId ;
unsigned cancelSymId ;
unsigned writeSymId ;
unsigned printSymId ;
} cmDspAutoGain_t ;
cmDspClass_t _cmAutoGainDC ;
cmDspInst_t * _cmDspAutoGainAlloc ( cmDspCtx_t * ctx , cmDspClass_t * classPtr , unsigned storeSymId , unsigned instSymId , unsigned id , unsigned va_cnt , va_list vl )
{
cmDspVarArg_t args [ ] =
{
{ " chCnt " , kChCntAgId , 0 , 0 , kUIntDsvFl | kReqArgDsvFl , " Audio channel count. " } ,
{ " hop " , kHopAgId , 0 , 0 , kDoubleDsvFl | kReqArgDsvFl , " RMS hop in milliseconds. " } ,
{ " med " , kMedNAgId , 0 , 0 , kUIntDsvFl | kReqArgDsvFl , " Median filter hop count. " } ,
{ " avg " , kAvgNAgId , 0 , 0 , kUIntDsvFl | kReqArgDsvFl , " Average filter hop count. " } ,
{ " sup " , kSupNAgId , 0 , 0 , kUIntDsvFl | kReqArgDsvFl , " Supression filter hop count. " } ,
{ " off " , kOffNAgId , 0 , 0 , kUIntDsvFl | kReqArgDsvFl , " Offset filter hop count. " } ,
{ " supC " , kSupCoefAgId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kReqArgDsvFl , " Suppression coefficent. " } ,
{ " onThr " , kOnThrAgId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kReqArgDsvFl , " Onset threshold in dB. " } ,
{ " offThr " , kOffThrAgId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kReqArgDsvFl , " Offset threshold in dB. " } ,
{ " sel " , kSelAgId , 0 , 0 , kInDsvFl | kSymDsvFl | kNoArgDsvFl , " Action Selector: start | proc | cancel. " } ,
{ " id " , kIdAgId , 0 , 0 , kInDsvFl | kIntDsvFl | kNoArgDsvFl , " Channel id input. " } ,
} ;
va_list vl1 ;
unsigned i ;
// verify that at least one var arg exists
if ( va_cnt < 1 )
{
cmDspClassErr ( ctx , classPtr , kInvalidArgDspRC , " The AutoGain constructor must be given the audio channel count as its first argument. " ) ;
return NULL ;
}
2013-10-17 01:52:59 +00:00
// copy the va_list so that it can be used again in cmDspInstAlloc()
va_copy ( vl1 , vl ) ;
2012-10-30 03:52:39 +00:00
// get the first var arg which should be a filename
unsigned chCnt = va_arg ( vl , unsigned ) ;
if ( chCnt = = 0 )
{
cmDspClassErr ( ctx , classPtr , kInvalidArgDspRC , " The AutoGain constructor requires at least 1 audio channel. " ) ;
2013-10-17 01:52:59 +00:00
va_end ( vl1 ) ;
2012-10-30 03:52:39 +00:00
return NULL ;
}
unsigned fixArgCnt = sizeof ( args ) / sizeof ( args [ 0 ] ) ;
unsigned argCnt = fixArgCnt + 2 * chCnt ;
unsigned gainBaseAgId = kInBaseAgId + chCnt ;
cmDspVarArg_t a [ argCnt + 1 ] ;
assert ( fixArgCnt = = kInBaseAgId ) ;
// setup the output gain args
cmDspArgCopy ( a , argCnt , 0 , args , fixArgCnt ) ;
cmDspArgSetupN ( ctx , a , argCnt , kInBaseAgId , chCnt , " in " , kInBaseAgId , 0 , 0 , kInDsvFl | kAudioBufDsvFl , " audio in " ) ;
cmDspArgSetupN ( ctx , a , argCnt , gainBaseAgId , chCnt , " gain " , gainBaseAgId , 0 , 0 , kOutDsvFl | kDoubleDsvFl , " calibrated channel gain " ) ;
cmDspArgSetupNull ( a + argCnt ) ; // set terminating arg. flag
// instantiate the object
cmDspAutoGain_t * p = cmDspInstAlloc ( cmDspAutoGain_t , ctx , classPtr , a , instSymId , id , storeSymId , va_cnt , vl1 ) ;
// assign the current gain coefficients
for ( i = 0 ; i < chCnt ; + + i )
cmDspSetDefaultDouble ( ctx , & p - > inst , gainBaseAgId + i , 0.0 , 1.0 ) ;
// allocate the auto gain calculation proc
p - > agp = cmAutoGainAlloc ( ctx - > cmProcCtx , NULL , 0 , 0 , 0 , 0 , NULL ) ;
p - > chCnt = chCnt ;
p - > chIdx = cmInvalidIdx ;
p - > gainBaseAgId = gainBaseAgId ;
p - > startSymId = cmSymTblRegisterStaticSymbol ( ctx - > stH , " start " ) ;
p - > procSymId = cmSymTblRegisterStaticSymbol ( ctx - > stH , " proc " ) ;
p - > cancelSymId = cmSymTblRegisterStaticSymbol ( ctx - > stH , " cancel " ) ;
p - > printSymId = cmSymTblRegisterStaticSymbol ( ctx - > stH , " print " ) ;
cmDspSetDefaultSymbol ( ctx , & p - > inst , kSelAgId , p - > cancelSymId ) ;
cmDspSetDefaultInt ( ctx , & p - > inst , kIdAgId , 0 , cmInvalidId ) ;
2013-10-17 01:52:59 +00:00
va_end ( vl1 ) ;
2012-10-30 03:52:39 +00:00
return & p - > inst ;
}
cmDspRC_t _cmDspAutoGainFree ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspAutoGain_t * p = ( cmDspAutoGain_t * ) inst ;
cmAutoGainFree ( & p - > agp ) ;
return kOkDspRC ;
}
cmDspRC_t _cmDspAutoGainReset ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
rc = cmDspApplyAllDefaults ( ctx , inst ) ;
return rc ;
}
cmDspRC_t _cmDspAutoGainExec ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspAutoGain_t * p = ( cmDspAutoGain_t * ) inst ;
unsigned curInChIdx = cmDspInt ( inst , kIdAgId ) ;
if ( cmDspSymbol ( inst , kSelAgId ) = = p - > startSymId & & curInChIdx ! = cmInvalidId )
{
unsigned inChVarId = kInBaseAgId + curInChIdx ;
const cmSample_t * ip = cmDspAudioBuf ( ctx , inst , inChVarId , 0 ) ;
unsigned iSmpCnt = cmDspVarRows ( inst , inChVarId ) ;
cmAutoGainProcCh ( p - > agp , ip , iSmpCnt ) ;
}
return kOkDspRC ;
}
cmDspRC_t _cmDspAutoGainInit ( cmDspCtx_t * ctx , cmDspInst_t * inst )
{
cmDspAutoGain_t * p = ( cmDspAutoGain_t * ) inst ;
cmGateDetectParams gd ;
unsigned i ;
// collect the params into a cmGateDetectParams recd
gd . medCnt = cmDspUInt ( inst , kMedNAgId ) ;
gd . avgCnt = cmDspUInt ( inst , kAvgNAgId ) ;
gd . suprCnt = cmDspUInt ( inst , kSupNAgId ) ;
gd . offCnt = cmDspUInt ( inst , kOffNAgId ) ;
gd . suprCoeff = cmDspDouble ( inst , kSupCoefAgId ) ;
gd . onThreshDb = cmDspDouble ( inst , kOnThrAgId ) ;
gd . offThreshDb = cmDspDouble ( inst , kOffThrAgId ) ;
// setup the internal auto-gain object
if ( cmAutoGainInit ( p - > agp , cmDspSamplesPerCycle ( ctx ) , cmDspSampleRate ( ctx ) , cmDspDouble ( inst , kHopAgId ) , p - > chCnt , & gd ) ! = cmOkRC )
return cmDspInstErr ( ctx , inst , kSubSysFailDspRC , " The internal auto-gain instance could not be initialized. " ) ;
// send out gain's of 1.0 so that the input audio is not
// biased by any existing scaling.
for ( i = 0 ; i < p - > chCnt ; + + i )
cmDspSetDouble ( ctx , inst , p - > gainBaseAgId + i , 1.0 ) ;
return kOkDspRC ;
}
cmDspRC_t _cmDspAutoGainRecv ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspAutoGain_t * p = ( cmDspAutoGain_t * ) inst ;
cmDspRC_t rc = kOkDspRC ;
switch ( evt - > dstVarId )
{
case kSelAgId :
{
// store the current 'sel' state
unsigned prvSymId = cmDspSymbol ( inst , kSelAgId ) ;
// update it 'sel' to the new state
cmDspSetEvent ( ctx , inst , evt ) ;
// get the new state
unsigned newSymId = cmDspSymbol ( inst , kSelAgId ) ;
//
// if PRINTing was requested
//
if ( newSymId = = p - > printSymId )
{
cmRptPrintf ( & ctx - > cmCtx - > rpt , " Auto-Gain Report \n " ) ;
cmAutoGainPrint ( p - > agp , & ctx - > cmCtx - > rpt ) ;
goto doneLabel ;
}
//
// if calibration was CANCELLED
//
if ( newSymId = = p - > cancelSymId )
{
cmDspSetInt ( ctx , inst , kIdAgId , cmInvalidId ) ;
cmRptPrintf ( & ctx - > cmCtx - > rpt , " cancelled \n " ) ;
goto doneLabel ;
}
//
// if calibration STARTup was requested - initialize the autogain proc
//
if ( newSymId = = p - > startSymId )
{
_cmDspAutoGainInit ( ctx , inst ) ;
cmRptPrintf ( & ctx - > cmCtx - > rpt , " started \n " ) ;
goto doneLabel ;
}
//
// if calibration PROCessing was requested
//
if ( newSymId = = p - > procSymId & & prvSymId = = p - > startSymId )
{
cmRptPrintf ( & ctx - > cmCtx - > rpt , " proc \n " ) ;
// set the current channel id to 'cmInvalidId' to stop calls to
// cmAutoGainProcCh() in _cmDspAutoGainExec()
cmDspSetInt ( ctx , inst , kIdAgId , cmInvalidId ) ;
// update the auto gain coefficients
if ( cmAutoGainCalcGains ( p - > agp ) = = cmOkRC )
{
// send the new auto gain coefficients to the output ports
unsigned i ;
for ( i = 0 ; i < p - > chCnt ; + + i )
cmDspSetDouble ( ctx , inst , p - > gainBaseAgId + i , p - > agp - > chArray [ i ] . gain ) ;
}
goto doneLabel ;
}
}
break ;
case kIdAgId :
cmDspSetEvent ( ctx , inst , evt ) ;
if ( cmDspSymbol ( inst , kSelAgId ) = = p - > startSymId )
{
cmRptPrintf ( & ctx - > cmCtx - > rpt , " id:%i \n " , cmDspInt ( inst , kIdAgId ) ) ;
cmAutoGainStartCh ( p - > agp , p - > chIdx = cmDspInt ( inst , kIdAgId ) ) ;
}
break ;
default :
{ assert ( 0 ) ; }
}
doneLabel :
return rc ;
}
struct cmDspClass_str * cmAutoGainClassCons ( cmDspCtx_t * ctx )
{
cmDspClassSetup ( & _cmAutoGainDC , ctx , " AutoGain " ,
NULL ,
_cmDspAutoGainAlloc ,
_cmDspAutoGainFree ,
_cmDspAutoGainReset ,
_cmDspAutoGainExec ,
_cmDspAutoGainRecv ,
NULL , NULL ,
" Auto-gain calibrator. " ) ;
return & _cmAutoGainDC ;
}
//==========================================================================================================================================
enum
{
kHopMsEfId , // RMS window length in milliseconds
kMedCntEfId , //
kAvgCntEfId , //
kSuprCntEfId , //
kOffCntEfId , //
kSuprCoefEfId , //
kOnThrDbEfId , //
kOffThrDbEfId , //
kMaxDbEfId ,
kInEfId ,
kGateEfId ,
kRmsEfId ,
kLevelEfId ,
kOnEfId ,
kOffEfId
} ;
cmDspClass_t _cmEnvFollowDC ;
typedef struct
{
cmDspInst_t inst ;
cmShiftBuf * sbp ;
cmGateDetect2 * gdp ;
} cmDspEnvFollow_t ;
cmDspInst_t * _cmDspEnvFollowAlloc ( cmDspCtx_t * ctx , cmDspClass_t * classPtr , unsigned storeSymId , unsigned instSymId , unsigned id , unsigned va_cnt , va_list vl )
{
cmDspVarArg_t args [ ] =
{
{ " wnd " , kHopMsEfId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kOptArgDsvFl , " RMS Window length " } ,
{ " med " , kMedCntEfId , 0 , 0 , kInDsvFl | kUIntDsvFl | kOptArgDsvFl , " Median filter length. " } ,
{ " avg " , kAvgCntEfId , 0 , 0 , kInDsvFl | kUIntDsvFl | kOptArgDsvFl , " Averaging filter length. " } ,
{ " sup " , kSuprCntEfId , 0 , 0 , kInDsvFl | kUIntDsvFl | kOptArgDsvFl , " Supression filter length. " } ,
{ " off " , kOffCntEfId , 0 , 0 , kInDsvFl | kUIntDsvFl | kOptArgDsvFl , " Offset detection window length " } ,
{ " supc " , kSuprCoefEfId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kOptArgDsvFl , " Suppression shape coefficient " } ,
{ " ondb " , kOnThrDbEfId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kOptArgDsvFl , " Onset threshold dB. " } ,
{ " offdb " , kOffThrDbEfId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kOptArgDsvFl , " Offset threshold dB " } ,
{ " maxdb " , kMaxDbEfId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kOptArgDsvFl , " Max reference dB " } ,
{ " in " , kInEfId , 0 , 0 , kInDsvFl | kAudioBufDsvFl , " Audio input " } ,
{ " gate " , kGateEfId , 0 , 0 , kOutDsvFl | kBoolDsvFl , " Gate state output. " } ,
{ " rms " , kRmsEfId , 0 , 0 , kOutDsvFl | kDoubleDsvFl , " Signal level RMS " } ,
{ " level " , kLevelEfId , 0 , 0 , kOutDsvFl | kDoubleDsvFl , " Signal level 0.0-1.0 as scale between offset thresh dB and max dB " } ,
{ " ons " , kOnEfId , 0 , 0 , kOutDsvFl | kUIntDsvFl , " Onset counter " } ,
{ " offs " , kOffEfId , 0 , 0 , kOutDsvFl | kUIntDsvFl , " Offset counter " } ,
{ NULL , 0 , 0 , 0 , 0 }
} ;
cmDspEnvFollow_t * p = cmDspInstAlloc ( cmDspEnvFollow_t , ctx , classPtr , args , instSymId , id , storeSymId , va_cnt , vl ) ;
p - > sbp = cmShiftBufAlloc ( ctx - > cmProcCtx , NULL , 0 , 0 , 0 ) ;
p - > gdp = cmGateDetectAlloc2 ( ctx - > cmProcCtx , NULL , 0 , NULL ) ;
// set default values for the parameters that were not explicitely set in the va_arg list
cmDspSetDefaultDouble ( ctx , & p - > inst , kHopMsEfId , 0 , 12 ) ;
cmDspSetDefaultUInt ( ctx , & p - > inst , kMedCntEfId , 0 , 5 ) ;
cmDspSetDefaultUInt ( ctx , & p - > inst , kAvgCntEfId , 0 , 9 ) ;
cmDspSetDefaultUInt ( ctx , & p - > inst , kSuprCntEfId , 0 , 6 ) ;
cmDspSetDefaultUInt ( ctx , & p - > inst , kOffCntEfId , 0 , 3 ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kSuprCoefEfId , 0 , 1.4 ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kOnThrDbEfId , 0 , - 45 ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kOffThrDbEfId , 0 , - 80 ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kMaxDbEfId , 0 , - 10.0 ) ;
cmDspSetDefaultUInt ( ctx , & p - > inst , kOnEfId , 0 , 0 ) ;
cmDspSetDefaultUInt ( ctx , & p - > inst , kOffEfId , 0 , 0 ) ;
return & p - > inst ;
}
cmDspRC_t _cmDspEnvFollowFree ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspEnvFollow_t * p = ( cmDspEnvFollow_t * ) inst ;
cmGateDetectFree2 ( & p - > gdp ) ;
cmShiftBufFree ( & p - > sbp ) ;
return kOkDspRC ;
}
cmDspRC_t _cmDspEnvFollowReset ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspEnvFollow_t * p = ( cmDspEnvFollow_t * ) inst ;
cmDspRC_t rc = kOkDspRC ;
if ( ( rc = cmDspApplyAllDefaults ( ctx , inst ) ) ! = kOkDspRC )
return rc ;
cmGateDetectParams r ;
r . medCnt = cmDspUInt ( inst , kMedCntEfId ) ;
r . avgCnt = cmDspUInt ( inst , kAvgCntEfId ) ;
r . suprCnt = cmDspUInt ( inst , kSuprCntEfId ) ;
r . offCnt = cmDspUInt ( inst , kOffCntEfId ) ;
r . suprCoeff = cmDspDouble ( inst , kSuprCoefEfId ) ;
r . onThreshDb = cmDspDouble ( inst , kOnThrDbEfId ) ;
r . offThreshDb = cmDspDouble ( inst , kOffThrDbEfId ) ;
double sr = cmDspSampleRate ( ctx ) ;
double hopSmpCnt = floor ( sr * cmDspDouble ( inst , kHopMsEfId ) / 1000 ) ;
unsigned wndSmpCnt = floor ( r . medCnt * hopSmpCnt ) ;
if ( cmShiftBufInit ( p - > sbp , cmDspSamplesPerCycle ( ctx ) , wndSmpCnt , hopSmpCnt ) ! = cmOkRC )
return cmDspInstErr ( ctx , inst , kInstResetFailDspRC , " The gate detector shift buffer initialization failed. " ) ;
if ( cmGateDetectInit2 ( p - > gdp , cmDspSamplesPerCycle ( ctx ) , & r ) ! = cmOkRC )
return cmDspInstErr ( ctx , inst , kInstResetFailDspRC , " The gate detector shift buffer initialization failed. " ) ;
return rc ;
}
cmDspRC_t _cmDspEnvFollowExec ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspEnvFollow_t * p = ( cmDspEnvFollow_t * ) inst ;
unsigned iChIdx = 0 ;
const cmSample_t * ip = cmDspAudioBuf ( ctx , inst , kInEfId , iChIdx ) ;
unsigned iSmpCnt = cmDspVarRows ( inst , kInEfId ) ;
double maxDb = cmDspDouble ( inst , kMaxDbEfId ) ;
double offDb = cmDspDouble ( inst , kOffThrDbEfId ) ;
while ( cmShiftBufExec ( p - > sbp , ip , iSmpCnt ) )
{
cmGateDetectExec2 ( p - > gdp , p - > sbp - > outV , p - > sbp - > outN ) ;
// RMS is going out at the audio rate - maybe there should be an option
// to send it only when the gate changes - this could significantly
// cut down on unnecessary transmission if the RMS is only used
// when the gate changes
cmDspSetDouble ( ctx , inst , kRmsEfId , p - > gdp - > rms ) ;
double rmsDb = p - > gdp - > rms < 0.00001 ? - 100.0 : 20.0 * log10 ( p - > gdp - > rms ) ;
double level = maxDb < = offDb ? 0 : fabs ( ( offDb - cmMax ( offDb , cmMin ( maxDb , rmsDb ) ) ) / ( maxDb - offDb ) ) ;
cmDspSetDouble ( ctx , inst , kLevelEfId , level ) ;
if ( p - > gdp - > onFl | | p - > gdp - > offFl )
{
cmDspSetBool ( ctx , inst , kGateEfId , p - > gdp - > gateFl ) ;
if ( p - > gdp - > onFl )
cmDspSetUInt ( ctx , inst , kOnEfId , cmDspUInt ( inst , kOnEfId ) + 1 ) ;
if ( p - > gdp - > offFl )
cmDspSetUInt ( ctx , inst , kOffEfId , cmDspUInt ( inst , kOffEfId ) + 1 ) ;
}
}
return kOkDspRC ;
}
cmDspRC_t _cmDspEnvFollowRecv ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc ;
cmDspEnvFollow_t * p = ( cmDspEnvFollow_t * ) inst ;
if ( ( rc = cmDspSetEvent ( ctx , inst , evt ) ) = = kOkDspRC )
{
switch ( evt - > dstVarId )
{
case kOnThrDbEfId :
cmGateDetectSetOnThreshDb2 ( p - > gdp , cmDspDouble ( inst , kOnThrDbEfId ) ) ;
break ;
case kOffThrDbEfId :
cmGateDetectSetOffThreshDb2 ( p - > gdp , cmDspDouble ( inst , kOffThrDbEfId ) ) ;
break ;
}
}
return rc ;
}
struct cmDspClass_str * cmEnvFollowClassCons ( cmDspCtx_t * ctx )
{
cmDspClassSetup ( & _cmEnvFollowDC , ctx , " EnvFollow " ,
NULL ,
_cmDspEnvFollowAlloc ,
_cmDspEnvFollowFree ,
_cmDspEnvFollowReset ,
_cmDspEnvFollowExec ,
_cmDspEnvFollowRecv ,
NULL , NULL ,
" Envelope follower and gate detector. " ) ;
return & _cmEnvFollowDC ;
}
//==========================================================================================================================================
// Fade in and out an arbitrary number of audio signals based on gate signals.
// When the gate is high the signal fades in and when the gate is low the signal fades out.
// Constructor Args:
// Required: Count of input and output channels.
// Optional: Fade time in milliseconds.
//
// Inputs:
// bool Control gates
// audio Input audio.
// Outputs:
// audio Output audio
// double Channel gains.
enum
{
kChCntXfId ,
kFadeTimeMsXfId ,
kMstrGateXfId ,
2013-08-13 22:21:42 +00:00
kFadeInTimeMsXfId ,
kFadeOutTimeMsXfId ,
2013-11-03 19:51:26 +00:00
kResetXfId ,
2012-10-30 03:52:39 +00:00
kOnXfId ,
kOffXfId ,
kGateBaseXfId ,
} ;
cmDspClass_t _cmXfaderDC ;
typedef struct
{
cmDspInst_t inst ;
cmXfader * xfdp ;
unsigned inBaseXfId ;
unsigned outBaseXfId ;
2012-12-18 22:46:07 +00:00
unsigned stateBaseXfId ;
2012-10-30 03:52:39 +00:00
unsigned gainBaseXfId ;
unsigned chCnt ;
bool * chGateV ;
unsigned onSymId ;
unsigned offSymId ;
} cmDspXfader_t ;
cmDspInst_t * _cmDspXfaderAlloc ( cmDspCtx_t * ctx , cmDspClass_t * classPtr , unsigned storeSymId , unsigned instSymId , unsigned id , unsigned va_cnt , va_list vl )
{
cmDspVarArg_t args [ ] =
{
2013-08-13 22:21:42 +00:00
{ " chs " , kChCntXfId , 0 , 0 , kUIntDsvFl | kReqArgDsvFl , " Input and Output channel count " } ,
{ " ms " , kFadeTimeMsXfId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kOptArgDsvFl , " Fade time in milliseonds. " } ,
{ " mgate " , kMstrGateXfId , 0 , 0 , kInDsvFl | kBoolDsvFl | kOptArgDsvFl , " Master gate - can be used to set all gates. " } ,
{ " ims " , kFadeInTimeMsXfId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kOptArgDsvFl , " Fade in time in milliseonds. " } ,
{ " oms " , kFadeOutTimeMsXfId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kOptArgDsvFl , " Fade out time in milliseonds. " } ,
2013-11-03 19:51:26 +00:00
{ " reset " , kResetXfId , 0 , 0 , kInDsvFl | kBoolDsvFl , " Jump to gate states rather than fade. " } ,
2013-08-13 22:21:42 +00:00
{ " on " , kOnXfId , 0 , 0 , kOutDsvFl | kSymDsvFl , " Send 'on' when all ch's transition from off to on. " } ,
{ " off " , kOffXfId , 0 , 0 , kOutDsvFl | kSymDsvFl , " Send 'off' when all ch's transition from on to off. " } ,
2012-10-30 03:52:39 +00:00
} ;
if ( va_cnt < 1 )
{
cmDspClassErr ( ctx , classPtr , kInvalidArgDspRC , " The Xfader object must be given a channel count argument. " ) ;
return NULL ;
}
va_list vl1 ;
va_copy ( vl1 , vl ) ;
2012-12-18 22:46:07 +00:00
unsigned chCnt = va_arg ( vl , int ) ;
unsigned fixArgCnt = sizeof ( args ) / sizeof ( args [ 0 ] ) ;
unsigned argCnt = fixArgCnt + 5 * chCnt ;
unsigned inBaseXfId = kGateBaseXfId + chCnt ;
unsigned outBaseXfId = inBaseXfId + chCnt ;
unsigned stateBaseXfId = outBaseXfId + chCnt ;
unsigned gainBaseXfId = stateBaseXfId + chCnt ;
2012-10-30 03:52:39 +00:00
cmDspVarArg_t a [ argCnt + 1 ] ;
// setup the input gate detectors and the output gain args
cmDspArgCopy ( a , argCnt , 0 , args , fixArgCnt ) ;
cmDspArgSetupN ( ctx , a , argCnt , kGateBaseXfId , chCnt , " gate " , kGateBaseXfId , 0 , 0 , kInDsvFl | kBoolDsvFl , " gate flags " ) ;
cmDspArgSetupN ( ctx , a , argCnt , inBaseXfId , chCnt , " in " , inBaseXfId , 0 , 0 , kInDsvFl | kAudioBufDsvFl , " audio input " ) ;
cmDspArgSetupN ( ctx , a , argCnt , outBaseXfId , chCnt , " out " , outBaseXfId , 0 , 1 , kOutDsvFl | kAudioBufDsvFl , " audio output " ) ;
2012-12-18 22:46:07 +00:00
cmDspArgSetupN ( ctx , a , argCnt , stateBaseXfId , chCnt , " state " , stateBaseXfId , 0 , 0 , kOutDsvFl | kBoolDsvFl , " current fader state " ) ;
2012-10-30 03:52:39 +00:00
cmDspArgSetupN ( ctx , a , argCnt , gainBaseXfId , chCnt , " gain " , gainBaseXfId , 0 , 0 , kOutDsvFl | kDoubleDsvFl , " gain output " ) ;
cmDspArgSetupNull ( a + argCnt ) ; // set terminating arg. flag
cmDspXfader_t * p = cmDspInstAlloc ( cmDspXfader_t , ctx , classPtr , a , instSymId , id , storeSymId , va_cnt , vl1 ) ;
double fadeTimeMs = cmDspDouble ( & p - > inst , kFadeTimeMsXfId ) ;
p - > xfdp = cmXfaderAlloc ( ctx - > cmProcCtx , NULL , cmDspSampleRate ( ctx ) , chCnt , fadeTimeMs ) ;
p - > inBaseXfId = inBaseXfId ;
p - > outBaseXfId = outBaseXfId ;
2012-12-18 22:46:07 +00:00
p - > stateBaseXfId = stateBaseXfId ;
2012-10-30 03:52:39 +00:00
p - > gainBaseXfId = gainBaseXfId ;
p - > chCnt = chCnt ;
p - > chGateV = cmMemAllocZ ( bool , p - > chCnt ) ;
p - > onSymId = cmSymTblRegisterStaticSymbol ( ctx - > stH , " on " ) ;
p - > offSymId = cmSymTblRegisterStaticSymbol ( ctx - > stH , " off " ) ;
// set default values for the parameters that were not explicitely set in the va_arg list
cmDspSetDefaultDouble ( ctx , & p - > inst , kFadeTimeMsXfId , 0 , 100 ) ;
cmDspSetDefaultBool ( ctx , & p - > inst , kMstrGateXfId , false , false ) ;
2012-12-18 22:46:07 +00:00
cmDspSetDefaultSymbol ( ctx , & p - > inst , kOnXfId , p - > onSymId ) ;
cmDspSetDefaultSymbol ( ctx , & p - > inst , kOffXfId , p - > offSymId ) ;
int i ;
for ( i = 0 ; i < chCnt ; + + i )
cmDspSetDefaultBool ( ctx , & p - > inst , stateBaseXfId + i , false , false ) ;
2013-10-17 01:52:59 +00:00
va_end ( vl1 ) ;
2012-10-30 03:52:39 +00:00
return & p - > inst ;
}
cmDspRC_t _cmDspXfaderFree ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspXfader_t * p = ( cmDspXfader_t * ) inst ;
cmMemFree ( p - > chGateV ) ;
cmXfaderFree ( & p - > xfdp ) ;
return kOkDspRC ;
}
cmDspRC_t _cmDspXfaderReset ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
rc = cmDspApplyAllDefaults ( ctx , inst ) ;
cmDspXfader_t * p = ( cmDspXfader_t * ) inst ;
// TODO: zeroing of output audio buffers should be built into cmDspApplyAllDefaults().
unsigned i ;
for ( i = 0 ; i < p - > chCnt ; + + i )
cmDspZeroAudioBuf ( ctx , inst , p - > outBaseXfId + i ) ;
return rc ;
}
cmDspRC_t _cmDspXfaderExec ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = cmOkRC ;
cmDspXfader_t * p = ( cmDspXfader_t * ) inst ;
unsigned i ;
// update the internal cross fader by providing it with new gate settings and generate new gain values
cmXfaderExec ( p - > xfdp , cmDspSamplesPerCycle ( ctx ) , p - > chGateV , p - > chCnt ) ;
for ( i = 0 ; i < p - > chCnt ; + + i )
{
unsigned n = cmDspAudioBufSmpCount ( ctx , inst , p - > outBaseXfId + i , 0 ) ;
cmSample_t * op = cmDspAudioBuf ( ctx , inst , p - > outBaseXfId + i , 0 ) ;
const cmSample_t * ip = cmDspAudioBuf ( ctx , inst , p - > inBaseXfId + i , 0 ) ;
2013-11-02 01:33:03 +00:00
cmSample_t gain = ( cmSample_t ) p - > xfdp - > chArray [ i ] . ep_gain ;
2013-11-03 19:51:26 +00:00
2012-10-30 03:52:39 +00:00
if ( op ! = NULL )
{
if ( ip = = NULL )
cmVOS_Zero ( op , n ) ;
else
cmVOS_MultVVS ( op , n , ip , gain ) ;
}
2012-12-18 22:46:07 +00:00
if ( p - > xfdp - > chArray [ i ] . onFl )
2015-10-22 21:59:38 +00:00
{
2012-12-18 22:46:07 +00:00
cmDspSetBool ( ctx , inst , p - > stateBaseXfId + i , true ) ;
2015-10-22 21:59:38 +00:00
}
2012-12-18 22:46:07 +00:00
if ( p - > xfdp - > chArray [ i ] . offFl )
2015-10-22 21:59:38 +00:00
{
2012-12-18 22:46:07 +00:00
cmDspSetBool ( ctx , inst , p - > stateBaseXfId + i , false ) ;
2015-10-22 21:59:38 +00:00
}
2012-10-30 03:52:39 +00:00
// send the gain output
cmDspSetDouble ( ctx , inst , p - > gainBaseXfId + i , gain ) ;
2013-11-03 19:51:26 +00:00
2012-10-30 03:52:39 +00:00
}
if ( p - > xfdp - > onFl )
cmDspSetSymbol ( ctx , inst , kOnXfId , p - > onSymId ) ;
if ( p - > xfdp - > offFl )
cmDspSetSymbol ( ctx , inst , kOffXfId , p - > offSymId ) ;
return rc ;
}
cmDspRC_t _cmDspXfaderRecv ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc ;
cmDspXfader_t * p = ( cmDspXfader_t * ) inst ;
if ( ( rc = cmDspSetEvent ( ctx , inst , evt ) ) ! = kOkDspRC )
return rc ;
switch ( evt - > dstVarId )
{
case kFadeTimeMsXfId :
// if this is an xfade time event then transfer the new xfade time to the xfade proc
cmXfaderSetXfadeTime ( p - > xfdp , cmDspDouble ( inst , kFadeTimeMsXfId ) ) ;
break ;
case kMstrGateXfId :
{
bool fl = cmDspBool ( inst , kMstrGateXfId ) ;
unsigned i ;
for ( i = 0 ; i < p - > chCnt ; + + i )
p - > chGateV [ i ] = fl ;
}
break ;
2013-08-13 22:21:42 +00:00
case kFadeInTimeMsXfId :
cmXfaderSetXfadeInTime ( p - > xfdp , cmDspDouble ( inst , kFadeInTimeMsXfId ) ) ;
break ;
case kFadeOutTimeMsXfId :
cmXfaderSetXfadeOutTime ( p - > xfdp , cmDspDouble ( inst , kFadeOutTimeMsXfId ) ) ;
break ;
2013-11-03 19:51:26 +00:00
case kResetXfId :
{
cmXfaderExec ( p - > xfdp , cmDspSamplesPerCycle ( ctx ) , p - > chGateV , p - > chCnt ) ;
cmXfaderJumpToDestinationGain ( p - > xfdp ) ;
// force the chGateV[] to match the xfaders state
int i ;
for ( i = 0 ; i < p - > chCnt ; + + i )
{
bool gateFl = p - > xfdp - > chArray [ i ] . gateFl ;
p - > chGateV [ i ] = gateFl ;
cmDspSetBool ( ctx , inst , p - > stateBaseXfId + i , gateFl ) ;
cmDspSetDouble ( ctx , inst , p - > gainBaseXfId + i , gateFl ? 1.0 : 0.0 ) ;
}
}
break ;
2012-10-30 03:52:39 +00:00
}
// record gate changes into p->chGateV[] for later use in _cmDspXfaderExec().
if ( kGateBaseXfId < = evt - > dstVarId & & evt - > dstVarId < kGateBaseXfId + p - > chCnt )
{
p - > chGateV [ evt - > dstVarId - kGateBaseXfId ] = cmDspBool ( inst , evt - > dstVarId ) ;
}
return rc ;
}
struct cmDspClass_str * cmXfaderClassCons ( cmDspCtx_t * ctx )
{
cmDspClassSetup ( & _cmXfaderDC , ctx , " Xfader " ,
NULL ,
_cmDspXfaderAlloc ,
_cmDspXfaderFree ,
_cmDspXfaderReset ,
_cmDspXfaderExec ,
_cmDspXfaderRecv ,
NULL , NULL ,
" Cross fade gain generator. " ) ;
return & _cmXfaderDC ;
}
//==========================================================================================================================================
enum
{
kFnCcId ,
kSelCcId ,
kDoneCcId ,
kGainBaseCcId
} ;
cmDspClass_t _cmChCfgDC ;
typedef struct
{
cmDspInst_t inst ;
cmChCfg * ccp ;
unsigned midiBaseCcId ;
unsigned hzBaseCcId ;
unsigned chBaseCcId ;
unsigned nsflBaseCcId ;
unsigned nshzBaseCcId ;
unsigned printSymId ;
unsigned writeSymId ;
unsigned nsCmdSymId ;
unsigned hzCmdSymId ;
unsigned resetSymId ;
} cmDspChCfg_t ;
cmDspInst_t * _cmDspChCfgAlloc ( cmDspCtx_t * ctx , cmDspClass_t * classPtr , unsigned storeSymId , unsigned instSymId , unsigned id , unsigned va_cnt , va_list vl )
{
cmDspVarArg_t args [ ] =
{
{ " fn " , kFnCcId , 0 , 0 , kStrzDsvFl | kReqArgDsvFl , " Channel configuration JSON file name. " } ,
{ " sel " , kSelCcId , 0 , 0 , kInDsvFl | kSymDsvFl , " Action selector: print | write | ns | reset " } ,
{ " done " , kDoneCcId , 0 , 0 , kOutDsvFl | kSymDsvFl , " Trigger following action. " }
} ;
if ( va_cnt < 1 )
{
cmDspClassErr ( ctx , classPtr , kInvalidArgDspRC , " The channel configuration object must be given a file name argument. " ) ;
return NULL ;
}
va_list vl1 ;
va_copy ( vl1 , vl ) ;
const cmChar_t * chCfgFn = va_arg ( vl , cmChar_t * ) ;
cmChCfg * ccp = cmChCfgAlloc ( ctx - > cmProcCtx , NULL , ctx - > cmCtx , chCfgFn ) ;
if ( ccp = = NULL | | ccp - > chCnt = = 0 )
{
cmDspClassErr ( ctx , classPtr , kInvalidArgDspRC , " The channel configuration object could not be initialized with the file name '%s'. " , cmStringNullGuard ( chCfgFn ) ) ;
return NULL ;
}
unsigned chCnt = ccp - > chCnt ;
unsigned nsChCnt = ccp - > nsChCnt ;
unsigned fixArgCnt = sizeof ( args ) / sizeof ( args [ 0 ] ) ;
unsigned argCnt = fixArgCnt + 5 * chCnt + nsChCnt ;
unsigned midiBaseCcId = kGainBaseCcId + chCnt ;
unsigned hzBaseCcId = midiBaseCcId + chCnt ;
unsigned chBaseCcId = hzBaseCcId + chCnt ;
unsigned nsflBaseCcId = chBaseCcId + chCnt ;
unsigned nshzBaseCcId = nsflBaseCcId + chCnt ;
cmDspChCfg_t * p = NULL ;
cmDspVarArg_t a [ argCnt + 1 ] ;
unsigned i , j ;
// setup the input gate detectors and the output gain args
cmDspArgCopy ( a , argCnt , 0 , args , fixArgCnt ) ;
cmDspArgSetupN ( ctx , a , argCnt , kGainBaseCcId , chCnt , " gain " , kGainBaseCcId , 0 , 0 , kSendDfltDsvFl | kInDsvFl | kOutDsvFl | kDoubleDsvFl , " Gain input and output. " ) ;
cmDspArgSetupN ( ctx , a , argCnt , midiBaseCcId , chCnt , " midi " , midiBaseCcId , 0 , 0 , kSendDfltDsvFl | kOutDsvFl | kUIntDsvFl , " MIDI pitch output " ) ;
cmDspArgSetupN ( ctx , a , argCnt , hzBaseCcId , chCnt , " hz " , hzBaseCcId , 0 , 0 , kSendDfltDsvFl | kOutDsvFl | kDoubleDsvFl , " pitch output in Hz " ) ;
cmDspArgSetupN ( ctx , a , argCnt , chBaseCcId , chCnt , " ch " , chBaseCcId , 0 , 0 , kSendDfltDsvFl | kOutDsvFl | kUIntDsvFl , " Audio channel index " ) ;
cmDspArgSetupN ( ctx , a , argCnt , nsflBaseCcId , chCnt , " nsfl " , nsflBaseCcId , 0 , 0 , kOutDsvFl | kBoolDsvFl , " noise shaper enables " ) ;
cmDspArgSetupN ( ctx , a , argCnt , nshzBaseCcId , nsChCnt , " nshz " , nshzBaseCcId , 0 , 0 , kOutDsvFl | kDoubleDsvFl , " noise-shaper pitch output in Hz " ) ;
cmDspArgSetupNull ( a + argCnt ) ; // set terminating arg. flag
if ( ( p = cmDspInstAlloc ( cmDspChCfg_t , ctx , classPtr , a , instSymId , id , storeSymId , va_cnt , vl1 ) ) = = NULL )
return NULL ;
p - > ccp = ccp ;
p - > midiBaseCcId = midiBaseCcId ;
p - > hzBaseCcId = hzBaseCcId ;
p - > chBaseCcId = chBaseCcId ;
p - > nsflBaseCcId = nsflBaseCcId ;
p - > nshzBaseCcId = nshzBaseCcId ;
p - > writeSymId = cmSymTblRegisterStaticSymbol ( ctx - > stH , " write " ) ;
p - > printSymId = cmSymTblRegisterStaticSymbol ( ctx - > stH , " print " ) ;
p - > nsCmdSymId = cmSymTblRegisterStaticSymbol ( ctx - > stH , " ns " ) ;
p - > hzCmdSymId = cmSymTblRegisterStaticSymbol ( ctx - > stH , " hz " ) ;
p - > resetSymId = cmSymTblRegisterStaticSymbol ( ctx - > stH , " reset " ) ;
for ( i = 0 , j = 0 ; i < chCnt ; + + i )
{
double hz = cmMidiToHz ( ccp - > chArray [ i ] . midi ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kGainBaseCcId + i , 0.0 , ccp - > chArray [ i ] . gain ) ;
cmDspSetDefaultUInt ( ctx , & p - > inst , p - > midiBaseCcId + i , 0 , ccp - > chArray [ i ] . midi ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , p - > hzBaseCcId + i , 0.0 , hz ) ;
cmDspSetDefaultUInt ( ctx , & p - > inst , p - > chBaseCcId + i , 0 , ccp - > chArray [ i ] . ch ) ;
cmDspSetDefaultBool ( ctx , & p - > inst , p - > nsflBaseCcId + i , false , false ) ;
if ( ccp - > chArray [ i ] . nsFl )
{
cmDspSetDefaultDouble ( ctx , & p - > inst , p - > nshzBaseCcId + j , 0.0 , hz ) ;
+ + j ;
}
}
cmDspSetDefaultSymbol ( ctx , & p - > inst , kDoneCcId , cmInvalidId ) ;
cmDspSetDefaultSymbol ( ctx , & p - > inst , kSelCcId , cmInvalidId ) ;
return & p - > inst ;
}
cmDspRC_t _cmDspChCfgFree ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspChCfg_t * p = ( cmDspChCfg_t * ) inst ;
cmChCfgFree ( & p - > ccp ) ;
return kOkDspRC ;
}
cmDspRC_t _cmDspChCfgReset ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
rc = cmDspApplyAllDefaults ( ctx , inst ) ;
return rc ;
}
cmDspRC_t _cmDspChCfgRecv ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc ;
cmDspChCfg_t * p = ( cmDspChCfg_t * ) inst ;
if ( ( rc = cmDspSetEvent ( ctx , inst , evt ) ) = = kOkDspRC )
{
if ( evt - > dstVarId = = kSelCcId )
{
unsigned selId = cmDspSymbol ( inst , kSelCcId ) ;
if ( selId = = p - > resetSymId )
{
_cmDspChCfgReset ( ctx , inst , evt ) ;
}
else
if ( selId = = p - > hzCmdSymId )
{
unsigned i ;
// snd the hz
for ( i = 0 ; i < p - > ccp - > chCnt ; + + i )
cmDspSetDouble ( ctx , inst , p - > hzBaseCcId + i , cmDspDouble ( inst , p - > hzBaseCcId + i ) ) ;
}
else
if ( selId = = p - > nsCmdSymId )
{
cmRptPrintf ( ctx - > rpt , " ChCfg:NS \n " ) ;
unsigned i ;
// send the ns flags
for ( i = 0 ; i < p - > ccp - > chCnt ; + + i )
cmDspSetBool ( ctx , inst , p - > nsflBaseCcId + i , p - > ccp - > chArray [ i ] . nsFl ) ;
// snd the ns hz
for ( i = 0 ; i < p - > ccp - > nsChCnt ; + + i )
cmDspSetDouble ( ctx , inst , p - > nshzBaseCcId + i , cmDspDouble ( inst , p - > nshzBaseCcId + i ) ) ;
cmDspSetSymbol ( ctx , inst , kDoneCcId , p - > nsCmdSymId ) ;
}
else
if ( selId = = p - > printSymId )
{
cmRptPrintf ( & ctx - > cmCtx - > rpt , " Channel Cfg Report \n " ) ;
cmChCfgPrint ( p - > ccp , ctx - > rpt ) ;
}
else
{
if ( selId = = p - > writeSymId )
{
unsigned i ;
cmRptPrintf ( & ctx - > cmCtx - > rpt , " writing \n " ) ;
// copy the gain values into the internal chCfg object ...
for ( i = 0 ; i < p - > ccp - > chCnt ; + + i )
p - > ccp - > chArray [ i ] . gain = cmDspDouble ( inst , kGainBaseCcId + i ) ;
// ... and write the object
cmChCfgWrite ( p - > ccp ) ;
}
}
}
}
return rc ;
}
struct cmDspClass_str * cmChCfgClassCons ( cmDspCtx_t * ctx )
{
cmDspClassSetup ( & _cmChCfgDC , ctx , " ChCfg " ,
NULL ,
_cmDspChCfgAlloc ,
_cmDspChCfgFree ,
_cmDspChCfgReset ,
NULL ,
_cmDspChCfgRecv ,
NULL , NULL ,
" PP Channel Configuration Object. " ) ;
return & _cmChCfgDC ;
}
//==========================================================================================================================================
enum
{
kRsrcCdId ,
kMaxTimeSpanCdId ,
kMinNoteCntCdId ,
kDetectCdId ,
kCountCdId ,
kGateBaseCdId
} ;
cmDspClass_t _cmChordDetectDC ;
typedef struct
{
cmDspInst_t inst ;
cmChordDetect * cdp ;
unsigned rmsBaseCdId ;
unsigned chCnt ;
bool * chGateV ; // chGateV[ chCnt ]
cmReal_t * chRmsV ; // chRmsV[ chCnt ]
unsigned * chEnaV ; // chEnaV[ chCnt ]
unsigned count ;
} cmDspChordDetect_t ;
cmDspInst_t * _cmDspChordDetectAlloc ( cmDspCtx_t * ctx , cmDspClass_t * classPtr , unsigned storeSymId , unsigned instSymId , unsigned id , unsigned va_cnt , va_list vl )
{
cmDspVarArg_t args [ ] =
{
{ " rsrc " , kRsrcCdId , 0 , 0 , kStrzDsvFl | kReqArgDsvFl , " Channel enable flag array. " } ,
{ " span " , kMaxTimeSpanCdId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kOptArgDsvFl , " Max. onset time span. " } ,
{ " notes " , kMinNoteCntCdId , 0 , 0 , kInDsvFl | kUIntDsvFl | kOptArgDsvFl , " Min. note count per chord. " } ,
{ " detect " , kDetectCdId , 0 , 0 , kOutDsvFl | kBoolDsvFl , " Chord detect flag. " } ,
{ " count " , kCountCdId , 0 , 0 , kOutDsvFl | kUIntDsvFl , " Count of chords detected since last reset. " }
} ;
if ( va_cnt < 1 )
{
cmDspClassErr ( ctx , classPtr , kInvalidArgDspRC , " The chord detector must be given a channel enable flags array resource argument . " ) ;
return NULL ;
}
va_list vl1 ;
va_copy ( vl1 , vl ) ;
const cmChar_t * rsrc = va_arg ( vl , const cmChar_t * ) ;
unsigned * enaV = NULL ;
unsigned chCnt = 0 ;
if ( cmDspRsrcUIntArray ( ctx - > dspH , & chCnt , & enaV , rsrc , NULL ) ! = kOkDspRC )
{
2013-10-17 01:52:59 +00:00
va_end ( vl1 ) ;
2012-10-30 03:52:39 +00:00
cmDspClassErr ( ctx , classPtr , kInvalidArgDspRC , " The chord detector channel index resource '%s' could not be read. " , cmStringNullGuard ( rsrc ) ) ;
return NULL ;
}
//cmRptPrintf(ctx->rpt,"cd %s chs:%i\n",rsrc,chCnt);
unsigned fixArgCnt = sizeof ( args ) / sizeof ( args [ 0 ] ) ;
unsigned argCnt = fixArgCnt + 2 * chCnt ;
unsigned rmsBaseCdId = kGateBaseCdId + chCnt ;
cmDspVarArg_t a [ argCnt + 1 ] ;
unsigned i ;
cmDspChordDetect_t * p ;
// setup the input gate detectors and the output gain args
cmDspArgCopy ( a , argCnt , 0 , args , fixArgCnt ) ;
cmDspArgSetupN ( ctx , a , argCnt , kGateBaseCdId , chCnt , " gate " , kGateBaseCdId , 0 , 0 , kInDsvFl | kOutDsvFl | kBoolDsvFl , " Channel gate input and output. " ) ;
cmDspArgSetupN ( ctx , a , argCnt , rmsBaseCdId , chCnt , " rms " , rmsBaseCdId , 0 , 0 , kInDsvFl | kOutDsvFl | kDoubleDsvFl , " Channel RMS input and output " ) ;
cmDspArgSetupNull ( a + argCnt ) ; // set terminating arg. flag
if ( ( p = cmDspInstAlloc ( cmDspChordDetect_t , ctx , classPtr , a , instSymId , id , storeSymId , va_cnt , vl1 ) ) = = NULL )
return NULL ;
double dfltMaxTimeSpanMs = 50.0 ;
unsigned dfltMinNoteCnt = 2 ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kMaxTimeSpanCdId , 0.0 , dfltMaxTimeSpanMs ) ;
cmDspSetDefaultUInt ( ctx , & p - > inst , kMinNoteCntCdId , 0 , dfltMinNoteCnt ) ;
cmDspSetDefaultBool ( ctx , & p - > inst , kDetectCdId , false , false ) ;
cmDspSetDefaultUInt ( ctx , & p - > inst , kCountCdId , 0 , 0 ) ;
for ( i = 0 ; i < chCnt ; + + i )
{
cmDspSetDefaultBool ( ctx , & p - > inst , kGateBaseCdId + i , false , false ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , rmsBaseCdId + i , 0.0 , 0.0 ) ;
}
p - > cdp = cmChordDetectAlloc ( ctx - > cmProcCtx , NULL , cmDspSampleRate ( ctx ) , chCnt , cmDspDouble ( & p - > inst , kMaxTimeSpanCdId ) , cmDspUInt ( & p - > inst , kMinNoteCntCdId ) ) ;
p - > rmsBaseCdId = rmsBaseCdId ;
p - > chCnt = chCnt ;
p - > chGateV = cmMemAllocZ ( bool , chCnt ) ;
p - > chRmsV = cmMemAllocZ ( cmReal_t , chCnt ) ;
p - > chEnaV = enaV ;
2013-10-17 01:52:59 +00:00
va_end ( vl1 ) ;
2012-10-30 03:52:39 +00:00
return & p - > inst ;
}
cmDspRC_t _cmDspChordDetectFree ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspChordDetect_t * p = ( cmDspChordDetect_t * ) inst ;
cmChordDetectFree ( & p - > cdp ) ;
cmMemFree ( p - > chGateV ) ;
cmMemFree ( p - > chRmsV ) ;
return kOkDspRC ;
}
cmDspRC_t _cmDspChordDetectReset ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
rc = cmDspApplyAllDefaults ( ctx , inst ) ;
return rc ;
}
cmDspRC_t _cmDspChordDetectExec ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspChordDetect_t * p = ( cmDspChordDetect_t * ) inst ;
cmChordDetectExec ( p - > cdp , cmDspSamplesPerCycle ( ctx ) , p - > chGateV , p - > chRmsV , p - > chCnt ) ;
if ( p - > cdp - > detectFl )
{
unsigned i ;
for ( i = 0 ; i < p - > chCnt ; + + i )
{
bool fl = p - > cdp - > chArray [ i ] . chordFl ;
cmDspSetBool ( ctx , inst , kGateBaseCdId + i , fl ) ;
cmDspSetDouble ( ctx , inst , p - > rmsBaseCdId + i , fl ? p - > cdp - > chArray [ i ] . candRMS : 0 ) ;
}
cmDspSetBool ( ctx , inst , kDetectCdId , true ) ;
cmDspSetUInt ( ctx , inst , kCountCdId , cmDspUInt ( inst , kCountCdId ) + 1 ) ;
}
cmVOB_Zero ( p - > chGateV , p - > chCnt ) ;
cmVOR_Zero ( p - > chRmsV , p - > chCnt ) ;
return rc ;
}
cmDspRC_t _cmDspChordDetectRecv ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspChordDetect_t * p = ( cmDspChordDetect_t * ) inst ;
if ( kGateBaseCdId < = evt - > dstVarId & & evt - > dstVarId < kGateBaseCdId + p - > chCnt )
{
unsigned idx = evt - > dstVarId - kGateBaseCdId ;
if ( p - > chEnaV [ idx ] )
p - > chGateV [ idx ] = cmDsvGetBool ( evt - > valuePtr ) ;
//cmRptPrintf(ctx->rpt,"cd gate:%i e:%i v:%i\n",idx,p->chEnaV[idx],p->chGateV[idx]);
}
else
if ( p - > rmsBaseCdId < = evt - > dstVarId & & evt - > dstVarId < p - > rmsBaseCdId + p - > chCnt )
{
unsigned idx = evt - > dstVarId - p - > rmsBaseCdId ;
if ( p - > chEnaV [ idx ] )
p - > chRmsV [ idx ] = cmDsvGetReal ( evt - > valuePtr ) ;
}
else
{
if ( ( rc = cmDspSetEvent ( ctx , inst , evt ) ) = = kOkDspRC )
{
switch ( evt - > dstVarId )
{
case kMaxTimeSpanCdId :
cmChordDetectSetSpanMs ( p - > cdp , cmDspDouble ( inst , kMaxTimeSpanCdId ) ) ;
break ;
case kMinNoteCntCdId :
p - > cdp - > minNotesPerChord = cmDspUInt ( inst , kMinNoteCntCdId ) ;
break ;
}
}
}
return rc ;
}
struct cmDspClass_str * cmChordDetectClassCons ( cmDspCtx_t * ctx )
{
cmDspClassSetup ( & _cmChordDetectDC , ctx , " ChordDetect " ,
NULL ,
_cmDspChordDetectAlloc ,
_cmDspChordDetectFree ,
_cmDspChordDetectReset ,
_cmDspChordDetectExec ,
_cmDspChordDetectRecv ,
NULL , NULL ,
" Chord detector. " ) ;
return & _cmChordDetectDC ;
}
//==========================================================================================================================================
enum
{
kTimeFaId ,
kGateFaId ,
kInFaId ,
kGainFaId ,
kOutFaId
} ;
cmDspClass_t _cmFaderDC ;
typedef struct
{
cmDspInst_t inst ;
cmFader * fdp ;
} cmDspFader_t ;
cmDspInst_t * _cmDspFaderAlloc ( cmDspCtx_t * ctx , cmDspClass_t * classPtr , unsigned storeSymId , unsigned instSymId , unsigned id , unsigned va_cnt , va_list vl )
{
cmDspVarArg_t args [ ] =
{
{ " time " , kTimeFaId , 0 , 0 , kDoubleDsvFl | kOptArgDsvFl , " Fade time in milliseconds. " } ,
{ " gate " , kGateFaId , 0 , 0 , kInDsvFl | kBoolDsvFl , " Gate control signal. " } ,
{ " in " , kInFaId , 0 , 0 , kInDsvFl | kAudioBufDsvFl , " Audio input. " } ,
{ " gain " , kGainFaId , 0 , 0 , kOutDsvFl | kDoubleDsvFl , " gain output. " } ,
{ " out " , kOutFaId , 0 , 0 , kOutDsvFl | kAudioBufDsvFl , " Audio out. " } ,
{ NULL , 0 , 0 , 0 , 0 , NULL }
} ;
cmDspFader_t * p ;
if ( ( p = cmDspInstAlloc ( cmDspFader_t , ctx , classPtr , args , instSymId , id , storeSymId , va_cnt , vl ) ) = = NULL )
return NULL ;
double dfltFadeTimeMs = 100.0 ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kTimeFaId , 0.0 , dfltFadeTimeMs ) ;
p - > fdp = cmFaderAlloc ( ctx - > cmProcCtx , NULL , cmDspSampleRate ( ctx ) , dfltFadeTimeMs ) ;
return & p - > inst ;
}
cmDspRC_t _cmDspFaderFree ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspFader_t * p = ( cmDspFader_t * ) inst ;
cmFaderFree ( & p - > fdp ) ;
return kOkDspRC ;
}
cmDspRC_t _cmDspFaderReset ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspFader_t * p = ( cmDspFader_t * ) inst ;
rc = cmDspApplyAllDefaults ( ctx , inst ) ;
cmDspZeroAudioBuf ( ctx , inst , kOutFaId ) ;
cmFaderSetFadeTime ( p - > fdp , cmDspDouble ( inst , kTimeFaId ) ) ;
return rc ;
}
cmDspRC_t _cmDspFaderExec ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspFader_t * p = ( cmDspFader_t * ) inst ;
unsigned n = cmDspAudioBufSmpCount ( ctx , inst , kOutFaId , 0 ) ;
cmSample_t * op = cmDspAudioBuf ( ctx , inst , kOutFaId , 0 ) ;
const cmSample_t * ip = cmDspAudioBuf ( ctx , inst , kInFaId , 0 ) ;
cmFaderExec ( p - > fdp , n , cmDspBool ( inst , kGateFaId ) , false , ip , op ) ;
cmDspSetDouble ( ctx , inst , kGainFaId , p - > fdp - > gain ) ;
return rc ;
}
cmDspRC_t _cmDspFaderRecv ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspFader_t * p = ( cmDspFader_t * ) inst ;
if ( ( rc = cmDspSetEvent ( ctx , inst , evt ) ) = = kOkDspRC )
{
if ( evt - > dstVarId = = kTimeFaId )
cmFaderSetFadeTime ( p - > fdp , cmDspDouble ( inst , kTimeFaId ) ) ;
}
return rc ;
}
struct cmDspClass_str * cmFaderClassCons ( cmDspCtx_t * ctx )
{
cmDspClassSetup ( & _cmFaderDC , ctx , " Fader " ,
NULL ,
_cmDspFaderAlloc ,
_cmDspFaderFree ,
_cmDspFaderReset ,
_cmDspFaderExec ,
_cmDspFaderRecv ,
NULL , NULL ,
" Audio fade in/out controller. " ) ;
return & _cmFaderDC ;
}
//==========================================================================================================================================
enum
{
kChCntNsId ,
kTrigNsId ,
kDoneNsId ,
kGateBaseNsId
} ;
enum
{
kGroupNonNsId ,
kGroup0NsId ,
kGroup1NsId
} ;
cmDspClass_t _cmNoteSelectDC ;
typedef struct
{
cmDspInst_t inst ;
unsigned chCnt ;
unsigned rmsBaseNsId ;
unsigned gate0BaseNsId ;
unsigned gate1BaseNsId ;
unsigned gate2BaseNsId ;
unsigned gate3BaseNsId ;
unsigned gate4BaseNsId ;
bool * chGateV ; // chGateV[chCnt]
cmReal_t * chRmsV ; // chRmsV[ chCnt ];
unsigned * chGroupV ; // chGroupV[ chCnt ] (0=non-chord 1=low/high 2=middle)
unsigned count ;
unsigned doneSymId ;
} cmDspNoteSelect_t ;
cmDspInst_t * _cmDspNoteSelectAlloc ( cmDspCtx_t * ctx , cmDspClass_t * classPtr , unsigned storeSymId , unsigned instSymId , unsigned id , unsigned va_cnt , va_list vl )
{
cmDspVarArg_t args [ ] =
{
{ " ch_cnt " , kChCntNsId , 0 , 0 , kUIntDsvFl | kReqArgDsvFl , " Channel count. " } ,
{ " trig " , kTrigNsId , 0 , 0 , kInDsvFl | kBoolDsvFl , " Trigger note selection. " } ,
{ " done " , kDoneNsId , 0 , 0 , kOutDsvFl | kSymDsvFl , " Sends 'done' after new set of outputs have been sent. " } ,
} ;
if ( va_cnt < 1 )
{
cmDspClassErr ( ctx , classPtr , kInvalidArgDspRC , " The note selector must be given a channel count argument . " ) ;
return NULL ;
}
va_list vl1 ;
unsigned CD0chanN = 0 ;
unsigned CD1chanN = 0 ;
unsigned * CD0chan = NULL ;
unsigned * CD1chan = NULL ;
const cmChar_t * CD0rsrc = " CD0chan " ;
const cmChar_t * CD1rsrc = " CD1chan " ;
if ( cmDspRsrcUIntArray ( ctx - > dspH , & CD0chanN , & CD0chan , CD0rsrc , NULL ) ! = kOkDspRC )
{
cmDspClassErr ( ctx , classPtr , kInvalidArgDspRC , " The chord detector channel index resource '%s' could not be read. " , cmStringNullGuard ( CD0rsrc ) ) ;
return NULL ;
}
if ( cmDspRsrcUIntArray ( ctx - > dspH , & CD1chanN , & CD1chan , CD1rsrc , NULL ) ! = kOkDspRC )
{
cmDspClassErr ( ctx , classPtr , kInvalidArgDspRC , " The chord detector channel index resource '%s' could not be read. " , cmStringNullGuard ( CD1rsrc ) ) ;
return NULL ;
}
2013-10-17 01:52:59 +00:00
va_copy ( vl1 , vl ) ;
2012-10-30 03:52:39 +00:00
unsigned chCnt = va_arg ( vl , unsigned ) ;
unsigned fixArgCnt = sizeof ( args ) / sizeof ( args [ 0 ] ) ;
unsigned argCnt = fixArgCnt + 7 * chCnt ;
unsigned rmsBaseNsId = kGateBaseNsId + 1 * chCnt ;
unsigned gate0BaseNsId = kGateBaseNsId + 2 * chCnt ;
unsigned gate1BaseNsId = kGateBaseNsId + 3 * chCnt ;
unsigned gate2BaseNsId = kGateBaseNsId + 4 * chCnt ;
unsigned gate3BaseNsId = kGateBaseNsId + 5 * chCnt ;
unsigned gate4BaseNsId = kGateBaseNsId + 6 * chCnt ;
cmDspVarArg_t a [ argCnt + 1 ] ;
unsigned i ;
cmDspNoteSelect_t * p ;
// setup the input gate detectors and the output gain args
cmDspArgCopy ( a , argCnt , 0 , args , fixArgCnt ) ;
cmDspArgSetupN ( ctx , a , argCnt , kGateBaseNsId , chCnt , " gate " , kGateBaseNsId , 0 , 0 , kInDsvFl | kBoolDsvFl , " Channel gate input. " ) ;
cmDspArgSetupN ( ctx , a , argCnt , rmsBaseNsId , chCnt , " rms " , rmsBaseNsId , 0 , 0 , kInDsvFl | kDoubleDsvFl , " Channel RMS input " ) ;
cmDspArgSetupN ( ctx , a , argCnt , gate0BaseNsId , chCnt , " gate-0 " , gate0BaseNsId , 0 , 0 , kOutDsvFl | kBoolDsvFl , " Channel gate set 0 output. " ) ;
cmDspArgSetupN ( ctx , a , argCnt , gate1BaseNsId , chCnt , " gate-1 " , gate1BaseNsId , 0 , 0 , kOutDsvFl | kBoolDsvFl , " Channel gate set 1 output. " ) ;
cmDspArgSetupN ( ctx , a , argCnt , gate2BaseNsId , chCnt , " gate-2 " , gate2BaseNsId , 0 , 0 , kOutDsvFl | kBoolDsvFl , " Channel gate set 2 output. " ) ;
cmDspArgSetupN ( ctx , a , argCnt , gate3BaseNsId , chCnt , " gate-3 " , gate3BaseNsId , 0 , 0 , kOutDsvFl | kBoolDsvFl , " Channel gate set 3 output. " ) ;
cmDspArgSetupN ( ctx , a , argCnt , gate4BaseNsId , chCnt , " gate-4 " , gate4BaseNsId , 0 , 0 , kOutDsvFl | kBoolDsvFl , " Channel gate set 4 output. " ) ;
cmDspArgSetupNull ( a + argCnt ) ; // set terminating arg. flag
if ( ( p = cmDspInstAlloc ( cmDspNoteSelect_t , ctx , classPtr , a , instSymId , id , storeSymId , va_cnt , vl1 ) ) = = NULL )
return NULL ;
cmDspSetDefaultBool ( ctx , & p - > inst , kTrigNsId , false , false ) ;
cmDspSetDefaultSymbol ( ctx , & p - > inst , kDoneNsId , cmInvalidId ) ;
p - > rmsBaseNsId = rmsBaseNsId ;
p - > gate0BaseNsId = gate0BaseNsId ;
p - > gate1BaseNsId = gate1BaseNsId ;
p - > gate2BaseNsId = gate2BaseNsId ;
p - > gate3BaseNsId = gate3BaseNsId ;
p - > gate4BaseNsId = gate4BaseNsId ;
p - > chCnt = chCnt ;
p - > chGateV = cmMemAllocZ ( bool , chCnt ) ;
p - > chRmsV = cmMemAllocZ ( cmReal_t , chCnt ) ;
p - > chGroupV = cmMemAllocZ ( unsigned , chCnt ) ;
p - > doneSymId = cmSymTblRegisterStaticSymbol ( ctx - > stH , " done " ) ;
for ( i = 0 ; i < CD0chanN ; + + i )
{
if ( CD0chan [ i ] > = chCnt )
cmDspInstErr ( ctx , & p - > inst , kInvalidArgDspRC , " The chord detector resource array '%s' value %i is out of range %i. " , cmStringNullGuard ( CD0rsrc ) , CD0chan [ i ] , chCnt ) ;
else
p - > chGroupV [ CD0chan [ i ] ] = kGroup0NsId ;
}
for ( i = 0 ; i < CD1chanN ; + + i )
{
if ( CD1chan [ i ] > = chCnt )
cmDspInstErr ( ctx , & p - > inst , kInvalidArgDspRC , " The chord detector resource array '%s' value %i is out of range %i. " , cmStringNullGuard ( CD1rsrc ) , CD1chan [ i ] , chCnt ) ;
else
p - > chGroupV [ CD1chan [ i ] ] = kGroup1NsId ;
}
for ( i = 0 ; i < chCnt ; + + i )
{
cmDspSetDefaultDouble ( ctx , & p - > inst , rmsBaseNsId + i , 0.0 , 0.0 ) ;
cmDspSetDefaultBool ( ctx , & p - > inst , gate0BaseNsId + i , false , false ) ;
cmDspSetDefaultBool ( ctx , & p - > inst , gate1BaseNsId + i , false , false ) ;
cmDspSetDefaultBool ( ctx , & p - > inst , gate2BaseNsId + i , false , false ) ;
cmDspSetDefaultBool ( ctx , & p - > inst , gate3BaseNsId + i , false , false ) ;
// the non-chord channel selections should always be on
cmDspSetDefaultBool ( ctx , & p - > inst , gate4BaseNsId + i , false , p - > chGroupV [ i ] = = kGroupNonNsId ) ;
}
2013-10-17 01:52:59 +00:00
va_end ( vl1 ) ;
2012-10-30 03:52:39 +00:00
return & p - > inst ;
}
cmDspRC_t _cmDspNoteSelectFree ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspNoteSelect_t * p = ( cmDspNoteSelect_t * ) inst ;
cmMemFree ( p - > chGateV ) ;
cmMemFree ( p - > chRmsV ) ;
cmMemFree ( p - > chGroupV ) ;
return kOkDspRC ;
}
cmDspRC_t _cmDspNoteSelectReset ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspNoteSelect_t * p = ( cmDspNoteSelect_t * ) inst ;
rc = cmDspApplyAllDefaults ( ctx , inst ) ;
cmVOR_Zero ( p - > chRmsV , p - > chCnt ) ;
return rc ;
}
cmDspRC_t _cmDspNoteSelectRecv ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspNoteSelect_t * p = ( cmDspNoteSelect_t * ) inst ;
// store incoming gate values
if ( kGateBaseNsId < = evt - > dstVarId & & evt - > dstVarId < kGateBaseNsId + p - > chCnt )
p - > chGateV [ evt - > dstVarId - kGateBaseNsId ] = cmDsvGetBool ( evt - > valuePtr ) ;
else
// store incoming RMS values
if ( p - > rmsBaseNsId < = evt - > dstVarId & & evt - > dstVarId < p - > rmsBaseNsId + p - > chCnt )
p - > chRmsV [ evt - > dstVarId - p - > rmsBaseNsId ] = cmDsvGetReal ( evt - > valuePtr ) ;
else
{
// if a chord detection was triggered
if ( ( rc = cmDspSetEvent ( ctx , inst , evt ) ) = = kOkDspRC & & evt - > dstVarId = = kTrigNsId )
{
unsigned i ;
cmReal_t maxRms = 0 ;
unsigned maxIdx = cmInvalidIdx ;
for ( i = 1 ; i < p - > chCnt ; + + i )
{
// if this channel had an onset and is a possible chord note and is the max RMS chord note
if ( p - > chGroupV [ i ] ! = kGroupNonNsId & & p - > chGateV [ i ] & & ( maxIdx = = cmInvalidIdx | | p - > chRmsV [ i ] > maxRms ) )
{
maxRms = p - > chRmsV [ i ] ;
maxIdx = i ;
}
}
for ( i = 0 ; i < p - > chCnt ; + + i )
{
bool fl = p - > chGroupV [ i ] ! = kGroupNonNsId ;
bool chosenFl = fl & & i = = maxIdx ;
bool otherFl = fl & & i ! = maxIdx & & p - > chGateV [ i ] ;
bool cd0Fl = p - > chGroupV [ i ] = = kGroup0NsId & & ( ! otherFl ) & & ( ! chosenFl ) ;
bool cd1Fl = p - > chGroupV [ i ] = = kGroup1NsId & & ( ! otherFl ) & & ( ! chosenFl ) ;
// gate set 0: set output gate for max chord note
cmDspSetBool ( ctx , inst , p - > gate0BaseNsId + i , chosenFl ) ;
// gate set 1: set output gate for non-max chord notes
cmDspSetBool ( ctx , inst , p - > gate1BaseNsId + i , otherFl ) ;
// gate set 2: set output gate for non-chord notes
cmDspSetBool ( ctx , inst , p - > gate2BaseNsId + i , cd0Fl ) ;
// gate set 3: set output gate for non-chord notes
cmDspSetBool ( ctx , inst , p - > gate3BaseNsId + i , cd1Fl ) ;
// gate set 4: set output gate for non-chord notes
cmDspSetBool ( ctx , inst , p - > gate4BaseNsId + i , ! fl ) ;
}
// send the 'done' symbol to notify the gate receivers that the
// new set of gates is complete
cmDspSetSymbol ( ctx , inst , kDoneNsId , p - > doneSymId ) ;
// zero the RMS vector
cmVOR_Zero ( p - > chRmsV , p - > chCnt ) ;
}
}
return rc ;
}
struct cmDspClass_str * cmNoteSelectClassCons ( cmDspCtx_t * ctx )
{
cmDspClassSetup ( & _cmNoteSelectDC , ctx , " NoteSelect " ,
NULL ,
_cmDspNoteSelectAlloc ,
_cmDspNoteSelectFree ,
_cmDspNoteSelectReset ,
NULL ,
_cmDspNoteSelectRecv ,
NULL , NULL ,
" Chord detector. " ) ;
return & _cmNoteSelectDC ;
}
//==========================================================================================================================================
enum
{
kTrigNnId ,
kDoneNnId ,
kGateBaseNnId
} ;
cmDspClass_t _cmNetNoteSelectDC ;
# define _cmNetNoteSelPortCnt (10)
typedef struct
{
cmDspInst_t inst ;
unsigned chCnt ;
unsigned rmsBaseNnId ;
unsigned gateBaseNNId [ _cmNetNoteSelPortCnt ] ;
bool * chGateV ; // chGateV[chCnt]
cmReal_t * chRmsV ; // chRmsV[ chCnt ];
unsigned * portChCntV ; // portChCntV[ 10 ]
unsigned * portBaseIdV ; // portBaseIdV[ 10 ]
unsigned * chPortV ; // chPortV[ chCnt ]
unsigned * chPortIdxV ; // chPortIdxV[ chCnt ]
unsigned * ncPortV ; // ncPortV[ chCnt ]
unsigned * ncPortIdxV ; // ncPortIdxV[ chCnt ]
unsigned count ;
unsigned doneSymId ;
} cmDspNetNoteSelect_t ;
cmDspInst_t * _cmDspNetNoteSelectAlloc ( cmDspCtx_t * ctx , cmDspClass_t * classPtr , unsigned storeSymId , unsigned instSymId , unsigned id , unsigned va_cnt , va_list vl )
{
unsigned chCnt = 0 ;
const cmChar_t * label = NULL ;
const cmChar_t * chPortRsrc = " nsChSelChV " ;
unsigned * chPortV = NULL ;
const cmChar_t * chPortIdxRsrc = " nsChSelChIdxV " ;
unsigned * chPortIdxV = NULL ;
const cmChar_t * ncPortRsrc = " nsNcSelChV " ;
unsigned * ncPortV = NULL ;
const cmChar_t * ncPortIdxRsrc = " nsNcSelChIdxV " ;
unsigned * ncPortIdxV = NULL ;
unsigned i , j , n ;
cmDspVarArg_t args [ ] =
{
{ " trig " , kTrigNnId , 0 , 0 , kInDsvFl | kBoolDsvFl , " Trigger note selection. " } ,
{ " done " , kDoneNnId , 0 , 0 , kOutDsvFl | kSymDsvFl , " Sends 'done' after new set of outputs have been sent. " } ,
} ;
if ( cmDspRsrcUIntArray ( ctx - > dspH , & chCnt , & chPortV , label = chPortRsrc , NULL ) ! = kOkDspRC )
{
cmDspClassErr ( ctx , classPtr , kRsrcNotFoundDspRC , " The resource '%s' could not be read. " , label ) ;
return NULL ;
}
if ( cmDspRsrcUIntArray ( ctx - > dspH , & n , & chPortIdxV , label = chPortIdxRsrc , NULL ) ! = kOkDspRC )
{
cmDspClassErr ( ctx , classPtr , kRsrcNotFoundDspRC , " The resource '%s' could not be read. " , label ) ;
return NULL ;
}
assert ( n = = chCnt ) ;
if ( cmDspRsrcUIntArray ( ctx - > dspH , & n , & ncPortV , label = ncPortRsrc , NULL ) ! = kOkDspRC )
{
cmDspClassErr ( ctx , classPtr , kRsrcNotFoundDspRC , " The resource '%s' could not be read. " , label ) ;
return NULL ;
}
assert ( n = = chCnt ) ;
if ( cmDspRsrcUIntArray ( ctx - > dspH , & n , & ncPortIdxV , label = ncPortIdxRsrc , NULL ) ! = kOkDspRC )
{
cmDspClassErr ( ctx , classPtr , kRsrcNotFoundDspRC , " The resource '%s' could not be read. " , label ) ;
return NULL ;
}
assert ( n = = chCnt ) ;
unsigned fixArgCnt = sizeof ( args ) / sizeof ( args [ 0 ] ) ;
unsigned rmsBaseNnId = kGateBaseNnId + chCnt ;
// get the count of ch's on each port
unsigned * portChCntV = cmLhAllocZ ( ctx - > lhH , unsigned , _cmNetNoteSelPortCnt ) ;
unsigned * portBaseIdV = cmLhAllocZ ( ctx - > lhH , unsigned , _cmNetNoteSelPortCnt ) ;
for ( i = 0 ; i < _cmNetNoteSelPortCnt ; + + i )
{
// get the count of ch's in the ith gate output port
portChCntV [ i ] = cmVOU_Count ( chPortV , chCnt , i ) + cmVOU_Count ( ncPortV , chCnt , i ) ;
// ports 1 and 6 are duplicates of ports 0 and 5
if ( i = = 1 | | i = = 6 )
portChCntV [ i ] = portChCntV [ i - 1 ] ;
// set the base port id for this port
if ( i > 0 )
portBaseIdV [ i ] = portBaseIdV [ i - 1 ] + portChCntV [ i - 1 ] ;
else
portBaseIdV [ i ] = rmsBaseNnId + chCnt ;
}
unsigned argCnt = fixArgCnt + ( 2 * chCnt ) + cmVOU_Sum ( portChCntV , _cmNetNoteSelPortCnt ) ;
cmDspVarArg_t a [ argCnt + 1 ] ;
cmDspNetNoteSelect_t * p ;
// setup the input gate detectors and the output gain args
cmDspArgCopy ( a , argCnt , 0 , args , fixArgCnt ) ;
cmDspArgSetupN ( ctx , a , argCnt , kGateBaseNnId , chCnt , " gate " , kGateBaseNnId , 0 , 0 , kInDsvFl | kBoolDsvFl , " Channel gate input. " ) ;
cmDspArgSetupN ( ctx , a , argCnt , rmsBaseNnId , chCnt , " rms " , rmsBaseNnId , 0 , 0 , kInDsvFl | kDoubleDsvFl , " Channel RMS input " ) ;
cmDspArgSetupN ( ctx , a , argCnt , portBaseIdV [ 0 ] , portChCntV [ 0 ] , " gate-0 " , portBaseIdV [ 0 ] , 0 , 0 , kOutDsvFl | kBoolDsvFl , " Channel gate set 0 output. " ) ;
cmDspArgSetupN ( ctx , a , argCnt , portBaseIdV [ 1 ] , portChCntV [ 1 ] , " gate-1 " , portBaseIdV [ 1 ] , 0 , 0 , kOutDsvFl | kBoolDsvFl , " Channel gate set 1 output. " ) ;
cmDspArgSetupN ( ctx , a , argCnt , portBaseIdV [ 2 ] , portChCntV [ 2 ] , " gate-2 " , portBaseIdV [ 2 ] , 0 , 0 , kOutDsvFl | kBoolDsvFl , " Channel gate set 2 output. " ) ;
cmDspArgSetupN ( ctx , a , argCnt , portBaseIdV [ 3 ] , portChCntV [ 3 ] , " gate-3 " , portBaseIdV [ 3 ] , 0 , 0 , kOutDsvFl | kBoolDsvFl , " Channel gate set 3 output. " ) ;
cmDspArgSetupN ( ctx , a , argCnt , portBaseIdV [ 4 ] , portChCntV [ 4 ] , " gate-4 " , portBaseIdV [ 4 ] , 0 , 0 , kOutDsvFl | kBoolDsvFl , " Channel gate set 4 output. " ) ;
cmDspArgSetupN ( ctx , a , argCnt , portBaseIdV [ 5 ] , portChCntV [ 5 ] , " gate-5 " , portBaseIdV [ 5 ] , 0 , 0 , kOutDsvFl | kBoolDsvFl , " Channel gate set 5 output. " ) ;
cmDspArgSetupN ( ctx , a , argCnt , portBaseIdV [ 6 ] , portChCntV [ 6 ] , " gate-6 " , portBaseIdV [ 6 ] , 0 , 0 , kOutDsvFl | kBoolDsvFl , " Channel gate set 6 output. " ) ;
cmDspArgSetupN ( ctx , a , argCnt , portBaseIdV [ 7 ] , portChCntV [ 7 ] , " gate-7 " , portBaseIdV [ 7 ] , 0 , 0 , kOutDsvFl | kBoolDsvFl , " Channel gate set 7 output. " ) ;
cmDspArgSetupN ( ctx , a , argCnt , portBaseIdV [ 8 ] , portChCntV [ 8 ] , " gate-8 " , portBaseIdV [ 8 ] , 0 , 0 , kOutDsvFl | kBoolDsvFl , " Channel gate set 8 output. " ) ;
cmDspArgSetupN ( ctx , a , argCnt , portBaseIdV [ 9 ] , portChCntV [ 9 ] , " gate-9 " , portBaseIdV [ 9 ] , 0 , 0 , kOutDsvFl | kBoolDsvFl , " Channel gate set 9 output. " ) ;
cmDspArgSetupNull ( a + argCnt ) ; // set terminating arg. flag
if ( ( p = cmDspInstAlloc ( cmDspNetNoteSelect_t , ctx , classPtr , a , instSymId , id , storeSymId , 0 , vl ) ) = = NULL )
return NULL ;
cmDspSetDefaultBool ( ctx , & p - > inst , kTrigNnId , false , false ) ;
cmDspSetDefaultSymbol ( ctx , & p - > inst , kDoneNnId , cmInvalidId ) ;
p - > rmsBaseNnId = rmsBaseNnId ;
p - > chCnt = chCnt ;
p - > chGateV = cmMemAllocZ ( bool , chCnt ) ;
p - > chRmsV = cmMemAllocZ ( cmReal_t , chCnt ) ;
p - > portChCntV = portChCntV ;
p - > portBaseIdV = portBaseIdV ;
p - > doneSymId = cmSymTblRegisterStaticSymbol ( ctx - > stH , " done " ) ;
p - > chPortV = chPortV ;
p - > chPortIdxV = chPortIdxV ;
p - > ncPortV = ncPortV ;
p - > ncPortIdxV = ncPortIdxV ;
for ( i = 0 ; i < chCnt ; + + i )
{
cmDspSetDefaultBool ( ctx , & p - > inst , kGateBaseNnId + i , false , false ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , rmsBaseNnId + i , 0.0 , 0.0 ) ;
}
for ( i = 0 ; i < _cmNetNoteSelPortCnt ; + + i )
for ( j = 0 ; j < p - > portChCntV [ i ] ; + + j )
cmDspSetDefaultBool ( ctx , & p - > inst , p - > portBaseIdV [ i ] + j , false , false ) ;
return & p - > inst ;
}
cmDspRC_t _cmDspNetNoteSelectFree ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspNetNoteSelect_t * p = ( cmDspNetNoteSelect_t * ) inst ;
cmMemFree ( p - > chGateV ) ;
cmMemFree ( p - > chRmsV ) ;
return kOkDspRC ;
}
cmDspRC_t _cmDspNetNoteSelectReset ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspNetNoteSelect_t * p = ( cmDspNetNoteSelect_t * ) inst ;
rc = cmDspApplyAllDefaults ( ctx , inst ) ;
cmVOR_Zero ( p - > chRmsV , p - > chCnt ) ;
return rc ;
}
cmDspRC_t _cmDspNetNoteSelectRecv ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspNetNoteSelect_t * p = ( cmDspNetNoteSelect_t * ) inst ;
// store incoming gate values
if ( kGateBaseNnId < = evt - > dstVarId & & evt - > dstVarId < kGateBaseNnId + p - > chCnt )
{
p - > chGateV [ evt - > dstVarId - kGateBaseNnId ] = cmDsvGetBool ( evt - > valuePtr ) ;
//unsigned idx = evt->dstVarId - kGateBaseNnId;
//cmRptPrintf(ctx->rpt,"ns gate:%i %i\n",idx, p->chGateV[ idx ]);
}
else
// store incoming RMS values
if ( p - > rmsBaseNnId < = evt - > dstVarId & & evt - > dstVarId < p - > rmsBaseNnId + p - > chCnt )
{
p - > chRmsV [ evt - > dstVarId - p - > rmsBaseNnId ] = cmDsvGetReal ( evt - > valuePtr ) ;
}
else
{
// if a chord detection was triggered
if ( ( rc = cmDspSetEvent ( ctx , inst , evt ) ) = = kOkDspRC & & evt - > dstVarId = = kTrigNnId )
{
unsigned i ;
cmReal_t maxRms = 0 ;
unsigned maxIdx = cmInvalidIdx ;
for ( i = 1 ; i < p - > chCnt ; + + i )
{
// if this channel had an onset and is a possible chord note and is the max RMS chord note
if ( p - > chGateV [ i ] & & ( maxIdx = = cmInvalidIdx | | p - > chRmsV [ i ] > maxRms ) )
{
maxRms = p - > chRmsV [ i ] ;
maxIdx = i ;
}
}
for ( i = 0 ; i < p - > chCnt ; + + i )
{
bool chosenFl = i = = maxIdx ;
bool otherFl = i ! = maxIdx & & p - > chGateV [ i ] ;
bool nonFl = chosenFl = = false & & otherFl = = false ;
unsigned k ;
// if this is a chord channel
if ( p - > chPortV [ i ] ! = cmInvalidIdx )
{
// get the port associated with this chord note
k = p - > chPortV [ i ] ;
assert ( k + 1 < _cmNetNoteSelPortCnt ) ;
assert ( p - > chPortIdxV [ i ] < p - > portChCntV [ k ] & & p - > chPortIdxV [ i ] < p - > portChCntV [ k + 1 ] ) ;
// set the chosen and other gate outputs based on the state of
// chosenFl and otherFl
cmDspSetBool ( ctx , inst , p - > portBaseIdV [ k ] + p - > chPortIdxV [ i ] , chosenFl ) ;
cmDspSetBool ( ctx , inst , p - > portBaseIdV [ k + 1 ] + p - > chPortIdxV [ i ] , otherFl ) ;
}
// all channels have a 'single' note channel
assert ( p - > ncPortV [ i ] ! = cmInvalidIdx ) ;
k = p - > ncPortV [ i ] ;
assert ( k < _cmNetNoteSelPortCnt ) ;
assert ( p - > ncPortIdxV [ i ] < p - > portChCntV [ k ] ) ;
cmDspSetBool ( ctx , inst , p - > portBaseIdV [ k ] + p - > ncPortIdxV [ i ] , nonFl ) ;
}
// send the 'done' symbol to notify the gate receivers that the
// new set of gates is complete
cmDspSetSymbol ( ctx , inst , kDoneNnId , p - > doneSymId ) ;
// zero the RMS vector
cmVOR_Zero ( p - > chRmsV , p - > chCnt ) ;
}
}
return rc ;
}
struct cmDspClass_str * cmNetNoteSelectClassCons ( cmDspCtx_t * ctx )
{
cmDspClassSetup ( & _cmNetNoteSelectDC , ctx , " NetNoteSelect " ,
NULL ,
_cmDspNetNoteSelectAlloc ,
_cmDspNetNoteSelectFree ,
_cmDspNetNoteSelectReset ,
NULL ,
_cmDspNetNoteSelectRecv ,
NULL , NULL ,
" Chord detector. " ) ;
return & _cmNetNoteSelectDC ;
}
//==========================================================================================================================================
enum
{
kBypassCfId ,
kMinHzCfId ,
kFbFlCfId ,
kHzCfId ,
kAlphaCfId ,
kInCfId ,
kOutCfId
} ;
cmDspClass_t _cmCombFiltDC ;
typedef struct
{
cmDspInst_t inst ;
cmCombFilt * cfp ;
} cmDspCombFilt_t ;
cmDspInst_t * _cmDspCombFiltAlloc ( cmDspCtx_t * ctx , cmDspClass_t * classPtr , unsigned storeSymId , unsigned instSymId , unsigned id , unsigned va_cnt , va_list vl )
{
cmDspVarArg_t args [ ] =
{
{ " bypass " , kBypassCfId , 0 , 0 , kInDsvFl | kBoolDsvFl | kReqArgDsvFl , " Bypass enable flag. " } ,
{ " minhz " , kMinHzCfId , 0 , 0 , kDoubleDsvFl | kReqArgDsvFl , " Minimum frequency limit. " } ,
{ " fb " , kFbFlCfId , 0 , 0 , kInDsvFl | kBoolDsvFl | kReqArgDsvFl , " Configure the filter in feedback mode. " } ,
{ " hz " , kHzCfId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kReqArgDsvFl , " Lowest comb frequency. " } ,
{ " alpha " , kAlphaCfId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kReqArgDsvFl , " Filter coefficent. " } ,
{ " in " , kInCfId , 0 , 0 , kInDsvFl | kAudioBufDsvFl , " Audio input. " } ,
{ " out " , kOutCfId , 0 , 1 , kOutDsvFl | kAudioBufDsvFl , " Audio out. " } ,
{ NULL , 0 , 0 , 0 , 0 , NULL }
} ;
cmDspCombFilt_t * p ;
if ( ( p = cmDspInstAlloc ( cmDspCombFilt_t , ctx , classPtr , args , instSymId , id , storeSymId , va_cnt , vl ) ) = = NULL )
return NULL ;
p - > cfp = cmCombFiltAlloc ( ctx - > cmProcCtx , NULL ,
cmDspSampleRate ( ctx ) ,
cmDspBool ( & p - > inst , kFbFlCfId ) ,
cmDspDouble ( & p - > inst , kMinHzCfId ) ,
cmDspDouble ( & p - > inst , kAlphaCfId ) ,
cmDspDouble ( & p - > inst , kHzCfId ) ,
cmDspBool ( & p - > inst , kBypassCfId ) ) ;
return & p - > inst ;
}
cmDspRC_t _cmDspCombFiltFree ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspCombFilt_t * p = ( cmDspCombFilt_t * ) inst ;
cmCombFiltFree ( & p - > cfp ) ;
return kOkDspRC ;
}
cmDspRC_t _cmDspCombFiltReset ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspCombFilt_t * p = ( cmDspCombFilt_t * ) inst ;
rc = cmDspApplyAllDefaults ( ctx , inst ) ;
cmDspZeroAudioBuf ( ctx , inst , kOutCfId ) ;
cmCombFiltInit ( p - > cfp ,
cmDspSampleRate ( ctx ) ,
cmDspBool ( inst , kFbFlCfId ) ,
cmDspDouble ( inst , kMinHzCfId ) ,
cmDspDouble ( inst , kAlphaCfId ) ,
cmDspDouble ( inst , kHzCfId ) ,
cmDspBool ( inst , kBypassCfId ) ) ;
return rc ;
}
cmDspRC_t _cmDspCombFiltExec ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspCombFilt_t * p = ( cmDspCombFilt_t * ) inst ;
unsigned n = cmDspAudioBufSmpCount ( ctx , inst , kOutCfId , 0 ) ;
cmSample_t * op = cmDspAudioBuf ( ctx , inst , kOutCfId , 0 ) ;
const cmSample_t * ip = cmDspAudioBuf ( ctx , inst , kInCfId , 0 ) ;
cmCombFiltExec ( p - > cfp , ip , op , n ) ;
return rc ;
}
cmDspRC_t _cmDspCombFiltRecv ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspCombFilt_t * p = ( cmDspCombFilt_t * ) inst ;
if ( ( rc = cmDspSetEvent ( ctx , inst , evt ) ) = = kOkDspRC )
{
switch ( evt - > dstVarId )
{
case kHzCfId :
cmCombFiltSetHz ( p - > cfp , cmDspDouble ( inst , evt - > dstVarId ) ) ;
//printf("%s hz:%f\n",cmSymTblLabel(ctx->stH,inst->symId),cmDspDouble(inst,evt->dstVarId));
break ;
case kAlphaCfId :
cmCombFiltSetAlpha ( p - > cfp , cmDspDouble ( inst , evt - > dstVarId ) ) ;
break ;
case kBypassCfId :
p - > cfp - > bypassFl = cmDspBool ( inst , evt - > dstVarId ) ;
break ;
}
}
return rc ;
}
struct cmDspClass_str * cmCombFiltClassCons ( cmDspCtx_t * ctx )
{
cmDspClassSetup ( & _cmCombFiltDC , ctx , " CombFilt " ,
NULL ,
_cmDspCombFiltAlloc ,
_cmDspCombFiltFree ,
_cmDspCombFiltReset ,
_cmDspCombFiltExec ,
_cmDspCombFiltRecv ,
NULL , NULL ,
" Comb Filter " ) ;
return & _cmCombFiltDC ;
}
//==========================================================================================================================================
enum
{
kPortCntSoId ,
kOpSoId ,
kOutSoId ,
kBaseOpdSoId
} ;
cmDspClass_t _cmScalarOpDC ;
struct cmDspScalarOp_str ;
typedef cmDspRC_t ( * _cmDspScalarOpFunc_t ) ( cmDspCtx_t * ctx , cmDspInst_t * inst ) ;
typedef struct cmDspScalar_str
{
cmDspInst_t inst ;
_cmDspScalarOpFunc_t func ;
unsigned inPortCnt ;
} cmDspScalarOp_t ;
cmDspRC_t _cmDspScalarOpFuncMult ( cmDspCtx_t * ctx , cmDspInst_t * inst )
{
cmDspScalarOp_t * p = ( cmDspScalarOp_t * ) inst ;
double val = 1.0 ;
unsigned i ;
for ( i = 0 ; i < p - > inPortCnt ; + + i )
val * = cmDspDouble ( inst , kBaseOpdSoId + i ) ;
cmDspSetDouble ( ctx , inst , kOutSoId , val ) ;
return kOkDspRC ;
}
cmDspRC_t _cmDspScalarOpFuncAdd ( cmDspCtx_t * ctx , cmDspInst_t * inst )
{
cmDspScalarOp_t * p = ( cmDspScalarOp_t * ) inst ;
double val = 0 ;
unsigned i ;
for ( i = 0 ; i < p - > inPortCnt ; + + i )
val + = cmDspDouble ( inst , kBaseOpdSoId + i ) ;
cmDspSetDouble ( ctx , inst , kOutSoId , val ) ;
return kOkDspRC ;
}
// var args syntax: "<in_port_cnt> <op_string> <opd_label_0> <opd_dflt_val_0> <opd_label_1> <opd_dflt_val_1> ... <opd_label_n> <opd_dflt_val_n>
cmDspInst_t * _cmDspScalarOpAlloc ( cmDspCtx_t * ctx , cmDspClass_t * classPtr , unsigned storeSymId , unsigned instSymId , unsigned id , unsigned va_cnt , va_list vl )
{
cmDspVarArg_t args [ ] =
{
{ " cnt " , kPortCntSoId , 0 , 0 , kUIntDsvFl | kReqArgDsvFl , " Input port count " } ,
{ " op " , kOpSoId , 0 , 0 , kStrzDsvFl | kReqArgDsvFl , " Operation symbol as a string. " } ,
{ " out " , kOutSoId , 0 , 0 , kDoubleDsvFl | kOutDsvFl , " Operation output. " } ,
} ;
cmDspScalarOp_t * p ;
if ( va_cnt < 2 )
{
cmDspClassErr ( ctx , classPtr , kVarArgParseFailDspRC , " The 'ScalarOp' constructor must have a count of input ports and operation identifier string. " ) ;
return NULL ;
}
va_list vl1 ;
va_copy ( vl1 , vl ) ;
unsigned inPortCnt = va_arg ( vl , unsigned ) ;
const cmChar_t * opIdStr = va_arg ( vl , const cmChar_t * ) ;
unsigned fixArgCnt = sizeof ( args ) / sizeof ( args [ 0 ] ) ;
unsigned argCnt = fixArgCnt + inPortCnt ;
cmDspVarArg_t a [ argCnt + 1 ] ;
double dfltVal [ inPortCnt ] ;
unsigned i ;
_cmDspScalarOpFunc_t fp = NULL ;
// validate the count of input ports
if ( inPortCnt = = 0 )
{
cmDspClassErr ( ctx , classPtr , kVarNotValidDspRC , " The 'ScalarOp' constructor input port argument must be non-zero. " ) ;
2013-10-17 01:52:59 +00:00
goto errLabel ;
2012-10-30 03:52:39 +00:00
}
// locate the operation function
if ( strcmp ( opIdStr , " * " ) = = 0 )
fp = _cmDspScalarOpFuncMult ;
else
if ( strcmp ( opIdStr , " + " ) = = 0 )
fp = _cmDspScalarOpFuncAdd ;
// validate the operation function
if ( fp = = NULL )
{
cmDspClassErr ( ctx , classPtr , kVarNotValidDspRC , " The 'ScalarOp' constructor operation string id '%s' did not match a known operation. " , cmStringNullGuard ( opIdStr ) ) ;
2013-10-17 01:52:59 +00:00
goto errLabel ;
2012-10-30 03:52:39 +00:00
}
// setup the fixed args
cmDspArgCopy ( a , argCnt , 0 , args , fixArgCnt ) ;
for ( i = 0 ; i < inPortCnt ; + + i )
{
// get the operand label
const cmChar_t * label = va_arg ( vl , const cmChar_t * ) ;
// get the operand default value
dfltVal [ i ] = va_arg ( vl , double ) ;
// setup the arg recd
cmDspArgSetup ( ctx , a + fixArgCnt + i , label , cmInvalidId , kBaseOpdSoId + i , 0 , 0 , kDoubleDsvFl | kInDsvFl , " Operand " ) ;
}
cmDspArgSetupNull ( a + argCnt ) ; // set terminating arg. flag
if ( ( p = cmDspInstAlloc ( cmDspScalarOp_t , ctx , classPtr , a , instSymId , id , storeSymId , 2 , vl1 ) ) = = NULL )
2013-10-17 01:52:59 +00:00
goto errLabel ;
2012-10-30 03:52:39 +00:00
for ( i = 0 ; i < inPortCnt ; + + i )
cmDspSetDefaultDouble ( ctx , & p - > inst , kBaseOpdSoId + i , 0.0 , dfltVal [ i ] ) ;
p - > inPortCnt = inPortCnt ;
p - > func = fp ;
2013-10-17 01:52:59 +00:00
va_end ( vl1 ) ;
2012-10-30 03:52:39 +00:00
return & p - > inst ;
2013-10-17 01:52:59 +00:00
errLabel :
va_end ( vl1 ) ;
return NULL ;
2012-10-30 03:52:39 +00:00
}
cmDspRC_t _cmDspScalarOpReset ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
rc = cmDspApplyAllDefaults ( ctx , inst ) ;
return rc ;
}
cmDspRC_t _cmDspScalarOpRecv ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspScalarOp_t * p = ( cmDspScalarOp_t * ) inst ;
if ( ( rc = cmDspSetEvent ( ctx , inst , evt ) ) = = kOkDspRC )
{
if ( evt - > dstVarId = = kBaseOpdSoId )
p - > func ( ctx , inst ) ;
}
return rc ;
}
struct cmDspClass_str * cmScalarOpClassCons ( cmDspCtx_t * ctx )
{
cmDspClassSetup ( & _cmScalarOpDC , ctx , " ScalarOp " ,
NULL ,
_cmDspScalarOpAlloc ,
NULL ,
_cmDspScalarOpReset ,
NULL ,
_cmDspScalarOpRecv ,
NULL , NULL ,
" Scalar Operations " ) ;
return & _cmScalarOpDC ;
}
//==========================================================================================================================================
enum
{
kChCntGsId ,
kGroupCntGsId ,
kChsPerGroupGsId ,
kBaseGateGsId ,
} ;
cmDspClass_t _cmGroupSelDC ;
typedef struct
{
cmDspInst_t inst ;
unsigned chCnt ;
unsigned groupCnt ;
cmGroupSel * gsp ;
unsigned baseRmsGsId ;
unsigned baseOutGsId ;
} cmDspGroupSel_t ;
cmDspInst_t * _cmDspGroupSelAlloc ( cmDspCtx_t * ctx , cmDspClass_t * classPtr , unsigned storeSymId , unsigned instSymId , unsigned id , unsigned va_cnt , va_list vl )
{
cmDspVarArg_t args [ ] =
{
{ " chCnt " , kChCntGsId , 0 , 0 , kUIntDsvFl | kReqArgDsvFl , " Channel count. " } ,
{ " groupCnt " , kGroupCntGsId , 0 , 0 , kUIntDsvFl | kReqArgDsvFl , " Group count. " } ,
{ " chsPerGroup " , kChsPerGroupGsId , 0 , 0 , kUIntDsvFl | kInDsvFl | kReqArgDsvFl , " Channels per group. " }
} ;
if ( va_cnt < 2 )
{
cmDspClassErr ( ctx , classPtr , kVarArgParseFailDspRC , " The 'GroupSel' constructor must have a channel and group count. " ) ;
return NULL ;
}
va_list vl1 ;
va_copy ( vl1 , vl ) ;
cmDspGroupSel_t * p ;
unsigned i ;
unsigned chCnt = va_arg ( vl , unsigned ) ;
unsigned groupCnt = va_arg ( vl , unsigned ) ;
unsigned outCnt = chCnt * groupCnt ;
unsigned fixArgCnt = sizeof ( args ) / sizeof ( args [ 0 ] ) ;
unsigned baseRmsGsId = kBaseGateGsId + chCnt ;
unsigned baseOutGsId = baseRmsGsId + chCnt ;
unsigned argCnt = baseOutGsId + outCnt ;
cmDspVarArg_t a [ argCnt + 1 ] ;
cmDspArgCopy ( a , argCnt , 0 , args , fixArgCnt ) ;
cmDspArgSetupN ( ctx , a , argCnt , kBaseGateGsId , chCnt , " gate " , kBaseGateGsId , 0 , 0 , kInDsvFl | kBoolDsvFl , " Channel gate input. " ) ;
cmDspArgSetupN ( ctx , a , argCnt , baseRmsGsId , chCnt , " rms " , baseRmsGsId , 0 , 0 , kInDsvFl | kDoubleDsvFl , " Channel RMS input " ) ;
for ( i = 0 ; i < groupCnt ; + + i )
{
int labelCharCnt = 31 ;
char label [ labelCharCnt + 1 ] ;
snprintf ( label , labelCharCnt , " gate-%i " , i ) ;
cmDspArgSetupN ( ctx , a , argCnt , baseOutGsId + ( i * chCnt ) , chCnt , label , baseOutGsId + ( i * chCnt ) , 0 , 0 , kOutDsvFl | kBoolDsvFl , " Output gates " ) ;
}
cmDspArgSetupNull ( a + argCnt ) ; // set terminating arg. flag
if ( ( p = cmDspInstAlloc ( cmDspGroupSel_t , ctx , classPtr , a , instSymId , id , storeSymId , va_cnt , vl1 ) ) = = NULL )
2013-10-17 01:52:59 +00:00
{
va_end ( vl1 ) ;
2012-10-30 03:52:39 +00:00
return NULL ;
2013-10-17 01:52:59 +00:00
}
2012-10-30 03:52:39 +00:00
p - > chCnt = chCnt ;
p - > groupCnt = groupCnt ;
p - > gsp = cmGroupSelAlloc ( ctx - > cmProcCtx , NULL , 0 , 0 , 0 ) ;
p - > baseRmsGsId = baseRmsGsId ;
p - > baseOutGsId = baseOutGsId ;
for ( i = 0 ; i < chCnt ; + + i )
{
cmDspSetDefaultBool ( ctx , & p - > inst , kBaseGateGsId , false , false ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , baseRmsGsId , 0.0 , 0.0 ) ;
}
for ( i = 0 ; i < outCnt ; + + i )
cmDspSetDefaultBool ( ctx , & p - > inst , baseOutGsId , false , false ) ;
2013-10-17 01:52:59 +00:00
va_end ( vl1 ) ;
2012-10-30 03:52:39 +00:00
return & p - > inst ;
}
cmDspRC_t _cmDspGroupSelFree ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspGroupSel_t * p = ( cmDspGroupSel_t * ) inst ;
cmGroupSelFree ( & p - > gsp ) ;
return kOkDspRC ;
}
cmDspRC_t _cmDspGroupSelReset ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspGroupSel_t * p = ( cmDspGroupSel_t * ) inst ;
rc = cmDspApplyAllDefaults ( ctx , inst ) ;
cmGroupSelInit ( p - > gsp , p - > chCnt , p - > groupCnt , cmDspUInt ( & p - > inst , kChsPerGroupGsId ) ) ;
return rc ;
}
cmDspRC_t _cmDspGroupSelExec ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspGroupSel_t * p = ( cmDspGroupSel_t * ) inst ;
if ( cmGroupSelExec ( p - > gsp ) = = cmOkRC & & p - > gsp - > updateFl )
{
unsigned i , j ;
for ( i = 0 ; i < p - > groupCnt ; + + i )
{
cmGroupSelGrp * gp = p - > gsp - > groupArray + i ;
if ( gp - > releaseFl )
{
for ( j = 0 ; j < gp - > chIdxCnt ; + + j )
cmDspSetBool ( ctx , inst , p - > baseOutGsId + ( i * p - > chCnt ) + gp - > chIdxArray [ j ] , false ) ;
}
if ( gp - > createFl )
{
for ( j = 0 ; j < gp - > chIdxCnt ; + + j )
cmDspSetBool ( ctx , inst , p - > baseOutGsId + ( i * p - > chCnt ) + gp - > chIdxArray [ j ] , true ) ;
}
}
}
return rc ;
}
cmDspRC_t _cmDspGroupSelRecv ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspGroupSel_t * p = ( cmDspGroupSel_t * ) inst ;
if ( ( rc = cmDspSetEvent ( ctx , inst , evt ) ) = = kOkDspRC )
{
if ( evt - > dstVarId = = kChsPerGroupGsId )
p - > gsp - > chsPerGroup = cmDspUInt ( inst , kChsPerGroupGsId ) ;
else
if ( kBaseGateGsId < = evt - > dstVarId & & evt - > dstVarId < ( kBaseGateGsId + p - > chCnt ) )
cmGroupSetChannelGate ( p - > gsp , evt - > dstVarId - kBaseGateGsId , cmDspDouble ( inst , evt - > dstVarId ) ) ;
else
if ( p - > baseRmsGsId < = evt - > dstVarId & & evt - > dstVarId < ( p - > baseRmsGsId + p - > chCnt ) )
cmGroupSetChannelRMS ( p - > gsp , evt - > dstVarId - p - > baseRmsGsId , cmDspDouble ( inst , evt - > dstVarId ) ) ;
}
return rc ;
}
struct cmDspClass_str * cmGroupSelClassCons ( cmDspCtx_t * ctx )
{
cmDspClassSetup ( & _cmGroupSelDC , ctx , " GroupSel " ,
NULL ,
_cmDspGroupSelAlloc ,
_cmDspGroupSelFree ,
_cmDspGroupSelReset ,
_cmDspGroupSelExec ,
_cmDspGroupSelRecv ,
NULL , NULL ,
" Group selector. " ) ;
return & _cmGroupSelDC ;
}
//==========================================================================================================================================
enum
{
kInChCntNmId ,
kOutChCntNmId ,
kFadeTimeNmId ,
kBaseGateNmId ,
} ;
cmDspClass_t _cmAudioNofM_DC ;
typedef struct
{
cmDspInst_t inst ;
unsigned inChCnt ;
unsigned outChCnt ;
cmAudioNofM * nmp ;
unsigned baseInNmId ;
unsigned baseOutNmId ;
unsigned baseGainNmId ;
} cmDspAudioNofM_t ;
cmDspInst_t * _cmDspAudioNofM_Alloc ( cmDspCtx_t * ctx , cmDspClass_t * classPtr , unsigned storeSymId , unsigned instSymId , unsigned id , unsigned va_cnt , va_list vl )
{
if ( va_cnt < 2 )
{
cmDspClassErr ( ctx , classPtr , kVarArgParseFailDspRC , " The 'AudioNofM' constructor must given input and output channel counts. " ) ;
return NULL ;
}
va_list vl1 ;
va_copy ( vl1 , vl ) ;
int inChCnt = va_arg ( vl , int ) ;
int outChCnt = va_arg ( vl , int ) ;
unsigned baseInNmId = kBaseGateNmId + inChCnt ;
unsigned baseOutNmId = baseInNmId + inChCnt ;
unsigned baseGainNmId = baseOutNmId + outChCnt ;
unsigned i ;
cmDspAudioNofM_t * p = cmDspInstAllocV ( cmDspAudioNofM_t , ctx , classPtr , instSymId , id , storeSymId , va_cnt , vl1 ,
1 , " ichs " , kInChCntNmId , 0 , 0 , kUIntDsvFl | kReqArgDsvFl , " Input channel count. " ,
1 , " ochs " , kOutChCntNmId , 0 , 0 , kUIntDsvFl | kReqArgDsvFl , " Output channel count. " ,
1 , " time " , kFadeTimeNmId , 0 , 0 , kDoubleDsvFl | kOptArgDsvFl | kInDsvFl , " Fade time in milliseconds. " ,
inChCnt , " gate " , kBaseGateNmId , 0 , 0 , kBoolDsvFl | kInDsvFl , " Gate inputs. " ,
inChCnt , " in " , baseInNmId , 0 , 0 , kInDsvFl | kAudioBufDsvFl , " Audio input " ,
outChCnt , " out " , baseOutNmId , 0 , 1 , kOutDsvFl | kAudioBufDsvFl , " Audio output " ,
outChCnt , " gain " , baseGainNmId , 0 , 0 , kOutDsvFl | kDoubleDsvFl , " Gain output " ,
0 ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kFadeTimeNmId , 0.0 , 25.0 ) ;
p - > inChCnt = inChCnt ;
p - > outChCnt = outChCnt ;
p - > nmp = cmAudioNofMAlloc ( ctx - > cmProcCtx , NULL , 0 , 0 , 0 , 0 ) ;
p - > baseInNmId = baseInNmId ;
p - > baseOutNmId = baseOutNmId ;
p - > baseGainNmId = baseGainNmId ;
for ( i = 0 ; i < outChCnt ; + + i )
cmDspSetDefaultDouble ( ctx , & p - > inst , baseGainNmId + i , 0.0 , 0.0 ) ;
2013-10-17 01:52:59 +00:00
va_end ( vl1 ) ;
2012-10-30 03:52:39 +00:00
return & p - > inst ;
}
cmDspRC_t _cmDspAudioNofM_Free ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspAudioNofM_t * p = ( cmDspAudioNofM_t * ) inst ;
cmAudioNofMFree ( & p - > nmp ) ;
return kOkDspRC ;
}
cmDspRC_t _cmDspAudioNofM_Reset ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspAudioNofM_t * p = ( cmDspAudioNofM_t * ) inst ;
unsigned i ;
if ( ( rc = cmDspApplyAllDefaults ( ctx , inst ) ) = = kOkDspRC )
{
for ( i = 0 ; i < p - > outChCnt ; + + i )
cmDspZeroAudioBuf ( ctx , inst , p - > baseOutNmId + i ) ;
cmAudioNofMInit ( p - > nmp , cmDspSampleRate ( ctx ) , p - > inChCnt , p - > outChCnt , cmDspDouble ( & p - > inst , kFadeTimeNmId ) ) ;
}
return rc ;
}
cmDspRC_t _cmDspAudioNofM_Exec ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspAudioNofM_t * p = ( cmDspAudioNofM_t * ) inst ;
unsigned i ;
const cmSample_t * x [ p - > inChCnt ] ;
cmSample_t * y [ p - > outChCnt ] ;
2013-12-12 17:21:54 +00:00
unsigned n = 0 ;
2012-10-30 03:52:39 +00:00
for ( i = 0 ; i < p - > inChCnt ; + + i )
{
if ( i = = 0 )
n = cmDspAudioBufSmpCount ( ctx , inst , p - > baseInNmId + i , 0 ) ;
else
{ assert ( n = = cmDspAudioBufSmpCount ( ctx , inst , p - > baseInNmId + i , 0 ) ) ; }
x [ i ] = cmDspAudioBuf ( ctx , inst , p - > baseInNmId + i , 0 ) ;
}
for ( i = 0 ; i < p - > outChCnt ; + + i )
{
y [ i ] = cmDspAudioBuf ( ctx , inst , p - > baseOutNmId + i , 0 ) ;
assert ( n = = cmDspAudioBufSmpCount ( ctx , inst , p - > baseOutNmId + i , 0 ) ) ;
cmVOS_Zero ( y [ i ] , n ) ;
}
cmAudioNofMExec ( p - > nmp , x , p - > inChCnt , y , p - > outChCnt , n ) ;
for ( i = 0 ; i < p - > outChCnt ; + + i )
{
cmAudioNofM_In * ip = p - > nmp - > outArray [ i ] . list ;
double v = 0 ;
for ( ; ip ! = NULL ; ip = ip - > link )
v + = ip - > fader - > gain ;
cmDspSetDouble ( ctx , inst , p - > baseGainNmId + i , v ) ;
}
return rc ;
}
cmDspRC_t _cmDspAudioNofM_Recv ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspAudioNofM_t * p = ( cmDspAudioNofM_t * ) inst ;
if ( ( rc = cmDspSetEvent ( ctx , inst , evt ) ) = = kOkDspRC )
{
if ( kBaseGateNmId < = evt - > dstVarId & & evt - > dstVarId < = kBaseGateNmId + p - > inChCnt )
cmAudioNofMSetChannelGate ( p - > nmp , evt - > dstVarId - kBaseGateNmId , cmDspBool ( inst , evt - > dstVarId ) ) ;
}
return rc ;
}
struct cmDspClass_str * cmAudioNofMClassCons ( cmDspCtx_t * ctx )
{
cmDspClassSetup ( & _cmAudioNofM_DC , ctx , " AudioNofM " ,
NULL ,
_cmDspAudioNofM_Alloc ,
_cmDspAudioNofM_Free ,
_cmDspAudioNofM_Reset ,
_cmDspAudioNofM_Exec ,
_cmDspAudioNofM_Recv ,
NULL , NULL ,
" Audio N of M Switch " ) ;
return & _cmAudioNofM_DC ;
}
//==========================================================================================================================================
enum
{
kInChCntRmId ,
kBypassRmId ,
kGainRmId ,
kOutRmId ,
kBaseInRmId
} ;
cmDspClass_t _cmRingModDC ;
typedef struct
{
cmDspInst_t inst ;
unsigned inChCnt ;
} cmDspRingMod_t ;
cmDspInst_t * _cmDspRingModAlloc ( cmDspCtx_t * ctx , cmDspClass_t * classPtr , unsigned storeSymId , unsigned instSymId , unsigned id , unsigned va_cnt , va_list vl )
{
if ( va_cnt < 1 )
{
cmDspClassErr ( ctx , classPtr , kVarArgParseFailDspRC , " The 'RingMod' constructor must given an input channel counts. " ) ;
return NULL ;
}
va_list vl1 ;
va_copy ( vl1 , vl ) ;
int inChCnt = va_arg ( vl , int ) ;
cmDspRingMod_t * p = cmDspInstAllocV ( cmDspRingMod_t , ctx , classPtr , instSymId , id , storeSymId , va_cnt , vl1 ,
1 , " ichs " , kInChCntRmId , 0 , 0 , kUIntDsvFl | kReqArgDsvFl , " Input channel count. " ,
1 , " bypass " , kBypassRmId , 0 , 0 , kInDsvFl | kBoolDsvFl | kOptArgDsvFl , " Bypass enable " ,
1 , " gain " , kGainRmId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kOptArgDsvFl , " Output gain (default:1.0) " ,
1 , " out " , kOutRmId , 0 , 1 , kOutDsvFl | kAudioBufDsvFl , " Audio output " ,
inChCnt , " in " , kBaseInRmId , 0 , 0 , kInDsvFl | kAudioBufDsvFl , " Audio input " ,
0 ) ;
cmDspSetDefaultBool ( ctx , & p - > inst , kBypassRmId , false , false ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kGainRmId , 0.0 , 1.0 ) ;
p - > inChCnt = inChCnt ;
2013-10-17 01:52:59 +00:00
va_end ( vl1 ) ;
2012-10-30 03:52:39 +00:00
return & p - > inst ;
}
cmDspRC_t _cmDspRingModReset ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
if ( ( rc = cmDspApplyAllDefaults ( ctx , inst ) ) = = kOkDspRC )
{
cmDspZeroAudioBuf ( ctx , inst , kOutRmId ) ;
}
return rc ;
}
cmDspRC_t _cmDspRingModExec ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspRingMod_t * p = ( cmDspRingMod_t * ) inst ;
unsigned i , j ;
cmSample_t * y = cmDspAudioBuf ( ctx , inst , kOutRmId , 0 ) ;
const cmSample_t * x0 = cmDspAudioBuf ( ctx , inst , kBaseInRmId , 0 ) ;
unsigned n = cmDspAudioBufSmpCount ( ctx , inst , kOutRmId , 0 ) ;
double gain = cmDspDouble ( inst , kGainRmId ) ;
bool bypassFl = cmDspBool ( inst , kBypassRmId ) ;
for ( i = 1 ; i < p - > inChCnt ; + + i )
{
assert ( n = = cmDspAudioBufSmpCount ( ctx , inst , kBaseInRmId + i , 0 ) ) ;
const cmSample_t * x1 = cmDspAudioBuf ( ctx , inst , kBaseInRmId + i , 0 ) ;
if ( bypassFl )
{
for ( j = 0 ; j < n ; + + j )
y [ j ] = x0 [ j ] + x1 [ j ] ;
}
else
{
for ( j = 0 ; j < n ; + + j )
y [ j ] = x0 [ j ] * x1 [ j ] * gain ;
}
x0 = y ;
}
return rc ;
}
cmDspRC_t _cmDspRingModRecv ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
return cmDspSetEvent ( ctx , inst , evt ) ;
}
struct cmDspClass_str * cmRingModClassCons ( cmDspCtx_t * ctx )
{
cmDspClassSetup ( & _cmRingModDC , ctx , " RingMod " ,
NULL ,
_cmDspRingModAlloc ,
NULL ,
_cmDspRingModReset ,
_cmDspRingModExec ,
_cmDspRingModRecv ,
NULL , NULL ,
" Ring modulator " ) ;
return & _cmRingModDC ;
}
//==========================================================================================================================================
enum
{
kMaxCntMdId ,
kDelayMdId ,
2014-05-31 16:49:01 +00:00
kClearMdId ,
2012-10-30 03:52:39 +00:00
kInMdId ,
kOutMdId ,
} ;
cmDspClass_t _cmMsgDelayDC ;
typedef struct cmDspMsgDelayEle_str
{
unsigned outTimeSmp ;
cmDspValue_t value ;
struct cmDspMsgDelayEle_str * link ;
} cmDspMsgDelayEle_t ;
typedef struct
{
cmDspInst_t inst ;
unsigned maxCnt ;
cmDspMsgDelayEle_t * array ; // array[maxCnt];
cmDspMsgDelayEle_t * avail ;
cmDspMsgDelayEle_t * active ;
} cmDspMsgDelay_t ;
cmDspInst_t * _cmDspMsgDelayAlloc ( cmDspCtx_t * ctx , cmDspClass_t * classPtr , unsigned storeSymId , unsigned instSymId , unsigned id , unsigned va_cnt , va_list vl )
{
cmDspMsgDelay_t * p = cmDspInstAllocV ( cmDspMsgDelay_t , ctx , classPtr , instSymId , id , storeSymId , va_cnt , vl ,
1 , " maxcnt " , kMaxCntMdId , 0 , 0 , kUIntDsvFl | kReqArgDsvFl , " Maximum count of elements in the delay " ,
1 , " delay " , kDelayMdId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kOptArgDsvFl , " Delay time in millisecond. " ,
2014-05-31 16:49:01 +00:00
1 , " clear " , kClearMdId , 0 , 0 , kInDsvFl | kTypeDsvMask , " Clear delay " ,
1 , " in " , kInMdId , 0 , 0 , kInDsvFl | kUIntDsvFl , " Msg input " ,
1 , " out " , kOutMdId , 0 , 0 , kOutDsvFl | kUIntDsvFl , " Msg output " ,
2012-10-30 03:52:39 +00:00
0 ) ;
if ( p = = NULL )
return NULL ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kDelayMdId , 0.0 , 0.0 ) ;
cmDspSetDefaultBool ( ctx , & p - > inst , kOutMdId , false , false ) ;
p - > maxCnt = cmDspUInt ( & p - > inst , kMaxCntMdId ) ;
p - > array = cmMemAllocZ ( cmDspMsgDelayEle_t , p - > maxCnt ) ;
return & p - > inst ;
}
cmDspRC_t _cmDspMsgDelayFree ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspMsgDelay_t * p = ( cmDspMsgDelay_t * ) inst ;
cmMemFree ( p - > array ) ;
return kOkDspRC ;
}
// insert a value in the delay list
cmDspRC_t _cmDspMsgDelayInsert ( cmDspCtx_t * ctx , cmDspMsgDelay_t * p , unsigned delayTimeSmp , const cmDspValue_t * valPtr )
{
cmDspRC_t rc = kOkDspRC ;
// protect against pre-reset calls
if ( p - > avail = = NULL & & p - > active = = NULL )
return kOkDspRC ;
// if there are no available delay elements
if ( p - > avail = = NULL )
return cmDspInstErr ( ctx , & p - > inst , kInvalidStateDspRC , " The message delay has exhausted it's internal message store. " ) ;
// we only do the simplest kind of copying to avoid allocating memory
// TODO: fix this
if ( cmDsvIsMtx ( valPtr ) | | cmIsFlag ( valPtr - > flags , kProxyDsvFl ) )
return cmDspInstErr ( ctx , & p - > inst , kInvalidArgDspRC , " The message delay cannot yet store matrix or proxy types. " ) ;
// get a pointer to the next available element
cmDspMsgDelayEle_t * np = p - > avail ;
// remove the new ele from the avail list
p - > avail = np - > link ;
// calc the new ele's exec time
np - > outTimeSmp = ctx - > cycleCnt * cmDspSamplesPerCycle ( ctx ) + delayTimeSmp ;
// copy the msg value into the delay line element
// TODO: this should be a real copy that supports all types
np - > value = * valPtr ;
cmDspMsgDelayEle_t * ep = p - > active ;
cmDspMsgDelayEle_t * pp = NULL ;
// if the active list is empty ...
if ( ep = = NULL )
{
// ... make the avail element the first on the list
p - > active = np ;
np - > link = NULL ;
}
else
{
// iterate through the list and find the active links which
// the new ele falls between based on its execution time
while ( ep ! = NULL )
{
// ep's exec time is greater than the new ele's exec time
if ( ep - > outTimeSmp > np - > outTimeSmp )
{
// insert the new ele in the active list before 'ep'
if ( pp = = NULL )
{
np - > link = p - > active ;
p - > active = np ;
}
else
{
np - > link = pp - > link ;
pp - > link = np ;
}
break ;
}
pp = ep ;
ep = ep - > link ;
}
// if the new element is last on the list
if ( ep = = NULL )
{
assert ( pp ! = NULL & & pp - > link = = NULL ) ;
pp - > link = np ;
np - > link = NULL ;
}
}
return rc ;
}
2014-05-31 16:49:01 +00:00
void _cmDspMsgDelayClear ( cmDspInst_t * inst )
2012-10-30 03:52:39 +00:00
{
unsigned i ;
2014-05-31 16:49:01 +00:00
cmDspMsgDelay_t * p = ( cmDspMsgDelay_t * ) inst ;
2012-10-30 03:52:39 +00:00
unsigned maxCnt = cmDspUInt ( inst , kMaxCntMdId ) ;
p - > active = NULL ;
p - > avail = NULL ;
// put all ele's on the available list
for ( i = 0 ; i < maxCnt ; + + i )
{
p - > array [ i ] . link = p - > avail ;
p - > avail = p - > array + i ;
}
2014-05-31 16:49:01 +00:00
}
cmDspRC_t _cmDspMsgDelayReset ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
if ( ( rc = cmDspApplyDefault ( ctx , inst , kDelayMdId ) ) = = kOkDspRC )
{
_cmDspMsgDelayClear ( inst ) ;
2012-10-30 03:52:39 +00:00
}
return rc ;
}
cmDspRC_t _cmDspMsgDelayExec ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * e )
{
cmDspRC_t rc = kOkDspRC ;
cmDspMsgDelay_t * p = ( cmDspMsgDelay_t * ) inst ;
unsigned framesPerCycle = cmDspSamplesPerCycle ( ctx ) ;
unsigned begTimeSmp = ctx - > cycleCnt * framesPerCycle ;
unsigned endTimeSmp = begTimeSmp + framesPerCycle ;
while ( p - > active ! = NULL )
{
if ( p - > active - > outTimeSmp > = endTimeSmp )
break ;
cmDspMsgDelayEle_t * ep = p - > active ;
// remove the element from the active list and place it on the available list.
p - > active = p - > active - > link ; // advance the active list
ep - > link = p - > avail ; // put the cur. element on the avail list
p - > avail = ep ; //
// output the element value
if ( ( rc = cmDspValueSet ( ctx , inst , kOutMdId , & ep - > value , 0 ) ) ! = kOkDspRC )
return cmDspInstErr ( ctx , inst , rc , " Message delay output failed. " ) ;
}
return rc ;
}
cmDspRC_t _cmDspMsgDelayRecv ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspMsgDelay_t * p = ( cmDspMsgDelay_t * ) inst ;
switch ( evt - > dstVarId )
{
case kDelayMdId :
rc = cmDspSetEvent ( ctx , inst , evt ) ;
break ;
2014-05-31 16:49:01 +00:00
case kClearMdId :
_cmDspMsgDelayClear ( inst ) ;
break ;
2012-10-30 03:52:39 +00:00
case kInMdId :
{
unsigned delayTimeSmp = floor ( cmDspDouble ( & p - > inst , kDelayMdId ) * cmDspSampleRate ( ctx ) / 1000.0 ) ;
rc = _cmDspMsgDelayInsert ( ctx , p , delayTimeSmp , evt - > valuePtr ) ;
}
break ;
}
return rc ;
}
struct cmDspClass_str * cmMsgDelayClassCons ( cmDspCtx_t * ctx )
{
cmDspClassSetup ( & _cmMsgDelayDC , ctx , " MsgDelay " ,
NULL ,
_cmDspMsgDelayAlloc ,
_cmDspMsgDelayFree ,
_cmDspMsgDelayReset ,
_cmDspMsgDelayExec ,
_cmDspMsgDelayRecv ,
NULL , NULL ,
" Message Delay " ) ;
return & _cmMsgDelayDC ;
}
//==========================================================================================================================================
enum
{
kBegLnId ,
kEndLnId ,
kDurLnId ,
kCmdLnId ,
2015-04-09 20:12:04 +00:00
kRateLnId ,
2012-10-30 03:52:39 +00:00
kOutLnId ,
} ;
cmDspClass_t _cmLineDC ;
typedef struct cmDspLineEle_str
{
unsigned outTimeSmp ;
cmDspValue_t value ;
struct cmDspLineEle_str * link ;
} cmDspLineEle_t ;
typedef struct
{
cmDspInst_t inst ;
unsigned onSymId ;
unsigned offSymId ;
unsigned resetSymId ;
unsigned curSmpIdx ;
2015-04-09 20:12:04 +00:00
double phase ;
2012-10-30 03:52:39 +00:00
bool onFl ;
} cmDspLine_t ;
cmDspInst_t * _cmDspLineAlloc ( cmDspCtx_t * ctx , cmDspClass_t * classPtr , unsigned storeSymId , unsigned instSymId , unsigned id , unsigned va_cnt , va_list vl )
{
cmDspLine_t * p = cmDspInstAllocV ( cmDspLine_t , ctx , classPtr , instSymId , id , storeSymId , va_cnt , vl ,
1 , " beg " , kBegLnId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kReqArgDsvFl , " Begin value. " ,
1 , " end " , kEndLnId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kReqArgDsvFl , " End value. " ,
1 , " dur " , kDurLnId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kReqArgDsvFl , " Duration (ms) " ,
1 , " cmd " , kCmdLnId , 0 , 0 , kInDsvFl | kSymDsvFl | kOptArgDsvFl , " Command: on | off | reset " ,
2015-04-09 20:12:04 +00:00
1 , " rate " , kRateLnId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kOptArgDsvFl , " Output messages per second " ,
2012-10-30 03:52:39 +00:00
1 , " out " , kOutLnId , 0 , 0 , kOutDsvFl | kDoubleDsvFl , " Output " ,
0 ) ;
if ( p = = NULL )
return NULL ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kOutLnId , 0.0 , cmDspDefaultDouble ( & p - > inst , kBegLnId ) ) ;
2015-04-09 20:12:04 +00:00
cmDspSetDefaultDouble ( ctx , & p - > inst , kRateLnId , 0.0 , 0.0 ) ;
2012-10-30 03:52:39 +00:00
p - > onSymId = cmSymTblRegisterStaticSymbol ( ctx - > stH , " on " ) ;
p - > offSymId = cmSymTblRegisterStaticSymbol ( ctx - > stH , " off " ) ;
p - > resetSymId = cmSymTblRegisterStaticSymbol ( ctx - > stH , " reset " ) ;
2015-04-09 20:12:04 +00:00
2012-10-30 03:52:39 +00:00
return & p - > inst ;
}
cmDspRC_t _cmDspLineFree ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
return kOkDspRC ;
}
cmDspRC_t _cmDspLineReset ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspLine_t * p = ( cmDspLine_t * ) inst ;
p - > curSmpIdx = 0 ;
p - > onFl = false ;
2015-04-09 20:12:04 +00:00
p - > phase = 0 ;
2012-10-30 03:52:39 +00:00
return cmDspApplyAllDefaults ( ctx , inst ) ;
}
cmDspRC_t _cmDspLineExec ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * e )
{
cmDspRC_t rc = kOkDspRC ;
cmDspLine_t * p = ( cmDspLine_t * ) inst ;
if ( p - > onFl = = false )
return kOkDspRC ;
2015-04-09 20:12:04 +00:00
unsigned sPc = cmDspSamplesPerCycle ( ctx ) ;
2012-10-30 03:52:39 +00:00
double beg = cmDspDouble ( inst , kBegLnId ) ;
double end = cmDspDouble ( inst , kEndLnId ) ;
2015-04-09 20:12:04 +00:00
double rate = cmDspDouble ( inst , kRateLnId ) ;
2012-10-30 03:52:39 +00:00
double ms = cmDspDouble ( inst , kDurLnId ) ;
double durSmpCnt = floor ( ms * cmDspSampleRate ( ctx ) / 1000 ) ;
double out = beg + ( end - beg ) * p - > curSmpIdx / durSmpCnt ;
2015-04-09 20:12:04 +00:00
double phsMax = rate = = 0 ? sPc : cmDspSampleRate ( ctx ) / rate ;
// we can never output with a period shorter than
// the length of one audio buffer
if ( phsMax < sPc )
phsMax = sPc ;
2012-10-30 03:52:39 +00:00
if ( beg < end )
{
if ( out > = end )
{
out = end ;
p - > onFl = false ;
}
}
else
{
if ( out < = end )
{
out = end ;
p - > onFl = false ;
}
}
2015-04-09 20:12:04 +00:00
p - > phase + = sPc ;
if ( p - > phase > = sPc )
{
cmDspSetDouble ( ctx , inst , kOutLnId , out ) ;
p - > phase - = sPc ;
}
2012-10-30 03:52:39 +00:00
2015-04-09 20:12:04 +00:00
p - > curSmpIdx + = sPc ;
2012-10-30 03:52:39 +00:00
return rc ;
}
cmDspRC_t _cmDspLineRecv ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspLine_t * p = ( cmDspLine_t * ) inst ;
if ( ( rc = cmDspSetEvent ( ctx , inst , evt ) ) = = kOkDspRC )
{
switch ( evt - > dstVarId )
{
case kCmdLnId :
{
unsigned symId = cmDspSymbol ( inst , kCmdLnId ) ;
if ( symId = = p - > onSymId )
p - > onFl = true ;
else
if ( symId = = p - > offSymId )
p - > onFl = false ;
else
if ( symId = = p - > resetSymId )
{
p - > curSmpIdx = 0 ;
p - > onFl = true ;
}
}
break ;
}
}
return rc ;
}
struct cmDspClass_str * cmLineClassCons ( cmDspCtx_t * ctx )
{
cmDspClassSetup ( & _cmLineDC , ctx , " Line " ,
NULL ,
_cmDspLineAlloc ,
_cmDspLineFree ,
_cmDspLineReset ,
_cmDspLineExec ,
_cmDspLineRecv ,
NULL , NULL ,
" Line " ) ;
return & _cmLineDC ;
}
//==========================================================================================================================================
enum
{
kTrigModeAdId ,
kMinLvlAdId ,
kDlyMsAdId ,
kAtkMsAdId ,
kAtkLvlAdId ,
kDcyMsAdId ,
kSusLvlAdId ,
kSusMsAdId ,
kRlsMsAdId ,
kTScaleAdId ,
kAScaleAdId ,
kGateAdId ,
kRmsAdId ,
kOutAdId ,
kCmdAdId
} ;
cmDspClass_t _cmAdsrDC ;
typedef struct
{
cmDspInst_t inst ;
cmAdsr * p ;
} cmDspAdsr_t ;
cmDspInst_t * _cmDspAdsrAlloc ( cmDspCtx_t * ctx , cmDspClass_t * classPtr , unsigned storeSymId , unsigned instSymId , unsigned id , unsigned va_cnt , va_list vl )
{
cmDspAdsr_t * p = cmDspInstAllocV ( cmDspAdsr_t , ctx , classPtr , instSymId , id , storeSymId , va_cnt , vl ,
1 , " trig " , kTrigModeAdId , 0 , 0 , kBoolDsvFl | kInDsvFl | kOptArgDsvFl , " Trigger mode (offset ignored). " ,
1 , " min " , kMinLvlAdId , 0 , 0 , kDoubleDsvFl | kInDsvFl | kOptArgDsvFl , " Minimum level (dflt:0.0). " ,
1 , " dly " , kDlyMsAdId , 0 , 0 , kDoubleDsvFl | kInDsvFl | kOptArgDsvFl , " Delay milliseconds. " ,
1 , " atk " , kAtkMsAdId , 0 , 0 , kDoubleDsvFl | kInDsvFl | kOptArgDsvFl , " Attack milliseconds. " ,
1 , " alvl " , kAtkLvlAdId , 0 , 0 , kDoubleDsvFl | kInDsvFl | kOptArgDsvFl , " Attack Level. " ,
1 , " dcy " , kDcyMsAdId , 0 , 0 , kDoubleDsvFl | kInDsvFl | kOptArgDsvFl , " Decay milliseconds. " ,
1 , " sus " , kSusLvlAdId , 0 , 0 , kDoubleDsvFl | kInDsvFl | kOptArgDsvFl , " Sustain Level. " ,
1 , " hold " , kSusMsAdId , 0 , 0 , kDoubleDsvFl | kInDsvFl | kOptArgDsvFl , " Sustain Ms (trig mode only). " ,
1 , " rls " , kRlsMsAdId , 0 , 0 , kDoubleDsvFl | kInDsvFl | kOptArgDsvFl , " Release milliseconds. " ,
1 , " tscale " , kTScaleAdId , 0 , 0 , kDoubleDsvFl | kInDsvFl , " Time scale. " ,
1 , " ascale " , kAScaleAdId , 0 , 0 , kDoubleDsvFl | kInDsvFl , " Amplitude scale. " ,
1 , " gate " , kGateAdId , 0 , 0 , kBoolDsvFl | kInDsvFl , " Gate input. " ,
1 , " rms " , kRmsAdId , 0 , 0 , kDoubleDsvFl | kInDsvFl , " RMS input. " ,
1 , " out " , kOutAdId , 0 , 0 , kDoubleDsvFl | kOutDsvFl , " Level output. " ,
1 , " cmd " , kCmdAdId , 0 , 0 , kSymDsvFl | kInDsvFl , " Command input. " ,
0 ) ;
cmDspSetDefaultBool ( ctx , & p - > inst , kTrigModeAdId , false , false ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kMinLvlAdId , 0.0 , 0.0 ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kDlyMsAdId , 0.0 , 0.0 ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kAtkMsAdId , 0.0 , 5.0 ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kAtkLvlAdId , 0.0 , 1.0 ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kDcyMsAdId , 0.0 , 10.0 ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kSusLvlAdId , 0.0 , 0.8 ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kSusMsAdId , 0.0 , 50.0 ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kRlsMsAdId , 0.0 , 20.0 ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kTScaleAdId , 0.0 , 1.0 ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kAScaleAdId , 0.0 , 1.0 ) ;
cmDspSetDefaultBool ( ctx , & p - > inst , kGateAdId , false , false ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kRmsAdId , 0.0 , 0.0 ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kOutAdId , 0.0 , cmDspDouble ( & p - > inst , kMinLvlAdId ) ) ;
p - > p = cmAdsrAlloc ( ctx - > cmProcCtx , NULL , false , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ) ;
return & p - > inst ;
}
cmDspRC_t _cmDspAdsrFree ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspAdsr_t * p = ( cmDspAdsr_t * ) inst ;
cmAdsrFree ( & p - > p ) ;
return kOkDspRC ;
}
cmDspRC_t _cmDspAdsrReset ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspAdsr_t * p = ( cmDspAdsr_t * ) inst ;
if ( ( rc = cmDspApplyAllDefaults ( ctx , inst ) ) = = kOkDspRC )
{
bool trigFl = cmDspBool ( inst , kTrigModeAdId ) ;
cmReal_t minL = cmDspDouble ( inst , kMinLvlAdId ) ;
cmReal_t dlyMs = cmDspDouble ( inst , kDlyMsAdId ) ;
cmReal_t atkMs = cmDspDouble ( inst , kAtkMsAdId ) ;
cmReal_t atkL = cmDspDouble ( inst , kAtkLvlAdId ) ;
cmReal_t dcyMs = cmDspDouble ( inst , kDcyMsAdId ) ;
cmReal_t susMs = cmDspDouble ( inst , kSusMsAdId ) ;
cmReal_t susL = cmDspDouble ( inst , kSusLvlAdId ) ;
cmReal_t rlsMs = cmDspDouble ( inst , kRlsMsAdId ) ;
cmAdsrInit ( p - > p , cmDspSampleRate ( ctx ) , trigFl , minL , dlyMs , atkMs , atkL , dcyMs , susMs , susL , rlsMs ) ;
}
return rc ;
}
cmDspRC_t _cmDspAdsrExec ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspAdsr_t * p = ( cmDspAdsr_t * ) inst ;
bool gateFl = cmDspBool ( inst , kGateAdId ) ;
//double rms = cmDspDouble(inst,kRmsAdId);
double tscale = cmDspDouble ( inst , kTScaleAdId ) ;
double ascale = cmDspDouble ( inst , kAScaleAdId ) ;
//
// HACK HACK HACK HACK
// HACK HACK HACK HACK
// HACK HACK HACK HACK see the accompanying hack in cmProc3.c cmAdsrExec()
// HACK HACK HACK HACK
// HACK HACK HACK HACK
//
/*
double db = rms < 0.00001 ? - 100.0 : 20.0 * log10 ( rms ) ;
double dbMax = - 15.0 ;
double dbMin = - 58.0 ;
db = cmMin ( dbMax , cmMax ( dbMin , db ) ) ;
double scale = ( db - dbMin ) / ( dbMax - dbMin ) ;
*/
cmReal_t out = cmAdsrExec ( p - > p , cmDspSamplesPerCycle ( ctx ) , gateFl , tscale , ascale ) ;
rc = cmDspSetDouble ( ctx , inst , kOutAdId , out ) ;
return rc ;
}
cmDspRC_t _cmDspAdsrRecv ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspAdsr_t * p = ( cmDspAdsr_t * ) inst ;
if ( ( rc = cmDspSetEvent ( ctx , inst , evt ) ) ! = kOkDspRC )
return rc ;
if ( evt - > dstVarId = = kCmdAdId )
{
cmAdsrReport ( p - > p , ctx - > rpt ) ;
return rc ;
}
cmReal_t v = cmDspDouble ( inst , evt - > dstVarId ) ;
switch ( evt - > dstVarId )
{
case kTrigModeAdId :
p - > p - > trigModeFl = cmDspBool ( inst , kTrigModeAdId ) ;
break ;
case kMinLvlAdId :
cmAdsrSetLevel ( p - > p , v , kDlyAdsrId ) ;
break ;
case kDlyMsAdId :
cmAdsrSetTime ( p - > p , v , kDlyAdsrId ) ;
break ;
case kAtkMsAdId :
cmAdsrSetTime ( p - > p , v , kAtkAdsrId ) ;
break ;
case kAtkLvlAdId :
cmAdsrSetLevel ( p - > p , v , kAtkAdsrId ) ;
break ;
case kDcyMsAdId :
cmAdsrSetTime ( p - > p , v , kDcyAdsrId ) ;
break ;
case kSusMsAdId :
cmAdsrSetTime ( p - > p , v , kSusAdsrId ) ;
break ;
case kSusLvlAdId :
cmAdsrSetLevel ( p - > p , v , kSusAdsrId ) ;
break ;
case kRlsMsAdId :
cmAdsrSetTime ( p - > p , v , kRlsAdsrId ) ;
break ;
}
return rc ;
}
struct cmDspClass_str * cmAdsrClassCons ( cmDspCtx_t * ctx )
{
cmDspClassSetup ( & _cmAdsrDC , ctx , " Adsr " ,
NULL ,
_cmDspAdsrAlloc ,
_cmDspAdsrFree ,
_cmDspAdsrReset ,
_cmDspAdsrExec ,
_cmDspAdsrRecv ,
NULL , NULL ,
" ADSR Envelope Generator " ) ;
return & _cmAdsrDC ;
}
//==========================================================================================================================================
enum
{
kBypassCmId ,
kThreshDbCmId ,
kRatioCmId ,
kAtkMsCmId ,
kRlsMsCmId ,
kInGainCmId ,
kOutGainCmId ,
kWndMsCmId ,
kMaxWndMsCmId ,
kInCmId ,
kOutCmId ,
kEnvCmId
} ;
cmDspClass_t _cmCompressorDC ;
typedef struct
{
cmDspInst_t inst ;
cmCompressor * p ;
} cmDspCompressor_t ;
cmDspInst_t * _cmDspCompressorAlloc ( cmDspCtx_t * ctx , cmDspClass_t * classPtr , unsigned storeSymId , unsigned instSymId , unsigned id , unsigned va_cnt , va_list vl )
{
cmDspCompressor_t * p = cmDspInstAllocV ( cmDspCompressor_t , ctx , classPtr , instSymId , id , storeSymId , va_cnt , vl ,
1 , " bypass " , kBypassCmId , 0 , 0 , kInDsvFl | kBoolDsvFl | kReqArgDsvFl , " Bypass enable " ,
1 , " thr " , kThreshDbCmId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kReqArgDsvFl , " Threshold in dB. " ,
1 , " ratio " , kRatioCmId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kReqArgDsvFl , " Ratio numerator. " ,
1 , " atk " , kAtkMsCmId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kOptArgDsvFl , " Attack milliseconds " ,
1 , " rls " , kRlsMsCmId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kOptArgDsvFl , " Release milliseconds " ,
1 , " igain " , kInGainCmId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kOptArgDsvFl , " Input gain. " ,
1 , " ogain " , kOutGainCmId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kOptArgDsvFl , " Makeup Gain " ,
1 , " wnd " , kWndMsCmId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kOptArgDsvFl , " RMS window milliseconds. " ,
1 , " maxwnd " , kMaxWndMsCmId , 0 , 0 , kDoubleDsvFl | kOptArgDsvFl , " Max. RMS window milliseconds. " ,
1 , " in " , kInCmId , 0 , 0 , kInDsvFl | kAudioBufDsvFl , " Audio input " ,
1 , " out " , kOutCmId , 0 , 1 , kOutDsvFl | kAudioBufDsvFl , " Audio output " ,
1 , " env " , kEnvCmId , 0 , 0 , kOutDsvFl | kDoubleDsvFl , " Envelope out " ,
0 ) ;
p - > p = cmCompressorAlloc ( ctx - > cmProcCtx , NULL , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , false ) ;
cmDspSetDefaultBool ( ctx , & p - > inst , kBypassCmId , false , false ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kAtkMsCmId , 0.0 , 20.0 ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kRlsMsCmId , 0.0 , 20.0 ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kInGainCmId , 0.0 , 1.0 ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kOutGainCmId , 0.0 , 1.0 ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kWndMsCmId , 0.0 , 200.0 ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kMaxWndMsCmId , 0.0 , 1000.0 ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kEnvCmId , 0.0 , 0.0 ) ;
return & p - > inst ;
}
cmDspRC_t _cmDspCompressorFree ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspCompressor_t * p = ( cmDspCompressor_t * ) inst ;
cmCompressorFree ( & p - > p ) ;
return kOkDspRC ;
}
cmDspRC_t _cmDspCompressorReset ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspCompressor_t * p = ( cmDspCompressor_t * ) inst ;
if ( ( rc = cmDspApplyAllDefaults ( ctx , inst ) ) = = kOkDspRC )
{
cmDspZeroAudioBuf ( ctx , inst , kOutCmId ) ;
cmReal_t threshDb = cmDspDouble ( inst , kThreshDbCmId ) ;
cmReal_t ratio = cmDspDouble ( inst , kRatioCmId ) ;
cmReal_t atkMs = cmDspDouble ( inst , kAtkMsCmId ) ;
cmReal_t rlsMs = cmDspDouble ( inst , kRlsMsCmId ) ;
cmReal_t inGain = cmDspDouble ( inst , kInGainCmId ) ;
cmReal_t outGain = cmDspDouble ( inst , kOutGainCmId ) ;
cmReal_t wndMs = cmDspDouble ( inst , kWndMsCmId ) ;
cmReal_t maxWndMs = cmDspDouble ( inst , kMaxWndMsCmId ) ;
bool bypassFl = cmDspBool ( inst , kBypassCmId ) ;
cmCompressorInit ( p - > p , cmDspSampleRate ( ctx ) , cmDspSamplesPerCycle ( ctx ) , inGain , maxWndMs , wndMs , threshDb , ratio , atkMs , rlsMs , outGain , bypassFl ) ;
}
return rc ;
}
cmDspRC_t _cmDspCompressorExec ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspCompressor_t * p = ( cmDspCompressor_t * ) inst ;
cmSample_t * y = cmDspAudioBuf ( ctx , inst , kOutCmId , 0 ) ;
const cmSample_t * x = cmDspAudioBuf ( ctx , inst , kInCmId , 0 ) ;
unsigned n = cmDspAudioBufSmpCount ( ctx , inst , kOutCmId , 0 ) ;
if ( x ! = NULL )
{
cmCompressorExec ( p - > p , x , y , n ) ;
rc = cmDspSetDouble ( ctx , inst , kEnvCmId , p - > p - > gain ) ;
}
return rc ;
}
cmDspRC_t _cmDspCompressorRecv ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc ;
cmDspCompressor_t * p = ( cmDspCompressor_t * ) inst ;
if ( ( rc = cmDspSetEvent ( ctx , inst , evt ) ) ! = kOkDspRC )
return rc ;
cmReal_t v = cmDspDouble ( inst , evt - > dstVarId ) ;
switch ( evt - > dstVarId )
{
case kThreshDbCmId :
cmCompressorSetThreshDb ( p - > p , v ) ;
break ;
case kRatioCmId :
p - > p - > ratio_num = v ;
break ;
case kAtkMsCmId :
cmCompressorSetAttackMs ( p - > p , v ) ;
break ;
case kRlsMsCmId :
cmCompressorSetReleaseMs ( p - > p , v ) ;
break ;
case kInGainCmId :
p - > p - > inGain = v ;
break ;
case kOutGainCmId :
p - > p - > outGain = v ;
break ;
case kWndMsCmId :
cmCompressorSetRmsWndMs ( p - > p , v ) ;
break ;
case kBypassCmId :
p - > p - > bypassFl = cmDspBool ( inst , kBypassCmId ) ;
break ;
}
return rc ;
}
struct cmDspClass_str * cmCompressorClassCons ( cmDspCtx_t * ctx )
{
cmDspClassSetup ( & _cmCompressorDC , ctx , " Compressor " ,
NULL ,
_cmDspCompressorAlloc ,
_cmDspCompressorFree ,
_cmDspCompressorReset ,
_cmDspCompressorExec ,
_cmDspCompressorRecv ,
NULL , NULL ,
" Compressor " ) ;
return & _cmCompressorDC ;
}
//==========================================================================================================================================
enum
{
kBypassBqId ,
kModeBqId ,
kF0HzBqId ,
kQBqId ,
kGainDbBqId ,
kInBqId ,
kOutBqId
} ;
cmDspClass_t _cmBiQuadEqDC ;
typedef struct
{
const cmChar_t * label ;
unsigned mode ;
unsigned symbol ;
} cmDspBiQuadMap_t ;
cmDspBiQuadMap_t _cmDspBiQuadMap [ ] =
{
{ " LP " , kLpfBqId , cmInvalidId } ,
{ " HP " , kHpFBqId , cmInvalidId } ,
{ " BP " , kBpfBqId , cmInvalidId } ,
{ " Notch " , kNotchBqId , cmInvalidId } ,
{ " AP " , kAllpassBqId , cmInvalidId } ,
{ " Peak " , kPeakBqId , cmInvalidId } ,
{ " LSh " , kLowShelfBqId , cmInvalidId } ,
{ " HSh " , kHighShelfBqId , cmInvalidId } ,
{ NULL , cmInvalidId , cmInvalidId }
} ;
typedef struct
{
cmDspInst_t inst ;
cmBiQuadEq * p ;
} cmDspBiQuadEq_t ;
cmDspInst_t * _cmDspBiQuadEqAlloc ( cmDspCtx_t * ctx , cmDspClass_t * classPtr , unsigned storeSymId , unsigned instSymId , unsigned id , unsigned va_cnt , va_list vl )
{
cmDspBiQuadEq_t * p = cmDspInstAllocV ( cmDspBiQuadEq_t , ctx , classPtr , instSymId , id , storeSymId , va_cnt , vl ,
1 , " bypass " , kBypassBqId , 0 , 0 , kInDsvFl | kBoolDsvFl | kReqArgDsvFl , " Bypass enable. " ,
1 , " mode " , kModeBqId , 0 , 0 , kInDsvFl | kSymDsvFl | kReqArgDsvFl , " Mode Symbol: LP|HP|BP|AP|Notch|Pk|LSh|HSh. " ,
1 , " f0 " , kF0HzBqId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kReqArgDsvFl , " Center or edge frequecy in Hz. " ,
1 , " Q " , kQBqId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kReqArgDsvFl , " Q " ,
1 , " gain " , kGainDbBqId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kOptArgDsvFl , " Gain Db (Pk,LSh,Hsh only) " ,
1 , " in " , kInBqId , 0 , 0 , kInDsvFl | kAudioBufDsvFl , " Audio input " ,
1 , " out " , kOutBqId , 0 , 1 , kOutDsvFl | kAudioBufDsvFl , " Audio output " ,
0 ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kGainDbBqId , 0.0 , 1.0 ) ;
p - > p = cmBiQuadEqAlloc ( ctx - > cmProcCtx , NULL , 0 , 0 , 0 , 0 , 0 , false ) ;
// register the filter mode symbols
unsigned i ;
for ( i = 0 ; _cmDspBiQuadMap [ i ] . label ! = NULL ; + + i )
if ( _cmDspBiQuadMap [ i ] . symbol = = cmInvalidId )
_cmDspBiQuadMap [ i ] . symbol = cmSymTblRegisterStaticSymbol ( ctx - > stH , _cmDspBiQuadMap [ i ] . label ) ;
return & p - > inst ;
}
cmDspRC_t _cmDspBiQuadEqFree ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspBiQuadEq_t * p = ( cmDspBiQuadEq_t * ) inst ;
cmBiQuadEqFree ( & p - > p ) ;
return kOkDspRC ;
}
unsigned _cmDspBiQuadEqModeId ( cmDspCtx_t * ctx , cmDspInst_t * inst , unsigned modeSymId )
{
unsigned i ;
for ( i = 0 ; _cmDspBiQuadMap [ i ] . label ! = NULL ; + + i )
if ( _cmDspBiQuadMap [ i ] . symbol = = modeSymId )
return _cmDspBiQuadMap [ i ] . mode ;
cmDspInstErr ( ctx , inst , kVarNotValidDspRC , " The mode string '%s' is not valid. " , cmStringNullGuard ( cmSymTblLabel ( ctx - > stH , modeSymId ) ) ) ;
return cmInvalidId ;
}
cmDspRC_t _cmDspBiQuadEqReset ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspBiQuadEq_t * p = ( cmDspBiQuadEq_t * ) inst ;
if ( ( rc = cmDspApplyAllDefaults ( ctx , inst ) ) = = kOkDspRC )
{
cmDspZeroAudioBuf ( ctx , inst , kOutBqId ) ;
unsigned modeSymId = cmDspSymbol ( inst , kModeBqId ) ;
cmReal_t f0Hz = cmDspDouble ( inst , kF0HzBqId ) ;
cmReal_t Q = cmDspDouble ( inst , kQBqId ) ;
cmReal_t gainDb = cmDspDouble ( inst , kGainDbBqId ) ;
unsigned mode = _cmDspBiQuadEqModeId ( ctx , inst , modeSymId ) ;
bool bypassFl = cmDspBool ( inst , kBypassBqId ) ;
if ( mode ! = cmInvalidId )
cmBiQuadEqInit ( p - > p , cmDspSampleRate ( ctx ) , mode , f0Hz , Q , gainDb , bypassFl ) ;
}
return rc ;
}
cmDspRC_t _cmDspBiQuadEqExec ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspBiQuadEq_t * p = ( cmDspBiQuadEq_t * ) inst ;
cmSample_t * y = cmDspAudioBuf ( ctx , inst , kOutBqId , 0 ) ;
const cmSample_t * x = cmDspAudioBuf ( ctx , inst , kInBqId , 0 ) ;
unsigned n = cmDspAudioBufSmpCount ( ctx , inst , kOutBqId , 0 ) ;
cmBiQuadEqExec ( p - > p , x , y , n ) ;
return rc ;
}
cmDspRC_t _cmDspBiQuadEqRecv ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc ;
cmDspBiQuadEq_t * p = ( cmDspBiQuadEq_t * ) inst ;
if ( ( rc = cmDspSetEvent ( ctx , inst , evt ) ) ! = kOkDspRC )
return rc ;
cmReal_t f0Hz = p - > p - > f0Hz ;
cmReal_t Q = p - > p - > Q ;
cmReal_t gainDb = p - > p - > gainDb ;
unsigned mode = p - > p - > mode ;
if ( evt - > dstVarId = = kModeBqId )
{
if ( ( mode = _cmDspBiQuadEqModeId ( ctx , inst , cmDspSymbol ( inst , kModeBqId ) ) ) = = cmInvalidId )
rc = kVarNotValidDspRC ;
}
else
{
cmReal_t v = cmDspDouble ( inst , evt - > dstVarId ) ;
switch ( evt - > dstVarId )
{
case kF0HzBqId :
f0Hz = v ;
break ;
case kQBqId :
Q = v ;
break ;
case kGainDbBqId :
gainDb = v ;
break ;
case kBypassBqId :
p - > p - > bypassFl = cmDspBool ( inst , kBypassBqId ) ;
break ;
}
}
cmBiQuadEqSet ( p - > p , mode , f0Hz , Q , gainDb ) ;
return rc ;
}
struct cmDspClass_str * cmBiQuadEqClassCons ( cmDspCtx_t * ctx )
{
cmDspClassSetup ( & _cmBiQuadEqDC , ctx , " BiQuadEq " ,
NULL ,
_cmDspBiQuadEqAlloc ,
_cmDspBiQuadEqFree ,
_cmDspBiQuadEqReset ,
_cmDspBiQuadEqExec ,
_cmDspBiQuadEqRecv ,
NULL , NULL ,
" Bi-Quad EQ Filters " ) ;
return & _cmBiQuadEqDC ;
}
//==========================================================================================================================================
enum
{
kBypassDsId ,
kInGainDsId ,
kSrateDsId ,
kBitsDsId ,
kRectDsId ,
kFullDsId ,
kClipDbDsId ,
kOutGainDsId ,
kInDsId ,
kOutDsId
} ;
cmDspClass_t _cmDistDsDC ;
typedef struct
{
cmDspInst_t inst ;
cmDistDs * p ;
} cmDspDistDs_t ;
cmDspInst_t * _cmDspDistDsAlloc ( cmDspCtx_t * ctx , cmDspClass_t * classPtr , unsigned storeSymId , unsigned instSymId , unsigned id , unsigned va_cnt , va_list vl )
{
cmDspDistDs_t * p = cmDspInstAllocV ( cmDspDistDs_t , ctx , classPtr , instSymId , id , storeSymId , va_cnt , vl ,
1 , " bypass " , kBypassDsId , 0 , 0 , kInDsvFl | kBoolDsvFl | kOptArgDsvFl , " Bypass enable. " ,
1 , " igain " , kInGainDsId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kOptArgDsvFl , " Input gain. " ,
1 , " srate " , kSrateDsId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kOptArgDsvFl , " Down-sample rate. " ,
1 , " bits " , kBitsDsId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kOptArgDsvFl , " Bits per sample " ,
1 , " rect " , kRectDsId , 0 , 0 , kInDsvFl | kBoolDsvFl | kOptArgDsvFl , " Rectify flag " ,
1 , " full " , kFullDsId , 0 , 0 , kInDsvFl | kBoolDsvFl | kOptArgDsvFl , " 1=Full 0=Half rectify " ,
1 , " clip " , kClipDbDsId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kOptArgDsvFl , " Clip dB " ,
1 , " ogain " , kOutGainDsId , 0 , 0 , kInDsvFl | kDoubleDsvFl | kOptArgDsvFl , " Output gain " ,
1 , " in " , kInDsId , 0 , 0 , kInDsvFl | kAudioBufDsvFl , " Audio input " ,
1 , " out " , kOutDsId , 0 , 1 , kOutDsvFl | kAudioBufDsvFl , " Audio output " ,
0 ) ;
cmDspSetDefaultBool ( ctx , & p - > inst , kBypassDsId , false , false ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kInGainDsId , 0.0 , 1.0 ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kSrateDsId , 0.0 , cmDspSampleRate ( ctx ) ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kBitsDsId , 0.0 , 24.0 ) ;
cmDspSetDefaultBool ( ctx , & p - > inst , kRectDsId , false , false ) ;
cmDspSetDefaultBool ( ctx , & p - > inst , kFullDsId , false , false ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kClipDbDsId , 0.0 , 0.0 ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kOutGainDsId , 0.0 , 1.0 ) ;
p - > p = cmDistDsAlloc ( ctx - > cmProcCtx , NULL , 0 , 0 , 0 , 0 , false , false , 0 , 0 , false ) ;
return & p - > inst ;
}
cmDspRC_t _cmDspDistDsFree ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspDistDs_t * p = ( cmDspDistDs_t * ) inst ;
cmDistDsFree ( & p - > p ) ;
return kOkDspRC ;
}
cmDspRC_t _cmDspDistDsReset ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspDistDs_t * p = ( cmDspDistDs_t * ) inst ;
if ( ( rc = cmDspApplyAllDefaults ( ctx , inst ) ) = = kOkDspRC )
{
cmDspZeroAudioBuf ( ctx , inst , kOutDsId ) ;
bool bypassFl = cmDspBool ( inst , kBypassDsId ) ;
cmReal_t inGain = cmDspDouble ( inst , kInGainDsId ) ;
cmReal_t downSrate = cmDspDouble ( inst , kSrateDsId ) ;
cmReal_t bits = cmDspDouble ( inst , kBitsDsId ) ;
bool rectFl = cmDspBool ( inst , kRectDsId ) ;
bool fullFl = cmDspBool ( inst , kFullDsId ) ;
cmReal_t clipDb = cmDspDouble ( inst , kClipDbDsId ) ;
cmReal_t outGain = cmDspDouble ( inst , kOutGainDsId ) ;
cmDistDsInit ( p - > p , cmDspSampleRate ( ctx ) , inGain , downSrate , bits , rectFl , fullFl , clipDb , outGain , bypassFl ) ;
}
return rc ;
}
cmDspRC_t _cmDspDistDsExec ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspDistDs_t * p = ( cmDspDistDs_t * ) inst ;
unsigned n = cmDspAudioBufSmpCount ( ctx , inst , kOutDsId , 0 ) ;
cmSample_t * y = cmDspAudioBuf ( ctx , inst , kOutDsId , 0 ) ;
const cmSample_t * x = cmDspAudioBuf ( ctx , inst , kInDsId , 0 ) ;
cmDistDsExec ( p - > p , x , y , n ) ;
return rc ;
}
cmDspRC_t _cmDspDistDsRecv ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspDistDs_t * p = ( cmDspDistDs_t * ) inst ;
if ( ( rc = cmDspSetEvent ( ctx , inst , evt ) ) = = kOkDspRC )
{
switch ( evt - > dstVarId )
{
case kInGainDsId :
p - > p - > inGain = cmDspDouble ( inst , kInGainDsId ) ;
break ;
case kSrateDsId :
p - > p - > downSrate = cmDspDouble ( inst , kSrateDsId ) ;
break ;
case kBitsDsId :
p - > p - > bits = cmDspDouble ( inst , kBitsDsId ) ;
break ;
case kRectDsId :
p - > p - > rectFl = cmDspBool ( inst , kRectDsId ) ;
break ;
case kFullDsId :
p - > p - > fullFl = cmDspBool ( inst , kFullDsId ) ;
break ;
case kClipDbDsId :
p - > p - > clipDb = cmDspDouble ( inst , kClipDbDsId ) ;
break ;
case kOutGainDsId :
p - > p - > outGain = cmDspDouble ( inst , kOutGainDsId ) ;
break ;
case kBypassDsId :
p - > p - > bypassFl = cmDspBool ( inst , kBypassDsId ) ;
break ;
}
}
return rc ;
}
struct cmDspClass_str * cmDistDsClassCons ( cmDspCtx_t * ctx )
{
cmDspClassSetup ( & _cmDistDsDC , ctx , " DistDs " ,
NULL ,
_cmDspDistDsAlloc ,
_cmDspDistDsFree ,
_cmDspDistDsReset ,
_cmDspDistDsExec ,
_cmDspDistDsRecv ,
NULL , NULL ,
2013-03-02 01:27:08 +00:00
" Distortion and Downsampler " ) ;
2012-10-30 03:52:39 +00:00
return & _cmDistDsDC ;
}
//==========================================================================================================================================
enum
{
kInDlId ,
kOutDlId
} ;
cmDspClass_t _cmDbToLinDC ;
typedef struct
{
cmDspInst_t inst ;
} cmDspDbToLin_t ;
cmDspInst_t * _cmDspDbToLinAlloc ( cmDspCtx_t * ctx , cmDspClass_t * classPtr , unsigned storeSymId , unsigned instSymId , unsigned id , unsigned va_cnt , va_list vl )
{
cmDspDbToLin_t * p = cmDspInstAllocV ( cmDspDbToLin_t , ctx , classPtr , instSymId , id , storeSymId , va_cnt , vl ,
1 , " in " , kInDlId , 0 , 0 , kInDsvFl | kDoubleDsvFl , " Input " ,
1 , " out " , kOutDlId , 0 , 0 , kOutDsvFl | kDoubleDsvFl , " Output " ,
0 ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kInDlId , 0.0 , - 1000.0 ) ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kOutDlId , 0.0 , 0.0 ) ;
return & p - > inst ;
}
cmDspRC_t _cmDspDbToLinReset ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
return cmDspApplyAllDefaults ( ctx , inst ) ;
}
cmDspRC_t _cmDspDbToLinRecv ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
if ( ( rc = cmDspSetEvent ( ctx , inst , evt ) ) = = kOkDspRC )
{
if ( evt - > dstVarId = = kInDlId )
{
double db = cmMax ( 0.0 , cmMin ( 100.0 , cmDspDouble ( inst , kInDlId ) ) ) ;
double lin = db = = 0 ? 0.0 : pow ( 10.0 , ( db - 100.0 ) / 20.0 ) ;
cmDspSetDouble ( ctx , inst , kOutDlId , lin ) ;
}
}
return rc ;
}
struct cmDspClass_str * cmDbToLinClassCons ( cmDspCtx_t * ctx )
{
cmDspClassSetup ( & _cmDbToLinDC , ctx , " DbToLin " ,
NULL ,
_cmDspDbToLinAlloc ,
NULL ,
_cmDspDbToLinReset ,
NULL ,
_cmDspDbToLinRecv ,
NULL , NULL ,
" dB to Linear converter " ) ;
return & _cmDbToLinDC ;
}
//==========================================================================================================================================
// Pass any N of M inputs
enum
{
kInChCntNoId ,
kOutChCntNoId ,
kXfadeMsNoId ,
kCmdNoId ,
kSelIdxNoId ,
kBaseGateNoId
} ;
cmDspClass_t _cmNofM_DC ;
typedef struct
{
cmDspInst_t inst ;
unsigned iChCnt ;
unsigned oChCnt ;
unsigned * map ; // map[ oChCnt ]
cmXfader * * xf ; // xf[ oChCnt ];
unsigned cfgSymId ;
unsigned onSymId ;
unsigned offSymId ;
bool verboseFl ;
unsigned baseBaseInNoId ; // first data input port id
unsigned baseBaseOutNoId ; // first data output port id
unsigned baseInFloatNoId ;
unsigned baseInBoolNoId ;
unsigned baseInSymNoId ;
unsigned baseInAudioNoId ;
unsigned baseOutFloatNoId ;
unsigned baseOutBoolNoId ;
unsigned baseOutSymNoId ;
unsigned baseOutAudioNoId ;
bool printFl ;
} cmDspNofM_t ;
cmDspInst_t * _cmDspNofM_Alloc ( cmDspCtx_t * ctx , cmDspClass_t * classPtr , unsigned storeSymId , unsigned instSymId , unsigned id , unsigned va_cnt , va_list vl )
{
if ( va_cnt < 2 )
{
cmDspClassErr ( ctx , classPtr , kVarArgParseFailDspRC , " The 'NofM' constructor must given input and output channel counts. " ) ;
return NULL ;
}
va_list vl1 ;
va_copy ( vl1 , vl ) ;
int iChCnt = va_arg ( vl , int ) ;
int oChCnt = va_arg ( vl , int ) ;
if ( oChCnt > iChCnt )
{
2013-10-17 01:52:59 +00:00
va_end ( vl1 ) ;
2012-10-30 03:52:39 +00:00
cmDspClassErr ( ctx , classPtr , kVarArgParseFailDspRC , " The 'NofM' output count must be less than or equal to the input count. " ) ;
return NULL ;
}
unsigned baseInFloatNoId = kBaseGateNoId + iChCnt ;
unsigned baseInBoolNoId = baseInFloatNoId + iChCnt ;
unsigned baseInSymNoId = baseInBoolNoId + iChCnt ;
unsigned baseInAudioNoId = baseInSymNoId + iChCnt ;
unsigned baseOutFloatNoId = baseInAudioNoId + iChCnt ;
unsigned baseOutBoolNoId = baseOutFloatNoId + oChCnt ;
unsigned baseOutSymNoId = baseOutBoolNoId + oChCnt ;
unsigned baseOutAudioNoId = baseOutSymNoId + oChCnt ;
unsigned i ;
cmDspNofM_t * p = cmDspInstAllocV ( cmDspNofM_t , ctx , classPtr , instSymId , id , storeSymId , va_cnt , vl1 ,
1 , " ichs " , kInChCntNoId , 0 , 0 , kUIntDsvFl | kReqArgDsvFl , " Input channel count. " ,
1 , " ochs " , kOutChCntNoId , 0 , 0 , kUIntDsvFl | kReqArgDsvFl , " Output channel count. " ,
1 , " ms " , kXfadeMsNoId , 0 , 0 , kDoubleDsvFl | kInDsvFl | kOptArgDsvFl , " Audio Cross-fade time in milliseconds. " ,
1 , " cmd " , kCmdNoId , 0 , 0 , kSymDsvFl | kInDsvFl , " Command input. " ,
1 , " seli " , kSelIdxNoId , 0 , 0 , kUIntDsvFl | kInDsvFl , " Enable gate at index. " ,
iChCnt , " sel " , kBaseGateNoId , 0 , 0 , kBoolDsvFl | kInDsvFl , " Selector Gate inputs. " ,
iChCnt , " f-in " , baseInFloatNoId , 0 , 0 , kDoubleDsvFl | kInDsvFl , " Float input " ,
iChCnt , " b-in " , baseInBoolNoId , 0 , 0 , kBoolDsvFl | kInDsvFl , " Bool input " ,
iChCnt , " s-in " , baseInSymNoId , 0 , 0 , kSymDsvFl | kInDsvFl , " Symbol input " ,
iChCnt , " a-in " , baseInAudioNoId , 0 , 0 , kAudioBufDsvFl | kInDsvFl , " Audio input " ,
oChCnt , " f-out " , baseOutFloatNoId , 0 , 0 , kDoubleDsvFl | kOutDsvFl , " Float output " ,
oChCnt , " b-out " , baseOutBoolNoId , 0 , 0 , kBoolDsvFl | kOutDsvFl , " Bool output " ,
oChCnt , " s-out " , baseOutSymNoId , 0 , 0 , kSymDsvFl | kOutDsvFl , " Symbol output " ,
oChCnt , " a-out " , baseOutAudioNoId , 0 , 1 , kAudioBufDsvFl | kOutDsvFl , " Audio output " ,
0 ) ;
p - > iChCnt = iChCnt ;
p - > oChCnt = oChCnt ;
p - > map = cmMemAllocZ ( unsigned , oChCnt ) ;
p - > xf = cmMemAllocZ ( cmXfader * , oChCnt ) ;
p - > cfgSymId = cmSymTblRegisterStaticSymbol ( ctx - > stH , " cfg " ) ;
p - > onSymId = cmSymTblRegisterStaticSymbol ( ctx - > stH , " on " ) ;
p - > offSymId = cmSymTblRegisterStaticSymbol ( ctx - > stH , " off " ) ;
p - > verboseFl = false ;
p - > baseBaseInNoId = baseInFloatNoId ;
p - > baseBaseOutNoId = baseOutFloatNoId ;
p - > baseInFloatNoId = baseInFloatNoId ;
p - > baseInBoolNoId = baseInBoolNoId ;
p - > baseInSymNoId = baseInSymNoId ;
p - > baseInAudioNoId = baseInAudioNoId ;
p - > baseOutFloatNoId = baseOutFloatNoId ;
p - > baseOutBoolNoId = baseOutBoolNoId ;
p - > baseOutSymNoId = baseOutSymNoId ;
p - > baseOutAudioNoId = baseOutAudioNoId ;
for ( i = 0 ; i < oChCnt ; + + i )
{
cmDspSetDefaultDouble ( ctx , & p - > inst , baseOutFloatNoId + i , 0.0 , 0.0 ) ;
cmDspSetDefaultBool ( ctx , & p - > inst , baseOutBoolNoId + i , false , false ) ;
cmDspSetDefaultSymbol ( ctx , & p - > inst , baseOutSymNoId + i , cmInvalidId ) ;
p - > xf [ i ] = cmXfaderAlloc ( ctx - > cmProcCtx , NULL , 0 , 0 , 0 ) ;
}
cmDspSetDefaultDouble ( ctx , & p - > inst , kXfadeMsNoId , 0.0 , 15.0 ) ;
2013-10-17 01:52:59 +00:00
va_end ( vl1 ) ;
2012-10-30 03:52:39 +00:00
return & p - > inst ;
}
cmDspRC_t _cmDspNofM_Free ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspNofM_t * p = ( cmDspNofM_t * ) inst ;
unsigned i ;
for ( i = 0 ; i < p - > oChCnt ; + + i )
cmXfaderFree ( & p - > xf [ i ] ) ;
cmMemFree ( p - > map ) ;
cmMemFree ( p - > xf ) ;
return kOkDspRC ;
}
cmDspRC_t _cmDspNofM_Reset ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspNofM_t * p = ( cmDspNofM_t * ) inst ;
unsigned i ;
if ( ( rc = cmDspApplyAllDefaults ( ctx , inst ) ) = = kOkDspRC )
{
for ( i = 0 ; i < p - > oChCnt ; + + i )
{
cmDspZeroAudioBuf ( ctx , inst , p - > baseOutAudioNoId + i ) ;
p - > map [ i ] = cmInvalidIdx ;
double xfadeMs = cmDspDouble ( inst , kXfadeMsNoId ) ;
cmXfaderInit ( p - > xf [ i ] , cmDspSampleRate ( ctx ) , p - > iChCnt , xfadeMs ) ;
}
}
return rc ;
}
cmDspRC_t _cmDspNofM_Exec ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspNofM_t * p = ( cmDspNofM_t * ) inst ;
unsigned i ;
const cmSample_t * x [ p - > iChCnt ] ;
for ( i = 0 ; i < p - > iChCnt ; + + i )
x [ i ] = cmDspAudioBuf ( ctx , inst , p - > baseInAudioNoId + i , 0 ) ;
// for each valid p->map[] element
for ( i = 0 ; i < p - > oChCnt ; + + i )
{
cmSample_t * y = cmDspAudioBuf ( ctx , inst , p - > baseOutAudioNoId + i , 0 ) ;
unsigned n = cmDspAudioBufSmpCount ( ctx , inst , p - > baseOutAudioNoId + i , 0 ) ;
if ( y ! = NULL )
{
y = cmVOS_Zero ( y , n ) ;
cmXfaderExecAudio ( p - > xf [ i ] , n , NULL , p - > iChCnt , x , y ) ;
}
}
return rc ;
}
cmDspRC_t _cmDspNofM_Recv ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspNofM_t * p = ( cmDspNofM_t * ) inst ;
unsigned i , j ;
assert ( evt - > dstVarId < p - > baseBaseOutNoId ) ;
// store the incoming value
if ( ( rc = cmDspSetEvent ( ctx , inst , evt ) ) ! = kOkDspRC )
return rc ;
// if this is a fade time
if ( evt - > dstVarId = = kXfadeMsNoId )
{
for ( i = 0 ; i < p - > oChCnt ; + + i )
cmXfaderSetXfadeTime ( p - > xf [ i ] , cmDspDouble ( inst , kXfadeMsNoId ) ) ;
return rc ;
}
// if this is an index selector
if ( kSelIdxNoId = = evt - > dstVarId )
{
unsigned idx ;
if ( ( idx = cmDspUInt ( inst , kSelIdxNoId ) ) > = p - > iChCnt )
rc = cmDspInstErr ( ctx , inst , kInvalidArgDspRC , " The selection index ('%i') is out of the channel range, (%i). " , idx , p - > iChCnt ) ;
else
{
cmDspSetBool ( ctx , inst , kBaseGateNoId + idx , true ) ;
if ( p - > verboseFl )
cmRptPrintf ( ctx - > rpt , " nom seli:%i \n " , idx ) ;
}
return rc ;
}
// NOTE: the internal state DOES NOT CHANGE until a message arrives
// on the 'cmd' port
// if anything arrives on the command port - then read the gate states and rebuild the map
if ( evt - > dstVarId = = kCmdNoId )
{
unsigned cmdSymId = cmDspSymbol ( inst , kCmdNoId ) ;
// if cmdSymId == 'on' then turn on all selection gates
if ( cmdSymId = = p - > onSymId )
{
for ( i = 0 ; i < p - > oChCnt ; + + i )
cmDspSetBool ( ctx , inst , kBaseGateNoId + i , true ) ;
}
else
// if cmdSymId == 'off' then turn off all selection gates
if ( cmdSymId = = p - > offSymId )
{
if ( p - > verboseFl )
cmRptPrintf ( ctx - > rpt , " nom: off \n " ) ;
for ( i = 0 ; i < p - > oChCnt ; + + i )
cmDspSetBool ( ctx , inst , kBaseGateNoId + i , false ) ;
}
else
// cmdSymId == 'print' then print the in/out map[]
if ( cmdSymId = = cmSymTblId ( ctx - > stH , " print " ) )
{
for ( i = 0 ; i < p - > oChCnt ; + + i )
cmRptPrintf ( ctx - > rpt , " %i:%i " , i , p - > map [ i ] ) ;
cmRptPrintf ( ctx - > rpt , " \n " ) ;
cmRptPrintf ( ctx - > rpt , " %i usecs \n " , ctx - > execDurUsecs ) ;
p - > printFl = ! p - > printFl ;
}
if ( p - > verboseFl )
cmRptPrintf ( ctx - > rpt , " Nom: %s " , inst - > symId ! = cmInvalidId ? cmSymTblLabel ( ctx - > stH , inst - > symId ) : " " ) ;
// 5/26
if ( p - > iChCnt = = p - > oChCnt )
cmVOU_Fill ( p - > map , p - > oChCnt , cmInvalidIdx ) ;
// for each input
for ( i = 0 , j = 0 ; i < p - > iChCnt ; + + i )
{
// if this input is switched on
if ( cmDspBool ( inst , kBaseGateNoId + i ) )
{
if ( j > = p - > oChCnt )
{
cmDspInstErr ( ctx , inst , kVarNotValidDspRC , " To many inputs have been turned on for %i outputs. " , p - > oChCnt ) ;
break ;
}
// assign input i to output j
p - > map [ j ] = i ;
// fade in ch i and fade out all others
cmXfaderSelectOne ( p - > xf [ j ] , i ) ;
+ + j ;
if ( p - > verboseFl )
cmRptPrintf ( ctx - > rpt , " %i " , i ) ;
}
else // 5/26
{
if ( p - > iChCnt = = p - > oChCnt )
+ + j ;
}
}
// deselect all other output channels
//for(; j<p->oChCnt; ++j)
//{
// p->map[j] = cmInvalidIdx;
// cmXfaderAllOff(p->xf[j]);
//}
// 5/26
if ( p - > iChCnt = = p - > oChCnt )
{
for ( j = 0 ; j < p - > oChCnt ; + + j )
if ( p - > map [ j ] = = cmInvalidIdx )
cmXfaderAllOff ( p - > xf [ j ] ) ;
}
else
{
for ( ; j < p - > oChCnt ; + + j )
{
p - > map [ j ] = cmInvalidIdx ;
cmXfaderAllOff ( p - > xf [ j ] ) ;
}
}
if ( p - > verboseFl )
cmRptPrintf ( ctx - > rpt , " \n " ) ;
// zero the audio buffers of unused output channels
for ( i = 0 ; i < p - > oChCnt ; + + i )
if ( p - > map [ i ] = = cmInvalidIdx )
cmDspZeroAudioBuf ( ctx , inst , p - > baseOutAudioNoId + i ) ;
}
// if this is an input data event
if ( p - > baseBaseInNoId < = evt - > dstVarId & & evt - > dstVarId < p - > baseBaseOutNoId )
{
// get the input channel this event occurred on
unsigned iChIdx = ( evt - > dstVarId - p - > baseBaseInNoId ) % p - > iChCnt ;
// is iChIdx mapped to an output ...
for ( i = 0 ; i < p - > oChCnt ; + + i )
if ( p - > map [ i ] = = iChIdx )
break ;
// ... no - nothing else to do
if ( i = = p - > oChCnt )
return kOkDspRC ;
// ... yes set the output ...
// double
if ( p - > baseInFloatNoId < = evt - > dstVarId & & evt - > dstVarId < p - > baseInFloatNoId + p - > iChCnt )
{
cmDspSetDouble ( ctx , inst , p - > baseOutFloatNoId + i , cmDspDouble ( inst , evt - > dstVarId ) ) ;
}
else
// bool
if ( p - > baseInBoolNoId < = evt - > dstVarId & & evt - > dstVarId < p - > baseInBoolNoId + p - > iChCnt )
{
cmDspSetBool ( ctx , inst , p - > baseOutBoolNoId + i , cmDspBool ( inst , evt - > dstVarId ) ) ;
if ( p - > printFl )
cmRptPrintf ( ctx - > rpt , " %i %i \n " , p - > baseOutBoolNoId + i , cmDspBool ( inst , evt - > dstVarId ) ) ;
}
else
// symbol
if ( p - > baseInSymNoId < = evt - > dstVarId & & evt - > dstVarId < p - > baseInSymNoId + p - > iChCnt )
cmDspSetSymbol ( ctx , inst , p - > baseOutSymNoId + i , cmDspSymbol ( inst , evt - > dstVarId ) ) ;
}
return rc ;
}
struct cmDspClass_str * cmNofMClassCons ( cmDspCtx_t * ctx )
{
cmDspClassSetup ( & _cmNofM_DC , ctx , " NofM " ,
NULL ,
_cmDspNofM_Alloc ,
_cmDspNofM_Free ,
_cmDspNofM_Reset ,
_cmDspNofM_Exec ,
_cmDspNofM_Recv ,
NULL , NULL ,
" N of M Switch " ) ;
return & _cmNofM_DC ;
}
//==========================================================================================================================================
enum
{
kInChCnt1oId ,
kInChIdx1oId ,
kOutFloat1oId ,
kOutBool1oId ,
kOutSym1oId ,
kOutAudio1oId ,
kBaseInFloat1oId
} ;
cmDspClass_t _cm1ofN_DC ;
typedef struct
{
cmDspInst_t inst ;
unsigned iChCnt ;
unsigned oChCnt ;
unsigned iChIdx ;
unsigned baseBaseIn1oId ; // first data input port id
unsigned baseInFloat1oId ;
unsigned baseInBool1oId ;
unsigned baseInSym1oId ;
unsigned baseInAudio1oId ;
unsigned baseOutFloat1oId ;
unsigned baseOutBool1oId ;
unsigned baseOutSym1oId ;
unsigned baseOutAudio1oId ;
} cmDsp1ofN_t ;
cmDspInst_t * _cmDsp1ofN_Alloc ( cmDspCtx_t * ctx , cmDspClass_t * classPtr , unsigned storeSymId , unsigned instSymId , unsigned id , unsigned va_cnt , va_list vl )
{
if ( va_cnt < 1 )
{
cmDspClassErr ( ctx , classPtr , kVarArgParseFailDspRC , " The '1ofN' constructor must given input channel count. " ) ;
return NULL ;
}
va_list vl1 ;
va_copy ( vl1 , vl ) ;
int iChCnt = va_arg ( vl , int ) ;
unsigned baseInFloat1oId = kBaseInFloat1oId ;
unsigned baseInBool1oId = baseInFloat1oId + iChCnt ;
unsigned baseInSym1oId = baseInBool1oId + iChCnt ;
unsigned baseInAudio1oId = baseInSym1oId + iChCnt ;
cmDsp1ofN_t * p = cmDspInstAllocV ( cmDsp1ofN_t , ctx , classPtr , instSymId , id , storeSymId , va_cnt , vl1 ,
1 , " ichs " , kInChCnt1oId , 0 , 0 , kUIntDsvFl | kReqArgDsvFl , " Input channel count. " ,
1 , " chidx " , kInChIdx1oId , 0 , 0 , kUIntDsvFl | kReqArgDsvFl | kInDsvFl , " Input channel selector index. " ,
1 , " f-out " , kOutFloat1oId , 0 , 0 , kDoubleDsvFl | kOutDsvFl , " Float output " ,
1 , " b-out " , kOutBool1oId , 0 , 0 , kBoolDsvFl | kOutDsvFl , " Bool output " ,
1 , " s-out " , kOutSym1oId , 0 , 0 , kSymDsvFl | kOutDsvFl , " Symbol output " ,
1 , " a-out " , kOutAudio1oId , 0 , 1 , kAudioBufDsvFl | kOutDsvFl , " Audio output " ,
iChCnt , " f-in " , baseInFloat1oId , 0 , 0 , kDoubleDsvFl | kInDsvFl , " Float input " ,
iChCnt , " b-in " , baseInBool1oId , 0 , 0 , kBoolDsvFl | kInDsvFl , " Bool input " ,
iChCnt , " s-in " , baseInSym1oId , 0 , 0 , kSymDsvFl | kInDsvFl , " Symbol input " ,
iChCnt , " a-in " , baseInAudio1oId , 0 , 0 , kAudioBufDsvFl | kInDsvFl , " Audio input " ,
0 ) ;
p - > iChCnt = iChCnt ;
p - > baseBaseIn1oId = kBaseInFloat1oId ;
p - > baseInFloat1oId = baseInFloat1oId ;
p - > baseInBool1oId = baseInBool1oId ;
p - > baseInSym1oId = baseInSym1oId ;
p - > baseInAudio1oId = baseInAudio1oId ;
cmDspSetDefaultDouble ( ctx , & p - > inst , kOutFloat1oId , 0.0 , 0.0 ) ;
cmDspSetDefaultBool ( ctx , & p - > inst , kOutBool1oId , false , false ) ;
cmDspSetDefaultSymbol ( ctx , & p - > inst , kOutSym1oId , cmInvalidId ) ;
2013-10-17 01:52:59 +00:00
va_end ( vl1 ) ;
2012-10-30 03:52:39 +00:00
return & p - > inst ;
}
cmDspRC_t _cmDsp1ofN_Free ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
return kOkDspRC ;
}
cmDspRC_t _cmDsp1ofN_Reset ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
if ( ( rc = cmDspApplyAllDefaults ( ctx , inst ) ) = = kOkDspRC )
{
cmDspZeroAudioBuf ( ctx , inst , kOutAudio1oId ) ;
}
return rc ;
}
cmDspRC_t _cmDsp1ofN_Exec ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDsp1ofN_t * p = ( cmDsp1ofN_t * ) inst ;
unsigned iChIdx = cmDspUInt ( inst , kInChIdx1oId ) ;
cmSample_t * dp = cmDspAudioBuf ( ctx , inst , kOutAudio1oId , 0 ) ;
const cmSample_t * sp = cmDspAudioBuf ( ctx , inst , p - > baseInAudio1oId + iChIdx , 0 ) ;
unsigned n = cmDspAudioBufSmpCount ( ctx , inst , kOutAudio1oId , 0 ) ;
if ( dp ! = NULL )
{
if ( sp = = NULL )
cmVOS_Zero ( dp , n ) ;
else
cmVOS_Copy ( dp , n , sp ) ;
}
return rc ;
}
cmDspRC_t _cmDsp1ofN_Recv ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDsp1ofN_t * p = ( cmDsp1ofN_t * ) inst ;
// ignore out of range input channel
if ( evt - > dstVarId = = kInChIdx1oId & & cmDsvGetUInt ( evt - > valuePtr ) > = p - > iChCnt )
{
cmDspInstErr ( ctx , inst , kVarNotValidDspRC , " The selector channel index %i is out of range. " , cmDsvGetUInt ( evt - > valuePtr ) ) ;
return kOkDspRC ;
}
// store the incoming value
if ( ( rc = cmDspSetEvent ( ctx , inst , evt ) ) ! = kOkDspRC )
return rc ;
// if this is an input data event
if ( p - > baseBaseIn1oId < = evt - > dstVarId )
{
// get the input channel this event occurred on
unsigned iChIdx = ( evt - > dstVarId - p - > baseBaseIn1oId ) % p - > iChCnt ;
// if the event did not arrive on the selected input channel - there is nothing else to do
if ( iChIdx ! = cmDspUInt ( inst , kInChIdx1oId ) )
return kOkDspRC ;
// The event arrived on the input channel - send it out the output
// double
if ( p - > baseInFloat1oId < = evt - > dstVarId & & evt - > dstVarId < p - > baseInFloat1oId + p - > iChCnt )
cmDspSetDouble ( ctx , inst , kOutFloat1oId , cmDspDouble ( inst , evt - > dstVarId ) ) ;
else
// bool
if ( p - > baseInBool1oId < = evt - > dstVarId & & evt - > dstVarId < p - > baseInBool1oId + p - > iChCnt )
cmDspSetBool ( ctx , inst , kOutBool1oId , cmDspBool ( inst , evt - > dstVarId ) ) ;
else
// symbol
if ( p - > baseInSym1oId < = evt - > dstVarId & & evt - > dstVarId < p - > baseInSym1oId + p - > iChCnt )
cmDspSetSymbol ( ctx , inst , kOutSym1oId , cmDspSymbol ( inst , evt - > dstVarId ) ) ;
}
return rc ;
}
struct cmDspClass_str * cm1ofNClassCons ( cmDspCtx_t * ctx )
{
cmDspClassSetup ( & _cm1ofN_DC , ctx , " 1ofN " ,
NULL ,
_cmDsp1ofN_Alloc ,
_cmDsp1ofN_Free ,
_cmDsp1ofN_Reset ,
_cmDsp1ofN_Exec ,
_cmDsp1ofN_Recv ,
NULL , NULL ,
" 1 of N Switch " ) ;
return & _cm1ofN_DC ;
}
//==========================================================================================================================================
// Send a 'true' out on the selected channel.
// Send a 'false' out on the deselected channel.
enum
{
kChCnt1uId ,
kSel1uId ,
kBaseOut1uId
} ;
cmDspClass_t _cm1Up_DC ;
typedef struct
{
cmDspInst_t inst ;
} cmDsp1Up_t ;
cmDspInst_t * _cmDsp1Up_Alloc ( cmDspCtx_t * ctx , cmDspClass_t * classPtr , unsigned storeSymId , unsigned instSymId , unsigned id , unsigned va_cnt , va_list vl )
{
if ( va_cnt < 1 )
{
cmDspClassErr ( ctx , classPtr , kVarArgParseFailDspRC , " The '1Up' constructor must given output channel count. " ) ;
return NULL ;
}
va_list vl1 ;
va_copy ( vl1 , vl ) ;
int chCnt = va_arg ( vl , int ) ;
cmDsp1Up_t * p = cmDspInstAllocV ( cmDsp1Up_t , ctx , classPtr , instSymId , id , storeSymId , va_cnt , vl1 ,
1 , " chcnt " , kChCnt1uId , 0 , 0 , kUIntDsvFl | kReqArgDsvFl , " Output channel count. " ,
1 , " sel " , kSel1uId , 0 , 0 , kUIntDsvFl | kOptArgDsvFl | kInDsvFl , " Channel index selector. " ,
chCnt , " out " , kBaseOut1uId , 0 , 0 , kBoolDsvFl | kOutDsvFl , " Gate outputs " ,
0 ) ;
unsigned i ;
cmDspSetDefaultUInt ( ctx , & p - > inst , kSel1uId , 0.0 , 0.0 ) ;
for ( i = 0 ; i < chCnt ; + + i )
cmDspSetDefaultBool ( ctx , & p - > inst , kBaseOut1uId + i , false , false ) ;
2013-10-17 01:52:59 +00:00
va_end ( vl1 ) ;
2012-10-30 03:52:39 +00:00
return & p - > inst ;
}
cmDspRC_t _cmDsp1Up_Reset ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
if ( ( rc = cmDspApplyAllDefaults ( ctx , inst ) ) = = kOkDspRC )
{
unsigned chIdx = cmDspUInt ( inst , kSel1uId ) ;
unsigned chCnt = cmDspUInt ( inst , kChCnt1uId ) ;
unsigned i ;
for ( i = 0 ; i < chCnt ; + + i )
cmDspSetBool ( ctx , inst , kBaseOut1uId + i , i = = chIdx ) ;
}
return rc ;
}
cmDspRC_t _cmDsp1Up_Recv ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
if ( evt - > dstVarId = = kSel1uId )
{
unsigned chIdx = cmDspUInt ( inst , kSel1uId ) ;
unsigned chCnt = cmDspUInt ( inst , kChCnt1uId ) ;
// turn off the previously selected channel
if ( chIdx ! = cmInvalidIdx & & chIdx < chCnt )
cmDspSetBool ( ctx , inst , kBaseOut1uId + chIdx , false ) ;
// set the new channel index
cmDspSetEvent ( ctx , inst , evt ) ;
// get the new channel index
chIdx = cmDspUInt ( inst , kSel1uId ) ;
// send the new channel index
if ( chIdx ! = cmInvalidIdx & & chIdx < chCnt )
cmDspSetBool ( ctx , inst , kBaseOut1uId + chIdx , true ) ;
}
return rc ;
}
struct cmDspClass_str * cm1UpClassCons ( cmDspCtx_t * ctx )
{
cmDspClassSetup ( & _cm1Up_DC , ctx , " 1Up " ,
NULL ,
_cmDsp1Up_Alloc ,
NULL ,
_cmDsp1Up_Reset ,
NULL ,
_cmDsp1Up_Recv ,
NULL , NULL ,
" Set one input high and all others low. " ) ;
return & _cm1Up_DC ;
}
//==========================================================================================================================================
// Convert a 'true'/'false' gate to an 'on'/'off' symbol
enum
{
kOnSymGsId ,
kOffSymGsId ,
kOnGsId ,
kOffGsId ,
kBothGsId ,
kOutGsId
} ;
cmDspClass_t _cmGateToSym_DC ;
typedef struct
{
cmDspInst_t inst ;
} cmDspGateToSym_t ;
cmDspInst_t * _cmDspGateToSym_Alloc ( cmDspCtx_t * ctx , cmDspClass_t * classPtr , unsigned storeSymId , unsigned instSymId , unsigned id , unsigned va_cnt , va_list vl )
{
cmDspGateToSym_t * p = cmDspInstAllocV ( cmDspGateToSym_t , ctx , classPtr , instSymId , id , storeSymId , va_cnt , vl ,
1 , " on_sym " , kOnSymGsId , 0 , 0 , kSymDsvFl | kInDsvFl | kOptArgDsvFl , " 'on' symbol id (default:'on') " ,
1 , " off_sym " , kOffSymGsId , 0 , 0 , kSymDsvFl | kInDsvFl | kOptArgDsvFl , " 'off' symbol id (default:'off') " ,
2012-12-18 22:46:07 +00:00
1 , " on " , kOnGsId , 0 , 0 , kBoolDsvFl | kInDsvFl , " On - send out 'on' symbol when a 'true' is received. " ,
1 , " off " , kOffGsId , 0 , 0 , kBoolDsvFl | kInDsvFl , " Off - send out 'off' symbol when a 'false' is received. " ,
1 , " both " , kBothGsId , 0 , 0 , kBoolDsvFl | kInDsvFl , " Send 'on' on 'true' and 'off' on 'false'. " ,
1 , " out " , kOutGsId , 0 , 0 , kSymDsvFl | kOutDsvFl , " Output " ,
2012-10-30 03:52:39 +00:00
0 ) ;
unsigned onSymId = cmSymTblRegisterStaticSymbol ( ctx - > stH , " on " ) ;
unsigned offSymId = cmSymTblRegisterStaticSymbol ( ctx - > stH , " off " ) ;
cmDspSetDefaultSymbol ( ctx , & p - > inst , kOnSymGsId , onSymId ) ;
cmDspSetDefaultSymbol ( ctx , & p - > inst , kOffSymGsId , offSymId ) ;
cmDspSetDefaultSymbol ( ctx , & p - > inst , kOutGsId , cmInvalidId ) ;
return & p - > inst ;
}
cmDspRC_t _cmDspGateToSym_Reset ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
if ( ( rc = cmDspApplyAllDefaults ( ctx , inst ) ) = = kOkDspRC )
{
}
return rc ;
}
cmDspRC_t _cmDspGateToSym_Recv ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
if ( ( rc = cmDspSetEvent ( ctx , inst , evt ) ) = = kOkDspRC )
{
unsigned onSymId = cmDspSymbol ( inst , kOnSymGsId ) ;
unsigned offSymId = cmDspSymbol ( inst , kOffSymGsId ) ;
switch ( evt - > dstVarId )
{
case kOnGsId :
if ( cmDspBool ( inst , kOnGsId ) )
cmDspSetSymbol ( ctx , inst , kOutGsId , onSymId ) ;
break ;
case kOffGsId :
2013-09-28 19:40:55 +00:00
if ( ! cmDspBool ( inst , kOffGsId ) )
2012-10-30 03:52:39 +00:00
cmDspSetSymbol ( ctx , inst , kOutGsId , offSymId ) ;
break ;
case kBothGsId :
cmDspSetSymbol ( ctx , inst , kOutGsId , cmDspBool ( inst , kBothGsId ) ? onSymId : offSymId ) ;
break ;
}
}
return rc ;
}
struct cmDspClass_str * cmGateToSymClassCons ( cmDspCtx_t * ctx )
{
cmDspClassSetup ( & _cmGateToSym_DC , ctx , " GateToSym " ,
NULL ,
_cmDspGateToSym_Alloc ,
NULL ,
_cmDspGateToSym_Reset ,
NULL ,
_cmDspGateToSym_Recv ,
NULL , NULL ,
" Convert a 'true'/'false' gate to an 'on'/'off' symbol. " ) ;
return & _cmGateToSym_DC ;
}
//==========================================================================================================================================
enum
{
kOutPtsId ,
kBaseInPtsId
} ;
cmDspClass_t _cmPortToSym_DC ;
typedef struct
{
cmDspInst_t inst ;
unsigned * symIdArray ;
unsigned symIdCnt ;
unsigned baseOutPtsId ;
} cmDspPortToSym_t ;
cmDspInst_t * _cmDspPortToSym_Alloc ( cmDspCtx_t * ctx , cmDspClass_t * classPtr , unsigned storeSymId , unsigned instSymId , unsigned id , unsigned va_cnt , va_list vl )
{
va_list vl1 ;
va_copy ( vl1 , vl ) ;
if ( va_cnt < 1 )
{
2013-10-17 01:52:59 +00:00
va_end ( vl1 ) ;
2012-10-30 03:52:39 +00:00
cmDspClassErr ( ctx , classPtr , kVarArgParseFailDspRC , " The 'PortToSym' constructor argument list must contain at least one symbol label. " ) ;
return NULL ;
}
unsigned symCnt = va_cnt ;
unsigned argCnt = 1 + 2 * symCnt ;
cmDspVarArg_t args [ argCnt + 1 ] ;
unsigned * symIdArray = cmMemAllocZ ( unsigned , symCnt ) ;
unsigned baseOutPtsId = kBaseInPtsId + symCnt ;
// setup the output port arg recd
cmDspArgSetup ( ctx , args , " out " , cmInvalidId , kOutPtsId , 0 , 0 , kOutDsvFl | kSymDsvFl , " Output " ) ;
unsigned i ;
for ( i = 0 ; i < symCnt ; + + i )
{
// get the symbol label
const cmChar_t * symLabel = va_arg ( vl , const char * ) ;
assert ( symLabel ! = NULL ) ;
// register the symbol
symIdArray [ i ] = cmSymTblRegisterSymbol ( ctx - > stH , symLabel ) ;
cmDspArgSetup ( ctx , args + kBaseInPtsId + i , symLabel , cmInvalidId , kBaseInPtsId + i , 0 , 0 , kInDsvFl | kTypeDsvMask , cmTsPrintfH ( ctx - > lhH , " %s Input. " , symLabel ) ) ;
cmDspArgSetup ( ctx , args + baseOutPtsId + i , symLabel , cmInvalidId , baseOutPtsId + i , 0 , 0 , kOutDsvFl | kSymDsvFl , cmTsPrintfH ( ctx - > lhH , " %s Output. " , symLabel ) ) ;
}
cmDspArgSetupNull ( args + argCnt ) ;
cmDspPortToSym_t * p = cmDspInstAlloc ( cmDspPortToSym_t , ctx , classPtr , args , instSymId , id , storeSymId , 0 , vl1 ) ;
p - > symIdCnt = symCnt ;
p - > symIdArray = symIdArray ;
p - > baseOutPtsId = baseOutPtsId ;
cmDspSetDefaultSymbol ( ctx , & p - > inst , kOutPtsId , cmInvalidId ) ;
2013-10-17 01:52:59 +00:00
va_end ( vl1 ) ;
2012-10-30 03:52:39 +00:00
return & p - > inst ;
}
cmDspRC_t _cmDspPortToSym_Free ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspPortToSym_t * p = ( cmDspPortToSym_t * ) inst ;
cmMemFree ( p - > symIdArray ) ;
return kOkDspRC ;
}
cmDspRC_t _cmDspPortToSym_Reset ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
return cmDspApplyAllDefaults ( ctx , inst ) ;
}
cmDspRC_t _cmDspPortToSym_Recv ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspPortToSym_t * p = ( cmDspPortToSym_t * ) inst ;
// if a msg of any type is recieved on an input port - send out the associated symbol
if ( kBaseInPtsId < = evt - > dstVarId & & evt - > dstVarId < kBaseInPtsId + p - > symIdCnt )
{
unsigned idx = evt - > dstVarId - kBaseInPtsId ;
assert ( idx < p - > symIdCnt ) ;
cmDspSetSymbol ( ctx , inst , p - > baseOutPtsId + idx , p - > symIdArray [ idx ] ) ;
return cmDspSetSymbol ( ctx , inst , kOutPtsId , p - > symIdArray [ evt - > dstVarId - kBaseInPtsId ] ) ;
}
return rc ;
}
struct cmDspClass_str * cmPortToSymClassCons ( cmDspCtx_t * ctx )
{
cmDspClassSetup ( & _cmPortToSym_DC , ctx , " PortToSym " ,
NULL ,
_cmDspPortToSym_Alloc ,
_cmDspPortToSym_Free ,
_cmDspPortToSym_Reset ,
NULL ,
_cmDspPortToSym_Recv ,
NULL , NULL ,
" If a message of any kind is received on a port then send the symbol associated with the port. " ) ;
return & _cmPortToSym_DC ;
}
//==========================================================================================================================================
enum
{
kOutChCntRtId ,
kOutChIdxRtId ,
kInFloatRtId ,
kInBoolRtId ,
kInSymRtId ,
kInAudioRtId ,
kBaseOutFloatRtId
} ;
cmDspClass_t _cmRouter_DC ;
typedef struct
{
cmDspInst_t inst ;
unsigned oChCnt ;
unsigned oChIdx ;
unsigned baseBaseOutRtId ; // first data input port id
unsigned baseInFloatRtId ;
unsigned baseInBoolRtId ;
unsigned baseInSymRtId ;
unsigned baseInAudioRtId ;
unsigned baseOutFloatRtId ;
unsigned baseOutBoolRtId ;
unsigned baseOutSymRtId ;
unsigned baseOutAudioRtId ;
} cmDspRouter_t ;
cmDspInst_t * _cmDspRouter_Alloc ( cmDspCtx_t * ctx , cmDspClass_t * classPtr , unsigned storeSymId , unsigned instSymId , unsigned id , unsigned va_cnt , va_list vl )
{
if ( va_cnt < 1 )
{
cmDspClassErr ( ctx , classPtr , kVarArgParseFailDspRC , " The 'Router' constructor must be given an output channel count. " ) ;
return NULL ;
}
va_list vl1 ;
va_copy ( vl1 , vl ) ;
int oChCnt = va_arg ( vl , int ) ;
unsigned baseOutFloatRtId = kBaseOutFloatRtId ;
unsigned baseOutBoolRtId = baseOutFloatRtId + oChCnt ;
unsigned baseOutSymRtId = baseOutBoolRtId + oChCnt ;
unsigned baseOutAudioRtId = baseOutSymRtId + oChCnt ;
cmDspRouter_t * p = cmDspInstAllocV ( cmDspRouter_t , ctx , classPtr , instSymId , id , storeSymId , va_cnt , vl1 ,
1 , " ochs " , kOutChCntRtId , 0 , 0 , kUIntDsvFl | kReqArgDsvFl , " Output channel count. " ,
1 , " sel " , kOutChIdxRtId , 0 , 0 , kUIntDsvFl | kReqArgDsvFl | kInDsvFl , " Output channel index selector. " ,
1 , " f-in " , kInFloatRtId , 0 , 0 , kDoubleDsvFl | kInDsvFl , " Float input " ,
1 , " b-in " , kInBoolRtId , 0 , 0 , kBoolDsvFl | kInDsvFl , " Bool input " ,
1 , " s-in " , kInSymRtId , 0 , 0 , kSymDsvFl | kInDsvFl , " Symbol input " ,
1 , " a-in " , kInAudioRtId , 0 , 0 , kAudioBufDsvFl | kInDsvFl , " Audio input " ,
oChCnt , " f-out " , baseOutFloatRtId , 0 , 0 , kDoubleDsvFl | kOutDsvFl , " Float output " ,
oChCnt , " b-out " , baseOutBoolRtId , 0 , 0 , kBoolDsvFl | kOutDsvFl , " Bool output " ,
oChCnt , " s-out " , baseOutSymRtId , 0 , 0 , kSymDsvFl | kOutDsvFl , " Symbol output " ,
oChCnt , " a-out " , baseOutAudioRtId , 0 , 1 , kAudioBufDsvFl | kOutDsvFl , " Audio output " ,
0 ) ;
p - > oChCnt = oChCnt ;
p - > baseBaseOutRtId = kBaseOutFloatRtId ;
p - > baseOutFloatRtId = baseOutFloatRtId ;
p - > baseOutBoolRtId = baseOutBoolRtId ;
p - > baseOutSymRtId = baseOutSymRtId ;
p - > baseOutAudioRtId = baseOutAudioRtId ;
unsigned i ;
for ( i = 0 ; i < oChCnt ; + + i )
{
cmDspSetDefaultDouble ( ctx , & p - > inst , baseOutFloatRtId + i , 0.0 , 0.0 ) ;
cmDspSetDefaultBool ( ctx , & p - > inst , baseOutBoolRtId + i , false , false ) ;
cmDspSetDefaultSymbol ( ctx , & p - > inst , baseOutSymRtId + i , cmInvalidId ) ;
}
2013-10-17 01:52:59 +00:00
va_end ( vl1 ) ;
2012-10-30 03:52:39 +00:00
return & p - > inst ;
}
cmDspRC_t _cmDspRouter_Free ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
return kOkDspRC ;
}
cmDspRC_t _cmDspRouter_Reset ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspRouter_t * p = ( cmDspRouter_t * ) inst ;
if ( ( rc = cmDspApplyAllDefaults ( ctx , inst ) ) = = kOkDspRC )
{
unsigned i ;
for ( i = 0 ; i < p - > oChCnt ; + + i )
cmDspZeroAudioBuf ( ctx , inst , p - > baseOutAudioRtId + i ) ;
2015-10-22 21:59:38 +00:00
2012-10-30 03:52:39 +00:00
}
return rc ;
}
cmDspRC_t _cmDspRouter_Exec ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspRouter_t * p = ( cmDspRouter_t * ) inst ;
unsigned oChIdx = cmDspUInt ( inst , kOutChIdxRtId ) ;
cmSample_t * dp = cmDspAudioBuf ( ctx , inst , p - > baseOutAudioRtId + oChIdx , 0 ) ;
const cmSample_t * sp = cmDspAudioBuf ( ctx , inst , kInAudioRtId , 0 ) ;
unsigned n = cmDspAudioBufSmpCount ( ctx , inst , p - > baseOutAudioRtId , 0 ) ;
if ( dp ! = NULL )
{
if ( sp = = NULL )
cmVOS_Zero ( dp , n ) ;
else
cmVOS_Copy ( dp , n , sp ) ;
}
return rc ;
}
cmDspRC_t _cmDspRouter_Recv ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspRouter_t * p = ( cmDspRouter_t * ) inst ;
// ignore out of range output channel selection
if ( evt - > dstVarId = = kOutChIdxRtId & & cmDsvGetUInt ( evt - > valuePtr ) > = p - > oChCnt )
{
cmDspInstErr ( ctx , inst , kVarNotValidDspRC , " The selector channel index %i is out of of range. " , cmDsvGetUInt ( evt - > valuePtr ) ) ;
return kOkDspRC ;
}
2015-10-22 21:59:38 +00:00
/*
if ( evt - > dstVarId = = kOutChIdxRtId & & cmDsvGetUInt ( evt - > valuePtr ) < p - > oChCnt )
{
const cmChar_t * symLbl = cmSymTblLabel ( ctx - > stH , inst - > symId ) ;
cmDspInstErr ( ctx , inst , kOkDspRC , " Router: ch:%i %s \n " , cmDsvGetUInt ( evt - > valuePtr ) , symLbl = = NULL ? " " : symLbl ) ;
}
*/
2012-10-30 03:52:39 +00:00
// store the incoming value
if ( evt - > dstVarId < p - > baseBaseOutRtId )
if ( ( rc = cmDspSetEvent ( ctx , inst , evt ) ) ! = kOkDspRC )
return rc ;
unsigned chIdx = cmDspUInt ( inst , kOutChIdxRtId ) ;
switch ( evt - > dstVarId )
{
case kInFloatRtId :
cmDspSetDouble ( ctx , inst , p - > baseOutFloatRtId + chIdx , cmDspDouble ( inst , kInFloatRtId ) ) ;
break ;
case kInBoolRtId :
cmDspSetBool ( ctx , inst , p - > baseOutBoolRtId + chIdx , cmDspBool ( inst , kInBoolRtId ) ) ;
break ;
case kInSymRtId :
cmDspSetSymbol ( ctx , inst , p - > baseOutSymRtId + chIdx , cmDspSymbol ( inst , kInSymRtId ) ) ;
break ;
}
return rc ;
}
struct cmDspClass_str * cmRouterClassCons ( cmDspCtx_t * ctx )
{
cmDspClassSetup ( & _cmRouter_DC , ctx , " Router " ,
NULL ,
_cmDspRouter_Alloc ,
_cmDspRouter_Free ,
_cmDspRouter_Reset ,
_cmDspRouter_Exec ,
_cmDspRouter_Recv ,
NULL , NULL ,
" 1 to N Router " ) ;
return & _cmRouter_DC ;
}
2012-12-17 20:47:44 +00:00
//==========================================================================================================================================
2012-12-18 22:46:07 +00:00
// Purpose: AvailCh can be used to implement a channel switching circuit.
//
// Inputs:
// chs - The count of channels. Constructor only argument.
// trig - Any input causes the next available channel, i, to be enabled.
// gate[i] transmits 'true'. In 'exclusive (0) mode all active
// channels are then requested to shutdown by transmitting 'false' on
// gate[] - only the new channel will be active. In 'multi' (1) mode
// no signal is sent out the gate[].
// dis[chCnt] - Recieves a gate signal from an external object which indicates
// when a channel is no longer active. When a 'false' is received on dis[i]
// the channel i is marked as available. In 'multi' mode 'false' is
// then transmitted on gate[i].
// Outputs:
// gate[chCnt] - 'true' is transmitted when a channel is made active (see trig)
// 'false' is transmitted to notify the channel that it should shutdown.
// The channel is not considered actually shutdown until dis[i]
// recieves a 'false'.
2015-10-09 22:32:55 +00:00
// ch The next prospective next available channel is sent whenever it
// becomes available. A next channel becomes available when
// a channel is marked as inactive via dis[i] or when
// a new channel is made active, via trigger, and another
// channel active channel exists.
2012-12-18 22:46:07 +00:00
// Notes:
// The gate[] output is designed to work with the gate[] input of Xfader. When
// availCh.gate[] goes high Xfader fades in, when availCh.gate[] goes low
// Xfader fades out. The dis[] channel is designed to connect from Xfader.state[].
2013-12-10 21:27:15 +00:00
// Xfader.state[] goes low when a fade-out is complete, the connected AvailCh
// is then marked as available.
2012-12-17 20:47:44 +00:00
enum
{
kChCntAvId ,
2012-12-18 22:46:07 +00:00
kModeAvId ,
2012-12-17 20:47:44 +00:00
kTrigAvId ,
2013-11-03 19:51:26 +00:00
kResetAvId ,
2012-12-17 20:47:44 +00:00
kChIdxAvId ,
2012-12-18 22:46:07 +00:00
kBaseDisInAvId ,
kExclusiveModeAvId = 0 ,
kMultiModeAvId = 1
2012-12-17 20:47:44 +00:00
} ;
cmDspClass_t _cmAvailCh_DC ;
typedef struct
{
cmDspInst_t inst ;
unsigned chCnt ;
2012-12-18 22:46:07 +00:00
unsigned baseDisInAvId ;
unsigned baseGateOutAvId ;
2012-12-17 20:47:44 +00:00
bool * stateArray ;
2015-10-09 22:32:55 +00:00
unsigned nextAvailChIdx ;
unsigned audioCycleCnt ;
2012-12-17 20:47:44 +00:00
} cmDspAvailCh_t ;
cmDspInst_t * _cmDspAvailCh_Alloc ( cmDspCtx_t * ctx , cmDspClass_t * classPtr , unsigned storeSymId , unsigned instSymId , unsigned id , unsigned va_cnt , va_list vl )
{
if ( va_cnt < 1 )
{
cmDspClassErr ( ctx , classPtr , kVarArgParseFailDspRC , " The 'AvailCh' constructor must be given an channel count. " ) ;
return NULL ;
}
va_list vl1 ;
va_copy ( vl1 , vl ) ;
int chCnt = va_arg ( vl , int ) ;
if ( chCnt < = 0 )
{
2013-10-17 01:52:59 +00:00
va_end ( vl1 ) ;
2012-12-17 20:47:44 +00:00
cmDspClassErr ( ctx , classPtr , kInvalidArgDspRC , " The 'AvailCh' constructor must be given a positive channel count. " ) ;
return NULL ;
}
2012-12-18 22:46:07 +00:00
unsigned baseDisInAvId = kBaseDisInAvId ;
unsigned baseGateOutAvId = baseDisInAvId + chCnt ;
2012-12-17 20:47:44 +00:00
cmDspAvailCh_t * p = cmDspInstAllocV ( cmDspAvailCh_t , ctx , classPtr , instSymId , id , storeSymId , va_cnt , vl1 ,
2012-12-18 22:46:07 +00:00
1 , " chs " , kChCntAvId , 0 , 0 , kUIntDsvFl | kReqArgDsvFl , " Channel count. " ,
1 , " mode " , kModeAvId , 0 , 0 , kUIntDsvFl | kInDsvFl , " Mode: 0=exclusive (dflt) 1=multi " ,
1 , " trig " , kTrigAvId , 0 , 0 , kTypeDsvMask | kInDsvFl , " Trigger the unit to select the next available channel. " ,
2013-11-03 19:51:26 +00:00
1 , " reset " , kResetAvId , 0 , 0 , kBoolDsvFl | kInDsvFl | kOutDsvFl , " Reset to default state " ,
2012-12-18 22:46:07 +00:00
1 , " ch " , kChIdxAvId , 0 , 0 , kUIntDsvFl | kOutDsvFl , " Currently selected channel. " ,
chCnt , " dis " , baseDisInAvId , 0 , 0 , kBoolDsvFl | kInDsvFl , " Disable channel gate " ,
chCnt , " gate " , baseGateOutAvId , 0 , 0 , kBoolDsvFl | kOutDsvFl , " Active channel gate " ,
2012-12-17 20:47:44 +00:00
0 ) ;
p - > chCnt = chCnt ;
2012-12-18 22:46:07 +00:00
p - > baseDisInAvId = baseDisInAvId ;
p - > baseGateOutAvId = baseGateOutAvId ;
2015-10-09 22:32:55 +00:00
p - > nextAvailChIdx = cmInvalidIdx ;
p - > audioCycleCnt = 0 ;
2012-12-17 20:47:44 +00:00
unsigned i ;
for ( i = 0 ; i < chCnt ; + + i )
2012-12-18 22:46:07 +00:00
{
2015-10-09 22:32:55 +00:00
cmDspSetDefaultBool ( ctx , & p - > inst , baseDisInAvId + i , false , false ) ;
2012-12-18 22:46:07 +00:00
cmDspSetDefaultBool ( ctx , & p - > inst , baseGateOutAvId + i , false , false ) ;
}
cmDspSetDefaultUInt ( ctx , & p - > inst , kModeAvId , 0 , kExclusiveModeAvId ) ;
2015-10-22 21:59:38 +00:00
cmDspSetDefaultUInt ( ctx , & p - > inst , kChIdxAvId , 0 , 0 ) ;
2013-10-17 01:52:59 +00:00
va_end ( vl1 ) ;
2012-12-17 20:47:44 +00:00
return & p - > inst ;
}
cmDspRC_t _cmDspAvailCh_Free ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
return kOkDspRC ;
}
2015-10-09 22:32:55 +00:00
cmDspRC_t _cmDspAvailCh_DoReset ( cmDspCtx_t * ctx , cmDspInst_t * inst )
{
unsigned i ;
cmDspAvailCh_t * p = ( cmDspAvailCh_t * ) inst ;
2015-10-22 21:59:38 +00:00
2015-10-09 22:32:55 +00:00
// ch 0 is the channel receiving parameters
2015-10-22 21:59:38 +00:00
cmDspSetUInt ( ctx , inst , kChIdxAvId , 0 ) ;
2015-10-09 22:32:55 +00:00
for ( i = 0 ; i < p - > chCnt ; + + i )
{
cmDspSetBool ( ctx , inst , p - > baseDisInAvId + i , i = = 0 ) ; // disable all channels except ch zero
cmDspSetBool ( ctx , inst , p - > baseGateOutAvId + i , i = = 0 ) ; // enable channel 0
}
p - > audioCycleCnt = 0 ;
p - > nextAvailChIdx = cmInvalidIdx ;
// transmit reset
cmDspSetBool ( ctx , inst , kResetAvId , false ) ;
return kOkDspRC ;
}
2012-12-17 20:47:44 +00:00
cmDspRC_t _cmDspAvailCh_Reset ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
2015-10-09 22:32:55 +00:00
cmDspRC_t rc ;
if ( ( rc = cmDspApplyAllDefaults ( ctx , inst ) ) = = kOkDspRC )
{
rc = _cmDspAvailCh_DoReset ( ctx , inst ) ;
}
return rc ;
2012-12-17 20:47:44 +00:00
}
2015-10-22 21:59:38 +00:00
void _cmDspAvailCh_SetNextAvailCh ( cmDspCtx_t * ctx , cmDspInst_t * inst , bool warnFl , const char * label )
2015-10-09 22:32:55 +00:00
{
cmDspAvailCh_t * p = ( cmDspAvailCh_t * ) inst ;
unsigned i ;
2015-10-22 21:59:38 +00:00
// if a valid next avail ch already exists then do nothing
2015-10-09 22:32:55 +00:00
if ( p - > nextAvailChIdx ! = cmInvalidIdx )
return ;
2015-10-22 21:59:38 +00:00
// for each channel
2015-10-09 22:32:55 +00:00
for ( i = 0 ; i < p - > chCnt ; + + i )
{
// the channel's active state is held in the 'dis' variable.
bool activeFl = cmDspBool ( inst , p - > baseDisInAvId + i ) ;
// if ch[i] is the first avail inactive channel
if ( ! activeFl )
{
2015-10-22 21:59:38 +00:00
p - > nextAvailChIdx = i ; // then make it the next available channel
2015-10-09 22:32:55 +00:00
break ;
}
}
// if no available channels were found
2015-10-22 21:59:38 +00:00
if ( p - > nextAvailChIdx = = cmInvalidIdx )
{
if ( warnFl )
cmDspInstErr ( ctx , inst , kInvalidStateDspRC , " No available channels exist. " ) ;
}
2015-10-09 22:32:55 +00:00
else
{
// Notify the external world which channel is to be used next.
// This allows routers which are switching parameters between
// xfade channels to switch new parameter values to go to the
// next available channel rather than the current channel.
// The next available channel will then be faded up with the
// new parameters on the next trigger command.
2015-10-22 21:59:38 +00:00
cmDspSetUInt ( ctx , inst , kChIdxAvId , p - > nextAvailChIdx ) ;
2015-10-09 22:32:55 +00:00
}
}
cmDspRC_t _cmDspAvailCh_Exec ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspAvailCh_t * p = ( cmDspAvailCh_t * ) inst ;
p - > audioCycleCnt + = 1 ;
2015-10-22 21:59:38 +00:00
// Setting the next available channel here solves the problem of sending the
2015-10-09 22:32:55 +00:00
// first 'ch' output after the program starts executing.
2015-10-22 21:59:38 +00:00
// The problem is that 'ch' should be set to 0 for the first
2015-10-09 22:32:55 +00:00
// execution cycle so that parameters may be set to the initial active channel
// during the first cycle. After the first cycle however parameters should be
// sent to the next channel which will be faded up. Setting
// 'ch' here accomplishes this without relying on an external signal.
// Note that we wait until the second cycle because we don't know where
// this 'availCh' will be in the execution cycle relative to other processors.
// If it is at the beginning then other processors that might be setting
// initial parameters will not have had a chance to run before the
// 'ch' change. Waiting unitl the second cycle guarantees that all the
// other processors had at least one chance to run.
if ( p - > audioCycleCnt = = 2 )
{
2015-10-22 21:59:38 +00:00
_cmDspAvailCh_SetNextAvailCh ( ctx , inst , true , " exec " ) ;
2015-10-09 22:32:55 +00:00
}
return rc ;
}
2012-12-17 20:47:44 +00:00
cmDspRC_t _cmDspAvailCh_Recv ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspAvailCh_t * p = ( cmDspAvailCh_t * ) inst ;
2012-12-18 22:46:07 +00:00
bool exclModeFl = cmDspUInt ( inst , kModeAvId ) = = kExclusiveModeAvId ;
2015-10-09 22:32:55 +00:00
// if this is a reset
2013-11-03 19:51:26 +00:00
if ( evt - > dstVarId = = kResetAvId )
{
2015-10-09 22:32:55 +00:00
return _cmDspAvailCh_DoReset ( ctx , inst ) ;
2013-11-03 19:51:26 +00:00
}
2012-12-17 20:47:44 +00:00
// if this is a trigger
if ( evt - > dstVarId = = kTrigAvId )
{
2015-10-09 22:32:55 +00:00
// if no available channels were previously found
if ( p - > nextAvailChIdx = = cmInvalidIdx )
cmDspInstErr ( ctx , inst , kInvalidStateDspRC , " There are no available channels to trigger. " ) ;
2013-12-10 21:27:15 +00:00
else
{
2015-10-22 21:59:38 +00:00
// indicate that ch[nexAvailChIdx] is no longer available
2015-10-09 22:32:55 +00:00
cmDspSetBool ( ctx , inst , p - > baseDisInAvId + p - > nextAvailChIdx , true ) ;
// raise the gate to start the xfade.
cmDspSetBool ( ctx , inst , p - > baseGateOutAvId + p - > nextAvailChIdx , true ) ;
2012-12-18 22:46:07 +00:00
2013-12-10 21:27:15 +00:00
if ( exclModeFl )
{
2015-10-09 22:32:55 +00:00
unsigned i ;
2013-12-10 21:27:15 +00:00
for ( i = 0 ; i < p - > chCnt ; + + i )
2015-10-09 22:32:55 +00:00
if ( i ! = p - > nextAvailChIdx & & cmDspBool ( inst , p - > baseDisInAvId + i ) )
2013-12-10 21:27:15 +00:00
cmDspSetBool ( ctx , inst , p - > baseGateOutAvId + i , false ) ;
}
2015-10-09 22:32:55 +00:00
2015-10-22 21:59:38 +00:00
// invalidate nextAvailChIdx
2015-10-09 22:32:55 +00:00
p - > nextAvailChIdx = cmInvalidIdx ;
// It may be possible to know the next avail ch so try to set it here.
2015-10-22 21:59:38 +00:00
_cmDspAvailCh_SetNextAvailCh ( ctx , inst , false , " trig " ) ;
2015-10-09 22:32:55 +00:00
2012-12-18 22:46:07 +00:00
}
2013-11-03 19:51:26 +00:00
2013-12-10 21:27:15 +00:00
2012-12-17 20:47:44 +00:00
return rc ;
}
// if this is an incoming disable message.
2012-12-18 22:46:07 +00:00
if ( p - > baseDisInAvId < = evt - > dstVarId & & evt - > dstVarId < p - > baseDisInAvId + p - > chCnt & & cmDsvGetBool ( evt - > valuePtr ) = = false )
2015-10-09 22:32:55 +00:00
{
2012-12-18 22:46:07 +00:00
cmDspSetEvent ( ctx , inst , evt ) ;
2015-10-09 22:32:55 +00:00
2015-10-22 21:59:38 +00:00
// a channel was disabled so a new channel should be available for selection
if ( p - > audioCycleCnt > 0 )
_cmDspAvailCh_SetNextAvailCh ( ctx , inst , true , " dis " ) ;
2015-10-09 22:32:55 +00:00
2012-12-18 22:46:07 +00:00
if ( ! exclModeFl )
cmDspSetBool ( ctx , inst , p - > baseGateOutAvId + ( evt - > dstVarId - p - > baseDisInAvId ) , false ) ;
2012-12-17 20:47:44 +00:00
}
return rc ;
}
struct cmDspClass_str * cmAvailChClassCons ( cmDspCtx_t * ctx )
{
cmDspClassSetup ( & _cmAvailCh_DC , ctx , " AvailCh " ,
NULL ,
_cmDspAvailCh_Alloc ,
_cmDspAvailCh_Free ,
_cmDspAvailCh_Reset ,
2015-10-09 22:32:55 +00:00
_cmDspAvailCh_Exec ,
2012-12-17 20:47:44 +00:00
_cmDspAvailCh_Recv ,
NULL , NULL ,
" Enable the next availabled channel " ) ;
return & _cmAvailCh_DC ;
}
2012-10-30 03:52:39 +00:00
//==========================================================================================================================================
enum
{
kGroupSymPrId ,
kLabelPrId ,
kCmdPrId ,
kDonePrId ,
kListPrId ,
kSelPrId
} ;
cmDspClass_t _cmPreset_DC ;
typedef struct
{
cmDspInst_t inst ;
unsigned storeCmdSymId ;
unsigned recallCmdSymId ;
unsigned doneSymId ;
cmJsonH_t jsH ;
cmJsonNode_t * np ;
} cmDspPreset_t ;
cmDspRC_t _cmDspPresetUpdateList ( cmDspCtx_t * ctx , cmDspPreset_t * p , unsigned groupSymId )
{
cmDspRC_t rc = kOkDspRC ;
// initialize the JSON tree
if ( cmJsonInitialize ( & p - > jsH , ctx - > cmCtx ) ! = kOkJsRC )
{
rc = cmDspInstErr ( ctx , & p - > inst , kJsonFailDspRC , " JSON preset list handle initialization failed. " ) ;
goto errLabel ;
}
// create the JSON tree root container
if ( cmJsonCreateObject ( p - > jsH , NULL ) = = NULL )
{
rc = cmDspInstErr ( ctx , & p - > inst , kJsonFailDspRC , " JSON preset list root object create failed. " ) ;
goto errLabel ;
}
// if a valid preset group symbol was given
if ( groupSymId ! = cmInvalidId )
{
// get the JSON list containing the preset labels and symId's for this preset group
if ( cmDspSysPresetPresetJsonList ( ctx - > dspH , groupSymId , & p - > jsH ) ! = kOkDspRC )
{
rc = cmDspInstErr ( ctx , & p - > inst , kSubSysFailDspRC , " Request for a preset list failed. " ) ;
goto errLabel ;
}
// get a pointer to the JSON 'presetArray' array node
if ( ( p - > np = cmJsonFindValue ( p - > jsH , " presetArray " , NULL , kArrayTId ) ) = = NULL )
{
rc = cmDspInstErr ( ctx , & p - > inst , kJsonFailDspRC , " Preset list is empty or synatax is not recognized. " ) ;
goto errLabel ;
}
// set the JSON list
if ( ( rc = cmDspSetJson ( ctx , & p - > inst , kListPrId , p - > np ) ) ! = kOkDspRC )
{
rc = cmDspInstErr ( ctx , & p - > inst , rc , " Preset list set failed. " ) ;
goto errLabel ;
}
}
errLabel :
return rc ;
}
cmDspRC_t _cmDspPresetDoRecall ( cmDspCtx_t * ctx , cmDspPreset_t * p , const cmChar_t * groupLabel , const cmChar_t * presetLabel )
{
cmDspRC_t rc ;
// recall the preset
if ( ( rc = cmDspSysPresetRecall ( ctx - > dspH , groupLabel , presetLabel ) ) ! = kOkDspRC )
return cmDspInstErr ( ctx , & p - > inst , kSubSysFailDspRC , " Preset recall failed for group:'%s' preset:'%s'. " , cmStringNullGuard ( groupLabel ) , cmStringNullGuard ( presetLabel ) ) ;
// send out a notification that a new preset has been loaded
return cmDspSetSymbol ( ctx , & p - > inst , kDonePrId , p - > doneSymId ) ;
}
// selIdx is base 1, not base 0, because it references the JSON tree rows where the
// first row contains the titles.
cmDspRC_t _cmDspPresetListSelectRecall ( cmDspCtx_t * ctx , cmDspPreset_t * p , unsigned selIdx )
{
cmDspRC_t rc = kOkDspRC ;
const cmChar_t * presetLabel ;
const cmChar_t * groupLabel ;
unsigned groupSymId ;
unsigned presetSymId ;
const cmJsonNode_t * rnp ;
// validate the JSON tree
if ( cmJsonIsValid ( p - > jsH ) = = false | | p - > np = = NULL )
{
rc = cmDspInstErr ( ctx , & p - > inst , kJsonFailDspRC , " Preset recall failed. The preset JSON tree does not exist. " ) ;
goto errLabel ;
}
// validate the group id
if ( ( groupSymId = cmDspSymbol ( & p - > inst , kGroupSymPrId ) ) = = cmInvalidId )
{
rc = cmDspInstErr ( ctx , & p - > inst , kVarNotValidDspRC , " Preset recall failed. The preset group symbol has not been set. " ) ;
goto errLabel ;
}
// validate the selection index
if ( selIdx > = cmJsonChildCount ( p - > np ) )
{
rc = cmDspInstErr ( ctx , & p - > inst , kVarNotValidDspRC , " Preset recall failed. The preset index: %i is out of range 0-%i " , selIdx , cmJsonChildCount ( p - > np ) ) ;
goto errLabel ;
}
// get the preset element
if ( ( rnp = cmJsonArrayElementC ( p - > np , selIdx ) ) = = NULL )
{
rc = cmDspInstErr ( ctx , & p - > inst , kJsonFailDspRC , " Preset recall failed. Unable to retrieve preset JSON element. " ) ;
goto errLabel ;
}
// verify the JSON syntax
assert ( rnp - > typeId = = kArrayTId & & cmJsonChildCount ( rnp ) = = 2 & & cmJsonArrayElementC ( rnp , 1 ) - > typeId = = kIntTId ) ;
// get the preset symbol id
if ( cmJsonUIntValue ( cmJsonArrayElementC ( rnp , 1 ) , & presetSymId ) ! = kOkJsRC )
{
rc = cmDspInstErr ( ctx , & p - > inst , kJsonFailDspRC , " Preset recall failed. Unable to retrieve preset symbol id. " ) ;
goto errLabel ;
}
// convert symbols to strings
groupLabel = cmSymTblLabel ( ctx - > stH , groupSymId ) ;
presetLabel = cmSymTblLabel ( ctx - > stH , presetSymId ) ;
rc = _cmDspPresetDoRecall ( ctx , p , groupLabel , presetLabel ) ;
errLabel :
return rc ;
}
cmDspInst_t * _cmDspPreset_Alloc ( cmDspCtx_t * ctx , cmDspClass_t * classPtr , unsigned storeSymId , unsigned instSymId , unsigned id , unsigned va_cnt , va_list vl )
{
cmDspPreset_t * p = cmDspInstAllocV ( cmDspPreset_t , ctx , classPtr , instSymId , id , storeSymId , va_cnt , vl ,
1 , " sym " , kGroupSymPrId , 0 , 0 , kInDsvFl | kSymDsvFl | kReqArgDsvFl , " Preset group symbol. " ,
1 , " label " , kLabelPrId , 0 , 0 , kInDsvFl | kStrzDsvFl | kOptArgDsvFl , " Preset label " ,
1 , " cmd " , kCmdPrId , 0 , 0 , kInDsvFl | kSymDsvFl , " Command input " ,
1 , " done " , kDonePrId , 0 , 0 , kOutDsvFl | kSymDsvFl , " Send 'done' symbol after preset recall. " ,
1 , " list " , kListPrId , 0 , 0 , kInDsvFl | kJsonDsvFl , " Preset list as a JSON array. " ,
1 , " sel " , kSelPrId , 0 , 0 , kInDsvFl | kUIntDsvFl , " Preset index selection index " ,
0 ) ;
p - > jsH = cmJsonNullHandle ;
p - > np = NULL ;
p - > storeCmdSymId = cmSymTblRegisterStaticSymbol ( ctx - > stH , " store " ) ;
p - > recallCmdSymId = cmSymTblRegisterStaticSymbol ( ctx - > stH , " recall " ) ;
p - > doneSymId = cmSymTblRegisterStaticSymbol ( ctx - > stH , " done " ) ;
cmDspSetDefaultBool ( ctx , & p - > inst , kDonePrId , false , false ) ;
cmDspSetDefaultSymbol ( ctx , & p - > inst , kGroupSymPrId , cmInvalidId ) ;
cmDspSetDefaultStrcz ( ctx , & p - > inst , kLabelPrId , NULL , " " ) ;
unsigned height = 5 ;
cmDspUiMsgListCreate ( ctx , & p - > inst , height , kListPrId , kSelPrId ) ;
return & p - > inst ;
}
cmDspRC_t _cmDspPreset_Free ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspPreset_t * p = ( cmDspPreset_t * ) inst ;
cmJsonFinalize ( & p - > jsH ) ;
return kOkDspRC ;
}
cmDspRC_t _cmDspPreset_Reset ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc ;
cmDspPreset_t * p = ( cmDspPreset_t * ) inst ;
if ( ( rc = cmDspApplyAllDefaults ( ctx , inst ) ) = = kOkDspRC )
{
_cmDspPresetUpdateList ( ctx , p , cmDspSymbol ( inst , kGroupSymPrId ) ) ;
}
return rc ;
}
cmDspRC_t _cmDspPreset_Recv ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspPreset_t * p = ( cmDspPreset_t * ) inst ;
switch ( evt - > dstVarId )
{
case kListPrId :
return rc ; // we don't yet handle lists arriving by the input port
case kSelPrId :
{
// sel idx is base 1 because the first row in the msg list contains the titles
unsigned selIdx = cmDsvGetUInt ( evt - > valuePtr ) ;
if ( ( rc = _cmDspPresetListSelectRecall ( ctx , p , selIdx ) ) ! = kOkDspRC )
return rc ;
}
break ;
}
if ( ( rc = cmDspSetEvent ( ctx , inst , evt ) ) ! = kOkDspRC )
return rc ;
// if this is a store or recall command
if ( evt - > dstVarId = = kCmdPrId )
{
unsigned cmdSymId = cmDspSymbol ( inst , kCmdPrId ) ;
if ( cmdSymId = = p - > storeCmdSymId | | cmdSymId = = p - > recallCmdSymId )
{
unsigned groupSymId ;
const cmChar_t * groupLabel ;
const cmChar_t * presetLabel ;
// get the group symbol
if ( ( groupSymId = cmDspSymbol ( inst , kGroupSymPrId ) ) = = cmInvalidId )
return cmDspInstErr ( ctx , inst , kVarNotValidDspRC , " The preset group symbol id is not set. " ) ;
// get the group label
if ( ( groupLabel = cmSymTblLabel ( ctx - > stH , groupSymId ) ) = = NULL )
return cmDspInstErr ( ctx , inst , kVarNotValidDspRC , " The preset group label was not found. " ) ;
// get the preset label
if ( ( presetLabel = cmDspStrcz ( inst , kLabelPrId ) ) = = NULL | | strlen ( presetLabel ) = = 0 )
return cmDspInstErr ( ctx , inst , kVarNotValidDspRC , " The preset label was not set. " ) ;
// if this is a store command
if ( cmdSymId = = p - > storeCmdSymId )
{
// create a new preset
if ( ( rc = cmDspSysPresetCreate ( ctx - > dspH , groupLabel , presetLabel ) ) ! = kOkDspRC )
return cmDspInstErr ( ctx , inst , kSubSysFailDspRC , " Preset create failed for group:'%s' preset:'%s'. " , cmStringNullGuard ( groupLabel ) , cmStringNullGuard ( presetLabel ) ) ;
// update the list with the new preset
rc = _cmDspPresetUpdateList ( ctx , p , groupSymId ) ;
}
else // otherwise this must be a recall command
{
rc = _cmDspPresetDoRecall ( ctx , p , groupLabel , presetLabel ) ;
}
}
}
return rc ;
}
struct cmDspClass_str * cmPresetClassCons ( cmDspCtx_t * ctx )
{
cmDspClassSetup ( & _cmPreset_DC , ctx , " Preset " ,
NULL ,
_cmDspPreset_Alloc ,
_cmDspPreset_Free ,
_cmDspPreset_Reset ,
NULL ,
_cmDspPreset_Recv ,
NULL , NULL ,
" Preset Manager " ) ;
return & _cmPreset_DC ;
}
//==========================================================================================================================================
enum
{
kAttrBcId ,
kMsgBcId
} ;
cmDspClass_t _cmBcastSym_DC ;
typedef struct
{
cmDspInst_t inst ;
unsigned onSymId ;
unsigned offSymId ;
} cmDspBcastSym_t ;
cmDspInst_t * _cmDspBcastSym_Alloc ( cmDspCtx_t * ctx , cmDspClass_t * classPtr , unsigned storeSymId , unsigned instSymId , unsigned id , unsigned va_cnt , va_list vl )
{
cmDspBcastSym_t * p = cmDspInstAllocV ( cmDspBcastSym_t , ctx , classPtr , instSymId , id , storeSymId , va_cnt , vl ,
1 , " attr " , kAttrBcId , 0 , 0 , kSymDsvFl | kInDsvFl | kOptArgDsvFl , " Instance which have this attribute symbol will receive the message. " ,
1 , " msg " , kMsgBcId , 0 , 0 , kTypeDsvMask | kInDsvFl , " Msg to broadcast. " ,
0 ) ;
cmDspSetDefaultSymbol ( ctx , & p - > inst , kAttrBcId , cmInvalidId ) ;
return & p - > inst ;
}
cmDspRC_t _cmDspBcastSym_Reset ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
if ( ( rc = cmDspApplyAllDefaults ( ctx , inst ) ) = = kOkDspRC )
{
}
return rc ;
}
cmDspRC_t _cmDspBcastSym_Recv ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
if ( evt - > dstVarId = = kAttrBcId )
return cmDspSetEvent ( ctx , inst , evt ) ;
if ( evt - > dstVarId = = kMsgBcId )
{
unsigned attrSymId = cmDspSymbol ( inst , kAttrBcId ) ;
if ( cmDsvIsSymbol ( evt - > valuePtr ) )
{
printf ( " bcast: %i %s \n " , attrSymId , cmSymTblLabel ( ctx - > stH , cmDsvSymbol ( evt - > valuePtr ) ) ) ;
}
return cmDspSysBroadcastValue ( ctx - > dspH , attrSymId , evt - > valuePtr ) ;
}
return rc ;
}
struct cmDspClass_str * cmBcastSymClassCons ( cmDspCtx_t * ctx )
{
cmDspClassSetup ( & _cmBcastSym_DC , ctx , " BcastSym " ,
NULL ,
_cmDspBcastSym_Alloc ,
NULL ,
_cmDspBcastSym_Reset ,
NULL ,
_cmDspBcastSym_Recv ,
NULL , NULL ,
" Set one input high and all others low. " ) ;
return & _cmBcastSym_DC ;
}
//==========================================================================================================================================
enum
{
kRsrcSlId ,
kCmdSlId ,
kTrigSlId ,
kOutSlId ,
} ;
cmDspClass_t _cmSegLineDC ;
typedef struct
{
cmDspInst_t inst ;
double * x ; // x[n]
unsigned n ;
unsigned i ; // current segment
unsigned m ; // cur cnt
} cmDspSegLine_t ;
cmDspInst_t * _cmDspSegLineAlloc ( cmDspCtx_t * ctx , cmDspClass_t * classPtr , unsigned storeSymId , unsigned instSymId , unsigned id , unsigned va_cnt , va_list vl )
{
cmDspSegLine_t * p = cmDspInstAllocV ( cmDspSegLine_t , ctx , classPtr , instSymId , id , storeSymId , va_cnt , vl ,
1 , " rsrc " , kRsrcSlId , 0 , 0 , kInDsvFl | kStrzDsvFl | kReqArgDsvFl , " Name of resource array. " ,
1 , " cmd " , kCmdSlId , 0 , 0 , kInDsvFl | kSymDsvFl , " Command " ,
1 , " trig " , kTrigSlId , 0 , 0 , kInDsvFl | kTypeDsvMask , " Trigger " ,
1 , " out " , kOutSlId , 0 , 0 , kOutDsvFl | kDoubleDsvFl , " Output " ,
0 ) ;
if ( p = = NULL )
return NULL ;
// The array is expected to contain interleaved values:
// cnt_0, val_0, cnt_1, val_1 .... cnt_n val_n
// The 'cnt_x' values give the count of trigger values upon which the output will be 'val_x'.
if ( cmDspRsrcDblArray ( ctx - > dspH , & p - > n , & p - > x , cmDspDefaultStrcz ( & p - > inst , kRsrcSlId ) , NULL ) ! = kOkDspRC )
{
cmDspClassErr ( ctx , classPtr , kVarArgParseFailDspRC , " The 'SegLine' constructor resource array could not be read. " ) ;
return NULL ;
}
cmDspSetDefaultDouble ( ctx , & p - > inst , kOutSlId , 0.0 , p - > n > = 2 ? p - > x [ 1 ] : 0.0 ) ;
p - > i = 0 ;
p - > m = 0 ;
return & p - > inst ;
}
cmDspRC_t _cmDspSegLineReset ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspSegLine_t * p = ( cmDspSegLine_t * ) inst ;
p - > i = 0 ;
p - > m = 0 ;
return cmDspApplyAllDefaults ( ctx , inst ) ;
}
cmDspRC_t _cmDspSegLineRecv ( cmDspCtx_t * ctx , cmDspInst_t * inst , const cmDspEvt_t * evt )
{
cmDspRC_t rc = kOkDspRC ;
cmDspSegLine_t * p = ( cmDspSegLine_t * ) inst ;
if ( ( rc = cmDspSetEvent ( ctx , inst , evt ) ) = = kOkDspRC )
{
switch ( evt - > dstVarId )
{
case kTrigSlId :
{
double val = cmDspDouble ( inst , kOutSlId ) ;
if ( p - > i < p - > n )
{
if ( p - > m > = p - > x [ p - > i ] )
p - > i + = 2 ;
if ( p - > i < p - > n )
{
double x0 = p - > x [ p - > i - 2 ] ;
double y0 = p - > x [ p - > i - 1 ] ;
double x1 = p - > x [ p - > i + 0 ] ;
double y1 = p - > x [ p - > i + 1 ] ;
double dx = x1 - x0 ;
double dy = y1 - y0 ;
val = y0 + ( p - > m - x0 ) * dy / dx ;
printf ( " i:%i m=%i x0:%f y0:%f x1:%f y1:%f : %f \n " , p - > i , p - > m , x0 , y0 , x1 , y1 , val ) ;
}
else
{
val = p - > x [ p - > n - 1 ] ;
}
+ + p - > m ;
}
cmDspSetDouble ( ctx , inst , kOutSlId , val ) ;
}
break ;
case kCmdSlId :
p - > i = 0 ;
p - > m = 0 ;
break ;
}
}
return rc ;
}
struct cmDspClass_str * cmSegLineClassCons ( cmDspCtx_t * ctx )
{
cmDspClassSetup ( & _cmSegLineDC , ctx , " SegLine " ,
NULL ,
_cmDspSegLineAlloc ,
NULL ,
_cmDspSegLineReset ,
NULL ,
_cmDspSegLineRecv ,
NULL , NULL ,
" SegLine " ) ;
return & _cmSegLineDC ;
}