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.

cmDspPgmPP.c 19KB

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