use of com.xenoage.zong.io.midi.out.dynamics.type.GradientDynamics in project Zong by Xenoage.
the class DynamicsFinder method findStaffDynamics.
/**
* Walk through the measures of the given staff and repetition and find the dynamics.
* Starts with the given initial dynamic. Returns the dynamic value at the end of the
* repetition.
*/
private DynamicValue findStaffDynamics(int staff, int repetition, DynamicValue startDynamics) {
val rep = repetitions.get(repetition);
// walk through the measures
Time currentStartTime = rep.start;
DynamicsType currentDynamic = new FixedDynamics(startDynamics);
for (int iMeasure : range(rep.start.getMeasure(), rep.end.getMeasure())) {
if (iMeasure >= score.getMeasuresCount())
break;
val measure = score.getMeasure(atMeasure(staff, iMeasure));
for (val beat : measure.getDirections().getBeats()) {
val newTime = Companion.time(iMeasure, beat);
DynamicsType newDynamic = null;
// if beat is out of the repetition range, ignore it
if (false == rep.contains(newTime))
continue;
// find dynamics change
if (currentDynamic instanceof GradientDynamics) {
// wedge ending at this beat?
val closedWedge = getWedgeEndAt(staff, newTime, (GradientDynamics) currentDynamic);
if (closedWedge != null) {
currentDynamic = closedWedge;
// continue with the end dynamic of the wedge
newDynamic = new FixedDynamics(closedWedge.end);
}
} else if (newDynamic == null) {
// new dynamic starting? then close currently open period and open new one
newDynamic = getStaffDynamicStartAt(staff, newTime, currentDynamic.getEndValue());
}
// when change was found, apply it
if (newDynamic != null) {
if (false == currentStartTime.equals(newTime) && false == currentDynamic.equals(newDynamic)) {
val period = new DynamicsPeriod(currentStartTime, newTime, currentDynamic);
periods.addPeriodToStaff(period, staff, repetition);
currentStartTime = newTime;
}
currentDynamic = newDynamic;
}
}
}
// close the dynamics period at the end of the repetition
val period = new DynamicsPeriod(currentStartTime, rep.end, currentDynamic);
periods.addPeriodToStaff(period, staff, repetition);
return currentDynamic.getEndValue();
}
use of com.xenoage.zong.io.midi.out.dynamics.type.GradientDynamics in project Zong by Xenoage.
the class DynamicsFinder method getStaffDynamicStartAt.
/**
* Returns the {@link DynamicsType} starting at the given time within the given staff (not a voice),
* or null, if nothing starts here.
*/
@MaybeNull
private DynamicsType getStaffDynamicStartAt(int staff, Time time, DynamicValue currentDynamicValue) {
val measure = score.getMeasure(atMeasure(staff, time.getMeasure()));
// when there is a Wedge (possible with a Dynamic as the start volume), create
// a gradient dynamic, when there is only a Dynamic, create a fixed dynamic
val foundDynamic = (Dynamic) measure.getDirections().get(time.getBeat(), MusicElementType.Dynamic);
val foundWedge = (Wedge) measure.getDirections().get(time.getBeat(), MusicElementType.Wedge);
if (foundWedge != null) {
// gradient
val startDynamicValue = (foundDynamic != null ? foundDynamic.getValue() : currentDynamicValue);
val endDynamicValue = startDynamicValue.getWedgeEndValue(foundWedge.getType());
// can be replaced later, when end dynamic is found
return new GradientDynamics(startDynamicValue, endDynamicValue);
} else if (foundDynamic != null) {
// fixed value
return new FixedDynamics(foundDynamic.getValue());
}
return null;
}
use of com.xenoage.zong.io.midi.out.dynamics.type.GradientDynamics in project Zong by Xenoage.
the class DynamicsFinderTest method getAdvancedExpectedPeriods.
/**
* See {@link #testAdvanced()}.
*/
private DynamicsPeriods getAdvancedExpectedPeriods() {
val d = new DynamicsPeriodsBuilder();
// staff 0
d.addPeriodToStaff(new DynamicsPeriod(Companion.time(0, Companion.get_0()), Companion.time(2, Companion.get_0()), new FixedDynamics(mp)), 0, 0);
d.addPeriodToStaff(new DynamicsPeriod(Companion.time(2, Companion.get_0()), Companion.time(3, Companion.get_0()), new FixedDynamics(pp)), 0, 0);
d.addPeriodToStaff(new DynamicsPeriod(Companion.time(1, Companion.get_0()), Companion.time(3, Companion.get_1$2()), new FixedDynamics(pp)), 0, 1);
d.addPeriodToStaff(new DynamicsPeriod(Companion.time(3, Companion.get_1$2()), Companion.time(3, Companion.get_3$4()), new FixedDynamics(f)), 0, 1);
d.addPeriodToStaff(new DynamicsPeriod(Companion.time(3, Companion.get_3$4()), Companion.time(4, Companion.get_1$4()), new GradientDynamics(f, ff)), 0, // ff: implicit target after f-cresc
1);
d.addPeriodToStaff(new DynamicsPeriod(Companion.time(4, Companion.get_1$4()), Companion.time(4, Companion.get_1$2()), new FixedDynamics(ff)), 0, 1);
d.addPeriodToStaff(new DynamicsPeriod(Companion.time(4, Companion.get_1$2()), Companion.time(5, Companion.get_0()), new FixedDynamics(pp)), 0, 1);
/* TODO: ZONG-100
//voice 1 in staff 0
d.addPeriodToVoice(new DynamicsPeriod(
time(0, _1$2), time(3, _0), new FixedDynamics(mf)), 0, 1, 0); */
// only 1st time; we do not see the mf again
// staff 1
d.addPeriodToStaff(new DynamicsPeriod(Companion.time(0, Companion.get_0()), Companion.time(2, Companion.get_0()), new GradientDynamics(ff, mp)), 1, 0);
d.addPeriodToStaff(new DynamicsPeriod(Companion.time(2, Companion.get_0()), Companion.time(3, Companion.get_0()), new FixedDynamics(mp)), 1, 0);
d.addPeriodToStaff(new // f remains, we do not jump in the middle of a cresc
DynamicsPeriod(Companion.time(1, Companion.get_0()), Companion.time(3, Companion.get_0()), new FixedDynamics(mp)), 1, 1);
d.addPeriodToStaff(new DynamicsPeriod(Companion.time(3, Companion.get_0()), Companion.time(5, Companion.get_0()), new FixedDynamics(p)), 1, 1);
return d.build();
}
use of com.xenoage.zong.io.midi.out.dynamics.type.GradientDynamics in project Zong by Xenoage.
the class DynamicsFinder method getWedgeEndAt.
/**
* Checks, if there is a {@link WedgeEnd} at the given time within the given staff (not a voice).
* If yes, the given open wedge is closed and returned.
*/
@MaybeNull
private GradientDynamics getWedgeEndAt(int staff, Time time, GradientDynamics openWedge) {
val measure = score.getMeasure(atMeasure(staff, time.getMeasure()));
val foundDynamic = (Dynamic) measure.getDirections().get(time.getBeat(), MusicElementType.Dynamic);
val foundWedgeEnd = (WedgeEnd) measure.getDirections().get(time.getBeat(), MusicElementType.WedgeEnd);
if (foundWedgeEnd != null) {
val endDynamicValue = (foundDynamic != null ? foundDynamic.getValue() : openWedge.end);
return new GradientDynamics(openWedge.start, endDynamicValue);
}
return null;
}
Aggregations