コード例 #1
0
        /// <summary>
        /// 通过Midi生成时间序列
        /// </summary>
        /// <param name="fileName">Midi文件路径</param>
        /// <param name="timeLine">时间序列</param>
        /// <param name="rate">播放速率(New BPM = BPM * rate)</param>
        /// <param name="synchroTick">节奏间隔(MidiTick),设置此项后将忽略播放速率</param>
        /// <returns>时间序列</returns>
        public TimeLine Serialize(string fileName, TimeLine timeLine, double rate = -1, int synchroTick = -1, ShowProgress showProgress = null)
        {
            try
            {
                if (timeLine == null)
                {
                    timeLine = new TimeLine();
                }
                var midiFile = new MidiFile(fileName, false);
                #region HeadParam
                timeLine.Param["MidiFileFormat"].Value  = midiFile.FileFormat;
                timeLine.Param["MidiTracksCount"].Value = midiFile.Tracks;
                timeLine.Param["MidiDeltaTicksPerQuarterNote"].Value = midiFile.DeltaTicksPerQuarterNote;
                #endregion
                #region Nodes
                //Public Event
                var    timeSignature = midiFile.Events[0].OfType <TimeSignatureEvent>().FirstOrDefault();
                double bpm           = 0;
                timeLine.BeatsPerBar  = timeSignature == null ? 4 : timeSignature.Numerator;
                timeLine.TicksPerBar  = timeSignature == null ? midiFile.DeltaTicksPerQuarterNote * 4 : (timeSignature.Numerator * midiFile.DeltaTicksPerQuarterNote * 4) / (1 << timeSignature.Denominator);
                timeLine.TicksPerBeat = timeLine.TicksPerBar / timeLine.BeatsPerBar;
                #region MidiFile -> MidiNodes(Unordered)
                List <MidiNode> MidiNodes = new List <MidiNode>();
                //Foreach Events in MidiFile
                for (int i = 0; i < midiFile.Tracks; i++)
                {
                    //Track Events
                    var track      = "";
                    var instrument = "";
                    var vol        = -1;
                    var pan        = -1;
                    foreach (MidiEvent midiEvent in midiFile.Events[i])
                    {
                        //Event BPM
                        if (new Regex("(?<=SetTempo )\\d+(?=bpm \\(\\d+\\))").Match(midiEvent.ToString()).Success)
                        {
                            bpm = Int32.Parse(new Regex("(?<=SetTempo )\\d+(?=bpm \\(\\d+\\))").Match(midiEvent.ToString()).Value);
                            if (rate > 0)
                            {
                                bpm *= rate;
                            }
                            MidiNodes.Add(new MidiNode()
                            {
                                IsEvent = true, Param = new Dictionary <string, _Node_INT>()
                                {
                                    { "BeatPerMinute", new _Node_INT()
                                      {
                                          Value = (int)bpm
                                      } }, { "DeltaTickStart", new _Node_INT()
                                             {
                                                 Value = midiEvent.DeltaTime
                                             } }, { "MinecraftTickStart", new _Node_INT()
                                                    {
                                                        Value = 0
                                                    } }
                                }
                            });
                        }
                        //Event Track Name
                        if (new Regex("(?<=SequenceTrackName ).+(?=$)").Match(midiEvent.ToString()).Success)
                        {
                            track = new Regex("(?<=SequenceTrackName ).+(?=$)").Match(midiEvent.ToString()).Value;
                        }
                        //Event Instrument Name
                        if (new Regex("(?<=PatchChange Ch: \\d+ ).+(?=$)").Match(midiEvent.ToString()).Success)
                        {
                            instrument = new Regex("(?<=PatchChange Ch: \\d+ ).+(?=$)").Match(midiEvent.ToString()).Value;
                        }
                        //Event Track Volume
                        if (new Regex("(?<=MainVolume Value )\\d*(?=$)").Match(midiEvent.ToString()).Success)
                        {
                            Int32.TryParse(new Regex("(?<=MainVolume Value )\\d*(?=$)").Match(midiEvent.ToString()).Value, out vol);
                        }
                        //Event Track Pan
                        if (new Regex("(?<=Pan Value )\\d*(?=$)").Match(midiEvent.ToString()).Success)
                        {
                            Int32.TryParse(new Regex("(?<=Pan Value )\\d*(?=$)").Match(midiEvent.ToString()).Value, out pan);
                        }
                        if (!MidiEvent.IsNoteOff(midiEvent))
                        {
                            //Get Param
                            var MBT           = GetMBT(midiEvent.AbsoluteTime, midiFile.DeltaTicksPerQuarterNote, timeSignature);
                            var EventAnalysis = AnalysisEvent(midiEvent, instrument);
                            //Write into MidiNodes
                            if (EventAnalysis != null)
                            {
                                var MidiNode = new MidiNode();
                                #region Param
                                //Time-related
                                MidiNode.Param["DeltaTickStart"].Value = (int)EventAnalysis.StartTick;
                                //MidiNode Starts Needs more Calculation
                                MidiNode.Param["DeltaTickDuration"].Value     = (int)EventAnalysis.Length;
                                MidiNode.Param["MinecraftTickDuration"].Value = (int)MinecraftTickDuration(EventAnalysis.Length, midiFile.DeltaTicksPerQuarterNote, timeSignature, (int)bpm);
                                MidiNode.Param["BeatPerMinute"].Value         = (int)bpm;
                                //Bar-related
                                MidiNode.Param["BarIndex"].Value     = (int)MBT[0];
                                MidiNode.Param["BeatDuration"].Value = (int)MBT[1];
                                //Note-related
                                MidiNode.Param["Channel"].Value  = (int)EventAnalysis.Channel;
                                MidiNode.Param["Pitch"].Value    = (int)EventAnalysis.Pitch;
                                MidiNode.Param["Velocity"].Value = (int)EventAnalysis.Velocity;
                                MidiNode.Param["Panning"].Value  = pan;
                                //Track-related
                                MidiNode.Instrument = EventAnalysis.Instrument;
                                MidiNode.TrackName  = track;
                                //PlaySound-related
                                MidiNode.PlaySound             = new PlaySoundInfo();
                                MidiNode.PlaySound.MandaVolume = (vol < 0) ? 100 : vol;
                                MidiNode.PlaySound.SetPan(pan);
                                //Generate Track & Instrument List
                                var currentTrack = timeLine.TrackList.AsEnumerable().FirstOrDefault(t => t.Name == track);
                                if (currentTrack == null)
                                {
                                    currentTrack = new TimeLine.MidiSettingInspector {
                                        Name = track, Type = TimeLine.MidiSettingType.Track, Enable = true
                                    }; timeLine.TrackList.Add(currentTrack);
                                }                                                                                                                                                                                            //Add new Track
                                var currentInstrument = timeLine.InstrumentList.AsEnumerable().FirstOrDefault(ins => ins.Name == EventAnalysis.Instrument);
                                if (currentInstrument == null)
                                {
                                    currentInstrument = new TimeLine.MidiSettingInspector {
                                        Name = EventAnalysis.Instrument, Type = TimeLine.MidiSettingType.Instrument, Enable = true
                                    }; timeLine.InstrumentList.Add(currentInstrument);
                                }                                                                                                                                                                                                                                        //Add new Instrument
                                if (!currentTrack.Instruments.Any(ins => ins.Name == EventAnalysis.Instrument))
                                {
                                    currentTrack.Instruments.Add(currentInstrument);
                                    currentTrack.InstrumentsUid.Add(currentInstrument.Uid);
                                }//Line Track
                                if (!currentInstrument.Tracks.Any(t => t.Name == track))
                                {
                                    currentInstrument.Tracks.Add(currentTrack);
                                    currentInstrument.TracksUid.Add(currentTrack.Uid);
                                }
                                #endregion
                                MidiNodes.Add(MidiNode);
                            }
                        }
                    }
                }
                #endregion
                #region MidiNodes in Order
                /* Set Total Progress */ timeLine.totalProgress = MidiNodes.Count * 2;
                bpm = 0;
                long bpm_key_t  = 0; //When BPM Changes
                long bpm_key_mt = 0;
                MidiNodes = (from n in MidiNodes
                             orderby n.Param["DeltaTickStart"].Value
                             select n).ToList();          //Make Nodes in Order
                int synchroCount = 0;
                for (int i = 0; i < MidiNodes.Count; i++) //Calculate Tick Start
                {
                    var n = MidiNodes[i];
                    if (n.IsEvent)
                    {
                        if (bpm != 0)
                        {
                            bpm_key_mt = MinecraftTickStart(n.Param["DeltaTickStart"].Value, midiFile.DeltaTicksPerQuarterNote, timeSignature, bpm, bpm_key_t, bpm_key_mt);
                        }
                        bpm       = n.Param["BeatPerMinute"].Value;
                        bpm_key_t = n.Param["DeltaTickStart"].Value;
                    }
                    else
                    {
                        n.Param["BeatPerMinute"].Value = (int)bpm;
                    }
                    if (synchroTick <= 0)
                    {
                        n.Param["MinecraftTickStart"].Value = (int)MinecraftTickStart(n.Param["DeltaTickStart"].Value, midiFile.DeltaTicksPerQuarterNote, timeSignature, bpm, bpm_key_t, bpm_key_mt);
                    }
                    else
                    { //Using synchroTick
                        n.Param["MinecraftTickStart"].Value = n.Param["DeltaTickStart"].Value / synchroTick;
                        if (n.Param["DeltaTickStart"].Value % synchroTick == 0)
                        {
                            synchroCount++;
                        }
                    }
                    /* Update Current Progress */ timeLine.currentProgress++; if (showProgress != null && timeLine.totalProgress > 0)
                    {
                        showProgress((double)timeLine.currentProgress / timeLine.totalProgress);
                    }
                }
                timeLine.SynchronousRate = (double)synchroCount / MidiNodes.Count;
                #endregion
                #region MidiNodes -> TickNodes
                //Creat and Set Lenth of TickNodes
                if (timeLine.TickNodes == null)
                {
                    timeLine.TickNodes = new List <TickNode>();
                }
                var maxTick = MidiNodes.Max(n => n.Param["MinecraftTickStart"].Value);
                if (maxTick >= timeLine.TickNodes.Count)
                {
                    var nowCount = timeLine.TickNodes.Count;
                    for (int i = 0; i < maxTick - nowCount + 1; i++)
                    {
                        timeLine.TickNodes.Add(new TickNode());
                    }
                }
                //MidiNodes -> TickNodes
                foreach (MidiNode node in MidiNodes)
                {
                    var index      = node.Param["MinecraftTickStart"].Value;
                    var track      = node.TrackName;
                    var instrument = node.Instrument;
                    if (timeLine.TickNodes[index].MidiTracks.ContainsKey(track) == false)
                    {
                        timeLine.TickNodes[index].MidiTracks.Add(track, new Dictionary <string, List <MidiNode> >());
                    }
                    if (timeLine.TickNodes[index].MidiTracks[track].ContainsKey(instrument) == false)
                    {
                        timeLine.TickNodes[index].MidiTracks[track].Add(instrument, new List <MidiNode>());
                    }
                    timeLine.TickNodes[index].MidiTracks[track][instrument].Add(node);
                    timeLine.TickNodes[index].BPM         = node.Param["BeatPerMinute"].Value;
                    timeLine.TickNodes[index].CurrentTick = index;
                    /* Update Current Progress */ timeLine.currentProgress++; if (showProgress != null && timeLine.totalProgress > 0)
                    {
                        showProgress((double)timeLine.currentProgress / timeLine.totalProgress);
                    }
                }
                #endregion
                timeLine.Param["TotalTicks"].Value = timeLine.TickNodes.Count;
                return(timeLine);

                //minecraft tick  = AbsoluteTime / (bpm * ticksPerBeat) * 1200
                #endregion
            }
            catch
            {
                return(null);
            }
        }
コード例 #2
0
        } //选中/取消选中元素

        private void Update(TimeLine.MidiSettingInspector i)
        {
            if (计分板输出.IsChecked != null)
            {
                i.EnableScore = 计分板输出.IsChecked == true;
            }
            if (Playsound输出.IsChecked != null)
            {
                i.EnablePlaysound = Playsound输出.IsChecked == true;
            }
            if (小节索引.IsChecked != null)
            {
                i.BarIndex = 小节索引.IsChecked == true;
            }
            if (小节长度.IsChecked != null)
            {
                i.BeatDuration = 小节长度.IsChecked == true;
            }
            if (频道.IsChecked != null)
            {
                i.Channel = 频道.IsChecked == true;
            }
            if (键持续时间.IsChecked != null)
            {
                i.DeltaTickDuration = 键持续时间.IsChecked == true;
            }
            if (键起始时间.IsChecked != null)
            {
                i.DeltaTickStart = 键起始时间.IsChecked == true;
            }
            if (力度.IsChecked != null)
            {
                i.Velocity = 力度.IsChecked == true;
            }
            if (音高.IsChecked != null)
            {
                i.Pitch = 音高.IsChecked == true;
            }
            if (键持续刻数.IsChecked != null)
            {
                i.MinecraftTickDuration = 键持续刻数.IsChecked == true;
            }
            if (键起始刻数.IsChecked != null)
            {
                i.MinecraftTickStart = 键起始刻数.IsChecked == true;
            }
            if (Stopsound.IsChecked != null)
            {
                i.PlaysoundSetting.StopSound = Stopsound.IsChecked == true;
            }
            if (音高播放.IsChecked != null)
            {
                i.PlaysoundSetting.PitchPlayable = 音高播放.IsChecked == true;
            }
            if (播放相对坐标X.GetValue(TextBoxHelper.WatermarkProperty).ToString() == "")
            {
                i.PlaysoundSetting.ExecuteCood[0] = (播放相对坐标X.Text != "") ? Double.Parse(播放相对坐标X.Text) : 0;
            }
            if (播放相对坐标Y.GetValue(TextBoxHelper.WatermarkProperty).ToString() == "")
            {
                i.PlaysoundSetting.ExecuteCood[1] = (播放相对坐标X.Text != "") ? Double.Parse(播放相对坐标Y.Text) : 0;
            }
            if (播放相对坐标Z.GetValue(TextBoxHelper.WatermarkProperty).ToString() == "")
            {
                i.PlaysoundSetting.ExecuteCood[2] = (播放相对坐标X.Text != "") ? Double.Parse(播放相对坐标Z.Text) : 0;
            }
            if (相对玩家.GetValue(TextBoxHelper.WatermarkProperty).ToString() == "")
            {
                i.PlaysoundSetting.ExecuteTarget = 相对玩家.Text;
            }
            if (播放对象.GetValue(TextBoxHelper.WatermarkProperty).ToString() == "")
            {
                i.PlaysoundSetting.PlayTarget = 播放对象.Text;
            }
            if (源.GetValue(TextBoxHelper.WatermarkProperty).ToString() == "")
            {
                i.PlaysoundSetting.PlaySource = 源.Text;
            }
            if (子表达式.GetValue(TextBoxHelper.WatermarkProperty).ToString() == "")
            {
                i.PlaysoundSetting.InheritExpression = (子表达式.Text != "") ? 子表达式.Text : null;
            }
            if (额外延时.GetValue(TextBoxHelper.WatermarkProperty).ToString() == "")
            {
                i.PlaysoundSetting.ExtraDelay = (额外延时.Text != "") ? Int32.Parse(额外延时.Text) : -1;
            }
            if (音色名称.GetValue(TextBoxHelper.WatermarkProperty).ToString() == "")
            {
                i.PlaysoundSetting.SoundName = 音色名称.Text;
            }
            if (音量大小.Visibility == Visibility.Visible)
            {
                i.PlaysoundSetting.PercVolume = (音量增益.Value != -1) ? (int)(音量增益.Value * 2) : -1;
            }
        }