cmScore.h/c : The durSecs's cmScEvt_t field of pedal down events now contains

the length of time the pedal is held down and the 'pitch' field is set
to the MIDI id of the pedal.
This commit is contained in:
Kevin Larke 2015-02-24 15:42:24 -08:00
parent a89cadec84
commit 9e11eb49b8
2 changed files with 70 additions and 6 deletions

View File

@ -35,6 +35,8 @@ enum
kTypeLabelColScIdx = 3,
kDSecsColScIdx = 4,
kSecsColScIdx = 5,
kD0ColScIdx = 9,
kD1ColScIdx = 10,
kPitchColScIdx = 11,
kBarColScIdx = 13,
kSkipColScIdx = 14,
@ -1222,6 +1224,10 @@ cmScRC_t _cmScParseFile( cmSc_t* p, cmCtx_t* ctx, const cmChar_t* fn )
double secs;
double cur_secs = 0;
const unsigned pedalBaseMidiId = 64;
const unsigned pedalN = 3;
cmScoreEvt_t* pedalV[] = { NULL,NULL,NULL };
p->sectList = cmMemAllocZ(cmScSect_t,1); // section zero
//_cmScNewSet(p); // preallocate the first set
@ -1293,14 +1299,21 @@ cmScRC_t _cmScParseFile( cmSc_t* p, cmCtx_t* ctx, const cmChar_t* fn )
case kNonEvtScId: // parse note-on events
if((rc = _cmScParseNoteOn(p, i, p->array, j, barNumb, barNoteIdx )) == kOkScRC )
{
// this note was successfully parsed so time has advanced
secs = p->array[j].secs;
// if this note was not assigned time a time then set it
if( p->array[j].secs == DBL_MAX )
{
p->array[j].secs = cur_secs;
// note that 'secs' is now set to DBL_MAX so cur_secs will not be updated on this row iteration
}
// if this note was marked to skip then don't advance j (and thereby
// write over this scEvt with the next note). ...
if( cmIsFlag(p->array[j].flags,kSkipScFl) == false )
{
p->array[j].index = j;
p->array[j].index = j; // ... otherwise advance j
++j;
}
@ -1308,6 +1321,51 @@ cmScRC_t _cmScParseFile( cmSc_t* p, cmCtx_t* ctx, const cmChar_t* fn )
}
break;
case kCtlEvtScId:
{
unsigned d0 = cmCsvCellUInt( p->cH,i,kD0ColScIdx);
unsigned d1 = cmCsvCellUInt( p->cH,i,kD1ColScIdx);
// if this is a pedal event
if( pedalBaseMidiId <= d0 && d0 < pedalBaseMidiId + pedalN )
{
bool pedalDnFl = d1 >= 64;
unsigned pedalIdx = d0 - pedalBaseMidiId;
assert( pedalBaseMidiId <= pedalIdx && pedalIdx < pedalN );
// store the pedal type identifer in the pitch field
p->array[j].pitch = d0;
// if this is a pedal-down message ...
if( pedalDnFl )
{
if( pedalV[pedalIdx] != NULL )
cmErrWarnMsg(&p->err,kPedalInvalidScRC,"The score contains multiple pedal down messages withouth an intervening pedal up message in or near bar %i.",barNumb );
else
pedalV[pedalIdx] = p->array + j; // ... store a pointer to the scEvt recd in pedalV[]
p->array[j].flags |= kPedalDnFl;
}
else // ... else this is a pedal-up msg ...
{
p->array[j].flags |= kPedalUpFl;
if( pedalV[pedalIdx] == NULL )
cmErrWarnMsg(&p->err,kPedalInvalidScRC,"The score contains multiple pedal up messages withouth an intervening pedal down message in or near bar %i.",barNumb );
else // ... update the pedal down duration in the pedal-down message assoc'd w/ this pedal-up msg.
{
pedalV[pedalIdx]->durSecs = p->array[j].secs - pedalV[pedalIdx]->secs;
pedalV[pedalIdx] = NULL;
}
}
}
}
// fall through
default:
// Returns DBL_MAX on error.
secs = cmCsvCellDouble(p->cH, i, kSecsColScIdx );
@ -1316,6 +1374,7 @@ cmScRC_t _cmScParseFile( cmSc_t* p, cmCtx_t* ctx, const cmChar_t* fn )
if( rc == kOkScRC )
{
// if sec's is valid then update cur_secs
if( secs != DBL_MAX )
cur_secs = secs;
@ -1423,7 +1482,6 @@ cmScRC_t _cmScInitLocArray( cmSc_t* p )
return rc;
}
cmScRC_t cmScoreInitialize( cmCtx_t* ctx, cmScH_t* hp, const cmChar_t* fn, double srate, const unsigned* dynRefArray, unsigned dynRefCnt, cmScCb_t cbFunc, void* cbArg, cmSymTblH_t stH )
{
cmScRC_t rc = kOkScRC;
@ -2589,3 +2647,5 @@ void cmScoreFix( cmCtx_t* ctx )
cmCsvFinalize(&csvH);
}

View File

@ -13,7 +13,8 @@ extern "C" {
kInvalidIdxScRC,
kTimeLineFailScRC,
kInvalidDynRefCntScRC,
kMidiFileFailScRC
kMidiFileFailScRC,
kPedalInvalidScRC
};
enum
@ -31,7 +32,8 @@ extern "C" {
kBarEvtScId,
kPgmEvtScId,
kCtlEvtScId,
kNonEvtScId
kNonEvtScId,
kPedalEvtScId
};
// Flags used by cmScoreEvt_t.flags
@ -42,7 +44,9 @@ extern "C" {
kTempoScFl = 0x004, // This note is marked for tempo measurement
kSkipScFl = 0x008, // This isn't a real event (e.g. tied note) skip over it
kGraceScFl = 0x010, // This is a grace note
kInvalidScFl = 0x020 // This note has a calculated time
kInvalidScFl = 0x020, // This note has a calculated time
kPedalDnFl = 0x040, // This is a pedal down event (pitch holds the pedal id and durSecs holds the time the pedal will remain down.)
kPedalUpFl = 0x080 // This is a pedal up event (pitch holds the pedal id)
};
@ -79,7 +83,7 @@ extern "C" {
double durSecs; // Duration in seconds
unsigned index; // Index of this event in the event array.
unsigned locIdx; // Index of the location containing this event
cmMidiByte_t pitch; // MIDI pitch of this note
cmMidiByte_t pitch; // MIDI pitch of this note or the MIDI pedal id of pedal down/up msg (64=sustain 65=sostenuto 66=soft)
unsigned flags; // Attribute flags for this event
unsigned dynVal; // Dynamcis value pppp to ffff (1 to 11) for this note.
double frac; // Note's time value for tempo and non-grace evenness notes.