一个发声的问题(100分)

  • 主题发起人 MicroStar
  • 开始时间
M

MicroStar

Unregistered / Unconfirmed
GUEST, unregistred user!
我用MediaPlayer 播放wav同一个wav文件不同的部分,
但发现一个部分还没播放完,就去播放下一个部分!
那位能付代码.
 
D

dwwang

Unregistered / Unconfirmed
GUEST, unregistred user!
我觉得如果你能把代码贴上来比较好。
 
M

MicroStar

Unregistered / Unconfirmed
GUEST, unregistred user!
源代码类似:
procedure TMainForm.CCEdit1KeyPress(Sender: TObject;
var Key: Char);
begin

MediaPlayer1.FileName:=GetWavFileName(Key);
MediaPlayer1.Play;
end;
function TMainForm.GerWavFileName(C:Char);
begin

C:=Upcase(C);
case C of
'A' : GetWavFileName:='A.wav';
'B' : GetWavFileName:='B.wav';
'
'
'
end;
end;
请dwwang诊断!

 
D

dwwang

Unregistered / Unconfirmed
GUEST, unregistred user!
这不是不同的wav文件吗?怎么叫同一个wav文件的不同部分呢?
解决办法有两个:
一是可以在play之前设置MediaPlayer1.wait:=true;
play之后MediaPlayer1.close;
这样播放完一个文件之前,是无法选择另一个文件的.
但你的程序其它部分也无法执行.
二是判断MediaPlayer1.Mode是否为mpPlaying,
判断的位置取决于你的程序逻辑,一般是在变更文件名之前吧!
 
M

MicroStar

Unregistered / Unconfirmed
GUEST, unregistred user!
LenOfChar:Integer;//每个字的长度
procedure TMainForm.CCEdit1KeyPress(Sender: TObject;
var Key: Char);
var Pos:Integer;
begin

Pos:=GetWavPos(Key);// 取得该字在wav 中的位置
MediaPlayer1.PlayForm:=LenofChar*Pos;
MediaPlayer1.PlayTo:=LenOfChar*(Pos+1);

MediaPlayer1.Play;
end;
我试了一下在OnNotify里没处理但没成功,
在Edit里,敲击键盘的速度太快时出现只读
追后的一两个字!请大虾指点!

 
D

dwwang

Unregistered / Unconfirmed
GUEST, unregistred user!
有点糊涂了 :(
>MediaPlayer1.PlayForm:=LenofChar*Pos;
>MediaPlayer1.PlayTo:=LenOfChar*(Pos+1);
这意思是只播放一个字长的wav吧?
>"敲击键盘的速度太快时出现只读
追后的一两个字"
你的问题到底是什么呢?
 

唐晓锋

Unregistered / Unconfirmed
GUEST, unregistred user!
我时想在Edit里面敲击键盘的时候发出字母的声音
LenOfChar:Integer;//每个字在音库中的长度
>MediaPlayer1.PlayForm:=LenofChar*Pos;
>MediaPlayer1.PlayTo:=LenOfChar*(Pos+1);
//播放一个字长的wav!
但是敲击键盘的速度太快时,只有后面的几个,能
播放出来!慢慢的敲击就没毛病!
 
D

dwwang

Unregistered / Unconfirmed
GUEST, unregistred user!
如果是这样的话, 我说的第一个办法正好解决了,
反正时间很短,没什么感觉.
 
H

huizhang

Unregistered / Unconfirmed
GUEST, unregistred user!
按照dwwang大虾说的第二个方法,在play之前用一个while循环检查一下如果正在播
放就等待放完再播放。
但是,播放声音的速度肯定赶不上敲键盘的速度,最好是为你所敲入的字符建立一个
堆栈,敲入的字符放到栈底,每次从栈顶弹出一个字符并且播放其读音,播放之后再弹出下一个。
 
T

tqz

Unregistered / Unconfirmed
GUEST, unregistred user!
用 PlaySound函数更方便。
 
M

MicroStar

Unregistered / Unconfirmed
GUEST, unregistred user!
tqz兄:
你能讲的详细点吗?
 
D

dwwang

Unregistered / Unconfirmed
GUEST, unregistred user!
PlaySound是个WinAPI,但好像没有播放一部分的功能.
看看Win32.hlp就可以了.
 
C

Chart

Unregistered / Unconfirmed
GUEST, unregistred user!
用 OnNotify 是对的, 但要记住播放的键的顺序,不要管击键的速度,
顺序播放既可。
又:为什么要用 TEdit? 还要封住控制键,且不美观...
 
H

huizhang

Unregistered / Unconfirmed
GUEST, unregistred user!
大家好像都没有理解 MicroStar 的问题, 他搞了一个 wav 文件内有所有字母的读音,
每个字母的播放时间是固定的。另外有一个TEdit,每次键入一个字符的时候就播放
该字符的读音。问题是键入下一个字符太快了的话前一个读音还没播放完就播放新键
入的字符了。
因为键入字符的速度是无法控制的,也不可能键入一个字符后等待声音播放完后才允
许键入下一个字符。
唯一的做法是为每一个键入的字符做一个记录,记录其声音是否被播放完毕,如果
已经播放完毕,再播放下一个字符的读音。
我前面所提到的堆栈是一种解决办法,但不是最好的办法。要想作得好一点看来也不
是那么容易的事情。
 
D

dwwang

Unregistered / Unconfirmed
GUEST, unregistred user!
我想大家都理解了MicroStar的问题,只是没想出好办法 :)
huizhang大虾的办法有道理,但数据结构显然应该是队列
而不是堆栈,不止对否?
并且这个操作要在OnKeyPress的第一句话检查一个标志,
判断当前是否有声音在播放,没有,则置标志,并开始播放
如有,则将字符放入队列。
然后结合我的第一种方法,将声音的播放置为强制等待。
播放结束后,检查队列,如果有字符,取出来再播放;
如没有,则将标志置为空。
早知道要写这么多,还不如来段伪码了呢! :(
 

曹晓钢

Unregistered / Unconfirmed
GUEST, unregistred user!
用队列好像也不是一个好办法.如果用户一口气打了几千个单词,
然后就可以泡一杯茶,美美的欣赏几分钟音乐了.
所以这个队列还是必须设长度限制的.
或者用DirectSound试一试,我记得他是可以允许多个wav合成的.
 
M

MicroStar

Unregistered / Unconfirmed
GUEST, unregistred user!
曹晓刚:
能举个具体点的例子吗?
 
D

dwwang

Unregistered / Unconfirmed
GUEST, unregistred user!
用我的第二种办法就不会喽!
声音发完之前根本敲不进字母(呵呵,够黑的)
 
T

tqz

Unregistered / Unconfirmed
GUEST, unregistred user!
曹晓钢的想法对,可以让不同的wav混在一起发声,这样就会减少发声对击键的滞后。
但是不必用DirectSound,可以用MS 的 Audio mixer services ,用它可以实现混音。
有一个VCL:dwavemix.zip封装了这些函数,但是我下载的版本CRC校验错:(
可以自己到DSP或torry去看看。
 
C

CJ

Unregistered / Unconfirmed
GUEST, unregistred user!
我同意dwwang的看法,结合之:
1、做一队列设长度为X如果超过长度则不允许输入;
2、每次判断队列是否有字符,如有出队列,并且播放;
这样可以环节矛盾,
 
顶部