cmProc.h/c: Added cmScModulator cmDspKr.h/c,cmDspPgmKr add cmScMod

This commit is contained in:
kevin 2013-02-08 23:48:54 -08:00
parent 9a65b1bbaa
commit 9b9e626287
6 changed files with 719 additions and 24 deletions

416
cmProc4.c
View File

@ -1442,6 +1442,7 @@ void _cmScMatchPathPop( cmScMatch* r )
r->p_cur = tp;
}
double _cmScMatchCalcCandidateCost( cmScMatch* r )
{
cmScMatchPath_t* cp = r->p_cur;
@ -1959,7 +1960,7 @@ cmRC_t cmScMatcherInit( cmScMatcher* p, double srate, cmScH_t scH, unsigned scW
p->cbFunc = cbFunc;
p->cbArg = cbArg;
p->mn = midiWndN;
p->midiBuf = cmMemResize(cmScMatchMidi_t,p->midiBuf,p->mn);
p->midiBuf = cmMemResizeZ(cmScMatchMidi_t,p->midiBuf,p->mn);
p->stepCnt = 3;
p->maxMissCnt = p->stepCnt+1;
p->rn = 2 * cmScoreEvtCount(scH);
@ -2552,8 +2553,8 @@ cmRC_t cmScMeasInit( cmScMeas* p, cmScH_t scH, double srate, const unsigned*
p->mn = 2 * cmScoreEvtCount(scH);
p->midiBuf = cmMemResizeZ(cmScMatchMidi_t,p->midiBuf,p->mn);
p->sn = cmScoreSetCount(scH);
p->set = cmMemResize(cmScMeasSet_t,p->set,p->sn);
p->dynRef = cmMemResize(unsigned,p->dynRef,dynRefCnt);
p->set = cmMemResizeZ(cmScMeasSet_t,p->set,p->sn);
p->dynRef = cmMemResizeZ(unsigned,p->dynRef,dynRefCnt);
p->dn = dynRefCnt;
p->srate = srate;
@ -2753,7 +2754,7 @@ unsigned _cmScMeasTimeAlign( cmScMeas* p, cmScMeasSet_t* sp, cmScMatchMidi_t* m,
assert(b[0].smpIdx != cmInvalidIdx && b[bn-1].smpIdx != cmInvalidIdx);
// calc avg. smpIdx and insert missing values
// calc avg. smpIdx, insert missing values, and convert b[].smpIdx to delta smp index
for(i=0,j=0; i<bn; ++i)
{
if( b[i].cnt > 1 )
@ -2820,7 +2821,7 @@ double _cmScMeasEven( cmScMeas* p, cmScMeasSet_t* sp, cmScMatchMidi_t* m, unsign
// calc std-dev of delta time
double d_sd = 0;
for(i=0; i<bn-1; ++i)
d_sd += (b[i].val-d_avg) * (b[i].val-d_avg);
d_sd += (b[i].val-d_avg) * (b[i].val-d_avg);
// if there is no deviation then we can't compute a z-score
// (this will happen if we fill in all the missing values based on 2 values)
@ -2832,7 +2833,7 @@ double _cmScMeasEven( cmScMeas* p, cmScMeasSet_t* sp, cmScMatchMidi_t* m, unsign
// calc avg. z-score
double z = 0;
for(i=0; i<bn-1; ++i)
z += fabs(b[i].val - d_avg)/d_sd;
z += fabs(b[i].val - d_avg)/d_sd;
double val = z / (bn-1);
@ -3063,6 +3064,7 @@ cmRC_t cmScMeasExec( cmScMeas* p, unsigned mni, unsigned locIdx, unsigned scEvtI
return cmCtxRtCondition( &p->obj, cmEofRC, "The MIDI buffer is full.");
int n_mii = cmInvalidIdx;
// locate the MIDI event assoc'd with 'mni' ...
if( p->mii>0 && mni <= p->midiBuf[p->mii-1].mni )
{
@ -3115,6 +3117,7 @@ cmRC_t cmScMeasExec( cmScMeas* p, unsigned mni, unsigned locIdx, unsigned scEvtI
}
p->vsi = p->nsi;
p->vsli = p->nsli;
// for each cmScore location between p->nsli and scLocIdx
for(; p->nsli<=scLocIdx && p->nsi < p->sn; ++p->nsli)
@ -3123,7 +3126,6 @@ cmRC_t cmScMeasExec( cmScMeas* p, unsigned mni, unsigned locIdx, unsigned scEvtI
// ahead of the next sets ending location.
while( cmMin(maxScLocIdx,p->set[p->nsi].esli+1) == p->nsli )
{
// calculate the value assoc'd with p->set[p->nsi]
_cmScMeasCalcVal(p, p->set + p->nsi, n_mii );
@ -3158,10 +3160,10 @@ cmRC_t cmScAlignScanToTimeLineEvent( cmScMatcher* p, cmTlH_t tlH, cmTlObj_t* top
switch( rc )
{
case cmOkRC: // continue processing MIDI events
case cmOkRC: // continue processing MIDI events
break;
case cmEofRC: // end of the score was encountered
case cmEofRC: // end of the score was encountered
break;
case cmInvalidArgRC: // p->eli was not set correctly
@ -3323,3 +3325,399 @@ void cmScAlignScanMarkers( cmRpt_t* rpt, cmTlH_t tlH, cmScH_t scH )
cmScMeasFree(&mp);
cmCtxFree(&ctx);
}
//=======================================================================================================================
cmScModulator* cmScModulatorAlloc( cmCtx* c, 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 )
{
cmScModulator* op = cmObjAlloc(cmScModulator,c,p);
if( ctx != NULL )
if( cmScModulatorInit(op,ctx,stH,srate,samplesPerCycle,fn,modLabel,cbFunc,cbArg) != cmOkRC )
cmScModulatorFree(&op);
return op;
}
cmRC_t cmScModulatorFree( cmScModulator** pp )
{
cmRC_t rc = cmOkRC;
if( pp==NULL || *pp==NULL )
return rc;
cmScModulator* p = *pp;
if((rc = cmScModulatorFinal(p)) != cmOkRC )
return rc;
cmMemFree(p->earray);
cmObjFree(pp);
return rc;
}
typedef struct
{
unsigned typeId;
unsigned minArgCnt;
const cmChar_t* label;
} _cmScModTypeMap_t;
_cmScModTypeMap_t _cmScModTypeArray[] =
{
{ kSetModTId, 1, "set" },
{ kLineModTId, 2, "line" },
{ kSetLineModTId, 3, "sline" },
{ kInvalidModTId, 0, "<invalid>"}
};
const _cmScModTypeMap_t* _cmScModTypeLabelToMap( const cmChar_t* label )
{
unsigned i;
for(i=0; _cmScModTypeArray[i].typeId!=kInvalidModTId; ++i)
if( strcmp(_cmScModTypeArray[i].label,label) == 0 )
return _cmScModTypeArray + i;
return NULL;
}
cmScModVar_t* _cmScModulatorInsertValue( cmScModulator* p, unsigned varSymId )
{
cmScModVar_t* vp = p->vlist;
for(; vp!=NULL; vp=vp->vlink)
if( varSymId == vp->varSymId )
return vp;
vp = cmMemAllocZ(cmScModVar_t,1);
vp->varSymId = varSymId;
vp->vlink = p->vlist;
p->vlist = vp;
return vp;
}
cmRC_t _cmScModulatorInsertEntry(cmScModulator* p, unsigned idx, unsigned scLocIdx, unsigned modSymId, unsigned varSymId, unsigned typeId, const double* av, unsigned an)
{
assert( idx < p->en );
if( p->modSymId != modSymId )
return cmOkRC;
p->earray[idx].scLocIdx = scLocIdx;
p->earray[idx].typeId = typeId;
p->earray[idx].parray = an==0 ? NULL : cmMemAllocZ(double,an);
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;
}
/*
{
[
{ loc:123, mod:modlabel, var:varlabel, param:[ ] }
]
}
*/
cmRC_t _cmScModulatorParse( cmScModulator* p, cmCtx_t* ctx, cmSymTblH_t stH, const cmChar_t* fn )
{
cmRC_t rc = cmOkRC;
cmJsonNode_t* jnp = NULL;
cmJsonH_t jsH = cmJsonNullHandle;
unsigned i;
// read the JSON file
if( cmJsonInitializeFromFile(&jsH, fn, ctx ) != kOkJsRC )
return cmCtxRtCondition( &p->obj, cmInvalidArgRC, "JSON file parse failed on the modulator file: %s.",cmStringNullGuard(fn) );
jnp = cmJsonRoot(jsH);
// validate that the first child as an array
if( jnp==NULL || ((jnp = cmJsonNodeMemberValue(jnp,"array")) == NULL) || cmJsonIsArray(jnp)==false )
{
rc = cmCtxRtCondition( &p->obj, cmInvalidArgRC, "Modulator file header syntax error in file:%s",cmStringNullGuard(fn) );
goto errLabel;
}
// allocate the entry array
p->en = cmJsonChildCount(jnp);
p->earray = cmMemResizeZ(cmScModEntry_t,p->earray,p->en);
for(i=0; i<p->en; ++i)
{
cmJsRC_t jsRC;
const char* errLabelPtr = NULL;
unsigned scLocIdx = cmInvalidIdx;
const cmChar_t* modLabel = NULL;
const cmChar_t* varLabel = NULL;
const cmChar_t* typeLabel = NULL;
cmJsonNode_t* onp = cmJsonArrayElement(jnp,i);
cmJsonNode_t* dnp = NULL;
const _cmScModTypeMap_t* map = NULL;
if((jsRC = cmJsonMemberValues( onp, &errLabelPtr,
"loc", kIntTId, &scLocIdx,
"mod", kStringTId, &modLabel,
"var", kStringTId, &varLabel,
"type",kStringTId, &typeLabel,
NULL )) != kOkJsRC )
{
if( errLabelPtr == NULL )
rc = cmCtxRtCondition( &p->obj, cmInvalidArgRC, "Error:%s on record at index %i in file:%s",errLabelPtr,i,cmStringNullGuard(fn) );
else
rc = cmCtxRtCondition( &p->obj, cmInvalidArgRC, "Synax error in Modulator record at index %i in file:%s",i,cmStringNullGuard(fn) );
goto errLabel;
}
// validate the entry type label
if((map = _cmScModTypeLabelToMap(typeLabel)) == NULL )
{
rc = cmCtxRtCondition( &p->obj, cmInvalidArgRC, "Unknown entry type '%s' in Modulator record at index %i in file:%s",cmStringNullGuard(typeLabel),i,cmStringNullGuard(fn) );
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 varSymId = cmSymTblRegisterSymbol(stH,varLabel);
// the data may be an array of doubles ....
if( cmJsonIsArray(dnp) )
{
unsigned an = cmJsonChildCount(dnp);
double av[an];
unsigned j;
// read each element in the data array
for(j=0; j<an; ++j)
if( cmJsonRealValue(cmJsonArrayElement(dnp,j), av+j ) != kOkJsRC )
{
rc = cmCtxRtCondition( &p->obj, cmInvalidArgRC, "Error parsing in Modulator 'data' record at index %i value index %i in file:%s",i,j,cmStringNullGuard(fn) );
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:
// release the JSON tree
if( cmJsonIsValid(jsH) )
cmJsonFinalize(&jsH);
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 rc;
if((rc = cmScModulatorFinal(p)) != cmOkRC )
return rc;
p->modSymId = cmSymTblRegisterSymbol(stH,modLabel);
p->cbFunc = cbFunc;
p->cbArg = cbArg;
p->samplesPerCycle = samplesPerCycle;
p->srate = srate;
if((rc = _cmScModulatorParse(p,ctx,stH,fn)) != cmOkRC )
goto errLabel;
errLabel:
if( rc != cmOkRC )
cmScModulatorFinal(p);
else
cmScModulatorReset(p,0);
return rc;
}
cmRC_t cmScModulatorFinal( cmScModulator* p )
{
unsigned i;
// release each value record
cmScModVar_t* vp = p->vlist;
while( vp!=NULL )
{
cmScModVar_t* np = vp->vlink;
cmMemFree(vp);
vp=np;
}
// release each entry record
for(i=0; i<p->en; ++i)
cmMemFree(p->earray[i].parray);
return cmOkRC;
}
unsigned cmScModulatorVarCount( cmScModulator* p )
{
unsigned n = 0;
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);
}
void _cmScModUnlink( cmScModulator* p, cmScModVar_t* vp, cmScModVar_t* pp )
{
if( pp == NULL )
p->alist = vp->alink;
else
pp->alink = vp->alink;
vp->flags = 0;
vp->alink = NULL;
vp->entry = NULL;
}
// Type specific variable activation
cmRC_t _cmScModActivate(cmScModulator* p, cmScModEntry_t* ep )
{
cmRC_t rc = cmOkRC;
cmScModVar_t* vp = ep->valPtr;
switch( ep->typeId )
{
case kSetModTId:
break;
case kLineModTId:
vp->v0 = vp->value;
vp->phase = 0;
break;
case kSetLineModTId:
vp->value = ep->parray[0];
vp->v0 = ep->parray[0];
vp->phase = 0;
ep->parray[0] = ep->parray[1];
ep->parray[1] = ep->parray[2];
break;
default:
{ assert(0); }
}
return rc;
}
// Return true if vp should be deactivated otherwise return false.
bool _cmScModExec( cmScModulator* p, cmScModVar_t* vp )
{
bool fl = false;
switch( vp->entry->typeId )
{
case kSetModTId:
p->cbFunc(p->cbArg,vp->varSymId,vp->entry->parray[0]);
fl = true;
break;
case kSetLineModTId:
case kLineModTId:
{
double v1 = vp->entry->parray[0];
double v = vp->value + (v1-vp->v0) * (vp->phase * p->samplesPerCycle) / (p->srate * vp->entry->parray[1]);
if((fl = (vp->value <= v1 && v >= v1) || (vp->value >= v1 && v <= v1 )) == true )
v = v1;
vp->phase += 1;
vp->value = v;
p->cbFunc(p->cbArg,vp->varSymId,v);
}
break;
default:
{ assert(0); }
}
return fl;
}
cmRC_t cmScModulatorExec( cmScModulator* p, unsigned scLocIdx )
{
cmRC_t trc;
cmRC_t rc = cmOkRC;
// 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)
{
cmScModEntry_t* ep = p->earray + p->nei;
// if the variable assoc'd with this entry is not on the active list ...
if( cmIsFlag(ep->valPtr->flags,kActiveModFl) == false )
{
// ... then push it onto the front of the active list ...
ep->valPtr->flags = kActiveModFl;
ep->valPtr->alink = p->alist;
p->alist = ep->valPtr;
}
// do type specific activation
if((trc = _cmScModActivate(p,ep)) != cmOkRC )
rc = trc;
ep->valPtr->entry = ep;
}
cmScModVar_t* pp = NULL;
cmScModVar_t* vp = p->alist;
for(; vp!=NULL; vp=vp->alink)
{
if( _cmScModExec(p,vp) )
_cmScModUnlink(p,vp,pp);
else
pp = vp;
}
return rc;
}

View File

@ -436,7 +436,7 @@ typedef struct
unsigned nsli; // next score location index
unsigned vsi; // set[vsi:nsi-1] indicates sets with new values following a call to cmScMeasExec()
unsigned vsli; // vsli:nsli-1 indicates cmScore loc's to check for section triggers following a call to cmScMeasExec()
} cmScMeas;
//
@ -448,7 +448,9 @@ typedef struct
// 2) dynRef][ is the gives the MIDI velocity range for each dynamics
// category: pppp-fff
//
// 3) See a cmDspKr.c _cmScFolMatcherCb() for an example of how
// cmScMeas.vsi and cmScMeas.vsli are used to act on the results of
// a call to cmMeasExec().
cmScMeas* cmScMeasAlloc( cmCtx* c, cmScMeas* p, cmScH_t scH, double srate, const unsigned* dynRefArray, unsigned dynRefCnt );
cmRC_t cmScMeasFree( cmScMeas** pp );
@ -475,6 +477,75 @@ unsigned cmScAlignScanToTimeLineEvent( cmScMatcher* p, cmTlH_t tlH, cmTlObj_t*
// notes in each marker region and the score.
void cmScAlignScanMarkers( cmRpt_t* rpt, cmTlH_t tlH, cmScH_t scH );
//=======================================================================================================================
enum
{
kInvalidModTId,
kSetModTId, // set variable to parray[0] at scLocIdx
kLineModTId, // linear ramp variable to parray[0] over parray[1] seconds
kSetLineModTId, // set variable to parray[0] and ramp to parray[1] over parray[2] seconds
};
enum
{
kActiveModFl = 0x01
};
struct cmScModEntry_str;
typedef struct cmScModVar_str
{
unsigned flags; // see kXXXModFl flags above.
unsigned varSymId; // variable name
double value; // current value
double v0; // reserved internal variable
unsigned phase; // cycle phase since activation
struct cmScModEntry_str* entry; // last entry assoc'd with this value
struct cmScModVar_str* vlink; // p->vlist link
struct cmScModVar_str* alink; // p->alist link
} cmScModVar_t;
typedef struct cmScModEntry_str
{
unsigned scLocIdx; // entry start time
unsigned typeId; // variable type
double* parray; // parray[pn] - parameter array
unsigned pn; // parameter count
cmScModVar_t* valPtr; // target variable
} cmScModEntry_t;
typedef void (*cmScModCb_t)( void* cbArg, unsigned varSymId, double value );
typedef struct
{
cmObj obj;
unsigned modSymId; // modulator name
cmScModCb_t cbFunc; // active value callback function
void* cbArg; // first arg to cbFunc()
unsigned samplesPerCycle; // interval in samples between calls to cmScModulatorExec()
double srate; // system sample rate
cmScModEntry_t* earray; // earray[en] - entry array sorted on ascending cmScModEntry_t.scLocIdx
unsigned en; // count
cmScModVar_t* vlist; // variable list
cmScModVar_t* alist; // active variable list
unsigned nei; // next entry index
} cmScModulator;
cmScModulator* cmScModulatorAlloc( cmCtx* c, 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 cmScModulatorFree( cmScModulator** pp );
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 cmScModulatorFinal( cmScModulator* p );
// Return count of variables.
unsigned cmScModulatorVarCount( cmScModulator* p );
// Return a pointer to the variable at vlist[idx].
cmScModVar_t* cmScModulatorVar( cmScModulator* p, unsigned idx );
cmRC_t cmScModulatorReset( cmScModulator* p, unsigned scLocIdx );
cmRC_t cmScModulatorExec( cmScModulator* p, unsigned scLocIdx );
#ifdef __cplusplus
}
#endif

View File

@ -5019,7 +5019,7 @@ cmDspClassConsFunc_t _cmDspClassBuiltInArray[] =
cmScoreClassCons,
cmMidiFilePlayClassCons,
cmScFolClassCons,
cmScModClassCons,
NULL,
};

View File

@ -11,6 +11,7 @@
#include "cmFile.h"
#include "cmSymTbl.h"
#include "cmJson.h"
#include "cmText.h"
#include "cmPrefs.h"
#include "cmDspValue.h"
#include "cmMsgProtocol.h"
@ -155,6 +156,10 @@ cmDspRC_t _cmDspKrExec(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt
const cmSample_t* ip = cmDspAudioBuf(ctx,inst,kAudioInKrId,iChIdx);
unsigned iSmpCnt = cmDspVarRows(inst,kAudioInKrId);
// if no connected
if( iSmpCnt == 0 )
return rc;
unsigned oChIdx = 0;
cmSample_t* op = cmDspAudioBuf(ctx,inst,kAudioOutKrId,oChIdx);
unsigned oSmpCnt = cmDspVarRows(inst,kAudioOutKrId);
@ -896,16 +901,20 @@ cmDspRC_t _cmDspScFolFree(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t*
return kOkDspRC;
}
// This is a callback function from cmScMatcherExec() which is called when
// this cmDspFol object receives a new score location index.
void _cmScFolMatcherCb( cmScMatcher* p, void* arg, cmScMatcherResult_t* rp )
{
cmDspScFolCbArg_t* ap = (cmDspScFolCbArg_t*)arg;
if( cmScMeasExec(ap->sfp->smp, rp->mni, rp->locIdx, rp->scEvtIdx, rp->flags, rp->smpIdx, rp->pitch, rp->vel ) == cmOkRC )
{
cmDspInst_t* inst = (cmDspInst_t*)ap->sfp;
cmDspInst_t* inst = &(ap->sfp->inst);
// send 'set' values that were calculated on the previous call to cmScMeasExec()
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 )
{
@ -925,6 +934,16 @@ void _cmScFolMatcherCb( cmScMatcher* p, void* arg, cmScMatcherResult_t* rp )
{ assert(0); }
}
}
/*
// trigger 'section' starts
for(i=ap->sfp->smp->vsli; i<ap->sfp->smp->nsli; ++i)
{
const cmScoreLoc_t* locPtr = cmScoreLoc(ap->sfp->smp->mp->scH,i);
if( locPtr->begSectPtr != NULL )
cmDspSetUInt(ap->ctx,inst,kSectIndexSfId,locPtr->begSectPtr->index);
}
*/
}
}
@ -1047,3 +1066,149 @@ struct cmDspClass_str* cmScFolClassCons( cmDspCtx_t* ctx )
return &_cmScFolDC;
}
//==========================================================================================================================================
enum
{
kScLocIdxMdId
};
cmDspClass_t _cmModulatorDC;
typedef struct
{
cmDspInst_t inst;
cmScModulator* mp;
cmDspCtx_t* tmp_ctx; // used to temporarily hold the current cmDspCtx during callback
} cmDspScMod_t;
void _cmDspScModCb( void* arg, unsigned varSymId, double value )
{
cmDspScMod_t* p = (cmDspScMod_t*)arg;
cmDspVar_t* varPtr;
if((varPtr = cmDspVarSymbolToPtr( p->tmp_ctx, &p->inst, varSymId, 0 )) == NULL )
return;
cmDspSetDouble(p->tmp_ctx,&p->inst,varPtr->constId,value);
}
cmDspInst_t* _cmDspScModAlloc(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[] =
{
{ "index", kScLocIdxMdId,0,0, kInDsvFl | kUIntDsvFl, "Score follower index input."},
{ NULL, 0, 0, 0, 0 }
};
// validate the argument count
if( va_cnt != 2 )
{
cmDspClassErr(ctx,classPtr,kInvalidArgDspRC,"The Modulator requires at least two arguments.");
return NULL;
}
// read the modulator file and label strings
const cmChar_t* fn = va_arg(vl1,const cmChar_t*);
const cmChar_t* modLabel = va_arg(vl1,const cmChar_t*);
// validate the file
if( fn==NULL || cmFsIsFile(fn)==false )
{
cmDspClassErr(ctx,classPtr,kInvalidArgDspRC,"The Modulator file '%s' is not valid.",cmStringNullGuard(fn));
return NULL;
}
// allocate the internal modulator object
cmScModulator* mp = cmScModulatorAlloc(ctx->cmProcCtx, NULL, ctx->cmCtx, ctx->stH, cmDspSampleRate(ctx), cmDspSamplesPerCycle(ctx), fn, modLabel, _cmDspScModCb, NULL );
if(mp == NULL )
{
cmDspClassErr(ctx,classPtr,kInvalidArgDspRC,"The internal modulator object initialization failed.");
return NULL;
}
unsigned fixArgCnt = 1;
unsigned argCnt = fixArgCnt + cmScModulatorVarCount(mp);
cmDspVarArg_t a[ argCnt+1 ];
unsigned i;
cmDspArgCopy( a, argCnt, 0, args, fixArgCnt );
for(i=fixArgCnt; i<argCnt; ++i)
{
unsigned varIdx = i - fixArgCnt;
const cmScModVar_t* vp = cmScModulatorVar(mp,varIdx);
const cmChar_t* label = cmSymTblLabel( ctx->stH, vp->varSymId );
const cmChar_t* docStr = cmTsPrintfS("Variable output for %s",label);
cmDspArgSetup(ctx, a + i, label, cmInvalidId, i, 0, 0, kOutDsvFl | kDoubleDsvFl, docStr );
}
cmDspArgSetupNull(a+argCnt); // set terminating arg. flags
cmDspScMod_t* p = cmDspInstAlloc(cmDspScMod_t,ctx,classPtr,a,instSymId,id,storeSymId,0,vl);
p->mp = mp;
mp->cbArg = p; // set the modulator callback arg
cmDspSetDefaultUInt(ctx,&p->inst,kScLocIdxMdId,0,0);
return &p->inst;
}
cmDspRC_t _cmDspScModFree(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
{
cmDspRC_t rc = kOkDspRC;
cmDspScMod_t* p = (cmDspScMod_t*)inst;
if( cmScModulatorFree(&p->mp) != kOkTlRC )
return cmErrMsg(&inst->classPtr->err, kInstFinalFailDspRC, "Modulator release failed.");
return rc;
}
cmDspRC_t _cmDspScModReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
{
cmDspRC_t rc = kOkDspRC;
cmDspApplyAllDefaults(ctx,inst);
return rc;
}
cmDspRC_t _cmDspScModRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
{
cmDspSetEvent(ctx,inst,evt);
return kOkDspRC;
}
cmDspRC_t _cmDspScModExec(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
{
cmDspRC_t rc = kOkDspRC;
cmDspScMod_t* p = (cmDspScMod_t*)inst;
p->tmp_ctx = ctx;
cmScModulatorExec(p->mp,cmDspUInt(inst,kScLocIdxMdId));
return rc;
}
struct cmDspClass_str* cmScModClassCons( cmDspCtx_t* ctx )
{
cmDspClassSetup(&_cmModulatorDC,ctx,"ScMod",
NULL,
_cmDspScModAlloc,
_cmDspScModFree,
_cmDspScModReset,
_cmDspScModExec,
_cmDspScModRecv,
NULL,NULL,
"Score Driven Variable Modulator.");
return &_cmModulatorDC;
}

View File

@ -10,6 +10,7 @@ extern "C" {
struct cmDspClass_str* cmScoreClassCons( cmDspCtx_t* ctx );
struct cmDspClass_str* cmMidiFilePlayClassCons( cmDspCtx_t* ctx );
struct cmDspClass_str* cmScFolClassCons( cmDspCtx_t* ctx );
struct cmDspClass_str* cmScModClassCons( cmDspCtx_t* ctx );
#ifdef __cplusplus
}

View File

@ -38,7 +38,7 @@ typedef struct
const cmChar_t* tlFn;
const cmChar_t* audPath;
const cmChar_t* scFn;
const cmChar_t* modFn;
} krRsrc_t;
cmDspRC_t krLoadRsrc(cmDspSysH_t h, cmErr_t* err, krRsrc_t* r)
@ -50,6 +50,7 @@ cmDspRC_t krLoadRsrc(cmDspSysH_t h, cmErr_t* err, krRsrc_t* r)
cmDspRsrcString(h,&r->tlFn, "timeLineFn", NULL);
cmDspRsrcString(h,&r->audPath,"tlAudioFilePath", NULL);
cmDspRsrcString(h,&r->scFn, "scoreFn", NULL);
cmDspRsrcString(h,&r->modFn, "modFn", NULL);
if((rc = cmDspSysLastRC(h)) != kOkDspRC )
cmErrMsg(err,rc,"A KR DSP resource load failed.");
@ -66,6 +67,8 @@ cmDspRC_t _cmDspSysPgm_TimeLine(cmDspSysH_t h, void** userPtrPtr )
unsigned wtLoopCnt = 1; // 1=play once (-1=loop forever)
unsigned wtInitMode = 0; // initial wt mode is 'silence'
unsigned wtSmpCnt = floor(cmDspSysSampleRate(h)); // wt length == srate
int krWndSmpCnt = 2048;
int krHopFact = 4;
memset(&r,0,sizeof(r));
cmErrSetup(&err,&cmCtx->rpt,"Kr Timeline");
@ -80,6 +83,9 @@ cmDspRC_t _cmDspSysPgm_TimeLine(cmDspSysH_t h, void** userPtrPtr )
cmDspInst_t* pts = cmDspSysAllocInst(h,"PortToSym", NULL, 2, "on", "off" );
cmDspInst_t* mfp = cmDspSysAllocInst(h,"MidiFilePlay",NULL, 0 );
cmDspInst_t* sfp = cmDspSysAllocInst(h,"ScFol", NULL, 1, r.scFn );
cmDspInst_t* kr0p = cmDspSysAllocInst(h,"Kr", NULL, 2, krWndSmpCnt, krHopFact );
cmDspInst_t* kr1p = cmDspSysAllocInst(h,"Kr", NULL, 2, krWndSmpCnt, krHopFact );
cmDspInst_t* ao0p = cmDspSysAllocInst(h,"AudioOut", NULL, 1, 0 );
cmDspInst_t* ao1p = cmDspSysAllocInst(h,"AudioOut", NULL, 1, 1 );
@ -89,14 +95,44 @@ cmDspRC_t _cmDspSysPgm_TimeLine(cmDspSysH_t h, void** userPtrPtr )
cmDspInst_t* prtb = cmDspSysAllocInst(h,"Button", "print", 2, kButtonDuiId, 1.0 );
cmDspInst_t* qtb = cmDspSysAllocInst(h,"Button", "quiet", 2, kButtonDuiId, 1.0 );
cmDspInst_t* prp = cmDspSysAllocInst(h,"Printer", NULL, 1, ">" );
//cmDspInst_t* prd = cmDspSysAllocInst(h,"Printer", NULL, 1, "DYN:" );
//cmDspInst_t* pre = cmDspSysAllocInst(h,"Printer", NULL, 1, "EVEN:" );
cmDspInst_t* prd = cmDspSysAllocInst(h,"Printer", NULL, 1, "DYN:" );
cmDspInst_t* pre = cmDspSysAllocInst(h,"Printer", NULL, 1, "EVEN:" );
cmDspInst_t* prt = cmDspSysAllocInst(h,"Printer", NULL, 1, "TEMPO:");
//cmDspInst_t* prv = cmDspSysAllocInst(h,"Printer", NULL, 1, "Value:");
cmDspSysNewColumn(h,0);
cmDspInst_t* md0p = cmDspSysAllocInst(h,"Scalar", "Mode", 5, kNumberDuiId, 0.0, 4.0, 1.0, 1.0);
cmDspInst_t* ws0p = cmDspSysAllocInst(h,"MsgList","wndSmpCnt", 3, "wndSmpCnt", NULL, 2);
cmDspInst_t* hf0p = cmDspSysAllocInst(h,"MsgList","hopFact", 3, "hopFact", NULL, 2);
cmDspInst_t* th0p = cmDspSysAllocInst(h,"Scalar", "threshold", 5, kNumberDuiId, 0.0, 100.0, 1.0, 60.0 );
cmDspInst_t* us0p = cmDspSysAllocInst(h,"Scalar", "upr slope", 5, kNumberDuiId, 0.0, 10.0, 0.01, 0.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* iv0p = cmDspSysAllocInst(h,"Scalar", "invert", 5, kNumberDuiId, 0.0, 1.0, 1.0, 0.0 );
cmDspSysNewColumn(h,0);
//cmDspInst_t* al1p = cmDspSysAllocInst(h,"MsgList","audFiles", 2, "audFiles",NULL);
//cmDspInst_t* fl1p = cmDspSysAllocInst(h,"MsgList","audFrags1", 2, "audFrags",NULL);
//cmDspInst_t* fn1p = cmDspSysAllocInst(h,"Sprintf","filename", 1, "%s/%s_%02i.wav");
cmDspInst_t* md1p = cmDspSysAllocInst(h,"Scalar", "Mode1", 5, kNumberDuiId, 0.0, 4.0, 1.0, 1.0);
cmDspInst_t* ws1p = cmDspSysAllocInst(h,"MsgList","wndSmpCnt1", 3, "wndSmpCnt", NULL, 2);
cmDspInst_t* hf1p = cmDspSysAllocInst(h,"MsgList","hopFact1", 3, "hopFact", NULL, 2);
cmDspInst_t* th1p = cmDspSysAllocInst(h,"Scalar", "threshold1", 5, kNumberDuiId, 0.0, 100.0, 1.0, 60.0 );
cmDspInst_t* us1p = cmDspSysAllocInst(h,"Scalar", "upr slope1", 5, kNumberDuiId, 0.0, 10.0, 0.01, 0.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* iv1p = cmDspSysAllocInst(h,"Scalar", "invert1", 5, kNumberDuiId, 0.0, 1.0, 1.0, 0.0 );
if((rc = cmDspSysLastRC(h)) != kOkDspRC )
return rc;
// phasor->wt->aout
cmDspSysConnectAudio(h, php, "out", wtp, "phs" ); // phs -> wt
//cmDspSysConnectAudio(h, wtp, "out", kr0p, "in" ); // wt->kr
//cmDspSysConnectAudio(h, wtp, "out", kr1p, "in" );
//cmDspSysConnectAudio(h, kr0p, "out", ao0p, "in"); // kr->aout- 0
//cmDspSysConnectAudio(h, kr1p, "out", ao1p, "in");
cmDspSysConnectAudio(h, wtp, "out", ao0p, "in" ); // wt -> aout0
cmDspSysConnectAudio(h, wtp, "out", ao1p, "in" ); // wt -> aout1
@ -132,27 +168,51 @@ cmDspRC_t _cmDspSysPgm_TimeLine(cmDspSysH_t h, void** userPtrPtr )
// MIDI file player to score-follower and score - the order of connections is the same
// as the msg transmision order from MFP
cmDspSysInstallCb(h, mfp, "smpidx", scp, "smpidx", NULL );
cmDspSysInstallCb(h, mfp, "d1", scp, "d1", NULL );
//cmDspSysInstallCb(h, mfp, "smpidx", scp, "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, "d0", scp, "d0", NULL );
//cmDspSysInstallCb(h, mfp, "d0", scp, "d0", NULL );
cmDspSysInstallCb(h, mfp, "d0", sfp, "d0", NULL );
cmDspSysInstallCb(h, mfp, "status", scp, "status", NULL );
//cmDspSysInstallCb(h, mfp, "status", scp, "status", NULL );
cmDspSysInstallCb(h, mfp, "status", sfp, "status", NULL );
// score follower to score
cmDspSysInstallCb(h, sfp, "out", scp, "loc", NULL );
//cmDspSysInstallCb(h, sfp, "out", modp, "index", NULL );
cmDspSysInstallCb(h, ws0p, "out", kr0p, "wndn", NULL ); // wndSmpCnt->kr
cmDspSysInstallCb(h, hf0p, "out", kr0p, "hopf", NULL ); // hopFact->kr
cmDspSysInstallCb(h, md0p, "val", kr0p, "mode", NULL ); // mode->kr
cmDspSysInstallCb(h, th0p, "val", kr0p, "thrh", NULL ); // thresh->kr
cmDspSysInstallCb(h, ls0p, "val", kr0p, "lwrs", NULL ); // lwrSlope->kr
cmDspSysInstallCb(h, us0p, "val", kr0p, "uprs", NULL ); // uprSlope->kr
cmDspSysInstallCb(h, of0p, "val", kr0p, "offs", NULL ); // offset->kr
cmDspSysInstallCb(h, iv0p, "val", kr0p, "invt", NULL ); // invert->kr
cmDspSysInstallCb(h, ws1p, "out", kr1p, "wndn", NULL ); // wndSmpCnt->kr
cmDspSysInstallCb(h, hf1p, "out", kr1p, "hopf", NULL ); // hopFact->kr
cmDspSysInstallCb(h, md1p, "val", kr1p, "mode", NULL ); // mode->kr
cmDspSysInstallCb(h, th1p, "val", kr1p, "thrh", NULL ); // thresh->kr
cmDspSysInstallCb(h, ls1p, "val", kr1p, "lwrs", NULL ); // lwrSlope->kr
cmDspSysInstallCb(h, us1p, "val", kr1p, "uprs", NULL ); // uprSlope->kr
cmDspSysInstallCb(h, of1p, "val", kr1p, "offs", NULL ); // offset->kr
cmDspSysInstallCb(h, iv1p, "val", kr1p, "invt", NULL ); // invert->kr
// Printer connections
cmDspSysInstallCb(h, tlp, "afn", prp, "in", NULL );
cmDspSysInstallCb(h, tlp, "mfn", prp, "in", NULL );
cmDspSysInstallCb(h, tlp, "sel", prp, "in", NULL );
cmDspSysInstallCb(h, sfp, "out", prp, "in", NULL );
//cmDspSysInstallCb(h, scp, "even", pre, "in", NULL );
//cmDspSysInstallCb(h, scp, "dyn", prd, "in", NULL );
cmDspSysInstallCb(h, sfp, "even", pre, "in", NULL );
cmDspSysInstallCb(h, sfp, "dyn", prd, "in", NULL );
cmDspSysInstallCb(h, sfp, "tempo",prt, "in", NULL );
//cmDspSysInstallCb(h, modp,"v0", prv, "in", NULL );
//cmDspSysInstallCb(h, modp,"v1", prv, "in", NULL );
//cmDspSysInstallCb(h, modp,"v2", prv, "in", NULL );
cmDspSysInstallCb(h, prtb, "sym", sfp, "cmd", NULL );
cmDspSysInstallCb(h, qtb, "sym", sfp, "cmd", NULL );