diff --git a/tts/text/input_parsing/parser.py b/tts/text/input_parsing/parser.py index 26d73a3..cbdbb87 100644 --- a/tts/text/input_parsing/parser.py +++ b/tts/text/input_parsing/parser.py @@ -17,11 +17,11 @@ class ArpabetSequence: def __init__(self, sequence: str): self.sequence = sequence -class GraphemeSquence: +class GraphemeSequence: def __init__(self, sequence: str): self.sequence = sequence -ParsedSequence = List[Union[ArpabetSequence, GraphemeSquence]] +ParsedSequence = List[Union[ArpabetSequence, GraphemeSequence]] def parse_grapheme_and_arpabet_sequence(input_text: str) -> ParsedSequence: """ @@ -35,7 +35,7 @@ def parse_grapheme_and_arpabet_sequence(input_text: str) -> ParsedSequence: input_text = input_text.strip() m = _curly_re.match(input_text) if not m: - sequence.append(GraphemeSquence(input_text)) + sequence.append(GraphemeSequence(input_text)) break before = m.group(1).strip() @@ -43,7 +43,7 @@ def parse_grapheme_and_arpabet_sequence(input_text: str) -> ParsedSequence: after = m.group(3).strip() if before: - sequence.append(GraphemeSquence(before)) + sequence.append(GraphemeSequence(before)) if bracketed: sequence.append(ArpabetSequence(bracketed)) diff --git a/tts/text/input_parsing/test_parser.py b/tts/text/input_parsing/test_parser.py index 543479c..6545bc5 100644 --- a/tts/text/input_parsing/test_parser.py +++ b/tts/text/input_parsing/test_parser.py @@ -1,11 +1,11 @@ -from tts.text.input_parsing.parser import ArpabetSequence, GraphemeSquence, parse_grapheme_and_arpabet_sequence +from tts.text.input_parsing.parser import ArpabetSequence, GraphemeSequence, parse_grapheme_and_arpabet_sequence class TestParser: def test_only_text(self): parsed = parse_grapheme_and_arpabet_sequence("This is a test") assert len(parsed) == 1 - assert isinstance(parsed[0], GraphemeSquence) + assert isinstance(parsed[0], GraphemeSequence) def test_only_arpabet(self): parsed = parse_grapheme_and_arpabet_sequence("{T EH1 S T IH0 NG}") @@ -15,31 +15,31 @@ class TestParser: def test_text_and_arpabet(self): parsed = parse_grapheme_and_arpabet_sequence("This is a {T EH1 S T}") assert len(parsed) == 2 - assert isinstance(parsed[0], GraphemeSquence) + assert isinstance(parsed[0], GraphemeSequence) assert isinstance(parsed[1], ArpabetSequence) def test_text_and_arpabet_interleved_1(self): parsed = parse_grapheme_and_arpabet_sequence("{DH IH1 S} is a {T EH1 S T}") assert len(parsed) == 3 assert isinstance(parsed[0], ArpabetSequence) - assert isinstance(parsed[1], GraphemeSquence) + assert isinstance(parsed[1], GraphemeSequence) assert isinstance(parsed[2], ArpabetSequence) def test_text_and_arpabet_interleved_2(self): parsed = parse_grapheme_and_arpabet_sequence("Check out {DH IH1 S} {T EH1 S T} of the {S IH1 S T AH0 M}") assert len(parsed) == 5 - assert isinstance(parsed[0], GraphemeSquence) + assert isinstance(parsed[0], GraphemeSequence) assert isinstance(parsed[1], ArpabetSequence) assert isinstance(parsed[2], ArpabetSequence) - assert isinstance(parsed[3], GraphemeSquence) + assert isinstance(parsed[3], GraphemeSequence) assert isinstance(parsed[4], ArpabetSequence) def test_text_and_arpabet_interleved_2(self): parsed = parse_grapheme_and_arpabet_sequence("Check out {DH IH1 S} {T EH1 S T} of the {S IH1 S T AH0 M}.") assert len(parsed) == 6 - assert isinstance(parsed[0], GraphemeSquence) + assert isinstance(parsed[0], GraphemeSequence) assert isinstance(parsed[1], ArpabetSequence) assert isinstance(parsed[2], ArpabetSequence) - assert isinstance(parsed[3], GraphemeSquence) + assert isinstance(parsed[3], GraphemeSequence) assert isinstance(parsed[4], ArpabetSequence) - assert isinstance(parsed[5], GraphemeSquence) \ No newline at end of file + assert isinstance(parsed[5], GraphemeSequence) \ No newline at end of file diff --git a/tts/text/phonetization/english_phonetization.py b/tts/text/phonetization/english_phonetization.py index 60674aa..10dd3f2 100644 --- a/tts/text/phonetization/english_phonetization.py +++ b/tts/text/phonetization/english_phonetization.py @@ -1,4 +1,5 @@ from typing import List +from tts.text.input_parsing.parser import ArpabetSequence, GraphemeSequence, ParsedSequence from tts.text.phonetization.base_phonetization import BasePhonetization from tts.text.phonetization.cmudict import CMUDict @@ -7,7 +8,7 @@ class EnglishPhonetization(BasePhonetization): def __init__(self, phoneme_dictionary: CMUDict): super().__init__(phoneme_dictionary) - def try_convert_to_phonemes(self, grapheme_sequence: str) -> List[str]: + def try_convert_to_phonemes(self, grapheme_sequence: str) -> ParsedSequence: """ Attempt to enrich a grapheme sequence with phonemes where word lookup succeeds. Grapheme symbols will be left in place. @@ -21,9 +22,9 @@ class EnglishPhonetization(BasePhonetization): if maybe_phonemes: # NB: Dictionary returns a list of possible matches. # We'll just use the first. - converted_words.append(maybe_phonemes[0]) + converted_words.append(ArpabetSequence(maybe_phonemes[0])) else: # TODO: Use g2p prediction to predict the phonemes. - converted_words.append(word) + converted_words.append(GraphemeSequence(word)) return converted_words diff --git a/tts/text/pipeline/english_pipeline_v1.py b/tts/text/pipeline/english_pipeline_v1.py index 38e405f..2e704a9 100644 --- a/tts/text/pipeline/english_pipeline_v1.py +++ b/tts/text/pipeline/english_pipeline_v1.py @@ -1,5 +1,5 @@ from typing import List -from tts.text.input_parsing.parser import GraphemeSquence, ParsedSequence, parse_grapheme_and_arpabet_sequence +from tts.text.input_parsing.parser import ArpabetSequence, GraphemeSequence, ParsedSequence, parse_grapheme_and_arpabet_sequence from tts.text.normalization.english_normalization import EnglishNormalization from tts.text.phonetization.cmudict import CMUDict from tts.text.phonetization.english_phonetization import EnglishPhonetization @@ -16,27 +16,34 @@ class EnglishPipelineV1(BasePipeline): """Convert raw user input into a numerical sequence for ML inference.""" parsed_sequence = parse_grapheme_and_arpabet_sequence(input_text) - self._normalize_graphemes(parsed_sequence) - self._convert_phonemes(parsed_sequence) + + parsed_sequence = self._convert_phonemes(parsed_sequence) - - integer_sequence = [] - - return integer_sequence + return self._convert_to_integer_sequence(parsed_sequence) def _normalize_graphemes(self, parsed_sequence: ParsedSequence): for i in range(len(parsed_sequence)): subsequence = parsed_sequence[i] - if isinstance(subsequence, GraphemeSquence): + if isinstance(subsequence, GraphemeSequence): normalized = _ENGLISH_NORMALIZER.normalize(subsequence.sequence) - parsed_sequence[i] = GraphemeSquence(normalized) + parsed_sequence[i] = GraphemeSequence(normalized) - def _convert_phonemes(self, parsed_sequence: ParsedSequence): - for i in range(len(parsed_sequence)): - subsequence = parsed_sequence[i] - if isinstance(subsequence, GraphemeSquence): - converted = _ENGLISH_PHONETIZER.try_convert_to_phonemes(subsequence.sequence) - converted = ' '.join(converted) - parsed_sequence[i] = GraphemeSquence(converted) + def _convert_phonemes(self, parsed_sequence: ParsedSequence) -> ParsedSequence: + # NB: We will likely break grapheme runs into multiple arpabet sequences, extending the + # output list length. + updated_sequence = [] + + for subsequence in parsed_sequence: + if isinstance(subsequence, ArpabetSequence): + updated_sequence.append(subsequence) + + elif isinstance(subsequence, GraphemeSequence): + converted_sequence = _ENGLISH_PHONETIZER.try_convert_to_phonemes(subsequence.sequence) + updated_sequence.extend(converted_sequence) + + return updated_sequence + + def _convert_to_integer_sequence(self, parsed_sequence: ParsedSequence) -> List[int]: + pass \ No newline at end of file diff --git a/tts/text/pipeline/legacy_vocodes_pipeline.py b/tts/text/pipeline/legacy_vocodes_pipeline.py index e69de29..4235843 100644 --- a/tts/text/pipeline/legacy_vocodes_pipeline.py +++ b/tts/text/pipeline/legacy_vocodes_pipeline.py @@ -0,0 +1,2 @@ +# TODO: In the future we may allow uploads of legacy vocodes models. +# These models utilize a very unique encoding scheme.