322 rivejä
7.4 KiB
C
322 rivejä
7.4 KiB
C
#include "cmGlobal.h"
|
|
#include "cmRpt.h"
|
|
#include "cmErr.h"
|
|
#include "cmCtx.h"
|
|
#include "cmMem.h"
|
|
#include "cmMallocDebug.h"
|
|
#include "cmAudioPort.h"
|
|
#include "cmAudioPortFile.h"
|
|
#include "cmAudioFileDev.h"
|
|
|
|
typedef struct
|
|
{
|
|
cmAfdH_t devH;
|
|
unsigned devIdx; // afp dev idx
|
|
unsigned baseApDevIdx; // global audio device index for first afp device
|
|
} cmApDev_t;
|
|
|
|
typedef struct
|
|
{
|
|
cmErr_t err;
|
|
cmApDev_t* devArray;
|
|
unsigned devCnt;
|
|
unsigned baseApDevIdx;
|
|
} cmApf_t;
|
|
|
|
cmApf_t* _cmApf = NULL;
|
|
|
|
cmApRC_t cmApFileAllocate( cmRpt_t* rpt )
|
|
{
|
|
cmApRC_t rc = kOkApRC;
|
|
|
|
if( _cmApf != NULL )
|
|
cmApFileFree();
|
|
|
|
_cmApf = cmMemAllocZ(cmApf_t,1);
|
|
|
|
cmErrSetup(&_cmApf->err,rpt,"Audio Port File");
|
|
_cmApf->devArray = NULL;
|
|
_cmApf->devCnt = 0;
|
|
_cmApf->baseApDevIdx = 0;
|
|
|
|
return rc;
|
|
}
|
|
|
|
cmApRC_t cmApFileFree()
|
|
{
|
|
cmApRC_t rc = kOkApRC;
|
|
|
|
if( _cmApf == NULL )
|
|
return rc;
|
|
|
|
if((rc = cmApFileFinalize()) != kOkApRC )
|
|
return rc;
|
|
|
|
cmMemFree(_cmApf);
|
|
_cmApf = NULL;
|
|
return rc;
|
|
}
|
|
|
|
|
|
cmApRC_t cmApFileInitialize( cmRpt_t* rpt, unsigned baseApDevIdx )
|
|
{
|
|
cmApRC_t rc = kOkApRC;
|
|
|
|
unsigned i = 0;
|
|
for(; i<_cmApf->devCnt; ++i)
|
|
_cmApf->devArray[i].baseApDevIdx = baseApDevIdx;
|
|
|
|
_cmApf->baseApDevIdx = baseApDevIdx;
|
|
|
|
return rc;
|
|
}
|
|
|
|
cmApRC_t cmApFileFinalize()
|
|
{
|
|
cmApRC_t rc = kOkApRC;
|
|
|
|
if( _cmApf == NULL )
|
|
return kOkApRC;
|
|
|
|
unsigned i;
|
|
for(i=0; i<_cmApf->devCnt; ++i)
|
|
{
|
|
cmApRC_t rc0;
|
|
if((rc0 = cmApFileDeviceDestroy(i)) != kOkApRC )
|
|
rc = rc0;
|
|
}
|
|
|
|
cmMemPtrFree(&_cmApf->devArray);
|
|
_cmApf->devCnt = 0;
|
|
|
|
cmMemPtrFree(&_cmApf);
|
|
|
|
return rc;
|
|
}
|
|
|
|
unsigned cmApFileDeviceCreate(
|
|
const cmChar_t* devLabel,
|
|
const cmChar_t* iFn,
|
|
const cmChar_t* oFn,
|
|
unsigned oBits,
|
|
unsigned oChCnt )
|
|
{
|
|
unsigned i;
|
|
|
|
// find an available device slot
|
|
for(i=0; i<_cmApf->devCnt; ++i)
|
|
if( cmAudioFileDevIsValid( _cmApf->devArray[i].devH ) == false )
|
|
break;
|
|
|
|
// if no device slot is availd ...
|
|
if( i == _cmApf->devCnt )
|
|
{
|
|
// ... create a new one
|
|
_cmApf->devArray = cmMemResizePZ(cmApDev_t, _cmApf->devArray, _cmApf->devCnt+1);
|
|
++_cmApf->devCnt;
|
|
}
|
|
|
|
// open the file device
|
|
if( cmAudioFileDevInitialize( &_cmApf->devArray[i].devH, devLabel, i, iFn, oFn, oBits, oChCnt, _cmApf->err.rpt ) != kOkAfdRC )
|
|
{
|
|
cmErrMsg(&_cmApf->err,kAudioPortFileFailApRC,"The audio file device initialization failed.");
|
|
i = cmInvalidIdx;
|
|
goto errLabel;
|
|
}
|
|
|
|
_cmApf->devArray[i].devIdx = i;
|
|
|
|
errLabel:
|
|
|
|
return i;
|
|
}
|
|
|
|
cmApRC_t cmApFileDeviceDestroy( unsigned devIdx )
|
|
{
|
|
if( cmAudioFileDevFinalize( &_cmApf->devArray[devIdx].devH ) != kOkAfdRC )
|
|
return cmErrMsg(&_cmApf->err,kAudioPortFileFailApRC,"The audio file device finalize failed.");
|
|
|
|
return kOkApRC;
|
|
}
|
|
|
|
unsigned cmApFileDeviceCount()
|
|
{ return _cmApf->devCnt; }
|
|
|
|
const char* cmApFileDeviceLabel( unsigned devIdx )
|
|
{
|
|
assert( devIdx < cmApFileDeviceCount());
|
|
return cmAudioFileDevLabel( _cmApf->devArray[devIdx].devH );
|
|
}
|
|
|
|
unsigned cmApFileDeviceChannelCount( unsigned devIdx, bool inputFl )
|
|
{
|
|
assert( devIdx < cmApFileDeviceCount());
|
|
return cmAudioFileDevChannelCount( _cmApf->devArray[devIdx].devH, inputFl );
|
|
}
|
|
|
|
double cmApFileDeviceSampleRate( unsigned devIdx )
|
|
{
|
|
assert( devIdx < cmApFileDeviceCount());
|
|
return cmAudioFileDevSampleRate( _cmApf->devArray[devIdx].devH );
|
|
}
|
|
|
|
unsigned cmApFileDeviceFramesPerCycle( unsigned devIdx, bool inputFl )
|
|
{
|
|
assert( devIdx < cmApFileDeviceCount());
|
|
return cmAudioFileDevFramesPerCycle( _cmApf->devArray[devIdx].devH, inputFl );
|
|
}
|
|
|
|
cmApRC_t cmApFileDeviceSetup(
|
|
unsigned devIdx,
|
|
double srate,
|
|
unsigned framesPerCycle,
|
|
cmApCallbackPtr_t callbackPtr,
|
|
void* userCbPtr )
|
|
{
|
|
assert( devIdx < cmApFileDeviceCount());
|
|
|
|
if( cmAudioFileDevSetup( _cmApf->devArray[devIdx].devH,_cmApf->baseApDevIdx,srate,framesPerCycle,callbackPtr,userCbPtr) != kOkAfdRC )
|
|
return cmErrMsg(&_cmApf->err,kAudioPortFileFailApRC,"The audio file device setup failed.");
|
|
|
|
return kOkApRC;
|
|
}
|
|
|
|
cmApRC_t cmApFileDeviceStart( unsigned devIdx )
|
|
{
|
|
assert( devIdx < cmApFileDeviceCount());
|
|
|
|
if( cmAudioFileDevStart( _cmApf->devArray[devIdx].devH ) != kOkAfdRC )
|
|
return cmErrMsg(&_cmApf->err,kAudioPortFileFailApRC,"The audio file device setup failed.");
|
|
|
|
return kOkApRC;
|
|
}
|
|
|
|
cmApRC_t cmApFileDeviceStop( unsigned devIdx )
|
|
{
|
|
assert( devIdx < cmApFileDeviceCount());
|
|
|
|
if( cmAudioFileDevStop( _cmApf->devArray[devIdx].devH ) != kOkAfdRC )
|
|
return cmErrMsg(&_cmApf->err,kAudioPortFileFailApRC,"The audio file device setup failed.");
|
|
|
|
return kOkApRC;
|
|
}
|
|
|
|
bool cmApFileDeviceIsStarted( unsigned devIdx )
|
|
{
|
|
assert( devIdx < cmApFileDeviceCount());
|
|
return cmAudioFileDevIsStarted( _cmApf->devArray[devIdx].devH );
|
|
}
|
|
|
|
void cmApFileReport( cmRpt_t* rpt )
|
|
{
|
|
unsigned i;
|
|
for(i=0; _cmApf->devCnt; ++i)
|
|
{
|
|
cmRptPrintf(rpt,"%i: ",i);
|
|
cmAudioFileDevReport( _cmApf->devArray[i].devH, rpt );
|
|
cmRptPrintf(rpt,"\n");
|
|
}
|
|
}
|
|
|
|
|
|
// device callback function used with cmAudioPortFileTest() note that this assumes
|
|
// that the packet buffer contain non-interleaved data.
|
|
void _cmApFileTestCb(
|
|
cmApAudioPacket_t* inPktArray,
|
|
unsigned inPktCnt,
|
|
cmApAudioPacket_t* outPktArray,
|
|
unsigned outPktCnt )
|
|
{
|
|
cmApAudioPacket_t* ip = inPktArray;
|
|
cmApAudioPacket_t* op = outPktArray;
|
|
unsigned opi = 0;
|
|
unsigned ipi = 0;
|
|
unsigned oci = 0;
|
|
unsigned ici = 0;
|
|
|
|
while(1)
|
|
{
|
|
if( ici == ip->chCnt)
|
|
{
|
|
ici = 0;
|
|
if( ++ipi >= inPktCnt )
|
|
break;
|
|
|
|
ip = inPktArray + ipi;
|
|
}
|
|
|
|
|
|
if( oci == op->chCnt )
|
|
{
|
|
oci = 0;
|
|
if( ++opi >= outPktCnt )
|
|
break;
|
|
|
|
ip = outPktArray + opi;
|
|
}
|
|
|
|
assert( ip->audioFramesCnt == op->audioFramesCnt );
|
|
assert( cmIsFlag(ip->flags,kInterleavedApFl)==false && cmIsFlag(ip->flags,kInterleavedApFl)==false );
|
|
|
|
cmApSample_t* ibp = ((cmApSample_t*)ip->audioBytesPtr) + (ip->audioFramesCnt*ici);
|
|
cmApSample_t* obp = ((cmApSample_t*)op->audioBytesPtr) + (op->audioFramesCnt*oci);
|
|
|
|
memcpy(obp,ibp,ip->audioFramesCnt*sizeof(cmApSample_t));
|
|
|
|
++ici;
|
|
++oci;
|
|
}
|
|
}
|
|
|
|
|
|
void cmApFileTest( cmRpt_t* rpt )
|
|
{
|
|
unsigned dev0Idx;
|
|
|
|
const cmChar_t* promptStr = "apf> q=quit 1=start 0=stop\n";
|
|
const cmChar_t* label0 = "file0";
|
|
const cmChar_t* i0Fn = "/home/kevin/media/audio/McGill-1/1 Audio Track.aiff";
|
|
const cmChar_t* o0Fn = "/home/kevin/temp/afd1.aif";
|
|
unsigned o0Bits = 16;
|
|
unsigned o0ChCnt = 2;
|
|
double srate = 44100;
|
|
unsigned framesPerCycle = 512;
|
|
|
|
// initialize audio port file API
|
|
if( cmApFileInitialize(rpt,0) != kOkApRC )
|
|
return;
|
|
|
|
// create an audio port file
|
|
if((dev0Idx = cmApFileDeviceCreate(label0,i0Fn,o0Fn,o0Bits,o0ChCnt)) == cmInvalidIdx )
|
|
goto errLabel;
|
|
|
|
// configure an audio port file
|
|
if( cmApFileDeviceSetup( dev0Idx, srate, framesPerCycle, _cmApFileTestCb, NULL ) != kOkAfdRC )
|
|
goto errLabel;
|
|
|
|
char c;
|
|
fputs(promptStr,stderr);
|
|
fflush(stdin);
|
|
|
|
while((c=getchar()) != 'q')
|
|
{
|
|
switch(c)
|
|
{
|
|
case '0': cmApFileDeviceStart(dev0Idx); break;
|
|
case '1': cmApFileDeviceStop(dev0Idx); break;
|
|
}
|
|
|
|
fputs(promptStr,stderr);
|
|
fflush(stdin);
|
|
c = 0;
|
|
}
|
|
|
|
|
|
|
|
errLabel:
|
|
//cmApFileDeviceDestroy(dev0Idx);
|
|
|
|
cmApFileFinalize();
|
|
|
|
}
|