Воспроизведение звука слишком медленно на более медленных ПК?

#c #winapi #playsound

#c #winapi #воспроизведение звука

Вопрос:

Я создал программу, которая выдает звук щелчка при каждом нажатии клавиши на клавиатуре. Когда я попробовал программу на своем ПК (с Ryzen 3900x) и на одном из моих ноутбуков (с i7 8850h), она воспроизводила звук безупречно, без каких-либо задержек, даже при быстром наборе текста.

Но на более медленном ноутбуке, который я использую для учебы, он неправильно воспроизводит звук, особенно при быстром наборе текста. (Звук либо задерживается, либо воспроизводится только небольшая часть перед остановкой)

Я не могу найти проблему, кроме того, что воспроизведение звука может быть слишком медленным или что-то в этом роде. Это не имеет никакого отношения к загрузке звукового файла, потому что я воспроизводю звук из памяти. Это также не распознавание нажатия клавиши, потому что вывод на консоль (какая клавиша нажата) происходит почти мгновенно.

Вот мой код:

 #ifndef UNICODE
#define UNICODE
#endif // UNICODE

#include <stdio.h>
#include <stdlib.h>
#include <w32api.h>
#define WINVER WindowsXP
#include <windows.h>
#include <winuser.h>

BYTE* byteAudio = NULL;

LRESULT CALLBACK WinProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    if(uMsg == WM_INPUT)
    {
        HRAWINPUT hRawInput = (HRAWINPUT)lParam;
        RAWINPUT input      = { 0 };
        UINT size           = sizeof(input);
        GetRawInputData(hRawInput, RID_INPUT,amp;input,amp;size,sizeof(RAWINPUTHEADER));

        if(input.data.keyboard.Flags == 0)
        {
            //PlaySoundW(TEXT("res/click.wav"), NULL, SND_ASYNC | SND_FILENAME);
            PlaySound(byteAudio, SND_MEMORY, SND_ASYNC | SND_MEMORY);
            printf("vkey: %x, flag: %dn",input.data.keyboard.VKey, input.data.keyboard.Flags);
        }
    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpComLine, int iShowCmd)
{
    const char* CLASS_NAME = "RawInputClass";
    FILE* fPtr;
    long lFileSize;

    //Gets file size
    fPtr        = fopen("res/click.wav", "rb");
    if(!fPtr)
    {
        printf("Error while opening file!");
        return -1;
    }
    fseek(fPtr, 0, SEEK_END);
    lFileSize   = ftell(fPtr);
    rewind(fPtr);

    //Reads file into byte-Array
    byteAudio = (BYTE*)malloc(lFileSize * sizeof(BYTE));
    if(!byteAudio)
    {
        printf("byteAudio; OUT_OF_MEMORY"); //If that happens, it is probably time for an upgrade
        return -1;
    }
    fread(byteAudio, lFileSize, 1, fPtr);
    fclose(fPtr);

    //Create Message-Only window

    WNDCLASS wnd        = { 0 };
    wnd.hInstance       = GetModuleHandle(NULL);
    wnd.lpfnWndProc     = WinProc;
    wnd.lpszClassName   = CLASS_NAME;

    RegisterClass(amp;wnd);

    HWND hWnd = CreateWindowExW(0, CLASS_NAME, TEXT("THE WINDOW IS INVISIBLE SO WHO CARES!"),
                                0, 0, 0, 0, 0, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL);
    RAWINPUTDEVICE rid = { 0 };
    rid.usUsagePage = 0x01;
    rid.usUsage = 0x06; //keyboard
    rid.dwFlags = RIDEV_INPUTSINK | RIDEV_NOLEGACY;
    rid.hwndTarget = hWnd;

    RegisterRawInputDevices(amp;rid, 1, sizeof(RAWINPUTDEVICE));

    MSG msg;
    while(GetMessage(amp;msg, NULL, 0, 0))
    {
        TranslateMessage(amp;msg);
        DispatchMessage(amp;msg);
    }
}
  

Комментарии:

1. Я не знаю, почему мой пост получает downvoted. Пожалуйста, скажите мне, что не так в моем вопросе, чтобы я мог соответствующим образом его отредактировать

2. SND_MEMORY для 2-го аргумента (hMod) неверно. Воспроизведение звука не может перекрывать звуки волн, вызов его во время воспроизведения SND_ASYNC приводит к остановке текущего воспроизведения, а затем к повторному запуску, что, вероятно, и происходит.

3. Я не могу воспроизвести вашу проблему. Согласно вашему описанию, это может быть связано только с самим компьютером. Может быть, вы можете предоставить нам больше информации, чтобы воспроизвести вашу проблему.

4. @Ascendise Я думаю, что это не имеет никакого отношения к используемому звуковому файлу, возможно, вам нужно выяснить другие возможные повторяющиеся причины, помимо компьютера.

5. Да, у меня все работает нормально. Я использую i7-7700CPU и наушники. Я некоторое время пытался вводить данные, и все работает нормально.

Ответ №1:

Вы используете метод опроса, который является медленным.

 while(GetMessage(amp;msg, NULL, 0, 0))
{
    /* stuff */
}
  

Прочитайте о том, что такое прерывания и для чего они используются. Это решит вашу проблему.

Комментарии:

1. Не так. Это стандартный цикл сообщений Win32. GetMessage блокируется до тех пор, пока сообщение не будет добавлено в очередь.

2. Это именно то, что делает метод опроса . Может быть, я слепой, но я не вижу никакой процедуры прерывания .

3. Введение в устройства с человеческим интерфейсом (HID): learn.microsoft.com/en-us/windows-hardware/drivers/hid PS в разделе legacy также есть полезная информация

4. Нет. Этот код ожидает, пока сообщения не будут добавлены в очередь. Затем он обрабатывает их. Базовый тариф для программистов пользовательского интерфейса Windows.

5. «Прерывание» скрыто в реализации GetMessage . Запуск вызывающего потока не запланирован до тех пор, пока сообщение не станет доступным. Это часть управляемого событиями API Windows и полная противоположность «опросу» .