libcm is a C development framework with an emphasis on audio signal processing applications.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

cmDspPgmPP.c 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579
  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 "cmText.h"
  11. #include "cmFileSys.h"
  12. #include "cmSymTbl.h"
  13. #include "cmJson.h"
  14. #include "cmPrefs.h"
  15. #include "cmDspValue.h"
  16. #include "cmMsgProtocol.h"
  17. #include "cmThread.h"
  18. #include "cmUdpPort.h"
  19. #include "cmUdpNet.h"
  20. #include "cmSerialPort.h"
  21. #include "cmTime.h"
  22. #include "cmAudioSys.h"
  23. #include "cmProcObj.h"
  24. #include "cmDspCtx.h"
  25. #include "cmDspClass.h"
  26. #include "cmDspSys.h"
  27. #include "cmDspPgm.h"
  28. #include "cmDspPgmPPMain.h"
  29. #include "cmAudioFile.h"
  30. #include "cmProcObj.h"
  31. #include "cmProc.h"
  32. #include "cmProc3.h"
  33. #include "cmVectOpsTemplateMain.h"
  34. #include "cmVectOps.h"
  35. /*
  36. subnet [ aout ] = fx_chain( ain, hzV )
  37. {
  38. cmpThreshDb = -40.0;
  39. cmpRatio = 4;
  40. cmpAtkMs = 30.0;
  41. cmpRlsMs = 100.0;
  42. dstInGain = 1.0;
  43. dstDSrate = 44100.0;
  44. dstBits = 24;
  45. eqMode = "LP";
  46. eqHz = hzV[ _i ];
  47. dlyMaxMs = 10000.0;
  48. dlyFb = 0.8;
  49. loop = loopRecd( );
  50. ps = pitchShift( );
  51. cmp = compressor( cmpThreshDb, cmpRatio, cmpAtkMs, cmpRlsMs );
  52. dst = distortion( dstInGain, dstDSrate, dstBits );
  53. eq = eq( eqMode, eqHz );
  54. dly = delay( dlyMaxMs, dlyFb );
  55. ain -> in.loop.out -> in.ps.out -> in.ps.out
  56. loop.out -> ps.in;
  57. ps.out -> cmp.in;
  58. cmp.out -> dst.in;
  59. dst.out -> eq.in;
  60. eq.out -> dly.in;
  61. dly.out -> aout
  62. }
  63. audInMapV = [ 0, 1, 0, 1];
  64. audOutMapV = [ 0, 1 ];
  65. hzV = [ 110 220 440 880 ];
  66. ain = audioInput( audioInMap, 1.0 )[ chCnt ];
  67. ef = envFollower( )[ chCnt ];
  68. mtr = meter(0.0,1.0,0.0)[ chCnt ];
  69. fx = fx_chain( ain )( hzV )[ chCnt ];
  70. aout = audioOutput( audioOutMap, 1.0 )[ chCnt ];
  71. ain.out -> ef.in
  72. ef.rms -> mtr.in
  73. */
  74. // Use the resource int arrays 'pitchList' and 'groupList' to create
  75. // the following resource int arrays:
  76. // CDmidi - MIDI pitch of all chord notes
  77. // CD0midi - MIDI pitch of all low/high chord notes
  78. // CD1midi - MIDI pitch of all middle chord notes
  79. // NONmidi - MIDI pitch of all non-chord notes.
  80. // CDchan - channel index of all chord notes
  81. // CD0chan - channel index of all low/high chord notes
  82. // CD1chan - channel index of all middle chord notes
  83. // NONchan - channel index of all non-chord notes.
  84. //
  85. cmDspRC_t _cmDspPgm_Main_ProcRsrc( cmDspSysH_t h, cmErr_t* err )
  86. {
  87. cmDspRC_t rc;
  88. unsigned* midiList = NULL;
  89. unsigned midiCnt = 0;
  90. unsigned* groupList = NULL;
  91. unsigned groupCnt = 0;
  92. const cmChar_t* midiListRsrcLabel = "midiList";
  93. const cmChar_t* groupListRsrcLabel = "groupList";
  94. cmJsonH_t jsH = cmDspSysPgmRsrcHandle(h);
  95. unsigned i,j,k;
  96. if((rc = cmDspRsrcUIntArray(h,&midiCnt,&midiList,midiListRsrcLabel,NULL)) != kOkDspRC )
  97. {
  98. rc = cmErrMsg(err,kRsrcNotFoundDspRC,"The resource '%s' could not be read.",midiListRsrcLabel);
  99. goto errLabel;
  100. }
  101. if((rc = cmDspRsrcUIntArray(h,&groupCnt,&groupList,groupListRsrcLabel,NULL)) != kOkDspRC )
  102. {
  103. rc = cmErrMsg(err,kRsrcNotFoundDspRC,"The resource '%s' could not be read.",groupListRsrcLabel);
  104. goto errLabel;
  105. }
  106. if( midiCnt != groupCnt )
  107. {
  108. rc = cmErrMsg(err,kInvalidStateDspRC,"The resource arrays:%s and %s were not the same length.",midiListRsrcLabel,groupListRsrcLabel);
  109. goto errLabel;
  110. }
  111. for(i=0; i<4; ++i)
  112. {
  113. int midi[ midiCnt ];
  114. int chan[ midiCnt ];
  115. const cmChar_t* label = NULL;
  116. const cmChar_t* label1;
  117. for(j=0,k=0; j<midiCnt; ++j)
  118. {
  119. if( (i<=2 && groupList[j] == i) || (i==3 && groupList[j]!=0) )
  120. {
  121. midi[k] = midiList[j];
  122. chan[k] = j;
  123. ++k;
  124. }
  125. }
  126. switch( i )
  127. {
  128. case 0:
  129. label = "NON";
  130. break;
  131. case 1:
  132. label = "CD0";
  133. break;
  134. case 2:
  135. label = "CD1";
  136. break;
  137. case 3:
  138. label = "CD";
  139. break;
  140. }
  141. if( cmJsonInsertPairIntArray( jsH, cmJsonRoot(jsH), label1 = cmTsPrintfS("%smidi",label), k, midi ) != kOkJsRC )
  142. {
  143. rc = cmErrMsg(err,kJsonFailDspRC,"The chord detector pitch resource '%s' could not be created.", cmStringNullGuard(label1));
  144. goto errLabel;
  145. }
  146. if( cmJsonInsertPairIntArray( jsH, cmJsonRoot(jsH), label1 = cmTsPrintfS("%schan",label), k, chan) != kOkJsRC )
  147. {
  148. rc = cmErrMsg(err,kJsonFailDspRC,"The chord detector channel index resource '%s' could not be created.", cmStringNullGuard(label1));
  149. goto errLabel;
  150. }
  151. }
  152. errLabel:
  153. return rc;
  154. }
  155. // Use the resource int arrays 'MidiList',"MachineList", "ChordList" and 'GroupList' to create
  156. // the resource int arrays. XXXchan arrays contain indexes between 0 and 15. When used with
  157. // the chord detector this the 'local' channels are 0-15 and the remote channels are 16-31.
  158. // NLCDmidi - MIDI pitch of all local chord notes
  159. // NLCD0midi - MIDI pitch of all local low single notes
  160. // NLCD1midi - MIDI pitch of all local middle single notes
  161. // NLEEmidi - MIDI pitch of all local e-e single notes.
  162. // NLCDchan - channel index of all local chord notes
  163. // NLCD0chan - channel index of all local high single notes
  164. // NLCD1chan - channel index of all local middle single notes
  165. // NLEEchan - channel index of all local e-e single notes.
  166. // NRCDmidi - MIDI pitch of all remote chord notes
  167. // NRCD0midi - MIDI pitch of all remote low single notes
  168. // NRCD1midi - MIDI pitch of all remote middle single notes
  169. // NREEmidi - MIDI pitch of all remote e-e single notes.
  170. // NRCDchan - channel index of all remote chord notes
  171. // NRCD0chan - channel index of all remote high single notes
  172. // NRCD1chan - channel index of all remote middle single notes
  173. // NREEchan - channel index of all remote e-e single notes.
  174. // 'local' refers to the machine running the chord detector
  175. // 'remote' refers to the machine not running the chord detector
  176. cmDspRC_t _cmDspPgm_Main_NetProcRsrc( cmDspSysH_t h, cmErr_t* err )
  177. {
  178. cmDspRC_t rc = kOkDspRC;
  179. const cmChar_t* midiListRsrcLabel = "MidiList";
  180. unsigned* midiList = NULL;
  181. unsigned midiCnt = 0;
  182. const cmChar_t* machListRsrcLabel = "MachineList";
  183. unsigned* machList = NULL;
  184. unsigned machCnt = 0;
  185. const cmChar_t* groupListRsrcLabel = "GroupList";
  186. unsigned* groupList = NULL;
  187. unsigned groupCnt = 0;
  188. const cmChar_t* chordListRsrcLabel = "ChordList";
  189. unsigned* chordList = NULL;
  190. unsigned chordCnt = 0;
  191. cmJsonH_t jsH = cmDspSysPgmRsrcHandle(h);
  192. const cmChar_t* localNetNodeLabel = NULL;
  193. unsigned localNetNodeId = cmInvalidId;
  194. bool verboseFl = false;
  195. unsigned i,j,k,m;
  196. // get the network node id of this machine
  197. if(( cmDspRsrcString(h, &localNetNodeLabel, "cdLocalNetNode", NULL )) != kOkDspRC )
  198. {
  199. rc = cmErrMsg(err,kRsrcNotFoundDspRC,"The resource 'cdLocalNetNode' could not be read.");
  200. goto errLabel;
  201. }
  202. if(( localNetNodeId = cmDspSysNetNodeLabelToId(h,localNetNodeLabel)) == cmInvalidId )
  203. {
  204. cmErrMsg(err,kInvalidArgDspRC,"The network node label '%s' is not valid.",cmStringNullGuard(localNetNodeLabel));
  205. goto errLabel;
  206. }
  207. // get the pitch assigned to each channel
  208. if((rc = cmDspRsrcUIntArray(h,&midiCnt,&midiList,midiListRsrcLabel,NULL)) != kOkDspRC )
  209. {
  210. rc = cmErrMsg(err,kRsrcNotFoundDspRC,"The resource '%s' could not be read.",midiListRsrcLabel);
  211. goto errLabel;
  212. }
  213. // get the network node id of each channel
  214. if((rc = cmDspRsrcUIntArray(h,&machCnt,&machList,machListRsrcLabel,NULL)) != kOkDspRC )
  215. {
  216. rc = cmErrMsg(err,kRsrcNotFoundDspRC,"The resource '%s' could not be read.",machListRsrcLabel);
  217. goto errLabel;
  218. }
  219. // get the group id of each channel
  220. if((rc = cmDspRsrcUIntArray(h,&groupCnt,&groupList,groupListRsrcLabel,NULL)) != kOkDspRC )
  221. {
  222. rc = cmErrMsg(err,kRsrcNotFoundDspRC,"The resource '%s' could not be read.",groupListRsrcLabel);
  223. goto errLabel;
  224. }
  225. // get the chord detector flag for each channel
  226. if((rc = cmDspRsrcUIntArray(h,&chordCnt,&chordList,chordListRsrcLabel,NULL)) != kOkDspRC )
  227. {
  228. rc = cmErrMsg(err,kRsrcNotFoundDspRC,"The resource '%s' could not be read.",chordListRsrcLabel);
  229. goto errLabel;
  230. }
  231. if( midiCnt != groupCnt || midiCnt != machCnt)
  232. {
  233. rc = cmErrMsg(err,kInvalidStateDspRC,"The resource arrays:%s, %s and %s were not all the same length.",midiListRsrcLabel,machListRsrcLabel,groupListRsrcLabel);
  234. goto errLabel;
  235. }
  236. if( 1 )
  237. {
  238. const cmChar_t* label1;
  239. unsigned ten = 10;
  240. int nsChSelChV[ midiCnt ]; // note selector chord port [0, 5]
  241. int nsChSelChIdxV[ midiCnt ]; // index on note selector port
  242. int nsNcSelChV[ midiCnt ]; // note selector single-note port [ 2, 3, 4, 7,8,9 ]
  243. int nsNcSelChIdxV[ midiCnt ]; // index on note selector single-note port
  244. unsigned chIdxCntV[ ten ]; // next index for each note selector port
  245. cmVOU_Fill(chIdxCntV,ten,0);
  246. for(i=0; i<midiCnt; ++i)
  247. {
  248. unsigned localFl = i<16;
  249. unsigned selIdx = localFl ? 0 : 5; // chord port
  250. unsigned chordChFl = chordList[i] != 0; // is this a chord channel
  251. nsChSelChV[i] = cmInvalidIdx;
  252. nsChSelChIdxV[i] = cmInvalidIdx;
  253. if( chordChFl )
  254. {
  255. nsChSelChV[ i ] = selIdx;
  256. nsChSelChIdxV[ i ] = chIdxCntV[ selIdx ];
  257. chIdxCntV[ selIdx ] += 1;
  258. }
  259. switch( groupList[i] )
  260. {
  261. case 0: selIdx = localFl ? 4 : 9; break; // e-e group
  262. case 1: selIdx = localFl ? 2 : 7; break; // hi/lo group
  263. case 2: selIdx = localFl ? 3 : 8; break; // mid group
  264. default:
  265. { assert(0); }
  266. }
  267. assert( selIdx < ten );
  268. nsNcSelChV[ i ] = selIdx;
  269. nsNcSelChIdxV[ i ] = chIdxCntV[ selIdx ];
  270. chIdxCntV[ selIdx ] += 1;
  271. }
  272. if( verboseFl )
  273. {
  274. cmVOI_PrintL("nsChSelChV", err->rpt, 1, midiCnt, nsChSelChV );
  275. cmVOI_PrintL("nsChSelChIdxV", err->rpt, 1, midiCnt, nsChSelChIdxV );
  276. cmVOI_PrintL("nsNcSelChV", err->rpt, 1, midiCnt, nsNcSelChV );
  277. cmVOI_PrintL("nsNcSelChIdxV", err->rpt, 1, midiCnt, nsNcSelChIdxV );
  278. }
  279. if( cmJsonInsertPairIntArray( jsH, cmJsonRoot(jsH), label1 = "nsChSelChV", midiCnt, nsChSelChV ) != kOkJsRC )
  280. {
  281. rc = cmErrMsg(err,kJsonFailDspRC,"The note selector resource '%s' could not be created.", cmStringNullGuard(label1));
  282. goto errLabel;
  283. }
  284. if( cmJsonInsertPairIntArray( jsH, cmJsonRoot(jsH), label1 = "nsChSelChIdxV", midiCnt, nsChSelChIdxV ) != kOkJsRC )
  285. {
  286. rc = cmErrMsg(err,kJsonFailDspRC,"The note selector resource '%s' could not be created.", cmStringNullGuard(label1));
  287. goto errLabel;
  288. }
  289. if( cmJsonInsertPairIntArray( jsH, cmJsonRoot(jsH), label1 = "nsNcSelChV", midiCnt, nsNcSelChV ) != kOkJsRC )
  290. {
  291. rc = cmErrMsg(err,kJsonFailDspRC,"The note selector resource '%s' could not be created.", cmStringNullGuard(label1));
  292. goto errLabel;
  293. }
  294. if( cmJsonInsertPairIntArray( jsH, cmJsonRoot(jsH), label1 = "nsNcSelChIdxV", midiCnt, nsNcSelChIdxV ) != kOkJsRC )
  295. {
  296. rc = cmErrMsg(err,kJsonFailDspRC,"The note selector resource '%s' could not be created.", cmStringNullGuard(label1));
  297. goto errLabel;
  298. }
  299. for(i=0; i<ten; ++i)
  300. {
  301. int midi[ midiCnt ];
  302. int chan[ midiCnt ];
  303. for(j=0,k=0; j<midiCnt; ++j)
  304. {
  305. m = i;
  306. if( m == 1 || m == 6 )
  307. m -= 1;
  308. if( nsChSelChV[j] == m )
  309. {
  310. midi[k] = midiList[j];
  311. chan[k] = j>15 ? j-16 : j;
  312. assert( k == nsChSelChIdxV[j] );
  313. ++k;
  314. }
  315. if( nsNcSelChV[j] == m )
  316. {
  317. midi[k] = midiList[j];
  318. chan[k] = j>15 ? j-16 : j;
  319. assert( k == nsNcSelChIdxV[j] );
  320. ++k;
  321. }
  322. }
  323. if( cmJsonInsertPairIntArray( jsH, cmJsonRoot(jsH), label1 = cmTsPrintfS("nsMidi-%i",i), k, midi ) != kOkJsRC )
  324. {
  325. rc = cmErrMsg(err,kJsonFailDspRC,"The note selector resource '%s' could not be created.", cmStringNullGuard(label1));
  326. goto errLabel;
  327. }
  328. if( verboseFl )
  329. cmVOI_PrintL(label1, err->rpt, 1, k, midi );
  330. if( cmJsonInsertPairIntArray( jsH, cmJsonRoot(jsH), label1 = cmTsPrintfS("nsChan-%i",i), k, chan ) != kOkJsRC )
  331. {
  332. rc = cmErrMsg(err,kJsonFailDspRC,"The note selector resource '%s' could not be created.", cmStringNullGuard(label1));
  333. goto errLabel;
  334. }
  335. if( verboseFl )
  336. cmVOI_PrintL(label1, err->rpt, 1, k, chan );
  337. }
  338. }
  339. errLabel:
  340. return rc;
  341. }
  342. const cmChar_t* _cmDspPP_SelCheckTitle( cmDspSysH_t h, unsigned i )
  343. { return _cmDspPP_CircuitDesc(i)->title; }
  344. cmDspRC_t _cmDspSysPgm_Main( cmDspSysH_t h, void** userPtrPtr )
  345. {
  346. cmDspRC_t rc = kOkDspRC;
  347. const cmChar_t* chCfgFn = NULL;
  348. cmCtx_t* cmCtx = cmDspSysPgmCtx(h);
  349. double efOnThrDb = -40;
  350. double efOffThrDb = -70;
  351. double efMaxDb = -15;
  352. unsigned circuitCnt = _cmDspPP_CircuitDescCount();
  353. unsigned resetSymId = cmDspSysRegisterStaticSymbol(h,"_reset");
  354. bool inFileFl = false;
  355. cmErr_t err;
  356. _cmDspPP_Ctx_t ctx;
  357. cmDspPP_CircuitSwitch_t sw;
  358. memset(&sw,0,sizeof(sw));
  359. // set up the global context record
  360. memset(&ctx,0,sizeof(ctx));
  361. ctx.oChCnt = 2;
  362. ctx.err = &err;
  363. cmErrSetup(&err,&cmCtx->rpt,"PP Main");
  364. // create the individual non-networked chord detector resource arrays from the base resource arrays
  365. if((rc =_cmDspPgm_Main_ProcRsrc(h,&err)) != kOkDspRC )
  366. goto errLabel;
  367. // create the individual networked chord detector resource arrays from the base resource arrays
  368. if((rc = _cmDspPgm_Main_NetProcRsrc(h,&err)) != kOkDspRC )
  369. goto errLabel;
  370. // get the channel cfg configuration file name
  371. if( cmJsonPathToString( cmDspSysPgmRsrcHandle(h), NULL, NULL, "chCfgFn", &chCfgFn ) != kOkJsRC )
  372. {
  373. rc = cmErrMsg(&err,kRsrcNotFoundDspRC,"The 'chCfgFn' resource was not found.");
  374. goto errLabel;
  375. }
  376. // get the count of channels from the ch. cfg. array
  377. if(( ctx.iChCnt = cmChCfgChannelCount(cmCtx,chCfgFn,&ctx.nsCnt)) == 0 )
  378. {
  379. rc = cmErrMsg(&err,kPgmCfgFailDspRC,"Unable to obtain the channel count from '%s'.",cmStringNullGuard(chCfgFn));
  380. goto errLabel;
  381. }
  382. if( rc == kOkDspRC )
  383. {
  384. unsigned inChCnt,outChCnt;
  385. // channel cfg
  386. ctx.chCfg = cmDspSysAllocInst( h, "ChCfg", NULL, 1, chCfgFn );
  387. // global printer
  388. ctx.print = cmDspSysAllocInst( h, "Printer", NULL, 1, ">" );
  389. cmDspInst_t** ain;
  390. cmDspInst_t* phs;
  391. // audio input
  392. if( inFileFl )
  393. {
  394. unsigned wtSmpCnt = (unsigned)cmDspSysSampleRate(h);
  395. unsigned wtMode = 1; //file mode
  396. const cmChar_t* fn = "/home/kevin/media/audio/gate_detect/gate_detect2.aif";
  397. phs = cmDspSysAllocInst(h,"Phasor", NULL, 0 );
  398. ain = cmDspSysAllocInstArray(h, ctx.iChCnt, "WaveTable", NULL, NULL, 3, wtSmpCnt, wtMode, fn );
  399. inChCnt = ctx.iChCnt;
  400. }
  401. else
  402. {
  403. ain = cmDspSysAllocAudioInAR( h, "audioInMap", 1.0, &inChCnt );
  404. }
  405. // envelope followers and RMS meters
  406. cmDspSysAllocLabel(h,"EF Gates",kLeftAlignDuiId );
  407. cmDspInst_t** ef = cmDspSysAllocInstArray( h, ctx.iChCnt,"EnvFollow", NULL, NULL, 0 );
  408. cmDspInst_t** mtr = cmDspSysAllocInstArray( h, ctx.iChCnt,"Meter", "mtr", NULL, 3, 0.0, 0.0, 1.0 );
  409. // Level meters
  410. cmDspSysNewColumn(h,200);
  411. cmDspSysAllocLabel(h,"Level",kLeftAlignDuiId );
  412. cmDspInst_t** lvl = cmDspSysAllocInstArray( h, ctx.iChCnt,"Meter", "lvl", NULL, 3, 0.0, 0.0, 1.0 );
  413. assert( inChCnt == ctx.iChCnt );
  414. // Onset count displays
  415. cmDspSysNewColumn(h,200);
  416. cmDspInst_t** onn = cmDspSysAllocInstArray( h, ctx.iChCnt,"Scalar", "on", NULL, 5, kNumberDuiId, 0.0, 10000.0, 1.0, 0.0 );
  417. cmDspSysNewColumn(h,200);
  418. // program reset button
  419. cmDspInst_t* resetBtn = cmDspSysAllocButton( h, "reset", 0 );
  420. cmDspSysAssignInstAttrSymbol(h,resetBtn, resetSymId );
  421. // circuit selection check-boxes
  422. cmDspInst_t** csel = cmDspSysAllocInstArray( h, circuitCnt, "Button", NULL, _cmDspPP_SelCheckTitle, 2, kCheckDuiId, 0.0 );
  423. cmDspSysNewColumn(h,200);
  424. cmDspSysAllocLabel(h,"Out Gains",kLeftAlignDuiId );
  425. // output gain controls
  426. cmDspInst_t** ogain = cmDspSysAllocInstArray( h, ctx.oChCnt,"Scalar", "mgain", NULL, 5, kNumberDuiId, 0.0, 10.0, 0.01, 1.0);
  427. // envelope follower parameters
  428. cmDspInst_t* onThr = cmDspSysAllocScalar( h, "On Thresh",-100.0, 0.0, 0.1, efOnThrDb);
  429. cmDspInst_t* offThr = cmDspSysAllocScalar( h, "Off Thresh",-100.0, 0.0, 0.1, efOffThrDb);
  430. cmDspInst_t* maxDb = cmDspSysAllocScalar( h, "Max Db", -100.0, 0.0, 0.1, efMaxDb);
  431. // switcher and circuits
  432. _cmDspPP_CircuitSwitchAlloc(h, &ctx, &sw, resetBtn, csel, ain, ef);
  433. // audio output
  434. cmDspInst_t** aout = cmDspSysAllocAudioOutAR( h, "audioOutMap", 1.0, &outChCnt );
  435. assert( outChCnt == ctx.oChCnt );
  436. //cmDspInst_t* prt = cmDspSysAllocInst( h, "Printer", NULL, 2, "", 250 );
  437. // check for errors
  438. if((rc = cmDspSysLastRC(h)) != kOkDspRC )
  439. goto doneLabel;
  440. if( inFileFl )
  441. {
  442. cmDspSysConnectAudio11N1( h, phs, "out", ain, "phs", ctx.iChCnt ); // phs -> wt
  443. cmDspSysConnectAudioN1N1( h, ain, "out", ef, "in", ctx.iChCnt ); // wt -> EF
  444. }
  445. else
  446. {
  447. cmDspSysConnectAudioN1N1( h, ain, "out", ef, "in", ctx.iChCnt ); // ain -> EF
  448. }
  449. cmDspSysInstallCb1NN1( h, ctx.chCfg, "gain", ain, "gain", ctx.iChCnt ); // chCfg -> ain (gain)
  450. cmDspSysConnectAudioN1N1( h, sw.omix, "out", aout, "in", ctx.oChCnt ); // Sw.mix -> aout
  451. cmDspSysInstallCbN1N1( h, ogain, "val", aout, "gain", ctx.oChCnt ); // gain -> aout
  452. cmDspSysInstallCb( h, resetBtn,"sym", ctx.chCfg, "sel", NULL ); // reset -> chCfg
  453. cmDspSysInstallCbN1N1( h, ef, "gate", mtr, "in", ctx.iChCnt ); // EF -> meter (gate)
  454. cmDspSysInstallCbN1N1( h, ef, "level", lvl, "in", ctx.iChCnt ); // EF -> meter (level)
  455. cmDspSysInstallCbN1N1( h, ef, "ons", onn, "val", ctx.iChCnt );
  456. cmDspSysInstallCb11N1( h, onThr, "val", ef, "ondb", ctx.iChCnt ); // EF sensivity settings
  457. cmDspSysInstallCb11N1( h, offThr, "val", ef, "offdb", ctx.iChCnt ); //
  458. cmDspSysInstallCb11N1( h, maxDb, "val", ef, "maxdb", ctx.iChCnt ); //
  459. //cmDspSysInstallCbN111( h, ef, "level", prt, "in", ctx.iChCnt );
  460. doneLabel:
  461. _cmDspPP_CircuitSwitchFree(h, &sw );
  462. }
  463. errLabel:
  464. if( rc != kOkDspRC )
  465. cmErrMsg(&err,rc,"'main' construction failed.");
  466. return rc;
  467. }