예제 #1
0
        public void BuildVibratoInfo(RenderNote note, RenderNote prevNote, RenderNote nextNote, out VibratoInfo vibratoInfo, out VibratoInfo vibratoPrevInfo)
        {
            vibratoInfo = new VibratoInfo {
                Start = 0, End = 0, Vibrato = note.Vibrato, Length = note.FinalLength
            };
            if (prevNote != null)
            {
                vibratoPrevInfo = new VibratoInfo
                {
                    Start   = 0,
                    End     = 0,
                    Vibrato = prevNote.Vibrato,
                    Length  = prevNote.FinalLength
                }
            }
            ;
            else
            {
                vibratoPrevInfo = new VibratoInfo {
                    Start = 0, End = 0, Vibrato = null, Length = 0
                }
            };

            if (note.Vibrato != null && note.Vibrato.Depth != 0)
            {
                vibratoInfo.End   = MusicMath.Current.TickToMillisecond(note.FinalLength, Tempo);
                vibratoInfo.Start = vibratoInfo.End * (1 - note.Vibrato.Length / 100);
            }

            if (prevNote != null && prevNote.Vibrato != null && prevNote.Vibrato.Depth != 0)
            {
                vibratoPrevInfo.Start = -MusicMath.Current.TickToMillisecond(prevNote.FinalLength, Tempo) * prevNote.Vibrato.Length / 100;
                vibratoPrevInfo.End   = 0;
            }
        }
예제 #2
0
        private RenderNote[] BuildRenderNotes(Ust ust, Singer singer)
        {
            var renderNotes = new List <RenderNote>();

            for (int i = 0; i < ust.Notes.Length; i++)
            {
                var renderNote = RenderNote.CreateFromNote(ust.Notes[i]);
                renderNote.Oto = singer.FindOto(renderNote) ?? Oto.CreateDefault();
                renderNotes.Add(renderNote);
            }

            for (int i = 0; i < renderNotes.Count; i++)
            {
                var note = renderNotes[i];
                var next = renderNotes.ElementAtOrDefault(i + 1);
                note.Envelope = new Envelope(note, next);
            }

            var pitchController = new PitchController(ust.Tempo);

            for (int i = 0; i < renderNotes.Count; i++)
            {
                var prev = renderNotes.ElementAtOrDefault(i - 1);
                var curr = renderNotes.ElementAtOrDefault(i);
                var next = renderNotes.ElementAtOrDefault(i + 1);

                pitchController.BuildPitchData(curr, prev, next);
            }

            return(renderNotes.ToArray());
        }
예제 #3
0
        private string BuildRequest(Ust ust, Singer singer, string output, string resampler, string appendtool, string tempFolder)
        {
            stringBuilder = new StringBuilder();

            var notes = BuildRenderNotes(ust, singer);

            for (int i = 0; i < notes.Length; i++)
            {
                RenderNote note     = notes[i];
                RenderNote next     = notes.ElementAtOrDefault(i + 1);
                var        tempFile = Path.Combine(tempFolder, $"_{i.ToString().PadLeft(3, '0')}_[{note.ParsedLyric}]_[{note.NoteNum}]_[{note.FinalLength}].wav");
                if (note.IsRest)
                {
                    SendRestToAppendTool(note.FinalLength, output, tempFile, ust.Tempo, appendtool);
                }
                else
                {
                    SendToResampler(note, next, tempFile, ust.VoiceDir, ust.Flags, resampler);
                    SendToAppendTool(note, next, tempFile, appendtool, ust.Tempo, output);
                }
            }

            var result = stringBuilder.ToString();

            stringBuilder.Clear();
            stringBuilder = null;
            return(result);
        }
예제 #4
0
        /// <summary>
        ///     Send Note to AppendTool
        /// </summary>
        private void SendToAppendTool(RenderNote note, RenderNote next, string filename, string appendtool, double tempo, string output)
        {
            var offset = note.Oto.Preutterance;

            if (next != null)
            {
                offset -= next.Oto.StraightPreutterance;
            }

            var    envelope = note.Envelope;
            var    sign     = offset >= 0 ? "+" : "-";
            var    length   = $"{note.FinalLength}@{tempo}{sign}{Math.Abs(offset).ToString("f0")}";
            string ops      = string.Format("{0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} {11} {12}",
                                            0,      //note.Stp, // STP,
                                            length, //note.RequiredLength,
                                            envelope.p1,
                                            envelope.p2,
                                            envelope.p3,
                                            envelope.v1,
                                            envelope.v2,
                                            envelope.v3,
                                            envelope.v4,
                                            note.Oto.Overlap,
                                            envelope.p4,
                                            envelope.p5,
                                            envelope.v5);
            var request = $"\"{appendtool}\" \"{output}\" \"{filename}\" {ops} \r\n";

            stringBuilder.AppendLine(request);
        }
예제 #5
0
        private void SendToResampler(RenderNote note, RenderNote next, string tempFilename, string voiceDir, string flags, string resampler)
        {
            var    pitchBase64    = Base64.Current.Base64EncodeInt12(note.PitchBend.Array);
            var    oto            = note.Oto;
            var    otoFile        = Path.Combine(voiceDir, oto.File);
            var    stringNum      = MusicMath.Current.NoteNum2String(note.NoteNum - 24);
            var    requiredLength = GetRequiredLength(note, next);
            string request        = string.Format(
                "\"{0}\" \"{1}\" \"{2}\" {3} {4} \"{5}\" {6} {7} {8} {9} {10} {11} !{12} {13}\r\n\r\n",
                resampler,
                otoFile,
                tempFilename,
                stringNum,
                note.Velocity * 100,
                "D" + note.Flags,
                oto.Offset,
                requiredLength,
                oto.Consonant,
                oto.Cutoff,
                note.Intensity,
                0.0, //note.Modulation,
                note.NoteNum,
                pitchBase64);

            stringBuilder.AppendLine(request);
        }
예제 #6
0
        private int GetRequiredLength(RenderNote note, RenderNote next)
        {
            var    len            = note.FinalLength;
            double requiredLength = len + note.Oto.Preutterance;
            //if (next != null)
            //    requiredLength -= next.StraightPre;

            var stp = 0;

            requiredLength = Math.Ceiling((requiredLength + stp + 25) / 50) * 50;
            return((int)requiredLength);
        }
예제 #7
0
        public static RenderNote CreateFromNote(Note note)
        {
            var renderNote = new RenderNote();

            renderNote.FinalLength = note.FinalLength;
            renderNote.NoteNum     = note.NoteNum;
            renderNote.Intensity   = note.Intensity;
            renderNote.ParsedLyric = note.ParsedLyric;
            renderNote.Lyric       = note.Lyric;
            renderNote.IsRest      = note.IsRest;
            renderNote.Flags       = note.Flags;
            renderNote.Velocity    = note.Velocity;

            return(renderNote);
        }
예제 #8
0
        public PitchInfo BuildPitchInfo(RenderNote note, RenderNote prevNote, RenderNote nextNote)
        {
            var pitchInfo       = new PitchInfo();
            var autoPitchLength = 40;
            var autoPitchOffset = -20;
            var firstNoteRaise  = 10;

            var oto = note.Oto;
            var pps = new List <PitchPoint>();

            foreach (var pp in note.PitchBend.Points)
            {
                pps.Add(pp);
            }
            if (pps.Count == 0)
            {
                var offsetY = prevNote == null ? firstNoteRaise : GetPitchDiff(note.NoteNum, prevNote.NoteNum);
                pps.Add(new PitchPoint(MusicMath.Current.TickToMillisecond(autoPitchOffset, Tempo), -offsetY));
                pps.Add(new PitchPoint(MusicMath.Current.TickToMillisecond(autoPitchOffset + autoPitchLength, Tempo), 0));
                note.PitchBend.Data = pps;
            }

            var cutoffFromNext = nextNote != null ? nextNote.Oto.StraightPreutterance : 0;

            // end and start ms
            var    startMs = pps.First().X < -oto.Preutterance ? pps.First().X : -oto.Preutterance;
            double endMs   = MusicMath.Current.TickToMillisecond(note.FinalLength, Tempo) - cutoffFromNext;

            // if not all the length involved, add end and/or start pitch points
            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));
            }

            var start = (int)MusicMath.Current.SnapMs(pps.First().X, Tempo);
            var end   = (int)MusicMath.Current.SnapMs(pps.Last().X, Tempo);

            // combine all
            pitchInfo.Start       = start;
            pitchInfo.End         = end;
            pitchInfo.PitchPoints = pps.ToArray();
            return(pitchInfo);
        }
예제 #9
0
 public Envelope(RenderNote note, RenderNote next = null)
 {
     p1 = note.Oto.Overlap;
     p2 = note.Oto.Preutterance;
     p3 = 30;
     p4 = 0;
     p5 = 0;
     v1 = 60;
     v2 = 100;
     v3 = 60;
     v4 = 0;
     v5 = 100;
     if (next != null)
     {
         p3 = next.Oto.Overlap;
     }
 }
예제 #10
0
        public void BuildPitchData(RenderNote note, RenderNote prevNote, RenderNote nextNote)
        {
            BuildVibratoInfo(note, prevNote, nextNote, out var vibratoInfo, out var vibratoPrevInfo);
            var pitches   = BuildVibrato(vibratoInfo, vibratoPrevInfo);
            var pitchInfo = BuildPitchInfo(note, prevNote, nextNote);
            var pitchesP  = BuildPitch(pitchInfo);

            if (pitchInfo.Start > 0)
            {
                throw new Exception();
            }
            var offset = -pitchInfo.Start / INTERVAL_TICK;

            pitches = Interpolate(pitchesP, pitches, offset);
            note.PitchBend.Array = pitches;
            var renderNote = (RenderNote)note;

            renderNote.PitchInfo   = pitchInfo;
            renderNote.VibratoInfo = vibratoInfo;
        }