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

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