Merge branch 'master' of klarke.webfactional.com:webapps/gitweb/repos/libcm
This commit is contained in:
commit
e426f5dbd1
2
.gitignore
vendored
2
.gitignore
vendored
@ -1 +1,3 @@
|
||||
Makefile.in
|
||||
.DS_Store
|
||||
|
||||
|
@ -112,6 +112,14 @@ void _cmMsf_ReportMidiErrors( const _cmMsf_ScoreFollow_t* f, cmScH_t scH, const
|
||||
}
|
||||
}
|
||||
|
||||
void _cmMsf_WriteMatchFileHeader( cmFileH_t fH )
|
||||
{
|
||||
cmFilePrintf(fH," Score Score Score MIDI MIDI MIDI\n");
|
||||
cmFilePrintf(fH," Bar UUID Pitch UUID Ptch Vel.\n");
|
||||
cmFilePrintf(fH,"- ----- ----- ----- ----- ---- ----\n");
|
||||
}
|
||||
|
||||
|
||||
// Write one scScoreMatcherResult_t record to the file fH.
|
||||
unsigned _cmMsf_WriteMatchFileLine( cmFileH_t fH, cmScH_t scH, const cmScMatcherResult_t* r )
|
||||
{
|
||||
@ -130,7 +138,7 @@ unsigned _cmMsf_WriteMatchFileLine( cmFileH_t fH, cmScH_t scH, const cmScMatcher
|
||||
cmMidiToSciPitch(e->pitch,buf,5);
|
||||
}
|
||||
|
||||
cmFilePrintf(fH,"m %3i %5i %4s %5i %4s %3i\n",
|
||||
cmFilePrintf(fH,"m %5i %5i %5s %5i %4s %3i\n",
|
||||
loc==NULL ? 0 : loc->barNumb, // score evt bar
|
||||
scUid, // score event uuid
|
||||
buf, // score event pitch
|
||||
@ -147,17 +155,17 @@ void _cmMsf_ScoreFollowCb( struct cmScMatcher_str* p, void* arg, cmScMatcherResu
|
||||
r->rV[r->rN++] = *rp;
|
||||
}
|
||||
|
||||
cmMsfRC_t cmMidiScoreFollowMain( cmCtx_t* ctx )
|
||||
cmMsfRC_t cmMidiScoreFollowMain(
|
||||
cmCtx_t* ctx,
|
||||
const cmChar_t* scoreCsvFn, // score CSV file as generated from cmXScoreTest().
|
||||
const cmChar_t* midiFn, // MIDI file to track
|
||||
const cmChar_t* matchRptOutFn, // Score follow status report
|
||||
const cmChar_t* matchSvgOutFn, // Score follow graphic report
|
||||
const cmChar_t* midiOutFn, // (optional) midiFn with apply sostenuto and velocities from the score to the MIDI file
|
||||
const cmChar_t* tlBarOutFn // (optional) bar positions sutiable for use in a cmTimeLine description file.
|
||||
)
|
||||
{
|
||||
cmMsfRC_t rc = kOkMsfRC;
|
||||
//const cmChar_t* scoreFn = cmFsMakeUserDirFn("src/kc/src/kc/data","mod2e.csv");
|
||||
const cmChar_t* scoreFn = cmFsMakeUserDirFn("temp","a7.csv");
|
||||
const cmChar_t* midiFn = cmFsMakeUserDirFn("media/projects/imag_themes/scores/gen","round1-utf8_11.mid");
|
||||
const cmChar_t* outFn = cmFsMakeUserDirFn("temp","match.txt");
|
||||
const cmChar_t* svgFn = cmFsMakeUserDirFn("temp","score0.html");
|
||||
const cmChar_t* newMidiFn= cmFsMakeUserDirFn("temp","a7.mid");
|
||||
const cmChar_t* tlBarFn = cmFsMakeUserDirFn("temp","time_line_temp.txt");
|
||||
|
||||
cmMsfRC_t rc = kOkMsfRC;
|
||||
double srate = 96000.0;
|
||||
cmScMatcher* smp = NULL;
|
||||
cmScH_t scH = cmScNullHandle;
|
||||
@ -179,16 +187,16 @@ cmMsfRC_t cmMidiScoreFollowMain( cmCtx_t* ctx )
|
||||
cmCtx* prCtx = cmCtxAlloc(NULL, err.rpt, cmLHeapNullHandle, cmSymTblNullHandle );
|
||||
|
||||
// initialize the score
|
||||
if( cmScoreInitialize( ctx, &scH, scoreFn, srate, NULL, 0, NULL, NULL, cmSymTblNullHandle) != kOkScRC )
|
||||
if( cmScoreInitialize( ctx, &scH, scoreCsvFn, srate, NULL, 0, NULL, NULL, cmSymTblNullHandle) != kOkScRC )
|
||||
{
|
||||
rc = cmErrMsg(&err,kFailMsfRC,"cmScoreInitialize() failed on %s",cmStringNullGuard(scoreFn));
|
||||
rc = cmErrMsg(&err,kFailMsfRC,"cmScoreInitialize() failed on %s",cmStringNullGuard(scoreCsvFn));
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// setup the callback record
|
||||
if((sfr.rAllocN = cmScoreEvtCount( scH )*2) == 0)
|
||||
{
|
||||
rc = cmErrMsg(&err,kFailMsfRC,"The score %s appears to be empty.",cmStringNullGuard(scoreFn));
|
||||
rc = cmErrMsg(&err,kFailMsfRC,"The score %s appears to be empty.",cmStringNullGuard(scoreCsvFn));
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
@ -229,19 +237,21 @@ cmMsfRC_t cmMidiScoreFollowMain( cmCtx_t* ctx )
|
||||
printf("MIDI notes:%i Score Events:%i\n",mN,cmScoreEvtCount(scH));
|
||||
|
||||
// create the output file
|
||||
if( cmFileOpen(&fH,outFn,kWriteFileFl,&ctx->rpt) != kOkFileRC )
|
||||
if( cmFileOpen(&fH,matchRptOutFn,kWriteFileFl,&ctx->rpt) != kOkFileRC )
|
||||
{
|
||||
rc = cmErrMsg(&err,kFailMsfRC,"Unable to create the file '%s'.",cmStringNullGuard(outFn));
|
||||
rc = cmErrMsg(&err,kFailMsfRC,"Unable to create the file '%s'.",cmStringNullGuard(matchRptOutFn));
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// allocate the graphics object
|
||||
if( cmScoreMatchGraphicAlloc( ctx, &smgH, scoreFn, midiFn ) != kOkSmgRC )
|
||||
if( cmScoreMatchGraphicAlloc( ctx, &smgH, scoreCsvFn, midiFn ) != kOkSmgRC )
|
||||
{
|
||||
rc = cmErrMsg(&err,kFailMsfRC,"Score Match Graphics allocation failed..");
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// write the match report output file header
|
||||
_cmMsf_WriteMatchFileHeader(fH);
|
||||
|
||||
// for each score follower callback record
|
||||
for(i=0; i<sfr.rN; ++i)
|
||||
@ -267,12 +277,14 @@ cmMsfRC_t cmMidiScoreFollowMain( cmCtx_t* ctx )
|
||||
//cmMidiFilePrintMsgs( mfH, &ctx->rpt );
|
||||
|
||||
// write the tracking match file as an SVG file.
|
||||
cmScoreMatchGraphicWrite( smgH, svgFn );
|
||||
cmScoreMatchGraphicWrite( smgH, matchSvgOutFn );
|
||||
|
||||
// write a cmTimeLine file which contains markers at each bar position
|
||||
cmScoreMatchGraphicGenTimeLineBars(smgH, tlBarFn, srate );
|
||||
if( tlBarOutFn != NULL )
|
||||
cmScoreMatchGraphicGenTimeLineBars(smgH, tlBarOutFn, srate );
|
||||
|
||||
cmScoreMatchGraphicUpdateMidiFromScore( ctx, smgH, newMidiFn );
|
||||
if( midiOutFn != NULL )
|
||||
cmScoreMatchGraphicUpdateMidiFromScore( ctx, smgH, midiOutFn );
|
||||
|
||||
|
||||
errLabel:
|
||||
@ -286,12 +298,12 @@ cmMsfRC_t cmMidiScoreFollowMain( cmCtx_t* ctx )
|
||||
|
||||
cmCtxFree(&prCtx);
|
||||
|
||||
cmFsFreeFn(scoreFn);
|
||||
cmFsFreeFn(midiFn);
|
||||
cmFsFreeFn(outFn);
|
||||
cmFsFreeFn(svgFn);
|
||||
cmFsFreeFn(newMidiFn);
|
||||
cmFsFreeFn(tlBarFn);
|
||||
//cmFsFreeFn(scoreCsvFn);
|
||||
//cmFsFreeFn(midiFn);
|
||||
//cmFsFreeFn(matchRptOutFn);
|
||||
//cmFsFreeFn(matchSvgOutFn);
|
||||
//cmFsFreeFn(outMidiFn);
|
||||
//cmFsFreeFn(tlBarFn);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -15,7 +15,15 @@ extern "C" {
|
||||
typedef cmRC_t cmMsfRC_t;
|
||||
|
||||
|
||||
cmMsfRC_t cmMidiScoreFollowMain( cmCtx_t* ctx );
|
||||
cmMsfRC_t cmMidiScoreFollowMain(
|
||||
cmCtx_t* ctx,
|
||||
const cmChar_t* scoreCsvFn, // score CSV file as generated from cmXScoreTest().
|
||||
const cmChar_t* midiFn, // MIDI file to track
|
||||
const cmChar_t* matchRptOutFn, // Score follow status report
|
||||
const cmChar_t* matchSvgOutFn, // Score follow graphic report
|
||||
const cmChar_t* midiOutFn, // (optional) midiFn with apply sostenuto and velocities from the score to the MIDI file
|
||||
const cmChar_t* tlBarOutFn // (optional) bar positions sutiable for use in a cmTimeLine description file.
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -154,15 +154,16 @@ cmScEvtRef_t _cmScEvtRefArray[] =
|
||||
|
||||
cmScEvtRef_t _cmScDynRefArray[] =
|
||||
{
|
||||
{ 1, 0, "pppp"},
|
||||
{ 2, 0, "ppp" },
|
||||
{ 3, 0, "pp" },
|
||||
{ 4, 0, "p" },
|
||||
{ 5, 0, "mp" },
|
||||
{ 6, 0, "mf" },
|
||||
{ 7, 0, "f" },
|
||||
{ 8, 0, "ff" },
|
||||
{ 9, 0, "fff" },
|
||||
{ 1, 0, "silent"},
|
||||
{ 2, 0, "pppp"},
|
||||
{ 3, 0, "ppp" },
|
||||
{ 4, 0, "pp" },
|
||||
{ 5, 0, "p" },
|
||||
{ 6, 0, "mp" },
|
||||
{ 7, 0, "mf" },
|
||||
{ 8, 0, "f" },
|
||||
{ 9, 0, "ff" },
|
||||
{ 10, 0, "fff" },
|
||||
{ kInvalidDynScId,0, "***" },
|
||||
};
|
||||
|
||||
@ -361,6 +362,22 @@ void _cmScFreeMarkList( cmScMark_t* markList )
|
||||
}
|
||||
}
|
||||
|
||||
void _cmScFreeSectList( cmSc_t* p )
|
||||
{
|
||||
|
||||
// release the section linked list
|
||||
cmScSect_t* sp = p->sectList;
|
||||
cmScSect_t* np = NULL;
|
||||
while(sp!=NULL)
|
||||
{
|
||||
np = sp->link;
|
||||
cmMemFree(sp);
|
||||
sp = np;
|
||||
}
|
||||
|
||||
p->sectList = NULL;
|
||||
}
|
||||
|
||||
void _cmScFreeSetList( cmScSet_t* setList )
|
||||
{
|
||||
cmScSet_t* tp = setList;
|
||||
@ -412,6 +429,8 @@ cmScRC_t _cmScFinalize( cmSc_t* p )
|
||||
cmMemFree(p->sets);
|
||||
}
|
||||
|
||||
_cmScFreeSectList( p );
|
||||
|
||||
_cmScFreeSetList(p->setList);
|
||||
|
||||
_cmScFreeMarkList(p->markList);
|
||||
@ -1124,9 +1143,10 @@ cmScRC_t _cmScProcSets( cmSc_t* p )
|
||||
|
||||
|
||||
|
||||
cmScRC_t _cmScProcSections( cmSc_t* p, cmScSect_t* sectList )
|
||||
cmScRC_t _cmScProcSections( cmSc_t* p )
|
||||
{
|
||||
cmScRC_t rc = kOkScRC;
|
||||
cmScSect_t* sectList = p->sectList;
|
||||
unsigned i;
|
||||
|
||||
// count the sections
|
||||
@ -1171,15 +1191,8 @@ cmScRC_t _cmScProcSections( cmSc_t* p, cmScSect_t* sectList )
|
||||
}
|
||||
}
|
||||
|
||||
// release the section linked list
|
||||
sp = sectList;
|
||||
cmScSect_t* np = NULL;
|
||||
while(sp!=NULL)
|
||||
{
|
||||
np = sp->link;
|
||||
cmMemFree(sp);
|
||||
sp = np;
|
||||
}
|
||||
|
||||
_cmScFreeSectList(p);
|
||||
|
||||
//_cmScPrintSets("Sets",p->setList );
|
||||
|
||||
@ -1592,7 +1605,7 @@ cmScRC_t cmScoreInitialize( cmCtx_t* ctx, cmScH_t* hp, const cmChar_t* fn, doubl
|
||||
if((rc = _cmScInitLocArray(p)) != kOkScRC )
|
||||
goto errLabel;
|
||||
|
||||
if((rc = _cmScProcSections(p,p->sectList)) != kOkScRC )
|
||||
if((rc = _cmScProcSections(p)) != kOkScRC )
|
||||
goto errLabel;
|
||||
|
||||
if((rc = _cmScProcMarkers(p)) != kOkScRC )
|
||||
@ -2409,6 +2422,16 @@ cmScRC_t cmScoreDecode( const void* msg, unsigned msgByteCnt, cmScMsg_t* m)
|
||||
return kOkScRC;
|
||||
}
|
||||
|
||||
const cmChar_t* _cmScoreSectionLabel( cmSc_t* p, const cmScoreEvt_t* r )
|
||||
{
|
||||
unsigned i;
|
||||
for(i=0; i<p->sectCnt; ++i)
|
||||
if( p->sect[i].locPtr != NULL && p->sect[i].locPtr->index == r->locIdx && p->sect[i].begEvtIndex == r->index )
|
||||
return p->sect[i].label;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void _cmScorePrintHdr( cmRpt_t* rpt )
|
||||
{
|
||||
cmRptPrintf(rpt,"evnt CSV bar\n");
|
||||
@ -2416,12 +2439,13 @@ void _cmScorePrintHdr( cmRpt_t* rpt )
|
||||
cmRptPrintf(rpt,"----- ----- ----- --- --- ----- ----- --- -------\n");
|
||||
}
|
||||
|
||||
void _cmScorePrintEvent( const cmScoreEvt_t* r, unsigned i, cmRpt_t* rpt )
|
||||
void _cmScorePrintEvent( cmSc_t* p, const cmScoreEvt_t* r, unsigned i, cmRpt_t* rpt )
|
||||
{
|
||||
bool eolFl = true;
|
||||
switch(r->type)
|
||||
{
|
||||
case kBarEvtScId:
|
||||
cmRptPrintf(rpt,"%5i %5i %3i bar\n",
|
||||
cmRptPrintf(rpt,"%5i %5i %3i bar ",
|
||||
i,
|
||||
r->line,
|
||||
r->barNumb );
|
||||
@ -2429,7 +2453,7 @@ void _cmScorePrintEvent( const cmScoreEvt_t* r, unsigned i, cmRpt_t* rpt )
|
||||
|
||||
case kPedalEvtScId:
|
||||
case kNonEvtScId:
|
||||
cmRptPrintf(rpt,"%5i %5i %5i %3i %3i %s %5s %c%c%c %s\n",
|
||||
cmRptPrintf(rpt,"%5i %5i %5i %3i %3i %s %5s %c%c%c %-7s ",
|
||||
i,
|
||||
r->line,
|
||||
r->locIdx,
|
||||
@ -2440,13 +2464,21 @@ void _cmScorePrintEvent( const cmScoreEvt_t* r, unsigned i, cmRpt_t* rpt )
|
||||
cmIsFlag(r->flags,kEvenScFl) ? 'e' : ' ',
|
||||
cmIsFlag(r->flags,kTempoScFl) ? 't' : ' ',
|
||||
cmIsFlag(r->flags,kDynScFl) ? 'd' : ' ',
|
||||
//cmIsFlag(r->flags,kDynScFl) ? 7-strlen(cmScDynIdToLabel(r->dynVal)) : 7,
|
||||
cmIsFlag(r->flags,kDynScFl) ? cmScDynIdToLabel(r->dynVal) : "");
|
||||
break;
|
||||
|
||||
default:
|
||||
eolFl = false;
|
||||
break;
|
||||
}
|
||||
|
||||
const cmChar_t* sectionLabel;
|
||||
if((sectionLabel = _cmScoreSectionLabel(p,r)) != NULL )
|
||||
cmRptPrintf(rpt,"section:%s ",sectionLabel);
|
||||
|
||||
cmRptPrintf(rpt,"\n");
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -2458,7 +2490,7 @@ void cmScorePrint( cmScH_t h, cmRpt_t* rpt )
|
||||
_cmScorePrintHdr(rpt);
|
||||
|
||||
for(i=0; i<p->cnt; ++i)
|
||||
_cmScorePrintEvent(p->array+i,i,rpt);
|
||||
_cmScorePrintEvent(p,p->array+i,i,rpt);
|
||||
}
|
||||
|
||||
|
||||
@ -2483,7 +2515,7 @@ void cmScorePrintSets( cmScH_t h, cmRpt_t* rpt )
|
||||
|
||||
_cmScorePrintHdr(rpt);
|
||||
for(j=0; j<s->eleCnt; ++j)
|
||||
_cmScorePrintEvent(*s->eleArray+j,j,rpt);
|
||||
_cmScorePrintEvent(p,*s->eleArray+j,j,rpt);
|
||||
|
||||
cmRptPrintf(rpt,"Targets Section: ");
|
||||
for(j=0; j<s->sectCnt; ++j)
|
||||
@ -2709,7 +2741,7 @@ cmScRC_t cmScoreFileFromMidi( cmCtx_t* ctx, const cmChar_t* midiFn, const c
|
||||
}
|
||||
|
||||
|
||||
void cmScoreTest( cmCtx_t* ctx, const cmChar_t* fn )
|
||||
void cmScoreReport( cmCtx_t* ctx, const cmChar_t* fn )
|
||||
{
|
||||
cmScH_t h = cmScNullHandle;
|
||||
if( cmScoreInitialize(ctx,&h,fn,0,NULL,0,NULL,NULL, cmSymTblNullHandle ) != kOkScRC )
|
||||
@ -2720,6 +2752,11 @@ void cmScoreTest( cmCtx_t* ctx, const cmChar_t* fn )
|
||||
cmScoreFinalize(&h);
|
||||
}
|
||||
|
||||
void cmScoreTest( cmCtx_t* ctx, const cmChar_t* fn )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// 1. Fix absolute message time which was incorrect on original score file.
|
||||
// 2.
|
||||
void cmScoreFix( cmCtx_t* ctx )
|
||||
|
@ -280,6 +280,10 @@ extern "C" {
|
||||
// Generate a new score file from a MIDI file.
|
||||
cmScRC_t cmScoreFileFromMidi( cmCtx_t* ctx, const cmChar_t* midiFn, const cmChar_t* scoreFn );
|
||||
|
||||
// Print open the score file 'fn' and report the contents. This function
|
||||
// simply wraps calls to cmScoreInitialize() and cmScorePrint().
|
||||
void cmScoreReport( cmCtx_t* ctx, const cmChar_t* fn );
|
||||
|
||||
void cmScoreTest( cmCtx_t* ctx, const cmChar_t* fn );
|
||||
|
||||
//)
|
||||
|
@ -538,7 +538,7 @@ cmSmgRC_t cmScoreMatchGraphicWrite( cmSmgH_t h, const cmChar_t* fn )
|
||||
svgHeight += 10; // add a right and lower border
|
||||
svgWidth += 10;
|
||||
|
||||
cmFilePrintf(fH,"<!DOCTYPE html>\n<html>\n<head><link rel=\"stylesheet\" type=\"text/css\" href=\"score0.css\"></head><body>\n<svg width=\"%i\" height=\"%i\">\n",svgWidth,svgHeight);
|
||||
cmFilePrintf(fH,"<!DOCTYPE html>\n<html>\n<head><link rel=\"stylesheet\" type=\"text/css\" href=\"cmScoreMatchGraphic.css\"></head><body>\n<svg width=\"%i\" height=\"%i\">\n",svgWidth,svgHeight);
|
||||
|
||||
for(i=0; i<p->locN; ++i)
|
||||
{
|
||||
@ -690,7 +690,7 @@ cmSmgRC_t _cmScoreMatchGraphicInsertMidiMsg( cmSmg_t* p, cmMidiFileH_t mfH, bool
|
||||
cmMidiByte_t midi_vel = pedalDnFl ? 64 : 0;
|
||||
cmMidiByte_t midi_ch = 0;
|
||||
|
||||
printf("pedal:%s\n",pedalDnFl?"down":"up");
|
||||
//printf("pedal:%s\n",pedalDnFl?"down":"up");
|
||||
|
||||
// insert a pedal msg relative to the reference event
|
||||
if( cmMidiFileInsertMsg(mfH, m->uid, dtick_offset, midi_ch, kCtlMdId, kSostenutoCtlMdId, midi_vel ) != kOkMfRC )
|
||||
@ -798,8 +798,6 @@ cmSmgRC_t cmScoreMatchGraphicUpdateMidiFromScore( cmCtx_t* ctx, cmSmgH_t h, cons
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
cmMidiFilePrintMsgs(mfH, p->err.rpt );
|
||||
|
||||
|
||||
errLabel:
|
||||
cmMidiFileClose(&mfH);
|
||||
|
@ -134,7 +134,7 @@ cmTlMidiFile_t* _cmTlMidiFileObjPtr( _cmTl_t* p, cmTlObj_t* op, bool errFl )
|
||||
if( op==NULL || op->typeId != kMidiFileTlId )
|
||||
{
|
||||
if( errFl && p != NULL)
|
||||
cmErrMsg(&p->err,kTypeCvtFailTlRC,"A time line object type promotion failed.");
|
||||
cmErrMsg(&p->err,kTypeCvtFailTlRC,"A time line object type promotion to MIDI file failed.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -147,7 +147,7 @@ cmTlMidiEvt_t* _cmTlMidiEvtObjPtr( _cmTl_t* p, cmTlObj_t* op, bool errFl )
|
||||
if( op==NULL || op->typeId != kMidiEvtTlId )
|
||||
{
|
||||
if( errFl && p != NULL )
|
||||
cmErrMsg(&p->err,kTypeCvtFailTlRC,"A time line object type promotion failed.");
|
||||
cmErrMsg(&p->err,kTypeCvtFailTlRC,"A time line object type promotion to MIDI event failed.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -173,7 +173,7 @@ cmTlAudioEvt_t* _cmTlAudioEvtObjPtr( _cmTl_t* p, cmTlObj_t* op, bool errFl )
|
||||
if( op==NULL || op->typeId != kAudioEvtTlId )
|
||||
{
|
||||
if( errFl && p != NULL)
|
||||
cmErrMsg(&p->err,kTypeCvtFailTlRC,"A time line object type promotion failed.");
|
||||
cmErrMsg(&p->err,kTypeCvtFailTlRC,"A time line object type promotion to audio event failed.");
|
||||
return NULL;
|
||||
}
|
||||
return (cmTlAudioEvt_t*)op;
|
||||
@ -186,7 +186,7 @@ cmTlMarker_t* _cmTlMarkerObjPtr( _cmTl_t* p, cmTlObj_t* op, bool errFl )
|
||||
if( op==NULL || op->typeId != kMarkerTlId )
|
||||
{
|
||||
if( errFl && p != NULL)
|
||||
cmErrMsg(&p->err,kTypeCvtFailTlRC,"A time line object type promotion failed.");
|
||||
cmErrMsg(&p->err,kTypeCvtFailTlRC,"A time line object type promotion to marker object failed.");
|
||||
return NULL;
|
||||
}
|
||||
return (cmTlMarker_t*)op;
|
||||
@ -1227,31 +1227,37 @@ _cmTlObj_t* _cmTimeLineObjAtTime( _cmTl_t* p, unsigned seqId, unsigned seqSmpIdx
|
||||
_cmTlObj_t* op = p->seq[seqId].first;
|
||||
_cmTlObj_t* min_op = NULL;
|
||||
unsigned minDist = UINT_MAX;
|
||||
bool inFl = false;
|
||||
|
||||
// for each object in the requested sequence
|
||||
for(; op!=NULL; op=op->next)
|
||||
if( typeId==cmInvalidId || op->obj->typeId == typeId )
|
||||
{
|
||||
// if seqSmpIdx is inside this object - then return it as the solution
|
||||
bool in0Fl = false;
|
||||
|
||||
// if seqSmpIdx is inside this object - then the returned object must contain seqSmpIdx
|
||||
// (but the ideal point to return is the one which contains seqSmpIdx and also has
|
||||
// a begin or end point very close to seqSmpIdx - so this defer selecting an object
|
||||
// until all objects which may contain seqSmpIdx have been examined
|
||||
if((op->obj->seqSmpIdx <= seqSmpIdx && seqSmpIdx < (op->obj->seqSmpIdx + op->obj->durSmpCnt)))
|
||||
return op;
|
||||
{
|
||||
inFl = true; // the returned object must contain seqSmpIdx
|
||||
in0Fl = true; // this object contains seqSmpIdx
|
||||
}
|
||||
|
||||
// measure the distance from seqSmpIdx to the begin and end of this object
|
||||
unsigned d0 = op->obj->seqSmpIdx < seqSmpIdx ? seqSmpIdx - op->obj->seqSmpIdx : op->obj->seqSmpIdx - seqSmpIdx;
|
||||
unsigned d1 = op->obj->seqSmpIdx+op->obj->durSmpCnt < seqSmpIdx ? seqSmpIdx - op->obj->seqSmpIdx+op->obj->durSmpCnt : op->obj->seqSmpIdx+op->obj->durSmpCnt - seqSmpIdx;
|
||||
|
||||
// d0 and d1 should decrease as the cur object approaches seqSmpIdx
|
||||
// If they do not then the search is over - return the closest point.
|
||||
if( d0>minDist && d1>minDist)
|
||||
break;
|
||||
|
||||
// track the min dist and the assoc'd obj
|
||||
if( d0 < minDist )
|
||||
if( d0 < minDist && (inFl==false || inFl==in0Fl))
|
||||
{
|
||||
minDist = d0;
|
||||
min_op = op;
|
||||
}
|
||||
|
||||
if( d1 < minDist )
|
||||
if( d1 < minDist && (inFl==false || inFl==in0Fl))
|
||||
{
|
||||
minDist = d1;
|
||||
min_op = op;
|
||||
|
1001
app/cmXScore.c
1001
app/cmXScore.c
File diff suppressed because it is too large
Load Diff
@ -18,7 +18,9 @@ extern "C" {
|
||||
kPedalStateErrorXsRc,
|
||||
kMidiFailXsRC,
|
||||
kFileFailXsRC,
|
||||
kSvgFailXsRC
|
||||
kSvgFailXsRC,
|
||||
kOverlapWarnXsRC,
|
||||
kZeroLengthEventXsRC
|
||||
};
|
||||
|
||||
typedef cmRC_t cmXsRC_t;
|
||||
@ -41,32 +43,23 @@ extern "C" {
|
||||
//
|
||||
// M-x load-file ~/src/emacs/proc_music_xml.el
|
||||
//
|
||||
// 3) How to assigned dynamic markings (they are not attached to notes). (from MIDI file?)
|
||||
// 4) Tempo syntax is inconsistent (only a problem in full part2 score)
|
||||
// 5) Heel is being parsed but not used.
|
||||
// 6) Sostenuto pedal events are not being parsed because they are not pedal events.
|
||||
// 7) What is a 'pedal-change' event vs. a 'pedal-stop' event.
|
||||
// 8) Verify the colors. (done)
|
||||
// 9) Remove blank bars at end (done in xml - do in score)
|
||||
//10) Need to assign section targets (always default to next section)
|
||||
//11) Mark tied notes for skip. (done)
|
||||
//12) Determine note off locations based on ties and slurs - defer 'pedal' to player
|
||||
//13) Check that the measures are given in sorted order.
|
||||
//14) Current implementation assumes meter changes only occur at measure boundaries.
|
||||
//15) Score Fixes: Add meter to bar 1, fix time errors (shown in voice report)
|
||||
//16) The order of notes is now correct (4/6/16) after applying
|
||||
// the grace note ordering changed specified in 'score_print_mk_edit.txt',
|
||||
// via cmXScoreReorder() however the ticks are now incorrect - fix them.
|
||||
|
||||
cmXsRC_t cmXScoreInitialize( cmCtx_t* ctx, cmXsH_t* hp, const cmChar_t* xmlFn );
|
||||
// Initialize an cmXScore object from a Sibelius generated MusicXML file.
|
||||
// Optionally include an 'edit' file to attach additional score information.
|
||||
// Note that the 'edit' file is created by marking up a file created via
|
||||
// cmXScoreReport().
|
||||
cmXsRC_t cmXScoreInitialize( cmCtx_t* ctx, cmXsH_t* hp, const cmChar_t* xmlFn, const cmChar_t* editFn );
|
||||
cmXsRC_t cmXScoreFinalize( cmXsH_t* hp );
|
||||
|
||||
|
||||
bool cmXScoreIsValid( cmXsH_t h );
|
||||
|
||||
cmXsRC_t cmXScoreWriteCsv( cmXsH_t h, const cmChar_t* csvFn );
|
||||
|
||||
void cmXScoreReport( cmXsH_t h, cmRpt_t* rpt, bool sortFl );
|
||||
|
||||
cmXsRC_t cmXScoreGenEditFile( cmCtx_t* ctx, const cmChar_t* xmlFn, const cmChar_t* outFn );
|
||||
|
||||
// Generate the CSV file suitable for use by cmScore.
|
||||
cmXsRC_t cmXScoreTest( cmCtx_t* ctx, const cmChar_t* xmlFn, const cmChar_t* reorderFn, const cmChar_t* csvOutFn, const cmChar_t* midiOutFn );
|
||||
|
||||
|
203
cmMidiFile.c
203
cmMidiFile.c
@ -8,8 +8,11 @@
|
||||
#include "cmMallocDebug.h"
|
||||
#include "cmLinkedHeap.h"
|
||||
#include "cmTime.h"
|
||||
#include "cmText.h"
|
||||
#include "cmMidi.h"
|
||||
#include "cmMidiFile.h"
|
||||
#include "cmSvgWriter.h"
|
||||
|
||||
|
||||
#ifdef cmBIG_ENDIAN
|
||||
#define mfSwap16(v) (v)
|
||||
@ -256,7 +259,7 @@ cmMfRC_t _cmMidiFileReadChannelMsg( _cmMidiFile_t* mfp, cmMidiByte_t* rsPtr, cmM
|
||||
unsigned byteN = cmMidiStatusToByteCount(tmp->status);
|
||||
|
||||
if( byteN==kInvalidMidiByte || byteN > 2 )
|
||||
return cmErrMsg(&mfp->err,kInvalidStatusMfRC,"Invalid status:0x%x %i.",tmp->status,tmp->status);
|
||||
return cmErrMsg(&mfp->err,kInvalidStatusMfRC,"Invalid status:0x%x %i byte cnt:%i.",tmp->status,tmp->status,byteN);
|
||||
|
||||
unsigned i;
|
||||
for(i=useRsFl; i<byteN; ++i)
|
||||
@ -339,7 +342,7 @@ cmMfRC_t _cmMidiFileReadTrack( _cmMidiFile_t* mfp, unsigned short trkIdx )
|
||||
if((rc = _cmMidiFileRead8(mfp,&status)) != kOkMfRC )
|
||||
return rc;
|
||||
|
||||
//printf("st:%i 0x%x\n",status,status);
|
||||
//printf("%5i st:%i 0x%x\n",dticks,status,status);
|
||||
|
||||
// append a track msg
|
||||
if((rc = _cmMidiFileAppendTrackMsg( mfp, trkIdx, dticks, status, &tmp )) != kOkMfRC )
|
||||
@ -677,7 +680,10 @@ cmMfRC_t cmMidiFileOpen( cmCtx_t* ctx, cmMidiFileH_t* hp, const char* fn )
|
||||
rc = cmErrMsg(&p->err,kFileFailMfRC,"MIDI file close failed.");
|
||||
|
||||
if( rc != kOkMfRC )
|
||||
{
|
||||
_cmMidiFileClose(p);
|
||||
hp->h = NULL;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
@ -971,12 +977,75 @@ cmMfRC_t _cmMidiFileWriteMetaMsg( _cmMidiFile_t* mfp, const cmMidiTrackMsg_t* tm
|
||||
return rc;
|
||||
}
|
||||
|
||||
cmMfRC_t _cmMidiFileInsertEotMsg( _cmMidiFile_t* p, unsigned trkIdx )
|
||||
{
|
||||
_cmMidiTrack_t* trk = p->trkV + trkIdx;
|
||||
cmMidiTrackMsg_t* m0 = NULL;
|
||||
cmMidiTrackMsg_t* m = trk->base;
|
||||
|
||||
// locate the current EOT msg on this track
|
||||
for(; m!=NULL; m=m->link)
|
||||
{
|
||||
if( m->status == kMetaStId && m->metaId == kEndOfTrkMdId )
|
||||
{
|
||||
// If this EOT msg is the last msg in the track ...
|
||||
if( m->link == NULL )
|
||||
{
|
||||
assert( m == trk->last );
|
||||
return kOkMfRC; // ... then there is nothing else to do
|
||||
}
|
||||
|
||||
// If this EOT msg is not the last in the track ...
|
||||
if( m0 != NULL )
|
||||
m0->link = m->link; // ... then unlink it
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
m0 = m;
|
||||
}
|
||||
|
||||
// if we get here then the last msg in the track was not an EOT msg
|
||||
|
||||
// if there was no previously allocated EOT msg
|
||||
if( m == NULL )
|
||||
{
|
||||
m = _cmMidiFileAllocMsg(p, trkIdx, 1, kMetaStId );
|
||||
m->metaId = kEndOfTrkMdId;
|
||||
trk->cnt += 1;
|
||||
|
||||
}
|
||||
|
||||
// link an EOT msg as the last msg on the track
|
||||
|
||||
// if the track is currently empty
|
||||
if( m0 == NULL )
|
||||
{
|
||||
trk->base = m;
|
||||
trk->last = m;
|
||||
}
|
||||
else // link the msg as the last on on the track
|
||||
{
|
||||
assert( m0 == trk->last);
|
||||
m0->link = m;
|
||||
m->link = NULL;
|
||||
trk->last = m;
|
||||
}
|
||||
|
||||
return kOkMfRC;
|
||||
|
||||
}
|
||||
|
||||
cmMfRC_t _cmMidiFileWriteTrack( _cmMidiFile_t* mfp, unsigned trkIdx )
|
||||
{
|
||||
cmMfRC_t rc = kOkMfRC;
|
||||
cmMidiTrackMsg_t* tmp = mfp->trkV[trkIdx].base;
|
||||
cmMidiByte_t runStatus = 0;
|
||||
|
||||
// be sure there is a EOT msg at the end of this track
|
||||
if((rc = _cmMidiFileInsertEotMsg(mfp, trkIdx )) != kOkMfRC )
|
||||
return rc;
|
||||
|
||||
for(; tmp != NULL; tmp=tmp->link)
|
||||
{
|
||||
// write the msg tick count
|
||||
@ -1380,8 +1449,11 @@ cmMfRC_t cmMidiFileInsertTrackMsg( cmMidiFileH_t h, unsigned trkIdx, const cmMi
|
||||
m1->dtick = m1->atick - m->atick;
|
||||
}
|
||||
|
||||
p->trkV[trkIdx].cnt += 1;
|
||||
p->msgVDirtyFl = true;
|
||||
|
||||
|
||||
|
||||
return kOkMfRC;
|
||||
|
||||
}
|
||||
@ -1403,6 +1475,8 @@ cmMfRC_t cmMidiFileInsertTrackChMsg( cmMidiFileH_t h, unsigned trkIdx, unsigned
|
||||
m.byteCnt = sizeof(cm);
|
||||
m.u.chMsgPtr = &cm;
|
||||
|
||||
assert( m.status >= kNoteOffMdId && m.status <= kPbendMdId );
|
||||
|
||||
return cmMidiFileInsertTrackMsg(h,trkIdx,&m);
|
||||
}
|
||||
|
||||
@ -1836,6 +1910,38 @@ void cmMidiFilePrintTracks( cmMidiFileH_t h, unsigned trkIdx, cmRpt_t* rpt )
|
||||
void cmMidiFileTestPrint( void* printDataPtr, const char* fmt, va_list vl )
|
||||
{ vprintf(fmt,vl); }
|
||||
|
||||
cmMidiFileDensity_t* cmMidiFileNoteDensity( cmMidiFileH_t h, unsigned* cntRef )
|
||||
{
|
||||
int msgN = cmMidiFileMsgCount(h);
|
||||
const cmMidiTrackMsg_t** msgs = cmMidiFileMsgArray(h);
|
||||
cmMidiFileDensity_t* dV = cmMemAllocZ(cmMidiFileDensity_t,msgN);
|
||||
|
||||
int i,j,k;
|
||||
for(i=0,k=0; i<msgN && k<msgN; ++i)
|
||||
if( msgs[i]->status == kNoteOnMdId && msgs[i]->u.chMsgPtr->d1 > 0 )
|
||||
{
|
||||
dV[k].uid = msgs[i]->uid;
|
||||
dV[k].amicro = msgs[i]->amicro;
|
||||
|
||||
for(j=i; j>=0; --j)
|
||||
{
|
||||
if( msgs[i]->amicro - msgs[j]->amicro > 1000000 )
|
||||
break;
|
||||
|
||||
dV[k].density += 1;
|
||||
}
|
||||
|
||||
k += 1;
|
||||
|
||||
}
|
||||
|
||||
if( cntRef != NULL )
|
||||
*cntRef = k;
|
||||
|
||||
return dV;
|
||||
}
|
||||
|
||||
|
||||
cmMfRC_t cmMidiFileGenPlotFile( cmCtx_t* ctx, const cmChar_t* midiFn, const cmChar_t* outFn )
|
||||
{
|
||||
cmMfRC_t rc = kOkMfRC;
|
||||
@ -1872,6 +1978,99 @@ cmMfRC_t cmMidiFileGenPlotFile( cmCtx_t* ctx, const cmChar_t* midiFn, const cmCh
|
||||
return rc;
|
||||
}
|
||||
|
||||
cmMfRC_t cmMidiFileGenSvgFile( cmCtx_t* ctx, const cmChar_t* midiFn, const cmChar_t* outSvgFn, const cmChar_t* cssFn )
|
||||
{
|
||||
cmMfRC_t rc = kOkMfRC;
|
||||
cmSvgH_t svgH = cmSvgNullHandle;
|
||||
cmMidiFileH_t mfH = cmMidiFileNullHandle;
|
||||
unsigned msgN = 0;
|
||||
const cmMidiTrackMsg_t** msgs = NULL;
|
||||
unsigned noteHeight = 10;
|
||||
double micros_per_sec = 1000.0;
|
||||
unsigned i;
|
||||
|
||||
if((rc = cmMidiFileOpen(ctx,&mfH,midiFn)) != kOkMfRC )
|
||||
{
|
||||
rc = cmErrMsg(&ctx->err,rc,"Unable to open the MIDI file '%s'.",cmStringNullGuard(midiFn));
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
cmMidiFileCalcNoteDurations( mfH );
|
||||
|
||||
msgN = cmMidiFileMsgCount(mfH);
|
||||
msgs = cmMidiFileMsgArray(mfH);
|
||||
|
||||
|
||||
if( cmSvgWriterAlloc(ctx,&svgH) != kOkSvgRC )
|
||||
{
|
||||
rc = cmErrMsg(&ctx->err,kSvgFailMfRC,"Unable to create the MIDI SVG output file '%s'.",cmStringNullGuard(outSvgFn));
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
|
||||
for(i=0; i<msgN && rc==kOkMfRC; ++i)
|
||||
if( msgs[i]->status == kNoteOnMdId && msgs[i]->u.chMsgPtr->d1 > 0 )
|
||||
{
|
||||
const cmMidiTrackMsg_t* m = msgs[i];
|
||||
|
||||
|
||||
if( cmSvgWriterRect(svgH, m->amicro/micros_per_sec, m->u.chMsgPtr->d0 * noteHeight, m->u.chMsgPtr->durMicros/micros_per_sec, noteHeight-1, "note" ) != kOkSvgRC )
|
||||
rc = kSvgFailMfRC;
|
||||
|
||||
const cmChar_t* t0 = cmMidiToSciPitch(m->u.chMsgPtr->d0,NULL,0);
|
||||
|
||||
if( cmSvgWriterText(svgH, (m->amicro + (m->u.chMsgPtr->durMicros/2)) / micros_per_sec, m->u.chMsgPtr->d0 * noteHeight, t0, "text" ) != kOkSvgRC )
|
||||
rc = kSvgFailMfRC;
|
||||
|
||||
}
|
||||
|
||||
if( rc != kOkMfRC )
|
||||
{
|
||||
cmErrMsg(&ctx->err,rc,"SVG Shape insertion failed.");
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
unsigned dN = 0;
|
||||
cmMidiFileDensity_t* dV = cmMidiFileNoteDensity( mfH, &dN );
|
||||
double t0 = 0;
|
||||
double y0 = 64.0;
|
||||
cmChar_t* tx = NULL;
|
||||
|
||||
for(i=0; i<dN; ++i)
|
||||
{
|
||||
const cmMidiTrackMsg_t* m;
|
||||
|
||||
if((m = _cmMidiFileUidToMsg( _cmMidiFileHandleToPtr(mfH), dV[i].uid )) == NULL )
|
||||
rc = cmErrMsg(&ctx->err,kUidNotFoundMfRC,"The MIDI msg form UID:%i was not found.",dV[i].uid);
|
||||
else
|
||||
{
|
||||
double t1 = m->amicro / micros_per_sec;
|
||||
double y1 = dV[i].density * noteHeight;
|
||||
|
||||
cmSvgWriterLine(svgH, t0, y0, t1, y1, "density" );
|
||||
cmSvgWriterText(svgH, t1, y1, tx = cmTsPrintfP(tx,"%i",dV[i].density),"dtext");
|
||||
|
||||
t0 = t1;
|
||||
y0 = y1;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
cmMemFree(dV);
|
||||
cmMemFree(tx);
|
||||
|
||||
if( rc == kOkMfRC )
|
||||
if( cmSvgWriterWrite(svgH,cssFn,outSvgFn) != kOkSvgRC )
|
||||
rc = cmErrMsg(&ctx->err,kSvgFailMfRC,"SVG file write to '%s' failed.",cmStringNullGuard(outSvgFn));
|
||||
|
||||
|
||||
errLabel:
|
||||
cmMidiFileClose(&mfH);
|
||||
cmSvgWriterFree(&svgH);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void cmMidiFilePrintControlNumbers( cmCtx_t* ctx, const char* fn )
|
||||
{
|
||||
cmMidiFileH_t h = cmMidiFileNullHandle;
|
||||
|
21
cmMidiFile.h
21
cmMidiFile.h
@ -117,7 +117,8 @@ extern "C" {
|
||||
kLargeDeltaTickMfRC, // 12 (a large delta tick value was filtered)
|
||||
kUidNotFoundMfRC, // 13
|
||||
kUidNotANoteMsgMfRC, // 14
|
||||
kInvalidTrkIndexMfRC // 15
|
||||
kInvalidTrkIndexMfRC,// 15
|
||||
kSvgFailMfRC // 16
|
||||
};
|
||||
|
||||
extern cmMidiFileH_t cmMidiFileNullHandle;
|
||||
@ -212,11 +213,27 @@ extern "C" {
|
||||
|
||||
void cmMidiFilePrintMsgs( cmMidiFileH_t h, cmRpt_t* rpt );
|
||||
void cmMidiFilePrintTrack( cmMidiFileH_t h, unsigned trkIdx, cmRpt_t* rpt );
|
||||
void cmMidiFileTest( const char* fn, cmCtx_t* ctx );
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned uid;
|
||||
unsigned long long amicro;
|
||||
unsigned density;
|
||||
|
||||
} cmMidiFileDensity_t;
|
||||
|
||||
// Generate the note onset density measure for each note in the MIDI file.
|
||||
// Delete the returned memory with a call to cmMemFree().
|
||||
cmMidiFileDensity_t* cmMidiFileNoteDensity( cmMidiFileH_t h, unsigned* cntRef );
|
||||
|
||||
// Generate a piano-roll plot description file which can be displayed with cmXScore.m
|
||||
cmMfRC_t cmMidiFileGenPlotFile( cmCtx_t* ctx, const cmChar_t* midiFn, const cmChar_t* outFn );
|
||||
|
||||
cmMfRC_t cmMidiFileGenSvgFile( cmCtx_t* ctx, const cmChar_t* midiFn, const cmChar_t* outSvgFn, const cmChar_t* cssFn );
|
||||
|
||||
void cmMidiFileTest( const char* fn, cmCtx_t* ctx );
|
||||
|
||||
|
||||
|
||||
//)
|
||||
|
||||
|
@ -167,6 +167,32 @@ void _cmSvgSize( cmSvg_t* p, double* widthRef, double* heightRef )
|
||||
*heightRef = max_y - min_y;
|
||||
}
|
||||
|
||||
void _cmSvgWriterFlipY( cmSvg_t* p, unsigned height )
|
||||
{
|
||||
cmSvgEle_t* e = p->elist;
|
||||
for(; e!=NULL; e=e->link)
|
||||
{
|
||||
e->y0 = (-e->y0) + height;
|
||||
e->y1 = (-e->y1) + height;
|
||||
|
||||
if( e->id == kRectSvgId )
|
||||
{
|
||||
double t = e->y1;
|
||||
e->y1 = e->y0;
|
||||
e->y0 = t;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
"<script type=\"text/javascript\" src=\"svg-pan-zoom.min.js\"></script>\n"
|
||||
"<script>\n"
|
||||
" var panZoom = null;\n"
|
||||
" function doOnLoad() { panZoom = svgPanZoom(document.querySelector('#mysvg'), { controlIconsEnabled:true } ) }\n"
|
||||
"</script>\n"
|
||||
|
||||
*/
|
||||
|
||||
cmSvgRC_t cmSvgWriterWrite( cmSvgH_t h, const cmChar_t* cssFn, const cmChar_t* outFn )
|
||||
{
|
||||
@ -176,15 +202,29 @@ cmSvgRC_t cmSvgWriterWrite( cmSvgH_t h, const cmChar_t* cssFn, const cmChar_t*
|
||||
double svgHeight = 0;
|
||||
cmSvgEle_t* e = p->elist;
|
||||
cmFileH_t fH = cmFileNullHandle;
|
||||
cmChar_t* s0 = NULL;
|
||||
cmChar_t* s1 = NULL;
|
||||
|
||||
cmChar_t hdr[] =
|
||||
"<!DOCTYPE html>\n"
|
||||
"<html>\n"
|
||||
"<head>\n"
|
||||
"<meta charset=\"utf-8\">\n"
|
||||
"<link rel=\"stylesheet\" type=\"text/css\" href=\"%s\">\n"
|
||||
"</head>\n"
|
||||
"<body onload=\"doOnLoad()\">\n"
|
||||
"<svg id=\"mysvg\" width=\"%f\" height=\"%f\">\n";
|
||||
|
||||
|
||||
|
||||
_cmSvgSize(p, &svgWidth, &svgHeight );
|
||||
|
||||
if( cmFileOpen(&fH,outFn,kWriteFileFl,p->err.rpt) != kOkFileRC )
|
||||
return cmErrMsg(&p->err,kFileFailSvgRC,"SVG file create failed for '%s'.",cmStringNullGuard(outFn));
|
||||
_cmSvgWriterFlipY( p, svgHeight );
|
||||
|
||||
if( cmFilePrintf(fH,"<!DOCTYPE html>\n<html>\n<head><link rel=\"stylesheet\" type=\"text/css\" href=\"%s\"></head><body>\n<svg width=\"%f\" height=\"%f\">\n",svgWidth,svgHeight,cssFn) != kOkFileRC )
|
||||
// print the file header
|
||||
if( (s0 = cmTsPrintfP(s0,hdr,cssFn,svgWidth,svgHeight)) == NULL )
|
||||
{
|
||||
rc = cmErrMsg(&p->err,kFileFailSvgRC,"File prefix write failed.");
|
||||
rc = cmErrMsg(&p->err,kPrintFailSvgRC,"File prefix write failed.");
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
@ -193,18 +233,18 @@ cmSvgRC_t cmSvgWriterWrite( cmSvgH_t h, const cmChar_t* cssFn, const cmChar_t*
|
||||
switch( e->id )
|
||||
{
|
||||
case kRectSvgId:
|
||||
if( cmFilePrintf(fH,"<rect x=\"%f\" y=\"%f\" width=\"%f\" height=\"%f\" class=\"%s\"/>\n",e->x0,e->y0,e->x1-e->x0,e->y1-e->y0,e->cssClass) != kOkFileRC )
|
||||
rc = kFileFailSvgRC;
|
||||
if( (s1 = cmTsPrintfP(s1,"<rect x=\"%f\" y=\"%f\" width=\"%f\" height=\"%f\" class=\"%s\"/>\n",e->x0,e->y0,e->x1-e->x0,e->y1-e->y0,e->cssClass)) == NULL )
|
||||
rc = kPrintFailSvgRC;
|
||||
break;
|
||||
|
||||
case kLineSvgId:
|
||||
if( cmFilePrintf(fH,"<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" class=\"%s\"/>\n",e->x0,e->y0,e->x1,e->y1,e->cssClass) != kOkFileRC )
|
||||
rc = kFileFailSvgRC;
|
||||
if( (s1 = cmTsPrintfP(s1,"<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" class=\"%s\"/>\n",e->x0,e->y0,e->x1,e->y1,e->cssClass)) == NULL )
|
||||
rc = kPrintFailSvgRC;
|
||||
break;
|
||||
|
||||
case kTextSvgId:
|
||||
if( cmFilePrintf(fH,"<text x=\"%f\" y=\"%f\" class=\"%s\">%s</text>\n",e->x0,e->y0,e->cssClass,e->text) != kOkFileRC )
|
||||
rc = kFileFailSvgRC;
|
||||
if( (s1 = cmTsPrintfP(s1,"<text x=\"%f\" y=\"%f\" class=\"%s\">%s</text>\n",e->x0,e->y0,e->cssClass,e->text)) == NULL )
|
||||
rc = kPrintFailSvgRC;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -214,21 +254,38 @@ cmSvgRC_t cmSvgWriterWrite( cmSvgH_t h, const cmChar_t* cssFn, const cmChar_t*
|
||||
|
||||
if( rc != kOkSvgRC )
|
||||
{
|
||||
rc = cmErrMsg(&p->err,kFileFailSvgRC,"Element write failed.");
|
||||
rc = cmErrMsg(&p->err,kPrintFailSvgRC,"Element write failed.");
|
||||
break;
|
||||
}
|
||||
|
||||
s0 = cmTextAppendSS(s0,s1);
|
||||
|
||||
}
|
||||
|
||||
if( cmFilePrint(fH,"</svg>\n</body>\n</html>\n") != kOkFileRC )
|
||||
if( (s1 = cmTsPrintfP(s1,"</svg>\n</body>\n</html>\n")) == NULL )
|
||||
{
|
||||
rc = cmErrMsg(&p->err,kFileFailSvgRC,"File suffix write failed.");
|
||||
rc = cmErrMsg(&p->err,kPrintFailSvgRC,"File suffix write failed.");
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
if( cmFileOpen(&fH,outFn,kWriteFileFl,p->err.rpt) != kOkFileRC )
|
||||
{
|
||||
rc = cmErrMsg(&p->err,kFileFailSvgRC,"SVG file create failed for '%s'.",cmStringNullGuard(outFn));
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
if( cmFilePrint(fH,s0 = cmTextAppendSS(s0,s1)) != kOkFileRC )
|
||||
{
|
||||
rc = cmErrMsg(&p->err,kFileFailSvgRC,"File write failed.");
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
errLabel:
|
||||
cmFileClose(&fH);
|
||||
|
||||
cmMemFree(s0);
|
||||
cmMemFree(s1);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@ enum
|
||||
{
|
||||
kOkSvgRC = cmOkRC,
|
||||
kFileFailSvgRC,
|
||||
kPrintFailSvgRC,
|
||||
kLHeapFailSvgRC
|
||||
};
|
||||
|
||||
@ -21,10 +22,14 @@ enum
|
||||
cmSvgRC_t cmSvgWriterFree( cmSvgH_t* hp );
|
||||
bool cmSvgWriterIsValid( cmSvgH_t h );
|
||||
|
||||
cmSvgRC_t cmSvgWriterRect( cmSvgH_t h, double x, double y, double ww, double hh, const cmChar_t* cssClassLabel );
|
||||
cmSvgRC_t cmSvgWriterRect( cmSvgH_t h, double x, double y, double ww, double hh, const cmChar_t* cssClassLabel );
|
||||
cmSvgRC_t cmSvgWriterLine( cmSvgH_t h, double x0, double y0, double x1, double y1, const cmChar_t* cssClassLabel );
|
||||
cmSvgRC_t cmSvgWriterText( cmSvgH_t h, double x, double y, const cmChar_t* text, const cmChar_t* cssClassLabel );
|
||||
|
||||
// Write the SVG file. Note that header on this file references the CSS file 'cssFn'
|
||||
// and the Javascript file svg-pan-zoom.min.js from https://github.com/ariutta/svg-pan-zoom.
|
||||
// Both the CSS file and svg-pan-zoom.min.js should therefore be in the same directory
|
||||
// as the output HTML file.
|
||||
cmSvgRC_t cmSvgWriterWrite( cmSvgH_t h, const cmChar_t* cssFn, const cmChar_t* outFn );
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -657,7 +657,7 @@ cmDspRC_t _cmDspTimeLineRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_
|
||||
cmTlObj_t* op;
|
||||
if((op = cmTimeLineIdToObj(p->tlH, cmInvalidId, markerId )) != NULL )
|
||||
{
|
||||
assert(op->typeId == kMarkerTlId);
|
||||
assert(op->typeId == kMarkerTlId || op->typeId == kMidiEvtTlId );
|
||||
|
||||
p->afIdx = op->begSmpIdx;
|
||||
|
||||
|
@ -201,7 +201,7 @@ void _cmDspSys_TlXformChain( cmDspSysH_t h, cmDspTlXform_t* c, unsigned preGrpS
|
||||
cmDspInst_t* max_lwr_ctl = cmDspSysAllocScalarP( h,preGrpSymId, NULL, lbl("Max Lwr"), 0.0, -1.0, 5.0, 3.0);
|
||||
cmDspInst_t* min_off_ctl = cmDspSysAllocScalarP( h,preGrpSymId, NULL, lbl("Min Off"), 0.0, 50.0, 0.1, 30.0);
|
||||
cmDspInst_t* max_off_ctl = cmDspSysAllocScalarP( h,preGrpSymId, NULL, lbl("Max Off"), 0.0, 50.0, 0.1, 30.0);
|
||||
cmDspInst_t* min_wet_ctl = cmDspSysAllocScalarP( h,preGrpSymId, NULL, lbl("Min Wet"), 0.0, 1.0, 0.01, 1.0);
|
||||
cmDspInst_t* min_wet_ctl = cmDspSysAllocScalarP( h,preGrpSymId, NULL, lbl("Min Wet"), 0.0, 1.0, 0.01, 0.0);
|
||||
cmDspInst_t* max_wet_ctl = cmDspSysAllocScalarP( h,preGrpSymId, NULL, lbl("Max Wet"), 0.0, 1.0, 0.01, 1.0);
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user