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

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