Copyright (C) Kevin Larke 2009-2020

This file is part of libcm.

libcm is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

libcm is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

See the GNU General Public License distributed with the libcm package or look here: .


cmPitchShift : Time-domain pitch shifter based on sample rate conversion.

typedef struct
{
  double      wi;
  double      xi;
  int         yn;
  cmSample_t* y;
  int         yii;
  int         yoi;
  int         ynn;
  
} cmPitchShiftOsc_t;


typedef struct
{
  cmObj       obj;
  unsigned    procSmpCnt;
  double      srate;
  
  int               outN;        // procSmpCnt
  int               wn;          
  int               xn;          
  int               bn;          
  cmSample_t*       b;           // b[bn]
  cmSample_t*       x;           // x[xn] 
  cmSample_t*       wnd;         // wnd[wn]
  cmSample_t*       outV;        // outV[outN];
  int               xni;         
  bool              cubeFl;      
  cmPitchShiftOsc_t osc[2];      
  
  
} cmPitchShift;

cmPitchShift* cmPitchShiftAlloc( cmCtx* c, cmPitchShift* p, unsigned procSmpCnt, cmReal_t srate );
cmRC_t        cmPitchShiftFree( cmPitchShift** pp );
cmRC_t        cmPitchShiftInit( cmPitchShift* p, unsigned procSmpCnt, cmReal_t srate );
cmRC_t        cmPitchShiftFinal(cmPitchShift* p );
cmRC_t        cmPitchShiftExec( cmPitchShift* p, const cmSample_t* x, cmSample_t* y, unsigned n, double shiftRatio, bool bypassFl );


cmLoopRecord : Audio interactive loop recorder.

typedef struct
{
  double     xi;   // index into xV[]
  double     wi;   // index into wV[]
  cmSample_t u;    // cross-fade window polarity 
} cmLoopRecdOsc;

typedef struct
{
  cmLoopRecdOsc osc[2];        
  cmSample_t*   xV;            // xV[ xN ]
  int           xN;            // maxRecdSmpCnt
  int           xfN;           // cross-fade sample count
  int           xii;           // xV[] recording input index
  cmSample_t*   wV;            // wV[ xN ] window function (actually contains xii values after recording)
} cmLoopRecdBuf;

typedef struct
{
  cmObj          obj;
  cmSample_t*    bufMem;
  unsigned       maxRecdSmpCnt;
  cmLoopRecdBuf* bufArray;
  unsigned       bufArrayCnt;
  cmSample_t*    outV;
  unsigned       outN;
  unsigned       procSmpCnt;
  unsigned       xfadeSmpCnt;
  unsigned       recdBufIdx;
  unsigned       playBufIdx;
  bool           recdFl;
  bool           playFl;
  
} cmLoopRecord;

cmLoopRecord* cmLoopRecordAlloc( cmCtx* c, cmLoopRecord* p, unsigned procSmpCnt, unsigned maxRecdSmpCnt, unsigned xfadeSmpCnt );
cmRC_t        cmLoopRecordFree( cmLoopRecord** pp );
cmRC_t        cmLoopRecordInit( cmLoopRecord* p, unsigned procSmpCnt, unsigned maxRecdSmpCnt, unsigned xfadeSmpCnt );
cmRC_t        cmLoopRecordFinal( cmLoopRecord* p );
// rgain=recorder output gain, pgain=pass through gain
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 );



cmGateDetector : Detect when a signal onsets and offsets.
typedef struct
{
  cmObj       obj;
  unsigned    rmsN;
  cmSample_t* rmsV;           // rmsV[rmsN] previous rmsN values. rmsV[rmsN-1] == rms 
  cmSample_t  rms;            // RMS of last procSmpCnt samples
  unsigned    wndN;
  cmSample_t* wndV;
  cmSample_t  mean;
  cmSample_t  d0;
  unsigned    durSmpCnt;      // duration of the current gate polarity in samples
  bool        gateFl;
  bool        deltaFl;  
  cmReal_t    onThreshPct;
  cmReal_t    onThreshDb;
  cmReal_t    offThreshDb;    
} cmGateDetect;

cmGateDetect* cmGateDetectAlloc( cmCtx* c, cmGateDetect* p, unsigned procSmpCnt, cmReal_t onThreshPct, cmReal_t onThreshDb, cmReal_t offThreshDb );
cmRC_t       cmGateDetectFree( cmGateDetect** p );
cmRC_t       cmGateDetectInit( cmGateDetect* p, unsigned procSmpCnt, cmReal_t onThreshPct, cmReal_t onThreshDb, cmReal_t offThreshDb );
cmRC_t       cmGateDetectFinal(cmGateDetect* p );
cmRC_t       cmGateDetectExec( cmGateDetect* p, const cmSample_t* x, unsigned xn );


cmGateDetector2 : Improved gate detector to detect when a signal onsets and offsets.
typedef struct
{
  unsigned medCnt;        // length of the median filter
  unsigned avgCnt;        // length of the (rms - med) moving avg. filter
  unsigned suprCnt;       // length of the supression window
  unsigned offCnt;        // length of the offset detection window
  cmReal_t suprCoeff;     // supression signal shape coeff
  cmReal_t onThreshDb;    // onset threshold
  cmReal_t offThreshDb;   // offset threshold
} cmGateDetectParams;

typedef struct
{
  cmObj              obj;
  cmGateDetectParams args;
  
  cmSample_t*        medV;    // medV[medCnt] 
  unsigned           medIdx; 
  cmSample_t*        avgV;    // avgV[avgCnt]
  unsigned           avgIdx;
  cmSample_t*        fcofV;   // fcofV[medCnt]
  cmSample_t*        fdlyV;   // fdlyV[medCnt]
  cmSample_t*        suprV;   // suprV[suprCnt]
  unsigned           suprIdx;
  cmSample_t*        pkV;     // pkV[3]
  cmSample_t*        offV;    // offV[offCnt]
  unsigned           offIdx;
  
  unsigned           pkFl;      
  bool               gateFl;    // set by onset, cleared by offset
  bool               onFl;      // set if an onset was detected
  bool               offFl;     // set if an offset was detected
  
  cmReal_t           onThresh;
  cmReal_t           offThresh;
  
  cmSample_t         rms;    // RMS
  cmSample_t         med;    // median RMS over last medCnt exec's
  cmSample_t         dif;    // max(0, RMS - median_RMS)
  cmSample_t         avg;    // avg dif's over last avgCnt exec's
  cmSample_t         ons;    // dif - avg
  cmSample_t         flt;    // filtered(ons)
  cmSample_t         sup;    // flt w/ suppression
} cmGateDetect2;


cmGateDetect2* cmGateDetectAlloc2( cmCtx* c, cmGateDetect2* p, unsigned procSmpCnt, const cmGateDetectParams* args );
cmRC_t         cmGateDetectFree2( cmGateDetect2** p );
cmRC_t         cmGateDetectInit2( cmGateDetect2* p, unsigned procSmpCnt, const cmGateDetectParams* args );
cmRC_t         cmGateDetectFinal2(cmGateDetect2* p );
cmRC_t         cmGateDetectExec2( cmGateDetect2* p, const cmSample_t* x, unsigned xn );
void           cmGateDetectSetOnThreshDb2( cmGateDetect2* p, cmReal_t db );
void           cmGateDetectSetOffThreshDb2( cmGateDetect2* p, cmReal_t db );


cmAutoGain : Automatically balance a set of audio signals by adjusting their level.

//
// Calculate a set of automatic gain adjustments for a set of audio channels.
//
// 1)  Call cmAutoGainInit() to reset the object.
// 2)  Call  cmAutoGainStartCh() and provide an id to identify the channel.
// 3)  Call  cmAutoGainProcCh() with audio from the channel identified in 2)
// 4)  Repeat 2) and 3) for for all channels.  
// 5)  Call cmAutoGainCalcGains() to set the value of cmAutoGainCh.gain.
// 
// The gain coefficents are set to balance the overall gain. 
// (i.e. Loud channels are decreased and quiet channels are increased.)

typedef struct
{
  unsigned id;          // channel id
  cmReal_t gain;        // gain adjustment coefficient
  unsigned onCnt;       // count of onsets detected 
  unsigned offCnt;      // count of offsets detected
  cmReal_t gateMaxAvg;  // average of the max values for each detected event
} cmAutoGainCh;

typedef struct
{
  cmObj          obj;
  cmShiftBuf*    sbp;
  cmGateDetect2* gdp;
  cmAutoGainCh*  chArray;  
  unsigned       chCnt;
  
  
  cmAutoGainCh* chp;
  unsigned      gateCnt;
  cmReal_t      gateSum;
  cmReal_t      gateMax;
  cmReal_t      minRms;
  
} cmAutoGain;

cmAutoGain* cmAutoGainAlloc( cmCtx* c, cmAutoGain* p, unsigned procSmpCnt, cmReal_t srate, cmReal_t hopMs, unsigned chCnt, const cmGateDetectParams* gd_args );
cmRC_t      cmAutoGainFree( cmAutoGain** p );
cmRC_t      cmAutoGainInit( cmAutoGain* p, unsigned procSmpCnt, cmReal_t srate, cmReal_t hopMs, unsigned chCnt, const cmGateDetectParams* gd_args );
cmRC_t      cmAutoGainFinal( cmAutoGain* p );

// Notify the object that the following calls to cmAutoGainProcCh()
// should be associed with the channel 'id'.
cmRC_t      cmAutoGainStartCh( cmAutoGain* p, unsigned id );

// Examine the signal arriving from the channel specified in the previous
// call to cmAutoGainProcCh() and determine the max RMS value for each 
// event contained in the signal. 
cmRC_t      cmAutoGainProcCh( cmAutoGain* p, const cmSample_t* x, unsigned xn );

// Calculate the cmAutoGainCh.gain coefficient for each channel.
cmRC_t      cmAutoGainCalcGains( cmAutoGain* p );

void        cmAutoGainPrint( cmAutoGain* p, cmRpt_t* rpt );


cmChCfg : Configure a 'fluxo' pickup channel.
typedef struct
{
  unsigned        ch;
  unsigned        ssi;
  const cmChar_t* pitchStr;
  unsigned        midi;
  cmReal_t        gain;
  bool            nsFl;   // noise shaper channel
  bool            cdFl;   // chord detector channel
} cmChCfgCh;

typedef struct
{
  cmObj           obj;
  cmChCfgCh*      chArray;
  unsigned        chCnt;
  unsigned        nsChCnt;  // count of noise-shaper channels
  const cmChar_t* fn;
  cmJsonH_t       jsH;
  cmJsonNode_t*   cap;
} cmChCfg;

cmChCfg* cmChCfgAlloc( cmCtx* c, cmChCfg* p, cmCtx_t* ctx, const cmChar_t* fn );
cmRC_t   cmChCfgFree(  cmChCfg** pp );
cmRC_t   cmChCfgInit(  cmChCfg*  p, cmCtx_t* ctx, const cmChar_t* fn );
cmRC_t   cmChCfgFinal( cmChCfg*  p );
cmRC_t   cmChCfgWrite( cmChCfg* p );
void     cmChCfgPrint( cmChCfg* p, cmRpt_t* rpt );
unsigned cmChCfgChannelCount( cmCtx_t* ctx, const cmChar_t* fn, unsigned* nsChCntPtr );
unsigned cmChCfgChannelIndex( cmCtx_t* ctx, const cmChar_t* fn, unsigned chIdx );


cmChordDetector : Chord detector based on evaluating signals from cmGateDetector2.

typedef struct 
{
  bool     readyFl;      // This channel has received an offset since it was last a candidate.
  bool     candFl;       // This channel is a chord candidate
  unsigned candSmpTime;  // Time that this channel became a candidate
  cmReal_t candRMS;      // RMS when this channel became a candidate
  bool     chordFl;      // This channel is part of the current chord
  bool     gateFl;       // Previous gate state
} cmChordDetectCh;

typedef struct
{
  cmObj            obj;
  unsigned         maxTimeSpanSmpCnt;  // maximum time between onsets of first and last note of chord
  unsigned         minNotesPerChord;   // the min. number of notes required to form a chord
  unsigned         chCnt;              // count of channels
  cmChordDetectCh* chArray;            // channel state array
  bool             detectFl;           // true when a new chord has been detected
  unsigned         timeSmp;            // current time
  cmReal_t         srate;
} cmChordDetect;

cmChordDetect* cmChordDetectAlloc( cmCtx*c, cmChordDetect* p, cmReal_t srate, unsigned chCnt, cmReal_t maxTimeSpanMs, unsigned minNotesPerChord  );
cmRC_t         cmChordDetectFree(  cmChordDetect** pp );
cmRC_t         cmChordDetectInit(  cmChordDetect* p, cmReal_t srate, unsigned chCnt, cmReal_t maxTimeSpanMs, unsigned minNotesPerChord );
cmRC_t         cmChordDetectFinal( cmChordDetect* p );
cmRC_t         cmChordDetectExec(  cmChordDetect* p, unsigned procSmpCnt, const bool* gateV, const cmReal_t* rmsV, unsigned chCnt );
cmRC_t         cmChordDetectSetSpanMs( cmChordDetect* p, cmReal_t maxTimeSpanMs );


cmXfader : Audio cross fade controller.
// This object is not really a cross-fader.  It is really just a multichannel
// fader - which just calculates the fade gain but does not actually apply it
// to the audio signal - unless you use cmXfaderExecAudio()
typedef struct
{
  cmReal_t ep_gain;  // equal power xfade gain
  cmReal_t gain;     // linear gain
  bool     gateFl;  // true if channel is on
  bool     onFl;    // true if gateFl transitioned to true on this cycle 
  bool     offFl;   // true if gateFl transitioned to false on this cycle
} cmXfaderCh;

typedef struct
{
  cmObj       obj;
  unsigned    chCnt;
  cmXfaderCh* chArray;
  unsigned    fadeSmpCnt;  
  unsigned    fadeInSmpCnt;
  unsigned    fadeOutSmpCnt;
  cmReal_t    srate;
  bool        gateFl;   // true if any channels are on
  bool        onFl;     // true on cycle where gate transitions to 'on'.
  bool        offFl;    // true on cycle where gate transitions to 'off'.
} cmXfader;

cmXfader* cmXfaderAlloc( cmCtx*c, cmXfader* p, cmReal_t srate, unsigned chCnt, cmReal_t fadeTimeMs  );
cmRC_t    cmXfaderFree(  cmXfader** pp );
cmRC_t    cmXfaderInit(  cmXfader* p, cmReal_t srate, unsigned chCnt, cmReal_t fadeTimeMs  );
cmRC_t    cmXfaderFinal(  cmXfader* p );
cmRC_t    cmXfaderExec(  cmXfader* p, unsigned procSmpCnt, const bool* gateV, unsigned chCnt );
cmRC_t    cmXfaderExecAudio( cmXfader* p, unsigned procSmpCnt, const bool* gateV, unsigned chCnt, const cmSample_t* x[], cmSample_t* y );
void      cmXfaderSetXfadeTime( cmXfader* p, cmReal_t fadeTimeMs );
void      cmXfaderSetXfadeInTime( cmXfader* p, cmReal_t fadeTimeMs );
void      cmXfaderSetXfadeOutTime( cmXfader* p, cmReal_t fadeTimeMs );

// Set all gates to false except chIdx.
void      cmXfaderSelectOne( cmXfader* p, unsigned chIdx );
void      cmXfaderAllOff( cmXfader* p );
void      cmXfaderJumpToDestinationGain( cmXfader* p );  // jump to dest. gain based on gate state


cmFader : Fade in/out an audio signal based on the state of a gate control signal.
// This fader object accepts a gate signal. When the gate is high it increments
// the gain until it reaches 1.0. When the gate is low it decrements the gain
// until it reaches 0.0.  The fade time is the lenght of time the gain will take
// to transition from 0.0 to 1.0 or 1.0 to 0.0.
typedef struct
{
  cmObj       obj;
  unsigned    fadeSmpCnt;   // time to fade from 0-&gt1 or 1-&gt0 
  cmReal_t    srate;
  cmReal_t    gain;
} cmFader;

cmFader*  cmFaderAlloc( cmCtx*c, cmFader* p, cmReal_t srate, cmReal_t fadeTimeMs  );
cmRC_t    cmFaderFree(  cmFader** pp );
cmRC_t    cmFaderInit(  cmFader* p, cmReal_t srate, cmReal_t fadeTimeMs  );
cmRC_t    cmFaderFinal( cmFader* p );
cmRC_t    cmFaderExec(  cmFader* p, unsigned procSmpCnt, bool gateFl, bool mixFl, const cmSample_t* x, cmSample_t* y );
void      cmFaderSetFadeTime( cmFader* p, cmReal_t fadeTimeMs );


cmCombFilt : Comb and Inverse Comb filter algorithm with a variable fractional delay.
struct cmIDelay_str;
typedef struct
{
  cmObj     obj;
  cmReal_t  srate;          // system sample rate
  bool      feedbackFl;     // set if this is a feedback comb filter
  cmReal_t  minHz;          // lowest comb frequency this comb filter can support
  cmReal_t  hz;             // location of first comb
  cmReal_t  alpha;          // filter coeff.
  cmReal_t  dN;             // max length of the the cf delay line
  unsigned  dn;             // current length of cf delay line
  cmReal_t* d;              // d[dn] filter delay line
  cmReal_t* b;              // b[dn] feedforward coeff's
  cmReal_t* a;              // a[dn] feedback coeff's
  cmReal_t  b0;             // feedforward coeff 0
  bool      bypassFl;       // bypass enable flag
  struct cmIDelay_str* idp;
  
} cmCombFilt;

cmCombFilt* cmCombFiltAlloc( cmCtx* c, cmCombFilt* p, cmReal_t srate, bool feedbackFl, cmReal_t minHz, cmReal_t alpha, cmReal_t hz, bool bypassFl );
cmRC_t      cmCombFiltFree(  cmCombFilt** pp);
cmRC_t      cmCombFiltInit(  cmCombFilt* p, cmReal_t srate, bool feedbackFl, cmReal_t minHz, cmReal_t alpha, cmReal_t hz, bool bypassFl );
cmRC_t      cmCombFiltFinal( cmCombFilt* p );
cmRC_t      cmCombFiltExec(  cmCombFilt* p, const cmSample_t* x, cmSample_t* y, unsigned n );
void        cmCombFiltSetAlpha( cmCombFilt* p, cmReal_t alpha );
cmRC_t      cmCombFiltSetHz( cmCombFilt* p, cmReal_t hz );


cmDcFilt : DC Filter algorithm.

typedef struct
{
  cmObj    obj;
  cmReal_t d[2];  
  cmReal_t b[1];  
  cmReal_t a[1];  // a[dn] feedback coeff's
  cmReal_t b0;                  // feedforward coeff 0
  bool     bypassFl;
} cmDcFilt;

cmDcFilt* cmDcFiltAlloc( cmCtx* c, cmDcFilt* p, bool bypassFl );
cmRC_t    cmDcFiltFree(  cmDcFilt** pp);
cmRC_t    cmDcFiltInit(  cmDcFilt* p, bool bypassFl );
cmRC_t    cmDcFiltFinal( cmDcFilt* p );
cmRC_t    cmDcFiltExec(  cmDcFilt* p, const cmSample_t* x, cmSample_t* y, unsigned n );


cmIDelay : Variable interpolating fractional audio delay line.

typedef struct cmIDelay_str
{
  cmObj       obj;
  cmSample_t* d;   // d[dn] delay line
  int         dn;  // sizeo of delay 
  cmSample_t* m;   // memory buffer
  int         mn;  // size of memory bufer (dn+3) 
  int         ii;  // input index
  unsigned    tn;  // count of taps 
  cmReal_t*   ti;  // ti[tn] tap locations (fractional delay from t-&gtii)
  cmReal_t*   tff;  // tg[tn] tap out gain
  cmReal_t*   tfb; // tfb[tn] tap feedback gain
  cmReal_t    srate;
} cmIDelay;

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 );
cmRC_t    cmIDelayFree( cmIDelay** pp );
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 );
cmRC_t    cmIDelayFinal(cmIDelay* p );
cmRC_t    cmIDelayExec( cmIDelay* p, const cmSample_t* x, cmSample_t* y, unsigned n );
cmRC_t    cmIDelaySetTapMs( cmIDelay* p, unsigned tapIdx, cmReal_t tapMs );



cmGroupSel : Assign channel to dynamic groups under gate control.

// This object sequentially assigns channels to groups when their gates go high.
// 'chsPerGroup' channels will be assigned to each group.  No channel will be
// assigned to any group unless there are at least 'chsPerGroup' available
// (unassigned) channels.
// Channels are released from groups when one of the member channels gates goes low.
//

typedef struct
{
  cmReal_t rms;        // current rms of this input channel
  bool     gateFl;     // current gate state of this input channel
  bool     readyFl;    // this channel is available to be assigned to a group
  bool     offsetFl;   // the gate went low during this cycle (cleared on exec)
  unsigned groupIdx;   // group this channel is assigned to or cmInvalidIdx if it is not assigned to any group 
} cmGroupSelCh;

typedef struct
{
  unsigned* chIdxArray;  // chIdxArray[p-&gtchCnt] array of indexes to channels assigned to this group
  unsigned  chIdxCnt;    // count indexes in chIdxArray[] or 0 if the channel is not in use
  bool      releaseFl;   // true during the cycle that this group was released on
  bool      createFl;    // true during the cycle that this group was created on
} cmGroupSelGrp;

typedef struct
{
  cmObj obj;
  
  
  cmGroupSelCh*  chArray;      // chArray[chCnt]
  unsigned       chCnt;        // count of channels
  cmGroupSelGrp* groupArray;   // groupArray[groupCnt]
  unsigned       groupCnt;     // count of groups - must be &lt= chCnt - can be changed at any time 
  unsigned       chsPerGroup;  // channels per group
  bool           updateFl;     // set during exec if channels were assigned or released 
  
} cmGroupSel;

cmGroupSel* cmGroupSelAlloc( cmCtx* c, cmGroupSel* p, unsigned chCnt, unsigned groupCnt, unsigned chsPerGroup );
cmRC_t      cmGroupSelFree( cmGroupSel** pp );
cmRC_t      cmGroupSelInit( cmGroupSel* p, unsigned chCnt, unsigned groupCnt, unsigned chsPerGroup );
cmRC_t      cmGroupSelFinal( cmGroupSel* p );
cmRC_t      cmGroupSetChannelGate( cmGroupSel* p, unsigned chIdx, bool gateFl );
cmRC_t      cmGroupSetChannelRMS(  cmGroupSel* p, unsigned chIdx, cmReal_t rms );

// After exec if the p-&gtupdateFl is set then iterate through
// p-&gtgroupArray[]. Groups that have been created will have their 'createFl' set
// and groups that will be removed on the next cycle have their 'releaseFl' set.
cmRC_t      cmGroupSelExec( cmGroupSel* p );


cmAudioNofM : Route N of M possible input channels to N output channels under gate control.

// Route N of M input channels to N output channels.
// The N channels are selected from the first N gates to go high.

typedef struct cmAudioNofM_In_str
{
  bool        gateFl;
  bool        onsetFl;
  bool        offsetFl;
  unsigned    outChIdx;
  cmFader*    fader;
  struct cmAudioNofM_In_str* link;
} cmAudioNofM_In;

typedef struct
{
  struct cmAudioNofM_In_str* list;
} cmAudioNofM_Out;

typedef struct
{
  cmObj            obj;
  unsigned         iChCnt;       // (M) input channel count 
  cmAudioNofM_In*  inArray;      // chArray[ M ] - input channel array
  unsigned         oChCnt;       // (N) output channel count
  cmAudioNofM_Out* outArray;     // outArray[N] - output channel array
  unsigned         nxtOutChIdx;  // ch assoc;d with the next onset gate will be assined to this output channel
} cmAudioNofM;

cmAudioNofM* cmAudioNofMAlloc( cmCtx* c, cmAudioNofM* p, cmReal_t srate, unsigned iChCnt, unsigned oChCnt, cmReal_t fadeTimeMs );
cmRC_t       cmAudioNofMFree( cmAudioNofM** pp );
cmRC_t       cmAudioNofMInit( cmAudioNofM* p, cmReal_t srate, unsigned iChCnt, unsigned oChCnt, cmReal_t fadeTimeMs );
cmRC_t       cmAudioNofMFinal( cmAudioNofM* p );
cmRC_t       cmAudioNofMSetChannelGate( cmAudioNofM* p, unsigned inChIdx, bool gateFl );

// Sum the audio contained in x[inChCnt][n] into y[outChCnt][n] according 
// to the state of the object.
// Notes
// 1) y[n] should be zeroed by the caller as the output is summed into this buffer.
// 2) inChCnt should equal p-&gtiChCnt and outChCnt should equal p-&gtoChCnt
cmRC_t       cmAudioNofMExec( cmAudioNofM* p, const cmSample_t* x[], unsigned inChCnt, cmSample_t* y[], unsigned outChCnt, unsigned n );
cmRC_t       cmAudioNofMSetFadeMs( cmAudioNofM* p, cmReal_t fadeTimeMs );



cmAdsr : ADSR audio evelope generator.

enum { kDlyAdsrId, kAtkAdsrId, kDcyAdsrId, kSusAdsrId, kRlsAdsrId, kDoneAdsrId };

typedef struct
{
  cmObj    obj;
  cmReal_t srate;
  bool     trigModeFl;  // gate on triggers start, gate-off ignored
  cmReal_t levelMin;
  cmReal_t scaleDur;    
  
  int      dlySmp;
  int      atkSmp;
  cmReal_t atkLevel;
  int      dcySmp;
  int      susSmp;             // only used in trigger mode
  cmReal_t susLevel;
  int      rlsSmp;
  
  unsigned state;              // current state
  int      durSmp;             // time in current state
  cmReal_t level;              // current level 
  bool     gateFl;             // last gate state
  
  cmReal_t atkBegLevel;        // attack starting level
  cmReal_t atkDurSmp;          // attack duration 
  
  cmReal_t rlsLevel;           // release starting level
  cmReal_t rlsDurSmp;          // release duration 
  
  cmReal_t actAtkLevel;
  cmReal_t actSusLevel;
  
  
} cmAdsr;

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 ); 
cmRC_t    cmAdsrFree(  cmAdsr** pp );
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 );
cmRC_t    cmAdsrFinal( cmAdsr* p );
cmReal_t  cmAdsrExec( cmAdsr* p, unsigned procSmpCnt, bool gateFl, cmReal_t tscale, cmReal_t ascale );
void      cmAdsrSetTime( cmAdsr* p, cmReal_t ms, unsigned id );
void      cmAdsrSetLevel( cmAdsr* p, cmReal_t level, unsigned id );
void      cmAdsrReport( cmAdsr* p, cmRpt_t* rpt );


cmCompressor : Audio dynamics compressor algorithm.
enum { kAtkCompId, kRlsCompId };

typedef struct
{
  cmObj       obj;
  cmReal_t    srate;           // system sample rate
  unsigned    procSmpCnt;      // samples per exec cycle
  cmReal_t    inGain;          // input gain
  cmReal_t    threshDb;        // threshold in dB (max:100 min:0) 
  cmReal_t    ratio_num;       // numerator of the ratio
  unsigned    atkSmp;          // time to reduce the signal by 10.0 db
  unsigned    rlsSmp;          // time to increase the signal by 10.0 db
  cmReal_t    outGain;         // makeup gain
  bool        bypassFl;        // bypass enable
  
  cmSample_t* rmsWnd;          // rmsWnd[rmsWndAllocCnt]
  unsigned    rmsWndAllocCnt;  
  unsigned    rmsWndCnt;       // current RMS window size (rmsWndCnt must be &lt= rmsWndAllocCnt)
  unsigned    rmsWndIdx;       // next RMS window input index
  
  unsigned    state;           // env. state
  cmReal_t    rmsDb;           // current incoming signal RMS (max:100 min:0)
  cmReal_t    gain;            // current compressor gain
  
  cmReal_t    timeConstDb;     // the atk/rls will incr/decr by 'timeConstDb' per atkMs/rlsMs.
  cmReal_t    pkDb;            
  cmReal_t    accumDb;         
  
} cmCompressor;

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, cmReal_t atkMs, cmReal_t rlsMs, cmReal_t outGain, bool bypassFl );
cmRC_t  cmCompressorFree( cmCompressor** pp );
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, cmReal_t atkMs, cmReal_t rlsMs, cmReal_t outGain, bool bypassFl );  
cmRC_t  cmCompressorFinal( cmCompressor* p );
cmRC_t  cmCompressorExec( cmCompressor* p, const cmSample_t* x, cmSample_t* y, unsigned n );
void    cmCompressorSetAttackMs( cmCompressor* p, cmReal_t ms );
void    cmCompressorSetReleaseMs( cmCompressor* p, cmReal_t ms );
void    cmCompressorSetThreshDb(  cmCompressor* p, cmReal_t thresh );
void    cmCompressorSetRmsWndMs( cmCompressor* p, cmReal_t ms );



cmBiQuad : General purpose Biquad filter algorithm.

// BiQuad Audio Eq's based on Robert Bristow-Johnson's recipes.
// http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt
// See filter_rbj.m for equivalent octave code.

enum
{
  kLpfBqId,
  kHpFBqId,
  kBpfBqId,
  kNotchBqId,
  kAllpassBqId,
  kPeakBqId,
  kLowShelfBqId,
  kHighShelfBqId
};

typedef struct
{
  cmObj obj;
  
  cmReal_t srate;
  unsigned mode;
  cmReal_t f0Hz;
  cmReal_t Q;
  cmReal_t gainDb;
  
  cmReal_t d[4];
  cmReal_t b[3];
  cmReal_t a[3];
  
  bool bypassFl;
  
} cmBiQuadEq;

cmBiQuadEq* cmBiQuadEqAlloc( cmCtx* c, cmBiQuadEq* p, cmReal_t srate, unsigned mode, cmReal_t f0Hz, cmReal_t Q, cmReal_t gainDb, bool bypassFl );
cmRC_t      cmBiQuadEqFree( cmBiQuadEq** pp );
cmRC_t      cmBiQuadEqInit( cmBiQuadEq* p, cmReal_t srate, unsigned mode, cmReal_t f0Hz, cmReal_t Q, cmReal_t gainDb, bool bypassFl );  
cmRC_t      cmBiQuadEqFinal( cmBiQuadEq* p );
cmRC_t      cmBiQuadEqExec( cmBiQuadEq* p, const cmSample_t* x, cmSample_t* y, unsigned n );
void        cmBiQuadEqSet( cmBiQuadEq* p, unsigned mode, cmReal_t f0Hz, cmReal_t Q, cmReal_t gainDb );



cmDistDs : Guitar style distortion effect.
typedef struct
{
  cmObj      obj;
  cmReal_t   srate;
  cmReal_t   downSrate;
  cmReal_t   bits;
  bool       rectFl;
  bool       fullFl;
  cmReal_t   clipDb;
  cmReal_t   inGain;
  cmReal_t   outGain;
  bool       bypassFl;
  
  double     fracIdx;
  cmSample_t lastVal;
  
  cmSample_t lastY;
  cmSample_t lastX;
} cmDistDs;

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 );
cmRC_t    cmDistDsFree( cmDistDs** p );
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 );
cmRC_t    cmDistDsFinal( cmDistDs* p );
cmRC_t    cmDistDsExec(  cmDistDs* p, const cmSample_t* x, cmSample_t* y, unsigned n );