SoFunction
Updated on 2025-03-07

How to get recorded audio using Windows API

This article introduces the method of obtaining audio streams using the examples. The specific steps are as follows:

1. First, you need to include the following reference object

#include <>
#include ""
#pragma comment(lib, "")

2. 7 functions are required to obtain audio

1. waveInGetNumDevs: Returns the number of waveform sound input devices ready in the system

UINT waveInGetNumDevs(VOID);

2. waveInGetDevCaps: Check the characteristics of the specified waveform input device

MMRESULT waveInGetDevCaps( 
 UINT_PTR   uDeviceID, 
 LPWAVEINCAPS pwic,    
 UINT     cbwic    
);
//uDeviceID The audio input device identifier, which can also be a handle to an open audio input device.// I personally believe that if multiple devices were obtained in the previous step, each device can be identified with an index.//  
//pwic A pointer to the WAVEINCAPS structure, containing the audio characteristics of the device.//
//Cbwic WAVEINCAPS structure size, just use sizeof.//
//The result of the execution of the MMRESULT function// MMSYSERR_NOERROR indicates successful execution// MMSYSERR_BADDEVICEID Index goes beyond the bounds// MMSYSERR_NODRIVER No ready device// MMSYSERR_NOMEM cannot allocate or lock memory

Introducing the meaning of WAVEINCAPS structure:

typedef struct { 
  WORD   wMid;        //Driver ID defined by audio equipment manufacturer  WORD   wPid;        //Product identification of audio input device  MMVERSION vDriverVersion;    //Driver version number  TCHAR   szPname[MAXPNAMELEN];//Manufacturer name  DWORD   dwFormats;      //Supported formats, see MSDN  WORD   wChannels;      // Supported number of channels  WORD   wReserved1;      //Reserve parameters} WAVEINCAPS;

3. waveInOpen: Open the specified audio input device and record it

MMRESULT waveInOpen(
 LPHWAVEIN    phwi,        //Receive the pointer of the HWAVEIN structure identified by the open audio input device UINT_PTR    uDeviceID,      //Specify a device ID that needs to be turned on. You can use WAVE_MAPPER to select a device that records in the specified recording format LPWAVEFORMATEX pwfx,        // A required format for recording the WAVEFORMATEX structure pointer DWORD_PTR   dwCallback,    //Point to a callback function, event handle, window handle, thread identifier to handle recording events. DWORD_PTR   dwCallbackInstance, // Parameters passed to the callback mechanism DWORD     fdwOpen      //Open the device method ID, specify the type of callback. See CSDN);

Introducing the meaning of WAVEFORMATEX structure:

typedef struct { 
  WORD wFormatTag;    //Format of waveform sound, mono dual channel uses WAVE_FORMAT_PCM. When included in the WAVEFORMATEXTENSIBLE structure, use WAVE_FORMAT_EXTENSIBLE.  WORD nChannels;    //Number of channels  DWORD nSamplesPerSec;  //Sampling rate.WFormatTag is WAVE_FORMAT_PCM, there are 8.0kHz, 11.025kHz, 22.05kHz, and 44.1kHz.  DWORD nAvgBytesPerSec;  //Number of sampled bytes per second. Calculated by nSamplesPerSec * nChannels * wBitsPerSample / 8  WORD nBlockAlign;    //The number of bytes per sample. Calculated by nChannels * wBitsPerSample / 8  WORD wBitsPerSample;  //The number of sample bits.wFormatTag is WAVE_FORMAT_PCM, it is 8 or 16  WORD cbSize;      //WFormatTag is WAVE_FORMAT_PCM, this parameter is ignored} WAVEFORMATEX;

Introduce the dwCallback callback function format:

void CALLBACK waveInProc(
 HWAVEIN hwi,     //The device handle of this function is called back UINT uMsg,      //Waveform sound input information, marking off (WIM_CLOSE), buffer full (WIM_DATA), on (WIM_OPEN). DWORD_PTR dwInstance, //The data specified by the user in waveInOpen DWORD_PTR dwParam1,  //(LPWAVEHDR)dwParam1, the buffer specified by the user DWORD_PTR dwParam2   
);

4. waveInPrepareHeader: Prepare a buffer for the audio input device

MMRESULT waveInPrepareHeader(
 HWAVEIN hwi,  //Audio input device handle LPWAVEHDR pwh,//Pointer to WAVEHDR structure identifying the prepared buffer UINT cbwh    //The size of the WAVEHDR structure is used, just use sizeof);

Introducing the WAVEHDR structure:

typedef struct wavehdr_tag { 
  LPSTR   lpData;     //Point to the buffer of waveform format  DWORD   dwBufferLength; //Buffer size  DWORD   dwBytesRecorded; //How much data is currently stored  DWORD_PTR dwUser;     //User Data  DWORD   dwFlags;      //Information provided for the buffer, use WHDR_PREPARED in the waveInPrepareHeader function  DWORD   dwLoops;     //Use when output, identify the number of playbacks  struct wavehdr_tag * lpNext;//reserved
  DWORD_PTR reserved;     //reserved
} WAVEHDR, *LPWAVEHDR; 

5. waveInAddBuffer: Send the buffer to the device. If the buffer is full, it will not work. (The parameters are the same as above)

MMRESULT waveInAddBuffer(
 HWAVEIN hwi, 
 LPWAVEHDR pwh, 
 UINT cbwh 
); 

6. waveInStart: Start recording

MMRESULT waveInStart(
 HWAVEIN hwi // Device handle);

7. waveInClose: Turn off the device

MRESULT waveInClose(
 HWAVEIN hwi // Device handle);

3. The complete example code is as follows:

//document#include &lt;&gt;
#include &lt;&gt;
#include ""
#pragma comment(lib, "")
void PlayMusi();
void WaveInitFormat(LPWAVEFORMATEX m_WaveFormat, WORD nCh,DWORD nSampleRate,WORD BitsPerSample);
DWORD CALLBACK MicCallback(HWAVEIN hwavein, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2);
void RecordWave();

void main()
{
 //PlayMusi();
 RecordWave();
 while(1);
}
void RecordWave()
{
 int count = waveInGetNumDevs();//1
 printf("\nNumber of audio inputs: %d\n",count);

 WAVEINCAPS waveIncaps;
 MMRESULT mmResult = waveInGetDevCaps(0,&amp;waveIncaps,sizeof(WAVEINCAPS));//2
 printf("\nAudio input device: %s\n",);

 if(MMSYSERR_NOERROR==mmResult)
 {
 HWAVEIN phwi;
 WAVEFORMATEX pwfx;
 WaveInitFormat(&amp;pwfx,1,8000,8);
 printf("\nRequest to turn on the audio input device");
 printf("\nSampling parameters: Mono 8kHz 8bit\n");
 mmResult=waveInOpen(&amp;phwi,WAVE_MAPPER,&amp;pwfx,(DWORD)(MicCallback),NULL,CALLBACK_FUNCTION);//3

 if(MMSYSERR_NOERROR==mmResult)
 {
  WAVEHDR pwh1;
  char buffer1[10240];
  =buffer1;
  =10240;
  =1;
  =0;
  mmResult=waveInPrepareHeader(phwi,&amp;pwh1,sizeof(WAVEHDR));//4
  printf("\nPrepare buffer 1");

  WAVEHDR pwh2;
  char buffer2[10240];
  =buffer2;
  =10240;
  =2;
  =0;
  mmResult=waveInPrepareHeader(phwi,&amp;pwh2,sizeof(WAVEHDR));//4
  printf("\nPrepare buffer 2\n");

  if(MMSYSERR_NOERROR==mmResult)
  {
  mmResult=waveInAddBuffer(phwi,&amp;pwh1,sizeof(WAVEHDR));//5
  printf("\nAdd buffer 1 to audio input device");
  mmResult=waveInAddBuffer(phwi,&amp;pwh2,sizeof(WAVEHDR));//5
  printf("\nAdd buffer 2 to audio input device\n");

  if(MMSYSERR_NOERROR==mmResult)
  {
   mmResult=waveInStart(phwi);//6
   printf("\nRequest to start recording\n");
  }
  }
 }

 }
}
DWORD CALLBACK MicCallback(HWAVEIN hwavein, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
{
 switch(uMsg) 
 {
 case WIM_OPEN:
  printf("\nThe device is turned on...\n");
  break;
 
 case WIM_DATA:
  printf("\nBuffer %d is full...\n",((LPWAVEHDR)dwParam1)-&gt;dwUser);
  waveInAddBuffer (hwavein, (LPWAVEHDR)dwParam1, sizeof (WAVEHDR)) ;
  break;
 
 case WIM_CLOSE:
  printf("\nThe device has been turned off...\n");
  break;
 default:
  break;
 }
 return 0;
}
void WaveInitFormat(LPWAVEFORMATEX m_WaveFormat, WORD nCh,DWORD nSampleRate,WORD BitsPerSample)
{
 m_WaveFormat-&gt;wFormatTag = WAVE_FORMAT_PCM;
 m_WaveFormat-&gt;nChannels = nCh;
 m_WaveFormat-&gt;nSamplesPerSec = nSampleRate;
 m_WaveFormat-&gt;nAvgBytesPerSec = nSampleRate * nCh * BitsPerSample/8;
 m_WaveFormat-&gt;nBlockAlign = m_WaveFormat-&gt;nChannels * BitsPerSample/8;
 m_WaveFormat-&gt;wBitsPerSample = BitsPerSample;
 m_WaveFormat-&gt;cbSize = 0;
}
void PlayMusi()
{
 int error = mciSendString("open C:\\Users\\Angel\\Desktop\\How much love can I do again.mp3 alias myDivece", NULL, 0, NULL);
 if (error == 0)
 {
 mciSendString("play myDivece", NULL, 0, NULL); //Play }
}