Esempio n. 1
0
        private RenderItem BuildRenderItem(UPhoneme phoneme, UVoicePart part, UProject project)
        {
            USinger singer  = project.Tracks[part.TrackNo].Singer;
            string  rawfile = Lib.EncodingUtil.ConvertEncoding(singer.FileEncoding, singer.PathEncoding, phoneme.Oto.File);

            rawfile = Path.Combine(singer.Path, rawfile);

            double strechRatio      = Math.Pow(2, 1.0 - (double)(int)phoneme.Parent.Expressions["velocity"].Data / 100);
            double length           = phoneme.Oto.Preutter * strechRatio + phoneme.Envelope.Points[4].X;
            double requiredLength   = Math.Ceiling(length / 50 + 1) * 50;
            double lengthAdjustment = phoneme.TailIntrude == 0 ? phoneme.Preutter : phoneme.Preutter - phoneme.TailIntrude + phoneme.TailOverlap;

            RenderItem item = new RenderItem()
            {
                // For resampler
                RawFile        = rawfile,
                NoteNum        = phoneme.Parent.NoteNum,
                Velocity       = (int)phoneme.Parent.Expressions["velocity"].Data,
                Volume         = (int)phoneme.Parent.Expressions["volume"].Data,
                StrFlags       = phoneme.Parent.GetResamplerFlags(),
                PitchData      = BuildPitchData(phoneme, part, project),
                RequiredLength = (int)requiredLength,
                Oto            = phoneme.Oto,
                Tempo          = project.BPM,

                // For connector
                SkipOver = phoneme.Oto.Preutter * strechRatio - phoneme.Preutter,
                PosMs    = project.TickToMillisecond(part.PosTick + phoneme.Parent.PosTick + phoneme.PosTick) - phoneme.Preutter,
                DurMs    = project.TickToMillisecond(phoneme.DurTick) + lengthAdjustment,
                Envelope = phoneme.Envelope.Points
            };

            return(item);
        }
Esempio n. 2
0
            public override object Deserialize(IDictionary <string, object> dictionary, Type type, JavaScriptSerializer serializer)
            {
                UPhoneme result = new UPhoneme()
                {
                    PosTick      = Convert.ToInt32(dictionary["pos"]),
                    Phoneme      = dictionary["pho"] as string,
                    AutoEnvelope = Convert.ToBoolean(dictionary["autoenv"]),
                    AutoRemapped = Convert.ToBoolean(dictionary["remap"])
                };

                if (!result.AutoEnvelope)
                {
                    var env = dictionary["env"] as ArrayList;
                    for (int i = 0; i < 10; i++)
                    {
                        if (i % 2 == 0)
                        {
                            result.Envelope.Points[i / 2].X = Convert.ToDouble(env[i]);
                        }
                        else
                        {
                            result.Envelope.Points[i / 2].Y = Convert.ToDouble(env[i]);
                        }
                    }
                }
                return(result);
            }
Esempio n. 3
0
        public RenderItem(UPhoneme phoneme, UVoicePart part, UProject project)
        {
            var singer = project.Tracks[part.TrackNo].Singer;

            SourceFile = phoneme.Oto.File;
            SourceFile = Path.Combine(PathManager.Inst.InstalledSingersPath, SourceFile);

            var strechRatio      = Math.Pow(2, 1.0 - (double)(int)phoneme.Parent.Expressions["velocity"].Data / 100);
            var length           = phoneme.Oto.Preutter * strechRatio + phoneme.Envelope.Points[4].X;
            var requiredLength   = Math.Ceiling(length / 50 + 1) * 50;
            var lengthAdjustment = phoneme.TailIntrude == 0 ? phoneme.Preutter : phoneme.Preutter - phoneme.TailIntrude + phoneme.TailOverlap;

            NoteNum        = phoneme.Parent.NoteNum;
            Velocity       = (int)phoneme.Parent.Expressions["velocity"].Data;
            Volume         = (int)phoneme.Parent.Expressions["volume"].Data;
            StrFlags       = phoneme.Parent.GetResamplerFlags();
            PitchData      = BuildPitchData(phoneme, part, project);
            RequiredLength = (int)requiredLength;
            Oto            = phoneme.Oto;
            Tempo          = project.BPM;

            SkipOver = phoneme.Oto.Preutter * strechRatio - phoneme.Preutter;
            PosMs    = project.TickToMillisecond(part.PosTick + phoneme.Parent.PosTick + phoneme.PosTick) - phoneme.Preutter;
            DurMs    = project.TickToMillisecond(phoneme.DurTick) + lengthAdjustment;
            Envelope = phoneme.Envelope.Points;

            phonemeName = phoneme.Phoneme;
        }
Esempio n. 4
0
 public PhonemeChangeOverlapState(Canvas canvas, PianoRollViewModel vm,
                                  UNote leadingNote, UPhoneme phoneme, int index) : base(canvas, vm)
 {
     this.leadingNote = leadingNote;
     this.phoneme     = phoneme;
     this.index       = index;
 }
Esempio n. 5
0
 public SetPhonemeExpressionCommand(UProject project, UPhoneme phoneme, string abbr, float value)
 {
     this.project = project;
     this.phoneme = phoneme;
     Key          = abbr;
     newValue     = value;
     oldValue     = phoneme.GetExpression(project, abbr).Item1;
 }
Esempio n. 6
0
        private void UpdateOverlapAdjustment(UVoicePart part)
        {
            UPhoneme lastPhoneme = null;
            UNote    lastNote    = null;

            foreach (UNote note in part.Notes)
            {
                foreach (UPhoneme phoneme in note.Phonemes)
                {
                    if (lastPhoneme != null)
                    {
                        int    gapTick = phoneme.Parent.PosTick + phoneme.PosTick - lastPhoneme.Parent.PosTick - lastPhoneme.EndTick;
                        double gapMs   = DocManager.Inst.Project.TickToMillisecond(gapTick);
                        if (gapMs < phoneme.Preutter)
                        {
                            phoneme.Overlapped = true;
                            double lastDurMs       = DocManager.Inst.Project.TickToMillisecond(lastPhoneme.DurTick);
                            double correctionRatio = (lastDurMs + Math.Min(0, gapMs)) / 2 / (phoneme.Preutter - phoneme.Overlap);
                            if (phoneme.Preutter - phoneme.Overlap > gapMs + lastDurMs / 2)
                            {
                                phoneme.OverlapCorrection = true;
                                phoneme.Preutter          = gapMs + (phoneme.Preutter - gapMs) * correctionRatio;
                                phoneme.Overlap          *= correctionRatio;
                            }
                            else if (phoneme.Preutter > gapMs + lastDurMs)
                            {
                                phoneme.OverlapCorrection = true;
                                phoneme.Overlap          *= correctionRatio;
                                phoneme.Preutter          = gapMs + lastDurMs;
                            }
                            else
                            {
                                phoneme.OverlapCorrection = false;
                            }

                            lastPhoneme.TailIntrude = phoneme.Preutter - gapMs;
                            lastPhoneme.TailOverlap = phoneme.Overlap;
                        }
                        else
                        {
                            phoneme.Overlapped      = false;
                            lastPhoneme.TailIntrude = 0;
                            lastPhoneme.TailOverlap = 0;
                        }
                    }
                    else
                    {
                        phoneme.Overlapped = false;
                    }
                    lastPhoneme = phoneme;
                }
                lastNote = note;
            }
        }
Esempio n. 7
0
        public RenderItem(UPhoneme phoneme, UVoicePart part, UTrack track, UProject project, string resamplerName)
        {
            SourceFile    = phoneme.oto.File;
            SourceFile    = Path.Combine(PathManager.Inst.InstalledSingersPath, SourceFile);
            ResamplerName = resamplerName;
            if (project.expressions.TryGetValue("eng", out var descriptor))
            {
                int    index     = (int)phoneme.GetExpression(project, "eng").Item1;
                string resampler = descriptor.options[index];
                if (!string.IsNullOrEmpty(resampler))
                {
                    ResamplerName = resampler;
                }
            }
            string ext = Path.GetExtension(SourceFile);

            SourceTemp = Path.Combine(PathManager.Inst.GetCachePath(null),
                                      $"{HashHex(track.Singer.Id)}-{HashHex(phoneme.oto.Set)}-{HashHex(SourceFile)}{ext}");

            Velocity   = (int)phoneme.GetExpression(project, "vel").Item1;
            Volume     = (int)phoneme.GetExpression(project, "vol").Item1;
            Modulation = (int)phoneme.GetExpression(project, "mod").Item1;
            var strechRatio      = Math.Pow(2, 1.0 - Velocity / 100.0);
            var length           = phoneme.oto.Preutter * strechRatio + phoneme.envelope.data[4].X;
            var requiredLength   = Math.Ceiling(length / 50 + 1) * 50;
            var lengthAdjustment = phoneme.tailIntrude == 0 ? phoneme.preutter : phoneme.preutter - phoneme.tailIntrude + phoneme.tailOverlap;

            NoteNum        = phoneme.Parent.tone;
            StrFlags       = phoneme.GetResamplerFlags(project);
            PitchData      = BuildPitchData(phoneme, part, project);
            RequiredLength = (int)requiredLength;
            Oto            = phoneme.oto;
            Tempo          = project.bpm;

            SkipOver = phoneme.oto.Preutter * strechRatio - phoneme.preutter;
            PosMs    = project.TickToMillisecond(part.position + phoneme.Parent.position + phoneme.position) - phoneme.preutter;
            DurMs    = project.TickToMillisecond(phoneme.Duration) + lengthAdjustment;
            Envelope = phoneme.envelope.data;

            phonemeName = phoneme.phoneme;
        }
Esempio n. 8
0
        private void UpdatePhonemeDurTick(UVoicePart part)
        {
            UNote    lastNote    = null;
            UPhoneme lastPhoneme = null;

            foreach (UNote note in part.Notes)
            {
                foreach (UPhoneme phoneme in note.Phonemes)
                {
                    phoneme.DurTick = phoneme.Parent.DurTick - phoneme.PosTick;
                    if (lastPhoneme != null)
                    {
                        if (lastPhoneme.Parent == phoneme.Parent)
                        {
                            lastPhoneme.DurTick = phoneme.PosTick - lastPhoneme.PosTick;
                        }
                    }
                    lastPhoneme = phoneme;
                }
                lastNote = note;
            }
        }
Esempio n. 9
0
        private List <int> BuildPitchData(UPhoneme phoneme, UVoicePart part, UProject project)
        {
            var pitches  = new List <int>();
            var lastNote = part.Notes.OrderByDescending(x => x).Where(x => x.CompareTo(phoneme.Parent) < 0).FirstOrDefault();
            var nextNote = part.Notes.Where(x => x.CompareTo(phoneme.Parent) > 0).FirstOrDefault();
            // Get relevant pitch points
            var pps = new List <PitchPoint>();

            var lastNoteInvolved = lastNote != null && phoneme.Overlapped;
            var nextNoteInvolved = nextNote != null && nextNote.Phonemes[0].Overlapped;

            double lastVibratoStartMs = 0;
            double lastVibratoEndMs   = 0;
            double vibratoStartMs     = 0;
            double vibratoEndMs       = 0;

            if (lastNoteInvolved)
            {
                var offsetMs = DocManager.Inst.Project.TickToMillisecond(phoneme.Parent.PosTick - lastNote.PosTick);
                foreach (var pp in lastNote.PitchBend.Points)
                {
                    var newpp = pp.Clone();
                    newpp.X -= offsetMs;
                    newpp.Y -= (phoneme.Parent.NoteNum - lastNote.NoteNum) * 10;
                    pps.Add(newpp);
                }
                if (lastNote.Vibrato.Depth != 0)
                {
                    lastVibratoStartMs = -DocManager.Inst.Project.TickToMillisecond(lastNote.DurTick) * lastNote.Vibrato.Length / 100;
                    lastVibratoEndMs   = 0;
                }
            }

            foreach (var pp in phoneme.Parent.PitchBend.Points)
            {
                pps.Add(pp);
            }

            if (phoneme.Parent.Vibrato.Depth != 0)
            {
                vibratoEndMs   = DocManager.Inst.Project.TickToMillisecond(phoneme.Parent.DurTick);
                vibratoStartMs = vibratoEndMs * (1 - phoneme.Parent.Vibrato.Length / 100);
            }

            if (nextNoteInvolved)
            {
                var offsetMs = DocManager.Inst.Project.TickToMillisecond(phoneme.Parent.PosTick - nextNote.PosTick);
                foreach (var pp in nextNote.PitchBend.Points)
                {
                    var newpp = pp.Clone();
                    newpp.X -= offsetMs;
                    newpp.Y -= (phoneme.Parent.NoteNum - nextNote.NoteNum) * 10;
                    pps.Add(newpp);
                }
            }

            var startMs = DocManager.Inst.Project.TickToMillisecond(phoneme.PosTick) - phoneme.Oto.Preutter;
            var endMs   = DocManager.Inst.Project.TickToMillisecond(phoneme.DurTick) -
                          (nextNote != null && nextNote.Phonemes[0].Overlapped ? nextNote.Phonemes[0].Preutter - nextNote.Phonemes[0].Overlap : 0);

            if (pps.Count > 0)
            {
                if (pps.First().X > startMs)
                {
                    pps.Insert(0, new PitchPoint(startMs, pps.First().Y));
                }

                if (pps.Last().X < endMs)
                {
                    pps.Add(new PitchPoint(endMs, pps.Last().Y));
                }
            }
            else
            {
                throw new Exception("Zero pitch points.");
            }

            // Interpolation
            const int intervalTick = 5;
            var       intervalMs   = DocManager.Inst.Project.TickToMillisecond(intervalTick);
            var       currMs       = startMs;
            var       i            = 0;

            while (currMs < endMs)
            {
                while (pps[i + 1].X < currMs)
                {
                    i++;
                }

                var pit = MusicMath.InterpolateShape(pps[i].X, pps[i + 1].X, pps[i].Y, pps[i + 1].Y, currMs, pps[i].Shape);
                pit *= 10;

                // Apply vibratos
                if (currMs < lastVibratoEndMs && currMs >= lastVibratoStartMs)
                {
                    pit += InterpolateVibrato(lastNote.Vibrato, currMs - lastVibratoStartMs);
                }

                if (currMs < vibratoEndMs && currMs >= vibratoStartMs)
                {
                    pit += InterpolateVibrato(phoneme.Parent.Vibrato, currMs - vibratoStartMs);
                }

                pitches.Add((int)pit);
                currMs += intervalMs;
            }

            return(pitches);
        }
Esempio n. 10
0
        private List <int> BuildPitchData(UPhoneme phoneme, UVoicePart part, UProject project)
        {
            int  leftBound  = phoneme.Parent.position + phoneme.position - project.MillisecondToTick(phoneme.preutter);
            int  rightBound = phoneme.Parent.position + phoneme.position + phoneme.Duration - project.MillisecondToTick(phoneme.tailIntrude - phoneme.tailOverlap);
            var  leftNote   = phoneme.Parent;
            var  rightNote  = phoneme.Parent;
            bool oneMore    = true;

            while ((leftBound < leftNote.RightBound || oneMore) && leftNote.Prev != null && leftNote.Prev.End == leftNote.position)
            {
                leftNote = leftNote.Prev;
                if (leftBound >= leftNote.RightBound)
                {
                    oneMore = false;
                }
            }
            oneMore = true;
            while ((rightBound > rightNote.LeftBound || oneMore) && rightNote.Next != null && rightNote.Next.position == rightNote.End)
            {
                rightNote = rightNote.Next;
                if (rightBound <= rightNote.LeftBound)
                {
                    oneMore = false;
                }
            }

            // Collect pitch curve and vibratos.
            var   points      = new List <PitchPoint>();
            var   vibratos    = new List <Tuple <double, double, UVibrato> >();
            var   note        = leftNote;
            float vel         = Velocity;
            var   strechRatio = Math.Pow(2, 1.0 - vel / 100);
            float correction  = (float)(phoneme.oto.Preutter * (strechRatio - 1));

            while (true)
            {
                var offsetMs = (float)project.TickToMillisecond(note.position - phoneme.Parent.position);
                foreach (var point in note.pitch.data)
                {
                    var newpp = point.Clone();
                    newpp.X += offsetMs + correction;
                    newpp.Y -= (phoneme.Parent.tone - note.tone) * 10;
                    points.Add(newpp);
                }
                if (note.vibrato.length != 0)
                {
                    double vibratoStartMs = project.TickToMillisecond(note.position + note.duration * (1 - note.vibrato.length / 100) - phoneme.Parent.position);
                    double vibratoEndMs   = project.TickToMillisecond(note.End - phoneme.Parent.position);
                    vibratos.Add(Tuple.Create(vibratoStartMs, vibratoEndMs, note.vibrato));
                }
                if (note == rightNote)
                {
                    break;
                }
                note = note.Next;
            }

            // Expand curve if necessary.
            float startMs = (float)(project.TickToMillisecond(phoneme.position) - phoneme.oto.Preutter);
            float endMs   = (float)(project.TickToMillisecond(phoneme.End) - phoneme.tailIntrude + phoneme.tailOverlap);

            if (points.First().X > startMs)
            {
                points.Insert(0, new PitchPoint(startMs, points.First().Y));
            }
            if (points.Last().X < endMs)
            {
                points.Add(new PitchPoint(endMs, points.Last().Y));
            }

            // Interpolation.
            var       pitches      = new List <int>();
            const int intervalTick = 5;
            float     intervalMs   = (float)project.TickToMillisecond(intervalTick);
            float     currMs       = startMs;
            int       i            = 0;
            int       vibrato      = 0;

            while (currMs < endMs)
            {
                while (points[i + 1].X < currMs)
                {
                    i++;
                }
                var pit = MusicMath.InterpolateShape(points[i].X, points[i + 1].X, points[i].Y, points[i + 1].Y, currMs, points[i].shape) * 10;
                while (vibrato < vibratos.Count - 1 && vibratos[vibrato].Item2 < currMs)
                {
                    vibrato++;
                }
                if (vibrato < vibratos.Count && vibratos[vibrato].Item1 <= currMs && currMs < vibratos[vibrato].Item2)
                {
                    pit += InterpolateVibrato(vibratos[vibrato].Item3, currMs - vibratos[vibrato].Item1, vibratos[vibrato].Item2 - vibratos[vibrato].Item1, project);
                }
                pitches.Add((int)pit);
                currMs += intervalMs;
            }

            return(pitches);
        }