示例#1
0
 /// <summary>
 /// Initializes a new instance of the Track class with another instance
 /// of the Track class.
 /// </summary>
 /// <param name="trk">
 /// The Track instance to use for initialization.
 /// </param>
 public Track(Track trk)
 {
     // Copy events from the existing track into this one.
     foreach(MidiEvent e in trk.midiEvents)
     {
         this.midiEvents.Add(e.Clone());
     }
 }
示例#2
0
        /// <summary>
        /// Initializes a new instance of the TrackPlayer class with the 
        /// specified MIDI sender, tick generator, and track.
        /// </summary>
        /// <param name="midiSender">
        /// The MIDI sender to use for sending MIDI messages.
        /// </param>
        /// <param name="tickGen">
        /// The tick generator used for timing the playback of MIDI messages.
        /// </param>
        /// <param name="trk">
        /// The track to play back.
        /// </param>
        public TrackPlayer(IMidiSender midiSender, TickGenerator tickGen, Track trk)
        {
            this._midiSender = midiSender;
            this.tickGen = tickGen;
            this.trk = trk;

            tickGen.Tick += new EventHandler(TickHandler);

            // Set playback position at the beginning of the track.
            Seek(0);
        }
示例#3
0
        /// <summary>
        /// Reads the number of tracks in the Midi file.
        /// </summary>
        /// <returns>
        /// <b>MidiFileResult.Succes</b> if the track count and format type 
        /// are valid; otherwise, <b>MidiFileResult.InvalidFormat</b>.
        /// </returns>
        private MidiFileResult ReadTrackCount()
        {
            MidiFileResult result = MidiFileResult.Success;
            byte[] trackCount = binReader.ReadBytes(TrackCountByteCount);

            // Convert array to the same byte order as this platform.
            ConvertByteArray(trackCount);

            // Convert array to number.
            tracks = new Track[BitConverter.ToInt16(trackCount, 0)];

            // If there are more than one track and the Midi file is type 0.
            if(tracks.Length > 1 && Format == 0)
            {
                // Indicate that the format is invalid. A type 0 Midi file can
                // only have one track.
                result = MidiFileResult.InvalidFormat;
            }

            // If the format is valid.
            if(result == MidiFileResult.Success)
            {
                // Allocate tracks.
                for(int i = 0; i < tracks.Length; i++)
                {
                    tracks[i] = new Track();
                }
            }

            return result;
        }
示例#4
0
 /// <summary>
 /// Initializes a new instance of the TrackEnumerator class with 
 /// the specified track to iterate over.
 /// </summary>
 /// <param name="owner">
 /// The track to iterate over.
 /// </param>
 public TrackEnumerator(Track owner)
 {
     this.owner = owner;
     version = owner.Version;
 }
示例#5
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="tracks"></param>
        /// <returns></returns>
        public static Track Merge(ArrayList tracks)
        {
            Track mergedTrack = new Track();
            Track currentTrack;
            ArrayList trackList = new ArrayList();
            ArrayList events = new ArrayList();
            ArrayList trackIndexes = new ArrayList();

            for(int i = 0; i < tracks.Count; i++)
            {
                currentTrack = (Track)tracks[i];

                if(currentTrack.Count > 1)
                {
                    trackList.Add(currentTrack);
                    trackIndexes.Add(0);
                    events.Add(currentTrack[0]);
                }
            }

            while(events.Count > 0)
            {
                int n = 0;
                MidiEvent e1 = (MidiEvent)events[0];
                MidiEvent e2;
                int ticks = e1.Ticks;

                for(int i = 1; i < events.Count; i++)
                {
                    e1 = (MidiEvent)events[i];

                    if(e1.Ticks < ticks)
                    {
                        ticks = e1.Ticks;
                        n = i;
                    }
                }

                e1 = (MidiEvent)events[n];
                mergedTrack.Add(e1);

                for(int i = 0; i < events.Count; i++)
                {
                    e2 = (MidiEvent)events[i];
                    e2.Ticks -= e1.Ticks;
                    events[i] = e2;
                }

                int counter = (int)trackIndexes[n] + 1;

                currentTrack = (Track)trackList[n];

                if(counter < currentTrack.Count - 1)
                {
                    events[n] = currentTrack[counter];
                    trackIndexes[n] = counter;
                }
                else
                {
                    trackList.RemoveAt(n);
                    trackIndexes.RemoveAt(n);
                    events.RemoveAt(n);
                }
            }

            return mergedTrack;
        }
示例#6
0
        /// <summary>
        /// Merges two tracks together.
        /// </summary>
        /// <param name="trackA">
        /// The first of two tracks to merge.
        /// </param>
        /// <param name="trackB">
        /// The second of two tracks to merge.
        /// </param>
        /// <returns>
        /// The merged track.
        /// </returns>
        public static Track Merge(Track trackA, Track trackB)
        {
            Track trkA = new Track(trackA);
            Track trkB = new Track(trackB);
            Track mergedTrack = new Track();
            int a = 0, b = 0;

            //
            // The following algorithm merges two Midi tracks together. It
            // assumes that both tracks are valid in that both end with a
            // end of track meta message.
            //

            // While neither the end of track A or track B has been reached.
            while(a < trkA.Count - 1 && b < trkB.Count - 1)
            {
                // While the end of track A has not been reached and the
                // current Midi event in track A comes before the current Midi
                // event in track B.
                while(a < trkA.Count - 1 && trkA[a].Ticks <= trkB[b].Ticks)
                {
                    // Slide the events in track B backwards by the amount of
                    // ticks in the current event in track A. This keeps both
                    // tracks in sync.
                    trkB.Slide(b, -trkA[a].Ticks);

                    // Add the current event in track A to the merged track.
                    mergedTrack.Add(trkA[a]);

                    // Move to the next Midi event in track A.
                    a++;
                }

                // If the end of track A has not yet been reached.
                if(a < trkA.Count - 1)
                {
                    // While the end of track B has not been reached and the
                    // current Midi event in track B comes before the current Midi
                    // event in track A.
                    while(b < trkB.Count - 1 && trkB[b].Ticks < trkA[a].Ticks)
                    {
                        // Slide the events in track A backwards by the amount of
                        // ticks in the current event in track B. This keeps both
                        // tracks in sync.
                        trkA.Slide(a, -trkB[b].Ticks);

                        // Add the current event in track B to the merged track.
                        mergedTrack.Add(trkB[b]);

                        // Move forward to the next Midi event in track B.
                        b++;
                    }
                }
            }

            // If the end of track A has not yet been reached.
            if(a < trkA.Count - 1)
            {
                // Add the rest of the events in track A to the merged track.
                while(a < trkA.Count - 1)
                {
                    mergedTrack.Add(trkA[a]);
                    a++;
                }
            }
                // Else if the end of track B has not yet been reached.
            else if(b < trkB.Count - 1)
            {
                // Add the rest of the events in track B to the merged track.
                while(b < trkB.Count - 1)
                {
                    mergedTrack.Add(trkB[b]);
                    b++;
                }
            }

            return mergedTrack;
        }
示例#7
0
        /// <summary>
        /// Removes the specified track from the sequence.
        /// </summary>
        /// <param name="trk">
        /// The track to remove.
        /// </param>
        /// <exception cref="InvalidOperationException">
        /// Thrown if the sequence is currently locked.
        /// </exception>
        public void Remove(Track trk)
        {
            // Enforce preconditions.
            if(IsLocked())
                throw new InvalidOperationException(
                    "Cannot modify sequence. It is currently locked.");

            int i = 0;

            while(i < tracks.Count)
            {
                DictionaryEntry de = (DictionaryEntry)tracks[i];

                if((Track)de.Key == trk)
                {
                    tracks.RemoveAt(i);
                    break;
                }
                else
                {
                    i++;
                }
            }

            version++;
        }
示例#8
0
        /// <summary>
        /// Adds a track to the Sequence.
        /// </summary>
        /// <param name="trk">
        /// The track to add to the Sequence.
        /// </param>
        /// <exception cref="InvalidOperationException">
        /// Thrown if the sequence is currently locked.
        /// </exception>
        public void Add(Track trk)
        {
            // Enforce preconditions.
            if(IsLocked())
                throw new InvalidOperationException(
                    "Cannot modify sequence. It is currently locked.");

            tracks.Add(new DictionaryEntry(trk, trk.Version));

            version++;
        }
示例#9
0
        /// <summary>
        /// Writes the specified track to MIDI file.
        /// </summary>
        /// <param name="trk">
        /// The track to write to the MIDI file.
        /// </param>
        private void WriteTrack(Track trk)
        {
            writer.Write(TrackHeaderID);

            //
            // The length of the track in bytes will be written to the
            // MIDI file first. However, at this point, the length is unknown.
            //
            // The track is written to a memory stream first. After this is
            // done, the length of the track can be retrieved from the stream.
            // This value is written to the MIDI file followed by the contents
            // of the stream.
            //

            midiStream = new MemoryStream();

            MessageWriter msgWriter = new MessageWriter(midiStream);

            // Write each MIDI event to the stream via the message writer.
            for(int i = 0; i < trk.Count; i++)
            {
                msgWriter.WriteNextEvent(trk[i]);
            }

            // Get the length of the track.
            int trackLength = (int)midiStream.Length;

            // Convert value if this platform uses the little endian format.
            if(BitConverter.IsLittleEndian)
            {
                byte[] b = BitConverter.GetBytes(trackLength);
                Array.Reverse(b);
                trackLength = BitConverter.ToInt32(b, 0);
            }

            // Write track length.
            writer.Write(trackLength);

            midiStream.Position = 0;

            // Write the contents of the stream to the MIDI file.
            for(int i = 0; i < midiStream.Length; i++)
            {
                writer.Write((byte)midiStream.ReadByte());
            }
        }