⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 musicplay.cpp

📁 一个基于VC++的音乐播放功能的程序代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/******************************************************************************
 * 文件名:player.cpp
 * 说明  :根据摄像头拍摄的人体动作来演奏音乐
 * Modified by PRTsinghua@hotmail.com
******************************************************************************/

#include "stdafx.h"
#include "MusicPlay.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


#include <windows.h>
#include <dshow.h>
#include <stdio.h>
#include <conio.h>
#include <qedit.h>	// SampleGrabber用
#include <math.h>
#include <windowsx.h>
#include <mmsystem.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <ctype.h>

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

#undef  M_PI
#define M_PI 3.1415926535897932
#define HUGE 

#define MAX_FILENAME_SIZE   128

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

#define x_size 160
#define y_size 120
#define MAX_CNTR 10000
#define GRAY 128
#define PI 3.14159

// 图像结构
typedef struct{				
	HINSTANCE			hi;
	HWND				hwnd;		// 自己的窗口操作
	BYTE				*lpBmpData;	// BMP数据
	BITMAPINFOHEADER	bih;		// 位图信息
} IMG0;

// WAVE结构
typedef struct waveInst {
	HANDLE hWaveInst;
	HANDLE hWaveHdr;
	HANDLE hWaveData;
} WAVEINST;

typedef WAVEINST FAR *LPWAVEINST;

// 全局变量和函数
int NumDevsOut;
WORD Version;
char		szAppName[]		= "oscillat";	// 应用名
HINSTANCE	hInstApp		= NULL;			// 起动操作
HWND		hwndApp			= NULL;			// 主要窗口的操作
HWND		hwndChild[7]	= {NULL};		// 文件名窗口的操作
HWAVEOUT	hWaveOut		= NULL;
LPWAVEHDR	lpWaveHdr		= NULL;
int		tate;
int		yoko;
int		scale = 1;
long	rec_freq = 44100L;
short	rec_bits = 8;
long	sec = 5;
char	buf[256];
#define	HANON (1.05946309435929526)

DWORD	th_Proc0( void );
LRESULT	CALLBACK grProc0( HWND, UINT, WPARAM, LPARAM );
DWORD	th_Proc1( void );
LRESULT	CALLBACK grProc1( HWND, UINT, WPARAM, LPARAM );

BOOL	initVideo(void);
void	closeVideo(void);
void	initGraphic(void);
void	closeGraphic(void);
void	closeVideo(void);
void	initWindow0(void);
void	initWindow1(void);
void	openWindow0(void);
void	openWindow1(void);
void	masuku(BYTE *);
int		obtain_contour(int x_start, int y_start, unsigned char image[y_size][x_size]);
int		remove_areas(BYTE *);
void	haikei(BYTE *pRGB, BYTE *pRGB0, BYTE *pRGB1); 
void	HSV(double *H, double *S, double *V, double B, double G, double R);
int		remove_areas2(void);

void cleanup(LPWAVEINST lpWaveInst);
void oscillatPlay(int, double);
void oscillatStop(void);
void makedata(DWORD dwDataSize, int pattern, double freq, unsigned char HUGE * lpData);

ICreateDevEnum	*pDevEnum	= NULL;
IGraphBuilder	*pGraph		= NULL;
IMediaControl	*pMC		= NULL;
ICaptureGraphBuilder2	*pCapture = NULL;
IBaseFilter		*pF			= NULL;
ISampleGrabber	*pGrab		= NULL;		// 以上这些变量最后要释放

IMG0	img00, img01;

unsigned char image1[y_size][x_size];
unsigned char image3[y_size][x_size];
unsigned char line[x_size*y_size*3];
int chain_code[MAX_CNTR];
int Freeman[8][2] = 
	{
		{1,0}, {1,-1}, {0,-1}, {-1,-1}, 
		{-1,0}, {-1,1}, {0,1}, {1,1}
	};
int ch_x[2];
int ch_y[2];
int check;
double Z;
int onkai = 0;

CWinApp theApp;

using namespace std;


// 主函数
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
	int nRetCode = 0;

	// 初始化MFC
	if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
	{
		cerr << _T("Fatal Error: MFC initialization failed") << endl;
		nRetCode = 1;
		return nRetCode;
	}
	
	int		X_SIZE, Y_SIZE;
	BYTE	*pRGB0, *pRGB1;
	HRESULT	hr;

	initVideo();	// 视频的初期化
	initGraphic();	// 图像画面的初期化
	initWindow0();	// 视频画面表示的Window的初期化
	initWindow1(); 	// 图像画面表示的Widow的初期化

	printf( "图像输入开始,请按任意键\n" ); 
	getch();
	printf( "图像输入已经开始了,暂时停止 -- q\n" ); 

	// ---- 图像输入开始 ----
	// 制作表示窗口
	openWindow0();
	openWindow1();

	pGrab -> SetBufferSamples(TRUE);	// 开始grab
 	pMC -> Run();						// 开始rendering

	// ***********  追加  ******************
	BYTE *pRGB, *pRGB2;
	Sleep(1000);
	
	printf("记录初期背景图像,按任意键\n");
	getch();
	
	long n = img00.bih.biSizeImage;
	pRGB = (BYTE *)malloc(n);	// pRGB 初期背景图像的排列
	pRGB2 = (BYTE *)malloc(n);	// pRGB 初期背景图像的排列
	if (pRGB == NULL) 
	{
		printf("内存不足(pRGB)\n");
	}
	
	hr = pGrab -> GetCurrentBuffer( &n, (long *)pRGB );
	
	// ********** 到这里为止 ******************

	while(1)
	{
	 	long n = img00.bih.biSizeImage;
		hr = pGrab -> GetCurrentBuffer( &n, (long *)img00.lpBmpData );

		pRGB0	= img00.lpBmpData;
		pRGB1	= img01.lpBmpData;
		X_SIZE	= img00.bih.biWidth;
		Y_SIZE	= img00.bih.biHeight;

		// pRGB0 视频图像的图像排列
		// pRGB1 进行图像处理后的图像的排列
		// 数据的格式,沿着从下到上的方向。
		// 按BGR的顺序排列

		haikei(pRGB, pRGB0, pRGB1);
		masuku(pRGB1);
		remove_areas(pRGB1);

		InvalidateRect( img00.hwnd, NULL, FALSE);	// 输入画像窗口的更新
		InvalidateRect( img01.hwnd, NULL, FALSE);	// 画像窗口的更新

		if( kbhit() )
		{
			getch();
			hr = pMC -> Pause();
			printf("grab停止:结束 - q  、再次打开 - 别的键\n");
			if(getch() == 'q')
				break;
			pMC -> Run();
		}
	}
	
	pMC -> Stop();
	pGrab -> SetBufferSamples( 0 );
	// ---- 结束操作 ---- 
	
	oscillatStop();
	
	closeVideo();
	closeGraphic();

	SendMessage( img00.hwnd, WM_CLOSE, 0, 0 );	// 图像输入窗口结束
	SendMessage( img01.hwnd, WM_CLOSE, 0, 0 );	// 图像表示窗口结束

	return 0;
}


/******************************************************************************
 * 源图像窗口的创建与消息循环
******************************************************************************/
DWORD th_Proc0( void )
{
	MSG msg;

	int sm0 = GetSystemMetrics( SM_CYCAPTION );
	int sm1 = GetSystemMetrics( SM_CXDLGFRAME ); // WS_OVRELAPP的时候,框子的宽度
	int sm2 = GetSystemMetrics( SM_CYDLGFRAME ); // 变成了SM_CYDLGFRAME
	// 创建窗口
	img00.hwnd = CreateWindow( "GRC0",			// 组的名字
				"Source Image",
				WS_OVERLAPPED | WS_VISIBLE,		// 窗口的属性
				0, 100,							// 表示的位置
				img00.bih.biWidth  + sm1 * 2,	// 描绘大小,计算大小
				img00.bih.biHeight + sm0 + sm2 * 2,
				HWND_DESKTOP,
				NULL, img00.hi, NULL 	     );					

	while( GetMessage( &msg, NULL, 0, 0 ) )
	{
		TranslateMessage( &msg );
		DispatchMessage( &msg );
	}

	return 0;
}


/******************************************************************************
 * 处理后图像窗口的创建与消息循环
******************************************************************************/
DWORD th_Proc1( void )
{
	MSG msg;

	int sm0 = GetSystemMetrics( SM_CYCAPTION );
	int sm1 = GetSystemMetrics( SM_CXDLGFRAME ); // WS_OVRELAPP的时候,框子的宽度
	int sm2 = GetSystemMetrics( SM_CYDLGFRAME ); // 变成了SM_CYDLGFRAME
	// 创建窗口
	img01.hwnd = CreateWindow( "GRC1",			// 小组的名字
				"Result Image",
				WS_OVERLAPPED | WS_VISIBLE,		// 窗口的属性
				0, 400,							// 表示的位置
				img01.bih.biWidth  + sm1 * 2,	// 描绘大小 计算大小
				img01.bih.biHeight + sm0 + sm2 * 2,
				HWND_DESKTOP,						
				NULL, img01.hi, NULL 	     );					

	while( GetMessage( &msg, NULL, 0, 0 ) )
	{
		TranslateMessage( &msg );
		DispatchMessage( &msg );
	}

	return 0;
}


/******************************************************************************
 * 窗口的取得,仅仅在再一次的描绘中进行
******************************************************************************/
LRESULT CALLBACK grProc0( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
{
				
	PAINTSTRUCT	ps;

    switch (msg)
	{
	case WM_PAINT:							// 描绘位图
		BeginPaint( hwnd, &ps );
		SetDIBitsToDevice( ps.hdc, 0, 0,	// 复制刚才x,y的坐标
					img00.bih.biWidth,		// DIB的宽度
					img00.bih.biHeight,		// DIB的高度
					0, 0,					// DIB的坐标 
					0,						// 扫描线
					img00.bih.biHeight,		// 扫描线的数量
					img00.lpBmpData,
					(BITMAPINFO *)&( img00.bih),	// 分派到BITMAPINFO
					DIB_RGB_COLORS );
        EndPaint( hwnd, &ps );
		return 0;

	case WM_DESTROY:
		PostQuitMessage( 0 );				// 结束信息循环
		break;			

	default:
		return DefWindowProc( hwnd, msg, wp, lp );
	}
	
	return 0;	
}


/******************************************************************************
 * 窗口的取得,仅仅在再一次的描绘中进行
******************************************************************************/
LRESULT CALLBACK grProc1( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
{
				
	PAINTSTRUCT	ps;

    switch (msg)
	{
	case WM_PAINT:							// 描绘位图
		BeginPaint( hwnd, &ps );
		SetDIBitsToDevice( ps.hdc, 0, 0,	// 复制刚才x,y的坐标
					img01.bih.biWidth,		// DIB的宽度
					img01.bih.biHeight,		// DIB的高度
					0, 0,					// DIB的坐标 
					0,						// 扫描线
					img01.bih.biHeight,		// 扫描线的数量
					img01.lpBmpData,
					(BITMAPINFO *)&( img01.bih),	// 分派到BITMAPINFO
					DIB_RGB_COLORS );
        EndPaint( hwnd, &ps );
		return 0;

	case WM_DESTROY:
		PostQuitMessage( 0 );				// 结束信息循环
		break;			

	default:
		return DefWindowProc( hwnd, msg, wp, lp );
	}
	return 0;
	
}


/******************************************************************************
 * 初始化Video
******************************************************************************/
BOOL initVideo(void)
{
	AM_MEDIA_TYPE   amt;

	CoInitialize(NULL);		// COM的初期化

	// ---- 输入计算的准备 ----

	// 搜索输入设备
	IBaseFilter  *pbf = NULL;
	IMoniker * pMoniker = NULL;
    ULONG cFetched;
    
	// 创建输入设备的各个部分
    CoCreateInstance( CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC,
					  IID_ICreateDevEnum, (void ** ) &pDevEnum);

    // 设置视频输入设备的各个部分
    IEnumMoniker * pClassEnum = NULL;
    pDevEnum -> CreateClassEnumerator(
					CLSID_VideoInputDeviceCategory, &pClassEnum, 0);
    
	if (pClassEnum == NULL)
	{
		AfxMessageBox("没有发现摄像头,程序将退出!");
		pDevEnum -> Release();
		CoUninitialize();

        return FALSE ;
    }
 
	// 取得最初发现的视频输入设备object的接口
    pClassEnum -> Next(1, &pMoniker, &cFetched);
	pMoniker->BindToObject( 0, 0, IID_IBaseFilter, (void**)&pbf );
 	
	// ---- 过虑图像的准备 ----
    // 创建过虑图像,取得接口
    CoCreateInstance( CLSID_FilterGraph, NULL, CLSCTX_INPROC,
					  IID_IGraphBuilder, (void **) &pGraph);
    pGraph -> QueryInterface( IID_IMediaControl, (LPVOID *) &pMC );
	// 把输入图像追加到过虑图像
    pGraph -> AddFilter( pbf, L"Video Capture");
	// 因为进行了追加所以解除参照的输入图像
    pbf -> Release();

	// ---- 过虑图像的准备 ----
    // 创建过虑图像,取得接口
	CoCreateInstance( CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, 
                      IID_IBaseFilter, (LPVOID *)&pF);
	pF -> QueryInterface( IID_ISampleGrabber, (void **)&pGrab );
	// 把输入图像追加到过虑图像
	ZeroMemory(&amt, sizeof(AM_MEDIA_TYPE));
	amt.majortype  = MEDIATYPE_Video;
	amt.subtype    = MEDIASUBTYPE_RGB24;
	amt.formattype = FORMAT_VideoInfo; 
	pGrab -> SetMediaType( &amt );
	// 把grubber过虑追加到过虑图像
	pGraph -> AddFilter(pF, L"SamGra");

	// ---- 输入图像的准备 ----
	// 创建输入图像   
	CoCreateInstance( CLSID_CaptureGraphBuilder2 , NULL, CLSCTX_INPROC,
				      IID_ICaptureGraphBuilder2, (void **) &pCapture );
    // 把过虑图像编入到输入图像
    pCapture -> SetFiltergraph( pGraph );
    // 输入图像的设定,设定grubber为rendering输出
    pCapture -> RenderStream (&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,
                                pbf, NULL, pF);
  
	// ---- 表示窗口的准备 ----
	// 位图信息的取得	
	pGrab -> GetConnectedMediaType( &amt ); 
	// 获得视频头部的信息
	VIDEOINFOHEADER *pVideoHeader = (VIDEOINFOHEADER*)amt.pbFormat;
	// 在视频的头部包含位图的信息
	// 把位图的信息复制到BITMAPINFO的结构体中
	BITMAPINFO BitmapInfo;
	ZeroMemory( &BitmapInfo, sizeof(BitmapInfo) );
	CopyMemory( &BitmapInfo.bmiHeader, &(pVideoHeader->bmiHeader), 
				sizeof(BITMAPINFOHEADER));

	img00.bih = BitmapInfo.bmiHeader;
 	long n = img00.bih.biSizeImage;
	
	char s[100];
	sprintf(s, "Video Width: %ld  Video Height: %ld", 
				img00.bih.biWidth, img00.bih.biHeight);
	AfxMessageBox(s);
	
	img00.lpBmpData = (BYTE *)malloc( n );
	
	// ************* 追加 *****************

	if (img00.lpBmpData == NULL) {
		AfxMessageBox("内存不足!");
	}
	
	img00.hi = (HINSTANCE)GetWindowLong( HWND_DESKTOP, GWL_HINSTANCE );
	return true;
}


/******************************************************************************
 * 初始化Graphics
******************************************************************************/
void initGraphic(void)
{
	// 把位图的信息复制到BITMAPINFO的结构体中
	BITMAPINFO BitmapInfo;
	ZeroMemory( &BitmapInfo, sizeof(BitmapInfo) );
	CopyMemory( &BitmapInfo.bmiHeader, &img00.bih, 
				sizeof(BITMAPINFOHEADER));
	img01.bih = BitmapInfo.bmiHeader;
 	long n = img01.bih.biSizeImage;

	img01.lpBmpData = (BYTE *)malloc( n );
	
	// **************** 追加 ******************

	if (img01.lpBmpData == NULL) {
		printf("内存不足 (img01.lpBmpData)\n");
	}

	img01.hi = (HINSTANCE)GetWindowLong( HWND_DESKTOP, GWL_HINSTANCE );
}


/******************************************************************************
 * 关闭Video
******************************************************************************/
void closeVideo(void)
{
    // 接口的解除
    pMC -> Release();		
	pDevEnum -> Release();
    pGraph -> Release();
    pCapture -> Release();
	
	CoUninitialize();

	free( img00.lpBmpData );
}


/******************************************************************************
 * 关闭Graphic
******************************************************************************/
void closeGraphic(void)
{
	free( img01.lpBmpData );
}


/******************************************************************************
 * 初始化窗口0
******************************************************************************/
void initWindow0(void)
{
	// 表示窗口的定义
	WNDCLASSEX	wc;							// 新做成的窗口组
	memset( &wc, 0, sizeof(WNDCLASSEX) );
	wc.cbSize        = sizeof(WNDCLASSEX);	
	wc.lpfnWndProc   = grProc0;				// 取得持有这个组的窗口
	wc.hInstance     = (HINSTANCE)GetWindowLong( HWND_DESKTOP, GWL_HINSTANCE ); 
	wc.lpszClassName = "GRC0";				// 这个组的名字
	wc.cbWndExtra    = 10;					// 确保相关的结构体的特点的范围
	RegisterClassEx( &wc );					// 窗口组的登记

}


/******************************************************************************
 * 初始化窗口1
******************************************************************************/
void initWindow1(void)
{
								// 表示窗口的定义
	WNDCLASSEX	wc;							// 新做成的窗口组
	memset( &wc, 0, sizeof(WNDCLASSEX) );
	wc.cbSize        = sizeof(WNDCLASSEX);	
	wc.lpfnWndProc   = grProc1;				// 取得持有这个组的窗口
	wc.hInstance     = (HINSTANCE)GetWindowLong( HWND_DESKTOP, GWL_HINSTANCE ); 
	wc.lpszClassName = "GRC1";				// 这个组的名字
	wc.cbWndExtra    = 10;					// 确保相关的结构体的特点的范围
	RegisterClassEx( &wc );					// 窗口组的登记
}


/******************************************************************************
 * 打开窗口0
******************************************************************************/
void openWindow0(void)
{
	DWORD tid;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -