Пример #1
0
        /** 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);
        }
Пример #2
0
        /** 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));
        }
Пример #3
0
        /** 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);
              }
        }
Пример #4
0
        /** 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;
        }
Пример #5
0
        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());
        }
Пример #6
0
        /** 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);
        }
Пример #7
0
 /** 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);
 }
Пример #8
0
 /** 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);
 }
Пример #9
0
        /** 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);
            }
        }