|
, i% z4 F/ K2 N6 m- V
华 中 师 范 大 学 卢 小 海(flier@126.com) 3 h" }9 D* T5 D2 p5 i5 {
各位朋友,请加入本站邮件列表,你将得到本站最新更新及动态。 ) \% |7 p4 d1 g! \2 O- K7 l
# a+ g: R9 M" C3 [# t& }: g1 t1 s
---- 金 山 词 霸2000 的 英 文 全 文 朗 读 功 能 相 信 一 定 给 尝 试 过 的 用 户 留 下 了 很 深 刻 的 印 象, 而 作 为 一 个 程 序 设 计 者, 你 一 定 也 想 在 自 己 的 程 序 中 加 入 类 似 的 功 能 吧, 因 为 那 将 让 自 己 的 程 序 增 色 不 少。 - b2 w3 T3 q' h; D0 ]: d
----其 实 这 并 不 是 一 件 困 难 的 事, 因 为 金 山 词 霸 实 际 上 也 只 是 直 接 使 用 了MS 的TTS(Text -to -Speech) 技 术 而 已, 通 过 对MS Speech API 的 编 程, 我 们 完 全 可 以 实 现 比 其 更 强 大 的 功 能。 下 面, 让 我 们 在Delphi 环 境 下 实 际 尝 试 一 下。
( _$ B: ?1 b& w4 ]! i----首 先 从 金 山 词 霸 的 光 盘 上\ciba 目 录 下 运 行 并 安 装mstts.exe(MS TTS engine) 和spchapi.exe(MS Speech API)。 " u, B0 [- z4 y4 T7 x/ u: F
----再 在Delphi 里 新 建 一 个Application。
% k7 B2 f( ]* M# I5 ~3 [----然 后 从Delphi 的 菜 单Project/Import Type Library... 中 选 击Add..., 浏 览 到Windows 目 录 下 的Speech 子 目 录 里, 打 开vtxtauto.tlb, 可 以 看 到 下 面Class names 中 会 出 现 我 们 需 要 的 接 口 的 包 装 类 的 名 字TVTxtAuto, 注 意 对 话 框 底 部 的Generate Component Wrapper 需 要 被 选 中, 点 击Create Unit 就 可 以 打 开 一 个 名 为VTxtAuto_TLB 的Unit。
* y$ i' n; q* h) ?----至 此, 我 们 就 可 以 开 始 实 际 编 程 了。
9 `! z9 Z- V( ~4 E----首 先 在Form 的OnCreate 中 对 需 要 使 用 接 口 初 始 化 并 进 行 注 册:
! f- X, I% W' q; M3 W ...
& E2 `! R" e3 }# c# {, ^ procedure TfrmMain.FormCreate(Sender: TObject);
) Z. ~! x& F+ v begin) S7 l9 G1 U, i2 P2 j) ]
FISpeech := CoVTxtAuto_.Create;
: M& \9 P" H8 U& K FISpeech.Register(‘Demo Site', ‘Demo App');, p; E8 g4 ~$ w# _
end;. H; W* v: K! M/ u( w8 H. A
... 2 ^* x2 u+ F2 o8 X
----由 于Delphi 对 接 口 进 行 了 良 好 的 包 装, 因 此 只 需 直 接 建 立 包 装 类, 其 他 后 台 的 操 作 如 接 口 的 查 询、 释 放 等 交 给Delphi 在 后 台 自 动 完 成。 " g, d) X1 V% a- ^) y
----注 意 这 里 的Register 操 作 是 必 不 可 少 的, 因 为 可 能 有 多 个 程 序 不 同 设 置 使 用TTS 引 擎。 ( Q( W2 l L" ^1 U9 x6 ]/ r+ R! s
----然 后 在MainForm 上 放 一 个TMemo 和 若 干 个 TButton, 并 在 其OnClick 中 加 入 对 应 的 代 码。
. r( ~( I; `6 S: KForm 定 义 如 下:
1 c* E# D0 Y' U; m) ~% a$ ^8 | object frmMain: TfrmMain; L+ w+ g5 J: Q, p8 w! Y' X
Left = 296
! K4 ` n' p9 O% O Top = 187( G2 D$ t* Y; [
BorderStyle = bsDialog
6 l+ Z7 }- b) k) e! I/ ` Caption = ‘ 英 文 全 文 朗 读 演 示'
\4 W. Y4 R1 g \* s8 R ClientHeight = 1852 X3 y1 l, ?9 c1 c! Y1 y
ClientWidth = 456. l( P4 U1 V8 N% l1 z0 `$ k
Color = clBtnFace
: e; k/ P& P& h5 @% |8 t5 ]6 o Font.Charset = GB2312_CHARSET( |/ T/ n* {0 p+ l" l% c) u
Font.Color = clWindowText
( \: [, P: g: E Font.Height = -12
# S# g6 H" K% f, d Font.Name = ‘ 宋 体'+ g1 S% H1 _) x7 L; b
Font.Style = []
& ?$ ^5 I5 z D g$ \ OldCreateOrder = False
2 K% M% `: b/ J* R+ ~ Position = poDesktopCenter
* a' ?( I+ o( @( C+ t6 Q: ` OnCreate = FormCreate1 ]) T! V- X5 Y5 _) f
PixelsPerInch = 96% u. S- m0 X( N/ z1 P
TextHeight = 12( `# P% Y& O4 S5 ^8 i. G3 i
object memText: TMemo( ], _9 a8 R5 F# e+ W% A% ]1 O3 y
Left = 8% d6 S" g7 U1 K
Top = 83 l! I9 Z. E- P4 |
Width = 361% o* r% G8 d/ v0 [5 Y0 K
Height = 169- ~( Y* k! e0 }, ~2 f/ I
ScrollBars = ssVertical
8 t/ l8 s! c) r- T/ Z" ] TabOrder = 0
J G9 J+ u" z1 I' [8 d end1 |( ^. Q4 g# G5 U* o1 V+ |, |! R
object btnRead: TButton! d6 @1 a1 M, j6 x; h* [
Left = 376+ {5 w: `% q [9 H6 L6 D1 ^0 M
Top = 8
8 k9 |1 q) O; d( V Width = 751 G6 e3 b5 [/ \
Height = 25
! y. a" N- X0 p; S Caption = ‘ 朗 读( &R)'
/ d# p4 T3 t" \; c* }- x- U TabOrder = 13 X V& O2 P' c7 {9 m' c! M$ e8 k
OnClick = btnReadClick
6 ?, ^% z( i9 t8 v7 i/ Z6 U; [ end/ C) A! g7 y, x: e8 X8 K
object btnPause: TButton
; c- h' f% {% G7 R, B Left = 376, c# _$ e; a! M; I- W0 q$ p) r7 K5 G
Top = 404 h' p) a* O9 g2 U( A% D
Width = 75. S8 p+ L7 X; s* D/ B& w
Height = 25# v' }# U2 q s2 v# x6 ?
Caption = ‘ 暂 停( &P)'! U5 R3 G- n/ u, Y' v; Q5 r
Enabled = False3 Q, E0 j, Q* x r# Q4 D O
TabOrder = 2
9 F3 B& t C, [$ \ OnClick = btnPauseClick
+ f/ c# a; K6 \) P5 B4 t end
Y( n/ `' z' J5 I$ q6 h object btnStop: TButton
3 Z6 h3 C6 Z( A6 t Left = 376# O6 G5 Z' \4 B6 \% ]1 ]& _2 `6 B
Top = 72) |% U2 ]# Z5 O4 b: e# m
Width = 75' a! c1 e8 _7 N5 o
Height = 25& C6 v3 F4 D1 Y& S! e
Caption = ‘ 停 止( &S)'+ Y) w7 h' _1 {0 ]- O: F
Enabled = False0 K' W/ c2 Z$ t8 T4 e: W+ |* X5 C
TabOrder = 30 L, R; N# U+ `, b
OnClick = btnStopClick
6 V X5 [/ p9 `* `0 y. y end; F3 q0 n5 Z/ X
object btnForward: TButton
5 T' q; Q. W) x Left = 376# d0 {( j/ ]6 X
Top = 120
; N' r8 [2 J/ d- n' d Width = 75
% c) T* u' ~ M# f: _1 g Height = 25
8 T3 b/ d/ g2 `6 v0 a1 {. w: x Caption = ‘ 下 一 句( &N)') x' W8 {2 ]0 g7 u9 Z6 n
Enabled = False' K9 H _7 h/ d z7 J
TabOrder = 4
# [3 c$ N1 k9 B6 T9 O OnClick = btnForwardClick5 R! n# j8 [# {" k2 Y6 y3 v
end
* v6 V: _" H! \1 ^ object btnRewind: TButton" r9 c* k& Y* _' `3 I/ h3 n0 o$ J
Left = 3762 F0 w9 Q( T9 S3 Y+ L
Top = 152/ i- A, b3 B. W$ O$ z
Width = 75' C* v# [+ G% V
Height = 25* \8 r$ E! i: H, ?2 \
Caption = ‘ 上 一 句( &W)'" T& W/ C2 L. s+ \! @' G
Enabled = False; J! |; j3 O/ l x% B
TabOrder = 5
# \* _, _- B( K OnClick = btnRewindClick! O- S8 N; Y2 s `1 v' B5 q3 v
end
1 t6 _8 q: R- j) B5 D, T7 Z end
& p ?& z# U* J3 _! B' U3 W----关 键 代 码 段 如 下:
3 a/ ~7 S/ r( w8 K---- 1. 朗 读 与 停 止 ( @/ b2 G9 v+ {6 E* u$ h" E8 Y+ i
...# D) g, R: k) _$ J1 `
procedure TfrmMain.btnReadClick(Sender: TObject);
, l5 |) r& S5 g9 M' k r begin
+ K3 G8 L0 H& E FISpeech.Speak(memText.Lines.Text, vtxtst_ 3 z; l8 |. E1 W# `3 L: ~
READING);
. @& G; A" W y9 V# w# y c$ G btnPause.Enabled := True;, Z8 Z. C0 i3 U2 U
btnStop.Enabled := True;
- d( E2 H4 ]% ^1 J: T end;
3 { W2 R4 x' M% X
" K( _) _' p6 T: `2 _procedure TfrmMain.btnStopClick(Sender: TObject);
) m6 G+ M2 e8 i begin( X4 N9 X8 \+ a
FISpeech.StopSpeaking;" s+ D4 @( s" G- k Y
btnPause.Enabled := False;8 N, ?0 P2 j2 W. Y3 n# ]1 e3 m% e
btnStop.Enabled := False;
* h! N: N8 K9 L7 H t btnPause.Caption := ‘ 暂 停( &P)';
, H* Q$ }6 B* F' v- L( @ end;
6 ?7 e7 X) k: `( v- r: o/ d) f ...
$ m5 m# b2 O, U----Speak 成 员 函 数 的 第 一 个 参 数 向TTS 引 擎 传 递 需 要 朗 读 的 文 字, 第 二 个 参 数 由 指 定 朗 读 时 使 用 的 语 气 和 优 先 级 的 两 个 符 号 合 并 而 成。
& f# z- U4 f$ \6 b- U# B1 y9 U' x, H# S0 F) y/ w: R! n
---- 2. 暂 停 与 恢 复
. J8 @, O8 G/ x/ S ...
3 I* Y& h) F5 i( |/ d: eprocedure TfrmMain.btnPauseClick(Sender: TObject);$ d2 ~, U3 \, A
begin, k9 G7 j. S$ D9 Q" H
with FISpeech do, r9 M$ J O" p) n, x6 X
if IsSpeaking then# K1 Y! n- K1 R- l9 j0 X* x8 g/ h
begin2 k8 L" U- p2 G
AudioPause;4 f/ S) O3 H5 A* w
btnPause.Caption := ‘ 恢 复( &R)';
; G, k3 o' W+ |2 `# p end
/ i7 Y! e8 l4 M8 i+ M4 H else
" E; ?9 E" n% H/ B; G2 q2 o* g begin& B& r* q9 E" Z0 W
AudioResume;( F: p- f3 K( U1 }: p& T
btnPause.Caption := ‘ 暂 停( &P)';& ]0 @3 j4 z e
end;
# ]. g, w) O3 H% p. G# H8 p& ^end;
9 k1 q# R# w. P$ ?- u7 z S% N. p... " u. D! U* E5 h
----这 里 通 过IsSpeaking 属 性 可 以 取 得 当 前 状 态, 然 后 通 过AudioPause 和AudioResume 暂 停 和 恢 复 朗 读。 / }+ v) q4 q" p: L, l& q8 d m& k
----另 外 用 成 员 函 数AudioFastForward 和AudioRewind 可 以 向 前 和 后 跳 过 一 句 朗 读, 通 过 读 写Speed 属 性 还 可 以 取 得 或 设 置 朗 读 的 语 速, 单 位 是 字/ 分, 缺 省 值 为170。
0 X' E$ k2 r `3 e% e----注 意Speed 和Enabled 属 性 缺 省 设 置 是 只 写 的, 但 实 际 上IVTxtAuto 提 供 了Get_Speed 和Get_Enabled 函 数, 所 以 我 们 只 要 把VTxtAuto_TLB 单 元 中 的 声 明 修 改 一 下, 如: 4 j1 Z* Q: e7 J' m; |: K
...
/ R/ l. f6 F9 ]! d+ TIVTxtAuto = interface(IDispatch)
# o& h( M7 P7 F* B ...4 A3 \7 f; z e6 I, ?: K
property Speed: Integer read Get_Speed write Set_Speed;
% H1 h) Y. K1 P/ f property Enabled: Integer read Get_Enabled write Set_Enabled;
% E" |% K% z: n) M ...
9 _% t$ T9 h5 R! i/ f1 _5 {7 fend;( s, H' C* P- S
... 5 H, S' T& a8 x- L; }8 @4 g* b: S( ], o
----即 可 正 常 使 用Speed 和Enabled 属 性 了。 8 c0 ~9 O5 j, u5 y, \) l2 W" ^9 ] d
----至 此, 一 个 简 单 的 英 文 全 文 朗 读 器 就 完 成 了, 有 兴 趣 的 朋 友 可 以 为 其 加 入 监 视 剪 贴 板, 热 键 激 活 等 功 能。
) s/ T! I3 }1 j' g1 q----本 文 程 序 在Win NT/98 + Delphi 4/5 环 境 下 调 试 通 过。! w& _+ r3 A% W! W
& K2 J+ A: [- {# a. s/ D7 T
|