Source code of Windows XP (NT5)
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.

1272 lines
46 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (c) 1998-2001 Microsoft Corporation
  6. //
  7. // File: ptrntrk.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. // PtrnTrk.cpp : Implementation of the Pattern Track info and state structs
  11. #include "PtrnTrk.h"
  12. #include "dmusici.h"
  13. #include "dmusicf.h"
  14. #include "debug.h"
  15. /////////////////////////////////////////////////////////////////////////////
  16. // PatternTrackState
  17. PatternTrackState::PatternTrackState() :
  18. m_pStyle(NULL),
  19. m_pSegState(NULL),
  20. m_pPerformance(NULL),
  21. m_mtPerformanceOffset(0),
  22. m_dwVirtualTrackID(0),
  23. m_pPatternTrack(NULL),
  24. m_pTrack(NULL),
  25. m_mtCurrentChordTime(0),
  26. m_mtNextChordTime(0),
  27. m_mtLaterChordTime(0),
  28. m_pPattern(NULL),
  29. m_pdwPChannels(NULL),
  30. m_pVariations(NULL),
  31. m_pdwVariationMask(NULL),
  32. m_pdwRemoveVariations(NULL),
  33. m_pmtPartOffset(NULL),
  34. m_nInversionGroupCount(0),
  35. m_fNewPattern(TRUE),
  36. m_fStateActive(TRUE),
  37. // m_fStatePlay(TRUE),
  38. m_pMappings(NULL),
  39. m_ppEventSeek(NULL),
  40. m_dwGroupID(0xffffffff),
  41. m_plVariationSeeds(NULL),
  42. m_nTotalGenerators(0),
  43. m_mtPatternStart(0),
  44. m_dwValidate(0),
  45. m_hrPlayCode(S_OK),
  46. m_pfChangedVariation(NULL)
  47. {
  48. ZeroMemory(&m_NextChord, sizeof(DMUS_CHORD_PARAM));
  49. wcscpy(m_CurrentChord.wszName, L"M7");
  50. m_CurrentChord.wMeasure = 0;
  51. m_CurrentChord.bBeat = 0;
  52. m_CurrentChord.bSubChordCount = 1;
  53. m_CurrentChord.bKey = 12;
  54. m_CurrentChord.dwScale = DEFAULT_SCALE_PATTERN;
  55. m_CurrentChord.bFlags = 0;
  56. for (int n = 0; n < DMUS_MAXSUBCHORD; n++)
  57. {
  58. m_CurrentChord.SubChordList[n].dwChordPattern = DEFAULT_CHORD_PATTERN;
  59. m_CurrentChord.SubChordList[n].dwScalePattern = DEFAULT_SCALE_PATTERN;
  60. m_CurrentChord.SubChordList[n].dwInversionPoints = 0xffffff;
  61. m_CurrentChord.SubChordList[n].dwLevels = 0xffffffff;
  62. m_CurrentChord.SubChordList[n].bChordRoot = 12; // 2C
  63. m_CurrentChord.SubChordList[n].bScaleRoot = 0;
  64. }
  65. for (int i = 0; i < INVERSIONGROUPLIMIT; i++)
  66. m_aInversionGroups[i].m_wGroupID = 0;
  67. }
  68. PatternTrackState::~PatternTrackState()
  69. {
  70. if (m_pmtPartOffset)
  71. delete [] m_pmtPartOffset;
  72. if (m_pdwPChannels)
  73. delete [] m_pdwPChannels;
  74. if (m_pVariations)
  75. delete [] m_pVariations;
  76. if (m_pdwVariationMask)
  77. delete [] m_pdwVariationMask;
  78. if (m_pdwRemoveVariations)
  79. delete [] m_pdwRemoveVariations;
  80. if (m_pMappings) delete [] m_pMappings;
  81. if (m_ppEventSeek) delete [] m_ppEventSeek;
  82. if (m_plVariationSeeds) delete [] m_plVariationSeeds;
  83. if (m_pPattern) m_pPattern->Release();
  84. if (m_pfChangedVariation)
  85. {
  86. delete [] m_pfChangedVariation;
  87. }
  88. }
  89. HRESULT PatternTrackState::InitPattern(CDirectMusicPattern* pTargetPattern, MUSIC_TIME mtNow, CDirectMusicPattern* pOldPattern)
  90. {
  91. m_fNewPattern = TRUE;
  92. m_mtPatternStart = mtNow;
  93. short nPartCount = (short) pTargetPattern->m_PartRefList.GetCount();
  94. // initialize an array to keep track of variations in parts.
  95. // if the current pattern is the same as the previous pattern,
  96. // use the existing array.
  97. if (m_pPattern != pTargetPattern || pOldPattern)
  98. {
  99. ////////////////// create an array of variation bools //////////////////
  100. if (m_pfChangedVariation) delete [] m_pfChangedVariation;
  101. m_pfChangedVariation = new bool[nPartCount];
  102. if (!m_pfChangedVariation)
  103. {
  104. return E_OUTOFMEMORY;
  105. }
  106. ////////////////// create an array of part offsets //////////////////
  107. if (m_pmtPartOffset != NULL) delete [] m_pmtPartOffset;
  108. m_pmtPartOffset = new MUSIC_TIME[nPartCount];
  109. if (!m_pmtPartOffset)
  110. {
  111. return E_OUTOFMEMORY;
  112. }
  113. ////////////////// create an array of seek pointers //////////////////
  114. if (m_ppEventSeek) delete [] m_ppEventSeek;
  115. m_ppEventSeek = new CDirectMusicEventItem*[nPartCount];
  116. if (!m_ppEventSeek)
  117. {
  118. return E_OUTOFMEMORY;
  119. }
  120. ////////////////// create and initialize PChannels //////////////////
  121. if (m_pdwPChannels != NULL) delete [] m_pdwPChannels;
  122. m_pdwPChannels = new DWORD[nPartCount];
  123. if (!m_pdwPChannels)
  124. {
  125. return E_OUTOFMEMORY;
  126. }
  127. TListItem<DirectMusicPartRef>* pPartRef = pTargetPattern->m_PartRefList.GetHead();
  128. for (int i = 0; pPartRef != NULL; pPartRef = pPartRef->GetNext(), i++)
  129. {
  130. m_pdwPChannels[i] = pPartRef->GetItemValue().m_dwLogicalPartID;
  131. }
  132. if (!pOldPattern ||
  133. pTargetPattern->m_strName != pOldPattern->m_strName ||
  134. nPartCount != pOldPattern->m_PartRefList.GetCount() )
  135. {
  136. ////////////////// create and initialize variations //////////////////
  137. if (m_pVariations != NULL) delete [] m_pVariations;
  138. m_pVariations = new BYTE[nPartCount];
  139. if (!m_pVariations)
  140. {
  141. return E_OUTOFMEMORY;
  142. }
  143. if (m_pdwVariationMask != NULL) delete [] m_pdwVariationMask;
  144. m_pdwVariationMask = new DWORD[nPartCount];
  145. if (!m_pdwVariationMask)
  146. {
  147. return E_OUTOFMEMORY;
  148. }
  149. if (m_pdwRemoveVariations != NULL) delete [] m_pdwRemoveVariations;
  150. m_pdwRemoveVariations = new DWORD[nPartCount];
  151. if (!m_pdwRemoveVariations)
  152. {
  153. return E_OUTOFMEMORY;
  154. }
  155. for (int i = 0; i < nPartCount; i++)
  156. {
  157. m_pdwVariationMask[i] = 0;
  158. if ( (pTargetPattern->m_dwFlags & DMUS_PATTERNF_PERSIST_CONTROL) &&
  159. m_pPatternTrack &&
  160. m_pPatternTrack->m_pVariations &&
  161. m_pPatternTrack->m_pdwRemoveVariations )
  162. {
  163. m_pVariations[i] = m_pPatternTrack->m_pVariations[i];
  164. m_pdwRemoveVariations[i] = m_pPatternTrack->m_pdwRemoveVariations[i];
  165. }
  166. else
  167. {
  168. m_pVariations[i] = -1;
  169. m_pdwRemoveVariations[i] = 0;
  170. }
  171. }
  172. }
  173. }
  174. // initialize the part offset array and seek pointer array.
  175. for (int i = 0; i < nPartCount; i++)
  176. {
  177. m_pmtPartOffset[i] = 0;
  178. m_ppEventSeek[i] = NULL;
  179. }
  180. // Set up the new pattern.
  181. if (m_pPattern != pTargetPattern)
  182. {
  183. pTargetPattern->AddRef();
  184. if (m_pPattern) m_pPattern->Release();
  185. m_pPattern = pTargetPattern;
  186. }
  187. return S_OK;
  188. }
  189. // This assumes the time sig remains constant for the length of the segment.
  190. // If time sigs change, we won't necessarily have one generator per beat, but
  191. // this will still give consistent playback behavior under most circumstances;
  192. // the exception is a controlling segment that interupts somewhere after the
  193. // time signature changes.
  194. HRESULT PatternTrackState::InitVariationSeeds(long lBaseSeed)
  195. {
  196. // Get the Segment length
  197. MUSIC_TIME mtLength = 0;
  198. IDirectMusicSegment* pSegment = NULL;
  199. if (m_pSegState)
  200. {
  201. if (SUCCEEDED(m_pSegState->GetSegment(&pSegment)))
  202. {
  203. pSegment->GetLength(&mtLength);
  204. pSegment->Release();
  205. }
  206. }
  207. else
  208. {
  209. return E_POINTER;
  210. }
  211. // Get the current time sig and use it to get the number of beats in the segment
  212. DirectMusicTimeSig TimeSig = PatternTimeSig();
  213. int nBeats = TimeSig.ClocksToBeat(mtLength);
  214. // Create an array with the required number of beats, and use the Base Seed to
  215. // seed a random number generator at each beat
  216. if (m_plVariationSeeds) delete [] m_plVariationSeeds;
  217. m_plVariationSeeds = new CRandomNumbers[nBeats];
  218. if (!m_plVariationSeeds)
  219. {
  220. m_nTotalGenerators = 0;
  221. return E_OUTOFMEMORY;
  222. }
  223. else
  224. {
  225. m_nTotalGenerators = nBeats;
  226. for (int i = 0; i < nBeats; i++)
  227. {
  228. m_plVariationSeeds[i].Seed(lBaseSeed);
  229. lBaseSeed = m_plVariationSeeds[i].Next();
  230. }
  231. return S_OK;
  232. }
  233. }
  234. HRESULT PatternTrackState::RemoveVariationSeeds()
  235. {
  236. if (m_plVariationSeeds) delete [] m_plVariationSeeds;
  237. m_plVariationSeeds = NULL;
  238. m_nTotalGenerators = 0;
  239. return S_OK;
  240. }
  241. long PatternTrackState::RandomVariation(MUSIC_TIME mtTime, long lModulus)
  242. {
  243. if (m_plVariationSeeds)
  244. {
  245. DirectMusicTimeSig TimeSig = PatternTimeSig();
  246. int nBeat = TimeSig.ClocksToBeat(mtTime);
  247. // In case time sigs change somehow, make sure we get a valid generator
  248. if (nBeat >= m_nTotalGenerators) nBeat = m_nTotalGenerators - 1;
  249. return m_plVariationSeeds[nBeat].Next(lModulus);
  250. }
  251. else
  252. {
  253. // regular old rand...
  254. return rand() % lModulus;
  255. }
  256. }
  257. void PatternTrackState::GetNextChord(MUSIC_TIME mtNow, MUSIC_TIME mtOffset, IDirectMusicPerformance* pPerformance, BOOL fStart, BOOL fSkipVariations)
  258. {
  259. HRESULT hr = S_OK;
  260. {
  261. hr = pPerformance->GetParam(GUID_ChordParam, m_dwGroupID, DMUS_SEG_ANYTRACK, mtNow + mtOffset,
  262. &m_mtNextChordTime, (void*) &m_CurrentChord);
  263. if (SUCCEEDED(hr))
  264. {
  265. m_mtCurrentChordTime = mtNow;
  266. if (m_mtNextChordTime) m_mtNextChordTime += mtNow;
  267. TraceI(4, "[1] Offset: %d Next Chord: %d\n", mtOffset, m_mtNextChordTime);
  268. #ifdef DBG
  269. if (!m_CurrentChord.bSubChordCount)
  270. {
  271. Trace(2, "Warning: Attempt to get a chord resulted in a chord with no subchords.\n");
  272. }
  273. #endif
  274. }
  275. }
  276. // instead of failing here completely, I'll just give m_mtNextChordTime and m_CurrentChord
  277. // fallback values
  278. if (FAILED(hr))
  279. {
  280. m_mtCurrentChordTime = 0;
  281. m_mtNextChordTime = 0;
  282. if (!m_pStyle || !m_pStyle->UsingDX8()) // otherwise use current chord info
  283. {
  284. wcscpy(m_CurrentChord.wszName, L"M7");
  285. m_CurrentChord.wMeasure = 0;
  286. m_CurrentChord.bBeat = 0;
  287. m_CurrentChord.bSubChordCount = 1;
  288. m_CurrentChord.bKey = 12;
  289. m_CurrentChord.dwScale = DEFAULT_SCALE_PATTERN;
  290. m_CurrentChord.SubChordList[0].dwChordPattern = DEFAULT_CHORD_PATTERN;
  291. m_CurrentChord.SubChordList[0].dwScalePattern = DEFAULT_SCALE_PATTERN;
  292. m_CurrentChord.SubChordList[0].dwInversionPoints = 0xffffff;
  293. m_CurrentChord.SubChordList[0].dwLevels = 0xffffffff;
  294. m_CurrentChord.SubChordList[0].bChordRoot = 12; // 2C
  295. m_CurrentChord.SubChordList[0].bScaleRoot = 0;
  296. }
  297. }
  298. TraceI(3, "Current Chord: %d %s [%d] HRESULT: %x\n",
  299. m_CurrentChord.SubChordList[0].bChordRoot, m_CurrentChord.wszName, mtNow, hr);
  300. if (m_mtNextChordTime > 0)
  301. {
  302. hr = pPerformance->GetParam(GUID_ChordParam, m_dwGroupID, DMUS_SEG_ANYTRACK, m_mtNextChordTime + mtOffset,
  303. &m_mtLaterChordTime, (void*) &m_NextChord);
  304. if (SUCCEEDED(hr))
  305. {
  306. if (m_mtLaterChordTime) m_mtLaterChordTime += m_mtNextChordTime;
  307. TraceI(4, "[3] Offset: %d Later Chord: %d\n", mtOffset, m_mtLaterChordTime);
  308. #ifdef DBG
  309. if (!m_NextChord.bSubChordCount)
  310. {
  311. Trace(2, "Warning: Attempt to get a chord resulted in a chord with no subchords.\n");
  312. }
  313. #endif
  314. }
  315. }
  316. if (!fSkipVariations)
  317. {
  318. // Select a variation for each part in the pattern, based on the moaw and the
  319. // previous and next chords.
  320. DWORD dwFlags = 0;
  321. if (m_fNewPattern) dwFlags |= COMPUTE_VARIATIONSF_NEW_PATTERN;
  322. if (fStart) dwFlags |= COMPUTE_VARIATIONSF_START;
  323. if (m_pStyle && m_pStyle->UsingDX8()) dwFlags |= COMPUTE_VARIATIONSF_DX8;
  324. m_pPattern->ComputeVariations(dwFlags, m_CurrentChord, m_NextChord,
  325. m_abVariationGroups, m_pdwVariationMask, m_pdwRemoveVariations, m_pVariations, mtNow, m_mtNextChordTime, this);
  326. m_fNewPattern = FALSE;
  327. if ( (m_pPattern->m_dwFlags & DMUS_PATTERNF_PERSIST_CONTROL) &&
  328. m_pPatternTrack &&
  329. m_pPatternTrack->m_pVariations &&
  330. m_pPatternTrack->m_pdwRemoveVariations)
  331. {
  332. // update track's m_pVariations and m_pdwRemoveVariations (for each part)
  333. for (int i = 0; i < m_pPattern->m_PartRefList.GetCount(); i++)
  334. {
  335. m_pPatternTrack->m_pVariations[i] = m_pVariations[i];
  336. m_pPatternTrack->m_pdwRemoveVariations[i] = m_pdwRemoveVariations[i];
  337. }
  338. }
  339. }
  340. }
  341. DMStyleStruct* PatternTrackState::FindStyle(MUSIC_TIME mtTime, MUSIC_TIME& rmtTime)
  342. {
  343. IDMStyle* pStyle = NULL;
  344. DMStyleStruct* pResult = NULL;
  345. if (m_pPatternTrack && m_pPatternTrack->m_pISList.GetHead())
  346. {
  347. TListItem<StylePair>* pScan = m_pPatternTrack->m_pISList.GetHead();
  348. for(; pScan; pScan = pScan->GetNext())
  349. {
  350. if (pScan->GetItemValue().m_pStyle) break;
  351. }
  352. if (pScan)
  353. {
  354. pStyle = pScan->GetItemValue().m_pStyle;
  355. for(pScan = pScan->GetNext(); pScan; pScan = pScan->GetNext())
  356. {
  357. StylePair& rScan = pScan->GetItemValue();
  358. if (rScan.m_pStyle)
  359. {
  360. if ( mtTime < rScan.m_mtTime) break;
  361. pStyle = rScan.m_pStyle;
  362. }
  363. }
  364. rmtTime = (pScan != NULL) ? pScan->GetItemValue().m_mtTime : 0;
  365. if (pStyle)
  366. {
  367. pStyle->GetStyleInfo((void**)&pResult);
  368. }
  369. else
  370. {
  371. return NULL;
  372. }
  373. }
  374. }
  375. return pResult;
  376. }
  377. DWORD PatternTrackState::Variations(DirectMusicPartRef&, int nPartIndex)
  378. {
  379. return (m_pVariations[nPartIndex] == 0xff) ? 0 : (1 << m_pVariations[nPartIndex]);
  380. }
  381. BOOL PatternTrackState::PlayAsIs()
  382. {
  383. return FALSE;
  384. }
  385. BOOL PatternTrackState::MapPChannel(DWORD dwPChannel, DWORD& dwMapPChannel)
  386. {
  387. for (DWORD dw = 0; dw < m_pPatternTrack->m_dwPChannels; dw++)
  388. {
  389. if (m_pPatternTrack->m_pdwPChannels[dw] == dwPChannel)
  390. {
  391. dwMapPChannel = m_pMappings[dw].m_dwPChannelMap;
  392. return m_pMappings[dw].m_fMute;
  393. }
  394. }
  395. dwMapPChannel = 0;
  396. return FALSE;
  397. }
  398. inline int RandomExp(BYTE bRange)
  399. {
  400. int nResult = 0;
  401. if (0 <= bRange && bRange <= 190)
  402. {
  403. nResult = bRange;
  404. }
  405. else if (191 <= bRange && bRange <= 212)
  406. {
  407. nResult = ((bRange - 190) * 5) + 190;
  408. }
  409. else if (213 <= bRange && bRange <= 232)
  410. {
  411. nResult = ((bRange - 212) * 10) + 300;
  412. }
  413. else // bRange > 232
  414. {
  415. nResult = ((bRange - 232) * 50) + 500;
  416. }
  417. return (rand() % nResult) - (nResult >> 1);
  418. }
  419. HRESULT PatternTrackState::PlayParts(MUSIC_TIME mtStart,
  420. MUSIC_TIME mtEnd,
  421. MUSIC_TIME mtOffset,
  422. REFERENCE_TIME rtOffset,
  423. MUSIC_TIME mtSection,
  424. IDirectMusicPerformance* pPerformance,
  425. DWORD dwPartFlags,
  426. DWORD dwPlayFlags,
  427. bool& rfReLoop)
  428. {
  429. if (dwPlayFlags & DMUS_TRACKF_PLAY_OFF)
  430. {
  431. return S_OK;
  432. }
  433. if (!m_pPattern) // This shouldn't happen
  434. {
  435. return DMUS_E_NOT_INIT;
  436. }
  437. HRESULT hr = S_OK;
  438. bool fClockTime = (dwPartFlags & PLAYPARTSF_CLOCKTIME) ? true : false;
  439. bool fStart = (dwPartFlags & PLAYPARTSF_START) ? true : false;
  440. bool fGetChordStart = fStart;
  441. bool fFirstCall = (dwPartFlags & PLAYPARTSF_FIRST_CALL) ? true : false;
  442. bool fReloop = (dwPartFlags & PLAYPARTSF_RELOOP) ? true : false;
  443. bool fFlush = (dwPartFlags & PLAYPARTSF_FLUSH) ? true : false;
  444. MUSIC_TIME mtNewChord = mtStart;
  445. TListItem<DirectMusicPartRef>* pPartRef = m_pPattern->m_PartRefList.GetHead();
  446. for (short i = 0; pPartRef != NULL; pPartRef = pPartRef->GetNext(), i++)
  447. {
  448. m_pfChangedVariation[i] = false;
  449. MUSIC_TIME mtFinish = mtEnd;
  450. CurveSeek Curves;
  451. MUSIC_TIME mtNow = 0;
  452. DirectMusicPart* pPart = pPartRef->GetItemValue().m_pDMPart;
  453. DirectMusicTimeSig& TimeSig =
  454. (pPart->m_timeSig.m_bBeat != 0) ? pPart->m_timeSig : PatternTimeSig();
  455. MUSIC_TIME mtPartLength = TimeSig.ClocksPerMeasure() * pPart->m_wNumMeasures;
  456. if (fFirstCall)
  457. {
  458. if (fFlush)
  459. {
  460. GetNextMute(pPartRef->GetItemValue().m_dwLogicalPartID, 0, mtStart, mtOffset, pPerformance, fClockTime);
  461. m_ppEventSeek[i] = NULL;
  462. }
  463. if (fStart)
  464. {
  465. m_pmtPartOffset[i] = 0;
  466. }
  467. if (mtPartLength)
  468. {
  469. while (mtStart >= mtSection + m_pmtPartOffset[i] + mtPartLength)
  470. {
  471. m_pmtPartOffset[i] += mtPartLength;
  472. }
  473. }
  474. if (mtFinish > mtSection + m_pmtPartOffset[i] + mtPartLength)
  475. {
  476. rfReLoop = TRUE;
  477. mtFinish = mtSection + m_pmtPartOffset[i] + mtPartLength;
  478. }
  479. }
  480. if (!fReloop || mtFinish > mtSection + m_pmtPartOffset[i] + mtPartLength)
  481. {
  482. if (fReloop)
  483. {
  484. m_pmtPartOffset[i] += mtPartLength;
  485. }
  486. CDirectMusicEventItem* pEvent = NULL;
  487. if (fFirstCall) pEvent = m_ppEventSeek[i];
  488. if (!pEvent) pEvent = pPart->EventList.GetHead();
  489. BumpTime(pEvent, TimeSig, mtSection + m_pmtPartOffset[i], mtNow);
  490. if (pEvent)
  491. {
  492. GetNextMute(pPartRef->GetItemValue().m_dwLogicalPartID, mtStart, mtNow, mtOffset, pPerformance, fClockTime);
  493. }
  494. while (pEvent != NULL && mtNow < mtFinish)
  495. {
  496. if (fFirstCall && fStart &&
  497. mtNow < mtStart &&
  498. pEvent->m_dwEventTag == DMUS_EVENT_CURVE)
  499. {
  500. if (Variations(pPartRef->GetItemValue(), i) &
  501. pEvent->m_dwVariation)
  502. {
  503. TraceI(4, "Found a curve\n");
  504. Curves.AddCurve(pEvent, mtNow);
  505. }
  506. }
  507. if (mtNow >= mtStart)
  508. {
  509. if (mtNow < mtNewChord)
  510. {
  511. // Revert to the chord in effect at mtNow
  512. TraceI(4, "WARNING: Reverting to chord at %d\n", mtNow);
  513. GetNextChord(mtNow, mtOffset, pPerformance, (dwPartFlags & PLAYPARTSF_START) ? true : false);
  514. mtNewChord = mtNow;
  515. }
  516. else if ((mtNow >= m_mtNextChordTime) || m_mtNextChordTime == 0)
  517. {
  518. TraceI(4, "Getting new chord. Now: %d Next: %d\n", mtNow, m_mtNextChordTime);
  519. GetNextChord(mtNow, mtOffset, pPerformance, fGetChordStart);
  520. mtNewChord = mtNow;
  521. fGetChordStart = false;
  522. }
  523. TraceI(4, "Play %d (%d + %d + %d)\n", mtNow, TimeSig.GridToClocks(pEvent->m_nGridStart), mtSection, m_pmtPartOffset[i]);
  524. PlayPatternEvent(
  525. mtNow,
  526. pEvent,
  527. TimeSig,
  528. mtSection + m_pmtPartOffset[i],
  529. mtOffset,
  530. rtOffset,
  531. pPerformance,
  532. i,
  533. pPartRef->GetItemValue(),
  534. fClockTime,
  535. 0,
  536. m_pfChangedVariation[i]);
  537. }
  538. pEvent = pEvent->GetNext();
  539. BumpTime(pEvent, TimeSig, mtSection + m_pmtPartOffset[i], mtNow);
  540. MUSIC_TIME mtMute = pEvent ? mtNow : mtFinish - 1;
  541. GetNextMute(pPartRef->GetItemValue().m_dwLogicalPartID, mtStart, mtMute, mtOffset, pPerformance, fClockTime);
  542. }
  543. m_ppEventSeek[i] = pEvent;
  544. // If we've got curve events, send them now
  545. if (fFirstCall && fStart)
  546. {
  547. TraceI(4, "Playing curves (after loop)\n");
  548. Curves.PlayCurves(this,
  549. TimeSig,
  550. mtSection + m_pmtPartOffset[i],
  551. mtOffset,
  552. rtOffset,
  553. pPerformance,
  554. i,
  555. pPartRef->GetItemValue(),
  556. fClockTime,
  557. mtStart - (mtSection + m_pmtPartOffset[i]));
  558. }
  559. }
  560. }
  561. return hr;
  562. }
  563. // when creating a note event, both the passed in offset and the note's offset must
  564. // be added to the note's time
  565. void PatternTrackState::PlayPatternEvent(
  566. MUSIC_TIME mtNow,
  567. CDirectMusicEventItem* pEventItem,
  568. DirectMusicTimeSig& TimeSig,
  569. MUSIC_TIME mtPartOffset,
  570. MUSIC_TIME mtSegmentOffset,
  571. REFERENCE_TIME rtOffset,
  572. IDirectMusicPerformance* pPerformance,
  573. short nPart,
  574. DirectMusicPartRef& rPartRef,
  575. BOOL fClockTime,
  576. MUSIC_TIME mtPartStart,
  577. bool& rfChangedVariation)
  578. {
  579. DMUS_NOTE_PMSG* pNote = NULL;
  580. DMUS_CURVE_PMSG* pCurve = NULL;
  581. DWORD dwMapPChannel = 0;
  582. BOOL fMute = MapPChannel(rPartRef.m_dwLogicalPartID, dwMapPChannel);
  583. if ( (!fMute) &&
  584. (Variations(rPartRef, nPart) & pEventItem->m_dwVariation) )
  585. {
  586. CDMStyleCurve* pCurveEvent = NULL;
  587. CDMStyleNote* pNoteEvent = NULL;
  588. CDMStyleMarker* pMarkerEvent = NULL;
  589. if (pEventItem->m_dwEventTag == DMUS_EVENT_MARKER) // we have a marker event
  590. {
  591. // If we're not ignoring marker events and we've hit a variation stop point that's
  592. // either not chord-aligned or on the chord, then get a new variation.
  593. pMarkerEvent = (CDMStyleMarker*)pEventItem;
  594. if ( (rPartRef.m_pDMPart && (rPartRef.m_pDMPart->m_dwFlags & DMUS_PARTF_USE_MARKERS)) &&
  595. (pMarkerEvent->m_wFlags & DMUS_MARKERF_STOP) &&
  596. (mtNow != m_mtPatternStart) &&
  597. (!(pMarkerEvent->m_wFlags & DMUS_MARKERF_CHORD_ALIGN) ||
  598. (mtNow == m_mtCurrentChordTime) ||
  599. (mtNow == m_mtNextChordTime)) )
  600. {
  601. TraceI(3, "Computing variations at %d Pattern start: %d...\n", mtNow, m_mtPatternStart);
  602. DWORD dwFlags = COMPUTE_VARIATIONSF_NEW_PATTERN | COMPUTE_VARIATIONSF_MARKER;
  603. if ((pMarkerEvent->m_wFlags & DMUS_MARKERF_CHORD_ALIGN))
  604. {
  605. dwFlags |= COMPUTE_VARIATIONSF_CHORD_ALIGN;
  606. }
  607. if (m_pStyle && m_pStyle->UsingDX8()) dwFlags |= COMPUTE_VARIATIONSF_DX8;
  608. if (rfChangedVariation) dwFlags |= COMPUTE_VARIATIONSF_CHANGED;
  609. m_pPattern->ComputeVariationGroup(
  610. rPartRef,
  611. nPart,
  612. dwFlags,
  613. m_CurrentChord,
  614. m_NextChord,
  615. m_abVariationGroups,
  616. m_pdwVariationMask,
  617. m_pdwRemoveVariations,
  618. m_pVariations,
  619. mtNow + pMarkerEvent->m_nTimeOffset,
  620. m_mtNextChordTime,
  621. this);
  622. rfChangedVariation = true;
  623. if ( (m_pPattern->m_dwFlags & DMUS_PATTERNF_PERSIST_CONTROL) &&
  624. m_pPatternTrack &&
  625. m_pPatternTrack->m_pVariations &&
  626. m_pPatternTrack->m_pdwRemoveVariations )
  627. {
  628. // update track's m_pVariations and m_pdwRemoveVariations (for this part)
  629. m_pPatternTrack->m_pVariations[nPart] = m_pVariations[nPart];
  630. m_pPatternTrack->m_pdwRemoveVariations[nPart] = m_pdwRemoveVariations[nPart];
  631. }
  632. }
  633. else
  634. {
  635. TraceI(3, "NOT computing variations at %d Pattern start: %d Chord times: %d, %d Flags: %x\n",
  636. mtNow, m_mtPatternStart, m_mtCurrentChordTime, m_mtNextChordTime, pMarkerEvent->m_wFlags);
  637. }
  638. }
  639. else if (pEventItem->m_dwEventTag == DMUS_EVENT_CURVE) // we have a curve event
  640. {
  641. pCurveEvent = (CDMStyleCurve*)pEventItem;
  642. if (SUCCEEDED(pPerformance->AllocPMsg( sizeof(DMUS_CURVE_PMSG),
  643. (DMUS_PMSG**) &pCurve)))
  644. {
  645. MUSIC_TIME mtSegmentTime = TimeSig.GridToClocks(pCurveEvent->m_nGridStart) +
  646. pCurveEvent->m_nTimeOffset + mtPartOffset;
  647. if (fClockTime)
  648. {
  649. pCurve->wMeasure = 0;
  650. pCurve->bBeat = 0;
  651. pCurve->bGrid = 0;
  652. pCurve->nOffset = pCurveEvent->m_nTimeOffset;
  653. pCurve->rtTime = (mtSegmentTime * REF_PER_MIL) + rtOffset;
  654. pCurve->dwFlags = DMUS_PMSGF_REFTIME | DMUS_PMSGF_LOCKTOREFTIME;
  655. }
  656. else
  657. {
  658. pCurve->wMeasure = (WORD)TimeSig.GridsToMeasure(pCurveEvent->m_nGridStart);
  659. pCurve->bBeat = (BYTE)TimeSig.GridsToBeat(pCurveEvent->m_nGridStart);
  660. pCurve->bGrid = (BYTE)TimeSig.GridOffset(pCurveEvent->m_nGridStart);
  661. pCurve->nOffset = pCurveEvent->m_nTimeOffset;
  662. pCurve->mtTime = mtSegmentTime + mtSegmentOffset;
  663. pCurve->dwFlags = DMUS_PMSGF_MUSICTIME;
  664. }
  665. pCurve->mtResetDuration = pCurveEvent->m_mtResetDuration;
  666. pCurve->mtDuration = pCurveEvent->m_mtDuration;
  667. pCurve->nResetValue = pCurveEvent->m_nResetValue;
  668. pCurve->bFlags = pCurveEvent->m_bFlags;
  669. pCurve->dwType = DMUS_PMSGT_CURVE;
  670. pCurve->dwPChannel = dwMapPChannel;
  671. pCurve->dwVirtualTrackID = m_dwVirtualTrackID; // ??
  672. pCurve->nStartValue = pCurveEvent->m_StartValue; // curve's start value
  673. pCurve->nEndValue = pCurveEvent->m_EndValue; // curve's end value
  674. pCurve->bType = pCurveEvent->m_bEventType; // type of curve
  675. pCurve->bCurveShape = pCurveEvent->m_bCurveShape; // shape of curve
  676. pCurve->bCCData = pCurveEvent->m_bCCData; // CC# if this is a control change type
  677. pCurve->dwGroupID = m_dwGroupID;
  678. pCurve->wParamType = pCurveEvent->m_wParamType;
  679. pCurve->wMergeIndex = pCurveEvent->m_wMergeIndex;
  680. // Set the DX8 flag to indicate the wMergeIndex and wParamType fields are valid.
  681. pCurve->dwFlags |= DMUS_PMSGF_DX8;
  682. if (mtPartStart) // only set on invalidation
  683. {
  684. MUSIC_TIME mtOffset = mtPartOffset + mtSegmentOffset;
  685. if (pCurve->mtTime + pCurve->mtDuration >= mtPartStart + mtOffset)
  686. {
  687. pCurve->mtOriginalStart = pCurve->mtTime;
  688. pCurve->mtTime = mtPartStart + mtOffset;
  689. }
  690. else
  691. {
  692. pCurve->mtResetDuration -= (mtPartStart + mtOffset - pCurve->mtTime);
  693. if (pCurve->mtResetDuration < 0) pCurve->mtResetDuration = 0;
  694. pCurve->mtTime = mtPartStart + mtOffset;
  695. pCurve->bCurveShape = DMUS_CURVES_INSTANT;
  696. }
  697. }
  698. IDirectMusicGraph* pGraph;
  699. if( SUCCEEDED( m_pSegState->QueryInterface( IID_IDirectMusicGraph,
  700. (void**)&pGraph )))
  701. {
  702. pGraph->StampPMsg( (DMUS_PMSG*)pCurve );
  703. pGraph->Release();
  704. }
  705. if(FAILED(pPerformance->SendPMsg( (DMUS_PMSG*)pCurve)))
  706. {
  707. pPerformance->FreePMsg( (DMUS_PMSG*)pCurve);
  708. }
  709. }
  710. }
  711. else if (pEventItem->m_dwEventTag == DMUS_EVENT_NOTE) // we have a note event
  712. {
  713. pNoteEvent = (CDMStyleNote*)pEventItem;
  714. BYTE bPlayModeFlags =
  715. (pNoteEvent->m_bPlayModeFlags & DMUS_PLAYMODE_NONE) ?
  716. rPartRef.m_pDMPart->m_bPlayModeFlags :
  717. pNoteEvent->m_bPlayModeFlags;
  718. BYTE bMidiValue = 0;
  719. short nMidiOffset = 0;
  720. HRESULT hr = rPartRef.ConvertMusicValue(pNoteEvent,
  721. m_CurrentChord,
  722. bPlayModeFlags,
  723. PlayAsIs(),
  724. m_aInversionGroups,
  725. pPerformance,
  726. bMidiValue,
  727. nMidiOffset);
  728. if (SUCCEEDED(hr) &&
  729. SUCCEEDED(pPerformance->AllocPMsg( sizeof(DMUS_NOTE_PMSG),
  730. (DMUS_PMSG**) &pNote)))
  731. {
  732. pNote->bFlags = DMUS_NOTEF_NOTEON | pNoteEvent->m_bFlags;
  733. MUSIC_TIME mtSegmentTime = TimeSig.GridToClocks(pNoteEvent->m_nGridStart) +
  734. pNoteEvent->m_nTimeOffset + mtPartOffset;
  735. if (fClockTime)
  736. {
  737. pNote->wMeasure = 0;
  738. pNote->bBeat = 0;
  739. pNote->bGrid = 0;
  740. pNote->nOffset = pNoteEvent->m_nTimeOffset;
  741. pNote->rtTime = (mtSegmentTime * REF_PER_MIL) + rtOffset;
  742. pNote->dwFlags = DMUS_PMSGF_REFTIME | DMUS_PMSGF_LOCKTOREFTIME;
  743. }
  744. else
  745. {
  746. pNote->wMeasure = (WORD)TimeSig.GridsToMeasure(pNoteEvent->m_nGridStart);
  747. pNote->bBeat = (BYTE)TimeSig.GridsToBeat(pNoteEvent->m_nGridStart);
  748. pNote->bGrid = (BYTE)TimeSig.GridOffset(pNoteEvent->m_nGridStart);
  749. pNote->nOffset = pNoteEvent->m_nTimeOffset;
  750. pNote->mtTime = mtSegmentTime + mtSegmentOffset;
  751. pNote->dwFlags = DMUS_PMSGF_MUSICTIME;
  752. }
  753. // time needs be jiggled by pNoteEvent->m_bTimeRange
  754. if (pNoteEvent->m_bTimeRange)
  755. pNote->mtTime += RandomExp(pNoteEvent->m_bTimeRange);
  756. pNote->mtDuration = pNoteEvent->m_mtDuration;
  757. // duration needs be jiggled by pNoteEvent->m_bDurRange
  758. if (pNoteEvent->m_bDurRange)
  759. pNote->mtDuration += RandomExp(pNoteEvent->m_bDurRange);
  760. // (rand() % pNoteEvent->m_bDurRange) - (pNoteEvent->m_bDurRange >> 1);
  761. pNote->bVelocity = pNoteEvent->m_bVelocity;
  762. // velocity needs be jiggled by pNoteEvent->m_bVelRange
  763. if (pNoteEvent->m_bVelRange)
  764. pNote->bVelocity +=
  765. (rand() % pNoteEvent->m_bVelRange) - (pNoteEvent->m_bVelRange >> 1);
  766. if (pNote->bVelocity < 1) pNote->bVelocity = 1;
  767. if (pNote->bVelocity > 127) pNote->bVelocity = 127;
  768. pNote->wMusicValue = pNoteEvent->m_wMusicValue;
  769. pNote->bMidiValue = bMidiValue;
  770. pNote->dwType = DMUS_PMSGT_NOTE;
  771. pNote->bPlayModeFlags = bPlayModeFlags;
  772. pNote->dwPChannel = dwMapPChannel;
  773. pNote->dwVirtualTrackID = m_dwVirtualTrackID; // ??
  774. pNote->bSubChordLevel = rPartRef.m_bSubChordLevel;
  775. pNote->dwGroupID = m_dwGroupID;
  776. pNote->bTimeRange = pNoteEvent->m_bTimeRange;
  777. pNote->bDurRange = pNoteEvent->m_bDurRange;
  778. pNote->bVelRange = pNoteEvent->m_bVelRange;
  779. pNote->cTranspose = (char) nMidiOffset;
  780. IDirectMusicGraph* pGraph;
  781. if( SUCCEEDED( m_pSegState->QueryInterface( IID_IDirectMusicGraph,
  782. (void**)&pGraph )))
  783. {
  784. pGraph->StampPMsg( (DMUS_PMSG*)pNote );
  785. pGraph->Release();
  786. }
  787. if (pNote->dwFlags & DMUS_PMSGF_REFTIME)
  788. {
  789. TraceI(5, "PLAY %d @%d\n", rPartRef.m_dwLogicalPartID,
  790. (MUSIC_TIME) (pNote->rtTime/REF_PER_MIL));
  791. }
  792. else
  793. {
  794. TraceI(5, "PLAY %d @%d: %x [%d]{%x}\n", rPartRef.m_dwLogicalPartID, pNote->mtTime,
  795. pNote->wMusicValue, pNote->bMidiValue, Variations(rPartRef, nPart));
  796. }
  797. if(FAILED(pPerformance->SendPMsg( (DMUS_PMSG*)pNote) ))
  798. {
  799. pPerformance->FreePMsg( (DMUS_PMSG*)pNote);
  800. }
  801. }
  802. }
  803. }
  804. }
  805. void PatternTrackState::SendTimeSigMessage(MUSIC_TIME mtNow, MUSIC_TIME mtOffset, MUSIC_TIME mtTime, IDirectMusicPerformance* pPerformance)
  806. {
  807. if (!m_pStyle) return;
  808. IDirectMusicGraph* pGraph = NULL;
  809. DMUS_TIMESIG_PMSG* pTimeSig;
  810. if( FAILED( m_pSegState->QueryInterface( IID_IDirectMusicGraph,
  811. (void**)&pGraph )))
  812. {
  813. pGraph = NULL;
  814. }
  815. if( SUCCEEDED( pPerformance->AllocPMsg( sizeof(DMUS_TIMESIG_PMSG),
  816. (DMUS_PMSG**)&pTimeSig )))
  817. {
  818. if( mtTime < mtNow )
  819. {
  820. // this only happens in the case where we've puposefully seeked
  821. // and need to time stamp this event with the start time
  822. pTimeSig->mtTime = mtNow + mtOffset;
  823. }
  824. else
  825. {
  826. pTimeSig->mtTime = mtTime + mtOffset;
  827. }
  828. pTimeSig->bBeatsPerMeasure = m_pStyle->m_TimeSignature.m_bBeatsPerMeasure;
  829. pTimeSig->bBeat = m_pStyle->m_TimeSignature.m_bBeat;
  830. pTimeSig->wGridsPerBeat = m_pStyle->m_TimeSignature.m_wGridsPerBeat;
  831. pTimeSig->dwFlags |= DMUS_PMSGF_MUSICTIME;
  832. pTimeSig->dwVirtualTrackID = m_dwVirtualTrackID;
  833. pTimeSig->dwType = DMUS_PMSGT_TIMESIG;
  834. pTimeSig->dwGroupID = m_dwGroupID;
  835. if( pGraph )
  836. {
  837. pGraph->StampPMsg( (DMUS_PMSG*)pTimeSig );
  838. pGraph->Release();
  839. }
  840. TraceI(3, "TimeSigtrk: TimeSig event\n");
  841. if(FAILED(pPerformance->SendPMsg( (DMUS_PMSG*)pTimeSig )))
  842. {
  843. pPerformance->FreePMsg( (DMUS_PMSG*)pTimeSig );
  844. }
  845. }
  846. }
  847. // send measure and beat notifications
  848. MUSIC_TIME PatternTrackState::NotifyMeasureBeat(
  849. MUSIC_TIME mtStart, MUSIC_TIME mtEnd, MUSIC_TIME mtOffset, IDirectMusicPerformance* pPerformance, DWORD dwFlags )
  850. {
  851. if (dwFlags & DMUS_TRACKF_NOTIFY_OFF)
  852. {
  853. return S_OK;
  854. }
  855. DMUS_NOTIFICATION_PMSG* pEvent = NULL;
  856. BYTE bCurrentBeat;
  857. WORD wCurrentMeasure;
  858. DirectMusicTimeSig& rTimeSig = PatternTimeSig();
  859. // now actually generate the beat events.
  860. // Generate events that are on beat boundaries, from mtStart to mtEnd
  861. long lQuantize = ( DMUS_PPQ * 4 ) / rTimeSig.m_bBeat;
  862. long lAbsoluteBeat = mtStart / lQuantize;
  863. bCurrentBeat = (BYTE) (lAbsoluteBeat % rTimeSig.m_bBeatsPerMeasure);
  864. wCurrentMeasure = (WORD) (lAbsoluteBeat / rTimeSig.m_bBeatsPerMeasure);
  865. while( mtStart < mtEnd )
  866. {
  867. if( SUCCEEDED( pPerformance->AllocPMsg( sizeof(DMUS_NOTIFICATION_PMSG),
  868. (DMUS_PMSG**)&pEvent )))
  869. {
  870. pEvent->dwField1 = 0;
  871. pEvent->dwField2 = 0;
  872. pEvent->dwType = DMUS_PMSGT_NOTIFICATION;
  873. pEvent->mtTime = mtStart + mtOffset;
  874. pEvent->dwFlags = DMUS_PMSGF_MUSICTIME | DMUS_PMSGF_TOOL_ATTIME;
  875. m_pSegState->QueryInterface(IID_IUnknown, (void**)&pEvent->punkUser);
  876. pEvent->dwNotificationOption = DMUS_NOTIFICATION_MEASUREBEAT;
  877. pEvent->dwField1 = bCurrentBeat;
  878. pEvent->dwField2 = wCurrentMeasure;
  879. pEvent->guidNotificationType = GUID_NOTIFICATION_MEASUREANDBEAT;
  880. pEvent->dwGroupID = m_dwGroupID;
  881. IDirectMusicGraph* pGraph;
  882. if( SUCCEEDED( m_pSegState->QueryInterface( IID_IDirectMusicGraph,
  883. (void**)&pGraph )))
  884. {
  885. pGraph->StampPMsg((DMUS_PMSG*) pEvent );
  886. pGraph->Release();
  887. }
  888. if(FAILED(pPerformance->SendPMsg((DMUS_PMSG*) pEvent )))
  889. {
  890. pPerformance->FreePMsg( (DMUS_PMSG*)pEvent);;
  891. }
  892. }
  893. bCurrentBeat++;
  894. if( bCurrentBeat >= rTimeSig.m_bBeatsPerMeasure )
  895. {
  896. bCurrentBeat = 0;
  897. wCurrentMeasure++;
  898. }
  899. mtStart += lQuantize;
  900. }
  901. return mtEnd;
  902. }
  903. MUSIC_TIME PatternTrackState::PartOffset(int nPartIndex)
  904. {
  905. return m_pmtPartOffset[nPartIndex];
  906. }
  907. /////////////////////////////////////////////////////////////////////////////
  908. // PatternTrackInfo
  909. PatternTrackInfo::PatternTrackInfo() :
  910. m_fNotifyMeasureBeat(FALSE), m_dwPChannels(0), m_pdwPChannels(NULL),
  911. m_fActive(TRUE),
  912. // m_fTrackPlay(TRUE),
  913. m_fStateSetBySetParam(FALSE),
  914. // m_fStatePlaySetBySetParam(FALSE),
  915. m_fChangeStateMappings(FALSE),
  916. m_lRandomNumberSeed(0),
  917. m_dwValidate(0),
  918. m_pVariations(NULL),
  919. m_pdwRemoveVariations(NULL)
  920. {
  921. }
  922. PatternTrackInfo::PatternTrackInfo(
  923. const PatternTrackInfo* pInfo, MUSIC_TIME mtStart, MUSIC_TIME mtEnd) :
  924. m_dwPChannels(0), m_pdwPChannels(NULL), m_lRandomNumberSeed(0), m_dwValidate(0),
  925. m_pVariations(NULL), m_pdwRemoveVariations(NULL)
  926. {
  927. if (pInfo)
  928. {
  929. m_fChangeStateMappings = pInfo->m_fChangeStateMappings;
  930. m_fNotifyMeasureBeat = pInfo->m_fNotifyMeasureBeat;
  931. m_fActive = pInfo->m_fActive;
  932. // m_fTrackPlay = pInfo->m_fTrackPlay;
  933. m_fStateSetBySetParam = pInfo->m_fStateSetBySetParam;
  934. // m_fStatePlaySetBySetParam = pInfo->m_fStatePlaySetBySetParam;
  935. }
  936. TListItem<StylePair>* pScan = pInfo->m_pISList.GetHead();
  937. //1////////////////////////////////////////
  938. TListItem<StylePair>* pPrevious = NULL;
  939. //1////////////////////////////////////////
  940. for(; pScan; pScan = pScan->GetNext())
  941. {
  942. StylePair& rScan = pScan->GetItemValue();
  943. //2////////////////////////////////////////
  944. if (rScan.m_mtTime < mtStart)
  945. {
  946. pPrevious = pScan;
  947. }
  948. //2////////////////////////////////////////
  949. else if (rScan.m_mtTime < mtEnd)
  950. {
  951. //3////////////////////////////////////////
  952. if (rScan.m_mtTime == mtStart)
  953. {
  954. pPrevious = NULL;
  955. }
  956. //3////////////////////////////////////////
  957. TListItem<StylePair>* pNew = new TListItem<StylePair>;
  958. if (pNew)
  959. {
  960. StylePair& rNew = pNew->GetItemValue();
  961. rNew.m_mtTime = rScan.m_mtTime - mtStart;
  962. rNew.m_pStyle = rScan.m_pStyle;
  963. if (rNew.m_pStyle) rNew.m_pStyle->AddRef();
  964. m_pISList.AddTail(pNew);
  965. }
  966. }
  967. }
  968. //4////////////////////////////////////////
  969. if (pPrevious)
  970. {
  971. TListItem<StylePair>* pNew = new TListItem<StylePair>;
  972. if (pNew)
  973. {
  974. StylePair& rNew = pNew->GetItemValue();
  975. rNew.m_mtTime = 0;
  976. rNew.m_pStyle = pPrevious->GetItemValue().m_pStyle;
  977. if (rNew.m_pStyle) rNew.m_pStyle->AddRef();
  978. m_pISList.AddHead(pNew);
  979. }
  980. }
  981. //4////////////////////////////////////////
  982. }
  983. PatternTrackInfo::~PatternTrackInfo()
  984. {
  985. if (m_pdwPChannels) delete [] m_pdwPChannels;
  986. if (m_pVariations) delete [] m_pVariations;
  987. if (m_pdwRemoveVariations) delete [] m_pdwRemoveVariations;
  988. }
  989. PatternTrackState* PatternTrackInfo::FindState(IDirectMusicSegmentState* pSegState)
  990. {
  991. TListItem<StatePair>* pPair = m_StateList.GetHead();
  992. for (; pPair; pPair = pPair->GetNext())
  993. {
  994. if (pPair->GetItemValue().m_pSegState == pSegState)
  995. {
  996. return pPair->GetItemValue().m_pStateData;
  997. }
  998. }
  999. return NULL;
  1000. }
  1001. HRESULT PatternTrackInfo::EndPlay(PatternTrackState* pStateData)
  1002. {
  1003. if (!pStateData) return E_FAIL;
  1004. for (TListItem<StatePair>* pScan = m_StateList.GetHead(); pScan; pScan = pScan->GetNext())
  1005. {
  1006. StatePair& rPair = pScan->GetItemValue();
  1007. if (pStateData == rPair.m_pStateData)
  1008. {
  1009. rPair.m_pSegState = NULL;
  1010. rPair.m_pStateData = NULL;
  1011. break;
  1012. }
  1013. }
  1014. delete pStateData;
  1015. return S_OK;
  1016. }
  1017. HRESULT STDMETHODCALLTYPE PatternTrackInfo::AddNotificationType(
  1018. /* [in] */ REFGUID rGuidNotify)
  1019. {
  1020. if( rGuidNotify == GUID_NOTIFICATION_MEASUREANDBEAT )
  1021. {
  1022. m_fNotifyMeasureBeat = TRUE;
  1023. return S_OK;
  1024. }
  1025. else
  1026. {
  1027. return S_FALSE;
  1028. }
  1029. }
  1030. HRESULT STDMETHODCALLTYPE PatternTrackInfo::RemoveNotificationType(
  1031. /* [in] */ REFGUID rGuidNotify)
  1032. {
  1033. if( rGuidNotify == GUID_NOTIFICATION_MEASUREANDBEAT )
  1034. {
  1035. m_fNotifyMeasureBeat = FALSE;
  1036. return S_OK;
  1037. }
  1038. else
  1039. {
  1040. return S_FALSE;
  1041. }
  1042. }
  1043. HRESULT PatternTrackInfo::InitTrackVariations(CDirectMusicPattern* pPattern)
  1044. {
  1045. HRESULT hr = S_OK;
  1046. if ( pPattern && (pPattern->m_dwFlags & DMUS_PATTERNF_PERSIST_CONTROL) )
  1047. {
  1048. // delete the variation arrays if they exist;
  1049. if (m_pVariations)
  1050. {
  1051. delete [] m_pVariations;
  1052. m_pVariations = NULL;
  1053. }
  1054. if (m_pdwRemoveVariations)
  1055. {
  1056. delete [] m_pdwRemoveVariations;
  1057. m_pdwRemoveVariations = NULL;
  1058. }
  1059. // init the variation arrays to the number of parts in the pattern
  1060. int nPartCount = pPattern->m_PartRefList.GetCount();
  1061. m_pVariations = new BYTE[nPartCount];
  1062. if (!m_pVariations)
  1063. {
  1064. return E_OUTOFMEMORY;
  1065. }
  1066. m_pdwRemoveVariations = new DWORD[nPartCount];
  1067. if (!m_pdwRemoveVariations)
  1068. {
  1069. return E_OUTOFMEMORY;
  1070. }
  1071. for (int i = 0; i < nPartCount; i++)
  1072. {
  1073. m_pVariations[i] = -1;
  1074. m_pdwRemoveVariations[i] = 0;
  1075. }
  1076. }
  1077. return hr;
  1078. }
  1079. HRESULT PatternTrackInfo::MergePChannels()
  1080. {
  1081. TList<DWORD> PChannelList;
  1082. DMStyleStruct* pStruct = NULL;
  1083. HRESULT hr = S_OK;
  1084. TListItem<StylePair>* pScan = m_pISList.GetHead();
  1085. for( ; pScan; pScan = pScan->GetNext())
  1086. {
  1087. if (pScan->GetItemValue().m_pStyle)
  1088. {
  1089. pScan->GetItemValue().m_pStyle->GetStyleInfo((void**)&pStruct);
  1090. TListItem<DWORD>* pChannel = pStruct->m_PChannelList.GetHead();
  1091. for (; pChannel; pChannel = pChannel->GetNext() )
  1092. {
  1093. AdjoinPChannel(PChannelList, pChannel->GetItemValue() );
  1094. }
  1095. }
  1096. }
  1097. if (PChannelList.IsEmpty())
  1098. {
  1099. AdjoinPChannel(PChannelList, 0);
  1100. }
  1101. TListItem<DWORD>* pPChannel = PChannelList.GetHead();
  1102. m_dwPChannels = pPChannel->GetCount();
  1103. if (m_pdwPChannels) delete [] m_pdwPChannels;
  1104. m_pdwPChannels = new DWORD[m_dwPChannels];
  1105. if (!m_pdwPChannels)
  1106. {
  1107. hr = E_OUTOFMEMORY;
  1108. }
  1109. else
  1110. {
  1111. for (int i = 0; i < (int)m_dwPChannels; i++)
  1112. {
  1113. m_pdwPChannels[i] = pPChannel->GetItemValue();
  1114. pPChannel = pPChannel->GetNext();
  1115. }
  1116. m_fChangeStateMappings = TRUE;
  1117. }
  1118. return hr;
  1119. }
  1120. inline int CurveIndex(CDirectMusicEventItem* pEvent)
  1121. {
  1122. CDMStyleCurve* pCurve = NULL;
  1123. if (pEvent->m_dwEventTag == DMUS_EVENT_CURVE)
  1124. {
  1125. pCurve = (CDMStyleCurve*)pEvent;
  1126. switch (pCurve->m_bEventType)
  1127. {
  1128. case DMUS_CURVET_CCCURVE:
  1129. return pCurve->m_bCCData & 0x7f;
  1130. case DMUS_CURVET_PATCURVE:
  1131. return (pCurve->m_bCCData & 0x7f) + 128;
  1132. case DMUS_CURVET_PBCURVE:
  1133. return 256;
  1134. case DMUS_CURVET_MATCURVE:
  1135. return 257;
  1136. default:
  1137. return -1;
  1138. }
  1139. }
  1140. return -1;
  1141. }
  1142. CurveSeek::CurveSeek()
  1143. {
  1144. for (int nType = 0; nType < CURVE_TYPES; nType++)
  1145. {
  1146. m_apCurves[nType] = NULL;
  1147. m_amtTimeStamps[nType] = 0;
  1148. }
  1149. m_fFoundCurve = false;
  1150. }
  1151. void CurveSeek::AddCurve(CDirectMusicEventItem* pEvent, MUSIC_TIME mtTimeStamp)
  1152. {
  1153. int nIndex = CurveIndex(pEvent);
  1154. if (nIndex >= 0)
  1155. {
  1156. if (!m_apCurves[nIndex] ||
  1157. m_amtTimeStamps[nIndex] < mtTimeStamp)
  1158. {
  1159. m_apCurves[nIndex] = pEvent;
  1160. m_amtTimeStamps[nIndex] = mtTimeStamp;
  1161. m_fFoundCurve = true;
  1162. }
  1163. }
  1164. }
  1165. void CurveSeek::PlayCurves(
  1166. PatternTrackState* pStateData,
  1167. DirectMusicTimeSig& TimeSig,
  1168. MUSIC_TIME mtPatternOffset,
  1169. MUSIC_TIME mtOffset,
  1170. REFERENCE_TIME rtOffset,
  1171. IDirectMusicPerformance* pPerformance,
  1172. short nPart,
  1173. DirectMusicPartRef& rPartRef,
  1174. BOOL fClockTime,
  1175. MUSIC_TIME mtPartStart)
  1176. {
  1177. if (m_fFoundCurve)
  1178. {
  1179. for (int nType = 0; nType < CURVE_TYPES; nType++)
  1180. {
  1181. CDirectMusicEventItem* pScan = m_apCurves[nType];
  1182. if (pScan)
  1183. {
  1184. int nGrid = pScan->m_nGridStart;
  1185. CDirectMusicEventItem* pWinner = pScan;
  1186. MUSIC_TIME mtBiggest = pWinner->m_nTimeOffset;
  1187. for (; pScan && pScan->m_nGridStart == nGrid; pScan = pScan->GetNext())
  1188. {
  1189. if (pScan->m_dwEventTag == DMUS_EVENT_CURVE &&
  1190. pScan->m_nTimeOffset > mtBiggest)
  1191. {
  1192. pWinner = pScan;
  1193. mtBiggest = pWinner->m_nTimeOffset;
  1194. }
  1195. }
  1196. MUSIC_TIME mtNow = 0;
  1197. bool fChange = false;
  1198. pStateData->BumpTime(pWinner, TimeSig, mtPatternOffset, mtNow);
  1199. pStateData->PlayPatternEvent(
  1200. mtNow,
  1201. pWinner,
  1202. TimeSig,
  1203. mtPatternOffset,
  1204. mtOffset,
  1205. rtOffset,
  1206. pPerformance,
  1207. nPart,
  1208. rPartRef,
  1209. fClockTime,
  1210. mtPartStart,
  1211. fChange);
  1212. }
  1213. }
  1214. m_fFoundCurve = false;
  1215. }
  1216. }