760 rindas
31 KiB
C
760 rindas
31 KiB
C
#ifndef cmProc3_h
|
|
#define cmProc3_h
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
//( { file_desc:"Processor Library 3" kw:[proclib]}
|
|
//)
|
|
|
|
//( { label:cmPitchShift file_desc:"Time-domain pitch shifter based on sample rate conversion." kw:[proc]}
|
|
|
|
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 );
|
|
|
|
//------------------------------------------------------------------------------------------------------------
|
|
//)
|
|
//( { label:cmLoopRecord file_desc:"Audio interactive loop recorder." kw:[proc]}
|
|
|
|
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 );
|
|
|
|
|
|
//------------------------------------------------------------------------------------------------------------
|
|
//)
|
|
//( { label:cmGateDetector file_desc:"Detect when a signal onsets and offsets." kw:[proc]}
|
|
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 );
|
|
|
|
//------------------------------------------------------------------------------------------------------------
|
|
//)
|
|
//( { label:cmGateDetector2 file_desc:"Improved gate detector to detect when a signal onsets and offsets." kw:[proc]}
|
|
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 );
|
|
|
|
//------------------------------------------------------------------------------------------------------------
|
|
//)
|
|
|
|
//( { label:cmAutoGain file_desc:"Automatically balance a set of audio signals by adjusting their level." kw:[proc fluxo]}
|
|
|
|
//
|
|
// 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 );
|
|
|
|
//------------------------------------------------------------------------------------------------------------
|
|
//)
|
|
|
|
//( { label:cmChCfg file_desc:"Configure a 'fluxo' pickup channel." kw:[proc fluxo]}
|
|
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 );
|
|
|
|
//------------------------------------------------------------------------------------------------------------
|
|
//)
|
|
|
|
//( { label:cmChordDetector file_desc:"Chord detector based on evaluating signals from cmGateDetector2." kw:[proc]}
|
|
|
|
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 );
|
|
|
|
//------------------------------------------------------------------------------------------------------------
|
|
//)
|
|
|
|
//( { label:cmXfader file_desc:"Audio cross fade controller." kw:[proc]}
|
|
// 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
|
|
|
|
//------------------------------------------------------------------------------------------------------------
|
|
//)
|
|
|
|
//( { label:cmFader file_desc:"Fade in/out an audio signal based on the state of a gate control signal." kw:[proc]}
|
|
// 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->1 or 1->0
|
|
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 );
|
|
|
|
//------------------------------------------------------------------------------------------------------------
|
|
//)
|
|
|
|
//( { label:cmCombFilt file_desc:"Comb and Inverse Comb filter algorithm with a variable fractional delay." kw:[proc]}
|
|
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 );
|
|
|
|
//------------------------------------------------------------------------------------------------------------
|
|
//)
|
|
|
|
//( { label:cmDcFilt file_desc:"DC Filter algorithm." kw:[proc]}
|
|
|
|
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 );
|
|
|
|
//------------------------------------------------------------------------------------------------------------
|
|
//)
|
|
|
|
//( { label:cmIDelay file_desc:"Variable interpolating fractional audio delay line." kw:[proc]}
|
|
|
|
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->ii)
|
|
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 );
|
|
|
|
|
|
//------------------------------------------------------------------------------------------------------------
|
|
//)
|
|
|
|
//( { label:cmGroupSel file_desc:"Assign channel to dynamic groups under gate control." kw:[proc]}
|
|
|
|
// 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->chCnt] 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 <= 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->updateFl is set then iterate through
|
|
// p->groupArray[]. 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 );
|
|
|
|
//------------------------------------------------------------------------------------------------------------
|
|
//)
|
|
|
|
//( { label:cmAudioNofM file_desc:"Route N of M possible input channels to N output channels under gate control." kw:[proc]}
|
|
|
|
// 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->iChCnt and outChCnt should equal p->oChCnt
|
|
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 );
|
|
|
|
|
|
//------------------------------------------------------------------------------------------------------------
|
|
//)
|
|
|
|
//( { label:cmAdsr file_desc:"ADSR audio evelope generator." kw:[proc]}
|
|
|
|
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 );
|
|
|
|
//------------------------------------------------------------------------------------------------------------
|
|
//)
|
|
|
|
//( { label:cmCompressor file_desc:"Audio dynamics compressor algorithm." kw:[proc]}
|
|
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 <= 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 );
|
|
|
|
|
|
//------------------------------------------------------------------------------------------------------------
|
|
//)
|
|
|
|
//( { label:cmBiQuad file_desc:"General purpose Biquad filter algorithm." kw:[proc]}
|
|
|
|
// 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 );
|
|
|
|
|
|
//------------------------------------------------------------------------------------------------------------
|
|
//)
|
|
|
|
//( { label:cmDistDs file_desc:"Guitar style distortion effect." kw:[proc]}
|
|
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 );
|
|
//------------------------------------------------------------------------------------------------------------
|
|
//)
|
|
|
|
|
|
//=======================================================================================================================
|
|
/*
|
|
typedef struct
|
|
{
|
|
cmObj obj;
|
|
} cmUnitDelay;
|
|
|
|
cmUnitDelay* cmUnitDelayAlloc( cmCtx* c, cmUnitDelay* p, cmReal_t srate, unsigned smpCnt, unsigned inCnt, unsigned outCnt, const cmReal_t delayMsV, unsigned delayCnt );
|
|
cmRC_t cmUnitDelayFree( cmUnitDelay* p );
|
|
cmRC_t cmUnitDelayInit( cmUnitDelay* p, cmReal_t srate, unsigned smpCnt, braunsigned inCnt, unsigned outCnt, const cmReal_t delayMsV, unsigned delayCnt );
|
|
cmRC_t cmUnitDelayFinal( cmUnitDelay* p );
|
|
cmRC_t cmUnitDelayExec( cmUnitDelay* p, const cmSample_t** x, unsigned inChCnt, cmSample_t** y, unsigned outChCnt, unsigned smpCnt );
|
|
*/
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
|
|
#endif
|