Merge branch 'master' of klarke.webfactional.com:webapps/git/repos/libcm
This commit is contained in:
commit
6d317d54ca
10
Makefile.am
10
Makefile.am
@ -6,8 +6,11 @@ cmSRC =
|
|||||||
cmHDR += src/libcm/cmErr.h src/libcm/cmCtx.h src/libcm/cmRpt.h src/libcm/cmGlobal.h src/libcm/cmComplexTypes.h src/libcm/cmFloatTypes.h src/libcm/cmPrefix.h
|
cmHDR += src/libcm/cmErr.h src/libcm/cmCtx.h src/libcm/cmRpt.h src/libcm/cmGlobal.h src/libcm/cmComplexTypes.h src/libcm/cmFloatTypes.h src/libcm/cmPrefix.h
|
||||||
cmSRC += src/libcm/cmErr.c src/libcm/cmCtx.c src/libcm/cmRpt.c src/libcm/cmGlobal.c
|
cmSRC += src/libcm/cmErr.c src/libcm/cmCtx.c src/libcm/cmRpt.c src/libcm/cmGlobal.c
|
||||||
|
|
||||||
cmHDR += src/libcm/cmSerialize.h src/libcm/cmSymTbl.h src/libcm/cmFileSys.h src/libcm/cmFile.h src/libcm/cmMem.h src/libcm/cmTime.h src/libcm/cmPgmOpts.h
|
cmHDR += src/libcm/cmSerialize.h src/libcm/cmSymTbl.h src/libcm/cmHashTbl.h src/libcm/cmFileSys.h src/libcm/cmFile.h
|
||||||
cmSRC += src/libcm/cmSerialize.c src/libcm/cmSymTbl.c src/libcm/cmFileSys.c src/libcm/cmFile.c src/libcm/cmMem.c src/libcm/cmTime.c src/libcm/cmPgmOpts.c
|
cmSRC += src/libcm/cmSerialize.c src/libcm/cmSymTbl.c src/libcm/cmHashTbl.c src/libcm/cmFileSys.c src/libcm/cmFile.c
|
||||||
|
|
||||||
|
cmHDR += src/libcm/cmMem.h src/libcm/cmTime.h src/libcm/cmPgmOpts.h
|
||||||
|
cmSRC += src/libcm/cmMem.c src/libcm/cmTime.c src/libcm/cmPgmOpts.c
|
||||||
|
|
||||||
cmHDR += src/libcm/cmData.h src/libcm/cmLib.h src/libcm/cmText.h src/libcm/cmTextTemplate.h
|
cmHDR += src/libcm/cmData.h src/libcm/cmLib.h src/libcm/cmText.h src/libcm/cmTextTemplate.h
|
||||||
cmSRC += src/libcm/cmData.c src/libcm/cmLib.c src/libcm/cmText.c src/libcm/cmTextTemplate.c
|
cmSRC += src/libcm/cmData.c src/libcm/cmLib.c src/libcm/cmText.c src/libcm/cmTextTemplate.c
|
||||||
@ -71,6 +74,9 @@ cmSRC += src/libcm/cmProcObj.c src/libcm/cmProc.c src/libcm/cmProc2.c src/libcm/
|
|||||||
cmHDR += src/libcm/app/cmOnset.h src/libcm/app/cmTimeLine.h src/libcm/app/cmScore.h src/libcm/app/cmScoreProc.h
|
cmHDR += src/libcm/app/cmOnset.h src/libcm/app/cmTimeLine.h src/libcm/app/cmScore.h src/libcm/app/cmScoreProc.h
|
||||||
cmSRC += src/libcm/app/cmOnset.c src/libcm/app/cmTimeLine.c src/libcm/app/cmScore.c src/libcm/app/cmScoreProc.c
|
cmSRC += src/libcm/app/cmOnset.c src/libcm/app/cmTimeLine.c src/libcm/app/cmScore.c src/libcm/app/cmScoreProc.c
|
||||||
|
|
||||||
|
cmHDR += src/libcm/app/cmSdb.h
|
||||||
|
cmSRC += src/libcm/app/cmSdb.c
|
||||||
|
|
||||||
cmHDR += src/libcm/app/cmPickup.h src/libcm/cmRbm.h src/libcm/cmTaskMgr.h src/libcm/cmSyncRecd.h
|
cmHDR += src/libcm/app/cmPickup.h src/libcm/cmRbm.h src/libcm/cmTaskMgr.h src/libcm/cmSyncRecd.h
|
||||||
cmSRC += src/libcm/app/cmPickup.c src/libcm/cmRbm.c src/libcm/cmTaskMgr.c src/libcm/cmSyncRecd.c
|
cmSRC += src/libcm/app/cmPickup.c src/libcm/cmRbm.c src/libcm/cmTaskMgr.c src/libcm/cmSyncRecd.c
|
||||||
|
|
||||||
|
724
app/cmSdb.c
Normal file
724
app/cmSdb.c
Normal file
@ -0,0 +1,724 @@
|
|||||||
|
#include "cmGlobal.h"
|
||||||
|
#include "cmRpt.h"
|
||||||
|
#include "cmErr.h"
|
||||||
|
#include "cmCtx.h"
|
||||||
|
#include "cmMem.h"
|
||||||
|
#include "cmMallocDebug.h"
|
||||||
|
#include "cmLinkedHeap.h"
|
||||||
|
#include "cmLex.h"
|
||||||
|
#include "cmCsv.h"
|
||||||
|
#include "cmSdb.h"
|
||||||
|
#include "cmText.h"
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
kUuidColIdx,
|
||||||
|
kBaseUuidColIdx,
|
||||||
|
kChIdxColIdx,
|
||||||
|
kObiColIdx,
|
||||||
|
kIbiColIdx,
|
||||||
|
kIeiColIdx,
|
||||||
|
kOeiColIdx,
|
||||||
|
kSrcColIdx,
|
||||||
|
kMidiColIdx,
|
||||||
|
kInstrColIdx,
|
||||||
|
kSrateColIdx,
|
||||||
|
kChCntColIdx,
|
||||||
|
kNotesColIdx,
|
||||||
|
kAfnColIdx,
|
||||||
|
kInvalidColIdx
|
||||||
|
} cmSdbColIdx_t;
|
||||||
|
|
||||||
|
struct cmSdb_str;
|
||||||
|
|
||||||
|
typedef struct cmSdbRspBlk_str
|
||||||
|
{
|
||||||
|
unsigned* indexV; // indexV[ cmSdb_t.blkIdxAllocCnt ]
|
||||||
|
unsigned cnt; // count of indexes used
|
||||||
|
struct cmSdbRspBlk_str* link; // cmSdbRsp_t.blocks link
|
||||||
|
} cmSdbRspBlk_t;
|
||||||
|
|
||||||
|
typedef struct cmSdbRsp_str
|
||||||
|
{
|
||||||
|
struct cmSdb_str* p; //
|
||||||
|
cmSdbRspBlk_t* blocks; // first block ptr
|
||||||
|
cmSdbRspBlk_t* ebp; // end block ptr
|
||||||
|
unsigned cnt; // total count of indexes
|
||||||
|
struct cmSdbRsp_str* link; // cmSdb_t.responses link
|
||||||
|
} cmSdbRsp_t;
|
||||||
|
|
||||||
|
typedef struct cmSdb_str
|
||||||
|
{
|
||||||
|
cmCtx_t ctx;
|
||||||
|
cmLHeapH_t lhH;
|
||||||
|
cmCsvH_t csvH;
|
||||||
|
cmSdbEvent_t* eV;
|
||||||
|
unsigned eN;
|
||||||
|
unsigned blkIdxAllocCnt;
|
||||||
|
struct cmSdbRsp_str* responses;
|
||||||
|
} cmSdb_t;
|
||||||
|
|
||||||
|
cmSdbH_t cmSdbNullHandle = cmSTATIC_NULL_HANDLE;
|
||||||
|
cmSdbResponseH_t cmSdbResponseNullHandle = cmSTATIC_NULL_HANDLE;
|
||||||
|
|
||||||
|
cmSdb_t* _cmSdbHandleToPtr( cmSdbH_t h )
|
||||||
|
{
|
||||||
|
cmSdb_t* p = (cmSdb_t*)h.h;
|
||||||
|
assert( p != NULL );
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmSdbRsp_t* _cmSdbRspHandleToPtr( cmSdbResponseH_t h )
|
||||||
|
{
|
||||||
|
cmSdbRsp_t* p = (cmSdbRsp_t*)h.h;
|
||||||
|
assert( p != NULL );
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _cmSdbRspBlkFree( cmSdb_t* p, cmSdbRspBlk_t* bp )
|
||||||
|
{
|
||||||
|
cmLhFree(p->lhH, bp->indexV);
|
||||||
|
cmLhFree(p->lhH, bp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
cmSdbRspBlk_t* _cmSdbRspBlkUnlink( cmSdbRsp_t* rp, cmSdbRspBlk_t* bp )
|
||||||
|
{
|
||||||
|
cmSdbRspBlk_t* dp = rp->blocks;
|
||||||
|
cmSdbRspBlk_t* pp = NULL;
|
||||||
|
for(; dp!=NULL; dp=dp->link)
|
||||||
|
{
|
||||||
|
if( dp == bp )
|
||||||
|
{
|
||||||
|
if( pp == NULL )
|
||||||
|
rp->blocks = dp->link;
|
||||||
|
else
|
||||||
|
pp->link = dp->link;
|
||||||
|
|
||||||
|
return bp;
|
||||||
|
}
|
||||||
|
|
||||||
|
pp = dp;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _cmSdbRspInsertIndex( cmSdb_t* p, cmSdbRsp_t* rp, unsigned evtIndex )
|
||||||
|
{
|
||||||
|
|
||||||
|
if( rp->ebp == NULL || rp->ebp->cnt == p->blkIdxAllocCnt )
|
||||||
|
{
|
||||||
|
cmSdbRspBlk_t* bp = cmLhAllocZ(p->lhH,cmSdbRspBlk_t,1);
|
||||||
|
bp->indexV = cmLhAllocZ(p->lhH,unsigned,p->blkIdxAllocCnt);
|
||||||
|
|
||||||
|
if( rp->ebp != NULL )
|
||||||
|
rp->ebp->link = bp;
|
||||||
|
|
||||||
|
if( rp->blocks == NULL )
|
||||||
|
rp->blocks = bp;
|
||||||
|
|
||||||
|
rp->ebp = bp;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
assert( rp->ebp!=NULL && rp->ebp->cnt < p->blkIdxAllocCnt );
|
||||||
|
|
||||||
|
rp->ebp->indexV[ rp->ebp->cnt++ ] = evtIndex;
|
||||||
|
rp->cnt += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _cmSdbRspRelease( cmSdbRsp_t* rp )
|
||||||
|
{
|
||||||
|
while( rp->blocks != NULL )
|
||||||
|
{
|
||||||
|
cmSdbRspBlk_t* np = rp->blocks->link;
|
||||||
|
cmSdbRspBlk_t* bp;
|
||||||
|
|
||||||
|
if((bp = _cmSdbRspBlkUnlink(rp,rp->blocks)) != NULL )
|
||||||
|
_cmSdbRspBlkFree(rp->p,bp);
|
||||||
|
|
||||||
|
rp->blocks = np;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmLhFree(rp->p->lhH,rp);
|
||||||
|
}
|
||||||
|
|
||||||
|
cmSdbRsp_t* _cmSdbRspUnlink( cmSdbRsp_t* rp )
|
||||||
|
{
|
||||||
|
cmSdb_t* p = rp->p;
|
||||||
|
cmSdbRsp_t* dp = p->responses;
|
||||||
|
cmSdbRsp_t* pp = NULL;
|
||||||
|
|
||||||
|
for(; dp!=NULL; dp=dp->link)
|
||||||
|
{
|
||||||
|
if( dp == rp )
|
||||||
|
{
|
||||||
|
if( pp == NULL )
|
||||||
|
p->responses = dp->link;
|
||||||
|
else
|
||||||
|
pp->link = dp->link;
|
||||||
|
|
||||||
|
return rp;
|
||||||
|
}
|
||||||
|
|
||||||
|
pp = dp;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert( 0 );
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void _cmSdbRspFree( cmSdbRsp_t* rp )
|
||||||
|
{
|
||||||
|
_cmSdbRspUnlink(rp);
|
||||||
|
_cmSdbRspRelease(rp);
|
||||||
|
}
|
||||||
|
|
||||||
|
cmSdbRsp_t* _cmSdbRspAlloc( cmSdb_t* p, cmSdbResponseH_t* rhp )
|
||||||
|
{
|
||||||
|
if( cmSdbResponseFree(rhp) != kOkSdbRC )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
cmSdbRsp_t* rp = cmLhAllocZ(p->lhH,cmSdbRsp_t,1);
|
||||||
|
rp->p = p;
|
||||||
|
rp->link = p->responses;
|
||||||
|
p->responses = rp;
|
||||||
|
|
||||||
|
rhp->h = rp;
|
||||||
|
|
||||||
|
return rp;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmSdbRC_t _cmSdbDestroy( cmSdb_t* p )
|
||||||
|
{
|
||||||
|
cmSdbRC_t rc = kOkSdbRC;
|
||||||
|
|
||||||
|
if( cmCsvFinalize(&p->csvH) != kOkCsvRC )
|
||||||
|
rc = cmErrMsg(&p->ctx.err,kCsvFailSdbRC,"CSV file finalize failed.");
|
||||||
|
|
||||||
|
while( p->responses != NULL )
|
||||||
|
_cmSdbRspRelease(p->responses);
|
||||||
|
|
||||||
|
cmLHeapDestroy(&p->lhH);
|
||||||
|
cmMemFree(p);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmSdbRC_t cmSdbCreate( cmCtx_t* ctx, cmSdbH_t* hp, const cmChar_t* audioDir, const cmChar_t* csvFn )
|
||||||
|
{
|
||||||
|
cmSdbRC_t rc;
|
||||||
|
if((rc = cmSdbDestroy(hp)) != kOkSdbRC )
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
cmSdb_t* p = cmMemAllocZ(cmSdb_t,1);
|
||||||
|
p->ctx = *ctx;
|
||||||
|
p->blkIdxAllocCnt = 1024;
|
||||||
|
|
||||||
|
cmErrSetup(&p->ctx.err,&ctx->rpt,"sdb");
|
||||||
|
|
||||||
|
if( cmLHeapIsValid( p->lhH = cmLHeapCreate(8192,ctx)) == false )
|
||||||
|
{
|
||||||
|
rc = cmErrMsg(&p->ctx.err,kLHeapFailSdbRC,"Linked heap mgr. allocation failed.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
hp->h = p;
|
||||||
|
|
||||||
|
if( csvFn != NULL )
|
||||||
|
if((rc = cmSdbLoad(*hp,csvFn)) != kOkSdbRC )
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
if( rc != kOkSdbRC )
|
||||||
|
_cmSdbDestroy(p);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmSdbRC_t cmSdbDestroy( cmSdbH_t* hp )
|
||||||
|
{
|
||||||
|
cmSdbRC_t rc = kOkSdbRC;
|
||||||
|
|
||||||
|
if( hp==NULL || cmSdbIsValid(*hp)==false )
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
cmSdb_t* p = _cmSdbHandleToPtr(*hp);
|
||||||
|
|
||||||
|
if((rc = _cmSdbDestroy(p)) != kOkSdbRC )
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
hp->h = NULL;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cmSdbIsValid( cmSdbH_t h )
|
||||||
|
{ return h.h != NULL; }
|
||||||
|
|
||||||
|
|
||||||
|
cmSdbRC_t _cmSdbSyntaxError(cmSdb_t* p, const cmChar_t* csvFn, unsigned rowIdx, unsigned colIdx, const cmChar_t* colLabel )
|
||||||
|
{
|
||||||
|
return cmErrMsg(&p->ctx.err,kSyntaxErrSdbRC,"A syntax error was found at row %i col %i (label:%s) in '%s'.",rowIdx+1,colIdx+1,cmStringNullGuard(colLabel),cmStringNullGuard(csvFn));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
cmSdbRC_t cmSdbLoad( cmSdbH_t h, const cmChar_t* csvFn )
|
||||||
|
{
|
||||||
|
cmSdbRC_t rc = kOkSdbRC;
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
cmSdb_t* p = _cmSdbHandleToPtr(h);
|
||||||
|
|
||||||
|
if( cmCsvInitializeFromFile(&p->csvH, csvFn, 0, &p->ctx ) != kOkCsvRC )
|
||||||
|
{
|
||||||
|
rc = cmErrMsg(&p->ctx.err,kCsvFailSdbRC,"CSV file load fail on '%s'.",cmStringNullGuard(csvFn));
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
p->eN = cmCsvRowCount(p->csvH)-1;
|
||||||
|
|
||||||
|
// release all the memory held by the linked heap
|
||||||
|
cmLHeapClear(p->lhH,true);
|
||||||
|
|
||||||
|
p->eV = cmLhAllocZ(p->lhH,cmSdbEvent_t,p->eN);
|
||||||
|
|
||||||
|
|
||||||
|
for(i=0; rc==kOkSdbRC && i<p->eN; ++i)
|
||||||
|
{
|
||||||
|
unsigned rowIdx = i+1;
|
||||||
|
|
||||||
|
if((p->eV[i].uuid = cmCsvCellUInt(p->csvH,rowIdx,kUuidColIdx)) == UINT_MAX )
|
||||||
|
rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kUuidColIdx,"uuid");
|
||||||
|
|
||||||
|
if((p->eV[i].baseUuid = cmCsvCellUInt(p->csvH,rowIdx,kBaseUuidColIdx)) == UINT_MAX )
|
||||||
|
rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kBaseUuidColIdx,"baseUuid");
|
||||||
|
|
||||||
|
if((p->eV[i].chIdx = cmCsvCellUInt(p->csvH,rowIdx,kChIdxColIdx)) == UINT_MAX )
|
||||||
|
rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kChIdxColIdx,"chIdx");
|
||||||
|
else
|
||||||
|
p->eV[i].chIdx -= 1; // CSV channel index is 1 based
|
||||||
|
|
||||||
|
if((p->eV[i].obi = cmCsvCellUInt(p->csvH,rowIdx,kObiColIdx)) == UINT_MAX )
|
||||||
|
rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kObiColIdx,"obi");
|
||||||
|
else
|
||||||
|
p->eV[i].obi -= 1;
|
||||||
|
|
||||||
|
if((p->eV[i].ibi = cmCsvCellUInt(p->csvH,rowIdx,kIbiColIdx)) == UINT_MAX )
|
||||||
|
rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kIbiColIdx,"ibi");
|
||||||
|
else
|
||||||
|
p->eV[i].ibi -= 1;
|
||||||
|
|
||||||
|
if((p->eV[i].iei = cmCsvCellUInt(p->csvH,rowIdx,kIeiColIdx)) == UINT_MAX )
|
||||||
|
rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kIeiColIdx,"obi");
|
||||||
|
else
|
||||||
|
p->eV[i].iei -= 1;
|
||||||
|
|
||||||
|
if((p->eV[i].oei = cmCsvCellUInt(p->csvH,rowIdx,kOeiColIdx)) == UINT_MAX )
|
||||||
|
rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kOeiColIdx,"ibi");
|
||||||
|
else
|
||||||
|
p->eV[i].oei -= 1;
|
||||||
|
|
||||||
|
if((p->eV[i].src = cmCsvCellText(p->csvH,rowIdx,kSrcColIdx)) == NULL )
|
||||||
|
rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kSrcColIdx,"src");
|
||||||
|
|
||||||
|
if((p->eV[i].midi = cmCsvCellInt(p->csvH,rowIdx,kMidiColIdx)) == INT_MAX )
|
||||||
|
rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kMidiColIdx,"midi");
|
||||||
|
|
||||||
|
if((p->eV[i].instr = cmCsvCellText(p->csvH,rowIdx,kInstrColIdx)) == NULL )
|
||||||
|
rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kInstrColIdx,"instr");
|
||||||
|
|
||||||
|
if((p->eV[i].srate = cmCsvCellUInt(p->csvH,rowIdx,kSrateColIdx)) == UINT_MAX )
|
||||||
|
rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kSrateColIdx,"srate");
|
||||||
|
|
||||||
|
if((p->eV[i].chCnt = cmCsvCellUInt(p->csvH,rowIdx,kChCntColIdx)) == UINT_MAX )
|
||||||
|
rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kChCntColIdx,"chCnt");
|
||||||
|
|
||||||
|
|
||||||
|
cmCsvCell_t* c;
|
||||||
|
if((c = cmCsvCellPtr(p->csvH,rowIdx,kNotesColIdx)) == NULL )
|
||||||
|
{
|
||||||
|
rc = cmErrMsg(&p->ctx.err,kSyntaxErrSdbRC,"Syntax Error: No 'notes' or 'audio file name' field for row %i in '%s'.",rowIdx+1,cmStringNullGuard(csvFn));
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// count the number of 'notes'
|
||||||
|
unsigned nn = 0;
|
||||||
|
for(; c->rowPtr != NULL; c=c->rowPtr)
|
||||||
|
++nn;
|
||||||
|
|
||||||
|
if( nn > 0 )
|
||||||
|
{
|
||||||
|
unsigned k = 0;
|
||||||
|
|
||||||
|
// allocate the 'notes' ptr array - the last entry is set to NULL.
|
||||||
|
p->eV[i].notesV = cmLhAllocZ(p->lhH,const cmChar_t*,nn+1);
|
||||||
|
|
||||||
|
// read each note
|
||||||
|
for(c=cmCsvCellPtr(p->csvH,rowIdx,kNotesColIdx); c!=NULL&&c->rowPtr!=NULL; c=c->rowPtr,++k)
|
||||||
|
if(( p->eV[i].notesV[k] = cmCsvCellText(p->csvH,rowIdx,kNotesColIdx+k)) == NULL )
|
||||||
|
rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kNotesColIdx+k,"notes");
|
||||||
|
|
||||||
|
assert(k==nn);
|
||||||
|
}
|
||||||
|
|
||||||
|
// read the audio file name
|
||||||
|
if((p->eV[i].afn = cmCsvCellText(p->csvH,rowIdx,kNotesColIdx+nn)) == NULL )
|
||||||
|
rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kNotesColIdx+nn,"afn");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare 'label' to every string in tV[i] and return true if any comparision is a match.
|
||||||
|
// If 'subFlV[i]' is set then 'label' must only contain tV[i] as a substring to match.
|
||||||
|
// If 'negFlV[i]' is set then return true if any comparision is a mismatch.
|
||||||
|
bool _cmSdbSelectText( const cmSdbEvent_t* r, const cmChar_t** tV, const bool* subFlV, const bool* negFlV, const cmChar_t* label )
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
if( label == NULL )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if( tV == NULL )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
for(i=0; tV[i]!=NULL; ++i)
|
||||||
|
{
|
||||||
|
bool matchFl = false;
|
||||||
|
if( subFlV[i] )
|
||||||
|
matchFl = strstr(label,tV[i]) != NULL;
|
||||||
|
else
|
||||||
|
matchFl = strcmp(tV[i],label)==0;
|
||||||
|
|
||||||
|
if( negFlV[i] )
|
||||||
|
matchFl = !matchFl;
|
||||||
|
|
||||||
|
if(matchFl)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned _cmSdbStrVectCnt( const cmChar_t** v )
|
||||||
|
{
|
||||||
|
unsigned n = 0;
|
||||||
|
unsigned i = 0;
|
||||||
|
|
||||||
|
if( v == NULL )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for(i=0; v[i]!=NULL; ++i)
|
||||||
|
++n;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _cmSdbStrVectFlags( const cmChar_t** v, bool* sV, bool* nV )
|
||||||
|
{
|
||||||
|
unsigned i = 0;
|
||||||
|
if( v == NULL )
|
||||||
|
return;
|
||||||
|
|
||||||
|
for(i=0; v[i]!=NULL; ++i)
|
||||||
|
{
|
||||||
|
nV[i] = false;
|
||||||
|
sV[i] = false;
|
||||||
|
|
||||||
|
if( strncmp(v[i],"*!",2)==0 || strncmp(v[i],"!*",2)==0)
|
||||||
|
{
|
||||||
|
sV[i] = nV[i] = true;
|
||||||
|
v[i] += 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( strncmp(v[i],"!",1)==0 )
|
||||||
|
{
|
||||||
|
nV[i] = true;
|
||||||
|
v[i] += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( strncmp(v[i],"*",1)==0 )
|
||||||
|
{
|
||||||
|
sV[i] = true;
|
||||||
|
v[i] += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cmSdbRC_t cmSdbSelect(
|
||||||
|
cmSdbH_t h,
|
||||||
|
double srate,
|
||||||
|
const cmChar_t** instrV,
|
||||||
|
const cmChar_t** srcV,
|
||||||
|
const cmChar_t** notesV,
|
||||||
|
double minDurSec,
|
||||||
|
double maxDurSec,
|
||||||
|
unsigned minChCnt,
|
||||||
|
cmSdbResponseH_t* rhp )
|
||||||
|
{
|
||||||
|
cmSdbRC_t rc = kOkSdbRC;
|
||||||
|
cmSdb_t* p = _cmSdbHandleToPtr(h);
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
cmSdbRsp_t* rp = _cmSdbRspAlloc(p,rhp);
|
||||||
|
|
||||||
|
// get the length of each string vector
|
||||||
|
unsigned srcN = _cmSdbStrVectCnt(srcV);
|
||||||
|
unsigned insN = _cmSdbStrVectCnt(instrV);
|
||||||
|
unsigned notN = _cmSdbStrVectCnt(notesV);
|
||||||
|
|
||||||
|
// allocate flag vectors
|
||||||
|
bool srcSubFlV[ srcN ];
|
||||||
|
bool srcNegFlV[ srcN ];
|
||||||
|
bool insSubFlV[ insN ];
|
||||||
|
bool insNegFlV[ insN ];
|
||||||
|
bool notSubFlV[ notN ];
|
||||||
|
bool notNegFlV[ notN ];
|
||||||
|
|
||||||
|
// fill the flag vectors
|
||||||
|
_cmSdbStrVectFlags(srcV, srcSubFlV,srcNegFlV);
|
||||||
|
_cmSdbStrVectFlags(instrV,insSubFlV,insNegFlV);
|
||||||
|
_cmSdbStrVectFlags(notesV,notSubFlV,notNegFlV);
|
||||||
|
|
||||||
|
for(i=0; i<p->eN; ++i)
|
||||||
|
{
|
||||||
|
const cmSdbEvent_t* r = p->eV + i;
|
||||||
|
double durSec = (double)r->srate * (r->oei - r->obi);
|
||||||
|
unsigned j;
|
||||||
|
|
||||||
|
if( srate!=0 && srate!=r->srate )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if( durSec < minDurSec || (maxDurSec!=0 && maxDurSec < durSec) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if( minChCnt!=0 && r->chCnt > minChCnt )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if( !_cmSdbSelectText(r,srcV,srcSubFlV,srcNegFlV,r->src) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if( !_cmSdbSelectText(r,instrV,insSubFlV,insNegFlV,r->instr) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if( r->notesV != NULL )
|
||||||
|
for(j=0; r->notesV[j]!=NULL; ++j)
|
||||||
|
if( _cmSdbSelectText(r,notesV,notSubFlV,notNegFlV,r->notesV[j]) == true )
|
||||||
|
break;
|
||||||
|
|
||||||
|
if( r->notesV[j]==NULL )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
|
||||||
|
_cmSdbRspInsertIndex(p,rp,i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmSdbRC_t cmSdbSelectChPairs( cmSdbH_t h, const cmSdbEvent_t* ep, cmSdbResponseH_t* rhp )
|
||||||
|
{
|
||||||
|
cmSdbRC_t rc = kOkSdbRC;
|
||||||
|
cmSdb_t* p = _cmSdbHandleToPtr(h);
|
||||||
|
cmSdbRsp_t* rp = _cmSdbRspAlloc(p,rhp);
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
// for each channel of this event
|
||||||
|
for(i=0; i<ep->chCnt; ++i)
|
||||||
|
{
|
||||||
|
// if i channel is not the known events channel
|
||||||
|
if( ep->chIdx != i )
|
||||||
|
{
|
||||||
|
unsigned j;
|
||||||
|
|
||||||
|
// examine each record
|
||||||
|
for(j=0; j<p->eN; ++j)
|
||||||
|
// if eV[j] shares a baseUuid but is on a different channel than *ep ...
|
||||||
|
if( p->eV[j].baseUuid == ep->baseUuid && p->eV[j].chIdx==i )
|
||||||
|
{
|
||||||
|
// .. then a match has been found
|
||||||
|
_cmSdbRspInsertIndex(p,rp,j);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( j== p->eN )
|
||||||
|
{
|
||||||
|
rc = cmErrMsg(&p->ctx.err,kChPairNotFoundSdbRC,"The channel pair associated with 'id:%i instr:%s src:%s ch index:%i could not be found.",ep->uuid,cmStringNullGuard(ep->instr),cmStringNullGuard(ep->src),ep->chIdx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned cmSdbResponseCount( cmSdbResponseH_t rh )
|
||||||
|
{
|
||||||
|
cmSdbRsp_t* rp = _cmSdbRspHandleToPtr(rh);
|
||||||
|
return rp->cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cmSdbEvent_t* cmSdbResponseEvent( cmSdbResponseH_t rh, unsigned index )
|
||||||
|
{
|
||||||
|
cmSdbRsp_t* rp = _cmSdbRspHandleToPtr(rh);
|
||||||
|
|
||||||
|
if( index >= rp->cnt )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
cmSdbRspBlk_t* bp = rp->blocks;
|
||||||
|
unsigned i;
|
||||||
|
for(i=0; bp!=NULL; i+=bp->cnt,bp=bp->link)
|
||||||
|
if( i <= index && index < (i + bp->cnt) )
|
||||||
|
return rp->p->eV + bp->indexV[index-i];
|
||||||
|
|
||||||
|
cmErrMsg(&rp->p->ctx.err,kInvalidRspIdxSdbRC,"Invalid query response index=%i.",index);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cmSdbResponseIsValid( cmSdbResponseH_t rh )
|
||||||
|
{ return rh.h != NULL; }
|
||||||
|
|
||||||
|
cmSdbRC_t cmSdbResponseFree( cmSdbResponseH_t* rhp )
|
||||||
|
{
|
||||||
|
cmSdbRC_t rc = kOkSdbRC;
|
||||||
|
|
||||||
|
if( rhp == NULL || cmSdbResponseIsValid(*rhp)==false )
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
cmSdbRsp_t* rp = _cmSdbRspHandleToPtr(*rhp);
|
||||||
|
|
||||||
|
_cmSdbRspFree(rp);
|
||||||
|
|
||||||
|
rhp->h = NULL;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmSdbResponsePrint( cmSdbResponseH_t rh, cmRpt_t* rpt )
|
||||||
|
{
|
||||||
|
unsigned n = cmSdbResponseCount(rh);
|
||||||
|
unsigned i;
|
||||||
|
for(i=0; i<n; ++i)
|
||||||
|
{
|
||||||
|
const cmSdbEvent_t* e = cmSdbResponseEvent(rh,i);
|
||||||
|
if( e != NULL )
|
||||||
|
cmRptPrintf(rpt,"%6i %6i %2i %12i %12i %12i %12i %2i %6i %2i %10s %15s\n",
|
||||||
|
e->uuid,e->baseUuid,e->chIdx,e->obi,e->ibi,e->iei,e->oei,e->midi,e->srate,e->chCnt,
|
||||||
|
cmStringNullGuard(e->src), cmStringNullGuard(e->instr) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cmSdbRC_t cmSdbSyncChPairs( cmSdbH_t h )
|
||||||
|
{
|
||||||
|
cmSdbRC_t rc = kOkSdbRC;
|
||||||
|
cmSdb_t* p = _cmSdbHandleToPtr(h);
|
||||||
|
unsigned i;
|
||||||
|
// for each multi-channel event
|
||||||
|
for(i=0; i<p->eN; ++i)
|
||||||
|
if(p->eV[i].chCnt > 1 )
|
||||||
|
{
|
||||||
|
const cmSdbEvent_t* ep = p->eV + i;
|
||||||
|
unsigned iV[ep->chCnt];
|
||||||
|
unsigned j,k;
|
||||||
|
|
||||||
|
// load iV[] with the event indexes of the channel pairs
|
||||||
|
for(j=0,k=0; j<p->eN && k<ep->chCnt; ++j)
|
||||||
|
if( p->eV[j].baseUuid == ep->baseUuid )
|
||||||
|
{
|
||||||
|
assert( p->eV[j].chIdx < ep->chCnt );
|
||||||
|
|
||||||
|
iV[p->eV[j].chIdx] = j;
|
||||||
|
++k;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( k != ep->chCnt )
|
||||||
|
rc = cmErrMsg(&p->ctx.err,kChPairNotFoundSdbRC,"The channel pair associated with 'id:%i instr:%s src:%s ch index:%i could not be found.",ep->uuid,cmStringNullGuard(ep->instr),cmStringNullGuard(ep->src),ep->chIdx);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned mobi = ep->obi;
|
||||||
|
unsigned mibi = ep->ibi;
|
||||||
|
unsigned miei = ep->iei;
|
||||||
|
unsigned moei = ep->oei;
|
||||||
|
|
||||||
|
// get the min onsets and max offsets
|
||||||
|
for(j=0; j<ep->chCnt; ++j)
|
||||||
|
{
|
||||||
|
mobi = cmMin(mobi,p->eV[ iV[j] ].obi);
|
||||||
|
mibi = cmMin(mibi,p->eV[ iV[j] ].ibi);
|
||||||
|
miei = cmMax(miei,p->eV[ iV[j] ].iei);
|
||||||
|
moei = cmMax(moei,p->eV[ iV[j] ].oei);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the onsets to the min onset / offsets to max offsets
|
||||||
|
for(j=0; j<ep->chCnt; ++j)
|
||||||
|
{
|
||||||
|
p->eV[ iV[j] ].obi = mobi;
|
||||||
|
p->eV[ iV[j] ].ibi = mibi;
|
||||||
|
p->eV[ iV[j] ].iei = miei;
|
||||||
|
p->eV[ iV[j] ].oei = moei;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
cmSdbRC_t cmSdbTest( cmCtx_t* ctx )
|
||||||
|
{
|
||||||
|
cmSdbRC_t rc = kOkSdbRC;
|
||||||
|
cmSdbH_t h = cmSdbNullHandle;
|
||||||
|
const cmChar_t* audioDir = "/home/kevin/media/audio";
|
||||||
|
const cmChar_t* csvFn = "/home/kevin/temp/sdb0/sdb_master.csv";
|
||||||
|
cmErr_t err;
|
||||||
|
|
||||||
|
cmErrSetup(&err,&ctx->rpt,"sdb test");
|
||||||
|
|
||||||
|
if((rc = cmSdbCreate(ctx, &h, audioDir, csvFn )) != kOkSdbRC )
|
||||||
|
{
|
||||||
|
rc = cmErrMsg(&err,rc,"sdb create failed.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((rc = cmSdbSyncChPairs(h)) != kOkSdbRC )
|
||||||
|
{
|
||||||
|
rc = cmErrMsg(&err,rc,"sdb sync-ch-pairs failed.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(0)
|
||||||
|
{
|
||||||
|
cmSdbResponseH_t rH = cmSdbResponseNullHandle;
|
||||||
|
|
||||||
|
const cmChar_t* instrV[] = { "*viol", NULL };
|
||||||
|
|
||||||
|
if((rc = cmSdbSelect(h,0,instrV,NULL,NULL,0,0,0,&rH)) != kOkSdbRC )
|
||||||
|
{
|
||||||
|
rc = cmErrMsg(&err,rc,"sdb query failed.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
cmSdbResponsePrint(rH,&ctx->rpt);
|
||||||
|
|
||||||
|
cmSdbResponseFree(&rH);
|
||||||
|
}
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
if((rc = cmSdbDestroy(&h)) != kOkSdbRC )
|
||||||
|
rc = cmErrMsg(&err,rc,"sdb destroy failed.");
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
169
app/cmSdb.h
Normal file
169
app/cmSdb.h
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
#ifndef cmSdb_h
|
||||||
|
#define cmSdb_h
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
The data for this object is stored in a CSV file with the following column syntax.
|
||||||
|
|
||||||
|
Column Name Type Description
|
||||||
|
------ -------- ----- -----------------------------------------------------
|
||||||
|
1 uuid uint Unique integer identifier for this event
|
||||||
|
2 baseUuid uint uuid of channel 0 for this event
|
||||||
|
3 chIdx uint Channel index (stereo: 1=left 2=right)
|
||||||
|
4 obi uint Outer onset sample index into 'afn'.
|
||||||
|
5 ibi uint Inner onset sample index into 'afn'.
|
||||||
|
6 iei uint Inner offset sample index into 'afn'.
|
||||||
|
7 oei uint Outer offset sample index into 'afn'.
|
||||||
|
8 src text Source label for this event (e.g. mcgill, ui )
|
||||||
|
9 midi uint MIDI pitch number or -1 if the sample is not pitched
|
||||||
|
10 instr text Instrument label.
|
||||||
|
11 srate uint Sample rate of audio file reference by 'afn'.
|
||||||
|
10 chCnt uint Count of channels for this event.
|
||||||
|
* notes text 0 or more free form double quoted text notes.
|
||||||
|
* afn text File name of the audio file this event occurs in.
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
#. Each event represents a mono audio signal. If the event is drawn
|
||||||
|
from a multi-channel audio file then the 'chCnt' field will be
|
||||||
|
greater than one. If 'chCnt' is greater than one then the associated
|
||||||
|
samples can be found by collecting all events that share the
|
||||||
|
same 'baseUuid'.
|
||||||
|
|
||||||
|
#. There may be zero or more columns of 'notes'. If there are no
|
||||||
|
notes then the 'afn' field is in column 11.
|
||||||
|
|
||||||
|
#. The index values (chIdx,obi,ibi,iei,oei) as stored in the CSV file
|
||||||
|
are 1 based. These values are decreased by 1 by the cmSdb CSV reader
|
||||||
|
so that their cmSdb value is zero based. See cmSdbLoad().
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
kOkSdbRC,
|
||||||
|
kLHeapFailSdbRC,
|
||||||
|
kCsvFailSdbRC,
|
||||||
|
kSyntaxErrSdbRC,
|
||||||
|
kInvalidRspIdxSdbRC,
|
||||||
|
kChPairNotFoundSdbRC
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef cmHandle_t cmSdbH_t;
|
||||||
|
typedef cmHandle_t cmSdbResponseH_t;
|
||||||
|
|
||||||
|
typedef cmRC_t cmSdbRC_t;
|
||||||
|
extern cmSdbH_t cmSdbNullHandle_t;
|
||||||
|
extern cmSdbResponseH_t cmSdbResponseNullHandle_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned uuid; // unique id of this sample
|
||||||
|
unsigned baseUuid; // uuid of channel 0
|
||||||
|
unsigned chIdx; // channel index (0=left,1=right)
|
||||||
|
unsigned obi; // outer onset
|
||||||
|
unsigned ibi; // inner onset
|
||||||
|
unsigned iei; // inner offset
|
||||||
|
unsigned oei; // outer offset
|
||||||
|
unsigned midi; // MIDI pitch or -1 for unpitched instruments
|
||||||
|
unsigned srate; // sample rate
|
||||||
|
unsigned chCnt; // source channel count
|
||||||
|
const cmChar_t* src; // sample source (e.g. mcgill, ui )
|
||||||
|
const cmChar_t* instr; // instrument label
|
||||||
|
const cmChar_t* afn; // audio file name
|
||||||
|
const cmChar_t** notesV; // NULL terminated list of terms describing the event.
|
||||||
|
} cmSdbEvent_t;
|
||||||
|
|
||||||
|
|
||||||
|
cmSdbRC_t cmSdbCreate( cmCtx_t* ctx, cmSdbH_t* hp, const cmChar_t* audioDir, const cmChar_t* csvFn );
|
||||||
|
cmSdbRC_t cmSdbDestroy( cmSdbH_t* hp );
|
||||||
|
|
||||||
|
bool cmSdbIsValid( cmSdbH_t h );
|
||||||
|
|
||||||
|
cmSdbRC_t cmSdbLoad( cmSdbH_t h, const cmChar_t* csvFn );
|
||||||
|
|
||||||
|
// Select a set of events from the sample database.
|
||||||
|
//
|
||||||
|
// The possible selection criteria are:
|
||||||
|
// sample rate
|
||||||
|
// instrument label
|
||||||
|
// source label
|
||||||
|
// notes labels
|
||||||
|
// event duration
|
||||||
|
//
|
||||||
|
// In order to match an event all active criteria
|
||||||
|
// must match. In other words the match implies a
|
||||||
|
// logical AND operation on each match criteria.
|
||||||
|
// Each of the criteria can be made inactive by
|
||||||
|
// specifying particular key values.
|
||||||
|
// sample rate = 0
|
||||||
|
// instrument label = NULL
|
||||||
|
// source label = NULL
|
||||||
|
// notes labels = NULL
|
||||||
|
// event duration = minDurSec=0 maxDurSec=0
|
||||||
|
//
|
||||||
|
// For the text array arguments (instrV,srcV,notesV)
|
||||||
|
// each element of the array is a key which is attempts to
|
||||||
|
// match the associated field in each event record.
|
||||||
|
// By default a match is triggered if the key text is identical to the
|
||||||
|
// event field text. The match algorithm can be modified by
|
||||||
|
// specifying a '*' as the first character in the key field.
|
||||||
|
// In this case a the key need only be a substring of the
|
||||||
|
// event field to trigger a match. For example "*viol"
|
||||||
|
// will return events that match both "violin" and "viola".
|
||||||
|
//
|
||||||
|
// To specify a mismatch as a successful match
|
||||||
|
// (i.e. to return events which do not match the key text)
|
||||||
|
// prefix the key with a '!' character.
|
||||||
|
//
|
||||||
|
// Note that it is legal to specify both '!' and '*'. In
|
||||||
|
// which case a match will be triggered by fields where
|
||||||
|
// the key text is not a substring of the field text.
|
||||||
|
//
|
||||||
|
// All query response handles returned from this function
|
||||||
|
// should eventualy be released by the application via a call to
|
||||||
|
// cmSdbResponseFree().
|
||||||
|
cmSdbRC_t cmSdbSelect(
|
||||||
|
cmSdbH_t h,
|
||||||
|
double srate, // event sample rate or 0 to ignore
|
||||||
|
const cmChar_t** instrV, // array of instrument labels to match
|
||||||
|
const cmChar_t** srcV, // array of 'src' labels to match
|
||||||
|
const cmChar_t** notesV, // array of text 'notes' to match
|
||||||
|
double minDurSec, // min event duration
|
||||||
|
double maxDurSec, // max event duration or 0 to ignore
|
||||||
|
unsigned minChCnt, // min ch cnt or 0 to ignore
|
||||||
|
cmSdbResponseH_t* rhp );
|
||||||
|
|
||||||
|
// Given the event 'ep' locate the channel pairs associated with that event.
|
||||||
|
// The response handle returned from this function must be released
|
||||||
|
// by a call to cmSdbResponseFree().
|
||||||
|
cmSdbRC_t cmSdbSelectChPairs( cmSdbH_t h, const cmSdbEvent_t* ep, cmSdbResponseH_t* rhp );
|
||||||
|
|
||||||
|
// Return the count of events in a query response.
|
||||||
|
unsigned cmSdbResponseCount( cmSdbResponseH_t rh );
|
||||||
|
|
||||||
|
// Return the event at 'index' in from a query response.
|
||||||
|
// Legal 'index' range: 0<=index<=cmSdbResponseCount().
|
||||||
|
const cmSdbEvent_t* cmSdbResponseEvent( cmSdbResponseH_t rh, unsigned index );
|
||||||
|
|
||||||
|
// Return true if the 'rh' is a non-NULL query response handle.
|
||||||
|
bool cmSdbResponseIsValid( cmSdbResponseH_t rh );
|
||||||
|
|
||||||
|
// Release the resource held by a query response.
|
||||||
|
cmSdbRC_t cmSdbResponseFree( cmSdbResponseH_t* rhp );
|
||||||
|
void cmSdbResponsePrint( cmSdbResponseH_t rh, cmRpt_t* rpt );
|
||||||
|
|
||||||
|
// Time align all channel pairs by setting the onset times to
|
||||||
|
// the minimum time among all the pairs and the offset times to
|
||||||
|
// the maximum among all the pairs.
|
||||||
|
cmSdbRC_t cmSdbSyncChPairs( cmSdbH_t h );
|
||||||
|
|
||||||
|
cmSdbRC_t cmSdbTest( cmCtx_t* ctx );
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
48
cmCsv.c
48
cmCsv.c
@ -7,7 +7,7 @@
|
|||||||
#include "cmMallocDebug.h"
|
#include "cmMallocDebug.h"
|
||||||
#include "cmLex.h"
|
#include "cmLex.h"
|
||||||
#include "cmLinkedHeap.h"
|
#include "cmLinkedHeap.h"
|
||||||
#include "cmSymTbl.h"
|
#include "cmHashTbl.h"
|
||||||
#include "cmCsv.h"
|
#include "cmCsv.h"
|
||||||
#include "cmText.h"
|
#include "cmText.h"
|
||||||
|
|
||||||
@ -48,9 +48,9 @@ typedef struct cmCsvUdef_str
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
cmErr_t err;
|
cmErr_t err;
|
||||||
void* rptDataPtr; //
|
void* rptDataPtr; //
|
||||||
cmLexH lexH; // parsing lexer
|
cmLexH lexH; // parsing lexer
|
||||||
cmSymTblH_t symTblH; // all XML identifiers and data is stored as a symbol in this table
|
cmHashTblH_t htH; // hash table handle
|
||||||
cmLHeapH_t heapH;
|
cmLHeapH_t heapH;
|
||||||
cmCsvBind_t* bindPtr; // base of the binder linked list
|
cmCsvBind_t* bindPtr; // base of the binder linked list
|
||||||
cmCsvCell_t* curRowPtr; // used by the parser to track the row being filled
|
cmCsvCell_t* curRowPtr; // used by the parser to track the row being filled
|
||||||
@ -95,15 +95,15 @@ cmCsvRC_t cmCsvInitialize( cmCsvH_t *hp, cmCtx_t* ctx )
|
|||||||
|
|
||||||
cmErrSetup(&p->err,&ctx->rpt,"CSV");
|
cmErrSetup(&p->err,&ctx->rpt,"CSV");
|
||||||
|
|
||||||
// create the symbol table
|
// create the hash table
|
||||||
if( cmSymTblIsValid(p->symTblH = cmSymTblCreate(cmSymTblNullHandle,0,ctx)) == false )
|
if( cmHashTblCreate(ctx,&p->htH,8192) != kOkHtRC )
|
||||||
{
|
{
|
||||||
rc = _cmCsvError(p,kSymTblErrCsvRC,"Symbol table creation failed.");
|
rc = _cmCsvError(p,kHashTblErrCsvRC,"Hash table creation failed.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
// allocate the linked heap mgr
|
// allocate the linked heap mgr
|
||||||
if( cmLHeapIsValid(p->heapH = cmLHeapCreate(1024,ctx)) == false )
|
if( cmLHeapIsValid(p->heapH = cmLHeapCreate(8192,ctx)) == false )
|
||||||
{
|
{
|
||||||
rc = _cmCsvError(p,kMemAllocErrCsvRC,"Linked heap object allocation failed.");
|
rc = _cmCsvError(p,kMemAllocErrCsvRC,"Linked heap object allocation failed.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
@ -161,8 +161,8 @@ cmCsvRC_t cmCsvFinalize( cmCsvH_t *hp )
|
|||||||
if((lexRC = cmLexFinal(&p->lexH)) != kOkLexRC )
|
if((lexRC = cmLexFinal(&p->lexH)) != kOkLexRC )
|
||||||
return _cmCsvError(p,kLexErrCsvRC,"Lexer finalization failed.\nLexer Error:%s",cmLexRcToMsg(lexRC));
|
return _cmCsvError(p,kLexErrCsvRC,"Lexer finalization failed.\nLexer Error:%s",cmLexRcToMsg(lexRC));
|
||||||
|
|
||||||
// free the symbol table
|
// free the hash table
|
||||||
cmSymTblDestroy(&p->symTblH);
|
cmHashTblDestroy(&p->htH);
|
||||||
|
|
||||||
// free the handle
|
// free the handle
|
||||||
cmMemPtrFree(&hp->h);
|
cmMemPtrFree(&hp->h);
|
||||||
@ -352,8 +352,8 @@ cmCsvRC_t _cmCsvCreateCell( cmCsv_t* p, const char* tokenText, unsigned flags, u
|
|||||||
cmCsvRC_t rc = kOkCsvRC;
|
cmCsvRC_t rc = kOkCsvRC;
|
||||||
|
|
||||||
// register the token text as a symbol
|
// register the token text as a symbol
|
||||||
if((symId = cmSymTblRegisterSymbol(p->symTblH,tokenText)) == cmInvalidId )
|
if((symId = cmHashTblStoreStr(p->htH,tokenText)) == cmInvalidId )
|
||||||
return _cmCsvError(p,kSymTblErrCsvRC,"Symbol registration failed. for '%s' on line %i column %i.",tokenText,lexRow,lexCol);
|
return _cmCsvError(p,kHashTblErrCsvRC,"Symbol registration failed. for '%s' on line %i column %i.",tokenText,lexRow,lexCol);
|
||||||
|
|
||||||
// allocate a cell
|
// allocate a cell
|
||||||
if((rc = _cmCsvAllocCell(p,symId,flags,cellRow,cellCol,&cp,lexTId)) != kOkCsvRC )
|
if((rc = _cmCsvAllocCell(p,symId,flags,cellRow,cellCol,&cp,lexTId)) != kOkCsvRC )
|
||||||
@ -561,8 +561,8 @@ const char* cmCsvCellSymText( cmCsvH_t h, unsigned symId )
|
|||||||
cmCsv_t* p = _cmCsvHandleToPtr(h);
|
cmCsv_t* p = _cmCsvHandleToPtr(h);
|
||||||
const char* cp;
|
const char* cp;
|
||||||
|
|
||||||
if((cp = cmSymTblLabel(p->symTblH,symId)) == NULL )
|
if((cp = cmHashTblStr(p->htH,symId)) == NULL )
|
||||||
_cmCsvError(p,kSymTblErrCsvRC,"The text associated with the symbol '%i' was not found.",symId);
|
_cmCsvError(p,kHashTblErrCsvRC,"The text associated with the symbol '%i' was not found.",symId);
|
||||||
|
|
||||||
return cp;
|
return cp;
|
||||||
}
|
}
|
||||||
@ -573,7 +573,7 @@ cmCsvRC_t cmCsvCellSymInt( cmCsvH_t h, unsigned symId, int* vp )
|
|||||||
cmCsv_t* p = _cmCsvHandleToPtr(h);
|
cmCsv_t* p = _cmCsvHandleToPtr(h);
|
||||||
|
|
||||||
if((cp = cmCsvCellSymText(h,symId)) == NULL )
|
if((cp = cmCsvCellSymText(h,symId)) == NULL )
|
||||||
return kSymTblErrCsvRC;
|
return kHashTblErrCsvRC;
|
||||||
|
|
||||||
if( cmTextToInt(cp,vp,&p->err) != kOkTxRC )
|
if( cmTextToInt(cp,vp,&p->err) != kOkTxRC )
|
||||||
return _cmCsvError(p,kDataCvtErrCsvRC,"CSV text to int value failed.");
|
return _cmCsvError(p,kDataCvtErrCsvRC,"CSV text to int value failed.");
|
||||||
@ -587,7 +587,7 @@ cmCsvRC_t cmCsvCellSymUInt( cmCsvH_t h, unsigned symId, unsigned* vp )
|
|||||||
cmCsv_t* p = _cmCsvHandleToPtr(h);
|
cmCsv_t* p = _cmCsvHandleToPtr(h);
|
||||||
|
|
||||||
if((cp = cmCsvCellSymText(h,symId)) == NULL )
|
if((cp = cmCsvCellSymText(h,symId)) == NULL )
|
||||||
return kSymTblErrCsvRC;
|
return kHashTblErrCsvRC;
|
||||||
|
|
||||||
if( cmTextToUInt(cp,vp,&p->err) != kOkTxRC )
|
if( cmTextToUInt(cp,vp,&p->err) != kOkTxRC )
|
||||||
return _cmCsvError(p,kDataCvtErrCsvRC,"CSV text to uint value failed.");
|
return _cmCsvError(p,kDataCvtErrCsvRC,"CSV text to uint value failed.");
|
||||||
@ -601,7 +601,7 @@ cmCsvRC_t cmCsvCellSymFloat( cmCsvH_t h, unsigned symId, float* vp )
|
|||||||
cmCsv_t* p = _cmCsvHandleToPtr(h);
|
cmCsv_t* p = _cmCsvHandleToPtr(h);
|
||||||
|
|
||||||
if((cp = cmCsvCellSymText(h,symId)) == NULL )
|
if((cp = cmCsvCellSymText(h,symId)) == NULL )
|
||||||
return kSymTblErrCsvRC;
|
return kHashTblErrCsvRC;
|
||||||
|
|
||||||
if( cmTextToFloat(cp,vp,&p->err) != kOkTxRC )
|
if( cmTextToFloat(cp,vp,&p->err) != kOkTxRC )
|
||||||
return _cmCsvError(p,kDataCvtErrCsvRC,"CSV text to float value failed.");
|
return _cmCsvError(p,kDataCvtErrCsvRC,"CSV text to float value failed.");
|
||||||
@ -615,7 +615,7 @@ cmCsvRC_t cmCsvCellSymDouble( cmCsvH_t h, unsigned symId, double* vp )
|
|||||||
cmCsv_t* p = _cmCsvHandleToPtr(h);
|
cmCsv_t* p = _cmCsvHandleToPtr(h);
|
||||||
|
|
||||||
if((cp = cmCsvCellSymText(h,symId)) == NULL )
|
if((cp = cmCsvCellSymText(h,symId)) == NULL )
|
||||||
return kSymTblErrCsvRC;
|
return kHashTblErrCsvRC;
|
||||||
|
|
||||||
if( cmTextToDouble(cp,vp,&p->err) != kOkTxRC )
|
if( cmTextToDouble(cp,vp,&p->err) != kOkTxRC )
|
||||||
return _cmCsvError(p,kDataCvtErrCsvRC,"CSV text to double value failed.");
|
return _cmCsvError(p,kDataCvtErrCsvRC,"CSV text to double value failed.");
|
||||||
@ -695,8 +695,8 @@ unsigned cmCsvInsertSymText( cmCsvH_t h, const char* text )
|
|||||||
cmCsv_t* p = _cmCsvHandleToPtr(h);
|
cmCsv_t* p = _cmCsvHandleToPtr(h);
|
||||||
unsigned symId;
|
unsigned symId;
|
||||||
|
|
||||||
if((symId = cmSymTblRegisterSymbol(p->symTblH,text)) == cmInvalidId )
|
if((symId = cmHashTblStoreStr(p->htH,text)) == cmInvalidId )
|
||||||
_cmCsvError(p,kSymTblErrCsvRC,"'%s' could not be inserted into the symbol table.",text);
|
_cmCsvError(p,kHashTblErrCsvRC,"'%s' could not be inserted into the symbol table.",text);
|
||||||
|
|
||||||
return symId;
|
return symId;
|
||||||
}
|
}
|
||||||
@ -1134,8 +1134,8 @@ cmCsvRC_t cmCsvWrite( cmCsvH_t h, const char* fn )
|
|||||||
{
|
{
|
||||||
const char* tp;
|
const char* tp;
|
||||||
|
|
||||||
if((tp = cmSymTblLabel(p->symTblH,cp->symId)) == NULL )
|
if((tp = cmHashTblStr(p->htH,cp->symId)) == NULL )
|
||||||
return _cmCsvError(p,kSymTblErrCsvRC,"Unable to locate the symbol text for cell at row:%i col:%i.",cp->row,cp->col);
|
return _cmCsvError(p,kHashTblErrCsvRC,"Unable to locate the symbol text for cell at row:%i col:%i.",cp->row,cp->col);
|
||||||
|
|
||||||
if( cmIsFlag(cp->flags,kTextTMask) )
|
if( cmIsFlag(cp->flags,kTextTMask) )
|
||||||
fprintf(fp,"\"");
|
fprintf(fp,"\"");
|
||||||
@ -1179,8 +1179,8 @@ cmCsvRC_t cmCsvPrint( cmCsvH_t h, unsigned rowCnt )
|
|||||||
{
|
{
|
||||||
const char* tp;
|
const char* tp;
|
||||||
|
|
||||||
if((tp = cmSymTblLabel(p->symTblH,cp->symId)) == NULL )
|
if((tp = cmHashTblStr(p->htH,cp->symId)) == NULL )
|
||||||
_cmCsvError(p,kSymTblErrCsvRC,"The text associated with the symbol '%i' was not found.",cp->symId);
|
_cmCsvError(p,kHashTblErrCsvRC,"The text associated with the symbol '%i' was not found.",cp->symId);
|
||||||
|
|
||||||
fputs(tp,stdin);
|
fputs(tp,stdin);
|
||||||
}
|
}
|
||||||
|
2
cmCsv.h
2
cmCsv.h
@ -11,7 +11,7 @@ extern "C" {
|
|||||||
kOkCsvRC = 0,
|
kOkCsvRC = 0,
|
||||||
kMemAllocErrCsvRC,
|
kMemAllocErrCsvRC,
|
||||||
kLexErrCsvRC,
|
kLexErrCsvRC,
|
||||||
kSymTblErrCsvRC,
|
kHashTblErrCsvRC,
|
||||||
kSyntaxErrCsvRC,
|
kSyntaxErrCsvRC,
|
||||||
kFileOpenErrCsvRC,
|
kFileOpenErrCsvRC,
|
||||||
kFileCreateErrCsvRC,
|
kFileCreateErrCsvRC,
|
||||||
|
464
cmHashTbl.c
Normal file
464
cmHashTbl.c
Normal file
@ -0,0 +1,464 @@
|
|||||||
|
#include "cmGlobal.h"
|
||||||
|
#include "cmFloatTypes.h"
|
||||||
|
#include "cmRpt.h"
|
||||||
|
#include "cmErr.h"
|
||||||
|
#include "cmCtx.h"
|
||||||
|
#include "cmMem.h"
|
||||||
|
#include "cmLinkedHeap.h"
|
||||||
|
#include "cmMallocDebug.h"
|
||||||
|
#include "cmMath.h"
|
||||||
|
#include "cmHashTbl.h"
|
||||||
|
#include "cmText.h"
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
kFreeHtFl = 0x01,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct cmHtValue_str
|
||||||
|
{
|
||||||
|
unsigned flags; // See kXXXHtFl above.
|
||||||
|
unsigned id; // unique id associated with this value
|
||||||
|
void* value; // value blob
|
||||||
|
unsigned byteCnt; // size of value blob in bytes
|
||||||
|
struct cmHtValue_str* link; // cmHtBucket_t.list link
|
||||||
|
} cmHtValue_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
cmHtValue_t* list; // value list
|
||||||
|
cmHtValue_t* avail; // available value slots - formed from cmHashTblRemoved() values.
|
||||||
|
unsigned nextIdx; // next unused index for this bucket
|
||||||
|
} cmHtBucket_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
cmErr_t err;
|
||||||
|
cmLHeapH_t lhH; // memory for hash table buckets, values, value blobs.
|
||||||
|
unsigned bucketCnt; // hash table bucket cnt
|
||||||
|
unsigned linkCnt; // max length of collision list for each bucket
|
||||||
|
unsigned mask; // hash id bucket index mask (masks the MSB's of the hash-id)
|
||||||
|
unsigned maskShift; // shift required to move the lowest 'mask' bit to the LSB.
|
||||||
|
cmHtBucket_t* b; // b[bucketCnt] bucket array
|
||||||
|
} cmHt_t;
|
||||||
|
|
||||||
|
cmHashTblH_t cmHashTblNullHandle = cmSTATIC_NULL_HANDLE;
|
||||||
|
|
||||||
|
#define _cmHtBucketIndex( p, id ) (((id) & (p)->mask) >> (p)->maskShift)
|
||||||
|
|
||||||
|
cmHt_t* _cmHtHandleToPtr( cmHashTblH_t h )
|
||||||
|
{
|
||||||
|
cmHt_t* p = (cmHt_t*)h.h;
|
||||||
|
assert(p!=NULL);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the bucket index portion of the hash id.
|
||||||
|
unsigned _cmHtGenId( cmHt_t* p, const void* v, unsigned byteCnt )
|
||||||
|
{
|
||||||
|
unsigned i,j;
|
||||||
|
const char* cv = v;
|
||||||
|
unsigned h = 0;
|
||||||
|
|
||||||
|
for(i=0,j=3; i<byteCnt; ++i,++j)
|
||||||
|
h += ((unsigned)cv[i]) << ((j&0x3)*8);
|
||||||
|
|
||||||
|
return h & p->mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Given an id find the value.
|
||||||
|
cmHtValue_t* _cmHtIdToValue( cmHt_t* p, unsigned id )
|
||||||
|
{
|
||||||
|
if( id == cmInvalidId )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
unsigned bi = _cmHtBucketIndex(p,id);
|
||||||
|
|
||||||
|
assert(bi < p->bucketCnt);
|
||||||
|
|
||||||
|
cmHtValue_t* v = p->b[bi].list;
|
||||||
|
for(; v!=NULL; v=v->link)
|
||||||
|
if( v->id == id )
|
||||||
|
return v;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Given a value find the id
|
||||||
|
cmHtValue_t* _cmHtValueToId( cmHt_t* p, const void* value, unsigned byteCnt, unsigned id )
|
||||||
|
{
|
||||||
|
if( id == cmInvalidId )
|
||||||
|
id = _cmHtGenId(p,value,byteCnt);
|
||||||
|
|
||||||
|
unsigned bi = _cmHtBucketIndex(p,id);
|
||||||
|
|
||||||
|
assert(bi < p->bucketCnt);
|
||||||
|
|
||||||
|
cmHtValue_t* v = p->b[bi].list;
|
||||||
|
for(; v!=NULL; v=v->link)
|
||||||
|
if( v->byteCnt==byteCnt && memcmp(value,v->value,byteCnt)==0 )
|
||||||
|
return v;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmHtRC_t _cmHtDestroy( cmHt_t* p )
|
||||||
|
{
|
||||||
|
cmHtRC_t rc = kOkHtRC;
|
||||||
|
cmLHeapDestroy(&p->lhH);
|
||||||
|
cmMemFree(p->b);
|
||||||
|
cmMemFree(p);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmHtRC_t cmHashTblCreate( cmCtx_t* ctx, cmHashTblH_t* hp, unsigned bucketCnt )
|
||||||
|
{
|
||||||
|
cmHtRC_t rc;
|
||||||
|
if((rc = cmHashTblDestroy(hp)) != kOkHtRC )
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
cmHt_t* p = cmMemAllocZ(cmHt_t,1);
|
||||||
|
|
||||||
|
cmErrSetup(&p->err,&ctx->rpt,"hash table");
|
||||||
|
|
||||||
|
if(cmLHeapIsValid(p->lhH = cmLHeapCreate(8192,ctx)) == false )
|
||||||
|
{
|
||||||
|
cmErrMsg(&p->err,kLHeapFailHtRC,"Internal linked heap mgr. create failed.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// force the bucket count to be a power of two
|
||||||
|
p->bucketCnt = cmNextPowerOfTwo(bucketCnt);
|
||||||
|
p->mask = p->bucketCnt - 1;
|
||||||
|
|
||||||
|
// calcluate the hash-id bucket mask
|
||||||
|
for(p->maskShift=0; (0x80000000 & p->mask) == 0; ++p->maskShift )
|
||||||
|
p->mask <<= 1;
|
||||||
|
|
||||||
|
// calculate the maximum collisions per bucket mask
|
||||||
|
p->linkCnt = ~p->mask;
|
||||||
|
|
||||||
|
// allocate the bucket array
|
||||||
|
p->b = cmMemAllocZ(cmHtBucket_t,p->bucketCnt);
|
||||||
|
|
||||||
|
hp->h = p;
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
if( rc != kOkHtRC )
|
||||||
|
_cmHtDestroy(p);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmHtRC_t cmHashTblDestroy( cmHashTblH_t* hp )
|
||||||
|
{
|
||||||
|
cmHtRC_t rc = kOkHtRC;
|
||||||
|
if(hp==NULL || cmHashTblIsValid(*hp)==false )
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
cmHt_t* p = _cmHtHandleToPtr(*hp);
|
||||||
|
|
||||||
|
if((rc = _cmHtDestroy(p)) != kOkHtRC )
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
hp->h = NULL;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cmHashTblIsValid( cmHashTblH_t h )
|
||||||
|
{ return h.h!=NULL; }
|
||||||
|
|
||||||
|
unsigned cmHashTblStoreBase( cmHashTblH_t h, void* v, unsigned byteCnt, bool staticFl )
|
||||||
|
{
|
||||||
|
cmHt_t* p = _cmHtHandleToPtr(h);
|
||||||
|
cmHtValue_t* vp = NULL;
|
||||||
|
unsigned id = _cmHtGenId(p, v, byteCnt );
|
||||||
|
|
||||||
|
// if the value is already stored then there is nothing else to do
|
||||||
|
if((vp = _cmHtValueToId(p,v,byteCnt,id)) != NULL )
|
||||||
|
return vp->id;
|
||||||
|
|
||||||
|
unsigned bi = _cmHtBucketIndex(p,id);
|
||||||
|
|
||||||
|
assert(bi < p->bucketCnt );
|
||||||
|
|
||||||
|
cmHtBucket_t* b = p->b + bi;
|
||||||
|
|
||||||
|
if( b->avail != NULL )
|
||||||
|
{
|
||||||
|
vp = b->avail;
|
||||||
|
b->avail = b->avail->link;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( b->nextIdx == p->linkCnt || (id + b->nextIdx) == cmInvalidId )
|
||||||
|
{
|
||||||
|
cmErrMsg(&p->err,kHashFaultHtRC,"The hash table bucket at index %i is exhaused.",bi);
|
||||||
|
return cmInvalidId;
|
||||||
|
}
|
||||||
|
|
||||||
|
vp = cmLhAllocZ(p->lhH,cmHtValue_t,1);
|
||||||
|
vp->id = id + b->nextIdx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
assert( vp->id != cmInvalidId );
|
||||||
|
|
||||||
|
vp->link = b->list;
|
||||||
|
b->list = vp;
|
||||||
|
vp->byteCnt = byteCnt;
|
||||||
|
|
||||||
|
if( staticFl )
|
||||||
|
vp->value = v;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vp->value = cmLhAlloc(p->lhH,char,byteCnt);
|
||||||
|
memcpy(vp->value,v,byteCnt);
|
||||||
|
vp->flags = cmSetFlag(vp->flags,kFreeHtFl);
|
||||||
|
}
|
||||||
|
|
||||||
|
return vp->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned cmHashTblStore( cmHashTblH_t h, void* v, unsigned byteCnt )
|
||||||
|
{ return cmHashTblStoreBase(h,v,byteCnt,false); }
|
||||||
|
|
||||||
|
unsigned cmHashTblStoreStatic( cmHashTblH_t h, void* v, unsigned byteCnt )
|
||||||
|
{ return cmHashTblStoreBase(h,v,byteCnt,true); }
|
||||||
|
|
||||||
|
unsigned _cmHashTblStoreStr( cmHashTblH_t h, const cmChar_t* s, bool staticFl )
|
||||||
|
{
|
||||||
|
unsigned n = cmTextLength(s);
|
||||||
|
if( n == 0 )
|
||||||
|
{
|
||||||
|
s = "";
|
||||||
|
n = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmHashTblStoreBase(h,(void*)s,n+1,staticFl);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned cmHashTblStoreStr( cmHashTblH_t h, const cmChar_t* s )
|
||||||
|
{ return _cmHashTblStoreStr(h,s,false); }
|
||||||
|
|
||||||
|
unsigned cmhashTblStoreStaticStr( cmHashTblH_t h, const cmChar_t* s )
|
||||||
|
{ return _cmHashTblStoreStr(h,s,true); }
|
||||||
|
|
||||||
|
unsigned cmHashTblStoreV( cmHashTblH_t h, const cmChar_t* fmt, va_list vl )
|
||||||
|
{
|
||||||
|
cmChar_t* s = NULL;
|
||||||
|
s = cmTsVPrintfP(s,fmt,vl);
|
||||||
|
unsigned id = _cmHashTblStoreStr(h,s,false);
|
||||||
|
cmMemFree(s);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned cmHashTblStoreF( cmHashTblH_t h, const cmChar_t* fmt, ... )
|
||||||
|
{
|
||||||
|
va_list vl;
|
||||||
|
va_start(vl,fmt);
|
||||||
|
unsigned id = cmHashTblStoreV(h,fmt,vl);
|
||||||
|
va_end(vl);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned cmHashTblId( cmHashTblH_t h, const void* value, unsigned byteCnt )
|
||||||
|
{
|
||||||
|
cmHt_t* p = _cmHtHandleToPtr(h);
|
||||||
|
cmHtValue_t* vp;
|
||||||
|
|
||||||
|
if((vp = _cmHtValueToId(p,value,byteCnt,cmInvalidId)) == NULL )
|
||||||
|
return cmInvalidId;
|
||||||
|
|
||||||
|
return vp->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned cmHashTblStrToId( cmHashTblH_t h, const cmChar_t* str )
|
||||||
|
{
|
||||||
|
if( str == NULL )
|
||||||
|
return cmInvalidId;
|
||||||
|
|
||||||
|
return cmHashTblId(h,str,cmTextLength(str)+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const void* cmHashTblValue( cmHashTblH_t h, unsigned id, unsigned* byteCntRef )
|
||||||
|
{
|
||||||
|
cmHt_t* p = _cmHtHandleToPtr(h);
|
||||||
|
cmHtValue_t* vp;
|
||||||
|
|
||||||
|
if((vp = _cmHtIdToValue(p, id)) != NULL )
|
||||||
|
{
|
||||||
|
if( byteCntRef != NULL )
|
||||||
|
*byteCntRef = vp->byteCnt;
|
||||||
|
|
||||||
|
return vp->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const cmChar_t* cmHashTblStr( cmHashTblH_t h, unsigned id )
|
||||||
|
{ return (const cmChar_t*)cmHashTblValue(h,id,NULL); }
|
||||||
|
|
||||||
|
|
||||||
|
cmHtRC_t cmHashTblRemove( cmHashTblH_t h, unsigned id )
|
||||||
|
{
|
||||||
|
cmHt_t* p = _cmHtHandleToPtr(h);
|
||||||
|
unsigned bi = _cmHtBucketIndex(p,id);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
assert(bi < p->bucketCnt);
|
||||||
|
|
||||||
|
cmHtBucket_t* b = p->b + bi;
|
||||||
|
|
||||||
|
cmHtValue_t* vp = b->list;
|
||||||
|
cmHtValue_t* pp = NULL;
|
||||||
|
|
||||||
|
for(; vp!=NULL; vp=vp->link)
|
||||||
|
{
|
||||||
|
if( vp->id == id )
|
||||||
|
{
|
||||||
|
if( pp == NULL )
|
||||||
|
b->list = vp->link;
|
||||||
|
else
|
||||||
|
pp->link = vp->link;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pp = vp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( vp == NULL )
|
||||||
|
return cmErrMsg(&p->err,kInvalidIdHtRC,"A value could not be found for the hash id 0x%x.",id);
|
||||||
|
|
||||||
|
if( cmIsFlag(vp->flags,kFreeHtFl ) )
|
||||||
|
cmLhFree(p->lhH,vp->value);
|
||||||
|
|
||||||
|
|
||||||
|
vp->flags = 0;
|
||||||
|
vp->value = NULL;
|
||||||
|
vp->byteCnt = 0;
|
||||||
|
|
||||||
|
// Note: Do not set the id to zero since we want to consert id's
|
||||||
|
// and this recd will be reused by the next call to cmHashTblStoreBase().
|
||||||
|
|
||||||
|
return kOkHtRC;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
cmHtRC_t cmHashTblLastRC( cmHashTblH_t h )
|
||||||
|
{
|
||||||
|
cmHt_t* p = _cmHtHandleToPtr(h);
|
||||||
|
return cmErrLastRC(&p->err);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _cmHashTblBucketReport( cmHtBucket_t* b, cmRpt_t* rpt )
|
||||||
|
{
|
||||||
|
cmHtValue_t* vp = b->list;
|
||||||
|
unsigned i;
|
||||||
|
for(i=0; vp!=NULL && i<10; vp=vp->link,++i)
|
||||||
|
cmRptPrintf(rpt,"0x%x : %s\n",vp->id,((const cmChar_t*)vp->value));
|
||||||
|
|
||||||
|
cmRptPrintf(rpt,"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmHashTblReport( cmHashTblH_t h, cmRpt_t* rpt )
|
||||||
|
{
|
||||||
|
cmHt_t* p = _cmHtHandleToPtr(h);
|
||||||
|
unsigned i;
|
||||||
|
for(i=0; i<p->bucketCnt; ++i)
|
||||||
|
{
|
||||||
|
//if( p->b[i].nextIdx > 0 )
|
||||||
|
// cmRptPrintf(rpt,"%i,%i\n",i,p->b[i].nextIdx);
|
||||||
|
|
||||||
|
if( p->b[i].nextIdx > 100 )
|
||||||
|
_cmHashTblBucketReport(p->b + i,rpt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
cmHtRC_t cmHashTblTest( cmCtx_t* ctx )
|
||||||
|
{
|
||||||
|
cmHtRC_t rc = kOkHtRC;
|
||||||
|
cmHashTblH_t h = cmHashTblNullHandle;
|
||||||
|
cmErr_t err;
|
||||||
|
cmErrSetup(&err,&ctx->rpt,"hash table test");
|
||||||
|
|
||||||
|
if((rc = cmHashTblCreate(ctx,&h,8192)) != kOkHtRC )
|
||||||
|
return cmErrMsg(&err,rc,"Hash table create failed.");
|
||||||
|
|
||||||
|
const cmChar_t* arr[] =
|
||||||
|
{
|
||||||
|
"1",
|
||||||
|
"12",
|
||||||
|
"123",
|
||||||
|
"1234",
|
||||||
|
"12345",
|
||||||
|
"123456",
|
||||||
|
"123456",
|
||||||
|
"123456",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned n = sizeof(arr)/sizeof(arr[0]);
|
||||||
|
unsigned ids[ n ];
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
// store the values from arr[]
|
||||||
|
for(; arr[i]!=NULL; ++i)
|
||||||
|
if((ids[i] = cmHashTblStoreStr(h,arr[i])) == cmInvalidId )
|
||||||
|
{
|
||||||
|
rc = cmErrMsg(&err,cmHashTblLastRC(h),"Hash store failed on: '%s.",cmStringNullGuard(arr[i]));
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// remove a value
|
||||||
|
unsigned rem_idx = 3;
|
||||||
|
if((rc = cmHashTblRemove(h, ids[rem_idx] )) != kOkHtRC )
|
||||||
|
{
|
||||||
|
rc = cmErrMsg(&err,rc,"Hash removed failed.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// insert the same value - which should restore the removed value
|
||||||
|
if((ids[rem_idx] = cmHashTblStoreStr(h,arr[rem_idx])) == cmInvalidId )
|
||||||
|
{
|
||||||
|
rc = cmErrMsg(&err,cmHashTblLastRC(h),"Hash store failed on: '%s.",cmStringNullGuard(arr[rem_idx]));
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// lookup all the stored values by id
|
||||||
|
for(--i; i>=0; --i)
|
||||||
|
{
|
||||||
|
const cmChar_t* s;
|
||||||
|
|
||||||
|
if((s = cmHashTblStr(h,ids[i])) == NULL )
|
||||||
|
rc = cmErrMsg(&err,kInvalidIdHtRC,"The value associated with hash-id:0x%x could not be found.",ids[i]);
|
||||||
|
else
|
||||||
|
printf("%i : %s\n",i,cmStringNullGuard(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for(i=0; arr[i]!=NULL; ++i)
|
||||||
|
{
|
||||||
|
unsigned id = cmHashTblStrToId(h, arr[i]);
|
||||||
|
printf("%i : 0x%x : %s\n",i, id, cmStringNullGuard(cmHashTblStr(h, id)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
cmHashTblReport(h, &ctx->rpt );
|
||||||
|
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
cmHashTblDestroy(&h);
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
}
|
67
cmHashTbl.h
Normal file
67
cmHashTbl.h
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
#ifndef cmHashTbl_h
|
||||||
|
#define cmHashTbl_h
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
kOkHtRC,
|
||||||
|
kLHeapFailHtRC,
|
||||||
|
kHashFaultHtRC,
|
||||||
|
kInvalidIdHtRC
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef cmRC_t cmHtRC_t;
|
||||||
|
typedef cmHandle_t cmHashTblH_t;
|
||||||
|
extern cmHashTblH_t cmHashTblNullHandle;
|
||||||
|
|
||||||
|
cmHtRC_t cmHashTblCreate( cmCtx_t* ctx, cmHashTblH_t* hp, unsigned bucketCnt );
|
||||||
|
|
||||||
|
cmHtRC_t cmHashTblDestroy( cmHashTblH_t* hp );
|
||||||
|
|
||||||
|
bool cmHashTblIsValid( cmHashTblH_t h );
|
||||||
|
|
||||||
|
// cmhashTblStoreBase() is the canonical store function.
|
||||||
|
// Set 'staticFl' to true if the value does not need to be reallocated
|
||||||
|
// and copied into the internal storage space.
|
||||||
|
// Returns a value which uniquely identifies the value. If a unique
|
||||||
|
// identifier cannot be generated then the function returns cmInvalidId
|
||||||
|
// and sets the hash table error code to kHashFaultRC.
|
||||||
|
unsigned cmHashTblStoreBase( cmHashTblH_t h, void* v, unsigned byteCnt, bool staticFl );
|
||||||
|
|
||||||
|
unsigned cmHashTblStore( cmHashTblH_t h, void* v, unsigned byteCnt );
|
||||||
|
unsigned cmHashTblStoreStatic( cmHashTblH_t h, void* v, unsigned byteCnt );
|
||||||
|
unsigned cmHashTblStoreStr( cmHashTblH_t h, const cmChar_t* s );
|
||||||
|
unsigned cmhashTblStoreStaticStr( cmHashTblH_t h, const cmChar_t* s );
|
||||||
|
unsigned cmHashTblStoreV( cmHashTblH_t h, const cmChar_t* fmt, va_list vl );
|
||||||
|
unsigned cmHashTblStoreF( cmHashTblH_t h, const cmChar_t* fmt, ... );
|
||||||
|
|
||||||
|
// Given a value find an id.
|
||||||
|
unsigned cmHashTblId( cmHashTblH_t h, const void* value, unsigned byteCnt );
|
||||||
|
unsigned cmHashTblStrToId( cmHashTblH_t h, const cmChar_t* str );
|
||||||
|
|
||||||
|
// Returns NULL if no value is associated with 'id'.
|
||||||
|
// 'byteCntRef' is optional.
|
||||||
|
const void* cmHashTblValue( cmHashTblH_t h, unsigned id, unsigned* byteCntRef );
|
||||||
|
|
||||||
|
// Wrapper around cmHashTblValue() which assumes that the stored value is a
|
||||||
|
// zero terminated string.
|
||||||
|
const cmChar_t* cmHashTblStr( cmHashTblH_t h, unsigned id );
|
||||||
|
|
||||||
|
// Remove a value.
|
||||||
|
cmHtRC_t cmHashTblRemove( cmHashTblH_t h, unsigned id );
|
||||||
|
|
||||||
|
// Return the last error id generated by the cmHashTbl object.
|
||||||
|
cmHtRC_t cmHashTblLastRC( cmHashTblH_t h );
|
||||||
|
|
||||||
|
void cmHashTblReport( cmHashTblH_t h, cmRpt_t* rpt );
|
||||||
|
|
||||||
|
cmHtRC_t cmHashTblTest( cmCtx_t* ctx );
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
123
cmSyncRecd.c
123
cmSyncRecd.c
@ -11,6 +11,7 @@
|
|||||||
#include "cmSyncRecd.h"
|
#include "cmSyncRecd.h"
|
||||||
#include "cmVectOpsTemplateMain.h"
|
#include "cmVectOpsTemplateMain.h"
|
||||||
#include "cmMidi.h"
|
#include "cmMidi.h"
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
kInvalidSrId,
|
kInvalidSrId,
|
||||||
@ -76,44 +77,44 @@ cmSr_t* _cmSrHtoP( cmSyncRecdH_t h )
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
cmSrRC_t _cmSrWriteCache( cmSr_t* p )
|
cmSyRC_t _cmSrWriteCache( cmSr_t* p )
|
||||||
{
|
{
|
||||||
if( cmFileWrite(p->fH,p->cache,p->ci * sizeof(cmSrRecd_t)) != kOkFileRC )
|
if( cmFileWrite(p->fH,p->cache,p->ci * sizeof(cmSrRecd_t)) != kOkFileRC )
|
||||||
return cmErrMsg(&p->err,kFileFailSrRC,"File write failed.");
|
return cmErrMsg(&p->err,kFileFailSyRC,"File write failed.");
|
||||||
|
|
||||||
p->fn += p->ci;
|
p->fn += p->ci;
|
||||||
p->ci = 0;
|
p->ci = 0;
|
||||||
|
|
||||||
return kOkSrRC;
|
return kOkSyRC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
cmSrRC_t _cmSrFinal( cmSr_t* p )
|
cmSyRC_t _cmSrFinal( cmSr_t* p )
|
||||||
{
|
{
|
||||||
cmSrRC_t rc = kOkSrRC;
|
cmSyRC_t rc = kOkSyRC;
|
||||||
|
|
||||||
// write any remaining cache records
|
// write any remaining cache records
|
||||||
if( cmIsFlag(p->flags,kReadSrFl) == false )
|
if( cmIsFlag(p->flags,kReadSrFl) == false )
|
||||||
{
|
{
|
||||||
if((rc = _cmSrWriteCache(p)) == kOkSrRC )
|
if((rc = _cmSrWriteCache(p)) == kOkSyRC )
|
||||||
{
|
{
|
||||||
if(cmFileSeek(p->fH,kBeginFileFl,p->offs) != kOkFileRC )
|
if(cmFileSeek(p->fH,kBeginFileFl,p->offs) != kOkFileRC )
|
||||||
rc = cmErrMsg(&p->err,kFileFailSrRC, "File seek fail on file offset positioning.");
|
rc = cmErrMsg(&p->err,kFileFailSyRC, "File seek fail on file offset positioning.");
|
||||||
else
|
else
|
||||||
if(cmFileWriteUInt(p->fH,&p->fn,1) != kOkFileRC )
|
if(cmFileWriteUInt(p->fH,&p->fn,1) != kOkFileRC )
|
||||||
rc = cmErrMsg(&p->err,kFileFailSrRC, "File write failed on record count.");
|
rc = cmErrMsg(&p->err,kFileFailSyRC, "File write failed on record count.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// release the audio file object
|
// release the audio file object
|
||||||
if( cmAudioFileIsValid(p->afH) )
|
if( cmAudioFileIsValid(p->afH) )
|
||||||
if( cmAudioFileDelete(&p->afH) != kOkAfRC )
|
if( cmAudioFileDelete(&p->afH) != kOkAfRC )
|
||||||
return cmErrMsg(&p->err,kAudioFileFailSrRC,"Audio file object delete failed.");
|
return cmErrMsg(&p->err,kAudioFileFailSyRC,"Audio file object delete failed.");
|
||||||
|
|
||||||
// release the sync-recd file object
|
// release the sync-recd file object
|
||||||
if( cmFileIsValid(p->fH) )
|
if( cmFileIsValid(p->fH) )
|
||||||
if( cmFileClose(&p->fH) != kOkFileRC )
|
if( cmFileClose(&p->fH) != kOkFileRC )
|
||||||
return cmErrMsg(&p->err,kFileFailSrRC,"File close failed.");
|
return cmErrMsg(&p->err,kFileFailSyRC,"File close failed.");
|
||||||
|
|
||||||
cmMemFree(p->cache);
|
cmMemFree(p->cache);
|
||||||
cmMemFree(p->map);
|
cmMemFree(p->map);
|
||||||
@ -134,27 +135,27 @@ cmSr_t* _cmSrAlloc( cmCtx_t* ctx, unsigned flags )
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
cmSrRC_t cmSyncRecdCreate( cmCtx_t* ctx, cmSyncRecdH_t* hp, const cmChar_t* srFn, const cmChar_t* audioFn, double srate, unsigned chCnt, unsigned bits )
|
cmSyRC_t cmSyncRecdCreate( cmCtx_t* ctx, cmSyncRecdH_t* hp, const cmChar_t* srFn, const cmChar_t* audioFn, double srate, unsigned chCnt, unsigned bits )
|
||||||
{
|
{
|
||||||
cmSrRC_t rc = kOkSrRC;
|
cmSyRC_t rc = kOkSyRC;
|
||||||
cmRC_t afRC = kOkAfRC;
|
cmRC_t afRC = kOkAfRC;
|
||||||
|
|
||||||
assert( audioFn != NULL );
|
assert( audioFn != NULL );
|
||||||
|
|
||||||
if((rc = cmSyncRecdFinal(hp)) != kOkSrRC )
|
if((rc = cmSyncRecdFinal(hp)) != kOkSyRC )
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
cmSr_t* p = _cmSrAlloc(ctx,0);
|
cmSr_t* p = _cmSrAlloc(ctx,0);
|
||||||
|
|
||||||
if( cmFileOpen(&p->fH,srFn,kWriteFileFl,&ctx->rpt) != kOkFileRC )
|
if( cmFileOpen(&p->fH,srFn,kWriteFileFl,&ctx->rpt) != kOkFileRC )
|
||||||
{
|
{
|
||||||
rc = cmErrMsg(&p->err,kFileFailSrRC,"Unable to create the sync-recd file '%s'.",cmStringNullGuard(srFn));
|
rc = cmErrMsg(&p->err,kFileFailSyRC,"Unable to create the sync-recd file '%s'.",cmStringNullGuard(srFn));
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( cmAudioFileIsValid(p->afH = cmAudioFileNewCreate(audioFn,srate,bits,chCnt,&afRC,&ctx->rpt))==false)
|
if( cmAudioFileIsValid(p->afH = cmAudioFileNewCreate(audioFn,srate,bits,chCnt,&afRC,&ctx->rpt))==false)
|
||||||
{
|
{
|
||||||
rc = cmErrMsg(&p->err,kAudioFileFailSrRC,"Unable to create the sync-recd audio file '%s'.",cmStringNullGuard(audioFn));
|
rc = cmErrMsg(&p->err,kAudioFileFailSyRC,"Unable to create the sync-recd audio file '%s'.",cmStringNullGuard(audioFn));
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,47 +164,47 @@ cmSrRC_t cmSyncRecdCreate( cmCtx_t* ctx, cmSyncRecdH_t* hp, const cmChar_t* srFn
|
|||||||
|
|
||||||
if( cmFileWriteUInt(p->fH,&fileUUId,1) != kOkFileRC )
|
if( cmFileWriteUInt(p->fH,&fileUUId,1) != kOkFileRC )
|
||||||
{
|
{
|
||||||
rc = cmErrMsg(&p->err,kFileFailSrRC,"File write failed on UUID.");
|
rc = cmErrMsg(&p->err,kFileFailSyRC,"File write failed on UUID.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( cmFileWriteUInt(p->fH,&audioFnCnt,1) != kOkFileRC )
|
if( cmFileWriteUInt(p->fH,&audioFnCnt,1) != kOkFileRC )
|
||||||
{
|
{
|
||||||
rc = cmErrMsg(&p->err,kFileFailSrRC,"File write failed on audio file length write count.");
|
rc = cmErrMsg(&p->err,kFileFailSyRC,"File write failed on audio file length write count.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( cmFileWriteChar(p->fH,audioFn,audioFnCnt) != kOkFileRC )
|
if( cmFileWriteChar(p->fH,audioFn,audioFnCnt) != kOkFileRC )
|
||||||
{
|
{
|
||||||
rc = cmErrMsg(&p->err,kFileFailSrRC,"File write failed on audio file string.");
|
rc = cmErrMsg(&p->err,kFileFailSyRC,"File write failed on audio file string.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( cmFileTell(p->fH,&p->offs) != kOkFileRC )
|
if( cmFileTell(p->fH,&p->offs) != kOkFileRC )
|
||||||
{
|
{
|
||||||
rc = cmErrMsg(&p->err,kFileFailSrRC,"Unable to determine file offset.");
|
rc = cmErrMsg(&p->err,kFileFailSyRC,"Unable to determine file offset.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( cmFileWriteUInt(p->fH,&p->fn,1) != kOkFileRC )
|
if( cmFileWriteUInt(p->fH,&p->fn,1) != kOkFileRC )
|
||||||
{
|
{
|
||||||
rc = cmErrMsg(&p->err,kFileFailSrRC,"File write failed on initial record count.");
|
rc = cmErrMsg(&p->err,kFileFailSyRC,"File write failed on initial record count.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
hp->h = p;
|
hp->h = p;
|
||||||
|
|
||||||
errLabel:
|
errLabel:
|
||||||
if( rc != kOkSrRC )
|
if( rc != kOkSyRC )
|
||||||
_cmSrFinal(p);
|
_cmSrFinal(p);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
cmSrRC_t cmSyncRecdOpen( cmCtx_t* ctx, cmSyncRecdH_t* hp, const cmChar_t* srFn )
|
cmSyRC_t cmSyncRecdOpen( cmCtx_t* ctx, cmSyncRecdH_t* hp, const cmChar_t* srFn )
|
||||||
{
|
{
|
||||||
cmSrRC_t rc = kOkSrRC;
|
cmSyRC_t rc = kOkSyRC;
|
||||||
cmRC_t afRC = kOkAfRC;
|
cmRC_t afRC = kOkAfRC;
|
||||||
unsigned fileUUId = cmInvalidId;
|
unsigned fileUUId = cmInvalidId;
|
||||||
unsigned audioFnCnt = 0;
|
unsigned audioFnCnt = 0;
|
||||||
@ -213,26 +214,26 @@ cmSrRC_t cmSyncRecdOpen( cmCtx_t* ctx, cmSyncRecdH_t* hp, const cmChar_t* srFn
|
|||||||
unsigned mcnt = 0;
|
unsigned mcnt = 0;
|
||||||
unsigned* tiV = NULL;
|
unsigned* tiV = NULL;
|
||||||
|
|
||||||
if((rc = cmSyncRecdFinal(hp)) != kOkSrRC )
|
if((rc = cmSyncRecdFinal(hp)) != kOkSyRC )
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
cmSr_t* p = _cmSrAlloc(ctx,kReadSrFl);
|
cmSr_t* p = _cmSrAlloc(ctx,kReadSrFl);
|
||||||
|
|
||||||
if( cmFileOpen(&p->fH,srFn,kReadFileFl,&ctx->rpt) != kOkFileRC )
|
if( cmFileOpen(&p->fH,srFn,kReadFileFl,&ctx->rpt) != kOkFileRC )
|
||||||
{
|
{
|
||||||
rc = cmErrMsg(&p->err,kFileFailSrRC,"Unable to open the sync-recd file '%s'.",cmStringNullGuard(srFn));
|
rc = cmErrMsg(&p->err,kFileFailSyRC,"Unable to open the sync-recd file '%s'.",cmStringNullGuard(srFn));
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( cmFileReadUInt(p->fH,&fileUUId,1) != kOkFileRC )
|
if( cmFileReadUInt(p->fH,&fileUUId,1) != kOkFileRC )
|
||||||
{
|
{
|
||||||
rc = cmErrMsg(&p->err,kFileFailSrRC,"File read failed on UUId.");
|
rc = cmErrMsg(&p->err,kFileFailSyRC,"File read failed on UUId.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( cmFileReadUInt(p->fH,&audioFnCnt,1) != kOkFileRC )
|
if( cmFileReadUInt(p->fH,&audioFnCnt,1) != kOkFileRC )
|
||||||
{
|
{
|
||||||
rc = cmErrMsg(&p->err,kFileFailSrRC,"File read failed on audio file name count.");
|
rc = cmErrMsg(&p->err,kFileFailSyRC,"File read failed on audio file name count.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,20 +241,20 @@ cmSrRC_t cmSyncRecdOpen( cmCtx_t* ctx, cmSyncRecdH_t* hp, const cmChar_t* srFn
|
|||||||
|
|
||||||
if( cmFileReadChar(p->fH,audioFn,audioFnCnt) != kOkFileRC )
|
if( cmFileReadChar(p->fH,audioFn,audioFnCnt) != kOkFileRC )
|
||||||
{
|
{
|
||||||
rc = cmErrMsg(&p->err,kFileFailSrRC,"File read failed on audio file string.");
|
rc = cmErrMsg(&p->err,kFileFailSyRC,"File read failed on audio file string.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( cmFileReadUInt(p->fH,&p->fn,1) != kOkFileRC )
|
if( cmFileReadUInt(p->fH,&p->fn,1) != kOkFileRC )
|
||||||
{
|
{
|
||||||
rc = cmErrMsg(&p->err,kFileFailSrRC,"File read failed on record count.");
|
rc = cmErrMsg(&p->err,kFileFailSyRC,"File read failed on record count.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
// store the file offset to the first recd
|
// store the file offset to the first recd
|
||||||
if( cmFileTell(p->fH,&p->offs) != kOkFileRC )
|
if( cmFileTell(p->fH,&p->offs) != kOkFileRC )
|
||||||
{
|
{
|
||||||
rc = cmErrMsg(&p->err,kFileFailSrRC,"Unable to determine the current file offset.");
|
rc = cmErrMsg(&p->err,kFileFailSyRC,"Unable to determine the current file offset.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,7 +265,7 @@ cmSrRC_t cmSyncRecdOpen( cmCtx_t* ctx, cmSyncRecdH_t* hp, const cmChar_t* srFn
|
|||||||
cmSrRecd_t r;
|
cmSrRecd_t r;
|
||||||
if( cmFileRead(p->fH,&r,sizeof(r)) != kOkFileRC )
|
if( cmFileRead(p->fH,&r,sizeof(r)) != kOkFileRC )
|
||||||
{
|
{
|
||||||
rc = cmErrMsg(&p->err,kFileFailSrRC,"Unable to read the record at index %i.");
|
rc = cmErrMsg(&p->err,kFileFailSyRC,"Unable to read the record at index %i.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -288,7 +289,7 @@ cmSrRC_t cmSyncRecdOpen( cmCtx_t* ctx, cmSyncRecdH_t* hp, const cmChar_t* srFn
|
|||||||
// rewind to the begining of the records
|
// rewind to the begining of the records
|
||||||
if( cmFileSeek(p->fH,kBeginFileFl,p->offs) != kOkFileRC )
|
if( cmFileSeek(p->fH,kBeginFileFl,p->offs) != kOkFileRC )
|
||||||
{
|
{
|
||||||
rc = cmErrMsg(&p->err,kFileFailSrRC,"Unable to seek to first recd offset.");
|
rc = cmErrMsg(&p->err,kFileFailSyRC,"Unable to seek to first recd offset.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,7 +304,7 @@ cmSrRC_t cmSyncRecdOpen( cmCtx_t* ctx, cmSyncRecdH_t* hp, const cmChar_t* srFn
|
|||||||
{
|
{
|
||||||
if( cmFileRead(p->fH,p->cache + p->ci,sizeof(cmSrRecd_t)) != kOkFileRC )
|
if( cmFileRead(p->fH,p->cache + p->ci,sizeof(cmSrRecd_t)) != kOkFileRC )
|
||||||
{
|
{
|
||||||
rc = cmErrMsg(&p->err,kFileFailSrRC,"Unable to read the record at index %i.");
|
rc = cmErrMsg(&p->err,kFileFailSyRC,"Unable to read the record at index %i.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -317,7 +318,7 @@ cmSrRC_t cmSyncRecdOpen( cmCtx_t* ctx, cmSyncRecdH_t* hp, const cmChar_t* srFn
|
|||||||
// rewind to the first recd
|
// rewind to the first recd
|
||||||
if( cmFileSeek(p->fH,kBeginFileFl,p->offs) != kOkFileRC )
|
if( cmFileSeek(p->fH,kBeginFileFl,p->offs) != kOkFileRC )
|
||||||
{
|
{
|
||||||
rc = cmErrMsg(&p->err,kFileFailSrRC,"Unable to seek to first recd offset.");
|
rc = cmErrMsg(&p->err,kFileFailSyRC,"Unable to seek to first recd offset.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -328,7 +329,7 @@ cmSrRC_t cmSyncRecdOpen( cmCtx_t* ctx, cmSyncRecdH_t* hp, const cmChar_t* srFn
|
|||||||
cmSrRecd_t r;
|
cmSrRecd_t r;
|
||||||
if( cmFileRead(p->fH,&r,sizeof(r)) != kOkFileRC )
|
if( cmFileRead(p->fH,&r,sizeof(r)) != kOkFileRC )
|
||||||
{
|
{
|
||||||
rc = cmErrMsg(&p->err,kFileFailSrRC,"Unable to read the record at index %i.");
|
rc = cmErrMsg(&p->err,kFileFailSyRC,"Unable to read the record at index %i.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -358,7 +359,7 @@ cmSrRC_t cmSyncRecdOpen( cmCtx_t* ctx, cmSyncRecdH_t* hp, const cmChar_t* srFn
|
|||||||
// open the audio file
|
// open the audio file
|
||||||
if( cmAudioFileIsValid(p->afH = cmAudioFileNewOpen(audioFn,&p->afInfo,&afRC,&ctx->rpt ))==false)
|
if( cmAudioFileIsValid(p->afH = cmAudioFileNewOpen(audioFn,&p->afInfo,&afRC,&ctx->rpt ))==false)
|
||||||
{
|
{
|
||||||
rc = cmErrMsg(&p->err,kAudioFileFailSrRC,"Unable to open the sync-recd audio file '%s'.",cmStringNullGuard(audioFn));
|
rc = cmErrMsg(&p->err,kAudioFileFailSyRC,"Unable to open the sync-recd audio file '%s'.",cmStringNullGuard(audioFn));
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -371,22 +372,22 @@ cmSrRC_t cmSyncRecdOpen( cmCtx_t* ctx, cmSyncRecdH_t* hp, const cmChar_t* srFn
|
|||||||
cmMemFree(tiV);
|
cmMemFree(tiV);
|
||||||
cmMemFree(audioFn);
|
cmMemFree(audioFn);
|
||||||
|
|
||||||
if( rc != kOkSrRC )
|
if( rc != kOkSyRC )
|
||||||
_cmSrFinal(p);
|
_cmSrFinal(p);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
cmSrRC_t cmSyncRecdFinal( cmSyncRecdH_t* hp )
|
cmSyRC_t cmSyncRecdFinal( cmSyncRecdH_t* hp )
|
||||||
{
|
{
|
||||||
cmSrRC_t rc = kOkSrRC;
|
cmSyRC_t rc = kOkSyRC;
|
||||||
|
|
||||||
if( hp==NULL || cmSyncRecdIsValid(*hp)==false)
|
if( hp==NULL || cmSyncRecdIsValid(*hp)==false)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
cmSr_t* p = _cmSrHtoP(*hp);
|
cmSr_t* p = _cmSrHtoP(*hp);
|
||||||
|
|
||||||
if((rc = _cmSrFinal(p)) != kOkSrRC )
|
if((rc = _cmSrFinal(p)) != kOkSyRC )
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
hp->h = NULL;
|
hp->h = NULL;
|
||||||
@ -397,9 +398,9 @@ cmSrRC_t cmSyncRecdFinal( cmSyncRecdH_t* hp )
|
|||||||
bool cmSyncRecdIsValid( cmSyncRecdH_t h )
|
bool cmSyncRecdIsValid( cmSyncRecdH_t h )
|
||||||
{ return h.h != NULL; }
|
{ return h.h != NULL; }
|
||||||
|
|
||||||
cmSrRC_t cmSyncRecdMidiWrite( cmSyncRecdH_t h, const cmTimeSpec_t* timestamp, unsigned status, unsigned d0, unsigned d1 )
|
cmSyRC_t cmSyncRecdMidiWrite( cmSyncRecdH_t h, const cmTimeSpec_t* timestamp, unsigned status, unsigned d0, unsigned d1 )
|
||||||
{
|
{
|
||||||
cmSrRC_t rc = kOkSrRC;
|
cmSyRC_t rc = kOkSyRC;
|
||||||
cmSr_t* p = _cmSrHtoP(h);
|
cmSr_t* p = _cmSrHtoP(h);
|
||||||
cmSrRecd_t* rp = p->cache + p->ci;
|
cmSrRecd_t* rp = p->cache + p->ci;
|
||||||
rp->tid = kMidiSrId;
|
rp->tid = kMidiSrId;
|
||||||
@ -416,9 +417,9 @@ cmSrRC_t cmSyncRecdMidiWrite( cmSyncRecdH_t h, const cmTimeSpec_t* timestamp, u
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
cmSrRC_t cmSyncRecdAudioWrite( cmSyncRecdH_t h, const cmTimeSpec_t* timestamp, unsigned smpIdx, const cmSample_t* ch[], unsigned chCnt, unsigned frmCnt )
|
cmSyRC_t cmSyncRecdAudioWrite( cmSyncRecdH_t h, const cmTimeSpec_t* timestamp, unsigned smpIdx, const cmSample_t* ch[], unsigned chCnt, unsigned frmCnt )
|
||||||
{
|
{
|
||||||
cmSrRC_t rc = kOkSrRC;
|
cmSyRC_t rc = kOkSyRC;
|
||||||
cmSr_t* p = _cmSrHtoP(h);
|
cmSr_t* p = _cmSrHtoP(h);
|
||||||
cmSrRecd_t* rp = p->cache + p->ci;
|
cmSrRecd_t* rp = p->cache + p->ci;
|
||||||
rp->tid = kAudioSrId;
|
rp->tid = kAudioSrId;
|
||||||
@ -428,25 +429,25 @@ cmSrRC_t cmSyncRecdAudioWrite( cmSyncRecdH_t h, const cmTimeSpec_t* timestamp, u
|
|||||||
p->ci += 1;
|
p->ci += 1;
|
||||||
|
|
||||||
if( p->ci == p->cn )
|
if( p->ci == p->cn )
|
||||||
if((rc = _cmSrWriteCache(p)) != kOkSrRC )
|
if((rc = _cmSrWriteCache(p)) != kOkSyRC )
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
|
|
||||||
if( cmAudioFileWriteSample(p->afH,frmCnt,chCnt,(cmSample_t**)ch) != kOkAfRC )
|
if( cmAudioFileWriteSample(p->afH,frmCnt,chCnt,(cmSample_t**)ch) != kOkAfRC )
|
||||||
rc = cmErrMsg(&p->err,kAudioFileFailSrRC,"Audio file write failed.");
|
rc = cmErrMsg(&p->err,kAudioFileFailSyRC,"Audio file write failed.");
|
||||||
|
|
||||||
errLabel:
|
errLabel:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
cmSrRC_t cmSyncRecdPrint( cmSyncRecdH_t h )
|
cmSyRC_t cmSyncRecdPrint( cmSyncRecdH_t h )
|
||||||
{
|
{
|
||||||
cmSrRC_t rc = kOkSrRC;
|
cmSyRC_t rc = kOkSyRC;
|
||||||
cmSr_t* p = _cmSrHtoP(h);
|
cmSr_t* p = _cmSrHtoP(h);
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
if( cmIsFlag(p->flags,kReadSrFl)==false)
|
if( cmIsFlag(p->flags,kReadSrFl)==false)
|
||||||
return cmErrMsg(&p->err,kInvalidOpSrRC,"The 'print' operation is only valid on sync-recd files opened for reading.");
|
return cmErrMsg(&p->err,kInvalidOpSyRC,"The 'print' operation is only valid on sync-recd files opened for reading.");
|
||||||
|
|
||||||
for(i=0; i<p->cn; ++i)
|
for(i=0; i<p->cn; ++i)
|
||||||
{
|
{
|
||||||
@ -457,9 +458,9 @@ cmSrRC_t cmSyncRecdPrint( cmSyncRecdH_t h )
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
cmSrRC_t cmSyncRecdAudioFile( cmSyncRecdH_t h, const cmChar_t* fn )
|
cmSyRC_t cmSyncRecdAudioFile( cmSyncRecdH_t h, const cmChar_t* fn )
|
||||||
{
|
{
|
||||||
cmSrRC_t rc = kOkSrRC;
|
cmSyRC_t rc = kOkSyRC;
|
||||||
cmSr_t* p = _cmSrHtoP(h);
|
cmSr_t* p = _cmSrHtoP(h);
|
||||||
cmAudioFileH_t afH = cmNullAudioFileH;
|
cmAudioFileH_t afH = cmNullAudioFileH;
|
||||||
unsigned chCnt = 2;
|
unsigned chCnt = 2;
|
||||||
@ -474,19 +475,19 @@ cmSrRC_t cmSyncRecdAudioFile( cmSyncRecdH_t h, const cmChar_t* fn )
|
|||||||
chs[1] = buf+frmCnt;
|
chs[1] = buf+frmCnt;
|
||||||
|
|
||||||
if( cmIsFlag(p->flags,kReadSrFl)==false)
|
if( cmIsFlag(p->flags,kReadSrFl)==false)
|
||||||
return cmErrMsg(&p->err,kInvalidOpSrRC,"The 'audio-file-output' operation is only valid on sync-recd files opened for reading.");
|
return cmErrMsg(&p->err,kInvalidOpSyRC,"The 'audio-file-output' operation is only valid on sync-recd files opened for reading.");
|
||||||
|
|
||||||
/// Open an audio file for writing
|
/// Open an audio file for writing
|
||||||
if(cmAudioFileIsValid(afH = cmAudioFileNewCreate(fn, p->afInfo.srate, p->afInfo.bits, chCnt, &afRC, p->err.rpt))==false)
|
if(cmAudioFileIsValid(afH = cmAudioFileNewCreate(fn, p->afInfo.srate, p->afInfo.bits, chCnt, &afRC, p->err.rpt))==false)
|
||||||
{
|
{
|
||||||
rc = cmErrMsg(&p->err,kAudioFileFailSrRC,"Unable to create the synchronized audio file '%s'.",cmStringNullGuard(fn));
|
rc = cmErrMsg(&p->err,kAudioFileFailSyRC,"Unable to create the synchronized audio file '%s'.",cmStringNullGuard(fn));
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
// rewind the input audio file
|
// rewind the input audio file
|
||||||
if( cmAudioFileSeek(p->afH,0) != kOkAfRC )
|
if( cmAudioFileSeek(p->afH,0) != kOkAfRC )
|
||||||
{
|
{
|
||||||
rc = cmErrMsg(&p->err,kAudioFileFailSrRC,"Seek failed during synchronized audio file output.");
|
rc = cmErrMsg(&p->err,kAudioFileFailSyRC,"Seek failed during synchronized audio file output.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -500,7 +501,7 @@ cmSrRC_t cmSyncRecdAudioFile( cmSyncRecdH_t h, const cmChar_t* fn )
|
|||||||
// read frmCnt samples from the first channel of the input audio file
|
// read frmCnt samples from the first channel of the input audio file
|
||||||
if( cmAudioFileReadSample(p->afH, frmCnt, chIdx, 1, chs, &actFrmCnt ) != kOkAfRC )
|
if( cmAudioFileReadSample(p->afH, frmCnt, chIdx, 1, chs, &actFrmCnt ) != kOkAfRC )
|
||||||
{
|
{
|
||||||
rc = cmErrMsg(&p->err,kAudioFileFailSrRC,"Audio file read failed.");
|
rc = cmErrMsg(&p->err,kAudioFileFailSyRC,"Audio file read failed.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -515,7 +516,7 @@ cmSrRC_t cmSyncRecdAudioFile( cmSyncRecdH_t h, const cmChar_t* fn )
|
|||||||
// write the audio output samples
|
// write the audio output samples
|
||||||
if( cmAudioFileWriteSample(afH, frmCnt, chCnt, chs ) != kOkAfRC )
|
if( cmAudioFileWriteSample(afH, frmCnt, chCnt, chs ) != kOkAfRC )
|
||||||
{
|
{
|
||||||
rc = cmErrMsg(&p->err,kAudioFileFailSrRC,"Synchronized audio file write failed.");
|
rc = cmErrMsg(&p->err,kAudioFileFailSyRC,"Synchronized audio file write failed.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -523,12 +524,12 @@ cmSrRC_t cmSyncRecdAudioFile( cmSyncRecdH_t h, const cmChar_t* fn )
|
|||||||
|
|
||||||
errLabel:
|
errLabel:
|
||||||
if( cmAudioFileDelete(&afH) != kOkAfRC )
|
if( cmAudioFileDelete(&afH) != kOkAfRC )
|
||||||
rc = cmErrMsg(&p->err,kAudioFileFailSrRC,"Synchronized audio file close failed.");
|
rc = cmErrMsg(&p->err,kAudioFileFailSyRC,"Synchronized audio file close failed.");
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
cmSrRC_t cmSyncRecdTest( cmCtx_t* ctx )
|
cmSyRC_t cmSyncRecdTest( cmCtx_t* ctx )
|
||||||
{
|
{
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
@ -536,7 +537,7 @@ cmSrRC_t cmSyncRecdTest( cmCtx_t* ctx )
|
|||||||
kTestFailRC,
|
kTestFailRC,
|
||||||
};
|
};
|
||||||
|
|
||||||
cmSrRC_t rc = kOkSrRC;
|
cmSyRC_t rc = kOkSyRC;
|
||||||
const cmChar_t* srFn = "/home/kevin/temp/kr/sr/sr0.sr";
|
const cmChar_t* srFn = "/home/kevin/temp/kr/sr/sr0.sr";
|
||||||
const cmChar_t* aFn = "/home/kevin/temp/kr/sr/sync_af.aiff";
|
const cmChar_t* aFn = "/home/kevin/temp/kr/sr/sync_af.aiff";
|
||||||
cmErr_t err;
|
cmErr_t err;
|
||||||
@ -545,7 +546,7 @@ cmSrRC_t cmSyncRecdTest( cmCtx_t* ctx )
|
|||||||
cmErrSetup(&err,&ctx->rpt,"SyncRecdTest");
|
cmErrSetup(&err,&ctx->rpt,"SyncRecdTest");
|
||||||
|
|
||||||
|
|
||||||
if((rc = cmSyncRecdOpen(ctx, &srH, srFn )) != kOkSrRC )
|
if((rc = cmSyncRecdOpen(ctx, &srH, srFn )) != kOkSyRC )
|
||||||
{
|
{
|
||||||
cmErrMsg(&err,kTestFailRC,"Sync-recd open failed.");
|
cmErrMsg(&err,kTestFailRC,"Sync-recd open failed.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
@ -555,7 +556,7 @@ cmSrRC_t cmSyncRecdTest( cmCtx_t* ctx )
|
|||||||
cmSyncRecdAudioFile(srH,aFn);
|
cmSyncRecdAudioFile(srH,aFn);
|
||||||
|
|
||||||
errLabel:
|
errLabel:
|
||||||
if((rc = cmSyncRecdFinal(&srH)) != kOkSrRC )
|
if((rc = cmSyncRecdFinal(&srH)) != kOkSyRC )
|
||||||
cmErrMsg(&err,kTestFailRC,"Sync-recd close failed.");
|
cmErrMsg(&err,kTestFailRC,"Sync-recd close failed.");
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
22
cmSyncRecd.h
22
cmSyncRecd.h
@ -7,26 +7,26 @@ extern "C" {
|
|||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
kOkSrRC,
|
kOkSyRC,
|
||||||
kFileFailSrRC,
|
kFileFailSyRC,
|
||||||
kAudioFileFailSrRC,
|
kAudioFileFailSyRC,
|
||||||
kInvalidOpSrRC
|
kInvalidOpSyRC
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef cmHandle_t cmSyncRecdH_t;
|
typedef cmHandle_t cmSyncRecdH_t;
|
||||||
typedef cmRC_t cmSrRC_t;
|
typedef cmRC_t cmSyRC_t;
|
||||||
extern cmSyncRecdH_t cmSyncRecdNullHandle;
|
extern cmSyncRecdH_t cmSyncRecdNullHandle;
|
||||||
|
|
||||||
cmSrRC_t cmSyncRecdCreate( cmCtx_t* ctx, cmSyncRecdH_t* hp, const cmChar_t* srFn, const cmChar_t* audioFn, double srate, unsigned chCnt, unsigned bits );
|
cmSyRC_t cmSyncRecdCreate( cmCtx_t* ctx, cmSyncRecdH_t* hp, const cmChar_t* srFn, const cmChar_t* audioFn, double srate, unsigned chCnt, unsigned bits );
|
||||||
cmSrRC_t cmSyncRecdOpen( cmCtx_t* ctx, cmSyncRecdH_t* hp, const cmChar_t* srFn );
|
cmSyRC_t cmSyncRecdOpen( cmCtx_t* ctx, cmSyncRecdH_t* hp, const cmChar_t* srFn );
|
||||||
cmSrRC_t cmSyncRecdFinal( cmSyncRecdH_t* hp );
|
cmSyRC_t cmSyncRecdFinal( cmSyncRecdH_t* hp );
|
||||||
bool cmSyncRecdIsValid( cmSyncRecdH_t h );
|
bool cmSyncRecdIsValid( cmSyncRecdH_t h );
|
||||||
|
|
||||||
cmSrRC_t cmSyncRecdMidiWrite( cmSyncRecdH_t h, const cmTimeSpec_t* timestamp, unsigned status, unsigned d0, unsigned d1 );
|
cmSyRC_t cmSyncRecdMidiWrite( cmSyncRecdH_t h, const cmTimeSpec_t* timestamp, unsigned status, unsigned d0, unsigned d1 );
|
||||||
cmSrRC_t cmSyncRecdAudioWrite( cmSyncRecdH_t h, const cmTimeSpec_t* timestamp, unsigned smpIdx, const cmSample_t* ch[], unsigned chCnt, unsigned frmCnt );
|
cmSyRC_t cmSyncRecdAudioWrite( cmSyncRecdH_t h, const cmTimeSpec_t* timestamp, unsigned smpIdx, const cmSample_t* ch[], unsigned chCnt, unsigned frmCnt );
|
||||||
|
|
||||||
|
|
||||||
cmSrRC_t cmSyncRecdTest( cmCtx_t* ctx );
|
cmSyRC_t cmSyncRecdTest( cmCtx_t* ctx );
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -2383,7 +2383,7 @@ cmDspRC_t _cmDspNanoMapSend( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned st, un
|
|||||||
|
|
||||||
void _cmDspNanoMapPgm( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned pgm )
|
void _cmDspNanoMapPgm( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned pgm )
|
||||||
{
|
{
|
||||||
cmDspNanoMap_t* p = (cmDspNanoMap_t*)inst;
|
//cmDspNanoMap_t* p = (cmDspNanoMap_t*)inst;
|
||||||
|
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
@ -2430,7 +2430,7 @@ cmDspRC_t _cmDspNanoMapReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_
|
|||||||
|
|
||||||
cmDspRC_t _cmDspNanoMapRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
|
cmDspRC_t _cmDspNanoMapRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
|
||||||
{
|
{
|
||||||
cmDspNanoMap_t* p = (cmDspNanoMap_t*)inst;
|
//cmDspNanoMap_t* p = (cmDspNanoMap_t*)inst;
|
||||||
|
|
||||||
switch( evt->dstVarId )
|
switch( evt->dstVarId )
|
||||||
{
|
{
|
||||||
@ -3070,7 +3070,7 @@ cmDspRC_t _cmDspSyncRecdCreateFile( cmDspCtx_t* ctx, cmDspInst_t* inst )
|
|||||||
return cmDspInstErr(ctx,&p->inst,kFileSysFailDspRC,"Sync-recd file name generation failed for dir='%s' and prefix='%s'.",cmStringNullGuard(dir),cmStringNullGuard(srFn));
|
return cmDspInstErr(ctx,&p->inst,kFileSysFailDspRC,"Sync-recd file name generation failed for dir='%s' and prefix='%s'.",cmStringNullGuard(dir),cmStringNullGuard(srFn));
|
||||||
|
|
||||||
unsigned bits = cmDspUInt(inst,kBitsSrId);
|
unsigned bits = cmDspUInt(inst,kBitsSrId);
|
||||||
if( cmSyncRecdCreate( ctx->cmCtx, &p->srH, p->srFn, p->aFn, cmDspSampleRate(ctx), p->chCnt, bits ) != kOkSrRC )
|
if( cmSyncRecdCreate( ctx->cmCtx, &p->srH, p->srFn, p->aFn, cmDspSampleRate(ctx), p->chCnt, bits ) != kOkSyRC )
|
||||||
return cmDspInstErr(ctx,&p->inst,kSubSysFailDspRC,"Sync-recd file create failed for '%s'.",p->srFn);
|
return cmDspInstErr(ctx,&p->inst,kSubSysFailDspRC,"Sync-recd file create failed for '%s'.",p->srFn);
|
||||||
|
|
||||||
p->smpIdx = 0;
|
p->smpIdx = 0;
|
||||||
@ -3152,7 +3152,7 @@ cmDspRC_t _cmDspSyncRecdExec(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_
|
|||||||
}
|
}
|
||||||
|
|
||||||
if( n>0 && cmSyncRecdIsValid(p->srH ) )
|
if( n>0 && cmSyncRecdIsValid(p->srH ) )
|
||||||
if( cmSyncRecdAudioWrite( p->srH, &ctx->ctx->iTimeStamp, p->smpIdx, x, p->chCnt, n ) != kOkSrRC )
|
if( cmSyncRecdAudioWrite( p->srH, &ctx->ctx->iTimeStamp, p->smpIdx, x, p->chCnt, n ) != kOkSyRC )
|
||||||
return cmDspInstErr(ctx,&p->inst,kSubSysFailDspRC,"Sync-recd audio update failed.");
|
return cmDspInstErr(ctx,&p->inst,kSubSysFailDspRC,"Sync-recd audio update failed.");
|
||||||
|
|
||||||
p->smpIdx += n;
|
p->smpIdx += n;
|
||||||
@ -3179,7 +3179,7 @@ cmDspRC_t _cmDspSyncRecdRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_
|
|||||||
//printf("%i %i\n",cmDspUInt(inst,kD1SrId),cmTimeElapsedMicros(&ts,&p->ats));
|
//printf("%i %i\n",cmDspUInt(inst,kD1SrId),cmTimeElapsedMicros(&ts,&p->ats));
|
||||||
|
|
||||||
if( cmSyncRecdIsValid(p->srH ) )
|
if( cmSyncRecdIsValid(p->srH ) )
|
||||||
if( cmSyncRecdMidiWrite(p->srH, &ts, cmDspUInt(inst,kStatusSrId), cmDspUInt(inst,kD0SrId), cmDspUInt(inst,kD1SrId) ) != kOkSrRC )
|
if( cmSyncRecdMidiWrite(p->srH, &ts, cmDspUInt(inst,kStatusSrId), cmDspUInt(inst,kD0SrId), cmDspUInt(inst,kD1SrId) ) != kOkSyRC )
|
||||||
return cmDspInstErr(ctx,&p->inst,kSubSysFailDspRC,"Sync-recd MIDI update failed.");
|
return cmDspInstErr(ctx,&p->inst,kSubSysFailDspRC,"Sync-recd MIDI update failed.");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user