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;
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章