Exemple #1
0
            public bool Equals(CVVCPlus_French_Syllable obj)
            {
                if (obj == null)
                {
                    return(false);
                }

                return(obj.Onset == this.Onset &&
                       obj.Nucleus == this.Nucleus &&
                       obj.Coda == this.Coda);
            }
Exemple #2
0
            /// <summary>
            /// takes a lyric and splits it into its onset/nucleus/coda parts
            /// returns a CVVC_English_Syllable of [null, null, null] if not recognized
            /// </summary>
            /// <param name="lyric"></param>
            /// <returns></returns>
            public static CVVCPlus_French_Syllable SplitSyllable(string lyric)
            {
                var matches = syllable_RE.Match(lyric).Groups;
                var result  = new CVVCPlus_French_Syllable();

                if (matches.Count < 3)
                {
                    // not recognized
                    result.Onset   = null;
                    result.Nucleus = null;
                    result.Coda    = null;
                    return(new CVVCPlus_French_Syllable((string)null, null, null));
                }

                result.Onset   = matches[1].Value;
                result.Nucleus = matches[2].Value;
                result.Coda    = matches[3].Value;

                // otherwise, return as expected
                return(result);
            }
Exemple #3
0
        /*public static readonly List<string> vowels = new List<string>(new string[]
         * {
         *   "a", "ai", "e", "eh", "en", "eu", "i", "in", "o", "on", "oo", "ou", "u", "ui", "oi"
         * });
         * public static readonly List<string> consonants = new List<string>(new string[]
         * {
         *  "b","d","f","g","j","k","l","m","n","p","r","s","sh","t","v","z"
         * });
         * public static readonly List<string> starting_clusters = new List<string>(new string[]
         * {
         *  "br", "bl", "bz", "dr", "dl", "fr", "fl", "gr", "gl", "gz", "jr", "jl", "kr", "kl", "ks", "mr", "ml", "nr", "nl",
         *  "pr", "pl", "ps", "sr", "sl", "sk", "shr", "shl", "tr", "tl", "ts", "vr", "vl", "zr", "zl"
         * });
         * public static readonly List<string> ending_clusters = new List<string>(new string[]
         * {
         *  "rb", "lb", "zb", "rd", "ld", "rf", "lf", "rg", "lg", "zg", "rj", "lj", "rk", "lk", "sk", "rl", "rm", "lm", "zm", "sm",
         *  "rn", "ln", "zn", "sn", "rp", "lp", "zp", "sp", "rs", "ls", "rsh", "lsh", "rt", "lt", "st", "rv", "lv", "rz", "lz"
         * });*/

        /*
         * /// <summary>
         * /// split a French syllable into its onset, nucleus, and coda
         * /// or a (null, null, null) tuple if the lyric can't be recognized
         * /// </summary>
         * /// <param name="lyric"></param>
         * /// <returns></returns>
         * private static Tuple<List<string>, string, List<string>> split_CVVC_French(string lyric)
         * {
         * var toReturnOnset = new List<string>();
         * var toReturnCoda = new List<string>();
         * var toReturnNucleus = "";
         * var all_starting_clusters = consonants.Concat(starting_clusters);
         * var max_starting_cluster_length = all_starting_clusters.Max(s => s.Length);
         * var all_ending_clusters = consonants.Concat(ending_clusters);
         * var next_lyric = lyric;
         *
         * // find onset
         * var continue_searching = true;
         * while (continue_searching) {
         *  continue_searching = false;
         *  // find a single onset
         *  for (var i = 0; i < max_starting_cluster_length; i++)
         *  {
         *      if (all_starting_clusters.Any(
         *          prefix => lyric.StartsWith(prefix) && prefix.Length == max_starting_cluster_length
         *          ))
         *      {
         *          // iterates upwards, so at the end of the for loop, next_lyric is the maximum
         *          next_lyric = lyric.Substring(i);
         *          continue_searching = true;
         *      }
         *  }
         *  // if (continue_searching) toReturnOnset.Add(lyric.Substring(0, i));
         *  lyric = next_lyric;
         * }
         *
         * // find a single onset
         * for (var i = 0; i < max_starting_cluster_length; i++)
         * {
         *  if (all_starting_clusters.Any(
         *      prefix => lyric.StartsWith(prefix) && prefix.Length == max_starting_cluster_length
         *      ))
         *  {
         *      // iterates upwards, so at the end of the for loop, next_lyric is the maximum
         *      toReturnNucleus = lyric.Substring(i);
         *      next_lyric = lyric.Substring(i);
         *      continue_searching = true;
         *  }
         * }
         * lyric = next_lyric;
         *
         * // otherwise, return as expected
         * return new Tuple<List<string>, string, List<string>>(toReturnOnset,toReturnNucleus,toReturnCoda);
         * }*/

        /// <summary>
        /// Return the current note, split up as necessary to match the prev and next notes
        /// (Returns a new copy of all notes; the inputs are unchanged)
        ///
        /// </summary>
        /// <param name="prev"></param>
        /// <param name="curr"></param>
        /// <param name="next"></param>
        /// <returns></returns>
        public static List <UtauNote> GetConnectingNotes(UtauNote prev, UtauNote curr, UtauNote next)
        {
            CVVCPlus_French_Syllable lyric_split = CVVCPlus_French_Syllable.SplitSyllable(curr.Lyric);
            string nextlyric_start = CVVCPlus_French_Syllable.StartingConsonant(next.Lyric);


            List <UtauNote> toReturn = new List <UtauNote>();

            //if unrecognized, return the note untouched
            if (lyric_split.Onset == null && lyric_split.Nucleus == null)
            {
                return(new List <UtauNote> {
                    new UtauNote(curr)
                });
            }

            // add in the base note
            UtauNote CV = new UtauNote(curr);

            CV.Lyric = lyric_split.Onset + lyric_split.Nucleus;
            toReturn.Add(CV);

            // add in the VC note (first figuring out what C to add in)
            UtauNote VC = new UtauNote(curr);
            string   VC_consonant;

            if (lyric_split.Coda != "")
            {
                VC_consonant = lyric_split.Coda;
            }
            else if (nextlyric_start != "")
            {
                VC_consonant = nextlyric_start;
            }
            else
            {
                VC_consonant = null;
            }

            if (VC_consonant != null)
            {
                var matches = not_to_be_confused_for_nasals_RE.IsMatch(lyric_split.Nucleus);

                if (matches && VC_consonant == the_nasal_consonant)
                {
                    //SPECIAL CASE: handle non-nasals followed by n
                    VC.Lyric = lyric_split.Nucleus + " " + VC_consonant;
                }
                else
                {
                    //ORDINARY CASE
                    VC.Lyric = lyric_split.Nucleus + VC_consonant;
                }

                VC.Length = 120; //TODO: something more clever with lengths. For now, 120 is a 16th note
                toReturn.Add(VC);
                CV.Length = CV.Length - 120;
            }

            // adjust first sound if previous note is a rest (and this note has no starting consonant)
            if (lyric_split.Onset == "" && (prev == null || prev.IsRest))
            {
                toReturn[0].Lyric = "-" + toReturn[0].Lyric;
            }
            // adjust last sound if following note is a rest (and this note has no ending consonant)
            if (lyric_split.Coda == "" && (next == null || next.IsRest))
            {
                VC.Lyric  = lyric_split.Nucleus + "-";
                VC.Length = 120; //TODO: something more clever with lengths. For now, 120 is a 16th note
                toReturn.Add(VC);
                CV.Length = CV.Length - 120;
            }

            //TODO: double-check what's going on with the UtauNote copy constructor and why the tempo is being copied from the next note or something
            //for now, hack:
            toReturn.ForEach(note =>
            {
                //note.MainValues.Remove("Tempo"); //remove if exists
            });
            return(toReturn);

            /*Tuple<string, string, string> lyric_split = null;// split_CVVC_French(curr.Lyric);
             * Tuple<string, string, string> nextlyric_split = null;// split_CVVC_French(next.Lyric);
             * if (next.IsRest)
             * {
             *  nextlyric_split = null;// new Tuple<string, string>("R", null);
             * }
             *
             * List<UtauNote> toReturn = new List<UtauNote>();
             *
             * // add in the base note
             * UtauNote CV = new UtauNote(curr);
             * if (prev == null || prev.IsRest)
             * {
             *  CV.Lyric = "- " + CV.Lyric;
             * }
             * toReturn.Add(CV);
             *
             * // if necessary, add in the connecting note
             * string conn = null;// GetConnectingLyric(lyric_split.Item1, lyric_split.Item2, nextlyric_split.Item1, nextlyric_split.Item2);
             *
             * if (conn != null)
             * {
             *  UtauNote VC = new UtauNote(curr);
             *  VC.Lyric = conn;
             *  CV.Length = CV.Length - 60; //TODO: something more clever with lengths. For now, 60 is a 32th note
             *  VC.Length = 60;
             *  toReturn.Add(VC);
             * }
             *
             * return toReturn;*/
        }