|
" ]" A1 i. b/ j6 Z
华 中 师 范 大 学 卢 小 海(flier@126.com)
) I& `* d, ]" I+ r0 |+ B$ ~7 U4 Q 各位朋友,请加入本站邮件列表,你将得到本站最新更新及动态。
. H+ w* o$ c5 K( X1 ]4 f3 |) i# A$ g3 z- H1 K' E' Z. A+ H
---- 金 山 词 霸2000 的 英 文 全 文 朗 读 功 能 相 信 一 定 给 尝 试 过 的 用 户 留 下 了 很 深 刻 的 印 象, 而 作 为 一 个 程 序 设 计 者, 你 一 定 也 想 在 自 己 的 程 序 中 加 入 类 似 的 功 能 吧, 因 为 那 将 让 自 己 的 程 序 增 色 不 少。 7 n- _! K- U+ K7 y5 o6 k
----其 实 这 并 不 是 一 件 困 难 的 事, 因 为 金 山 词 霸 实 际 上 也 只 是 直 接 使 用 了MS 的TTS(Text -to -Speech) 技 术 而 已, 通 过 对MS Speech API 的 编 程, 我 们 完 全 可 以 实 现 比 其 更 强 大 的 功 能。 下 面, 让 我 们 在Delphi 环 境 下 实 际 尝 试 一 下。 3 T) ^- `- V9 o5 E3 R
----首 先 从 金 山 词 霸 的 光 盘 上\ciba 目 录 下 运 行 并 安 装mstts.exe(MS TTS engine) 和spchapi.exe(MS Speech API)。
' p: M, i* m4 r----再 在Delphi 里 新 建 一 个Application。
( |* M, j2 K. [2 t2 F& K: E----然 后 从Delphi 的 菜 单Project/Import Type Library... 中 选 击Add..., 浏 览 到Windows 目 录 下 的Speech 子 目 录 里, 打 开vtxtauto.tlb, 可 以 看 到 下 面Class names 中 会 出 现 我 们 需 要 的 接 口 的 包 装 类 的 名 字TVTxtAuto, 注 意 对 话 框 底 部 的Generate Component Wrapper 需 要 被 选 中, 点 击Create Unit 就 可 以 打 开 一 个 名 为VTxtAuto_TLB 的Unit。
7 y6 G) c9 K" j3 |) g; X3 S% X9 T0 h----至 此, 我 们 就 可 以 开 始 实 际 编 程 了。 / y+ Y: i+ g" |, q# t
----首 先 在Form 的OnCreate 中 对 需 要 使 用 接 口 初 始 化 并 进 行 注 册: & N- s5 P2 S* U
...5 _) Z) b2 M( \$ h6 k8 A
procedure TfrmMain.FormCreate(Sender: TObject);
% F% ]2 [9 ^) ? begin" k+ w1 X$ b. g. t8 e, w' P
FISpeech := CoVTxtAuto_.Create;6 G$ U: D+ k( l# r- z
FISpeech.Register(‘Demo Site', ‘Demo App');
* j( A( @( t8 p6 E end;
2 H) @% [0 o7 [2 W& H... 3 D* h$ n l8 p' r8 G6 Z7 V( L
----由 于Delphi 对 接 口 进 行 了 良 好 的 包 装, 因 此 只 需 直 接 建 立 包 装 类, 其 他 后 台 的 操 作 如 接 口 的 查 询、 释 放 等 交 给Delphi 在 后 台 自 动 完 成。 9 i. y. P3 P$ T7 {2 r0 N
----注 意 这 里 的Register 操 作 是 必 不 可 少 的, 因 为 可 能 有 多 个 程 序 不 同 设 置 使 用TTS 引 擎。
( i0 Z! m4 n3 u3 ^7 A, z# S3 Z----然 后 在MainForm 上 放 一 个TMemo 和 若 干 个 TButton, 并 在 其OnClick 中 加 入 对 应 的 代 码。 l2 b9 X# \% U( D0 f. R. S
Form 定 义 如 下: ( d' D; [2 Y5 N
object frmMain: TfrmMain8 {3 x9 E. g" m9 l
Left = 296: C7 }# K m7 P" \6 E. ~
Top = 187# c9 t- p9 U+ w( @
BorderStyle = bsDialog# Y* b5 O+ n) p+ |7 ?% ~. a4 l
Caption = ‘ 英 文 全 文 朗 读 演 示'
- N% T% H2 S. C& _: a) e! O& t' | ClientHeight = 185) |0 s2 t# m0 f- F K& p
ClientWidth = 456
) c; H$ X. T! Y% q' p) P# w Color = clBtnFace
" E4 z' ]+ ^# b6 e( ? Font.Charset = GB2312_CHARSET
# \" {1 A* d- |/ \! F Font.Color = clWindowText
3 X/ X2 L0 e9 ~) O Font.Height = -12
2 U) G% r7 j' z' k7 T$ T Font.Name = ‘ 宋 体'
3 B& F9 ^1 o: |' q& R% P! w Font.Style = []
: Y% {4 j! x. r2 b# l- } OldCreateOrder = False
, q5 r& }3 ^3 ] Position = poDesktopCenter5 Q c. u3 J' s$ R& o) d- P
OnCreate = FormCreate
5 p/ h6 N ~. U% _ PixelsPerInch = 969 X, n+ t; u" P' n3 c3 f3 w5 l7 Q
TextHeight = 12. [% r, f8 S& |7 @3 P
object memText: TMemo
+ F+ U: ]8 Y% l2 v. n, e5 W Left = 8" {2 m- L! G6 q8 I8 X. O7 `
Top = 8
& W5 S6 L& Y& M6 W5 p' I Width = 361' @+ s4 w6 U4 L- O5 r4 r
Height = 169, O" Q, r- }' x) |* G& _4 D
ScrollBars = ssVertical6 N+ Q" y# O& x- s' P# l4 ]0 n
TabOrder = 0$ j6 V; ], U1 @( N o, C+ k: F0 g) [
end% M. S7 h1 I. \
object btnRead: TButton" t0 F# O- Z' \ l( T6 D
Left = 376
, S5 Z l: [! B' M9 P( \ Top = 8& Y' R9 Y7 [6 @; C
Width = 75 z& g$ T+ p' R2 L" E
Height = 25
3 L; [6 o' D* Y; e) X. C Caption = ‘ 朗 读( &R)'
0 {) q7 E! Y4 }# q: F TabOrder = 17 @. I) f" Q* H3 W* x/ A
OnClick = btnReadClick
/ \& R7 j2 P: B- F( c% _) k end' v2 g. w+ o# K. |) G; l1 Q
object btnPause: TButton
% _: c6 ]% m- b5 d8 m Left = 376$ V7 i/ D0 N$ Y: v6 U# Z5 n- H
Top = 400 Y3 s$ S( T* M
Width = 75
- ^4 _5 {+ r q+ y2 {2 R Height = 250 {- D) j V6 i. o
Caption = ‘ 暂 停( &P)'8 N, h" T+ E' a3 D; b
Enabled = False
$ V# o2 o! \" j4 R TabOrder = 2" j8 `9 X* {7 b9 X% [
OnClick = btnPauseClick
8 r: \; c9 S1 ` end
& k( o' i& e! t5 j' h P' M* C8 u object btnStop: TButton
7 K& l0 f- W! q, a' G Left = 376
8 U* l) ~" E9 Q Top = 72
% k1 ?! f+ _9 h' U) E Width = 75
3 @- J' d- w$ }$ p& y Height = 254 B4 A; }" X8 P
Caption = ‘ 停 止( &S)'
' b/ |3 j, {9 d# I8 N2 M Enabled = False" u5 l4 m) a8 I g' `+ a
TabOrder = 3
2 d) E$ f, T/ Z A) O OnClick = btnStopClick' W$ d' I* i; N$ A
end
+ ?: z. e/ y6 h4 V. Y0 E object btnForward: TButton
: Z. X, v5 Y: x. R; p Left = 376
/ c1 N8 z. S" R0 v: N& D7 v Top = 1209 B, M+ b& F% ]
Width = 75
4 @2 [% a2 q- [- |# |, e# L Height = 25/ K$ ?" B3 s5 Y% M. G+ i
Caption = ‘ 下 一 句( &N)'# a" i9 ~+ |* C5 m+ L( r' o
Enabled = False) i6 J) s4 s" X5 F! H3 L' O
TabOrder = 4
+ e, G' c# q% k, B! \2 j8 ^ OnClick = btnForwardClick
& }# X* x, D- R5 R, u end; p& w- z4 Z) B/ H! p2 k
object btnRewind: TButton
- ?" Y6 t, l, T8 T S& ]2 | Left = 3767 G7 M# D8 D8 j: Q: `& H
Top = 152
1 p7 J9 K4 P6 [! d! @$ [* r# a Width = 754 z8 { s; M) n4 h
Height = 25. r) N1 V, B" x$ {% @
Caption = ‘ 上 一 句( &W)'
, {( H% r7 j- D( p- Z: o- M Enabled = False: l G" y; g$ Q, a4 [$ z: W7 A' Y
TabOrder = 5
0 [. E8 g2 _3 }$ I! m) w& I" J OnClick = btnRewindClick
6 l" z6 N# t& Q7 _3 h end7 ]) J( ~+ ]4 t \- a, r
end ' m( q7 Q2 b& T$ M
----关 键 代 码 段 如 下: % ?* x! x J3 C
---- 1. 朗 读 与 停 止 B1 i9 x0 d/ s5 X1 _7 v
...
: O. ]4 y% j2 u/ C+ jprocedure TfrmMain.btnReadClick(Sender: TObject);# R; m5 z* D4 D' k; |
begin- Z8 F: |+ X# E$ q7 p9 Q5 B- @
FISpeech.Speak(memText.Lines.Text, vtxtst_ , K g) n. F4 i; I
READING);8 k+ ?4 u) K, @
btnPause.Enabled := True;' C- B! b3 Y" i% v6 i8 N
btnStop.Enabled := True;0 x) v0 g- [% O' s. o' T$ B% ]
end;
; m" }/ B# j, y1 F2 _- C4 L( T1 v+ j
& I2 R4 g$ j# ?! w4 @procedure TfrmMain.btnStopClick(Sender: TObject);
9 v. Y) k N' d( G" O7 ^ begin
6 P7 ~) C) [+ X0 u FISpeech.StopSpeaking;
* l- W& C) \+ W* G9 o btnPause.Enabled := False;4 [: a( E2 U, Y% C% f; @8 {4 |+ A
btnStop.Enabled := False;
2 q4 ~" h% {/ l W: x' l btnPause.Caption := ‘ 暂 停( &P)';& h# S! g6 } i' K2 w; f
end;% A7 f0 E" P8 f5 R# d' @
...
' N8 Q# K3 {: z1 b- J----Speak 成 员 函 数 的 第 一 个 参 数 向TTS 引 擎 传 递 需 要 朗 读 的 文 字, 第 二 个 参 数 由 指 定 朗 读 时 使 用 的 语 气 和 优 先 级 的 两 个 符 号 合 并 而 成。 8 @5 V' }* p; [6 b
" G! T* B. E' y& g- s, o---- 2. 暂 停 与 恢 复 * h. ?9 M z! @3 |! A
...# t6 M, j0 K+ S" D5 I# s' P: p
procedure TfrmMain.btnPauseClick(Sender: TObject);0 v4 s# M/ Y, x- Z% o# n4 c" B/ |' `8 k
begin
1 Z+ D+ @: g4 y/ V8 T. X4 E with FISpeech do
) A% j, t2 j( ~0 H" x8 ] if IsSpeaking then3 L% Z3 J8 F: X9 r, [! h
begin
& ]( q7 }. O! R9 T$ N" ?! r AudioPause;
+ U% }, _4 n9 E3 s- ?4 x btnPause.Caption := ‘ 恢 复( &R)';! E3 X- }8 g7 c s+ y$ o: L7 ~
end
, F1 v6 ~7 O% n3 J) V8 ? else: c2 Z, ? V: U4 W7 M- ]) `) X
begin
" B/ { O4 G9 G5 x! D/ b AudioResume;% I2 X7 a; F: k( Z7 Y
btnPause.Caption := ‘ 暂 停( &P)';
. W8 x5 z- l7 ? end;
4 M, ]9 w$ O2 C5 @3 oend;/ I6 T. T8 Q3 v. U0 r! m
...
4 }- T( B/ T2 b/ I# V# m1 H+ b----这 里 通 过IsSpeaking 属 性 可 以 取 得 当 前 状 态, 然 后 通 过AudioPause 和AudioResume 暂 停 和 恢 复 朗 读。
& ]* d0 F! V$ G' [7 M+ ~' u' v9 u: p5 H----另 外 用 成 员 函 数AudioFastForward 和AudioRewind 可 以 向 前 和 后 跳 过 一 句 朗 读, 通 过 读 写Speed 属 性 还 可 以 取 得 或 设 置 朗 读 的 语 速, 单 位 是 字/ 分, 缺 省 值 为170。
# @. V% I; H( C6 A* t4 q6 @----注 意Speed 和Enabled 属 性 缺 省 设 置 是 只 写 的, 但 实 际 上IVTxtAuto 提 供 了Get_Speed 和Get_Enabled 函 数, 所 以 我 们 只 要 把VTxtAuto_TLB 单 元 中 的 声 明 修 改 一 下, 如: * X# b) X3 Q& O$ t& E
...! v- l, ?7 f4 E$ t# }+ a" A8 V
IVTxtAuto = interface(IDispatch)1 e# F7 i! L: e3 Q
...+ l3 B! }& l& \7 V0 l$ o9 v, q" q! ]
property Speed: Integer read Get_Speed write Set_Speed;
2 |9 B* J" @: j5 B/ H! c+ { property Enabled: Integer read Get_Enabled write Set_Enabled;# t5 ^3 b. V; V
...
# z( c% y- Y) a5 Jend;
O7 o" U2 U) G ... 4 H& I: j" \5 O8 s- C' z9 ?$ }' f
----即 可 正 常 使 用Speed 和Enabled 属 性 了。 & }$ V6 N8 ]2 N1 X i
----至 此, 一 个 简 单 的 英 文 全 文 朗 读 器 就 完 成 了, 有 兴 趣 的 朋 友 可 以 为 其 加 入 监 视 剪 贴 板, 热 键 激 活 等 功 能。
5 L) I& c2 k3 T5 l----本 文 程 序 在Win NT/98 + Delphi 4/5 环 境 下 调 试 通 过。
0 `) r: R6 o2 e( G9 D& ]. a
# Z5 F( I- `3 ?7 `: I |