cmXScore.c : Added _cmXScoreGraceInsertTimeXXX().
This commit is contained in:
parent
fdfe4d404a
commit
be6dc19ade
178
app/cmXScore.c
178
app/cmXScore.c
@ -37,33 +37,34 @@ cmXsH_t cmXsNullHandle = cmSTATIC_NULL_HANDLE;
|
||||
|
||||
enum
|
||||
{
|
||||
kSectionXsFl = 0x0000001, // rvalue holds section number
|
||||
kBarXsFl = 0x0000002,
|
||||
kRestXsFl = 0x0000004,
|
||||
kGraceXsFl = 0x0000008,
|
||||
kDotXsFl = 0x0000010,
|
||||
kChordXsFl = 0x0000020,
|
||||
kDynXsFl = 0x0000040,
|
||||
kEvenXsFl = 0x0000080,
|
||||
kTempoXsFl = 0x0000100,
|
||||
kHeelXsFl = 0x0000200,
|
||||
kTieBegXsFl = 0x0000400,
|
||||
kTieEndXsFl = 0x0000800,
|
||||
kTieProcXsFl = 0x0001000,
|
||||
kDampDnXsFl = 0x0002000,
|
||||
kDampUpXsFl = 0x0004000,
|
||||
kDampUpDnXsFl = 0x0008000,
|
||||
kSostDnXsFl = 0x0010000,
|
||||
kSostUpXsFl = 0x0020000,
|
||||
kMetronomeXsFl = 0x0040000, // duration holds BPM
|
||||
kOnsetXsFl = 0x0080000, // this is a sounding note
|
||||
kBegGroupXsFl = 0x0100000,
|
||||
kEndGroupXsFl = 0x0200000,
|
||||
kBegGraceXsFl = 0x0400000, // beg grace note group
|
||||
kEndGraceXsFl = 0x0800000, // end grace note group
|
||||
kAddGraceXsFl = 0x1000000, // end grace note group operator flag - add time
|
||||
kSubGraceXsFl = 0x2000000, // " " " " " " - subtract time
|
||||
kFirstGraceXsFl = 0x4000000, // " " " " " " - sync to first note
|
||||
kSectionXsFl = 0x00000001, // rvalue holds section number
|
||||
kBarXsFl = 0x00000002,
|
||||
kRestXsFl = 0x00000004,
|
||||
kGraceXsFl = 0x00000008,
|
||||
kDotXsFl = 0x00000010,
|
||||
kChordXsFl = 0x00000020,
|
||||
kDynXsFl = 0x00000040,
|
||||
kEvenXsFl = 0x00000080,
|
||||
kTempoXsFl = 0x00000100,
|
||||
kHeelXsFl = 0x00000200,
|
||||
kTieBegXsFl = 0x00000400,
|
||||
kTieEndXsFl = 0x00000800,
|
||||
kTieProcXsFl = 0x00001000,
|
||||
kDampDnXsFl = 0x00002000,
|
||||
kDampUpXsFl = 0x00004000,
|
||||
kDampUpDnXsFl = 0x00008000,
|
||||
kSostDnXsFl = 0x00010000,
|
||||
kSostUpXsFl = 0x00020000,
|
||||
kMetronomeXsFl = 0x00040000, // duration holds BPM
|
||||
kOnsetXsFl = 0x00080000, // this is a sounding note
|
||||
kBegGroupXsFl = 0x00100000,
|
||||
kEndGroupXsFl = 0x00200000,
|
||||
kBegGraceXsFl = 0x00400000, // (b) beg grace note group
|
||||
kEndGraceXsFl = 0x00800000, // end grace note group
|
||||
kAddGraceXsFl = 0x01000000, // (a) end grace note group operator flag - add time
|
||||
kSubGraceXsFl = 0x02000000, // (s) " " " " " " - subtract time
|
||||
kAFirstGraceXsFl = 0x04000000, // (A) add time after first note
|
||||
kNFirstGraceXsFl = 0x08000000 // (n) grace notes start as soon as possible after first note and add time
|
||||
|
||||
};
|
||||
|
||||
@ -1464,6 +1465,9 @@ cmXsRC_t _cmXScoreProcessPedals( cmXScore_t* p )
|
||||
cmErrWarnMsg(&p->err,kPedalStateErrorXsRc,"Sostenuto left down at the end of a part.");
|
||||
}
|
||||
|
||||
|
||||
_cmXScoreSort(p);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -1479,21 +1483,30 @@ void _cmXScoreInsertTime( cmXScore_t* p, cmXsMeas_t* mp, cmXsNote_t* np, unsigne
|
||||
}
|
||||
}
|
||||
|
||||
// Insert the grace notes in between the first and last note in the group
|
||||
// by inserting time between the first and last note.
|
||||
void _cmXScoreGraceInsertTime( cmXScore_t* p, unsigned graceGroupId, cmXsNote_t* aV[], unsigned aN )
|
||||
void _cmXScoreGraceInsertTimeBase( cmXScore_t* p, unsigned graceGroupId, cmXsNote_t* aV[], unsigned aN, unsigned initTick )
|
||||
{
|
||||
cmXsNote_t* np = NULL;
|
||||
unsigned expand_ticks = 0;
|
||||
unsigned ticks = aV[aN-1]->tick;
|
||||
unsigned i;
|
||||
cmXsNote_t* np = NULL;
|
||||
unsigned expand_ticks = 0;
|
||||
unsigned ticks = initTick;
|
||||
|
||||
unsigned t0 = 0;
|
||||
unsigned i;
|
||||
|
||||
for(i=0; i<aN; ++i)
|
||||
if( cmIsFlag(aV[i]->flags,kGraceXsFl) && aV[i]->graceGroupId == graceGroupId )
|
||||
{
|
||||
aV[i]->tick = ticks;
|
||||
ticks += aV[i]->duration;
|
||||
expand_ticks += aV[i]->duration;
|
||||
np = aV[i];
|
||||
// if this grace note falls on the same tick as the previous grace note
|
||||
if( np != NULL && aV[i]->tick == t0 )
|
||||
aV[i]->tick = np->tick;
|
||||
else
|
||||
{
|
||||
t0 = aV[i]->tick; // store the unmodified tick value of this note
|
||||
aV[i]->tick = ticks; // set the new tick value
|
||||
ticks += aV[i]->duration; // calc the next grace not location
|
||||
expand_ticks += aV[i]->duration; // track how much we are expanding time by
|
||||
}
|
||||
|
||||
np = aV[i];
|
||||
}
|
||||
|
||||
np = np->slink;
|
||||
@ -1501,24 +1514,59 @@ void _cmXScoreGraceInsertTime( cmXScore_t* p, unsigned graceGroupId, cmXsNote_t*
|
||||
_cmXScoreInsertTime(p,np->meas,np,expand_ticks);
|
||||
}
|
||||
|
||||
// Insert the grace notes in between the first and last note in the group
|
||||
// by inserting time between the first and last note.
|
||||
// Note that in effect his means that the last note is pushed back
|
||||
// in time by the total duration of the grace notes.
|
||||
void _cmXScoreGraceInsertTime( cmXScore_t* p, unsigned graceGroupId, cmXsNote_t* aV[], unsigned aN )
|
||||
{
|
||||
_cmXScoreGraceInsertTimeBase( p, graceGroupId,aV,aN, aV[aN-1]->tick );
|
||||
}
|
||||
|
||||
// Insert the grace notes in between the first and last note in the group
|
||||
// but do not insert any additional time betwee the first and last note.
|
||||
// In effect time is removed from the first note and taken by the grace notes.
|
||||
// The time position of the last note is therefore unchanged.
|
||||
void _cmXScoreGraceOverlayTime( cmXScore_t* p, unsigned graceGroupId, cmXsNote_t* aV[], unsigned aN )
|
||||
{
|
||||
assert(aN >= 3 );
|
||||
|
||||
unsigned t = aV[aN-1]->tick;
|
||||
int i = (int)aN-2;
|
||||
int i = (int)aN-2;
|
||||
cmXsNote_t* np = aV[aN-1];
|
||||
unsigned t0 = -1;
|
||||
|
||||
for(; i>0; --i)
|
||||
if( cmIsFlag(aV[i]->flags,kGraceXsFl) && aV[i]->graceGroupId == graceGroupId )
|
||||
{
|
||||
aV[i]->tick = t - aV[i]->duration;
|
||||
t = aV[i]->tick;
|
||||
if( aV[i]->tick == t0)
|
||||
aV[i]->tick = np->tick;
|
||||
else
|
||||
{
|
||||
t0 = aV[i]->tick;
|
||||
aV[i]->tick = np->tick - aV[i]->duration;
|
||||
}
|
||||
|
||||
np = aV[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Play the first grace at the time of the first note in the group (which is a non-grace note)
|
||||
// and then expand time while inserting the other grace notes.
|
||||
void _cmXScoreGraceInsertAfterFirst( cmXScore_t* p, unsigned graceGroupId, cmXsNote_t* aV[], unsigned aN )
|
||||
{
|
||||
_cmXScoreGraceInsertTimeBase( p, graceGroupId,aV,aN, aV[0]->tick );
|
||||
}
|
||||
|
||||
|
||||
// Play the first grace not shortly (one grace note duration) after the first note
|
||||
// in the group (which is a non-grace note) and then expand time while inserting the other
|
||||
// grace notes.
|
||||
void _cmXScoreGraceInsertSoonAfterFirst( cmXScore_t* p, unsigned graceGroupId, cmXsNote_t* aV[], unsigned aN )
|
||||
{
|
||||
_cmXScoreGraceInsertTimeBase( p, graceGroupId,aV,aN, aV[0]->tick + aV[1]->duration );
|
||||
}
|
||||
|
||||
|
||||
// Adjust the locations of grace notes. Note that this must be done
|
||||
// after reordering so that we can be sure that the order in time of
|
||||
// the notes in each group has been set prior to building the
|
||||
@ -1528,14 +1576,18 @@ cmXsRC_t _cmXScoreProcessGraceNotes( cmXScore_t* p )
|
||||
cmXsRC_t rc = kOkXsRC;
|
||||
unsigned graceGroupId = 1;
|
||||
double graceDurSec = 1.0/15.0; // duration of all grace notes in seconds
|
||||
|
||||
|
||||
for(; 1; ++graceGroupId)
|
||||
{
|
||||
cmXsNote_t* gn0p = NULL;
|
||||
cmXsNote_t* gn1p = NULL;
|
||||
cmXsNote_t* gn0p = NULL; // first note in the grace group
|
||||
cmXsNote_t* gn1p = NULL; // last note in the grace group
|
||||
unsigned gN = 0;
|
||||
cmXsPart_t* pp = p->partL;
|
||||
double ticksPerSec = 0;
|
||||
|
||||
// Build a note chain, using cmXsNote_t.grace, between gn0p and
|
||||
// gn1p containing all the grace notes with
|
||||
// cmXsNote_t.graceGroupId == graceGroupId.
|
||||
|
||||
for(; pp!=NULL; pp=pp->link)
|
||||
{
|
||||
@ -1571,11 +1623,11 @@ cmXsRC_t _cmXScoreProcessGraceNotes( cmXScore_t* p )
|
||||
np->duration = floor(ticksPerSec * graceDurSec);
|
||||
|
||||
gN += 1;
|
||||
}
|
||||
}
|
||||
|
||||
} //
|
||||
}
|
||||
}
|
||||
} // for each note in this meassure
|
||||
} // for each measure
|
||||
} // for each part
|
||||
|
||||
// no records were found for this grace id - we're done
|
||||
if( gn0p == NULL )
|
||||
@ -1587,7 +1639,6 @@ cmXsRC_t _cmXScoreProcessGraceNotes( cmXScore_t* p )
|
||||
rc = cmErrMsg(&p->err,kSyntaxErrorXsRC,"The grace not group ending in meas %i has fewer than 3 (%i) members.", gn1p->meas->number, gN );
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// gn0p is now set to the first note in th group
|
||||
// gn1p is now set to the last note in the group
|
||||
@ -1606,7 +1657,7 @@ cmXsRC_t _cmXScoreProcessGraceNotes( cmXScore_t* p )
|
||||
break;
|
||||
}
|
||||
|
||||
// count the total number of events between gn0p and gn1p
|
||||
// Count the total number of events between gn0p and gn1p
|
||||
cmXsNote_t* n0p = NULL;
|
||||
cmXsNote_t* n1p = gn0p;
|
||||
cmXsMeas_t* mp = gn0p->meas;
|
||||
@ -1624,8 +1675,8 @@ cmXsRC_t _cmXScoreProcessGraceNotes( cmXScore_t* p )
|
||||
if(1)
|
||||
{
|
||||
bool fl = n0p != NULL && n0p->tick < n1p->tick;
|
||||
unsigned type = n1p->flags & (kBegGraceXsFl|kEndGraceXsFl|kAddGraceXsFl|kSubGraceXsFl|kFirstGraceXsFl);
|
||||
printf("%3i 0x%08x %i %5i %i\n",n1p->graceGroupId,type,n1p->tick,n1p->duration,fl);
|
||||
unsigned type = n1p->flags & (kBegGraceXsFl|kEndGraceXsFl|kAddGraceXsFl|kSubGraceXsFl|kAFirstGraceXsFl|kNFirstGraceXsFl);
|
||||
printf("%3i 0x%08x %i %3i %5i %i\n",n1p->graceGroupId,type,n1p->meas->number,n1p->tick,n1p->duration,fl);
|
||||
}
|
||||
|
||||
++aN;
|
||||
@ -1653,7 +1704,7 @@ cmXsRC_t _cmXScoreProcessGraceNotes( cmXScore_t* p )
|
||||
n0p = n1p;
|
||||
}
|
||||
|
||||
switch( gn1p->flags & (kAddGraceXsFl | kSubGraceXsFl | kFirstGraceXsFl) )
|
||||
switch( gn1p->flags & (kAddGraceXsFl | kSubGraceXsFl | kAFirstGraceXsFl | kNFirstGraceXsFl ) )
|
||||
{
|
||||
case kAddGraceXsFl:
|
||||
_cmXScoreGraceInsertTime(p, graceGroupId, aV, aN );
|
||||
@ -1663,7 +1714,12 @@ cmXsRC_t _cmXScoreProcessGraceNotes( cmXScore_t* p )
|
||||
_cmXScoreGraceOverlayTime(p, graceGroupId, aV, aN );
|
||||
break;
|
||||
|
||||
case kFirstGraceXsFl:
|
||||
case kAFirstGraceXsFl:
|
||||
_cmXScoreGraceInsertAfterFirst(p,graceGroupId,aV,aN);
|
||||
break;
|
||||
|
||||
case kNFirstGraceXsFl:
|
||||
_cmXScoreGraceInsertSoonAfterFirst(p,graceGroupId,aV,aN);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -2136,7 +2192,8 @@ cmXsRC_t _cmXScoreReorderParseGrace(cmXScore_t* p, const cmChar_t* b, unsigned
|
||||
case 'b': r->graceFlags |= kBegGraceXsFl; break;
|
||||
case 'a': r->graceFlags |= kAddGraceXsFl | kEndGraceXsFl; break;
|
||||
case 's': r->graceFlags |= kSubGraceXsFl | kEndGraceXsFl; break;
|
||||
case 'f': r->graceFlags |= kFirstGraceXsFl | kEndGraceXsFl; break;
|
||||
case 'A': r->graceFlags |= kAFirstGraceXsFl| kEndGraceXsFl; break;
|
||||
case 'n': r->graceFlags |= kNFirstGraceXsFl| kEndGraceXsFl; break;
|
||||
case 'g': break;
|
||||
|
||||
case '%':
|
||||
@ -3015,7 +3072,7 @@ cmXsRC_t _cmXsWriteMidiSvg( cmCtx_t* ctx, cmXScore_t* p, cmXsMidiFile_t* mf, con
|
||||
{
|
||||
cmXsRC_t rc = kOkXsRC;
|
||||
cmSvgH_t svgH = cmSvgNullHandle;
|
||||
cmXsSvgEvt_t* e = mf->elist;
|
||||
cmXsSvgEvt_t* e = mf->elist;
|
||||
unsigned noteHeight = 10;
|
||||
const cmChar_t* svgFn = cmFsMakeFn(dir,fn,"html",NULL);
|
||||
const cmChar_t* cssFn = cmFsMakeFn(NULL,fn,"css",NULL);
|
||||
@ -3198,7 +3255,11 @@ cmXsRC_t cmXScoreTest(
|
||||
return cmErrMsg(&ctx->err,rc,"XScore alloc failed.");
|
||||
|
||||
if( reorderFn != NULL )
|
||||
cmXScoreReorder(h,reorderFn);
|
||||
if((rc = cmXScoreReorder(h,reorderFn)) != kOkXsRC )
|
||||
{
|
||||
cmErrMsg(&ctx->err,rc,"XScore reorder failed.");
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// assign durations to pedal down events
|
||||
_cmXScoreProcessPedals(_cmXScoreHandleToPtr(h));
|
||||
@ -3239,6 +3300,7 @@ cmXsRC_t cmXScoreTest(
|
||||
|
||||
cmXScoreReport(h,&ctx->rpt,true);
|
||||
|
||||
errLabel:
|
||||
return cmXScoreFinalize(&h);
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user