123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942 |
- #include "cmGlobal.h"
- #include "cmRpt.h"
- #include "cmErr.h"
- #include "cmCtx.h"
- #include "cmMem.h"
- #include "cmMallocDebug.h"
- #include "cmAudioPort.h"
- #include "cmAudioAggDev.h"
- #include "cmThread.h" // cmThUIntIncr()
-
- #include "cmApBuf.h" // only needed for cmApBufTest().
-
- //#include <unistd.h> // usleep
-
- enum
- {
- kBufArrayCnt = 2
- };
-
- struct cmApAgg_str;
-
- typedef struct
- {
- unsigned physDevIdx;
- struct cmApAgg_str* ap;
-
- unsigned iChIdx;
- unsigned iChCnt;
-
- unsigned oChIdx;
- unsigned oChCnt;
- } cmApAggDev_t;
-
- typedef struct cmApAgg_str
- {
- cmChar_t* label; // agg. device label
- unsigned aggDevIdx; // agg. device index
- unsigned sysDevIdx; // system device index
- unsigned devCnt; // count of phys devices
- cmApAggDev_t* devArray; // devArray[ devCnt ] - physical device array
- unsigned iChCnt; // sum of phys device input channels
- unsigned oChCnt; // sum of phys device output channels
- double srate; // agg. dev sample rate
- unsigned framesPerCycle; // agg. dev frames per cycle
- unsigned flags; // kAgInFl | kAgOutFl
- cmApCallbackPtr_t cbFunc; // client supplied callback func
- void* cbArg; // client supplied callback func arg.
- bool startedFl; // true if the agg. device is started
- struct cmApAgg_str* link; // _cmAg.list link
- } cmApAgg_t;
-
- typedef struct
- {
- cmErr_t err;
- cmApAgg_t* list;
- } cmApAggMain_t;
-
- cmApAggMain_t _cmAg;
-
-
- void _cmApAggCb( cmApAudioPacket_t* inPktArray, unsigned inPktCnt, cmApAudioPacket_t* outPktArray, unsigned outPktCnt )
- {
- unsigned i;
- cmApAudioPacket_t pkt;
-
- for(i=0; i<inPktCnt; ++i)
- {
- cmApAggDev_t* dp = (cmApAggDev_t*)inPktArray[i].userCbPtr;
- pkt = inPktArray[i];
- pkt.devIdx = dp->ap->sysDevIdx;
- pkt.begChIdx = dp->iChIdx;
- pkt.userCbPtr = dp->ap->cbArg;
- dp->ap->cbFunc( &pkt, 1, NULL, 0 );
- }
-
- for(i=0; i<outPktCnt; ++i)
- {
- cmApAggDev_t* dp = (cmApAggDev_t*)outPktArray[i].userCbPtr;
- pkt = outPktArray[i];
- pkt.devIdx = dp->ap->sysDevIdx;
- pkt.begChIdx = dp->oChIdx;
- pkt.userCbPtr = dp->ap->cbArg;
- dp->ap->cbFunc( NULL, 0, &pkt, 1 );
- }
-
- }
-
-
- void _cmApAgDeleteAggDev( cmApAgg_t* ap )
- {
- cmApAgg_t* cp = _cmAg.list;
- cmApAgg_t* pp = NULL;
- while( cp != NULL )
- {
- if( cp == ap )
- {
- if( pp == NULL )
- _cmAg.list = cp->link;
- else
- pp->link = cp->link;
-
- cmMemFree(ap->label);
- cmMemFree(ap->devArray);
- cmMemFree(ap);
- return;
- }
- pp = cp;
- cp = cp->link;
- }
- }
-
- cmAgRC_t cmApAggAllocate( cmRpt_t* rpt )
- {
- cmAgRC_t rc = kOkAgRC;
-
- cmErrSetup(&_cmAg.err,rpt,"cmAudioAggDev");
-
- _cmAg.list = NULL;
-
- return rc;
- }
-
- cmAgRC_t cmApAggFree()
- {
- cmAgRC_t rc = kOkAgRC;
-
- while( _cmAg.list != NULL )
- _cmApAgDeleteAggDev(_cmAg.list );
-
- return rc;
- }
-
- cmAgRC_t cmApAggInitialize( cmRpt_t* rpt, unsigned baseApDevIdx )
- {
- cmApAgg_t* ap = _cmAg.list;
- unsigned i;
-
- assert( baseApDevIdx == cmApDeviceCount() );
-
- for(i=0; ap!=NULL; ap=ap->link,++i)
- {
- ap->sysDevIdx = cmApDeviceCount() + i;
- ap->iChCnt = 0;
- ap->oChCnt = 0;
-
- unsigned i;
- for(i=0; i<ap->devCnt; ++i)
- {
- ap->devArray[i].iChIdx = ap->iChCnt;
- ap->devArray[i].oChIdx = ap->oChCnt;
- ap->devArray[i].iChCnt = cmApDeviceChannelCount(ap->devArray[i].physDevIdx,true);
- ap->devArray[i].oChCnt = cmApDeviceChannelCount(ap->devArray[i].physDevIdx,false);
- ap->iChCnt += ap->devArray[i].iChCnt;
- ap->oChCnt += ap->devArray[i].oChCnt;
- }
-
-
- }
-
- return kOkAgRC;
- }
-
- cmAgRC_t cmApAggFinalize()
- { return kOkAgRC; }
-
- cmAgRC_t cmApAggCreateDevice(
- const cmChar_t* label,
- unsigned devCnt,
- const unsigned physDevIdxArray[],
- unsigned flags )
- {
- cmAgRC_t rc = kOkAgRC;
- unsigned i;
-
- if( devCnt < 2 )
- return cmErrMsg(&_cmAg.err,kMustAggTwoAgRC,"Cannot aggregate less than two devices.");
- /*
-
- for(i=0; i<devCnt; ++i)
- {
- unsigned physDevIdx = physDevIdxArray[i];
-
- if( cmApAggIsDeviceAggregated(physDevIdx) )
- return cmErrMsg(&_cmAg.err,kDevAlreadyAggAgRC,"The physical device associated with index '%i' ('%s') has already been assigned to another aggregated device.",physDevIdx,cmStringNullGuard(cmApDeviceLabel(physDevIdx)));
-
- if( cmApDeviceIsStarted(physDevIdx) )
- return cmErrMsg(&_cmAg.err,kCantUseStartedDevAgRC,"The physical device associated with index '%i' ('%s') cannot be aggregated while it is running.",physDevIdx,cmStringNullGuard(cmApDeviceLabel(physDevIdx)));
-
- }
- */
-
- cmApAgg_t* ap = cmMemAllocZ(cmApAgg_t,1);
- ap->label = cmMemAllocStr(label==NULL?"Aggregated Device":label);
- ap->devArray = cmMemAllocZ(cmApAggDev_t,devCnt);
- ap->aggDevIdx = cmApAggDeviceCount();
- ap->sysDevIdx = cmInvalidIdx;
- ap->devCnt = devCnt;
- ap->iChCnt = 0;
- ap->oChCnt = 0;
-
- for(i=0; i<devCnt; ++i)
- {
- ap->devArray[i].ap = ap;
- ap->devArray[i].physDevIdx = physDevIdxArray[i];
- }
-
- ap->link = _cmAg.list;
- _cmAg.list = ap;
-
- return rc;
- }
-
- cmApAgg_t* _cmApAggDevIdxToPtr( unsigned aggDevIdx )
- {
- cmApAgg_t* ap = _cmAg.list;
- unsigned i = 0;
- for(; ap!=NULL; ap=ap->link,++i)
- if( ap->aggDevIdx == aggDevIdx )
- return ap;
- return NULL;
- }
-
- cmAgRC_t _cmApAggGetAgg( unsigned aggDevIdx, cmApAgg_t** retPtrPtr )
- {
- if((*retPtrPtr = _cmApAggDevIdxToPtr(aggDevIdx)) == NULL )
- return cmErrMsg(&_cmAg.err,kInvalidDevIdxAgRC,"The aggregate system device index '%i' is invalid.");
- return kOkAgRC;
- }
-
-
- bool cmApAggIsDeviceAggregated( unsigned physDevIdx )
- {
- cmApAgg_t* ap = _cmAg.list;
- for(; ap!=NULL; ap=ap->link)
- {
- unsigned i;
- for(i=0; i<ap->devCnt; ++i)
- if( ap->devArray[i].physDevIdx == physDevIdx )
- return true;
- }
- return false;
- }
-
- cmAgRC_t cmApAggDeviceCount()
- {
- unsigned devCnt=0;
- cmApAgg_t* ap = _cmAg.list;
- for(; ap!=NULL; ap=ap->link)
- ++devCnt;
-
- return devCnt;
- }
-
- const char* cmApAggDeviceLabel( unsigned aggDevIdx )
- {
- cmApAgg_t* ap;
- cmAgRC_t rc;
- if((rc = _cmApAggGetAgg(aggDevIdx, &ap )) == kOkAgRC )
- return ap->label;
- return NULL;
- }
-
- unsigned cmApAggDeviceChannelCount( unsigned aggDevIdx, bool inputFl )
- {
- cmApAgg_t* ap;
- cmAgRC_t rc;
- if((rc = _cmApAggGetAgg(aggDevIdx, &ap )) == kOkAgRC )
- return inputFl ? ap->iChCnt : ap->oChCnt;
- return 0;
- }
-
- double cmApAggDeviceSampleRate( unsigned aggDevIdx )
- {
- cmApAgg_t* ap;
- cmAgRC_t rc;
- if((rc = _cmApAggGetAgg(aggDevIdx, &ap )) == kOkAgRC )
- return ap->srate;
- return 0;
- }
-
- unsigned cmApAggDeviceFramesPerCycle( unsigned aggDevIdx, bool inputFl )
- {
- cmApAgg_t* ap;
- cmAgRC_t rc;
- if((rc = _cmApAggGetAgg(aggDevIdx, &ap )) == kOkAgRC )
- return ap->framesPerCycle;
- return 0;
- }
-
- cmAgRC_t cmApAggDeviceSetup(
- unsigned aggDevIdx,
- double srate,
- unsigned framesPerCycle,
- cmApCallbackPtr_t callbackPtr,
- void* userCbPtr )
- {
- cmApAgg_t* ap;
- cmAgRC_t rc;
- unsigned i;
-
- if((rc = _cmApAggGetAgg(aggDevIdx, &ap )) != kOkAgRC )
- return rc;
-
- if((rc = cmApAggDeviceStop(aggDevIdx)) != kOkAgRC )
- return rc;
-
- for(i=0; i<ap->devCnt; ++i)
- {
- unsigned physDevIdx = ap->devArray[i].physDevIdx;
- cmApAggDev_t* devPtr = ap->devArray + i;
-
- if( cmApDeviceSetup( physDevIdx, srate, framesPerCycle, _cmApAggCb, devPtr ) != kOkApRC )
- rc = cmErrMsg(&_cmAg.err,kPhysDevSetupFailAgRC,"The physical device (index:%i '%s') setup failed for sample rate:%f frames-per-cycle:%i.",physDevIdx,cmStringNullGuard(cmApDeviceLabel(physDevIdx)),srate,framesPerCycle);
- }
-
- if( rc == kOkAgRC )
- {
- ap->cbFunc = callbackPtr;
- ap->cbArg = userCbPtr;
- }
-
- return rc;
- }
-
- cmAgRC_t cmApAggDeviceStart( unsigned aggDevIdx )
- {
- cmAgRC_t rc = kOkAgRC;
- cmApAgg_t* ap;
- unsigned i;
-
- if((rc = _cmApAggGetAgg(aggDevIdx, &ap )) != kOkAgRC )
- return rc;
-
- for(i=0; i<ap->devCnt; ++i)
- {
- unsigned physDevIdx = ap->devArray[i].physDevIdx;
-
- if( cmApDeviceStart( physDevIdx ) != kOkApRC )
- return cmErrMsg(&_cmAg.err,kPhysDevStartFailAgRC,"The physical device (index:%i '%s') start failed.",physDevIdx,cmStringNullGuard(cmApDeviceLabel(physDevIdx)));
-
- //usleep(1000);
- }
-
- ap->startedFl = true;
-
- return rc;
- }
-
- cmAgRC_t cmApAggDeviceStop( unsigned aggDevIdx )
- {
- cmAgRC_t rc = kOkAgRC;
- cmApAgg_t* ap;
- unsigned i;
-
- if((rc = _cmApAggGetAgg(aggDevIdx, &ap )) != kOkAgRC )
- return rc;
-
- for(i=0; i<ap->devCnt; ++i)
- {
- unsigned physDevIdx = ap->devArray[i].physDevIdx;
-
- if( cmApDeviceStop( physDevIdx ) != kOkApRC )
- return cmErrMsg(&_cmAg.err,kPhysDevStartFailAgRC,"The physical device (index:%i '%s') start failed.",physDevIdx,cmStringNullGuard(cmApDeviceLabel(physDevIdx)));
- }
-
- ap->startedFl = false;
-
- return rc;
- }
-
- bool cmApAggDeviceIsStarted( unsigned aggDevIdx )
- {
- cmApAgg_t* ap;
-
- if(_cmApAggGetAgg(aggDevIdx, &ap ) != kOkAgRC )
- return false;
-
- return ap->startedFl;
- }
-
-
-
-
-
-
- typedef struct
- {
- unsigned bufCnt; // 2=double buffering 3=triple buffering
- unsigned chIdx; // first test channel
- unsigned chCnt; // count of channels to test
- unsigned framesPerCycle; // DSP frames per cycle
- unsigned bufFrmCnt; // count of DSP frames used by the audio buffer (bufCnt * framesPerCycle)
- unsigned bufSmpCnt; // count of samples used by the audio buffer (chCnt * bufFrmCnt)
- unsigned inDevIdx; // input device index
- unsigned outDevIdx; // output device index
- double srate; // audio sample rate
- unsigned meterMs; // audio meter buffer length
-
- // param's and state for cmApSynthSine()
- bool synthFl;
- unsigned phase; // sine synth phase
- double frqHz; // sine synth frequency in Hz
-
- // buffer and state for cmApCopyIn/Out()
- cmApSample_t* buf; // buf[bufSmpCnt] - circular interleaved audio buffer
- unsigned bufInIdx; // next input buffer index
- unsigned bufOutIdx; // next output buffer index
- unsigned bufFullCnt; // count of full samples
-
- unsigned cbCnt; // count the callback
- unsigned underunCnt; //
- unsigned overunCnt;
-
- double* iMeter; // iMeter[ chCnt ]
-
- FILE* ifp;
- FILE* ofp;
- } cmApAggPortTestRecd;
-
- // The application can request any block of channels from the device. The packets are provided with the starting
- // device channel and channel count. This function converts device channels and channel counts to buffer
- // channel indexes and counts.
- //
- // Example:
- // input output
- // i,n i n
- // App: 0,4 0 1 2 3 -> 2 2
- // Pkt 2,8 2 3 4 5 6 7 8 -> 0 2
- //
- // The return value is the count of application requested channels located in this packet.
- //
- // input: *appChIdxPtr and appChCnt describe a block of device channels requested by the application.
- // *pktChIdxPtr and pktChCnt describe a block of device channels provided to the application
- //
- // output:*appChIdxPtr and <return value> describe a block of app buffer channels which will send/recv samples.
- // *pktChIdxPtr and <return value> describe a block of pkt buffer channels which will send/recv samples
- //
- unsigned _cmApAggDeviceToBuffer( unsigned* appChIdxPtr, unsigned appChCnt, unsigned* pktChIdxPtr, unsigned pktChCnt )
- {
- unsigned abi = *appChIdxPtr;
- unsigned aei = abi+appChCnt-1;
-
- unsigned pbi = *pktChIdxPtr;
- unsigned pei = pbi+pktChCnt-1;
-
- // if the ch's rqstd by the app do not overlap with this packet - return false.
- if( aei < pbi || abi > pei )
- return 0;
-
- // if the ch's rqstd by the app overlap with the beginning of the pkt channel block
- if( abi < pbi )
- {
- appChCnt -= pbi - abi;
- *appChIdxPtr = pbi - abi;
- *pktChIdxPtr = 0;
- }
- else
- {
- // the rqstd ch's begin inside the pkt channel block
- pktChCnt -= abi - pbi;
- *pktChIdxPtr = abi - pbi;
- *appChIdxPtr = 0;
- }
-
- // if the pkt channels extend beyond the rqstd ch block
- if( aei < pei )
- pktChCnt -= pei - aei;
- else
- appChCnt -= aei - pei; // the rqstd ch's extend beyond or coincide with the pkt block
-
- // the returned channel count must always be the same for both the rqstd and pkt
- return cmMin(appChCnt,pktChCnt);
-
- }
-
-
- // synthesize a sine signal into an interleaved audio buffer
- unsigned _cmApAggSynthSine( cmApAggPortTestRecd* r, float* p, unsigned chIdx, unsigned chCnt, unsigned frmCnt, unsigned phs, double hz )
- {
- long ph = 0;
- unsigned i;
- unsigned bufIdx = r->chIdx;
- unsigned bufChCnt;
-
- if( (bufChCnt = _cmApAggDeviceToBuffer( &bufIdx, r->chCnt, &chIdx, chCnt )) == 0)
- return phs;
-
-
- //if( r->cbCnt < 50 )
- // printf("ch:%i cnt:%i ch:%i cnt:%i bi:%i bcn:%i\n",r->chIdx,r->chCnt,chIdx,chCnt,bufIdx,bufChCnt);
-
-
- for(i=bufIdx; i<bufIdx+bufChCnt; ++i)
- {
- unsigned j;
- float* op = p + i;
-
- ph = phs;
- for(j=0; j<frmCnt; j++, op+=chCnt, ph++)
- {
- *op = (float)(0.9 * sin( 2.0 * M_PI * hz * ph / r->srate ));
- }
- }
-
- return ph;
- }
-
- // Copy the audio samples in the interleaved audio buffer sp[srcChCnt*srcFrameCnt]
- // to the internal record buffer.
- void _cmApAggCopyIn( cmApAggPortTestRecd* r, const cmApSample_t* sp, unsigned srcChIdx, unsigned srcChCnt, unsigned srcFrameCnt )
- {
- unsigned i,j;
-
- unsigned chCnt = cmMin(r->chCnt,srcChCnt);
-
- // write the incoming sample to an output file for debugging
- if( r->ifp != NULL )
- if( fwrite(sp,sizeof(cmApSample_t),srcChCnt*srcFrameCnt,r->ifp) != srcChCnt*srcFrameCnt )
- printf("file write fail.\n");
-
- // zero the input meter array
- for(i=0; i<r->chCnt; ++i)
- r->iMeter[i] = 0;
-
- for(i=0; i<srcFrameCnt; ++i)
- {
- // copy samples from the src to the buffer - both src and buffer are interleaved
- for(j=0; j<chCnt; ++j)
- {
- r->buf[ r->bufInIdx + j ] = sp[ (i*srcChCnt) + srcChIdx + j ];
-
- // record the max value in the input meter array
- if( r->buf[ r->bufInIdx + j ] > r->iMeter[j] )
- r->iMeter[j] = r->buf[ r->bufInIdx + j ];
- }
-
- // zero channels that are not used in the buffer
- for(; j<r->chCnt; ++j)
- r->buf[ r->bufInIdx + j ] = 0;
-
- // advance to the next frame
- r->bufInIdx = (r->bufInIdx+r->chCnt) % r->bufFrmCnt;
- }
-
- //r->bufFullCnt = (r->bufFullCnt + srcFrameCnt) % r->bufFrmCnt;
- cmThUIntIncr(&r->bufFullCnt,srcFrameCnt);
-
- if( r->bufFullCnt > r->bufFrmCnt )
- {
- //printf("Input buffer overrun.\n");
- ++r->overunCnt;
- r->bufFullCnt = 0;
- }
-
- }
-
- // Copy audio samples out of the internal record buffer into dp[dstChCnt*dstFrameCnt].
- void _cmApAggCopyOut( cmApAggPortTestRecd* r, cmApSample_t* dp, unsigned dstChIdx, unsigned dstChCnt, unsigned dstFrameCnt )
- {
-
- // if there are not enough samples available to fill the destination
- // buffer then zero the dst buf.
- if( r->bufFullCnt < dstFrameCnt )
- {
- //printf("Empty Output Buffer %i < %i\n",r->bufFullCnt,dstFrameCnt);
- memset( dp, 0, dstFrameCnt*dstChCnt*sizeof(cmApSample_t) );
- ++r->underunCnt;
- }
- else
- {
- unsigned i,j;
- unsigned chCnt = cmMin(dstChCnt,r->chCnt);
-
- for(i=0; i<dstFrameCnt; ++i)
- {
- // copy the stored buffer samples to the dst buffer
- for(j=0; j<chCnt; ++j)
- dp[ (i*dstChCnt) + dstChIdx + j ] = r->buf[ r->bufOutIdx + j ];
-
- // zero unset channels in the dst buffer
- for(; j<dstChCnt; ++j)
- dp[ (i*dstChCnt) + dstChIdx + j ] = 0;
-
- r->bufOutIdx = (r->bufOutIdx + r->chCnt) % r->bufFrmCnt;
- }
-
- cmThUIntDecr(&r->bufFullCnt,dstFrameCnt);
- }
-
- if( r->ofp != NULL )
- fwrite(dp,sizeof(cmApSample_t),dstChCnt*dstFrameCnt,r->ofp);
- }
-
- // Audio port callback function called from the audio device thread.
- void _cmApAggPortCb( cmApAudioPacket_t* inPktArray, unsigned inPktCnt, cmApAudioPacket_t* outPktArray, unsigned outPktCnt )
- {
- unsigned i;
-
- // for each incoming audio packet
-
- for(i=0; i<inPktCnt; ++i)
- {
- cmApAggPortTestRecd* r = (cmApAggPortTestRecd*)inPktArray[i].userCbPtr;
-
- if( r->synthFl==false && inPktArray[i].devIdx == r->inDevIdx )
- {
- // copy the incoming audio into an internal buffer where it can be picked up by _cpApCopyOut().
- _cmApAggCopyIn( r, (cmApSample_t*)inPktArray[i].audioBytesPtr, inPktArray[i].begChIdx, inPktArray[i].chCnt, inPktArray[i].audioFramesCnt );
- }
- ++r->cbCnt;
-
- //printf("i %4i in:%4i out:%4i\n",r->bufFullCnt,r->bufInIdx,r->bufOutIdx);
- }
-
- unsigned hold_phase = 0;
-
- // for each outgoing audio packet
- for(i=0; i<outPktCnt; ++i)
- {
- cmApAggPortTestRecd* r = (cmApAggPortTestRecd*)outPktArray[i].userCbPtr;
-
- if( outPktArray[i].devIdx == r->outDevIdx )
- {
- // zero the output buffer
- memset(outPktArray[i].audioBytesPtr,0,outPktArray[i].chCnt * outPktArray[i].audioFramesCnt * sizeof(cmApSample_t) );
-
- // if the synth is enabled
- if( r->synthFl )
- {
- unsigned tmp_phase = _cmApAggSynthSine( r, outPktArray[i].audioBytesPtr, outPktArray[i].begChIdx, outPktArray[i].chCnt, outPktArray[i].audioFramesCnt, r->phase, r->frqHz );
-
- // the phase will only change on packets that are actually used
- if( tmp_phase != r->phase )
- hold_phase = tmp_phase;
- }
- else
- {
- // copy the any audio in the internal record buffer to the playback device
- _cmApAggCopyOut( r, (cmApSample_t*)outPktArray[i].audioBytesPtr, outPktArray[i].begChIdx, outPktArray[i].chCnt, outPktArray[i].audioFramesCnt );
- }
- }
-
- r->phase = hold_phase;
-
- //printf("o %4i in:%4i out:%4i\n",r->bufFullCnt,r->bufInIdx,r->bufOutIdx);
- // count callbacks
- ++r->cbCnt;
- }
- }
-
-
- // print the usage message for cmAudioPortTest.c
- void _cmApAggPrintUsage( cmRpt_t* rpt )
- {
- char msg[] =
- "cmApAggPortTest() command switches\n"
- "-r <srate> -c <chcnt> -b <bufcnt> -f <frmcnt> -i <idevidx> -o <odevidx> -t -p -h \n"
- "\n"
- "-r <srate> = sample rate\n"
- "-a <chidx> = first channel\n"
- "-c <chcnt> = audio channels\n"
- "-b <bufcnt> = count of buffers\n"
- "-f <frmcnt> = count of samples per buffer\n"
- "-i <idevidx> = input device index\n"
- "-o <odevidx> = output device index\n"
- "-p = print report but do not start audio devices\n"
- "-h = print this usage message\n";
-
- cmRptPrintf(rpt,msg);
- }
-
- // Get a command line option.
- int _cmApAggGetOpt( int argc, const char* argv[], const char* label, int defaultVal, bool boolFl )
- {
- int i = 0;
- for(; i<argc; ++i)
- if( strcmp(label,argv[i]) == 0 )
- {
- if(boolFl)
- return 1;
-
- if( i == (argc-1) )
- return defaultVal;
-
- return atoi(argv[i+1]);
- }
-
- return defaultVal;
- }
-
-
- void _cmApBufShowMeter( cmRpt_t* rpt, unsigned devIdx )
- {
- unsigned faultCnt = 0;
- unsigned meterCnt = cmApBufChannelCount(devIdx,kInApFl);
- double meterArray[ meterCnt ];
-
- unsigned n = cmApBufGetStatus(devIdx, kInApFl, meterArray, meterCnt, &faultCnt );
- unsigned i;
-
- cmRptPrintf(rpt,"In: actual:%i fault: %i : ",n,faultCnt);
- for(i=0; i<meterCnt; ++i)
- cmRptPrintf(rpt,"%i:%f ",i,meterArray[i]);
- cmRptPrintf(rpt,"\n");
- }
-
-
- unsigned _cmAggGlobalInDevIdx = 0;
- unsigned _cmAggGlobalOutDevIdx = 0;
-
- void _cmApAggPortCb2( cmApAudioPacket_t* inPktArray, unsigned inPktCnt, cmApAudioPacket_t* outPktArray, unsigned outPktCnt )
- {
-
- cmApBufInputToOutput( _cmAggGlobalInDevIdx, _cmAggGlobalOutDevIdx );
-
- cmApBufUpdate( inPktArray, inPktCnt, outPktArray, outPktCnt );
- }
-
-
- void recdPrint();
-
- // Audio Port testing function
- int cmApAggTest( bool runFl, cmCtx_t* ctx, int argc, const char* argv[] )
- {
- cmApAggPortTestRecd r;
- unsigned i;
- cmRpt_t* rpt = &ctx->rpt;
-
- if( _cmApAggGetOpt(argc,argv,"-h",0,true) )
- _cmApAggPrintUsage(rpt);
-
-
- runFl = _cmApAggGetOpt(argc,argv,"-p",!runFl,true)?false:true;
- r.chIdx = _cmApAggGetOpt(argc,argv,"-a",0,false);
- r.chCnt = _cmApAggGetOpt(argc,argv,"-c",2,false);
- r.bufCnt = _cmApAggGetOpt(argc,argv,"-b",3,false);
- r.framesPerCycle = _cmApAggGetOpt(argc,argv,"-f",512,false);
- r.bufFrmCnt = (r.bufCnt*r.framesPerCycle);
- r.bufSmpCnt = (r.chCnt * r.bufFrmCnt);
- r.synthFl = false;
- r.meterMs = 50;
-
- cmApSample_t buf[r.bufSmpCnt];
- double imeter[r.chCnt];
-
- r.iMeter = imeter;
-
- r.inDevIdx = _cmAggGlobalInDevIdx = _cmApAggGetOpt(argc,argv,"-i",0,false);
- r.outDevIdx = _cmAggGlobalOutDevIdx = _cmApAggGetOpt(argc,argv,"-o",2,false);
- r.phase = 0;
- r.frqHz = 2000;
- r.srate = 44100;
- r.bufInIdx = 0;
- r.bufOutIdx = 0;
- r.bufFullCnt = 0;
-
- r.buf = buf;
- r.cbCnt = 0;
- r.underunCnt = 0;
- r.overunCnt = 0;
- r.ifp = NULL;
- r.ofp = NULL;
-
-
- if(0)
- {
- if((r.ifp = fopen("/home/kevin/temp/itemp0.bin","wb")) == NULL )
- cmRptPrintf(rpt,"File open failed.\n");
-
- if((r.ofp = fopen("/home/kevin/temp/otemp0.bin","wb")) == NULL )
- cmRptPrintf(rpt,"File open failed.\n");
- }
-
- cmRptPrintf(rpt,"%s in:%i out:%i chidx:%i chs:%i bufs=%i frm=%i rate=%f\n",runFl?"exec":"rpt",r.inDevIdx,r.outDevIdx,r.chIdx,r.chCnt,r.bufCnt,r.framesPerCycle,r.srate);
-
- // allocate the aggregate device system
- if( cmApAggAllocate(rpt) != kOkAgRC )
- {
- cmRptPrintf(rpt,"The aggregate device system allocation failed.\n");
- return 1;
- }
-
-
- unsigned physDevIdxArray[] = { 0, 1 };
- unsigned physDevCnt = sizeof(physDevIdxArray)/sizeof(physDevIdxArray[0]);
- if( cmApAggCreateDevice("aggdev",physDevCnt,physDevIdxArray,kInAggFl | kOutAggFl) != kOkAgRC )
- {
- cmRptPrintf(rpt,"The aggregate device creation failed.n");
- goto doneLabel;
- }
-
-
- // initialize the audio device interface
- if( cmApInitialize(rpt) != kOkApRC )
- {
- cmRptPrintf(rpt,"Initialize failed.\n");
- goto doneLabel;
- }
-
- // report the current audio device configuration
- for(i=0; i<cmApDeviceCount(); ++i)
- {
- cmRptPrintf(rpt,"%i [in: chs=%i frames=%i] [out: chs=%i frames=%i] srate:%f %s\n",i,cmApDeviceChannelCount(i,true),cmApDeviceFramesPerCycle(i,true),cmApDeviceChannelCount(i,false),cmApDeviceFramesPerCycle(i,false),cmApDeviceSampleRate(i),cmApDeviceLabel(i));
- }
- // report the current audio devices using the audio port interface function
- cmApReport(rpt);
-
-
- if( runFl )
- {
- // initialize the audio bufer
- cmApBufInitialize( cmApDeviceCount(), r.meterMs );
-
- // setup the buffer for the output device
- cmApBufSetup( r.outDevIdx, r.srate, r.framesPerCycle, r.bufCnt, cmApDeviceChannelCount(r.outDevIdx,true), r.framesPerCycle, cmApDeviceChannelCount(r.outDevIdx,false), r.framesPerCycle );
-
- // setup the buffer for the input device
- if( r.inDevIdx != r.outDevIdx )
- cmApBufSetup( r.inDevIdx, r.srate, r.framesPerCycle, r.bufCnt, cmApDeviceChannelCount(r.inDevIdx,true), r.framesPerCycle, cmApDeviceChannelCount(r.inDevIdx,false), r.framesPerCycle );
-
- // setup an input device
- if( cmApDeviceSetup(r.inDevIdx,r.srate,r.framesPerCycle,_cmApAggPortCb2,&r) != kOkApRC )
- {
- cmRptPrintf(rpt,"In device setup failed.\n");
- goto errLabel;
- }
-
- // setup an output device
- if( r.inDevIdx != r.outDevIdx )
- {
- if(cmApDeviceSetup(r.outDevIdx,r.srate,r.framesPerCycle,_cmApAggPortCb2,&r) != kOkApRC )
- {
- cmRptPrintf(rpt,"Out device setup failed.\n");
- goto errLabel;
- }
- }
-
- // start the input device
- if( cmApDeviceStart(r.inDevIdx) != kOkApRC )
- {
- cmRptPrintf(rpt,"In device start failed.\n");
- goto errLabel;
- }
-
- if( r.inDevIdx != r.outDevIdx )
- {
- // start the output device
- if( cmApDeviceStart(r.outDevIdx) != kOkApRC )
- {
- cmRptPrintf(rpt,"Out Device start failed.\n");
- goto errLabel;
- }
- }
-
- cmApBufEnableChannel(r.inDevIdx, -1, kInApFl | kEnableApFl );
- cmApBufEnableChannel(r.outDevIdx, -1, kOutApFl | kEnableApFl );
- cmApBufEnableMeter(r.inDevIdx, -1, kInApFl | kEnableApFl );
-
- cmRptPrintf(rpt,"q=quit O/o output tone, I/i input tone P/p pass\n");
- char c;
- while((c=getchar()) != 'q')
- {
- //cmApDeviceRtReport(rpt,r.outDevIdx);
-
- switch(c)
- {
- case 'i':
- case 'I':
- cmApBufEnableTone(r.inDevIdx,-1,kInApFl | (c=='I'?kEnableApFl:0));
- break;
-
- case 'o':
- case 'O':
- cmApBufEnableTone(r.outDevIdx,-1,kOutApFl | (c=='O'?kEnableApFl:0));
- break;
-
- case 'p':
- case 'P':
- cmApBufEnablePass(r.outDevIdx,-1,kOutApFl | (c=='P'?kEnableApFl:0));
- break;
-
- case 's':
- cmApBufReport(rpt);
- break;
-
- case 'm':
- _cmApBufShowMeter(rpt,_cmAggGlobalInDevIdx);
-
- /*
- cmRptPrintf(rpt,"iMeter: ");
- for(i=0; i<r.chCnt; ++i)
- cmRptPrintf(rpt,"%f ",r.iMeter[i]);
- cmRptPrintf(rpt,"\n");
- */
- break;
-
-
- case 'r':
- recdPrint();
- break;
-
- default:
- cmRptPrintf(rpt,"cb:%i\n",r.cbCnt);
- }
-
- }
-
- errLabel:
- // stop the input device
- if( cmApDeviceIsStarted(r.inDevIdx) )
- if( cmApDeviceStop(r.inDevIdx) != kOkApRC )
- cmRptPrintf(rpt,"In device stop failed.\n");
-
- // stop the output device
- if( cmApDeviceIsStarted(r.outDevIdx) )
- if( cmApDeviceStop(r.outDevIdx) != kOkApRC )
- cmRptPrintf(rpt,"Out device stop failed.\n");
- }
-
- doneLabel:
-
- // report the count of audio buffer callbacks
- cmRptPrintf(rpt,"cb:%i under:%i over:%i\n", r.cbCnt, r.underunCnt, r.overunCnt );
-
-
- // release any resources held by the audio port interface
- if( cmApFinalize() != kOkApRC )
- cmRptPrintf(rpt,"Finalize failed.\n");
-
- if( cmApAggFree() != kOkAgRC )
- cmRptPrintf(rpt,"Agg device system free failed.");
-
- if(r.ifp != NULL)
- fclose(r.ifp);
-
- if(r.ofp != NULL)
- fclose(r.ofp);
-
- cmApBufFinalize();
-
- return 0;
- }
|