|
* y# ~, r a5 n+ l5 f
华 中 师 范 大 学 卢 小 海(flier@126.com) 1 |: C0 x( C2 k/ [) p! j
各位朋友,请加入本站邮件列表,你将得到本站最新更新及动态。
3 m5 a S. q1 N& f! ]% p1 L, J& X! A9 _
---- 金 山 词 霸2000 的 英 文 全 文 朗 读 功 能 相 信 一 定 给 尝 试 过 的 用 户 留 下 了 很 深 刻 的 印 象, 而 作 为 一 个 程 序 设 计 者, 你 一 定 也 想 在 自 己 的 程 序 中 加 入 类 似 的 功 能 吧, 因 为 那 将 让 自 己 的 程 序 增 色 不 少。
9 A! ~' E; N! I* a+ N; P/ A9 ?2 L----其 实 这 并 不 是 一 件 困 难 的 事, 因 为 金 山 词 霸 实 际 上 也 只 是 直 接 使 用 了MS 的TTS(Text -to -Speech) 技 术 而 已, 通 过 对MS Speech API 的 编 程, 我 们 完 全 可 以 实 现 比 其 更 强 大 的 功 能。 下 面, 让 我 们 在Delphi 环 境 下 实 际 尝 试 一 下。
/ H3 e+ S0 \3 h1 r' x& G, P----首 先 从 金 山 词 霸 的 光 盘 上\ciba 目 录 下 运 行 并 安 装mstts.exe(MS TTS engine) 和spchapi.exe(MS Speech API)。 $ P) E+ k. S8 o/ M7 H4 [$ W5 `0 u
----再 在Delphi 里 新 建 一 个Application。 / c: F9 ~/ g1 f w/ r' x( x
----然 后 从Delphi 的 菜 单Project/Import Type Library... 中 选 击Add..., 浏 览 到Windows 目 录 下 的Speech 子 目 录 里, 打 开vtxtauto.tlb, 可 以 看 到 下 面Class names 中 会 出 现 我 们 需 要 的 接 口 的 包 装 类 的 名 字TVTxtAuto, 注 意 对 话 框 底 部 的Generate Component Wrapper 需 要 被 选 中, 点 击Create Unit 就 可 以 打 开 一 个 名 为VTxtAuto_TLB 的Unit。
- t# d1 J( }! k----至 此, 我 们 就 可 以 开 始 实 际 编 程 了。
3 b r& A1 g9 @1 `" \----首 先 在Form 的OnCreate 中 对 需 要 使 用 接 口 初 始 化 并 进 行 注 册: ' L! x& B) B1 @* D& _4 B( h" P
...
+ E- [/ y3 s3 m% I procedure TfrmMain.FormCreate(Sender: TObject);
; k6 U! b% C) k$ h( K begin
* n6 t4 C7 X/ g; o FISpeech := CoVTxtAuto_.Create;) P. F. J7 M% q
FISpeech.Register(‘Demo Site', ‘Demo App');# ^# ?0 `8 W$ N3 ?- x
end;
m: O# v2 v+ i/ j# @+ q... $ y5 ^7 v$ T( m% e- b
----由 于Delphi 对 接 口 进 行 了 良 好 的 包 装, 因 此 只 需 直 接 建 立 包 装 类, 其 他 后 台 的 操 作 如 接 口 的 查 询、 释 放 等 交 给Delphi 在 后 台 自 动 完 成。 ' A- t. P& `6 x; O- ?9 ^
----注 意 这 里 的Register 操 作 是 必 不 可 少 的, 因 为 可 能 有 多 个 程 序 不 同 设 置 使 用TTS 引 擎。
' ?8 o6 |7 E: C4 e0 D& @----然 后 在MainForm 上 放 一 个TMemo 和 若 干 个 TButton, 并 在 其OnClick 中 加 入 对 应 的 代 码。
9 j7 P9 A4 u ^* q4 |5 i4 \' UForm 定 义 如 下:
9 n# A9 f! I2 ^1 q2 N object frmMain: TfrmMain
9 ?' x. G3 c3 T+ f! i Left = 296% ?6 M4 z- C1 n4 e p
Top = 1876 f( l' r1 o7 K, H! ]6 Z' W3 o. L
BorderStyle = bsDialog/ n- a8 k5 e1 g
Caption = ‘ 英 文 全 文 朗 读 演 示'# @. ~8 O# ` K3 @( y
ClientHeight = 185
6 }% a. W4 Y* c% {- l5 h, H ClientWidth = 456
3 {: Q Q1 I/ x8 z( M, J Color = clBtnFace) T' c$ r$ P% _7 h( [
Font.Charset = GB2312_CHARSET
3 v/ B! [. Z2 i" w Font.Color = clWindowText
0 h# o4 F- j0 ? Font.Height = -121 \! S5 p9 M: Z8 l+ t) w# Z
Font.Name = ‘ 宋 体'
4 n9 \ L, O: n' b' Z" i1 R Font.Style = []
% |" x8 e9 E# d; x7 @$ Q1 p8 N OldCreateOrder = False& z, @* v' a2 A5 _
Position = poDesktopCenter
% k( b, u6 m" {/ F9 g! I8 R OnCreate = FormCreate _4 m) V( {4 B8 _/ r
PixelsPerInch = 96
B( {, g! v+ P& p. \" s8 y TextHeight = 12# e: `7 s) A, U
object memText: TMemo
. Q# c9 _' ]9 S$ q Left = 8
/ D, S& }8 x' S5 k Top = 8
' n- `9 e9 u9 U9 a* h4 M Width = 361. p. Y7 b1 B" c( z
Height = 169. y6 q3 c! I# e+ N7 {
ScrollBars = ssVertical. ^# P/ l' F# Q7 J
TabOrder = 0) D7 D; H0 ?# d3 q: r+ ^& b7 A3 \
end* X: a n9 U* l; h! K, W8 x: N i
object btnRead: TButton/ N5 c* t1 F& A( b4 C
Left = 376" s: @) P" z, E9 l
Top = 8
" B5 h, _# p$ q' r. N: w( V Width = 75& b4 F! o% W8 i' q/ e1 H- U
Height = 25, q9 T. G2 u: [! D
Caption = ‘ 朗 读( &R)'( b6 J( o) f7 ]: Z; S( A8 n) R; v8 a$ n
TabOrder = 1
9 y, ^4 k! m1 k! Q( W* o3 X0 A OnClick = btnReadClick* B2 ~" `8 e2 C: X9 P
end8 K( v; G- b4 R: E$ m- p
object btnPause: TButton
* B9 ]9 M; @% `% c7 E Left = 3763 x: g" Y# b5 W
Top = 40
5 X7 d; o: Y; H F6 f) G/ b: I+ n& r9 r Width = 75
, b9 ^9 q/ ]; R7 B2 ? Height = 25$ n# L# H/ {( U% {2 |: |
Caption = ‘ 暂 停( &P)'
; B2 G! e/ x# i Enabled = False3 L1 b z3 e0 @7 S4 K7 @
TabOrder = 20 @0 w$ h2 s7 [) x8 I
OnClick = btnPauseClick( ^" \+ B9 l6 p( U# m9 {0 A) n
end
! D( I) ?5 ~+ N7 B object btnStop: TButton
: K/ b( n- _/ g8 E Left = 376( @* c0 G: X0 J
Top = 72
" c) K/ ~5 A9 w- G4 M) x# O8 m Width = 753 a1 C6 P6 r" ]1 D7 [. ?
Height = 25
8 m. T' U! ?7 ~! d" l. P Caption = ‘ 停 止( &S)'4 T2 k& L6 |7 r
Enabled = False+ o) N' ~/ D: T$ D, I# Y9 A/ \4 T/ R6 U
TabOrder = 3! _2 v b) r+ J2 R
OnClick = btnStopClick. p- |5 G1 @3 K5 k8 S
end; ~+ r+ X% L4 n/ l- [
object btnForward: TButton- T7 Q$ T5 }5 i7 @% }' T7 {+ o
Left = 376
. M# w0 x% E E) r- ?4 G6 m Top = 120; Z! Y7 u0 j- m# {3 P" o
Width = 75
& N+ z! m% A6 G# [- C, E$ n6 L Height = 25' L& g9 E9 o+ t1 p- S# P
Caption = ‘ 下 一 句( &N)') l2 v0 x; T' E6 r
Enabled = False2 X' \) N" L3 X8 M
TabOrder = 4+ H0 q# e: A7 i3 u- Q( p/ X
OnClick = btnForwardClick
4 d3 o- k, o) k8 f end; u5 b3 }; x% ?, d* \; S$ S" A
object btnRewind: TButton
/ H2 ` l5 _: y+ Q6 \ Left = 376 A8 y) O0 m9 J% B2 W
Top = 152- k8 n( f) P/ {7 x8 N" K
Width = 75
6 Q! n9 u1 q2 g" ]! i/ ^3 p Height = 25
7 N5 w* W! o: h Caption = ‘ 上 一 句( &W)'
. V E6 X$ i3 L* U Enabled = False
8 z9 q# {9 e4 B/ l TabOrder = 5
' \# S& x5 |5 Y9 N" b( ~2 g! U OnClick = btnRewindClick
* l' R6 g) Y2 P end6 A, ?$ N" W+ o; P5 s u- s
end * g) s: T' ^2 H% ]5 k
----关 键 代 码 段 如 下: 9 o& g1 m6 V1 I6 n5 a7 x
---- 1. 朗 读 与 停 止 8 v" P5 c/ J3 f6 R
...
' c$ K, k* p4 f( a9 {6 [/ v3 eprocedure TfrmMain.btnReadClick(Sender: TObject);
" e2 O) {$ U1 m0 I) n, g6 i. C begin
! {( v2 S- i$ r, ?4 c FISpeech.Speak(memText.Lines.Text, vtxtst_
3 ]' R% T* [% JREADING);
6 E5 N3 c: k' D6 C1 q1 e ~ btnPause.Enabled := True;
' {7 R/ s3 w, T3 U: j2 m btnStop.Enabled := True;
9 V; |9 h5 \! X. [ end;. P+ N' J$ X" o
& C" A6 }8 T0 }/ @
procedure TfrmMain.btnStopClick(Sender: TObject);! N7 A9 p% O- \2 ?5 U
begin
2 M ?$ X% o0 V( j _1 ? FISpeech.StopSpeaking;
( W( J, [7 H# {7 ] btnPause.Enabled := False;5 u8 A! _1 t( c L. m5 y. y
btnStop.Enabled := False;( B* l5 H% X4 {7 }3 H
btnPause.Caption := ‘ 暂 停( &P)';
$ p! @' u4 {# A. Z6 | end;0 L" f1 @* n% l) Q- z$ C
...
0 O& K' N2 \7 k |3 Y. [9 a& f, ^----Speak 成 员 函 数 的 第 一 个 参 数 向TTS 引 擎 传 递 需 要 朗 读 的 文 字, 第 二 个 参 数 由 指 定 朗 读 时 使 用 的 语 气 和 优 先 级 的 两 个 符 号 合 并 而 成。 9 R% g$ [8 g# ?' k" J, h6 L$ e
( D% A7 N9 f: j* X9 h
---- 2. 暂 停 与 恢 复
" C9 T# d' t" ~ ...6 ^3 d4 Y% {0 `* j, N
procedure TfrmMain.btnPauseClick(Sender: TObject);
: D: l7 l: f$ a+ c) F3 i4 q begin
' N# H# N/ B. a6 ? ]8 }: I! ~ with FISpeech do
" ^2 M: I2 g8 E/ `8 z, X- w if IsSpeaking then& r3 O% N# P: X2 u) M8 e4 Y. q
begin
; W( q0 R) b8 `; V4 }( E7 e AudioPause;& u: B P. q& i9 o5 a2 a" U
btnPause.Caption := ‘ 恢 复( &R)'; T9 u9 l" K& D
end' z# M# u) {2 l! j
else
/ v& t3 h3 G% i5 ^( q begin. \( h2 Z1 J; v; {3 P4 z
AudioResume;
$ f: Z6 \. G- m# d btnPause.Caption := ‘ 暂 停( &P)';' d! N4 o# q! n7 b9 ?& d( v
end;4 D1 E" \ J8 d. U& q+ p6 o6 T5 J: U# O
end;
2 s0 Z1 H3 _- x$ s# o4 E/ n...
7 ?' S, I# ]( x1 Y/ \7 U----这 里 通 过IsSpeaking 属 性 可 以 取 得 当 前 状 态, 然 后 通 过AudioPause 和AudioResume 暂 停 和 恢 复 朗 读。 1 c6 @ j- U% ] l/ C
----另 外 用 成 员 函 数AudioFastForward 和AudioRewind 可 以 向 前 和 后 跳 过 一 句 朗 读, 通 过 读 写Speed 属 性 还 可 以 取 得 或 设 置 朗 读 的 语 速, 单 位 是 字/ 分, 缺 省 值 为170。
! Y2 _4 \9 s2 q8 w# J' G, Z----注 意Speed 和Enabled 属 性 缺 省 设 置 是 只 写 的, 但 实 际 上IVTxtAuto 提 供 了Get_Speed 和Get_Enabled 函 数, 所 以 我 们 只 要 把VTxtAuto_TLB 单 元 中 的 声 明 修 改 一 下, 如: 4 Y/ D7 K K% K2 k1 }2 `! [
... M B2 M7 W; ~ N7 s+ w q
IVTxtAuto = interface(IDispatch)
1 h& u$ R$ j2 f2 M$ t" { ...1 K' D* ?3 n6 L
property Speed: Integer read Get_Speed write Set_Speed;
" [( K: ]6 Z6 z- z5 F2 y property Enabled: Integer read Get_Enabled write Set_Enabled;, g9 u7 \ q% L4 Y) I
...3 t/ f; n$ D" }1 p2 K) ^/ D& G" p
end;/ l' _/ o r& r
... . |7 U2 d U; ^+ m
----即 可 正 常 使 用Speed 和Enabled 属 性 了。 : {0 L% v6 _9 p: x
----至 此, 一 个 简 单 的 英 文 全 文 朗 读 器 就 完 成 了, 有 兴 趣 的 朋 友 可 以 为 其 加 入 监 视 剪 贴 板, 热 键 激 活 等 功 能。
; o. B% n: F2 B----本 文 程 序 在Win NT/98 + Delphi 4/5 环 境 下 调 试 通 过。$ |6 W9 b; d- d
" e* g' H' E: ?5 H- I8 Z |