8

私はC#で基本的なライティングアプリを書いていますが、入力時にタイプライターの音をプログラムに生成させたいと思っていました。RichTextBoxのKeyPressイベントを、キーが押されるたびにSoundPlayerを使用して短いwavファイルを再生する関数にフックしましたが、しばらくすると、コンピューターのクロールが遅くなり、プロセスをチェックしていることに気付きました。 .exeは5ギガバイトのRAMを使用していました。

私が使用しているコードは次のとおりです。

プログラムの開始時にグローバル変数としてSoundPlayerを初期化します。

SoundPlayer sp = new SoundPlayer("typewriter.wav")

次に、KeyPressイベントで私は単に電話します

sp.Play();

誰かが大量のメモリ使用の原因を知っていますか?ファイルの長さは1秒未満なので、目詰まりしすぎないようにする必要があります。

4

8 に答える 8

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...は、2つのメモリ内バッファが必要です。1つはヘッダー用の小さなバッファで、もう1つは実際のサンプルデータを含む可能性のある大きなバッファです。リンクした修正プログラムの記事では、毎回数百バイトのリークPlayが呼び出されると述べています。これは、コードが毎回新しいヘッダーをインスタンス化していて、適切に破棄されていない可能性があることを意味します。SoundPlayer(これはAPIをラップすることを前提としていwaveOut...ます-これが当てはまるかどうかはわかりません)

プログラマーは、「車輪の再発明をしない」という格言を当然のことと考えています。まあ、時々ホイールは必死に再発明する必要があります。

于 2011-01-29T17:50:23.297 に答える
2

SoundPlayerのバグである可能性があります。

コードプロジェクトに関するこの記事を試してみてください。おそらくそれはあなたにいくつかのヒントを与えるでしょう。

于 2010-11-05T16:48:25.760 に答える
0

Loadサウンドプレーヤーの方法を使用してサウンドをロードしてから、playを呼び出してみてください。Playは、2番目のスレッドを使用してファイルをロード(まだロードされていない場合)および再生します。

コンストラクターは最初にファイルをロードしないかもしれませんが(これはかなり可能だと思います)、プレーヤーをサウンドファイル名にわずかに関連付けます。

于 2010-11-05T16:33:47.593 に答える
0

このサンプルを使用しました。WWFM(別名「WorkedWell ForMe」)。コード(ほぼ確実に、十分に純粋です)または別のサウンドファイルのエラーを検索してみてください。

于 2011-01-25T12:15:58.387 に答える
0

サウンドを再生した後、SoundPlayerを破棄してみてください。次に、ガベージコレクターを実行します。それでも追加のメモリを消費する場合は、本当に厄介なことが起こっているので、別のコンピュータでテストを実行する必要があります。

于 2011-01-26T14:01:07.550 に答える
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
于 2011-01-30T00:30:07.317 に答える
0

これは厳密に言えば答えではないので、これが私の質問に対する受け入れられた答えであることを確認しませんが、同じ問題を抱えている人のための解決策です(そしてそれが私のシステムに問題がないことも確認します)

私はManagedDirectXのAudioPlaybackライブラリを使用してサウンドを実装することにしました。これはSoundPlayerとほぼ同じくらい使いやすいですが、問題は正常に解決されました。

知りたい人のために、コードは単純です:

1)audioplaybackdllへの参照を追加します。

2)Audioオブジェクト(私は私のサウンドと名付けました)を作成し、フォーム上で変数にして、再度参照できるようにします。コンストラクターを使用して、再生するファイル名を設定します。

3)sound.Play();でファイルを再生します。

4)ファイルを再度再生する必要がある場合は、次の行を使用します。

sound.SeekCurrentPosition(0, SeekPositionFlags.AbsolutePositioning);

それはかなり速く、そしてかなり良いです。さまざまなサウンドエフェクトが必要な場合は、すべてが常にメモリ内にあるため、メモリの問題が発生しますが、1つのサウンドを大量に再生する必要がある場合は、Audiodlg.exeを膨らませることなくこれを実行できます。

于 2011-02-01T23:17:02.607 に答える
0

using()を試してみてください

using(SoundPlayer sp = new SoundPlayer("typewriter.wav")) {
   sp.Play();
}

プロセスが終了すると、sp.Play()メモリはシステムの自動に戻ります。

于 2011-11-12T09:48:15.480 に答える