1. 文档中心
  2. 比卜创造 Micro:bit
  3. API 参考
  4. 语音合成

speech

speech 模块让 micro:bit 说话、唱歌并发出其他类语音声音。默认情况下,声音会通过边缘连接器上的引脚 0 以及板载扬声器输出。你可以将有线耳机或扬声器连接到边缘连接器的引脚 0 与 GND 来收听声音。

语音合成示意
语音合成示意

使用前需先导入:

import speech

下文示例均假设已完成导入。

函数

translate(words)

给定字符串 words 中的英文单词,返回包含适当音素(用于发音)的最佳猜测字符串。

此函数用于生成音素的初步近似,可进一步手工编辑以提高准确性、语调和重音。

pronounce(phonemes, *, pitch=64, speed=72, mouth=128, throat=128)

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

发音字符串 phonemes 中的音素。详见下文音素用法,以精细控制语音合成器输出。可覆盖可选参数 pitch、speed、mouth、throat 以改变音色(音质)。

可选参数 pin 可指定输出引脚,覆盖默认的 pin0。若不想从引脚输出声音,可使用 pin=None。

say(words, *, pitch=64, speed=72, mouth=128, throat=128)

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

说出字符串 words 中的英文单词。对英语效果尚可。可覆盖可选参数以改变音色。这是 speech.pronounce(speech.translate(words)) 的简写。

sing(phonemes, *, pitch=64, speed=72, mouth=128, throat=128)

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

演唱字符串 phonemes 中的音素。改变音高与音符时长见下文。可覆盖可选参数以改变音色。

标点

标点用于改变语音表达方式。合成器理解四种标点:连字符、逗号、句号和问号。

连字符(-)标记从句边界,插入短停顿。

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

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

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

问号也插入停顿但使音高上升。这对「are we home yet?」这类是非问句效果较好,对「why are we going home?」这类复杂问句效果较差——后者宜用句号。

音色

声音的音色即音质——例如 DALEK 与人类声音的差异。要控制音色,可调整 pitch、speed、mouth 和 throat 参数的数值。

音高(声音高低)和语速(说话快慢)较直观,一般分类如下:

Pitch(音高):

  • 0–20 不实用
  • 20–30 很高
  • 30–40 高
  • 40–50 偏高正常
  • 50–70 正常
  • 70–80 偏低正常
  • 80–90 低
  • 90–255 很低

(默认 64)

Speed(语速):

  • 0–20 不实用
  • 20–40 很快
  • 40–60 快
  • 60–70 快对话
  • 70–75 正常对话
  • 75–90 叙述
  • 90–100 慢
  • 100–225 很慢

(默认 72)

mouth 与 throat 较难用文字说明,以下描述基于我们改变各设置时听到的印象。

mouth 数值越低,越像说话时不动嘴唇;数值越高(最高 255),越像夸张口型。

throat 数值越低,说话越放松;数值越高,语调越紧张。

关键是实验并调整,直到得到你想要的效果。

入门示例:

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 函数接受包含简化可读版国际音标的字符串,以及可选标注以表示语调与重音。

使用音素的优势是你不必会拼写——只需知道怎么说,就能按语音拼写。

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

简单元音                          浊辅音
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
双元音                                   V        se(v)en
EY           m(a)de                    DH       (th)en
AY           h(igh)
OY           b(oy)
AW           h(ow)                     清辅音
OW           sl(ow)                    S         (S)am
UW           cr(ew)                    SH        fi(sh)
                                           F         (f)ish
                                           TH        (th)in
特殊音素                                 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 (声门塞音)        /H        a(h)ead

以下非标准符号也可使用:

YX           双元音结尾(Y 的弱版)
WX           双元音结尾(W 的弱版)
RX           元音后的 R(R 的平滑版)
LX           元音后的 L(L 的平滑版)
/X           非前元音或辅音前的 H — 如 (wh)o
DX           如 pi(t)y 中的 T(T 的弱版)

较少使用的音素组合(及建议替代):

音素组合       你可能想要:           除非音节分割如:
GS             GZ 如 ba(gs)         bu(gs)pray
BS             BZ 如 slo(bz)        o(bsc)ene
DS             DZ 如 su(ds)         Hu(ds)son
PZ             PS 如 sla(ps)        -----
TZ             TS 如 cur(ts)y       -----
KZ             KS 如 fi(x)          -----
NG             NXG 如 singing       i(ng)rate
NK             NXK 如 bank          Su(nk)ist

若使用上述以外的音素,将引发 ValueError 异常。音素以字符串传入:

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

音素分为元音与辅音两大类。元音又分为简单元音与双元音——简单元音发音不变,双元音从一个音过渡到另一个。例如说「oil」时,「oi」从「oh」过渡到「ee」。

辅音也分浊辅音与清辅音。浊辅音需声带振动,如 L、N、Z;清辅音靠气流,如 P、T、SH。

熟悉后音素系统很简单。起初某些拼写可能棘手(如「adventure」含「CH」),规则是写你怎么说,不是怎么拼。实验是解决难词的最好办法。

为使语音自然易懂,常用内置重音系统添加语调或强调。

有八个重音标记,用数字 1–8 表示。在要重读的元音后插入相应数字。例如「/HEHLOW」缺乏表情,改为「/HEH3LOW」会更友好。

重音也可改变词义。考虑「Why should I walk to the store?」,可有多种读法:

# 你需要一个理由
speech.pronounce("WAY2 SHUH7D AY WAO5K TUX DHAH STOH5R.")
# 你不太愿意去
speech.pronounce("WAY7 SHUH2D AY WAO7K TUX DHAH STOH5R.")
# 你想让别人去
speech.pronounce("WAY5 SHUH7D AY2 WAO7K TUX DHAH STOHR.")
# 你更想开车
speech.pronounce("WAY5 SHUHD AY7 WAO2K TUX7 DHAH STOHR.")
# 你想去别处
speech.pronounce("WAY5 SHUHD AY WAO5K TUX DHAH STOH2OH7R.")

不同重音产生更有表现力的语调。它们通过提高或降低音高、延长对应元音实现,数字越小强调越强烈。重音标记也有助于正确发音难词——若某音节不够清晰,可加入中性重音标记。

也可通过重音标记延长发音:

speech.pronounce("/HEH5EH4EH3EH2EH2EH3EH4EH5EHLP.")

演唱

可以让 BiBoPython 演唱音素。

做法是在音素前标注与音高相关的数字——数字越小音越高。数字大致对应下图音符:

要标注音高,在音素前加井号 # 和音高数字。音高保持到出现新标注。例如唱音阶:

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」。

实验、仔细听并调整,是确定重复次数以达到所需时长的唯一可靠方法。

工作原理

原始手册解释得很清楚:

首先,我们不录制实际语音波形,只存储频率频谱。这样既省内存又有其他优势。其次,我们存储一些关于时序的数据——各音素在不同情况下的持续时间,以及过渡时间以便与相邻音素混合。第三,我们设计规则系统处理这些数据——很快我们的计算机就开始咿呀学语了。

—— S.A.M. 用户手册。

输出经 audio 模块提供的函数处理,于是 micro:bit 就能说话了。