libcm is a C development framework with an emphasis on audio signal processing applications.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

cmProc3.c 89KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675
  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 "cmRpt.h"
  6. #include "cmErr.h"
  7. #include "cmCtx.h"
  8. #include "cmMem.h"
  9. #include "cmMallocDebug.h"
  10. #include "cmLinkedHeap.h"
  11. #include "cmSymTbl.h"
  12. #include "cmFloatTypes.h"
  13. #include "cmComplexTypes.h"
  14. #include "cmFileSys.h"
  15. #include "cmJson.h"
  16. #include "cmProcObj.h"
  17. #include "cmProcTemplate.h"
  18. #include "cmAudioFile.h"
  19. #include "cmMath.h"
  20. #include "cmProc.h"
  21. #include "cmVectOps.h"
  22. #include "cmProc3.h"
  23. #include "cmTime.h"
  24. #include "cmMidi.h" // cmMidiToSciPitch();
  25. cmPitchShift* cmPitchShiftAlloc( cmCtx* c, cmPitchShift* p, unsigned procSmpCnt, cmReal_t srate )
  26. {
  27. cmPitchShift* op = cmObjAlloc(cmPitchShift, c, p );
  28. if( procSmpCnt != 0 )
  29. if( cmPitchShiftInit(op, procSmpCnt,srate) != cmOkRC )
  30. cmPitchShiftFree(&op);
  31. return op;
  32. }
  33. cmRC_t cmPitchShiftFinal(cmPitchShift* p )
  34. { return cmOkRC; }
  35. #define _cube_interp(x,y0,y1,y2,y3) ((y3) - (y2) - (y0) + (y1))*(x)*(x)*(x) + ((y0) - (y1) - ((y3) - (y2) - (y0) + (y1)))*(x)*(x) + ((y2) - (y0))*(x) + (y1)
  36. #define _lin_interp(x,y0,y1) (y0) + (x) * ((y1)-(y0))
  37. /*
  38. cmRC_t cmPitchShiftFree( cmPitchShift** pp )
  39. {
  40. cmRC_t rc = cmOkRC;
  41. if( pp != NULL && *pp != NULL )
  42. {
  43. cmPitchShift* p = *pp;
  44. if(( rc = cmPitchShiftFinal(p)) == cmOkRC )
  45. {
  46. cmMemPtrFree(&p->x);
  47. cmMemPtrFree(&p->y);
  48. cmMemPtrFree(&p->cf);
  49. cmObjFree(pp);
  50. }
  51. }
  52. return rc;
  53. }
  54. cmRC_t cmPitchShiftInit( cmPitchShift* p, unsigned procSmpCnt, double srate )
  55. {
  56. cmRC_t rc;
  57. if((rc = cmPitchShiftFinal(p)) != cmOkRC )
  58. return rc;
  59. p->procSmpCnt = procSmpCnt;
  60. p->srate = srate;
  61. p->wn = 4096;
  62. p->cfn = 1024;
  63. p->outN = p->procSmpCnt;
  64. p->x = cmMemResizeZ(cmSample_t, p->x,procSmpCnt + 3 );
  65. p->y = cmMemResizeZ(cmSample_t, p->y, p->wn );
  66. p->cf = cmMemResizeZ(cmSample_t, p->cf, p->cfn );
  67. p->pii = procSmpCnt + p->cfn;
  68. p->poi = 0;
  69. p->outV = p->y;
  70. p->prv_x0 = 0;
  71. p->prv_x1 = 0;
  72. p->genFl = true;
  73. p->xfi = 3;
  74. p->cfi = 0;
  75. p->cubeFl = true;
  76. p->linCfFl = true;
  77. assert( p->cfn+p->procSmpCnt < p->wn );
  78. unsigned i;
  79. for(i=0; i<p->cfn; ++i)
  80. {
  81. p->cf[i] = (sin(((double)i/p->cfn * M_PI) - (M_PI/2.0)) + 1.0) / 2.0;
  82. p->cf[i] = (double)i/p->cfn;
  83. }
  84. return rc;
  85. }
  86. // Algorithm:
  87. // 1. Generate srate converted values into p->y[] until it is full.
  88. // 2. Playback from y[] ignoring any incoming samples until less than
  89. // p->cfn + p->procSmpCnt samples remain in y[] (i.e. pii < procSmpCnt + cfn).
  90. // 3. At this point begin generating samples from the input and crossfading them
  91. // with the last cfn samples in y[].
  92. // 4. After cfn new samples have been crossfaded proceed to fill the remaining
  93. // space in y[]
  94. // 5. Goto 2.
  95. //
  96. // Note that since we are pitch shifting down (ratio<1.0) the number of samples generated
  97. // will always be greater than the number of input samples.
  98. //
  99. // Notes:
  100. // For small downward shifts there will be large time aliasing because the length of time
  101. // to fill the buffer (step 4) will because only a few extra samples
  102. // are generated on each input cycle. Try decreasing the window length as the pitch ratio increases.
  103. //
  104. // Implement smoothly varying ratio changes.
  105. //
  106. // Change model so that at ratio 1.0 the input is effectively being constantly cross faded to produce
  107. // identity output.
  108. void _cmPitchShiftDown( cmPitchShift* p, double ratio, const cmSample_t* x, unsigned xn )
  109. {
  110. // shift off the expired samples
  111. memmove(p->y,p->y + p->procSmpCnt, (p->pii - p->procSmpCnt) * sizeof(cmSample_t));
  112. p->pii -= p->procSmpCnt;
  113. // if not currently generating and there are less than cfn + procSmpCnt samples remaining ...
  114. if( p->genFl == false && p->pii <= p->procSmpCnt + p->cfn )
  115. {
  116. // ... then setup to begin generating
  117. p->cfi = 0;
  118. p->genFl = true;
  119. p->xfi = 3;
  120. }
  121. if( p->genFl )
  122. {
  123. // setup the incoming samples
  124. p->x[0] = p->prv_x0;
  125. p->x[1] = p->prv_x1;
  126. p->x[2] = p->prv_x2;
  127. memcpy(p->x+2,x,p->procSmpCnt*sizeof(cmSample_t));
  128. int n0 = p->cubeFl ? xn+1 : xn+2;
  129. // as long as there are incoming samples available and space left in the output buffer
  130. for(; p->xfi < n0 && p->pii < p->wn; p->xfi += ratio )
  131. {
  132. unsigned xii = floor(p->xfi);
  133. double frac = p->xfi - xii;
  134. // generate the value of the output sample
  135. cmSample_t value;
  136. if( p->cubeFl )
  137. value = _cube_interp(frac,p->x[xii-1],p->x[xii],p->x[xii+1],p->x[xii+2]);
  138. else
  139. value = p->x[ xii ] + frac * (p->x[ xii+1 ] - p->x[xii]);
  140. // if xfading
  141. if( p->cfi < p->cfn )
  142. {
  143. // calc index into y[] of the sample to crossfade with
  144. int idx = p->pii - p->cfn + p->cfi;
  145. p->y[idx] = (1.0 - p->cf[p->cfi]) * p->y[idx] + p->cf[p->cfi] * value;
  146. ++p->cfi;
  147. }
  148. else
  149. {
  150. // else fill the remaing space in y[]
  151. p->y[p->pii] = value;
  152. ++p->pii;
  153. }
  154. }
  155. // if the output buffer is full then stop generating
  156. if( p->pii == p->wn )
  157. p->genFl = false;
  158. }
  159. // reset the input index to the beginning of the buffer
  160. p->xfi -= xn;
  161. p->prv_x0 = x[xn-3];
  162. p->prv_x1 = x[xn-2];
  163. p->prv_x2 = x[xn-1];
  164. }
  165. cmRC_t cmPitchShiftExec( cmPitchShift* p, const cmSample_t* x, cmSample_t* y, unsigned n, double shiftRatio )
  166. {
  167. assert(n == p->procSmpCnt);
  168. if( shiftRatio >= 1 )
  169. memcpy(y,x,n*sizeof(cmSample_t));
  170. else
  171. {
  172. _cmPitchShiftDown(p,shiftRatio,x,n);
  173. if( y != NULL )
  174. memcpy(y,p->y,n*sizeof(cmSample_t));
  175. }
  176. return cmOkRC;
  177. }
  178. */
  179. cmRC_t cmPitchShiftFree( cmPitchShift** pp )
  180. {
  181. cmRC_t rc = cmOkRC;
  182. if( pp != NULL && *pp != NULL )
  183. {
  184. cmPitchShift* p = *pp;
  185. if(( rc = cmPitchShiftFinal(p)) == cmOkRC )
  186. {
  187. cmMemPtrFree(&p->b);
  188. cmMemPtrFree(&p->outV);
  189. cmMemPtrFree(&p->wnd);
  190. cmMemPtrFree(&p->osc[0].y);
  191. cmMemPtrFree(&p->osc[1].y);
  192. cmObjFree(pp);
  193. }
  194. }
  195. return rc;
  196. }
  197. /*
  198. cmRC_t cmPitchShiftInit( cmPitchShift* p, unsigned procSmpCnt, double srate)
  199. {
  200. cmRC_t rc;
  201. if((rc = cmPitchShiftFinal(p)) != cmOkRC )
  202. return rc;
  203. p->procSmpCnt = procSmpCnt;
  204. p->srate = srate;
  205. p->wn = 4096;
  206. p->in = 2*p->wn + p->procSmpCnt;
  207. p->outN = p->procSmpCnt;
  208. p->m = cmMemResizeZ(cmSample_t, p->m,p->in + 2 );
  209. p->x = p->m + 1;
  210. p->outV = cmMemResizeZ(cmSample_t, p->outV,procSmpCnt );
  211. p->wnd = cmMemResizeZ(cmSample_t, p->wnd, p->wn+1 );
  212. p->ii = 1;
  213. p->cubeFl = true;
  214. p->ei0 = -1;
  215. p->ei1 = -1;
  216. p->osc[0].ratio = 1.0;
  217. p->osc[0].wi = 0;
  218. p->osc[0].xi = 0;
  219. p->osc[0].yN = 2*p->wn;
  220. p->osc[0].y = cmMemResizeZ(cmSample_t, p->osc[0].y, p->osc[0].yN );
  221. p->osc[0].yii = 0;
  222. p->osc[0].yoi = 0;
  223. p->osc[0].ynn = 0;
  224. p->osc[1].ratio = 1.0;
  225. p->osc[1].wi = floor(p->wn/2);
  226. p->osc[1].xi = 0;
  227. p->osc[1].yN = 2*p->wn;
  228. p->osc[1].y = cmMemResizeZ(cmSample_t, p->osc[1].y, p->osc[1].yN );
  229. p->osc[1].yii = 0;
  230. p->osc[1].yoi = 0;
  231. p->osc[1].ynn = 0;
  232. assert( p->in >= p->procSmpCnt + 1 );
  233. cmVOS_Hann( p->wnd, p->wn+1 );
  234. return rc;
  235. }
  236. #define _isInNoGoZone(p,i) ( ((0 <= (i)) && ((i) <= (p)->ei0)) || (((p)->ii <= (i)) && ((i) <= (p)->ei1)) )
  237. #define _isNotInNoGoZone(p,i) (!_isInNoGoZone(p,i))
  238. void _startNewWindow( cmPitchShift* p, cmPitchShiftOsc_t* op, int li, double ratio)
  239. {
  240. op->wi = 0;
  241. if( op->ratio < 1.0 )
  242. op->xi = p->ii - p->procSmpCnt;
  243. else
  244. op->xi = p->ii + (li)*(p->procSmpCnt/ratio);
  245. while( op->xi < 0 )
  246. op->xi += p->in-1;
  247. while( op->xi > (p->in-1) )
  248. op->xi -= (p->in-1);
  249. op->xi = floor(op->xi);
  250. }
  251. void _cmPitchShiftOsc( cmPitchShift* p, cmPitchShiftOsc_t* op, double ratio )
  252. {
  253. int li = 0;
  254. bool contFl = 1;
  255. // if we are waiting to start a new window until the output buffer drains
  256. if( op->wi==-1 )
  257. {
  258. // if the output buffer has enough samples to complete this cycle - return
  259. if(op->ynn >= p->procSmpCnt)
  260. return;
  261. // otherwise start a new window
  262. _startNewWindow(p,op,li,ratio);
  263. }
  264. // iterate until all output samples have been generated
  265. for(li=0; contFl; ++li)
  266. {
  267. // iterate over one window or until output is complete
  268. while( op->wi < p->wn )
  269. {
  270. int wii = floor(op->wi);
  271. double frac = op->wi - wii;
  272. int xii = (op->xi + wii) % (p->in-1);
  273. cmSample_t wnd = p->wnd[ wii ] + frac * (p->wnd[wii+1] - p->wnd[wii]);
  274. cmSample_t val;
  275. // if enough samples have been generated and the next input will not be in the no-go zone
  276. if( (op->ynn >= p->procSmpCnt) && _isNotInNoGoZone(p,xii-1) && _isNotInNoGoZone(p,xii+2) )
  277. {
  278. contFl = false;
  279. break;
  280. }
  281. if( op->ynn >= op->yN )
  282. {
  283. printf("OVER\n");
  284. contFl = false;
  285. break;
  286. }
  287. // generate the value of the output sample
  288. if( p->cubeFl )
  289. val = _cube_interp(frac,p->x[xii-1],p->x[xii],p->x[xii+1],p->x[xii+2]);
  290. else
  291. val = p->x[ xii ] + frac * (p->x[ xii+1 ] - p->x[xii]);
  292. // apply the window function and assign to output
  293. op->y[op->yii] = wnd * val;
  294. // incr the count of samples in y[]
  295. ++op->ynn;
  296. // advance the output buffers input location
  297. op->yii = (op->yii + 1) % op->yN;
  298. op->wi += ratio; // increment the window location
  299. }
  300. // if a window completed
  301. if( op->wi >= p->wn )
  302. {
  303. if( (ratio < 1.0) && (op->ynn >= p->procSmpCnt) )
  304. {
  305. op->wi = -1;
  306. break;
  307. }
  308. _startNewWindow(p,op,li+1,ratio);
  309. }
  310. }
  311. }
  312. // in=5
  313. // m x
  314. // 0 1 2 3 4 5
  315. // 1 x x a b c d e
  316. // 2 c d e f g h i
  317. // 3 g h i j k l m
  318. //
  319. // ratio < 1 - the output oscillators must be able to generate 1 complete window prior to new samples
  320. // overwriting the oscillators location in the input buffer.
  321. cmRC_t cmPitchShiftExec( cmPitchShift* p, const cmSample_t* x, cmSample_t* y, unsigned xn, double ratio )
  322. {
  323. cmRC_t rc = cmOkRC;
  324. //memcpy(y,x,xn*sizeof(cmSample_t));
  325. //return rc;
  326. int i;
  327. // copy in the incoming samples
  328. for(i=0; i<xn; ++i)
  329. {
  330. p->x[p->ii] = x[i];
  331. ++p->ii;
  332. if( p->ii == p->in+1 )
  333. {
  334. p->x[-1] = p->x[p->in-2];
  335. p->x[ 0] = p->x[p->in-1];
  336. p->x[ 1] = p->x[p->in];
  337. p->ii = 2;
  338. }
  339. }
  340. // locate the section of the input buffer which
  341. // will be written over on the next cycle.
  342. // The oscillators have to avoid ending in this area
  343. if( (p->in+1) - p->ii >= p->procSmpCnt )
  344. {
  345. p->ei1 = p->ii + p->procSmpCnt - 1;
  346. p->ei0 = -1;
  347. }
  348. else
  349. {
  350. int n = (p->in+1) - p->ii;
  351. p->ei1 = (p->ii + n) - 1;
  352. p->ei0 = (p->procSmpCnt - n) - 1;
  353. }
  354. //memset(p->outV,0,p->procSmpCnt*sizeof(cmSample_t));
  355. _cmPitchShiftOsc(p, p->osc + 0, ratio );
  356. _cmPitchShiftOsc(p, p->osc + 1, ratio );
  357. // mix the indidual output of the two oscillators to form the final output
  358. if( p->osc[0].ynn < p->procSmpCnt || p->osc[1].ynn < p->procSmpCnt )
  359. printf("UNDER\n");
  360. for(i=0; i<p->procSmpCnt; ++i)
  361. {
  362. p->outV[i] = p->osc[0].y[p->osc[0].yoi] + p->osc[1].y[p->osc[1].yoi];
  363. p->osc[0].yoi = (p->osc[0].yoi + 1) % p->osc[0].yN;
  364. p->osc[1].yoi = (p->osc[1].yoi + 1) % p->osc[1].yN;
  365. }
  366. p->osc[0].ynn -= p->procSmpCnt;
  367. p->osc[1].ynn -= p->procSmpCnt;
  368. if( y != NULL )
  369. memcpy(y,p->outV,p->outN*sizeof(cmSample_t));
  370. return rc;
  371. }
  372. */
  373. cmRC_t cmPitchShiftInit( cmPitchShift* p, unsigned procSmpCnt, double srate)
  374. {
  375. cmRC_t rc;
  376. if((rc = cmPitchShiftFinal(p)) != cmOkRC )
  377. return rc;
  378. p->procSmpCnt = procSmpCnt;
  379. p->outN = procSmpCnt;
  380. p->outV = cmMemAllocZ(cmSample_t,procSmpCnt);
  381. p->wn = 2048;
  382. p->xn = 2*p->wn + procSmpCnt;
  383. p->bn = p->xn + 3;
  384. p->b = cmMemAllocZ(cmSample_t,p->bn);
  385. p->x = p->b + 1;
  386. p->wnd = cmMemAllocZ(cmSample_t,p->wn+1);
  387. p->xni = p->xn - procSmpCnt + 2;
  388. p->cubeFl = true;
  389. int i;
  390. for(i=0; i<2; ++i)
  391. {
  392. cmPitchShiftOsc_t* op = p->osc + i;
  393. op->xi = p->procSmpCnt;
  394. op->yn = p->wn * 2;
  395. op->y = cmMemAllocZ(cmSample_t,op->yn);
  396. op->yii= 0;
  397. op->yoi= 0;
  398. op->ynn= 0;
  399. op->wi = i==0 ? 0 : p->wn/2;
  400. }
  401. cmVOS_Hann(p->wnd,p->wn+1);
  402. return rc;
  403. }
  404. void _cmPitchShiftOscExec( cmPitchShift* p, cmPitchShiftOsc_t* op, double ratio )
  405. {
  406. int k = 0;
  407. // account for right buffer shift on input
  408. op->xi -= p->procSmpCnt;
  409. // pass through code for testing
  410. if(0)
  411. {
  412. int i;
  413. for(i=0; i<p->procSmpCnt; ++i)
  414. {
  415. op->y[op->yii] = p->x[ (int)floor(op->xi) ];
  416. op->yii = (op->yii + 1) % op->yn;
  417. op->ynn += 1;
  418. op->xi += 1.0;
  419. }
  420. return;
  421. }
  422. while(1)
  423. {
  424. int wii = floor(op->wi);
  425. double wfrac = op->wi - wii;
  426. int xii = floor(op->xi);
  427. double vfrac = op->xi - xii;
  428. cmSample_t val;
  429. // if enough output samples have been generated and we are outside the no-land zone
  430. if( (op->ynn >= p->procSmpCnt && op->xi >= p->procSmpCnt) )
  431. break;
  432. if( op->xi >= p->xn )
  433. {
  434. //printf("Wrap %f %f\n",op->xi,op->wi);
  435. }
  436. cmSample_t wnd = p->wnd[ wii ] + wfrac * (p->wnd[wii+1] - p->wnd[wii]);
  437. // generate the value of the output sample
  438. if( p->cubeFl )
  439. val = _cube_interp(vfrac,p->x[xii-1],p->x[xii],p->x[xii+1],p->x[xii+2]);
  440. else
  441. val = p->x[ xii ] + vfrac * (p->x[ xii+1 ] - p->x[xii]);
  442. // apply the window function and assign to output
  443. op->y[op->yii] = wnd * val;
  444. // incr the count of samples in y[]
  445. ++op->ynn;
  446. // advance the output buffers input location
  447. op->yii = (op->yii + 1) % op->yn;
  448. op->wi += ratio<1 ? 1 : ratio; // increment the window location
  449. op->xi += ratio;
  450. if( op->wi >= p->wn )
  451. {
  452. ++k;
  453. op->wi = 0;
  454. if( ratio < 1 )
  455. op->xi = p->xni; // begin of most recent block of procSmpCnt input samples
  456. else
  457. op->xi = k*p->procSmpCnt/ratio;
  458. }
  459. }
  460. //if( op->ynn != p->procSmpCnt )
  461. // printf("wi:%f xi:%f ynn:%i\n",op->wi,op->xi,op->ynn);
  462. }
  463. // b: 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17
  464. // x: -1 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16
  465. //
  466. // On each cycle:
  467. // 1) shift x[] left by procSmpCnt samples.
  468. // 2) add new samples on right side of x[]
  469. // 3) oscillator scans from right to left.
  470. cmRC_t cmPitchShiftExec( cmPitchShift* p, const cmSample_t* x, cmSample_t* y, unsigned xn, double ratio, bool bypassFl )
  471. {
  472. if(0)
  473. {
  474. memcpy(p->outV,x,xn*sizeof(cmSample_t));
  475. if( y != NULL )
  476. memcpy(y,x,xn*sizeof(cmSample_t));
  477. return cmOkRC;
  478. }
  479. if( y == NULL )
  480. return cmOkRC;
  481. if( x == NULL )
  482. {
  483. cmVOS_Zero(y,xn);
  484. return cmOkRC;
  485. }
  486. if( bypassFl )
  487. {
  488. memcpy(p->outV,x,xn*sizeof(cmSample_t));
  489. if( y != NULL )
  490. memcpy(y,x,xn*sizeof(cmSample_t));
  491. return cmOkRC;
  492. }
  493. int i;
  494. memmove(p->x - 1, p->x+p->procSmpCnt-1,(p->xn - p->procSmpCnt + 3)*sizeof(cmSample_t));
  495. memcpy( p->x + p->xni, x, xn * sizeof(cmSample_t) );
  496. //memmove(p->x + p->procSmpCnt -1, p->x - 1, (p->xn - p->procSmpCnt + 3) * sizeof(cmSample_t));
  497. //memcpy( p->x-1, x, xn * sizeof(cmSample_t));
  498. _cmPitchShiftOscExec(p, p->osc + 0, ratio );
  499. _cmPitchShiftOscExec(p, p->osc + 1, ratio );
  500. // mix the indidual output of the two oscillators to form the final output
  501. if( p->osc[0].ynn < p->procSmpCnt || p->osc[1].ynn < p->procSmpCnt )
  502. printf("UNDER\n");
  503. for(i=0; i<p->procSmpCnt; ++i)
  504. {
  505. p->outV[i] = p->osc[0].y[p->osc[0].yoi] + p->osc[1].y[p->osc[1].yoi];
  506. p->osc[0].yoi = (p->osc[0].yoi + 1) % p->osc[0].yn;
  507. p->osc[1].yoi = (p->osc[1].yoi + 1) % p->osc[1].yn;
  508. }
  509. p->osc[0].ynn -= p->procSmpCnt;
  510. p->osc[1].ynn -= p->procSmpCnt;
  511. if( y != NULL )
  512. memcpy(y,p->outV,xn*sizeof(cmSample_t));
  513. return cmOkRC;
  514. }
  515. //=======================================================================================================================
  516. cmLoopRecord* cmLoopRecordAlloc(
  517. cmCtx* c, cmLoopRecord* p, unsigned procSmpCnt, unsigned maxRecdSmpCnt, unsigned xfadeSmpCnt )
  518. {
  519. cmLoopRecord* op = cmObjAlloc(cmLoopRecord, c, p );
  520. if( procSmpCnt != 0 )
  521. if( cmLoopRecordInit(op, procSmpCnt, maxRecdSmpCnt, xfadeSmpCnt) != cmOkRC )
  522. cmLoopRecordFree(&op);
  523. return op;
  524. }
  525. /*
  526. cmRC_t cmLoopRecordFree( cmLoopRecord** pp )
  527. {
  528. cmRC_t rc = cmOkRC;
  529. if( pp != NULL && *pp != NULL )
  530. {
  531. cmLoopRecord* p = *pp;
  532. if(( rc = cmLoopRecordFinal(p)) == cmOkRC )
  533. {
  534. cmMemPtrFree(&p->bufMem);
  535. cmMemPtrFree(&p->bufArray);
  536. cmMemPtrFree(&p->outV);
  537. cmMemPtrFree(&p->xfadeFunc);
  538. cmObjFree(pp);
  539. }
  540. }
  541. return rc;
  542. }
  543. cmRC_t cmLoopRecordInit( cmLoopRecord* p, unsigned procSmpCnt, unsigned maxRecdSmpCnt, unsigned xfadeSmpCnt )
  544. {
  545. cmRC_t rc;
  546. unsigned i;
  547. if((rc = cmLoopRecordFinal(p)) != cmOkRC )
  548. return rc;
  549. assert( xfadeSmpCnt < maxRecdSmpCnt );
  550. p->maxRecdSmpCnt = maxRecdSmpCnt;
  551. p->bufArrayCnt = 2;
  552. p->bufMem = cmMemResizeZ( cmSample_t, p->bufMem, maxRecdSmpCnt * p->bufArrayCnt );
  553. p->bufArray = cmMemResizeZ( cmLoopRecdBuf, p->bufArray, p->bufArrayCnt );
  554. p->outV = cmMemResizeZ( cmSample_t, p->outV, procSmpCnt );
  555. p->xfadeFunc = cmMemResizeZ( cmSample_t, p->xfadeFunc, xfadeSmpCnt+1 );
  556. p->outN = procSmpCnt;
  557. p->procSmpCnt = procSmpCnt;
  558. p->xfadeSmpCnt = xfadeSmpCnt;
  559. p->recdBufIdx = 0;
  560. p->playBufIdx = 1;
  561. p->recdFl = false;
  562. p->playFl = false;
  563. for(i=0; i<p->bufArrayCnt; ++i)
  564. {
  565. p->bufArray[i].bV = p->bufMem + (i * maxRecdSmpCnt);
  566. p->bufArray[i].bN = maxRecdSmpCnt;
  567. p->bufArray[i].xfi = xfadeSmpCnt;
  568. }
  569. for(i=0; i<=p->xfadeSmpCnt; ++i)
  570. p->xfadeFunc[i] = (cmReal_t)i/p->xfadeSmpCnt;
  571. return rc;
  572. }
  573. cmRC_t cmLoopRecordFinal( cmLoopRecord* p )
  574. { return cmOkRC; }
  575. cmRC_t cmLoopRecordExec( cmLoopRecord* p, const cmSample_t* x, cmSample_t* y, unsigned xn, bool recdFl, bool playFl )
  576. {
  577. unsigned i;
  578. // if the recdFl was enabled
  579. if(recdFl==true && p->recdFl==false)
  580. {
  581. p->recdFl = true;
  582. p->bufArray[p->recdBufIdx].bii = 0;
  583. p->bufArray[p->recdBufIdx].boi = 0;
  584. printf("Recd:on %i\n",p->recdBufIdx);
  585. }
  586. else
  587. // if the recdFl was disabled
  588. if( recdFl==false && p->recdFl==true )
  589. {
  590. p->recdFl = false;
  591. playFl = true;
  592. p->playBufIdx = p->recdBufIdx;
  593. p->recdBufIdx = (p->recdBufIdx + 1) % p->bufArrayCnt;
  594. printf("Recd:off\n");
  595. }
  596. // if the playFl triggered on
  597. if( playFl==true && p->playFl==false)
  598. {
  599. p->bufArray[p->playBufIdx].boi = 0;
  600. p->playFl = true;
  601. //printf("Play:on %i %i\n",p->playBufIdx,p->bufArray[p->playBufIdx].bii);
  602. }
  603. // if recording
  604. if( p->recdFl )
  605. {
  606. cmLoopRecdBuf* rp = p->bufArray + p->recdBufIdx;
  607. for(i=0; i<xn && rp->bii < rp->bN; ++i,++rp->bii)
  608. {
  609. rp->bV[ rp->bii ] = x[i];
  610. }
  611. p->recdFl = rp->bii != rp->bN;
  612. }
  613. // if playing
  614. if( p->playFl )
  615. {
  616. cmLoopRecdBuf* rp = p->bufArray + p->playBufIdx;
  617. unsigned xf0n = p->xfadeSmpCnt/2;
  618. unsigned xf1n = rp->bii - p->xfadeSmpCnt/2;
  619. unsigned xfi0 = (rp->boi + p->xfadeSmpCnt/2) % rp->bii;
  620. for(i=0; i<xn; ++i)
  621. {
  622. bool fl = rp->boi < xf0n || rp->boi > xf1n;
  623. cmSample_t env = fl ? p->xfadeFunc[ rp->xfi ] : 1;
  624. p->outV[i] = ((1.0-env) * rp->bV[ rp->boi ]) + (env * rp->bV[ xfi0 ]);
  625. rp->boi = (rp->boi + 1) % rp->bii;
  626. xfi0 = (xfi0 + 1) % rp->bii;
  627. }
  628. }
  629. if( y != NULL )
  630. memcpy(y,p->outV,xn*sizeof(cmSample_t));
  631. return cmOkRC;
  632. }
  633. */
  634. cmRC_t cmLoopRecordFree( cmLoopRecord** pp )
  635. {
  636. cmRC_t rc = cmOkRC;
  637. if( pp != NULL && *pp != NULL )
  638. {
  639. cmLoopRecord* p = *pp;
  640. if(( rc = cmLoopRecordFinal(p)) == cmOkRC )
  641. {
  642. cmMemPtrFree(&p->bufMem);
  643. cmMemPtrFree(&p->bufArray);
  644. cmMemPtrFree(&p->outV);
  645. cmObjFree(pp);
  646. }
  647. }
  648. return rc;
  649. }
  650. cmRC_t cmLoopRecordInit( cmLoopRecord* p, unsigned procSmpCnt, unsigned maxRecdSmpCnt, unsigned xfadeSmpCnt )
  651. {
  652. cmRC_t rc;
  653. unsigned i;
  654. if((rc = cmLoopRecordFinal(p)) != cmOkRC )
  655. return rc;
  656. assert( xfadeSmpCnt < maxRecdSmpCnt );
  657. p->maxRecdSmpCnt = maxRecdSmpCnt;
  658. p->bufArrayCnt = 2;
  659. p->bufMem = cmMemResizeZ( cmSample_t, p->bufMem, (maxRecdSmpCnt+3) * p->bufArrayCnt * 2 );
  660. p->bufArray = cmMemResizeZ( cmLoopRecdBuf, p->bufArray, p->bufArrayCnt );
  661. p->outV = cmMemResizeZ( cmSample_t, p->outV, procSmpCnt );
  662. p->outN = procSmpCnt;
  663. p->procSmpCnt = procSmpCnt;
  664. p->xfadeSmpCnt = xfadeSmpCnt;
  665. p->recdBufIdx = 0;
  666. p->playBufIdx = 1;
  667. p->recdFl = false;
  668. p->playFl = false;
  669. for(i=0; i<p->bufArrayCnt; ++i)
  670. {
  671. p->bufArray[i].xV = p->bufMem + ((2 * i + 0) * (maxRecdSmpCnt+3)) + 1;
  672. p->bufArray[i].xN = maxRecdSmpCnt;
  673. p->bufArray[i].xii = 0;
  674. p->bufArray[i].wV = p->bufMem + ((2 * i + 1) * (maxRecdSmpCnt+3));
  675. }
  676. return rc;
  677. }
  678. cmRC_t cmLoopRecordFinal( cmLoopRecord* p )
  679. { return cmOkRC; }
  680. void _cmLoopRecordOscExec( cmLoopRecord* p, cmLoopRecdBuf* rp, cmLoopRecdOsc* op, double ratio )
  681. {
  682. unsigned i;
  683. for(i=0; i<p->outN; ++i)
  684. {
  685. int xi = floor(op->xi);
  686. double vfrac = op->xi - xi;
  687. cmSample_t val = _cube_interp(vfrac,rp->xV[xi-1],rp->xV[xi],rp->xV[xi+1],rp->xV[xi+2]);
  688. int wi = floor(op->wi);
  689. double wfrac = op->wi - wi;
  690. cmSample_t wnd = rp->wV[ wi ] + wfrac * (rp->wV[wi+1] - rp->wV[wi]);
  691. wnd = (wnd - 0.5) * op->u + 0.5;
  692. p->outV[i] += wnd * val;
  693. op->wi += ratio;
  694. if( op->wi >= rp->xii )
  695. {
  696. op->wi -= rp->xii;
  697. op->u *= -1.0;
  698. }
  699. op->xi += ratio;
  700. if( op->xi >= rp->xii )
  701. op->xi -= rp->xii;
  702. }
  703. }
  704. //
  705. // a b c d e f g h i - osc 0 sample value
  706. // 0.0 .25 0.5 .75 1.0 1.0 .75 0.5 .25 - osc 0 window value
  707. //
  708. // e f g h i a b c d - osc 1 sample value
  709. // 1.0 .75 0.5 .25 0.0 0.0 .25 0.5 .75 - osc 1 window value
  710. //
  711. // Notes:
  712. // 1) The window values transition through zero
  713. // at the loop point.
  714. // 2)
  715. cmRC_t cmLoopRecordExec( cmLoopRecord* p, const cmSample_t* x, cmSample_t* y, unsigned xn, bool bypassFl, bool recdFl, bool playFl, double ratio, double pgain, double rgain )
  716. {
  717. int i,j;
  718. assert( xn <= p->outN );
  719. if( bypassFl )
  720. {
  721. memcpy(p->outV,x,xn*sizeof(cmSample_t));
  722. if( y != NULL )
  723. {
  724. //memcpy(y,x,xn*sizeof(cmSample_t));
  725. cmVOS_MultVVS(y,xn,x,pgain);
  726. }
  727. return cmOkRC;
  728. }
  729. // if the recdFl was enabled
  730. if(recdFl==true && p->recdFl==false)
  731. {
  732. p->recdFl = true;
  733. p->bufArray[p->recdBufIdx].xii = 0;
  734. //printf("Recd:on %i\n",p->recdBufIdx);
  735. }
  736. else
  737. // if the recdFl was disabled
  738. if( recdFl==false && p->recdFl==true )
  739. {
  740. cmLoopRecdBuf* rp = p->bufArray + p->recdBufIdx;
  741. // arrange the 'wrap-around' samples
  742. rp->xV[-1] = rp->xV[rp->xii-1];
  743. rp->xV[rp->xii ] = rp->xV[0];
  744. rp->xV[rp->xii+1] = rp->xV[1];
  745. // calc the length of the cross-fade
  746. if( rp->xii < p->xfadeSmpCnt * 2)
  747. rp->xfN = rp->xii/2;
  748. else
  749. rp->xfN = p->xfadeSmpCnt;
  750. assert( rp->xfN > 0 );
  751. // fill the crossfade window with zeros
  752. cmVOS_Zero(rp->wV,rp->xii);
  753. // fill the last xfN samples in the xfade window vector with a fade-in slope
  754. int xfi = rp->xii - rp->xfN;
  755. for(j=0; j<rp->xfN; ++j)
  756. rp->wV[xfi+j] = (cmSample_t)j/rp->xfN;
  757. // initialize the oscillators
  758. for(j=0; j<2; ++j)
  759. {
  760. //
  761. rp->osc[j].xi = j==0 ? 0.0 : rp->xfN; // oscillators are p->xfN samples out of phase
  762. rp->osc[j].u = j==0 ? 1.0 : -1.0; // set windows to have opposite polarity
  763. rp->osc[j].wi = xfi; // begin window at cross-fade
  764. }
  765. p->recdFl = false;
  766. p->playFl = true;
  767. p->playBufIdx = p->recdBufIdx;
  768. p->recdBufIdx = (p->recdBufIdx + 1) % p->bufArrayCnt;
  769. //printf("Recd:off\n");
  770. }
  771. // if recording
  772. if( p->recdFl )
  773. {
  774. cmLoopRecdBuf* rp = p->bufArray + p->recdBufIdx;
  775. for(i=0; i<xn && rp->xii < rp->xN; ++i,++rp->xii)
  776. {
  777. rp->xV[ rp->xii ] = x[i];
  778. }
  779. }
  780. if( playFl && p->bufArray[p->playBufIdx].xii > 0 )
  781. {
  782. p->playFl = !p->playFl;
  783. if( p->playFl )
  784. {
  785. // reset oscillators to start at the begin of loop
  786. }
  787. }
  788. if( p->playFl )
  789. {
  790. cmLoopRecdBuf* rp = p->bufArray + p->playBufIdx;
  791. cmVOS_Zero(p->outV,p->outN);
  792. _cmLoopRecordOscExec(p,rp, rp->osc + 0, ratio );
  793. _cmLoopRecordOscExec(p,rp, rp->osc + 1, ratio );
  794. }
  795. if( y != NULL )
  796. {
  797. //memcpy(y,p->outV,xn*sizeof(cmSample_t));
  798. for(i=0; i<p->outN; ++i)
  799. y[i] = (pgain * x[i]) + (rgain * p->outV[i]);
  800. }
  801. return cmOkRC;
  802. }
  803. //=======================================================================================================================
  804. cmGateDetect* cmGateDetectAlloc( cmCtx* c, cmGateDetect* p, unsigned procSmpCnt, cmReal_t onThreshPct, cmReal_t onThreshDb, cmReal_t offThreshDb )
  805. {
  806. cmGateDetect* op = cmObjAlloc(cmGateDetect, c, p );
  807. if( procSmpCnt != 0 )
  808. if( cmGateDetectInit(op, procSmpCnt, onThreshPct, onThreshDb, offThreshDb) != cmOkRC )
  809. cmGateDetectFree(&op);
  810. return op;
  811. }
  812. cmRC_t cmGateDetectFree( cmGateDetect** pp )
  813. {
  814. cmRC_t rc;
  815. if( pp==NULL || *pp == NULL )
  816. return cmOkRC;
  817. cmGateDetect* p = *pp;
  818. if((rc = cmGateDetectFinal(p)) != cmOkRC )
  819. return rc;
  820. cmMemPtrFree(&p->rmsV);
  821. cmMemPtrFree(&p->wndV);
  822. cmObjFree(pp);
  823. return cmOkRC;
  824. }
  825. cmRC_t cmGateDetectInit( cmGateDetect* p, unsigned procSmpCnt, cmReal_t onThreshPct, cmReal_t onThreshDb, cmReal_t offThreshDb )
  826. {
  827. cmRC_t rc;
  828. if((rc = cmGateDetectFinal(p)) != cmOkRC )
  829. return rc;
  830. p->rmsN = 3;
  831. p->rmsV = cmMemResizeZ(cmSample_t,p->rmsV,p->rmsN);
  832. p->wndN = 9;
  833. p->wndV = cmMemResizeZ(cmSample_t,p->wndV,p->wndN);
  834. p->rms = 0;
  835. p->durSmpCnt = 0;
  836. p->gateFl = false;
  837. p->deltaFl = false;
  838. p->onThreshPct = onThreshPct;
  839. p->onThreshDb = onThreshDb;
  840. p->offThreshDb = offThreshDb;
  841. return rc;
  842. }
  843. cmRC_t cmGateDetectFinal(cmGateDetect* p )
  844. {
  845. return cmOkRC;
  846. }
  847. cmRC_t cmGateDetectExec22( cmGateDetect* p, const cmSample_t* x, unsigned xn )
  848. {
  849. p->deltaFl = false;
  850. p->rms = cmVOS_RMS(x,xn,xn);
  851. cmReal_t db = p->rms==0 ? -100 : 20*log10(p->rms);
  852. //cmSample_t b0 = 0;
  853. cmSample_t b1 = 0;
  854. cmVOS_Shift(p->rmsV,p->rmsN,-1,p->rms);
  855. // if gate is on
  856. if( p->gateFl )
  857. {
  858. p->deltaFl = db < p->offThreshDb;
  859. }
  860. else
  861. {
  862. //cmVOS_Lsq1(NULL,p->rmsV,p->rmsN,&b0,&b1);
  863. // p->deltaFl = b1 > p->onThreshPct && db > p->onThreshDb;
  864. unsigned i;
  865. for(i=0; i<p->rmsN-1; ++i)
  866. b1 += p->rmsV[i+1] - p->rmsV[i];
  867. b1 /= p->rmsN;
  868. p->deltaFl = b1 > p->onThreshPct && db > p->onThreshDb;
  869. }
  870. if( p->deltaFl )
  871. {
  872. p->gateFl = !p->gateFl;
  873. p->durSmpCnt = xn;
  874. }
  875. else
  876. {
  877. p->durSmpCnt += xn;
  878. }
  879. //p->rms = b1;
  880. //printf("%f %f %i %f;\n",db,p->rms,p->deltaFl,b1);
  881. return cmOkRC;
  882. }
  883. cmRC_t cmGateDetectExec( cmGateDetect* p, const cmSample_t* x, unsigned xn )
  884. {
  885. p->deltaFl = false;
  886. p->rms = cmVOS_RMS(x,xn,xn);
  887. cmReal_t db = p->rms==0 ? -100 : 20*log10(p->rms);
  888. unsigned i;
  889. cmSample_t d = 0;
  890. // update the rms window
  891. cmVOS_Shift(p->rmsV,p->rmsN,-1,p->rms);
  892. // calc. derr of RMS
  893. for(i=0; i<p->rmsN-1; ++i)
  894. d += p->rmsV[i+1] - p->rmsV[i];
  895. d /= p->rmsN;
  896. // zero negative derr's
  897. d = d<0 ? 0 : d;
  898. // update the peak window
  899. cmVOS_Shift(p->wndV,p->wndN,-1,d);
  900. p->mean = cmVOS_Mean(p->wndV,p->wndN);
  901. // if this is an offset
  902. if( p->gateFl && db < p->offThreshDb )
  903. {
  904. p->gateFl = false;
  905. p->deltaFl = true;
  906. }
  907. else
  908. // if this may be an onset.
  909. if( db > p->onThreshDb )
  910. {
  911. i = p->wndN - 2;
  912. // if previous derr was a peak
  913. if( p->wndV[i]>0 && p->wndV[i-1] < p->wndV[i] && p->wndV[i] > p->wndV[i+1] )
  914. {
  915. // and the peak is the largest value in the exteneded window
  916. if( p->wndV[i] > p->mean )
  917. {
  918. p->deltaFl = true;
  919. p->gateFl = true;
  920. p->durSmpCnt = 0;
  921. }
  922. }
  923. }
  924. if( p->gateFl )
  925. p->durSmpCnt += xn;
  926. p->rms = p->d0;
  927. p->d0 = d;
  928. return cmOkRC;
  929. }
  930. //=======================================================================================================================
  931. cmGateDetect2* cmGateDetectAlloc2( cmCtx* c, cmGateDetect2* p, unsigned procSmpCnt, const cmGateDetectParams* args )
  932. {
  933. cmGateDetect2* op = cmObjAlloc(cmGateDetect2, c, p );
  934. if( procSmpCnt != 0 )
  935. if( cmGateDetectInit2(op, procSmpCnt, args) != cmOkRC )
  936. cmGateDetectFree2(&op);
  937. return op;
  938. }
  939. cmRC_t cmGateDetectFree2( cmGateDetect2** pp )
  940. {
  941. cmRC_t rc;
  942. if( pp==NULL || *pp == NULL )
  943. return cmOkRC;
  944. cmGateDetect2* p = *pp;
  945. if((rc = cmGateDetectFinal2(p)) != cmOkRC )
  946. return rc;
  947. cmMemPtrFree(&p->medV);
  948. cmObjFree(pp);
  949. return cmOkRC;
  950. }
  951. cmRC_t cmGateDetectInit2( cmGateDetect2* p, unsigned procSmpCnt, const cmGateDetectParams* args )
  952. {
  953. cmRC_t rc;
  954. if((rc = cmGateDetectFinal2(p)) != cmOkRC )
  955. return rc;
  956. unsigned pkCnt = 3;
  957. unsigned eleCnt = 3*args->medCnt + args->avgCnt + args->suprCnt + args->offCnt + pkCnt;
  958. unsigned i;
  959. p->args = *args;
  960. p->medV = cmMemResizeZ(cmSample_t,p->medV,eleCnt);
  961. p->fcofV = p->medV + args->medCnt;
  962. p->fdlyV = p->fcofV + args->medCnt;
  963. p->avgV = p->fdlyV + args->medCnt;
  964. p->suprV = p->avgV + args->avgCnt;
  965. p->offV = p->suprV + args->suprCnt;
  966. p->pkV = p->offV + args->offCnt;
  967. assert( p->medV + eleCnt == p->pkV + pkCnt );
  968. p->medIdx = 0;
  969. p->avgIdx = 0;
  970. p->suprIdx = args->suprCnt;
  971. p->offIdx = 0;
  972. p->pkFl = false;
  973. p->gateFl = false;
  974. p->onFl = false;
  975. p->offFl = false;
  976. cmGateDetectSetOnThreshDb2(p,args->onThreshDb);
  977. cmGateDetectSetOnThreshDb2(p,args->offThreshDb);
  978. p->fcofV[0] = 1.0;
  979. for(i=1; i<args->medCnt; ++i)
  980. {
  981. p->fcofV[i] = (1.0 - 1.0/args->medCnt) / ( pow(2.0,i-1) );
  982. //printf("%i %f ",i,p->fcofV[i]);
  983. }
  984. for(i=0; i<args->suprCnt; ++i)
  985. {
  986. p->suprV[i] = 1.0/pow(args->suprCoeff,i + 1.0);
  987. //printf("%i %f ",i,p->suprV[i]);
  988. }
  989. return rc;
  990. }
  991. cmRC_t cmGateDetectFinal2(cmGateDetect2* p )
  992. { return cmOkRC; }
  993. void _cmGateDetectPickPeak( cmGateDetect2* p, cmSample_t input )
  994. {
  995. p->pkV[0] = p->pkV[1];
  996. p->pkV[1] = p->pkV[2];
  997. p->pkV[2] = input;
  998. // if supression is active - apply it to the center pkV[]
  999. if( p->suprIdx < p->args.suprCnt )
  1000. {
  1001. p->pkV[1] -= p->pkV[1] * p->suprV[p->suprIdx];
  1002. p->suprIdx = (p->suprIdx + 1) % p->args.suprCnt;
  1003. }
  1004. p->sup = p->pkV[1];
  1005. // if the center value in pkV[] is a local peak and above the onset threshold
  1006. if( p->pkV[1] > p->onThresh && p->pkV[0] < p->pkV[1] && p->pkV[1] > p->pkV[2] )
  1007. {
  1008. p->suprIdx = 0;
  1009. p->gateFl = true;
  1010. p->onFl = true;
  1011. }
  1012. // update the offset buffer
  1013. p->offV[p->offIdx] = fabs(p->pkV[2]);
  1014. p->offIdx = (p->offIdx + 1) % p->args.offCnt;
  1015. // if this is an offset
  1016. if( p->gateFl==true && cmVOS_Mean(p->offV,p->args.offCnt) < p->offThresh )
  1017. {
  1018. p->gateFl = false;
  1019. p->offFl = true;
  1020. }
  1021. }
  1022. void _cmGateDetectPickPeak2( cmGateDetect2* p, cmSample_t input )
  1023. {
  1024. // if supression is active - apply it to the input
  1025. if( p->suprIdx < p->args.suprCnt )
  1026. {
  1027. input -= input * p->suprV[p->suprIdx];
  1028. ++p->suprIdx;// = (p->suprIdx + 1) % p->args.suprCnt;
  1029. }
  1030. // update the peak buffer
  1031. p->pkV[0] = p->pkV[1];
  1032. p->pkV[1] = p->pkV[2];
  1033. p->pkV[2] = input;
  1034. p->sup = input;
  1035. // if the signal increased above the threshold and is not already waiting for a peak
  1036. if( p->pkV[1] < input && input > p->onThresh && p->pkFl == false )
  1037. {
  1038. p->pkFl = true;
  1039. p->gateFl = true;
  1040. p->onFl = true;
  1041. }
  1042. // if the center value in pkV[] is a local peak and above the onset threshold ...
  1043. if( p->gateFl && p->pkFl && p->pkV[0] < p->pkV[1] && p->pkV[1] > p->pkV[2] )
  1044. {
  1045. p->suprIdx = 0; // ... turn on supression
  1046. p->pkFl = false; // ... not longer waiting for the peak
  1047. }
  1048. // update the offset buffer
  1049. p->offV[p->offIdx] = fabs(input);
  1050. p->offIdx = (p->offIdx + 1) % p->args.offCnt;
  1051. // if this is an offset
  1052. if( p->gateFl==true && cmVOS_Mean(p->offV,p->args.offCnt) < p->offThresh )
  1053. {
  1054. p->gateFl = false;
  1055. p->offFl = true;
  1056. p->pkFl = false;
  1057. }
  1058. }
  1059. cmRC_t cmGateDetectExec2( cmGateDetect2* p, const cmSample_t* x, unsigned xn )
  1060. {
  1061. p->rms = cmVOS_RMS(x,xn,xn); // take RMS of incoming window
  1062. p->medV[ p->medIdx ] = p->rms; // input RMS to median filter
  1063. p->medIdx = (p->medIdx + 1) % p->args.medCnt;
  1064. p->med = cmVOS_Median(p->medV,p->args.medCnt); // calc the median
  1065. p->dif = cmMax(0,p->rms - p->med); // dif = half_rect( rms - med )
  1066. p->avgV[ p->avgIdx ] = p->dif; // input dif to avg filter
  1067. p->avgIdx = (p->avgIdx + 1) % p->args.avgCnt;
  1068. p->avg = cmVOS_Mean(p->avgV,p->args.avgCnt); // calc the avg
  1069. p->ons = p->dif - p->avg; // ons = dif - avg
  1070. cmVOS_Shift(p->fdlyV,p->args.medCnt,1,p->ons);
  1071. p->flt = cmVOS_MultSumVV(p->fdlyV,p->fcofV,p->args.medCnt);
  1072. p->offFl = false;
  1073. p->onFl = false;
  1074. _cmGateDetectPickPeak2(p,p->flt);
  1075. return cmOkRC;
  1076. }
  1077. void _cmGateDetectSetDb2( cmGateDetect2* p, cmReal_t db, cmReal_t* dbPtr )
  1078. {
  1079. *dbPtr = pow(10.0, db/20.0 );
  1080. }
  1081. void cmGateDetectSetOnThreshDb2( cmGateDetect2* p, cmReal_t db )
  1082. { _cmGateDetectSetDb2(p,db,&p->onThresh); }
  1083. void cmGateDetectSetOffThreshDb2( cmGateDetect2* p, cmReal_t db )
  1084. { _cmGateDetectSetDb2(p,db,&p->offThresh); }
  1085. //=======================================================================================================================
  1086. cmAutoGain* cmAutoGainAlloc( cmCtx* c, cmAutoGain* p, unsigned procSmpCnt, cmReal_t srate, cmReal_t hopMs, unsigned chCnt, const cmGateDetectParams* gd_args )
  1087. {
  1088. cmAutoGain* op = cmObjAlloc(cmAutoGain, c, p );
  1089. op->sbp = cmShiftBufAlloc(c,NULL,0,0,0);
  1090. op->gdp = cmGateDetectAlloc2(c,NULL,0,NULL);
  1091. if( procSmpCnt != 0 )
  1092. if( cmAutoGainInit(op, procSmpCnt, srate, hopMs, chCnt, gd_args) != cmOkRC )
  1093. cmAutoGainFree(&op);
  1094. return op;
  1095. }
  1096. cmRC_t cmAutoGainFree( cmAutoGain** pp )
  1097. {
  1098. cmRC_t rc;
  1099. if( pp==NULL || *pp == NULL )
  1100. return cmOkRC;
  1101. cmAutoGain* p = *pp;
  1102. if((rc = cmAutoGainFinal(p)) != cmOkRC )
  1103. return rc;
  1104. cmMemPtrFree(&p->chArray);
  1105. p->chCnt = 0;
  1106. cmShiftBufFree(&p->sbp);
  1107. cmGateDetectFree2(&p->gdp);
  1108. cmObjFree(pp);
  1109. return cmOkRC;
  1110. }
  1111. cmRC_t cmAutoGainInit( cmAutoGain* p, unsigned procSmpCnt, cmReal_t srate, cmReal_t hopMs, unsigned chCnt, const cmGateDetectParams* gd_args )
  1112. {
  1113. unsigned i;
  1114. cmRC_t rc;
  1115. if((rc = cmAutoGainFinal(p)) != cmOkRC )
  1116. return rc;
  1117. unsigned hopSmpCnt = (unsigned)floor(srate * hopMs / 1000.0);
  1118. unsigned wndSmpCnt = hopSmpCnt * gd_args->medCnt;
  1119. cmShiftBufInit(p->sbp,procSmpCnt,wndSmpCnt,hopSmpCnt);
  1120. cmGateDetectInit2(p->gdp,procSmpCnt,gd_args);
  1121. p->chCnt = chCnt;
  1122. p->chArray = cmMemResizeZ(cmAutoGainCh,p->chArray,p->chCnt);
  1123. p->chp = NULL;
  1124. for(i=0; i<p->chCnt; ++i)
  1125. p->chArray[i].id = cmInvalidIdx;
  1126. return rc;
  1127. }
  1128. cmRC_t cmAutoGainFinal( cmAutoGain* p )
  1129. { return cmOkRC;}
  1130. void _cmAutoGainChannelFinish( cmAutoGain* p )
  1131. {
  1132. if( p->chp != NULL )
  1133. {
  1134. if( p->gateMax != 0 )
  1135. {
  1136. p->gateSum += p->gateMax;
  1137. p->gateCnt += 1;
  1138. }
  1139. p->chp->gateMaxAvg = p->gateCnt == 0 ? 0.0 : p->gateSum / p->gateCnt;
  1140. }
  1141. }
  1142. cmRC_t cmAutoGainStartCh( cmAutoGain* p, unsigned id )
  1143. {
  1144. cmReal_t rmsMax = 1.0;
  1145. unsigned i;
  1146. if( id == cmInvalidIdx )
  1147. return cmOkRC;
  1148. // do intermediate channel calculations on the last selected channel
  1149. if( p->chp != NULL )
  1150. _cmAutoGainChannelFinish( p );
  1151. // if 'id' has already been used
  1152. // then select the associated channel as the current channel
  1153. // otherwise select the next avail channel as the current channel
  1154. for(i=0; i<p->chCnt; ++i)
  1155. if( p->chArray[i].id == id || p->chArray[i].id == cmInvalidId )
  1156. {
  1157. p->chp = p->chArray + i;
  1158. break;
  1159. }
  1160. if( p->chp == NULL )
  1161. return cmCtxRtCondition( &p->obj, cmArgAssertRC, "All channels are in use.");
  1162. p->chp->id = id;
  1163. p->gateCnt = 0;
  1164. p->gateSum = 0;
  1165. p->gateMax = 0;
  1166. p->minRms = rmsMax;
  1167. return cmOkRC;
  1168. }
  1169. // The goal of this process is to locate the max RMS value during
  1170. // the duration of each note. When all the notes have been processed for
  1171. // a given channel the average maximum value for all of the notes is
  1172. // then calculated.
  1173. cmRC_t cmAutoGainProcCh( cmAutoGain* p, const cmSample_t* x, unsigned xn )
  1174. {
  1175. // shift the new samples into the shift buffer
  1176. while(cmShiftBufExec(p->sbp,x,xn))
  1177. {
  1178. // update the gate detector
  1179. cmGateDetectExec2(p->gdp,p->sbp->outV,p->sbp->outN);
  1180. // write the output matrix file
  1181. //if( _cmPuWriteMtxFile(p,segFl) != kOkPuRC )
  1182. // goto errLabel;
  1183. // if this frame is an RMS minimum or onset or offset
  1184. // then select it as a possible segment end.
  1185. // Note that for onsets this will effectively force the end to
  1186. // come after the onset because the onset will not be an energy minimum
  1187. // relative to subsequent frames.
  1188. if( p->gdp->rms < p->minRms || p->gdp->onFl || p->gdp->offFl )
  1189. {
  1190. p->minRms = p->gdp->rms;
  1191. // count onsets
  1192. if( p->gdp->onFl )
  1193. ++p->chp->onCnt;
  1194. // count offsets
  1195. if( p->gdp->offFl )
  1196. {
  1197. ++p->chp->offCnt;
  1198. // update the gate sum and count
  1199. p->gateSum += p->gateMax;
  1200. p->gateCnt += 1;
  1201. p->gateMax = 0;
  1202. }
  1203. }
  1204. // track the max RMS value during this gate
  1205. if( p->gdp->gateFl && p->gdp->rms > p->gateMax )
  1206. p->gateMax = p->gdp->rms;
  1207. }
  1208. return cmOkRC;
  1209. }
  1210. cmRC_t cmAutoGainCalcGains( cmAutoGain* p )
  1211. {
  1212. unsigned i;
  1213. cmReal_t avg = 0;
  1214. if( p->chCnt == 0 )
  1215. return cmOkRC;
  1216. // verify that all channels were input
  1217. for(i=0; i<p->chCnt; ++i)
  1218. if( p->chArray[i].id == cmInvalidId )
  1219. break;
  1220. if( i != p->chCnt )
  1221. return cmCtxRtCondition( &p->obj, cmArgAssertRC, "All channels must be set prior to calculating gains.");
  1222. // process the last channel
  1223. _cmAutoGainChannelFinish(p);
  1224. // p->chp isn't used again unless we restart the indidual channel processing
  1225. p->chp = NULL;
  1226. for(i=0; i<p->chCnt; ++i)
  1227. avg += p->chArray[i].gateMaxAvg;
  1228. avg /= p->chCnt;
  1229. for(i=0; i<p->chCnt; ++i)
  1230. {
  1231. cmReal_t d = p->chArray[i].gateMaxAvg==0 ? 1.0 : p->chArray[i].gateMaxAvg;
  1232. p->chArray[i].gain = avg / d;
  1233. }
  1234. return cmOkRC;
  1235. }
  1236. void cmAutoGainPrint( cmAutoGain* p, cmRpt_t* rpt )
  1237. {
  1238. unsigned i=0;
  1239. for(i=0; i<p->chCnt; ++i)
  1240. {
  1241. cmAutoGainCh* chp = p->chArray + i;
  1242. cmRptPrintf(rpt,"midi:%3i %4s on:%i off:%i avg:%5.5f gain:%5.5f\n",
  1243. chp->id,
  1244. cmStringNullGuard(cmMidiToSciPitch(chp->id,NULL,0)),
  1245. chp->onCnt, chp->offCnt, chp->gateMaxAvg, chp->gain );
  1246. }
  1247. }
  1248. //==========================================================================================================================================
  1249. cmChCfg* cmChCfgAlloc( cmCtx* c, cmChCfg* p, cmCtx_t* ctx, const cmChar_t* fn )
  1250. {
  1251. cmChCfg* op = cmObjAlloc(cmChCfg, c, p );
  1252. if( fn != NULL )
  1253. if( cmChCfgInit( op, ctx, fn ) != cmOkRC )
  1254. cmChCfgFree(&op);
  1255. return op;
  1256. }
  1257. cmRC_t cmChCfgFree( cmChCfg** pp )
  1258. {
  1259. cmRC_t rc = cmOkRC;
  1260. if( pp == NULL || *pp == NULL )
  1261. return cmOkRC;
  1262. cmChCfg* p = *pp;
  1263. if((rc = cmChCfgFinal(p)) != cmOkRC )
  1264. return rc;
  1265. cmMemPtrFree(&p->chArray);
  1266. cmFsFreeFn(p->fn);
  1267. cmObjFree(pp);
  1268. return cmOkRC;
  1269. }
  1270. enum { kChColIdx, kSsiColIdx, kPitchColIdx, kMidiColIdx, kGainColIdx, kNsFlColIdx, kCdFlColIdx, kColCnt };
  1271. cmRC_t cmChCfgInit( cmChCfg* p, cmCtx_t* ctx, const cmChar_t* fn )
  1272. {
  1273. cmRC_t rc = cmOkRC;
  1274. unsigned i,j;
  1275. const cmChar_t* ch_array_label = "ch_array";
  1276. typedef struct
  1277. {
  1278. unsigned id;
  1279. const char* label;
  1280. } map_t;
  1281. map_t map[ kColCnt ] =
  1282. {
  1283. { kChColIdx, "ch" },
  1284. { kSsiColIdx, "ssi" },
  1285. { kPitchColIdx, "pitch" },
  1286. { kMidiColIdx, "midi" },
  1287. { kGainColIdx, "gain" },
  1288. { kNsFlColIdx, "ns_fl"},
  1289. { kCdFlColIdx, "cd_fl"}
  1290. };
  1291. if((rc = cmChCfgFinal(p)) != cmOkRC )
  1292. return rc;
  1293. p->fn = cmFsMakeFn(cmFsPrefsDir(),fn,NULL,NULL);
  1294. // read the channel cfg JSON file
  1295. if( cmJsonInitializeFromFile(&p->jsH, p->fn, ctx ) != kOkJsRC )
  1296. {
  1297. rc = cmCtxRtCondition( &p->obj, cmSubSysFailRC, "JSON initialize failed on '%s'.",cmStringNullGuard(p->fn));
  1298. goto errLabel;
  1299. }
  1300. // locate the 'ch_array' node
  1301. if((p->cap = cmJsonFindValue( p->jsH, ch_array_label, cmJsonRoot(p->jsH), kArrayTId )) == NULL )
  1302. {
  1303. rc = cmCtxRtCondition( &p->obj, cmSubSysFailRC, "Unable to locate the JSON element '%s'.",ch_array_label);
  1304. goto errLabel;
  1305. }
  1306. unsigned rowCnt = cmJsonChildCount(p->cap);
  1307. // there must be at least 1 label row and 1 ch row
  1308. if( rowCnt < 2 )
  1309. {
  1310. rc = cmCtxRtCondition( &p->obj, cmSubSysFailRC, "The 'ch_array' appears to be empty.");
  1311. goto errLabel;
  1312. }
  1313. // allocate the ch array
  1314. p->chCnt = rowCnt - 1;
  1315. p->chArray = cmMemResizeZ( cmChCfgCh, p->chArray, p->chCnt );
  1316. p->nsChCnt = 0;
  1317. // read each row
  1318. for(i=0; i<rowCnt; ++i)
  1319. {
  1320. // get the array on row i
  1321. const cmJsonNode_t* np = cmJsonArrayElementC(p->cap,i);
  1322. // all row arrays contain 'kColCnt' elements
  1323. if( cmJsonChildCount(np) != kColCnt )
  1324. {
  1325. rc = cmCtxRtCondition( &p->obj, cmSubSysFailRC, "All 'ch_array' element at index %i does not contain %i values.",i,kColCnt);
  1326. goto errLabel;
  1327. }
  1328. // for each columns
  1329. for(j=0; j<kColCnt; ++j)
  1330. {
  1331. const cmJsonNode_t* cp = cmJsonArrayElementC(np,j);
  1332. // the first row contains the labels ....
  1333. if( i == 0 )
  1334. {
  1335. // verify that the column format is as expected
  1336. if( cmJsonIsString(cp)==false || strcmp(cp->u.stringVal,map[j].label) != 0 )
  1337. {
  1338. rc = cmCtxRtCondition( &p->obj, cmSubSysFailRC, "The first row column at index %i of 'ch_array' should be the label '%s'.",map[j].label);
  1339. goto errLabel;
  1340. }
  1341. }
  1342. else // ... other rows contain Ch Cfg's.
  1343. {
  1344. cmChCfgCh* chp = p->chArray + (i-1);
  1345. switch(j)
  1346. {
  1347. case kChColIdx: rc = cmJsonUIntValue( cp, &chp->ch ); break;
  1348. case kSsiColIdx: rc = cmJsonUIntValue( cp, &chp->ssi ); break;
  1349. case kPitchColIdx: rc = cmJsonStringValue( cp, &chp->pitchStr ); break;
  1350. case kMidiColIdx: rc = cmJsonUIntValue( cp, &chp->midi ); break;
  1351. case kGainColIdx: rc = cmJsonRealValue( cp, &chp->gain ); break;
  1352. case kNsFlColIdx:
  1353. rc = cmJsonBoolValue( cp, &chp->nsFl );
  1354. if( chp->nsFl )
  1355. ++p->nsChCnt;
  1356. break;
  1357. case kCdFlColIdx: rc = cmJsonBoolValue( cp, &chp->cdFl ); break;
  1358. default:
  1359. { assert(0); }
  1360. }
  1361. if( rc != kOkJsRC )
  1362. {
  1363. rc = cmCtxRtCondition( &p->obj, cmSubSysFailRC, "An error occurred while reading the '%s' column on row index:%i .", map[j].label,i);
  1364. goto errLabel;
  1365. }
  1366. }
  1367. }
  1368. }
  1369. errLabel:
  1370. return rc;
  1371. }
  1372. cmRC_t cmChCfgFinal( cmChCfg* p )
  1373. {
  1374. cmRC_t rc = cmOkRC;
  1375. if( cmJsonIsValid(p->jsH) )
  1376. if( cmJsonFinalize(&p->jsH) != kOkJsRC )
  1377. rc = cmCtxRtCondition( &p->obj, cmSubSysFailRC, "JSON finalize failed.");
  1378. return rc;
  1379. }
  1380. cmRC_t cmChCfgWrite( cmChCfg* p )
  1381. {
  1382. cmRC_t rc = cmOkRC;
  1383. unsigned i;
  1384. for(i=0; i<p->chCnt; ++i)
  1385. {
  1386. // get the array on row i+1
  1387. cmJsonNode_t* np = cmJsonArrayElement(p->cap,i+1);
  1388. // get the ele in the 'gainColIdx' column
  1389. np = cmJsonArrayElement(np,kGainColIdx);
  1390. assert( cmJsonIsReal(np) );
  1391. np->u.realVal = p->chArray[i].gain;
  1392. }
  1393. if( cmJsonWrite( p->jsH, cmJsonRoot(p->jsH), p->fn ) != kOkJsRC )
  1394. rc = cmCtxRtCondition( &p->obj, cmSubSysFailRC, "The JSON Channel Cfg file write failed on '%s'.",cmStringNullGuard(p->fn));
  1395. return rc;
  1396. }
  1397. void cmChCfgPrint( cmChCfg* p, cmRpt_t* rpt )
  1398. {
  1399. unsigned i;
  1400. for(i=0; i<p->chCnt; ++i)
  1401. {
  1402. const cmChCfgCh* chp = p->chArray + i;
  1403. cmRptPrintf(rpt,"%3i %3i %4s %3i %5.5f\n",chp->ch,chp->ssi,chp->pitchStr,chp->midi,chp->gain);
  1404. }
  1405. }
  1406. unsigned cmChCfgChannelCount( cmCtx_t* ctx, const cmChar_t* fn, unsigned* nsChCntPtr )
  1407. {
  1408. cmChCfg* ccp;
  1409. unsigned chCnt = 0;
  1410. cmCtx* c = cmCtxAlloc(NULL, &ctx->rpt, cmLHeapNullHandle, cmSymTblNullHandle );
  1411. if((ccp = cmChCfgAlloc(c, NULL, ctx, fn )) == NULL )
  1412. goto errLabel;
  1413. chCnt = ccp->chCnt;
  1414. if( nsChCntPtr != NULL )
  1415. *nsChCntPtr = ccp->nsChCnt;
  1416. cmChCfgFree(&ccp);
  1417. errLabel:
  1418. cmCtxFree(&c);
  1419. return chCnt;
  1420. }
  1421. unsigned cmChCfgChannelIndex( cmCtx_t* ctx, const cmChar_t* fn, unsigned chIdx )
  1422. {
  1423. cmChCfg* ccp;
  1424. unsigned retChIdx = -1;
  1425. cmCtx* c = cmCtxAlloc(NULL, &ctx->rpt, cmLHeapNullHandle, cmSymTblNullHandle );
  1426. if((ccp = cmChCfgAlloc(c, NULL, ctx, fn )) == NULL )
  1427. goto errLabel;
  1428. if( chIdx >= ccp->chCnt )
  1429. cmCtxRtCondition( &ccp->obj, cmArgAssertRC, "The channel index %i is not less than the channel count %i when querying '%s'.",chIdx,ccp->chCnt,cmStringNullGuard(ccp->fn));
  1430. else
  1431. retChIdx = ccp->chArray[chIdx].ch;
  1432. cmChCfgFree(&ccp);
  1433. errLabel:
  1434. cmCtxFree(&c);
  1435. return retChIdx;
  1436. }
  1437. //==========================================================================================================================================
  1438. cmChordDetect* cmChordDetectAlloc( cmCtx*c, cmChordDetect* p, cmReal_t srate, unsigned chCnt, cmReal_t maxTimeSpanMs, unsigned minNotesPerChord )
  1439. {
  1440. cmChordDetect* op = cmObjAlloc(cmChordDetect, c, p );
  1441. if( srate != 0 )
  1442. if( cmChordDetectInit( op, srate, chCnt, maxTimeSpanMs, minNotesPerChord ) != cmOkRC )
  1443. cmChordDetectFree(&op);
  1444. return op;
  1445. }
  1446. cmRC_t cmChordDetectFree( cmChordDetect** pp )
  1447. {
  1448. cmRC_t rc = cmOkRC;
  1449. if( pp == NULL || *pp == NULL )
  1450. return cmOkRC;
  1451. cmChordDetect* p = *pp;
  1452. if((rc = cmChordDetectFinal(p)) != cmOkRC )
  1453. return rc;
  1454. cmMemPtrFree(&p->chArray);
  1455. cmObjFree(pp);
  1456. return cmOkRC;
  1457. }
  1458. cmRC_t cmChordDetectInit( cmChordDetect* p, cmReal_t srate, unsigned chCnt, cmReal_t maxTimeSpanMs, unsigned minNotesPerChord )
  1459. {
  1460. cmRC_t rc;
  1461. if((rc = cmChordDetectFinal(p)) != cmOkRC )
  1462. return rc;
  1463. p->chArray = cmMemResizeZ(cmChordDetectCh, p->chArray, chCnt );
  1464. p->chCnt = chCnt;
  1465. p->minNotesPerChord = minNotesPerChord;
  1466. p->detectFl = false;
  1467. p->timeSmp = 0;
  1468. p->srate = srate;
  1469. cmChordDetectSetSpanMs(p,maxTimeSpanMs);
  1470. unsigned i;
  1471. for(i=0; i<p->chCnt; ++i)
  1472. p->chArray[i].readyFl = true;
  1473. return rc;
  1474. }
  1475. cmRC_t cmChordDetectFinal( cmChordDetect* P )
  1476. { return cmOkRC; }
  1477. cmRC_t cmChordDetectExec( cmChordDetect* p, unsigned procSmpCnt, const bool* gateV, const cmReal_t* rmsV, unsigned chCnt )
  1478. {
  1479. assert( chCnt == p->chCnt );
  1480. chCnt = cmMin(chCnt,p->chCnt);
  1481. cmRC_t rc = cmOkRC;
  1482. unsigned candCnt = 0;
  1483. cmChordDetectCh* oldCand = NULL;
  1484. unsigned i;
  1485. p->detectFl = false;
  1486. p->timeSmp += procSmpCnt;
  1487. // update the readyFl's and candFl's based on onset and offsets
  1488. for(i=0; i<chCnt; ++i)
  1489. {
  1490. cmChordDetectCh* cp = p->chArray + i;
  1491. // if onset and the channel is ready
  1492. if( gateV[i] && cp->gateFl==false && cp->readyFl )
  1493. {
  1494. cp->candSmpTime = p->timeSmp;
  1495. cp->candRMS = rmsV[i];
  1496. cp->candFl = true;
  1497. }
  1498. // if offset then this channel is again ready to be a candidate
  1499. if( gateV[i]==false && cp->gateFl )
  1500. {
  1501. cp->readyFl = true;
  1502. }
  1503. cp->gateFl = gateV[i];
  1504. cp->chordFl = false;
  1505. }
  1506. // check if we have enough channels to form a chord and
  1507. // expire channels that have passed the max time out value
  1508. for(i=0; i<chCnt; ++i)
  1509. {
  1510. cmChordDetectCh* cp = p->chArray + i;
  1511. unsigned ageSmpCnt = p->timeSmp - cp->candSmpTime;
  1512. // if this is a candiate ...
  1513. if( cp->candFl )
  1514. {
  1515. // ... that has not expired
  1516. if( ageSmpCnt <= p->maxTimeSpanSmpCnt )
  1517. {
  1518. // track the oldest candidate
  1519. if( oldCand==NULL || cp->candSmpTime < oldCand->candSmpTime )
  1520. oldCand = cp;
  1521. ++candCnt;
  1522. }
  1523. else // ... that has expired
  1524. {
  1525. cp->candFl = false;
  1526. }
  1527. }
  1528. }
  1529. // If we have enough notes and the oldest candiate will expire on the next cycle.
  1530. // (By waiting for the oldest note to almost expire we gather the maximum number of
  1531. // possible notes given the time duration. If we remove this condition then
  1532. // we will tend to trigger chord detection with fewer notes.)
  1533. if( oldCand != NULL )
  1534. {
  1535. unsigned nextAge = p->timeSmp + procSmpCnt - oldCand->candSmpTime;
  1536. if( candCnt >= p->minNotesPerChord && nextAge >= p->maxTimeSpanSmpCnt )
  1537. {
  1538. for(i=0; i<chCnt; ++i)
  1539. {
  1540. cmChordDetectCh* cp = p->chArray + i;
  1541. if( cp->candFl )
  1542. {
  1543. cp->chordFl = true;
  1544. cp->candFl = false;
  1545. }
  1546. }
  1547. p->detectFl = true;
  1548. }
  1549. }
  1550. return rc;
  1551. }
  1552. cmRC_t cmChordDetectSetSpanMs( cmChordDetect* p, cmReal_t maxTimeSpanMs )
  1553. {
  1554. p->maxTimeSpanSmpCnt = floor( maxTimeSpanMs * p->srate / 1000.0 );
  1555. return cmOkRC;
  1556. }
  1557. //==========================================================================================================================================
  1558. cmXfader* cmXfaderAlloc( cmCtx*c, cmXfader* p, cmReal_t srate, unsigned chCnt, cmReal_t fadeTimeMs )
  1559. {
  1560. cmXfader* op = cmObjAlloc(cmXfader, c, p );
  1561. if( srate != 0 )
  1562. if( cmXfaderInit( op, srate, chCnt, fadeTimeMs ) != cmOkRC )
  1563. cmXfaderFree(&op);
  1564. return op;
  1565. }
  1566. cmRC_t cmXfaderFree( cmXfader** pp )
  1567. {
  1568. cmRC_t rc = cmOkRC;
  1569. if( pp == NULL || *pp == NULL )
  1570. return cmOkRC;
  1571. cmXfader* p = *pp;
  1572. if((rc = cmXfaderFinal(p)) != cmOkRC )
  1573. return rc;
  1574. cmMemPtrFree(&p->chArray);
  1575. cmObjFree(pp);
  1576. return cmOkRC;
  1577. }
  1578. cmRC_t cmXfaderInit( cmXfader* p, cmReal_t srate, unsigned chCnt, cmReal_t fadeTimeMs )
  1579. {
  1580. cmRC_t rc;
  1581. if((rc = cmXfaderFinal(p)) != cmOkRC )
  1582. return rc;
  1583. p->chCnt = chCnt;
  1584. p->chArray = cmMemResizeZ(cmXfaderCh,p->chArray,p->chCnt);
  1585. p->srate = srate;
  1586. p->gateFl = false;
  1587. p->onFl = false;
  1588. p->offFl = false;
  1589. cmXfaderSetXfadeTime(p,fadeTimeMs);
  1590. return rc;
  1591. }
  1592. cmRC_t cmXfaderFinal( cmXfader* p )
  1593. { return cmOkRC; }
  1594. cmRC_t cmXfaderExec( cmXfader* p, unsigned procSmpCnt, const bool* chGateV, unsigned chCnt )
  1595. {
  1596. assert( chCnt == p->chCnt);
  1597. chCnt = cmMin(chCnt,p->chCnt);
  1598. bool gateFl = false;
  1599. // gain change associated with procSmpCnt
  1600. //cmReal_t dgain = (cmReal_t)procSmpCnt / p->fadeSmpCnt;
  1601. cmReal_t i_dgain = (cmReal_t)procSmpCnt / p->fadeInSmpCnt;
  1602. cmReal_t o_dgain = (cmReal_t)procSmpCnt / p->fadeOutSmpCnt;
  1603. unsigned i;
  1604. // for each channel
  1605. for(i=0; i<chCnt; ++i)
  1606. {
  1607. cmXfaderCh* cp = p->chArray + i;
  1608. cp->onFl = false;
  1609. cp->offFl = false;
  1610. if( chGateV != NULL )
  1611. {
  1612. cp->onFl = chGateV[i] && !cp->gateFl; // notice fade-in transition begin
  1613. cp->gateFl = chGateV[i];
  1614. }
  1615. cmReal_t g = cp->gain;
  1616. if( cp->gateFl )
  1617. {
  1618. cp->gain = cmMin(cp->gain + i_dgain,1.0);
  1619. cp->ep_gain = sqrt(0.5 - 0.5 * cos(3.14159*cp->gain));
  1620. }
  1621. else
  1622. {
  1623. cp->gain = cmMax(cp->gain - o_dgain,0.0);
  1624. cp->ep_gain = sqrt(0.5 - 0.5 * cos(3.14159*cp->gain));
  1625. cp->offFl = g>0.0 && cp->gain==0.0; // notice fade-out transition end
  1626. }
  1627. if( cp->gain != 0.0 )
  1628. gateFl = true;
  1629. }
  1630. p->onFl = false;
  1631. p->offFl = false;
  1632. if( p->gateFl==false && gateFl==true )
  1633. p->onFl = true;
  1634. else
  1635. if( p->gateFl==true && gateFl==false )
  1636. p->offFl = true;
  1637. p->gateFl = gateFl;
  1638. return cmOkRC;
  1639. }
  1640. cmRC_t cmXfaderExecAudio( cmXfader* p, unsigned procSmpCnt, const bool* gateV, unsigned chCnt, const cmSample_t* x[], cmSample_t* y )
  1641. {
  1642. cmRC_t rc;
  1643. assert( chCnt == p->chCnt);
  1644. chCnt = cmMin(chCnt,p->chCnt);
  1645. if((rc = cmXfaderExec(p,procSmpCnt,gateV,chCnt)) != cmOkRC )
  1646. return rc;
  1647. unsigned i;
  1648. for(i=0; i<chCnt; ++i)
  1649. if( x[i] != NULL )
  1650. cmVOS_MultVaVS(y,procSmpCnt,x[i],p->chArray[i].ep_gain);
  1651. return rc;
  1652. }
  1653. void cmXfaderSetXfadeTime( cmXfader* p, cmReal_t fadeTimeMs )
  1654. {
  1655. p->fadeSmpCnt = floor(fadeTimeMs * p->srate /1000.0);
  1656. p->fadeInSmpCnt = p->fadeSmpCnt;
  1657. p->fadeOutSmpCnt = p->fadeSmpCnt;
  1658. }
  1659. void cmXfaderSetXfadeInTime( cmXfader* p, cmReal_t fadeTimeMs )
  1660. {
  1661. p->fadeInSmpCnt = floor(fadeTimeMs * p->srate /1000.0);
  1662. }
  1663. void cmXfaderSetXfadeOutTime( cmXfader* p, cmReal_t fadeTimeMs )
  1664. {
  1665. p->fadeOutSmpCnt = floor(fadeTimeMs * p->srate /1000.0);
  1666. }
  1667. void cmXfaderSelectOne( cmXfader* p, unsigned chIdx )
  1668. {
  1669. unsigned i = 0;
  1670. for(i=0; i<p->chCnt; ++i)
  1671. p->chArray[i].gateFl = i == chIdx;
  1672. }
  1673. void cmXfaderAllOff( cmXfader* p )
  1674. {
  1675. unsigned i = 0;
  1676. for(i=0; i<p->chCnt; ++i)
  1677. p->chArray[i].gateFl = false;
  1678. }
  1679. void cmXfaderJumpToDestinationGain( cmXfader* p )
  1680. {
  1681. unsigned i = 0;
  1682. for(i=0; i<p->chCnt; ++i)
  1683. {
  1684. if( p->chArray[i].gateFl )
  1685. p->chArray[i].gain = 1.0;
  1686. else
  1687. p->chArray[i].gain = 0.0;
  1688. p->chArray[i].onFl = false;
  1689. p->chArray[i].offFl = false;
  1690. p->chArray[i].ep_gain = p->chArray[i].gain;
  1691. }
  1692. }
  1693. //==========================================================================================================================================
  1694. cmFader* cmFaderAlloc( cmCtx*c, cmFader* p, cmReal_t srate, cmReal_t fadeTimeMs )
  1695. {
  1696. cmFader* op = cmObjAlloc(cmFader, c, p );
  1697. if( srate != 0 )
  1698. if( cmFaderInit( op, srate, fadeTimeMs ) != cmOkRC )
  1699. cmFaderFree(&op);
  1700. return op;
  1701. }
  1702. cmRC_t cmFaderFree( cmFader** pp )
  1703. {
  1704. cmRC_t rc = cmOkRC;
  1705. if( pp == NULL || *pp == NULL )
  1706. return cmOkRC;
  1707. cmFader* p = *pp;
  1708. if((rc = cmFaderFinal(p)) != cmOkRC )
  1709. return rc;
  1710. cmObjFree(pp);
  1711. return cmOkRC;
  1712. }
  1713. cmRC_t cmFaderInit( cmFader* p, cmReal_t srate, cmReal_t fadeTimeMs )
  1714. {
  1715. cmRC_t rc;
  1716. if((rc = cmFaderFinal(p)) != cmOkRC )
  1717. return rc;
  1718. p->srate = srate;
  1719. p->gain = 0.0;
  1720. cmFaderSetFadeTime(p,fadeTimeMs);
  1721. return rc;
  1722. }
  1723. cmRC_t cmFaderFinal( cmFader* p )
  1724. { return cmOkRC; }
  1725. cmRC_t cmFaderExec( cmFader* p, unsigned procSmpCnt, bool gateFl, bool mixFl, const cmSample_t* x, cmSample_t* y )
  1726. {
  1727. cmReal_t d = (gateFl ? 1.0 : -1.0) * procSmpCnt / p->fadeSmpCnt;
  1728. // TODO: add fade curves
  1729. p->gain = cmMin(1.0,cmMax(0.0,p->gain + d));
  1730. if( x!=NULL && y!=NULL )
  1731. {
  1732. if( mixFl )
  1733. cmVOS_MultVaVS(y, procSmpCnt, x, 1.0/* p->gain*/);
  1734. else
  1735. cmVOS_MultVVS(y,procSmpCnt,x,p->gain);
  1736. }
  1737. return cmOkRC;
  1738. }
  1739. void cmFaderSetFadeTime( cmFader* p, cmReal_t fadeTimeMs )
  1740. {
  1741. p->fadeSmpCnt = (unsigned)floor( fadeTimeMs * p->srate / 1000.0 );
  1742. }
  1743. //=======================================================================================================================
  1744. cmCombFilt* cmCombFiltAlloc( cmCtx* c, cmCombFilt* p, cmReal_t srate, bool feedbackFl, cmReal_t minHz, cmReal_t alpha, cmReal_t hz, bool bypassFl )
  1745. {
  1746. cmCombFilt* op = cmObjAlloc(cmCombFilt, c, p );
  1747. op->idp = cmIDelayAlloc(c, NULL, 0, 0, NULL, NULL, NULL, 0 );
  1748. if( srate != 0 )
  1749. if( cmCombFiltInit( op, srate, feedbackFl, minHz, alpha, hz, bypassFl ) != cmOkRC )
  1750. cmCombFiltFree(&op);
  1751. return op;
  1752. }
  1753. cmRC_t cmCombFiltFree( cmCombFilt** pp)
  1754. {
  1755. cmRC_t rc = cmOkRC;
  1756. if( pp == NULL || *pp == NULL )
  1757. return cmOkRC;
  1758. cmCombFilt* p = *pp;
  1759. if((rc = cmCombFiltFinal(p)) != cmOkRC )
  1760. return rc;
  1761. cmMemFree(p->a);
  1762. cmMemFree(p->b);
  1763. cmMemFree(p->d);
  1764. cmIDelayFree(&p->idp);
  1765. cmObjFree(pp);
  1766. return cmOkRC;
  1767. }
  1768. cmRC_t cmCombFiltInit( cmCombFilt* p, cmReal_t srate, bool feedbackFl, cmReal_t minHz, cmReal_t alpha, cmReal_t hz, bool bypassFl )
  1769. {
  1770. cmRC_t rc;
  1771. if((rc = cmCombFiltFinal(p)) != cmOkRC )
  1772. return rc;
  1773. p->feedbackFl = feedbackFl;
  1774. p->dN = cmMax(1,floor(srate / minHz ));
  1775. p->d = cmMemResizeZ( cmReal_t, p->d, p->dN+1 );
  1776. p->a = cmMemResizeZ( cmReal_t, p->a, p->dN );
  1777. p->b = cmMemResizeZ( cmReal_t, p->b, p->dN );
  1778. p->dn = 1;
  1779. p->alpha = alpha;
  1780. p->srate = srate;
  1781. p->bypassFl = bypassFl;
  1782. cmReal_t tapMs = p->dn * 1000.0 / srate;
  1783. cmReal_t tapFf = 1.0;
  1784. cmReal_t tapFb = 1.0;
  1785. cmIDelayInit(p->idp, srate, p->dN * 1000.0 / srate, &tapMs, &tapFf, &tapFb, 1 );
  1786. cmCombFiltSetHz(p,hz);
  1787. return rc;
  1788. }
  1789. cmRC_t cmCombFiltFinal( cmCombFilt* p )
  1790. { return cmOkRC; }
  1791. cmRC_t cmCombFiltExec( cmCombFilt* p, const cmSample_t* x, cmSample_t* y, unsigned n )
  1792. {
  1793. if( y == NULL )
  1794. return cmOkRC;
  1795. if( x == NULL )
  1796. {
  1797. cmVOS_Zero(y,n);
  1798. return cmOkRC;
  1799. }
  1800. if( p->bypassFl )
  1801. cmVOS_Copy(y,n,x);
  1802. else
  1803. cmIDelayExec(p->idp,x,y,n);
  1804. return cmOkRC;
  1805. }
  1806. void cmCombFiltSetAlpha( cmCombFilt* p, cmReal_t alpha )
  1807. {
  1808. p->b0 = 1.0 - fabs(alpha); // normalization coeff (could be applied directly to the input or output)
  1809. p->a[p->dn-1] = -alpha;
  1810. p->alpha = alpha;
  1811. p->idp->tff[0] = p->b0;
  1812. p->idp->tfb[0] = -alpha;
  1813. }
  1814. cmRC_t cmCombFiltSetHz( cmCombFilt* p, cmReal_t hz )
  1815. {
  1816. if( hz < p->minHz )
  1817. return cmCtxRtCondition( &p->obj, cmInvalidArgRC, "The comb filter frequency %f Hz is invalid given the minimum frequency setting of %f Hz.",hz,p->minHz );
  1818. // clear the current alpha
  1819. p->a[p->dn-1] = 0;
  1820. // change location of alpha in p->a[]
  1821. p->dn = cmMin(p->dN-1,cmMax(1,floor(p->srate / hz )));
  1822. p->hz = hz;
  1823. cmCombFiltSetAlpha(p,p->alpha); // the location of filter coeff changed - reset it here
  1824. cmIDelaySetTapMs(p->idp, 0,p->dn * 1000.0 / p->srate );
  1825. return cmOkRC;
  1826. }
  1827. //=======================================================================================================================
  1828. cmDcFilt* cmDcFiltAlloc( cmCtx* c, cmDcFilt* p, bool bypassFl )
  1829. {
  1830. cmDcFilt* op = cmObjAlloc(cmDcFilt, c, p );
  1831. if( cmDcFiltInit( op, bypassFl ) != cmOkRC )
  1832. cmDcFiltFree(&op);
  1833. return op;
  1834. }
  1835. cmRC_t cmDcFiltFree( cmDcFilt** pp)
  1836. {
  1837. cmRC_t rc = cmOkRC;
  1838. if( pp == NULL || *pp == NULL )
  1839. return cmOkRC;
  1840. cmDcFilt* p = *pp;
  1841. if((rc = cmDcFiltFinal(p)) != cmOkRC )
  1842. return rc;
  1843. cmObjFree(pp);
  1844. return cmOkRC;
  1845. }
  1846. cmRC_t cmDcFiltInit( cmDcFilt* p, bool bypassFl )
  1847. {
  1848. cmRC_t rc;
  1849. if((rc = cmDcFiltFinal(p)) != cmOkRC )
  1850. return rc;
  1851. p->b0 = 1;
  1852. p->b[0] = -1;
  1853. p->a[0] = -0.999;
  1854. p->d[0] = 0;
  1855. p->d[1] = 0;
  1856. p->bypassFl = bypassFl;
  1857. return rc;
  1858. }
  1859. cmRC_t cmDcFiltFinal( cmDcFilt* p )
  1860. { return cmOkRC; }
  1861. cmRC_t cmDcFiltExec( cmDcFilt* p, const cmSample_t* x, cmSample_t* y, unsigned n )
  1862. {
  1863. if( p->bypassFl )
  1864. cmVOS_Copy(y,n,x);
  1865. else
  1866. cmVOS_Filter(y,n,x,n,p->b0, p->b, p->a, p->d, 1 );
  1867. return cmOkRC;
  1868. }
  1869. //=======================================================================================================================
  1870. cmIDelay* cmIDelayAlloc( cmCtx* c, cmIDelay* p, cmReal_t srate, cmReal_t maxDelayMs, const cmReal_t* tapMs, const cmReal_t* tapFfGain, const cmReal_t* tapFbGain, unsigned tapCnt )
  1871. {
  1872. cmIDelay* op = cmObjAlloc(cmIDelay, c, p );
  1873. if( srate != 0 )
  1874. if( cmIDelayInit( op, srate, maxDelayMs, tapMs, tapFfGain, tapFbGain, tapCnt ) != cmOkRC )
  1875. cmIDelayFree(&op);
  1876. return op;
  1877. }
  1878. cmRC_t cmIDelayFree( cmIDelay** pp )
  1879. {
  1880. cmRC_t rc = cmOkRC;
  1881. if( pp == NULL || *pp == NULL )
  1882. return cmOkRC;
  1883. cmIDelay* p = *pp;
  1884. if((rc = cmIDelayFinal(p)) != cmOkRC )
  1885. return rc;
  1886. cmMemFree(p->m);
  1887. cmMemFree(p->ti);
  1888. cmMemFree(p->tff);
  1889. cmMemFree(p->tfb);
  1890. cmObjFree(pp);
  1891. return cmOkRC;
  1892. }
  1893. cmRC_t cmIDelayInit( cmIDelay* p, cmReal_t srate, cmReal_t maxDelayMs, const cmReal_t* tapMs, const cmReal_t* tapFfGain, const cmReal_t* tapFbGain, unsigned tapCnt )
  1894. {
  1895. cmRC_t rc;
  1896. if(( rc = cmIDelayFinal(p)) != cmOkRC )
  1897. return rc;
  1898. p->dn = (unsigned)floor( maxDelayMs * srate / 1000.0 );
  1899. p->mn = p->dn + 3;
  1900. p->m = cmMemResizeZ(cmSample_t,p->m,p->mn);
  1901. p->d = p->m + 1;
  1902. p->tn = tapCnt;
  1903. p->ti = cmMemResize(cmReal_t,p->ti,tapCnt);
  1904. p->tff = cmMemResize(cmReal_t,p->tff,tapCnt);
  1905. p->tfb = cmMemResize(cmReal_t,p->tfb,tapCnt);
  1906. p->srate = srate;
  1907. unsigned i;
  1908. for(i=0; i<tapCnt; ++i)
  1909. {
  1910. cmIDelaySetTapMs(p,i,tapMs[i]);
  1911. p->tff[i] = tapFfGain[i];
  1912. p->tfb[i] = tapFbGain[i];
  1913. }
  1914. return rc;
  1915. }
  1916. cmRC_t cmIDelayFinal(cmIDelay* p )
  1917. { return cmOkRC; }
  1918. cmRC_t cmIDelayExec( cmIDelay* p, const cmSample_t* x, cmSample_t* y, unsigned n )
  1919. {
  1920. unsigned i,j;
  1921. for(i=0; i<n; ++i)
  1922. {
  1923. cmSample_t fb = 0;
  1924. y[i] = 0;
  1925. // calculate the output sample
  1926. for(j=0; j<p->tn; ++j)
  1927. {
  1928. // get tap_j
  1929. cmReal_t tfi = p->ii - p->ti[j];
  1930. // mod it into 0:dn-1
  1931. while( tfi < 0 )
  1932. tfi += p->dn;
  1933. int ti = floor(tfi);
  1934. cmReal_t tf = tfi - ti;
  1935. cmSample_t v = _lin_interp(tf,p->d[ti],p->d[ti+1]); // _cube_interp(tf,p->d[ti-1],p->d[ti],p->d[ti+1],p->d[ti+2]);
  1936. y[i] += p->tff[j] * v;
  1937. fb += p->tfb[j] * v;
  1938. }
  1939. // insert incoming sample
  1940. p->d[p->ii] = x[i] + fb;
  1941. // advance the delay line
  1942. ++p->ii;
  1943. // handle beg/end delay sample duplication
  1944. // -1 0 1 2 .... dn-1 dn dn+1
  1945. // a b c a b c
  1946. // The samples at position -1 0 1 must be duplicated
  1947. // at positions dn-1,dn,dn+1 so that output sample calculation
  1948. // does not need to deal with buffer wrap-around issues.
  1949. if( p->ii == 1 )
  1950. p->d[p->dn] = x[i];
  1951. else
  1952. if( p->ii == 2 )
  1953. p->d[p->dn+1] = x[i];
  1954. else
  1955. if( p->ii == p->dn )
  1956. {
  1957. p->d[-1] = x[i];
  1958. p->ii = 0;
  1959. }
  1960. }
  1961. return cmOkRC;
  1962. }
  1963. cmRC_t cmIDelaySetTapMs( cmIDelay* p, unsigned tapIdx, cmReal_t tapMs )
  1964. {
  1965. cmRC_t rc = cmOkRC;
  1966. if( tapIdx < p->tn )
  1967. p->ti[tapIdx] = tapMs * p->srate / 1000.0;
  1968. else
  1969. rc = cmCtxRtCondition( &p->obj, cmInvalidArgRC, "Tap index %i is out of range 0 - %i.",tapIdx,p->tn-1 );
  1970. return rc;
  1971. }
  1972. //=======================================================================================================================
  1973. cmGroupSel* cmGroupSelAlloc( cmCtx* c, cmGroupSel* p, unsigned chCnt, unsigned groupCnt, unsigned chsPerGroup )
  1974. {
  1975. cmGroupSel* op = cmObjAlloc(cmGroupSel, c, p );
  1976. if( chCnt != 0 )
  1977. if( cmGroupSelInit( op, chCnt, groupCnt, chsPerGroup ) != cmOkRC )
  1978. cmGroupSelFree(&op);
  1979. return op;
  1980. }
  1981. cmRC_t cmGroupSelFree( cmGroupSel** pp )
  1982. {
  1983. cmRC_t rc = cmOkRC;
  1984. if( pp == NULL || *pp == NULL )
  1985. return cmOkRC;
  1986. cmGroupSel* p = *pp;
  1987. if((rc = cmGroupSelFinal(p)) != cmOkRC )
  1988. return rc;
  1989. cmMemFree(p->groupArray);
  1990. cmMemFree(p->chArray);
  1991. cmObjFree(pp);
  1992. return cmOkRC;
  1993. }
  1994. cmRC_t cmGroupSelInit( cmGroupSel* p, unsigned chCnt, unsigned groupCnt, unsigned chsPerGroup )
  1995. {
  1996. cmRC_t rc;
  1997. if((rc = cmGroupSelFinal(p)) != cmOkRC )
  1998. return rc;
  1999. p->chArray = cmMemResizeZ(cmGroupSelCh,p->chArray,chCnt);
  2000. p->groupArray = cmMemResizeZ(cmGroupSelGrp,p->groupArray,chCnt);
  2001. p->chCnt = chCnt;
  2002. p->groupCnt = groupCnt;
  2003. p->chsPerGroup = chsPerGroup;
  2004. unsigned i;
  2005. for(i=0; i<p->chCnt; ++i)
  2006. p->chArray[i].groupIdx = cmInvalidIdx;
  2007. for(i=0; i<p->groupCnt; ++i)
  2008. {
  2009. p->groupArray[i].chIdxArray = cmMemAllocZ(unsigned, p->chCnt);
  2010. p->groupArray[i].chIdxCnt = 0;
  2011. }
  2012. return rc;
  2013. }
  2014. cmRC_t cmGroupSelFinal( cmGroupSel* p )
  2015. {
  2016. unsigned i;
  2017. for(i=0; i<p->groupCnt; ++i)
  2018. cmMemFree(p->groupArray[i].chIdxArray);
  2019. return cmOkRC;
  2020. }
  2021. cmRC_t cmGroupSetChannelGate( cmGroupSel* p, unsigned chIdx, bool gateFl )
  2022. {
  2023. assert(chIdx <p->chCnt);
  2024. cmGroupSelCh* cp = p->chArray + chIdx;
  2025. if( gateFl==true && cp->gateFl==false )
  2026. {
  2027. cp->readyFl = true;
  2028. }
  2029. if( gateFl==false && cp->gateFl==true )
  2030. {
  2031. cp->offsetFl = true;
  2032. cp->readyFl = false;
  2033. }
  2034. cp->gateFl = gateFl;
  2035. //printf("ch:%i gate:%i ready:%i offset:%i grp:%i\n",chIdx,cp->gateFl,cp->readyFl,cp->offsetFl,cp->groupIdx);
  2036. return cmOkRC;
  2037. }
  2038. cmRC_t cmGroupSetChannelRMS( cmGroupSel* p, unsigned chIdx, cmReal_t rms )
  2039. {
  2040. assert(chIdx <p->chCnt);
  2041. cmGroupSelCh* cp = p->chArray + chIdx;
  2042. cp->rms = rms;
  2043. return cmOkRC;
  2044. }
  2045. cmRC_t cmGroupSelExec( cmGroupSel* p )
  2046. {
  2047. unsigned i,j;
  2048. unsigned availGroupCnt = 0;
  2049. p->chsPerGroup = cmMin( p->chsPerGroup, p->chCnt );
  2050. p->updateFl = false;
  2051. // clear the create and release flags on each group
  2052. // and get the count of available groups
  2053. for(i=0; i<p->groupCnt; ++i)
  2054. {
  2055. cmGroupSelGrp* gp = p->groupArray + i;
  2056. gp->createFl = false;
  2057. if( gp->releaseFl )
  2058. {
  2059. // clear the groupIdx from the channels assigned to this released group
  2060. for(j=0; j<gp->chIdxCnt; ++j)
  2061. p->chArray[ gp->chIdxArray[j] ].groupIdx = cmInvalidIdx;
  2062. gp->releaseFl = false;
  2063. gp->chIdxCnt = 0;
  2064. }
  2065. if( gp->chIdxCnt == 0 )
  2066. ++availGroupCnt;
  2067. }
  2068. // count the number of ready but unassigned ch's and
  2069. // release any groups which contain a channel with a gate offset
  2070. unsigned readyChCnt = 0;
  2071. for(i=0; i<p->chCnt; ++i)
  2072. {
  2073. cmGroupSelCh* cp = p->chArray + i;
  2074. // count the number of channels that are ready to be assigned
  2075. if( cp->readyFl )
  2076. ++readyChCnt;
  2077. // if this channel offset and it had been assigned to a group
  2078. // then mark its group for release
  2079. if( cp->offsetFl && cp->groupIdx != cmInvalidIdx )
  2080. {
  2081. p->groupArray[cp->groupIdx].releaseFl = true;
  2082. p->updateFl = true;
  2083. }
  2084. }
  2085. // assign ready ch's to available groups
  2086. while( readyChCnt > p->chsPerGroup && availGroupCnt > 0 )
  2087. {
  2088. unsigned groupIdx;
  2089. // locate an available group
  2090. for(groupIdx=0; groupIdx<p->groupCnt; ++groupIdx)
  2091. if( p->groupArray[groupIdx].chIdxCnt == 0 )
  2092. break;
  2093. if( groupIdx == p->groupCnt )
  2094. break;
  2095. --availGroupCnt;
  2096. cmGroupSelGrp* gp = p->groupArray + groupIdx;
  2097. printf("gs - group:%i chs: ",groupIdx);
  2098. // assign chsPerGroup ch's to this group
  2099. for(i=0; i<p->chCnt && gp->chIdxCnt < p->chsPerGroup; ++i)
  2100. if(p->chArray[i].readyFl )
  2101. {
  2102. p->chArray[i].readyFl = false; // this ch is no longer ready because it is assigned
  2103. p->chArray[i].groupIdx = groupIdx; // set this ch's group idx
  2104. gp->chIdxArray[ gp->chIdxCnt ] = i; // assign channel to group
  2105. gp->chIdxCnt += 1; // update the group ch count
  2106. gp->createFl = true;
  2107. p->updateFl = true;
  2108. --readyChCnt;
  2109. printf("%i ",i);
  2110. }
  2111. printf("\n");
  2112. }
  2113. return cmOkRC;
  2114. }
  2115. //=======================================================================================================================
  2116. cmAudioNofM* cmAudioNofMAlloc( cmCtx* c, cmAudioNofM* p, cmReal_t srate, unsigned inChCnt, unsigned outChCnt, cmReal_t fadeTimeMs )
  2117. {
  2118. cmAudioNofM* op = cmObjAlloc(cmAudioNofM, c, p );
  2119. if( srate != 0 )
  2120. if( cmAudioNofMInit( op, srate, inChCnt, outChCnt, fadeTimeMs ) != cmOkRC )
  2121. cmAudioNofMFree(&op);
  2122. return op;
  2123. }
  2124. cmRC_t cmAudioNofMFree( cmAudioNofM** pp )
  2125. {
  2126. cmRC_t rc = cmOkRC;
  2127. if( pp == NULL || *pp == NULL )
  2128. return cmOkRC;
  2129. cmAudioNofM* p = *pp;
  2130. if((rc = cmAudioNofMFinal(p)) != cmOkRC )
  2131. return rc;
  2132. cmMemFree(p->outArray);
  2133. cmMemFree(p->inArray);
  2134. cmObjFree(pp);
  2135. return cmOkRC;
  2136. }
  2137. cmRC_t cmAudioNofMInit( cmAudioNofM* p, cmReal_t srate, unsigned iChCnt, unsigned oChCnt, cmReal_t fadeTimeMs )
  2138. {
  2139. cmRC_t rc;
  2140. if((rc = cmAudioNofMFinal(p)) != cmOkRC )
  2141. return rc;
  2142. p->iChCnt = iChCnt;
  2143. p->inArray = cmMemResizeZ(cmAudioNofM_In,p->inArray,iChCnt);
  2144. p->oChCnt = oChCnt;
  2145. p->outArray = cmMemResizeZ(cmAudioNofM_Out,p->outArray,oChCnt);
  2146. p->nxtOutChIdx = 0;
  2147. unsigned i;
  2148. for(i=0; i<p->iChCnt; ++i)
  2149. {
  2150. p->inArray[i].fader = cmFaderAlloc(p->obj.ctx, NULL, srate, fadeTimeMs );
  2151. p->inArray[i].outChIdx = cmInvalidIdx;
  2152. }
  2153. cmAudioNofMSetFadeMs( p, fadeTimeMs );
  2154. return rc;
  2155. }
  2156. cmRC_t cmAudioNofMFinal( cmAudioNofM* p )
  2157. {
  2158. unsigned i;
  2159. for(i=0; i<p->iChCnt; ++i)
  2160. cmFaderFree(&p->inArray[i].fader);
  2161. return cmOkRC;
  2162. }
  2163. cmRC_t cmAudioNofMSetChannelGate( cmAudioNofM* p, unsigned inChIdx, bool gateFl )
  2164. {
  2165. assert( inChIdx < p->iChCnt );
  2166. cmAudioNofM_In* ip = p->inArray + inChIdx;
  2167. if( ip->gateFl && gateFl == false )
  2168. ip->offsetFl = true;
  2169. if( ip->gateFl == false && gateFl )
  2170. ip->onsetFl = true;
  2171. ip->gateFl = gateFl;
  2172. printf("nom: %p ch:%i gate:%i on:%i off:%i\n",p,inChIdx,ip->gateFl,ip->offsetFl,ip->onsetFl);
  2173. return cmOkRC;
  2174. }
  2175. cmRC_t cmAudioNofMExec( cmAudioNofM* p, const cmSample_t* x[], unsigned inChCnt, cmSample_t* y[], unsigned outChCnt, unsigned n )
  2176. {
  2177. assert( inChCnt == p->iChCnt && outChCnt == p->oChCnt );
  2178. unsigned i;
  2179. // for each output channel
  2180. for(i=0; i<p->oChCnt; ++i)
  2181. {
  2182. cmAudioNofM_Out* op = p->outArray + i;
  2183. cmAudioNofM_In* ip = op->list;
  2184. cmAudioNofM_In* pp = NULL;
  2185. // for each input assigned to this output chanenl
  2186. while( ip != NULL )
  2187. {
  2188. // if the channel is no longer active
  2189. if( ip->offsetFl && ip->fader->gain == 0.0 )
  2190. {
  2191. printf("nom: off - out:%i\n",ip->outChIdx);
  2192. // remove it from the output channels list
  2193. ip->offsetFl = false;
  2194. ip->outChIdx = cmInvalidIdx;
  2195. if( pp == NULL )
  2196. op->list = ip->link;
  2197. else
  2198. pp->link = ip->link;
  2199. }
  2200. pp = ip;
  2201. ip = ip->link;
  2202. }
  2203. }
  2204. // for each input channel
  2205. for(i=0; i<inChCnt; ++i)
  2206. {
  2207. cmAudioNofM_In* ip = p->inArray + i;
  2208. // if this channel is starting
  2209. if( ip->onsetFl == true && ip->offsetFl == false )
  2210. {
  2211. // assign it to the next output channel
  2212. ip->onsetFl = false;
  2213. ip->outChIdx = p->nxtOutChIdx;
  2214. ip->link = p->outArray[ ip->outChIdx ].list;
  2215. p->outArray[ ip->outChIdx ].list = ip;
  2216. p->nxtOutChIdx = (p->nxtOutChIdx + 1) % p->oChCnt;
  2217. printf("nom: on - in:%i out:%i\n",i,ip->outChIdx);
  2218. }
  2219. // if this channel is active - then mix its input
  2220. if( ip->outChIdx != cmInvalidIdx )
  2221. {
  2222. cmFaderExec( ip->fader, n, ip->gateFl, true, x[i], y[ ip->outChIdx ] );
  2223. }
  2224. }
  2225. return cmOkRC;
  2226. }
  2227. cmRC_t cmAudioNofMSetFadeMs( cmAudioNofM* p, cmReal_t fadeTimeMs )
  2228. {
  2229. unsigned i;
  2230. for(i=0; i<p->iChCnt; ++i)
  2231. cmFaderSetFadeTime(p->inArray[i].fader,fadeTimeMs);
  2232. return cmOkRC;
  2233. }
  2234. //=======================================================================================================================
  2235. cmAdsr* cmAdsrAlloc( cmCtx* c, cmAdsr* p, cmReal_t srate, bool trigFl, cmReal_t minL, cmReal_t dlyMs, cmReal_t atkMs, cmReal_t atkL, cmReal_t dcyMs, cmReal_t susMs, cmReal_t susL, cmReal_t rlsMs )
  2236. {
  2237. cmAdsr* op = cmObjAlloc(cmAdsr, c, p );
  2238. if( srate != 0 )
  2239. if( cmAdsrInit( op, srate, trigFl, minL, dlyMs, atkMs, atkL, dcyMs, susMs, susL, rlsMs ) != cmOkRC )
  2240. cmAdsrFree(&op);
  2241. return op;
  2242. }
  2243. cmRC_t cmAdsrFree( cmAdsr** pp )
  2244. {
  2245. cmRC_t rc = cmOkRC;
  2246. if( pp == NULL || *pp == NULL )
  2247. return cmOkRC;
  2248. cmAdsr* p = *pp;
  2249. if((rc = cmAdsrFinal(p)) != cmOkRC )
  2250. return rc;
  2251. cmObjFree(pp);
  2252. return cmOkRC;
  2253. }
  2254. cmRC_t cmAdsrInit( cmAdsr* p, cmReal_t srate, bool trigFl, cmReal_t minL, cmReal_t dlyMs, cmReal_t atkMs, cmReal_t atkL, cmReal_t dcyMs, cmReal_t susMs, cmReal_t susL, cmReal_t rlsMs )
  2255. {
  2256. cmRC_t rc;
  2257. if((rc = cmAdsrFinal(p)) != cmOkRC )
  2258. return rc;
  2259. // this is a limitation of the design - the design should be replaced with one
  2260. // which increments/decrements the level until it reaches a limit instead of calculating
  2261. // durations
  2262. //assert(atkL>=0 && minL>=0);
  2263. p->srate = srate;
  2264. p->trigModeFl = trigFl;
  2265. p->levelMin = minL;
  2266. p->scaleDur = 1.0;
  2267. cmAdsrSetTime(p,dlyMs,kDlyAdsrId);
  2268. cmAdsrSetTime(p,atkMs,kAtkAdsrId);
  2269. cmAdsrSetTime(p,dcyMs,kDcyAdsrId);
  2270. cmAdsrSetTime(p,susMs,kSusAdsrId);
  2271. cmAdsrSetTime(p,rlsMs,kRlsAdsrId);
  2272. cmAdsrSetLevel(p,atkL,kAtkAdsrId);
  2273. cmAdsrSetLevel(p,susL,kSusAdsrId);
  2274. p->state = kDoneAdsrId;
  2275. p->durSmp = 0;
  2276. p->level = p->levelMin;
  2277. p->gateFl = false;
  2278. p->atkDurSmp = 0;
  2279. p->rlsDurSmp = 0;
  2280. return cmOkRC;
  2281. }
  2282. cmRC_t cmAdsrFinal( cmAdsr* p )
  2283. { return cmOkRC; }
  2284. cmReal_t cmAdsrExec( cmAdsr* p, unsigned procSmpCnt, bool gateFl, cmReal_t tscale, cmReal_t ascale )
  2285. {
  2286. double scaleAmp = ascale;
  2287. double scaleDur = tscale;
  2288. // if onset
  2289. if( p->gateFl == false && gateFl==true )
  2290. {
  2291. p->scaleDur = scaleDur==0 ? 1.0 : fabs(scaleDur);
  2292. //printf("sd:%f %f\n",scaleDur,scaleAmp);
  2293. switch( p->state )
  2294. {
  2295. case kDlyAdsrId:
  2296. // if in delay mode when the re-attack occurs don't do anything
  2297. break;
  2298. case kAtkAdsrId:
  2299. case kDcyAdsrId:
  2300. case kSusAdsrId:
  2301. case kRlsAdsrId:
  2302. // if the atk level == 0 then fall through to kDoneAdsrId
  2303. if( p->actAtkLevel != 0 )
  2304. {
  2305. // re-attak mode:
  2306. // Scale the attack time to the current level relative to the attack level.
  2307. // In general this will result in a decrease in the attack duration.
  2308. p->atkDurSmp = cmMax(1,floor(p->atkSmp * (p->actAtkLevel - p->level) / p->actAtkLevel));
  2309. p->atkBegLevel = p->level;
  2310. p->durSmp = 0;
  2311. p->state = kAtkAdsrId;
  2312. p->actAtkLevel = p->atkLevel * scaleAmp;
  2313. p->actSusLevel = p->susLevel * scaleAmp;
  2314. break;
  2315. }
  2316. case kDoneAdsrId:
  2317. p->atkBegLevel = p->levelMin;
  2318. p->atkDurSmp = p->atkSmp;
  2319. p->state = p->dlySmp == 0 ? kAtkAdsrId : kDlyAdsrId;
  2320. p->durSmp = 0;
  2321. p->actAtkLevel = p->atkLevel * scaleAmp;
  2322. p->actSusLevel = p->susLevel * scaleAmp;
  2323. break;
  2324. default:
  2325. { assert(0); }
  2326. }
  2327. }
  2328. // if an offset occurred and we are not in trigger mode - then go into release mode
  2329. if( p->trigModeFl==false && p->gateFl == true && gateFl == false )
  2330. {
  2331. switch( p->state )
  2332. {
  2333. case kDlyAdsrId:
  2334. case kAtkAdsrId:
  2335. case kDcyAdsrId:
  2336. case kSusAdsrId:
  2337. if( p->actSusLevel == 0 )
  2338. p->state = kDoneAdsrId;
  2339. else
  2340. {
  2341. // scale the release time to the current level relative to the sustain level
  2342. p->rlsDurSmp = cmMax(1,floor(p->rlsSmp * p->level / p->actSusLevel));
  2343. p->rlsLevel = p->level;
  2344. p->durSmp = 0;
  2345. }
  2346. break;
  2347. case kRlsAdsrId:
  2348. case kDoneAdsrId:
  2349. // nothing to do
  2350. break;
  2351. default:
  2352. { assert(0); }
  2353. }
  2354. p->state = kRlsAdsrId;
  2355. }
  2356. p->gateFl = gateFl;
  2357. switch( p->state )
  2358. {
  2359. case kDlyAdsrId:
  2360. p->level = p->levelMin;
  2361. if( p->durSmp >= p->dlySmp )
  2362. {
  2363. p->state = kAtkAdsrId;
  2364. p->durSmp = 0;
  2365. if( p->trigModeFl )
  2366. {
  2367. p->atkBegLevel = p->level;
  2368. p->atkDurSmp = p->atkSmp;
  2369. }
  2370. }
  2371. break;
  2372. case kAtkAdsrId:
  2373. if( p->atkDurSmp != 0 )
  2374. p->level = p->atkBegLevel + (p->actAtkLevel - p->atkBegLevel) * cmMin(p->durSmp,p->atkDurSmp) / p->atkDurSmp;
  2375. if( p->durSmp >= p->atkDurSmp || p->atkDurSmp == 0 )
  2376. {
  2377. p->state = kDcyAdsrId;
  2378. p->durSmp = 0;
  2379. }
  2380. break;
  2381. case kDcyAdsrId:
  2382. if( p->dcySmp != 0 )
  2383. p->level = p->actAtkLevel - ((p->actAtkLevel - p->actSusLevel) * cmMin(p->durSmp,p->dcySmp) / p->dcySmp );
  2384. if( p->durSmp >= p->dcySmp || p->dcySmp==0 )
  2385. {
  2386. p->state = kSusAdsrId;
  2387. p->durSmp = 0;
  2388. }
  2389. break;
  2390. case kSusAdsrId:
  2391. p->level = p->actSusLevel;
  2392. if( p->trigModeFl==true && p->durSmp >= p->susSmp )
  2393. {
  2394. p->state = kRlsAdsrId;
  2395. p->durSmp = 0;
  2396. p->rlsLevel = p->level;
  2397. p->rlsDurSmp = p->rlsSmp;
  2398. }
  2399. break;
  2400. case kRlsAdsrId:
  2401. if( p->rlsDurSmp != 0 )
  2402. p->level = p->rlsLevel - ((p->rlsLevel - p->levelMin) * cmMin(p->durSmp,p->rlsDurSmp) / p->rlsDurSmp);
  2403. if( p->durSmp >= p->rlsDurSmp || p->rlsDurSmp==0 )
  2404. {
  2405. p->state = kDoneAdsrId;
  2406. p->durSmp = 0;
  2407. }
  2408. break;
  2409. case kDoneAdsrId:
  2410. p->level = p->levelMin;
  2411. break;
  2412. default:
  2413. { assert(0); }
  2414. }
  2415. p->durSmp += floor(procSmpCnt/p->scaleDur);
  2416. return p->level;
  2417. }
  2418. void _cmAdsrSetTime( cmAdsr* p, cmReal_t ms, int* smpPtr )
  2419. {
  2420. *smpPtr = cmMax(1,floor(p->srate * ms / 1000.0 ));
  2421. }
  2422. void cmAdsrSetTime( cmAdsr* p, cmReal_t ms, unsigned id )
  2423. {
  2424. switch( id )
  2425. {
  2426. case kDlyAdsrId:
  2427. _cmAdsrSetTime(p,ms,&p->dlySmp);
  2428. break;
  2429. case kAtkAdsrId:
  2430. _cmAdsrSetTime(p,ms,&p->atkSmp);
  2431. break;
  2432. case kDcyAdsrId:
  2433. _cmAdsrSetTime(p,ms,&p->dcySmp);
  2434. break;
  2435. case kSusAdsrId:
  2436. _cmAdsrSetTime(p,ms,&p->susSmp);
  2437. break;
  2438. case kRlsAdsrId:
  2439. _cmAdsrSetTime(p,ms,&p->rlsSmp);
  2440. break;
  2441. default:
  2442. { assert(0); }
  2443. }
  2444. }
  2445. void cmAdsrSetLevel( cmAdsr* p, cmReal_t level, unsigned id )
  2446. {
  2447. switch( id )
  2448. {
  2449. case kDlyAdsrId:
  2450. p->levelMin = level;
  2451. break;
  2452. case kAtkAdsrId:
  2453. p->atkLevel = level;
  2454. p->actAtkLevel = p->atkLevel;
  2455. break;
  2456. case kSusAdsrId:
  2457. p->susLevel = level;
  2458. p->actSusLevel = p->susLevel;
  2459. break;
  2460. default:
  2461. { assert(0); }
  2462. }
  2463. }
  2464. void cmAdsrReport( cmAdsr* p, cmRpt_t* rpt )
  2465. {
  2466. cmRptPrintf(rpt,"state:%i gate:%i phs:%i d:%i a:%i (%i) d:%i s:%i r:%i (%i) - min:%f atk:%f\n",p->state,p->gateFl,p->durSmp,p->dlySmp,p->atkSmp,p->atkDurSmp,p->dcySmp,p->susSmp,p->rlsSmp,p->rlsDurSmp, p->levelMin, p->atkLevel);
  2467. }
  2468. //=======================================================================================================================
  2469. cmCompressor* cmCompressorAlloc( cmCtx* c, cmCompressor* p, cmReal_t srate, unsigned procSmpCnt, cmReal_t inGain, cmReal_t rmsWndMaxMs, cmReal_t rmsWndMs, cmReal_t threshDb, cmReal_t ratio_num, cmReal_t atkMs, cmReal_t rlsMs, cmReal_t outGain, bool bypassFl )
  2470. {
  2471. cmCompressor* op = cmObjAlloc(cmCompressor, c, p );
  2472. if( srate != 0 )
  2473. if( cmCompressorInit( op, srate, procSmpCnt, inGain, rmsWndMaxMs, rmsWndMs, threshDb, ratio_num, atkMs, rlsMs, outGain, bypassFl ) != cmOkRC )
  2474. cmCompressorFree(&op);
  2475. return op;
  2476. }
  2477. cmRC_t cmCompressorFree( cmCompressor** pp )
  2478. {
  2479. cmRC_t rc = cmOkRC;
  2480. if( pp == NULL || *pp == NULL )
  2481. return cmOkRC;
  2482. cmCompressor* p = *pp;
  2483. if((rc = cmCompressorFinal(p)) != cmOkRC )
  2484. return rc;
  2485. cmMemFree(p->rmsWnd);
  2486. cmObjFree(pp);
  2487. return cmOkRC;
  2488. }
  2489. cmRC_t cmCompressorInit( cmCompressor* p, cmReal_t srate, unsigned procSmpCnt, cmReal_t inGain, cmReal_t rmsWndMaxMs, cmReal_t rmsWndMs, cmReal_t threshDb, cmReal_t ratio_num, cmReal_t atkMs, cmReal_t rlsMs, cmReal_t outGain, bool bypassFl )
  2490. {
  2491. cmRC_t rc;
  2492. if((rc = cmCompressorFinal(p)) != cmOkRC )
  2493. return rc;
  2494. p->srate = srate;
  2495. p->procSmpCnt = procSmpCnt;
  2496. p->threshDb = threshDb;
  2497. p->ratio_num = ratio_num;
  2498. cmCompressorSetAttackMs(p,atkMs);
  2499. cmCompressorSetReleaseMs(p,rlsMs);
  2500. p->inGain = inGain;
  2501. p->outGain = outGain;
  2502. p->bypassFl = bypassFl;
  2503. p->rmsWndAllocCnt = cmMax(1,(unsigned)floor(rmsWndMaxMs * srate / (1000.0 * procSmpCnt)));
  2504. p->rmsWnd = cmMemResizeZ(cmSample_t,p->rmsWnd,p->rmsWndAllocCnt);
  2505. cmCompressorSetRmsWndMs(p, rmsWndMs );
  2506. p->rmsWndIdx = 0;
  2507. p->state = kRlsCompId;
  2508. p->timeConstDb = 10.0;
  2509. p->accumDb = p->threshDb;
  2510. return rc;
  2511. }
  2512. cmRC_t cmCompressorFinal( cmCompressor* p )
  2513. { return cmOkRC; }
  2514. /*
  2515. The ratio determines to what degree a signal above the threshold is reduced.
  2516. Given a 2:1 ratio, a signal 2dB above the threshold will be reduced to 1db above the threshold.
  2517. Given a 4:1 ratio, a signal 2dB above the threshold will be reduced to 0.25db above the threshold.
  2518. Gain_reduction_db = (thresh - signal) / ratio_numerator (difference between the threshold and signal level after reduction)
  2519. Gain Coeff = 10^(gain_reduction_db / 20);
  2520. Total_reduction_db = signal - threshold + Gain_reduc_db
  2521. (total change in signal level)
  2522. The attack can be viewed as beginning at the threshold and moving to the peak
  2523. over some period of time. In linear terms this will go from 1.0 to the max gain
  2524. reductions. In this case we step from thresh to peak at a fixed rate in dB
  2525. based on the attack time.
  2526. Db: thresh - [thesh:peak] / ratio_num
  2527. Linear: pow(10, (thresh - [thesh:peak] / ratio_num)/20 );
  2528. During attacks p->accumDb increments toward the p->pkDb.
  2529. During release p->accumDb decrements toward the threshold.
  2530. (thresh - accumDb) / ratio_num gives the signal level which will be achieved
  2531. if this value is converted to linear form and applied as a gain coeff.
  2532. See compressor.m
  2533. */
  2534. cmRC_t cmCompressorExec( cmCompressor* p, const cmSample_t* x, cmSample_t* y, unsigned n )
  2535. {
  2536. cmSample_t xx[n];
  2537. cmVOS_MultVVS(xx,n,x,p->inGain); // apply input gain
  2538. p->rmsWnd[ p->rmsWndIdx ] = cmVOS_RMS(xx, n, n ); // calc and store signal RMS
  2539. p->rmsWndIdx = (p->rmsWndIdx + 1) % p->rmsWndCnt; // advance the RMS storage buffer
  2540. cmReal_t rmsLin = cmVOS_Sum(p->rmsWnd,p->rmsWndCnt) / p->rmsWndCnt; // calc avg RMS
  2541. cmReal_t rmsDb = cmMax(-100.0,20 * log10(cmMax(0.00001,rmsLin))); // convert avg RMS to dB
  2542. rmsDb += 100.0;
  2543. // if the compressor is bypassed
  2544. if( p->bypassFl )
  2545. {
  2546. cmVOS_Copy(y,n,x); // copy through - with no input gain
  2547. return cmOkRC;
  2548. }
  2549. // if the signal is above the threshold
  2550. if( rmsDb <= p->threshDb )
  2551. p->state = kRlsCompId;
  2552. else
  2553. {
  2554. if( rmsDb > p->pkDb )
  2555. p->pkDb = rmsDb;
  2556. p->state = kAtkCompId;
  2557. }
  2558. switch( p->state )
  2559. {
  2560. case kAtkCompId:
  2561. p->accumDb = cmMin(p->pkDb, p->accumDb + p->timeConstDb * n / p->atkSmp );
  2562. break;
  2563. case kRlsCompId:
  2564. p->accumDb = cmMax(p->threshDb, p->accumDb - p->timeConstDb * n / p->rlsSmp );
  2565. break;
  2566. }
  2567. p->gain = pow(10.0,(p->threshDb - p->accumDb) / (p->ratio_num * 20.0));
  2568. cmVOS_MultVVS(y,n,xx,p->gain * p->outGain);
  2569. return cmOkRC;
  2570. }
  2571. void _cmCompressorSetMs( cmCompressor* p, cmReal_t ms, unsigned* smpPtr )
  2572. { *smpPtr = cmMax(1,(unsigned)floor(ms * p->srate / 1000.0)); }
  2573. void cmCompressorSetAttackMs( cmCompressor* p, cmReal_t ms )
  2574. { _cmCompressorSetMs(p,ms,&p->atkSmp); }
  2575. void cmCompressorSetReleaseMs( cmCompressor* p, cmReal_t ms )
  2576. { _cmCompressorSetMs(p,ms,&p->rlsSmp); }
  2577. void cmCompressorSetThreshDb( cmCompressor* p, cmReal_t threshDb )
  2578. { p->threshDb = cmMax(0.0,100 + threshDb); }
  2579. void cmCompressorSetRmsWndMs( cmCompressor* p, cmReal_t ms )
  2580. {
  2581. p->rmsWndCnt = cmMax(1,(unsigned)floor(ms * p->srate / (1000.0 * p->procSmpCnt)));
  2582. // do not allow rmsWndCnt to exceed rmsWndAllocCnt
  2583. if( p->rmsWndCnt > p->rmsWndAllocCnt )
  2584. p->rmsWndCnt = p->rmsWndAllocCnt;
  2585. }
  2586. //=======================================================================================================================
  2587. cmBiQuadEq* cmBiQuadEqAlloc( cmCtx* c, cmBiQuadEq* p, cmReal_t srate, unsigned mode, cmReal_t f0Hz, cmReal_t Q, cmReal_t gainDb, bool bypassFl )
  2588. {
  2589. cmBiQuadEq* op = cmObjAlloc(cmBiQuadEq, c, p );
  2590. if( srate != 0 )
  2591. if( cmBiQuadEqInit( op, srate, mode, f0Hz, Q, gainDb, bypassFl ) != cmOkRC )
  2592. cmBiQuadEqFree(&op);
  2593. return op;
  2594. }
  2595. cmRC_t cmBiQuadEqFree( cmBiQuadEq** pp )
  2596. {
  2597. cmRC_t rc = cmOkRC;
  2598. if( pp == NULL || *pp == NULL )
  2599. return cmOkRC;
  2600. cmBiQuadEq* p = *pp;
  2601. if((rc = cmBiQuadEqFinal(p)) != cmOkRC )
  2602. return rc;
  2603. cmObjFree(pp);
  2604. return cmOkRC;
  2605. }
  2606. void _cmBiQuadEqInit( cmBiQuadEq* p )
  2607. {
  2608. cmReal_t w0 = 2*M_PI*p->f0Hz/p->srate;
  2609. cmReal_t cos_w0 = cos(w0);
  2610. cmReal_t alpha = sin(w0)/(2*p->Q);
  2611. if( p->mode==kLowShelfBqId || p->mode==kHighShelfBqId )
  2612. {
  2613. cmReal_t c = p->mode==kLowShelfBqId ? 1.0 : -1.0;
  2614. cmReal_t A = pow(10.0,p->gainDb/40.0);
  2615. cmReal_t B = 2*sqrt(A)*alpha;
  2616. p->b[0] = A*( (A+1) - c * (A-1)*cos_w0 + B );
  2617. p->b[1] = c*2*A*( (A-1) - c * (A+1)*cos_w0);
  2618. p->b[2] = A*( (A+1) - c * (A-1)*cos_w0 - B );
  2619. p->a[0] = (A+1) + c * (A-1)*cos_w0 + B;
  2620. p->a[1] = -c*2*( (A-1) + c * (A+1)*cos_w0);
  2621. p->a[2] = (A+1) + c * (A-1)*cos_w0 - B;
  2622. }
  2623. else
  2624. {
  2625. if( p->mode != kPeakBqId )
  2626. {
  2627. p->a[0] = 1 + alpha;
  2628. p->a[1] = -2*cos_w0;
  2629. p->a[2] = 1 - alpha;
  2630. }
  2631. switch(p->mode)
  2632. {
  2633. case kLpfBqId:
  2634. case kHpFBqId:
  2635. {
  2636. cmReal_t c = p->mode==kLpfBqId ? 1.0 : -1.0;
  2637. p->b[0] = (1 - c * cos_w0)/2;
  2638. p->b[1] = c * (1 - c * cos_w0);
  2639. p->b[2] = (1 - c * cos_w0)/2;
  2640. }
  2641. break;
  2642. case kBpfBqId:
  2643. p->b[0] = p->Q*alpha;
  2644. p->b[1] = 0;
  2645. p->b[2] = -p->Q*alpha;
  2646. break;
  2647. case kNotchBqId:
  2648. p->b[0] = 1;
  2649. p->b[1] = -2*cos_w0;
  2650. p->b[2] = 1;
  2651. break;
  2652. case kAllpassBqId:
  2653. p->b[0] = 1 - alpha;
  2654. p->b[1] = -2*cos_w0;
  2655. p->b[2] = 1 + alpha;
  2656. break;
  2657. case kPeakBqId:
  2658. {
  2659. cmReal_t A = pow(10.0,p->gainDb/40.0);
  2660. p->b[0] = 1 + alpha*A;
  2661. p->b[1] = -2*cos_w0;
  2662. p->b[2] = 1 - alpha*A;
  2663. p->a[0] = 1 + alpha/A;
  2664. p->a[1] = -2*cos_w0;
  2665. p->a[2] = 1 - alpha/A;
  2666. }
  2667. break;
  2668. }
  2669. }
  2670. cmReal_t a0 = p->a[0];
  2671. unsigned i=0;
  2672. for(; i<3; ++i)
  2673. {
  2674. p->b[i]/=a0;
  2675. p->a[i]/=a0;
  2676. }
  2677. if(0)
  2678. {
  2679. printf("sr:%f mode:%i f0:%f q:%f gain:%f\n", p->srate,p->mode,p->f0Hz,p->Q,p->gainDb);
  2680. for(i=0; i<3; ++i)
  2681. printf("a[%i]=%f b[%i]=%f ",i,p->a[i],i,p->b[i]);
  2682. printf("\n");
  2683. }
  2684. }
  2685. cmRC_t cmBiQuadEqInit( cmBiQuadEq* p, cmReal_t srate, unsigned mode, cmReal_t f0Hz, cmReal_t Q, cmReal_t gainDb, bool bypassFl )
  2686. {
  2687. cmRC_t rc;
  2688. if((rc = cmBiQuadEqFinal(p)) != cmOkRC )
  2689. return rc;
  2690. memset(p->d,0,sizeof(p->d));
  2691. p->srate = srate;
  2692. cmBiQuadEqSet(p, mode, f0Hz, Q, gainDb );
  2693. _cmBiQuadEqInit(p);
  2694. return rc;
  2695. }
  2696. cmRC_t cmBiQuadEqFinal( cmBiQuadEq* p )
  2697. { return cmOkRC;}
  2698. cmRC_t cmBiQuadEqExec( cmBiQuadEq* p, const cmSample_t* x, cmSample_t* y, unsigned n )
  2699. {
  2700. if( y == NULL )
  2701. return cmOkRC;
  2702. if( x == NULL )
  2703. {
  2704. cmVOS_Zero(y,n);
  2705. return cmOkRC;
  2706. }
  2707. if( p->bypassFl )
  2708. {
  2709. cmVOS_Copy(y,n,x);
  2710. return cmOkRC;
  2711. }
  2712. // Direct Form I implementation
  2713. unsigned i=0;
  2714. for(; i<n; ++i)
  2715. {
  2716. y[i] = p->b[0]*x[i] + p->b[1]*p->d[0] + p->b[2]*p->d[1] - p->a[1]*p->d[2] - p->a[2]*p->d[3];
  2717. p->d[1] = p->d[0];
  2718. p->d[0] = x[i];
  2719. p->d[3] = p->d[2];
  2720. p->d[2] = y[i];
  2721. }
  2722. return cmOkRC;
  2723. }
  2724. void cmBiQuadEqSet( cmBiQuadEq* p, unsigned mode, cmReal_t f0Hz, cmReal_t Q, cmReal_t gainDb )
  2725. {
  2726. p->mode = mode;
  2727. p->f0Hz = f0Hz;
  2728. p->Q = Q;
  2729. p->gainDb= gainDb;
  2730. _cmBiQuadEqInit(p);
  2731. }
  2732. //=======================================================================================================================
  2733. cmDistDs* cmDistDsAlloc( cmCtx* c, cmDistDs* p, cmReal_t srate, cmReal_t inGain, cmReal_t downSrate, cmReal_t bits, bool rectFl, bool fullFl, cmReal_t clipDb, cmReal_t outGain, bool bypassFl )
  2734. {
  2735. cmDistDs* op = cmObjAlloc(cmDistDs, c, p );
  2736. if( srate != 0 )
  2737. if( cmDistDsInit( op, srate, inGain, downSrate, bits, rectFl, fullFl, clipDb, outGain, bypassFl ) != cmOkRC )
  2738. cmDistDsFree(&op);
  2739. return op;
  2740. }
  2741. cmRC_t cmDistDsFree( cmDistDs** pp )
  2742. {
  2743. cmRC_t rc = cmOkRC;
  2744. if( pp == NULL || *pp == NULL )
  2745. return cmOkRC;
  2746. cmDistDs* p = *pp;
  2747. if((rc = cmDistDsFinal(p)) != cmOkRC )
  2748. return rc;
  2749. cmObjFree(pp);
  2750. return cmOkRC;
  2751. }
  2752. cmRC_t cmDistDsInit( cmDistDs* p, cmReal_t srate, cmReal_t inGain, cmReal_t downSrate, cmReal_t bits, bool rectFl, bool fullFl, cmReal_t clipDb, cmReal_t outGain, bool bypassFl )
  2753. {
  2754. cmRC_t rc;
  2755. if((rc = cmDistDsFinal(p)) != cmOkRC )
  2756. return rc;
  2757. p->srate = srate;
  2758. p->downSrate = downSrate;
  2759. p->bits = bits;
  2760. p->rectFl = rectFl;
  2761. p->fullFl = fullFl;
  2762. p->clipDb = clipDb;
  2763. p->inGain = inGain;
  2764. p->outGain = outGain;
  2765. p->bypassFl = bypassFl;
  2766. p->fracIdx = 0;
  2767. p->lastVal = 0;
  2768. p->lastY = 0;
  2769. p->lastX = 0;
  2770. return rc;
  2771. }
  2772. cmRC_t cmDistDsFinal( cmDistDs* p )
  2773. { return cmOkRC; }
  2774. void _cmDistDsExpr0( cmDistDs* p, const cmSample_t* x, cmSample_t* y, unsigned n )
  2775. {
  2776. unsigned i= 0;
  2777. for(i=0; i<n; ++i)
  2778. {
  2779. p->lastY = fmod(p->lastY + fabs(x[i] - p->lastX),2.0);
  2780. y[i] = cmVOS_RMS(x,n,n) * x[i] * (p->lastY - 1.0);
  2781. p->lastX = x[i];
  2782. }
  2783. }
  2784. void _cmDistDsExpr1( cmDistDs* p, cmSample_t* x, cmSample_t* y, unsigned n )
  2785. {
  2786. unsigned i= 0;
  2787. for(i=0; i<n; ++i)
  2788. {
  2789. p->lastY = fmod(p->lastY + fabs(x[i] - p->lastX),2.0*M_PI);
  2790. y[i] = x[i] * sin(p->lastY);
  2791. p->lastX = x[i];
  2792. }
  2793. }
  2794. cmRC_t cmDistDsExec( cmDistDs* p, const cmSample_t* x, cmSample_t* y, unsigned n )
  2795. {
  2796. if( x == NULL )
  2797. {
  2798. if( y != NULL )
  2799. cmVOS_Zero(y,n);
  2800. return cmOkRC;
  2801. }
  2802. if( p->bypassFl )
  2803. {
  2804. cmVOS_Copy(y,n,x);
  2805. return cmOkRC;
  2806. }
  2807. unsigned maxVal = cmMax(2,(unsigned)round(pow(2.0,p->bits)));
  2808. double incr = 1.0; // p->downSrate / p->srate;
  2809. unsigned i;
  2810. enum { kNoRectId, kFullRectId, kHalfRectId };
  2811. unsigned rectCode = kNoRectId;
  2812. //cmSample_t t[n];
  2813. //_cmDistDsExpr0(p,x,t,n);
  2814. //x = t;
  2815. if( p->rectFl )
  2816. {
  2817. if( p->fullFl )
  2818. rectCode = kFullRectId;
  2819. else
  2820. rectCode = kHalfRectId;
  2821. }
  2822. double clipLevel = p->clipDb < -100.0 ? 0.0 : pow(10.0,p->clipDb/20.0);
  2823. for(i=0; i<n; ++i)
  2824. {
  2825. double ii = floor(p->fracIdx);
  2826. p->fracIdx += incr;
  2827. // if it is time to sample again
  2828. if( floor(p->fracIdx) != ii )
  2829. {
  2830. cmSample_t v = p->inGain * floor(x[i] * maxVal) / maxVal;
  2831. switch( rectCode )
  2832. {
  2833. case kFullRectId:
  2834. v = (cmSample_t)fabs(v);
  2835. break;
  2836. case kHalfRectId:
  2837. if( v < 0.0 )
  2838. v = 0.0;
  2839. break;
  2840. }
  2841. if( fabs(v) > clipLevel )
  2842. v = v<0.0 ? -clipLevel : clipLevel;
  2843. p->lastVal = v * p->outGain;
  2844. }
  2845. y[i] = p->lastVal;
  2846. }
  2847. return cmOkRC;
  2848. }