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.

588 lines
19 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (c) 1999-1999 Microsoft Corporation
  6. //
  7. // File: mgentrk.h
  8. //
  9. //--------------------------------------------------------------------------
  10. /////////////////////////////////////////////////////////////////////////////
  11. // MelodyFragment
  12. #ifndef __MELGENTRK_H_
  13. #define __MELGENTRK_H_
  14. #include "dmusici.h"
  15. #include "TList.h"
  16. //#include "dmpublic.h" // remove when this gets incorporated into dmusici.h/dmusicf.h
  17. #include "dmstyle.h"
  18. #define DMUS_TRANSITIONF_GHOST_FOUND 1
  19. #define DMUS_TRANSITIONF_OVERLAP_FOUND 2
  20. #define DMUS_TRANSITIONF_LAST_FOUND 4
  21. #define DMUS_TRANSITIONF_GHOST_OK 8
  22. #define DMUS_TRANSITIONF_OVERLAP_OK 0x10
  23. #define DMUS_TRANSITIONF_LAST_OK 0x20
  24. // overlap delta is largest value less than a 128th note triplet
  25. #define OVERLAP_DELTA 15
  26. HRESULT CopyMelodyFragment(DMUS_MELODY_FRAGMENT& rTo, const DMUS_MELODY_FRAGMENT& rFrom);
  27. HRESULT CopyMelodyFragment(DMUS_MELODY_FRAGMENT& rTo, const DMUS_IO_MELODY_FRAGMENT& rFrom);
  28. HRESULT CopyMelodyFragment(DMUS_IO_MELODY_FRAGMENT& rTo, const DMUS_MELODY_FRAGMENT& rFrom);
  29. HRESULT CopyMelodyFragment(DMUS_IO_MELODY_FRAGMENT& rTo, const DMUS_IO_MELODY_FRAGMENT& rFrom);
  30. struct CompositionFragment;
  31. struct EventWrapper;
  32. BOOL Less(DMUS_IO_SEQ_ITEM& SeqItem1, DMUS_IO_SEQ_ITEM& SeqItem2);
  33. BOOL Greater(DMUS_IO_SEQ_ITEM& SeqItem1, DMUS_IO_SEQ_ITEM& SeqItem2);
  34. BOOL Less(EventWrapper& SeqItem1, EventWrapper& SeqItem2);
  35. BOOL Greater(EventWrapper& SeqItem1, EventWrapper& SeqItem2);
  36. /////////////////////////////////////////////////////////////////////////////
  37. // MelodyFragment
  38. struct MelodyFragment
  39. {
  40. MelodyFragment() {}
  41. MelodyFragment(DMUS_MELODY_FRAGMENT& rSource) :
  42. m_mtTime(rSource.mtTime),
  43. m_dwID(rSource.dwID),
  44. m_dwVariationFlags(rSource.dwVariationFlags),
  45. m_dwRepeatFragmentID(rSource.dwRepeatFragmentID),
  46. m_dwFragmentFlags(rSource.dwFragmentFlags),
  47. m_dwPlayModeFlags(rSource.dwPlayModeFlags),
  48. m_dwTransposeIntervals(rSource.dwTransposeIntervals),
  49. m_ConnectionArc(rSource.ConnectionArc),
  50. m_Command(rSource.Command)
  51. {
  52. wcscpy(m_wszVariationLabel, rSource.wszVariationLabel);
  53. }
  54. MelodyFragment(MelodyFragment& rSource) :
  55. m_mtTime(rSource.m_mtTime),
  56. m_dwID(rSource.m_dwID),
  57. m_dwVariationFlags(rSource.m_dwVariationFlags),
  58. m_dwRepeatFragmentID(rSource.m_dwRepeatFragmentID),
  59. m_dwFragmentFlags(rSource.m_dwFragmentFlags),
  60. m_dwPlayModeFlags(rSource.m_dwPlayModeFlags),
  61. m_dwTransposeIntervals(rSource.m_dwTransposeIntervals),
  62. m_ConnectionArc(rSource.m_ConnectionArc),
  63. m_Command(rSource.m_Command)
  64. {
  65. wcscpy(m_wszVariationLabel, rSource.m_wszVariationLabel);
  66. for (int i = 0; i < INVERSIONGROUPLIMIT; i++)
  67. {
  68. m_aInversionGroups[i] = rSource.m_aInversionGroups[i];
  69. }
  70. }
  71. HRESULT GetPattern(DMStyleStruct* pStyleStruct,
  72. CDirectMusicPattern*& rPattern,
  73. TListItem<CompositionFragment>* pLastFragment);
  74. HRESULT GetVariations(CompositionFragment& rCompFragment,
  75. CompositionFragment& rfragmentRepeat,
  76. CompositionFragment& rfragmentLast,
  77. DMUS_CHORD_PARAM& rCurrentChord,
  78. DMUS_CHORD_PARAM& rNextChord,
  79. MUSIC_TIME mtNextChord,
  80. TListItem<CompositionFragment>* pLastFragment);
  81. /* HRESULT GetVariation(DirectMusicPartRef& rPartRef,
  82. DMUS_CHORD_PARAM& rCurrentChord,
  83. MUSIC_TIME mtNext,
  84. MUSIC_TIME mtNextChord,
  85. IDirectMusicTrack* pChordTrack,
  86. DWORD& rdwVariation);
  87. */
  88. HRESULT GetChord(IDirectMusicSegment* pTempSeg,
  89. IDirectMusicSong* pSong,
  90. DWORD dwTrackGroup,
  91. MUSIC_TIME& rmtNext,
  92. DMUS_CHORD_PARAM& rCurrentChord,
  93. MUSIC_TIME& rmtCurrent,
  94. DMUS_CHORD_PARAM& rRealCurrentChord);
  95. HRESULT GetChord(MUSIC_TIME mtTime,
  96. IDirectMusicSegment* pTempSeg,
  97. IDirectMusicSong* pSong,
  98. DWORD dwTrackGroup,
  99. MUSIC_TIME& rmtNext,
  100. DMUS_CHORD_PARAM& rCurrentChord);
  101. HRESULT TestTransition(BYTE bMIDI,
  102. MUSIC_TIME mtTime,
  103. DMUS_CHORD_PARAM& rCurrentChord,
  104. int nPartIndex,
  105. DirectMusicPartRef& rPartRef,
  106. TListItem<CompositionFragment>* pLastFragment);
  107. HRESULT TestHarmonicConstraints(TListItem<EventWrapper>* pOldEventHead,
  108. TList<EventWrapper>& rNewEventList);
  109. HRESULT GetFirstNote(int nVariation,
  110. DMUS_CHORD_PARAM& rCurrentChord,
  111. CompositionFragment& rCompFragment,
  112. DirectMusicPartRef& rPartRef,
  113. BYTE& rbMidi,
  114. MUSIC_TIME& rmtNote);
  115. HRESULT GetNote(CDirectMusicEventItem* pEvent,
  116. DMUS_CHORD_PARAM& rCurrentChord,
  117. DirectMusicPartRef& rPartRef,
  118. BYTE& rbMidi);
  119. HRESULT GetEvent(CDirectMusicEventItem* pEvent,
  120. DMUS_CHORD_PARAM& rCurrentChord,
  121. DMUS_CHORD_PARAM& rRealCurrentChord,
  122. MUSIC_TIME mtNow,
  123. DirectMusicPartRef& rPartRef,
  124. TListItem<EventWrapper>*& rpEventItem);
  125. HRESULT TransposeEventList(int nInterval,
  126. CompositionFragment& rfragmentRepeat,
  127. DMUS_CHORD_PARAM& rCurrentChord,
  128. DMUS_CHORD_PARAM& rRealCurrentChord,
  129. BYTE bPlaymode,
  130. DirectMusicPartRef& rPartRef,
  131. TListItem<EventWrapper>*& rpOldEventHead,
  132. TList<EventWrapper>& rNewEventList,
  133. BYTE& rbFirstMIDI,
  134. MUSIC_TIME& rmtFirstTime);
  135. HRESULT GetRepeatedEvents(CompositionFragment& rfragmentRepeat,
  136. DMUS_CHORD_PARAM& rCurrentChord,
  137. DMUS_CHORD_PARAM& rRealCurrentChord,
  138. BYTE bPlaymode,
  139. int nPartIndex,
  140. DirectMusicPartRef& rPartRef,
  141. TListItem<CompositionFragment>* pLastFragment,
  142. MUSIC_TIME& rmtFirstNote,
  143. TList<EventWrapper>& rEventList);
  144. bool UsesRepeat()
  145. {
  146. return (m_dwFragmentFlags & DMUS_FRAGMENTF_USE_REPEAT) ? true : false;
  147. }
  148. bool UsesTransitionRules()
  149. {
  150. return (m_ConnectionArc.dwFlags & (DMUS_CONNECTIONF_GHOST | DMUS_CONNECTIONF_INTERVALS | DMUS_CONNECTIONF_OVERLAP)) ? true : false;
  151. }
  152. bool RepeatsWithConstraints()
  153. {
  154. return
  155. UsesRepeat() &&
  156. ( (m_dwFragmentFlags & (DMUS_FRAGMENTF_SCALE | DMUS_FRAGMENTF_CHORD)) ? true : false );
  157. }
  158. DWORD GetID()
  159. {
  160. return m_dwID;
  161. }
  162. DWORD GetRepeatID()
  163. {
  164. return m_dwRepeatFragmentID;
  165. }
  166. MUSIC_TIME GetTime()
  167. {
  168. return m_mtTime;
  169. }
  170. DMUS_COMMAND_PARAM GetCommand()
  171. {
  172. return m_Command;
  173. }
  174. DMUS_CONNECTION_RULE GetConnectionArc()
  175. {
  176. return m_ConnectionArc;
  177. }
  178. DWORD GetVariationFlags()
  179. {
  180. return m_dwVariationFlags;
  181. }
  182. void ClearInversionGroups()
  183. {
  184. for (int i = 0; i < INVERSIONGROUPLIMIT; i++)
  185. m_aInversionGroups[i].m_wGroupID = 0;
  186. }
  187. protected:
  188. MUSIC_TIME m_mtTime;
  189. DWORD m_dwID; // This fragment's ID
  190. WCHAR m_wszVariationLabel[DMUS_MAX_FRAGMENTLABEL]; // Each style translates this into a set of variations (held in part ref)
  191. DWORD m_dwVariationFlags; // A set of variations
  192. DWORD m_dwRepeatFragmentID; // ID of a fragment to repeat
  193. DWORD m_dwFragmentFlags; // including things like: invert the fragment, transpose it...
  194. DWORD m_dwPlayModeFlags; // including new playmodes (only use 8 bits of this)
  195. DWORD m_dwTransposeIntervals; // Legal transposition intervals (first 24 bits; two-octave range)
  196. DMUS_COMMAND_PARAM m_Command;
  197. DMUS_CONNECTION_RULE m_ConnectionArc;
  198. InversionGroup m_aInversionGroups[INVERSIONGROUPLIMIT]; // Inversion Groups for composing melodies
  199. };
  200. // TransitionConstraint (for keeping track of transition constraints)
  201. struct TransitionConstraint
  202. {
  203. TransitionConstraint() : dwFlags(0), bGhost(0), bOverlap(0), bLastPlayed(0)
  204. {
  205. }
  206. DWORD dwFlags;
  207. BYTE bGhost;
  208. BYTE bOverlap;
  209. BYTE bLastPlayed;
  210. };
  211. // EventOverlap (for remembering events that might overlap succeeding fragments)
  212. struct EventOverlap
  213. {
  214. ~EventOverlap()
  215. {
  216. ZeroMemory(&m_PartRef, sizeof(m_PartRef));
  217. m_pEvent = NULL;
  218. }
  219. DirectMusicPartRef m_PartRef;
  220. MUSIC_TIME m_mtTime;
  221. MUSIC_TIME m_mtDuration;
  222. CDirectMusicEventItem* m_pEvent;
  223. DMUS_CHORD_PARAM m_Chord;
  224. DMUS_CHORD_PARAM m_RealChord;
  225. };
  226. struct EventWrapper
  227. {
  228. EventWrapper() : m_pEvent(NULL), m_mtTime(0), m_bMIDI(0), m_dwPChannel(0), m_wMusic(0), m_bPlaymode(DMUS_PLAYMODE_NONE)
  229. {
  230. }
  231. ~EventWrapper()
  232. {
  233. m_pEvent = NULL;
  234. }
  235. CDirectMusicEventItem* m_pEvent;
  236. MUSIC_TIME m_mtTime;
  237. DWORD m_dwPChannel;
  238. WORD m_wMusic;
  239. BYTE m_bMIDI;
  240. BYTE m_bScaleFlat;
  241. BYTE m_bScaleSharp;
  242. BYTE m_bChordFlat;
  243. BYTE m_bChordSharp;
  244. BYTE m_bPlaymode;
  245. };
  246. // FragmentPartRecord (for keeping track of previously generated melody fragment parts)
  247. // (in addition to sequence events, may also want to keep track of note events)
  248. struct FragmentPartRecord
  249. {
  250. FragmentPartRecord()
  251. {
  252. }
  253. ~FragmentPartRecord()
  254. {
  255. m_listEvents.CleanUp();
  256. }
  257. TList<EventWrapper> m_listEvents;
  258. };
  259. // CompositionFragment (melody fragment used in the composition process)
  260. struct CompositionFragment : MelodyFragment
  261. {
  262. CompositionFragment()
  263. {
  264. m_aFragmentParts = NULL;
  265. m_abVariations = NULL;
  266. m_pStyle = NULL;
  267. m_pPattern = NULL;
  268. }
  269. CompositionFragment(MelodyFragment& rFragment) : MelodyFragment(rFragment)
  270. {
  271. m_aFragmentParts = NULL;
  272. m_abVariations = NULL;
  273. m_pStyle = NULL;
  274. m_pPattern = NULL;
  275. }
  276. ~CompositionFragment()
  277. {
  278. if (m_aFragmentParts) delete [] m_aFragmentParts;
  279. if (m_abVariations) delete [] m_abVariations;
  280. }
  281. HRESULT Init(CDirectMusicPattern* pPattern, DMStyleStruct* pStyleStruct, int nParts)
  282. {
  283. m_pStyle = pStyleStruct;
  284. m_pPattern = pPattern;
  285. m_abVariations = new BYTE [nParts];
  286. if (!m_abVariations)
  287. {
  288. return E_OUTOFMEMORY;
  289. }
  290. m_aFragmentParts = new FragmentPartRecord[nParts];
  291. if (!m_aFragmentParts)
  292. {
  293. delete [] m_abVariations;
  294. m_abVariations = NULL;
  295. return E_OUTOFMEMORY;
  296. }
  297. return S_OK;
  298. }
  299. void SetPattern(CDirectMusicPattern* pPattern)
  300. {
  301. m_pPattern = pPattern;
  302. }
  303. void SetStyle(DMStyleStruct* pStyle)
  304. {
  305. m_pStyle = pStyle;
  306. }
  307. TListItem<EventOverlap>* GetOverlapHead()
  308. {
  309. return m_listEventOverlaps.GetHead();
  310. }
  311. TList<EventWrapper>& EventList(int i)
  312. {
  313. return m_aFragmentParts[i].m_listEvents;
  314. }
  315. void AddOverlap(TListItem<EventOverlap>* pOverlap)
  316. {
  317. m_listEventOverlaps.AddHead(pOverlap);
  318. }
  319. TListItem<EventWrapper>* GetEventHead(int i)
  320. {
  321. return m_aFragmentParts[i].m_listEvents.GetHead();
  322. }
  323. TListItem<EventWrapper>* RemoveEventHead(int i)
  324. {
  325. return m_aFragmentParts[i].m_listEvents.RemoveHead();
  326. }
  327. void AddEvent(int i, TListItem<EventWrapper>* pEvent)
  328. {
  329. m_aFragmentParts[i].m_listEvents.AddHead(pEvent);
  330. }
  331. void InsertEvent(int i, TListItem<EventWrapper>* pEvent)
  332. {
  333. TListItem<EventWrapper>* pScan = m_aFragmentParts[i].m_listEvents.GetHead();
  334. TListItem<EventWrapper>* pPrevious = NULL;
  335. for (; pScan; pScan = pScan->GetNext() )
  336. {
  337. if ( Greater(pEvent->GetItemValue(), pScan->GetItemValue()) ) break;
  338. pPrevious = pScan;
  339. }
  340. if (!pPrevious)
  341. {
  342. m_aFragmentParts[i].m_listEvents.AddHead(pEvent);
  343. }
  344. else
  345. {
  346. pPrevious->SetNext(pEvent);
  347. pEvent->SetNext(pScan);
  348. }
  349. }
  350. void SortEvents(int i)
  351. {
  352. m_aFragmentParts[i].m_listEvents.MergeSort(Greater);
  353. }
  354. BOOL IsEmptyEvents(int i)
  355. {
  356. return m_aFragmentParts[i].m_listEvents.IsEmpty();
  357. }
  358. void CleanupEvents(int i)
  359. {
  360. m_aFragmentParts[i].m_listEvents.CleanUp();
  361. }
  362. DirectMusicTimeSig& GetTimeSig(DirectMusicPart* pPart)
  363. {
  364. if (pPart && pPart->m_timeSig.m_bBeat != 0)
  365. {
  366. return pPart->m_timeSig;
  367. }
  368. else if (m_pPattern && m_pPattern->m_timeSig.m_bBeat != 0)
  369. {
  370. return m_pPattern->m_timeSig;
  371. }
  372. else if (m_pStyle && m_pStyle->m_TimeSignature.m_bBeat != 0)
  373. {
  374. return m_pStyle->m_TimeSignature;
  375. }
  376. else
  377. {
  378. return m_staticTimeSig;
  379. }
  380. }
  381. CDirectMusicPattern* m_pPattern;
  382. FragmentPartRecord* m_aFragmentParts;
  383. BYTE* m_abVariations;
  384. TList<EventOverlap> m_listEventOverlaps;
  385. DMStyleStruct* m_pStyle;
  386. static DirectMusicTimeSig m_staticTimeSig;
  387. };
  388. /////////////////////////////////////////////////////////////////////////////
  389. // CMelodyFormulationTrack
  390. class CMelodyFormulationTrack :
  391. public IDirectMusicTrack8,
  392. public IPersistStream
  393. {
  394. public:
  395. CMelodyFormulationTrack();
  396. CMelodyFormulationTrack(const CMelodyFormulationTrack& rTrack, MUSIC_TIME mtStart, MUSIC_TIME mtEnd);
  397. ~CMelodyFormulationTrack();
  398. void Clear();
  399. // IUnknown
  400. //
  401. virtual STDMETHODIMP QueryInterface(const IID &iid, void **ppv);
  402. virtual STDMETHODIMP_(ULONG) AddRef();
  403. virtual STDMETHODIMP_(ULONG) Release();
  404. public:
  405. HRESULT STDMETHODCALLTYPE Init(
  406. /*[in]*/ IDirectMusicSegment* pSegment
  407. );
  408. HRESULT STDMETHODCALLTYPE InitPlay(
  409. /*[in]*/ IDirectMusicSegmentState* pSegmentState,
  410. /*[in]*/ IDirectMusicPerformance* pPerformance,
  411. /*[out]*/ void** ppStateData,
  412. /*[in]*/ DWORD dwTrackID,
  413. /*[in]*/ DWORD dwFlags
  414. );
  415. HRESULT STDMETHODCALLTYPE EndPlay(
  416. /*[in]*/ void* pStateData
  417. );
  418. HRESULT STDMETHODCALLTYPE Play(
  419. /*[in]*/ void* pStateData,
  420. /*[in]*/ MUSIC_TIME mtStart,
  421. /*[in]*/ MUSIC_TIME mtEnd,
  422. /*[in]*/ MUSIC_TIME mtOffset,
  423. DWORD dwFlags,
  424. IDirectMusicPerformance* pPerf,
  425. IDirectMusicSegmentState* pSegState,
  426. DWORD dwVirtualID
  427. );
  428. HRESULT STDMETHODCALLTYPE GetParam(
  429. REFGUID pCommandGuid,
  430. MUSIC_TIME mtTime,
  431. MUSIC_TIME* pmtNext,
  432. void *pData);
  433. HRESULT STDMETHODCALLTYPE SetParam(
  434. /* [in] */ REFGUID pCommandGuid,
  435. /* [in] */ MUSIC_TIME mtTime,
  436. /* [out] */ void __RPC_FAR *pData);
  437. HRESULT STDMETHODCALLTYPE AddNotificationType(
  438. /* [in] */ REFGUID pGuidNotify
  439. );
  440. HRESULT STDMETHODCALLTYPE RemoveNotificationType(
  441. /* [in] */ REFGUID pGuidNotify
  442. );
  443. HRESULT STDMETHODCALLTYPE Clone(
  444. MUSIC_TIME mtStart,
  445. MUSIC_TIME mtEnd,
  446. IDirectMusicTrack** ppTrack);
  447. HRESULT STDMETHODCALLTYPE IsParamSupported(
  448. /*[in]*/ REFGUID pGuid
  449. );
  450. // IDirectMusicTrack8 Methods
  451. STDMETHODIMP PlayEx(void* pStateData,REFERENCE_TIME rtStart,
  452. REFERENCE_TIME rtEnd,REFERENCE_TIME rtOffset,
  453. DWORD dwFlags,IDirectMusicPerformance* pPerf,
  454. IDirectMusicSegmentState* pSegSt,DWORD dwVirtualID) ;
  455. STDMETHODIMP GetParamEx(REFGUID rguidType,REFERENCE_TIME rtTime,
  456. REFERENCE_TIME* prtNext,void* pParam,void * pStateData, DWORD dwFlags) ;
  457. STDMETHODIMP SetParamEx(REFGUID rguidType,REFERENCE_TIME rtTime,void* pParam, void * pStateData, DWORD dwFlags) ;
  458. STDMETHODIMP Compose(IUnknown* pContext,
  459. DWORD dwTrackGroup,
  460. IDirectMusicTrack** ppResultTrack) ;
  461. STDMETHODIMP Join(IDirectMusicTrack* pNewTrack,
  462. MUSIC_TIME mtJoin,
  463. IUnknown* pContext,
  464. DWORD dwTrackGroup,
  465. IDirectMusicTrack** ppResultTrack) ;
  466. // IPersist methods
  467. HRESULT STDMETHODCALLTYPE GetClassID( LPCLSID pclsid );
  468. // IPersistStream methods
  469. HRESULT STDMETHODCALLTYPE IsDirty();
  470. HRESULT STDMETHODCALLTYPE Save( LPSTREAM pStream, BOOL fClearDirty );
  471. HRESULT STDMETHODCALLTYPE GetSizeMax( ULARGE_INTEGER* /*pcbSize*/ );
  472. HRESULT STDMETHODCALLTYPE Load( LPSTREAM pStream );
  473. // Methods for dealing with melody fragments
  474. HRESULT SendNotification(MUSIC_TIME mtTime,
  475. IDirectMusicPerformance* pPerf,
  476. IDirectMusicSegment* pSegment,
  477. IDirectMusicSegmentState* pSegState,
  478. DWORD dwFlags);
  479. HRESULT LoadFragments(LPSTREAM pStream, long lFileSize );
  480. HRESULT SetID(DWORD& rdwID);
  481. HRESULT GetID(DWORD& rdwID);
  482. HRESULT AddToSegment(IDirectMusicSegment* pTempSeg,
  483. IDirectMusicTrack* pNewPatternTrack,
  484. DWORD dwGroupBits);
  485. protected:
  486. // attributes
  487. long m_cRef;
  488. CRITICAL_SECTION m_CriticalSection; // for load and playback
  489. BYTE m_bRequiresSave;
  490. BOOL m_fNotifyRecompose;
  491. TList<DMUS_MELODY_FRAGMENT> m_FragmentList;
  492. DWORD m_dwLastId;
  493. BYTE m_bPlaymode; // playmode for events in the generated pattern track.
  494. };
  495. #endif // __MELGENTRK_H_