C/C++ 实现录音和播放

#include <iostream>
#include <windows.h>
#include <Mmsystem.h>
#pragma comment(lib, "winmm.lib") 

static BYTE*    file = (BYTE*)malloc(sizeof(BYTE) * 512);
static DWORD    hasRecorded = 0;
static BOOL     recurr = TRUE;
class USER
{
public:
	int a = 0;
	char b = 'a';
};

void CALLBACK callback(HWAVEIN   hwi,          // 设备句柄
	UINT      uMsg,							   // 消息
	DWORD_PTR dwInstance,					   // 对象
	DWORD_PTR dwParam1,						   // 参数1
	DWORD_PTR dwParam2);					   // 参数2

int main()
{
	HWAVEIN         hWaveIn;		        //输入设备
	HWAVEOUT        hWaveOut;		        //输出设备
	WAVEFORMATEX    waveform;	            //定义音频流格式
	BYTE* pBuffer1, * pBuffer2;				//输入音频缓冲区(左右声道)
	WAVEHDR         whdr_i1, whdr_i2;       //输入音频头
	WAVEHDR         whdr_o;                //输出音频头
	USER*			user = new USER();		//定义用户
	
	// 设备数量
	int count = waveInGetNumDevs();
	printf("\n音频输入数量:%d\n", count);

	// 设备名称
	WAVEINCAPS waveIncaps;
	MMRESULT mmResult = waveInGetDevCaps(0, &waveIncaps, sizeof(WAVEINCAPS));//2
	std::cout <<"设备名称:"<< waveIncaps.szPname << std::endl;

	// 设置音频流格式
	waveform.nSamplesPerSec = 44100;												// 采样率
	waveform.wBitsPerSample = 16;												// 采样精度
	waveform.nChannels = 2;                                                     // 声道个数
	waveform.cbSize = 0;														// 额外空间	
	waveform.wFormatTag = WAVE_FORMAT_PCM;										// 音频格式
	waveform.nBlockAlign = (waveform.wBitsPerSample * waveform.nChannels) / 8;  // 块对齐
	waveform.nAvgBytesPerSec = waveform.nBlockAlign * waveform.nSamplesPerSec;  // 传输速率

	//分配内存
	pBuffer1 = new BYTE[1024 * 10000];
	pBuffer2 = new BYTE[1024 * 10000];
	memset(pBuffer1, 0, 1024 * 10000);   // 内存置0
	memset(pBuffer2, 0, 1024 * 10000);   // 内存置0

	// 设置音频头
	whdr_i1.lpData = (LPSTR)pBuffer1; // 指向buffer
	whdr_i1.dwBufferLength = 1024 * 10000;     // buffer大小
	whdr_i1.dwBytesRecorded = 0;      // buffer存放大小
	whdr_i1.dwUser = 0;
	whdr_i1.dwFlags = 0;
	whdr_i1.dwLoops = 1;
	whdr_i2.lpData = (LPSTR)pBuffer1; // 指向buffer
	whdr_i2.dwBufferLength = 1024 * 10000;     // buffer大小
	whdr_i2.dwBytesRecorded = 0;      // buffer存放大小
	whdr_i2.dwUser = 0;
	whdr_i2.dwFlags = 0;
	whdr_i2.dwLoops = 1;

	// 开启录音
	MMRESULT mRet = waveInOpen(&hWaveIn, WAVE_MAPPER, &waveform, (DWORD_PTR)callback, (DWORD_PTR)user, CALLBACK_FUNCTION);
	waveInPrepareHeader(hWaveIn, &whdr_i1, sizeof(WAVEHDR));//准备buffer
	waveInPrepareHeader(hWaveIn, &whdr_i2, sizeof(WAVEHDR));//准备buffer
	waveInAddBuffer(hWaveIn, &whdr_i1, sizeof(WAVEHDR));    //添加buffer
	waveInAddBuffer(hWaveIn, &whdr_i2, sizeof(WAVEHDR));    //添加buffer

	waveInStart(hWaveIn);
	getchar();
	recurr = FALSE;
	//waveInStop(hWaveIn);
   waveInReset(hWaveIn);
	waveInClose(hWaveIn);

	HANDLE wait = CreateEvent(NULL, 0, 0, NULL);
	waveOutOpen(&hWaveOut, WAVE_MAPPER, &waveform, (DWORD_PTR)wait, 0L, CALLBACK_EVENT);

	// 播放录音
	whdr_o.lpData = (LPSTR)file;			// 指向buffer
	whdr_o.dwBufferLength = hasRecorded;    // buffer大小
	whdr_o.dwBytesRecorded = hasRecorded;
	whdr_o.dwFlags = 0;
	whdr_o.dwLoops = 1;

	
	ResetEvent(wait);
	waveOutPrepareHeader(hWaveOut, &whdr_o, sizeof(WAVEHDR));
	waveOutWrite(hWaveOut, &whdr_o, sizeof(WAVEHDR));
	/*Sleep(5000);*/
	DWORD dw = WaitForSingleObject(wait, INFINITE);
	if (dw == WAIT_OBJECT_0)
	{
		std::cout << "jieshu" << std::endl;
		return 0;
	}
}



void CALLBACK callback(HWAVEIN   hwi,                              // 设备句柄
						UINT      uMsg,							   // 消息
						DWORD_PTR dwInstance,					   // 对象
						DWORD_PTR dwParam1,						   // 参数1
						DWORD_PTR dwParam2)						   // 参数2
{
	// 获取对象
	USER* user2 = (USER*)dwInstance;
	// 获取音频头
	PWAVEHDR  pwhdr = (PWAVEHDR)dwParam1;

	// 处理消息
	switch (uMsg)
	{
	case WIM_OPEN:                                 // 打开录音设备

		printf("成功打开设备..\n");
		break;

	case WIM_DATA:                                 // 缓冲区已满
	{
		printf("缓冲池已满..\n");
		printf("a:%d , b:%c \n",user2->a,user2->b);
		// 缓冲池信息
		DWORD buflen = pwhdr->dwBufferLength;
		DWORD bytrecd = pwhdr->dwBytesRecorded;
		hasRecorded += bytrecd;

		// 缓冲扩增
		file = (BYTE*)realloc(file, hasRecorded * sizeof(BYTE));
		// 存储新内容
		if (file)
		{
			memcpy(&file[hasRecorded-bytrecd], pwhdr->lpData, bytrecd);
			printf("已存储:%d byte\n",hasRecorded);
		}
		// 循环 	
		if (recurr)
		{
			// 加入缓存
			waveInAddBuffer(hwi, pwhdr, sizeof(WAVEHDR));
		}
	}
	break;

	case WIM_CLOSE:                               // 关闭录音设备
	{
		printf("停止录音..\n");
		
	}
	break;

	default:
		break;
	}
}

 

  • 6
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论
FFmpeg是一个开源的跨平台的音视频处理工具,提供了多种功能来实现音视频的录制和转码等操作。 在使用FFmpeg进行录音操作时,需要借助FFmpeg的音频处理库libavcodec和音频采集库libavdevice。 首先,我们需要打开一个音频输入设备,可以是麦克风、音频文件等。使用libavformat中的avformat_open_input函数打开音频输入设备,并设置相应的参数,如采样率、声道数和格式等。 接下来,创建一个AVCodecContext对象,用于编解码音频数据。可以使用libavcodec中的avcodec_find_encoder函数找到合适的音频编码器,然后通过avcodec_open2函数打开编码器,得到相应的AVCodecContext对象。 然后,我们需要创建一个AVPacket对象,用于存储音频数据。使用av_packet_alloc函数创建一个空的AVPacket对象。 接下来,进入一个循环中不断读取音频数据并进行编码。使用av_read_frame函数从音频输入设备读取音频数据,传入之前创建的AVPacket对象,将读取到的音频数据存储到AVPacket对象中。 然后,调用avcodec_send_packet函数将AVPacket对象的数据发送给编码器进行编码。再使用avcodec_receive_frame函数从编码器中接收编码后的音频数据。 最后,将编码后的音频数据写入到输出文件或者输出设备中。可以使用libavformat中的av_write_frame函数将音频数据写入到输出文件或者输出设备中。 最后,需要释放资源。关闭音频输入设备、释放AVFormatContext对象和AVPacket对象等。 通过以上的步骤,我们就可以使用FFmpeg的C语言接口实现音频录制的功能了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ephemeroptera

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值