基于WASAPI的录音播音系统

该博客介绍了如何使用C++和Windows API在VS2022上实现录音(PCM格式)、播放(PCM、WAV、MP3格式)以及PCM到WAV的格式转换。代码示例包括输入参数设置、回调函数实现、文件遍历播放等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近写了一个小的系统,在VS2022平台上做的,主要是通过调用Windows的API接口实现录音(PCM格式),播音(PCM、WAV、Mp3格式),PCM格式转WAV格式、遍历指定文件夹下的所有音频文件并播放。废话不多说,直接上演示功能截图和代码,其他的不懂的随便一查都很多。
菜单界面菜单1功能,输入相关信息。

录音前设备相关信息录音结束菜单2的功能菜单2的功能菜单3的功能在这里插入代码片
#record.h
#include<Windows.h>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include"mmsystem.h"
#pragma comment(lib, “winmm.lib”)

/*
int audioSec = 3;
int inputDevice = 0;
int inputChannel = 2;
int inputBits = 16;
unsigned long inputSample = 16000;
static char bufferOne[1024];
static char bufferTwo[1024];
char generateAudioFileName1[100] = “mic.pcm”;
char generateAudioFileName2[100] = “ref.pcm”;
int count;
int i;
HWAVEIN phwi;
WAVEFORMATEX pwfx;
WAVEINCAPS waveincaps;
WAVEHDR pwhOne;
WAVEHDR pwhTwo;
FILE* f = NULL;
FILE* f2 = NULL;
/
int audioSec;
int inputDevice;
int inputChannel;
int inputBits;
unsigned long inputSample;
static char bufferOne[1024];
static char bufferTwo[1024];
char generateAudioFileName1[100];
char generateAudioFileName2[100];
int count;
int i;
HWAVEIN phwi;
WAVEFORMATEX pwfx;
WAVEINCAPS waveincaps;
WAVEHDR pwhOne;
WAVEHDR pwhTwo;
FILE
f = NULL;
FILE* f2 = NULL;
void inputSec()
{
/*
* int inputDevice, inputChannel, inputBits;
unsigned long inputSample;
*/
printf(“请输入预录音的文件名1:”);
scanf(“%s”, generateAudioFileName1);
printf(“\n”);
printf(“请输入预录音的文件名2:”);
scanf(“%s”, generateAudioFileName2);
printf(“\n”);
printf(“请输入要录音的设备:”);
scanf(“%d”, &inputDevice);
printf(“\n”);
printf(“请输入录音通道数:”);
scanf(“%d”, &inputChannel);
printf(“\n”);
printf(“请输入录音的采样率:”);
scanf(“%ld”, &inputSample);
printf(“\n”);
printf(“请输入录音的采样位数:”);
scanf(“%d”, &inputBits);
printf(“\n”);
printf(“请输入你要录制该音频的时长(单位/s):”);
int second;
scanf(“%d”, &second);
while (true)
{
if (second <= 0 || second > 100)
{
printf(“请按要求重新输入:”);
getchar();
scanf(“%d”, &second);
}
else {
break;
}
}
audioSec = second;
}

void stop()
{
MMRESULT mResult = waveInStop(phwi);
printf(“waveInStop value is: %d\n”, mResult);
//getchar();
system(“EXIT”);
mResult = waveInReset(phwi);
printf(“waveInReset value is: %d\n”, mResult);
//Sleep(1000);

mResult = waveInUnprepareHeader(phwi, &pwhOne, sizeof(WAVEHDR));
printf("waveInUnprepareHeader value is: %d", mResult);

mResult = waveInUnprepareHeader(phwi, &pwhTwo, sizeof(WAVEHDR));
printf("waveInUnprepareHeader value is: %d", mResult);

mResult = waveInClose(phwi);
//Sleep(1000);
printf("录音结束,返回值%d", mResult);
system("exit");

}
void PrintSign()
{
for (i = 0; i < audioSec; i++)
{
Sleep(1000);
count++;
system(“CLS”);
printf(“正在录音,%ds…\n”, i + 1);
}

if (count == audioSec)
{
	Sleep(1000);
	MMRESULT mResult;
	printf("时间已到,已停止录音,文件已保存到当前路径下!\n");
	stop();
	//printf("STOP函数已经运行!");
	//system("PAUSE");
}

}
void WaveForMatexInit(LPWAVEFORMATEX myWaveFormate, WORD nch, DWORD nSampleRate, WORD BitsPerSample, char* getFileName, char* filename2)
{

//printf("1\n");
f = fopen(getFileName, "wb");
//f = fopen("mic0.pcm", "wb");
//f2 = fopen("ref0.pcm", "wb");

#if 1
//printf(“2\n”);
if (f == NULL)
{
perror(“fopen”);

	//return 1;
}
else
{
	f2 = fopen(filename2, "wb");
}

#endif
myWaveFormate->wFormatTag = WAVE_FORMAT_PCM;
//myWaveFormate->wFormatTag = WAVE_FORMAT_2M16;
//myWaveFormate->wFormatTag = 0x0006;
myWaveFormate->nChannels = nch;
myWaveFormate->nSamplesPerSec = nSampleRate;
myWaveFormate->wBitsPerSample = BitsPerSample;
myWaveFormate->cbSize = sizeof(WAVEFORMATEX);
//myWaveFormate->cbSize = 0;
myWaveFormate->nAvgBytesPerSec = nSampleRate * nch * BitsPerSample / 8;
myWaveFormate->nBlockAlign = myWaveFormate->nChannels * BitsPerSample / 8;
}

static short mic0[256] = { 0 };
static short ref0[256] = { 0 };

DWORD CALLBACK MicCallback(HWAVEIN hwavein, UINT uMsg, DWORD dwInstance, DWORD dwParamOne, DWORD dwParamTwo)
{
short* p_data = NULL;
switch (uMsg)
{
case WIM_OPEN:
printf(“The Device is already open!\n”);
break;
case WIM_DATA:
//fwrite((void*)((WAVEHDR*)dwParamOne)->lpData, 2 * i, 1, f);
//fwrite((void*)((WAVEHDR*)dwParamOne)->lpData, 2 * i + 1, 1, f2);
// short* p_data = (short )buffer[1024 bytes];
p_data = (short
)(((WAVEHDR*)dwParamOne)->lpData);
//printf(“1:%p\n”, p_data);
//printf(“2:%p\n”, ((WAVEHDR*)dwParamOne)->lpData);
for (int j = 0; j < 256; j++) {
mic0[j] = p_data[2 * j];
ref0[j] = p_data[2 * j + 1];
}
fwrite(mic0, 256, 2, f);
fwrite(ref0, 256, 2, f2);

	//fwrite((void*)((WAVEHDR*)dwParamOne)->lpData, 1024, 1, f2);
	waveInAddBuffer(hwavein, (LPWAVEHDR)dwParamOne, sizeof(WAVEHDR));
	break;
case WIM_CLOSE:
	printf("The Device is already close!\n");
	break;
default:
	break;
}
return 0;

}
void AudioControl()
{
inputSec();
//获得系统中就绪的波形声音输入设备的数量
int num = waveInGetNumDevs();
printf(“系统声音输入设备数量:%d\n”, num);

MMRESULT mResult = waveInGetDevCaps(inputDevice, &waveincaps, sizeof(WAVEINCAPS));

if (mResult == MMSYSERR_NOERROR)
{
	printf("音频输入设备PID:%d\n", waveincaps.wPid);
	printf("音频输入设备wMID:%d\n", waveincaps.wMid);
	printf("该设备支持的声道数(waveincaps.wChannels):%d\n", waveincaps.wChannels);
	printf("音频输入设备支持的格式:%d\n", waveincaps.dwFormats);
	WaveForMatexInit(&pwfx, inputChannel, inputSample, inputBits, generateAudioFileName1, generateAudioFileName2);
	mResult = waveInOpen(&phwi, WAVE_MAPPER, &pwfx, (DWORD_PTR)(MicCallback), NULL, CALLBACK_FUNCTION);
	if (mResult == MMSYSERR_NOERROR)
	{
		pwhOne.lpData = bufferOne;
		pwhOne.dwBufferLength = 1024;
		pwhOne.dwUser = 1;//用户数据
		pwhOne.dwFlags = 0;//提供缓冲区标示
		//为音频输入设备准备一个缓冲区
		mResult = waveInPrepareHeader(phwi, &pwhOne, sizeof(WAVEHDR));
		if (mResult == MMSYSERR_NOERROR)
		{
			pwhTwo.lpData = bufferTwo;
			pwhTwo.dwBufferLength = 1024;
			pwhTwo.dwUser = 1;
			pwhTwo.dwFlags = 0;
			mResult = waveInPrepareHeader(phwi, &pwhTwo, sizeof(WAVEHDR));
			if (mResult == MMSYSERR_NOERROR)
			{
				mResult = waveInAddBuffer(phwi, &pwhOne, sizeof(WAVEHDR));
				if (mResult == MMSYSERR_NOERROR)
				{
					mResult = waveInAddBuffer(phwi, &pwhTwo, sizeof(WAVEHDR));
					if (mResult == MMSYSERR_NOERROR)
					{
						printf("1秒后开始录音!\n", audioSec);
						//Sleep(1000);
						mResult = waveInStart(phwi);
						PrintSign();
					}
				}
			}
		}
	}
}
else
{
	system("CLS");
	printf("!!!!输入的设备有误,无法打开!!!!");
	Sleep(2000);
	return;
}

}

#playPCM.h

#include <stdio.h>
#include <conio.h>
#include <Windows.h>
#include"record.h"
#pragma comment(lib, “winmm.lib”)

#define DATASIZE 102432
FILE
pcmfile;
HWAVEOUT hwo;
int cnt;
WAVEHDR wh1;
//WAVEHDR wh2;
WAVEFORMATEX wfx = { 0 };
int outSec = 0;
int outCount = 0;

void CALLBACK WaveCallback(HWAVEOUT hWave, UINT uMsg, DWORD dwInstance, DWORD paramOne, DWORD paramTwo)//回调函数
{
switch (uMsg)
{
case WOM_OPEN:
printf(“开始播放…\n”);
break;
case WOM_DONE:
{
LPWAVEHDR pWaveHeader = (LPWAVEHDR)paramOne;
pWaveHeader->dwBufferLength = fread(pWaveHeader->lpData, 1, DATASIZE, pcmfile);
if (pWaveHeader->dwBufferLength == 0)
{
break;
}
printf(“WOM_DONE %d\n”, pWaveHeader->dwBufferLength);
waveOutPrepareHeader(hwo, pWaveHeader, sizeof(WAVEHDR));
waveOutWrite(hwo, pWaveHeader, sizeof(WAVEHDR));

	printf("WOM_DONE\n");
	break;
}
case WOM_CLOSE:
	printf("播放已完成!\n");
}

}

void play(char* filename)
{
//printf(“请输入你要播放的时间(单位/s):”);
//scanf(“%d”, &outSec);
//FILE* pcmfile;
char pathName[100] = “D:\Workspace_VS\2022\audioAPI\pcmfile\”;
//char finallyName[100];
strcat(pathName, filename);
Sleep(1000);
printf(“当前文件路径为:%s\n”, pathName);
pcmfile = fopen(pathName, “rb”);
if (pcmfile == NULL)
{
printf(“%s文件打开失败!\n”, filename);
//Sleep(1000);
system(“PAUSE”);
return;

}
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nChannels = 2;
wfx.nSamplesPerSec = 16000;
wfx.wBitsPerSample = 16;
wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;
wfx.nBlockAlign = wfx.nChannels * wfx.wBitsPerSample / 8;
wfx.cbSize = 0;
waveOutOpen(&hwo, WAVE_MAPPER, &wfx, (DWORD)WaveCallback, 0L, CALLBACK_FUNCTION);

wh1.dwLoops = 0L;
wh1.lpData = new char[DATASIZE];
wh1.dwBufferLength = DATASIZE;
fread(wh1.lpData, 1, DATASIZE, pcmfile);
wh1.dwFlags = 0L;
MMRESULT mResult;
mResult = waveOutPrepareHeader(hwo, &wh1, sizeof(WAVEHDR));
if (mResult == MMSYSERR_NOERROR)
{
	//printf("mResult=%d!", mResult);
	mResult = waveOutWrite(hwo, &wh1, sizeof(WAVEHDR));
	//AudioControl();
	//printf("mResult=%d!", mResult);
	while (wh1.dwBufferLength != 0)
	{
		Sleep(500);
	}
	//Sleep(2000);
	mResult = waveOutUnprepareHeader(hwo, &wh1, sizeof(WAVEHDR));
	//printf("mResult=%d!", mResult);
	mResult = waveOutClose(hwo);
	//printf("mResult=%d!", mResult);
	delete[]wh1.lpData;
	fclose(pcmfile);

	//printf("OVER!");
	//_getch();
	Sleep(2000);
	//udgeOutTime();
}
//waveOutWrite(hwo, &wh1, sizeof(WAVEHDR));
return;

}

#findPCM.h
#include <stdio.h>
#include<io.h>

void findPcm()
{
/struct _finddata_t{
unsigned int attrib; //记录文件属性(隐藏、文件夹、只读等)
time_t time_create; //文件创建时间
time_t time_access; //文件最后被访问时间
time_t time_write; //文件最后被修改时间
_fsile_t size; //文件大小
char name[_MAX_FNAME]; //文件名
};
/

//文件存信息结构体 
struct _finddata_t file;
//保存文件句柄 
long handl;
int count = 0;

//long _findfirst(char * filespec , struct _finddata_t * fileinfo);
if ((handl = _findfirst("D:\\Workspace_VS\\2022\\audioAPI\\pcmfile\\*.pcm", &file)) == -1)
{
    printf("当前目录没有PCM文件\n");
}
else {
    do {
        count++;
        printf("*********************************\n");
        printf("第%d个文件:%s,文件大小:%d\n",count, file.name, file.size);
        Sleep(1000);
        play(file.name);
        printf("第%d个文件:%s播放结束!\n", count, file.name);
        Sleep(1000);
    } while (_findnext(handl, &file) == 0);//int _findnext( long handle, struct _finddata_t *fileinfo );
}
_findclose(handl);
printf("\n播放结束,该目录下共有%d文件!\n", count);
//stop();

}

主函数(audioAdmin.cpp)
#include<Windows.h>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<mmsystem.h>
#include “mmsystem.h”
#include “playPCM.h”
#include “findPCM.h”
#pragma comment(lib, “winmm.lib”)

//FILE* f = NULL;
//int count = 0;
char filename[50];
//Wav格式说明RIFF、FORMATE、DATA
//https://blog.youkuaiyun.com/weixin_48680270/article/details/123523517?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165830013416782425193967%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=165830013416782425193967&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_ecpm_v1~times_rank-3-123523517-null-null.142v32pc_search_v2,185v2control&utm_term=wav%E6%A0%BC%E5%BC%8F&spm=1018.2226.3001.4187
typedef struct {
char id[4];
unsigned long size;
char type[4];
}MYWAVERIFF;

typedef struct {
char id[4];
unsigned long size;
unsigned short audioFormat;
unsigned short numChannels;
unsigned long sampleRate;
unsigned long byteRate;
unsigned short blockAlign;
unsigned short bitsPerSample;
}MYWAVEFORMATE;

typedef struct {
char id[4];
unsigned long size;
}MYWAVEDATA;

long getSize()
{
FILE* f;
long size;
f = fopen(“audio.pcm”, “r”);
if (f == NULL)
{
printf(“文件打开失败!”);
}
fseek(f, 0, SEEK_END);
size = ftell(f);
printf(“源文件长度为:%d\n”, size);
fclose(f);
return size;
}

void convertWav(int channels, unsigned long sampleRate, int sampleBit)
{
MYWAVERIFF pcmRIFF;
MYWAVEFORMATE pcmFORMATE;
MYWAVEDATA pcmDATA;
FILE* f, * fpout;
long fileSize;
f = fopen(“audio.pcm”, “rb”);
if (f == NULL)
{
printf(“源文件打开失败!”);
return;
}
fpout = fopen(“audio.wav”, “wb”);
if (fpout == NULL)
{
printf(“文件打开错误!”);
return;
}
fileSize = getSize();
/*函数原型
void memcpy(void destin, void source, unsigned n);
参数
destin-- 指向用于存储复制内容的目标数组,类型强制转换为 void
指针。
source-- 指向要复制的数据源,类型强制转换为 void
指针。
n-- 要被复制的字节数。
/
memcpy(pcmRIFF.id, “RIFF”, strlen(“RIFF”));
pcmRIFF.size = 36 + fileSize;
memcpy(pcmRIFF.type, “WAVE”, strlen(“WAVE”));

//fseek(fpout, sizeof(MYWAVERIFF), SEEK_CUR);

int nriff = fwrite(&pcmRIFF, sizeof(pcmRIFF), 1, fpout);
printf("NRIFF: %d\n", nriff);

pcmFORMATE.numChannels = inputChannel;
pcmFORMATE.sampleRate = inputSample;
pcmFORMATE.bitsPerSample = inputBits;
pcmFORMATE.byteRate = inputSample * inputChannel * inputBits / 8;
pcmFORMATE.blockAlign = inputChannel * inputBits / 8;
pcmFORMATE.size = 16;
pcmFORMATE.audioFormat = WAVE_FORMAT_PCM; //the value is 1
memcpy(pcmFORMATE.id, "fmt", strlen("fmt "));

int nFormate = fwrite(&pcmFORMATE, sizeof(pcmFORMATE), 1, fpout);
printf("FORMATE: %d\n", nFormate);


memcpy(pcmDATA.id, "data", strlen("data"));
pcmDATA.size = fileSize;
int nData = fwrite(&pcmDATA, sizeof(pcmDATA), 1, fpout);
printf("DATA: %d\n", nData);
//system("PAUSE");

char* buffer = (char*)malloc(1024);
int ret;
while ((ret = fread(buffer, sizeof(char), 1024, f)) != 0)
{
	fwrite(buffer, sizeof(char), ret, fpout);
	printf("reading......\n");
}
free(buffer);

fclose(f);
fclose(fpout);
printf("转换完成!\n");

}

/*
void inputSec()
{

 int inputDevice, inputChannel, inputBits;
unsigned long inputSample;

printf("请输入预录音的文件名(需加后缀名):");
scanf("%s", generateAudioFileName);
printf("\n");
printf("请输入要录音的设备:");
scanf("%d", &inputDevice);
printf("\n");
printf("请输入录音通道数:");
scanf("%d", &inputChannel);
printf("\n");
printf("请输入录音的采样率:");
scanf("%ld", &inputSample);
printf("\n");
printf("请输入录音的采样位数:");
scanf("%d", &inputBits);
printf("\n");
printf("请输入你要录制该音频的时长(单位/s):");
int second;
scanf("%d", &second);
while (true)
{
	if (second <= 0 || second > 100)
	{
		printf("请按要求重新输入:");
		getchar();
		scanf("%d", &second);
	}
	else {
		break;
	}
}
audioSec = second;

}
*/
void playAudio()
{
//mciSendString()函数只能播放wav或mp3格式的音频
MMRESULT m = mciSendString(TEXT(“open yjm.mp3 alias bgm”), 0, 0, 0);
if (m == 0) {
printf(“正在播放Mp3的音频,按“p”暂停播放,“y”继续播放,“n”退出播放\n”);
m = mciSendString(TEXT(“play bgm”), NULL, 0, NULL);

	//m = mciSendString(TEXT("pause bgm"), NULL, 0, NULL);
	char isResume;
	char s;
	//s = getchar();
	//printf("已暂停播放, 继续播放请按“y”,退出请按“n”:");
	while (true)
	{
		scanf("%c", &isResume);
		switch (isResume)
		{
		case 'y':
			m = mciSendString(TEXT("resume bgm"), 0, 0, 0);
			printf("继续播放!\n");
			break;
		case 'p':
			mciSendString(TEXT("pause bgm"), 0, 0, 0);
			printf("暂停播放!\n");
			break;
		case 'n':
			mciSendString(TEXT("close bgm"), 0, 0, 0);
			break;
			//system("EXIT");
		default:
			break;
		}
		if (isResume == 'n')
		{
			break;
		}
	}
}
else
{
	printf("打开文件失败,错误码:%x", m);
	Sleep(2000);
}
system("CLS");
getchar();

}

void menu()
{
printf(“基于WASAPI的音频系统\n”);
printf(“\n”);
printf(“1、录制音频\n”);
printf(“\n”);
printf(“2、播放PCM音频\n”);
printf(“\n”);
printf(“3、播放Mp3音频\n”);
printf(“\n”);
printf(“****4、文件格式转换\n”);
printf(“\n”);
printf("***5、多PCM文件播放\n");
printf(“\n”);
printf(“6、退出系统\n”);
//printf(“\n注(按“a”开始录音,“t”退出系统,“s”播放Mp3音频,“p”播放PCM音频,“c”格式转换)\n”);
}
void main(int argc, const char
argv[])
{

/*
printf("argc:%d\n", argc);
printf("argv:%s\n", argv[1]);//拿到播放列表的文件名

char* play_list = (char *)argv[1];
FILE* fp_play = fopen(play_list, "rb");
char buf[32];//获取这列表要播放的音频文件
fgets(buf, 32, fp_play);//readline
printf("读取的第一个文件为:%s\n", buf);
char str_pilt[4];
int ste_len = strlen(buf);//7
int fileLen = ste_len - 6;
strncpy(str_pilt, buf + fileLen + 1, 3);
//strncpy(audioName, buffer, fileLen);
str_pilt[3] = '\0';
printf("提取后的字符为:%s\n", str_pilt);

if (strcmp(str_pilt, "wav") == 0) {
	//调用wav播放接口
}
else if (strcmp(str_pilt, "pcm") == 0) {
	//调用pcm播放接口
}
else if (strcmp(str_pilt, "mp3") == 0) {
	//调用mp3播放接口
}
*/



int a, b;
bool flag = FALSE;


while (1)
{
	menu();
	scanf("%d", &a);
	switch (int(a))
	{
	case 1:
		system("CLS");
		Sleep(250);
		printf("开始录制音频!\n");
		AudioControl();
		Sleep(2000);
		system("CLS");
		break;
	case 4:
		system("CLS");
		printf("正在将pcm格式音频转为wav格式!\n");
		convertWav(inputChannel, inputSample, inputBits);
		Sleep(1000);
		system("CLS");
		break;
	case 6:
		system("CLS");
		printf("退出系统!\n");
		break;
	case 3:
		system("CLS");
		playAudio();
		system("CLS");
		break;
	case 2:
		system("CLS");
		printf("请输入要播放的文件名:");
		scanf("%s", filename);
		play(filename);
		printf("播放结束!");
		system("CLS");
		break;
	case 5:
		system("CLS");
		findPcm();
		Sleep(2000);
		system("CLS");
		break;
	default:
		printf("输入有误,请按要求重新输入!");
		Sleep(1000);
		getchar();
		system("CLS");
		break;
	}
	if ((int)a == 6)
	{
		break;
		flag = true;
	}
}
if (flag == true)
{
	system("EXIT");
}

}

WASAPI (Windows Audio Session API) 的独占模式意味着音频设备只允许一个应用程序完全控制它,其他同时运行的应用程序将无法访问该设备。如果需要改为共享模式,通常是为了让多个应用程序能同时使用音频资源,可以采取以下步骤: 1. **检测支持**: 首先,确认系统和音频设备是否支持WASAPI共享。有些设备或系统默认就是共享模式。 2. **设置音频设备**: 在编程中,你需要明确指定打开音频流时使用共享模式。例如,在C++中使用DirectX SDK,你可以通过`IMMDeviceEnumerator::GetDefaultAudioEndpoint(eCapture, eConsole)`获取默认的录音端点,然后设置其属性为共享: ```cpp CoCreateInstance(__uuidof(MmDeviceEnumerator), nullptr, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (LPVOID*)&deviceEnumerator); COMMTIMEFORMAT format; format.nChannels = 2; format.wBitsPerSample = 16; // 设置共享模式 IMMDevice* audioEndpoint = deviceEnumerator->GetDefaultAudioEndpoint(eCapture, eConsole); audioEndpoint->SetProperty(__uuidof(IAudioEndpointVolume), reinterpret_cast< PROPVARIANT*>(&volumeProperties)); ``` 这里`volumeProperties`应包含`AM_MEDIA_TYPE`结构,其中`mFormat.dwChannelMask`应该表示立体声共享模式。 3. **同步访问**: 如果有多个线程需要共享设备,需要保证同步访问以避免数据混乱。使用`CriticalSection`、信号量或其他同步机制。 4. **权限管理**: 确保每个应用程序有足够的权限操作共享的音频设备。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值