def test_separator(): backend = SegmentsBackend('cree') text = 'achi acho' sep = separator.default_separator assert backend.phonemize(text, separator=sep) == u'ʌtʃɪ ʌtʃʊ ' assert backend.phonemize(text, separator=sep, strip=True) == u'ʌtʃɪ ʌtʃʊ'
def version(): """Return version information for front and backends""" # version of the phonemizer version = ('phonemizer-' + pkg_resources.get_distribution('phonemizer').version) # for each backend, check if it is available or not. If so get its version available = [] unavailable = [] if EspeakBackend.is_available(): available.append('espeak-' + ('ng-' if EspeakBackend.is_espeak_ng() else '') + EspeakBackend.version()) else: # pragma: nocover unavailable.append('espeak') if FestivalBackend.is_available(): available.append('festival-' + FestivalBackend.version()) else: # pragma: nocover unavailable.append('festival') if SegmentsBackend.is_available(): available.append('segments-' + SegmentsBackend.version()) else: # pragma: nocover unavailable.append('segments') # resumes the backends status in the final version string if available: version += '\navailable backends: ' + ', '.join(available) if unavailable: # pragma: nocover version += '\nuninstalled backends: ' + ', '.join(unavailable) return version
def test_segments(): text = 'achi, acho!' expected1 = 'ʌtʃɪ ʌtʃʊ' expected2 = 'ʌtʃɪ, ʌtʃʊ!' expected3 = 'ʌtʃɪ ʌtʃʊ ' expected4 = 'ʌtʃɪ, ʌtʃʊ!' out1 = SegmentsBackend('cree', preserve_punctuation=False).phonemize([text], strip=True)[0] assert out1 == expected1 out2 = SegmentsBackend('cree', preserve_punctuation=True).phonemize([text], strip=True)[0] assert out2 == expected2 out3 = SegmentsBackend('cree', preserve_punctuation=False).phonemize( [text], strip=False)[0] assert out3 == expected3 out4 = SegmentsBackend('cree', preserve_punctuation=True).phonemize([text], strip=False)[0] assert out4 == expected4
def test_separator_3(): backend = SegmentsBackend('cree') text = 'achi acho' sep = separator.Separator(word=' ', syllable=None, phone='_') assert backend.phonemize(text, separator=sep) == u'ʌ_tʃ_ɪ_ ʌ_tʃ_ʊ_ ' assert backend.phonemize(text, separator=sep, strip=True) \ == u'ʌ_tʃ_ɪ ʌ_tʃ_ʊ'
def test_separator_5(): backend = SegmentsBackend('cree') text = 'achi acho' sep = separator.Separator(phone=' ', word='_') assert backend.phonemize(text, separator=sep) == u'ʌ tʃ ɪ _ʌ tʃ ʊ _' assert backend.phonemize(text, separator=sep, strip=True) \ == u'ʌ tʃ ɪ_ʌ tʃ ʊ'
def test_separator_2(): backend = SegmentsBackend('cree') text = ['achi acho'] sep = Separator(word='_', phone=' ') assert backend.phonemize(text, separator=sep) == [u'ʌ tʃ ɪ _ʌ tʃ ʊ _'] assert backend.phonemize(text, separator=sep, strip=True) \ == [u'ʌ tʃ ɪ_ʌ tʃ ʊ']
def test_separator_4(): backend = SegmentsBackend('cree') text = 'achi acho' # TODO bug when sep.phone == ' ' with no sep.word sep = separator.Separator(phone=' ', word='') assert backend.phonemize(text, separator=sep) == u'ʌ tʃ ɪ ʌ tʃ ʊ ' assert backend.phonemize(text, separator=sep, strip=True) \ == u'ʌ tʃ ɪʌ tʃ ʊ'
def test_multiline(): backend = SegmentsBackend('cree') assert backend.phonemize('a') == u'ʌ ' assert backend.phonemize('aa') == u'ʌʌ ' assert backend.phonemize('a\n') == u'ʌ ' assert backend.phonemize('a\na') == u'ʌ \nʌ ' assert backend.phonemize('a\na\n') == u'ʌ \nʌ '
def version(): """Return version information for front and backends""" version = ('phonemizer-' + pkg_resources.get_distribution('phonemizer').version) return version + '\navailable backends: ' + ', '.join( ('festival-' + FestivalBackend.version(), ('espeak-' + ('ng-' if EspeakBackend.is_espeak_ng() else '') + EspeakBackend.version()), 'segments-' + SegmentsBackend.version()))
def test_multiline(): backend = SegmentsBackend('cree') assert backend.language == 'cree' assert backend.phonemize(['a']) == [u'ʌ '] assert backend.phonemize(['aa']) == [u'ʌʌ '] assert backend.phonemize(['a\n']) == [u'ʌ '] assert backend.phonemize(['a\na']) == [u'ʌ ʌ '] assert backend.phonemize(['a\na\n']) == [u'ʌ ʌ '] assert backend.phonemize(['a', 'a']) == [u'ʌ ', 'ʌ '] assert backend.phonemize(['a\n', 'a\n']) == [u'ʌ ', 'ʌ ']
def test_language(tmpdir): # check languages by name assert SegmentsBackend.is_supported_language('cree') assert not SegmentsBackend.is_supported_language('unexisting') # check languages by g2p file directory = pkg_resources.resource_filename( pkg_resources.Requirement.parse('phonemizer'), 'phonemizer/share') assert SegmentsBackend.is_supported_language( os.path.join(directory, 'cree.g2p')) assert not SegmentsBackend.is_supported_language( os.path.join(directory, 'cree')) assert not SegmentsBackend.is_supported_language( os.path.join(directory, 'unexisting.g2p')) # bad syntax in g2p file p = tmpdir.join('foo.g2p') p.write('\n'.join(['a a', 'b b b', 'c'])) assert not SegmentsBackend.is_supported_language(p)
def recognize(self, wav=None): if not self.eng.find("fest") == -1: # ======= festival english us only ===================================== from phonemizer.backend import FestivalBackend out1 = FestivalBackend( 'en-us', preserve_punctuation=False).phonemize(self.text, strip=True) elif not self.eng.find("esp") == -1: # ======= espeak ======================================================= from phonemizer.backend import EspeakBackend if not self.lan.find("en") == -1: backend = EspeakBackend('en-us') elif not self.lan.find("fr") == -1: backend = EspeakBackend('fr-fr') elif not self.lan.find("de") == -1 or not self.lan.find( "ger") == -1: backend = EspeakBackend('de-de') elif not self.lan.find("ita") == -1: backend = EspeakBackend('it-it') elif not self.lan.find("esp") == -1 or not self.lan.find( "spa") == -1: backend = EspeakBackend('es-es') else: print("Invalid Language specified") exit(1) sep = separator.Separator(word=';eword ', syllable=None, phone=' ') out1 = backend.phonemize(self.text, sep, False) elif not self.eng.find("mbr") == -1: # ====== mbrola ======================================================== from phonemizer.backend import EspeakBackend, EspeakMbrolaBackend if EspeakMbrolaBackend.is_available(): if not self.lan.find("en") == -1: EspeakMbrolaBackend('mb-en1') elif not self.lan.find("fr") == -1: EspeakMbrolaBackend('mb-fr2') elif not self.lan.find("de") == -1 or not self.lan.find( "ger") == -1: EspeakMbrolaBackend('mb-de1') elif not self.lan.find("ita") == -1: EspeakMbrolaBackend('mb-es1') elif not self.lan.find("esp") == -1 or not self.lan.find( "spa") == -1: EspeakMbrolaBackend('mb-it3') else: print("Invalid Language specified") exit(1) sep = separator.Separator(word=';eword ', syllable=None, phone=' ') out1 = backend.phonemize(self.text, sep, False) elif not self.eng.find("seg") == -1: # ===== segment ======================================================== from phonemizer.backend import SegmentsBackend if not self.lan.find("ja") == -1: backend = SegmentsBackend('japanese') else: print("Invalid Language specified") exit(1) sep = separator.Separator(word=';eword ', syllable=None, phone=' ') out1 = backend.phonemize(self.text, sep, False) else: print("Invalid Language specified") exit(1) print(out1) # return the result string to the speach engine
def test_bad_morpheme(): backend = SegmentsBackend('cree') with pytest.raises(ValueError): backend.phonemize('A')
def parse_args(): """Argument parser for the phonemization script""" parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, description='''Multilingual text to phonemes converter The 'phonemize' program allows simple phonemization of words and texts in many language using three backends: espeak, festival and segments. - espeak is a text-to-speech software supporting multiple languages and IPA (Internatinal Phonetic Alphabet) output. See http://espeak.sourceforge.net or https://github.com/espeak-ng/espeak-ng - festival is also a text-to-speech software. Currently only American English is supported and festival uses a custom phoneset (http://www.festvox.org/bsv/c4711.html), but festival is the only backend supporting tokenization at the syllable level. See http://www.cstr.ed.ac.uk/projects/festival - segments is a Unicode tokenizer that build a phonemization from a grapheme to phoneme mapping provided as a file by the user. See https://github.com/cldf/segments. See the '--language' option below for details on the languages supported by each backend. ''', epilog=''' Languages supported by the festival backend are: {festival} Languages supported by the segments backend are: {segments} Instead of a language you can also provide a file specifying a grapheme to phoneme mapping (see the files above for exemples). Languages supported by the espeak backend are: {espeak} Exemples: * Phonemize a US English text with espeak $ echo 'hello world' | phonemize -l en-us -b espeak həloʊ wɜːld * Phonemize a US English text with festival $ echo 'hello world' | phonemize -l en-us -b festival hhaxlow werld * Phonemize a Japanese text with segments $ echo 'konnichiwa tsekai' | phonemize -l japanese -b segments konnitʃiwa t͡sekai * Add a separator between phones $ echo 'hello world' | phonemize -l en-us -b festival -p '-' --strip hh-ax-l-ow w-er-l-d * Phonemize some French text file using espeak $ phonemize -l fr-fr -b espeak text.txt -o phones.txt '''.format(festival='\n'.join( '\t{}\t->\t{}'.format(k, v) for k, v in sorted(FestivalBackend.supported_languages().items())), segments='\n'.join( '\t{}\t->\t{}'.format(k, v) for k, v in sorted( SegmentsBackend.supported_languages().items())), espeak='\n'.join( '\t{}\t->\t{}'.format(k, v) for k, v in sorted( EspeakBackend.supported_languages().items())))) # general arguments parser.add_argument('--version', action='store_true', help='show version information and exit.') group = parser.add_mutually_exclusive_group() group.add_argument('-v', '--verbose', action='store_true', help='write all log messages to stderr ' '(displays only warnings by default).') group.add_argument('-q', '--quiet', action='store_true', help='do not display any log message, even warnings.') parser.add_argument( '-j', '--njobs', type=int, metavar='<int>', default=1, help='number of parallel jobs, default is %(default)s.') # input/output arguments group = parser.add_argument_group('input/output') group.add_argument( 'input', default=sys.stdin, nargs='?', metavar='<file>', help='input text file to phonemize, if not specified read from stdin.') group.add_argument( '-o', '--output', default=sys.stdout, metavar='<file>', help='output text file to write, if not specified write to stdout.') group = parser.add_argument_group('separators') group.add_argument('-p', '--phone-separator', metavar='<str>', default=separator.default_separator.phone, help='phone separator, default is "%(default)s".') group.add_argument('-w', '--word-separator', metavar='<str>', default=separator.default_separator.word, help='word separator, default is "%(default)s".') group.add_argument( '-s', '--syllable-separator', metavar='<str>', default=separator.default_separator.syllable, help='''syllable separator, only valid for festival backend, this option has no effect if espeak or segments is used. Default is "%(default)s".''') group.add_argument('--strip', action='store_true', help='removes the end separators in phonemized tokens.') group = parser.add_argument_group('backends') group.add_argument( '-b', '--backend', metavar='<str>', default='espeak', choices=['espeak', 'festival', 'segments'], help="""the phonemization backend, must be 'espeak', 'festival' or 'segments'. Default is %(default)s.""") group = parser.add_argument_group('specific to espeak backend') group.add_argument( '--with-stress', action='store_true', help='''when the option is set, the stresses on phonemes are present (stresses characters are ˈ'ˌ). By default stresses are removed.''') group.add_argument( '--sampa', action='store_true', help='''only valid for espeak-ng and NOT supported for espeak, use the "sampa" (Speech Assessment Methods Phonetic Alphabet) alphabet instead of "ipa" (International Phonetic Alphabet).''') group.add_argument( '--language-switch', default='keep-flags', choices=['keep-flags', 'remove-flags', 'remove-utterance'], help="""espeak can pronounce some words in another language (typically English) when phonemizing a text. This option setups the policy to use when such a language switch occurs. Three values are available: 'keep-flags' (the default), 'remove-flags' or 'remove-utterance'. The 'keep-flags' policy keeps the language switching flags, for example (en) or (jp), in the output. The 'remove-flags' policy removes them and the 'remove-utterance' policy removes the whole line of text including a language switch.""") group = parser.add_argument_group('language') group.add_argument( '-l', '--language', metavar='<str|file>', default='en-us', help='''the language code of the input text, see below for a list of supported languages. According to the language code you specify, the appropriate backend (segments, espeak or festival) will be called in background. Default is %(default)s.''') return parser.parse_args()
def parse_args(): """Argument parser for the phonemization script""" parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, description='''Multilingual text to phonemes converter The 'phonemize' program allows simple phonemization of words and texts in many language using three backends: espeak, festival and segments. - espeak is a text-to-speech software supporting multiple languages and IPA (Internatinal Phonetic Alphabet) output. See http://espeak.sourceforge.net or https://github.com/espeak-ng/espeak-ng - festival is also a text-to-speech software. Currently only American English is supported and festival uses a custom phoneset (http://www.festvox.org/bsv/c4711.html), but festival is the only backend supporting tokenization at the syllable level. See http://www.cstr.ed.ac.uk/projects/festival - segments is a Unicode tokenizer that build a phonemization from a grapheme to phoneme mapping provided as a file by the user. See https://github.com/cldf/segments. See the '--language' option below for details on the languages supported by each backend. ''', epilog=''' Languages supported by the festival backend are: {festival} Languages supported by the segments backend are: {segments} Instead of a language you can also provide a file specifying a grapheme to phoneme mapping (see the files above for exemples). Languages supported by the espeak backend are: {espeak} Exemples: * Phonemize a US English text with espeak $ echo 'hello world' | phonemize -l en-us -b espeak həloʊ wɜːld * Phonemize a US English text with festival $ echo 'hello world' | phonemize -l en-us -b festival hhaxlow werld * Phonemize a Japanese text with segments $ echo 'konnichiwa tsekai' | phonemize -l japanese -b segments konnitʃiwa t͡sekai * Add a separator between phones $ echo 'hello world' | phonemize -l en-us -b festival -p '-' --strip hh-ax-l-ow w-er-l-d * Phonemize some French text file using espeak $ phonemize -l fr-fr -b espeak text.txt -o phones.txt '''.format( festival='\n'.join( '\t{}\t->\t{}'.format(k, v) for k, v in sorted(FestivalBackend.supported_languages().items())), segments='\n'.join( '\t{}\t->\t{}'.format(k, v) for k, v in sorted(SegmentsBackend.supported_languages().items())), espeak='\n'.join( '\t{}\t->\t{}'.format(k, v) for k, v in sorted(EspeakBackend.supported_languages().items())))) # general arguments parser.add_argument( '--version', action='store_true', help='show version information and exit') parser.add_argument( '-v', '--verbose', action='store_true', help='write some log messages to stderr') parser.add_argument( '-j', '--njobs', type=int, metavar='<int>', default=1, help='number of parallel jobs, default is %(default)s') # input/output arguments group = parser.add_argument_group('input/output') group.add_argument( 'input', default=sys.stdin, nargs='?', metavar='<file>', help='input text file to phonemize, if not specified read from stdin') group.add_argument( '-o', '--output', default=sys.stdout, metavar='<file>', help='output text file to write, if not specified write to stdout') group = parser.add_argument_group('separators') group.add_argument( '-p', '--phone-separator', metavar='<str>', default=separator.default_separator.phone, help='phone separator, default is "%(default)s"') group.add_argument( '-w', '--word-separator', metavar='<str>', default=separator.default_separator.word, help='word separator, default is "%(default)s"') group.add_argument( '-s', '--syllable-separator', metavar='<str>', default=separator.default_separator.syllable, help='''syllable separator is available only for the festival backend, this option has no effect if espeak or segments is used. Default is "%(default)s"''') group.add_argument( '--strip', action='store_true', help='removes the end separators in phonemized tokens') group = parser.add_argument_group('language') group.add_argument( '-b', '--backend', metavar='<str>', default='espeak', choices=['espeak', 'festival', 'segments'], help="""the phonemization backend, must be 'espeak', 'festival' or 'segments'. Default is %(default)s""") group.add_argument( '-l', '--language', metavar='<str|file>', default='en-us', help='''the language code of the input text, see below for a list of supported languages. According to the language code you specify, the appropriate backend (segments, espeak or festival) will be called in background. Default is %(default)s''') return parser.parse_args()