/** Return the duration of this staff system. This is the start time * difference between the first and last measure start time slices in the * first staff plus the duration of the last measure. (It is assumed that all * staves in the staff system have the same duration.) * This is used to compute the screen hotspots of the measure starts. */ public Rational getDuration() { if (_duration != null) { return(_duration); } if (getStaffCount() == 0 || getStaff(0).getMeasureStartCount() == 0) { // There are no staffs or time slices! This is unexpected. Just return 0. // DEBUG: maybe this should be handled more gracefully. _duration = new Rational(0, 1); return(_duration); } Staff staff = getStaff(0); MeasureStartTimeSlice lastMeasureStart = staff.getMeasureStart(staff.getMeasureStartCount() - 1); IntRatio result = new IntRatio(lastMeasureStart.getStartTime()); result.sub(getStartTime()); result.add(lastMeasureStart.getDuration()); _duration = new Rational(result); return(_duration); }
/** This is a utility function to return the screen X position of * a left-positioned symbol (as defined by isLeftPositioned()). * This finds the hotspot of the next symbol in the time slice * which isLeftPositioned() (or the hotspot of the time slice itself * if there are no more) and subtracts from its X value * the (measure width - 10) / (the measure symbol count - 1). */ protected int findLeftPositionedX() { FinalPoint nextHotspot = null; for (int i = getIndex() + 1; i < getParentTimeSlice().getMusicSymbolCount(); ++i) { MusicSymbol nextSymbol = getParentTimeSlice().getMusicSymbol(i); if (nextSymbol.isLeftPositionedSymbol()) { nextHotspot = nextSymbol.getScreenHotspot(); break; } } if (nextHotspot == null) { // No next left positioned symbol, so use the time slice nextHotspot = getParentTimeSlice().getScreenHotspot(); } MeasureStartTimeSlice measure = getParentTimeSlice().getParentMeasureStart(); // Note that we know measure.getSymbolCount() is at least one return(nextHotspot.x - (measure.getWidth() - 10) / (measure.getSymbolCount() - 1)); }
/** This reads event TimeSlice chunks from parentInput's input stream until the next * measure start time slice or no more bytesRemaining in the parentInput, * adding the TimeSlice objects to the measureStart's time slice list. * When this reads the TimeSlice, it also adds the subsequent music * symbols to it. * * @param parentInput the parent RIFF object being used to read the input stream * @param measureStart the MeasureStartTimeSlice to which TimeSlice * objects are added. * @see TimeSlice */ public static void addTimeSlices(Riff parentInput, MeasureStartTimeSlice measureStart) { if (parentInput.getBytesRemaining() <= 0) // This is a measure start time slice with nothing after it in the staff return; if (parentInput.peekFOURCC().Equals(RIFF_ID) && parentInput.peekFirstChunkBYTE() == MEASURE_START) // The next chunk is already the start of a new measure return; TimeSlice timeSlice = RiffTimeSlice.maybeNew(parentInput); if (timeSlice == null) // For some reason, the first chunk after the measure start // time slice is not an event time slice. Create a fake one with // start time of 0/1. // DEBUG: should mock up an input file and test this. timeSlice = new TimeSlice(new Rational(0, 1), null); while (true) { if (measureStart.getTimeSliceCount() > 0 && measureStart.getTimeSlice (measureStart.getTimeSliceCount() - 1).getStartTime().Equals (timeSlice.getStartTime())) // This new time slice start time is the same as the last one, // so just continue using the last one. // DEBUG: this still doesn't ensure increasing order // DEBUG: This discards the tags in the newly read time slice timeSlice = measureStart.getTimeSlice(measureStart.getTimeSliceCount() - 1); else measureStart.addTimeSlice(timeSlice); // Read music symbols until the next time slice or // end of the staff. RiffTimeSlice.addMusicSymbols(parentInput, timeSlice); if (parentInput.getBytesRemaining() <= 0) // reached the end of the staff break; // We know the next chunk is a time slice. Check whether it is // a measure start. if (parentInput.peekFirstChunkBYTE() == MEASURE_START) // The next chunk is the start of a new measure break; // We have now ensured that the next chunk is an event time slice. timeSlice = RiffTimeSlice.newInstance(parentInput); } }
/** Creates new Staff from the parentInput's input stream. * The next object in the input stream must be of this type. * This also reads all the enclosed MeasureStartTimeSlice objects * which themselves contain the event TimeSlice and MusicSymbol objects. * * @param parentInput the parent RIFF object being used to read the input stream */ public static Staff newInstance(Riff parentInput) { Riff riffInput = new Riff(parentInput, "LIST"); riffInput.requireFOURCC(RIFF_ID); Staff staff = new Staff(RiffStaffHeader.newInstance(riffInput)); if (riffInput.getBytesRemaining() <= 0) // the staff is empty return staff; MeasureStartTimeSlice measureStart = RiffMeasureStartTimeSlice.maybeNew(riffInput); if (measureStart == null) { // For some reason, the first chunk in this staff is not a // measure start time slice. Create a fake one based // on the previous staff system's end time // DEBUG: must implement this! For now use start time of 0/1 measureStart = new MeasureStartTimeSlice(new Rational(0, 1), null); } while (true) { if (staff.getMeasureStartCount() > 0 && staff.getMeasureStart (staff.getMeasureStartCount() - 1).getStartTime().Equals (measureStart.getStartTime())) // This new measure start time is the same as the last one, // so just continue using the last one. // DEBUG: this still doesn't ensure increasing order // DEBUG: This discards the tags in the newly read measure start measureStart = staff.getMeasureStart(staff.getMeasureStartCount() - 1); else staff.addMeasureStart(measureStart); // Read event time slices until the next measure start time slice or // end of the staff RiffMeasureStartTimeSlice.addTimeSlices(riffInput, measureStart); if (riffInput.getBytesRemaining() <= 0) // reached the end of the staff break; // The previous call to readTimeSlices has already // ensured that the next chunk is a measure start time slice. measureStart = RiffMeasureStartTimeSlice.newInstance(riffInput); } return staff; }
public int getSymbolCount() { if (_symbolPositioner != null) { return(_symbolPositioner.getSymbolCount()); } // Create a new SymbolPositioner and add a position at each quarter note. _symbolPositioner = new SymbolPositioner(); Rational quarter = new Rational(1, 4); for (IntRatio r = new IntRatio(0, 1); r.compareTo(getDuration()) < 0; r.add(quarter)) { _symbolPositioner.add(new Rational(r), 0); } // Go through the entire staff system and for every measure which // has the same start time and duration as this, set its // SymbolPositioner to the new one and call its addToSymbolPositioner StaffSystem system = getParentStaff().getParentSystem(); for (int staffIndex = 0; staffIndex < system.getStaffCount(); ++staffIndex) { Staff staff = system.getStaff(staffIndex); for (int measureIndex = 0; measureIndex < staff.getMeasureStartCount(); ++measureIndex) { MeasureStartTimeSlice measure = staff.getMeasureStart(measureIndex); if (measure.getStartTime().Equals(getStartTime()) && measure.getDuration().Equals(getDuration())) { // This is an equivalent measure to this one in another // staff (or it is this same measure. measure._symbolPositioner = _symbolPositioner; measure.addToSymbolPositioner(); // There should not be any more measures in this staff // with the same start time. break; } } } return(_symbolPositioner.getSymbolCount()); }
/** Creates new Staff from the parentInput's input stream. * The next object in the input stream must be of this type. * This also reads all the enclosed MeasureStartTimeSlice objects * which themselves contain the event TimeSlice and MusicSymbol objects. * * @param parentInput the parent RIFF object being used to read the input stream */ static public Staff newInstance(Riff parentInput) { Riff riffInput = new Riff(parentInput, "LIST"); riffInput.requireFOURCC(RIFF_ID); Staff staff = new Staff(RiffStaffHeader.newInstance(riffInput)); if (riffInput.getBytesRemaining() <= 0) { // the staff is empty return(staff); } MeasureStartTimeSlice measureStart = RiffMeasureStartTimeSlice.maybeNew(riffInput); if (measureStart == null) { // For some reason, the first chunk in this staff is not a // measure start time slice. Create a fake one based // on the previous staff system's end time // DEBUG: must implement this! For now use start time of 0/1 measureStart = new MeasureStartTimeSlice(new Rational(0, 1), null); } while (true) { if (staff.getMeasureStartCount() > 0 && staff.getMeasureStart (staff.getMeasureStartCount() - 1).getStartTime().Equals (measureStart.getStartTime())) { // This new measure start time is the same as the last one, // so just continue using the last one. // DEBUG: this still doesn't ensure increasing order // DEBUG: This discards the tags in the newly read measure start measureStart = staff.getMeasureStart(staff.getMeasureStartCount() - 1); } else { staff.addMeasureStart(measureStart); } // Read event time slices until the next measure start time slice or // end of the staff RiffMeasureStartTimeSlice.addTimeSlices(riffInput, measureStart); if (riffInput.getBytesRemaining() <= 0) { // reached the end of the staff break; } // The previous call to readTimeSlices has already // ensured that the next chunk is a measure start time slice. measureStart = RiffMeasureStartTimeSlice.newInstance(riffInput); } return(staff); }
/** Add the given measure start timeslice to the MeasureStartTimeSlice list. * This does not call invalidate(), but you may need to before displaying. * * @param measureStart the MeasureStartTimeSlice to add. It is an error if * this is already the child of an object. * @throws HeirarchyException if the measureStart has already * been added as a child to another object. * @see #invalidate */ public void addMeasureStart(MeasureStartTimeSlice measureStart) { addChild(measureStart); }
/** This reads event TimeSlice chunks from parentInput's input stream until the next * measure start time slice or no more bytesRemaining in the parentInput, * adding the TimeSlice objects to the measureStart's time slice list. * When this reads the TimeSlice, it also adds the subsequent music * symbols to it. * * @param parentInput the parent RIFF object being used to read the input stream * @param measureStart the MeasureStartTimeSlice to which TimeSlice * objects are added. * @see TimeSlice */ static public void addTimeSlices (Riff parentInput, MeasureStartTimeSlice measureStart) { if (parentInput.getBytesRemaining() <= 0) { // This is a measure start time slice with nothing after it in the staff return; } if (parentInput.peekFOURCC().Equals(RIFF_ID) && parentInput.peekFirstChunkBYTE() == MEASURE_START) { // The next chunk is already the start of a new measure return; } TimeSlice timeSlice = RiffTimeSlice.maybeNew(parentInput); if (timeSlice == null) { // For some reason, the first chunk after the measure start // time slice is not an event time slice. Create a fake one with // start time of 0/1. // DEBUG: should mock up an input file and test this. timeSlice = new TimeSlice(new Rational(0, 1), null); } while (true) { if (measureStart.getTimeSliceCount() > 0 && measureStart.getTimeSlice (measureStart.getTimeSliceCount() - 1).getStartTime().Equals (timeSlice.getStartTime())) { // This new time slice start time is the same as the last one, // so just continue using the last one. // DEBUG: this still doesn't ensure increasing order // DEBUG: This discards the tags in the newly read time slice timeSlice = measureStart.getTimeSlice(measureStart.getTimeSliceCount() - 1); } else { measureStart.addTimeSlice(timeSlice); } // Read music symbols until the next time slice or // end of the staff. RiffTimeSlice.addMusicSymbols(parentInput, timeSlice); if (parentInput.getBytesRemaining() <= 0) { // reached the end of the staff break; } // We know the next chunk is a time slice. Check whether it is // a measure start. if (parentInput.peekFirstChunkBYTE() == MEASURE_START) { // The next chunk is the start of a new measure break; } // We have now ensured that the next chunk is an event time slice. timeSlice = RiffTimeSlice.newInstance(parentInput); } }