我正在用C#编写一个基本的写作应用程序,我希望程序能够在输入时输出打字机的声音。我已经将我的RichTextBox上的KeyPress事件挂钩到一个函数,该函数使用SoundPlayer每次按下一个键时播放一个简短的wav文件,但是我注意到一段时间后我的计算机慢慢爬行并检查我的进程,audiodlg .exe正在使用5 GIGABYTES RAM。
我正在使用的代码如下:
我使用
将SoundPlayer初始化为程序启动时的全局变量SoundPlayer sp = new SoundPlayer("typewriter.wav")
然后在KeyPress事件中我只需调用
sp.Play();
有人知道造成大量内存使用的原因吗?该文件不到一秒钟,所以它不应该堵塞太多东西。
答案 0 :(得分:6)
请勿使用SoundPlayer
- 请改用waveOut...
API:
http://www.codeproject.com/Articles/4889/A-full-duplex-audio-player-in-C-using-the-waveIn-w
SoundPlayer
更像是一个玩具,而不是一个可以投入生产的组件,虽然我确信编写它的MS实习生意味着很好。 :)
更新:如果您使用链接的示例并熟悉代码,您将看到SoundPlayer
实现可能出现的问题。使用waveOut...
函数播放音频涉及两个内存缓冲区:一个小的用于标头,一个可能大的缓冲区包含实际的样本数据。您链接的修补程序文章提到每次调用Play
时泄漏几百个字节,这意味着代码可能每次实例化一个新标头,然后不正确处理它。 (假设SoundPlayer
包装了waveOut...
API - 我不知道是否是这种情况)
程序员理所当然地认为“不要重新发明轮子”。好吧,有时轮子迫切需要重新发明。
答案 1 :(得分:2)
这可能是SoundPlayer中的一个错误。
在code project上试试这篇文章,也许它会给你一些提示。
答案 2 :(得分:0)
尝试使用声音播放器的Load
方法加载声音,然后调用播放。 Play使用第二个线程加载(如果尚未加载)并播放该文件。
也许构造函数最初没有加载文件(我认为这很可能),它会将播放器与声音文件名关联起来。
答案 3 :(得分:0)
我已经完成了this sample。 WWFM(又名“为我工作好”)。尝试在你的代码中搜索错误(我几乎可以肯定,这已经足够了)或其他声音文件。
答案 4 :(得分:0)
播放声音后尝试处理SoundPlayer。然后运行垃圾收集器。如果它仍然消耗额外的内存,那么真的很糟糕,你应该在另一台计算机上运行测试。
答案 5 :(得分:0)
我之前在Win32 API中使用了PlaySound函数来做类似的事情。 虽然这与您使用的语言不同,但下面是一个程序示例,它将在每100次击键时播放“mahnamahna.wav”。(是的,这很有趣)
format PE GUI 4.0
entry start
;Mahna Mahna.
include 'win32a.inc'
include 'helper.asm'
section '.idata' import data readable writeable
library kernel32,'KERNEL32.DLL',\
user32,'USER32.DLL',\
hook,'HOOK.DLL',\
winmm,'WINMM.DLL'
import hook,\
SetKeyPressedHandler,'SetKeyPressedHandler'
import winmm,\
PlaySound,'PlaySound'
include 'api\kernel32.inc'
include 'api\user32.inc'
section '.data' data readable writeable
szWavFile db "mahnamahna.wav",0
;String saying what the dll is called.
szDllName db "HOOK.DLL",0
;Name of the function in the dll for the keyboard procedure
szf_KeyboardProc db "KeyboardProc",0
;handle to the dll
hDll dd ?
;handle to the keyboard procedure
hKeyboardProc dd ?
;handle to the hook
hHook dd ?
kInput KBINPUT
keyCount dd 0x0 ;
;msg for the message pump
msg MSG
section '.text' code readable executable
start:
;Load the DLL into memory.
invoke LoadLibraryA,szDllName
cmp eax,0x0
je exit
mov [hDll],eax
invoke GetProcAddress,[hDll],szf_KeyboardProc
cmp eax,0x0
je freeLibrary
mov [hKeyboardProc],eax
invoke SetKeyPressedHandler,KeyPressedHandler
hook:
invoke SetWindowsHookEx,WH_KEYBOARD_LL,[hKeyboardProc],[hDll],0x0
cmp eax,0x0
je freeLibrary
mov [hHook],eax
msg_loop:
invoke GetMessage,msg,NULL,0,0
cmp eax,1
jb unhook
jne msg_loop
invoke TranslateMessage,msg
invoke DispatchMessage,msg
jmp msg_loop
proc KeyPressedHandler code,wparam,lparam
;Move the VK Code of the key they pressed into al.
xor eax,eax
mov eax,[lparam]
mov cx,word [eax]
cmp [wparam],WM_KEYDOWN
je .ProcessKeyDown
cmp [wparam],WM_KEYUP
je .ProcessKeyUp
.ProcessKeyDown:
ret ;No need to go any further - we only process characters on key up
.ProcessKeyUp:
mov edx,[keyCount]
inc edx
cmp cx,VK_F12
je unhook
;Hotkeys.
;F12 - Quit.
cmp edx,0x64
jne .done
call MahnaMahna
xor edx,edx
.done:
mov [keyCount],edx
ret
endp
proc MahnaMahna
invoke PlaySound,szWavFile,0x0,0x20000
ret
endp
unhook:
invoke UnhookWindowsHookEx,[hHook]
freeLibrary:
invoke FreeLibrary,[hDll]
exit:
invoke ExitProcess,0
如果没有以下dll(hook.dll)
,上述操作将无效 format PE GUI 4.0 DLL
entry _DllMain
include 'win32a.inc'
section '.data' data readable writeable
hKeyPressedHandler dd 0x0
section '.text' code readable executable
proc _DllMain hinstDLL,fdwReason,lpvReserved
mov eax,TRUE
ret
endp
proc SetKeyPressedHandler hProc
mov eax,[hProc]
mov [hKeyPressedHandler],eax
ret
endp
proc KeyboardProc code,wparam,lparam
cmp [code],0x0
jl CallNextHook
cmp [hKeyPressedHandler],0x0;Make sure our event handler is set.
je CallNextHook
;Call our handler.
invoke hKeyPressedHandler,[code],[wparam],[lparam]
CallNextHook:
invoke CallNextHookEx,0x0,[code],[wparam],[lparam]
ret
endp
section '.idata' import data readable writeable
library kernel32,'KERNEL32.DLL',\
user32,'USER32.DLL'
include 'api\kernel32.inc'
include 'api\user32.inc'
section '.edata' export data readable
export 'hook.DLL',\
KeyboardProc,'KeyboardProc',\
SetKeyPressedHandler,'SetKeyPressedHandler'
section '.reloc' fixups data discardable
答案 6 :(得分:0)
这不是严格意义上的答案,所以我不会将此确认为我的问题的可接受的答案,但对于那些遇到同样问题的人来说这是一个解决方案(并且也确认这不是我的系统有问题) )
我决定使用ManagedDirectX的AudioPlayback库实现声音,它与SoundPlayer一样容易使用,但已成功解决了我的问题。
对于那些想要了解的人来说,代码很简单:
1)添加对audioplayback dll的引用。
2)创建一个Audio对象(我命名为mine sound),使其成为表单上的变量,以便您可以再次引用它,使用构造函数设置它应该播放的文件名
3)使用sound.Play();
播放文件4)如果您需要再次播放该文件,请使用以下行:
sound.SeekCurrentPosition(0, SeekPositionFlags.AbsolutePositioning);
它相当快,而且相当不错。如果你需要很多不同的声音效果会有内存问题,因为它们都会一直存在于内存中,但是如果你需要一个声音来播放很多声音,那么这个声音就可以在不使你的Audiodlg.exe膨胀的情况下进行。
答案 7 :(得分:0)
你应该尝试使用()
using(SoundPlayer sp = new SoundPlayer("typewriter.wav")) {
sp.Play();
}
当流程结束时,sp.Play()内存返回到系统自动更新。