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.

1801 lines
62 KiB

  1. // Copyright (c) 1998-2001 Microsoft Corporation
  2. //
  3. // midifile.cpp
  4. //
  5. // original author: Dave Miller
  6. // original project: AudioActive
  7. // modified by: Mark Burton
  8. // project: DirectMusic
  9. //
  10. #include <windows.h>
  11. #include <mmsystem.h>
  12. #include <dsoundp.h>
  13. #include "debug.h"
  14. #define ASSERT assert
  15. #include "Template.h"
  16. #include "dmusici.h"
  17. #include "dmperf.h"
  18. #include "dmusicf.h"
  19. #include "..\dmusic\dmcollec.h"
  20. #include "alist.h"
  21. #include "tlist.h"
  22. #include "dmime.h"
  23. #include "..\dmband\dmbndtrk.h"
  24. #include "..\dmband\bandinst.h"
  25. typedef struct _DMUS_IO_BANKSELECT_ITEM
  26. {
  27. BYTE byLSB;
  28. BYTE byMSB;
  29. BYTE byPad[2];
  30. } DMUS_IO_BANKSELECT_ITEM;
  31. #define EVENT_VOICE 1 // Performance event
  32. #define EVENT_REALTIME 2 // qevent() must invoke interrupt
  33. #define EVENT_ONTIME 3 // event should be handled on time
  34. /* MIDI status bytes ==================================================*/
  35. #define MIDI_NOTEOFF 0x80
  36. #define MIDI_NOTEON 0x90
  37. #define MIDI_PTOUCH 0xA0
  38. #define MIDI_CCHANGE 0xB0
  39. #define MIDI_PCHANGE 0xC0
  40. #define MIDI_MTOUCH 0xD0
  41. #define MIDI_PBEND 0xE0
  42. #define MIDI_SYSX 0xF0
  43. #define MIDI_MTC 0xF1
  44. #define MIDI_SONGPP 0xF2
  45. #define MIDI_SONGS 0xF3
  46. #define MIDI_EOX 0xF7
  47. #define MIDI_CLOCK 0xF8
  48. #define MIDI_START 0xFA
  49. #define MIDI_CONTINUE 0xFB
  50. #define MIDI_STOP 0xFC
  51. #define MIDI_SENSE 0xFE
  52. #define ET_NOTEOFF ( MIDI_NOTEOFF >> 4 ) // 0x08
  53. #define ET_NOTEON ( MIDI_NOTEON >> 4 ) // 0x09
  54. #define ET_PTOUCH ( MIDI_PTOUCH >> 4 ) // 0x0A
  55. #define ET_CCHANGE ( MIDI_CCHANGE >> 4 ) // 0x0B
  56. #define ET_PCHANGE ( MIDI_PCHANGE >> 4 ) // 0x0C
  57. #define ET_MTOUCH ( MIDI_MTOUCH >> 4 ) // 0x0D
  58. #define ET_PBEND ( MIDI_PBEND >> 4 ) // 0x0E
  59. #define ET_SYSX ( MIDI_SYSX >> 4 ) // 0x0F
  60. #define ET_PBCURVE 0x03
  61. #define ET_CCCURVE 0x04
  62. #define ET_MATCURVE 0x05
  63. #define ET_PATCURVE 0x06
  64. #define ET_TEMPOEVENT 0x01
  65. #define ET_NOTDEFINED 0
  66. #define NUM_MIDI_CHANNELS 16
  67. struct FSEBlock;
  68. /* FullSeqEvent is SeqEvent plus next pointers*/
  69. typedef struct FullSeqEvent : DMUS_IO_SEQ_ITEM
  70. {
  71. struct FullSeqEvent* pNext;
  72. struct FullSeqEvent* pTempNext; /* used in the compresseventlist routine */
  73. long pos; /* used to keep track of the order of events in the file */
  74. private:
  75. DWORD dwPosInBlock;
  76. static FSEBlock* sm_pBlockList;
  77. public:
  78. static void CleanUp();
  79. void* operator new(size_t n);
  80. void operator delete(void* p);
  81. } FullSeqEvent;
  82. #define BITMAPSPERBLOCK 8
  83. struct FSEBlock
  84. {
  85. FSEBlock()
  86. {
  87. for(int i = 0 ; i < BITMAPSPERBLOCK ; ++i)
  88. {
  89. m_dwBitMap[i] = 0;
  90. }
  91. };
  92. FSEBlock* m_pNext;
  93. DWORD m_dwBitMap[BITMAPSPERBLOCK];
  94. FullSeqEvent m_Event[BITMAPSPERBLOCK][32];
  95. };
  96. FSEBlock* FullSeqEvent::sm_pBlockList;
  97. void FullSeqEvent::CleanUp()
  98. {
  99. FSEBlock* pBlock;
  100. FSEBlock* pNext;
  101. for(pBlock = sm_pBlockList ; pBlock != NULL ; pBlock = pNext)
  102. {
  103. #ifdef DEBUG
  104. for(int i = 0 ; i < BITMAPSPERBLOCK ; ++i)
  105. {
  106. if(pBlock->m_dwBitMap[i] != 0)
  107. {
  108. DebugBreak();
  109. }
  110. }
  111. #endif
  112. pNext = pBlock->m_pNext;
  113. delete pBlock;
  114. }
  115. sm_pBlockList = NULL;
  116. }
  117. void* FullSeqEvent::operator new(size_t n)
  118. {
  119. if(sm_pBlockList == NULL)
  120. {
  121. sm_pBlockList = new FSEBlock;
  122. if(sm_pBlockList == NULL)
  123. {
  124. return NULL;
  125. }
  126. sm_pBlockList->m_pNext = NULL;
  127. sm_pBlockList->m_dwBitMap[0] = 1;
  128. sm_pBlockList->m_Event[0][0].dwPosInBlock = 0;
  129. return &sm_pBlockList->m_Event[0][0];
  130. }
  131. FSEBlock* pBlock;
  132. int i;
  133. DWORD dw;
  134. for(pBlock = sm_pBlockList ; pBlock != NULL ; pBlock = pBlock->m_pNext)
  135. {
  136. for(i = 0 ; i < BITMAPSPERBLOCK ; ++i)
  137. {
  138. if(pBlock->m_dwBitMap[i] != 0xffff)
  139. {
  140. break;
  141. }
  142. }
  143. if(i < BITMAPSPERBLOCK)
  144. {
  145. break;
  146. }
  147. }
  148. if(pBlock == NULL)
  149. {
  150. pBlock = new FSEBlock;
  151. if(pBlock == NULL)
  152. {
  153. return NULL;
  154. }
  155. pBlock->m_pNext = sm_pBlockList;
  156. sm_pBlockList = pBlock;
  157. pBlock->m_dwBitMap[0] = 1;
  158. pBlock->m_Event[0][0].dwPosInBlock = 0;
  159. return &pBlock->m_Event[0][0];
  160. }
  161. for(dw = 0 ; (pBlock->m_dwBitMap[i] & (1 << dw)) != 0 ; ++dw);
  162. pBlock->m_dwBitMap[i] |= (1 << dw);
  163. pBlock->m_Event[i][dw].dwPosInBlock = (i << 6) | dw;
  164. return &pBlock->m_Event[i][dw];
  165. }
  166. void FullSeqEvent::operator delete(void* p)
  167. {
  168. FSEBlock* pBlock;
  169. int i;
  170. DWORD dw;
  171. FullSeqEvent* pEvent = (FullSeqEvent*)p;
  172. dw = pEvent->dwPosInBlock & 0x1f;
  173. i = pEvent->dwPosInBlock >> 6;
  174. for(pBlock = sm_pBlockList ; pBlock != NULL ; pBlock = pBlock->m_pNext)
  175. {
  176. if(p == &pBlock->m_Event[i][dw])
  177. {
  178. pBlock->m_dwBitMap[i] &= ~(1 << dw);
  179. return;
  180. }
  181. }
  182. }
  183. TList<StampedGMGSXG> gMidiModeList;
  184. // One for each MIDI channel 0-15
  185. DMUS_IO_BANKSELECT_ITEM gBankSelect[NUM_MIDI_CHANNELS];
  186. DWORD gPatchTable[NUM_MIDI_CHANNELS];
  187. long gPos; // Keeps track of order of events in the file
  188. DWORD gdwLastControllerTime[NUM_MIDI_CHANNELS]; // Holds the time of the last CC event.
  189. DWORD gdwControlCollisionOffset[NUM_MIDI_CHANNELS]; // Holds the index of the last CC.
  190. DWORD gdwLastPitchBendValue[NUM_MIDI_CHANNELS]; // Holds the value of the last pbend event.
  191. long glLastSysexTime;
  192. void CreateChordFromKey(char cSharpsFlats, BYTE bMode, DWORD dwTime, DMUS_CHORD_PARAM& rChord);
  193. void InsertMidiMode( TListItem<StampedGMGSXG>* pPair )
  194. {
  195. TListItem<StampedGMGSXG>* pScan = gMidiModeList.GetHead();
  196. if( NULL == pScan )
  197. {
  198. gMidiModeList.AddHead(pPair);
  199. }
  200. else
  201. {
  202. if( pPair->GetItemValue().mtTime < pScan->GetItemValue().mtTime )
  203. {
  204. gMidiModeList.AddHead(pPair);
  205. }
  206. else
  207. {
  208. pScan = pScan->GetNext();
  209. while( pScan )
  210. {
  211. if( pPair->GetItemValue().mtTime < pScan->GetItemValue().mtTime )
  212. {
  213. gMidiModeList.InsertBefore( pScan, pPair );
  214. break;
  215. }
  216. pScan = pScan->GetNext();
  217. }
  218. if( NULL == pScan )
  219. {
  220. gMidiModeList.AddTail(pPair);
  221. }
  222. }
  223. }
  224. }
  225. HRESULT LoadCollection(IDirectMusicCollection** ppIDMCollection,
  226. IDirectMusicLoader* pIDMLoader)
  227. {
  228. // Any changes made to this function should also be made to CDirectMusicBand::LoadCollection
  229. // in dmband.dll
  230. assert(ppIDMCollection);
  231. assert(pIDMLoader);
  232. DMUS_OBJECTDESC desc;
  233. memset(&desc, 0, sizeof(desc));
  234. desc.dwSize = sizeof(desc);
  235. desc.guidClass = CLSID_DirectMusicCollection;
  236. desc.guidObject = GUID_DefaultGMCollection;
  237. desc.dwValidData |= (DMUS_OBJ_CLASS | DMUS_OBJ_OBJECT);
  238. HRESULT hr = pIDMLoader->GetObject(&desc,IID_IDirectMusicCollection, (void**)ppIDMCollection);
  239. return hr;
  240. }
  241. // seeks to a 32-bit position in a stream.
  242. HRESULT __inline StreamSeek( LPSTREAM pStream, long lSeekTo, DWORD dwOrigin )
  243. {
  244. LARGE_INTEGER li;
  245. if( lSeekTo < 0 )
  246. {
  247. li.HighPart = -1;
  248. }
  249. else
  250. {
  251. li.HighPart = 0;
  252. }
  253. li.LowPart = lSeekTo;
  254. return pStream->Seek( li, dwOrigin, NULL );
  255. }
  256. // this function gets a long that is formatted the correct way
  257. // i.e. the motorola way as opposed to the intel way
  258. BOOL __inline GetMLong( LPSTREAM pStream, DWORD& dw )
  259. {
  260. union uLong
  261. {
  262. unsigned char buf[4];
  263. DWORD dw;
  264. } u;
  265. unsigned char ch;
  266. if( S_OK != pStream->Read( u.buf, 4, NULL ) )
  267. {
  268. return FALSE;
  269. }
  270. #ifndef _MAC
  271. // swap bytes
  272. ch = u.buf[0];
  273. u.buf[0] = u.buf[3];
  274. u.buf[3] = ch;
  275. ch = u.buf[1];
  276. u.buf[1] = u.buf[2];
  277. u.buf[2] = ch;
  278. #endif
  279. dw = u.dw;
  280. return TRUE;
  281. }
  282. // this function gets a short that is formatted the correct way
  283. // i.e. the motorola way as opposed to the intel way
  284. BOOL __inline GetMShort( LPSTREAM pStream, short& n )
  285. {
  286. union uShort
  287. {
  288. unsigned char buf[2];
  289. short n;
  290. } u;
  291. unsigned char ch;
  292. if( S_OK != pStream->Read( u.buf, 2, NULL ) )
  293. {
  294. return FALSE;
  295. }
  296. #ifndef _MAC
  297. // swap bytes
  298. ch = u.buf[0];
  299. u.buf[0] = u.buf[1];
  300. u.buf[1] = ch;
  301. #endif
  302. n = u.n;
  303. return TRUE;
  304. }
  305. static short snPPQN;
  306. static IStream* gpTempoStream = NULL;
  307. static IStream* gpSysExStream = NULL;
  308. static IStream* gpTimeSigStream = NULL;
  309. static DWORD gdwSizeTimeSigStream = 0;
  310. static DWORD gdwSizeSysExStream = 0;
  311. static DWORD gdwSizeTempoStream = 0;
  312. static DMUS_IO_TIMESIGNATURE_ITEM gTimeSig; // holds the latest time sig
  313. long glTimeSig = 1; // flag to see if we should be paying attention to time sigs.
  314. // this is needed because we only care about the time sigs on the first track to
  315. // contain them that we read
  316. static IDirectMusicTrack* g_pChordTrack = NULL;
  317. static DMUS_CHORD_PARAM g_Chord; // Holds the latest chord
  318. static DMUS_CHORD_PARAM g_DefaultChord; // in case no chords are extracted from the track
  319. static WORD GetVarLength( LPSTREAM pStream, DWORD& rfdwValue )
  320. {
  321. BYTE b;
  322. WORD wBytes;
  323. if( S_OK != pStream->Read( &b, 1, NULL ) )
  324. {
  325. rfdwValue = 0;
  326. return 0;
  327. }
  328. wBytes = 1;
  329. rfdwValue = b & 0x7f;
  330. while( ( b & 0x80 ) != 0 )
  331. {
  332. if( S_OK != pStream->Read( &b, 1, NULL ) )
  333. {
  334. break;
  335. }
  336. ++wBytes;
  337. rfdwValue = ( rfdwValue << 7 ) + ( b & 0x7f );
  338. }
  339. return wBytes;
  340. }
  341. #ifdef _MAC
  342. static DWORD ConvertTime( DWORD dwTime )
  343. {
  344. wide d;
  345. long l; // storage for the remainder
  346. if( snPPQN == DMUS_PPQ ) {
  347. return dwTime;
  348. }
  349. WideMultiply( dwTime, DMUS_PPQ, &d );
  350. return WideDivide( &d, snPPQN, &l );
  351. }
  352. #else
  353. static DWORD ConvertTime( DWORD dwTime )
  354. {
  355. __int64 d;
  356. if( snPPQN == DMUS_PPQ )
  357. {
  358. return dwTime;
  359. }
  360. d = dwTime;
  361. d *= DMUS_PPQ;
  362. d /= snPPQN;
  363. return (DWORD)d;
  364. }
  365. #endif
  366. static FullSeqEvent* ScanForDuplicatePBends( FullSeqEvent* lstEvent )
  367. {
  368. FullSeqEvent* pEvent;
  369. FullSeqEvent* pNextEvent;
  370. MUSIC_TIME mtCurrentTime = 0x7FFFFFFF; // We are scanning backwards in time, so start way in the future.
  371. WORD wDupeBits = 0; // Keep a bit array of all channels that have active PBends at mtCurrentTime.
  372. if( NULL == lstEvent ) return NULL;
  373. // Scan through the list of events. This list is in backwards order, with the first item read at the end
  374. // of the list. This makes it very easy to scan through and remove pitch bends that occur at the same time, since
  375. // we can remove the latter events (which occured earlier in the midi file.)
  376. for( pEvent = lstEvent ; pEvent ; pEvent = pNextEvent )
  377. {
  378. pNextEvent = pEvent->pNext;
  379. if( pNextEvent )
  380. {
  381. // If the time is not the same as the last, reset.
  382. if (pNextEvent->mtTime != mtCurrentTime)
  383. {
  384. // Reset the time.
  385. mtCurrentTime = pNextEvent->mtTime;
  386. // No duplicate pbends at this time.
  387. wDupeBits = 0;
  388. }
  389. if ((pNextEvent->bStatus & 0xf0) == MIDI_PBEND)
  390. {
  391. DWORD dwChannel = pNextEvent->dwPChannel;
  392. if (wDupeBits & (1 << dwChannel))
  393. {
  394. // There was a previous (therefore later in the file) pbend at this time. Delete this one.
  395. pEvent->pNext = pNextEvent->pNext;
  396. delete pNextEvent;
  397. pNextEvent = pEvent;
  398. }
  399. else
  400. {
  401. // This is the last instance of a pbend on this channel at this time, so hang on to it.
  402. wDupeBits |= (1 << dwChannel);
  403. }
  404. }
  405. }
  406. }
  407. return lstEvent;
  408. }
  409. static FullSeqEvent* CompressEventList( FullSeqEvent* lstEvent )
  410. {
  411. static FullSeqEvent* paNoteOnEvent[16][128];
  412. FullSeqEvent* pEvent;
  413. FullSeqEvent* pPrevEvent;
  414. FullSeqEvent* pNextEvent;
  415. FullSeqEvent* pHoldEvent;
  416. FullSeqEvent tempEvent;
  417. int nChannel;
  418. if( NULL == lstEvent ) return NULL;
  419. memset( paNoteOnEvent, 0, sizeof( paNoteOnEvent ) );
  420. pPrevEvent = NULL;
  421. // add an event to the beginning of the list as a place holder
  422. memset( &tempEvent, 0, sizeof(FullSeqEvent) );
  423. tempEvent.mtTime = -1;
  424. tempEvent.pNext = lstEvent;
  425. lstEvent = &tempEvent;
  426. // make sure that any events with the same time are sorted in order
  427. // they were read
  428. for( pEvent = lstEvent ; pEvent != NULL ; pEvent = pNextEvent )
  429. {
  430. pNextEvent = pEvent->pNext;
  431. if( pNextEvent )
  432. {
  433. BOOL fSwap = TRUE;
  434. // bubble sort
  435. while( fSwap )
  436. {
  437. fSwap = FALSE;
  438. pPrevEvent = pEvent;
  439. pNextEvent = pEvent->pNext;
  440. while( pNextEvent->pNext && ( pNextEvent->mtTime == pNextEvent->pNext->mtTime ))
  441. {
  442. if( pNextEvent->pNext->pos < pNextEvent->pos )
  443. {
  444. fSwap = TRUE;
  445. pHoldEvent = pNextEvent->pNext;
  446. pPrevEvent->pNext = pHoldEvent;
  447. pNextEvent->pNext = pHoldEvent->pNext;
  448. pHoldEvent->pNext = pNextEvent;
  449. pPrevEvent = pHoldEvent;
  450. continue;
  451. }
  452. pPrevEvent = pNextEvent;
  453. pNextEvent = pNextEvent->pNext;
  454. }
  455. }
  456. }
  457. }
  458. // remove the first, temporary event, added above
  459. lstEvent = lstEvent->pNext;
  460. pPrevEvent = NULL;
  461. // combine note on and note offs
  462. for( pEvent = lstEvent ; pEvent != NULL ; pEvent = pNextEvent )
  463. {
  464. pEvent->pTempNext = NULL;
  465. pNextEvent = pEvent->pNext;
  466. //nChannel = pEvent->bStatus & 0xf;
  467. nChannel = pEvent->dwPChannel;
  468. if( ( pEvent->bStatus & 0xf0 ) == MIDI_NOTEON )
  469. {
  470. // add this event to the end of the list of events based
  471. // on the event's pitch. Keeping track of multiple events
  472. // of the same pitch allows us to have overlapping notes
  473. // of the same pitch, choosing that note on's and note off's
  474. // follow in the same order.
  475. if( NULL == paNoteOnEvent[nChannel][pEvent->bByte1] )
  476. {
  477. paNoteOnEvent[nChannel][pEvent->bByte1] = pEvent;
  478. }
  479. else
  480. {
  481. FullSeqEvent* pScan;
  482. for( pScan = paNoteOnEvent[nChannel][pEvent->bByte1];
  483. pScan->pTempNext != NULL; pScan = pScan->pTempNext );
  484. pScan->pTempNext = pEvent;
  485. }
  486. }
  487. else if( ( pEvent->bStatus & 0xf0 ) == MIDI_NOTEOFF )
  488. {
  489. if( paNoteOnEvent[nChannel][pEvent->bByte1] != NULL )
  490. {
  491. paNoteOnEvent[nChannel][pEvent->bByte1]->mtDuration =
  492. pEvent->mtTime - paNoteOnEvent[nChannel][pEvent->bByte1]->mtTime;
  493. paNoteOnEvent[nChannel][pEvent->bByte1] =
  494. paNoteOnEvent[nChannel][pEvent->bByte1]->pTempNext;
  495. }
  496. if( pPrevEvent == NULL )
  497. {
  498. lstEvent = pNextEvent;
  499. }
  500. else
  501. {
  502. pPrevEvent->pNext = pNextEvent;
  503. }
  504. delete pEvent;
  505. continue;
  506. }
  507. pPrevEvent = pEvent;
  508. }
  509. for( pEvent = lstEvent ; pEvent != NULL ; pEvent = pEvent->pNext )
  510. {
  511. pEvent->mtTime = pEvent->mtTime;
  512. if( ( pEvent->bStatus & 0xf0 ) == MIDI_NOTEON )
  513. {
  514. pEvent->mtDuration = pEvent->mtDuration;
  515. if( pEvent->mtDuration == 0 ) pEvent->mtDuration = 1;
  516. }
  517. }
  518. return lstEvent;
  519. }
  520. static int CompareEvents( FullSeqEvent* pEvent1, FullSeqEvent* pEvent2 )
  521. {
  522. BYTE bEventType1 = static_cast<BYTE>( pEvent1->bStatus >> 4 );
  523. BYTE bEventType2 = static_cast<BYTE>( pEvent2->bStatus >> 4 );
  524. if( pEvent1->mtTime < pEvent2->mtTime )
  525. {
  526. return -1;
  527. }
  528. else if( pEvent1->mtTime > pEvent2->mtTime )
  529. {
  530. return 1;
  531. }
  532. else if( bEventType1 != ET_SYSX && bEventType2 != ET_SYSX )
  533. {
  534. BYTE bStatus1;
  535. BYTE bStatus2;
  536. bStatus1 = (BYTE)( pEvent1->bStatus & 0xf0 );
  537. bStatus2 = (BYTE)( pEvent2->bStatus & 0xf0 );
  538. if( bStatus1 == bStatus2 )
  539. {
  540. return 0;
  541. }
  542. else if( bStatus1 == MIDI_NOTEON )
  543. {
  544. return -1;
  545. }
  546. else if( bStatus2 == MIDI_NOTEON )
  547. {
  548. return 1;
  549. }
  550. else if( bStatus1 > bStatus2 )
  551. {
  552. return 1;
  553. }
  554. else if( bStatus1 < bStatus2 )
  555. {
  556. return -1;
  557. }
  558. }
  559. return 0;
  560. }
  561. static FullSeqEvent* MergeEvents( FullSeqEvent* lstLeftEvent, FullSeqEvent* lstRightEvent )
  562. {
  563. FullSeqEvent anchorEvent;
  564. FullSeqEvent* pEvent;
  565. anchorEvent.pNext = NULL;
  566. pEvent = &anchorEvent;
  567. do
  568. {
  569. if( CompareEvents( lstLeftEvent, lstRightEvent ) < 0 )
  570. {
  571. pEvent->pNext = lstLeftEvent;
  572. pEvent = lstLeftEvent;
  573. lstLeftEvent = lstLeftEvent->pNext;
  574. if( lstLeftEvent == NULL )
  575. {
  576. pEvent->pNext = lstRightEvent;
  577. }
  578. }
  579. else
  580. {
  581. pEvent->pNext = lstRightEvent;
  582. pEvent = lstRightEvent;
  583. lstRightEvent = lstRightEvent->pNext;
  584. if( lstRightEvent == NULL )
  585. {
  586. pEvent->pNext = lstLeftEvent;
  587. lstLeftEvent = NULL;
  588. }
  589. }
  590. } while( lstLeftEvent != NULL );
  591. return anchorEvent.pNext;
  592. }
  593. static FullSeqEvent* SortEventList( FullSeqEvent* lstEvent )
  594. {
  595. FullSeqEvent* pMidEvent;
  596. FullSeqEvent* pRightEvent;
  597. if( lstEvent != NULL && lstEvent->pNext != NULL )
  598. {
  599. pMidEvent = lstEvent;
  600. pRightEvent = pMidEvent->pNext->pNext;
  601. if( pRightEvent != NULL )
  602. {
  603. pRightEvent = pRightEvent->pNext;
  604. }
  605. while( pRightEvent != NULL )
  606. {
  607. pMidEvent = pMidEvent->pNext;
  608. pRightEvent = pRightEvent->pNext;
  609. if( pRightEvent != NULL )
  610. {
  611. pRightEvent = pRightEvent->pNext;
  612. }
  613. }
  614. pRightEvent = pMidEvent->pNext;
  615. pMidEvent->pNext = NULL;
  616. return MergeEvents( SortEventList( lstEvent ),
  617. SortEventList( pRightEvent ) );
  618. }
  619. return lstEvent;
  620. }
  621. static DWORD ReadEvent( LPSTREAM pStream, DWORD dwTime, FullSeqEvent** plstEvent, DMUS_IO_PATCH_ITEM** pplstPatchEvent )
  622. {
  623. static BYTE bRunningStatus;
  624. gPos++;
  625. dwTime = ConvertTime(dwTime);
  626. DWORD dwBytes;
  627. DWORD dwLen;
  628. FullSeqEvent* pEvent;
  629. DMUS_IO_PATCH_ITEM* pPatchEvent;
  630. DMUS_IO_SYSEX_ITEM* pSysEx;
  631. BYTE b;
  632. BYTE* pbSysExData = NULL;
  633. if( FAILED( pStream->Read( &b, 1, NULL ) ) )
  634. {
  635. return 0;
  636. }
  637. if( b < 0x80 )
  638. {
  639. StreamSeek( pStream, -1, STREAM_SEEK_CUR );
  640. b = bRunningStatus;
  641. dwBytes = 0;
  642. }
  643. else
  644. {
  645. dwBytes = 1;
  646. }
  647. if( b < 0xf0 )
  648. {
  649. bRunningStatus = (BYTE)b;
  650. switch( b & 0xf0 )
  651. {
  652. case MIDI_CCHANGE:
  653. case MIDI_PTOUCH:
  654. case MIDI_PBEND:
  655. case MIDI_NOTEOFF:
  656. case MIDI_NOTEON:
  657. if( FAILED( pStream->Read( &b, 1, NULL ) ) )
  658. {
  659. return dwBytes;
  660. }
  661. ++dwBytes;
  662. pEvent = new FullSeqEvent;
  663. if( pEvent == NULL )
  664. {
  665. return 0;
  666. }
  667. pEvent->mtTime = dwTime;
  668. pEvent->nOffset = 0;
  669. pEvent->pos = gPos;
  670. pEvent->mtDuration = 0;
  671. pEvent->bStatus = bRunningStatus & 0xf0;
  672. pEvent->dwPChannel = bRunningStatus & 0xf;
  673. pEvent->bByte1 = b;
  674. if( FAILED( pStream->Read( &b, 1, NULL ) ) )
  675. {
  676. delete pEvent;
  677. return dwBytes;
  678. }
  679. ++dwBytes;
  680. pEvent->bByte2 = b;
  681. if( ( pEvent->bStatus & 0xf0 ) == MIDI_NOTEON &&
  682. pEvent->bByte2 == 0 )
  683. {
  684. pEvent->bStatus = (BYTE)( MIDI_NOTEOFF );
  685. }
  686. /* If there are multiple controller events at the same time, seperate
  687. them by clock ticks.
  688. gdwLastControllerTime holds the time of the last CC event.
  689. gdwControlCollisionOffset holds the number of colliding CCs.
  690. */
  691. if ((pEvent->bStatus & 0xf0) == MIDI_CCHANGE)
  692. {
  693. DWORD dwChannel = pEvent->dwPChannel;
  694. if (dwTime == gdwLastControllerTime[dwChannel])
  695. {
  696. pEvent->mtTime += ++gdwControlCollisionOffset[dwChannel];
  697. }
  698. else
  699. {
  700. gdwControlCollisionOffset[dwChannel] = 0;
  701. gdwLastControllerTime[dwChannel] = dwTime;
  702. }
  703. }
  704. if(((pEvent->bStatus & 0xf0) == MIDI_CCHANGE) && (pEvent->bByte1 == 0 || pEvent->bByte1 == 0x20))
  705. {
  706. // We have a bank select or its LSB either of which are not added to event list
  707. if(pEvent->bByte1 == 0x20)
  708. {
  709. gBankSelect[pEvent->dwPChannel].byLSB = pEvent->bByte2;
  710. }
  711. else // pEvent->bByte1 == 0
  712. {
  713. gBankSelect[pEvent->dwPChannel].byMSB = pEvent->bByte2;
  714. }
  715. // We no longer need the event so we can free it
  716. delete pEvent;
  717. }
  718. else // Add to event list
  719. {
  720. pEvent->pNext = *plstEvent;
  721. *plstEvent = pEvent;
  722. }
  723. break;
  724. case MIDI_PCHANGE:
  725. if(FAILED(pStream->Read(&b, 1, NULL)))
  726. {
  727. return dwBytes;
  728. }
  729. ++dwBytes;
  730. pPatchEvent = new DMUS_IO_PATCH_ITEM;
  731. if(pPatchEvent == NULL)
  732. {
  733. return 0;
  734. }
  735. memset(pPatchEvent, 0, sizeof(DMUS_IO_PATCH_ITEM));
  736. pPatchEvent->lTime = dwTime - 1;
  737. pPatchEvent->byStatus = bRunningStatus;
  738. pPatchEvent->byPChange = b;
  739. pPatchEvent->byMSB = gBankSelect[bRunningStatus & 0xF].byMSB;
  740. pPatchEvent->byLSB = gBankSelect[bRunningStatus & 0xF].byLSB;
  741. pPatchEvent->dwFlags |= DMUS_IO_INST_PATCH;
  742. if((pPatchEvent->byMSB != 0xFF) && (pPatchEvent->byLSB != 0xFF))
  743. {
  744. pPatchEvent->dwFlags |= DMUS_IO_INST_BANKSELECT;
  745. }
  746. gPatchTable[bRunningStatus & 0xF] = 1;
  747. pPatchEvent->pNext = *pplstPatchEvent;
  748. pPatchEvent->pIDMCollection = NULL;
  749. *pplstPatchEvent = pPatchEvent;
  750. break;
  751. case MIDI_MTOUCH:
  752. if( FAILED( pStream->Read( &b, 1, NULL ) ) )
  753. {
  754. return dwBytes;
  755. }
  756. ++dwBytes;
  757. pEvent = new FullSeqEvent;
  758. if( pEvent == NULL )
  759. {
  760. return 0;
  761. }
  762. pEvent->mtTime = dwTime;
  763. pEvent->nOffset = 0;
  764. pEvent->pos = gPos;
  765. pEvent->mtDuration = 0;
  766. pEvent->bStatus = bRunningStatus & 0xf0;
  767. pEvent->dwPChannel = bRunningStatus & 0xf;
  768. pEvent->bByte1 = b;
  769. pEvent->pNext = *plstEvent;
  770. *plstEvent = pEvent;
  771. break;
  772. default:
  773. // this should NOT be possible - unknown midi note event type
  774. ASSERT(FALSE);
  775. break;
  776. }
  777. }
  778. else
  779. {
  780. switch( b )
  781. {
  782. case 0xf0:
  783. dwBytes += GetVarLength( pStream, dwLen );
  784. pSysEx = new DMUS_IO_SYSEX_ITEM;
  785. if( pSysEx != NULL )
  786. {
  787. pbSysExData = new BYTE[dwLen + 1];
  788. if( pbSysExData != NULL )
  789. {
  790. MUSIC_TIME mt = dwTime;
  791. if (mt == 0)
  792. {
  793. mt = glLastSysexTime++;
  794. if (mt > 0) mt = 0;
  795. }
  796. pbSysExData[0] = 0xf0;
  797. if( FAILED( pStream->Read( pbSysExData + 1, dwLen, NULL ) ) )
  798. {
  799. delete [] pbSysExData;
  800. delete pSysEx;
  801. return dwBytes;
  802. }
  803. if( pbSysExData[1] == 0x43 )
  804. {
  805. // check for XG files
  806. BYTE abXG[] = { 0xF0, 0x43, 0x10, 0x4C, 0x00, 0x00, 0x7E, 0x00, 0xF7 };
  807. int i;
  808. for( i = 0; i < 8; i++ )
  809. {
  810. if( i == 2 )
  811. {
  812. if( ( pbSysExData[i] & 0xF0 ) != abXG[i] )
  813. break;
  814. }
  815. else
  816. {
  817. if( pbSysExData[i] != abXG[i] )
  818. break;
  819. }
  820. }
  821. if( i == 8 ) // we have an XG!
  822. {
  823. TListItem<StampedGMGSXG>* pPair = new TListItem<StampedGMGSXG>;
  824. if (!pPair) return dwBytes;
  825. pPair->GetItemValue().mtTime = mt;
  826. pPair->GetItemValue().dwMidiMode = DMUS_MIDIMODEF_XG;
  827. InsertMidiMode(pPair);
  828. }
  829. }
  830. else if( pbSysExData[1] == 0x41 )
  831. {
  832. // check for GS files
  833. BYTE abGS[] = { 0xF0,0x41,0x00,0x42,0x12,0x40,0x00,0x7F,0x00,0x41,0xF7 };
  834. int i;
  835. for( i = 0; i < 10; i++ )
  836. {
  837. if( i != 2 )
  838. {
  839. if( pbSysExData[i] != abGS[i] )
  840. break;
  841. }
  842. }
  843. if( i == 10 ) // we have a GS!
  844. {
  845. TListItem<StampedGMGSXG>* pPair = new TListItem<StampedGMGSXG>;
  846. if (!pPair) return dwBytes;
  847. pPair->GetItemValue().mtTime = mt;
  848. pPair->GetItemValue().dwMidiMode = DMUS_MIDIMODEF_GS;
  849. InsertMidiMode(pPair);
  850. }
  851. }
  852. else if (( pbSysExData[1] == 0x7E ) && (pbSysExData[3] == 0x09))
  853. {
  854. TListItem<StampedGMGSXG>* pPair = new TListItem<StampedGMGSXG>;
  855. if (!pPair) return dwBytes;
  856. pPair->GetItemValue().mtTime = mt;
  857. pPair->GetItemValue().dwMidiMode = DMUS_MIDIMODEF_GM;
  858. InsertMidiMode(pPair);
  859. }
  860. pSysEx->mtTime = mt;
  861. pSysEx->dwPChannel = 0;
  862. DWORD dwTempLen = dwLen + 1;
  863. pSysEx->dwSysExLength = dwTempLen;
  864. if( NULL == gpSysExStream )
  865. {
  866. // create a stream to hold sysex events
  867. CreateStreamOnHGlobal( NULL, TRUE, &gpSysExStream );
  868. if( gpSysExStream )
  869. {
  870. DWORD dwTemp;
  871. // write the chunk header
  872. dwTemp = DMUS_FOURCC_SYSEX_TRACK;
  873. gpSysExStream->Write( &dwTemp, sizeof(DWORD), NULL );
  874. // write the overall size. (Replace this later with the
  875. // true overall size.)
  876. dwTemp = sizeof(DMUS_IO_TIMESIGNATURE_ITEM);
  877. // overall size (to be replaced later)
  878. gpSysExStream->Write( &dwTemp, sizeof(DWORD), NULL );
  879. }
  880. }
  881. if( gpSysExStream )
  882. {
  883. gpSysExStream->Write( &pSysEx->mtTime, sizeof(MUSIC_TIME), NULL );
  884. gpSysExStream->Write( &pSysEx->dwPChannel, sizeof(DWORD), NULL );
  885. gpSysExStream->Write( &pSysEx->dwSysExLength, sizeof(DWORD), NULL );
  886. gpSysExStream->Write( pbSysExData, dwTempLen, NULL );
  887. gdwSizeSysExStream += (sizeof(long) + sizeof(DWORD) + dwTempLen);
  888. }
  889. delete [] pbSysExData;
  890. delete pSysEx;
  891. }
  892. else
  893. {
  894. StreamSeek( pStream, dwLen, STREAM_SEEK_CUR );
  895. }
  896. }
  897. else
  898. {
  899. StreamSeek( pStream, dwLen, STREAM_SEEK_CUR );
  900. }
  901. dwBytes += dwLen;
  902. break;
  903. case 0xf7:
  904. // ignore sysex f7 chunks
  905. dwBytes += GetVarLength( pStream, dwLen );
  906. StreamSeek( pStream, dwLen, STREAM_SEEK_CUR );
  907. dwBytes += dwLen;
  908. break;
  909. case 0xff:
  910. if( FAILED( pStream->Read( &b, 1, NULL ) ) )
  911. {
  912. return dwBytes;
  913. }
  914. ++dwBytes;
  915. dwBytes += GetVarLength( pStream, dwLen );
  916. if( b == 0x51 ) // tempo change
  917. {
  918. DWORD dw = 0;
  919. DMUS_IO_TEMPO_ITEM tempo;
  920. while( dwLen > 0 )
  921. {
  922. if( FAILED( pStream->Read( &b, 1, NULL ) ) )
  923. {
  924. return dwBytes;
  925. }
  926. ++dwBytes;
  927. --dwLen;
  928. dw <<= 8;
  929. dw += b;
  930. }
  931. if (dw < 1) dw = 1;
  932. tempo.dblTempo = 60000000.0 / ((double)dw);
  933. tempo.lTime = dwTime;
  934. if( NULL == gpTempoStream )
  935. {
  936. // create a stream to hold tempo events
  937. CreateStreamOnHGlobal( NULL, TRUE, &gpTempoStream );
  938. if( gpTempoStream )
  939. {
  940. DWORD dwTemp;
  941. // write the chunk header
  942. dwTemp = DMUS_FOURCC_TEMPO_TRACK;
  943. gpTempoStream->Write( &dwTemp, sizeof(DWORD), NULL );
  944. // write the overall size. (Replace this later with the
  945. // true overall size.) Also write the size of the individual
  946. // structure.
  947. dwTemp = sizeof(DMUS_IO_TEMPO_ITEM);
  948. // overall size (to be replaced later)
  949. gpTempoStream->Write( &dwTemp, sizeof(DWORD), NULL );
  950. // individual structure.
  951. gpTempoStream->Write( &dwTemp, sizeof(DWORD), NULL );
  952. }
  953. }
  954. if( gpTempoStream )
  955. {
  956. gpTempoStream->Write( &tempo, sizeof(DMUS_IO_TEMPO_ITEM), NULL );
  957. gdwSizeTempoStream += sizeof(DMUS_IO_TEMPO_ITEM);
  958. }
  959. }
  960. else if( b == 0x58 && glTimeSig )
  961. {
  962. // glTimeSig will be set to 0 inside the main calling function
  963. // once we no longer care about time sigs.
  964. DMUS_IO_TIMESIGNATURE_ITEM timesig;
  965. if( FAILED( pStream->Read( &b, 1, NULL ) ) )
  966. {
  967. return dwBytes;
  968. }
  969. // set glTimeSig to 2 to signal to the main function that we've
  970. // read a time sig on this track
  971. glTimeSig = 2;
  972. gTimeSig.lTime = timesig.lTime = dwTime;
  973. gTimeSig.bBeatsPerMeasure = timesig.bBeatsPerMeasure = b;
  974. ++dwBytes;
  975. if( FAILED( pStream->Read( &b, 1, NULL ) ) )
  976. {
  977. return dwBytes;
  978. }
  979. gTimeSig.bBeat = timesig.bBeat = (BYTE)( 1 << b ); // 0 means 256th note
  980. gTimeSig.wGridsPerBeat = timesig.wGridsPerBeat = 4; // this is irrelavent for MIDI files
  981. if( NULL == gpTimeSigStream )
  982. {
  983. CreateStreamOnHGlobal( NULL, TRUE, &gpTimeSigStream );
  984. if( gpTimeSigStream )
  985. {
  986. DWORD dwTemp;
  987. // write the chunk header
  988. dwTemp = DMUS_FOURCC_TIMESIGNATURE_TRACK;
  989. gpTimeSigStream->Write( &dwTemp, sizeof(DWORD), NULL );
  990. // write the overall size. (Replace this later with the
  991. // true overall size.) Also write the size of the individual
  992. // structure.
  993. dwTemp = sizeof(DMUS_IO_TIMESIGNATURE_ITEM);
  994. // overall size (to be replaced later)
  995. gpTimeSigStream->Write( &dwTemp, sizeof(DWORD), NULL );
  996. // individual structure.
  997. gpTimeSigStream->Write( &dwTemp, sizeof(DWORD), NULL );
  998. gdwSizeTimeSigStream += sizeof(DWORD);
  999. }
  1000. }
  1001. if( gpTimeSigStream )
  1002. {
  1003. gpTimeSigStream->Write( &timesig, sizeof(DMUS_IO_TIMESIGNATURE_ITEM), NULL );
  1004. gdwSizeTimeSigStream += sizeof(DMUS_IO_TIMESIGNATURE_ITEM);
  1005. }
  1006. ++dwBytes;
  1007. StreamSeek( pStream, dwLen - 2, STREAM_SEEK_CUR );
  1008. dwBytes += ( dwLen - 2 );
  1009. }
  1010. else if( b == 0x59 )
  1011. {
  1012. // Read sharps/flats and major/minor bytes
  1013. if( FAILED( pStream->Read( &b, 1, NULL ) ) )
  1014. {
  1015. return dwBytes;
  1016. }
  1017. char cSharpsFlats = b;
  1018. ++dwBytes;
  1019. if( FAILED( pStream->Read( &b, 1, NULL ) ) )
  1020. {
  1021. return dwBytes;
  1022. }
  1023. BYTE bMode = b;
  1024. ++dwBytes;
  1025. // Create a chord (with one subchord) from the key info
  1026. CreateChordFromKey(cSharpsFlats, bMode, dwTime, g_Chord);
  1027. // If the chord track is empty, create it.
  1028. if (!g_pChordTrack)
  1029. {
  1030. HRESULT hr = CoCreateInstance(
  1031. CLSID_DirectMusicChordTrack, NULL, CLSCTX_INPROC,
  1032. IID_IDirectMusicTrack,
  1033. (void**)&g_pChordTrack );
  1034. if (!SUCCEEDED(hr)) return dwBytes;
  1035. // If dwTime > 0, use SetParam to insert the default chord at time 0
  1036. if (dwTime > 0)
  1037. {
  1038. g_pChordTrack->SetParam(GUID_ChordParam, 0, &g_DefaultChord);
  1039. }
  1040. }
  1041. // Use SetParam to insert the new chord into the chord track
  1042. g_pChordTrack->SetParam(GUID_ChordParam, dwTime, &g_Chord);
  1043. }
  1044. else
  1045. {
  1046. StreamSeek( pStream, dwLen, STREAM_SEEK_CUR );
  1047. dwBytes += dwLen;
  1048. }
  1049. break;
  1050. default:
  1051. break;
  1052. }
  1053. }
  1054. return dwBytes;
  1055. }
  1056. static void AddOffsets(FullSeqEvent* lstEvent, IDirectMusicTrack* pTimeSigTrack)
  1057. {
  1058. HRESULT hr;
  1059. MUSIC_TIME mtNext = 0;
  1060. DMUS_IO_TIMESIGNATURE_ITEM timesig;
  1061. timesig.bBeat = gTimeSig.bBeat ? gTimeSig.bBeat : 4;
  1062. timesig.bBeatsPerMeasure = gTimeSig.bBeatsPerMeasure ? gTimeSig.bBeatsPerMeasure : 4;
  1063. timesig.wGridsPerBeat = gTimeSig.wGridsPerBeat ? gTimeSig.wGridsPerBeat : 4;
  1064. timesig.lTime = 0;
  1065. short nClocksPerGrid = ((DMUS_PPQ * 4) / timesig.bBeat) / timesig.wGridsPerBeat;
  1066. if (pTimeSigTrack)
  1067. {
  1068. hr = pTimeSigTrack->GetParam(GUID_TimeSignature, 0, &mtNext, (void*)&timesig);
  1069. if (FAILED(hr))
  1070. {
  1071. mtNext = 0;
  1072. }
  1073. else
  1074. {
  1075. nClocksPerGrid = ((DMUS_PPQ * 4) / timesig.bBeat) / timesig.wGridsPerBeat;
  1076. }
  1077. }
  1078. for( FullSeqEvent* pEvent = lstEvent; pEvent; pEvent = pEvent->pNext )
  1079. {
  1080. if ( ( pEvent->bStatus & 0xf0 ) == MIDI_NOTEON )
  1081. {
  1082. if (mtNext && pTimeSigTrack && mtNext < pEvent->mtTime)
  1083. {
  1084. hr = pTimeSigTrack->GetParam(GUID_TimeSignature, mtNext, &mtNext, (void*)&timesig);
  1085. if (FAILED(hr))
  1086. {
  1087. mtNext = 0;
  1088. }
  1089. else
  1090. {
  1091. nClocksPerGrid = ((DMUS_PPQ * 4) / timesig.bBeat) / timesig.wGridsPerBeat;
  1092. }
  1093. }
  1094. ASSERT(nClocksPerGrid);
  1095. if( 0 == nClocksPerGrid ) nClocksPerGrid = 1; // this should never happen, but just in case.
  1096. pEvent->nOffset = (short) ((pEvent->mtTime - timesig.lTime) % nClocksPerGrid);
  1097. pEvent->mtTime -= pEvent->nOffset;
  1098. if (pEvent->nOffset > (nClocksPerGrid / 2))
  1099. {
  1100. // make it a negative offset and bump the time a corresponding amount
  1101. pEvent->nOffset -= nClocksPerGrid;
  1102. pEvent->mtTime += nClocksPerGrid;
  1103. }
  1104. }
  1105. }
  1106. }
  1107. /*
  1108. @method HRESULT | IDirectMusicPerformance | CreateSegmentFromMIDIStream |
  1109. Given a MIDI stream, creates a Segment that can be played via
  1110. <im IDirectMusicPerformance.PlaySegment>.
  1111. @parm LPSTREAM | pStream |
  1112. [in] The MIDI stream. It should be set to the correct seek to begin reading.
  1113. @parm IDirectMusicSegment* | pSegment |
  1114. [out] A pointer to contain the created Segment.
  1115. @rvalue DMUS_E_CANNOTREAD | There was an error attempting to read the MIDI file.
  1116. @rvalue S_OK
  1117. */
  1118. HRESULT CreateSegmentFromMIDIStream(LPSTREAM pStream,
  1119. IDirectMusicSegment* pSegment)
  1120. {
  1121. if(pSegment == NULL || pStream == NULL)
  1122. {
  1123. return E_POINTER;
  1124. }
  1125. HRESULT hr = DMUS_E_CANNOTREAD;
  1126. DWORD dwID;
  1127. DWORD dwCurTime;
  1128. DWORD dwLength;
  1129. DWORD dwSize;
  1130. short nFormat;
  1131. short nNumTracks;
  1132. short nTracksRead;
  1133. FullSeqEvent* lstEvent;
  1134. DMUS_IO_PATCH_ITEM* lstPatchEvent;
  1135. FullSeqEvent* lstTrackEvent;
  1136. HRESULT hrGM = S_OK;
  1137. EnterCriticalSection(&g_CritSec);
  1138. gpTempoStream = NULL;
  1139. gpSysExStream = NULL;
  1140. gpTimeSigStream = NULL;
  1141. gdwSizeTimeSigStream = 0;
  1142. gdwSizeSysExStream = 0;
  1143. gdwSizeTempoStream = 0;
  1144. glTimeSig = 1; // flag to see if we should be paying attention to time sigs.
  1145. // this is needed because we only care about the time sigs on the first track to
  1146. // contain them that we read
  1147. g_pChordTrack = NULL;
  1148. lstEvent = NULL;
  1149. lstPatchEvent = NULL;
  1150. nNumTracks = nTracksRead = 0;
  1151. dwLength = 0;
  1152. gPos = 0;
  1153. gMidiModeList.CleanUp();
  1154. if (g_pChordTrack)
  1155. {
  1156. g_pChordTrack->Release();
  1157. g_pChordTrack = NULL;
  1158. }
  1159. CreateChordFromKey(0, 0, 0, g_Chord);
  1160. CreateChordFromKey(0, 0, 0, g_DefaultChord);
  1161. memset(&gBankSelect, 0xFF, (sizeof(DMUS_IO_BANKSELECT_ITEM) * NUM_MIDI_CHANNELS));
  1162. memset(&gPatchTable, 0, (sizeof(DWORD) * NUM_MIDI_CHANNELS));
  1163. memset(&gTimeSig, 0, sizeof(DMUS_IO_TIMESIGNATURE_ITEM));
  1164. memset(&gdwLastControllerTime, 0xFF, (sizeof(DWORD) * NUM_MIDI_CHANNELS));
  1165. memset(&gdwControlCollisionOffset, 0, (sizeof(DWORD) * NUM_MIDI_CHANNELS));
  1166. glLastSysexTime = -5;
  1167. if( ( S_OK != pStream->Read( &dwID, sizeof( FOURCC ), NULL ) ) ||
  1168. !GetMLong( pStream, dwSize ) )
  1169. {
  1170. Trace(1,"Error: Failure parsing MIDI file.\n");
  1171. LeaveCriticalSection(&g_CritSec);
  1172. return DMUS_E_CANNOTREAD;
  1173. }
  1174. // check for RIFF MIDI files
  1175. if( dwID == mmioFOURCC( 'R', 'I', 'F', 'F' ) )
  1176. {
  1177. StreamSeek( pStream, 12, STREAM_SEEK_CUR );
  1178. if( ( S_OK != pStream->Read( &dwID, sizeof( FOURCC ), NULL ) ) ||
  1179. !GetMLong( pStream, dwSize ) )
  1180. {
  1181. Trace(1,"Error: Failure parsing MIDI file.\n");
  1182. LeaveCriticalSection(&g_CritSec);
  1183. return DMUS_E_CANNOTREAD;
  1184. }
  1185. }
  1186. // check for normal MIDI files
  1187. if( dwID != mmioFOURCC( 'M', 'T', 'h', 'd' ) )
  1188. {
  1189. LeaveCriticalSection(&g_CritSec);
  1190. Trace(1,"Error: Failure parsing MIDI file - can't find a valid header.\n");
  1191. return DMUS_E_CANNOTREAD;
  1192. }
  1193. GetMShort( pStream, nFormat );
  1194. GetMShort( pStream, nNumTracks );
  1195. GetMShort( pStream, snPPQN );
  1196. if( dwSize > 6 )
  1197. {
  1198. StreamSeek( pStream, dwSize - 6, STREAM_SEEK_CUR );
  1199. }
  1200. pStream->Read( &dwID, sizeof( FOURCC ), NULL );
  1201. while( dwID == mmioFOURCC( 'M', 'T', 'r', 'k' ) )
  1202. {
  1203. GetMLong( pStream, dwSize );
  1204. dwCurTime = 0;
  1205. lstTrackEvent = NULL;
  1206. long lSize = (long)dwSize;
  1207. while( lSize > 0 )
  1208. {
  1209. long lReturn;
  1210. lSize -= GetVarLength( pStream, dwID );
  1211. dwCurTime += dwID;
  1212. if (lSize > 0)
  1213. {
  1214. lReturn = ReadEvent( pStream, dwCurTime, &lstTrackEvent, &lstPatchEvent );
  1215. if( lReturn )
  1216. {
  1217. lSize -= lReturn;
  1218. }
  1219. else
  1220. {
  1221. Trace(1,"Error: Failure parsing MIDI file.\n");
  1222. hr = DMUS_E_CANNOTREAD;
  1223. goto END;
  1224. }
  1225. }
  1226. }
  1227. dwSize = lSize;
  1228. if( glTimeSig > 1 )
  1229. {
  1230. // if glTimeSig is greater than 1, it means we've read some time sigs
  1231. // from this track (it was set to 2 inside ReadEvent.) This means that
  1232. // we no longer want ReadEvent to pay any attention to time sigs, so
  1233. // we set this to 0.
  1234. glTimeSig = 0;
  1235. }
  1236. if( dwCurTime > dwLength )
  1237. {
  1238. dwLength = dwCurTime;
  1239. }
  1240. lstTrackEvent = ScanForDuplicatePBends( lstTrackEvent );
  1241. lstTrackEvent = SortEventList( lstTrackEvent );
  1242. lstTrackEvent = CompressEventList( lstTrackEvent );
  1243. lstEvent = List_Cat( lstEvent, lstTrackEvent );
  1244. if( FAILED( pStream->Read( &dwID, sizeof( FOURCC ), NULL ) ) )
  1245. {
  1246. break;
  1247. }
  1248. }
  1249. dwLength = ConvertTime(dwLength);
  1250. lstEvent = SortEventList( lstEvent );
  1251. // if( lstEvent ) Removed: this might be just a band, or sysex data, or whatever.
  1252. {
  1253. if(pSegment)
  1254. {
  1255. IPersistStream* pIPSTrack;
  1256. IDirectMusicTrack* pDMTrack;
  1257. hr = S_OK;
  1258. if (!g_pChordTrack)
  1259. {
  1260. hr = CoCreateInstance(
  1261. CLSID_DirectMusicChordTrack, NULL, CLSCTX_INPROC,
  1262. IID_IDirectMusicTrack,
  1263. (void**)&g_pChordTrack );
  1264. if (SUCCEEDED(hr))
  1265. {
  1266. g_pChordTrack->SetParam(GUID_ChordParam, 0, &g_DefaultChord);
  1267. }
  1268. }
  1269. if (SUCCEEDED(hr))
  1270. {
  1271. pSegment->InsertTrack( g_pChordTrack, 1 );
  1272. g_pChordTrack->Release();
  1273. g_pChordTrack = NULL;
  1274. }
  1275. // Note: We could be checking to see if there are actually tempo events,
  1276. // sysex events, etc. to see if it's really necessary to create these
  1277. // tracks...
  1278. // Create a Tempo Track in which to store the tempo events
  1279. if( gpTempoStream )
  1280. {
  1281. if( SUCCEEDED( CoCreateInstance( CLSID_DirectMusicTempoTrack,
  1282. NULL, CLSCTX_INPROC, IID_IPersistStream,
  1283. (void**)&pIPSTrack )))
  1284. {
  1285. StreamSeek( gpTempoStream, sizeof(DWORD), STREAM_SEEK_SET );
  1286. gpTempoStream->Write( &gdwSizeTempoStream, sizeof(DWORD), NULL );
  1287. StreamSeek( gpTempoStream, 0, STREAM_SEEK_SET );
  1288. pIPSTrack->Load( gpTempoStream );
  1289. if( SUCCEEDED( pIPSTrack->QueryInterface( IID_IDirectMusicTrack,
  1290. (void**)&pDMTrack ) ) )
  1291. {
  1292. pSegment->InsertTrack( pDMTrack, 1 );
  1293. pDMTrack->Release();
  1294. }
  1295. pIPSTrack->Release();
  1296. }
  1297. }
  1298. // Add a patch event for each MIDI channel that does not have one
  1299. DMUS_IO_PATCH_ITEM* pPatchEvent = NULL;
  1300. for(DWORD i = 0; i < 16; i++)
  1301. {
  1302. if(gPatchTable[i] == 0)
  1303. {
  1304. pPatchEvent = new DMUS_IO_PATCH_ITEM;
  1305. if(pPatchEvent == NULL)
  1306. {
  1307. continue;
  1308. }
  1309. memset(pPatchEvent, 0, sizeof(DMUS_IO_PATCH_ITEM));
  1310. pPatchEvent->lTime = ConvertTime(0);
  1311. pPatchEvent->byStatus = 0xC0 + (BYTE)(i & 0xf);
  1312. pPatchEvent->dwFlags |= (DMUS_IO_INST_PATCH);
  1313. pPatchEvent->pIDMCollection = NULL;
  1314. pPatchEvent->fNotInFile = TRUE;
  1315. pPatchEvent->pNext = lstPatchEvent;
  1316. lstPatchEvent = pPatchEvent;
  1317. }
  1318. }
  1319. if(lstPatchEvent)
  1320. {
  1321. // Create Band Track in which to store patch change events
  1322. IDirectMusicBandTrk* pBandTrack;
  1323. if(SUCCEEDED(CoCreateInstance(CLSID_DirectMusicBandTrack,
  1324. NULL,
  1325. CLSCTX_INPROC,
  1326. IID_IDirectMusicBandTrk,
  1327. (void**)&pBandTrack)))
  1328. {
  1329. // Get the loader from stream so we can open a required collections
  1330. IDirectMusicGetLoader* pIDMGetLoader = NULL;
  1331. IDirectMusicLoader* pIDMLoader = NULL;
  1332. hr = pStream->QueryInterface(IID_IDirectMusicGetLoader, (void**)&pIDMGetLoader);
  1333. if( SUCCEEDED(hr) )
  1334. {
  1335. hr = pIDMGetLoader->GetLoader(&pIDMLoader);
  1336. pIDMGetLoader->Release();
  1337. }
  1338. // IStream needs a loader attached
  1339. assert(SUCCEEDED(hr));
  1340. // Populate the the Band Track with patch change events
  1341. for(DMUS_IO_PATCH_ITEM* pEvent = lstPatchEvent; pEvent; pEvent = lstPatchEvent)
  1342. {
  1343. // Remove instrument from head of list and give to band
  1344. DMUS_IO_PATCH_ITEM* temp = pEvent->pNext;
  1345. pEvent->pNext = NULL;
  1346. lstPatchEvent = temp;
  1347. // We will try to load the collection but if we can not we will continure
  1348. // and use the default GM on the card
  1349. if(pIDMLoader)
  1350. {
  1351. HRESULT hrTemp = LoadCollection(&pEvent->pIDMCollection, pIDMLoader);
  1352. if (FAILED(hrTemp))
  1353. {
  1354. hrGM = hrTemp;
  1355. }
  1356. }
  1357. hr = pBandTrack->AddBand(pEvent);
  1358. // Release reference to collection
  1359. if(pEvent->pIDMCollection)
  1360. {
  1361. (pEvent->pIDMCollection)->Release();
  1362. pEvent->pIDMCollection = NULL;
  1363. }
  1364. delete pEvent;
  1365. if(FAILED(hr))
  1366. {
  1367. break;
  1368. }
  1369. }
  1370. if(SUCCEEDED(hr))
  1371. {
  1372. TListItem<StampedGMGSXG>* pPair = gMidiModeList.GetHead();
  1373. if( NULL == pPair )
  1374. {
  1375. // if we had nothing, generate a GM one so the band knows
  1376. // it was loaded from a midi file
  1377. // since the first band is set to play at -1,
  1378. // this is when the default midi mode must occur.
  1379. pBandTrack->SetGMGSXGMode(-1, DMUS_MIDIMODEF_GM);
  1380. }
  1381. for ( ; pPair; pPair = pPair->GetNext() )
  1382. {
  1383. StampedGMGSXG& rPair = pPair->GetItemValue();
  1384. pBandTrack->SetGMGSXGMode(rPair.mtTime, rPair.dwMidiMode);
  1385. }
  1386. gMidiModeList.CleanUp();
  1387. if(SUCCEEDED(pBandTrack->QueryInterface(IID_IDirectMusicTrack,
  1388. (void**)&pDMTrack)))
  1389. {
  1390. pSegment->InsertTrack(pDMTrack, 1);
  1391. pDMTrack->Release();
  1392. }
  1393. }
  1394. if(pBandTrack)
  1395. {
  1396. pBandTrack->Release();
  1397. }
  1398. if(pIDMLoader)
  1399. {
  1400. pIDMLoader->Release();
  1401. }
  1402. }
  1403. }
  1404. if( gpTimeSigStream )
  1405. {
  1406. // Create a TimeSig Track to store the TimeSig events
  1407. if( SUCCEEDED( CoCreateInstance( CLSID_DirectMusicTimeSigTrack,
  1408. NULL, CLSCTX_INPROC, IID_IPersistStream,
  1409. (void**)&pIPSTrack )))
  1410. {
  1411. // set the overall size to the correct size
  1412. StreamSeek( gpTimeSigStream, sizeof(DWORD), STREAM_SEEK_SET );
  1413. gpTimeSigStream->Write( &gdwSizeTimeSigStream, sizeof(DWORD), NULL );
  1414. // reset to beginning and persist to track.
  1415. StreamSeek( gpTimeSigStream, 0, STREAM_SEEK_SET );
  1416. pIPSTrack->Load( gpTimeSigStream );
  1417. if( SUCCEEDED( pIPSTrack->QueryInterface( IID_IDirectMusicTrack,
  1418. (void**)&pDMTrack ) ) )
  1419. {
  1420. pSegment->InsertTrack( pDMTrack, 1 );
  1421. AddOffsets(lstEvent, pDMTrack);
  1422. pDMTrack->Release();
  1423. }
  1424. pIPSTrack->Release();
  1425. }
  1426. }
  1427. else
  1428. {
  1429. AddOffsets(lstEvent, NULL);
  1430. }
  1431. lstEvent = SortEventList( lstEvent );
  1432. // Create a Sequence Track in which to store the notes, curves,
  1433. // and SysEx events.
  1434. //
  1435. if( SUCCEEDED( CoCreateInstance( CLSID_DirectMusicSeqTrack,
  1436. NULL, CLSCTX_INPROC, IID_IPersistStream,
  1437. (void**)&pIPSTrack )))
  1438. {
  1439. // Create a stream in which to place the events so we can
  1440. // give it to the SeqTrack.Load.
  1441. IStream* pEventStream;
  1442. if( S_OK == CreateStreamOnHGlobal( NULL, TRUE, &pEventStream ) )
  1443. {
  1444. // angusg: The implementation of memory IStream interface on
  1445. // CE can be inefficient if the stream memory isn't allocated
  1446. // before. It will call LocalRealloc on every IStream->Write
  1447. // for the amount that is written (in this case a small amount)
  1448. // this is incredible inefficient here as Realloc can be called
  1449. // thousands of times....
  1450. // The solution is to pre calculate the size of the stream and
  1451. // call ISteam->SetSize(), which calls LocalAlloc, to alloc the
  1452. // memory in one call.
  1453. // calculate the size of the stream storage
  1454. DWORD dwStreamStorageSize;
  1455. FullSeqEvent* pEvent;
  1456. // add the size of the chunk id's written below
  1457. dwStreamStorageSize = 5 * sizeof(DWORD);
  1458. // now count how many events need to be stored in the stream
  1459. for( pEvent = lstEvent; pEvent; pEvent = pEvent->pNext )
  1460. {
  1461. dwStreamStorageSize += sizeof(DMUS_IO_SEQ_ITEM);
  1462. }
  1463. ULARGE_INTEGER liSize;
  1464. liSize.QuadPart = dwStreamStorageSize;
  1465. // make the stream allocate the complete amount of memory
  1466. pEventStream->SetSize(liSize);
  1467. // Save the events into the stream
  1468. ULONG cb, cbWritten;
  1469. // Save the chunk id
  1470. DWORD dwTemp = DMUS_FOURCC_SEQ_TRACK;
  1471. pEventStream->Write( &dwTemp, sizeof(DWORD), NULL );
  1472. // Save the overall size. Count the number of events to determine.
  1473. dwSize = 0;
  1474. for( pEvent = lstEvent; pEvent; pEvent = pEvent->pNext )
  1475. {
  1476. dwSize++;
  1477. }
  1478. dwSize *= sizeof(DMUS_IO_SEQ_ITEM);
  1479. // add 8 for the subchunk
  1480. dwSize += 8;
  1481. pEventStream->Write( &dwSize, sizeof(DWORD), NULL );
  1482. // Save the subchunk id
  1483. dwTemp = DMUS_FOURCC_SEQ_LIST;
  1484. pEventStream->Write( &dwTemp, sizeof(DWORD), NULL );
  1485. // Subtract the previously added 8
  1486. dwSize -= 8;
  1487. // Save the size of the subchunk
  1488. pEventStream->Write( &dwSize, sizeof(DWORD), NULL );
  1489. // Save the structure size.
  1490. dwTemp = sizeof(DMUS_IO_SEQ_ITEM);
  1491. pEventStream->Write( &dwTemp, sizeof(DWORD), NULL );
  1492. // Save the events.
  1493. cb = sizeof(DMUS_IO_SEQ_ITEM); // doesn't have the next pointers
  1494. for( pEvent = lstEvent; pEvent; pEvent = pEvent->pNext )
  1495. {
  1496. if( dwLength < (DWORD)(pEvent->mtTime + pEvent->mtDuration) )
  1497. {
  1498. dwLength = pEvent->mtTime + pEvent->mtDuration;
  1499. }
  1500. pEventStream->Write( pEvent, cb, &cbWritten );
  1501. if( cb != cbWritten ) // error!
  1502. {
  1503. pEventStream->Release();
  1504. pEventStream = NULL;
  1505. hr = DMUS_E_CANNOTREAD;
  1506. break;
  1507. }
  1508. }
  1509. if( pEventStream ) // may be NULL
  1510. {
  1511. StreamSeek( pEventStream, 0, STREAM_SEEK_SET );
  1512. pIPSTrack->Load( pEventStream );
  1513. pEventStream->Release();
  1514. }
  1515. }
  1516. if( SUCCEEDED( pIPSTrack->QueryInterface( IID_IDirectMusicTrack,
  1517. (void**)&pDMTrack ) ) )
  1518. {
  1519. pSegment->InsertTrack( pDMTrack, 1 );
  1520. pDMTrack->Release();
  1521. }
  1522. pIPSTrack->Release();
  1523. }
  1524. // set the length of the segment. Set it to the measure boundary
  1525. // past the last note.
  1526. DWORD dwResolvedLength = gTimeSig.lTime;
  1527. if( 0 == gTimeSig.bBeat ) gTimeSig.bBeat = 4;
  1528. if( 0 == gTimeSig.bBeatsPerMeasure ) gTimeSig.bBeatsPerMeasure = 4;
  1529. if( 0 == gTimeSig.wGridsPerBeat ) gTimeSig.wGridsPerBeat = 4;
  1530. while( dwResolvedLength < dwLength )
  1531. {
  1532. dwResolvedLength += (((DMUS_PPQ * 4) / gTimeSig.bBeat) * gTimeSig.bBeatsPerMeasure);
  1533. }
  1534. pSegment->SetLength( dwResolvedLength );
  1535. if( gpSysExStream )
  1536. {
  1537. // Create a SysEx Track in which to store the SysEx events
  1538. if( SUCCEEDED( CoCreateInstance( CLSID_DirectMusicSysExTrack,
  1539. NULL, CLSCTX_INPROC, IID_IPersistStream,
  1540. (void**)&pIPSTrack )))
  1541. {
  1542. // write overall length
  1543. StreamSeek( gpSysExStream, sizeof(DWORD), STREAM_SEEK_SET );
  1544. gpSysExStream->Write( &gdwSizeSysExStream, sizeof(DWORD), NULL );
  1545. // seek to beginning and persist to track
  1546. StreamSeek( gpSysExStream, 0, STREAM_SEEK_SET );
  1547. pIPSTrack->Load( gpSysExStream );
  1548. if( SUCCEEDED( pIPSTrack->QueryInterface( IID_IDirectMusicTrack,
  1549. (void**)&pDMTrack ) ) )
  1550. {
  1551. pSegment->InsertTrack( pDMTrack, 1 );
  1552. pDMTrack->Release();
  1553. }
  1554. pIPSTrack->Release();
  1555. }
  1556. }
  1557. }
  1558. else
  1559. {
  1560. hr = E_POINTER;
  1561. }
  1562. }
  1563. END:
  1564. List_Free( lstEvent );
  1565. List_Free( lstPatchEvent );
  1566. FullSeqEvent::CleanUp();
  1567. // release our hold on the streams
  1568. RELEASE( gpTempoStream );
  1569. RELEASE( gpSysExStream );
  1570. RELEASE( gpTimeSigStream );
  1571. gpTempoStream = NULL;
  1572. gpSysExStream = NULL;
  1573. gpTimeSigStream = NULL;
  1574. gdwSizeTimeSigStream = 0;
  1575. gdwSizeSysExStream = 0;
  1576. gdwSizeTempoStream = 0;
  1577. LeaveCriticalSection(&g_CritSec);
  1578. if (SUCCEEDED(hrGM) || hr != S_OK )
  1579. {
  1580. return hr;
  1581. }
  1582. else
  1583. {
  1584. return DMUS_S_PARTIALLOAD;
  1585. }
  1586. }
  1587. // Creates and returns (in rChord) a DMUS_CHORD_PARAM given the three input params.
  1588. // the new chord will have one subchord containing the root, third, fifth, and seventh
  1589. // of the key (as indicated by the sharps/flats and mode). Scale will be either
  1590. // major or minor, depending on the mode (mode is 0 if major, 1 if minor).
  1591. void CreateChordFromKey(char cSharpsFlats, BYTE bMode, DWORD dwTime, DMUS_CHORD_PARAM& rChord)
  1592. {
  1593. static DWORD dwMajorScale = 0xab5ab5; // 1010 1011 0101 1010 1011 0101
  1594. static DWORD dwMinorScale = 0x5ad5ad; // 0101 1010 1101 0101 1010 1101
  1595. static DWORD dwMajor7Chord = 0x891; // 1000 1001 0001
  1596. static DWORD dwMinor7Chord = 0x489; // 0100 1000 1001
  1597. BYTE bScaleRoot = 0;
  1598. switch (cSharpsFlats)
  1599. {
  1600. case 0: bScaleRoot = bMode ? 9 : 0; break;
  1601. case 1: bScaleRoot = bMode ? 4 : 7; break;
  1602. case 2: bScaleRoot = bMode ? 11 : 2; break;
  1603. case 3: bScaleRoot = bMode ? 6 : 9; break;
  1604. case 4: bScaleRoot = bMode ? 1 : 4; break;
  1605. case 5: bScaleRoot = bMode ? 8 : 11; break;
  1606. case 6: bScaleRoot = bMode ? 3 : 6; break;
  1607. case 7: bScaleRoot = bMode ? 10 : 1; break;
  1608. case -1: bScaleRoot = bMode ? 2 : 5; break;
  1609. case -2: bScaleRoot = bMode ? 7 : 10; break;
  1610. case -3: bScaleRoot = bMode ? 0 : 3; break;
  1611. case -4: bScaleRoot = bMode ? 5 : 8; break;
  1612. case -5: bScaleRoot = bMode ? 10 : 1; break;
  1613. case -6: bScaleRoot = bMode ? 3 : 6; break;
  1614. case -7: bScaleRoot = bMode ? 8 : 11; break;
  1615. }
  1616. if (bMode)
  1617. {
  1618. wcscpy(rChord.wszName, L"m7");
  1619. }
  1620. else
  1621. {
  1622. wcscpy(rChord.wszName, L"M7");
  1623. }
  1624. DMUS_IO_TIMESIGNATURE_ITEM timesig;
  1625. timesig.bBeat = gTimeSig.bBeat ? gTimeSig.bBeat : 4;
  1626. timesig.bBeatsPerMeasure = gTimeSig.bBeatsPerMeasure ? gTimeSig.bBeatsPerMeasure : 4;
  1627. timesig.wGridsPerBeat = gTimeSig.wGridsPerBeat ? gTimeSig.wGridsPerBeat : 4;
  1628. DWORD dwAbsBeat = dwTime / ((DMUS_PPQ * 4) / timesig.bBeat);
  1629. rChord.wMeasure = (WORD)(dwAbsBeat / timesig.bBeatsPerMeasure);
  1630. rChord.bBeat = (BYTE)(dwAbsBeat % timesig.bBeatsPerMeasure);
  1631. rChord.bSubChordCount = 1;
  1632. rChord.SubChordList[0].dwChordPattern = bMode ? dwMinor7Chord : dwMajor7Chord;
  1633. rChord.SubChordList[0].dwScalePattern = bMode ? dwMinorScale : dwMajorScale;
  1634. rChord.SubChordList[0].dwInversionPoints = 0xffffff; // inversions allowed everywhere
  1635. rChord.SubChordList[0].dwLevels = 0xffffffff; // supports all levels
  1636. rChord.SubChordList[0].bChordRoot = bScaleRoot;
  1637. rChord.SubChordList[0].bScaleRoot = bScaleRoot;
  1638. }