|
) [7 j8 Y W B! }. ^! }& d6 ~华 中 师 范 大 学 卢 小 海(flier@126.com) 8 f# \. r3 p% D, ?: R/ V6 j
各位朋友,请加入本站邮件列表,你将得到本站最新更新及动态。
) `, G1 d& T( \) a5 w4 s2 {
+ F+ [5 y4 e5 b8 ~& r ---- 金 山 词 霸2000 的 英 文 全 文 朗 读 功 能 相 信 一 定 给 尝 试 过 的 用 户 留 下 了 很 深 刻 的 印 象, 而 作 为 一 个 程 序 设 计 者, 你 一 定 也 想 在 自 己 的 程 序 中 加 入 类 似 的 功 能 吧, 因 为 那 将 让 自 己 的 程 序 增 色 不 少。 - s& y; l' e/ P1 l
----其 实 这 并 不 是 一 件 困 难 的 事, 因 为 金 山 词 霸 实 际 上 也 只 是 直 接 使 用 了MS 的TTS(Text -to -Speech) 技 术 而 已, 通 过 对MS Speech API 的 编 程, 我 们 完 全 可 以 实 现 比 其 更 强 大 的 功 能。 下 面, 让 我 们 在Delphi 环 境 下 实 际 尝 试 一 下。
9 [4 e' y" ?' s----首 先 从 金 山 词 霸 的 光 盘 上\ciba 目 录 下 运 行 并 安 装mstts.exe(MS TTS engine) 和spchapi.exe(MS Speech API)。 7 I0 i1 q3 L2 {+ Y8 F5 ^+ {
----再 在Delphi 里 新 建 一 个Application。 2 V9 ]' q% `. M; _! |& Q
----然 后 从Delphi 的 菜 单Project/Import Type Library... 中 选 击Add..., 浏 览 到Windows 目 录 下 的Speech 子 目 录 里, 打 开vtxtauto.tlb, 可 以 看 到 下 面Class names 中 会 出 现 我 们 需 要 的 接 口 的 包 装 类 的 名 字TVTxtAuto, 注 意 对 话 框 底 部 的Generate Component Wrapper 需 要 被 选 中, 点 击Create Unit 就 可 以 打 开 一 个 名 为VTxtAuto_TLB 的Unit。
0 ?5 U# q- U7 I* `----至 此, 我 们 就 可 以 开 始 实 际 编 程 了。
* }9 @$ T" v) Q4 h3 K( a----首 先 在Form 的OnCreate 中 对 需 要 使 用 接 口 初 始 化 并 进 行 注 册: . w5 O2 t5 v- C+ U6 L
...
. D7 t6 N9 t$ a8 i" d, l procedure TfrmMain.FormCreate(Sender: TObject);
" s1 v/ Z. [: v. O( P begin
: d" S% ?0 J- ^0 \" G; e/ F FISpeech := CoVTxtAuto_.Create;) V: A2 B/ k# a" j6 v
FISpeech.Register(‘Demo Site', ‘Demo App');
; S& j9 N7 |0 p' L" b' |( n end;
5 Y% W6 S P: {: \, O) _9 h...
& r' Y: @% e) c ?4 o" d8 [----由 于Delphi 对 接 口 进 行 了 良 好 的 包 装, 因 此 只 需 直 接 建 立 包 装 类, 其 他 后 台 的 操 作 如 接 口 的 查 询、 释 放 等 交 给Delphi 在 后 台 自 动 完 成。
$ e3 g$ w# L6 P3 @, ?+ v----注 意 这 里 的Register 操 作 是 必 不 可 少 的, 因 为 可 能 有 多 个 程 序 不 同 设 置 使 用TTS 引 擎。 & ?$ O/ D G- @4 w0 Y
----然 后 在MainForm 上 放 一 个TMemo 和 若 干 个 TButton, 并 在 其OnClick 中 加 入 对 应 的 代 码。
8 c( K- h) A. I4 C0 p8 S/ G: dForm 定 义 如 下:
1 ]3 N9 x" O' j( N# j. S; f object frmMain: TfrmMain, F* ^ Y! y% s3 G
Left = 296
: r- v& y- j; D' y$ _) S% P" {0 t Top = 187( I, T+ O0 W+ O0 q
BorderStyle = bsDialog- ?/ T1 s, Q$ d1 I0 w( @
Caption = ‘ 英 文 全 文 朗 读 演 示'
& Q0 m M& e, y. |2 n7 g8 X ClientHeight = 185 e' W: p# G: `
ClientWidth = 456
& D! T. r! w) |5 q! M, |9 Q Color = clBtnFace3 n, f) J9 S) d" w% _- W7 @
Font.Charset = GB2312_CHARSET* J# c1 m6 O2 C; A5 H; j2 s
Font.Color = clWindowText) h+ N: r' j/ Z; Z7 r' x
Font.Height = -128 R; K; o1 z- B0 C( U6 r2 z
Font.Name = ‘ 宋 体'
8 T& L. O+ e/ h) z' I Font.Style = []# \0 w1 S; F' Q! n
OldCreateOrder = False9 H: s- E. c6 {, f% D* m8 Q1 q7 n
Position = poDesktopCenter4 F) e+ e, _6 ], X* K; U/ i
OnCreate = FormCreate. s4 t. J5 a* {/ b! x; A
PixelsPerInch = 96: f! a" J |0 O' Y, k/ ]
TextHeight = 128 U7 V7 X6 e: }9 w7 \& T
object memText: TMemo
4 w6 V9 H* M g. [ Left = 8' l/ F7 l$ y' t1 p# H0 ~! B+ J
Top = 8
8 o1 Z5 d7 a' N+ Q$ f+ v- `% y Width = 3613 f* s( F3 f: }' b( h2 p; c% r/ Z+ H
Height = 169
% j/ s2 X- u2 t' A ScrollBars = ssVertical
~$ Z) `/ o/ c" [5 _1 g. c TabOrder = 0
. f! S) f+ i6 _! O. d; O0 w% B end4 P! m2 |4 b& e: M$ L
object btnRead: TButton
$ X: l) s% B: ^% L6 g0 l& } Left = 376
" B5 {0 w5 X Y Top = 8' r( ~) Z* b) r
Width = 75" S% W' {/ ^5 \/ t) h. I3 D: q1 F7 X" Z
Height = 25
' L" M& k3 v3 w1 G& r Caption = ‘ 朗 读( &R)'
, w6 w6 J2 [( Q1 }* n v, L TabOrder = 1
' S* b1 ?8 r# k- t" m+ G6 b# U6 f OnClick = btnReadClick* t } b m* V' E2 y- S" v
end& L n& o6 q% s* E
object btnPause: TButton# V6 M, @# e8 S6 L* B; h7 V
Left = 376" W: T4 V( \( m/ ]- i% Z M
Top = 40% J: G9 W- e5 z0 f1 E
Width = 75
) n, J2 D0 d& a6 T3 q Height = 25! O( u& q0 t( U
Caption = ‘ 暂 停( &P)'8 c) L) W! \' V% V
Enabled = False7 _! [$ V5 y Q+ K8 r! N/ }
TabOrder = 2
9 n& z0 A ], C; m/ _& o OnClick = btnPauseClick, S$ a ?9 y/ P' C- A; C& x
end+ d* ?0 m) R D; p# T4 E
object btnStop: TButton7 A4 ?% V. @5 v( [, a
Left = 376
$ z' v+ K, |* w1 r. G1 Q( K5 Z Top = 72
( h2 C( E6 D3 \3 n- ^ Width = 75: G. k% F( d/ M6 C9 P; ^* }, I" u+ k
Height = 253 V' H. A7 x! g/ H$ Q$ W
Caption = ‘ 停 止( &S)'# B) ~, X2 k" ~1 O' P! o3 |8 W( [+ l
Enabled = False
8 s% {! y9 u5 l( {& u- ]+ V TabOrder = 3
1 N2 A( @' j0 @ OnClick = btnStopClick
; x8 u4 D$ s, y# `& U end( J6 H3 g3 t/ ?) e! I5 v7 w
object btnForward: TButton7 Q. p5 m1 x, ~& z& I' r
Left = 376+ P2 _5 g" H( d6 j9 S( d+ {' G
Top = 120
2 A0 d# R0 j5 c. e3 E$ E% z Width = 75
. x' {+ y0 q7 H8 x8 P& j Height = 25% p2 g$ U# g" D' J8 m7 r
Caption = ‘ 下 一 句( &N)'1 j. N0 W5 X$ d
Enabled = False
1 F/ \8 Y" V0 X1 X+ C: z TabOrder = 4
% |: h, j. |/ ~8 E9 n; m OnClick = btnForwardClick
1 {1 P2 Y5 S5 c b end+ G @' O0 [; `. Z: r
object btnRewind: TButton
0 E& W) m: ?/ z# ~( W Left = 376
* P+ z( u X& Z+ W# {) ~: c9 w Top = 152
, o. o( S9 H; J+ [ Width = 75& [* \" I h$ E O2 m+ R
Height = 25
0 w1 P4 J" s3 ]) A6 Y1 u Caption = ‘ 上 一 句( &W)'
; `3 [: g* d1 x Enabled = False
% F/ j+ g* N8 l) B g7 H5 i# o/ j TabOrder = 5
. g' v( s1 v/ F n. J2 l/ v OnClick = btnRewindClick- L: |. R9 ~! S
end
+ {( L! ?6 V, V( }! s; r! J! ]. D end
5 k' x4 ~$ u. I7 Q----关 键 代 码 段 如 下: % I( |/ V% b# T: ]3 ^
---- 1. 朗 读 与 停 止
0 k) r x- E- W' ?- } ...
3 i' \! g" @# Z1 H# `( T2 Cprocedure TfrmMain.btnReadClick(Sender: TObject);
# R2 e* I) [! I! [% \4 N6 | begin
4 a# e/ s( e; v6 w2 y: l( l FISpeech.Speak(memText.Lines.Text, vtxtst_ 8 ?5 z3 e9 W5 ]9 b' `
READING);
: L4 c7 k3 }6 z: b8 S! L% ? btnPause.Enabled := True;
b* W3 U1 Q; n btnStop.Enabled := True;5 {) W% C9 I) J0 c
end;
y9 C% w. q1 x* k3 B
; \2 e+ r9 m2 I# s$ x7 I$ lprocedure TfrmMain.btnStopClick(Sender: TObject);
8 d: Y9 v) e- h+ K begin
$ F3 j' X6 l( H. Z g FISpeech.StopSpeaking;
1 c! c# k8 j! n: f2 f5 ]# e btnPause.Enabled := False;
- e- X" f5 |. O C3 L btnStop.Enabled := False;
3 W% `" @: I: W$ M) _ btnPause.Caption := ‘ 暂 停( &P)';6 W$ X0 T, c# S2 D9 X
end;# d9 ]0 G6 ^ A2 r% J
...
; e) `$ S. L7 q8 V----Speak 成 员 函 数 的 第 一 个 参 数 向TTS 引 擎 传 递 需 要 朗 读 的 文 字, 第 二 个 参 数 由 指 定 朗 读 时 使 用 的 语 气 和 优 先 级 的 两 个 符 号 合 并 而 成。
( i1 W- U/ k8 Q. }& W/ d
2 h1 H' o* Z. m, D2 |' R7 R---- 2. 暂 停 与 恢 复
% h0 n0 G: Z6 s% ~* c$ I' g$ R ...
A) X7 ? z2 r' Cprocedure TfrmMain.btnPauseClick(Sender: TObject);7 K$ q$ r0 X' p! v$ d+ e# i+ w# x
begin- K4 r2 E3 H; b/ [1 h: J
with FISpeech do1 z% X4 d( _; q7 r1 Q( o9 W" h
if IsSpeaking then
0 {0 H+ z% b5 C9 J6 m9 C begin4 y/ y3 e. j. ?5 X
AudioPause;
4 w3 W% q* C9 n, m6 R. C btnPause.Caption := ‘ 恢 复( &R)';
x+ Y0 |9 T* P. e e2 a1 k end. y+ y8 i+ I2 i1 R1 N$ x, ]
else
0 V" \; d3 R; |: V8 l( _ begin; F' B" V2 m; p9 g* O: R/ G7 {
AudioResume;
$ ^ M3 f6 N9 u1 @3 f: A. q btnPause.Caption := ‘ 暂 停( &P)';
' o' G e$ d2 T3 {$ [; \ end;
2 Y- c& n: z( t, ?9 Z* uend;. w, K& |, ~) o" a2 a! r
...
+ h. { c, u. F" p9 I: L! R' R----这 里 通 过IsSpeaking 属 性 可 以 取 得 当 前 状 态, 然 后 通 过AudioPause 和AudioResume 暂 停 和 恢 复 朗 读。
. m8 q$ T+ M B, b: d----另 外 用 成 员 函 数AudioFastForward 和AudioRewind 可 以 向 前 和 后 跳 过 一 句 朗 读, 通 过 读 写Speed 属 性 还 可 以 取 得 或 设 置 朗 读 的 语 速, 单 位 是 字/ 分, 缺 省 值 为170。
2 \& }8 z: Z t/ L8 d3 S----注 意Speed 和Enabled 属 性 缺 省 设 置 是 只 写 的, 但 实 际 上IVTxtAuto 提 供 了Get_Speed 和Get_Enabled 函 数, 所 以 我 们 只 要 把VTxtAuto_TLB 单 元 中 的 声 明 修 改 一 下, 如: , \3 y- f3 \+ X1 ]) [1 Y+ i
...+ @( U, ?. {8 q6 R6 M
IVTxtAuto = interface(IDispatch)
]4 X4 F' w9 g ...0 G: N' o! y1 a- x
property Speed: Integer read Get_Speed write Set_Speed;
) r$ w( P: f) r+ U property Enabled: Integer read Get_Enabled write Set_Enabled;# P1 B0 T( R5 `1 x
...; J3 w D5 o( x/ o
end;
, m$ U" }& Z/ z9 {+ w" f2 O { ...
& t& F3 y$ q3 a7 n----即 可 正 常 使 用Speed 和Enabled 属 性 了。 / \. X0 `5 L+ ?; O7 [' @
----至 此, 一 个 简 单 的 英 文 全 文 朗 读 器 就 完 成 了, 有 兴 趣 的 朋 友 可 以 为 其 加 入 监 视 剪 贴 板, 热 键 激 活 等 功 能。 % j6 ]& v, l3 x, w
----本 文 程 序 在Win NT/98 + Delphi 4/5 环 境 下 调 试 通 过。
6 Z- t$ A# E, _; D" Y9 i7 Q1 } 8 \" k! s3 c+ w
|