cmProc4.h/c, cmDspKr.c, cmDspPgmKr.c: Many changes to debug cmScMod. Added _cmDspGSwitchAlloc().

This commit is contained in:
kevin 2013-03-01 17:40:04 -08:00
parent 650b2a95a4
commit c9dd87625a
4 changed files with 992 additions and 198 deletions

542
cmProc4.c
View File

@ -1630,16 +1630,14 @@ cmRC_t cmScMatchExec( cmScMatch* p, unsigned locIdx, unsigned locN, const cmScMa
} }
// Traverse the least cost path and: // Traverse the least cost path and:
// 1) Set p->esi to the score location index of the last MIDI note // 1) Return, esi, the score location index of the last MIDI note
// which has a positive match with the score and assign // which has a positive match with the score and assign
// the internal score index to cp->locIdx. // the internal score index to cp->locIdx.
// //
// 2) Set cmScAlignPath_t.locIdx - index into p->loc[] associated // 2) Set cmScAlignPath_t.locIdx - index into p->loc[] associated
// with each path element that is a 'substitute' or an 'insert'. // with each path element that is a 'substitute' or an 'insert'.
// //
// 3) Set p->missCnt: the count of trailing non-positive matches. // 3) Set *missCnPtr: the count of trailing non-positive matches.
// p->missCnt is eventually used in cmScAlignStep() to track the number
// of consecutive trailing missed notes.
// //
// i_opt is index into p->loc[] of p->p_opt. // i_opt is index into p->loc[] of p->p_opt.
unsigned cmScMatchDoSync( cmScMatch* p, unsigned i_opt, cmScMatchMidi_t* midiBuf, unsigned midiN, unsigned* missCntPtr ) unsigned cmScMatchDoSync( cmScMatch* p, unsigned i_opt, cmScMatchMidi_t* midiBuf, unsigned midiN, unsigned* missCntPtr )
@ -1961,6 +1959,7 @@ cmRC_t cmScMatcherInit( cmScMatcher* p, double srate, cmScH_t scH, unsigned scW
p->cbArg = cbArg; p->cbArg = cbArg;
p->mn = midiWndN; p->mn = midiWndN;
p->midiBuf = cmMemResizeZ(cmScMatchMidi_t,p->midiBuf,p->mn); p->midiBuf = cmMemResizeZ(cmScMatchMidi_t,p->midiBuf,p->mn);
p->initHopCnt = 50;
p->stepCnt = 3; p->stepCnt = 3;
p->maxMissCnt = p->stepCnt+1; p->maxMissCnt = p->stepCnt+1;
p->rn = 2 * cmScoreEvtCount(scH); p->rn = 2 * cmScoreEvtCount(scH);
@ -2083,7 +2082,7 @@ void cmScMatcherPrintPath( cmScMatcher* p )
_cmScMatchPrintPath(p->mp, p->mp->p_opt, p->begSyncLocIdx, p->midiBuf ); _cmScMatchPrintPath(p->mp, p->mp->p_opt, p->begSyncLocIdx, p->midiBuf );
} }
unsigned cmScMatcherScan( cmScMatcher* p, unsigned bli, unsigned scanCnt ) unsigned cmScMatcherScan( cmScMatcher* p, unsigned bli, unsigned hopCnt )
{ {
assert( p->mp != NULL && p->mp->mmn > 0 ); assert( p->mp != NULL && p->mp->mmn > 0 );
@ -2102,7 +2101,7 @@ unsigned cmScMatcherScan( cmScMatcher* p, unsigned bli, unsigned scanCnt )
return cmInvalidIdx; return cmInvalidIdx;
// calc the edit distance from pitchV[] to a sliding score window // calc the edit distance from pitchV[] to a sliding score window
for(i=0; rc==cmOkRC && (scanCnt==cmInvalidCnt || i<scanCnt); ++i) for(i=0; rc==cmOkRC && (hopCnt==cmInvalidCnt || i<hopCnt); ++i)
{ {
rc = cmScMatchExec(p->mp, bli + i, p->mp->msn, p->midiBuf, p->mp->mmn, s_opt ); rc = cmScMatchExec(p->mp, bli + i, p->mp->msn, p->midiBuf, p->mp->mmn, s_opt );
@ -2227,7 +2226,7 @@ cmRC_t cmScMatcherExec( cmScMatcher* p, unsigned smpIdx, unsigned status, c
{ {
bool fl = p->mbi > 0; bool fl = p->mbi > 0;
cmRC_t rc = cmOkRC; cmRC_t rc = cmOkRC;
unsigned eli = p->eli; unsigned org_eli = p->eli;
if( scLocIdxPtr != NULL ) if( scLocIdxPtr != NULL )
*scLocIdxPtr = cmInvalidIdx; *scLocIdxPtr = cmInvalidIdx;
@ -2239,7 +2238,7 @@ cmRC_t cmScMatcherExec( cmScMatcher* p, unsigned smpIdx, unsigned status, c
// if the MIDI buffer transitioned to full then perform an initial scan sync. // if the MIDI buffer transitioned to full then perform an initial scan sync.
if( fl && p->mbi == 0 ) if( fl && p->mbi == 0 )
{ {
if( (p->begSyncLocIdx = cmScMatcherScan(p,p->ili,cmInvalidCnt)) == cmInvalidIdx ) if( (p->begSyncLocIdx = cmScMatcherScan(p,p->ili,p->initHopCnt)) == cmInvalidIdx )
rc = cmInvalidArgRC; // signal init. scan sync. fail rc = cmInvalidArgRC; // signal init. scan sync. fail
else else
{ {
@ -2253,8 +2252,21 @@ cmRC_t cmScMatcherExec( cmScMatcher* p, unsigned smpIdx, unsigned status, c
rc = cmScMatcherStep(p); rc = cmScMatcherStep(p);
} }
if( scLocIdxPtr!=NULL && p->eli != eli ) // if we lost sync
if( p->eli == cmInvalidIdx )
{
// IF WE LOST SYNC THEN WE BETTER DO SOMETHING - LIKE INCREASE THE SCAN HOPS
// ON THE NEXT EVENT.
p->eli = org_eli;
}
else
{
if( scLocIdxPtr!=NULL && p->eli != org_eli )
{
//printf("LOC:%i bar:%i\n",p->eli,p->mp->loc[p->eli].barNumb);
*scLocIdxPtr = p->mp->loc[p->eli].scLocIdx; *scLocIdxPtr = p->mp->loc[p->eli].scLocIdx;
}
}
return rc; return rc;
} }
@ -2645,7 +2657,11 @@ cmRC_t cmScMeasReset( cmScMeas* p )
unsigned i; unsigned i;
for(i=0; i<p->sn; ++i) for(i=0; i<p->sn; ++i)
{
p->set[i].value = DBL_MAX; p->set[i].value = DBL_MAX;
p->set[i].tempo = 0;
p->set[i].match_cost = 0;
}
return rc; return rc;
} }
@ -3029,6 +3045,9 @@ void _cmScMeasCalcVal( cmScMeas* p, cmScMeasSet_t* sp, int n_mii )
if( cmScMatchDoSync(p->mp, bli, mb, mn, NULL ) == cmInvalidIdx ) if( cmScMatchDoSync(p->mp, bli, mb, mn, NULL ) == cmInvalidIdx )
return; return;
if( p->mp->opt_cost != DBL_MAX )
sp->match_cost = p->mp->opt_cost / sp->sp->eleCnt;
switch( sp->sp->varId ) switch( sp->sp->varId )
{ {
case kEvenVarScId: case kEvenVarScId:
@ -3050,7 +3069,7 @@ void _cmScMeasCalcVal( cmScMeas* p, cmScMeasSet_t* sp, int n_mii )
sp->tempo = r.tempo; sp->tempo = r.tempo;
// print the result // print the result
_cmScMeasPrintResult(p, sp, &r, bli, mb ); //_cmScMeasPrintResult(p, sp, &r, bli, mb );
MEAS_MATCH_CNT++; MEAS_MATCH_CNT++;
} }
@ -3378,38 +3397,53 @@ const _cmScModTypeMap_t* _cmScModTypeLabelToMap( const cmChar_t* label )
return NULL; return NULL;
} }
cmScModVar_t* _cmScModulatorInsertValue( cmScModulator* p, unsigned varSymId ) cmScModVar_t* _cmScModSymToVar( cmScModulator* p, unsigned varSymId )
{ {
cmScModVar_t* vp = p->vlist; cmScModVar_t* vp = p->vlist;
for(; vp!=NULL; vp=vp->vlink) for(; vp!=NULL; vp=vp->vlink)
if( varSymId == vp->varSymId ) if( varSymId == vp->varSymId )
return vp; return vp;
return NULL;
}
cmScModVar_t* _cmScModulatorInsertVar( cmScModulator* p, unsigned varSymId, unsigned flags )
{
cmScModVar_t* vp = _cmScModSymToVar(p,varSymId);
if( vp == NULL )
{
vp = cmMemAllocZ(cmScModVar_t,1); vp = cmMemAllocZ(cmScModVar_t,1);
vp->varSymId = varSymId; vp->varSymId = varSymId;
vp->outVarId = cmInvalidId;
vp->vlink = p->vlist; vp->vlink = p->vlist;
p->vlist = vp; p->vlist = vp;
}
vp->flags = flags;
vp->value = DBL_MAX;
vp->min = DBL_MAX;
vp->max = DBL_MAX;
vp->rate = DBL_MAX;
vp->phase = 0;
vp->entry = NULL;
vp->alink = NULL;
return vp; return vp;
} }
cmRC_t _cmScModulatorInsertEntry(cmScModulator* p, unsigned idx, unsigned scLocIdx, unsigned modSymId, unsigned varSymId, unsigned typeId, const double* av, unsigned an) cmScModEntry_t* _cmScModulatorInsertEntry(cmScModulator* p, unsigned idx, unsigned scLocIdx, unsigned modSymId, unsigned varSymId, unsigned typeId, unsigned paramCnt )
{ {
assert( idx < p->en ); assert( idx < p->en );
if( p->modSymId != modSymId )
return cmOkRC;
p->earray[idx].scLocIdx = scLocIdx; p->earray[idx].scLocIdx = scLocIdx;
p->earray[idx].typeId = typeId; p->earray[idx].typeId = typeId;
p->earray[idx].parray = an==0 ? NULL : cmMemAllocZ(double,an); p->earray[idx].varPtr = _cmScModulatorInsertVar(p,varSymId,0);
p->earray[idx].pn = an;
p->earray[idx].valPtr = _cmScModulatorInsertValue(p,varSymId);
unsigned i;
for(i=0; i<an; ++i)
p->earray[idx].parray[i] = av[i];
return cmOkRC; if( p->earray[idx].varPtr->outVarId == cmInvalidIdx )
p->earray[idx].varPtr->outVarId = p->outVarCnt++;
return p->earray + idx;
} }
@ -3421,12 +3455,57 @@ cmRC_t _cmScModulatorInsertEntry(cmScModulator* p, unsigned idx, unsigned scLocI
} }
*/ */
// Parameter values are found as values of the 'data','min' or 'max' fields.
// A parameter value may be either a symbol identifier (mapped to a variable)
// or a literal number. This function determines which form the paramter
// value takes and parses it accordingly.
cmRC_t _cmScModulatorParseParam( cmScModulator* p, cmSymTblH_t stH, cmJsonNode_t* np, cmScModParam_t* pp )
{
cmRC_t rc = cmOkRC;
switch( np->typeId )
{
case kIntTId:
case kRealTId:
if( cmJsonRealValue(np, &pp->val ) != kOkJsRC )
{
rc = cmCtxRtCondition( &p->obj, cmInvalidArgRC, "Error parsing in Modulator literal value." );
goto errLabel;
}
pp->pid = kLiteralModPId;
break;
case kStringTId:
{
const cmChar_t* label = NULL;
if( cmJsonStringValue(np, &label) != kOkJsRC )
{
rc = cmCtxRtCondition( &p->obj, cmInvalidArgRC, "Error parsing in Modulator symbol label." );
goto errLabel;
}
pp->symId = cmSymTblRegisterSymbol(stH,label);
pp->pid = kSymbolModPId;
}
break;
default:
rc = cmCtxRtCondition( &p->obj, cmInvalidArgRC, "Parameter value is not a number or identifier." );
goto errLabel;
break;
}
errLabel:
return rc;
}
cmRC_t _cmScModulatorParse( cmScModulator* p, cmCtx_t* ctx, cmSymTblH_t stH, const cmChar_t* fn ) cmRC_t _cmScModulatorParse( cmScModulator* p, cmCtx_t* ctx, cmSymTblH_t stH, const cmChar_t* fn )
{ {
cmRC_t rc = cmOkRC; cmRC_t rc = cmOkRC;
cmJsonNode_t* jnp = NULL; cmJsonNode_t* jnp = NULL;
cmJsonH_t jsH = cmJsonNullHandle; cmJsonH_t jsH = cmJsonNullHandle;
unsigned i; unsigned i = cmInvalidIdx;
unsigned j = cmInvalidIdx;
// read the JSON file // read the JSON file
if( cmJsonInitializeFromFile(&jsH, fn, ctx ) != kOkJsRC ) if( cmJsonInitializeFromFile(&jsH, fn, ctx ) != kOkJsRC )
@ -3442,10 +3521,11 @@ cmRC_t _cmScModulatorInsertEntry(cmScModulator* p, unsigned idx, unsigned scLocI
} }
// allocate the entry array // allocate the entry array
p->en = cmJsonChildCount(jnp); unsigned entryCnt = cmJsonChildCount(jnp);
p->earray = cmMemResizeZ(cmScModEntry_t,p->earray,p->en); p->earray = cmMemResizeZ(cmScModEntry_t,p->earray,entryCnt);
p->en = entryCnt;
for(i=0; i<p->en; ++i) for(i=0; i<entryCnt; ++i)
{ {
cmJsRC_t jsRC; cmJsRC_t jsRC;
const char* errLabelPtr = NULL; const char* errLabelPtr = NULL;
@ -3478,49 +3558,54 @@ cmRC_t _cmScModulatorInsertEntry(cmScModulator* p, unsigned idx, unsigned scLocI
goto errLabel; goto errLabel;
} }
// get a data pointer to the data node
if((dnp = cmJsonNodeMemberValue(onp,"data")) == NULL )
{
rc = cmCtxRtCondition( &p->obj, cmInvalidArgRC, "Synax error in Modulator 'data' record at index %i in file:%s",i,cmStringNullGuard(fn) );
goto errLabel;
}
unsigned modSymId = cmSymTblRegisterSymbol(stH,modLabel); unsigned modSymId = cmSymTblRegisterSymbol(stH,modLabel);
unsigned varSymId = cmSymTblRegisterSymbol(stH,varLabel); unsigned varSymId = cmSymTblRegisterSymbol(stH,varLabel);
// the data may be an array of doubles .... // the mod entry label must match the modulators label
if( cmJsonIsArray(dnp) ) if( p->modSymId != modSymId )
{ {
unsigned an = cmJsonChildCount(dnp); --p->en;
double av[an]; continue;
unsigned j; }
// read each element in the data array
for(j=0; j<an; ++j) // get the count of the elmenets in the data array
if( cmJsonRealValue(cmJsonArrayElement(dnp,j), av+j ) != kOkJsRC ) unsigned paramCnt = cmJsonChildCount(onp);
// fill the entry record and find or create the target var
cmScModEntry_t* ep = _cmScModulatorInsertEntry(p,i,scLocIdx,modSymId,varSymId,map->typeId,paramCnt);
typedef struct
{ {
rc = cmCtxRtCondition( &p->obj, cmInvalidArgRC, "Error parsing in Modulator 'data' record at index %i value index %i in file:%s",i,j,cmStringNullGuard(fn) ); const cmChar_t* label;
cmScModParam_t* param;
} map_t;
// parse the var and parameter records
map_t mapArray[] =
{
{ "min", &ep->min },
{ "max", &ep->max },
{ "rate",&ep->rate },
{ "val", &ep->beg },
{ "end", &ep->end },
{ "dur", &ep->dur },
{ NULL, NULL }
};
unsigned j=0;
for(j=0; mapArray[j].param!=NULL; ++j)
if((dnp = cmJsonFindValue(jsH,mapArray[j].label, onp, kInvalidTId )) != NULL )
if((rc = _cmScModulatorParseParam(p,stH,dnp,mapArray[j].param)) != cmOkRC )
goto errLabel; goto errLabel;
} }
_cmScModulatorInsertEntry(p,i,scLocIdx,modSymId,varSymId,map->typeId,av,an);
}
else // ... or a scalar
{
double v;
if( cmJsonRealValue(dnp,&v) != kOkJsRC )
{
rc = cmCtxRtCondition( &p->obj, cmInvalidArgRC, "Error paring in Modulator 'data' on record index %i.",i,cmStringNullGuard(fn));
goto errLabel;
}
_cmScModulatorInsertEntry(p,i,scLocIdx,modSymId,varSymId,map->typeId,&v,1);
}
}
errLabel: errLabel:
if( rc != cmOkRC )
cmCtxRtCondition( &p->obj, cmInvalidArgRC, "Error parsing in Modulator 'data' record at index %i value index %i in file:%s",i,j,cmStringNullGuard(fn) );
// release the JSON tree // release the JSON tree
if( cmJsonIsValid(jsH) ) if( cmJsonIsValid(jsH) )
cmJsonFinalize(&jsH); cmJsonFinalize(&jsH);
@ -3528,6 +3613,32 @@ cmRC_t _cmScModulatorInsertEntry(cmScModulator* p, unsigned idx, unsigned scLocI
return rc; return rc;
} }
cmRC_t _cmScModulatorReset( cmScModulator* p, cmCtx_t* ctx, unsigned scLocIdx )
{
cmRC_t rc = cmOkRC;
p->alist = NULL;
p->elist = NULL;
p->nei = 0;
p->outVarCnt = 0;
// reload the file
if((rc = _cmScModulatorParse(p,ctx,p->stH,p->fn)) != cmOkRC )
goto errLabel;
// clear the active flag on all variables
cmScModVar_t* vp = p->vlist;
for(; vp!=NULL; vp=vp->vlink)
{
vp->flags = cmClrFlag(vp->flags,kActiveModFl);
vp->alink = NULL;
}
errLabel:
return rc;
}
cmRC_t cmScModulatorInit( cmScModulator* p, cmCtx_t* ctx, cmSymTblH_t stH, double srate, unsigned samplesPerCycle, const cmChar_t* fn, const cmChar_t* modLabel, cmScModCb_t cbFunc, void* cbArg ) cmRC_t cmScModulatorInit( cmScModulator* p, cmCtx_t* ctx, cmSymTblH_t stH, double srate, unsigned samplesPerCycle, const cmChar_t* fn, const cmChar_t* modLabel, cmScModCb_t cbFunc, void* cbArg )
{ {
cmRC_t rc; cmRC_t rc;
@ -3535,29 +3646,28 @@ cmRC_t cmScModulatorInit( cmScModulator* p, cmCtx_t* ctx, cmSymTblH_t stH, doub
if((rc = cmScModulatorFinal(p)) != cmOkRC ) if((rc = cmScModulatorFinal(p)) != cmOkRC )
return rc; return rc;
p->fn = cmMemAllocStr(fn);
p->stH = stH;
p->modSymId = cmSymTblRegisterSymbol(stH,modLabel); p->modSymId = cmSymTblRegisterSymbol(stH,modLabel);
p->cbFunc = cbFunc; p->cbFunc = cbFunc;
p->cbArg = cbArg; p->cbArg = cbArg;
p->samplesPerCycle = samplesPerCycle; p->samplesPerCycle = samplesPerCycle;
p->srate = srate; p->srate = srate;
if((rc = _cmScModulatorParse(p,ctx,stH,fn)) != cmOkRC )
goto errLabel;
errLabel:
if( rc != cmOkRC ) if( rc != cmOkRC )
cmScModulatorFinal(p); cmScModulatorFinal(p);
else else
cmScModulatorReset(p,0); _cmScModulatorReset(p,ctx,0);
return rc; return rc;
} }
cmRC_t cmScModulatorFinal( cmScModulator* p ) cmRC_t cmScModulatorFinal( cmScModulator* p )
{ {
unsigned i; cmMemFree(p->fn);
// release each value record // release each var record
cmScModVar_t* vp = p->vlist; cmScModVar_t* vp = p->vlist;
while( vp!=NULL ) while( vp!=NULL )
{ {
@ -3566,61 +3676,126 @@ cmRC_t cmScModulatorFinal( cmScModulator* p )
vp=np; vp=np;
} }
// release each entry record return cmOkRC;
}
unsigned cmScModulatorOutVarCount( cmScModulator* p )
{ return p->outVarCnt; }
cmScModVar_t* cmScModulatorOutVar( cmScModulator* p, unsigned idx )
{
unsigned i;
for(i=0; i<p->en; ++i) for(i=0; i<p->en; ++i)
cmMemFree(p->earray[i].parray); if( p->earray[i].varPtr->outVarId == idx )
return p->earray[i].varPtr;
return NULL;
}
cmRC_t cmScModulatorSetValue( cmScModulator* p, unsigned varSymId, double value, double min, double max )
{
cmScModVar_t* vp;
// if the var does not exist ....
if((vp = _cmScModSymToVar(p, varSymId )) == NULL )
{
// ... then create it
vp = _cmScModulatorInsertVar(p,varSymId,kCalcModFl);
assert(vp!=NULL);
}
assert( min <= max);
vp->min = min;
vp->max = max;
vp->value = value;
return cmOkRC; return cmOkRC;
} }
unsigned cmScModulatorVarCount( cmScModulator* p )
cmRC_t cmScModulatorReset( cmScModulator* p, cmCtx_t* ctx, unsigned scLocIdx )
{ {
unsigned n = 0; _cmScModulatorReset(p,ctx,scLocIdx);
const cmScModVar_t* vp = p->vlist;
for(; vp!=NULL; vp=vp->vlink)
++n;
return n;
}
cmScModVar_t* cmScModulatorVar( cmScModulator* p, unsigned idx )
{
unsigned n = 0;
cmScModVar_t* vp = p->vlist;
for(; vp!=NULL; vp=vp->vlink,++n)
if( n == idx )
return vp;
assert(0);
return NULL;
}
cmRC_t cmScModulatorReset( cmScModulator* p, unsigned scLocIdx )
{
p->alist = NULL;
p->nei = 0;
return cmScModulatorExec(p,scLocIdx); return cmScModulatorExec(p,scLocIdx);
} }
void _cmScModUnlink( cmScModulator* p, cmScModVar_t* vp, cmScModVar_t* pp ) void _cmScModUnlinkActive( cmScModulator* p, cmScModVar_t* vp, cmScModVar_t* pp )
{ {
if( pp == NULL ) // if vp is the first link on the chain
if( vp == p->alist )
p->alist = vp->alink; p->alist = vp->alink;
else
// if vp is the last link on the chain
if( vp == p->elist )
p->elist = pp;
if( pp != NULL )
pp->alink = vp->alink; pp->alink = vp->alink;
vp->flags = 0; vp->flags = cmClrFlag(vp->flags,kActiveModFl);
vp->alink = NULL; vp->alink = NULL;
vp->entry = NULL; vp->entry = NULL;
} }
// Type specific variable activation // If the requested parameter has a value then return it in *valPtr.
// If it does not then do nothing. This function applies scaling to RHS values.
cmRC_t _cmScModGetParam( cmScModulator* p, const cmScModParam_t* pp, double* valPtr )
{
cmRC_t rc = cmOkRC;
switch( pp->pid )
{
case kInvalidModPId:
break;
case kLiteralModPId:
*valPtr = pp->val;
break;
case kSymbolModPId:
{
cmScModVar_t* vp;
// get a pointer to the parameter variable
if((vp = _cmScModSymToVar(p, pp->symId )) == NULL )
{
rc = cmCtxRtCondition( &p->obj, cmInvalidArgRC, "Variable '%s' not found.",cmSymTblLabel(p->stH,pp->symId));
goto errLabel;
}
// if this is not a 'calculated' paramter then scale it here.
if( cmIsFlag(vp->flags,kCalcModFl ) && vp->min!=DBL_MAX && vp->max!=DBL_MAX )
*valPtr = (vp->value - vp->min)/(vp->max-vp->min);
else
*valPtr = vp->value;
}
break;
default:
{ assert(0); }
}
errLabel:
return rc;
}
// Type specific variable activation -
cmRC_t _cmScModActivate(cmScModulator* p, cmScModEntry_t* ep ) cmRC_t _cmScModActivate(cmScModulator* p, cmScModEntry_t* ep )
{ {
cmRC_t rc = cmOkRC; cmRC_t rc = cmOkRC;
cmScModVar_t* vp = ep->valPtr; cmScModVar_t* vp = ep->varPtr;
// optionally update the min/max/rate values in the target var
if((rc = _cmScModGetParam(p,&ep->min,&vp->min)) != cmOkRC )
goto errLabel;
if((rc = _cmScModGetParam(p,&ep->max,&vp->max)) != cmOkRC )
goto errLabel;
if((rc = _cmScModGetParam(p,&ep->rate,&vp->rate)) != cmOkRC )
goto errLabel;
switch( ep->typeId ) switch( ep->typeId )
{ {
@ -3633,49 +3808,94 @@ cmRC_t _cmScModActivate(cmScModulator* p, cmScModEntry_t* ep )
break; break;
case kSetLineModTId: case kSetLineModTId:
vp->value = ep->parray[0]; _cmScModGetParam(p,&ep->beg,&vp->value); // starting value
vp->v0 = ep->parray[0]; vp->v0 = vp->value; // set initial value
vp->phase = 0; vp->phase = 0; // reset phase
ep->parray[0] = ep->parray[1];
ep->parray[1] = ep->parray[2];
break; break;
default: default:
{ assert(0); } { assert(0); }
} }
errLabel:
return rc;
}
// Callback the application with a new variable value.
cmRC_t _cmScModExecSendValue( cmScModulator* p, cmScModVar_t* vp )
{
cmRC_t rc = cmOkRC;
bool sendFl = true;
double v = vp->value;
// scale the output value - this is equiv to scaling the LHS
if( cmIsFlag(vp->flags,kCalcModFl) && vp->min!=DBL_MAX && vp->max!=DBL_MAX )
v = vp->min + v * (vp->max - vp->min);
// if an output rate throttle is in effect ....
if( vp->rate!=DBL_MAX && vp->phase!=0 )
sendFl = remainder(vp->phase*p->samplesPerCycle, p->srate*vp->rate/1000 ) < p->samplesPerCycle;
if(sendFl)
p->cbFunc(p->cbArg,vp->varSymId,v);
return rc; return rc;
} }
// Return true if vp should be deactivated otherwise return false. // Return true if vp should be deactivated otherwise return false.
bool _cmScModExec( cmScModulator* p, cmScModVar_t* vp ) bool _cmScModExec( cmScModulator* p, cmScModVar_t* vp )
{ {
cmRC_t rc = cmOkRC;
bool fl = false; bool fl = false;
switch( vp->entry->typeId ) switch( vp->entry->typeId )
{ {
case kSetModTId: case kSetModTId:
p->cbFunc(p->cbArg,vp->varSymId,vp->entry->parray[0]); {
if((rc = _cmScModGetParam(p,&vp->entry->beg,&vp->value)) != cmOkRC )
goto errLabel;
vp->phase = 0; // force the value to be sent
fl = true; fl = true;
}
break; break;
case kSetLineModTId: case kSetLineModTId:
case kLineModTId: case kLineModTId:
{ {
double v1 = vp->entry->parray[0]; double v1, td;
double v = vp->value + (v1-vp->v0) * (vp->phase * p->samplesPerCycle) / (p->srate * vp->entry->parray[1]);
// get the target value
if((rc = _cmScModGetParam(p,&vp->entry->end,&v1)) != cmOkRC)
goto errLabel;
// get the time duration
if((rc = _cmScModGetParam(p,&vp->entry->dur,&td)) != cmOkRC)
goto errLabel;
double v = vp->v0 + (v1-vp->v0) * (vp->phase * p->samplesPerCycle) / (p->srate * td);
if((fl = (vp->value <= v1 && v >= v1) || (vp->value >= v1 && v <= v1 )) == true ) if((fl = (vp->value <= v1 && v >= v1) || (vp->value >= v1 && v <= v1 )) == true )
v = v1; v = v1;
vp->phase += 1;
vp->value = v; vp->value = v;
p->cbFunc(p->cbArg,vp->varSymId,v);
} }
break; break;
default: default:
{ assert(0); } { assert(0); }
} }
// notify the application that a new variable value has been generated
rc = _cmScModExecSendValue(p,vp);
// increment the phase - after send because send notices when phase is zero
vp->phase += 1;
errLabel:
if( rc != cmOkRC )
fl = true;
return fl; return fl;
} }
@ -3686,25 +3906,35 @@ cmRC_t cmScModulatorExec( cmScModulator* p, unsigned scLocIdx )
cmRC_t rc = cmOkRC; cmRC_t rc = cmOkRC;
// trigger entries that have expired since the last call to this function // trigger entries that have expired since the last call to this function
for(; p->nei<p->en && p->earray[p->nei].scLocIdx<=scLocIdx; ++p->nei) for(; p->nei<p->en && (p->earray[p->nei].scLocIdx==-1 || p->earray[p->nei].scLocIdx<=scLocIdx); ++p->nei)
{ {
cmScModEntry_t* ep = p->earray + p->nei; cmScModEntry_t* ep = p->earray + p->nei;
// if the variable assoc'd with this entry is not on the active list ... // if the variable assoc'd with this entry is not on the active list ...
if( cmIsFlag(ep->valPtr->flags,kActiveModFl) == false ) if( cmIsFlag(ep->varPtr->flags,kActiveModFl) == false )
{ {
// ... then push it onto the front of the active list ... // ... then append it to the end of the active list ...
ep->valPtr->flags = kActiveModFl; ep->varPtr->flags |= kActiveModFl;
ep->valPtr->alink = p->alist;
p->alist = ep->valPtr; if( p->elist == NULL )
p->elist = ep->varPtr;
else
{
p->elist->alink = ep->varPtr;
p->elist = ep->varPtr;
} }
p->elist->alink = NULL;
if( p->alist == NULL )
p->alist = ep->varPtr;
}
// do type specific activation // do type specific activation
if((trc = _cmScModActivate(p,ep)) != cmOkRC ) if((trc = _cmScModActivate(p,ep)) != cmOkRC )
rc = trc; rc = trc;
ep->valPtr->entry = ep; ep->varPtr->entry = ep;
} }
@ -3714,10 +3944,90 @@ cmRC_t cmScModulatorExec( cmScModulator* p, unsigned scLocIdx )
for(; vp!=NULL; vp=vp->alink) for(; vp!=NULL; vp=vp->alink)
{ {
if( _cmScModExec(p,vp) ) if( _cmScModExec(p,vp) )
_cmScModUnlink(p,vp,pp); _cmScModUnlinkActive(p,vp,pp);
else else
pp = vp; pp = vp;
} }
return rc; return rc;
} }
void _cmScModDumpParam( cmScModulator* p, const cmChar_t* label, cmScModParam_t* pp )
{
printf("%s: ",label);
switch( pp->pid )
{
case kInvalidModPId:
printf("<invalid>");
break;
case kLiteralModPId:
if( pp->val == DBL_MAX )
printf("<max> ");
else
printf("%f ",pp->val);
break;
case kSymbolModPId:
printf("%s ",cmSymTblLabel(p->stH,pp->symId));
break;
default:
{ assert(0); }
}
}
void _cmScModDumpVal( cmChar_t* label, double val )
{
printf("%s:",label);
if( val == DBL_MAX )
printf("<max> " );
else
printf("%f ",val);
}
void _cmScModDumpVar( cmScModulator* p, const cmScModVar_t* vp )
{
printf("%7s %3i fl:0x%x entry:%p alink:%p ",cmSymTblLabel(p->stH,vp->varSymId),vp->outVarId,vp->flags,vp->entry,vp->alink);
_cmScModDumpVal("val",vp->value);
_cmScModDumpVal("min",vp->min);
_cmScModDumpVal("max",vp->max);
_cmScModDumpVal("rate",vp->rate);
_cmScModDumpVal("v0",vp->v0);
}
cmRC_t cmScModulatorDump( cmScModulator* p )
{
cmRC_t rc = cmOkRC;
printf("MOD:\n");
printf("nei:%i alist:%p outVarCnt:%i\n",p->nei,p->alist,p->outVarCnt);
printf("ENTRIES:\n");
unsigned i;
for(i=0; i<p->en; ++i)
{
cmScModEntry_t* ep = p->earray + i;
printf("%3i %4i %2i %7s ", i, ep->scLocIdx, ep->typeId, cmSymTblLabel(p->stH,ep->varPtr->varSymId));
_cmScModDumpParam(p," beg", &ep->beg);
_cmScModDumpParam(p," end", &ep->end);
_cmScModDumpParam(p," min", &ep->min);
_cmScModDumpParam(p," max", &ep->max);
_cmScModDumpParam(p," rate",&ep->rate);
printf("\n");
}
printf("VARIABLES\n");
cmScModVar_t* vp = p->vlist;
for(; vp!=NULL; vp=vp->vlink)
{
_cmScModDumpVar(p,vp);
printf("\n");
}
return rc;
}

View File

@ -5,8 +5,6 @@
extern "C" { extern "C" {
#endif #endif
typedef struct typedef struct
{ {
unsigned smpIdx; // time tag sample index for val unsigned smpIdx; // time tag sample index for val
@ -340,15 +338,16 @@ typedef void (*cmScMatcherCb_t)( struct cmScMatcher_str* p, void* arg, cmScMatch
unsigned ri; // next avail res[] recd. unsigned ri; // next avail res[] recd.
double s_opt; // double s_opt; //
unsigned missCnt; // count of consecutive trailing non-matches unsigned missCnt; // current count of consecutive trailing non-matches
unsigned ili; // index into loc[] to start scan following reset unsigned ili; // index into loc[] to start scan following reset
unsigned eli; // index into loc[] of the last positive match. unsigned eli; // index into loc[] of the last positive match.
unsigned mni; // track the count of MIDI events since the last call to cmScMatcherReset() unsigned mni; // current count of MIDI events since the last call to cmScMatcherReset()
unsigned mbi; // index of oldest MIDI event in midiBuf[]; 0 when the buffer is full. unsigned mbi; // index of oldest MIDI event in midiBuf[]; stays at 0 when the buffer is full.
unsigned begSyncLocIdx; // start of score window, in mp->loc[], of best match in previous scan unsigned begSyncLocIdx; // start of score window, in mp->loc[], of best match in previous scan
unsigned initHopCnt; // max window hops during the initial (when the MIDI buffer fills for first time) sync scan
unsigned stepCnt; // count of forward/backward score loc's to examine for a match during cmScMatcherStep(). unsigned stepCnt; // count of forward/backward score loc's to examine for a match during cmScMatcherStep().
unsigned maxMissCnt; // max. number of consecutive non-matches during step prior to executing a scan. unsigned maxMissCnt; // max. number of consecutive non-matches during step prior to executing a scan.
unsigned scanCnt; // count of time scan was executed inside cmScMatcherStep() unsigned scanCnt; // current count of times a resync-scan was executed during cmScMatcherStep()
bool printFl; bool printFl;
} cmScMatcher; } cmScMatcher;
@ -363,13 +362,13 @@ cmRC_t cmScMatcherFinal( cmScMatcher* p );
// 'scLocIdx' is a score index as used by cmScoreLoc(scH) not into p->mp->loc[]. // 'scLocIdx' is a score index as used by cmScoreLoc(scH) not into p->mp->loc[].
cmRC_t cmScMatcherReset( cmScMatcher* p, unsigned scLocIdx ); cmRC_t cmScMatcherReset( cmScMatcher* p, unsigned scLocIdx );
// Slide a score window scanCnt times, beginning at 'bli' (an // Slide a score window hopCnt times, beginning at 'bli' (an
// index int p->mp->loc[]) looking for the best match to p->midiBuf[]. // index int p->mp->loc[]) looking for the best match to p->midiBuf[].
// The score window contain scWndN (p->mp->mcn-1) score locations. // The score window contain scWndN (p->mp->mcn-1) score locations.
// Returns the index into p->mp->loc[] of the start of the best // Returns the index into p->mp->loc[] of the start of the best
// match score window. The score associated // match score window. The score associated
// with this match is stored in s_opt. // with this match is stored in s_opt.
unsigned cmScMatcherScan( cmScMatcher* p, unsigned bli, unsigned scanCnt ); unsigned cmScMatcherScan( cmScMatcher* p, unsigned bli, unsigned hopCnt );
// Step forward/back by p->stepCnt from p->eli. // Step forward/back by p->stepCnt from p->eli.
// p->eli must therefore be valid prior to calling this function. // p->eli must therefore be valid prior to calling this function.
@ -385,7 +384,7 @@ cmRC_t cmScMatcherStep( cmScMatcher* p );
// If the MIDI note passed by the call results in a successful match then // If the MIDI note passed by the call results in a successful match then
// p->eli will be updated to the location in p->mp->loc[] of the latest // p->eli will be updated to the location in p->mp->loc[] of the latest
// match, the MIDI note in p->midiBuf[] associated with this match // match, the MIDI note in p->midiBuf[] associated with this match
// will be assigned valid locIdx and scLocIdx values, and *scLocIdxPtr // will be assigned a valid locIdx and scLocIdx values, and *scLocIdxPtr
// will be set with the matched scLocIdx of the match. // will be set with the matched scLocIdx of the match.
// If this call does not result in a successful match *scLocIdxPtr is set // If this call does not result in a successful match *scLocIdxPtr is set
// to cmInvalidIdx. // to cmInvalidIdx.
@ -413,7 +412,9 @@ typedef struct
unsigned eli; // unsigned eli; //
double value; // DBL_MAX if the value has not yet been set double value; // DBL_MAX if the value has not yet been set
double tempo; // DBL_MAX until set double tempo; //
double match_cost; // cost of the match to the performance divided by sp->eleCnt
} cmScMeasSet_t; } cmScMeasSet_t;
@ -488,30 +489,57 @@ enum
enum enum
{ {
kActiveModFl = 0x01 kActiveModFl = 0x01, // this variable is on the 'active' list
kCalcModFl = 0x02 // when this variable is used as a parameter it's value must be calculated rather than used directly.
}; };
struct cmScModEntry_str; struct cmScModEntry_str;
typedef enum
{
kInvalidModPId,
kLiteralModPId, // this is a literal value
kSymbolModPId //
} cmScModPId_t;
typedef struct cmScModParam_str
{
cmScModPId_t pid; // parameter type: literal or symbol
unsigned symId; // symbol of external and internal variables
double val; // value of literals
} cmScModParam_t;
typedef struct cmScModVar_str typedef struct cmScModVar_str
{ {
unsigned flags; // see kXXXModFl flags above. unsigned flags; // see kXXXModFl flags above.
unsigned varSymId; // variable name unsigned varSymId; // variable name
double value; // current value unsigned outVarId; // output var id
double value; // current value of this variable
double v0; // reserved internal variable double v0; // reserved internal variable
unsigned phase; // cycle phase since activation unsigned phase; // cycle phase since activation
double min;
double max;
double rate; // output rate in milliseconds
struct cmScModEntry_str* entry; // last entry assoc'd with this value struct cmScModEntry_str* entry; // last entry assoc'd with this value
struct cmScModVar_str* vlink; // p->vlist link struct cmScModVar_str* vlink; // p->vlist link
struct cmScModVar_str* alink; // p->alist link struct cmScModVar_str* alink; // p->alist link
} cmScModVar_t; } cmScModVar_t;
// Each entry gives a time tagged location and some parameters
// for an algorthm which is used to set/modulate a value.
typedef struct cmScModEntry_str typedef struct cmScModEntry_str
{ {
unsigned scLocIdx; // entry start time unsigned scLocIdx; // entry start time
unsigned typeId; // variable type unsigned typeId; // variable type
double* parray; // parray[pn] - parameter array cmScModParam_t beg; // parameter values
unsigned pn; // parameter count cmScModParam_t end; //
cmScModVar_t* valPtr; // target variable cmScModParam_t dur; //
cmScModParam_t min; // min value for this variable
cmScModParam_t max; // max value for this variable
cmScModParam_t rate; // update rate in milliseconds (DBL_MAX to disable)
cmScModVar_t* varPtr; // target variable
} cmScModEntry_t; } cmScModEntry_t;
typedef void (*cmScModCb_t)( void* cbArg, unsigned varSymId, double value ); typedef void (*cmScModCb_t)( void* cbArg, unsigned varSymId, double value );
@ -519,7 +547,9 @@ typedef void (*cmScModCb_t)( void* cbArg, unsigned varSymId, double value );
typedef struct typedef struct
{ {
cmObj obj; cmObj obj;
cmChar_t* fn; // modulator score file
unsigned modSymId; // modulator name unsigned modSymId; // modulator name
cmSymTblH_t stH; // symbol table used by this modulator
cmScModCb_t cbFunc; // active value callback function cmScModCb_t cbFunc; // active value callback function
void* cbArg; // first arg to cbFunc() void* cbArg; // first arg to cbFunc()
unsigned samplesPerCycle; // interval in samples between calls to cmScModulatorExec() unsigned samplesPerCycle; // interval in samples between calls to cmScModulatorExec()
@ -528,7 +558,9 @@ typedef struct
unsigned en; // count unsigned en; // count
cmScModVar_t* vlist; // variable list cmScModVar_t* vlist; // variable list
cmScModVar_t* alist; // active variable list cmScModVar_t* alist; // active variable list
cmScModVar_t* elist; // last element on the active list
unsigned nei; // next entry index unsigned nei; // next entry index
unsigned outVarCnt; // count of unique vars that are targets of entry recds
} cmScModulator; } cmScModulator;
@ -538,13 +570,16 @@ cmRC_t cmScModulatorInit( cmScModulator* p, cmCtx_t* ctx, cmSymTblH_t s
cmRC_t cmScModulatorFinal( cmScModulator* p ); cmRC_t cmScModulatorFinal( cmScModulator* p );
// Return count of variables. // Return count of variables.
unsigned cmScModulatorVarCount( cmScModulator* p ); unsigned cmScModulatorOutVarCount( cmScModulator* p );
// Return a pointer to the variable at vlist[idx]. // Return a pointer to the variable at vlist[idx].
cmScModVar_t* cmScModulatorVar( cmScModulator* p, unsigned idx ); cmScModVar_t* cmScModulatorOutVar( cmScModulator* p, unsigned idx );
cmRC_t cmScModulatorReset( cmScModulator* p, unsigned scLocIdx ); cmRC_t cmScModulatorSetValue( cmScModulator* p, unsigned varSymId, double value, double min, double max );
cmRC_t cmScModulatorReset( cmScModulator* p, cmCtx_t* ctx, unsigned scLocIdx );
cmRC_t cmScModulatorExec( cmScModulator* p, unsigned scLocIdx ); cmRC_t cmScModulatorExec( cmScModulator* p, unsigned scLocIdx );
cmRC_t cmScModulatorDump( cmScModulator* p );
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -21,6 +21,7 @@
#include "cmAudioSys.h" #include "cmAudioSys.h"
#include "cmDspCtx.h" #include "cmDspCtx.h"
#include "cmDspClass.h" #include "cmDspClass.h"
#include "cmDspStore.h"
#include "cmDspUi.h" #include "cmDspUi.h"
#include "cmDspSys.h" #include "cmDspSys.h"
#include "cmMath.h" #include "cmMath.h"
@ -51,6 +52,8 @@ enum
kUprSlopeKrId, kUprSlopeKrId,
kOffsetKrId, kOffsetKrId,
kInvertKrId, kInvertKrId,
kBypassKrId,
kWetKrId,
kAudioInKrId, kAudioInKrId,
kAudioOutKrId kAudioOutKrId
}; };
@ -79,6 +82,8 @@ cmDspClass_t _cmKrDC;
{ "uprs", kUprSlopeKrId, 0, 0, kInDsvFl | kDoubleDsvFl | kOptArgDsvFl, "Upper Slope"}, { "uprs", kUprSlopeKrId, 0, 0, kInDsvFl | kDoubleDsvFl | kOptArgDsvFl, "Upper Slope"},
{ "offs", kOffsetKrId, 0, 0, kInDsvFl | kDoubleDsvFl | kOptArgDsvFl, "Offset"}, { "offs", kOffsetKrId, 0, 0, kInDsvFl | kDoubleDsvFl | kOptArgDsvFl, "Offset"},
{ "invt", kInvertKrId, 0, 0, kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "Invert"}, { "invt", kInvertKrId, 0, 0, kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "Invert"},
{ "bypass", kBypassKrId, 0, 0, kInDsvFl | kBoolDsvFl | kOptArgDsvFl, "Bypass enable flag." },
{ "wet", kWetKrId, 0, 0, kInDsvFl | kSampleDsvFl, "Wet mix level."},
{ "in", kAudioInKrId, 0, 0, kInDsvFl | kAudioBufDsvFl, "Audio Input" }, { "in", kAudioInKrId, 0, 0, kInDsvFl | kAudioBufDsvFl, "Audio Input" },
{ "out", kAudioOutKrId, 0, 1, kOutDsvFl | kAudioBufDsvFl, "Audio Output" }, { "out", kAudioOutKrId, 0, 1, kOutDsvFl | kAudioBufDsvFl, "Audio Output" },
{ NULL, 0, 0, 0, 0 } { NULL, 0, 0, 0, 0 }
@ -96,6 +101,9 @@ cmDspClass_t _cmKrDC;
cmDspSetDefaultDouble( ctx,&p->inst, kUprSlopeKrId, 0, 0.0 ); cmDspSetDefaultDouble( ctx,&p->inst, kUprSlopeKrId, 0, 0.0 );
cmDspSetDefaultDouble( ctx,&p->inst, kOffsetKrId, 0, 30.0); cmDspSetDefaultDouble( ctx,&p->inst, kOffsetKrId, 0, 30.0);
cmDspSetDefaultUInt( ctx,&p->inst, kInvertKrId, 0, 0 ); cmDspSetDefaultUInt( ctx,&p->inst, kInvertKrId, 0, 0 );
cmDspSetDefaultUInt( ctx,&p->inst, kBypassKrId, 0, 0 );
cmDspSetDefaultSample( ctx,&p->inst, kWetKrId, 0, 1.0);
//_cmDspKrCmInit(ctx,p); // initialize the cm library //_cmDspKrCmInit(ctx,p); // initialize the cm library
p->ctx = cmCtxAlloc(NULL,ctx->rpt,ctx->lhH,ctx->stH); p->ctx = cmCtxAlloc(NULL,ctx->rpt,ctx->lhH,ctx->stH);
@ -125,6 +133,7 @@ cmDspRC_t _cmDspKrSetup(cmDspCtx_t* ctx, cmDspKr_t* p )
unsigned olaWndTypeId =kHannWndId; unsigned olaWndTypeId =kHannWndId;
cmSpecDistFree(&p->sdp); cmSpecDistFree(&p->sdp);
p->sdp = cmSpecDistAlloc(p->ctx, NULL, cmDspSamplesPerCycle(ctx), cmDspSampleRate(ctx), wndSmpCnt, hopFact, olaWndTypeId); p->sdp = cmSpecDistAlloc(p->ctx, NULL, cmDspSamplesPerCycle(ctx), cmDspSampleRate(ctx), wndSmpCnt, hopFact, olaWndTypeId);
assert(p->sdp != NULL ); assert(p->sdp != NULL );
@ -165,10 +174,17 @@ cmDspRC_t _cmDspKrExec(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt
unsigned oSmpCnt = cmDspVarRows(inst,kAudioOutKrId); unsigned oSmpCnt = cmDspVarRows(inst,kAudioOutKrId);
const cmSample_t* sp; const cmSample_t* sp;
cmSample_t wet = cmDspSample(inst,kWetKrId);
cmSpecDistExec(p->sdp,ip,iSmpCnt); cmSpecDistExec(p->sdp,ip,iSmpCnt);
if((sp = cmSpecDistOut(p->sdp)) != NULL ) if((sp = cmSpecDistOut(p->sdp)) != NULL )
cmVOS_Copy(op,oSmpCnt,sp); {
cmVOS_MultVVS(op,oSmpCnt,sp,wet);
}
if( wet<1.0 )
cmVOS_MultSumVVS(op,oSmpCnt,ip,1.0-wet);
return rc; return rc;
} }
@ -178,6 +194,7 @@ cmDspRC_t _cmDspKrRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt
cmDspKr_t* p = (cmDspKr_t*)inst; cmDspKr_t* p = (cmDspKr_t*)inst;
cmDspRC_t rc = kOkDspRC; cmDspRC_t rc = kOkDspRC;
cmDspSetEvent(ctx,inst,evt); cmDspSetEvent(ctx,inst,evt);
switch( evt->dstVarId ) switch( evt->dstVarId )
@ -185,6 +202,22 @@ cmDspRC_t _cmDspKrRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt
case kWndSmpCntKrId: case kWndSmpCntKrId:
case kHopFactKrId: case kHopFactKrId:
_cmDspKrSetup(ctx,p); _cmDspKrSetup(ctx,p);
// THIS IS A HACK
// WHEN WND OR HOP CHANGE THE RESULTING CHANGES
// SHOULD BE ISOLATED IN cmSpecDist() AND THE
// CURRENT STATE OF THE PARAMETERS SHOULD NOT BE
// LOST - IF THE CHANGES WERE ISOLATED WITHIN PVANL
// AND PVSYN IT MIGHT BE POSSIBLE TO DO WITH
// MINIMAL AUDIO INTERUPTION.
p->sdp->mode = cmDspUInt(inst,kModeKrId);
p->sdp->thresh = cmDspDouble(inst,kThreshKrId);
p->sdp->uprSlope = cmDspDouble(inst,kUprSlopeKrId);
p->sdp->lwrSlope = cmDspDouble(inst,kLwrSlopeKrId);
p->sdp->offset = cmDspDouble(inst,kOffsetKrId);
p->sdp->invertFl = cmDspUInt(inst,kInvertKrId)!=0;
printf("wsn:%i hsn:%i\n",p->sdp->wndSmpCnt,p->sdp->hopSmpCnt); printf("wsn:%i hsn:%i\n",p->sdp->wndSmpCnt,p->sdp->hopSmpCnt);
break; break;
@ -195,16 +228,17 @@ cmDspRC_t _cmDspKrRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt
case kThreshKrId: case kThreshKrId:
p->sdp->thresh = cmDspDouble(inst,kThreshKrId); p->sdp->thresh = cmDspDouble(inst,kThreshKrId);
//printf("thr:p:%p sdp:%p %f\n",p,p->sdp,p->sdp->thresh);
break; break;
case kUprSlopeKrId: case kUprSlopeKrId:
p->sdp->uprSlope = cmDspDouble(inst,kUprSlopeKrId); p->sdp->uprSlope = cmDspDouble(inst,kUprSlopeKrId);
printf("upr slope:%f\n",p->sdp->uprSlope); //printf("upr slope:%f\n",p->sdp->uprSlope);
break; break;
case kLwrSlopeKrId: case kLwrSlopeKrId:
p->sdp->lwrSlope = cmDspDouble(inst,kLwrSlopeKrId); p->sdp->lwrSlope = cmDspDouble(inst,kLwrSlopeKrId);
printf("upr slope:%f\n",p->sdp->lwrSlope); //printf("upr slope:%f\n",p->sdp->lwrSlope);
break; break;
case kOffsetKrId: case kOffsetKrId:
@ -215,6 +249,9 @@ cmDspRC_t _cmDspKrRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt
p->sdp->invertFl = cmDspUInt(inst,kInvertKrId)!=0; p->sdp->invertFl = cmDspUInt(inst,kInvertKrId)!=0;
break; break;
case kWetKrId:
break;
default: default:
{ assert(0); } { assert(0); }
} }
@ -517,7 +554,7 @@ cmDspRC_t _cmDspScoreReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t*
} }
if((tlFn = cmDspStrcz(inst, kFnScId )) != NULL ) if((tlFn = cmDspStrcz(inst, kFnScId )) != NULL )
if( cmScoreInitialize(ctx->cmCtx, &p->scH, tlFn, cmDspSampleRate(ctx), dynRefArray, dynRefCnt, _cmDspScoreCb, p ) != kOkTlRC ) if( cmScoreInitialize(ctx->cmCtx, &p->scH, tlFn, cmDspSampleRate(ctx), dynRefArray, dynRefCnt, _cmDspScoreCb, p, cmSymTblNullHandle ) != kOkTlRC )
rc = cmErrMsg(&inst->classPtr->err, kInstResetFailDspRC, "Score file open failed."); rc = cmErrMsg(&inst->classPtr->err, kInstResetFailDspRC, "Score file open failed.");
errLabel: errLabel:
@ -822,7 +859,9 @@ enum
kOutSfId, kOutSfId,
kDynSfId, kDynSfId,
kEvenSfId, kEvenSfId,
kTempoSfId kTempoSfId,
kCostSfId,
kSymSfId
}; };
cmDspClass_t _cmScFolDC; cmDspClass_t _cmScFolDC;
@ -864,6 +903,8 @@ cmDspInst_t* _cmDspScFolAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned
{ "dyn", kDynSfId, 0, 0, kOutDsvFl| kDoubleDsvFl, "Dynamic value."}, { "dyn", kDynSfId, 0, 0, kOutDsvFl| kDoubleDsvFl, "Dynamic value."},
{ "even", kEvenSfId, 0, 0, kOutDsvFl| kDoubleDsvFl, "Evenness value."}, { "even", kEvenSfId, 0, 0, kOutDsvFl| kDoubleDsvFl, "Evenness value."},
{ "tempo", kTempoSfId, 0, 0, kOutDsvFl| kDoubleDsvFl, "Tempo value."}, { "tempo", kTempoSfId, 0, 0, kOutDsvFl| kDoubleDsvFl, "Tempo value."},
{ "cost", kCostSfId, 0, 0, kOutDsvFl| kDoubleDsvFl, "Match cost value."},
{ "sym", kSymSfId, 0, 0, kOutDsvFl| kSymDsvFl, "Symbol associated with a global variable which has changed value."},
{ NULL, 0, 0, 0, 0, NULL } { NULL, 0, 0, 0, 0, NULL }
}; };
@ -886,6 +927,7 @@ cmDspInst_t* _cmDspScFolAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned
cmDspSetDefaultDouble( ctx, &p->inst, kDynSfId, 0, 0); cmDspSetDefaultDouble( ctx, &p->inst, kDynSfId, 0, 0);
cmDspSetDefaultDouble( ctx, &p->inst, kEvenSfId, 0, 0); cmDspSetDefaultDouble( ctx, &p->inst, kEvenSfId, 0, 0);
cmDspSetDefaultDouble( ctx, &p->inst, kTempoSfId, 0, 0); cmDspSetDefaultDouble( ctx, &p->inst, kTempoSfId, 0, 0);
cmDspSetDefaultDouble( ctx, &p->inst, kCostSfId, 0, 0);
cmDspSetDefaultSymbol(ctx,&p->inst, kCmdSfId, p->quietSymId ); cmDspSetDefaultSymbol(ctx,&p->inst, kCmdSfId, p->quietSymId );
@ -916,6 +958,7 @@ void _cmScFolMatcherCb( cmScMatcher* p, void* arg, cmScMatcherResult_t* rp )
unsigned i; unsigned i;
for(i=ap->sfp->smp->vsi; i<ap->sfp->smp->nsi; ++i) for(i=ap->sfp->smp->vsi; i<ap->sfp->smp->nsi; ++i)
{ {
switch( ap->sfp->smp->set[i].sp->varId ) switch( ap->sfp->smp->set[i].sp->varId )
{ {
case kEvenVarScId: case kEvenVarScId:
@ -933,6 +976,26 @@ void _cmScFolMatcherCb( cmScMatcher* p, void* arg, cmScMatcherResult_t* rp )
default: default:
{ assert(0); } { assert(0); }
} }
cmDspSetDouble(ap->ctx,inst,kCostSfId,ap->sfp->smp->set[i].match_cost);
// Set the values in the global variable storage
cmDspValue_t vv,cv;
unsigned j;
cmDsvSetDouble(&vv,ap->sfp->smp->set[i].value);
cmDsvSetDouble(&cv,ap->sfp->smp->set[i].match_cost);
for(j=0; j<ap->sfp->smp->set[i].sp->sectCnt; ++j)
{
cmDspStoreSetValueViaSym(ap->ctx->dsH, ap->sfp->smp->set[i].sp->symArray[j], &vv );
cmDspStoreSetValueViaSym(ap->ctx->dsH, ap->sfp->smp->set[i].sp->costSymArray[j], &cv );
cmDspSetSymbol(ap->ctx,inst,kSymSfId,ap->sfp->smp->set[i].sp->symArray[j]);
cmDspSetSymbol(ap->ctx,inst,kSymSfId,ap->sfp->smp->set[i].sp->costSymArray[j]);
}
} }
/* /*
@ -957,7 +1020,7 @@ cmDspRC_t _cmDspScFolOpenScore( cmDspCtx_t* ctx, cmDspInst_t* inst )
if((fn = cmDspStrcz(inst,kFnSfId)) == NULL || strlen(fn)==0 ) if((fn = cmDspStrcz(inst,kFnSfId)) == NULL || strlen(fn)==0 )
return cmErrMsg(&inst->classPtr->err, kInvalidArgDspRC, "No score file name supplied."); return cmErrMsg(&inst->classPtr->err, kInvalidArgDspRC, "No score file name supplied.");
if( cmScoreInitialize(ctx->cmCtx, &p->scH, fn, cmDspSampleRate(ctx), NULL, 0, NULL, NULL ) != kOkScRC ) if( cmScoreInitialize(ctx->cmCtx, &p->scH, fn, cmDspSampleRate(ctx), NULL, 0, NULL, NULL, ctx->stH ) != kOkScRC )
return cmErrMsg(&inst->classPtr->err, kSubSysFailDspRC, "Unable to open the score '%s'.",fn); return cmErrMsg(&inst->classPtr->err, kSubSysFailDspRC, "Unable to open the score '%s'.",fn);
if( cmScoreIsValid(p->scH) ) if( cmScoreIsValid(p->scH) )
@ -1070,7 +1133,9 @@ struct cmDspClass_str* cmScFolClassCons( cmDspCtx_t* ctx )
enum enum
{ {
kScLocIdxMdId kScLocIdxMdId,
kResetIdxMdId,
kCmdMdId
}; };
cmDspClass_t _cmModulatorDC; cmDspClass_t _cmModulatorDC;
@ -1080,6 +1145,10 @@ typedef struct
cmDspInst_t inst; cmDspInst_t inst;
cmScModulator* mp; cmScModulator* mp;
cmDspCtx_t* tmp_ctx; // used to temporarily hold the current cmDspCtx during callback cmDspCtx_t* tmp_ctx; // used to temporarily hold the current cmDspCtx during callback
cmChar_t* fn;
cmChar_t* modLabel;
unsigned onSymId;
unsigned offSymId;
} cmDspScMod_t; } cmDspScMod_t;
void _cmDspScModCb( void* arg, unsigned varSymId, double value ) void _cmDspScModCb( void* arg, unsigned varSymId, double value )
@ -1102,6 +1171,8 @@ cmDspInst_t* _cmDspScModAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned
cmDspVarArg_t args[] = cmDspVarArg_t args[] =
{ {
{ "index", kScLocIdxMdId, 0,0, kInDsvFl | kUIntDsvFl, "Score follower index input."}, { "index", kScLocIdxMdId, 0,0, kInDsvFl | kUIntDsvFl, "Score follower index input."},
{ "reset", kResetIdxMdId, 0,0, kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "Reset the modulator and go to the score index."},
{ "cmd", kCmdMdId, 0,0, kInDsvFl | kSymDsvFl | kOptArgDsvFl, "on | off."},
{ NULL, 0, 0, 0, 0 } { NULL, 0, 0, 0, 0 }
}; };
@ -1116,6 +1187,8 @@ cmDspInst_t* _cmDspScModAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned
const cmChar_t* fn = va_arg(vl1,const cmChar_t*); const cmChar_t* fn = va_arg(vl1,const cmChar_t*);
const cmChar_t* modLabel = va_arg(vl1,const cmChar_t*); const cmChar_t* modLabel = va_arg(vl1,const cmChar_t*);
va_end(vl1);
// validate the file // validate the file
if( fn==NULL || cmFsIsFile(fn)==false ) if( fn==NULL || cmFsIsFile(fn)==false )
{ {
@ -1131,8 +1204,8 @@ cmDspInst_t* _cmDspScModAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned
cmDspClassErr(ctx,classPtr,kInvalidArgDspRC,"The internal modulator object initialization failed."); cmDspClassErr(ctx,classPtr,kInvalidArgDspRC,"The internal modulator object initialization failed.");
return NULL; return NULL;
} }
unsigned fixArgCnt = 1; unsigned fixArgCnt = sizeof(args)/sizeof(args[0]) - 1;
unsigned argCnt = fixArgCnt + cmScModulatorVarCount(mp); unsigned argCnt = fixArgCnt + cmScModulatorOutVarCount(mp);
cmDspVarArg_t a[ argCnt+1 ]; cmDspVarArg_t a[ argCnt+1 ];
unsigned i; unsigned i;
@ -1141,7 +1214,7 @@ cmDspInst_t* _cmDspScModAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned
for(i=fixArgCnt; i<argCnt; ++i) for(i=fixArgCnt; i<argCnt; ++i)
{ {
unsigned varIdx = i - fixArgCnt; unsigned varIdx = i - fixArgCnt;
const cmScModVar_t* vp = cmScModulatorVar(mp,varIdx); const cmScModVar_t* vp = cmScModulatorOutVar(mp,varIdx);
const cmChar_t* label = cmSymTblLabel( ctx->stH, vp->varSymId ); const cmChar_t* label = cmSymTblLabel( ctx->stH, vp->varSymId );
const cmChar_t* docStr = cmTsPrintfS("Variable output for %s",label); const cmChar_t* docStr = cmTsPrintfS("Variable output for %s",label);
@ -1149,13 +1222,21 @@ cmDspInst_t* _cmDspScModAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned
} }
cmDspArgSetupNull(a+argCnt); // set terminating arg. flags cmDspArgSetupNull(a+argCnt); // set terminating arg. flags
cmDspScMod_t* p = cmDspInstAlloc(cmDspScMod_t,ctx,classPtr,a,instSymId,id,storeSymId,0,vl); cmDspScMod_t* p = cmDspInstAlloc(cmDspScMod_t,ctx,classPtr,a,instSymId,id,storeSymId,va_cnt,vl);
p->fn = cmMemAllocStr(fn);
p->modLabel = cmMemAllocStr(modLabel);
p->mp = mp; p->mp = mp;
p->onSymId = cmSymTblId(ctx->stH,"on");
p->offSymId = cmSymTblId(ctx->stH,"off");
mp->cbArg = p; // set the modulator callback arg mp->cbArg = p; // set the modulator callback arg
cmDspSetDefaultUInt(ctx,&p->inst,kScLocIdxMdId,0,0);
cmDspSetDefaultUInt(ctx,&p->inst,kScLocIdxMdId,0,0);
cmDspSetDefaultSymbol(ctx,&p->inst,kCmdMdId,p->offSymId);
return &p->inst; return &p->inst;
} }
@ -1164,9 +1245,12 @@ cmDspRC_t _cmDspScModFree(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t*
cmDspRC_t rc = kOkDspRC; cmDspRC_t rc = kOkDspRC;
cmDspScMod_t* p = (cmDspScMod_t*)inst; cmDspScMod_t* p = (cmDspScMod_t*)inst;
if( cmScModulatorFree(&p->mp) != kOkTlRC ) if( cmScModulatorFree(&p->mp) != kOkTlRC )
return cmErrMsg(&inst->classPtr->err, kInstFinalFailDspRC, "Modulator release failed."); return cmErrMsg(&inst->classPtr->err, kInstFinalFailDspRC, "Modulator release failed.");
cmMemFree(p->fn);
cmMemFree(p->modLabel);
return rc; return rc;
} }
@ -1182,9 +1266,26 @@ cmDspRC_t _cmDspScModReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t*
cmDspRC_t _cmDspScModRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt ) cmDspRC_t _cmDspScModRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
{ {
cmDspScMod_t* p = (cmDspScMod_t*)inst;
cmDspSetEvent(ctx,inst,evt); cmDspSetEvent(ctx,inst,evt);
switch( evt->dstVarId )
{
case kResetIdxMdId:
cmDspSetUInt(ctx,inst,kScLocIdxMdId,cmDspUInt(inst,kResetIdxMdId));
break;
case kCmdMdId:
{
unsigned symId = cmDspSymbol(inst,kCmdMdId);
if( symId == p->onSymId )
cmScModulatorReset(p->mp, ctx->cmCtx, cmDspUInt(inst,kScLocIdxMdId));
}
break;
}
return kOkDspRC; return kOkDspRC;
} }
@ -1193,8 +1294,12 @@ cmDspRC_t _cmDspScModExec(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t*
cmDspRC_t rc = kOkDspRC; cmDspRC_t rc = kOkDspRC;
cmDspScMod_t* p = (cmDspScMod_t*)inst; cmDspScMod_t* p = (cmDspScMod_t*)inst;
if( cmDspSymbol(inst,kCmdMdId) != p->offSymId )
{
p->tmp_ctx = ctx; p->tmp_ctx = ctx;
cmScModulatorExec(p->mp,cmDspUInt(inst,kScLocIdxMdId)); cmScModulatorExec(p->mp,cmDspUInt(inst,kScLocIdxMdId));
}
return rc; return rc;
} }
@ -1212,3 +1317,201 @@ struct cmDspClass_str* cmScModClassCons( cmDspCtx_t* ctx )
return &_cmModulatorDC; return &_cmModulatorDC;
} }
//==========================================================================================================================================
enum
{
kInChCntGsId,
kOutGroupCntGsId,
kGroupSelIdxGsId,
kBaseInFloatGsId
};
cmDspClass_t _cmGSwitchDC;
typedef struct
{
cmDspInst_t inst;
unsigned iChCnt;
unsigned oGroupCnt;
unsigned baseInFloatGsId;
unsigned baseInSymGsId;
unsigned baseInBoolGsId;
unsigned baseOutFloatGsId;
unsigned baseOutSymGsId;
unsigned baseOutBoolGsId;
} cmDspGSwitch_t;
cmDspInst_t* _cmDspGSwitchAlloc(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);
cmDspVarArg_t args[] =
{
{ "ichs", kInChCntGsId, 0,0, kUIntDsvFl | kReqArgDsvFl, "Input channel count."},
{ "ochs", kOutGroupCntGsId, 0,0, kUIntDsvFl | kReqArgDsvFl, "Output group count."},
{ "sel", kGroupSelIdxGsId, 0,0, kInDsvFl | kUIntDsvFl, "Group select index."},
{ NULL, 0, 0, 0, 0 }
};
// validate the argument count
if( va_cnt != 2 )
{
cmDspClassErr(ctx,classPtr,kInvalidArgDspRC,"The GSwitch requires at least two arguments.");
return NULL;
}
// read the input ch and output group count
unsigned iChCnt = va_arg(vl1,unsigned);
unsigned oGroupCnt = va_arg(vl1,unsigned);
va_end(vl1);
// validate the channel counts
if( iChCnt == 0 || oGroupCnt==0 )
{
cmDspClassErr(ctx,classPtr,kInvalidArgDspRC,"The GSwitch input channel count and group count must be greater than zero.");
return NULL;
}
unsigned typeCnt = 3; // i.e. float,sym,bool
unsigned baseInFloatGsId = kBaseInFloatGsId;
unsigned baseInSymGsId = baseInFloatGsId + iChCnt;
unsigned baseInBoolGsId = baseInSymGsId + iChCnt;
unsigned baseOutFloatGsId = baseInBoolGsId + iChCnt;
unsigned baseOutSymGsId = baseOutFloatGsId + (iChCnt * oGroupCnt);
unsigned baseOutBoolGsId = baseOutSymGsId + (iChCnt * oGroupCnt);
unsigned fixArgCnt = 3;
unsigned varArgCnt = (iChCnt * typeCnt) + (iChCnt * typeCnt * oGroupCnt);
unsigned argCnt = fixArgCnt + varArgCnt;
cmDspVarArg_t a[ argCnt+1 ];
unsigned i;
cmDspArgCopy( a, argCnt, 0, args, fixArgCnt );
cmDspArgSetupN( ctx, a, argCnt, baseInFloatGsId, iChCnt, "f-in", baseInFloatGsId, 0, 0, kInDsvFl | kDoubleDsvFl, "Float input");
cmDspArgSetupN( ctx, a, argCnt, baseInSymGsId, iChCnt, "s-in", baseInSymGsId, 0, 0, kInDsvFl | kSymDsvFl, "Symbol input");
cmDspArgSetupN( ctx, a, argCnt, baseInBoolGsId, iChCnt, "b-in", baseInBoolGsId, 0, 0, kInDsvFl | kBoolDsvFl, "Bool input");
unsigned labelCharCnt = 63;
cmChar_t label[labelCharCnt+1];
label[labelCharCnt] = 0;
unsigned gsid = baseOutFloatGsId;
for(i=0; i<oGroupCnt; ++i, gsid+=iChCnt)
{
snprintf(label,labelCharCnt,"f-out-%i",i);
cmDspArgSetupN( ctx, a, argCnt, gsid, iChCnt, label, gsid, 0, 0, kInDsvFl | kDoubleDsvFl, "Float output");
}
gsid = baseOutSymGsId;
for(i=0; i<oGroupCnt; ++i, gsid+=iChCnt)
{
snprintf(label,labelCharCnt,"s-out-%i",i);
cmDspArgSetupN( ctx, a, argCnt, gsid, iChCnt, label, gsid, 0, 0, kInDsvFl | kSymDsvFl, "Symbol output");
}
gsid = baseOutBoolGsId;
for(i=0; i<oGroupCnt; ++i, gsid+=iChCnt)
{
snprintf(label,labelCharCnt,"b-out-%i",i);
cmDspArgSetupN( ctx,a, argCnt, gsid, iChCnt, label, gsid, 0, 0, kInDsvFl | kBoolDsvFl, "Bool output");
}
cmDspArgSetupNull(a+argCnt); // set terminating arg. flags
cmDspGSwitch_t* p = cmDspInstAlloc(cmDspGSwitch_t,ctx,classPtr,a,instSymId,id,storeSymId,va_cnt,vl);
p->iChCnt = iChCnt;
p->oGroupCnt = oGroupCnt;
p->baseInFloatGsId = baseInFloatGsId;
p->baseInSymGsId = baseInSymGsId;
p->baseInBoolGsId = baseInBoolGsId;
p->baseOutFloatGsId = baseOutFloatGsId;
p->baseOutSymGsId = baseOutSymGsId;
p->baseOutBoolGsId = baseOutBoolGsId;
cmDspSetDefaultUInt(ctx,&p->inst,kGroupSelIdxGsId,0,0);
return &p->inst;
}
cmDspRC_t _cmDspGSwitchReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
{
cmDspRC_t rc = kOkDspRC;
cmDspApplyAllDefaults(ctx,inst);
return rc;
}
cmDspRC_t _cmDspGSwitchRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
{
cmDspRC_t rc = kOkDspRC;
cmDspGSwitch_t* p = (cmDspGSwitch_t*)inst;
// if this is the group selector
if( evt->dstVarId == kGroupSelIdxGsId )
{
unsigned idx;
if( (idx = cmDsvGetUInt(evt->valuePtr)) > p->oGroupCnt )
cmDspInstErr(ctx,inst,kInvalidArgDspRC,"The GSwitch group select index %i is out of range %i.",idx,p->oGroupCnt);
else
cmDspSetEvent(ctx,inst,evt);
return rc;
}
// get the group selector
unsigned groupIdx = cmDspUInt(inst,kGroupSelIdxGsId);
assert( groupIdx < p->oGroupCnt);
// if this is a float input
if( p->baseInFloatGsId <= evt->dstVarId && evt->dstVarId < p->baseInFloatGsId + p->iChCnt )
{
unsigned outVarId = p->baseOutFloatGsId + (groupIdx * p->iChCnt) + (evt->dstVarId - p->baseInFloatGsId);
cmDspValueSet(ctx, inst, outVarId, evt->valuePtr, 0 );
return rc;
}
// if this is a symbol input
if( p->baseInSymGsId <= evt->dstVarId && evt->dstVarId < p->baseInSymGsId + p->iChCnt )
{
unsigned outVarId = p->baseOutSymGsId + (groupIdx * p->iChCnt) + (evt->dstVarId - p->baseInSymGsId);
cmDspValueSet(ctx, inst, outVarId, evt->valuePtr, 0 );
return rc;
}
// if this is a bool input
if( p->baseInBoolGsId <= evt->dstVarId && evt->dstVarId < p->baseInBoolGsId + p->iChCnt )
{
unsigned outVarId = p->baseOutBoolGsId + (groupIdx * p->iChCnt) + (evt->dstVarId - p->baseInBoolGsId);
cmDspValueSet(ctx, inst, outVarId, evt->valuePtr, 0 );
return rc;
}
return rc;
}
struct cmDspClass_str* cmGSwitchClassCons( cmDspCtx_t* ctx )
{
cmDspClassSetup(&_cmGSwitchDC,ctx,"GSwitch",
NULL,
_cmDspGSwitchAlloc,
NULL,
_cmDspGSwitchReset,
NULL,
_cmDspGSwitchRecv,
NULL,NULL,
"Ganged switch.");
return &_cmGSwitchDC;
}

View File

@ -69,6 +69,9 @@ cmDspRC_t _cmDspSysPgm_TimeLine(cmDspSysH_t h, void** userPtrPtr )
unsigned wtSmpCnt = floor(cmDspSysSampleRate(h)); // wt length == srate unsigned wtSmpCnt = floor(cmDspSysSampleRate(h)); // wt length == srate
int krWndSmpCnt = 2048; int krWndSmpCnt = 2048;
int krHopFact = 4; int krHopFact = 4;
unsigned xfadOutChCnt = 2;
double xfadMs = 200;
bool xfadAllOnFl = true;
memset(&r,0,sizeof(r)); memset(&r,0,sizeof(r));
cmErrSetup(&err,&cmCtx->rpt,"Kr Timeline"); cmErrSetup(&err,&cmCtx->rpt,"Kr Timeline");
@ -83,11 +86,15 @@ cmDspRC_t _cmDspSysPgm_TimeLine(cmDspSysH_t h, void** userPtrPtr )
cmDspInst_t* pts = cmDspSysAllocInst(h,"PortToSym", NULL, 2, "on", "off" ); cmDspInst_t* pts = cmDspSysAllocInst(h,"PortToSym", NULL, 2, "on", "off" );
cmDspInst_t* mfp = cmDspSysAllocInst(h,"MidiFilePlay",NULL, 0 ); cmDspInst_t* mfp = cmDspSysAllocInst(h,"MidiFilePlay",NULL, 0 );
cmDspInst_t* sfp = cmDspSysAllocInst(h,"ScFol", NULL, 1, r.scFn ); cmDspInst_t* sfp = cmDspSysAllocInst(h,"ScFol", NULL, 1, r.scFn );
cmDspInst_t* modp = cmDspSysAllocInst(h,"ScMod", NULL, 2, r.modFn, "m1" );
cmDspInst_t* kr0p = cmDspSysAllocInst(h,"Kr", NULL, 2, krWndSmpCnt, krHopFact ); cmDspInst_t* kr0p = cmDspSysAllocInst(h,"Kr", NULL, 2, krWndSmpCnt, krHopFact );
cmDspInst_t* kr1p = cmDspSysAllocInst(h,"Kr", NULL, 2, krWndSmpCnt, krHopFact ); cmDspInst_t* kr1p = cmDspSysAllocInst(h,"Kr", NULL, 2, krWndSmpCnt, krHopFact );
cmDspInst_t* xfad = cmDspSysAllocInst(h,"Xfader", NULL, 3, xfadOutChCnt, xfadMs, xfadAllOnFl );
cmDspInst_t* ao0p = cmDspSysAllocInst(h,"AudioOut", NULL, 1, 0 ); cmDspInst_t* ao0p = cmDspSysAllocInst(h,"AudioOut", NULL, 1, 0 );
cmDspInst_t* ao1p = cmDspSysAllocInst(h,"AudioOut", NULL, 1, 1 ); cmDspInst_t* ao1p = cmDspSysAllocInst(h,"AudioOut", NULL, 1, 1 );
//cmDspInst_t* af0p = cmDspSysAllocInst(h,"AudioFileOut",NULL, 2, "/home/kevin/temp/debug0.wav",1);
cmDspSysNewPage(h,"Controls"); cmDspSysNewPage(h,"Controls");
cmDspInst_t* onb = cmDspSysAllocInst(h,"Button", "start", 2, kButtonDuiId, 1.0 ); cmDspInst_t* onb = cmDspSysAllocInst(h,"Button", "start", 2, kButtonDuiId, 1.0 );
@ -109,6 +116,7 @@ cmDspRC_t _cmDspSysPgm_TimeLine(cmDspSysH_t h, void** userPtrPtr )
cmDspInst_t* ls0p = cmDspSysAllocInst(h,"Scalar", "lwr slope", 5, kNumberDuiId, 0.3, 10.0, 0.01, 2.0 ); cmDspInst_t* ls0p = cmDspSysAllocInst(h,"Scalar", "lwr slope", 5, kNumberDuiId, 0.3, 10.0, 0.01, 2.0 );
cmDspInst_t* of0p = cmDspSysAllocInst(h,"Scalar", "offset", 5, kNumberDuiId, 0.0, 100.0, 0.01, 30.0 ); cmDspInst_t* of0p = cmDspSysAllocInst(h,"Scalar", "offset", 5, kNumberDuiId, 0.0, 100.0, 0.01, 30.0 );
cmDspInst_t* iv0p = cmDspSysAllocInst(h,"Scalar", "invert", 5, kNumberDuiId, 0.0, 1.0, 1.0, 0.0 ); cmDspInst_t* iv0p = cmDspSysAllocInst(h,"Scalar", "invert", 5, kNumberDuiId, 0.0, 1.0, 1.0, 0.0 );
cmDspInst_t* wet0 = cmDspSysAllocInst(h,"Scalar", "wet", 5, kNumberDuiId, 0.0, 1.0,0.001, 1.0 );
cmDspSysNewColumn(h,0); cmDspSysNewColumn(h,0);
//cmDspInst_t* al1p = cmDspSysAllocInst(h,"MsgList","audFiles", 2, "audFiles",NULL); //cmDspInst_t* al1p = cmDspSysAllocInst(h,"MsgList","audFiles", 2, "audFiles",NULL);
@ -122,6 +130,11 @@ cmDspRC_t _cmDspSysPgm_TimeLine(cmDspSysH_t h, void** userPtrPtr )
cmDspInst_t* ls1p = cmDspSysAllocInst(h,"Scalar", "lwr slope1", 5, kNumberDuiId, 0.3, 10.0, 0.01, 2.0 ); cmDspInst_t* ls1p = cmDspSysAllocInst(h,"Scalar", "lwr slope1", 5, kNumberDuiId, 0.3, 10.0, 0.01, 2.0 );
cmDspInst_t* of1p = cmDspSysAllocInst(h,"Scalar", "offset1", 5, kNumberDuiId, 0.0, 100.0, 0.01, 30.0 ); cmDspInst_t* of1p = cmDspSysAllocInst(h,"Scalar", "offset1", 5, kNumberDuiId, 0.0, 100.0, 0.01, 30.0 );
cmDspInst_t* iv1p = cmDspSysAllocInst(h,"Scalar", "invert1", 5, kNumberDuiId, 0.0, 1.0, 1.0, 0.0 ); cmDspInst_t* iv1p = cmDspSysAllocInst(h,"Scalar", "invert1", 5, kNumberDuiId, 0.0, 1.0, 1.0, 0.0 );
cmDspInst_t* wet1 = cmDspSysAllocInst(h,"Scalar", "wet1", 5, kNumberDuiId, 0.0, 1.0,0.001, 1.0 );
cmDspSysNewColumn(h,0);
cmDspInst_t* ogain = cmDspSysAllocInst(h,"Scalar", "Out Gain", 5, kNumberDuiId, 0.0, 10.0,0.01, 3.0 );
//cmDspInst_t* reload = cmDspSysAllocInst(h,"Button", "Reload", 2, kButtonDuiId, 0.0 );
if((rc = cmDspSysLastRC(h)) != kOkDspRC ) if((rc = cmDspSysLastRC(h)) != kOkDspRC )
@ -129,13 +142,25 @@ cmDspRC_t _cmDspSysPgm_TimeLine(cmDspSysH_t h, void** userPtrPtr )
// phasor->wt->aout // phasor->wt->aout
cmDspSysConnectAudio(h, php, "out", wtp, "phs" ); // phs -> wt cmDspSysConnectAudio(h, php, "out", wtp, "phs" ); // phs -> wt
//cmDspSysConnectAudio(h, wtp, "out", kr0p, "in" ); // wt->kr
//cmDspSysConnectAudio(h, wtp, "out", kr1p, "in" ); if(1)
//cmDspSysConnectAudio(h, kr0p, "out", ao0p, "in"); // kr->aout- 0 {
//cmDspSysConnectAudio(h, kr1p, "out", ao1p, "in"); cmDspSysConnectAudio(h, wtp, "out", kr0p, "in" ); // wt->kr
cmDspSysConnectAudio(h, wtp, "out", kr1p, "in" );
cmDspSysConnectAudio(h, kr0p, "out", xfad, "in-0"); // kr->aout
cmDspSysConnectAudio(h, kr1p, "out", xfad, "in-1");
cmDspSysConnectAudio(h, xfad, "out-0", ao0p, "in"); // kr->aout
cmDspSysConnectAudio(h, xfad, "out-1", ao1p, "in");
}
else
{
cmDspSysConnectAudio(h, wtp, "out", ao0p, "in" ); // wt -> aout0 cmDspSysConnectAudio(h, wtp, "out", ao0p, "in" ); // wt -> aout0
cmDspSysConnectAudio(h, wtp, "out", ao1p, "in" ); // wt -> aout1 cmDspSysConnectAudio(h, wtp, "out", ao1p, "in" ); // wt -> aout1
//cmDspSysConnectAudio(h, wtp, "out", af0p, "in0" ); // wt -> audio file
}
// wave-table to time-line cursor
cmDspSysInstallCb( h, wtp, "fidx",tlp, "curs", NULL); cmDspSysInstallCb( h, wtp, "fidx",tlp, "curs", NULL);
// start connections // start connections
@ -144,6 +169,7 @@ cmDspRC_t _cmDspSysPgm_TimeLine(cmDspSysH_t h, void** userPtrPtr )
cmDspSysInstallCb(h, onb, "sym", mfp, "sel", NULL ); cmDspSysInstallCb(h, onb, "sym", mfp, "sel", NULL );
cmDspSysInstallCb(h, onb, "sym", pts, "on", NULL ); cmDspSysInstallCb(h, onb, "sym", pts, "on", NULL );
cmDspSysInstallCb(h, pts, "on", wtp, "cmd", NULL ); cmDspSysInstallCb(h, pts, "on", wtp, "cmd", NULL );
cmDspSysInstallCb(h, pts, "on", modp,"cmd", NULL );
// stop connections // stop connections
cmDspSysInstallCb(h, wtp, "done",offb,"in", NULL ); // 'done' from WT simulates pressing Stop btn. cmDspSysInstallCb(h, wtp, "done",offb,"in", NULL ); // 'done' from WT simulates pressing Stop btn.
@ -151,6 +177,7 @@ cmDspRC_t _cmDspSysPgm_TimeLine(cmDspSysH_t h, void** userPtrPtr )
cmDspSysInstallCb(h, offb, "sym", mfp, "sel", NULL ); cmDspSysInstallCb(h, offb, "sym", mfp, "sel", NULL );
cmDspSysInstallCb(h, offb, "sym", pts, "off", NULL ); cmDspSysInstallCb(h, offb, "sym", pts, "off", NULL );
cmDspSysInstallCb(h, pts, "off", wtp, "cmd", NULL ); cmDspSysInstallCb(h, pts, "off", wtp, "cmd", NULL );
cmDspSysInstallCb(h, pts, "off", modp,"cmd", NULL );
// time-line to wave-table selection // time-line to wave-table selection
cmDspSysInstallCb(h, tlp, "absi", wtp, "beg", NULL ); cmDspSysInstallCb(h, tlp, "absi", wtp, "beg", NULL );
@ -161,25 +188,32 @@ cmDspRC_t _cmDspSysPgm_TimeLine(cmDspSysH_t h, void** userPtrPtr )
cmDspSysInstallCb(h, tlp, "mbsi", mfp, "bsi", NULL ); cmDspSysInstallCb(h, tlp, "mbsi", mfp, "bsi", NULL );
cmDspSysInstallCb(h, tlp, "mesi", mfp, "esi", NULL ); cmDspSysInstallCb(h, tlp, "mesi", mfp, "esi", NULL );
cmDspSysInstallCb(h, tlp, "mfn", mfp, "fn", NULL ); cmDspSysInstallCb(h, tlp, "mfn", mfp, "fn", NULL );
// score to score follower - to set initial search location // score to score follower - to set initial search location
cmDspSysInstallCb(h, scp, "sel", sfp, "index", NULL ); cmDspSysInstallCb(h, scp, "sel", sfp, "index", NULL );
//cmDspSysInstallCb(h, scp, "sel", prv, "in", NULL );
cmDspSysInstallCb(h, scp, "sel", modp,"reset", NULL );
//cmDspSysInstallCb(h, reload,"out", modp, "reload", NULL );
// MIDI file player to score-follower and score - the order of connections is the same // MIDI file play er to score follower
// as the msg transmision order from MFP if(1)
//cmDspSysInstallCb(h, mfp, "smpidx", scp, "smpidx", NULL ); {
cmDspSysInstallCb(h, mfp, "smpidx", sfp, "smpidx", NULL ); cmDspSysInstallCb(h, mfp, "smpidx", sfp, "smpidx", NULL );
//cmDspSysInstallCb(h, mfp, "d1", scp, "d1", NULL );
cmDspSysInstallCb(h, mfp, "d1", sfp, "d1", NULL ); cmDspSysInstallCb(h, mfp, "d1", sfp, "d1", NULL );
//cmDspSysInstallCb(h, mfp, "d0", scp, "d0", NULL );
cmDspSysInstallCb(h, mfp, "d0", sfp, "d0", NULL ); cmDspSysInstallCb(h, mfp, "d0", sfp, "d0", NULL );
//cmDspSysInstallCb(h, mfp, "status", scp, "status", NULL );
cmDspSysInstallCb(h, mfp, "status", sfp, "status", NULL ); cmDspSysInstallCb(h, mfp, "status", sfp, "status", NULL );
}
// score follower to modulator and printers
cmDspSysInstallCb(h, sfp, "out", modp, "index", NULL );
cmDspSysInstallCb(h, sfp, "out", prp, "in", NULL );
cmDspSysInstallCb(h, sfp, "even", pre, "in", NULL );
cmDspSysInstallCb(h, sfp, "dyn", prd, "in", NULL );
cmDspSysInstallCb(h, sfp, "tempo",prt, "in", NULL );
// score follower to score cmDspSysInstallCb(h, prtb, "sym", sfp, "cmd", NULL );
//cmDspSysInstallCb(h, sfp, "out", modp, "index", NULL ); cmDspSysInstallCb(h, qtb, "sym", sfp, "cmd", NULL );
cmDspSysInstallCb(h, ws0p, "out", kr0p, "wndn", NULL ); // wndSmpCnt->kr cmDspSysInstallCb(h, ws0p, "out", kr0p, "wndn", NULL ); // wndSmpCnt->kr
@ -190,6 +224,7 @@ cmDspRC_t _cmDspSysPgm_TimeLine(cmDspSysH_t h, void** userPtrPtr )
cmDspSysInstallCb(h, us0p, "val", kr0p, "uprs", NULL ); // uprSlope->kr cmDspSysInstallCb(h, us0p, "val", kr0p, "uprs", NULL ); // uprSlope->kr
cmDspSysInstallCb(h, of0p, "val", kr0p, "offs", NULL ); // offset->kr cmDspSysInstallCb(h, of0p, "val", kr0p, "offs", NULL ); // offset->kr
cmDspSysInstallCb(h, iv0p, "val", kr0p, "invt", NULL ); // invert->kr cmDspSysInstallCb(h, iv0p, "val", kr0p, "invt", NULL ); // invert->kr
cmDspSysInstallCb(h, wet0, "val", kr0p, "wet", NULL ); // wet->kr
cmDspSysInstallCb(h, ws1p, "out", kr1p, "wndn", NULL ); // wndSmpCnt->kr cmDspSysInstallCb(h, ws1p, "out", kr1p, "wndn", NULL ); // wndSmpCnt->kr
cmDspSysInstallCb(h, hf1p, "out", kr1p, "hopf", NULL ); // hopFact->kr cmDspSysInstallCb(h, hf1p, "out", kr1p, "hopf", NULL ); // hopFact->kr
@ -199,23 +234,134 @@ cmDspRC_t _cmDspSysPgm_TimeLine(cmDspSysH_t h, void** userPtrPtr )
cmDspSysInstallCb(h, us1p, "val", kr1p, "uprs", NULL ); // uprSlope->kr cmDspSysInstallCb(h, us1p, "val", kr1p, "uprs", NULL ); // uprSlope->kr
cmDspSysInstallCb(h, of1p, "val", kr1p, "offs", NULL ); // offset->kr cmDspSysInstallCb(h, of1p, "val", kr1p, "offs", NULL ); // offset->kr
cmDspSysInstallCb(h, iv1p, "val", kr1p, "invt", NULL ); // invert->kr cmDspSysInstallCb(h, iv1p, "val", kr1p, "invt", NULL ); // invert->kr
cmDspSysInstallCb(h, wet1, "val", kr1p, "wet", NULL ); // wet->kr
cmDspSysInstallCb(h, ogain, "val", ao0p, "gain", NULL ); // output gain control
cmDspSysInstallCb(h, ogain, "val", ao1p, "gain", NULL );
// Printer connections // Printer connections
cmDspSysInstallCb(h, tlp, "afn", prp, "in", NULL ); cmDspSysInstallCb(h, tlp, "afn", prp, "in", NULL );
cmDspSysInstallCb(h, tlp, "mfn", prp, "in", NULL ); cmDspSysInstallCb(h, tlp, "mfn", prp, "in", NULL );
cmDspSysInstallCb(h, tlp, "sel", prp, "in", NULL ); cmDspSysInstallCb(h, tlp, "sel", prp, "in", NULL );
cmDspSysInstallCb(h, sfp, "out", prp, "in", NULL );
cmDspSysInstallCb(h, sfp, "even", pre, "in", NULL ); cmDspSysInstallCb(h, modp, "mod0", md0p, "val", NULL );
cmDspSysInstallCb(h, sfp, "dyn", prd, "in", NULL ); cmDspSysInstallCb(h, modp, "win0", kr0p, "wndn",NULL );
cmDspSysInstallCb(h, sfp, "tempo",prt, "in", NULL ); cmDspSysInstallCb(h, modp, "thr0", th0p, "val", NULL );
//cmDspSysInstallCb(h, modp,"v0", prv, "in", NULL ); cmDspSysInstallCb(h, modp, "upr0", us0p, "val", NULL );
//cmDspSysInstallCb(h, modp,"v1", prv, "in", NULL ); cmDspSysInstallCb(h, modp, "lwr0", ls0p, "val", NULL );
//cmDspSysInstallCb(h, modp,"v2", prv, "in", NULL ); cmDspSysInstallCb(h, modp, "off0", of0p, "val", NULL );
cmDspSysInstallCb(h, modp, "inv0", iv0p, "val", NULL );
cmDspSysInstallCb(h, modp, "wet0", wet0, "val", NULL );
cmDspSysInstallCb(h, modp, "xf0", xfad, "gate-0", NULL );
cmDspSysInstallCb(h, modp, "mod1", md1p, "val", NULL );
cmDspSysInstallCb(h, modp, "win1", kr1p, "wndn",NULL );
cmDspSysInstallCb(h, modp, "thr1", th1p, "val", NULL );
cmDspSysInstallCb(h, modp, "upr1", us1p, "val", NULL );
cmDspSysInstallCb(h, modp, "lwr1", ls1p, "val", NULL );
cmDspSysInstallCb(h, modp, "off1", of1p, "val", NULL );
cmDspSysInstallCb(h, modp, "inv1", iv1p, "val", NULL );
cmDspSysInstallCb(h, modp, "wet1", wet1, "val", NULL );
cmDspSysInstallCb(h, modp, "xf1", xfad, "gate-1", NULL );
cmDspSysInstallCb(h, prtb, "sym", sfp, "cmd", NULL );
cmDspSysInstallCb(h, qtb, "sym", sfp, "cmd", NULL );
return rc; return rc;
} }
cmDspRC_t _cmDspSysPgm_Switcher(cmDspSysH_t h, void** userPtrPtr )
{
cmDspRC_t rc = kOkDspRC;
const char* fn0 = "media/audio/20110723-Kriesberg/Audio Files/Piano 3_01.wav";
const cmChar_t* fn = cmFsMakeFn(cmFsUserDir(),fn0,NULL,NULL );
bool bypassFl = false;
double inGain = 1.0;
double dsrate = 96000.0;
double bits = 24.0;
bool rectifyFl = false;
bool fullRectFl = false;
double clipDb = -10.0;
double cfMinHz = 20.0;
double cfHz = 1000.0;
double cfAlpha = 0.9;
bool cfFbFl = true;
bool cfBypassFl = false;
unsigned outChCnt = 2;
double xfadeMs = 250;
cmDspInst_t* gsw = cmDspSysAllocInst(h,"GSwitch", NULL, 2, 12,2 );
cmDspInst_t* ofp = cmDspSysAllocInst(h,"Scalar", "Offset", 5, kNumberDuiId, 0.0, cmDspSysSampleRate(h)*600.0, 1.0, 6900000.0);
cmDspInst_t* fnp = cmDspSysAllocInst(h,"Fname", NULL, 3, false,"Audio Files (*.wav,*.aiff,*.aif)\tAudio Files (*.{wav,aiff,aif})",fn);
cmDspInst_t* php = cmDspSysAllocInst(h,"Phasor", NULL, 0 );
cmDspInst_t* wtp = cmDspSysAllocInst(h,"WaveTable",NULL, 2, ((int)cmDspSysSampleRate(h)), 1 );
cmDspInst_t* dst = cmDspSysAllocInst(h,"DistDs", NULL, 3, bypassFl, inGain, dsrate, bits );
cmDspInst_t* cf = cmDspSysAllocInst( h,"CombFilt", NULL, 5, cfBypassFl, cfMinHz, cfFbFl, cfMinHz, cfAlpha );
cmDspInst_t* xfad = cmDspSysAllocInst(h,"Xfader", NULL, 2, outChCnt, xfadeMs );
cmDspInst_t* ao0p = cmDspSysAllocInst(h,"AudioOut",NULL, 1, 0 );
cmDspInst_t* ao1p = cmDspSysAllocInst(h,"AudioOut",NULL, 1, 1 );
cmDspInst_t* ign = cmDspSysAllocScalar( h, "In Gain", 0.0, 10.0, 0.01, 1.0);
cmDspInst_t* rct = cmDspSysAllocCheck( h, "Rectify", rectifyFl);
cmDspInst_t* ful = cmDspSysAllocCheck( h, "Full/Half", fullRectFl);
cmDspInst_t* dsr = cmDspSysAllocScalar( h, "Srate", 0.0, 96000, 1.0, dsrate);
cmDspInst_t* dbt = cmDspSysAllocScalar( h, "bits", 2.0, 32.0, 1.0, bits);
cmDspInst_t* clip = cmDspSysAllocScalar( h, "Clip dB", -100.0, 0.0, 0.1, clipDb);
cmDspInst_t* ogn = cmDspSysAllocScalar( h, "Out Gain", 0.0, 10.0, 0.01, 1.0);
cmDspInst_t* cfhz = cmDspSysAllocScalar( h, "CF Hz", 25, 10000, 1, cfHz );
cmDspInst_t* cfalpha = cmDspSysAllocScalar( h, "CF Alpha", 0.0, 2.0, 0.001, cfAlpha);
cmDspInst_t* cfgain = cmDspSysAllocScalar( h, "CF Gain", 0.0, 20.0, 0.001, 1.0);
cmDspInst_t* cffb = cmDspSysAllocInst( h,"Button", "CF Fb", 2, kCheckDuiId, 0.0 );
cmDspInst_t* dfdb = cmDspSysAllocInst( h,"Button", "Dist Fade", 2, kCheckDuiId, 0.0 );
cmDspInst_t* cfdb = cmDspSysAllocInst( h,"Button", "CF Fade", 2, kCheckDuiId, 0.0 );
if((rc = cmDspSysLastRC(h)) != kOkDspRC )
return rc;
cmDspSysConnectAudio(h, php, "out", wtp, "phs" ); // phasor -> wave table
cmDspSysConnectAudio(h, wtp, "out", dst, "in" ); // wt -> dist
cmDspSysConnectAudio(h, dst, "out", xfad, "in-0"); // dist -> xfad
cmDspSysConnectAudio(h, xfad,"out-0",ao0p, "in" ); // xfad -> aout
cmDspSysConnectAudio(h, wtp, "out", cf, "in" ); // wt -> xfad
cmDspSysConnectAudio(h, cf, "out", xfad, "in-1"); // xfad -> cf
cmDspSysConnectAudio(h, xfad,"out-1",ao1p, "in" ); // cf -> aout
cmDspSysInstallCb(h, ofp, "val", wtp, "beg", NULL ); // offset -> wavetable
cmDspSysInstallCb(h, fnp, "out", wtp, "fn", NULL); // filename -> wavetable
// Distortion control connections
cmDspSysInstallCb(h, ign, "val", dst, "igain", NULL );
cmDspSysInstallCb(h, dsr, "val", dst, "srate", NULL );
cmDspSysInstallCb(h, dbt, "val", dst, "bits", NULL );
cmDspSysInstallCb(h, rct, "out", dst, "rect", NULL );
cmDspSysInstallCb(h, ful, "out", dst, "full", NULL );
cmDspSysInstallCb(h, clip, "val", dst, "clip", NULL );
cmDspSysInstallCb(h, ogn, "val", dst, "ogain", NULL );
cmDspSysInstallCb(h, cfhz, "val", cf, "hz", NULL );
cmDspSysInstallCb(h, cfalpha, "val", cf, "alpha", NULL );
cmDspSysInstallCb(h, cffb, "out", cf, "fb", NULL );
cmDspSysInstallCb(h, cfgain, "val", ao1p, "gain", NULL );
cmDspSysInstallCb(h, dfdb, "out", xfad, "gate-0", NULL);
cmDspSysInstallCb(h, cfdb, "out", xfad, "gate-1", NULL);
return cmDspSysLastRC(h);
}