Merge branch 'master' of klarke.webfactional.com:webapps/git/repos/libcm

This commit is contained in:
kevin 2014-01-25 16:19:34 -05:00
commit 6d317d54ca
10 changed files with 1535 additions and 104 deletions

View File

@ -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
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
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
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/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
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
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
cmSRC += src/libcm/app/cmPickup.c src/libcm/cmRbm.c src/libcm/cmTaskMgr.c src/libcm/cmSyncRecd.c

724
app/cmSdb.c Normal file
View 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
View 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
View File

@ -7,7 +7,7 @@
#include "cmMallocDebug.h"
#include "cmLex.h"
#include "cmLinkedHeap.h"
#include "cmSymTbl.h"
#include "cmHashTbl.h"
#include "cmCsv.h"
#include "cmText.h"
@ -48,9 +48,9 @@ typedef struct cmCsvUdef_str
typedef struct
{
cmErr_t err;
void* rptDataPtr; //
cmLexH lexH; // parsing lexer
cmSymTblH_t symTblH; // all XML identifiers and data is stored as a symbol in this table
void* rptDataPtr; //
cmLexH lexH; // parsing lexer
cmHashTblH_t htH; // hash table handle
cmLHeapH_t heapH;
cmCsvBind_t* bindPtr; // base of the binder linked list
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");
// create the symbol table
if( cmSymTblIsValid(p->symTblH = cmSymTblCreate(cmSymTblNullHandle,0,ctx)) == false )
// create the hash table
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;
}
// 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.");
goto errLabel;
@ -161,8 +161,8 @@ cmCsvRC_t cmCsvFinalize( cmCsvH_t *hp )
if((lexRC = cmLexFinal(&p->lexH)) != kOkLexRC )
return _cmCsvError(p,kLexErrCsvRC,"Lexer finalization failed.\nLexer Error:%s",cmLexRcToMsg(lexRC));
// free the symbol table
cmSymTblDestroy(&p->symTblH);
// free the hash table
cmHashTblDestroy(&p->htH);
// free the handle
cmMemPtrFree(&hp->h);
@ -352,8 +352,8 @@ cmCsvRC_t _cmCsvCreateCell( cmCsv_t* p, const char* tokenText, unsigned flags, u
cmCsvRC_t rc = kOkCsvRC;
// register the token text as a symbol
if((symId = cmSymTblRegisterSymbol(p->symTblH,tokenText)) == cmInvalidId )
return _cmCsvError(p,kSymTblErrCsvRC,"Symbol registration failed. for '%s' on line %i column %i.",tokenText,lexRow,lexCol);
if((symId = cmHashTblStoreStr(p->htH,tokenText)) == cmInvalidId )
return _cmCsvError(p,kHashTblErrCsvRC,"Symbol registration failed. for '%s' on line %i column %i.",tokenText,lexRow,lexCol);
// allocate a cell
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);
const char* cp;
if((cp = cmSymTblLabel(p->symTblH,symId)) == NULL )
_cmCsvError(p,kSymTblErrCsvRC,"The text associated with the symbol '%i' was not found.",symId);
if((cp = cmHashTblStr(p->htH,symId)) == NULL )
_cmCsvError(p,kHashTblErrCsvRC,"The text associated with the symbol '%i' was not found.",symId);
return cp;
}
@ -573,7 +573,7 @@ cmCsvRC_t cmCsvCellSymInt( cmCsvH_t h, unsigned symId, int* vp )
cmCsv_t* p = _cmCsvHandleToPtr(h);
if((cp = cmCsvCellSymText(h,symId)) == NULL )
return kSymTblErrCsvRC;
return kHashTblErrCsvRC;
if( cmTextToInt(cp,vp,&p->err) != kOkTxRC )
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);
if((cp = cmCsvCellSymText(h,symId)) == NULL )
return kSymTblErrCsvRC;
return kHashTblErrCsvRC;
if( cmTextToUInt(cp,vp,&p->err) != kOkTxRC )
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);
if((cp = cmCsvCellSymText(h,symId)) == NULL )
return kSymTblErrCsvRC;
return kHashTblErrCsvRC;
if( cmTextToFloat(cp,vp,&p->err) != kOkTxRC )
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);
if((cp = cmCsvCellSymText(h,symId)) == NULL )
return kSymTblErrCsvRC;
return kHashTblErrCsvRC;
if( cmTextToDouble(cp,vp,&p->err) != kOkTxRC )
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);
unsigned symId;
if((symId = cmSymTblRegisterSymbol(p->symTblH,text)) == cmInvalidId )
_cmCsvError(p,kSymTblErrCsvRC,"'%s' could not be inserted into the symbol table.",text);
if((symId = cmHashTblStoreStr(p->htH,text)) == cmInvalidId )
_cmCsvError(p,kHashTblErrCsvRC,"'%s' could not be inserted into the symbol table.",text);
return symId;
}
@ -1134,8 +1134,8 @@ cmCsvRC_t cmCsvWrite( cmCsvH_t h, const char* fn )
{
const char* tp;
if((tp = cmSymTblLabel(p->symTblH,cp->symId)) == NULL )
return _cmCsvError(p,kSymTblErrCsvRC,"Unable to locate the symbol text for cell at row:%i col:%i.",cp->row,cp->col);
if((tp = cmHashTblStr(p->htH,cp->symId)) == NULL )
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) )
fprintf(fp,"\"");
@ -1179,8 +1179,8 @@ cmCsvRC_t cmCsvPrint( cmCsvH_t h, unsigned rowCnt )
{
const char* tp;
if((tp = cmSymTblLabel(p->symTblH,cp->symId)) == NULL )
_cmCsvError(p,kSymTblErrCsvRC,"The text associated with the symbol '%i' was not found.",cp->symId);
if((tp = cmHashTblStr(p->htH,cp->symId)) == NULL )
_cmCsvError(p,kHashTblErrCsvRC,"The text associated with the symbol '%i' was not found.",cp->symId);
fputs(tp,stdin);
}

View File

@ -11,7 +11,7 @@ extern "C" {
kOkCsvRC = 0,
kMemAllocErrCsvRC,
kLexErrCsvRC,
kSymTblErrCsvRC,
kHashTblErrCsvRC,
kSyntaxErrCsvRC,
kFileOpenErrCsvRC,
kFileCreateErrCsvRC,

464
cmHashTbl.c Normal file
View 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
View 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

View File

@ -11,6 +11,7 @@
#include "cmSyncRecd.h"
#include "cmVectOpsTemplateMain.h"
#include "cmMidi.h"
typedef enum
{
kInvalidSrId,
@ -76,44 +77,44 @@ cmSr_t* _cmSrHtoP( cmSyncRecdH_t h )
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 )
return cmErrMsg(&p->err,kFileFailSrRC,"File write failed.");
return cmErrMsg(&p->err,kFileFailSyRC,"File write failed.");
p->fn += p->ci;
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
if( cmIsFlag(p->flags,kReadSrFl) == false )
{
if((rc = _cmSrWriteCache(p)) == kOkSrRC )
if((rc = _cmSrWriteCache(p)) == kOkSyRC )
{
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
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
if( cmAudioFileIsValid(p->afH) )
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
if( cmFileIsValid(p->fH) )
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->map);
@ -134,27 +135,27 @@ cmSr_t* _cmSrAlloc( cmCtx_t* ctx, unsigned flags )
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;
assert( audioFn != NULL );
if((rc = cmSyncRecdFinal(hp)) != kOkSrRC )
if((rc = cmSyncRecdFinal(hp)) != kOkSyRC )
return rc;
cmSr_t* p = _cmSrAlloc(ctx,0);
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;
}
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;
}
@ -163,47 +164,47 @@ cmSrRC_t cmSyncRecdCreate( cmCtx_t* ctx, cmSyncRecdH_t* hp, const cmChar_t* srFn
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;
}
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;
}
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;
}
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;
}
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;
}
hp->h = p;
errLabel:
if( rc != kOkSrRC )
if( rc != kOkSyRC )
_cmSrFinal(p);
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;
unsigned fileUUId = cmInvalidId;
unsigned audioFnCnt = 0;
@ -213,26 +214,26 @@ cmSrRC_t cmSyncRecdOpen( cmCtx_t* ctx, cmSyncRecdH_t* hp, const cmChar_t* srFn
unsigned mcnt = 0;
unsigned* tiV = NULL;
if((rc = cmSyncRecdFinal(hp)) != kOkSrRC )
if((rc = cmSyncRecdFinal(hp)) != kOkSyRC )
return rc;
cmSr_t* p = _cmSrAlloc(ctx,kReadSrFl);
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;
}
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;
}
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;
}
@ -240,20 +241,20 @@ cmSrRC_t cmSyncRecdOpen( cmCtx_t* ctx, cmSyncRecdH_t* hp, const cmChar_t* srFn
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;
}
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;
}
// store the file offset to the first recd
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;
}
@ -264,7 +265,7 @@ cmSrRC_t cmSyncRecdOpen( cmCtx_t* ctx, cmSyncRecdH_t* hp, const cmChar_t* srFn
cmSrRecd_t r;
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;
}
@ -288,7 +289,7 @@ cmSrRC_t cmSyncRecdOpen( cmCtx_t* ctx, cmSyncRecdH_t* hp, const cmChar_t* srFn
// rewind to the begining of the records
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;
}
@ -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 )
{
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;
}
@ -317,7 +318,7 @@ cmSrRC_t cmSyncRecdOpen( cmCtx_t* ctx, cmSyncRecdH_t* hp, const cmChar_t* srFn
// rewind to the first recd
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;
}
@ -328,7 +329,7 @@ cmSrRC_t cmSyncRecdOpen( cmCtx_t* ctx, cmSyncRecdH_t* hp, const cmChar_t* srFn
cmSrRecd_t r;
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;
}
@ -358,7 +359,7 @@ cmSrRC_t cmSyncRecdOpen( cmCtx_t* ctx, cmSyncRecdH_t* hp, const cmChar_t* srFn
// open the audio file
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;
}
@ -371,22 +372,22 @@ cmSrRC_t cmSyncRecdOpen( cmCtx_t* ctx, cmSyncRecdH_t* hp, const cmChar_t* srFn
cmMemFree(tiV);
cmMemFree(audioFn);
if( rc != kOkSrRC )
if( rc != kOkSyRC )
_cmSrFinal(p);
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)
return rc;
cmSr_t* p = _cmSrHtoP(*hp);
if((rc = _cmSrFinal(p)) != kOkSrRC )
if((rc = _cmSrFinal(p)) != kOkSyRC )
return rc;
hp->h = NULL;
@ -397,9 +398,9 @@ cmSrRC_t cmSyncRecdFinal( cmSyncRecdH_t* hp )
bool cmSyncRecdIsValid( cmSyncRecdH_t h )
{ 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);
cmSrRecd_t* rp = p->cache + p->ci;
rp->tid = kMidiSrId;
@ -416,9 +417,9 @@ cmSrRC_t cmSyncRecdMidiWrite( cmSyncRecdH_t h, const cmTimeSpec_t* timestamp, u
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);
cmSrRecd_t* rp = p->cache + p->ci;
rp->tid = kAudioSrId;
@ -428,25 +429,25 @@ cmSrRC_t cmSyncRecdAudioWrite( cmSyncRecdH_t h, const cmTimeSpec_t* timestamp, u
p->ci += 1;
if( p->ci == p->cn )
if((rc = _cmSrWriteCache(p)) != kOkSrRC )
if((rc = _cmSrWriteCache(p)) != kOkSyRC )
goto errLabel;
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:
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);
unsigned i;
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)
{
@ -457,9 +458,9 @@ cmSrRC_t cmSyncRecdPrint( cmSyncRecdH_t h )
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);
cmAudioFileH_t afH = cmNullAudioFileH;
unsigned chCnt = 2;
@ -474,19 +475,19 @@ cmSrRC_t cmSyncRecdAudioFile( cmSyncRecdH_t h, const cmChar_t* fn )
chs[1] = buf+frmCnt;
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
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;
}
// rewind the input audio file
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;
}
@ -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
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;
}
@ -515,7 +516,7 @@ cmSrRC_t cmSyncRecdAudioFile( cmSyncRecdH_t h, const cmChar_t* fn )
// write the audio output samples
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;
}
@ -523,12 +524,12 @@ cmSrRC_t cmSyncRecdAudioFile( cmSyncRecdH_t h, const cmChar_t* fn )
errLabel:
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;
}
cmSrRC_t cmSyncRecdTest( cmCtx_t* ctx )
cmSyRC_t cmSyncRecdTest( cmCtx_t* ctx )
{
enum
{
@ -536,7 +537,7 @@ cmSrRC_t cmSyncRecdTest( cmCtx_t* ctx )
kTestFailRC,
};
cmSrRC_t rc = kOkSrRC;
cmSyRC_t rc = kOkSyRC;
const cmChar_t* srFn = "/home/kevin/temp/kr/sr/sr0.sr";
const cmChar_t* aFn = "/home/kevin/temp/kr/sr/sync_af.aiff";
cmErr_t err;
@ -545,7 +546,7 @@ cmSrRC_t cmSyncRecdTest( cmCtx_t* ctx )
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.");
goto errLabel;
@ -555,7 +556,7 @@ cmSrRC_t cmSyncRecdTest( cmCtx_t* ctx )
cmSyncRecdAudioFile(srH,aFn);
errLabel:
if((rc = cmSyncRecdFinal(&srH)) != kOkSrRC )
if((rc = cmSyncRecdFinal(&srH)) != kOkSyRC )
cmErrMsg(&err,kTestFailRC,"Sync-recd close failed.");
return rc;

View File

@ -7,26 +7,26 @@ extern "C" {
enum
{
kOkSrRC,
kFileFailSrRC,
kAudioFileFailSrRC,
kInvalidOpSrRC
kOkSyRC,
kFileFailSyRC,
kAudioFileFailSyRC,
kInvalidOpSyRC
};
typedef cmHandle_t cmSyncRecdH_t;
typedef cmRC_t cmSrRC_t;
typedef cmRC_t cmSyRC_t;
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 );
cmSrRC_t cmSyncRecdOpen( cmCtx_t* ctx, cmSyncRecdH_t* hp, const cmChar_t* srFn );
cmSrRC_t cmSyncRecdFinal( cmSyncRecdH_t* hp );
cmSyRC_t cmSyncRecdCreate( cmCtx_t* ctx, cmSyncRecdH_t* hp, const cmChar_t* srFn, const cmChar_t* audioFn, double srate, unsigned chCnt, unsigned bits );
cmSyRC_t cmSyncRecdOpen( cmCtx_t* ctx, cmSyncRecdH_t* hp, const cmChar_t* srFn );
cmSyRC_t cmSyncRecdFinal( cmSyncRecdH_t* hp );
bool cmSyncRecdIsValid( cmSyncRecdH_t h );
cmSrRC_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 cmSyncRecdMidiWrite( cmSyncRecdH_t h, const cmTimeSpec_t* timestamp, unsigned status, unsigned d0, unsigned d1 );
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
}

View File

@ -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 )
{
cmDspNanoMap_t* p = (cmDspNanoMap_t*)inst;
//cmDspNanoMap_t* p = (cmDspNanoMap_t*)inst;
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 )
{
cmDspNanoMap_t* p = (cmDspNanoMap_t*)inst;
//cmDspNanoMap_t* p = (cmDspNanoMap_t*)inst;
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));
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);
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( 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.");
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));
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.");
}
break;