libcm is a C development framework with an emphasis on audio signal processing applications.
Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

cmDspClass.c 43KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432
  1. #include "cmPrefix.h"
  2. #include "cmGlobal.h"
  3. #include "cmFloatTypes.h"
  4. #include "cmRpt.h"
  5. #include "cmErr.h"
  6. #include "cmCtx.h"
  7. #include "cmMem.h"
  8. #include "cmMallocDebug.h"
  9. #include "cmLinkedHeap.h"
  10. #include "cmSymTbl.h"
  11. #include "cmPrefs.h"
  12. #include "cmJson.h"
  13. #include "cmDspValue.h"
  14. #include "cmMsgProtocol.h"
  15. #include "cmThread.h"
  16. #include "cmUdpPort.h"
  17. #include "cmUdpNet.h"
  18. #include "cmAudioSys.h"
  19. #include "cmProcObj.h"
  20. #include "cmDspCtx.h"
  21. #include "cmDspClass.h"
  22. #include "cmDspSys.h"
  23. cmDspRC_t cmDspClassSetup(
  24. cmDspClass_t* classPtr,
  25. cmDspCtx_t* ctx,
  26. const cmChar_t* classLabel,
  27. cmDspClassFunc_t finalClassFunc,
  28. cmDspConsFunc_t allocFunc,
  29. cmDspFunc_t freeFunc,
  30. cmDspFunc_t resetFunc,
  31. cmDspFunc_t execFunc,
  32. cmDspFunc_t recvFunc,
  33. cmDspStoreFunc_t storeFunc,
  34. cmDspAttrSymFunc_t sysRecvFunc,
  35. const cmChar_t* doc )
  36. {
  37. classPtr->labelStr = classLabel;
  38. classPtr->doc = doc;
  39. classPtr->finalClassFunc = finalClassFunc;
  40. classPtr->allocFunc = allocFunc;
  41. classPtr->freeFunc = freeFunc;
  42. classPtr->resetFunc = resetFunc;
  43. classPtr->execFunc = execFunc;
  44. classPtr->recvFunc = recvFunc;
  45. classPtr->storeFunc = storeFunc;
  46. classPtr->sysRecvFunc = sysRecvFunc;
  47. cmErrSetup( &classPtr->err, ctx->rpt, classLabel);
  48. return kOkDspRC;
  49. }
  50. // default DSP instance system recv function
  51. cmDspRC_t _cmDspInstSysRecvFunc( cmDspCtx_t* ctx, struct cmDspInst_str* inst, unsigned attrSymId, const cmDspValue_t* value )
  52. {
  53. if( cmDsvIsSymbol(value) )
  54. {
  55. unsigned msgSymId = cmDsvSymbol(value);
  56. if( msgSymId == ctx->_disableSymId )
  57. {
  58. inst->flags = cmSetFlag(inst->flags,kDisableExecInstFl );
  59. //printf("%s disabled\n",cmStringNullGuard(cmDspInstLabel(ctx,inst)));
  60. }
  61. else
  62. {
  63. if( msgSymId == ctx->_enableSymId )
  64. {
  65. inst->flags = cmClrFlag(inst->flags,kDisableExecInstFl );
  66. //printf("%s enabled\n",cmStringNullGuard(cmDspInstLabel(ctx,inst)));
  67. }
  68. }
  69. }
  70. if( inst->classPtr->sysRecvFunc != NULL )
  71. return inst->classPtr->sysRecvFunc(ctx,inst,attrSymId,value);
  72. return kOkDspRC;
  73. }
  74. void* cmDspInstAllocate(
  75. cmDspCtx_t* ctx,
  76. cmDspClass_t* classPtr,
  77. const cmDspVarArg_t* argV,
  78. unsigned instByteCnt,
  79. unsigned instSymId,
  80. unsigned instId,
  81. unsigned storeSymId,
  82. unsigned va_cnt,
  83. va_list vl )
  84. {
  85. unsigned i;
  86. unsigned varCnt = 0;
  87. unsigned varDataByteCnt = 0;
  88. unsigned va_idx = 0;
  89. unsigned reqArgCnt = 0;
  90. // check for duplicate variable names
  91. for(i=0; argV[i].label != NULL; ++i)
  92. if( argV[i].label != NULL )
  93. {
  94. unsigned j = 0;
  95. for(j=0; argV[j].label != NULL; ++j)
  96. if( i != j && argV[j].label != NULL && strcmp(argV[i].label,argV[j].label) == 0 )
  97. {
  98. // two variables have the same name
  99. unsigned mask = kInDsvFl | kOutDsvFl;
  100. // we allow two variables to have the same name as long as they are not both inputs or outputs
  101. if( (argV[j].flags & mask) == (argV[i].flags & mask))
  102. cmDspClassErr(ctx,classPtr,kVarDuplicateDspRC,"The variable label '%s' is used by multiple variables.",argV[i].label);
  103. }
  104. }
  105. // determine the count and size of the instance variables
  106. for(i=0; argV[i].label != NULL; ++i,++varCnt)
  107. {
  108. unsigned rn = argV[i].rn;
  109. unsigned flags = argV[i].flags;
  110. // audio buffer sample count is determined automatically
  111. if( cmAllFlags( argV[i].flags, kAudioBufDsvFl | kOutDsvFl ) )
  112. {
  113. rn = ctx->ctx->ss->args.dspFramesPerCycle;
  114. flags = kSampleDsvFl | kMtxDsvFl;
  115. }
  116. // determine the space needed for matrices of known size
  117. if( cmIsFlag(flags,kMtxDsvFl) && (rn*argV[i].cn) )
  118. {
  119. unsigned n = cmDsvByteCount( flags, rn, argV[i].cn );
  120. varDataByteCnt += n;
  121. }
  122. // determine the number of required arguments
  123. reqArgCnt += cmIsFlag(flags,kReqArgDsvFl) ? 1 : 0;
  124. }
  125. unsigned varRecdByteCnt = varCnt * sizeof(cmDspVar_t);
  126. unsigned ttlByteCnt = instByteCnt + varRecdByteCnt + varDataByteCnt;
  127. char* p = cmLHeapAllocZ(ctx->lhH, ttlByteCnt); // allocate the instance memory
  128. char* ep = p + ttlByteCnt; // record the end of the alloc'd memory
  129. cmDspInst_t* ip = (cmDspInst_t*)p; // set the instance ptr
  130. cmDspVar_t* varArray = (cmDspVar_t*)(p + instByteCnt); // set the instance variable recd array
  131. char* varDataPtr = (char*)(varArray + varCnt); // set the base of variable data buffer
  132. // setup the instance record
  133. ip->classPtr = classPtr;
  134. ip->symId = instSymId;
  135. ip->id = instId;
  136. ip->flags = kDisableExecInstFl;
  137. ip->presetGroupSymId = storeSymId;
  138. ip->varArray = varArray;
  139. ip->varCnt = varCnt;
  140. ip->freeFunc = classPtr->freeFunc;
  141. ip->resetFunc = classPtr->resetFunc;
  142. ip->execFunc = classPtr->execFunc;
  143. ip->recvFunc = classPtr->recvFunc;
  144. ip->storeFunc = classPtr->storeFunc;
  145. ip->sysRecvFunc = _cmDspInstSysRecvFunc;
  146. if( reqArgCnt > va_cnt )
  147. cmDspInstErr(ctx,ip,kVarArgParseFailDspRC,"The class requires %i arguments but only %i were given.",reqArgCnt,va_cnt);
  148. // setup the variable records
  149. for(i=0; i<varCnt; ++i)
  150. {
  151. unsigned flags = argV[i].flags;
  152. unsigned rn = argV[i].rn;
  153. // handle requests for audio output buffers
  154. if( cmAllFlags(argV[i].flags, kAudioBufDsvFl | kOutDsvFl ) )
  155. {
  156. // remove the audio buffer flag and reconstitute as a generic cmDspValue sample mtx type.
  157. //flags = cmClrFlag( argV[i].flags, kAudioBufDsvFl | kTypeDsvMask );
  158. flags = kSampleDsvFl | kMtxDsvFl;
  159. rn = ctx->ctx->ss->args.dspFramesPerCycle;
  160. }
  161. // the constId must be the same as the var index
  162. assert( i == argV[i].constId );
  163. bool reqArgFl = cmIsFlag(argV[i].flags,kReqArgDsvFl);
  164. bool optArgFl = cmIsFlag(argV[i].flags,kOptArgDsvFl);
  165. // verify that the required arg. exists
  166. if( reqArgFl && i>va_cnt )
  167. cmDspInstErr(ctx,ip,kVarArgParseFailDspRC,"The required argument '%s' is missing",argV[i].label);
  168. ip->varArray[i].flags = argV[i].flags; // store the original flag set as the var flags
  169. ip->varArray[i].constId = argV[i].constId;
  170. ip->varArray[i].symId = cmSymTblRegisterSymbol(ctx->stH,argV[i].label);
  171. ip->varArray[i].doc = argV[i].doc;
  172. ip->varArray[i].value.flags = argV[i].flags & kTypeDsvMask;
  173. // if this is a required or optional constructor arg. then assign it as the
  174. // default value for this variable
  175. if( va_idx < va_cnt && (reqArgFl || optArgFl) )
  176. {
  177. cmDspValue_t* vp = &ip->varArray[i].value;
  178. switch(ip->varArray[i].value.flags)
  179. {
  180. case kBoolDsvFl: cmDsvSetBool( vp, va_arg(vl,int )); break;
  181. case kCharDsvFl: cmDsvSetChar( vp, va_arg(vl,int )); break;
  182. case kUCharDsvFl: cmDsvSetUChar( vp, va_arg(vl,int )); break;
  183. case kShortDsvFl: cmDsvSetShort( vp, va_arg(vl,int )); break;
  184. case kUShortDsvFl: cmDsvSetUShort( vp, va_arg(vl,int )); break;
  185. case kLongDsvFl: cmDsvSetLong( vp, va_arg(vl,long )); break;
  186. case kULongDsvFl: cmDsvSetULong( vp, va_arg(vl,unsigned long )); break;
  187. case kIntDsvFl: cmDsvSetInt( vp, va_arg(vl,int )); break;
  188. case kUIntDsvFl: cmDsvSetUInt( vp, va_arg(vl,unsigned )); break;
  189. case kFloatDsvFl: cmDsvSetFloat( vp, va_arg(vl,double )); break;
  190. case kDoubleDsvFl: cmDsvSetDouble( vp, va_arg(vl,double )); break;
  191. case kSampleDsvFl: cmDsvSetSample( vp, va_arg(vl,double )); break;
  192. case kRealDsvFl: cmDsvSetReal( vp, va_arg(vl,double )); break;
  193. case kStrzDsvFl: cmDsvSetStrz( vp, va_arg(vl,cmChar_t* )); break;
  194. case kSymDsvFl: cmDsvSetSymbol( vp, va_arg(vl,unsigned )); break;
  195. default:
  196. cmDspInstErr(ctx,ip,kVarArgParseFailDspRC,"A var-args parse error occurred while parsing the variable '%s'.",argV[i].label);
  197. }
  198. // set the default value from the initial value
  199. cmDspValueSet(ctx, ip, i, vp, kSetDefaultDspFl );
  200. // store the fact that the default value was explicitely set.
  201. ip->varArray[i].flags = cmSetFlag(ip->varArray[i].flags,kDfltSetDsvFl);
  202. // track the number of va_list arg's read
  203. ++va_idx;
  204. }
  205. // assign memory to the matrix types of known size
  206. if( cmIsFlag(flags,kMtxDsvFl) && (rn*argV[i].cn) )
  207. {
  208. cmDsvSetMtx( &ip->varArray[i].value, flags, varDataPtr, rn, argV[i].cn );
  209. unsigned n = cmDsvByteCount( flags, rn, argV[i].cn );
  210. varDataPtr += n;
  211. }
  212. }
  213. assert( varDataPtr == ep );
  214. return p;
  215. }
  216. void _cmDspParseArgV( cmDspVarArg_t* a, va_list vl )
  217. {
  218. a->label = va_arg(vl,const char*);
  219. a->constId = va_arg(vl,unsigned);
  220. a->rn = va_arg(vl,unsigned);
  221. a->cn = va_arg(vl,unsigned);
  222. a->flags = va_arg(vl,unsigned);
  223. a->doc = va_arg(vl,const char*);
  224. }
  225. void* cmDspInstAllocateV(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned instByteCnt, unsigned instSymId, unsigned instId, unsigned storeSymId, unsigned va_cnt, va_list vl0, ... )
  226. {
  227. va_list vl1,vl2;
  228. va_start(vl1,vl0);
  229. va_copy(vl2,vl1);
  230. unsigned argCnt = 0;
  231. int repeatCnt;
  232. while( (repeatCnt = va_arg(vl1,int)) != 0 )
  233. {
  234. cmDspVarArg_t a;
  235. // do some value checking to possibly catch problems with the var_args format
  236. assert( repeatCnt > 0 && repeatCnt < 255 );
  237. argCnt += repeatCnt;
  238. _cmDspParseArgV(&a,vl1);
  239. }
  240. cmDspVarArg_t aa[ argCnt+1 ];
  241. unsigned j=0;
  242. while( (repeatCnt = va_arg(vl2,int)) != 0 )
  243. {
  244. cmDspVarArg_t a;
  245. _cmDspParseArgV(&a,vl2);
  246. cmDspArgSetupN(ctx,aa,argCnt,j,repeatCnt,a.label,a.constId,a.rn, a.cn, a.flags, a.doc );
  247. j += repeatCnt;
  248. }
  249. cmDspArgSetupNull(aa + argCnt);
  250. va_end(vl1);
  251. return cmDspInstAllocate(ctx,classPtr,aa,instByteCnt,instSymId,instId,storeSymId,va_cnt,vl0);
  252. }
  253. cmDspInstSymId_t* _cmDspInstFindAttrSymId( cmDspInst_t* inst, unsigned symId )
  254. {
  255. cmDspInstSymId_t* ip = inst->symIdList;
  256. for(; ip != NULL; ip=ip->link)
  257. if( ip->symId == symId )
  258. return ip;
  259. return NULL;
  260. }
  261. bool cmDspInstHasAttrSym( cmDspInst_t* inst, unsigned attrSymId )
  262. { return _cmDspInstFindAttrSymId(inst,attrSymId) != NULL; }
  263. cmDspRC_t cmDspInstRegisterAttrSym( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned symId )
  264. {
  265. cmDspInstSymId_t* ip;
  266. // if this symbol is already registered
  267. if((ip = _cmDspInstFindAttrSymId(inst,symId)) != NULL )
  268. return cmDspInstErr(ctx,inst,kOkDspRC,"The symbol '%s' is already registered with the instance.",cmStringNullGuard(cmSymTblLabel(ctx->stH,symId)));
  269. // try to find an unused symbol
  270. ip = inst->symIdList;
  271. for(; ip != NULL; ip=ip->link)
  272. if( ip->symId == cmInvalidId )
  273. break;
  274. // if no unused symbols were found then allocate a new one
  275. if( ip == NULL )
  276. {
  277. ip = cmLhAllocZ(ctx->lhH, cmDspInstSymId_t, 1 );
  278. ip->link = inst->symIdList;
  279. inst->symIdList = ip;
  280. }
  281. ip->symId = symId;
  282. return kOkDspRC;
  283. }
  284. cmDspRC_t cmDspInstRemoveAttrSym( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned symId )
  285. {
  286. cmDspInstSymId_t* ip;
  287. // if this symbol is already registered
  288. if((ip = _cmDspInstFindAttrSymId(inst,symId)) == NULL )
  289. return cmDspInstErr(ctx,inst,kOkDspRC,"The symbol '%s' is could not be found to be removed from the instance.",cmStringNullGuard(cmSymTblLabel(ctx->stH,symId)));
  290. // mark a symbol recd as inactive by setting the symbol id to cmInalidId
  291. ip->symId = cmInvalidId;
  292. return kOkDspRC;
  293. }
  294. cmDspRC_t _cmDspClassErrV( cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned instId, cmDspRC_t rc, const cmChar_t* fmt, va_list vl )
  295. {
  296. va_list vl2;
  297. va_copy(vl2,vl);
  298. unsigned n = vsnprintf(NULL,0,fmt,vl2)+1;
  299. cmChar_t buf[n+1];
  300. vsnprintf(buf,n,fmt,vl);
  301. if( instId == cmInvalidId )
  302. cmErrMsg( &classPtr->err, rc, "%s DSP Class:%s",buf, classPtr->labelStr);
  303. else
  304. cmErrMsg( &classPtr->err, rc, "%s DSP Class:%s Inst:%i",buf, classPtr->labelStr,instId);
  305. return rc;
  306. }
  307. cmDspRC_t cmDspClassErr( cmDspCtx_t* ctx, cmDspClass_t* classPtr, cmDspRC_t rc, const cmChar_t* fmt, ... )
  308. {
  309. va_list vl;
  310. va_start(vl,fmt);
  311. rc = _cmDspClassErrV(ctx,classPtr,cmInvalidId,rc,fmt,vl);
  312. va_end(vl);
  313. return rc;
  314. }
  315. cmDspRC_t cmDspInstErr( cmDspCtx_t* ctx, cmDspInst_t* inst, cmDspRC_t rc, const cmChar_t* fmt, ... )
  316. {
  317. va_list vl;
  318. va_start(vl,fmt);
  319. rc = _cmDspClassErrV(ctx,inst->classPtr,inst->id,rc,fmt,vl);
  320. va_end(vl);
  321. return rc;
  322. }
  323. void cmDspArgSetup(
  324. cmDspCtx_t* ctx,
  325. cmDspVarArg_t* arg,
  326. const cmChar_t* labelPrefix,
  327. unsigned labelId,
  328. unsigned constId,
  329. unsigned rn,
  330. unsigned cn,
  331. unsigned flags,
  332. const cmChar_t* docStr )
  333. {
  334. unsigned labelIdCharCnt = (unsigned)floor( labelId==0 ? 1.0 : log10(abs(labelId)) + 1.0 );
  335. int labelCharCnt = strlen(labelPrefix) + 1 + labelIdCharCnt + 1;
  336. cmChar_t label[ labelCharCnt + 1 ];
  337. const cmChar_t* lp;
  338. if( labelId == cmInvalidId )
  339. lp = labelPrefix;
  340. else
  341. {
  342. lp = label;
  343. label[labelCharCnt] = 0;
  344. snprintf(label,labelCharCnt,"%s-%i",labelPrefix,labelId);
  345. }
  346. // use the symbol table to hold the label string
  347. arg->label = cmSymTblLabel(ctx->stH,cmSymTblRegisterSymbol(ctx->stH,lp));
  348. arg->constId = constId;
  349. arg->rn = rn;
  350. arg->cn = cn;
  351. arg->flags = flags;
  352. arg->doc = cmLhAllocStr(ctx->lhH,docStr);;
  353. }
  354. unsigned cmDspArgCopy( cmDspVarArg_t* argArray, unsigned argN, unsigned dstIdx, const cmDspVarArg_t* s, unsigned sn )
  355. {
  356. assert( dstIdx + sn <= argN );
  357. unsigned i;
  358. for(i=0; i<sn; ++i)
  359. argArray[dstIdx+i] = s[i];
  360. return dstIdx + i;
  361. }
  362. unsigned cmDspArgSetupN(
  363. cmDspCtx_t* ctx,
  364. cmDspVarArg_t* arg,
  365. unsigned argN,
  366. unsigned dstIdx,
  367. unsigned cnt,
  368. const cmChar_t* labelPrefix,
  369. unsigned baseConstId,
  370. unsigned rn,
  371. unsigned cn,
  372. unsigned flags,
  373. const cmChar_t* staticDocStr )
  374. {
  375. assert( dstIdx + cnt <= argN );
  376. unsigned i;
  377. for(i=0; i<cnt; ++i)
  378. cmDspArgSetup(ctx,arg + dstIdx + i,labelPrefix, cnt==1 ? cmInvalidId : i, baseConstId + i, rn, cn, flags, staticDocStr );
  379. return dstIdx + i;
  380. }
  381. void cmDspArgSetupNull( cmDspVarArg_t* arg )
  382. { memset(arg,0,sizeof(*arg)); }
  383. const cmChar_t* cmDspInstLabel( cmDspCtx_t* ctx, cmDspInst_t* inst )
  384. {
  385. const char* noInstLbl = "<no_inst_lbl>";
  386. const char* lbl = noInstLbl;
  387. if( inst->symId == cmInvalidId )
  388. return lbl;
  389. if((lbl = cmSymTblLabel(ctx->stH,inst->symId)) == NULL )
  390. lbl = noInstLbl;
  391. return lbl;
  392. }
  393. cmDspRC_t _cmDspVarPtr( const cmDspInst_t* inst, unsigned varId, cmDspVar_t** retVarPtrPtr )
  394. {
  395. if( varId >= inst->varCnt )
  396. {
  397. *retVarPtrPtr = NULL;
  398. return cmErrMsg(&inst->classPtr->err,kVarNotFoundDspRC,"The variable id %i is invalid for DSP instance '%s' (id:%i) .", varId, inst->classPtr->labelStr, inst->id );
  399. }
  400. assert( inst->varArray[varId].constId == varId );
  401. *retVarPtrPtr = inst->varArray + varId;
  402. return kOkDspRC;
  403. }
  404. cmDspRC_t _cmDspVarAndValuePtr( cmDspInst_t* inst, unsigned varId, cmDspVar_t** varPtrPtr, cmDspValue_t** valPtrPtr )
  405. {
  406. cmDspRC_t rc;
  407. if((rc = _cmDspVarPtr(inst,varId,varPtrPtr)) != kOkDspRC )
  408. *valPtrPtr = NULL;
  409. else
  410. *valPtrPtr = cmDsvValuePtr(&(*varPtrPtr)->value);
  411. return rc;
  412. }
  413. cmDspRC_t _cmDspVarValuePtr( cmDspInst_t* inst, unsigned varId, cmDspValue_t** retValPtrPtr )
  414. {
  415. cmDspVar_t* varPtr = NULL;
  416. cmDspRC_t rc;
  417. if((rc = _cmDspVarPtr(inst,varId,&varPtr)) != kOkDspRC )
  418. *retValPtrPtr = NULL;
  419. else
  420. *retValPtrPtr = cmDsvValuePtr(&varPtr->value);
  421. return rc;
  422. }
  423. cmDspRC_t _cmDspVarDefaultPtr( cmDspInst_t* inst, unsigned varId, cmDspValue_t** retValPtrPtr )
  424. {
  425. cmDspVar_t* varPtr = NULL;
  426. cmDspRC_t rc;
  427. if((rc = _cmDspVarPtr(inst,varId,&varPtr)) != kOkDspRC )
  428. *retValPtrPtr = NULL;
  429. else
  430. *retValPtrPtr = &varPtr->dflt;
  431. return rc;
  432. }
  433. void _cmDspSendEvt( cmDspCtx_t* ctx, cmDspInst_t* srcInstPtr, unsigned srcVarId, const cmDspVar_t* varPtr )
  434. {
  435. cmDspEvt_t e;
  436. cmDspCb_t* cbp = varPtr->cbList;
  437. if( cbp == NULL )
  438. return;
  439. e.flags = kDfltEvtDspFlags;
  440. e.srcInstPtr = srcInstPtr;
  441. e.srcVarId = srcVarId;
  442. e.valuePtr = &varPtr->value;
  443. for(; cbp!=NULL; cbp=cbp->linkPtr)
  444. {
  445. e.dstVarId = cbp->dstVarId;
  446. e.dstDataPtr = cbp->dstDataPtr;
  447. if( cbp->dstInstPtr->recvFunc!=NULL)
  448. cbp->dstInstPtr->recvFunc(ctx,cbp->dstInstPtr,&e);
  449. }
  450. }
  451. cmDspVar_t* cmDspVarSymbolToPtr( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned varSymId, unsigned flags )
  452. {
  453. unsigned i;
  454. for(i=0; i<inst->varCnt; ++i)
  455. if( inst->varArray[i].symId == varSymId )
  456. {
  457. if( flags==0 || cmAllFlags(inst->varArray[i].flags,flags) )
  458. return inst->varArray + i;
  459. }
  460. cmDspInstErr(ctx,inst,kVarNotFoundDspRC,"The variable '%s' could not be found in the instance '%s' (id:%i).",
  461. cmSymTblLabel( ctx->stH, varSymId), inst->classPtr->labelStr, inst->id );
  462. return NULL;
  463. }
  464. const cmDspVar_t* cmDspVarIdToCPtr( const cmDspInst_t* inst, unsigned varId )
  465. {
  466. cmDspVar_t* varPtr;
  467. if( _cmDspVarPtr(inst, varId, &varPtr) != kOkDspRC )
  468. return NULL;
  469. return varPtr;
  470. }
  471. cmDspVar_t* cmDspVarIdToPtr( cmDspInst_t* inst, unsigned varId )
  472. {
  473. cmDspVar_t* varPtr;
  474. if( _cmDspVarPtr(inst, varId, &varPtr) != kOkDspRC )
  475. return NULL;
  476. return varPtr;
  477. }
  478. const cmChar_t* cmDspVarLabel( cmDspCtx_t* ctx, const cmDspInst_t* inst, unsigned varId )
  479. {
  480. const cmDspVar_t* varPtr;
  481. if(( varPtr = cmDspVarIdToCPtr(inst,varId) ) == NULL )
  482. return NULL;
  483. return cmSymTblLabel( ctx->stH, varPtr->symId);
  484. }
  485. cmDspRC_t cmDspOutputEvent( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned varId )
  486. {
  487. cmDspRC_t rc;
  488. cmDspVar_t* varPtr;
  489. if((rc = _cmDspVarPtr(inst, varId, &varPtr )) != kOkDspRC )
  490. return rc;
  491. _cmDspSendEvt(ctx, inst, varId, varPtr );
  492. return rc;
  493. }
  494. cmDspRC_t cmDspVarPresetWrite( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned varId )
  495. {
  496. cmDspRC_t rc;
  497. const cmDspVar_t* varPtr;
  498. if((varPtr = cmDspVarIdToCPtr(inst,varId)) == NULL )
  499. return cmDspInstErr(ctx,inst,kVarNotFoundDspRC,"Var with id %i not found during preset store.");
  500. if((rc = cmDspSysPresetWriteValue(ctx->dspH, varPtr->symId, &varPtr->value )) != kOkDspRC )
  501. return cmDspInstErr(ctx,inst,kSubSysFailDspRC,"Var preset storage failed on var:'%s'.",cmStringNullGuard(cmSymTblLabel(ctx->stH,varPtr->symId)));
  502. return rc;
  503. }
  504. cmDspRC_t cmDspVarPresetRead( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned varId )
  505. {
  506. cmDspRC_t rc;
  507. cmDspVar_t* varPtr;
  508. cmDspValue_t value;
  509. if((varPtr = cmDspVarIdToPtr(inst,varId)) == NULL )
  510. return cmDspInstErr(ctx,inst,kVarNotFoundDspRC,"Var with id %i not found during preset recall.");
  511. if((rc = cmDspSysPresetReadValue(ctx->dspH, varPtr->symId, &value )) != kOkDspRC )
  512. return cmDspInstErr(ctx,inst,kSubSysFailDspRC,"Var preset recall failed on var:'%s'.",cmStringNullGuard(cmSymTblLabel(ctx->stH,varPtr->symId)));
  513. return cmDspValueSet(ctx,inst,varId,&value,0);
  514. }
  515. cmDspRC_t cmDspVarPresetRdWr( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned varId, bool storeFl )
  516. {
  517. cmDspRC_t rc;
  518. if( storeFl )
  519. rc = cmDspVarPresetWrite(ctx,inst,varId);
  520. else
  521. rc = cmDspVarPresetRead(ctx,inst,varId);
  522. return rc;
  523. }
  524. double cmDspSampleRate( cmDspCtx_t* ctx )
  525. { return ctx->ctx->ss->args.srate; }
  526. unsigned cmDspSamplesPerCycle( cmDspCtx_t * ctx )
  527. { return ctx->ctx->ss->args.dspFramesPerCycle; }
  528. unsigned cmDspTypeFlags(const cmDspInst_t* inst, unsigned varId )
  529. {
  530. cmDspVar_t* varPtr;
  531. unsigned flags;
  532. if( _cmDspVarPtr(inst,varId,&varPtr) != kOkDspRC )
  533. return 0;
  534. cmDspValue_t* valPtr = cmDsvValuePtr(&varPtr->value);
  535. if( valPtr->flags != 0 )
  536. flags = valPtr->flags;
  537. else
  538. flags = varPtr->flags;
  539. return flags & kTypeDsvMask;
  540. }
  541. bool cmDspIsBool( const cmDspInst_t* inst, unsigned varId )
  542. { return cmIsFlag(cmDspTypeFlags(inst,varId),kBoolDsvFl); }
  543. bool cmDspIsInt( const cmDspInst_t* inst, unsigned varId )
  544. { return cmIsFlag(cmDspTypeFlags(inst,varId),kIntDsvFl); }
  545. bool cmDspIsUInt( const cmDspInst_t* inst, unsigned varId )
  546. { return cmIsFlag(cmDspTypeFlags(inst,varId),kUIntDsvFl); }
  547. bool cmDspIsDouble( const cmDspInst_t* inst, unsigned varId )
  548. { return cmIsFlag(cmDspTypeFlags(inst,varId),kDoubleDsvFl); }
  549. bool cmDspIsStrz( const cmDspInst_t* inst, unsigned varId )
  550. { return cmIsFlag(cmDspTypeFlags(inst,varId),kStrzDsvFl); }
  551. bool cmDspIsSymbol( const cmDspInst_t* inst, unsigned varId )
  552. { return cmIsFlag(cmDspTypeFlags(inst,varId),kSymDsvFl); }
  553. bool cmDspIsJson( const cmDspInst_t* inst, unsigned varId )
  554. { return cmIsFlag(cmDspTypeFlags(inst,varId),kJsonDsvFl); }
  555. bool cmDspBool( cmDspInst_t* inst, unsigned varId )
  556. {
  557. cmDspValue_t* vp;
  558. if(_cmDspVarValuePtr(inst,varId,&vp) != kOkDspRC )
  559. return 0;
  560. return cmDsvGetBool(vp);
  561. }
  562. int cmDspInt( cmDspInst_t* inst, unsigned varId )
  563. {
  564. cmDspValue_t* vp;
  565. if(_cmDspVarValuePtr(inst,varId,&vp) != kOkDspRC )
  566. return 0;
  567. return cmDsvGetInt(vp);
  568. }
  569. unsigned cmDspUInt( cmDspInst_t* inst, unsigned varId )
  570. {
  571. cmDspValue_t* vp;
  572. if(_cmDspVarValuePtr(inst,varId,&vp) != kOkDspRC )
  573. return 0;
  574. return cmDsvGetUInt(vp);
  575. }
  576. double cmDspDouble( cmDspInst_t* inst, unsigned varId )
  577. {
  578. cmDspValue_t* vp;
  579. if(_cmDspVarValuePtr(inst,varId,&vp) != kOkDspRC )
  580. return 0;
  581. return cmDsvGetDouble(vp);
  582. }
  583. cmSample_t cmDspSample( cmDspInst_t* inst, unsigned varId )
  584. {
  585. cmDspValue_t* vp;
  586. if(_cmDspVarValuePtr(inst,varId,&vp) != kOkDspRC )
  587. return 0;
  588. return cmDsvGetSample(vp);
  589. }
  590. cmReal_t cmDspReal( cmDspInst_t* inst, unsigned varId )
  591. {
  592. cmDspValue_t* vp;
  593. if(_cmDspVarValuePtr(inst,varId,&vp) != kOkDspRC )
  594. return 0;
  595. return cmDsvGetReal(vp);
  596. }
  597. const cmChar_t* cmDspStrcz( cmDspInst_t* inst, unsigned varId )
  598. {
  599. cmDspValue_t* vp;
  600. if(_cmDspVarValuePtr(inst,varId,&vp) != kOkDspRC )
  601. return NULL;
  602. return cmDsvStrcz(vp);
  603. }
  604. unsigned cmDspSymbol( cmDspInst_t* inst, unsigned varId )
  605. {
  606. cmDspValue_t* vp;
  607. if(_cmDspVarValuePtr(inst,varId,&vp) != kOkDspRC )
  608. return cmInvalidId;
  609. return cmDsvSymbol(vp);
  610. }
  611. cmJsonNode_t* cmDspJson( cmDspInst_t* inst, unsigned varId )
  612. {
  613. cmDspValue_t* vp;
  614. if(_cmDspVarValuePtr(inst,varId,&vp) != kOkDspRC )
  615. return NULL;
  616. return cmDsvJson(vp);
  617. }
  618. bool cmDspDefaultBool( cmDspInst_t* inst, unsigned varId )
  619. {
  620. cmDspValue_t* vp;
  621. if(_cmDspVarDefaultPtr(inst,varId,&vp) != kOkDspRC )
  622. return 0;
  623. return cmDsvGetBool(vp);
  624. }
  625. int cmDspDefaultInt( cmDspInst_t* inst, unsigned varId )
  626. {
  627. cmDspValue_t* vp;
  628. if(_cmDspVarDefaultPtr(inst,varId,&vp) != kOkDspRC )
  629. return 0;
  630. return cmDsvGetInt(vp);
  631. }
  632. unsigned cmDspDefaultUInt( cmDspInst_t* inst, unsigned varId )
  633. {
  634. cmDspValue_t* vp;
  635. if(_cmDspVarDefaultPtr(inst,varId,&vp) != kOkDspRC )
  636. return 0;
  637. return cmDsvGetUInt(vp);
  638. }
  639. double cmDspDefaultDouble( cmDspInst_t* inst, unsigned varId )
  640. {
  641. cmDspValue_t* vp;
  642. if(_cmDspVarDefaultPtr(inst,varId,&vp) != kOkDspRC )
  643. return 0;
  644. return cmDsvGetDouble(vp);
  645. }
  646. cmSample_t cmDspDefaultSample( cmDspInst_t* inst, unsigned varId )
  647. {
  648. cmDspValue_t* vp;
  649. if(_cmDspVarDefaultPtr(inst,varId,&vp) != kOkDspRC )
  650. return 0;
  651. return cmDsvGetSample(vp);
  652. }
  653. cmReal_t cmDspDefaultReal( cmDspInst_t* inst, unsigned varId )
  654. {
  655. cmDspValue_t* vp;
  656. if(_cmDspVarDefaultPtr(inst,varId,&vp) != kOkDspRC )
  657. return 0;
  658. return cmDsvGetReal(vp);
  659. }
  660. const cmChar_t* cmDspDefaultStrcz( cmDspInst_t* inst, unsigned varId )
  661. {
  662. cmDspValue_t* vp;
  663. if(_cmDspVarDefaultPtr(inst,varId,&vp) != kOkDspRC )
  664. return NULL;
  665. return cmDsvGetStrcz(vp);
  666. }
  667. unsigned cmDspDefaultSymbol( cmDspInst_t* inst, unsigned varId )
  668. {
  669. cmDspValue_t* vp;
  670. if(_cmDspVarDefaultPtr(inst,varId,&vp) != kOkDspRC )
  671. return cmInvalidId;
  672. return cmDsvGetSymbol(vp);
  673. }
  674. cmJsonNode_t* cmDspDefaultJson( cmDspInst_t* inst, unsigned varId )
  675. {
  676. cmDspValue_t* vp;
  677. if(_cmDspVarDefaultPtr(inst,varId,&vp) != kOkDspRC )
  678. return NULL;
  679. return cmDsvGetJson(vp);
  680. }
  681. cmDspRC_t cmDspValueSet( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned varId, const cmDspValue_t* svp, unsigned flags )
  682. {
  683. cmDspRC_t rc;
  684. cmDspVar_t* varPtr;
  685. // get a pointer to the var recd
  686. if((rc = _cmDspVarPtr(inst,varId,&varPtr)) != kOkDspRC )
  687. return rc;
  688. // get a pointer to the target value.
  689. cmDspValue_t* dvp = cmIsFlag(flags,kSetDefaultDspFl) ? &varPtr->dflt : cmDsvValuePtr(&varPtr->value);
  690. // store a pointer to the dst string memory in case we need to delete it later
  691. cmChar_t* rlsPtr = cmAllFlags(dvp->flags,kStrzDsvFl | kDynDsvFl) ? dvp->u.z : NULL;
  692. // set the dest type to the type shared with the source
  693. // ( this assumes that the dst may have multiple types but the source has one type)
  694. unsigned typeFlags = (varPtr->flags & svp->flags) & kTypeDsvMask;
  695. // if svp->flags is set to kNullDsvFl then use just the dst type
  696. if( typeFlags == 0 )
  697. typeFlags = varPtr->flags & kTypeDsvMask;
  698. // convert the source to the var type
  699. switch(typeFlags)
  700. {
  701. case kBoolDsvFl:
  702. cmDsvSetBool( dvp, cmDsvGetBool(svp));
  703. break;
  704. case kIntDsvFl:
  705. cmDsvSetInt( dvp, cmDsvGetInt(svp));
  706. break;
  707. case kUIntDsvFl:
  708. cmDsvSetUInt( dvp, cmDsvGetUInt(svp));
  709. break;
  710. case kDoubleDsvFl:
  711. cmDsvSetDouble(dvp, cmDsvGetDouble(svp));
  712. break;
  713. case kSymDsvFl:
  714. cmDsvSetSymbol(dvp, cmDsvGetSymbol(svp));
  715. break;
  716. case kJsonDsvFl:
  717. cmDsvSetJson( dvp, cmDsvJson(svp));
  718. break;
  719. case kStrzDsvFl:
  720. {
  721. const cmChar_t* sp;
  722. if( cmDsvIsSymbol(svp) )
  723. sp = cmSymTblLabel(ctx->stH,cmDsvSymbol(svp));
  724. else
  725. sp = cmDsvGetStrcz(svp);
  726. // don't copy over myself
  727. if( sp == dvp->u.z )
  728. rlsPtr = NULL;
  729. else
  730. {
  731. // if the source == NULL then set the dst to NULL
  732. // (NULL should always be a legitimate value)
  733. if( sp == NULL )
  734. cmDsvSetStrcz(dvp,sp);
  735. else
  736. {
  737. // if the source should not be copied into internal memory
  738. if( cmIsFlag(flags,kNoAllocDspFl) )
  739. cmDsvSetStrcz(dvp,sp);
  740. else
  741. {
  742. // allocate memory to hold the new string
  743. unsigned n = strlen(sp)+1;
  744. cmChar_t* dp = cmLhResizeN(ctx->lhH,cmChar_t,rlsPtr,n);
  745. strncpy(dp,sp,n);
  746. cmDsvSetStrz(dvp, dp);
  747. dvp->flags = cmSetFlag(dvp->flags,kDynDsvFl);
  748. rlsPtr = NULL;
  749. }
  750. }
  751. }
  752. }
  753. break;
  754. default:
  755. { assert(0); }
  756. }
  757. // if the dst contained a dynamically alloc'd string prior to being
  758. // set with a new value - then release the memory used by the original
  759. // string here
  760. if( rlsPtr != NULL )
  761. cmLHeapFree(ctx->lhH,rlsPtr);
  762. // notify listeners of the change of value
  763. if( cmIsFlag(flags,kNoSendDspFl) == false )
  764. _cmDspSendEvt( ctx, inst, varId, varPtr );
  765. // notify the UI of the change of value
  766. if( cmIsFlag(varPtr->flags,kUiDsvFl) && cmIsFlag(flags,kNoUpdateUiDspFl)==false )
  767. {
  768. cmDspUiSendVar( ctx, inst, varPtr );
  769. }
  770. return rc;
  771. }
  772. cmDspRC_t cmDspApplyDefault( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned varId )
  773. {
  774. cmDspRC_t rc;
  775. cmDspVar_t* varPtr;
  776. // get a pointer to the var recd
  777. if((rc = _cmDspVarPtr(inst,varId,&varPtr)) != kOkDspRC )
  778. return rc;
  779. if( cmIsFlag(varPtr->flags,kDfltSetDsvFl) )
  780. {
  781. // unless the var has kSendDfltDsvFl set we don't transmit the default values
  782. unsigned flags = cmIsFlag(varPtr->flags,kSendDfltDsvFl) ? 0 : kNoSendDspFl;
  783. return cmDspValueSet(ctx, inst, varId, &varPtr->dflt, flags );
  784. }
  785. return kOkDspRC;
  786. }
  787. cmDspRC_t cmDspApplyAllDefaults( cmDspCtx_t* ctx, cmDspInst_t* inst )
  788. {
  789. cmDspRC_t rc = kOkDspRC;
  790. unsigned i;
  791. for(i=0; i<inst->varCnt; ++i)
  792. if((rc = cmDspApplyDefault(ctx,inst,inst->varArray[i].constId)) != kOkDspRC )
  793. return rc;
  794. return rc;
  795. }
  796. cmDspRC_t cmDspSetDefault( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned varId, const cmDspValue_t* valPtr )
  797. {
  798. cmDspRC_t rc;
  799. cmDspVar_t* varPtr;
  800. // get a pointer to the var recd
  801. if((rc = _cmDspVarPtr(inst,varId,&varPtr)) != kOkDspRC )
  802. return rc;
  803. if(( cmDspValueSet( ctx, inst, varId, valPtr, kSetDefaultDspFl )) == kOkDspRC )
  804. {
  805. varPtr->flags = cmSetFlag(varPtr->flags, kDfltSetDsvFl);
  806. }
  807. return rc;
  808. }
  809. cmDspRC_t _cmDspDefaultSet( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned varId, const cmDspValue_t* valPtr, bool nonInitValIsEqualFl )
  810. {
  811. cmDspRC_t rc;
  812. cmDspVar_t* varPtr;
  813. // get a pointer to the var recd
  814. if((rc = _cmDspVarPtr(inst,varId,&varPtr)) != kOkDspRC )
  815. return rc;
  816. // if the dflt value was previuosly set and the default value is
  817. // not equal to the non-intialized value for this var then the default value
  818. // has already been set to a legal value
  819. if( cmIsFlag(varPtr->flags,kDfltSetDsvFl) && nonInitValIsEqualFl==false )
  820. return kOkDspRC;
  821. return cmDspSetDefault(ctx,inst,varId,valPtr);
  822. }
  823. cmDspRC_t cmDspSetDefaultBool( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned varId, bool nonInitVal, bool val )
  824. {
  825. cmDspValue_t v;
  826. double dv = cmDspDefaultBool(inst,varId);
  827. cmDsvSetBool(&v,val);
  828. return _cmDspDefaultSet(ctx,inst,varId,&v,dv==nonInitVal);
  829. }
  830. cmDspRC_t cmDspSetDefaultInt( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned varId, int nonInitVal, int val )
  831. {
  832. cmDspValue_t v;
  833. int dv = cmDspDefaultInt(inst,varId);
  834. cmDsvSetInt(&v,val);
  835. return _cmDspDefaultSet(ctx,inst,varId,&v,dv==nonInitVal);
  836. }
  837. cmDspRC_t cmDspSetDefaultUInt( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned varId, unsigned nonInitVal, unsigned val )
  838. {
  839. cmDspValue_t v;
  840. unsigned dv = cmDspDefaultUInt(inst,varId);
  841. cmDsvSetUInt(&v,val);
  842. return _cmDspDefaultSet(ctx,inst,varId,&v,dv==nonInitVal);
  843. }
  844. cmDspRC_t cmDspSetDefaultDouble( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned varId, double nonInitVal, double val )
  845. {
  846. cmDspValue_t v;
  847. double dv = cmDspDefaultDouble(inst,varId);
  848. cmDsvSetDouble(&v,val);
  849. return _cmDspDefaultSet(ctx,inst,varId,&v,dv==nonInitVal);
  850. }
  851. cmDspRC_t cmDspSetDefaultSample( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned varId, cmSample_t nonInitVal, cmSample_t val )
  852. {
  853. cmDspValue_t v;
  854. cmSample_t dv = cmDspDefaultSample(inst,varId);
  855. cmDsvSetSample(&v,val);
  856. return _cmDspDefaultSet(ctx,inst,varId,&v,dv==nonInitVal);
  857. }
  858. cmDspRC_t cmDspSetDefaultReal( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned varId, cmReal_t nonInitVal, cmReal_t val )
  859. {
  860. cmDspValue_t v;
  861. cmReal_t dv = cmDspDefaultReal(inst,varId);
  862. cmDsvSetReal(&v,val);
  863. return _cmDspDefaultSet(ctx,inst,varId,&v,dv==nonInitVal);
  864. }
  865. cmDspRC_t cmDspSetDefaultSymbol( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned varId, unsigned val )
  866. {
  867. cmDspValue_t v;
  868. unsigned dv = cmDspDefaultSymbol(inst,varId);
  869. cmDsvSetSymbol(&v,val);
  870. return _cmDspDefaultSet(ctx,inst,varId,&v,dv==cmInvalidId);
  871. }
  872. cmDspRC_t cmDspSetDefaultStrcz( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned varId, const cmChar_t* nonInitVal, const cmChar_t* val )
  873. {
  874. cmDspValue_t v;
  875. const cmChar_t* dv= cmDspDefaultStrcz(inst,varId);
  876. cmDsvSetStrcz(&v,val);
  877. bool fl = false; // assume the default and non-init value are not equal
  878. // if the pointers are the same then the strings must match
  879. if( dv == nonInitVal )
  880. fl = true;
  881. else
  882. // if both strings exist - then test if they are equal
  883. if( dv!=NULL && nonInitVal!=NULL)
  884. fl = strcmp(dv,nonInitVal)==0;
  885. return _cmDspDefaultSet(ctx,inst,varId,&v,fl);
  886. }
  887. cmDspRC_t cmDspSetDefaultJson( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned varId, cmJsonNode_t* nonInitVal, cmJsonNode_t* val )
  888. {
  889. cmDspValue_t v;
  890. cmJsonNode_t* dv= cmDspDefaultJson(inst,varId);
  891. cmDsvSetJson(&v,val);
  892. return _cmDspDefaultSet(ctx,inst,varId,&v,dv==nonInitVal);
  893. }
  894. cmDspRC_t cmDspSetBool( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned varId, bool val )
  895. {
  896. cmDspValue_t v;
  897. cmDsvSetBool(&v,val);
  898. return cmDspValueSet(ctx, inst, varId, &v, 0);
  899. }
  900. cmDspRC_t cmDspSetInt( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned varId, int val )
  901. {
  902. cmDspValue_t v;
  903. cmDsvSetInt(&v,val);
  904. return cmDspValueSet(ctx, inst, varId, &v, 0);
  905. }
  906. cmDspRC_t cmDspSetUInt( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned varId, unsigned val )
  907. {
  908. cmDspValue_t v;
  909. cmDsvSetUInt(&v,val);
  910. return cmDspValueSet(ctx, inst, varId, &v, 0);
  911. }
  912. cmDspRC_t cmDspSetDouble( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned varId, double val )
  913. {
  914. cmDspValue_t v;
  915. cmDsvSetDouble(&v,val);
  916. return cmDspValueSet(ctx, inst, varId, &v, 0);
  917. }
  918. cmDspRC_t cmDspSetSample( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned varId, cmSample_t val )
  919. {
  920. cmDspValue_t v;
  921. cmDsvSetSample(&v,val);
  922. return cmDspValueSet(ctx, inst, varId, &v, 0);
  923. }
  924. cmDspRC_t cmDspSetReal( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned varId, cmReal_t val )
  925. {
  926. cmDspValue_t v;
  927. cmDsvSetReal(&v,val);
  928. return cmDspValueSet(ctx, inst, varId, &v, 0);
  929. }
  930. cmDspRC_t cmDspSetStrcz( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned varId, const cmChar_t* val )
  931. {
  932. cmDspValue_t v;
  933. cmDsvSetStrcz(&v,val);
  934. return cmDspValueSet(ctx, inst, varId, &v, 0);
  935. }
  936. cmDspRC_t cmDspSetSymbol( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned varId, unsigned val )
  937. {
  938. cmDspValue_t v;
  939. cmDsvSetSymbol(&v,val);
  940. return cmDspValueSet(ctx, inst, varId, &v, 0);
  941. }
  942. cmDspRC_t cmDspSetJson( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned varId, cmJsonNode_t* val )
  943. {
  944. cmDspValue_t v;
  945. cmDsvSetJson(&v,val);
  946. return cmDspValueSet(ctx, inst, varId, &v, 0);
  947. }
  948. cmDspRC_t cmDspSetEvent( cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  949. {
  950. unsigned flags = kUpdateUiDspFl;
  951. // We will assume that all values should be reflected to the UI - unless
  952. // this event is known to have been generated by the UI (evt->kUiDspFl is set)
  953. // and evt->kUiEchoDspFl is not set.
  954. if( cmIsFlag(evt->flags,kUiDspFl)==true && cmIsFlag(evt->flags,kUiEchoDspFl)==false )
  955. flags = kNoUpdateUiDspFl;
  956. // Note: If the event target variable is not a UI variable
  957. // (i.e. cmDspVar_t.kUiDsvFl is not set) then calling cmDspValueSet()
  958. // with the kUpdateUiDspFl set has no effect.
  959. return cmDspValueSet(ctx,inst,evt->dstVarId, evt->valuePtr, flags);
  960. }
  961. cmDspRC_t cmDspSetEventUi( cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  962. { return cmDspValueSet(ctx,inst,evt->dstVarId, evt->valuePtr, kUpdateUiDspFl); }
  963. cmDspRC_t cmDspSetEventUiId( cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt, unsigned varId )
  964. {
  965. cmDspEvt_t e;
  966. cmDspEvtCopy(&e,evt);
  967. e.dstVarId = varId;
  968. evt = &e;
  969. return cmDspSetEventUi(ctx,inst,evt);
  970. }
  971. unsigned cmDspVarRows( cmDspInst_t* inst, unsigned varId )
  972. {
  973. cmDspValue_t* vp;
  974. if(_cmDspVarValuePtr(inst,varId,&vp) != kOkDspRC )
  975. return 0;
  976. return cmDsvRows(vp);
  977. }
  978. unsigned cmDspVarCols( cmDspInst_t* inst, unsigned varId )
  979. {
  980. cmDspValue_t* vp;
  981. if( _cmDspVarValuePtr(inst,varId,&vp) != kOkDspRC )
  982. return 0;
  983. return cmDsvCols(vp);
  984. }
  985. bool cmDspIsAudioInputConnected( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned varId )
  986. {
  987. cmDspValue_t* vp;
  988. if( _cmDspVarValuePtr(inst,varId,&vp ) != kOkDspRC )
  989. return false;
  990. if( cmAllFlags(vp->flags, kSampleDsvFl | kMtxDsvFl ))
  991. return true;
  992. return false;
  993. }
  994. cmDspRC_t cmDspZeroAudioBuf( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned varId )
  995. {
  996. cmDspValue_t* valPtr;
  997. cmDspVar_t* varPtr;
  998. cmDspRC_t rc;
  999. if((rc = _cmDspVarAndValuePtr(inst,varId,&varPtr,&valPtr)) != kOkDspRC )
  1000. return rc;
  1001. bool fl0 = cmAllFlags(valPtr->flags, kSampleDsvFl | kMtxDsvFl );
  1002. bool fl1 = cmIsFlag(varPtr->flags,kOutDsvFl);
  1003. if( fl0==false || fl1==false )
  1004. return cmDspInstErr(ctx,inst,kVarTypeErrDspRC,"The variable '%s' of DSP instance %s (id:%i) is not an output audio buffer.", cmDspVarLabel(ctx,inst,varId),inst->classPtr->labelStr,inst->id);
  1005. memset(cmDsvSampleMtx(valPtr), 0, cmDsvEleCount(valPtr)*sizeof(cmSample_t) );
  1006. return rc;
  1007. }
  1008. cmSample_t* cmDspAudioBuf( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned varId, unsigned chIdx )
  1009. {
  1010. cmDspValue_t* vp;
  1011. cmDspVar_t* varPtr;
  1012. cmDspRC_t rc;
  1013. if((rc = _cmDspVarAndValuePtr(inst,varId,&varPtr,&vp )) != kOkDspRC )
  1014. return NULL;
  1015. if( !cmAllFlags(vp->flags, kSampleDsvFl | kMtxDsvFl ))
  1016. {
  1017. // this is an unconnected audio input
  1018. if( cmAllFlags(varPtr->flags,kInDsvFl | kAudioBufDsvFl ) )
  1019. return NULL;
  1020. cmDspInstErr(ctx,inst,kVarTypeErrDspRC,"The variable '%s' of DSP instance '%s' (id:%i) is not an audio buffer.", cmDspVarLabel(ctx,inst,varId),inst->classPtr->labelStr,inst->id);
  1021. return NULL;
  1022. }
  1023. if( chIdx >= cmDsvCols(vp) )
  1024. {
  1025. cmDspInstErr(ctx,inst,kVarTypeErrDspRC,"Channel index %i of audio buffer variable '%s' in DSP instance '%s' (id:%i) is outside the channel count (%i).",
  1026. chIdx,cmDspVarLabel(ctx,inst,varId),inst->classPtr->labelStr,inst->id,cmDsvCols(vp));
  1027. }
  1028. return cmDsvSampleMtx(vp) + (chIdx * cmDsvRows(vp));
  1029. }
  1030. unsigned cmDspAudioBufSmpCount( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned varId, unsigned chIdx )
  1031. {
  1032. cmDspValue_t* vp;
  1033. cmDspRC_t rc;
  1034. if((rc = _cmDspVarValuePtr(inst,varId,&vp)) != kOkDspRC )
  1035. return 0;
  1036. if( !cmAllFlags(vp->flags, kSampleDsvFl | kMtxDsvFl ))
  1037. {
  1038. cmDspInstErr(ctx,inst,kVarTypeErrDspRC,"The variable '%s' of DSP instance '%s' (id:%i) is not an audio buffer or is an unconnected input audio buffer.", cmDspVarLabel(ctx,inst,varId),inst->classPtr->labelStr,inst->id);
  1039. return 0;
  1040. }
  1041. return cmDsvRows(vp);
  1042. }
  1043. cmDspRC_t cmDspInstInstallCb( cmDspCtx_t* ctx, cmDspInst_t* srcInstPtr, unsigned srcVarSymId, cmDspInst_t* dstInstPtr, unsigned dstVarSymId, void* dstDataPtr)
  1044. {
  1045. cmDspVar_t* srcVarPtr;
  1046. cmDspVar_t* dstVarPtr;
  1047. // get the src and dst var ptrs
  1048. if((srcVarPtr = cmDspVarSymbolToPtr(ctx,srcInstPtr,srcVarSymId,kOutDsvFl)) == NULL || (dstVarPtr = cmDspVarSymbolToPtr(ctx,dstInstPtr,dstVarSymId,kInDsvFl)) == NULL )
  1049. return cmDspInstErr(ctx,srcInstPtr,kInstCbInstallFailDspRC,"Callback installation failed for connection from '%s' (id:%i) var:'%s' to '%s' (id:%i) var:'%s'.",
  1050. srcInstPtr->classPtr->labelStr, srcInstPtr->id, cmSymTblLabel(ctx->stH,srcVarSymId), dstInstPtr->classPtr->labelStr, dstInstPtr->id, cmSymTblLabel(ctx->stH,dstVarSymId) );
  1051. // check for strict type conversion - this will fail for vars which allow multiple types
  1052. // (e.g. numbers and strings)
  1053. if( cmDsvCanConvertFlags(dstVarPtr->value.flags,srcVarPtr->value.flags) == false )
  1054. {
  1055. // if all the flags in the src are set in the dst then the match is ok
  1056. // (this will cover dst types which admit multiple types)
  1057. if( cmAllFlags(dstVarPtr->flags & kTypeDsvMask,srcVarPtr->flags & kTypeDsvMask) == false )
  1058. cmDspInstErr(ctx,srcInstPtr,kOkDspRC,"Data types may not be compatible for connection to '%s' id:%i var:'%s' from '%s'.",dstInstPtr->classPtr->labelStr, dstInstPtr->id, cmSymTblLabel(ctx->stH,dstVarSymId), cmSymTblLabel(ctx->stH,srcVarSymId));
  1059. }
  1060. if( cmIsFlag(srcVarPtr->flags, kAudioBufDsvFl) )
  1061. cmDspInstErr(ctx,srcInstPtr,kOkDspRC,"An audio source is being used as an event callback connection.");
  1062. if( cmIsFlag(dstVarPtr->flags, kAudioBufDsvFl ) )
  1063. cmDspInstErr(ctx,dstInstPtr,kOkDspRC,"An audio destination is the target of a callback connection.");
  1064. cmDspCb_t* r = cmLhAllocZ( ctx->lhH, cmDspCb_t, 1 );
  1065. r->srcVarSymId = srcVarSymId;
  1066. r->dstInstPtr = dstInstPtr;
  1067. r->dstVarId = dstVarPtr->constId;
  1068. r->dstDataPtr = dstDataPtr;
  1069. r->linkPtr = NULL;
  1070. cmDspCb_t* cp = srcVarPtr->cbList;
  1071. cmDspCb_t* pp = NULL;
  1072. for(; cp != NULL; cp = cp->linkPtr )
  1073. pp = cp;
  1074. if( pp == NULL )
  1075. srcVarPtr->cbList = r;
  1076. else
  1077. pp->linkPtr = r;
  1078. return kOkDspRC;
  1079. }
  1080. cmDspRC_t cmDspInstallCb( cmDspCtx_t* ctx, cmDspInst_t* srcInstPtr, const cmChar_t* srcVarLabel, cmDspInst_t* dstInstPtr, const cmChar_t* dstVarLabel, void* dstCbDataPtr)
  1081. {
  1082. unsigned srcVarSymId,dstVarSymId;
  1083. if( srcInstPtr == NULL && dstInstPtr == NULL )
  1084. return cmErrMsg(&ctx->cmCtx->err,kInstNotFoundDspRC,"The callback installation was passed a NULL source and destination processor instance pointer.");
  1085. if( srcInstPtr == NULL )
  1086. return cmErrMsg(&ctx->cmCtx->err,kInstNotFoundDspRC,"The callback installation was passed a NULL source processor instance pointer for connection to '%s'.",cmStringNullGuard(dstInstPtr->classPtr->labelStr));
  1087. if( dstInstPtr == NULL )
  1088. return cmErrMsg(&ctx->cmCtx->err,kInstNotFoundDspRC,"The callback installation was passed a NULL destination processor instance pointer for connection from '%s'.",cmStringNullGuard(srcInstPtr->classPtr->labelStr));
  1089. if((srcVarSymId = cmSymTblId( ctx->stH, srcVarLabel )) == cmInvalidId )
  1090. return cmDspInstErr(ctx,srcInstPtr,kSrcVarNotFoundDspRC,"Connection failed. The source variable '%s' could not found in '%s' (id:%i) for registration by '%s' (id:%i).",
  1091. srcVarLabel,srcInstPtr->classPtr->labelStr,srcInstPtr->id,dstInstPtr->classPtr->labelStr,dstInstPtr->id);
  1092. if((dstVarSymId = cmSymTblId( ctx->stH, dstVarLabel )) == cmInvalidId )
  1093. return cmDspInstErr(ctx,dstInstPtr,kSrcVarNotFoundDspRC,"Connection failed. The destination variable '%s' for the DSP instance '%s' (id:%i).",
  1094. dstVarLabel,dstInstPtr->classPtr->labelStr,dstInstPtr->id);
  1095. return cmDspInstInstallCb(ctx, srcInstPtr, srcVarSymId, dstInstPtr, dstVarSymId, dstCbDataPtr);
  1096. }
  1097. cmDspRC_t cmDspInstRemoveCb( cmDspCtx_t* ctx, cmDspInst_t* srcInstPtr, unsigned srcVarSymId, cmDspInst_t* dstInstPtr, unsigned dstVarId )
  1098. {
  1099. cmDspVar_t* varPtr;
  1100. if((varPtr = cmDspVarSymbolToPtr(ctx,srcInstPtr,srcVarSymId,kOutDsvFl)) == NULL )
  1101. return cmDspInstErr(ctx,srcInstPtr,kInstCbInstallFailDspRC,"Callback removal failed for instance '%s' (id:%i).",
  1102. srcInstPtr->classPtr->labelStr, srcInstPtr->id );
  1103. cmDspCb_t* cp = varPtr->cbList;
  1104. cmDspCb_t* pp = NULL;
  1105. for(; cp != NULL; cp = cp->linkPtr )
  1106. {
  1107. if( cp->srcVarSymId == srcVarSymId && cp->dstInstPtr == dstInstPtr && cp->dstVarId == dstVarId )
  1108. break;
  1109. pp = cp;
  1110. }
  1111. if( pp == NULL )
  1112. varPtr->cbList = cp->linkPtr;
  1113. else
  1114. pp->linkPtr = cp->linkPtr;
  1115. return kOkDspRC;
  1116. }
  1117. cmDspRC_t cmDspRemoveCb( cmDspCtx_t* ctx, cmDspInst_t* srcInstPtr, const cmChar_t* srcVarLabel, cmDspInst_t* dstInstPtr, unsigned dstVarId)
  1118. {
  1119. unsigned srcVarSymId;
  1120. if((srcVarSymId = cmSymTblId( ctx->stH, srcVarLabel )) == cmInvalidId )
  1121. return cmDspInstErr(ctx,srcInstPtr,kSrcVarNotFoundDspRC,"The variable '%s' could not found in '%s' (id:%i) do de-register for '%s' (id:%i).",
  1122. srcVarLabel,srcInstPtr->classPtr->labelStr,srcInstPtr->id,dstInstPtr->classPtr->labelStr,dstInstPtr->id);
  1123. return cmDspInstRemoveCb(ctx, srcInstPtr, srcVarSymId, dstInstPtr, dstVarId );
  1124. }
  1125. cmDspRC_t cmDspInstVarSetFlags( cmDspCtx_t* ctx, cmDspInst_t* instPtr, unsigned varId, unsigned flags )
  1126. {
  1127. cmDspVar_t* varPtr;
  1128. if(_cmDspVarPtr(instPtr, varId, &varPtr ) != kOkDspRC )
  1129. return cmDspInstErr(ctx,instPtr,kInstSetFlagsFailDspRC,"Set flags failed for DSP instance %s (id:%i).",instPtr->classPtr->labelStr,instPtr->id);
  1130. varPtr->flags = cmSetFlag(varPtr->flags,flags);
  1131. return kOkDspRC;
  1132. }