Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1131 lines
36 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Copyright (c) 1998-2001 Microsoft Corporation
  4. //
  5. // File: dmtempl.cpp
  6. //
  7. //--------------------------------------------------------------------------
  8. // DMTempl.cpp : Implementation of CDMTempl
  9. #include "DMTempl.h"
  10. #include <comdef.h>
  11. #include "dmusici.h"
  12. #include "dmusicf.h"
  13. #include "..\dmstyle\iostru.h"
  14. #include "debug.h"
  15. #include "..\shared\Validate.h"
  16. void TemplateStruct::AddIntro(TList<PlayChord>& PlayList, int nIntroLength)
  17. {
  18. TListItem<TemplateCommand> *pCommand = new TListItem<TemplateCommand>;
  19. if (pCommand)
  20. {
  21. BOOL fMerge = FALSE;
  22. TemplateCommand& rCommand = pCommand->GetItemValue();
  23. rCommand.m_nMeasure = 0;
  24. rCommand.m_dwChord = 0;
  25. rCommand.m_Command.bCommand = DMUS_COMMANDT_INTRO;
  26. rCommand.m_Command.bGrooveLevel = 0;
  27. rCommand.m_Command.bGrooveRange = 0;
  28. rCommand.m_Command.bRepeatMode = DMUS_PATTERNT_RANDOM;
  29. TListItem<PlayChord> *pChord = PlayList.GetHead();
  30. for (; pChord; pChord = pChord->GetNext())
  31. {
  32. pChord->GetItemValue().m_nMeasure += (short)nIntroLength;
  33. }
  34. TListItem<TemplateCommand> *pScan = m_CommandList.GetHead();
  35. for (; pScan; pScan = pScan->GetNext())
  36. {
  37. TemplateCommand& rScan = pScan->GetItemValue();
  38. if (rScan.m_nMeasure >= nIntroLength || !rScan.m_dwChord)
  39. rScan.m_nMeasure += (short)nIntroLength;
  40. else if (rScan.m_Command.bGrooveLevel != 0 || rScan.m_Command.bCommand == DMUS_COMMANDT_END)
  41. {
  42. rCommand.m_dwChord = rScan.m_dwChord;
  43. rScan.m_dwChord = 0;
  44. rScan.m_nMeasure += (short)nIntroLength;
  45. }
  46. else // merge with existing command
  47. {
  48. rScan.m_Command.bCommand = DMUS_COMMANDT_INTRO;
  49. rScan.m_Command.bGrooveLevel = 0;
  50. rScan.m_Command.bGrooveRange = 0;
  51. rScan.m_Command.bRepeatMode = DMUS_PATTERNT_RANDOM;
  52. fMerge = TRUE;
  53. }
  54. }
  55. m_nMeasures += (short)nIntroLength;
  56. if (fMerge)
  57. delete pCommand;
  58. else
  59. m_CommandList.AddHead(pCommand);
  60. }
  61. }
  62. void TemplateStruct::AddIntro(bool f1Bar, int nLength)
  63. {
  64. TListItem<TemplateCommand> *pCommand = new TListItem<TemplateCommand>;
  65. if (pCommand)
  66. {
  67. BOOL fMerge = FALSE;
  68. TemplateCommand& rCommand = pCommand->GetItemValue();
  69. rCommand.m_nMeasure = 0;
  70. rCommand.m_dwChord = 0;
  71. rCommand.m_Command.bCommand = DMUS_COMMANDT_INTRO;
  72. rCommand.m_Command.bGrooveLevel = 0;
  73. rCommand.m_Command.bGrooveRange = 0;
  74. rCommand.m_Command.bRepeatMode = DMUS_PATTERNT_RANDOM;
  75. TListItem<TemplateCommand> *pScan = m_CommandList.GetHead();
  76. for (; pScan; pScan = pScan->GetNext())
  77. {
  78. TemplateCommand& rScan = pScan->GetItemValue();
  79. if (rScan.m_nMeasure > 0 || !rScan.m_dwChord)
  80. rScan.m_nMeasure += (short)nLength;
  81. else if ( !f1Bar &&
  82. (rScan.m_Command.bGrooveLevel != 0 ||
  83. rScan.m_Command.bCommand != DMUS_COMMANDT_GROOVE) )
  84. {
  85. rCommand.m_dwChord = rScan.m_dwChord;
  86. rScan.m_dwChord = 0;
  87. rScan.m_nMeasure += (short)nLength;
  88. }
  89. else // merge with existing command
  90. {
  91. rScan.m_Command.bCommand = DMUS_COMMANDT_INTRO;
  92. rScan.m_Command.bGrooveLevel = 0;
  93. rScan.m_Command.bGrooveRange = 0;
  94. rScan.m_Command.bRepeatMode = DMUS_PATTERNT_RANDOM;
  95. fMerge = TRUE;
  96. }
  97. }
  98. if (!f1Bar) m_nMeasures += (short)nLength;
  99. if (fMerge)
  100. delete pCommand;
  101. else
  102. m_CommandList.AddHead(pCommand);
  103. }
  104. }
  105. void TemplateStruct::AddEnd(int nLength)
  106. {
  107. TListItem<TemplateCommand> *pCommand;
  108. TListItem<TemplateCommand> *pScan = m_CommandList.GetHead();
  109. for (; pScan; pScan = pScan->GetNext())
  110. {
  111. if (m_nMeasures - nLength == pScan->GetItemValue().m_nMeasure) break;
  112. }
  113. pCommand = (pScan) ? pScan : new TListItem<TemplateCommand>;
  114. if (pCommand)
  115. {
  116. TemplateCommand& rCommand = pCommand->GetItemValue();
  117. rCommand.m_nMeasure = m_nMeasures - nLength;
  118. if (!pScan || pScan->GetItemValue().m_nMeasure > 1) // otherwise keep the existing signpost
  119. {
  120. rCommand.m_dwChord = 0;
  121. }
  122. rCommand.m_Command.bCommand = DMUS_COMMANDT_END;
  123. rCommand.m_Command.bGrooveLevel = 0;
  124. rCommand.m_Command.bGrooveRange = 0;
  125. rCommand.m_Command.bRepeatMode = DMUS_PATTERNT_RANDOM;
  126. if (!pScan) m_CommandList.AddTail(pCommand);
  127. }
  128. }
  129. void TemplateStruct::FillInGrooveLevels()
  130. {
  131. BYTE bLastGrooveLevel = 62;
  132. TListItem<TemplateCommand>* pCommands = m_CommandList.GetHead();
  133. for(; pCommands; pCommands = pCommands->GetNext())
  134. {
  135. TemplateCommand& rCommand = pCommands->GetItemValue();
  136. if (rCommand.m_Command.bGrooveLevel == 0)
  137. {
  138. rCommand.m_Command.bGrooveLevel = bLastGrooveLevel;
  139. }
  140. else
  141. {
  142. bLastGrooveLevel = rCommand.m_Command.bGrooveLevel;
  143. }
  144. }
  145. }
  146. void TemplateStruct::IncorporateTemplate(
  147. short nMeasure, TemplateStruct* pTemplate, short nDirection)
  148. {
  149. if (!pTemplate) return;
  150. TListItem<TemplateCommand>* pCommands = pTemplate->m_CommandList.GetHead();
  151. for(; pCommands; pCommands = pCommands->GetNext())
  152. {
  153. TemplateCommand& rCommand = pCommands->GetItemValue();
  154. TListItem<TemplateCommand> *pNew = new TListItem<TemplateCommand>;
  155. if (pNew)
  156. {
  157. TemplateCommand& rNew = pNew->GetItemValue();
  158. rNew.m_nMeasure = rCommand.m_nMeasure + (short)nMeasure;
  159. ChangeCommand(rNew.m_Command, rCommand.m_Command, nDirection);
  160. rNew.m_dwChord = rCommand.m_dwChord;
  161. m_CommandList.AddHead(pNew);
  162. }
  163. }
  164. }
  165. void TemplateStruct::InsertCommand(TListItem<TemplateCommand> *pCommand, BOOL fIsCommand)
  166. {
  167. TListItem<TemplateCommand> *pScan;
  168. if( !pCommand )
  169. {
  170. return;
  171. }
  172. pCommand->SetNext(NULL);
  173. TemplateCommand& rCommand = pCommand->GetItemValue();
  174. pScan = m_CommandList.GetHead();
  175. if (pScan)
  176. {
  177. for (; pScan; pScan = pScan->GetNext())
  178. {
  179. TemplateCommand& rScan = pScan->GetItemValue();
  180. if (rScan.m_nMeasure == rCommand.m_nMeasure)
  181. {
  182. if (fIsCommand)
  183. {
  184. rScan.m_dwChord = 0;
  185. rScan.m_Command.bCommand = rCommand.m_Command.bCommand;
  186. rScan.m_Command.bGrooveLevel = rCommand.m_Command.bGrooveLevel;
  187. rScan.m_Command.bGrooveRange = rCommand.m_Command.bGrooveRange;
  188. rScan.m_Command.bRepeatMode = rCommand.m_Command.bRepeatMode;
  189. }
  190. else
  191. {
  192. rScan.m_dwChord = rCommand.m_dwChord;
  193. rScan.m_Command.bCommand = DMUS_COMMANDT_GROOVE;
  194. rScan.m_Command.bGrooveLevel = 0;
  195. rScan.m_Command.bGrooveRange = 0;
  196. rScan.m_Command.bRepeatMode = DMUS_PATTERNT_RANDOM;
  197. }
  198. delete pCommand;
  199. return;
  200. }
  201. if (rScan.m_nMeasure > rCommand.m_nMeasure)
  202. {
  203. m_CommandList.InsertBefore(pScan, pCommand);
  204. break;
  205. }
  206. }
  207. }
  208. if (!pScan)
  209. {
  210. m_CommandList.AddTail(pCommand);
  211. }
  212. }
  213. void TemplateStruct::AddCommand(int nMeasure, DWORD dwCommand)
  214. {
  215. TListItem<TemplateCommand>* pCommand = new TListItem<TemplateCommand>;
  216. if (pCommand)
  217. {
  218. TemplateCommand& rCommand = pCommand->GetItemValue();
  219. rCommand.m_nMeasure = (short)nMeasure;
  220. rCommand.m_Command.bGrooveRange = 0;
  221. rCommand.m_Command.bRepeatMode = DMUS_PATTERNT_RANDOM;
  222. switch (dwCommand)
  223. {
  224. case PF_FILL:
  225. rCommand.m_Command.bCommand = DMUS_COMMANDT_FILL;
  226. rCommand.m_Command.bGrooveLevel = 0;
  227. break;
  228. case PF_INTRO:
  229. rCommand.m_Command.bCommand = DMUS_COMMANDT_INTRO;
  230. rCommand.m_Command.bGrooveLevel = 0;
  231. break;
  232. case PF_BREAK:
  233. rCommand.m_Command.bCommand = DMUS_COMMANDT_BREAK;
  234. rCommand.m_Command.bGrooveLevel = 0;
  235. break;
  236. case PF_END:
  237. rCommand.m_Command.bCommand = DMUS_COMMANDT_END;
  238. rCommand.m_Command.bGrooveLevel = 0;
  239. break;
  240. case PF_A:
  241. rCommand.m_Command.bCommand = DMUS_COMMANDT_GROOVE;
  242. rCommand.m_Command.bGrooveLevel = 12;
  243. break;
  244. case PF_B:
  245. rCommand.m_Command.bCommand = DMUS_COMMANDT_GROOVE;
  246. rCommand.m_Command.bGrooveLevel = 37;
  247. break;
  248. case PF_C:
  249. rCommand.m_Command.bCommand = DMUS_COMMANDT_GROOVE;
  250. rCommand.m_Command.bGrooveLevel = 62;
  251. break;
  252. case PF_D:
  253. rCommand.m_Command.bCommand = DMUS_COMMANDT_GROOVE;
  254. rCommand.m_Command.bGrooveLevel = 87;
  255. break;
  256. default: // default to a Groove C
  257. rCommand.m_Command.bCommand = DMUS_COMMANDT_GROOVE;
  258. rCommand.m_Command.bGrooveLevel = 62;
  259. }
  260. InsertCommand( pCommand, TRUE );
  261. }
  262. }
  263. void TemplateStruct::AddChord(int nMeasure, DWORD dwChord)
  264. {
  265. TListItem<TemplateCommand>* pCommand = new TListItem<TemplateCommand>;
  266. if (pCommand)
  267. {
  268. pCommand->GetItemValue().m_nMeasure = (short)nMeasure;
  269. pCommand->GetItemValue().m_dwChord = dwChord;
  270. InsertCommand( pCommand, FALSE );
  271. }
  272. }
  273. int WeightedRand(int nRange)
  274. /* This randomly chooses a number within nrange. However, it heavily
  275. weights in favor of the first index, which has twice the chance
  276. of the second index, which has twice the chance of the third...
  277. */
  278. {
  279. int nTotal = 0;
  280. int index;
  281. unsigned int nGuess;
  282. if (nRange <= 0 || nRange > 15) return(0); // out of range.
  283. for (index = 0;index < nRange; index++)
  284. {
  285. nTotal += (1 << index);
  286. }
  287. nGuess = rand() % nTotal;
  288. nGuess++;
  289. for (;nGuess;index--)
  290. {
  291. nGuess = nGuess >> 1;
  292. }
  293. return(index);
  294. }
  295. void TemplateStruct::CreateSignPosts()
  296. {
  297. // First, figure out how many different sign posts we should use.
  298. // Should be the number of bits in measures minus two. Min is one.
  299. // For example, 8 measures gets us 2 sign posts.
  300. int nSPCount = -2;
  301. int nCopy = m_nMeasures;
  302. m_CommandList.RemoveAll();
  303. while (nCopy)
  304. {
  305. nSPCount++;
  306. nCopy = nCopy >> 1;
  307. }
  308. if (nSPCount < 1) nSPCount = 1;
  309. if (nSPCount > 7) nSPCount = 7;
  310. // Now, choose some signposts. We choose from the following set:
  311. // 1, A, C, E, B, D, F. Randomly, but heavily weighted towards the start
  312. // of the set.
  313. static DWORD adwSource[7] = { DMUS_SIGNPOSTF_1, DMUS_SIGNPOSTF_A, DMUS_SIGNPOSTF_C, DMUS_SIGNPOSTF_E, DMUS_SIGNPOSTF_B, DMUS_SIGNPOSTF_D, DMUS_SIGNPOSTF_F };
  314. DWORD adwChoice[7];
  315. DWORD adwSign[7];
  316. int anLength[7];
  317. DWORD dwLastChord;
  318. int index;
  319. for (index = 0;index < 7;index++)
  320. {
  321. adwChoice[index] = adwSource[index];
  322. adwSign[index] = 0;
  323. if (rand() % 3) anLength[index] = 4;
  324. else anLength[index] = 2;
  325. }
  326. if (rand() % 2) anLength[0] = 4;
  327. for (index = 0;index < nSPCount;index++)
  328. {
  329. int nPosition;
  330. int nScan = 0;
  331. if (index) nPosition = WeightedRand(7 - index);
  332. else nPosition = WeightedRand(3);
  333. for (;nScan < 7;nScan++)
  334. {
  335. if (adwChoice[nScan])
  336. {
  337. if (!nPosition)
  338. {
  339. adwSign[index] = adwChoice[nScan];
  340. if (rand() % 2) adwSign[index] |= DMUS_SIGNPOSTF_CADENCE;
  341. adwChoice[nScan] = 0;
  342. break;
  343. }
  344. nPosition--;
  345. }
  346. }
  347. }
  348. AddChord(0,dwLastChord = adwSign[0]);
  349. int nLast = 0;
  350. for (index = 0;index < m_nMeasures;)
  351. {
  352. DWORD dwCadence = 0;
  353. DWORD dwChord;
  354. index += anLength[nLast];
  355. if (index >= (m_nMeasures - 1))
  356. {
  357. if (rand() % 3) AddChord(m_nMeasures - 1,DMUS_SIGNPOSTF_1 | dwCadence);
  358. else AddChord(m_nMeasures - 1,adwSign[0] | dwCadence);
  359. break;
  360. }
  361. dwChord = adwSign[nLast = WeightedRand(nSPCount)];
  362. if (dwChord == dwLastChord)
  363. {
  364. dwChord = adwSign[nLast = WeightedRand(nSPCount)];
  365. }
  366. AddChord(index,dwChord | dwCadence);
  367. dwLastChord = dwChord;
  368. }
  369. }
  370. static void GrooveRange(TemplateStruct *pTemplate,int nStartm,int nEndm,
  371. int nStartg,int nEndg,BOOL fRandom)
  372. {
  373. static BYTE abGrooveLevels[4] = { 12, 37, 62, 87 };
  374. TListItem<TemplateCommand> *pCommand = pTemplate->m_CommandList.GetHead();
  375. TListItem<TemplateCommand> *pLast = NULL;
  376. int nRangem = nEndm - nStartm;
  377. int nRangeg = nEndg - nStartg;
  378. BYTE bLastGrooveLevel = 0;
  379. int nLastGroove = -1;
  380. int nLastMeasure = 0;
  381. for (; pCommand; pCommand = pCommand->GetNext())
  382. {
  383. TemplateCommand& rCommand = pCommand->GetItemValue();
  384. if (rCommand.m_Command.bCommand == DMUS_COMMANDT_GROOVE &&
  385. rCommand.m_Command.bGrooveLevel > 0)
  386. {
  387. bLastGrooveLevel = rCommand.m_Command.bGrooveLevel;
  388. nLastMeasure = rCommand.m_nMeasure;
  389. }
  390. if (rCommand.m_nMeasure >= nStartm)
  391. {
  392. if (rCommand.m_nMeasure >= nEndm) break;
  393. int nGroove;
  394. TListItem<TemplateCommand> *pNext = pCommand->GetNext();
  395. if (pNext)
  396. {
  397. nGroove =
  398. ((pNext->GetItemValue().m_nMeasure + rCommand.m_nMeasure ) >> 1) - nStartm;
  399. }
  400. else
  401. {
  402. nGroove = rCommand.m_nMeasure - nStartm;
  403. }
  404. if (fRandom)
  405. {
  406. nGroove = rand() % 3;
  407. nGroove += nLastGroove - 1;
  408. if (nGroove > 3) nGroove = 2;
  409. if (nGroove < 0) nGroove = 1;
  410. }
  411. else
  412. {
  413. nGroove *= nRangeg;
  414. nGroove += (nRangem >> 1);
  415. nGroove /= nRangem;
  416. nGroove += nStartg;
  417. }
  418. if ((nGroove >= 0) && (nGroove < 4))
  419. {
  420. if (abGrooveLevels[nGroove] != bLastGrooveLevel)
  421. {
  422. if (nLastGroove >= 0)
  423. {
  424. if (nLastGroove > nGroove) nGroove = nLastGroove - 1;
  425. else if (nLastGroove < nGroove) nGroove = nLastGroove + 1;
  426. }
  427. rCommand.m_Command.bGrooveLevel = abGrooveLevels[nGroove];
  428. rCommand.m_Command.bGrooveRange = 0;
  429. bLastGrooveLevel = abGrooveLevels[nGroove];
  430. nLastMeasure = rCommand.m_nMeasure;
  431. nLastGroove = nGroove;
  432. }
  433. else if (rCommand.m_nMeasure > (nLastMeasure + 6))
  434. {
  435. nGroove += ((rand() % 3) - 1);
  436. if (nGroove < 0) nGroove += 2;
  437. if (nGroove > 3) nGroove -= 2;
  438. if (!nRangeg)
  439. {
  440. if ((nGroove < nLastGroove) && (nGroove <= nStartg))
  441. {
  442. if (rand() % 2) nGroove++;
  443. }
  444. }
  445. if (abGrooveLevels[nGroove] != bLastGrooveLevel)
  446. {
  447. rCommand.m_Command.bGrooveLevel = abGrooveLevels[nGroove];
  448. rCommand.m_Command.bGrooveRange = 0;
  449. bLastGrooveLevel = abGrooveLevels[nGroove];
  450. nLastMeasure = rCommand.m_nMeasure;
  451. nLastGroove = nGroove;
  452. }
  453. }
  454. }
  455. }
  456. }
  457. }
  458. void TemplateStruct::CreateEmbellishments(WORD shape, int nFillLength, int nBreakLength)
  459. {
  460. // Put fills in. Scan forward through the list, placing fills
  461. // just prior to sign post changes. Each time, move forward a
  462. // random count.
  463. TListItem<TemplateCommand> *pCommand;
  464. BYTE bLastGroove = 0;
  465. BOOL fAddMore = FALSE;
  466. int nStartg, nEndg;
  467. switch (shape)
  468. {
  469. case DMUS_SHAPET_FALLING:
  470. nStartg = 3;
  471. nEndg = 0;
  472. break;
  473. case DMUS_SHAPET_LEVEL:
  474. nStartg = 2;
  475. nEndg = 2;
  476. fAddMore = TRUE;
  477. break;
  478. case DMUS_SHAPET_LOOPABLE:
  479. nStartg = 2;
  480. nEndg = 2;
  481. fAddMore = TRUE;
  482. break;
  483. case DMUS_SHAPET_LOUD:
  484. nStartg = 3;
  485. nEndg = 3;
  486. fAddMore = TRUE;
  487. break;
  488. case DMUS_SHAPET_QUIET:
  489. nStartg = 0;
  490. nEndg = 1;
  491. fAddMore = TRUE;
  492. break;
  493. case DMUS_SHAPET_PEAKING:
  494. nStartg = 0;
  495. nEndg = 3;
  496. GrooveRange(this, 0, m_nMeasures >> 1, nStartg, nEndg, FALSE);
  497. nStartg = 3;
  498. nEndg = 0;
  499. GrooveRange(this, m_nMeasures >> 1, m_nMeasures - 1, nStartg, nEndg, FALSE);
  500. nStartg = 0;
  501. nEndg = 0;
  502. break;
  503. case DMUS_SHAPET_RANDOM:
  504. nStartg = 0;
  505. nEndg = 0;
  506. GrooveRange(this, 0, m_nMeasures - 1, nStartg, nEndg, TRUE);
  507. break;
  508. case DMUS_SHAPET_RISING:
  509. nStartg = 0;
  510. nEndg = 3;
  511. break;
  512. case DMUS_SHAPET_SONG:
  513. default:
  514. nStartg = 2;
  515. nEndg = 2;
  516. fAddMore = TRUE;
  517. break;
  518. }
  519. if (nStartg || nEndg) GrooveRange(this, 0, m_nMeasures - 1, nStartg, nEndg, FALSE);
  520. pCommand = m_CommandList.GetHead();
  521. int nLastGrooveBar = 0;
  522. for (; pCommand; pCommand = pCommand->GetNext())
  523. {
  524. TemplateCommand& rCommand = pCommand->GetItemValue();
  525. if (rCommand.m_Command.bCommand == DMUS_COMMANDT_GROOVE)
  526. {
  527. BYTE bGrooveLevel = rCommand.m_Command.bGrooveLevel;
  528. if (bGrooveLevel && (bGrooveLevel != bLastGroove))
  529. {
  530. if (rand() % 2)
  531. {
  532. if ( (rCommand.m_nMeasure >= nFillLength) &&
  533. (rCommand.m_nMeasure - nFillLength > nLastGrooveBar) &&
  534. (bGrooveLevel > 50 || bLastGroove > 75) )
  535. {
  536. AddCommand(rCommand.m_nMeasure - nFillLength, PF_FILL);
  537. }
  538. else
  539. {
  540. if ((rCommand.m_nMeasure >= nBreakLength) &&
  541. (rCommand.m_nMeasure - nBreakLength > nLastGrooveBar) &&
  542. (rand() % 3) )
  543. {
  544. AddCommand(rCommand.m_nMeasure - nBreakLength, PF_BREAK);
  545. }
  546. }
  547. }
  548. }
  549. bLastGroove = bGrooveLevel;
  550. if (rCommand.m_Command.bGrooveLevel) nLastGrooveBar = rCommand.m_nMeasure;
  551. }
  552. }
  553. if (fAddMore)
  554. {
  555. int nLastMeasure = 0;
  556. nLastGrooveBar = 0;
  557. bLastGroove = 0;
  558. pCommand = m_CommandList.GetHead();
  559. for (; pCommand; pCommand = pCommand->GetNext())
  560. {
  561. TemplateCommand& rCommand = pCommand->GetItemValue();
  562. TListItem<TemplateCommand> *pNext = pCommand->GetNext();
  563. int nMeasure = rCommand.m_nMeasure;
  564. if (rCommand.m_Command.bCommand != DMUS_COMMANDT_GROOVE)
  565. {
  566. nLastMeasure = nMeasure;
  567. continue;
  568. }
  569. if (rCommand.m_Command.bCommand == DMUS_COMMANDT_GROOVE)
  570. {
  571. bLastGroove = rCommand.m_Command.bGrooveLevel;
  572. }
  573. if ( (nLastMeasure + nFillLength + nBreakLength + 4) < nMeasure )
  574. {
  575. if ((rand() % 3) == 0) // do something?
  576. { // perhaps a fill?
  577. nLastMeasure = nMeasure;
  578. if ((bLastGroove > 50) &&
  579. (nMeasure >= nFillLength) &&
  580. (nMeasure - nFillLength > nLastGrooveBar) &&
  581. (rand() % 2))
  582. {
  583. AddCommand(nMeasure - nFillLength, PF_FILL);
  584. }
  585. else
  586. {
  587. if (pNext)
  588. {
  589. while (nMeasure + nBreakLength <= pNext->GetItemValue().m_nMeasure )
  590. {
  591. AddCommand(nMeasure, PF_BREAK);
  592. nMeasure += nBreakLength;
  593. if (rand() % 2) break;
  594. }
  595. }
  596. }
  597. }
  598. }
  599. if (bLastGroove) nLastGrooveBar = rCommand.m_nMeasure;
  600. }
  601. }
  602. }
  603. /////////////////////////////////////////////////////////////////////////////
  604. // CDMTempl
  605. CDMTempl::CDMTempl( ) : m_cRef(1), m_pTemplateInfo(NULL), m_fCSInitialized(FALSE)
  606. {
  607. InterlockedIncrement(&g_cComponent);
  608. // Do this first since it might throw an exception
  609. //
  610. ::InitializeCriticalSection( &m_CriticalSection );
  611. m_fCSInitialized = TRUE;
  612. }
  613. CDMTempl::~CDMTempl()
  614. {
  615. if (m_fCSInitialized)
  616. {
  617. CleanUp();
  618. ::DeleteCriticalSection( &m_CriticalSection );
  619. }
  620. InterlockedDecrement(&g_cComponent);
  621. }
  622. void CDMTempl::CleanUp()
  623. {
  624. if( m_pTemplateInfo != NULL )
  625. {
  626. delete m_pTemplateInfo;
  627. m_pTemplateInfo = NULL;
  628. }
  629. }
  630. STDMETHODIMP CDMTempl::QueryInterface(
  631. const IID &iid,
  632. void **ppv)
  633. {
  634. V_INAME(CDMTempl::QueryInterface);
  635. V_PTRPTR_WRITE(ppv);
  636. V_REFGUID(iid);
  637. if (iid == IID_IUnknown || iid == IID_IDMTempl)
  638. {
  639. *ppv = static_cast<IDMTempl*>(this);
  640. }
  641. else if (iid == IID_IPersistStream)
  642. {
  643. *ppv = static_cast<IPersistStream*>(this);
  644. }
  645. else
  646. {
  647. *ppv = NULL;
  648. return E_NOINTERFACE;
  649. }
  650. reinterpret_cast<IUnknown*>(this)->AddRef();
  651. return S_OK;
  652. }
  653. STDMETHODIMP_(ULONG) CDMTempl::AddRef()
  654. {
  655. return InterlockedIncrement(&m_cRef);
  656. }
  657. STDMETHODIMP_(ULONG) CDMTempl::Release()
  658. {
  659. if (!InterlockedDecrement(&m_cRef))
  660. {
  661. delete this;
  662. return 0;
  663. }
  664. return m_cRef;
  665. }
  666. HRESULT CDMTempl::SaveCommandList( IAARIFFStream* pRIFF, DMUS_TIMESIGNATURE& rTimeSig )
  667. {
  668. IStream* pStream;
  669. MMCKINFO ck;
  670. HRESULT hr;
  671. DWORD cb;
  672. DWORD dwSize;
  673. DMUS_IO_COMMAND iCommand;
  674. TListItem<TemplateCommand>* pCommand;
  675. if (!m_pTemplateInfo) return E_FAIL;
  676. pStream = pRIFF->GetStream();
  677. if (!pStream) return E_FAIL;
  678. hr = E_FAIL;
  679. ck.ckid = FOURCC_COMMAND;
  680. if( pRIFF->CreateChunk( &ck, 0 ) == 0 )
  681. {
  682. dwSize = sizeof( DMUS_IO_COMMAND );
  683. hr = pStream->Write( &dwSize, sizeof( dwSize ), &cb );
  684. if( FAILED( hr ) || cb != sizeof( dwSize ) )
  685. {
  686. pStream->Release();
  687. return E_FAIL;
  688. }
  689. for( pCommand = m_pTemplateInfo->m_CommandList.GetHead(); pCommand != NULL ; pCommand = pCommand->GetNext() )
  690. {
  691. TemplateCommand& rCommand = pCommand->GetItemValue();
  692. if (rCommand.m_Command.bGrooveLevel || rCommand.m_Command.bCommand)
  693. {
  694. memset( &iCommand, 0, sizeof( iCommand ) );
  695. iCommand.mtTime = ClocksPerMeasure(rTimeSig) * rCommand.m_nMeasure;
  696. iCommand.wMeasure = rCommand.m_nMeasure;
  697. iCommand.bBeat = 0;
  698. iCommand.bCommand = rCommand.m_Command.bCommand;
  699. iCommand.bGrooveLevel = rCommand.m_Command.bGrooveLevel;
  700. iCommand.bGrooveRange = rCommand.m_Command.bGrooveRange;
  701. iCommand.bRepeatMode = rCommand.m_Command.bRepeatMode;
  702. if( FAILED( pStream->Write( &iCommand, sizeof( iCommand ), &cb ) ) ||
  703. cb != sizeof( iCommand ) )
  704. {
  705. break;
  706. }
  707. }
  708. }
  709. if( pCommand == NULL &&
  710. pRIFF->Ascend( &ck, 0 ) == 0 )
  711. {
  712. hr = S_OK;
  713. }
  714. }
  715. pStream->Release();
  716. return hr;
  717. }
  718. HRESULT CDMTempl::SaveSignPostList( IAARIFFStream* pRIFF, DMUS_TIMESIGNATURE& TimeSig )
  719. {
  720. IStream* pStream;
  721. MMCKINFO ck;
  722. HRESULT hr;
  723. DWORD cb;
  724. DWORD dwSize;
  725. DMUS_IO_SIGNPOST oSignPost;
  726. TListItem<TemplateCommand>* pCommand;
  727. ;
  728. if (!m_pTemplateInfo) return E_FAIL;
  729. pStream = pRIFF->GetStream();
  730. if (!pStream) return E_FAIL;
  731. hr = E_FAIL;
  732. ck.ckid = DMUS_FOURCC_SIGNPOST_TRACK_CHUNK;
  733. if( pRIFF->CreateChunk( &ck, 0 ) == 0 )
  734. {
  735. dwSize = sizeof( oSignPost );
  736. hr = pStream->Write( &dwSize, sizeof( dwSize ), &cb );
  737. if( FAILED( hr ) || cb != sizeof( dwSize ) )
  738. {
  739. pStream->Release();
  740. return E_FAIL;
  741. }
  742. for( pCommand = m_pTemplateInfo->m_CommandList.GetHead(); pCommand != NULL ; pCommand = pCommand->GetNext() )
  743. {
  744. TemplateCommand& rCommand = pCommand->GetItemValue();
  745. memset( &oSignPost, 0, sizeof( oSignPost ) );
  746. oSignPost.mtTime = ClocksPerMeasure(TimeSig) * rCommand.m_nMeasure;
  747. oSignPost.wMeasure = rCommand.m_nMeasure;
  748. oSignPost.dwChords = rCommand.m_dwChord;
  749. if( FAILED( pStream->Write( &oSignPost, sizeof( oSignPost ), &cb ) ) ||
  750. cb != sizeof( oSignPost ) )
  751. {
  752. break;
  753. }
  754. }
  755. if( pCommand == NULL &&
  756. pRIFF->Ascend( &ck, 0 ) == 0 )
  757. {
  758. hr = S_OK;
  759. }
  760. }
  761. pStream->Release();
  762. return hr;
  763. }
  764. HRESULT CDMTempl::Init(void* pTemplate)
  765. {
  766. CleanUp();
  767. m_pTemplateInfo = (TemplateStruct*)pTemplate;
  768. // fix groove levels in the command list
  769. // m_pTemplateInfo->FillInGrooveLevels();
  770. return S_OK;
  771. }
  772. HRESULT CDMTempl::CreateSegment(IDirectMusicSegment* pISegment)
  773. {
  774. if (!pISegment) return E_INVALIDARG;
  775. if (!m_pTemplateInfo) return E_FAIL;
  776. IDirectMusicTrack* pICommandTrack = NULL;
  777. IDirectMusicTrack* pISignPostTrack = NULL;
  778. IAARIFFStream* pCommandRIFF = NULL;
  779. IStream* pICommandStream = NULL;
  780. IPersistStream* pICommandTrackStream = NULL;
  781. IPersistStream* pISignPostTrackStream = NULL;
  782. IAARIFFStream* pSignPostRIFF = NULL;
  783. IStream* pISignPostStream = NULL;
  784. HRESULT hr = S_OK;
  785. DMUS_TIMESIGNATURE TimeSig;
  786. // Fill in the time sig event with default values (4/4, 16th note resolution)
  787. TimeSig.mtTime = 0;
  788. TimeSig.bBeatsPerMeasure = 4;
  789. TimeSig.bBeat = 4;
  790. TimeSig.wGridsPerBeat = 4;
  791. // 1. Create Command and Sign Post Tracks.
  792. hr = ::CoCreateInstance(
  793. CLSID_DirectMusicCommandTrack,
  794. NULL,
  795. CLSCTX_INPROC,
  796. IID_IDirectMusicTrack,
  797. (void**)&pICommandTrack
  798. );
  799. if (FAILED(hr)) goto ON_END;
  800. hr = ::CoCreateInstance(
  801. CLSID_DirectMusicSignPostTrack,
  802. NULL,
  803. CLSCTX_INPROC,
  804. IID_IDirectMusicTrack,
  805. (void**)&pISignPostTrack
  806. );
  807. if (FAILED(hr)) goto ON_END;
  808. // 2. Write the template's command list out to a stream.
  809. hr = CreateStreamOnHGlobal(NULL, TRUE, &pICommandStream);
  810. if (S_OK != hr) goto ON_END;
  811. AllocRIFFStream( pICommandStream, &pCommandRIFF);
  812. if (!pCommandRIFF)
  813. {
  814. hr = E_FAIL;
  815. goto ON_END;
  816. }
  817. SaveCommandList(pCommandRIFF, TimeSig);
  818. // 3. Use the command list stream as input to the Command Track's Load method.
  819. hr = pICommandTrack->QueryInterface(IID_IPersistStream, (void**)&pICommandTrackStream);
  820. if(FAILED(hr)) goto ON_END;
  821. StreamSeek(pICommandStream, 0, STREAM_SEEK_SET);
  822. hr = pICommandTrackStream->Load(pICommandStream);
  823. if(FAILED(hr)) goto ON_END;
  824. // 4. Write the template's sign post list out to a stream.
  825. hr = CreateStreamOnHGlobal(NULL, TRUE, &pISignPostStream);
  826. if(S_OK != hr) goto ON_END;
  827. AllocRIFFStream( pISignPostStream, &pSignPostRIFF);
  828. if (!pSignPostRIFF)
  829. {
  830. hr = E_FAIL;
  831. goto ON_END;
  832. }
  833. SaveSignPostList(pSignPostRIFF, TimeSig);
  834. // 5. Use the chord list stream as input to the Sign Post Track's Load method.
  835. hr = pISignPostTrack->QueryInterface(IID_IPersistStream, (void**)&pISignPostTrackStream);
  836. if(FAILED(hr)) goto ON_END;
  837. StreamSeek(pISignPostStream, 0, STREAM_SEEK_SET);
  838. hr = pISignPostTrackStream->Load(pISignPostStream);
  839. if (FAILED(hr)) goto ON_END;
  840. // 6. Create a Segment has been removed it is now passed in
  841. // 7. Initialize the segment appropriately.
  842. //pISegment->SetUserData(m_pTemplateInfo->m_nMeasures);
  843. pISegment->SetLength(ClocksPerMeasure(TimeSig) * m_pTemplateInfo->m_nMeasures);
  844. // 8. Insert the two Tracks into the Segment's Track list.
  845. pISegment->InsertTrack(pICommandTrack, 1);
  846. pISegment->InsertTrack(pISignPostTrack, 1);
  847. // Note: the segment must release the track objects...
  848. ON_END:
  849. if (pICommandTrack) pICommandTrack->Release();
  850. if (pISignPostTrack) pISignPostTrack->Release();
  851. if (pCommandRIFF) pCommandRIFF->Release();
  852. if (pICommandStream) pICommandStream->Release();
  853. if (pICommandTrackStream) pICommandTrackStream->Release();
  854. if (pISignPostTrackStream) pISignPostTrackStream->Release();
  855. if (pSignPostRIFF) pSignPostRIFF->Release();
  856. if (pISignPostStream) pISignPostStream->Release();
  857. return hr;
  858. }
  859. HRESULT CDMTempl::GetClassID( LPCLSID pclsid )
  860. {
  861. if ( pclsid == NULL ) return E_INVALIDARG;
  862. *pclsid = CLSID_DMTempl;
  863. return S_OK;
  864. }
  865. HRESULT CDMTempl::IsDirty()
  866. {
  867. return ( m_fDirty ) ? S_OK : S_FALSE;
  868. }
  869. static TListItem<TemplateCommand>* loadacommand( LPSTREAM pStream, DWORD dwSize )
  870. {
  871. CommandExt command;
  872. TListItem<TemplateCommand>* pCommand = new TListItem<TemplateCommand>;
  873. if( pCommand == NULL )
  874. {
  875. StreamSeek( pStream, dwSize, STREAM_SEEK_CUR );
  876. return NULL;
  877. }
  878. TemplateCommand& rCommand = pCommand->GetItemValue();
  879. if( dwSize > sizeof(CommandExt) )
  880. {
  881. pStream->Read( &command, sizeof(CommandExt), NULL );
  882. FixBytes( FBT_COMMANDEXT, &command );
  883. StreamSeek( pStream, dwSize - sizeof(CommandExt), STREAM_SEEK_CUR );
  884. }
  885. else
  886. {
  887. pStream->Read( &command, dwSize, NULL );
  888. FixBytes( FBT_COMMANDEXT, &command );
  889. }
  890. //rCommand.m_lTime = command->time;
  891. rCommand.m_nMeasure = command.measure;
  892. rCommand.m_Command.bGrooveRange = 0;
  893. rCommand.m_Command.bRepeatMode = 0;
  894. switch (command.command)
  895. {
  896. case PF_FILL:
  897. rCommand.m_Command.bCommand = DMUS_COMMANDT_FILL;
  898. rCommand.m_Command.bGrooveLevel = 0;
  899. break;
  900. case PF_INTRO:
  901. rCommand.m_Command.bCommand = DMUS_COMMANDT_INTRO;
  902. rCommand.m_Command.bGrooveLevel = 0;
  903. break;
  904. case PF_BREAK:
  905. rCommand.m_Command.bCommand = DMUS_COMMANDT_BREAK;
  906. rCommand.m_Command.bGrooveLevel = 0;
  907. break;
  908. case PF_END:
  909. rCommand.m_Command.bCommand = DMUS_COMMANDT_END;
  910. rCommand.m_Command.bGrooveLevel = 0;
  911. break;
  912. case PF_A:
  913. rCommand.m_Command.bCommand = DMUS_COMMANDT_GROOVE;
  914. rCommand.m_Command.bGrooveLevel = 12;
  915. break;
  916. case PF_B:
  917. rCommand.m_Command.bCommand = DMUS_COMMANDT_GROOVE;
  918. rCommand.m_Command.bGrooveLevel = 37;
  919. break;
  920. case PF_C:
  921. rCommand.m_Command.bCommand = DMUS_COMMANDT_GROOVE;
  922. rCommand.m_Command.bGrooveLevel = 62;
  923. break;
  924. case PF_D:
  925. rCommand.m_Command.bCommand = DMUS_COMMANDT_GROOVE;
  926. rCommand.m_Command.bGrooveLevel = 87;
  927. break;
  928. default: // default to a Groove with level 0 (interpretation: use previous groove level)
  929. // This happens in the measure following an embellishment
  930. rCommand.m_Command.bCommand = DMUS_COMMANDT_GROOVE;
  931. rCommand.m_Command.bGrooveLevel = 0;
  932. }
  933. rCommand.m_dwChord = command.chord;
  934. return pCommand;
  935. }
  936. HRESULT CDMTempl::LoadTemplate( LPSTREAM pStream, DWORD dwSize )
  937. {
  938. TListItem<TemplateCommand>* pCommand;
  939. DWORD id = 0;
  940. DWORD tsize = 0;
  941. DWORD segsize = 0;
  942. SCTtemplate* pTemplate;
  943. long lSize = dwSize;
  944. if ( pStream == NULL ) return E_INVALIDARG;
  945. pTemplate = new SCTtemplate;
  946. if( pTemplate == NULL )
  947. {
  948. StreamSeek( pStream, lSize, STREAM_SEEK_CUR );
  949. return E_OUTOFMEMORY;
  950. }
  951. if (!GetMLong( pStream, tsize ))
  952. {
  953. StreamSeek( pStream, lSize, STREAM_SEEK_CUR );
  954. delete pTemplate;
  955. return E_FAIL;
  956. }
  957. lSize -= 4;
  958. if( tsize > sizeof(SCTtemplate) )
  959. {
  960. pStream->Read( pTemplate, sizeof(SCTtemplate), NULL );
  961. FixBytes( FBT_SCTTEMPLATE, pTemplate );
  962. StreamSeek( pStream, tsize - sizeof(SCTtemplate), STREAM_SEEK_CUR );
  963. }
  964. else
  965. {
  966. pStream->Read( pTemplate, tsize, NULL );
  967. FixBytes( FBT_SCTTEMPLATE, pTemplate );
  968. }
  969. lSize -= tsize;
  970. m_pTemplateInfo = new TemplateStruct;
  971. if (!m_pTemplateInfo)
  972. {
  973. StreamSeek( pStream, lSize, STREAM_SEEK_CUR );
  974. return E_OUTOFMEMORY;
  975. }
  976. m_pTemplateInfo->m_strName = pTemplate->achName;
  977. m_pTemplateInfo->m_strType = pTemplate->achType;
  978. m_pTemplateInfo->m_nMeasures = pTemplate->nMeasures;
  979. delete pTemplate;
  980. while( lSize > 0 )
  981. {
  982. pStream->Read( &id, 4, NULL );
  983. if (!GetMLong( pStream, segsize ))
  984. {
  985. StreamSeek( pStream, lSize, STREAM_SEEK_CUR );
  986. break;
  987. }
  988. lSize -= 8;
  989. switch( id )
  990. {
  991. case mmioFOURCC( 'D', 'M', 'C', 's' ):
  992. pCommand = loadacommand( pStream, segsize );
  993. if( pCommand )
  994. {
  995. m_pTemplateInfo->m_CommandList.AddTail(pCommand);
  996. }
  997. break;
  998. default:
  999. StreamSeek( pStream, segsize, STREAM_SEEK_CUR );
  1000. break;
  1001. }
  1002. lSize -= segsize;
  1003. }
  1004. // fix groove levels in the command list
  1005. BYTE bLastGroove = 62;
  1006. pCommand = m_pTemplateInfo->m_CommandList.GetHead();
  1007. for (; pCommand; pCommand = pCommand->GetNext())
  1008. {
  1009. TemplateCommand& rCommand = pCommand->GetItemValue();
  1010. if (rCommand.m_Command.bGrooveLevel == 0)
  1011. {
  1012. rCommand.m_Command.bGrooveLevel = bLastGroove;
  1013. }
  1014. else bLastGroove = rCommand.m_Command.bGrooveLevel;
  1015. }
  1016. return S_OK;
  1017. }
  1018. // This loads a *single* template. I also need to handle files that contain
  1019. // *lists* of templates (but I can just load the first one in the list)
  1020. HRESULT CDMTempl::Load( LPSTREAM pStream )
  1021. {
  1022. FOURCC id;
  1023. DWORD dwSize;
  1024. HRESULT hr;
  1025. if ( pStream == NULL ) return E_INVALIDARG;
  1026. EnterCriticalSection( &m_CriticalSection );
  1027. CleanUp();
  1028. if( FAILED( pStream->Read( &id, sizeof( FOURCC ), NULL ) ) ||
  1029. !GetMLong( pStream, dwSize ) )
  1030. {
  1031. hr = E_FAIL;
  1032. goto end;
  1033. }
  1034. if( id != mmioFOURCC( 'L', 'P', 'T', 's' ) )
  1035. {
  1036. hr = E_FAIL;
  1037. goto end;
  1038. }
  1039. hr = LoadTemplate( pStream, dwSize );
  1040. end:
  1041. LeaveCriticalSection( &m_CriticalSection );
  1042. return hr;
  1043. }
  1044. HRESULT CDMTempl::Save( LPSTREAM pStream, BOOL fClearDirty )
  1045. {
  1046. return E_NOTIMPL;
  1047. }
  1048. HRESULT CDMTempl::GetSizeMax( ULARGE_INTEGER FAR* pcbSize )
  1049. {
  1050. return E_NOTIMPL;
  1051. }