示例#1
0
        /// <summary>Writes a MIDI file header out to the stream.</summary>
        /// <param name="outputStream">The output stream to which the header should be written.</param>
        /// <param name="numTracks">The number of tracks that will be a part of this sequence.</param>
        /// <remarks>This functionality is automatically performed during a Save.</remarks>
        private void WriteHeader(Stream outputStream, int numTracks)
        {
            // Check parameters
            Validate.NonNull("outputStream", outputStream);
            Validate.InRange("numTracks", numTracks, 1, int.MaxValue);

            // Write out the main header for the sequence
            MThdChunkHeader mainHeader = new MThdChunkHeader(Format, numTracks, m_division);

            mainHeader.Write(outputStream);
        }
示例#2
0
        /// <summary>Trims a MIDI file to a specified length.</summary>
        /// <param name="sequence">The sequence to be copied and trimmed.</param>
        /// <param name="startTime"></param>
        /// <param name="totalTime">The requested time length of the new MIDI sequence.</param>
        /// <returns>A MIDI sequence with only those events that fell before the requested time limit.</returns>
        public static MidiSequence Trim(this MidiSequence sequence, long startTime, long totalTime)
        {
            Validate.NonNull("sequence", sequence);
            Validate.InRange("startTime", startTime, 0, long.MaxValue);
            Validate.InRange("totalTime", totalTime, 0, long.MaxValue);

            // Create a new sequence to mimic the old
            MidiSequence newSequence = new MidiSequence(sequence.Format, sequence.Division);

            // Copy each track up to the specified time limit
            foreach (MidiTrack track in sequence)
            {
                // Create a new track in the new sequence to match the old track in the old sequence
                MidiTrack newTrack = newSequence.Tracks.AddNewTrack();

                // Convert all times in the old track to deltas
                track.Events.ConvertDeltasToTotals();
                int i = 0;

                for (i = 0; track.Events[i].DeltaTime < startTime; i++)
                {
                }

                // Copy over all events that fell before the specified time
                for (int j = i; j < track.Events.Count && track.Events[j].DeltaTime < totalTime; j++)
                {
                    newTrack.Events.Add(track.Events[j].DeepClone());
                }

                // Convert all times back (on both new and old tracks; the new one inherited the totals)
                track.Events.ConvertTotalsToDeltas();
                newTrack.Events.ConvertTotalsToDeltas();

                newTrack.Events[0].DeltaTime = 0;

                // If the new track lacks an end of track, add one
                if (!newTrack.HasEndOfTrack)
                {
                    newTrack.Events.Add(new EndOfTrackMetaMidiEvent(0));
                }
            }

            // Return the new sequence
            return(newSequence);
        }
        /// <summary>Converts the MIDI sequence into a new one with the desired format.</summary>
        /// <param name="sequence">The sequence to be converted.</param>
        /// <param name="format">The format to which we want to convert the sequence.</param>
        /// <param name="options">Options used when doing the conversion.</param>
        /// <returns>The new, converted sequence.</returns>
        public static MidiSequence Convert(this MidiSequence sequence, Format format, FormatConversionOption options)
        {
            Validate.NonNull("sequence", sequence);
            Validate.InRange("format", (int)format, (int)Format.Zero, (int)Format.Two);

            if (sequence.Format == format)
            {
                // If the desired format is the same as the original, just return a copy.
                // No transformation is necessary.
                sequence = new MidiSequence(sequence);
            }
            else if (format != Format.Zero || sequence.Tracks.Count == 1)
            {
                // If the desired format is is not 0 or there's only one track, just copy the sequence with a different format number.
                // If it's not zero, then multiple tracks are acceptable, so no transformation is necessary.
                // Or if there's only one track, then there's no possible transformation to be done.
                var newSequence = new MidiSequence(format, sequence.Division);
                foreach (MidiTrack t in sequence)
                {
                    newSequence.Tracks.Add(new MidiTrack(t));
                }
                sequence = newSequence;
            }
            else
            {
                // Now the harder cases, converting to format 0.  We need to combine all tracks into 1,
                // as format 0 requires that there only be a single track with all of the events for the song.
                sequence = new MidiSequence(sequence);

                // Iterate through all events in all tracks and change deltaTimes to actual times.
                // We'll then be able to sort based on time and change them back to deltas later.
                foreach (MidiTrack track in sequence)
                {
                    track.Events.ConvertDeltasToTotals();
                }

                // Add all events to new track (except for end of track markers!)
                int       trackNumber = 0;
                MidiTrack newTrack    = new MidiTrack();
                foreach (MidiTrack track in sequence)
                {
                    foreach (MidiEvent midiEvent in track.Events)
                    {
                        // If this event has a channel, and if we're storing tracks as channels, copy to it
                        if ((options & FormatConversionOption.CopyTrackToChannel) > 0 && trackNumber >= 0 && trackNumber <= 0xF)
                        {
                            var vme = midiEvent as VoiceMidiEvent;
                            if (vme != null)
                            {
                                vme.Channel = (byte)trackNumber;
                            }
                        }

                        // Add all events, except for end of track markers (we'll add our own)
                        if (!(midiEvent is EndOfTrackMetaMidiEvent))
                        {
                            newTrack.Events.Add(midiEvent);
                        }
                    }
                    trackNumber++;
                }

                // Sort the events by total time, then convert back to delta time,
                // and top things off with an end-of-track marker.
                newTrack.Events.Sort((x, y) => x.DeltaTime.CompareTo(y.DeltaTime));
                newTrack.Events.ConvertTotalsToDeltas();
                newTrack.Events.Add(new EndOfTrackMetaMidiEvent(0));

                // We now have all of the combined events in newTrack.  Clear out the sequence, replacing all the tracks
                // with this new one.
                sequence.Tracks.Clear();
                sequence.Tracks.Add(newTrack);
            }

            return(sequence);
        }