|
) u: l6 |% r% S' {- n, V
华 中 师 范 大 学 卢 小 海(flier@126.com) 7 w7 D" a; x9 ]1 e* J* M5 R* N& l
各位朋友,请加入本站邮件列表,你将得到本站最新更新及动态。 2 v& d; G1 \ w* E# D2 _
; E! X5 j. O I' Z A" o' K
---- 金 山 词 霸2000 的 英 文 全 文 朗 读 功 能 相 信 一 定 给 尝 试 过 的 用 户 留 下 了 很 深 刻 的 印 象, 而 作 为 一 个 程 序 设 计 者, 你 一 定 也 想 在 自 己 的 程 序 中 加 入 类 似 的 功 能 吧, 因 为 那 将 让 自 己 的 程 序 增 色 不 少。 " y, i/ G; D0 ]9 W C
----其 实 这 并 不 是 一 件 困 难 的 事, 因 为 金 山 词 霸 实 际 上 也 只 是 直 接 使 用 了MS 的TTS(Text -to -Speech) 技 术 而 已, 通 过 对MS Speech API 的 编 程, 我 们 完 全 可 以 实 现 比 其 更 强 大 的 功 能。 下 面, 让 我 们 在Delphi 环 境 下 实 际 尝 试 一 下。 $ N; k/ [4 V! H+ M# Q
----首 先 从 金 山 词 霸 的 光 盘 上\ciba 目 录 下 运 行 并 安 装mstts.exe(MS TTS engine) 和spchapi.exe(MS Speech API)。
J0 L1 K! v- T+ Y----再 在Delphi 里 新 建 一 个Application。 - N; l# C% C/ D5 {/ z! M
----然 后 从Delphi 的 菜 单Project/Import Type Library... 中 选 击Add..., 浏 览 到Windows 目 录 下 的Speech 子 目 录 里, 打 开vtxtauto.tlb, 可 以 看 到 下 面Class names 中 会 出 现 我 们 需 要 的 接 口 的 包 装 类 的 名 字TVTxtAuto, 注 意 对 话 框 底 部 的Generate Component Wrapper 需 要 被 选 中, 点 击Create Unit 就 可 以 打 开 一 个 名 为VTxtAuto_TLB 的Unit。
1 L- r, t. f& e4 B----至 此, 我 们 就 可 以 开 始 实 际 编 程 了。
% m0 E0 E9 J# T( c, R4 w$ _/ k- n$ `1 S----首 先 在Form 的OnCreate 中 对 需 要 使 用 接 口 初 始 化 并 进 行 注 册:
; U$ s/ E4 |7 C5 ^" [ ..." {2 ?+ m0 z0 i/ Z& x" I$ F
procedure TfrmMain.FormCreate(Sender: TObject);/ q4 X) Q7 {. B5 ]8 c
begin
( \2 P2 F" H+ t* ?, q5 p FISpeech := CoVTxtAuto_.Create;
6 v _( W+ g$ T# ~ FISpeech.Register(‘Demo Site', ‘Demo App');
2 ?3 H/ t- T7 k: s1 b4 s+ u end;
- j0 \. X! @ u7 l7 J+ S Z5 |...
3 w* Q( m# H; {* P& s6 K% [% P----由 于Delphi 对 接 口 进 行 了 良 好 的 包 装, 因 此 只 需 直 接 建 立 包 装 类, 其 他 后 台 的 操 作 如 接 口 的 查 询、 释 放 等 交 给Delphi 在 后 台 自 动 完 成。
( Y6 v5 p7 N2 g----注 意 这 里 的Register 操 作 是 必 不 可 少 的, 因 为 可 能 有 多 个 程 序 不 同 设 置 使 用TTS 引 擎。 ! v: n" F* j8 n) G+ v0 E" a
----然 后 在MainForm 上 放 一 个TMemo 和 若 干 个 TButton, 并 在 其OnClick 中 加 入 对 应 的 代 码。 & M7 c( d& V9 a6 N- u! X0 n& q- J
Form 定 义 如 下: $ q; [6 t2 K, B$ l k1 y
object frmMain: TfrmMain! |5 l& F+ _! o# ~& @! l% c5 t
Left = 296
- \5 Y8 t. z n5 F. r7 T Top = 1876 ], t7 X# q& [# x4 N D. |
BorderStyle = bsDialog2 S, R# ^6 `' U4 M
Caption = ‘ 英 文 全 文 朗 读 演 示'
5 Z' w0 S. p9 G+ @, I+ o! G7 O3 F ClientHeight = 185
9 a" @/ ]' g* Y ClientWidth = 456- y, u2 n3 [/ f$ q8 B8 W" E, V
Color = clBtnFace
6 {/ o" Z, C& `, _( S% W& E Font.Charset = GB2312_CHARSET
9 ]4 ?1 R3 {5 S- R( j' O- k Font.Color = clWindowText3 B' }1 w- T& s6 o, q: f
Font.Height = -12# `; V: U( O$ b$ U
Font.Name = ‘ 宋 体'
$ s- [% @! l) m Font.Style = []) ?. O. u5 t' _& ~
OldCreateOrder = False
* K, ~# C. W& M( R' O' E+ c Position = poDesktopCenter
- l. O( h2 {* ^5 Z OnCreate = FormCreate
3 U& J1 }( L5 ~; [8 q% S5 g PixelsPerInch = 96% G( X/ {+ H2 o r# A$ f3 j
TextHeight = 12
' x5 e" X/ G- c7 H object memText: TMemo
% _& m. |$ Z! G6 q+ }$ q Left = 8/ q1 K% @4 ]; n$ i+ o- q- C! Y
Top = 8
7 W& f( v2 _; U" F9 A Width = 3613 b3 O+ {: ^; O2 x
Height = 169
3 t6 F6 ^) ~9 @" Y ScrollBars = ssVertical. l1 W) P8 x; h
TabOrder = 0. A" ~& N; r" v3 r) `! S7 L+ _) y5 D
end; Y# N1 R! [3 |$ i+ \0 @
object btnRead: TButton
7 a8 V) M6 r4 @1 i4 ]: } Left = 376
/ P. c/ W' n; [! j" }- ^ Top = 8
+ Q) P0 Z5 E7 N/ ^4 R Width = 75
& E4 L( o; f" V* q! G( n Height = 255 y% D* w, D+ f1 u$ p2 p
Caption = ‘ 朗 读( &R)'
) |( }# ?, \" l$ V3 v+ d TabOrder = 1' f& o0 D* e' ?2 Y5 E( K! [1 h1 d9 f+ |- G
OnClick = btnReadClick
7 c) b: b$ b% n2 K end
, u# }+ s6 g& \' O7 I( O' _+ t object btnPause: TButton
0 u& l. n F7 e0 ~9 Y' |7 ^3 W8 N Left = 376
6 `& Q9 n1 T/ t$ o8 _0 d Top = 40
3 ]6 {1 C; r2 [1 u Width = 75
* k6 O7 i* N: j6 g- E Height = 25' U2 v6 Y/ M0 X# c# U S3 ~
Caption = ‘ 暂 停( &P)'
. N: S: {# d9 F+ K" i* m Enabled = False
3 M) ?: D0 G. ?0 a7 ~- u TabOrder = 2
6 h) ^7 F& g& C ~4 ?6 _$ K2 g4 R OnClick = btnPauseClick q: a X$ ]+ W- F1 |* N J2 }& Y' H
end
8 K5 i C9 q r& t object btnStop: TButton5 P) e& m8 ^( N; Y
Left = 376* _, x c. Z, ], H7 r
Top = 72
$ q p' ^1 ~! I4 X! b Width = 75
9 g) S- t. V0 Q: [( t* j Height = 25
5 a/ M6 Y6 N: z' ~! L Caption = ‘ 停 止( &S)'8 U" K% I* u8 q
Enabled = False5 T' ?7 U( w' A- I2 _
TabOrder = 3
* l3 J O9 i6 N ~ OnClick = btnStopClick
5 O6 q: j9 y) F1 Y end
; P. B$ w8 m) u! F8 w$ Q object btnForward: TButton
+ w: Q5 `' S4 l$ p& r( y/ x' y Left = 3762 k1 P9 ^- m- Y( `
Top = 120- D0 B" X2 r# h% ~0 ^: U
Width = 75$ ^2 R! ^' _/ b# ?. r# s
Height = 25: A s: \' H7 o$ `4 e5 x( A3 W4 p9 L
Caption = ‘ 下 一 句( &N)'/ S5 N, l! C. N* S# U, K
Enabled = False
" _) G2 R y, t3 w TabOrder = 4- T6 w; P* r: k2 S) l5 x2 y: |
OnClick = btnForwardClick ~1 B1 b! \( `* `4 ?
end2 H4 X1 ~% T# z8 R
object btnRewind: TButton9 {2 c' ]2 R, N% u$ }
Left = 3766 y8 }) n) W/ p6 a7 s6 [0 |8 k
Top = 152- I7 |, u5 Z' s( _- U. p; e0 ^4 l
Width = 75' h j# L3 R2 J. O9 _
Height = 25
) f+ n$ ]% [' m. ?5 I, @, I Caption = ‘ 上 一 句( &W)'
* z8 p I' O2 y8 ~7 ?' n Enabled = False+ @ _ ]# w5 T
TabOrder = 5
( J# C& i, m$ n, p OnClick = btnRewindClick. e, R8 E: q! @
end
0 w6 q! X# K E end
/ I, r- W' e/ G! s% i0 ^. t----关 键 代 码 段 如 下:
9 X& h* ?! x. g. n---- 1. 朗 读 与 停 止 & @& B) C, m2 `, \" R, L% \
...
! \! N; s+ F) iprocedure TfrmMain.btnReadClick(Sender: TObject);
* ?# G1 H7 N3 b9 b8 }: t d begin
$ w7 ~& z( K) S) H FISpeech.Speak(memText.Lines.Text, vtxtst_ % S7 P; ~! o. E1 @6 b9 X8 z2 a
READING);
( K& ?& W) I: ~- O4 h" E btnPause.Enabled := True;% P. d/ U# `' O. b/ ^
btnStop.Enabled := True;
$ Y4 P1 ]/ c6 x8 ^4 f0 u end;* E7 q$ X- G( X; b& K/ v& N- L
3 [- Q5 x8 w# o+ @5 {
procedure TfrmMain.btnStopClick(Sender: TObject);
" Y, ^$ o0 u% t. ]2 j. I! O5 D begin
& ?: A; t+ d+ s FISpeech.StopSpeaking;- `" H0 k; L, k
btnPause.Enabled := False;9 `( ?; k5 q6 y6 `; h. A: w8 e
btnStop.Enabled := False;; e; P: m, c7 n, U, `
btnPause.Caption := ‘ 暂 停( &P)';
* j1 J8 J3 g# x: Q end;3 [" K `$ h7 J- o( l9 @
... & f$ y! S* |8 s8 `9 n
----Speak 成 员 函 数 的 第 一 个 参 数 向TTS 引 擎 传 递 需 要 朗 读 的 文 字, 第 二 个 参 数 由 指 定 朗 读 时 使 用 的 语 气 和 优 先 级 的 两 个 符 号 合 并 而 成。
' k6 b- q1 ^. \/ V1 V9 a/ P
$ H9 m+ o' W9 |, k6 @---- 2. 暂 停 与 恢 复
2 x( a7 m4 T5 k/ [3 P ...
5 K" p* j0 T' Q8 {6 b$ qprocedure TfrmMain.btnPauseClick(Sender: TObject);
( Y) G& I" G# I begin
8 j: z( x1 g. v( b with FISpeech do
& S% B4 y6 |" L* C* |7 x if IsSpeaking then+ p. V1 ]. B) v* Z; P. Y
begin5 m8 J1 ?6 Q J4 v) V+ o5 B, x
AudioPause;3 H- z2 b2 L- i. ?- D
btnPause.Caption := ‘ 恢 复( &R)';
( T: z$ K9 v7 n7 d, q$ E# [3 r4 p end
* |4 l. g7 @' o, M! A/ h else" c* D. Y: v; n+ n( T9 F
begin
5 V+ f! [: N. w0 S' f& m AudioResume;
+ ?: s2 s2 S( `: G/ Q3 H9 D btnPause.Caption := ‘ 暂 停( &P)';6 C. ~5 B8 S2 E( j, m7 o
end;
. v9 J* B5 x% L/ i5 }/ A- \end;
- f' a; u3 j9 m/ b) }# {% h. M... $ I: i: ]% T. F0 v# |4 W1 P5 @
----这 里 通 过IsSpeaking 属 性 可 以 取 得 当 前 状 态, 然 后 通 过AudioPause 和AudioResume 暂 停 和 恢 复 朗 读。 : w9 d/ Z, z& M% c Q8 a
----另 外 用 成 员 函 数AudioFastForward 和AudioRewind 可 以 向 前 和 后 跳 过 一 句 朗 读, 通 过 读 写Speed 属 性 还 可 以 取 得 或 设 置 朗 读 的 语 速, 单 位 是 字/ 分, 缺 省 值 为170。
& \1 m$ A2 k& R3 l5 a2 N0 K----注 意Speed 和Enabled 属 性 缺 省 设 置 是 只 写 的, 但 实 际 上IVTxtAuto 提 供 了Get_Speed 和Get_Enabled 函 数, 所 以 我 们 只 要 把VTxtAuto_TLB 单 元 中 的 声 明 修 改 一 下, 如:
* @ K, o! M" m/ a" D ...9 @ c6 u. k0 c! c: T/ i
IVTxtAuto = interface(IDispatch)4 m, Q1 V5 q+ L# q! M j$ _" W
...
$ D4 r* D! s! H6 X. @9 i. Y property Speed: Integer read Get_Speed write Set_Speed;1 V4 r7 r r1 y! D1 j" |8 V
property Enabled: Integer read Get_Enabled write Set_Enabled;
, e3 B+ D; E9 s, ^) G ...7 X! V T5 E0 L) X- P+ n8 l
end;
! t: h$ g% B. k' c1 \% Z5 M+ |# Q0 B ... ; a0 S/ ^$ d) n) {4 ^# ]3 V
----即 可 正 常 使 用Speed 和Enabled 属 性 了。
N, d9 g$ n6 T- \1 d----至 此, 一 个 简 单 的 英 文 全 文 朗 读 器 就 完 成 了, 有 兴 趣 的 朋 友 可 以 为 其 加 入 监 视 剪 贴 板, 热 键 激 活 等 功 能。
$ n3 r6 ], e3 D" |) A5 `----本 文 程 序 在Win NT/98 + Delphi 4/5 环 境 下 调 试 通 过。
/ H2 z$ Q8 k7 i: U 6 a N4 T4 B* h& {; i
|