Exemple #1
0
        public void Phonemize(UProject project, UTrack track)
        {
            if (track.Singer == null || !track.Singer.Loaded)
            {
                return;
            }
            if (Extends != null)
            {
                return;
            }

            List <UNote> notes = new List <UNote> {
                this
            };

            while (notes.Last().Next != null && notes.Last().Next.Extends == this)
            {
                notes.Add(notes.Last().Next);
            }

            int endOffset = 0;

            if (notes.Last().Next != null && notes.Last().Next.phonemes.Count > 0)
            {
                endOffset = Math.Min(0, notes.Last().Next.position - notes.Last().End + notes.Last().Next.phonemes[0].position);
            }

            var  prev            = Prev?.ToProcessorNote();
            var  next            = notes.Last().Next?.ToProcessorNote();
            bool prevIsNeighbour = Prev?.End >= position;

            if (Prev?.Extends != null)
            {
                prev = Prev.Extends.ToProcessorNote();
                var phoneme = prev.Value;
                phoneme.duration = Prev.ExtendedDuration;
                prev             = phoneme;
            }
            bool nextIsNeighbour = notes.Last().End >= notes.Last().Next?.position;

            track.Phonemizer.SetTiming(project.bpm, project.beatUnit, project.resolution);
            var phonemizerNotes = notes.Select(note => note.ToProcessorNote()).ToArray();

            phonemizerNotes[phonemizerNotes.Length - 1].duration += endOffset;
            if (string.IsNullOrEmpty(phonemizerNotes[0].lyric) &&
                string.IsNullOrEmpty(phonemizerNotes[0].phoneticHint))
            {
                phonemes.Clear();
                return;
            }
            Phonemizer.Result phonemizerResult;
            try {
                phonemizerResult = track.Phonemizer.Process(
                    phonemizerNotes,
                    prev,
                    next,
                    prevIsNeighbour ? prev : null,
                    nextIsNeighbour ? next : null);
            } catch (Exception e) {
                Log.Error(e, "phonemizer error");
                phonemizerResult = new Phonemizer.Result()
                {
                    phonemes = new Phonemizer.Phoneme[] {
                        new Phonemizer.Phoneme {
                            phoneme = "error"
                        }
                    }
                };
            }
            var newPhonemes = phonemizerResult.phonemes;

            // Apply overrides.
            for (int i = phonemeOverrides.Count - 1; i >= 0; --i)
            {
                if (phonemeOverrides[i].IsEmpty)
                {
                    phonemeOverrides.RemoveAt(i);
                }
            }
            foreach (var o in phonemeOverrides)
            {
                if (o.index >= 0 && o.index < newPhonemes.Length)
                {
                    var p = newPhonemes[o.index];
                    if (o.phoneme != null)
                    {
                        p.phoneme = o.phoneme;
                    }
                    if (o.offset != null)
                    {
                        p.position += o.offset.Value;
                    }
                    newPhonemes[o.index] = p;
                }
            }
            // Safety treatment after phonemizer output and phoneme overrides.
            int maxPostion = notes.Last().End - notes.First().position + endOffset - 10;

            for (int i = newPhonemes.Length - 1; i >= 0; --i)
            {
                var p = newPhonemes[i];
                p.position     = Math.Min(p.position, maxPostion);
                newPhonemes[i] = p;
                maxPostion     = p.position - 10;
            }
            DistributePhonemes(notes, newPhonemes);
        }