diff --git a/cwFlowProc.cpp b/cwFlowProc.cpp index aa5cb5f..d39b596 100644 --- a/cwFlowProc.cpp +++ b/cwFlowProc.cpp @@ -72,6 +72,15 @@ namespace cw return rc; } + + class_members_t members = { + .create = create, + .destroy = destroy, + .value = value, + .exec = exec, + .report = nullptr + }; + } @@ -489,6 +498,340 @@ namespace cw } + //------------------------------------------------------------------------------------------------------------------ + // + // gain + // + namespace gain + { + enum + { + kInPId, + kGainPId, + kOutPId + }; + + rc_t create( instance_t* ctx ) + { + rc_t rc = kOkRC; + const abuf_t* abuf = nullptr; // + + // get the source audio buffer + if((rc = var_register_and_get(ctx, kAnyChIdx,kInPId,"in",abuf )) != kOkRC ) + goto errLabel; + + // register the gain + for(unsigned i=0; ichN; ++i) + if((rc = var_register( ctx, i, kGainPId, "gain" )) != kOkRC ) + goto errLabel; + + // create the output audio buffer + rc = var_register_and_set( ctx, "out", kOutPId, kAnyChIdx, abuf->srate, abuf->chN, abuf->frameN ); + + + errLabel: + return rc; + } + + rc_t destroy( instance_t* ctx ) + { return kOkRC; } + + rc_t value( instance_t* ctx, variable_t* var ) + { return kOkRC; } + + rc_t exec( instance_t* ctx ) + { + rc_t rc = kOkRC; + const abuf_t* ibuf = nullptr; + abuf_t* obuf = nullptr; + + // get the src buffer + if((rc = var_get(ctx,kInPId, kAnyChIdx, ibuf )) != kOkRC ) + goto errLabel; + + // get the dst buffer + if((rc = var_get(ctx,kOutPId, kAnyChIdx, obuf)) != kOkRC ) + goto errLabel; + + // for each channel + for(unsigned i=0; ichN; ++i) + { + sample_t* isig = ibuf->buf + i*ibuf->frameN; + sample_t* osig = obuf->buf + i*obuf->frameN; + sample_t gain = 1; + + var_get(ctx,kGainPId,i,gain); + + // apply the gain + for(unsigned j=0; jframeN; ++j) + osig[j] = gain * isig[j]; + } + + errLabel: + return rc; + } + + + class_members_t members = { + .create = create, + .destroy = destroy, + .value = value, + .exec = exec, + .report = nullptr + }; + + } + + + //------------------------------------------------------------------------------------------------------------------ + // + // audio_split + // + namespace audio_split + { + enum { + kInPId, + kSelectPId, + kGainPId, + kOutPId, + + }; + + typedef struct + { + bool* chSelMap; // [ inChCnt ] selected channel map + unsigned outChN; + } inst_t; + + + rc_t create( instance_t* ctx ) + { + rc_t rc = kOkRC; + const abuf_t* abuf = nullptr; // + inst_t* inst = mem::allocZ(); + + ctx->userPtr = inst; + + // get the source audio buffer + if((rc = var_register_and_get(ctx, kAnyChIdx,kInPId,"in",abuf )) != kOkRC ) + goto errLabel; + + if( abuf->chN ) + { + inst->chSelMap = mem::allocZ(abuf->chN); + + // register the gain + for(unsigned i=0; ichN; ++i) + { + if((rc = var_register_and_get( ctx, i, kSelectPId, "select", inst->chSelMap[i] )) != kOkRC ) + goto errLabel; + + if( inst->chSelMap[i] ) + { + // register an output gain control + if((rc = var_register( ctx, inst->outChN, kGainPId, "gain")) != kOkRC ) + goto errLabel; + + // count the number of selected channels to determine the count of output channels + inst->outChN += 1; + } + } + + // create the output audio buffer + if( inst->outChN == 0 ) + cwLogWarning("The audio split instance '%s' has no selected channels.",ctx->label); + else + rc = var_register_and_set( ctx, "out", kOutPId, kAnyChIdx, abuf->srate, inst->outChN, abuf->frameN ); + } + + errLabel: + return rc; + } + + rc_t destroy( instance_t* ctx ) + { + rc_t rc = kOkRC; + + inst_t* inst = (inst_t*)ctx->userPtr; + + mem::release(inst->chSelMap); + + mem::release(inst); + + return rc; + } + + rc_t value( instance_t* ctx, variable_t* var ) + { + rc_t rc = kOkRC; + return rc; + } + + rc_t exec( instance_t* ctx ) + { + rc_t rc = kOkRC; + const abuf_t* ibuf = nullptr; + abuf_t* obuf = nullptr; + inst_t* inst = (inst_t*)ctx->userPtr; + unsigned outChIdx = 0; + + if( inst->outChN ) + { + // get the src buffer + if((rc = var_get(ctx,kInPId, kAnyChIdx, ibuf )) != kOkRC ) + goto errLabel; + + // get the dst buffer + if((rc = var_get(ctx,kOutPId, kAnyChIdx, obuf)) != kOkRC ) + goto errLabel; + + // for each channel + for(unsigned i=0; ichN && outChIdxchN; ++i) + if( inst->chSelMap[i] ) + { + + sample_t* isig = ibuf->buf + i * ibuf->frameN; + sample_t* osig = obuf->buf + outChIdx * obuf->frameN; + sample_t gain = 1; + + var_get(ctx,kGainPId,outChIdx,gain); + + // apply the gain + for(unsigned j=0; jframeN; ++j) + osig[j] = gain * isig[j]; + + outChIdx += 1; + } + } + + errLabel: + return rc; + } + + class_members_t members = { + .create = create, + .destroy = destroy, + .value = value, + .exec = exec, + .report = nullptr + }; + + } + + //------------------------------------------------------------------------------------------------------------------ + // + // audio_merge + // + namespace audio_merge + { + enum { + kIn0PId, + kIn1PId, + kGainPId, + kOutPId, + }; + + typedef struct + { + } inst_t; + + + rc_t create( instance_t* ctx ) + { + rc_t rc = kOkRC; + const abuf_t* abuf0 = nullptr; // + const abuf_t* abuf1 = nullptr; + unsigned outChN = 0; + + // get the source audio buffer + if((rc = var_register_and_get(ctx, kAnyChIdx, + kIn0PId,"in0",abuf0, + kIn1PId,"in1",abuf1 )) != kOkRC ) + { + goto errLabel; + } + + assert( abuf0->frameN == abuf1->frameN ); + + outChN = abuf0->chN + abuf1->chN; + + // register the gain + for(unsigned i=0; israte, outChN, abuf0->frameN ); + + errLabel: + return rc; + } + + rc_t destroy( instance_t* ctx ) + { return kOkRC; } + + rc_t value( instance_t* ctx, variable_t* var ) + { return kOkRC; } + + unsigned _exec( instance_t* ctx, const abuf_t* ibuf, abuf_t* obuf, unsigned outChIdx ) + { + // for each channel + for(unsigned i=0; ichN && outChIdxchN; ++i) + { + + sample_t* isig = ibuf->buf + i * ibuf->frameN; + sample_t* osig = obuf->buf + outChIdx * obuf->frameN; + sample_t gain = 1; + + var_get(ctx,kGainPId,outChIdx,gain); + + // apply the gain + for(unsigned j=0; jframeN; ++j) + osig[j] = gain * isig[j]; + + outChIdx += 1; + } + + return outChIdx; + } + + rc_t exec( instance_t* ctx ) + { + rc_t rc = kOkRC; + const abuf_t* ibuf0 = nullptr; + const abuf_t* ibuf1 = nullptr; + abuf_t* obuf = nullptr; + unsigned oChIdx = 0; + + if((rc = var_get(ctx,kIn0PId, kAnyChIdx, ibuf0 )) != kOkRC ) + goto errLabel; + + if((rc = var_get(ctx,kIn1PId, kAnyChIdx, ibuf1 )) != kOkRC ) + goto errLabel; + + if((rc = var_get(ctx,kOutPId, kAnyChIdx, obuf)) != kOkRC ) + goto errLabel; + + oChIdx = _exec( ctx, ibuf0, obuf, oChIdx ); + oChIdx = _exec( ctx, ibuf1, obuf, oChIdx ); + + assert( oChIdx == obuf->chN ); + + errLabel: + return rc; + } + + class_members_t members = { + .create = create, + .destroy = destroy, + .value = value, + .exec = exec, + .report = nullptr + }; + + } + + //------------------------------------------------------------------------------------------------------------------ // // sine_tone @@ -579,15 +922,10 @@ namespace cw { for(unsigned i=0; ichN; ++i) { - real_t gain; - real_t hz; - srate_t srate; - - var_get( ctx, kFreqHzPId, i, hz ); - var_get( ctx, kGainPId, i, gain ); - var_get( ctx, kSratePId, i, srate ); - - sample_t* v = abuf->buf + (i*abuf->frameN); + real_t gain = val_get( ctx, kGainPId, i ); + real_t hz = val_get( ctx, kFreqHzPId, i ); + srate_t srate = val_get( ctx, kSratePId, i ); + sample_t* v = abuf->buf + (i*abuf->frameN); for(unsigned j=0; jframeN; ++j) v[j] = (sample_t)(gain * sin( inst->phaseA[i] + (2.0 * M_PI * j * hz/srate))); @@ -1246,6 +1584,128 @@ namespace cw }; } + //------------------------------------------------------------------------------------------------------------------ + // + // audio_delay + // + namespace audio_delay + { + enum + { + kInPId, + kMaxDelayMsPId, + kDelayMsPId, + kOutPId + }; + + typedef struct inst_str + { + abuf_t* delayBuf; // delayBuf->buf[ maxDelayFrameN ] + unsigned maxDelayFrameN; // length of the delay + unsigned* cntV; // cntV[ chN ] per channel delay + unsigned* idxV; // idxV[ chN ] per channel i/o idx + } inst_t; + + rc_t create( instance_t* ctx ) + { + rc_t rc = kOkRC; + const abuf_t* abuf = nullptr; // + inst_t* inst = mem::allocZ(); + real_t delayMs = 0; + real_t maxDelayMs = 0; + + // get the source audio buffer + if((rc = var_register_and_get(ctx, kAnyChIdx,kInPId,"in",abuf )) != kOkRC ) + goto errLabel; + + + inst->cntV = mem::allocZ(abuf->chN); + inst->idxV = mem::allocZ(abuf->chN); + + // register the gain + for(unsigned i=0; ichN; ++i) + { + if((rc = var_register_and_get( ctx, i, + kMaxDelayMsPId, "maxDelayMs", maxDelayMs, + kDelayMsPId, "delayMs", delayMs)) != kOkRC ) + { + goto errLabel; + } + + inst->maxDelayFrameN = std::max(inst->maxDelayFrameN, (unsigned)(maxDelayMs * abuf->srate / 1000.0) ); + + } + + inst->delayBuf = abuf_create( abuf->srate, abuf->chN, inst->maxDelayFrameN ); + + // create the output audio buffer + rc = var_register_and_set( ctx, "out", kOutPId, kAnyChIdx, abuf->srate, abuf->chN, abuf->frameN ); + + + errLabel: + return rc; + } + + rc_t destroy( instance_t* ctx ) + { + inst_t* inst = (inst_t*)ctx->userPtr; + + mem::release(inst->cntV); + mem::release(inst->idxV); + abuf_destroy(inst->delayBuf); + mem::release(inst); + + return kOkRC; + } + + rc_t value( instance_t* ctx, variable_t* var ) + { return kOkRC; } + + rc_t exec( instance_t* ctx ) + { + rc_t rc = kOkRC; + const abuf_t* ibuf = nullptr; + abuf_t* obuf = nullptr; + inst_t* inst = (inst_t*)ctx->userPtr; + + // get the src buffer + if((rc = var_get(ctx,kInPId, kAnyChIdx, ibuf )) != kOkRC ) + goto errLabel; + + // get the dst buffer + if((rc = var_get(ctx,kOutPId, kAnyChIdx, obuf)) != kOkRC ) + goto errLabel; + + // for each channel + for(unsigned i=0; ichN; ++i) + { + sample_t* isig = ibuf->buf + i*ibuf->frameN; + sample_t* osig = obuf->buf + i*obuf->frameN; + unsigned di = inst->idxV[i]; + + for(unsigned j=0; jframeN; ++j) + { + osig[j] = inst->delayBuf->buf[di]; + inst->delayBuf->buf[di] = isig[j]; + di = (di+1) % inst->cntV[i]; + } + } + + errLabel: + return rc; + } + + + class_members_t members = { + .create = create, + .destroy = destroy, + .value = value, + .exec = exec, + .report = nullptr + }; + + } + } diff --git a/cwFlowProc.h b/cwFlowProc.h index 58b8120..16ef859 100644 --- a/cwFlowProc.h +++ b/cwFlowProc.h @@ -6,10 +6,14 @@ namespace cw namespace audio_out { extern class_members_t members; } namespace audioFileIn { extern class_members_t members; } namespace audioFileOut { extern class_members_t members; } + namespace gain { extern class_members_t members; } + namespace audio_split { extern class_members_t members; } + namespace audio_merge { extern class_members_t members; } namespace sine_tone { extern class_members_t members; } namespace pv_analysis { extern class_members_t members; } namespace pv_synthesis { extern class_members_t members; } namespace spec_dist { extern class_members_t members; } namespace compressor { extern class_members_t members; } + namespace audio_delay { extern class_members_t members; } } }