Advertisement
xiahanlu

main.cpp

Jun 9th, 2018
340
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 64.63 KB | None | 0 0
  1. // =========================================================================================================================
  2. // 很简单的midi钢琴键盘程序, 使用DirectSDK和VC++写的, 需要 DirectX 9 SDK 9.0c June 2010
  3. // 写的太乱了, 以后有新想法可能会用 ATL重写一遍.
  4. // 原理就是根据用户按下的键, 索引出对应的调性和音阶内的音符
  5. // 按照 时值/力度/调性/阶内音符 的组合写入对应的midi消息 (这里力度没模拟, 或者说,模拟的很烂(?))...
  6. // 然后电脑就会反馈出具体的声音了.
  7. // 说白了就是按键->发消息..
  8. //
  9. // 可使用 至少三种midi合成端口
  10. // - midi映射, (128合成乐器)
  11. // - GS波表合成 (128合成乐器)
  12. // - DirectMusic强化合成器 (234种合成乐器)
  13. //
  14. // 键盘映射如下:
  15. // -----------------------------------------------------------------------------------------------------------------------
  16. // ZXCVBNM S D F G H - < LOW>
  17. // 1234567#1#2#4#5#6
  18. // QWERTYU 2 3 4 5 6 - < MID>
  19. // 1234567#1#2#4#5#6
  20. // IOP[]\E 9 0 - + B - < HIGH> E <- enter B <- backspace
  21. // 1234567#1#2#4#5#6
  22. // ----------------------------------------------------------------------------
  23. // 力反馈设置<试试看效果>.此设置用来模拟按键力度, 因为一般而言键盘是没办法返回按键力度的..
  24. // 上升沿, 也就是按键按下的时候到松开之前的这段过程.
  25. // 会给与一个初始力度的力值K. 此时按键如果一直处于按下状态会一直增加 K直到经过n个ticks 到达峰值MAX.
  26. // 下降沿, 也就是按键松开的时候, 这个时候要计算在上升沿时候实际经过的ticks跟n ticks的比值
  27. // 来跟预先设置的C ticks换算出降低到谷底需要的ticks, 到达0之后, 此时力程图链表项会被销毁, 一个力反馈键完成.
  28. // K, N, MAX, C 需要用户自行设置
  29. //
  30. // 调性键位 F1 - 中音基调性为1 (调性范围 -1 ~2) [note 0 ~ 35]
  31. // 调性键位 F2 - 中音基调性为2 (调性范围 0 ~3) [note 12 ~ 47]
  32. // 调性键位 F3 - 中音基调性为3 (调性范围 1 ~4) [note 24 ~ 59]
  33. // 调性键位 F4 - 中音基调性为4 (调性范围 2 ~5) [note 36 ~ 71]
  34. // 调性键位 F5 - 中音基调性为5 (调性范围 3 ~6) [note 48 ~ 83]
  35. // 调性键位 F6 - 中音基调性为6 (调性范围 4 ~7) [note 60 ~ 95]
  36. // 调性键位 F7 - 中音基调性为7 (调性范围 5 ~8) [note 72 ~ 95]
  37. // 调性键位 F8 - 中音基调性为8 (调性范围 6 ~8) [note 84 ~ 107]
  38. // 调性键位 F9 - 中音基调性为9 (调性范围 7 ~9) [note 96 ~ 119]
  39. // 调性键位 F10- 中音基调性为10(调性范围 8 ~10) [note 108 ~ 127] 为了兼容标准midi最大 note为127
  40. //
  41. // 支持七八种简单的, 如混响 3D的effect - 男的
  42. // =================================================================================================================
  43.  
  44. // 嵌入风格清单.
  45. # if defined (_M_IX86)
  46. # pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
  47. # elif defined (_M_IA64)
  48. # pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"")
  49. # elif defined (_M_X64)
  50. # pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
  51. # else
  52. # pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
  53. # endif
  54.  
  55. # include <windows.h>
  56. # include <windowsx.h>
  57. # include <d3d9.h>
  58. # include <d3dx9.h>
  59. # include <dinput.h>
  60. # include <assert.h>
  61. # include <tchar.h>
  62. # include <CommCtrl.h>
  63. # include <dmusicc.h>
  64. # include <dmusics.h>
  65. # include <dmusici.h>
  66. # include <dmusbuff.h>
  67. # include <ks.h>
  68. # include <vector>
  69. # include "resource.h"
  70.  
  71. // 杂项例子
  72. namespace CUtil {
  73. // windows 标准GS乐器指令集
  74. const TCHAR* std_instruments_set[]=
  75. {
  76. _T("1 Acoustic Grand Piano"),
  77. _T("2 Bright Acoustic Piano"),
  78. _T("3 Electric Grand Piano"),
  79. _T("4 Honky-tonk Piano"),
  80. _T("5 Electric Piano 1"),
  81. _T("6 Electric Piano 2"),
  82. _T("7 Harpsichord"),
  83. _T("8 Clavi"),
  84. _T("9 Celesta"),
  85. _T("10 Glockenspiel"),
  86. _T("11 Music Box"),
  87. _T("12 Vibraphone"),
  88. _T("13 Marimba"),
  89. _T("14 Xylophone"),
  90. _T("15 Tubular Bells"),
  91. _T("16 Dulcimer"),
  92. _T("17 Drawbar Organ"),
  93. _T("18 Percussive Organ"),
  94. _T("19 Rock Organ"),
  95. _T("20 Church Organ"),
  96. _T("21 Reed Organ"),
  97. _T("22 Accordion"),
  98. _T("23 Harmonica"),
  99. _T("24 Tango Accordion"),
  100. _T("2T5 Guitar (nylon)"),
  101. _T("26 Acoustic Guitar (steel)"),
  102. _T("27 Electric Guitar (jazz)"),
  103. _T("28 Electric Guitar (clean)"),
  104. _T("29 Electric Guitar (muted)"),
  105. _T("30 Overdriven Guitar"),
  106. _T("31 Distortion Guitar"),
  107. _T("32 Guitar Harmonics"),
  108. _T("33 Acoustic Bass"),
  109. _T("34 Electric Bass (finger)"),
  110. _T("35 Electric Bass (pick)"),
  111. _T("36 Fretless Bass"),
  112. _T("37 Slap Bass 1"),
  113. _T("38 Slap Bass 2"),
  114. _T("39 Synth Bass 1"),
  115. _T("40 Synth Bass 2"),
  116. _T("41 Violin"),
  117. _T("42 Viola"),
  118. _T("43 Cello"),
  119. _T("44 Contrabass"),
  120. _T("45 Tremolo Strings"),
  121. _T("46 Pizzicato Strings"),
  122. _T("47 Orchestral Harp"),
  123. _T("48 Timpani"),
  124. _T("49 String Ensemble 1"),
  125. _T("50 String Ensemble 2"),
  126. _T("51 SynthStrings 1"),
  127. _T("52 SynthStrings 2"),
  128. _T("53 Choir Aahs"),
  129. _T("54 Voice Oohs"),
  130. _T("55 Synth Voice"),
  131. _T("56 Orchestra Hit"),
  132. _T("57 Trumpet"),
  133. _T("58 Trombone"),
  134. _T("59 Tuba"),
  135. _T("60 Muted Trumpet"),
  136. _T("61 French Horn"),
  137. _T("62 Brass Section"),
  138. _T("63 SynthBrass 1"),
  139. _T("64 SynthBrass 2"),
  140. _T("65 Soprano Sax"),
  141. _T("66 Alto Sax"),
  142. _T("67 Tenor Sax"),
  143. _T("68 Baritone Sax"),
  144. _T("69 Oboe"),
  145. _T("70 English Horn"),
  146. _T("71 Bassoon"),
  147. _T("72 Clarinet"),
  148. _T("73 Piccolo"),
  149. _T("74 Flute"),
  150. _T("75 Recorder"),
  151. _T("76 Pan Flute"),
  152. _T("77 Blown Bottle"),
  153. _T("78 Shakuhachi"),
  154. _T("79 Whistle"),
  155. _T("80 Ocarina"),
  156. _T("81 Lead 1(square)"),
  157. _T("82 Lead 2 (sawtooth)"),
  158. _T("83 Lead 3 (calliope)"),
  159. _T("84 Lead 4 (chiff)"),
  160. _T("85 Lead 5 (charang)"),
  161. _T("86 Lead 6 (voice)"),
  162. _T("87 Lead 7 (fifths)"),
  163. _T("88 Lead 8 (bass+lead)"),
  164. _T("89 Pad 1 (new age)"),
  165. _T("90 Pad 2 (warm)"),
  166. _T("91 Pad 3 (polysynth)"),
  167. _T("92 Pad 4 (choir)"),
  168. _T("93 Pad 5 (bowed)"),
  169. _T("94 Pad 6 (metallic)"),
  170. _T("95 Pad 7 (halo)"),
  171. _T("96 Pad 8 (sweep)"),
  172. _T("97 FX 1 (rain)"),
  173. _T("98 FX 2 (soundtrack)"),
  174. _T("99 FX 3 (crystal)"),
  175. _T("100 FX 4 (atmosphere)"),
  176. _T("101 FX 5 (brightness)"),
  177. _T("102 FX 6 (goblins)"),
  178. _T("103 FX 7 (echoes)"),
  179. _T("104 FX 8 (sci-fi)"),
  180. _T("105 Sitar"),
  181. _T("106 Banjo"),
  182. _T("107 Shamisen"),
  183. _T("108 Koto"),
  184. _T("109 Kalimba"),
  185. _T("110 Bag Pipe"),
  186. _T("111 Fiddle"),
  187. _T("112 Shanai"),
  188. _T("113 Tinkle Bell"),
  189. _T("114 Agogo"),
  190. _T("115 Steel Drums"),
  191. _T("116 Woodblock"),
  192. _T("117 Taiko Drum"),
  193. _T("118 Melodic Tom"),
  194. _T("119 Synth Drum"),
  195. _T("120 Reverse Cymbal"),
  196. _T("121 Guitar Fret Noise"),
  197. _T("122 Breath Noise"),
  198. _T("123 Seashore"),
  199. _T("124 Bird Tweet"),
  200. _T("125 Telephone Ring"),
  201. _T("126 Helicopter"),
  202. _T("127 Applause"),
  203. _T("128 Gunshot")
  204. };
  205.  
  206. // 调整窗口客户区尺寸
  207. BOOL ReSizeClient (HWND hWindow,
  208. INT Width,
  209. INT Height,
  210. DWORD Style,
  211. DWORD StyleEx, BOOL bMenu )
  212. {
  213. RECT rcClient;
  214. if (!GetClientRect(hWindow, &rcClient ))
  215. return FALSE;
  216. if (Width != -1)
  217. rcClient.right = Width;
  218. if (Height != -1)
  219. rcClient.bottom = Height;
  220. if ( !AdjustWindowRectEx( &rcClient, Style, (!( Style & WS_CHILD ) && ( bMenu != NULL ) ), StyleEx ) )
  221. return FALSE;
  222. return SetWindowPos( hWindow, NULL, 0, 0, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top, SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE );
  223. }
  224. // 快速拷贝使用的汇编程式
  225. # if !defined (_WIN64)
  226. extern "C" {
  227. int CAlphaSingle32Unalign16_SSE (void * _vptr, int dword_byte,
  228. int dst_x, int dst_y,
  229. int dst_w, int dst_h,
  230. COLORREF col,
  231. BYTE alpha_dst, BYTE alpha_src);
  232. int CSurfaceCopy32 (void * _dvptr, int d_pos_x, int d_pos_y, int d_pitch,
  233. void * _svptr, int s_pos_x, int s_pos_y, int s_pitch,
  234. int w, int h);
  235. }
  236. # define CAlphaSingle CAlphaSingle32Unalign16_SSE
  237. # define CSurfaceCopy CSurfaceCopy32
  238. # else
  239. # endif
  240. };
  241.  
  242.  
  243. // Direct3D surface 类
  244. // 用来快速绘图, 离屏surface使用系统内存而非显存 (因为需要频繁读写).
  245.  
  246. class CDirectDraw
  247. {
  248. private:
  249. IDirect3DDevice9 *m_Direct3D9_device;
  250. IDirect3DSurface9 *m_Direct3D9_surface;
  251.  
  252. D3DPRESENT_PARAMETERS m_d3dpp;
  253.  
  254. HWND m_AttachWindow;
  255.  
  256. void initSettings (void) {
  257. m_Direct3D9_device = NULL;
  258. m_Direct3D9_surface = NULL;
  259. }
  260. void CreateD3dppSurface (int width, int height) {
  261.  
  262. // 重置 d3d描述
  263. ResetD3dpp (m_d3dpp, m_AttachWindow, width, height);
  264.  
  265. // 创建 d3d 设备
  266. HRESULT si = sm_Direct3D9_root->CreateDevice (0,
  267. D3DDEVTYPE_HAL,
  268. m_AttachWindow,
  269. D3DCREATE_SOFTWARE_VERTEXPROCESSING, &m_d3dpp, & m_Direct3D9_device);
  270. assert (SUCCEEDED (si));
  271. }
  272. public:
  273. // 显存/ 后备缓冲描述
  274. struct graph_desc {
  275. DWORD *__vptr;
  276. DWORD pitch;
  277. DWORD max_width;
  278. DWORD max_height;
  279. };
  280. // 锁显存/surface
  281. int lockBuffer (IDirect3DSurface9 *surface, RECT *rcLock, graph_desc &gd) {
  282. D3DLOCKED_RECT lock_rect;
  283. D3DSURFACE_DESC lock_desc;
  284. HRESULT rets = surface->LockRect (& lock_rect, rcLock, D3DLOCK_DISCARD | D3DLOCK_NOOVERWRITE);
  285. if (FAILED (rets))
  286. return -1;
  287. else ;
  288. rets = surface->GetDesc (& lock_desc);
  289. assert (SUCCEEDED (rets));
  290. gd.__vptr = (DWORD *) lock_rect.pBits;
  291. gd.pitch = lock_rect.Pitch;
  292. if (rcLock != NULL) {
  293. gd.max_width = abs (rcLock->right - rcLock->left);
  294. gd.max_height = abs (rcLock->bottom - rcLock->top);
  295. } else {
  296. gd.max_width = lock_desc.Width;
  297. gd.max_height = lock_desc.Height;
  298. }
  299. return 0;
  300. }
  301.  
  302. // 重置后备缓冲
  303. void resetBackSurface (int width, int height) {
  304. if (m_Direct3D9_surface != NULL) {
  305. m_Direct3D9_surface->Release ();
  306. m_Direct3D9_surface = NULL;
  307. }
  308. HRESULT rets = m_Direct3D9_device->CreateOffscreenPlainSurface (width, height, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM,
  309. & m_Direct3D9_surface, NULL);
  310. assert (SUCCEEDED (rets));
  311. }
  312.  
  313. int lockBuffer (RECT *rcLock, graph_desc &gd) {
  314. return lockBuffer (m_Direct3D9_surface, rcLock, gd);
  315. }
  316. int unlockBuffer (void) {
  317. HRESULT rets =m_Direct3D9_surface->UnlockRect ();
  318. if (FAILED (rets))
  319. return -1;
  320. else return 0;
  321. }
  322.  
  323. void ResetD3dppSurface (int width, int height) {
  324.  
  325. ResetD3dpp (m_d3dpp, m_AttachWindow, width, height);
  326.  
  327. HRESULT rets = m_Direct3D9_device->Reset (& m_d3dpp);
  328. assert (SUCCEEDED (rets));
  329. }
  330.  
  331. // 全局direct3d COM根
  332. static IDirect3D9 *sm_Direct3D9_root;
  333. public:
  334. static void InitDirect3D (void) {
  335. if (sm_Direct3D9_root == NULL) {
  336. sm_Direct3D9_root = Direct3DCreate9 (D3D_SDK_VERSION);
  337. assert (sm_Direct3D9_root != NULL);
  338. }
  339. }
  340. static void UninitDirect3D (void) {
  341. if (sm_Direct3D9_root != NULL) {
  342. sm_Direct3D9_root->Release ();
  343. sm_Direct3D9_root = NULL;
  344. }
  345. }
  346.  
  347. void ResetD3dpp (D3DPRESENT_PARAMETERS &d3dpp, HWND window, int width, int height) {
  348.  
  349. ZeroMemory (& d3dpp, sizeof (d3dpp));
  350.  
  351. d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
  352. d3dpp.SwapEffect = D3DSWAPEFFECT_COPY;
  353. d3dpp.Flags = 0;
  354. d3dpp.hDeviceWindow = window;
  355. d3dpp.Windowed = TRUE;
  356. d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; // 禁用 Direct3D垂直同步, 这点很重要. 否则会强制等待VBlank导致时间片浪费掉.
  357. d3dpp.BackBufferHeight = height;
  358. d3dpp.BackBufferWidth = width;
  359. }
  360. // 离屏表面传输到显存交换链
  361. int BlitBtoV (POINT *ptDst, POINT *ptSrc, SIZE *szSize) {
  362. IDirect3DSurface9 *t;
  363. D3DSURFACE_DESC lock_desc;
  364. int rc = -1;
  365. HRESULT rets = m_Direct3D9_device->GetBackBuffer (0, 0, D3DBACKBUFFER_TYPE_MONO, & t);
  366. assert (SUCCEEDED (rets));
  367. POINT ptSrcT = { 0, 0};
  368. POINT *ptPpc = ptSrc ? ptSrc : & ptSrcT;
  369. // 自动适配尺寸.
  370. rets = m_Direct3D9_surface->GetDesc (& lock_desc);
  371. assert (SUCCEEDED (rets));
  372. SIZE *szPpc = szSize;
  373. SIZE szSrcT;
  374. if (szPpc == NULL) {
  375. szPpc = & szSrcT;
  376. szSrcT.cx = lock_desc.Width - ptPpc->x;
  377. szSrcT.cy = lock_desc.Height - ptPpc->y;
  378. if (szSrcT.cx <= 0 || (szSrcT.cy <= 0))
  379. goto __cleanup;
  380. }
  381. RECT ac = { ptPpc->x, ptPpc->y, ptPpc->x + szPpc->cx, ptPpc->y + szPpc->cy};
  382. rets = m_Direct3D9_device->UpdateSurface (m_Direct3D9_surface, & ac, t, ptDst);
  383. rc = (SUCCEEDED (rets)) ? 0 : -1;
  384. __cleanup:
  385. rets = t->Release ();
  386. assert (SUCCEEDED (rets));
  387. return rc;
  388. }
  389. // 提交渲染至实际显示
  390. int postRender (RECT *ptDst, RECT *ptSrc) {
  391. HRESULT rets = m_Direct3D9_device->Present (ptSrc, ptDst, NULL, NULL);
  392. if (SUCCEEDED (rets))
  393. return 0;
  394. else return -1;
  395. }
  396. int postRender (POINT &ptDst, POINT &ptSrc, SIZE &size_) {
  397. RECT rcDst = { ptDst.x, ptDst.y, ptDst.x + size_.cx, ptDst.y + size_.cy};
  398. RECT rcSrc = { ptSrc.x, ptSrc.y, ptSrc.x + size_.cx, ptSrc.y + size_.cy};
  399. return postRender (& rcDst, & rcSrc);
  400. }
  401. // CTOR, 析构
  402. ~CDirectDraw () {
  403. if ( m_Direct3D9_surface != NULL) {
  404. m_Direct3D9_surface->Release ();
  405. m_Direct3D9_surface = NULL;
  406. }
  407. if ( m_Direct3D9_device != NULL) {
  408. m_Direct3D9_device->Release ();
  409. m_Direct3D9_device = NULL;
  410. }
  411. return ;
  412. }
  413. // DTOR, 构造
  414. CDirectDraw (HWND attach, SIZE &VSize, SIZE &BSize) {
  415. initSettings ();
  416. // 设置空刷子, 免得系统重画, 可能还会引起闪烁.
  417. SetClassLongPtr (attach, GCLP_HBRBACKGROUND, (LONG_PTR) GetStockObject (NULL_BRUSH)) ;
  418. m_AttachWindow = attach;
  419. CreateD3dppSurface (VSize.cx, VSize.cy);
  420. resetBackSurface (BSize.cx, BSize.cy);
  421. }
  422. static int __POW2 (int nc) {
  423. int n;
  424. for (n= 1; n < nc; n<<=1) {}
  425. return n;
  426. }
  427. // 加载纹理资源
  428. int LoadImage (TCHAR *fname, int width, int height, graph_desc &gd) {
  429. {
  430. IDirect3DTexture9 *tex;
  431. D3DXIMAGE_INFO infos;
  432.  
  433. if (FAILED ( D3DXCreateTextureFromFileEx (m_Direct3D9_device, fname,
  434. D3DX_DEFAULT_NONPOW2,
  435. D3DX_DEFAULT_NONPOW2,
  436. D3DX_FROM_FILE,
  437. 0,
  438. D3DFMT_UNKNOWN,
  439. D3DPOOL_MANAGED,
  440. D3DX_DEFAULT, // D3DX_DEFAULT
  441. D3DX_DEFAULT, // D3DX_DEFAULT
  442. 0, //D3DCOLOR_XRGB (0, 0, 0),
  443. & infos, NULL, & tex)) )
  444. return -1;
  445. {
  446. D3DLOCKED_RECT Vdesc;
  447. HRESULT sig;
  448. DWORD id2;
  449. // lock it
  450. sig = tex->LockRect (0, & Vdesc, NULL, D3DLOCK_READONLY);
  451. assert (SUCCEEDED (sig));
  452.  
  453. gd.max_width = infos.Width;
  454. gd.max_height = infos.Height;
  455. gd.pitch = __POW2 (Vdesc.Pitch); // step 4 * RGB-depth
  456. gd.__vptr = (DWORD *) _aligned_malloc (gd.pitch *gd.max_height, 64);
  457.  
  458. for (id2 = 0; id2 != infos.Height; id2++)
  459. memcpy ( & ( ((char *)gd.__vptr)[id2 * gd.pitch]),
  460. & ( ((char *)Vdesc.pBits)[id2 * Vdesc.Pitch]) ,
  461. infos.Width *4);
  462.  
  463. // unlock., release.
  464. tex->UnlockRect (0);
  465. tex->Release ();
  466. return 0;
  467. }
  468. return -1;
  469. }
  470. }
  471. int LoadImage (int resid, int width, int height, graph_desc &gd) {
  472. {
  473. IDirect3DTexture9 *tex;
  474. D3DXIMAGE_INFO infos;
  475.  
  476. if (FAILED ( D3DXCreateTextureFromResourceEx (m_Direct3D9_device, NULL,
  477. MAKEINTRESOURCE (resid),
  478. D3DX_DEFAULT_NONPOW2,
  479. D3DX_DEFAULT_NONPOW2,
  480. D3DX_FROM_FILE,
  481. 0,
  482. D3DFMT_UNKNOWN,
  483. D3DPOOL_MANAGED,
  484. D3DX_DEFAULT, // D3DX_DEFAULT
  485. D3DX_DEFAULT, // D3DX_DEFAULT
  486. 0, //D3DCOLOR_XRGB (0, 0, 0),
  487. & infos, NULL, & tex)) )
  488. return -1;
  489. {
  490. D3DLOCKED_RECT Vdesc;
  491. HRESULT sig;
  492. DWORD id2;
  493. // lock it
  494. sig = tex->LockRect (0, & Vdesc, NULL, D3DLOCK_READONLY);
  495. assert (SUCCEEDED (sig));
  496.  
  497. gd.max_width = infos.Width;
  498. gd.max_height = infos.Height;
  499. gd.pitch = __POW2 (Vdesc.Pitch); // step 4 * RGB-depth
  500. gd.__vptr = (DWORD *) _aligned_malloc (gd.pitch *gd.max_height, 64);
  501.  
  502. for (id2 = 0; id2 != infos.Height; id2++)
  503. memcpy ( & ( ((char *)gd.__vptr)[id2 * gd.pitch]),
  504. & ( ((char *)Vdesc.pBits)[id2 * Vdesc.Pitch]) ,
  505. infos.Width *4);
  506.  
  507. // unlock., release.
  508. tex->UnlockRect (0);
  509. tex->Release ();
  510. return 0;
  511. }
  512. return -1;
  513. }
  514. }
  515. int FreeImage (graph_desc &gd) {
  516. if (gd.__vptr != NULL) {
  517. _aligned_free (gd.__vptr);
  518. gd.__vptr = NULL;
  519. }
  520. }
  521. };
  522. // 静态类成员初始化
  523. IDirect3D9 *CDirectDraw::sm_Direct3D9_root = nullptr;
  524.  
  525. // 用来画按键信息. 这段写的相对烂的多.数据没测准.注释中关于方向大小位置的信息可能不太准.真是抱歉》。
  526. namespace CPianoDraw__ {
  527. # define HALF_MASK 0x80
  528. static struct dummt_ {
  529. TCHAR *harmonica_scale;
  530. int octave_step;
  531. int note;
  532. int midi_pos;
  533. BYTE mapDIK;
  534. } keyboard_mapper[36] = {
  535. // 低音
  536. { _T(" (1)"), 0, 1, 0, DIK_Z }, // 1
  537. { _T(" (#1)"), 0, 1 | HALF_MASK, 1, DIK_S }, //#1
  538. { _T(" (2)"), 0, 2, 2, DIK_X }, // 2
  539. { _T(" (#2)"), 0, 2 | HALF_MASK, 3, DIK_D }, //#2
  540. { _T(" (3)"), 0, 3, 4, DIK_C }, // 3
  541. { _T(" (4)"), 0, 4, 5, DIK_V }, // 4
  542. { _T(" (#4)"), 0, 4 | HALF_MASK, 6, DIK_F }, //#4
  543. { _T(" (5)"), 0, 5 , 7, DIK_B }, // 5
  544. { _T(" (#5)"), 0, 5 | HALF_MASK, 8, DIK_G }, //#5
  545. { _T(" (6)"), 0, 6 , 9, DIK_N }, // 6
  546. { _T(" (#6)"), 0, 6 | HALF_MASK,10, DIK_H }, //#6
  547. { _T(" (7)"), 0, 7 , 11, DIK_M }, // 7
  548. // 中音
  549. { _T(" 1"), 1, 1, 0+12, DIK_Q }, // 1
  550. { _T(" #1"), 1, 1 | HALF_MASK, 1+12, DIK_2 }, // #1
  551. { _T(" 2"), 1, 2, 2+12, DIK_W }, // 2
  552. { _T(" #2"), 1, 2 | HALF_MASK, 3+12, DIK_3 }, // #2
  553. { _T(" 3"), 1, 3, 4+12, DIK_E }, // 3
  554. { _T(" 4"), 1, 4, 5+12, DIK_R }, // 4
  555. { _T(" #4"), 1, 4 | HALF_MASK, 6+12, DIK_4 }, // #4
  556. { _T(" 5"), 1, 5 , 7+12, DIK_T }, // 5
  557. { _T(" #5"), 1, 5 | HALF_MASK, 8+12, DIK_5 }, // #5
  558. { _T(" 6"), 1, 6 , 9+12, DIK_Y }, // 6
  559. { _T(" #6"), 1, 6 | HALF_MASK,10+12, DIK_6 }, // #6
  560. { _T(" 7"), 1, 7 , 11+12, DIK_U }, // 7
  561. // 高音
  562. { _T(" [1]"), 2, 1, 0+24, DIK_I }, // 1
  563. { _T(" [#1]"), 2, 1 | HALF_MASK, 1+24, DIK_9 }, // #1
  564. { _T(" [2]"), 2, 2, 2+24, DIK_O }, // 2
  565. { _T(" [#2]"), 2, 2 | HALF_MASK, 3+24, DIK_0 }, // #2
  566. { _T(" [3]"), 2, 3, 4+24, DIK_P }, // 3
  567. { _T(" [4]"), 2, 4, 5+24, DIK_LBRACKET }, // 4
  568. { _T(" [#4]"), 2, 4 | HALF_MASK, 6+24, DIK_MINUS }, // #4
  569. { _T(" [5]"), 2, 5 , 7+24, DIK_RBRACKET }, // 5
  570. { _T(" [#5]"), 2, 5 | HALF_MASK, 8+24, DIK_EQUALS }, // #5
  571. { _T(" [6]"), 2, 6 , 9+24, DIK_BACKSLASH }, // 6
  572. { _T(" [#6]"), 2, 6 | HALF_MASK,10+24, DIK_BACK }, // #6
  573. { _T(" [7]"), 2, 7 , 11+24, DIK_RETURN } // 7
  574. };
  575.  
  576. static const DWORD sm_ColBlack = 0xffd200; // 钢琴黑键着色
  577. static const DWORD sm_ColWhite = 0x00fffc; // 钢琴白键着色
  578. static const BYTE sm_ShadowBlackAlpha = 32; // 黑键Alpha百分比
  579. static const BYTE sm_ShadowWhiteAlpha = 32; // 白键Alpha百分比
  580. // 黑键音阶基偏移
  581. static const int left_remain = 3;
  582. static const POINT sm_note_half1 = { 11 - left_remain, 1 }; // #1
  583. static const POINT sm_note_half2 = { 47 - left_remain, 1 }; // #2
  584. static const POINT sm_note_half4 = {103 - left_remain, 1 }; // #4
  585. static const POINT sm_note_half5 = {138 - left_remain, 1 }; // #5
  586. static const POINT sm_note_half6 = {169 - left_remain, 1 }; // #6
  587. // 白键音阶基偏移
  588. static const POINT sm_note_1 = { 3 - left_remain, 1 }; // 1 二次矩形绘制 X0Y54 W20H106 | X0Y0 W7H54
  589. static const POINT sm_note_2 = { 33 - left_remain, 1 }; // 2 二次矩形绘制 X0Y54 W21H106 | X6Y0 W7H54
  590. static const POINT sm_note_3 = { 64 - left_remain, 1 }; // 3 二次矩形绘制 X0Y54 W21H106 | X11Y0 W10H54
  591. static const POINT sm_note_4 = { 94 - left_remain, 1 }; // 4 二次矩形绘制 X0Y54 W22H106 | X0Y0 W8H54
  592. static const POINT sm_note_5 = {126 - left_remain, 1 }; // 5 二次矩形绘制 X0Y54 W20H106 | X5Y0 W6H154
  593. static const POINT sm_note_6 = {156 - left_remain, 1 }; // 6 二次矩形绘制 X0Y54 W20H106 | X10Y0 W2H154
  594. static const POINT sm_note_7 = {186 - left_remain, 1 }; // 7 二次矩形绘制 X0Y54 W20H106 | X11Y0 W9H54
  595. // 三音阶基偏移
  596. static const int octave_0 = 3;
  597. static const int octave_1 = 215;
  598. static const int octave_2 = 427;
  599. static const int octave_set[3] = { octave_0, octave_1, octave_2} ;
  600.  
  601. void drawPiano (CDirectDraw ::graph_desc &gd, int octave_step, int note /* 从1开始计数*/) {
  602. int octave_step_ = octave_step & 3;
  603. int note_ = note & 0x7;
  604. const int base_x = octave_set [octave_step_];
  605. if (FALSE != !! (note & HALF_MASK)) {
  606. // 画黑键
  607. const POINT *pt;
  608. switch (note_) {
  609. case 1: pt = & sm_note_half1; break ;
  610. case 2: pt = & sm_note_half2; break ;
  611. case 4: pt = & sm_note_half4; break ;
  612. case 5: pt = & sm_note_half5; break ;
  613. case 6: pt = & sm_note_half6; break ;
  614. default : assert (0); break ;
  615. }
  616. CUtil ::CAlphaSingle (gd.__vptr, gd.pitch, pt->x + base_x + 1,
  617. pt->y + 1,
  618. 27, 53,
  619. sm_ColBlack,
  620. sm_ShadowBlackAlpha,
  621. 255 - sm_ShadowBlackAlpha);
  622. } else {
  623. // 画白键
  624. int pos_x;
  625. RECT part2 = { 0, 3, 0, 57};
  626. POINT *base_pos = NULL;
  627. const POINT *base_pc = NULL;
  628. switch (note_) {
  629. case 1: base_pc = & sm_note_1; pos_x = 20; part2.right = 7; break ;
  630. case 2: base_pc = & sm_note_2; pos_x = 21; part2.left = 6; part2.right = 13; break ;
  631. case 3: base_pc = & sm_note_3; pos_x = 21; part2.left = 11; part2.right = 21; break ;
  632. case 4: base_pc = & sm_note_4; pos_x = 22; part2.right = 8; break ;
  633. case 5: base_pc = & sm_note_5; pos_x = 20; part2.left = 5; part2.right = 11; break ;
  634. case 6: base_pc = & sm_note_6; pos_x = 20; part2.left = 10; part2.right = 12; break ;
  635. case 7: base_pc = & sm_note_7; pos_x = 20; part2.left = 11; part2.right = 20; break ;
  636. default : assert (0);
  637. }
  638. CUtil ::CAlphaSingle (gd.__vptr, gd.pitch, base_pc->x + base_x + 1, 56, pos_x, 180,
  639. sm_ColWhite,
  640. sm_ShadowWhiteAlpha,
  641. 255 - sm_ShadowWhiteAlpha);
  642. CUtil ::CAlphaSingle (gd.__vptr, gd.pitch, base_pc->x + base_x + 1 + part2.left , 2,
  643. part2.right - part2.left,
  644. part2.bottom - part2.top,
  645. sm_ColWhite,
  646. sm_ShadowWhiteAlpha,
  647. 255 - sm_ShadowWhiteAlpha);
  648. }
  649. }
  650. };
  651.  
  652. // DirectInput8 对象, 用来快速获取按键消息状态
  653. class CDirectInput8 {
  654. private:
  655. // 全局 DirectInput8 COM根.
  656. static IDirectInput8 *sm_DirectInput8_root;
  657. public:
  658. IDirectInputDevice8 *m_input;
  659.  
  660. void initSettings (void) {
  661. m_input = NULL;
  662. ZeroMemory (m_keyBoardBuffer, sizeof (m_keyBoardBuffer));
  663. m_keyBoardBank = NULL;
  664. }
  665. void InitDeviceKeyboard (HWND hWindow) {
  666.  
  667. HRESULT sig = sm_DirectInput8_root->CreateDevice ( GUID_SysKeyboard, & m_input, NULL);
  668. assert (SUCCEEDED (sig));
  669. BOOL bOldisVisual = !! IsWindowVisible (hWindow);
  670. if (bOldisVisual == FALSE) // 不可见将会设置失败, 有趣.
  671. ShowWindow (hWindow, SW_SHOWNORMAL);
  672. sig = m_input->SetCooperativeLevel (hWindow, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND); // 设置非独占, 前台模式
  673. assert (SUCCEEDED (sig));
  674. sig = m_input->SetDataFormat ( (LPDIDATAFORMAT) & c_dfDIKeyboard);
  675. assert (SUCCEEDED (sig));
  676. if (bOldisVisual == FALSE) // 还原旧状态
  677. ShowWindow (hWindow, SW_HIDE);
  678. }
  679. static void InitDInput8 (void) {
  680. if (sm_DirectInput8_root == NULL) {
  681. HRESULT sig = DirectInput8Create (GetModuleHandle (NULL),
  682. DIRECTINPUT_VERSION,
  683. IID_IDirectInput8,
  684. (void **)& sm_DirectInput8_root, NULL);
  685. assert (SUCCEEDED (sig));
  686. }
  687. }
  688. static void UninitDInput8 (void) {
  689. if (sm_DirectInput8_root != NULL) {
  690. sm_DirectInput8_root->Release ();
  691. sm_DirectInput8_root = NULL;
  692. }
  693. }
  694.  
  695. void PollBuffer (void) {
  696. int s = m_keyBoardBank;
  697. s *= 256;
  698. // 尝试获得设备
  699. if ( FAILED( m_input->GetDeviceState (256, & m_keyBoardBuffer[s])) ) {
  700. // 获取失败, 可能是设备丢失, 方便处理就是假设设备丢失了
  701. if (FAILED (m_input->Acquire ())) {
  702. // 获取失败, 清零当前buffer状态
  703. ZeroMemory (& m_keyBoardBuffer[s], 256);
  704. } else {
  705. if ( FAILED( m_input->GetDeviceState (256, & m_keyBoardBuffer[s])) ) {
  706. ZeroMemory (& m_keyBoardBuffer[s], 256);
  707. }
  708. }
  709. }
  710. m_keyBoardBank ^= 1; // 切换bank
  711. }
  712. static const int JP_MASK_PRESS = 1; // 指示按下
  713. static const int JP_MASK_LAST = 2; // 指示是否持续按下/松开
  714.  
  715. typedef int JP_MASK;
  716.  
  717. JP_MASK getMask (BYTE DIK_idx) {
  718. JP_MASK t = 0;
  719. int s = m_keyBoardBank ^ 1;
  720. s *= 256;
  721. if ( ( m_keyBoardBuffer[s+DIK_idx] & 0x80) != 0) {
  722. t |= JP_MASK_PRESS;
  723. if ( ( m_keyBoardBuffer[(s^256)+DIK_idx] & 0x80) != 0) {
  724. // 按下-持续
  725. t |= JP_MASK_LAST;
  726. }
  727. } else {
  728. if ( ( m_keyBoardBuffer[(s^256)+DIK_idx] & 0x80) == 0) {
  729. // 松开-持续
  730. t |= JP_MASK_LAST;
  731. }
  732. }
  733. return t;
  734. }
  735. BOOL isPressedFirst (BYTE DIK_idx) {
  736. JP_MASK t = 0;
  737. int s = m_keyBoardBank ^ 1;
  738. s <<= 8;
  739. if ( ( m_keyBoardBuffer[s+DIK_idx] & 0x80) != 0
  740. && (( m_keyBoardBuffer[(s^256)+DIK_idx] & 0x80) == 0) ) {
  741. return TRUE;
  742. }
  743. return FALSE;
  744. }
  745. private:
  746. BYTE m_keyBoardBuffer[512]; // 按键记录缓冲.
  747. BYTE m_keyBoardBank; // 新旧按键缓冲切换指示
  748. public:
  749. // 构造
  750. CDirectInput8 (void) {
  751. initSettings ();
  752. }
  753. // 析构
  754. ~CDirectInput8 (void) {
  755. if ( m_input != NULL) {
  756. m_input->Unacquire ();
  757. m_input->Release ();
  758. m_input = NULL;
  759. }
  760. };
  761. };
  762. IDirectInput8 *CDirectInput8::sm_DirectInput8_root = nullptr;
  763.  
  764. // DirectMusc 部分
  765. // DMUS_PORTCAPS 的可变字符集版本
  766. // 主要用来枚举设备输入和输出
  767. typedef struct _DMUS_PORTCAPS_T {
  768. DWORD dwSize;
  769. DWORD dwFlags;
  770. GUID guidPort;
  771. DWORD dwClass;
  772. DWORD dwType;
  773. DWORD dwMemorySize;
  774. DWORD dwMaxChannelGroups;
  775. DWORD dwMaxVoices;
  776. DWORD dwMaxAudioChannels;
  777. DWORD dwEffectFlags;
  778. TCHAR szDescription[DMUS_MAX_DESCRIPTION];
  779. } DMUS_PORTCAPS_T, *LPDMUS_PORTCAPS_T;
  780.  
  781. // 音效合集
  782. // 这里, 翻遍google也没找到应用效果的例子程序.
  783. // 可能DirectSound的音效和DirectMusic音效混用的
  784. // 想法真的, 可能行不通(?)...
  785. // 熟悉的请告诉我, 谢谢.
  786. struct DirectMusic_EffectSet {
  787. IDirectSoundFXGargle8 *efs_Gargle; // 音效-漱口
  788. IDirectSoundFXChorus8 *efs_Chorus; // 音效-合唱
  789. IDirectSoundFXFlanger8 *efs_Flanger; // 音效-排雪板
  790. IDirectSoundFXEcho8 *efs_Echo; // 音效-回声
  791. IDirectSoundFXDistortion8 *efs_Distortion; // 音效-扭曲
  792. IDirectSoundFXCompressor8 *efs_Compressor; // 音效-压气
  793. IDirectSoundFXParamEq8 *efs_ParamEq; // 音效- 均衡器
  794. IDirectSoundFXWavesReverb8 *efs_Reverb; // 音效- 混响
  795. IDirectSoundFXI3DL2Reverb8 *efs_Reverb2; // 音效- 混响_level2
  796.  
  797. // 音效描述结构.
  798. DSFXGargle dsfx_Gargle;
  799. DSFXChorus dsfxChorus;
  800. DSFXFlanger dsfx_Flanger;
  801. DSFXEcho dsfx_Echo;
  802. DSFXDistortion dsfx_Distortion;
  803. DSFXCompressor dsfx_Compressor;
  804. DSFXParamEq dsfx_ParamEq;
  805. DSFXWavesReverb dsfx_Reverb;
  806. DSFXI3DL2Reverb dsfx_Reverb2;
  807. };
  808.  
  809. // 力反馈结构
  810. class CStrengthFeedback {
  811. private:
  812. BOOL m_EnableUse;
  813. BYTE m_InitValue;
  814. BYTE m_MaxValue;
  815. INT m_ticksToMax;
  816. INT m_ticksToMin;
  817. public :
  818. CStrengthFeedback () {
  819. m_EnableUse = FALSE;
  820. m_InitValue = 0x12;
  821. m_MaxValue = 0x7F;
  822. m_ticksToMax = 2000;
  823. m_ticksToMin = 0;
  824. }
  825. BOOL UseDescentEdge (void) {
  826. return (m_ticksToMin >= 0);
  827. }
  828. BOOL UseStrengthFeedback (void) {
  829. return !! m_EnableUse;
  830. }
  831. BOOL SetStrengthFeedback (BOOL Enable) {
  832. m_EnableUse = Enable;
  833. }
  834. void SetMaxValue (INT value) {
  835. m_MaxValue = value;
  836. }
  837. void SetInitValue (INT value) {
  838. m_InitValue = value;
  839. }
  840. INT GetMaxValue (void) {
  841. return m_MaxValue;
  842. }
  843. INT GetInitValue (void) {
  844. return m_InitValue;
  845. }
  846. void Set_ticksToMax (INT value) {
  847. m_ticksToMax = value;
  848. }
  849. void Set_ticksToMin (INT value) {
  850. m_ticksToMin = value;
  851. }
  852. INT Set_ticksToMax (void) {
  853. return m_ticksToMax;
  854. }
  855. INT Set_ticksToMin (void) {
  856. return m_ticksToMin;
  857. }
  858. };
  859.  
  860.  
  861.  
  862.  
  863.  
  864.  
  865. // DirectMusic类
  866. // 这个类中大部分代码参考自网络程式和SDK文档.对此表示感谢.
  867. class CDirectMusic_ {
  868. public :
  869. // 类成员变量
  870. BYTE m_bFixedVelocity; // 固定力度指示.
  871. IDirectMusicLoader8 *m_DLSloader; // DLS加载器.
  872. IDirectMusicDownloadedInstrument8* m_pDLSInstrument; // DLS 乐器指令集
  873. IDirectMusicInstrument8* m_pInstrument; // 乐器指令集
  874. IDirectMusicPort8* m_pOutputPort; // 基本端口 (输出·)。
  875. IDirectMusicCollection8 * m_DLSCollection;
  876. IDirectMusicBuffer8* m_DUS_soundbuffer;
  877. IDirectMusicPortDownload8 * m_PortDownload; //
  878. IReferenceClock* m_pClock; // 参考时钟计数.
  879. // IDirectMusicPort8* m_pInputPort; // 基本端口 (不使用_) 。
  880. //
  881. DMUS_PORTPARAMS8 m_OutputParams;
  882. // DMUS_PORTPARAMS8 m_InputParams;
  883.  
  884. GUID m_GuidSelOutputPort; // 当前选择的输出端口号的GUID.
  885. BOOL m_bSynthesizer; // DirectMusic强化合成器致能
  886. BOOL m_bUseStrengthFeedback; // 使用力反馈键位
  887. int m_SelInstructment; // 当前选择的乐器指令号/补丁号码.
  888. int m_DefaultStartOctaveLevel; // 默认基调性..
  889.  
  890. HWND m_AttahStatus; // 设置链接的状态栏
  891. std::vector <DMUS_PORTCAPS_T> m_OutputPortCache; // 输出端口缓存
  892.  
  893. void SetMiddleOctave (int level) {
  894. m_DefaultStartOctaveLevel = level;
  895. }
  896. int GetMiddleOctave (void) {
  897. return m_DefaultStartOctaveLevel;
  898. }
  899. void SetFixedVelocity (BYTE vel) {
  900. m_bFixedVelocity = vel;
  901. }
  902. int GetFixedVelocity (void) {
  903. return m_bFixedVelocity;
  904. }
  905. void SetInstructment (int id) {
  906. m_SelInstructment = id;
  907. }
  908. int GetInstructment (void) {
  909. return m_SelInstructment;
  910. }
  911. void SetOutportGUID (GUID &guid) {
  912. CopyMemory (& m_GuidSelOutputPort, & guid, sizeof (guid));
  913. }
  914. GUID & GetOutportGUID (void) {
  915. return m_GuidSelOutputPort;
  916. }
  917. public:
  918.  
  919. void ReleaseCollection (void) {
  920. if (m_DLSloader && m_DLSCollection) {
  921. m_DLSloader->ReleaseObjectByUnknown (m_DLSCollection);
  922. m_DLSCollection->Release ();
  923. m_DLSCollection = NULL;
  924. }
  925. }
  926. void ReleaseInstructment (void) {
  927. if (m_pDLSInstrument && m_pOutputPort) {
  928. m_pOutputPort->UnloadInstrument (m_pDLSInstrument);
  929. m_pDLSInstrument->Release ();
  930. m_pDLSInstrument = NULL;
  931. }
  932. if (m_pInstrument) {
  933. m_pInstrument->Release ();
  934. m_pInstrument = NULL;
  935. }
  936. }
  937. void ReleaseClock (void) {
  938. if (m_pClock) {
  939. m_pClock->Release ();
  940. m_pClock = NULL;
  941. }
  942. }
  943. void LoadDefaultDLS (void) {
  944. HRESULT sig = -1;
  945. DMUS_OBJECTDESC dmusdesc;
  946. // Sets to 0 the DMUS structure
  947.  
  948. ZeroMemory(&dmusdesc,sizeof(DMUS_OBJECTDESC));
  949. dmusdesc.dwSize = sizeof(DMUS_OBJECTDESC);
  950. dmusdesc.guidClass = CLSID_DirectMusicCollection;
  951. dmusdesc.guidObject = GUID_DefaultGMCollection;
  952. dmusdesc.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_OBJECT;
  953.  
  954. ReleaseCollection ();
  955. sig = m_DLSloader->GetObject(&dmusdesc,IID_IDirectMusicCollection,(void**)& m_DLSCollection);
  956. assert (SUCCEEDED (sig));
  957. }
  958. void LoadDefaultDLS (IDirectMusicCollection **p) {
  959. HRESULT sig = -1;
  960. DMUS_OBJECTDESC dmusdesc;
  961. // Sets to 0 the DMUS structure
  962.  
  963. ZeroMemory(&dmusdesc,sizeof(DMUS_OBJECTDESC));
  964. dmusdesc.dwSize = sizeof(DMUS_OBJECTDESC);
  965. dmusdesc.guidClass = CLSID_DirectMusicCollection;
  966. dmusdesc.guidObject = GUID_DefaultGMCollection;
  967. dmusdesc.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_OBJECT;
  968.  
  969. assert (m_DLSloader != NULL);
  970. sig = m_DLSloader->GetObject(&dmusdesc,IID_IDirectMusicCollection,(void**)p);
  971. assert (SUCCEEDED (sig));
  972. }
  973. void ReleaseDLS (IDirectMusicCollection *p) {
  974. if (m_DLSloader && p) {
  975. m_DLSloader->ReleaseObjectByUnknown (p);
  976. p->Release ();
  977. }
  978. }
  979. void ReleaseOutputPort (void) {
  980. if (m_pOutputPort) {
  981. m_pOutputPort->Release ();
  982. m_pOutputPort = NULL;
  983. }
  984. }
  985. void initSettings (void) {
  986. m_DLSloader = NULL; // DLS加载器.
  987. m_pDLSInstrument = NULL; // DLS 乐器指令集
  988. m_pInstrument = NULL; // 乐器指令集
  989. m_pOutputPort = NULL; // 基本端口 (输出·)。
  990. m_DLSCollection = NULL;
  991. m_DUS_soundbuffer = NULL;
  992. m_PortDownload = NULL; //
  993. m_pClock = NULL; // 参考时钟计数.
  994. m_AttahStatus = NULL;
  995. m_DefaultStartOctaveLevel = 8;
  996. m_bFixedVelocity = 127;
  997. }
  998.  
  999. //刷新输出端口缓存》
  1000. void FlushOutPortCache (void) {
  1001. m_OutputPortCache.clear (); // 清空之前的.
  1002. DMUS_PORTCAPS_T t;
  1003. int port_nums = CDirectMusic_ :: GetOutputPortNums ();
  1004. for (int id = 0; id != port_nums; id++) {
  1005. GetOutputPortInfos (id, & t);
  1006. m_OutputPortCache.push_back (t);
  1007. }
  1008. }
  1009. std::vector <DMUS_PORTCAPS_T>& GetOutPortCache (void) {
  1010. return m_OutputPortCache;
  1011. }
  1012.  
  1013. HRESULT SendMidiMsg (DWORD dwMsg)
  1014. {
  1015. HRESULT sig = -1;
  1016. REFERENCE_TIME rt;
  1017.  
  1018. sig = m_pClock->GetTime(&rt);
  1019. assert (SUCCEEDED (sig));
  1020. sig = m_DUS_soundbuffer->PackStructured(rt, m_OutputParams.dwChannelGroups, dwMsg);
  1021. assert (SUCCEEDED (sig));
  1022. sig = m_pOutputPort->PlayBuffer (m_DUS_soundbuffer);
  1023. assert (SUCCEEDED (sig));
  1024. sig = m_DUS_soundbuffer->Flush ();
  1025. assert (SUCCEEDED (sig));
  1026.  
  1027. return sig;
  1028. }
  1029.  
  1030. // 设置GUID表示和引用索引.
  1031. void SetGuidAndIndex (GUID &guid) {
  1032. CopyMemory (& m_GuidSelOutputPort, & guid, sizeof (GUID));
  1033. }
  1034. BOOL isEqualOutputPort (GUID &guid) {
  1035. return IsEqualGUID (m_GuidSelOutputPort, guid);
  1036. }
  1037. void ResetOutport (int outid, int instructid, DWORD effectFlags) {
  1038. // 重置
  1039. ZeroMemory(&m_OutputParams,sizeof(DMUS_PORTPARAMS8));
  1040. m_OutputParams.dwSize = sizeof(DMUS_PORTPARAMS8);
  1041.  
  1042. // 创建输入输出端口, 默认选择口琴乐器指令集
  1043. m_SelInstructment = instructid;
  1044. m_bSynthesizer = FALSE;
  1045.  
  1046. // 释放之前获得所有接口.
  1047. ReleaseInstructment ();
  1048. ReleaseCollection ();
  1049. ReleaseClock ();
  1050. ReleaseOutputPort ();
  1051.  
  1052. int nsel;
  1053. int nsize = m_OutputPortCache.size ();
  1054. assert (nsize> 0);
  1055. nsel = outid;
  1056. DMUS_PORTCAPS_T &pt = m_OutputPortCache[nsel];
  1057. pt.dwMaxChannelGroups = 1;
  1058. SetOutputPortInfos ( 0, 0, 0, effectFlags,0);
  1059.  
  1060. // 创建输出端口.
  1061. HRESULT sig = directMusic_base->CreatePort (pt.guidPort, & m_OutputParams, & m_pOutputPort, NULL);
  1062. // 使其活跃.
  1063. sig = m_pOutputPort->Activate (TRUE);
  1064. assert (SUCCEEDED (sig));
  1065. // 获取参考时钟》
  1066. sig = m_pOutputPort->GetLatencyClock (& m_pClock);
  1067. assert (SUCCEEDED (sig));
  1068.  
  1069. // 创建音频缓冲
  1070. DMUS_BUFFERDESC BufferDesc; // Create the DirectMusic buffer to store MIDI messages
  1071. ZeroMemory(&BufferDesc,sizeof(DMUS_BUFFERDESC));
  1072. BufferDesc.dwSize = sizeof(DMUS_BUFFERDESC);
  1073. BufferDesc.guidBufferFormat = GUID_NULL;
  1074. BufferDesc.cbBuffer = DMUS_EVENT_SIZE(32); // at least 32 bytes to store messages
  1075. sig = CDirectMusic_::directMusic_base->CreateMusicBuffer(&BufferDesc,& m_DUS_soundbuffer,NULL);
  1076. assert (SUCCEEDED (sig));
  1077. // 这啥叼接口...删了好像不报错..
  1078. m_PortDownload->Release ();
  1079.  
  1080. DWORD bInstruction = instructid;
  1081. DMUS_PORTCAPS t;
  1082. m_pOutputPort->GetCaps (& t);
  1083. assert (SUCCEEDED (sig));
  1084.  
  1085. // 通用波表和mapper一般23号是口琴
  1086. SetGuidAndIndex (pt.guidPort);
  1087. if ((pt.dwFlags & DMUS_PC_DLS) || (pt.dwFlags & DMUS_PC_DLS2))
  1088. {
  1089. sig = m_pOutputPort->QueryInterface (IID_IDirectMusicPortDownload8,(void**)& m_PortDownload);
  1090. assert (SUCCEEDED (sig));
  1091.  
  1092. m_bSynthesizer = TRUE;
  1093.  
  1094. // 加载默认的DLS 波表.
  1095. LoadDefaultDLS ();
  1096.  
  1097. WCHAR szBuf[MAX_PATH]; // 47是口琴
  1098. sig = m_DLSCollection->EnumInstrument (instructid, (DWORD *)& m_SelInstructment, szBuf, sizeof (szBuf)/ sizeof (szBuf[0]));
  1099. assert (SUCCEEDED (sig));
  1100.  
  1101. SetGuidAndIndex (pt.guidPort);
  1102.  
  1103. ReleaseInstructment ();
  1104. sig = m_DLSCollection->GetInstrument (m_SelInstructment, & m_pInstrument);
  1105. assert (SUCCEEDED (sig));
  1106. sig = m_pInstrument->SetPatch (1);
  1107. assert (SUCCEEDED (sig));
  1108.  
  1109. DMUS_NOTERANGE t;
  1110. t.dwLowNote = 0;
  1111. t.dwHighNote = 127; // 标准midi调性范围.
  1112.  
  1113. sig = m_pOutputPort->DownloadInstrument (m_pInstrument,
  1114. &m_pDLSInstrument, & t, 1);// 调性组为1 ...
  1115. assert (SUCCEEDED (sig));
  1116. bInstruction = 1;
  1117. m_SelInstructment = instructid;
  1118. }
  1119. // 发送消息. 应用改变.
  1120. SendMidiMsg ( EncodeMidiMessage (0xC0, 0, bInstruction, 0));
  1121. }
  1122. CDirectMusic_ (void) {
  1123.  
  1124. initSettings ();
  1125.  
  1126. // 初始化 DLS加载器.
  1127. HRESULT sig = CoCreateInstance(CLSID_DirectMusicLoader,NULL,
  1128. CLSCTX_INPROC_SERVER,IID_IDirectMusicLoader8,(LPVOID*)& m_DLSloader);
  1129. assert (SUCCEEDED (sig));
  1130.  
  1131. // 重置
  1132. ZeroMemory(&m_OutputParams,sizeof(DMUS_PORTPARAMS8));
  1133. m_OutputParams.dwSize = sizeof(DMUS_PORTPARAMS8);
  1134.  
  1135. // 创建输入输出端口, 默认选择口琴乐器指令集
  1136. m_SelInstructment = 23;
  1137. m_bSynthesizer = FALSE;
  1138.  
  1139. // 刷新端口缓存
  1140. FlushOutPortCache ();
  1141.  
  1142. int nsel;
  1143. int nsize = m_OutputPortCache.size ();
  1144.  
  1145.  
  1146.  
  1147. assert (nsize> 0);
  1148. nsel = nsize >= 2 ? 2 : 0;
  1149. DMUS_PORTCAPS_T &pt = m_OutputPortCache[nsel];
  1150. pt.dwMaxChannelGroups = 1;
  1151. SetOutputPortInfos ( 0, 0, 0, ( (pt.dwEffectFlags & DMUS_EFFECT_REVERB) ? DMUS_EFFECT_REVERB : 0),0);
  1152.  
  1153. // 创建输出端口.
  1154. sig = directMusic_base->CreatePort (pt.guidPort, & m_OutputParams, & m_pOutputPort, NULL);
  1155. // 使其活跃.
  1156. sig = m_pOutputPort->Activate (TRUE);
  1157. assert (SUCCEEDED (sig));
  1158. // 获取参考时钟》
  1159. sig = m_pOutputPort->GetLatencyClock (& m_pClock);
  1160. assert (SUCCEEDED (sig));
  1161.  
  1162. // 创建音频缓冲
  1163. DMUS_BUFFERDESC BufferDesc; // Create the DirectMusic buffer to store MIDI messages
  1164. ZeroMemory(&BufferDesc,sizeof(DMUS_BUFFERDESC));
  1165. BufferDesc.dwSize = sizeof(DMUS_BUFFERDESC);
  1166. BufferDesc.guidBufferFormat = GUID_NULL;
  1167. BufferDesc.cbBuffer = DMUS_EVENT_SIZE(32); // at least 32 bytes to store messages
  1168. sig = CDirectMusic_::directMusic_base->CreateMusicBuffer(&BufferDesc,& m_DUS_soundbuffer,NULL);
  1169. assert (SUCCEEDED (sig));
  1170. sig = m_pOutputPort->QueryInterface (IID_IDirectMusicPortDownload8,(void**)& m_PortDownload);
  1171. assert (SUCCEEDED (sig));
  1172. DWORD bInstruction = 0;
  1173. DMUS_PORTCAPS t;
  1174. m_pOutputPort->GetCaps (& t);
  1175. assert (SUCCEEDED (sig));
  1176.  
  1177. // 通用波表和mapper一般23号是口琴
  1178. SetGuidAndIndex (pt.guidPort);
  1179. if ((pt.dwFlags & DMUS_PC_DLS) || (pt.dwFlags & DMUS_PC_DLS2))
  1180. {
  1181. m_bSynthesizer = TRUE;
  1182.  
  1183. // 加载默认的DLS 波表.
  1184. LoadDefaultDLS ();
  1185.  
  1186. WCHAR szBuf[MAX_PATH]; // 47是口琴
  1187. sig = m_DLSCollection->EnumInstrument (47, (DWORD *)& m_SelInstructment, szBuf, sizeof (szBuf)/ sizeof (szBuf[0]));
  1188. assert (SUCCEEDED (sig));
  1189.  
  1190. SetGuidAndIndex (pt.guidPort);
  1191.  
  1192. ReleaseInstructment ();
  1193. sig = m_DLSCollection->GetInstrument (m_SelInstructment, & m_pInstrument);
  1194. assert (SUCCEEDED (sig));
  1195. sig = m_pInstrument->SetPatch (1);
  1196. assert (SUCCEEDED (sig));
  1197.  
  1198. DMUS_NOTERANGE t;
  1199. t.dwLowNote = 0;
  1200. t.dwHighNote = 127; // 标准midi调性范围.
  1201.  
  1202. sig = m_pOutputPort->DownloadInstrument (m_pInstrument,
  1203. &m_pDLSInstrument, & t, 1);// 调性组为1 ...
  1204. assert (SUCCEEDED (sig));
  1205. bInstruction = 1;
  1206. m_SelInstructment = 47;
  1207. }
  1208. // 发送消息. 应用改变.
  1209. SendMidiMsg ( EncodeMidiMessage (0xC0, 0, bInstruction, 0));
  1210. // 不枚举输入,
  1211. // 破软件根本不会有人真的拿着外接设备连起来弹琴的...
  1212. // 而且处理输入更加复杂, 本身DirectMusic就是一个复杂的东西..
  1213. // 降低下难度...
  1214. // -----------------------------------------------------------------------
  1215.  
  1216.  
  1217.  
  1218.  
  1219.  
  1220.  
  1221.  
  1222.  
  1223.  
  1224.  
  1225.  
  1226.  
  1227. }
  1228. // 设置输出端口信息
  1229. void SetOutputPortInfos (
  1230. DWORD dwVoices,
  1231. DWORD dwAudioChannels,
  1232. DWORD dwChannelGroups,
  1233. DWORD dwEffectFlags,
  1234. DWORD dwSampleRate ) {
  1235.  
  1236. m_OutputParams.dwValidParams = 0;
  1237.  
  1238. if (dwVoices) m_OutputParams.dwValidParams = DMUS_PORTPARAMS_VOICES;
  1239. if (dwAudioChannels) m_OutputParams.dwValidParams |= DMUS_PORTPARAMS_AUDIOCHANNELS;
  1240. if (dwChannelGroups) m_OutputParams.dwValidParams |= DMUS_PORTPARAMS_CHANNELGROUPS;
  1241. if (dwEffectFlags) m_OutputParams.dwValidParams |= DMUS_PORTPARAMS_EFFECTS;
  1242. if (dwSampleRate) m_OutputParams.dwValidParams |= DMUS_PORTPARAMS_SAMPLERATE;
  1243.  
  1244. m_OutputParams.dwVoices = dwVoices;
  1245. m_OutputParams.dwAudioChannels = dwAudioChannels;
  1246. m_OutputParams.dwChannelGroups = dwChannelGroups;
  1247. m_OutputParams.dwEffectFlags = dwEffectFlags;
  1248. m_OutputParams.dwSampleRate = dwSampleRate;
  1249. }
  1250.  
  1251. // 获取指定输出端口的信息
  1252. HRESULT GetOutputPortInfos (DWORD dwNumPort, DMUS_PORTCAPS_T *lpInfoPort) {
  1253. HRESULT hr = -1;
  1254. DMUS_PORTCAPS portinf;
  1255. DWORD dwIndex = 0, dwNum = -1;
  1256.  
  1257. ZeroMemory(&portinf,sizeof(portinf));
  1258. portinf.dwSize = sizeof(DMUS_PORTCAPS);
  1259.  
  1260. while ((hr = directMusic_base->EnumPort(dwIndex++,&portinf))==S_OK)
  1261. {
  1262. if (portinf.dwClass == DMUS_PC_OUTPUTCLASS) dwNum++;
  1263. if (dwNum == dwNumPort) break;
  1264. }
  1265.  
  1266. if (SUCCEEDED(hr) && (hr!=S_FALSE))
  1267. {
  1268. ZeroMemory(lpInfoPort,sizeof(DMUS_PORTCAPS_T));
  1269. CopyMemory(&(lpInfoPort->guidPort),&portinf.guidPort,sizeof(GUID));
  1270.  
  1271. #ifdef _UNICODE
  1272. _tcscpy(lpInfoPort->szDescription,portinf.wszDescription);
  1273. #else
  1274. wcstombs(lpInfoPort->szDescription,portinf.wszDescription,DMUS_MAX_DESCRIPTION);
  1275. #endif
  1276.  
  1277. lpInfoPort->dwClass = portinf.dwClass;
  1278. lpInfoPort->dwEffectFlags = portinf.dwEffectFlags;
  1279. lpInfoPort->dwFlags = portinf.dwFlags;
  1280. lpInfoPort->dwMemorySize = portinf.dwMemorySize;
  1281. lpInfoPort->dwMaxAudioChannels = portinf.dwMaxAudioChannels;
  1282. lpInfoPort->dwMaxChannelGroups = portinf.dwMaxChannelGroups;
  1283. lpInfoPort->dwMaxVoices = portinf.dwMaxVoices;
  1284. lpInfoPort->dwType = portinf.dwType;
  1285. }
  1286. return hr;
  1287. }
  1288. // 标准midi编码消息.
  1289. // 参考: https://www.midi.org/specifications/item/table-1-summary-of-midi-message
  1290. //
  1291. // typedef struct DMUS_MIDI_PMSGG {
  1292. // DMUS_PMSG_PART
  1293. // BYTE bStatus;
  1294. // BYTE bByte1;
  1295. // BYTE bByte2;
  1296. // BYTE bPad[1];
  1297. // } DMUS_MIDI_PMSG;
  1298.  
  1299. static DWORD EncodeMidiMessage (BYTE cmd, BYTE chan, BYTE data, BYTE data2)
  1300. {
  1301. DWORD msg;
  1302. msg = cmd | chan;
  1303. msg |= ( data << 8);
  1304. msg |= (data2 << 16);
  1305. return msg;
  1306. }
  1307. static DWORD EncodeMidiMessage (BYTE status, BYTE data, BYTE data2)
  1308. {
  1309. DWORD msg = status;
  1310. msg |= ( data << 8);
  1311. msg |= (data2 << 16);
  1312. return msg;
  1313. }
  1314.  
  1315.  
  1316. static IDirectMusic8* directMusic_base; // DirectMusic 演奏对象COM根
  1317. static IDirectSound8* directSound_attach; // 附加的DirectSound对象
  1318. // 获取midi输入 or 端口数量
  1319. static int GetPortNums (DWORD portType) {
  1320.  
  1321. DMUS_PORTCAPS portinf;
  1322. DWORD dwIndex = 0, dwNum = 0;
  1323. HRESULT hr = -1;
  1324.  
  1325. ZeroMemory(&portinf,sizeof(portinf));
  1326. portinf.dwSize = sizeof(DMUS_PORTCAPS);
  1327.  
  1328. while ((hr = directMusic_base->EnumPort (dwIndex++, &portinf))==S_OK)
  1329. { if (portinf.dwClass == portType) dwNum++; }
  1330. assert (hr == S_FALSE || (hr == S_OK));
  1331.  
  1332. return dwNum;
  1333. }
  1334. static int GetInputPortNums (void) {
  1335. return GetPortNums (DMUS_PC_INPUTCLASS);
  1336. }
  1337. static int GetOutputPortNums (void) {
  1338. return GetPortNums (DMUS_PC_OUTPUTCLASS);
  1339. }
  1340. static void InitDirectMusic (HWND hWindow) {
  1341. HRESULT sig = CoCreateInstance (CLSID_DirectMusic,NULL,
  1342. CLSCTX_INPROC,IID_IDirectMusic8,(void**)& directMusic_base);
  1343. assert (SUCCEEDED (sig));
  1344. sig = directMusic_base->SetDirectSound (NULL, hWindow);
  1345. assert (SUCCEEDED (sig));
  1346. int nums = GetOutputPortNums ();
  1347. }
  1348. };
  1349.  
  1350. IDirectMusic8* CDirectMusic_::directMusic_base = NULL; // DirectMusic 演奏对象COM根
  1351. IDirectSound8* CDirectMusic_::directSound_attach = NULL; // 附加的DirectSound对象
  1352.  
  1353.  
  1354.  
  1355.  
  1356.  
  1357.  
  1358.  
  1359.  
  1360.  
  1361.  
  1362. // 全局变量集合
  1363. namespace GlobalObject {
  1364. static enum RES_ID {
  1365. ID_STATUS_BAR = 1007
  1366. };
  1367.  
  1368.  
  1369. static LONGLONG FreshPer = 60; // 每秒屏幕刷新的次数
  1370. static HWND hWindowMain; // 主窗口句柄
  1371. static TCHAR szClassName[] = _T ("midi piano class"); // 主类名
  1372. static TCHAR szCaption[] = _T ("midi piano"); // 标题
  1373. static UINT uiWindowStyle = WS_OVERLAPPEDWINDOW & ~ WS_SIZEBOX & ~WS_MAXIMIZE & ~WS_MAXIMIZEBOX;
  1374. static UINT uiWindowStyleEx = 0;
  1375. static LONGLONG liTiming ; // NT高精度计时器基测计数
  1376. static SIZE sClientSize = { 637, 240 }; // 客户区尺寸
  1377. static LONGLONG liStartTiming = 0;
  1378. static HINSTANCE instance = NULL;
  1379. static HWND hStatus = NULL; // 状态栏句柄
  1380. static GUID guidOutputPort; // 当前获得输出端口GUID标识.
  1381. static CDirectDraw ::graph_desc gd_piano;
  1382. static CDirectDraw *DirectDrawObj;
  1383. static CDirectMusic_ *DirectMusicObj;
  1384. static CDirectInput8 *DirectInput8Obj;
  1385. static TCHAR *piano = _T ("piano.png");
  1386. static int DlgPortId = 0;
  1387. static int DlgInstructId = 0;
  1388. static void ResetVel (HWND hDlg) {
  1389. SetDlgItemInt (hDlg, IDET_VELOCITY, DirectMusicObj->GetFixedVelocity (), FALSE);
  1390. }
  1391.  
  1392. static void ResetOutputPort (HWND hDlg, int outid, int instructment = -1) {
  1393. int id = 0, ic = outid;
  1394. std::vector <DMUS_PORTCAPS_T>&t = DirectMusicObj->GetOutPortCache ();
  1395. std::vector <DMUS_PORTCAPS_T>::iterator p= t.begin ();
  1396. DMUS_PORTCAPS_T *c;
  1397. ComboBox_ResetContent (GetDlgItem (hDlg, IDCB_OUTPORT));
  1398. ComboBox_ResetContent (GetDlgItem (hDlg, IDCB_INSTRUCTMENTS));
  1399. SendMessage (GetDlgItem (hDlg, IDCK_WINMM), BM_SETCHECK, BST_UNCHECKED, 0);
  1400. SendMessage (GetDlgItem (hDlg, IDCK_SYNTH), BM_SETCHECK, BST_UNCHECKED, 0);
  1401. SendMessage (GetDlgItem (hDlg, IDCK_SYNTH), BM_SETCHECK, BST_UNCHECKED, 0);
  1402. SendMessage (GetDlgItem (hDlg, IDCK_REVERB), BM_SETCHECK, BST_UNCHECKED, 0);
  1403. SendMessage (GetDlgItem (hDlg, IDCK_CHORUS), BM_SETCHECK, BST_UNCHECKED, 0);
  1404. SendMessage (GetDlgItem (hDlg, IDCK_DELAY), BM_SETCHECK, BST_UNCHECKED, 0);
  1405. SendMessage (GetDlgItem (hDlg, IDCK_DLS), BM_SETCHECK, BST_UNCHECKED, 0);
  1406. SendMessage (GetDlgItem (hDlg, IDCK_DLS2), BM_SETCHECK, BST_UNCHECKED, 0);
  1407. for (; p != t.end (); id ++, p++) {
  1408. ComboBox_InsertString (GetDlgItem (hDlg, IDCB_OUTPORT), -1, (*p).szDescription);
  1409. if (id == outid)
  1410. c = & (*p);
  1411. }
  1412. ComboBox_SetCurSel ( GetDlgItem (hDlg, IDCB_OUTPORT), ic);
  1413. if ((c->dwFlags & DMUS_PC_DLS) || (c->dwFlags & DMUS_PC_DLS2)) {
  1414. if ((c->dwFlags & DMUS_PC_DLS))
  1415. SendMessage (GetDlgItem (hDlg, IDCK_DLS), BM_SETCHECK, BST_CHECKED, 0);
  1416. if ((c->dwFlags & DMUS_PC_DLS2))
  1417. SendMessage (GetDlgItem (hDlg, IDCK_DLS2), BM_SETCHECK, BST_CHECKED, 0);
  1418. }
  1419. EnableWindow (GetDlgItem (hDlg, IDCK_DLS), FALSE);
  1420. EnableWindow (GetDlgItem (hDlg, IDCK_DLS2), FALSE);
  1421.  
  1422. // 设置合成器类型
  1423. switch (c->dwType) {
  1424. case DMUS_PORT_WINMM_DRIVER: // windows多媒体库渲染驱动.
  1425. EnableWindow (GetDlgItem (hDlg, IDCK_WINMM), TRUE);
  1426. SendMessage (GetDlgItem (hDlg, IDCK_WINMM), BM_SETCHECK, BST_CHECKED, 0);
  1427. break ;
  1428. case DMUS_PORT_USER_MODE_SYNTH: // 用户模式软件合成器
  1429. EnableWindow (GetDlgItem (hDlg, IDCK_SYNTH), TRUE);
  1430. SendMessage (GetDlgItem (hDlg, IDCK_SYNTH), BM_SETCHECK, BST_CHECKED, 0);
  1431. break ;
  1432. case DMUS_PORT_KERNEL_MODE: // 基于NT内核模式的WDM驱动模型
  1433. EnableWindow (GetDlgItem (hDlg, IDCK_SYNTH), TRUE);
  1434. SendMessage (GetDlgItem (hDlg, IDCK_SYNTH), BM_SETCHECK, BST_CHECKED, 0);
  1435. break ;
  1436. }
  1437. EnableWindow (GetDlgItem (hDlg, IDCK_SYNTH), FALSE);
  1438. EnableWindow (GetDlgItem (hDlg, IDCK_WDM), FALSE);
  1439. EnableWindow (GetDlgItem (hDlg, IDCK_WINMM), FALSE);
  1440. EnableWindow (GetDlgItem (hDlg, IDCK_REVERB), FALSE);
  1441. EnableWindow (GetDlgItem (hDlg, IDCK_DELAY), FALSE);
  1442. EnableWindow (GetDlgItem (hDlg, IDCK_CHORUS), FALSE);
  1443.  
  1444. if (c->dwEffectFlags & DMUS_EFFECT_REVERB) { // 默认DirectMusic效果 标准混响.
  1445. EnableWindow (GetDlgItem (hDlg, IDCK_REVERB), TRUE);
  1446. SendMessage (GetDlgItem (hDlg, IDCK_REVERB), BM_SETCHECK, BST_CHECKED, 0);
  1447. }
  1448. if (c->dwEffectFlags & DMUS_EFFECT_CHORUS) { // 默认DirectMusic效果 标准合唱.
  1449. EnableWindow (GetDlgItem (hDlg, IDCK_CHORUS), TRUE);
  1450. SendMessage (GetDlgItem (hDlg, IDCK_CHORUS), BM_SETCHECK, BST_CHECKED, 0);
  1451. }
  1452. if (c->dwEffectFlags & DMUS_EFFECT_DELAY) { // 默认DirectMusic效果 标准延迟.
  1453. EnableWindow (GetDlgItem (hDlg, IDCK_DELAY), TRUE);
  1454. SendMessage (GetDlgItem (hDlg, IDCK_DELAY), BM_SETCHECK, BST_CHECKED, 0);
  1455. }
  1456. if ((c->dwFlags & DMUS_PC_DLS) || (c->dwFlags & DMUS_PC_DLS2)) {
  1457. IDirectMusicCollection8 *dc;
  1458. DirectMusicObj->LoadDefaultDLS (& dc);
  1459. for (int id = 0; TRUE; id++) {
  1460. WCHAR wszInstName[MAX_PATH];
  1461. TCHAR szInstName[MAX_PATH];
  1462. DWORD patch;
  1463. int cs = _stprintf (szInstName, _T("%d "), id+1);
  1464. HRESULT sig =
  1465. dc->EnumInstrument (id, & patch, wszInstName, sizeof (wszInstName)/ sizeof (wszInstName[0]));
  1466. assert ( SUCCEEDED (sig));
  1467. if (sig == S_FALSE) break ;
  1468. # ifdef _UNICODE
  1469. _tcscpy (& szInstName[cs],wszInstName);
  1470. # else
  1471. wcstombs (& szInstName[cs],wszInstName,MAX_PATH);
  1472. # endif
  1473. ComboBox_InsertString (GetDlgItem (hDlg, IDCB_INSTRUCTMENTS), -1, szInstName);
  1474. }
  1475. DirectMusicObj->ReleaseDLS (dc);
  1476. } else {
  1477. for (int id = 0; id != sizeof (CUtil ::std_instruments_set)/ sizeof (CUtil ::std_instruments_set[0]); id++) {
  1478. ComboBox_InsertString ( GetDlgItem (hDlg, IDCB_INSTRUCTMENTS), -1, CUtil ::std_instruments_set[id]);
  1479. }
  1480. }
  1481. ComboBox_SetCurSel ( GetDlgItem (hDlg, IDCB_INSTRUCTMENTS), (instructment < 0) ?0:instructment);
  1482. }
  1483. static void ResetOutputPort (HWND hDlg, int instructment = -1) {
  1484. std::vector <DMUS_PORTCAPS_T>&t = DirectMusicObj->GetOutPortCache ();
  1485. std::vector <DMUS_PORTCAPS_T>::iterator p= t.begin ();
  1486. DMUS_PORTCAPS_T *c;
  1487. for (int id =0; p != t.end (); id ++, p++) {
  1488. if (DirectMusicObj->isEqualOutputPort ((*p).guidPort)) {
  1489. ResetOutputPort (hDlg, id, instructment);
  1490. return ;
  1491. }
  1492. }
  1493. }
  1494. static int GetOutportPortByGUID (GUID &guid) {
  1495. std::vector <DMUS_PORTCAPS_T>&t = DirectMusicObj->GetOutPortCache ();
  1496. std::vector <DMUS_PORTCAPS_T>::iterator p= t.begin ();
  1497. DMUS_PORTCAPS_T *c;
  1498. for (int id =0; p != t.end (); id ++, p++) {
  1499. if (IsEqualGUID (guid, (*p).guidPort)) {
  1500. return id;
  1501. }
  1502. }
  1503. return -1;
  1504. }
  1505.  
  1506. static INT_PTR WINAPI DlgCallback_IoInstructments_ (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
  1507. UNREFERENCED_PARAMETER(lParam);
  1508. switch (msg)
  1509. {
  1510. case WM_INITDIALOG:
  1511. // 枚举Midi输出输出端口/乐器指令集合.
  1512. ( (void (*) (HWND, int))ResetOutputPort) (hDlg, DirectMusicObj->GetInstructment ());
  1513. DlgInstructId = GetOutportPortByGUID (DirectMusicObj->GetOutportGUID ());
  1514. DlgPortId = DirectMusicObj->GetInstructment ();
  1515. EnableWindow (GetDlgItem (hDlg, IDBT_FLUSH_CACHE), FALSE);
  1516. SetDlgItemInt (hDlg, IDET_VELOCITY, DirectMusicObj->GetFixedVelocity (), FALSE);
  1517. return (INT_PTR)TRUE;
  1518.  
  1519. case WM_COMMAND:
  1520. WORD wCtlId = LOWORD (wParam);
  1521. WORD wCmdMessage = HIWORD (wParam);
  1522. switch (wCtlId) {
  1523. case IDOK:
  1524. case IDCANCEL:
  1525. if (wCtlId == IDOK) {
  1526. TCHAR szBuf[1024];
  1527. szBuf[0] =0;
  1528. GetWindowText (GetDlgItem (hDlg, IDBT_FLUSH_CACHE), szBuf, sizeof (szBuf)/ sizeof (szBuf[0]));
  1529. if (szBuf[0] == 0) {
  1530. MessageBox (NULL, _T ("Please set vel"), _T ("IOSettings"), MB_ICONERROR);
  1531. return INT_PTR(FALSE);
  1532. }
  1533. BOOL t;
  1534. DirectMusicObj->SetFixedVelocity ( GetDlgItemInt (hDlg, IDET_VELOCITY, & t, FALSE) & 0x7F);
  1535. // 重新设置端口.
  1536. int pt = ComboBox_GetCurSel (GetDlgItem (hDlg, IDCB_OUTPORT));
  1537. int instructment = ComboBox_GetCurSel (GetDlgItem (hDlg, IDCB_INSTRUCTMENTS));
  1538. DirectMusicObj->ResetOutport (pt, instructment, 0);
  1539. }
  1540. EndDialog (hDlg, LOWORD(wParam));
  1541. return (INT_PTR)TRUE;
  1542. case IDCB_OUTPORT:
  1543. case IDCB_INPUT_PORT:
  1544. switch (wCmdMessage) {
  1545. case CBN_SELCHANGE:
  1546. // 获取当前端口索引.
  1547. {
  1548. int id = ComboBox_GetCurSel ((HWND) lParam);
  1549. if (wCtlId == IDCB_OUTPORT) {
  1550. if (id != DlgPortId) {
  1551. DlgInstructId = 0;
  1552. DlgPortId = id;
  1553. ResetOutputPort (hDlg, id, 0);
  1554. }
  1555. } else {
  1556. DlgInstructId = id;
  1557. }
  1558. }
  1559. default:
  1560. break;
  1561. }
  1562. default:
  1563. break ;
  1564. }
  1565. break;
  1566. }
  1567. return (INT_PTR)FALSE;
  1568. }
  1569.  
  1570.  
  1571.  
  1572.  
  1573. static int OnCreate (HWND hWindow) {
  1574. // 禁用中文输入法
  1575. ImmDisableIME(-1);
  1576. // 添加状态栏基础设置
  1577. InitCommonControls();
  1578. // 添加 状态栏 输入端口/输出端口/指令集/效果/中音基调
  1579. hStatus = CreateStatusWindow ( WS_CHILD | WS_VISIBLE, _T (""),
  1580. hWindow, ID_STATUS_BAR);
  1581.  
  1582. UINT widths[2];
  1583. RECT rcClient;
  1584. GetClientRect (hStatus, &rcClient);
  1585. int status_height = rcClient.bottom - rcClient.top;
  1586.  
  1587. widths[0] = 180;
  1588. widths[1] = rcClient.right;
  1589. SendMessage (hStatus, SB_SETPARTS, (WPARAM)(sizeof widths / sizeof widths[0]), (LPARAM)widths);
  1590.  
  1591. DirectDrawObj = new CDirectDraw (hWindow, sClientSize, sClientSize);
  1592. DirectDrawObj->LoadImage (IDBITMAP_PNG_PIANO_S3, sClientSize.cx, sClientSize.cy, gd_piano);
  1593. DirectInput8Obj = new CDirectInput8 ();
  1594. DirectInput8Obj->InitDeviceKeyboard (hWindow);
  1595.  
  1596. // 初始化NT计数器频率
  1597. QueryPerformanceFrequency ((PLARGE_INTEGER) & liTiming);
  1598.  
  1599.  
  1600.  
  1601.  
  1602.  
  1603. // 读取位图
  1604.  
  1605.  
  1606. // 枚举DirectMusic输出端口
  1607.  
  1608.  
  1609.  
  1610.  
  1611.  
  1612.  
  1613. CUtil ::ReSizeClient (hWindow,
  1614. GlobalObject::sClientSize.cx,
  1615. GlobalObject::sClientSize.cy + status_height,
  1616. GlobalObject :: uiWindowStyle,
  1617. 0, TRUE);
  1618.  
  1619. MoveWindow (hStatus, 0, 0, 0, 0,TRUE);
  1620.  
  1621.  
  1622. return 0;
  1623. }
  1624.  
  1625.  
  1626.  
  1627. static LRESULT CALLBACK WndProc (HWND hWindow, UINT meesage, WPARAM wParam, LPARAM lParam) {\
  1628. WORD id;
  1629. switch (meesage) {
  1630. case WM_COMMAND:
  1631. id = LOWORD (wParam);
  1632. // 分析菜单
  1633. switch (id) {
  1634. case ID_IO_INSTRUCTMENTS:
  1635.  
  1636. // midi输入输出设置模态对话框
  1637. DialogBox (instance, MAKEINTRESOURCE (IDD_IO_INSTRUCTMENTS), hWindow, DlgCallback_IoInstructments_);
  1638. default:
  1639. break ;
  1640.  
  1641.  
  1642.  
  1643.  
  1644. }
  1645.  
  1646.  
  1647. case WM_CREATE:
  1648. OnCreate (hWindow);
  1649.  
  1650. return 0;
  1651. case WM_DESTROY:
  1652. // 退出Windows 消息循环
  1653. PostQuitMessage (0);
  1654. return 0;
  1655. case WM_KEYDOWN:
  1656. case WM_KEYUP:
  1657. case WM_CHAR:
  1658. return 0;
  1659. case WM_PAINT:
  1660. // 去除无效矩形防止重复 WM_PAINT, 除此之外不做任何处理
  1661. RECT rcUpdate;
  1662. GetUpdateRect (hWindow, & rcUpdate, NULL);
  1663. OutputDebugString (_T ("WM_PAINT hit !...\n"));
  1664. if ( rcUpdate.bottom >= GlobalObject ::sClientSize.cy) {
  1665. OutputDebugString (_T ("DrawStatusBar hit !...\n"));
  1666. break ;
  1667. } else {
  1668. ValidateRect (hWindow, NULL);
  1669. OutputDebugString (_T ("NoDraw hit !...\n"));
  1670. }
  1671. return 0;
  1672. case WM_ERASEBKGND:
  1673. // 返回非0表示已经擦除背景防止闪烁
  1674. // https://msdn.microsoft.com/en-us/library/ms648055(VS.85).aspx
  1675. return !0;
  1676. default:
  1677. break;
  1678. }
  1679. return DefWindowProc (hWindow, meesage, wParam, lParam);
  1680. }
  1681. };
  1682.  
  1683. void doMain () {
  1684.  
  1685. // 测试是否需要更新画面
  1686. LONGLONG nCompFrep = GlobalObject ::liTiming / GlobalObject::FreshPer;
  1687. LONGLONG nCountCurrent;
  1688. QueryPerformanceCounter ((PLARGE_INTEGER) &nCountCurrent);
  1689. LONGLONG nTickProc = nCountCurrent - GlobalObject::liStartTiming;
  1690. BOOL bUpdateDraw = FALSE;
  1691. OutputDebugString (_T("HIT\n"));
  1692.  
  1693. if ( nTickProc >= nCompFrep) {
  1694. bUpdateDraw = TRUE;
  1695. GlobalObject::liStartTiming = nCountCurrent;
  1696. }
  1697.  
  1698.  
  1699.  
  1700.  
  1701. if (bUpdateDraw != FALSE) {
  1702.  
  1703.  
  1704.  
  1705.  
  1706.  
  1707.  
  1708.  
  1709.  
  1710.  
  1711.  
  1712. CDirectDraw ::graph_desc gd;
  1713. // 锁表面
  1714. GlobalObject::DirectDrawObj->lockBuffer (NULL, gd);
  1715.  
  1716. CUtil ::CSurfaceCopy32 (gd.__vptr, 0, 0,
  1717. gd.pitch, GlobalObject ::gd_piano.__vptr, 0, 0,
  1718. GlobalObject ::gd_piano.pitch, GlobalObject ::sClientSize.cx,GlobalObject ::sClientSize.cy);
  1719.  
  1720. GlobalObject ::DirectInput8Obj->PollBuffer ();
  1721. # define PRIVATE_UNWIND(id)\
  1722. if (GlobalObject ::DirectInput8Obj->isPressedFirst (DIK_F##id))\
  1723. { GlobalObject::DirectMusicObj->SetMiddleOctave (id); \
  1724. SendMessage (GlobalObject::hStatus, SB_SETTEXT, (WPARAM)0, (LPARAM)_T ( "MiddleOctave:" )_T(#id)); }
  1725.  
  1726. PRIVATE_UNWIND (1);
  1727. PRIVATE_UNWIND (2);
  1728. PRIVATE_UNWIND (3);
  1729. PRIVATE_UNWIND (4);
  1730. PRIVATE_UNWIND (5);
  1731. PRIVATE_UNWIND (6);
  1732. PRIVATE_UNWIND (7);
  1733. PRIVATE_UNWIND (8);
  1734. PRIVATE_UNWIND (9);
  1735. PRIVATE_UNWIND (10);
  1736.  
  1737. TCHAR szBuf[1024];
  1738. int pos = 0;
  1739. BYTE oct =GlobalObject ::DirectMusicObj->GetFixedVelocity () & 0x7F;
  1740. for (int id= 0; id != sizeof (CPianoDraw__ ::keyboard_mapper)/ sizeof (CPianoDraw__ ::keyboard_mapper[0]); id++) {
  1741. struct CPianoDraw__::dummt_ &c = CPianoDraw__ ::keyboard_mapper[id];
  1742. int mask = GlobalObject ::DirectInput8Obj->getMask (c.mapDIK);
  1743. if ( mask & CDirectInput8 ::JP_MASK_PRESS)
  1744. { CPianoDraw__ :: drawPiano (gd, c.octave_step, c.note);
  1745. int n = GlobalObject::DirectMusicObj->GetMiddleOctave () + c.octave_step - 1;
  1746. int cs = 12*n+c.midi_pos;
  1747. cs &= 127;
  1748. if ( ! (mask & CDirectInput8 ::JP_MASK_LAST))
  1749.  
  1750. {
  1751. GlobalObject ::DirectMusicObj->SendMidiMsg ( GlobalObject ::DirectMusicObj->EncodeMidiMessage (0x90, 0, cs, oct));
  1752. }
  1753. // 把按键信息推入缓冲
  1754. int nc = _tcslen (c.harmonica_scale);
  1755. memcpy (& szBuf[pos], c.harmonica_scale, nc * sizeof (TCHAR));
  1756. pos += nc;
  1757. }
  1758. else
  1759. {
  1760. int n = GlobalObject::DirectMusicObj->GetMiddleOctave () + c.octave_step - 1;
  1761. int cs = 12*n+c.midi_pos;
  1762. cs &= 127;
  1763. if ( ! (mask & CDirectInput8 ::JP_MASK_LAST))
  1764.  
  1765. {
  1766. GlobalObject ::DirectMusicObj->SendMidiMsg ( GlobalObject ::DirectMusicObj->EncodeMidiMessage (0x80, 0, cs, oct));
  1767. }
  1768. }
  1769.  
  1770. }
  1771. if (pos != 0) {
  1772. szBuf[pos] = 0;
  1773. SendMessage (GlobalObject::hStatus, SB_SETTEXT, (WPARAM)1, (LPARAM)szBuf);
  1774. }
  1775. // 解锁表面
  1776. GlobalObject::DirectDrawObj->unlockBuffer ();
  1777. }
  1778.  
  1779.  
  1780.  
  1781.  
  1782. if (bUpdateDraw != FALSE) {
  1783. POINT ptOrg = { 0, 0 };
  1784. SIZE sSize = { GlobalObject ::sClientSize.cx, GlobalObject ::sClientSize.cy};
  1785. GlobalObject::DirectDrawObj->BlitBtoV (NULL, NULL, NULL);
  1786. GlobalObject::DirectDrawObj->postRender (ptOrg, ptOrg, sSize);
  1787.  
  1788. }
  1789. }
  1790.  
  1791.  
  1792.  
  1793.  
  1794.  
  1795.  
  1796. int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
  1797. PSTR szCmdLine, int iCmdShow)
  1798. {
  1799. MSG msg ;
  1800. HRESULT sig = S_OK;
  1801. WNDCLASS wndclass = { CS_HREDRAW | CS_VREDRAW,
  1802. GlobalObject :: WndProc, 0, 0, hInstance,
  1803. LoadIcon (NULL, IDI_APPLICATION),
  1804. LoadCursor (NULL, IDC_ARROW),
  1805. (HBRUSH) GetStockObject (NULL_BRUSH),
  1806. (LPCTSTR) MAKEINTRESOURCE (IDRM_MAIN), GlobalObject ::szClassName };
  1807.  
  1808. if (!RegisterClass (&wndclass)) {
  1809. MessageBox ( NULL, TEXT ("This program requires Windows NT!"),
  1810. GlobalObject::szClassName, MB_ICONERROR) ;
  1811. return 0 ;
  1812. }
  1813.  
  1814. CoInitialize (NULL); // 初始化COM (DirectMusic).
  1815.  
  1816. CDirectDraw ::InitDirect3D ();
  1817. CDirectInput8 ::InitDInput8 ();
  1818.  
  1819. GlobalObject ::instance = hInstance;
  1820. GlobalObject ::hWindowMain = CreateWindow ( GlobalObject::szClassName,
  1821. GlobalObject ::szCaption,
  1822. GlobalObject :: uiWindowStyle,
  1823. CW_USEDEFAULT, CW_USEDEFAULT,
  1824. CW_USEDEFAULT,
  1825. CW_USEDEFAULT, NULL,
  1826. NULL, hInstance,
  1827. NULL) ;
  1828.  
  1829.  
  1830. // 初始化 DirectMusic COM根.
  1831. CDirectMusic_::InitDirectMusic (GlobalObject ::hWindowMain);
  1832.  
  1833.  
  1834.  
  1835.  
  1836.  
  1837.  
  1838.  
  1839.  
  1840.  
  1841.  
  1842.  
  1843. // create direct3d 9
  1844. // sm_Direct3D9_root = Direct3DCreate9 (DIRECT3D_VERSION);
  1845. //assert (sm_Direct3D9_root != NULL);
  1846.  
  1847. // create device
  1848. // D3DPRESENT_PARAMETERS d3dpp;
  1849. // ResetD3dpp (d3dpp, hwnd, 0, 0);
  1850. HRESULT si = 0;
  1851. // HRESULT si = sm_Direct3D9_root->CreateDevice (0,
  1852. // D3DDEVTYPE_HAL,
  1853. // hwnd,
  1854. // D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, & sm_Direct3D9_device);
  1855. assert (SUCCEEDED (si));
  1856. //si = sm_Direct3D9_device->CreateOffscreenPlainSurface (256, 256, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM,
  1857. // & sm_Direct3D9_surface, NULL);
  1858. assert (SUCCEEDED (si));
  1859.  
  1860.  
  1861. // 创建DirectMusic对象
  1862. GlobalObject :: DirectMusicObj = new CDirectMusic_ ();
  1863. TCHAR szBuf[32];
  1864. _stprintf (szBuf, _T ("MiddleOctave:%d"), GlobalObject :: DirectMusicObj->GetMiddleOctave ());
  1865. SendMessage (GlobalObject::hStatus, SB_SETTEXT, (WPARAM)0, (LPARAM)szBuf);
  1866.  
  1867. ShowWindow (GlobalObject ::hWindowMain, iCmdShow) ;
  1868. UpdateWindow (GlobalObject ::hWindowMain) ;
  1869. for (;;)
  1870. {
  1871. // 取出消息, 没有直接跳过.
  1872. while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  1873. {
  1874. if (msg.message == WM_QUIT)
  1875. return TRUE;
  1876. TranslateMessage(&msg);
  1877. DispatchMessage (&msg);
  1878. }
  1879. // 处理我们想要做的事情.
  1880. doMain ();
  1881. }
  1882. CDirectDraw ::UninitDirect3D ();
  1883. CDirectInput8 ::UninitDInput8 ();
  1884. return msg.wParam ;
  1885. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement