예제 #1
0
 void ValidateOto(UTrack track, UNote note)
 {
     phonemeMapped = string.Empty;
     if (Error)
     {
         return;
     }
     if (track.Singer == null || !track.Singer.Loaded)
     {
         Error = true;
         return;
     }
     // Load oto.
     if (track.Singer.TryGetMappedOto(phoneme, note.tone, out var oto))
     {
         this.oto      = oto;
         Error         = false;
         phonemeMapped = oto.Alias;
     }
     else
     {
         this.oto      = default;
         Error         = true;
         phonemeMapped = string.Empty;
     }
 }
예제 #2
0
 public void Validate(UProject project, UTrack track, UVoicePart part, UNote note)
 {
     Error = note.Error;
     ValidateDuration(note);
     ValidateOto(track, note);
     ValidateOverlap(project, note);
     ValidateEnvelope(project, note);
 }
예제 #3
0
        public static UNote Create()
        {
            var note = new UNote();

            note.pitch   = new UPitch();
            note.vibrato = new UVibrato();
            return(note);
        }
예제 #4
0
        public UNote CreateNote()
        {
            UNote note = UNote.Create();

            note.pitch.AddPoint(new PitchPoint(-25, 0));
            note.pitch.AddPoint(new PitchPoint(25, 0));
            return(note);
        }
예제 #5
0
        public override void Validate(UProject project, UTrack track)
        {
            UNote lastNote = null;

            foreach (UNote note in notes)
            {
                note.Prev = lastNote;
                note.Next = null;
                if (lastNote != null)
                {
                    lastNote.Next = note;
                }
                lastNote = note;
            }
            foreach (UNote note in notes)
            {
                note.ExtendedDuration = note.duration;
                if (note.Prev != null && note.Prev.End == note.position && note.lyric.StartsWith("..."))
                {
                    note.Extends = note.Prev.Extends ?? note.Prev;
                    note.Extends.ExtendedDuration = note.End - note.Extends.position;
                }
                else
                {
                    note.Extends = null;
                }
            }
            foreach (UNote note in notes.Reverse())
            {
                note.Phonemize(project, track);
            }
            UPhoneme lastPhoneme = null;

            foreach (UNote note in notes)
            {
                foreach (var phoneme in note.phonemes)
                {
                    phoneme.Parent = note;
                    phoneme.Prev   = lastPhoneme;
                    phoneme.Next   = null;
                    if (lastPhoneme != null)
                    {
                        lastPhoneme.Next = phoneme;
                    }
                    lastPhoneme = phoneme;
                }
            }
            foreach (UNote note in notes)
            {
                note.Validate(project, track, this);
            }
        }
예제 #6
0
        void ValidateOverlap(UProject project, UNote note)
        {
            if (Error)
            {
                return;
            }
            float consonantStretch = (float)Math.Pow(2f, 1.0f - GetExpression(project, "vel").Item1 / 100f);

            overlap    = (float)oto.Overlap * consonantStretch * (overlapScale ?? 1);
            preutter   = (float)oto.Preutter * consonantStretch * (preutterScale ?? 1);
            overlapped = false;

            if (Prev == null)
            {
                return;
            }
            int   gapTick     = Parent.position + position - (Prev.Parent.position + Prev.End);
            float gapMs       = (float)project.TickToMillisecond(gapTick);
            float maxPreutter = preutter;

            if (gapMs <= 0)
            {
                // Keep at least half of last phoneme, or 10% if preutterScale is set.
                overlapped  = true;
                maxPreutter = (float)project.TickToMillisecond(Prev.Duration) * (preutterScale == null ? 0.5f : 0.9f);
            }
            else if (gapMs < preutter)
            {
                maxPreutter = gapMs;
            }
            if (preutter > maxPreutter)
            {
                float ratio = maxPreutter / preutter;
                preutter = maxPreutter;
                overlap *= ratio;
            }
            preutter         = Math.Max(0, preutter);
            overlap          = Math.Min(overlap, preutter);
            Prev.tailIntrude = overlapped ? preutter : 0;
            Prev.tailOverlap = overlapped ? overlap : 0;
            Prev.ValidateEnvelope(project, Prev.Parent);
            if (Next == null)
            {
                tailIntrude = 0;
                tailOverlap = 0;
            }
        }
예제 #7
0
        public UstxSerializationTest(ITestOutputHelper output)
        {
            this.output = output;
            descriptor  = new UExpressionDescriptor("velocity", "vel", 0, 200, 100);

            note          = UNote.Create();
            note.position = 120;
            note.duration = 60;
            note.tone     = 42;
            note.lyric    = "あ";
            note.noteExpressions.Add(new UExpression(descriptor)
            {
                value = 99,
            });
            note.phonemeExpressions.Add(new UExpression(descriptor)
            {
                index = 0,
                value = 123,
            });
        }
예제 #8
0
 void ValidateDuration(UNote note)
 {
     if (Error)
     {
         return;
     }
     if (Parent.Extends != null)
     {
         Duration = Parent.Extends.ExtendedEnd - Parent.position - position;
     }
     else
     {
         Duration = Parent.ExtendedDuration - position;
     }
     if (Next != null)
     {
         Duration = Math.Min(Duration, Next.Parent.position + Next.position - (Parent.position + position));
     }
     Error = Duration <= 0;
 }
예제 #9
0
        void ValidateEnvelope(UProject project, UNote note)
        {
            if (Error)
            {
                return;
            }
            var vol = GetExpression(project, "vol").Item1;
            var atk = GetExpression(project, "atk").Item1;
            var dec = GetExpression(project, "dec").Item1;

            Vector2 p0, p1, p2, p3, p4;

            p0.X = -preutter;
            p1.X = p0.X + (overlapped ? overlap : 5f);
            p2.X = Math.Max(0f, p1.X);
            p3.X = (float)project.TickToMillisecond(Duration) - (float)tailIntrude;
            p4.X = p3.X + (float)tailOverlap;
            if (p3.X == p4.X)
            {
                p3.X = Math.Max(p2.X, p3.X - 25f);
            }

            p0.Y = 0f;
            p1.Y = vol;
            p1.X = p0.X + (overlapped ? overlap : 5f);
            p1.Y = atk * vol / 100f;
            p2.Y = vol;
            p3.Y = vol * (1f - dec / 100f);
            p4.Y = 0f;

            envelope.data[0] = p0;
            envelope.data[1] = p1;
            envelope.data[2] = p2;
            envelope.data[3] = p3;
            envelope.data[4] = p4;
        }