Ejemplo n.º 1
0
 private void OnMetaMessagePlayed(object sender, MetaMessageEventArgs e)
 {
     if (e.Message.MetaType == MetaType.Tempo)
     {
         TempoChangeBuilder builder = new TempoChangeBuilder(e.Message);
         midiTempo = (60000000 / builder.Tempo);
         OnTempoChange?.Invoke(this, midiTempo);
     }
     if (e.Message.MetaType == MetaType.Lyric)
     {
         MetaTextBuilder builder = new MetaTextBuilder(e.Message);
         if (e.MidiTrack == LoadedTrack)
         {
             OnLyric?.Invoke(this, builder.Text);
         }
     }
     if (e.Message.MetaType == MetaType.TrackName)
     {
         MetaTextBuilder builder = new MetaTextBuilder(e.Message);
         ParseTrackName(e.MidiTrack, builder.Text);
         if (e.MidiTrack == LoadedTrack)
         {
             OnTrackNameChange?.Invoke(this, builder.Text);
         }
     }
     if (e.Message.MetaType == MetaType.InstrumentName)
     {
         MetaTextBuilder builder = new MetaTextBuilder(e.Message);
         OnTrackNameChange?.Invoke(this, builder.Text);
         Console.WriteLine("Instrument name: " + builder.Text);
     }
 }
Ejemplo n.º 2
0
        public void AddTrack(string TrackName, List <TLBaseKeyFrame> KeyFrames)
        {
            Track t = new Track();

            MetaTextBuilder mtBuilder = new MetaTextBuilder(MetaType.TrackName, TrackName);

            mtBuilder.Build();
            t.Insert(0, mtBuilder.Result);

            foreach (TLMidiKeyFrame mk in KeyFrames)
            {
                ChannelMessageBuilder cmBuilder = new ChannelMessageBuilder();
                cmBuilder.Command     = ChannelCommand.NoteOn;
                cmBuilder.MidiChannel = mk.Channel;
                cmBuilder.Data1       = mk.Note;
                cmBuilder.Data2       = mk.Velocity;
                cmBuilder.Build();
                t.Insert((int)(mk.Time / SecondsPerMidiUnit), cmBuilder.Result);

                cmBuilder.Command = ChannelCommand.NoteOff;
                cmBuilder.Data1   = mk.Note;
                cmBuilder.Data2   = 0;
                cmBuilder.Build();
                t.Insert((int)(mk.End / SecondsPerMidiUnit), cmBuilder.Result);
            }

            FSequence.Add(t);
        }
        public override void CreateEvents()
        {
            props.SetUpdatedEventPair(Owner.Insert(DownTick, MetaTextBuilder.Create(MetaType.Text, Text)));

            if (IsNew)
            {
                AddToList();
            }
        }
Ejemplo n.º 4
0
        private Sequence CreateSequence()
        {
            if (tunes == null || tunes.Count < 2)
            {
                return(null);
            }

            selectedTune = 1;

            SetDefaultValues();
            nextNote = TimeSpan.Zero;
            SetHeaderValues();
            SetHeaderValues(selectedTune, true);
            StartMeasure();

            sequence        = new Sequence(Ppqn);
            sequence.Format = 1;
            metaTrack       = new Track();
            mainTrack       = new Track();
            sequence.Add(metaTrack);
            TempoChangeBuilder tempoBuilder = new TempoChangeBuilder();

            tempoBuilder.Tempo = Tempo;
            tempoBuilder.Build();
            metaTrack.Insert(0, tempoBuilder.Result);
            TimeSignatureBuilder timeBuilder = new TimeSignatureBuilder();

            timeBuilder.Numerator   = timeSigNumerator;
            timeBuilder.Denominator = timeSigDenominator;
            timeBuilder.Build();
            metaTrack.Insert(0, timeBuilder.Result);
            sequence.Add(mainTrack);

            MetaTextBuilder textBuilder = new MetaTextBuilder();

            textBuilder.Type = MetaType.TrackName;
            textBuilder.Text = "Tempo Track";
            textBuilder.Build();
            metaTrack.Insert(0, textBuilder.Result);

            textBuilder      = new MetaTextBuilder();
            textBuilder.Type = MetaType.TrackName;
            textBuilder.Text = "Tune 1";
            textBuilder.Build();
            mainTrack.Insert(0, textBuilder.Result);

            while (tokenIndex < tokens.Count)
            {
                AddNextNote();
            }

            return(sequence);
        }
Ejemplo n.º 5
0
    private void ParseMetaMessage()
    {
        if (trackIndex >= trackData.Length)
        {
            throw new MidiFileException("End of track unexpectedly reached.");
        }

        MetaType type = (MetaType)trackData[trackIndex];

        trackIndex++;

        if (trackIndex >= trackData.Length)
        {
            throw new MidiFileException("End of track unexpectedly reached.");
        }

        if (type == MetaType.EndOfTrack)
        {
            newTrack.EndOfTrackOffset = ticks - previousTicks;

            trackIndex++;
        }
        else
        {
            byte[] data = new byte[ReadVariableLengthValue()];
            Array.Copy(trackData, trackIndex, data, 0, data.Length);
            MetaMessage metaMsg = new MetaMessage(type, data);
            // Record the time signature information
            if (type == MetaType.TimeSignature)
            {
                TimeSignatureBuilder timeSignature = new TimeSignatureBuilder(metaMsg);
                timeSignatureNumerator   = timeSignature.Numerator;
                timeSignatureDenominator = timeSignature.Denominator;
            }
            // Record the track name
            else if (type == MetaType.TrackName)
            {
                MetaTextBuilder trackName = new MetaTextBuilder(metaMsg);
                newTrack.Name = trackName.Text;
            }
            newTrack.Insert(ticks, new MetaMessage(type, data));

            trackIndex += data.Length;
        }
    }
Ejemplo n.º 6
0
        public void Load(string file, int trackNum = 0)
        {
            Sequence = new Sequence();
            OnTrackNameChange?.Invoke(this, string.Empty);
            OnTempoChange?.Invoke(this, 0);

            if (!File.Exists(file))
            {
                throw new FileNotFoundException("Midi file does not exist.");
            }

            loadedError = string.Empty;
            try {
                Sequence = new Sequence(file);
            } catch (Exception e) {
                throw e;
            }
            if (trackNum >= Sequence.Count)
            {
                trackNum = Sequence.Count - 1;
            }

            loadedFilename = file;
            intendedTrack  = trackNum;

            preferredInstruments.Clear();
            preferredOctaveShift.Clear();

            // Collect statistics
            notesPlayedCount.Clear();
            foreach (Track track in Sequence)
            {
                notesPlayedCount[track] = 0;
                foreach (MidiEvent ev in track.Iterator())
                {
                    if (ev.MidiMessage is ChannelMessage chanMsg)
                    {
                        if (chanMsg.Command == ChannelCommand.NoteOn)
                        {
                            if (chanMsg.Data2 > 0)
                            {
                                notesPlayedCount[track]++;
                            }
                        }
                    }
                }
            }

            // Count notes and select fìrst that actually has stuff
            if (trackNum == 0)
            {
                while (trackNum < Sequence.Count)
                {
                    int tnotes = 0;

                    foreach (MidiEvent ev in Sequence[trackNum].Iterator())
                    {
                        if (intendedTrack == 0)
                        {
                            if (ev.MidiMessage is ChannelMessage chanMsg)
                            {
                                if (chanMsg.Command == ChannelCommand.NoteOn)
                                {
                                    tnotes++;
                                }
                            }
                            if (ev.MidiMessage is MetaMessage metaMsg)
                            {
                                if (metaMsg.MetaType == MetaType.Lyric)
                                {
                                    tnotes++;
                                }
                            }
                        }
                    }

                    if (tnotes == 0)
                    {
                        trackNum++;
                    }
                    else
                    {
                        break;
                    }
                }
                if (trackNum == Sequence.Count)
                {
                    Console.WriteLine("No playable track...");
                    trackNum = intendedTrack;
                }
            }

            // Show initial tempo
            foreach (MidiEvent ev in Sequence[0].Iterator())
            {
                if (ev.AbsoluteTicks == 0)
                {
                    if (ev.MidiMessage is MetaMessage metaMsg)
                    {
                        if (metaMsg.MetaType == MetaType.Tempo)
                        {
                            OnMetaMessagePlayed(this, new MetaMessageEventArgs(Sequence[0], metaMsg));
                        }
                    }
                }
            }

            // Parse track names and octave shifts
            foreach (Track track in Sequence)
            {
                foreach (MidiEvent ev in track.Iterator())
                {
                    if (ev.MidiMessage is MetaMessage metaMsg)
                    {
                        if (metaMsg.MetaType == MetaType.TrackName)
                        {
                            MetaTextBuilder builder = new MetaTextBuilder(metaMsg);
                            this.ParseTrackName(track, builder.Text);
                        }
                    }
                }
            }

            loadedTrack = trackNum;
            lyricCount  = 0;
            // Search beginning for text stuff
            foreach (MidiEvent ev in LoadedTrack.Iterator())
            {
                if (ev.MidiMessage is MetaMessage msg)
                {
                    if (msg.MetaType == MetaType.TrackName)
                    {
                        OnMetaMessagePlayed(this, new MetaMessageEventArgs(LoadedTrack, msg));
                    }
                    if (msg.MetaType == MetaType.Lyric)
                    {
                        lyricCount++;
                    }
                }
                if (ev.MidiMessage is ChannelMessage chanMsg)
                {
                    if (chanMsg.Command == ChannelCommand.ProgramChange)
                    {
                        OnSimpleChannelMessagePlayed(this, new ChannelMessageEventArgs(Sequence[0], chanMsg));
                    }
                }
            }

            OnLoad?.Invoke(this, EventArgs.Empty);
            Console.WriteLine("Loaded midi [" + file + "] track " + trackNum);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Creates a notechart from the specified midi path and the actual charttype
        /// (i.e. ExpertSingle from notes.mid).  Due to the overhead necessary to
        /// parse a midi file.  I am going to cram all midi->chart operations into
        /// one function call.
        /// This function uses the Sanford midi parser.  While it is horribly slow
        /// on larger (e.g. RB) midis, it works without a hitch on every midi I've
        /// come across.
        /// </summary>
        /// <param name="chartSelection">
        /// The information on which particular notechart to use.
        /// </param>
        /// <param name="chartInfo">The metadata on the chart.</param>
        /// <param name="BPMChanges">The list of BPM changes for this chart.</param>
        /// <returns>
        /// A filled out Notechart containing the needed information from the *.mid file.
        /// </returns>
        public static Notes ParseMidiInformationSanford(ChartSelection chartSelection,
                                                        Info chartInfo,
                                                        List <BPMChange> BPMChanges)
        {
            Notes notechartToReturn = new Notes();

            notechartToReturn.instrument = chartSelection.instrument;
            notechartToReturn.difficulty = chartSelection.difficulty;

            // The following two switch's are used to get the proper midi terminology for
            // the selected track and difficulty.
            string instrumentPart = null;
            int    greenKey       = 0;
            int    redKey         = 0;
            int    yellowKey      = 0;
            int    blueKey        = 0;
            int    orangeKey      = 0;

            switch (chartSelection.instrument)
            {
            case "Single":
                instrumentPart = "PART GUITAR";
                break;

            case "DoubleGuitar":
                instrumentPart = "PART GUITAR COOP";
                break;

            case "DoubleBass":
                instrumentPart = "PART BASS";
                break;

            case "Drums":
                instrumentPart = "PART DRUMS";
                break;

            default:
                instrumentPart = "PART GUITAR";
                break;
            }

            switch (chartSelection.difficulty)
            {
            case "Expert":
                greenKey  = 96;
                redKey    = 97;
                yellowKey = 98;
                blueKey   = 99;
                orangeKey = 100;
                break;

            case "Hard":
                greenKey  = 84;
                redKey    = 85;
                yellowKey = 86;
                blueKey   = 87;
                orangeKey = 88;
                break;

            case "Medium":
                greenKey  = 72;
                redKey    = 73;
                yellowKey = 74;
                blueKey   = 75;
                orangeKey = 76;
                break;

            case "Easy":
                greenKey  = 60;
                redKey    = 61;
                yellowKey = 62;
                blueKey   = 63;
                orangeKey = 64;
                break;

            default:
                greenKey  = 96;
                redKey    = 97;
                yellowKey = 98;
                blueKey   = 99;
                orangeKey = 100;
                break;
            }

            Sequence mySequence = new Sequence(chartSelection.directory + "\\notes.mid");
            Track    trackToUse = new Track();

            chartInfo.resolution = mySequence.Division;

            // Go through each event in the first track (which contains the BPM changes)
            // and parse the resulting string.
            Track sanTrack = mySequence[0];

            foreach (Sanford.Multimedia.Midi.MidiEvent currEvent in sanTrack.Iterator())
            {
                if (currEvent.MidiMessage.MessageType == MessageType.Meta)
                {
                    MetaMessage currMessage = currEvent.MidiMessage as MetaMessage;
                    //currTickValue += Convert.ToUInt32(splitEventString[1]);
                    if (currMessage.MetaType == MetaType.Tempo)
                    {
                        TempoChangeBuilder tempoBuilder = new TempoChangeBuilder(currMessage);
                        int midiBPMChange = tempoBuilder.Tempo;
                        // In midi files, bpm chages are stored as "microseconds per quarter note"
                        // and must be converted to BPM, and then into the non decimal format the game
                        // uses.
                        double currBPMDouble = 60000000 / (double)midiBPMChange;
                        uint   BPMToAdd      = (uint)(currBPMDouble * 1000);
                        BPMChanges.Add(new BPMChange((uint)currEvent.AbsoluteTicks, (uint)BPMToAdd));
                    }
                }
            }

            // Find the specified instrument's track
            for (int i = 1; i < mySequence.Count; i++)
            {
                sanTrack = mySequence[i];
                Sanford.Multimedia.Midi.MidiEvent currEvent = sanTrack.GetMidiEvent(0);
                if (currEvent.MidiMessage.MessageType == MessageType.Meta)
                {
                    MetaMessage currMessage = currEvent.MidiMessage as MetaMessage;
                    if (currMessage.MetaType == MetaType.TrackName)
                    {
                        MetaTextBuilder trackName = new MetaTextBuilder(currMessage);

                        // -If we come across a "T1 GEMS" track, we're in GH1 territory.
                        // -GH2/FoF has both PART BASS and PART RHYTHM (one or the other depending
                        //  on the chart).
                        if ((trackName.Text == instrumentPart) || (trackName.Text == "T1 GEMS") ||
                            ((trackName.Text == "PART RHYTHM") && (instrumentPart == "PART BASS")))
                        {
                            trackToUse = sanTrack;
                        }
                    }
                }
            }

            Note currNote  = new Note();
            bool blankNote = true;

            // Scan through and record every note specific to the selected difficulty
            foreach (Sanford.Multimedia.Midi.MidiEvent currEvent in trackToUse.Iterator())
            {
                // We need to specify wether a note is blank or not so we don't add
                // blank notes from other difficulties into the chart, but if we have
                // a filled out note, any nonzero tick value means we are moving to a
                // new note, so we must cut our ties and add this note to the chart.
                if ((currEvent.DeltaTicks != 0) && !blankNote)
                {
                    notechartToReturn.notes.Add(currNote);
                    currNote  = new Note();
                    blankNote = true;
                }

                if (currEvent.MidiMessage.MessageType == MessageType.Channel)
                {
                    ChannelMessage currMessage = currEvent.MidiMessage as ChannelMessage;
                    if (currMessage.Command == ChannelCommand.NoteOn)
                    {
                        // Only consider notes within the octave our difficulty is in.
                        if (((currMessage.Data1 == greenKey) || (currMessage.Data1 == redKey) ||
                             (currMessage.Data1 == yellowKey) || (currMessage.Data1 == blueKey) ||
                             (currMessage.Data1 == orangeKey)) && (currMessage.Data2 != 0))
                        {
                            // If it's a new note, we need to setup the tick value of it.
                            if (blankNote)
                            {
                                //currNote.TickValue = totalTickValue;
                                currNote.tickValue = (uint)currEvent.AbsoluteTicks;
                                blankNote          = false;
                            }
                            if (currMessage.Data1 == greenKey)
                            {
                                currNote.addNote(0);
                            }
                            else if (currMessage.Data1 == redKey)
                            {
                                currNote.addNote(1);
                            }
                            else if (currMessage.Data1 == yellowKey)
                            {
                                currNote.addNote(2);
                            }
                            else if (currMessage.Data1 == blueKey)
                            {
                                currNote.addNote(3);
                            }
                            else if (currMessage.Data1 == orangeKey)
                            {
                                currNote.addNote(4);
                            }
                        }
                    }
                }
            }

            return(notechartToReturn);
        }