How can you perform other functions simultaneously with PlaySound?

1

I'm writing a C++ Windows Application program which needs to Play a randomly chosen song from an array and the user needs to be able to play another song on the list at the click of a button. How would you stop the sound from the first song as to play the second song?

By pressing my button which plays the first song, the audio resource is played, however my program no longer responds to any clicks and the code does not continue until the song is complete. I have attempted using CreateThread(), however to no avail as my program remains in an unresponsive state.

The Function containing PlaySound:

LPTHREAD_START_ROUTINE WINAPI PlayWavFile(int resource) {
    PlaySound(MAKEINTRESOURCE(resource), hInst, SND_RESOURCE | SND_SYNC);
    return 0;
}

The case in the WndProc function which determines the result of button presses:

case WM_COMMAND:
        if (LOWORD(wParam) == 1) {
            HANDLE hThread = CreateThread(
                NULL,
                0,
                PlayWavFile(i),
                NULL,
                NULL,
                NULL
            );
        }
        else if (LOWORD(wParam) == 2) {
            HANDLE hPlaySecond = CreateThread(
                NULL,
                0,
                PlayWavFile(j),
                NULL,
                NULL,
                NULL
            );
        }
        else if (LOWORD(wParam) == 3) {
            HANDLE hStop = CreateThread(
                NULL,
                0,
                PlayWavFile(NULL),
                NULL,
                NULL,
                NULL
            );
        }
        break;

Also if if I try clicking my button which should give the wParam value of 3, the program reaches an exception which states:

Exception thrown at 0x00000000 in Audio Player.exe: 0xC0000005: Access violation executing location 0x00000000. occurred.

The end goal is that the program would just be responsive whilst the music plays in the background.

c++
windows
asked on Stack Overflow Jun 13, 2019 by Ethan Sigler • edited Jun 13, 2019 by Ethan Sigler

2 Answers

3

Just call PlaySound directly with SND_ASYNC instead of SND_SYNC. That would cause PlaySound to return immediately and play the sound in the background.

There's no need to mess around with threads for that.

answered on Stack Overflow Jun 13, 2019 by Shloim • edited Jun 13, 2019 by Shloim
2

When you do

HANDLE hThread = CreateThread(
    NULL,
    0,
    PlayWavFile(i),
    NULL,
    NULL,
    NULL
);

you are calling the function PlayWavFile, and are using the value it returns as the thread function to call. And since the function is always returning 0, which is a null pointer, it's equivalent to

HANDLE hThread = CreateThread(
    NULL,
    0,
    nullptr,
    NULL,
    NULL,
    NULL
);

The thread function arguments is of the type LPTHREAD_START_ROUTINE, which is a pointer to a function which takes an LPVOID argument, and returns a DWORD.

You need to change your thread function accordingly, and then call CreateThread as

HANDLE hThread = CreateThread(
    NULL,
    0,
    &PlayWavFile,  // Pass a pointer to the function
    reinterpret_cast<LPVOID>(i),    // The argument to pass
    NULL,
    NULL
);

With this the PlayWavFile could look something like

DWORD PlayWavFile(LPVOID argument) {
    int resource = reinterpret_cast<int>(argument);
    PlaySound(MAKEINTRESOURCE(resource), hInst, SND_RESOURCE | SND_SYNC);
    return 0;
}
answered on Stack Overflow Jun 13, 2019 by Some programmer dude • edited Jun 13, 2019 by Some programmer dude

User contributions licensed under CC BY-SA 3.0