/// <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)
        {
            Tuple <string, string> lyric_split     = split_CVVC_Chinese(curr.Lyric);
            Tuple <string, string> nextlyric_split = split_CVVC_Chinese(next.Lyric);

            if (next.IsRest)
            {
                nextlyric_split = 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 = 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);
        }
        /// <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)
        {
            Console.WriteLine("DOING CVVC+ FRENCH STUFF!");

            Console.WriteLine("Note: this is not yet implemented.");

            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);
        }
Esempio n. 3
0
        /// <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)
        {
            VCCV_English_Syllable lyric_split     = VCCV_English_Syllable.SplitSyllable(curr.Lyric);
            VCCV_English_Syllable nextlyric_split = VCCV_English_Syllable.SplitSyllable(next.Lyric);

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

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

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

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


            // if necessary, add a blending vowel _CV
            string editedV = GetStartingBlendVowel(lyric_split.Onset[0], lyric_split.Nucleus[0]);

            if (editedV != null)
            {
                UtauNote _CV = new UtauNote(curr);
                _CV.Lyric  = editedV;
                _CV.Length = CV.Length - 60; //TODO: something more clever with lengths. For now, 60 is a 32th note
                CV.Lyric   = lyric_split.Onset[0];
                CV.Length  = 60;
                toReturn.Add(_CV);
                CV = _CV; //relabel references
            }

            // figure out the ending
            List <string> ending_split = EndingParser(lyric_split.Coda[0]);

            if (ending_split.Count == 0)
            {
                string   newNote = GetConnectingSound(lyric_split.Nucleus[0], lyric_split.Coda[0], nextlyric_split.Onset[0], nextlyric_split.Nucleus[0]);
                UtauNote C_V     = new UtauNote(curr);
                if (newNote != null)
                {
                    CV.Length  = CV.Length - 60; //TODO: something more clever with lengths. For now, 60 is a 32th note
                    C_V.Lyric  = newNote;
                    C_V.Length = 60;
                    toReturn.Add(C_V);
                }
                else if (nextlyric_split.Nucleus[0] == null)
                {
                    UtauNote V_rest = new UtauNote(curr);
                    CV.Length     = CV.Length - 60; //TODO: something more clever with lengths. For now, 60 is a 32th note
                    V_rest.Lyric  = lyric_split.Nucleus[0];
                    V_rest.Length = 60;
                    toReturn.Add(V_rest);
                }
            }
            else if (ending_split.Count == 1)
            {
                string   newNote = GetEndingSound(lyric_split.Nucleus[0], lyric_split.Coda[0]);
                UtauNote VC      = new UtauNote(curr);
                if (newNote != null)
                {
                    CV.Length = CV.Length - 60; //TODO: something more clever with lengths. For now, 60 is a 32th note
                    VC.Lyric  = newNote;
                    VC.Length = 60;
                    if (Sonorant_Consonant_RE.IsMatch(lyric_split.Coda[0]) && !next.IsRest)
                    {
                        // on ending sonorants, add a dash before a C_C for blending
                        // this doesn't apply if the next sound is a rest
                        VC.Lyric = newNote + "-";
                    }
                    toReturn.Add(VC);
                }

                newNote = GetConnectingSound(lyric_split.Nucleus[0], lyric_split.Coda[0], nextlyric_split.Onset[0], nextlyric_split.Nucleus[0]);
                UtauNote C_V = new UtauNote(curr);
                if (newNote != null)
                {
                    CV.Length  = CV.Length - 60; //TODO: something more clever with lengths. For now, 60 is a 32th note
                    C_V.Lyric  = newNote;
                    C_V.Length = 60;
                    toReturn.Add(C_V);
                }
            }
            else
            {
                // ending consonant cluster(s) of some sort
                // TODO: more than one consonant cluster is not yet supported
                // e.g. b6lbz, which should be [b6][6l-][lb-][bz] is currently just [b6][6l-][lbz] but lbz is not a single sound

                string   newNote = GetEndingSound(lyric_split.Nucleus[0], ending_split[0]);
                UtauNote VC      = new UtauNote(curr);
                if (newNote != null)
                {
                    CV.Length = CV.Length - 60; //TODO: something more clever with lengths. For now, 60 is a 32th note
                    VC.Lyric  = newNote + "-";
                    VC.Length = 60;
                    toReturn.Add(VC);
                }

                UtauNote VCC = new UtauNote(curr);
                if (newNote != null)
                {
                    CV.Length  = CV.Length - 60; //TODO: something more clever with lengths. For now, 60 is a 32th note
                    VCC.Lyric  = string.Join("", ending_split);
                    VCC.Length = 60;
                    toReturn.Add(VCC);
                }

                newNote = GetConnectingSound(ending_split[ending_split.Count - 2], ending_split[ending_split.Count - 1],
                                             nextlyric_split.Onset[0], nextlyric_split.Nucleus[0]);
                UtauNote C_V = new UtauNote(curr);
                if (newNote != null)
                {
                    CV.Length  = CV.Length - 60; //TODO: something more clever with lengths. For now, 60 is a 32th note
                    C_V.Lyric  = newNote;
                    C_V.Length = 60;
                    toReturn.Add(C_V);
                }
            }


            // adjust first sound if previous note is a rest
            if (prev == null || prev.IsRest)
            {
                toReturn[0].Lyric = "-" + toReturn[0].Lyric;
            }
            else if (lyric_split.Onset[0] == "")
            {
                // if it's not following a rest but it starts with a vowel
                toReturn[0].Lyric = "_" + toReturn[0].Lyric;
            }
            // adjust last sound if following note is a rest
            if (next == null || next.IsRest)
            {
                toReturn[toReturn.Count - 1].Lyric = toReturn[toReturn.Count - 1].Lyric + "-";
            }

            foreach (UtauNote n in toReturn.Skip(1))
            {
                n.MainValues.Remove("Tempo");
                //Remove tempo marking from any except the first (which is where it was originally)
            }

            return(toReturn);
        }
        public void VCCV_English_test()
        {
            Console.WriteLine("STARTING ARPASING ENGLISH GetConnectingNotes TEST");

            //// reflection to test private stuff
            //var parent_type = typeof(VCCV_English);
            //var inner_type = parent_type.GetNestedType("VCCV_English_Syllable", BindingFlags.NonPublic);
            //PrivateType inner_type_private = new PrivateType(inner_type);

            //1
            var prev_note  = (UtauNote)null;
            var input_note = new UtauNote(new string[] {
                "[#0010]",
                "Length=380",
                "Lyric=f ay n",
                "NoteNum=50"
            });
            var next_note = new UtauNote(new string[] {
                "[#0011]",
                "Length=240",
                "Lyric=R",
                "NoteNum=46"
            });
            var result   = Arpasing_English.GetConnectingNotes(prev_note, input_note, next_note);
            var expected = new List <UtauNote>(new UtauNote[] {
                new UtauNote(new string[] {
                    "[#0010]",
                    "Length=60",
                    "Lyric=- f",
                    "NoteNum=50",
                }),
                new UtauNote(new string[] {
                    "[#0010]",
                    "Length=200",
                    "Lyric=f ay",
                    "NoteNum=50",
                }),
                new UtauNote(new string[] {
                    "[#0010]",
                    "Length=60",
                    "Lyric=ay n",
                    "NoteNum=50",
                }),
                new UtauNote(new string[] {
                    "[#0010]",
                    "Length=60",
                    "Lyric=n -",
                    "NoteNum=50",
                }),
            });

            CollectionAssert.AreEqual(expected.ConvertAll <string>(x => x.ToString()), result.ConvertAll <string>(x => x.ToString()));

            //2
            prev_note  = null;
            input_note = new UtauNote(new string[] {
                "[#0010]",
                "Length=380",
                "Lyric=ao r g",
                "NoteNum=50"
            });
            next_note = new UtauNote(new string[] {
                "[#0011]",
                "Length=240",
                "Lyric=R",
                "NoteNum=46"
            });
            result   = Arpasing_English.GetConnectingNotes(prev_note, input_note, next_note);
            expected = new List <UtauNote>(new UtauNote[] {
                new UtauNote(new string[] {
                    "[#0010]",
                    "Length=200",
                    "Lyric=- ao",
                    "NoteNum=50",
                }),
                new UtauNote(new string[] {
                    "[#0010]",
                    "Length=60",
                    "Lyric=ao r",
                    "NoteNum=50",
                }),
                new UtauNote(new string[] {
                    "[#0010]",
                    "Length=60",
                    "Lyric=r g",
                    "NoteNum=50",
                }),
                new UtauNote(new string[] {
                    "[#0010]",
                    "Length=60",
                    "Lyric=g -",
                    "NoteNum=50",
                }),
            });
            CollectionAssert.AreEqual(expected.ConvertAll <string>(x => x.ToString()), result.ConvertAll <string>(x => x.ToString()));

            //3
            prev_note = new UtauNote(new string[] {
                "[#0009]",
                "Length=240",
                "Lyric=R",
                "NoteNum=46"
            });
            input_note = new UtauNote(new string[] {
                "[#0010]",
                "Length=380",
                "Lyric=f l ay",
                "NoteNum=50"
            });
            next_note = new UtauNote(new string[] {
                "[#0011]",
                "Length=240",
                "Lyric=m iy",
                "NoteNum=46"
            });
            result   = Arpasing_English.GetConnectingNotes(prev_note, input_note, next_note);
            expected = new List <UtauNote>(new UtauNote[] {
                new UtauNote(new string[] {
                    "[#0010]",
                    "Length=60",
                    "Lyric=- f",
                    "NoteNum=50",
                }),
                new UtauNote(new string[] {
                    "[#0010]",
                    "Length=60",
                    "Lyric=f l",
                    "NoteNum=50",
                }),
                new UtauNote(new string[] {
                    "[#0010]",
                    "Length=200",
                    "Lyric=l ay",
                    "NoteNum=50",
                }),
                new UtauNote(new string[] {
                    "[#0010]",
                    "Length=60",
                    "Lyric=ay m",
                    "NoteNum=50",
                }),
            });
            CollectionAssert.AreEqual(expected.ConvertAll <string>(x => x.ToString()), result.ConvertAll <string>(x => x.ToString()));

            //4
            prev_note = new UtauNote(new string[] {
                "[#0009]",
                "Length=380",
                "Lyric=y uw",
                "NoteNum=46"
            });
            input_note = new UtauNote(new string[] {
                "[#0010]",
                "Length=380",
                "Lyric=m ah s t",
                "NoteNum=46"
            });
            next_note = new UtauNote(new string[] {
                "[#0011]",
                "Length=380",
                "Lyric=b iy",
                "NoteNum=46"
            });
            result   = Arpasing_English.GetConnectingNotes(prev_note, input_note, next_note);
            expected = new List <UtauNote>(new UtauNote[] {
                new UtauNote(new string[] {
                    "[#0010]",
                    "Length=200",
                    "Lyric=m ah",
                    "NoteNum=46",
                }),
                new UtauNote(new string[] {
                    "[#0010]",
                    "Length=60",
                    "Lyric=ah s",
                    "NoteNum=46",
                }),
                new UtauNote(new string[] {
                    "[#0010]",
                    "Length=60",
                    "Lyric=s t",
                    "NoteNum=46",
                }),
                new UtauNote(new string[] {
                    "[#0010]",
                    "Length=60",
                    "Lyric=t b",
                    "NoteNum=46",
                }),
            });
            result.ForEach(x => Console.WriteLine(x));
            CollectionAssert.AreEqual(expected.ConvertAll <string>(x => x.ToString()), result.ConvertAll <string>(x => x.ToString()));


            //5
            prev_note = new UtauNote(new string[] {
                "[#0009]",
                "Length=380",
                "Lyric=y uw",
                "NoteNum=46"
            });
            input_note = new UtauNote(new string[] {
                "[#0010]",
                "Length=380",
                "Lyric=aa r",
                "NoteNum=46"
            });
            next_note = null;
            result    = Arpasing_English.GetConnectingNotes(prev_note, input_note, next_note);
            expected  = new List <UtauNote>(new UtauNote[] {
                new UtauNote(new string[] {
                    "[#0010]",
                    "Length=260",
                    "Lyric=aa",
                    "NoteNum=46",
                }),
                new UtauNote(new string[] {
                    "[#0010]",
                    "Length=60",
                    "Lyric=aa r",
                    "NoteNum=46",
                }),
                new UtauNote(new string[] {
                    "[#0010]",
                    "Length=60",
                    "Lyric=r -",
                    "NoteNum=46",
                }),
            });
            result.ForEach(x => Console.WriteLine(x));
            CollectionAssert.AreEqual(expected.ConvertAll <string>(x => x.ToString()), result.ConvertAll <string>(x => x.ToString()));

            //6
            prev_note = new UtauNote(new string[] {
                "[#0009]",
                "Length=380",
                "Lyric=R",
                "NoteNum=46"
            });
            input_note = new UtauNote(new string[] {
                "[#0010]",
                "Length=380",
                "Lyric=aa r",
                "NoteNum=46"
            });
            next_note = null;
            result    = Arpasing_English.GetConnectingNotes(prev_note, input_note, next_note);
            expected  = new List <UtauNote>(new UtauNote[] {
                new UtauNote(new string[] {
                    "[#0010]",
                    "Length=260",
                    "Lyric=- aa",
                    "NoteNum=46",
                }),
                new UtauNote(new string[] {
                    "[#0010]",
                    "Length=60",
                    "Lyric=aa r",
                    "NoteNum=46",
                }),
                new UtauNote(new string[] {
                    "[#0010]",
                    "Length=60",
                    "Lyric=r -",
                    "NoteNum=46",
                }),
            });
            result.ForEach(x => Console.WriteLine(x));
            CollectionAssert.AreEqual(expected.ConvertAll <string>(x => x.ToString()), result.ConvertAll <string>(x => x.ToString()));

            Console.WriteLine("ENDING ARPASING ENGLISH GetConnectingNotes TEST");
        }
Esempio n. 5
0
        public void VCCV_English_test()
        {
            Console.WriteLine("STARTING VCCV ENGLISH GetConnectingNotes TEST");

            // reflection to test private stuff
            var         parent_type        = typeof(VCCV_English);
            var         inner_type         = parent_type.GetNestedType("VCCV_English_Syllable", BindingFlags.NonPublic);
            PrivateType inner_type_private = new PrivateType(inner_type);

            //1
            var input_note = new UtauNote(new string[] {
                "[#0010]",
                "Length=229",
                "Lyric=fIn",
                "NoteNum=50"
            });
            var next_note = new UtauNote(new string[] {
                "[#0011]",
                "Length=240",
                "Lyric=R",
                "NoteNum=46"
            });
            var result   = VCCV_English.GetConnectingNotes(null, input_note, next_note);
            var expected = new List <UtauNote>(new UtauNote[] {
                new UtauNote(new string[] {
                    "[#0010]",
                    "Length=169",
                    "Lyric=-fI",
                    "NoteNum=50",
                }),
                new UtauNote(new string[] {
                    "[#0010]",
                    "Length=60",
                    "Lyric=In-",
                    "NoteNum=50",
                }),
            });

            CollectionAssert.AreEqual(expected.ConvertAll <string>(x => x.ToString()), result.ConvertAll <string>(x => x.ToString()));

            //2
            input_note = new UtauNote(new string[] {
                "[#0010]",
                "Length=229",
                "Lyric=fIn",
                "NoteNum=50"
            });
            next_note = new UtauNote(new string[] {
                "[#0011]",
                "Length=240",
                "Lyric=dhen",
                "NoteNum=46"
            });
            result   = VCCV_English.GetConnectingNotes(null, input_note, next_note);
            expected = new List <UtauNote>(new UtauNote[] {
                new UtauNote(new string[] {
                    "[#0010]",
                    "Length=109",
                    "Lyric=-fI",
                    "NoteNum=50",
                }),
                new UtauNote(new string[] {
                    "[#0010]",
                    "Length=60",
                    "Lyric=In-",
                    "NoteNum=50",
                }),
                new UtauNote(new string[] {
                    "[#0010]",
                    "Length=60",
                    "Lyric=n dh",
                    "NoteNum=50",
                }),
            });
            CollectionAssert.AreEqual(expected.ConvertAll <string>(x => x.ToString()), result.ConvertAll <string>(x => x.ToString()));

            Console.WriteLine("ENDING VCCV ENGLISH GetConnectingNotes TEST");
        }
        /// <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)
        {
            VCCV_English_Syllable lyric_split     = VCCV_English_Syllable.SplitSyllable(curr.Lyric);
            VCCV_English_Syllable nextlyric_split = VCCV_English_Syllable.SplitSyllable(next.Lyric);

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

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

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

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


            // if necessary, add a blending vowel _CV
            string editedV = GetStartingBlendVowel(lyric_split.Onset[0], lyric_split.Nucleus[0]);

            if (editedV != null)
            {
                UtauNote _CV = new UtauNote(curr);
                _CV.Lyric  = editedV;
                _CV.Length = CV.Length - 60; //TODO: something more clever with lengths. For now, 60 is a 32th note
                CV.Lyric   = lyric_split.Onset[0];
                CV.Length  = 60;
                toReturn.Add(_CV);
                CV = _CV; //relabel references
            }

            // figure out the ending
            List <string> ending_split = EndingParser(lyric_split.Coda[0]);

            if (ending_split.Count == 0)
            {
                string   newNote = GetConnectingSound(lyric_split.Nucleus[0], lyric_split.Coda[0], nextlyric_split.Onset[0], nextlyric_split.Nucleus[0]);
                UtauNote C_V     = new UtauNote(curr);
                if (newNote != null)
                {
                    CV.Length  = CV.Length - 60; //TODO: something more clever with lengths. For now, 60 is a 32th note
                    C_V.Lyric  = newNote;
                    C_V.Length = 60;
                    toReturn.Add(C_V);
                }
                else if (nextlyric_split.Nucleus[0] == null)
                {
                    UtauNote V_rest = new UtauNote(curr);
                    CV.Length     = CV.Length - 60; //TODO: something more clever with lengths. For now, 60 is a 32th note
                    V_rest.Lyric  = lyric_split.Nucleus[0];
                    V_rest.Length = 60;
                    toReturn.Add(V_rest);
                }
            }
            else if (ending_split.Count == 1)
            {
                string   newNote = GetEndingSound(lyric_split.Nucleus[0], lyric_split.Coda[0]);
                UtauNote VC      = new UtauNote(curr);
                if (newNote != null)
                {
                    CV.Length = CV.Length - 60; //TODO: something more clever with lengths. For now, 60 is a 32th note
                    VC.Lyric  = newNote;
                    VC.Length = 60;
                    toReturn.Add(VC);
                }

                newNote = GetConnectingSound(lyric_split.Nucleus[0], lyric_split.Coda[0], nextlyric_split.Onset[0], nextlyric_split.Nucleus[0]);
                UtauNote C_V = new UtauNote(curr);
                if (newNote != null)
                {
                    CV.Length  = CV.Length - 60; //TODO: something more clever with lengths. For now, 60 is a 32th note
                    C_V.Lyric  = newNote;
                    C_V.Length = 60;
                    toReturn.Add(C_V);
                }
            }
            else
            {
                // ending consonant cluster(s) of some sort
                // TODO: more than one consonant cluster is not yet supported
                // e.g. b6lbz, which should be [b6][6l-][lb-][bz] is just [b6][6l-][lbz] but lbz is not a single sound

                string   newNote = GetEndingSound(lyric_split.Nucleus[0], ending_split[0]);
                UtauNote VC      = new UtauNote(curr);
                if (newNote != null)
                {
                    CV.Length = CV.Length - 60; //TODO: something more clever with lengths. For now, 60 is a 32th note
                    VC.Lyric  = newNote + "-";
                    VC.Length = 60;
                    toReturn.Add(VC);
                }

                UtauNote VCC = new UtauNote(curr);
                if (newNote != null)
                {
                    CV.Length  = CV.Length - 60; //TODO: something more clever with lengths. For now, 60 is a 32th note
                    VCC.Lyric  = string.Join("", ending_split);
                    VCC.Length = 60;
                    toReturn.Add(VCC);
                }

                newNote = GetConnectingSound(ending_split[ending_split.Count - 2], ending_split[ending_split.Count - 1],
                                             nextlyric_split.Onset[0], nextlyric_split.Nucleus[0]);
                UtauNote C_V = new UtauNote(curr);
                if (newNote != null)
                {
                    CV.Length  = CV.Length - 60; //TODO: something more clever with lengths. For now, 60 is a 32th note
                    C_V.Lyric  = newNote;
                    C_V.Length = 60;
                    toReturn.Add(C_V);
                }
            }


            // adjust first sound if previous note is a rest
            if (prev == null || prev.IsRest)
            {
                toReturn[0].Lyric = "-" + toReturn[0].Lyric;
            }
            // adjust last sound if following note is a rest
            if (next == null || next.IsRest)
            {
                toReturn[toReturn.Count - 1].Lyric = toReturn[toReturn.Count - 1].Lyric + "-";
            }

            return(toReturn);
        }
        /// <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)
        {
            Arpasing_English_Syllable currsyllable = Arpasing_English_Syllable.SplitSyllable(curr.Lyric);

            //if unrecognized, return the note untouched
            if (currsyllable == null || curr.IsRest)
            {
                return(new List <UtauNote> {
                    new UtauNote(curr)
                });
            }

            //default to hyphen if the prev/next is a rest or doesn't exist
            string prevsyllable_end   = "-";
            string nextsyllable_start = "-";

            if (prev != null && !prev.IsRest)
            {
                prevsyllable_end = null;
            }
            if (next != null && !next.IsRest)
            {
                var nextsyllable = Arpasing_English_Syllable.SplitSyllable(next.Lyric);
                nextsyllable_start = nextsyllable[0];
            }

            // identify the vowel (if more than one, choose any - here, we arbitrarily choose the last one)
            // if none, default to first phoneme
            int nucleus_index = 0;

            for (var i = 0; i < currsyllable.Count; i++)
            {
                if (Vowels.Contains(currsyllable[i]))
                {
                    nucleus_index = i;
                }
            }

            // build up the notes to return
            List <UtauNote> toReturn = new List <UtauNote>();
            UtauNote        note;

            if (prevsyllable_end != null)
            {
                // add in the note connecting to the previous note, if it exists
                note        = new UtauNote(curr);
                note.Lyric  = prevsyllable_end + " " + currsyllable[0];
                note.Length = 60; //TODO: something more clever with lengths. For now, 60 is a 32nd note
                toReturn.Add(note);
            }
            else if (nucleus_index == 0)
            {
                // we start with a vowel, and we don't have a - to start from
                // so we add it in manually
                note        = new UtauNote(curr);
                note.Lyric  = currsyllable[0];
                note.Length = 60; //TODO: something more clever with lengths. For now, 60 is a 32nd note
                toReturn.Add(note);
            }
            else
            {
                // we have no initial note, so decrement the nucleus_index
                nucleus_index -= 1;
            }

            for (var i = 0; i < currsyllable.Count - 1; i++)
            {
                note       = new UtauNote(curr);
                note.Lyric = currsyllable[i] + " " + currsyllable[i + 1];
                // set the note length to be 60 for now; we'll find the nucleus_index-th one and extend it at the end
                note.Length = 60; //TODO: something more clever with lengths. For now, 60 is a 32nd note
                toReturn.Add(note);
            }

            // add in the note connecting to the next note
            note        = new UtauNote(curr);
            note.Lyric  = currsyllable[currsyllable.Count - 1] + " " + nextsyllable_start;
            note.Length = 60; //TODO: something more clever with lengths. For now, 60 is a 32nd note
            toReturn.Add(note);

            toReturn[nucleus_index].Length = curr.Length - (toReturn.Count - 1) * 60; // TODO: does not handle the case when this ends up shorter than the original note

            return(toReturn);
        }
Esempio n. 8
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;*/
        }
        /// 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)
        public static List <UtauNote> GetConnectingNotes(UtauNote prev, UtauNote curr, UtauNote next)
        {
            CVVCEve_French_Syllable lyric_split = CVVCEve_French_Syllable.SplitSyllable(curr.Lyric);
            string nextlyric_start = CVVCEve_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)
            {
                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 (prev == null || prev.IsRest)
            {
                toReturn[0].Lyric = "- " + toReturn[0].Lyric;
            }

            //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);
        }
Esempio n. 10
0
        /// <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)
        {
            CVVC_English_Syllable lyric_split = CVVC_English_Syllable.SplitSyllable(curr.Lyric);
            string nextlyric_start            = CVVC_English_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)
            {
                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: vowel-vowel sounds like V

            return(toReturn);
        }