سؤال

أنا أكتب تطبيق كتابة أساسي في C# وأردت أن يجعل البرنامج أصوات الآلة الكاتبة كما كتبت. لقد قمت بتوصيل حدث المفاتيح على صندوق strichtext إلى وظيفة تستخدم ملفًا للصوت لتشغيل ملف WAV قصير في كل مرة يتم فيها الضغط على مفتاح ، ومع ذلك لاحظت بعد فترة من الوقت أن جهاز الكمبيوتر الخاص بي يتباطأ في الزحف والتحقق من عمليتي ، Audiodlg .

الرمز الذي أستخدمه كما يلي:

أقوم بتهيئة soundplayer كمتغير عالمي في البرنامج يبدأ بـ

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

ثم في حدث keypress أنا ببساطة أتصل به

sp.Play();

هل يعرف أي شخص ما الذي يسبب استخدام الذاكرة الثقيلة؟ الملف أقل من ثانية ثانية ، لذلك لا ينبغي أن يسد الأمر أكثر من اللازم.

هل كانت مفيدة؟

المحلول

لا تستخدم SoundPlayer - استخدم ال waveOut... API بدلاً من ذلك:

http://www.codeproject.com/articles/4889/a-full-duplex-audio-player-in-c-using-thewavein-w

SoundPlayer يشبه لعبة أكثر من عنصر جاهز للإنتاج ، على الرغم من أنني متأكد من أن MS Intern الذي كتبه يعني جيدًا. قون

تحديث: إذا كنت تستخدم العينة المرتبطة وتعرف على الرمز ، فسترى ما هو الخطأ على الأرجح في SoundPlayer تطبيق. لعب الصوت مع waveOut... تتضمن الوظائف مخزن المؤقتان في الذاكرة: واحد صغير للرأس ، وواحد مخزن مؤقت يحتمل أن يحتوي على بيانات العينة الفعلية. إن مقالة Hotfix التي ربطتها بتسرب بضع مئات من البايت في كل مرة Play يُطلق عليه ، مما يعني أن الكود ربما يكون له مثيل رأس جديد في كل مرة ومن ثم عدم التخلص منه بشكل صحيح. (هذا يفترض SoundPlayer يلف waveOut... API - لا أعرف ما إذا كان هذا هو الحال أم لا)

يأخذ المبرمجون أمرا مفروغا منه "لا تعيد اختراع العجلة". حسنًا ، في بعض الأحيان تحتاج العجلة إلى إعادة اختراع.

نصائح أخرى

يمكن أن يكون خلل في soundplayer.

جرب هذه المقالة على مشروع الرمز, ، ربما سوف يعطيك بعض التلميحات.

حاول استخدام Load طريقة مشغل الصوت لتحميل الصوت ، ثم الاتصال. يستخدم Play مؤشر ترابط ثانٍ للتحميل (إن لم يتم تحميله بالفعل) وتشغيل الملف.

ربما لا يقوم المنشئ بتحميل الملف مبدئيًا (وهو ما أعتقد أنه ممكن تمامًا) ، فهو يربط اللاعب باسم ملف الصوت.

لقد فعلت مع هذه العينة. WWFM (المعروف أيضًا باسم "عملت بشكل جيد بالنسبة لي). حاول البحث في الأخطاء في الكود الخاص بك (والتي ، أنا متأكد تقريبًا ، هي نقية بدرجة كافية) أو ملف صوت آخر.

حاول التخلص من سبراي لاي بعد تشغيل الصوت. ثم قم بتشغيل جامع القمامة. إذا كانت لا تزال تستهلك ذاكرة إضافية ، فسيحدث شيء سيء حقًا ويجب إجراء الاختبارات على جهاز كمبيوتر آخر.

لقد استخدمت تشغيل الصوت العمل داخل واجهة برمجة تطبيقات Win32 قبل القيام بشيء مماثل. على الرغم من أن هذا ليس في نفس اللغة التي تستخدمها ، إلا أنه مثال على برنامج يلعب "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

هذا ليس بمثابة إجابة صارمة ، لذلك لن أؤكد ذلك كإجابة مقبولة على سؤالي ، ولكن هذا حل لأولئك الذين واجهوا نفس المشكلات (وأكد أيضًا أنه ليس نظامي على خطأ)

قررت تنفيذ الصوت باستخدام مكتبة Audioplayback من ManagedDirectx ، والتي هي سهلة الاستخدام مثل SoundPlayer ، ولكن نجحت في حل مشكلتي.

بالنسبة لأولئك الذين يريدون أن يعرفوا ، فإن الكود بسيط:

1) إضافة مرجع إلى Audioplayback DLL.

2) قم بإنشاء كائن صوتي (قمت بتسمية صوت الألغام) ، اجعله متغيرًا في النموذج الخاص بك حتى تتمكن

3) تشغيل الملف باستخدام sound.play () ؛

4) إذا كنت بحاجة إلى تشغيل الملف مرة أخرى ، فاستخدم السطر التالي:

sound.SeekCurrentPosition(0, SeekPositionFlags.AbsolutePositioning);

إنه سريع إلى حد ما ، وجيد إلى حد ما. ستكون هناك مشكلات في الذاكرة إذا كنت بحاجة إلى الكثير من المؤثرات الصوتية المختلفة ، لأنها ستكون جميعها في الذاكرة ، ولكن إذا كنت بحاجة إلى صوت واحد لتشغيله كثيرًا ، فسيؤدي ذلك إلى القيام بذلك دون تضخيم Audiodlg.exe

يجب أن تحاول استخدام ()

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

عند الانتهاء من عملية SP.Play () ، تعود الذاكرة إلى نظامك التلقائي.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top