示例#1
0
        public static double Frequency2Note(double frequency)
        {
            string dummy;

            return(TuningFrequency.Frequency2Note(frequency, out dummy));
        }
示例#2
0
        public static double Frequency2Cents(double frequency)
        {
            double dummy;

            return(TuningFrequency.Frequency2Cents(frequency, out dummy));
        }
        /// <summary>
        /// Fill Arrangement 2014 from json and xml.
        /// </summary>
        /// <param name="attr"></param>
        /// <param name="xmlSongFile"></param>
        /// <param name="fixMultiTone">If set to <c>true</c> fix low bass tuning </param>
        /// <param name="fixLowBass">If set to <c>true</c> fix multitone exceptions </param>
        public Arrangement(Attributes2014 attr, string xmlSongFile, bool fixMultiTone = false, bool fixLowBass = false)
        {
            var isDirty = false;
            var song    = Song2014.LoadFromFile(xmlSongFile);

            this.SongFile = new SongFile {
                File = ""
            };
            this.SongXml = new SongXML {
                File = xmlSongFile
            };

            //Properties
            Debug.Assert(attr.ArrangementType != null, "Missing information from manifest (ArrangementType)");
            SetArrType(attr.ArrangementType);

            this.ArrangementPropeties = attr.ArrangementProperties;
            this.ArrangementSort      = attr.ArrangementSort;
            this.Name            = (ArrangementName)Enum.Parse(typeof(ArrangementName), attr.ArrangementName);
            this.ScrollSpeed     = Convert.ToInt32(attr.DynamicVisualDensity.Last() * 10);
            this.PluckedType     = (PluckedType)attr.ArrangementProperties.BassPick;
            this.RouteMask       = (RouteMask)attr.ArrangementProperties.RouteMask;
            this.BonusArr        = attr.ArrangementProperties.BonusArr == 1;
            this.Metronome       = (Metronome)attr.ArrangementProperties.Metronome;
            this.ToneMultiplayer = attr.Tone_Multiplayer;
            this.Id       = Guid.Parse(attr.PersistentID);
            this.MasterId = attr.MasterID_RDV;

            // Save xml comments
            this.XmlComments = Song2014.ReadXmlComments(xmlSongFile);

            // Filter out showlights\vocals
            if (ArrangementType != ArrangementType.Guitar && ArrangementType != ArrangementType.Bass)
            {
                return;
            }

            // Tones
            if (attr.Tones == null) // RS2012
            {
                this.ToneBase = attr.Tone_Base;

                if (attr.Tone_A != null || attr.Tone_B != null || attr.Tone_C != null || attr.Tone_D != null)
                {
                    throw new DataException("RS2012 CDLC has extraneous tone data.");
                }
            }
            else // RS2014 or Converter RS2012
            {
                // TODO: optimize using common Arrangment.cs method
                // verify the xml Tone_ exists in tone.manifest.json
                foreach (var jsonTone in attr.Tones)
                {
                    if (jsonTone == null)
                    {
                        continue;
                    }

                    // fix for tone.id (may not be needed/used by game)
                    Int32 toneId = 0;

                    // cleanup the xml arrangement file too
                    if (jsonTone.Name.ToLower() == attr.Tone_Base.ToLower())
                    {
                        this.ToneBase = song.ToneBase = attr.Tone_Base;
                    }
                    if (attr.Tone_A != null && jsonTone.Name.ToLower() == attr.Tone_A.ToLower())
                    {
                        this.ToneA = song.ToneA = attr.Tone_A;
                    }
                    if (attr.Tone_B != null && jsonTone.Name.ToLower() == attr.Tone_B.ToLower())
                    {
                        this.ToneB = song.ToneB = attr.Tone_B;
                        toneId     = 1;
                    }
                    if (attr.Tone_C != null && jsonTone.Name.ToLower() == attr.Tone_C.ToLower())
                    {
                        this.ToneC = song.ToneC = attr.Tone_C;
                        toneId     = 2;
                    }
                    if (attr.Tone_D != null && jsonTone.Name.ToLower() == attr.Tone_D.ToLower())
                    {
                        this.ToneD = song.ToneD = attr.Tone_D;
                        toneId     = 3;
                    }

                    // update EOF tone name and set tone id
                    if (song.Tones != null)
                    {
                        foreach (var xmlTone in song.Tones)
                        {
                            // fix some old toolkit behavior
                            if (xmlTone.Name == "ToneA")
                            {
                                xmlTone.Name = attr.Tone_A;
                            }
                            if (xmlTone.Name == "ToneB")
                            {
                                xmlTone.Name = attr.Tone_B;
                            }
                            if (xmlTone.Name == "ToneC")
                            {
                                xmlTone.Name = attr.Tone_C;
                            }
                            if (xmlTone.Name == "ToneD")
                            {
                                xmlTone.Name = attr.Tone_D;
                            }

                            if (xmlTone.Name.ToLower() == jsonTone.Name.ToLower() || jsonTone.Name.ToLower().EndsWith(xmlTone.Name.ToLower())) //todo: SAMENAME tone fix?
                            {
                                xmlTone.Name = jsonTone.Name;
                                xmlTone.Id   = toneId;
                            }
                        }
                    }


                    // song.Tones => id, name, time to apply tone is missing when song.Tones == null
                    if (song.Tones == null && toneId > 0)
                    {
                        // convert the corrupt multitone to a single tone instead of throwing exception
                        if (fixMultiTone)
                        {
                            song.Tones = new SongTone2014[0]; // => song.Tones.Length == 0
                            isDirty    = true;
                        }
                        else
                        {
                            throw new InvalidDataException("Tone data is missing in CDLC and multitones will not change properly in game." + Environment.NewLine + "Please re-author XML arrangements in EOF and repair multitones name and time changes.");
                        }
                    }
                }

                // convert corrupt multitone to single tone and/or cleanup/repair old toolkit single tone
                // ToneA in single tone ODLC is null/empty
                if ((song.Tones == null || song.Tones.Length == 0) && !String.IsNullOrEmpty(song.ToneA))
                {
                    song.ToneA    = song.ToneB = song.ToneC = String.Empty;
                    song.ToneBase = attr.Tone_Base;
                    this.ToneBase = attr.Tone_Base;
                    this.ToneA    = this.ToneB = this.ToneC = String.Empty;
                    isDirty       = true;
                }

                // set to standard tuning if no tuning exists
                if (song.Tuning == null)
                {
                    song.Tuning = new TuningStrings {
                        String0 = 0, String1 = 0, String2 = 0, String3 = 0, String4 = 0, String5 = 0
                    };
                    isDirty = true;
                }

                this.TuningStrings = song.Tuning;

                // NOTE: any serializing coverts abridged xml to standard xml arrangement
                // so only serialize if necessary to fix errors
                if (isDirty)
                {
                    using (var stream = File.Open(xmlSongFile, FileMode.Create))
                        song.Serialize(stream, true);

                    // write comments back to xml now so they are available for debugging (used for Guitar and Bass)
                    Song2014.WriteXmlComments(xmlSongFile, XmlComments, writeNewVers: false);
                }

                // do a quick check/repair of low bass tuning, only for RS2014 bass arrangements
                if (fixLowBass && song.Version == "7" && this.ArrangementType == ArrangementType.Bass)
                {
                    if (attr.Tuning.String0 < -4 && attr.CentOffset != -1200.0)
                    {
                        if (TuningFrequency.ApplyBassFix(this, fixLowBass))
                        {
                            attr.CentOffset = -1200.0; // Force 220Hz
                            song.Tuning     = Song2014.LoadFromFile(xmlSongFile).Tuning;
                        }
                    }
                }
            }

            // Set Final Tuning
            DetectTuning(song);
            this.CapoFret = attr.CapoFret;
            if (attr.CentOffset != null)
            {
                this.TuningPitch = attr.CentOffset.Cents2Frequency();
            }
        }