Esempio n. 1
0
        public void ConstrainNotesToMeasureBoundaries()
        {
            foreach (var note in this.Notes)
            {
                //get start and end boundary points for this note
                MidiTime startOfBar = new MidiTime(this.File, note.AveragePosition.Measures, 1, 0, this.TimeSignature);
                MidiTime endOfBar   = new MidiTime(this.File, note.AveragePosition.Measures + 1, 1, 0, this.TimeSignature);

                if (note.StartPosition.GetAsTotalTicks() < startOfBar.GetAsTotalTicks())
                {
                    //note is mostly in current bar but the note starts just before the bar start.
                    //Move the note start to the to start of the measure
                    note.StartPosition = new MidiTime(startOfBar);
                    note.CalculateEndPosition();
                }
                else if (note.EndPosition.GetAsTotalTicks() > endOfBar.GetAsTotalTicks())
                {
                    ///note is mostly in current bar but the note ends just after the bar end.
                    ///Shorten the length of the note.
                    ///This will only rarely happen because at this point the note lengths are 1 and so arent long enough to span two measures
                    note.Length = endOfBar.GetAsTotalTicks() - note.StartPosition.GetAsTotalTicks();
                    note.CalculateEndPosition();
                }
            }
        }
Esempio n. 2
0
 public MidiTime(MidiTime copyMe)
 {
     this.File          = copyMe.File;
     this.TimeSignature = copyMe.TimeSignature;
     this.Measures      = copyMe.Measures;
     this.Beats         = copyMe.Beats;
     this.Ticks         = copyMe.Ticks;
     this.Region        = copyMe.Region;
 }
Esempio n. 3
0
        /// <summary>
        /// the position of the region boundaries are calculated on the fly by using the current time
        /// signature and pulses per QN
        /// </summary>
        /// <param name="position"></param>
        /// <param name="pulsesPerQuarterNote"></param>
        /// <param name="timeSig"></param>
        /// <returns></returns>
        public Region GetRegion(MidiTime position, uint pulsesPerQuarterNote, TimeSignatureEvent timeSig)
        {
            uint posTicks = position.GetAsTotalTicks(pulsesPerQuarterNote, timeSig);

            foreach (Region r in this.Regions)
            {
                if (posTicks >= r.Start.GetAsTotalTicks(pulsesPerQuarterNote, timeSig) &&
                    posTicks < r.End.GetAsTotalTicks(pulsesPerQuarterNote, timeSig))
                {
                    return(r);
                }
            }

            return(null);
        }
Esempio n. 4
0
        public void ConvertToMidiFilesByRegionAndBarAndTrack(String outputPath)
        {
            if (this.Header.FormatType != TrackFormatType.MetaAndChannel)
            {
                throw new ApplicationException("cannot split file");
            }

            List <MidiFile> midiFiles = new List <MidiFile>();

            foreach (TrackChunk origTrack in this.Tracks)
            {
                /// do conversion in this order. by doing these conversions we also remove any
                /// overlapping notes.
                origTrack.MakeAllNotesSameKey(48);    //good for drums where we want the same note for all drum hits
                origTrack.MakeAllNotesSameLength(10); //smallest unit that wont overlap after cleaning duplicates
                //origTrack.ConstrainNotesToMeasureBoundaries();  //makes it easy to put the notes into 'measure' files
                //origTrack.RemoveNotesNotInMeasure();
                origTrack.RemoveNotesWhereNoteStartIsNotWithinMeasure();
                //origTrack.RemoveDuplicateNotes();
                origTrack.RemoveDuplicateNotes();

                //uint currentMeasure = 0;
                uint currentRegionMeasure = 0;

                TrackChunk newTrack            = null;
                MidiFile   newFile             = null;
                Region     currentRegion       = null;
                MidiTime   currentMeasureStart = null;
                Note       lastNote            = null;

                foreach (var note in origTrack.Notes)
                {
                    if (note.StartPosition.Region == null)
                    {
                        Debug.WriteLine(origTrack.TrackName.Text + " null region @" + note.StartPosition);

                        //Debug.WriteLine(note.ToString());
                        continue;
                    }

                    if (note.StartPosition.Region != currentRegion)
                    {
                        ///the first note in a new region
                        ///
                        currentRegion        = note.StartPosition.Region;
                        currentRegionMeasure = 0;   //reset
                    }

                    if (currentMeasureStart == null || note.StartPosition.Measures != currentMeasureStart.Measures)
                    {
                        currentRegionMeasure++;

                        ///the first note in a new measure
                        ///
                        newFile = new MidiFile();

                        String temp = origTrack.TrackName.Text.Substring(0, 2);
                        //if (temp.StartsWith("0"))
                        //    temp = temp.Substring(1);

                        String newTrackName = note.StartPosition.Region.ID + "-B" + currentRegionMeasure + "-T" + temp;
                        newFile.FileNameAndPath = outputPath + Path.DirectorySeparatorChar + newTrackName + ".mid";

                        newFile.Header.NumberOfTracks       = 1;
                        newFile.Header.FormatType           = TrackFormatType.Single;
                        newFile.Header.PulsesPerQuarterNote = this.Header.PulsesPerQuarterNote;
                        midiFiles.Add(newFile);

                        newTrack                 = new TrackChunk();
                        newTrack.TrackName       = new TrackNameEvent(newTrackName);
                        newTrack.TimeSignature   = new TimeSignatureEvent(origTrack.TimeSignature.Numerator, origTrack.TimeSignature.Denominator, origTrack.TimeSignature.MetronomePulse, origTrack.TimeSignature.ThirtySecondNotes);
                        newTrack.Tempo           = new TempoEvent(origTrack.Tempo.MicroSecondsPerQuarterNote, origTrack.TimeSignature.Denominator);
                        newTrack.CopyrightNotice = new CopyrightNoticeEvent("Joe Bacon 2013");
                        newTrack.DeviceName      = new DeviceNameEvent("MIDI-Bacon");
                        newFile.Tracks.Add(newTrack);

                        currentMeasureStart = new MidiTime(this, note.StartPosition.Measures, 1, 0, origTrack.TimeSignature);
                        lastNote            = null;
                    }

                    uint deltaTime = 0;

                    if (lastNote == null)
                    {
                        deltaTime = note.StartPosition.GetAsTotalTicks() - currentMeasureStart.GetAsTotalTicks();  //occurs on first note of measure
                    }
                    else
                    {
                        deltaTime = note.StartPosition.GetAsTotalTicks() - lastNote.EndPosition.GetAsTotalTicks();
                    }

                    ChannelMidiEvent noteOnEvent = ChannelMidiEvent.CreateNoteOnChannelMidiEvent(0, note.NoteNumber, note.Velocity, deltaTime);
                    newTrack.ChannelEvents.Add(noteOnEvent);

                    ChannelMidiEvent noteOffEvent = ChannelMidiEvent.CreateNoteOffChannelMidiEvent(0, note.NoteNumber, note.Length);
                    newTrack.ChannelEvents.Add(noteOffEvent);

                    lastNote = note;
                }
            }

            foreach (MidiFile mf in midiFiles)
            {
                mf.Export(mf.FileNameAndPath);
            }
        }