Speech

该模块使 micro:bit 说话、唱歌和发出其他类似声音的语音。默认情况下,声音输出将通过引脚 0 上的边缘连接器和 内置扬声器 V2。您可以将有线耳机或扬声器连接到边缘连接器上的引脚 0 和 GND 以听到声音:

_images/speech.png

笔记

这项工作基于 Sebastian Macke 惊人的逆向工程成果,该程序基于一个名为 SAM(软件自动嘴)的旧文本到语音 (TTS) 程序,最初于 1982 年为 Commodore 64 发布。结果是一个小型 C 库我们已经采用并适应了 micro:bit。您可以从 他的主页上了解更多信息 。本文档中的大部分信息均来自原始用户手册,可在 此处找到 。

语音合成器可以从多达 255 个字符的文本输入中产生大约 2.5 秒的声音。

要访问此模块,您需要:

import speech

我们假设您已经为以下示例完成了此操作。

职能

speech.translate(words)

给定字符串中的英语单词words,返回一个字符串,其中包含对要发音的适当音素的最佳猜测。输出是从这个 文本到音素转换表生成的

此函数应用于生成音素的第一近似值,可以进一步手动编辑以提高准确性、屈折和强调。

speech.pronounce(phonemes, *, pitch=64, speed=72, mouth=128, throat=128)
speech.pronounce(phonemes, *, pitch=64, speed=72, mouth=128, throat=128, pin=pin0)

发音字符串中的音素 phonemes。有关如何使用音素精细控制语音合成器输出的详细信息,请参见下文。覆盖可选的音高、速度、嘴巴和喉咙设置以更改声音的音色(质量)。

对于 micro:bitV2,可以使用一个可选参数来指定输出引脚,以覆盖pin0. 如果我们不想管脚播放出任何声音,可以使用pin=None.

speech.say(words, *, pitch=64, speed=72, mouth=128, throat=128)
speech.say(words, *, pitch=64, speed=72, mouth=128, throat=128, pin=pin0)

说出字符串中的英文单词 words。结果对于英语来说是半准确的。覆盖可选的音高、速度、嘴巴和喉咙设置以更改声音的音色(质量)。这是一个简写相当于:speech.pronounce(speech.translate(words))

speech.sing(phonemes, *, pitch=64, speed=72, mouth=128, throat=128)
speech.sing(phonemes, *, pitch=64, speed=72, mouth=128, throat=128, pin=pin0)

唱出字符串中包含的音素phonemes。改变音符的音高和持续时间如下所述。覆盖可选的音高、速度、嘴巴和喉咙设置以更改声音的音色(质量)。

标点

标点符号用于改变语音的传递。合成器理解四个标点符号:连字符、逗号、句号和问号。

连字符 (-)通过在语音中插入一个短暂的停顿来标记从句的边界。

逗号 (,)标记短语边界并插入大约为连字符两倍的停顿。

句号 (.) 和问号 (?) 结束句子。

句号插入停顿并导致音高下降。

问号也会插入停顿,但会导致音调升高。这适用于是/否问题,例如“我们到家了吗?” 而不是更复杂的问题,例如“我们为什么要回家?”。在后一种情况下,请使用句号。

邮票

声音的音色是声音的质量。这是 DALEK 的声音和人类的声音(例如)之间的区别。为了控制音色变化的数值设置pitch, speed, mouththroat参数。

音高(声音的高低)和速度(语音的传递速度)设置相当明显,通常分为以下几类:

沥青:

  • 0-20 不切实际
  • 20-30 很高
  • 30-40高
  • 40-50高正常
  • 50-70 正常
  • 70-80 低正常
  • 80-90低
  • 90-255 极低

(默认为 64)

速度:

  • 0-20 不切实际
  • 20-40 非常快
  • 40-60快
  • 60-70 快速会话
  • 70-75 正常会话
  • 75-90 叙事
  • 90-100慢
  • 100-225 很慢

(默认为 72)

嘴巴和喉咙值有点难以解释,下面的描述是基于我们对每个设置的值改变时产生的语音的听觉印象。

对于嘴巴,数字越小,听起来越像说话者说话时嘴唇不动。相比之下,更高的数字(最多 255)使它听起来像是用夸张的嘴巴运动来表达语音。

对于喉咙,数字越低,说话者听起来越放松。相反,数字越高,语气就越紧张。

重要的是尝试和调整设置,直到获得所需的效果。

为了让您开始,这里有一些示例:

speech.say("I am a little robot",  speed=92, pitch=60, throat=190, mouth=190)
speech.say("I am an elf", speed=72, pitch=64, throat=110, mouth=160)
speech.say("I am a news presenter", speed=82, pitch=72, throat=110, mouth=105)
speech.say("I am an old lady", speed=82, pitch=32, throat=145, mouth=145)
speech.say("I am E.T.", speed=100, pitch=64, throat=150, mouth=200)
speech.say("I am a DALEK - EXTERMINATE", speed=120, pitch=100, throat=100, mouth=200)

音素

say功能可以轻松生成语音 - 但通常不准确。为了确保语音合成器准确地按照您的意愿发音 ,您需要使用音素:可用于区分不同单词的最小的可感知不同的声音单位。从本质上讲,它们是语音的基石。

pronounce函数采用一个字符串,该字符串包含国际音标 的简化和可读版本以及可选的注释以指示屈折和强调。

使用音素的好处是您不必知道如何拼写!相反,您只需要知道如何说出这个词,就可以按语音拼写。

下表列出了合成器理解的音素。

笔记

该表包含作为字符的音素和示例单词。示例词具有音素的发音(在括号中),但不一定是相同的字母。

经常被忽视:“H”音的符号是/H。声门停止是声音的强制停止。

SIMPLE VOWELS                          VOICED CONSONANTS
IY           f(ee)t                    R        (r)ed
IH           p(i)n                     L        a(ll)ow
EH           b(e)g                     W        a(w)ay
AE           S(a)m                     W        (wh)ale
AA           p(o)t                     Y        (y)ou
AH           b(u)dget                  M        Sa(m)
AO           t(al)k                    N        ma(n)
OH           c(o)ne                    NX       so(ng)
UH           b(oo)k                    B        (b)ad
UX           l(oo)t                    D        (d)og
ER           b(ir)d                    G        a(g)ain
AX           gall(o)n                  J        (j)u(dg)e
IX           dig(i)t                   Z        (z)oo
                                       ZH       plea(s)ure
DIPHTHONGS                             V        se(v)en
EY           m(a)de                    DH       (th)en
AY           h(igh)
OY           b(oy)
AW           h(ow)                     UNVOICED CONSONANTS
OW           sl(ow)                    S         (S)am
UW           cr(ew)                    SH        fi(sh)
                                       F         (f)ish
                                       TH        (th)in
SPECIAL PHONEMES                       P         (p)oke
UL           sett(le) (=AXL)           T         (t)alk
UM           astron(om)y (=AXM)        K         (c)ake
UN           functi(on) (=AXN)         CH        spee(ch)
Q            kitt-en (glottal stop)    /H        a(h)ead

用户还可以使用以下非标准符号:

YX           diphthong ending (weaker version of Y)
WX           diphthong ending (weaker version of W)
RX           R after a vowel (smooth version of R)
LX           L after a vowel (smooth version of L)
/X           H before a non-front vowel or consonant - as in (wh)o
DX           T as in pi(t)y (weaker version of T)

以下是一些很少使用的音素组合(以及建议的替代方案):

PHONEME        YOU PROBABLY WANT:     UNLESS IT SPLITS SYLLABLES LIKE:
COMBINATION
GS             GZ e.g. ba(gs)         bu(gs)pray
BS             BZ e.g. slo(bz)        o(bsc)ene
DS             DZ e.g. su(ds)         Hu(ds)son
PZ             PS e.g. sla(ps)        -----
TZ             TS e.g. cur(ts)y       -----
KZ             KS e.g. fi(x)          -----
NG             NXG e.g. singing       i(ng)rate
NK             NXK e.g. bank          Su(nk)ist

如果您使用上述音素以外的任何其他内容,ValueError 则会引发异常。将音素作为这样的字符串传入:

speech.pronounce("/HEHLOW")  # "Hello"

音素分为两大类:元音和辅音。

元音进一步细分为简单元音和双元音。简单的元音不会像你说的那样改变它们的声音,而双元音以一种声音开始并以另一种声音结束。例如,当您说出“oil”这个词时,“oi”元音以“oh”音开头,但会变成“ee”音。

辅音也分为两组:浊音和清音。浊辅音要求说话者使用他们的声带来发出声音。例如,像“L”、“N”和“Z”这样的辅音是浊音。清辅音是由急促的空气产生的,例如“P”、“T”和“SH”。

一旦习惯了,音素系统就很容易了。首先,一些拼写可能看起来很棘手(例如,“adventure”中有一个“CH”),但规则是写出你所说的,而不是你拼写的。实验是解决有问题的词的最好方法。

语音听起来自然且易于理解也很重要。为了帮助提高口语输出的质量,使用内置的重音系统来添加变化或强调通常是好的。

有八个由数字表示的压力标记 1 - 8。只需在要重读的元音后插入所需的数字。例如,当拼出“/HEH3LOW”时,“/HEHLOW”的缺乏表达得到了很大改善(并且更加友好)。

也可以通过强调单词的方式来改变单词的含义。想想“我为什么要步行去商店?”这句话。它可以用几种不同的方式发音:

# You need a reason to do it.
speech.pronounce("WAY2 SHUH7D AY WAO5K TUX DHAH STOH5R.")
# You are reluctant to go.
speech.pronounce("WAY7 SHUH2D AY WAO7K TUX DHAH STOH5R.")
# You want someone else to do it.
speech.pronounce("WAY5 SHUH7D AY2 WAO7K TUX DHAH STOHR.")
# You'd rather drive.
speech.pronounce("WAY5 SHUHD AY7 WAO2K TUX7 DHAH STOHR.")
# You want to walk somewhere else.
speech.pronounce("WAY5 SHUHD AY WAO5K TUX DHAH STOH2OH7R.")

简而言之,演讲中的不同重音会产生更具表现力的语气。

它们通过提高或降低音调并根据您提供的数字拉长相关的元音来工作:

  1. 情绪压力很大
  2. 压力很大
  3. 压力比较大
  4. 普通压力
  5. 紧张的压力
  6. 中性(无音高变化)应力
  7. 俯仰应力
  8. 极端降音压力

数字越小,强调的越极端。但是,这种重音标记将有助于正确发音困难的单词。例如,如果一个音节发音不充分,请放置一个中性重音标记。

也可以使用重音标记来延长单词:

speech.pronounce("/HEH5EH4EH3EH2EH2EH3EH4EH5EHLP.”)

唱歌

可以让 MicroPython 唱出音素。

这是通过将音高相关数字注释到音素上来完成的。数字越小,音高越高。数字大致转换为音符,如下图所示:

_images/speech-pitch.png

注释的工作原理#是在音素前面预先添加一个哈希 ( ) 符号和音调编号。音高将保持不变,直到给出新的注释。例如,让 MicroPython 唱这样的音阶:

solfa = [
    "#115DOWWWWWW",   # Doh
    "#103REYYYYYY",   # Re
    "#94MIYYYYYY",    # Mi
    "#88FAOAOAOAOR",  # Fa
    "#78SOHWWWWW",    # Soh
    "#70LAOAOAOAOR",  # La
    "#62TIYYYYYY",    # Ti
    "#58DOWWWWWW",    # Doh
]
song = ''.join(solfa)
speech.sing(song, speed=100)

为了在一定时间内唱出一个音符,通过重复元音或浊辅音音素来扩展音符(如上例所示)。当心双元音 - 要扩展它们,您需要将它们分解成它们的组成部分。例如,“OY”可以扩展为“OHOHIYIYIY”。

实验、仔细聆听和调整是计算一个音素重复多少次以便音符持续所需持续时间的唯一可靠方法。

它是如何工作的?

原始手册解释得很好:

首先,我们只存储频谱,而不是记录实际的语音波形。通过这样做,我们可以节省内存并获得其他优势。其次,我们 [...] 存储一些有关计时的数据。这些是与每个音素在不同情况下的持续时间有关的数字,以及一些关于转换时间的数据,因此我们可以知道如何将一个音素与其相邻的音素混合。第三,我们设计了一个规则系统来处理所有这些数据,令我们惊讶的是,我们的计算机很快就开始胡言乱语了。

—SAM 用户手册。

输出通过 audio模块提供的功能进行管道传输,嘿,很快,我们有一个会说话的 micro:bit。

例子

"""
    speech.py
    ~~~~~~~~

    Simple speech example to make the micro:bit say, pronounce and sing
    something. This example requires a speaker/buzzer/headphones connected
    to P0 and GND,or the latest micro:bit device with built-in speaker.
"""
import speech
from microbit import sleep

# The say method attempts to convert English into phonemes.
speech.say("I can sing!")
sleep(1000)
speech.say("Listen to me!")
sleep(1000)

# Clearing the throat requires the use of phonemes. Changing
# the pitch and speed also helps create the right effect.
speech.pronounce("AEAE/HAEMM", pitch=200, speed=100)  # Ahem
sleep(1000)

# Singing requires a phoneme with an annotated pitch for each syllable.
solfa = [
    "#115DOWWWWWW",   # Doh
    "#103REYYYYYY",   # Re
    "#94MIYYYYYY",    # Mi
    "#88FAOAOAOAOR",  # Fa
    "#78SOHWWWWW",    # Soh
    "#70LAOAOAOAOR",  # La
    "#62TIYYYYYY",    # Ti
    "#58DOWWWWWW",    # Doh
]

# Sing the scale ascending in pitch.
song = ''.join(solfa)
speech.sing(song, speed=100)
# Reverse the list of syllables.
solfa.reverse()
song = ''.join(solfa)
# Sing the scale descending in pitch.
speech.sing(song, speed=100)