machine_1
machine_1

Reputation: 4454

Record from speakers and end a recording process by pressing a key instead of waiting specified amount of time

Based on the answer to the question How to record wav sound from mic using Windows API?, I went to the page whose link is provided in the answer and found an example code that records audio from microphone.

I would like to know how to change the code to:

1-Record from speakers instead.
2-If possible, stop recording by pressing a key instead of waiting the amount of time given as a function argument.

#include <Windows.h>

#pragma comment (lib, "Winmm.lib")


DWORD recordWAVEFile(DWORD dwMilliSeconds)
{
    UINT wDeviceID;
    DWORD dwReturn;
    MCI_OPEN_PARMS mciOpenParms;
    MCI_RECORD_PARMS mciRecordParms;
    MCI_SAVE_PARMS mciSaveParms;
    MCI_PLAY_PARMS mciPlayParms;

    mciOpenParms.lpstrDeviceType = "waveaudio";
    mciOpenParms.lpstrElementName = "";

    if (dwReturn = mciSendCommand(0, MCI_OPEN,
                                  MCI_OPEN_ELEMENT | MCI_OPEN_TYPE,
                                  (DWORD)(LPVOID)&mciOpenParms))
    {
        return (dwReturn);
    }

    wDeviceID = mciOpenParms.wDeviceID;

    mciRecordParms.dwTo = dwMilliSeconds;

    if (dwReturn = mciSendCommand(wDeviceID, MCI_RECORD,
        MCI_TO | MCI_WAIT, (DWORD)(LPVOID)&mciRecordParms))
    {
        mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
        return (dwReturn);
    }

    mciPlayParms.dwFrom = 0L;
    if (dwReturn = mciSendCommand(wDeviceID, MCI_PLAY,
        MCI_FROM | MCI_WAIT, (DWORD)(LPVOID)&mciPlayParms))
    {
        mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
        return (dwReturn);
    }
    if (MessageBox(NULL, "Do you want to save this recording?",
        "", MB_YESNO) == IDNO)
    {
        mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
        return (0L);
    }

    mciSaveParms.lpfilename = "tempfile.wav";
    if (dwReturn = mciSendCommand(wDeviceID, MCI_SAVE,
        MCI_SAVE_FILE | MCI_WAIT, (DWORD)(LPVOID)&mciSaveParms))
    {
        mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
        return (dwReturn);
    }

    return (0L);
}


LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);


int WINAPI WinMain(
    HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    PSTR szCmdLine,
    int iCmdShow)
{
    char szAppName[] = "App";
    char szWinName[] = "App";

    WNDCLASS wndclass;
    wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    wndclass.lpfnWndProc = WndProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName = NULL;
    wndclass.lpszClassName = szAppName;

    if (!RegisterClass(&wndclass))
    {
        MessageBox(
            NULL,
            TEXT("Failed to register window class."),
            szAppName,
            MB_ICONERROR);
        return 0;
    }

    HWND hwnd;
    hwnd = CreateWindow(
        szAppName,
        szWinName,
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        NULL,
        NULL,
        hInstance,
        NULL);

    if (!hwnd)
    {
        return 0;
    }

    ShowWindow(hwnd, iCmdShow);
    UpdateWindow(hwnd);

    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}

LRESULT CALLBACK WndProc(
    HWND hwnd,
    UINT message,
    WPARAM wParam,
    LPARAM lParam)
{
    switch (message)
    {
    case WM_KEYDOWN:
        switch (wParam)
        {
        case VK_RETURN:
            recordWAVEFile(4000);
            break;
        default:
            break;
        }
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}

Upvotes: 1

Views: 551

Answers (2)

boytjmjler
boytjmjler

Reputation: 1

You can using function:

MCIWndRecord 

Upvotes: 0

Michael Chourdakis
Michael Chourdakis

Reputation: 11158

With MCI you cannot pick a source other than the default. You have to use waveIn* functions (waveInOpen() accepts a parameter to select the input source).

The other option is to set the default input to something available using the (horrible) Mixer API, so MCI uses it.

However, not all sound cards support recording from the speakers ("what you hear" input). Actually, most of nowadays cheap cards coming with the motherboard do not have such an option.

The other question, to stop the recording, waveIn functions these are asynchronous, so you can simply stop recording with waveInStop(), waveInReset() and waveInClose() when a key is pressed.

Generally, sound business in Windows is not done with MCI, MCI is a very simple interface for quick playback and recording.

Upvotes: 1

Related Questions