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.

1571 lines
58 KiB

  1. // Copyright (c) 1996-2000 Microsoft Corporation. All rights reserved.
  2. // Instrument.cpp
  3. #include "common.h"
  4. #define STR_MODULENAME "DDKSynth.sys:Instr: "
  5. #include "math.h"
  6. void MemDump(char * prompt);
  7. #pragma code_seg()
  8. /*****************************************************************************
  9. * CSourceLFO::CSourceLFO()
  10. *****************************************************************************
  11. * Constructor for CSourceLFO.
  12. */
  13. CSourceLFO::CSourceLFO()
  14. {
  15. m_pfFrequency = 3804; // f = (256*4096*16*5hz)/(samplerate)
  16. m_stDelay = 0;
  17. m_prMWPitchScale = 0;
  18. m_vrMWVolumeScale = 0;
  19. m_vrVolumeScale = 0;
  20. m_prPitchScale = 0;
  21. }
  22. /*****************************************************************************
  23. * CSourceLFO::Init()
  24. *****************************************************************************
  25. * Initialize the CSourceLFO object.
  26. */
  27. void CSourceLFO::Init(DWORD dwSampleRate)
  28. {
  29. m_pfFrequency = (256 * 4096 * 16 * 5) / dwSampleRate;
  30. m_stDelay = 0;
  31. m_prMWPitchScale = 0;
  32. m_vrMWVolumeScale = 0;
  33. m_vrVolumeScale = 0;
  34. m_prPitchScale = 0;
  35. }
  36. /*****************************************************************************
  37. * CSourceLFO::SetSampleRate()
  38. *****************************************************************************
  39. * Set the sample rate delta.
  40. */
  41. void CSourceLFO::SetSampleRate(long lChange)
  42. {
  43. if (lChange > 0)
  44. {
  45. m_stDelay <<= lChange;
  46. m_pfFrequency <<= lChange;
  47. }
  48. else
  49. {
  50. m_stDelay >>= -lChange;
  51. m_pfFrequency >>= -lChange;
  52. }
  53. }
  54. /*****************************************************************************
  55. * CSourceLFO::Verify()
  56. *****************************************************************************
  57. * Sanity check on the object.
  58. */
  59. void CSourceLFO::Verify()
  60. {
  61. FORCEBOUNDS(m_pfFrequency,64,7600);
  62. FORCEBOUNDS(m_stDelay,0,441000);
  63. FORCEBOUNDS(m_vrVolumeScale,-1200,1200);
  64. FORCEBOUNDS(m_vrMWVolumeScale,-1200,1200);
  65. FORCEBOUNDS(m_prPitchScale,-1200,1200);
  66. FORCEBOUNDS(m_prMWPitchScale,-1200,1200);
  67. }
  68. /*****************************************************************************
  69. * CSourceEG::CSourceEG()
  70. *****************************************************************************
  71. * Constructor for this object.
  72. */
  73. CSourceEG::CSourceEG()
  74. {
  75. Init();
  76. }
  77. /*****************************************************************************
  78. * CSourceEG::Init()
  79. *****************************************************************************
  80. * Initialize the CSourceEG object.
  81. */
  82. void CSourceEG::Init()
  83. {
  84. m_stAttack = 0;
  85. m_stDecay = 0;
  86. m_pcSustain = 1000;
  87. m_stRelease = 0;
  88. m_trVelAttackScale = 0;
  89. m_trKeyDecayScale = 0;
  90. m_sScale = 0;
  91. }
  92. /*****************************************************************************
  93. * CSourceEG::SetSampleRate()
  94. *****************************************************************************
  95. * Set the sample rate delta.
  96. */
  97. void CSourceEG::SetSampleRate(long lChange)
  98. {
  99. if (lChange > 0)
  100. {
  101. m_stAttack <<= lChange;
  102. m_stDecay <<= lChange;
  103. m_stRelease <<= lChange;
  104. }
  105. else
  106. {
  107. m_stAttack >>= -lChange;
  108. m_stDecay >>= -lChange;
  109. m_stRelease >>= -lChange;
  110. }
  111. }
  112. /*****************************************************************************
  113. * CSourceEG::Verify()
  114. *****************************************************************************
  115. * Sanity check on the object.
  116. */
  117. void CSourceEG::Verify()
  118. {
  119. FORCEBOUNDS(m_stAttack,0,1764000);
  120. FORCEBOUNDS(m_stDecay,0,1764000);
  121. FORCEBOUNDS(m_pcSustain,0,1000);
  122. FORCEBOUNDS(m_stRelease,0,1764000);
  123. FORCEBOUNDS(m_sScale,-1200,1200);
  124. FORCEBOUNDS(m_trKeyDecayScale,-12000,12000);
  125. FORCEBOUNDS(m_trVelAttackScale,-12000,12000);
  126. }
  127. /*****************************************************************************
  128. * CSourceArticulation::CSourceArticulation()
  129. *****************************************************************************
  130. * Constructor for this object.
  131. */
  132. CSourceArticulation::CSourceArticulation()
  133. {
  134. m_wUsageCount = 0;
  135. m_sDefaultPan = 0;
  136. m_dwSampleRate = 22050;
  137. m_PitchEG.m_sScale = 0; // pitch envelope defaults to off
  138. }
  139. /*****************************************************************************
  140. * CSourceArticulation::Init()
  141. *****************************************************************************
  142. * Initialize the CSourceArticulation object.
  143. */
  144. void CSourceArticulation::Init(DWORD dwSampleRate)
  145. {
  146. m_dwSampleRate = dwSampleRate;
  147. m_LFO.Init(dwSampleRate); // Set to default values.
  148. m_PitchEG.Init();
  149. m_VolumeEG.Init();
  150. }
  151. /*****************************************************************************
  152. * CSourceArticulation::SetSampleRate()
  153. *****************************************************************************
  154. * Set the sample rate for this articulation.
  155. */
  156. void CSourceArticulation::SetSampleRate(DWORD dwSampleRate)
  157. {
  158. if (dwSampleRate != m_dwSampleRate)
  159. {
  160. long lChange;
  161. if (dwSampleRate > (m_dwSampleRate * 2))
  162. {
  163. lChange = 2; // going from 11 to 44.
  164. }
  165. else if (dwSampleRate > m_dwSampleRate)
  166. {
  167. lChange = 1; // must be doubling
  168. }
  169. else if ((dwSampleRate * 2) < m_dwSampleRate)
  170. {
  171. lChange = -2; // going from 44 to 11
  172. }
  173. else
  174. {
  175. lChange = -1; // that leaves halving.
  176. }
  177. m_dwSampleRate = dwSampleRate;
  178. m_LFO.SetSampleRate(lChange);
  179. m_PitchEG.SetSampleRate(lChange);
  180. m_VolumeEG.SetSampleRate(lChange);
  181. }
  182. }
  183. /*****************************************************************************
  184. * CSourceArticulation::Verify()
  185. *****************************************************************************
  186. * Sanity check on the object.
  187. */
  188. void CSourceArticulation::Verify()
  189. {
  190. m_LFO.Verify();
  191. m_PitchEG.Verify();
  192. m_VolumeEG.Verify();
  193. }
  194. /*****************************************************************************
  195. * CSourceArticulation::AddRef()
  196. *****************************************************************************
  197. * Implementation of standard COM interface.
  198. */
  199. void CSourceArticulation::AddRef()
  200. {
  201. m_wUsageCount++;
  202. }
  203. /*****************************************************************************
  204. * CSourceArticulation::Release()
  205. *****************************************************************************
  206. * Implementation of standard COM interface.
  207. */
  208. void CSourceArticulation::Release()
  209. {
  210. m_wUsageCount--;
  211. if (m_wUsageCount == 0)
  212. {
  213. delete this;
  214. }
  215. }
  216. /*****************************************************************************
  217. * CSourceSample::CSourceSample()
  218. *****************************************************************************
  219. * Constructor for this object.
  220. */
  221. CSourceSample::CSourceSample()
  222. {
  223. m_pWave = NULL;
  224. m_dwLoopStart = 0;
  225. m_dwLoopEnd = 1;
  226. m_dwSampleLength = 0;
  227. m_prFineTune = 0;
  228. m_dwSampleRate = 22050;
  229. m_bMIDIRootKey = 60;
  230. m_bOneShot = TRUE;
  231. m_bSampleType = 0;
  232. }
  233. /*****************************************************************************
  234. * CSourceSample::~CSourceSample()
  235. *****************************************************************************
  236. * Destructor for this object.
  237. */
  238. CSourceSample::~CSourceSample()
  239. {
  240. if (m_pWave != NULL)
  241. {
  242. m_pWave->Release();
  243. }
  244. }
  245. /*****************************************************************************
  246. * CSourceSample::Verify()
  247. *****************************************************************************
  248. * Sanity check on the object.
  249. */
  250. void CSourceSample::Verify()
  251. {
  252. if (m_pWave != NULL)
  253. {
  254. FORCEUPPERBOUNDS(m_dwSampleLength,m_pWave->m_dwSampleLength);
  255. FORCEBOUNDS(m_dwLoopEnd,1,m_dwSampleLength);
  256. FORCEUPPERBOUNDS(m_dwLoopStart,m_dwLoopEnd);
  257. if ((m_dwLoopEnd - m_dwLoopStart) < 6)
  258. {
  259. m_bOneShot = TRUE;
  260. }
  261. }
  262. FORCEBOUNDS(m_dwSampleRate,3000,80000);
  263. FORCEBOUNDS(m_bMIDIRootKey,0,127);
  264. FORCEBOUNDS(m_prFineTune,-1200,1200);
  265. }
  266. /*****************************************************************************
  267. * CSourceSample::CopyFromWave()
  268. *****************************************************************************
  269. * Duplicate a wave that is already referenced elsewhere.
  270. */
  271. BOOL CSourceSample::CopyFromWave()
  272. {
  273. if (m_pWave == NULL)
  274. {
  275. return FALSE;
  276. }
  277. m_dwSampleLength = m_pWave->m_dwSampleLength;
  278. m_dwSampleRate = m_pWave->m_dwSampleRate;
  279. m_bSampleType = m_pWave->m_bSampleType;
  280. if (m_bOneShot)
  281. {
  282. m_dwSampleLength--;
  283. if (m_pWave->m_bSampleType & SFORMAT_16)
  284. {
  285. m_pWave->m_pnWave[m_dwSampleLength] = 0;
  286. }
  287. else
  288. {
  289. char *pBuffer = (char *) m_pWave->m_pnWave;
  290. pBuffer[m_dwSampleLength] = 0;
  291. }
  292. }
  293. else
  294. {
  295. if (m_dwLoopStart >= m_dwSampleLength)
  296. {
  297. m_dwLoopStart = 0;
  298. }
  299. if (m_pWave->m_bSampleType & SFORMAT_16)
  300. {
  301. m_pWave->m_pnWave[m_dwSampleLength-1] =
  302. m_pWave->m_pnWave[m_dwLoopStart];
  303. }
  304. else
  305. {
  306. char *pBuffer = (char *) m_pWave->m_pnWave;
  307. pBuffer[m_dwSampleLength-1] =
  308. pBuffer[m_dwLoopStart];
  309. }
  310. }
  311. Verify();
  312. return (TRUE);
  313. }
  314. /*****************************************************************************
  315. * CWave::CWave()
  316. *****************************************************************************
  317. * Constructor for this object.
  318. */
  319. CWave::CWave()
  320. {
  321. m_hUserData = NULL;
  322. m_lpFreeHandle = NULL;
  323. m_pnWave = NULL;
  324. m_dwSampleRate = 22050;
  325. m_bSampleType = SFORMAT_16;
  326. m_dwSampleLength = 0;
  327. m_wUsageCount = 0;
  328. m_dwID = 0;
  329. m_wPlayCount = 0;
  330. m_pWaveMem = NULL;
  331. }
  332. /*****************************************************************************
  333. * CWave::~CWave()
  334. *****************************************************************************
  335. * Destructor for this object.
  336. */
  337. CWave::~CWave()
  338. {
  339. if (m_pWaveMem)
  340. {
  341. if (m_lpFreeHandle)
  342. {
  343. m_lpFreeHandle((HANDLE) this,m_hUserData);
  344. }
  345. else
  346. {
  347. delete m_pWaveMem;
  348. }
  349. m_pWaveMem = NULL;
  350. }
  351. m_pnWave = NULL;
  352. }
  353. /*****************************************************************************
  354. * CWave::Verify()
  355. *****************************************************************************
  356. * Sanity check on the object.
  357. */
  358. void CWave::Verify()
  359. {
  360. FORCEBOUNDS(m_dwSampleRate,3000,80000);
  361. }
  362. /*****************************************************************************
  363. * CWave::PlayOn()
  364. *****************************************************************************
  365. * Increment the play count.
  366. */
  367. void CWave::PlayOn()
  368. {
  369. m_wPlayCount++;
  370. AddRef();
  371. }
  372. /*****************************************************************************
  373. * CWave::PlayOff()
  374. *****************************************************************************
  375. * Decrement the play count.
  376. */
  377. void CWave::PlayOff()
  378. {
  379. m_wPlayCount--;
  380. Release();
  381. }
  382. /*****************************************************************************
  383. * CWave::IsPlaying()
  384. *****************************************************************************
  385. * Return whether the wave is currently playing.
  386. */
  387. BOOL CWave::IsPlaying()
  388. {
  389. return (m_wPlayCount);
  390. }
  391. /*****************************************************************************
  392. * CWave::AddRef()
  393. *****************************************************************************
  394. * Implementation of standard COM interface.
  395. */
  396. void CWave::AddRef()
  397. {
  398. m_wUsageCount++;
  399. }
  400. /*****************************************************************************
  401. * CWave::Release()
  402. *****************************************************************************
  403. * Implementation of standard COM interface.
  404. */
  405. void CWave::Release()
  406. {
  407. m_wUsageCount--;
  408. if (m_wUsageCount == 0)
  409. {
  410. delete this;
  411. }
  412. }
  413. /*****************************************************************************
  414. * CSourceRegion::CSourceRegion()
  415. *****************************************************************************
  416. * Constructor for this object.
  417. */
  418. CSourceRegion::CSourceRegion()
  419. {
  420. m_pArticulation = NULL;
  421. m_vrAttenuation = 0;
  422. m_prTuning = 0;
  423. m_bKeyHigh = 127;
  424. m_bKeyLow = 0;
  425. m_bGroup = 0;
  426. m_bAllowOverlap = FALSE;
  427. }
  428. /*****************************************************************************
  429. * CSourceRegion::~CSourceRegion()
  430. *****************************************************************************
  431. * Destructor for this object.
  432. */
  433. CSourceRegion::~CSourceRegion()
  434. {
  435. if (m_pArticulation)
  436. {
  437. m_pArticulation->Release();
  438. }
  439. }
  440. /*****************************************************************************
  441. * CSourceRegion::SetSampleRate()
  442. *****************************************************************************
  443. * Set the sample rate for this region. Forward this to the articulation.
  444. */
  445. void CSourceRegion::SetSampleRate(DWORD dwSampleRate)
  446. {
  447. if (m_pArticulation != NULL)
  448. {
  449. m_pArticulation->SetSampleRate(dwSampleRate);
  450. }
  451. }
  452. /*****************************************************************************
  453. * CSourceRegion::Verify()
  454. *****************************************************************************
  455. * Sanity check on the object.
  456. */
  457. void CSourceRegion::Verify()
  458. {
  459. FORCEBOUNDS(m_bKeyHigh,0,127);
  460. FORCEBOUNDS(m_bKeyLow,0,127);
  461. FORCEBOUNDS(m_prTuning,-12000,12000);
  462. FORCEBOUNDS(m_vrAttenuation,-9600,0);
  463. m_Sample.Verify();
  464. if (m_pArticulation != NULL)
  465. {
  466. m_pArticulation->Verify();
  467. }
  468. }
  469. /*****************************************************************************
  470. * CInstrument::CInstrument()
  471. *****************************************************************************
  472. * Constructor for this object.
  473. */
  474. CInstrument::CInstrument()
  475. {
  476. m_dwProgram = 0;
  477. }
  478. /*****************************************************************************
  479. * CInstrument::~CInstrument()
  480. *****************************************************************************
  481. * Destructor for this object.
  482. */
  483. CInstrument::~CInstrument()
  484. {
  485. while (!m_RegionList.IsEmpty())
  486. {
  487. CSourceRegion *pRegion = m_RegionList.RemoveHead();
  488. delete pRegion;
  489. }
  490. }
  491. /*****************************************************************************
  492. * CInstrument::Verify()
  493. *****************************************************************************
  494. * Sanity check on the object.
  495. */
  496. void CInstrument::Verify()
  497. {
  498. CSourceRegion *pRegion = m_RegionList.GetHead();
  499. CSourceArticulation *pArticulation = NULL;
  500. for (;pRegion != NULL;pRegion = pRegion->GetNext())
  501. {
  502. if (pRegion->m_pArticulation != NULL)
  503. {
  504. pArticulation = pRegion->m_pArticulation;
  505. }
  506. pRegion->Verify();
  507. }
  508. if (pArticulation)
  509. {
  510. pRegion = m_RegionList.GetHead();
  511. for (;pRegion != NULL;pRegion = pRegion->GetNext())
  512. {
  513. if (pRegion->m_pArticulation == NULL)
  514. {
  515. pRegion->m_pArticulation = pArticulation;
  516. pArticulation->AddRef();
  517. }
  518. }
  519. }
  520. }
  521. /*****************************************************************************
  522. * CInstrument::SetSampleRate()
  523. *****************************************************************************
  524. * Set the sample rate for this instrument (forward to region).
  525. */
  526. void CInstrument::SetSampleRate(DWORD dwSampleRate)
  527. {
  528. CSourceRegion *pRegion = m_RegionList.GetHead();
  529. for (;pRegion;pRegion = pRegion->GetNext())
  530. {
  531. pRegion->SetSampleRate(dwSampleRate);
  532. }
  533. }
  534. /*****************************************************************************
  535. * CInstrument::ScanForRegion()
  536. *****************************************************************************
  537. * Retrieve the region with the given note value from the list.
  538. */
  539. CSourceRegion * CInstrument::ScanForRegion(DWORD dwNoteValue)
  540. {
  541. CSourceRegion *pRegion = m_RegionList.GetHead();
  542. for (;pRegion;pRegion = pRegion->GetNext())
  543. {
  544. if (dwNoteValue >= pRegion->m_bKeyLow &&
  545. dwNoteValue <= pRegion->m_bKeyHigh)
  546. {
  547. break ;
  548. }
  549. }
  550. return pRegion;
  551. }
  552. /*****************************************************************************
  553. * CInstManager::SetSampleRate()
  554. *****************************************************************************
  555. * Set the sample rate for this instrument manager (forward to instruments).
  556. */
  557. void CInstManager::SetSampleRate(DWORD dwSampleRate)
  558. {
  559. DWORD dwIndex;
  560. m_dwSampleRate = dwSampleRate;
  561. EnterCriticalSection(&m_CriticalSection);
  562. for (dwIndex = 0; dwIndex < INSTRUMENT_HASH_SIZE; dwIndex++)
  563. {
  564. CInstrument *pInstrument = m_InstrumentList[dwIndex].GetHead();
  565. for (;pInstrument != NULL; pInstrument = pInstrument->GetNext())
  566. {
  567. pInstrument->SetSampleRate(dwSampleRate);
  568. }
  569. }
  570. LeaveCriticalSection(&m_CriticalSection);
  571. }
  572. /*****************************************************************************
  573. * CInstManager::CInstManager()
  574. *****************************************************************************
  575. * Constructor for this object.
  576. */
  577. CInstManager::CInstManager()
  578. {
  579. m_fCSInitialized = FALSE;
  580. m_dwSampleRate = 22050;
  581. InitializeCriticalSection(&m_CriticalSection);
  582. m_fCSInitialized = TRUE;
  583. }
  584. /*****************************************************************************
  585. * CInstManager::~CInstManager()
  586. *****************************************************************************
  587. * Destructor for this object.
  588. */
  589. CInstManager::~CInstManager()
  590. {
  591. if (m_fCSInitialized)
  592. {
  593. DWORD dwIndex;
  594. for (dwIndex = 0; dwIndex < INSTRUMENT_HASH_SIZE; dwIndex++)
  595. {
  596. while (!m_InstrumentList[dwIndex].IsEmpty())
  597. {
  598. CInstrument *pInstrument = m_InstrumentList[dwIndex].RemoveHead();
  599. delete pInstrument;
  600. }
  601. }
  602. for (dwIndex = 0; dwIndex < WAVE_HASH_SIZE; dwIndex++)
  603. {
  604. while (!m_WavePool[dwIndex].IsEmpty())
  605. {
  606. CWave *pWave = m_WavePool[dwIndex].RemoveHead();
  607. pWave->Release();
  608. }
  609. }
  610. while (!m_FreeWavePool.IsEmpty())
  611. {
  612. CWave *pWave = m_FreeWavePool.RemoveHead();
  613. pWave->Release();
  614. }
  615. DeleteCriticalSection(&m_CriticalSection);
  616. }
  617. }
  618. /*****************************************************************************
  619. * CInstManager::Verify()
  620. *****************************************************************************
  621. * Sanity check on the object.
  622. */
  623. void CInstManager::Verify()
  624. {
  625. DWORD dwIndex;
  626. EnterCriticalSection(&m_CriticalSection);
  627. for (dwIndex = 0; dwIndex < INSTRUMENT_HASH_SIZE; dwIndex++)
  628. {
  629. CInstrument *pInstrument = m_InstrumentList[dwIndex].GetHead();
  630. for (;pInstrument != NULL;pInstrument = pInstrument->GetNext())
  631. {
  632. pInstrument->Verify();
  633. }
  634. }
  635. LeaveCriticalSection(&m_CriticalSection);
  636. }
  637. /*****************************************************************************
  638. * CInstManager::GetInstrument()
  639. *****************************************************************************
  640. * Get the instrument that matches this program/key.
  641. */
  642. CInstrument * CInstManager::GetInstrument(DWORD dwProgram,DWORD dwKey)
  643. {
  644. EnterCriticalSection(&m_CriticalSection);
  645. CInstrument *pInstrument = m_InstrumentList[dwProgram % INSTRUMENT_HASH_SIZE].GetHead();
  646. for (;pInstrument != NULL; pInstrument = pInstrument->GetNext())
  647. {
  648. if (pInstrument->m_dwProgram == dwProgram)
  649. {
  650. if (pInstrument->ScanForRegion(dwKey) != NULL)
  651. {
  652. break;
  653. }
  654. else
  655. {
  656. Trace(1,"No region was found in instrument 0x%lx that matched note 0x%lx\n",
  657. dwProgram, dwKey);
  658. }
  659. }
  660. }
  661. LeaveCriticalSection(&m_CriticalSection);
  662. return (pInstrument);
  663. }
  664. /*****************************************************************************
  665. * TimeCents2Samples()
  666. *****************************************************************************
  667. * Translate from time cents to samples.
  668. */
  669. DWORD TimeCents2Samples(long tcTime, DWORD dwSampleRate)
  670. {
  671. if (tcTime == 0x80000000) return (0);
  672. double flTemp = tcTime;
  673. flTemp /= (65536 * 1200);
  674. flTemp = pow(2.0,flTemp);
  675. flTemp *= dwSampleRate;
  676. return (DWORD) flTemp;
  677. }
  678. /*****************************************************************************
  679. * PitchCents2PitchFract()
  680. *****************************************************************************
  681. * Translate from pitch cents to fractional pitch.
  682. */
  683. DWORD PitchCents2PitchFract(long pcRate,DWORD dwSampleRate)
  684. {
  685. double fTemp = pcRate;
  686. fTemp /= 65536;
  687. fTemp -= 6900;
  688. fTemp /= 1200;
  689. fTemp = pow(2.0,fTemp);
  690. fTemp *= 7381975040.0; // (440*256*16*4096);
  691. fTemp /= dwSampleRate;
  692. return (DWORD) (fTemp);
  693. }
  694. /*****************************************************************************
  695. * CSourceArticulation::Download()
  696. *****************************************************************************
  697. * Download an articulation to this object.
  698. */
  699. HRESULT
  700. CSourceArticulation::Download(DMUS_DOWNLOADINFO * pInfo,void * pvOffsetTable[],
  701. DWORD dwIndex, DWORD dwSampleRate,
  702. BOOL fNewFormat)
  703. {
  704. // Depending on whether this is the new DX7 format, we either are reading
  705. // a fixed set of parameters or parsing an articulation chunk directly
  706. // copied from the DLS file. The latter is obviously more flexible and it
  707. // turns out to make much more sense once we get to DLS2.
  708. if (fNewFormat)
  709. {
  710. DMUS_ARTICULATION2 * pdmArtic =
  711. (DMUS_ARTICULATION2 *) pvOffsetTable[dwIndex];
  712. while (pdmArtic)
  713. {
  714. if (pdmArtic->ulArtIdx)
  715. {
  716. if (pdmArtic->ulArtIdx >= pInfo->dwNumOffsetTableEntries)
  717. {
  718. return DMUS_E_BADARTICULATION;
  719. }
  720. DWORD dwPosition;
  721. void *pData = pvOffsetTable[pdmArtic->ulArtIdx];
  722. CONNECTIONLIST * pConnectionList =
  723. (CONNECTIONLIST *) pData;
  724. CONNECTION *pConnection;
  725. dwPosition = sizeof(CONNECTIONLIST);
  726. for (dwIndex = 0; dwIndex < pConnectionList->cConnections; dwIndex++)
  727. {
  728. pConnection = (CONNECTION *) ((BYTE *)pData + dwPosition);
  729. dwPosition += sizeof(CONNECTION);
  730. switch (pConnection->usSource)
  731. {
  732. case CONN_SRC_NONE :
  733. switch (pConnection->usDestination)
  734. {
  735. case CONN_DST_LFO_FREQUENCY :
  736. m_LFO.m_pfFrequency = PitchCents2PitchFract(
  737. pConnection->lScale,dwSampleRate);
  738. break;
  739. case CONN_DST_LFO_STARTDELAY :
  740. m_LFO.m_stDelay = TimeCents2Samples(
  741. (TCENT) pConnection->lScale,dwSampleRate);
  742. break;
  743. case CONN_DST_EG1_ATTACKTIME :
  744. m_VolumeEG.m_stAttack = TimeCents2Samples(
  745. (TCENT) pConnection->lScale,dwSampleRate);
  746. break;
  747. case CONN_DST_EG1_DECAYTIME :
  748. m_VolumeEG.m_stDecay = TimeCents2Samples(
  749. (TCENT) pConnection->lScale,dwSampleRate);
  750. break;
  751. case CONN_DST_EG1_SUSTAINLEVEL :
  752. m_VolumeEG.m_pcSustain =
  753. (SPERCENT) ((long) (pConnection->lScale >> 16));
  754. break;
  755. case CONN_DST_EG1_RELEASETIME :
  756. m_VolumeEG.m_stRelease = TimeCents2Samples(
  757. (TCENT) pConnection->lScale,dwSampleRate);
  758. break;
  759. case CONN_DST_EG2_ATTACKTIME :
  760. m_PitchEG.m_stAttack = TimeCents2Samples(
  761. (TCENT) pConnection->lScale,dwSampleRate);
  762. break;
  763. case CONN_DST_EG2_DECAYTIME :
  764. m_PitchEG.m_stDecay = TimeCents2Samples(
  765. (TCENT) pConnection->lScale,dwSampleRate);
  766. break;
  767. case CONN_DST_EG2_SUSTAINLEVEL :
  768. m_PitchEG.m_pcSustain =
  769. (SPERCENT) ((long) (pConnection->lScale >> 16));
  770. break;
  771. case CONN_DST_EG2_RELEASETIME :
  772. m_PitchEG.m_stRelease = TimeCents2Samples(
  773. (TCENT) pConnection->lScale,dwSampleRate);
  774. break;
  775. case CONN_DST_PAN :
  776. m_sDefaultPan = (short)
  777. ((long) ((long) pConnection->lScale >> 12) / 125);
  778. break;
  779. }
  780. break;
  781. case CONN_SRC_LFO :
  782. switch (pConnection->usControl)
  783. {
  784. case CONN_SRC_NONE :
  785. switch (pConnection->usDestination)
  786. {
  787. case CONN_DST_ATTENUATION :
  788. m_LFO.m_vrVolumeScale = (VRELS)
  789. ((long) ((pConnection->lScale * 10) >> 16));
  790. break;
  791. case CONN_DST_PITCH :
  792. m_LFO.m_prPitchScale = (PRELS)
  793. ((long) (pConnection->lScale >> 16));
  794. break;
  795. }
  796. break;
  797. case CONN_SRC_CC1 :
  798. switch (pConnection->usDestination)
  799. {
  800. case CONN_DST_ATTENUATION :
  801. m_LFO.m_vrMWVolumeScale = (VRELS)
  802. ((long) ((pConnection->lScale * 10) >> 16));
  803. break;
  804. case CONN_DST_PITCH :
  805. m_LFO.m_prMWPitchScale = (PRELS)
  806. ((long) (pConnection->lScale >> 16));
  807. break;
  808. }
  809. break;
  810. }
  811. break;
  812. case CONN_SRC_KEYONVELOCITY :
  813. switch (pConnection->usDestination)
  814. {
  815. case CONN_DST_EG1_ATTACKTIME :
  816. m_VolumeEG.m_trVelAttackScale = (TRELS)
  817. ((long) (pConnection->lScale >> 16));
  818. break;
  819. case CONN_DST_EG2_ATTACKTIME :
  820. m_PitchEG.m_trVelAttackScale = (TRELS)
  821. ((long) (pConnection->lScale >> 16));
  822. break;
  823. case CONN_DST_ATTENUATION :
  824. break;
  825. }
  826. break;
  827. case CONN_SRC_KEYNUMBER :
  828. switch (pConnection->usDestination)
  829. {
  830. case CONN_DST_EG1_DECAYTIME :
  831. m_VolumeEG.m_trKeyDecayScale = (TRELS)
  832. ((long) (pConnection->lScale >> 16));
  833. break;
  834. case CONN_DST_EG2_DECAYTIME :
  835. m_PitchEG.m_trKeyDecayScale = (TRELS)
  836. ((long) (pConnection->lScale >> 16));
  837. break;
  838. }
  839. break;
  840. case CONN_SRC_EG2 :
  841. switch (pConnection->usDestination)
  842. {
  843. case CONN_DST_PITCH :
  844. m_PitchEG.m_sScale = (short)
  845. ((long) (pConnection->lScale >> 16));
  846. break;
  847. }
  848. break;
  849. }
  850. }
  851. }
  852. if (pdmArtic->ulNextArtIdx)
  853. {
  854. if (pdmArtic->ulNextArtIdx >= pInfo->dwNumOffsetTableEntries)
  855. {
  856. return DMUS_E_BADARTICULATION;
  857. }
  858. pdmArtic = (DMUS_ARTICULATION2 *) pvOffsetTable[pdmArtic->ulNextArtIdx];
  859. }
  860. else
  861. {
  862. pdmArtic = NULL;
  863. }
  864. }
  865. }
  866. else
  867. {
  868. DMUS_ARTICULATION * pdmArtic =
  869. (DMUS_ARTICULATION *) pvOffsetTable[dwIndex];
  870. if (pdmArtic->ulArt1Idx)
  871. {
  872. if (pdmArtic->ulArt1Idx >= pInfo->dwNumOffsetTableEntries)
  873. {
  874. return DMUS_E_BADARTICULATION;
  875. }
  876. DMUS_ARTICPARAMS * pdmArticParams =
  877. (DMUS_ARTICPARAMS *) pvOffsetTable[pdmArtic->ulArt1Idx];
  878. m_LFO.m_pfFrequency = PitchCents2PitchFract(
  879. pdmArticParams->LFO.pcFrequency,dwSampleRate);
  880. m_LFO.m_stDelay = TimeCents2Samples(
  881. (TCENT) pdmArticParams->LFO.tcDelay,dwSampleRate);
  882. m_LFO.m_vrVolumeScale = (VRELS)
  883. ((long) ((pdmArticParams->LFO.gcVolumeScale * 10) >> 16));
  884. m_LFO.m_prPitchScale = (PRELS)
  885. ((long) (pdmArticParams->LFO.pcPitchScale >> 16));
  886. m_LFO.m_vrMWVolumeScale = (VRELS)
  887. ((long) ((pdmArticParams->LFO.gcMWToVolume * 10) >> 16));
  888. m_LFO.m_prMWPitchScale = (PRELS)
  889. ((long) (pdmArticParams->LFO.pcMWToPitch >> 16));
  890. m_VolumeEG.m_stAttack = TimeCents2Samples(
  891. (TCENT) pdmArticParams->VolEG.tcAttack,dwSampleRate);
  892. m_VolumeEG.m_stDecay = TimeCents2Samples(
  893. (TCENT) pdmArticParams->VolEG.tcDecay,dwSampleRate);
  894. m_VolumeEG.m_pcSustain =
  895. (SPERCENT) ((long) (pdmArticParams->VolEG.ptSustain >> 16));
  896. m_VolumeEG.m_stRelease = TimeCents2Samples(
  897. (TCENT) pdmArticParams->VolEG.tcRelease,dwSampleRate);
  898. m_VolumeEG.m_trVelAttackScale = (TRELS)
  899. ((long) (pdmArticParams->VolEG.tcVel2Attack >> 16));
  900. m_VolumeEG.m_trKeyDecayScale = (TRELS)
  901. ((long) (pdmArticParams->VolEG.tcKey2Decay >> 16));
  902. m_PitchEG.m_trKeyDecayScale = (TRELS)
  903. ((long) (pdmArticParams->PitchEG.tcKey2Decay >> 16));
  904. m_PitchEG.m_sScale = (short)
  905. ((long) (pdmArticParams->PitchEG.pcRange >> 16));
  906. m_PitchEG.m_trVelAttackScale = (TRELS)
  907. ((long) (pdmArticParams->PitchEG.tcVel2Attack >> 16));
  908. m_PitchEG.m_stAttack = TimeCents2Samples(
  909. (TCENT) pdmArticParams->PitchEG.tcAttack,dwSampleRate);
  910. m_PitchEG.m_stDecay = TimeCents2Samples(
  911. (TCENT) pdmArticParams->PitchEG.tcDecay,dwSampleRate);
  912. m_PitchEG.m_pcSustain =
  913. (SPERCENT) ((long) (pdmArticParams->PitchEG.ptSustain >> 16));
  914. m_PitchEG.m_stRelease = TimeCents2Samples(
  915. (TCENT) pdmArticParams->PitchEG.tcRelease,dwSampleRate);
  916. m_sDefaultPan = (short)
  917. ((long) ((long) pdmArticParams->Misc.ptDefaultPan >> 12) / 125);
  918. }
  919. }
  920. Verify(); // Make sure all parameters are legal.
  921. return S_OK;
  922. }
  923. /*****************************************************************************
  924. * CSourceRegion::Download()
  925. *****************************************************************************
  926. * Download a region to this object.
  927. * Parse through the region chunks, including any embedded articulation.
  928. */
  929. HRESULT CSourceRegion::Download(DMUS_DOWNLOADINFO * pInfo, // DMUS_DOWNLOADINFO header struct.
  930. void * pvOffsetTable[], // Offset table with embedded struct addresses.
  931. DWORD *pdwRegionIX, // Region index for first region.
  932. DWORD dwSampleRate, // Sample rate, used to convert time parameters.
  933. BOOL fNewFormat) // DMUS_DOWNLOADINFO_INSTRUMENT2 format?
  934. {
  935. DMUS_REGION * pdmRegion = (DMUS_REGION *) pvOffsetTable[*pdwRegionIX];
  936. *pdwRegionIX = pdmRegion->ulNextRegionIdx; // Clear to avoid loops.
  937. pdmRegion->ulNextRegionIdx = 0;
  938. // Read the Region chunk...
  939. m_bKeyHigh = (BYTE) pdmRegion->RangeKey.usHigh;
  940. m_bKeyLow = (BYTE) pdmRegion->RangeKey.usLow;
  941. if (pdmRegion->fusOptions & F_RGN_OPTION_SELFNONEXCLUSIVE)
  942. {
  943. m_bAllowOverlap = TRUE;
  944. }
  945. else
  946. {
  947. m_bAllowOverlap = FALSE;
  948. }
  949. m_bGroup = (BYTE) pdmRegion->usKeyGroup;
  950. // Now, the WSMP and WLOOP chunks...
  951. m_vrAttenuation = (short) ((long) ((pdmRegion->WSMP.lAttenuation) * 10) >> 16);
  952. m_Sample.m_prFineTune = pdmRegion->WSMP.sFineTune;
  953. m_Sample.m_bMIDIRootKey = (BYTE) pdmRegion->WSMP.usUnityNote;
  954. if (pdmRegion->WSMP.cSampleLoops == 0)
  955. {
  956. m_Sample.m_bOneShot = TRUE;
  957. }
  958. else
  959. {
  960. m_Sample.m_dwLoopStart = pdmRegion->WLOOP[0].ulStart;
  961. m_Sample.m_dwLoopEnd = m_Sample.m_dwLoopStart + pdmRegion->WLOOP[0].ulLength;
  962. m_Sample.m_bOneShot = FALSE;
  963. }
  964. m_Sample.m_dwSampleRate = dwSampleRate;
  965. // Then the WAVELINK...
  966. if (pdmRegion->WaveLink.ulChannel != WAVELINK_CHANNEL_LEFT)
  967. {
  968. return DMUS_E_NOTMONO;
  969. }
  970. m_Sample.m_dwID = (DWORD) pdmRegion->WaveLink.ulTableIndex;
  971. // Does it have its own articulation?
  972. if (pdmRegion->ulRegionArtIdx )
  973. {
  974. if (pdmRegion->ulRegionArtIdx >= pInfo->dwNumOffsetTableEntries)
  975. {
  976. return DMUS_E_BADARTICULATION;
  977. }
  978. CSourceArticulation *pArticulation = new CSourceArticulation;
  979. if (pArticulation)
  980. {
  981. pArticulation->Init(dwSampleRate);
  982. HRESULT hr = pArticulation->Download( pInfo, pvOffsetTable,
  983. pdmRegion->ulRegionArtIdx, dwSampleRate, fNewFormat);
  984. if (FAILED(hr))
  985. {
  986. delete pArticulation;
  987. return hr;
  988. }
  989. m_pArticulation = pArticulation;
  990. m_pArticulation->AddRef();
  991. }
  992. else
  993. {
  994. return E_OUTOFMEMORY;
  995. }
  996. }
  997. return S_OK;
  998. }
  999. /*****************************************************************************
  1000. * CInstManager::DownloadInstrument()
  1001. *****************************************************************************
  1002. * Download an instrument to this instrument manager. This is dispatched
  1003. * to the various appropriate objects.
  1004. *
  1005. * This is called by Download() when an instrument chunk is encountered.
  1006. * Using the offset table to resolve linkages, it scans through the instrument,
  1007. * parsing out regions and articulations, then finally linking the regions in the
  1008. * instrument to the waves, which should have been previously downloaded.
  1009. */
  1010. HRESULT CInstManager::DownloadInstrument(
  1011. LPHANDLE phDownload, // Pointer to download handle, to be created by synth.
  1012. DMUS_DOWNLOADINFO *pInfo, // DMUS_DOWNLOADINFO structure from the download chunk's head.
  1013. // This provides the total size of data, among other things.
  1014. void *pvOffsetTable[], // Offset table with addresses of all embedded structures.
  1015. void *pvData, // Pointer to start of download data.
  1016. BOOL fNewFormat) // Is this DMUS_DOWNLOADINFO_INSTRUMENT2 format download?
  1017. {
  1018. HRESULT hr = E_FAIL;
  1019. // The download data must start with the DMUS_INSTRUMENT chunk, so cast to that.
  1020. DMUS_INSTRUMENT *pdmInstrument = (DMUS_INSTRUMENT *) pvData;
  1021. CSourceArticulation *pArticulation = NULL;
  1022. // Create a new CInstrument structure. This stores everything that describes an instrument, including
  1023. // the articulations and regions.
  1024. CInstrument *pInstrument = new CInstrument;
  1025. if (pInstrument)
  1026. {
  1027. hr = S_OK;
  1028. // For debugging purposes, print a trace statement to show that the instrument has actually been downloaded.
  1029. // This only occurs in debug builds.
  1030. Trace(1,"Downloading instrument %lx\n",pdmInstrument->ulPatch);
  1031. pInstrument->m_dwProgram = pdmInstrument->ulPatch;
  1032. // Start by scanning through the regions.
  1033. DWORD dwRegionIX = pdmInstrument->ulFirstRegionIdx;
  1034. pdmInstrument->ulFirstRegionIdx = 0; // Clear to avoid loops.
  1035. while (dwRegionIX)
  1036. {
  1037. // For each region, verify that the index number is actually legal.
  1038. if (dwRegionIX >= pInfo->dwNumOffsetTableEntries)
  1039. {
  1040. hr = DMUS_E_BADINSTRUMENT;
  1041. goto ExitError;
  1042. }
  1043. CSourceRegion *pRegion = new CSourceRegion;
  1044. if (!pRegion)
  1045. {
  1046. hr = E_OUTOFMEMORY;
  1047. goto ExitError;
  1048. }
  1049. pInstrument->m_RegionList.AddHead(pRegion);
  1050. // Call the region's Download method to parse the region structure and optional embedded articulation.
  1051. hr = pRegion->Download(pInfo, pvOffsetTable, &dwRegionIX, m_dwSampleRate, fNewFormat);
  1052. if (FAILED(hr))
  1053. {
  1054. goto ExitError;
  1055. }
  1056. EnterCriticalSection(&m_CriticalSection);
  1057. // Once the region is parsed, we need to connect it to the wave, that should have been
  1058. // previously downloaded into the wavepool.
  1059. // Because of the hash table, the linked list is never very long, so the search is quick.
  1060. CWave *pWave = m_WavePool[pRegion->m_Sample.m_dwID % WAVE_HASH_SIZE].GetHead();
  1061. for (;pWave;pWave = pWave->GetNext())
  1062. {
  1063. // Each wave has a unique ID, which the regions match up with.
  1064. if (pRegion->m_Sample.m_dwID == pWave->m_dwID)
  1065. {
  1066. pRegion->m_Sample.m_pWave = pWave;
  1067. pWave->AddRef();
  1068. pRegion->m_Sample.CopyFromWave();
  1069. break;
  1070. }
  1071. }
  1072. LeaveCriticalSection(&m_CriticalSection);
  1073. }
  1074. // Once all the regions are loaded, see if we have a global articulation.
  1075. if (pdmInstrument->ulGlobalArtIdx)
  1076. {
  1077. // If so load it. First check that it's a valid index.
  1078. if (pdmInstrument->ulGlobalArtIdx >= pInfo->dwNumOffsetTableEntries)
  1079. {
  1080. hr = DMUS_E_BADARTICULATION;
  1081. goto ExitError;
  1082. }
  1083. // Create an articulation and have it parse the data.
  1084. pArticulation = new CSourceArticulation;
  1085. if (pArticulation)
  1086. {
  1087. // The articulation will convert all time parameters into sample times, so it needs to know the sample rate.
  1088. pArticulation->Init(m_dwSampleRate);
  1089. // Parse the articulation data. Note that the fNewFormat flag indicates whether this is in the DX6 fixed
  1090. // format articulation or the DX7 dynamic format (which is actually the same as the file format.)
  1091. hr = pArticulation->Download( pInfo, pvOffsetTable,
  1092. pdmInstrument->ulGlobalArtIdx, m_dwSampleRate, fNewFormat);
  1093. if (FAILED(hr))
  1094. {
  1095. goto ExitError;
  1096. }
  1097. // Once the global articulation is read, scan all regions and assign the articulation to all
  1098. // regions that don't have articulations yet.
  1099. for (CSourceRegion *pr = pInstrument->m_RegionList.GetHead();
  1100. pr != NULL;
  1101. pr = pr->GetNext())
  1102. {
  1103. if (pr->m_pArticulation == NULL)
  1104. {
  1105. pr->m_pArticulation = pArticulation;
  1106. pArticulation->AddRef();
  1107. }
  1108. }
  1109. if (!pArticulation->m_wUsageCount)
  1110. {
  1111. delete pArticulation;
  1112. pArticulation = NULL;
  1113. }
  1114. }
  1115. else
  1116. {
  1117. hr = E_OUTOFMEMORY;
  1118. goto ExitError;
  1119. }
  1120. }
  1121. else
  1122. {
  1123. for (CSourceRegion *pr = pInstrument->m_RegionList.GetHead();
  1124. pr != NULL;
  1125. pr = pr->GetNext())
  1126. {
  1127. if (pr->m_pArticulation == NULL)
  1128. {
  1129. hr = DMUS_E_NOARTICULATION;
  1130. goto ExitError;
  1131. }
  1132. }
  1133. }
  1134. if (SUCCEEDED(hr))
  1135. {
  1136. EnterCriticalSection(&m_CriticalSection);
  1137. // If this is a GM instrument, make sure that it will be searched for last by placing it at
  1138. // the end of the list. The DLS spec states that
  1139. // a DLS collection with the same patch as a GM instrument will always override the GM instrument.
  1140. if (pdmInstrument->ulFlags & DMUS_INSTRUMENT_GM_INSTRUMENT)
  1141. {
  1142. pInstrument->SetNext(NULL);
  1143. m_InstrumentList[pInstrument->m_dwProgram % INSTRUMENT_HASH_SIZE].AddTail(pInstrument);
  1144. }
  1145. else
  1146. {
  1147. m_InstrumentList[pInstrument->m_dwProgram % INSTRUMENT_HASH_SIZE].AddHead(pInstrument);
  1148. }
  1149. LeaveCriticalSection(&m_CriticalSection);
  1150. *phDownload = (HANDLE) pInstrument;
  1151. }
  1152. }
  1153. ExitError:
  1154. // Clean-up code.
  1155. if (FAILED(hr))
  1156. {
  1157. if (pArticulation)
  1158. {
  1159. delete pArticulation;
  1160. }
  1161. if (pInstrument)
  1162. {
  1163. delete pInstrument;
  1164. }
  1165. }
  1166. return hr;
  1167. }
  1168. /*****************************************************************************
  1169. * CInstManager::DownloadWave()
  1170. *****************************************************************************
  1171. * Download a wave to this instrument manager. It is put in the pool.
  1172. *
  1173. * This is called by Download when it receives a wave download chunk.
  1174. * DownloadWave parses the wave, converts the wave data if necessary, and
  1175. * places the wave in the wave pool, where it can subsequentley be
  1176. * connected to instruments. (All the waves referenced by an instrument
  1177. * are downloaded prior to downloading the instrument itself. This makes the
  1178. * whole process simpler and more reliable. Conversely, on unload, all
  1179. * waves are unloaded after the instruments that reference them.)
  1180. */
  1181. HRESULT CInstManager::DownloadWave(
  1182. LPHANDLE phDownload, // Download handle, to be returned. This will be
  1183. // used by a later Unload call to reference the wave.
  1184. DMUS_DOWNLOADINFO *pInfo, // DMUS_DOWNLOADINFO structure from the download chunk's head.
  1185. // This provides the total size of data, among other things.
  1186. void *pvOffsetTable[], // The table of offsets in the download data.
  1187. void *pvData) // Finally, the data itself.
  1188. {
  1189. // The start of the data should align with a DMUS_WAVE header.
  1190. DMUS_WAVE *pdmWave = (DMUS_WAVE *) pvData;
  1191. // Make sure that the wave data is properly uncompressed PCM data.
  1192. if (pdmWave->WaveformatEx.wFormatTag != WAVE_FORMAT_PCM)
  1193. {
  1194. return DMUS_E_NOTPCM;
  1195. }
  1196. // The data can only be mono format.
  1197. if (pdmWave->WaveformatEx.nChannels != 1)
  1198. {
  1199. return DMUS_E_NOTMONO;
  1200. }
  1201. // The data can be only 8 or 16 bit.
  1202. if (pdmWave->WaveformatEx.wBitsPerSample != 8 &&
  1203. pdmWave->WaveformatEx.wBitsPerSample != 16)
  1204. {
  1205. return DMUS_E_BADWAVE;
  1206. }
  1207. // Ensure that the index to the wave data is a legal value in the offset table.
  1208. if (pdmWave->ulWaveDataIdx >= pInfo->dwNumOffsetTableEntries)
  1209. {
  1210. return DMUS_E_BADWAVE;
  1211. }
  1212. // Create a wave object and parse the data into it.
  1213. CWave *pWave = new CWave;
  1214. if (pWave)
  1215. {
  1216. // We've already verified that the wave data index is a valid index, so go ahead
  1217. // and use the offset table to convert that into a valid DMUS_WAVEDATA structure pointer.
  1218. DMUS_WAVEDATA *pdmWaveData= (DMUS_WAVEDATA *)
  1219. pvOffsetTable[pdmWave->ulWaveDataIdx];
  1220. Trace(3,"Downloading wave %ld\n",pInfo->dwDLId);
  1221. // Now initialize the CWave structure.
  1222. pWave->m_dwID = pInfo->dwDLId;
  1223. pWave->m_pWaveMem = pInfo;
  1224. pWave->m_hUserData = NULL;
  1225. pWave->m_lpFreeHandle = NULL;
  1226. pWave->m_dwSampleLength = pdmWaveData->cbSize;
  1227. pWave->m_pnWave = (short *) &pdmWaveData->byData[0];
  1228. pWave->m_dwSampleRate = pdmWave->WaveformatEx.nSamplesPerSec;
  1229. // If the wave data is 8 bit, the data needs to be converted to
  1230. // two's complement representation.
  1231. if (pdmWave->WaveformatEx.wBitsPerSample == 8)
  1232. {
  1233. pWave->m_bSampleType = SFORMAT_8;
  1234. DWORD dwX;
  1235. char *pData = (char *) &pdmWaveData->byData[0];
  1236. for (dwX = 0; dwX < pWave->m_dwSampleLength; dwX++)
  1237. {
  1238. pData[dwX] -= (char) 128;
  1239. }
  1240. }
  1241. else if (pdmWave->WaveformatEx.wBitsPerSample == 16)
  1242. {
  1243. pWave->m_dwSampleLength >>= 1;
  1244. pWave->m_bSampleType = SFORMAT_16;
  1245. }
  1246. pWave->m_dwSampleLength++; // We always add one sample to the end for interpolation.
  1247. EnterCriticalSection(&m_CriticalSection);
  1248. // Place the wave in a hash table of wave lists to increase access speed.
  1249. m_WavePool[pWave->m_dwID % WAVE_HASH_SIZE].AddHead(pWave);
  1250. LeaveCriticalSection(&m_CriticalSection);
  1251. // Return the pointer to the internal CWave object as the handle. This will
  1252. // be used in a subsequant call to unload the wave object.
  1253. *phDownload = (HANDLE) pWave;
  1254. pWave->AddRef();
  1255. return S_OK;
  1256. }
  1257. return E_OUTOFMEMORY;
  1258. }
  1259. /*****************************************************************************
  1260. * CInstManager::Download()
  1261. *****************************************************************************
  1262. * Download to this instrument manager.
  1263. *
  1264. * This is the heart of the DLS download mechanism, and is called from CSynth::Download().
  1265. * It verifies the offset table and converts it into physical addresses. Then,
  1266. * depending on whether this is a wave or instrument download, it calls the
  1267. * appropriate method.
  1268. *
  1269. * The data is stored in a continuous chunk of memory,
  1270. * pointed to by pvData. However, at the head of the chunk are two data
  1271. * structures, which define the nature of the data to follow. These are
  1272. * the DMUS_DOWNLOADINFO and DMUS_OFFSETTABLE structures. DMUS_DOWNLOADINFO
  1273. * is a header which describes how to parse the data, including
  1274. * its size and intention (wave or instrument.) DMUS_OFFSETTABLE provides
  1275. * a set of indexes into the data segment which follows. All parsing through the data
  1276. * is managed through this table. Whenever a structure in the data references
  1277. * another structure, it describes it by an index into the offset table.
  1278. * The offset table then converts it into a physical address in the memory.
  1279. * This allows the synthesizer to do bounds checking on all
  1280. * references, making the implementation more robust. In kernel mode
  1281. * implementations, the driver can make its own private copy of the offset
  1282. * table, and so ensure that an application in user mode can not mess with
  1283. * its referencing and cause a crash. This implementation also makes a unique copy.
  1284. *
  1285. * Looking closer at DMUS_DOWNLOADINFO, DMUS_DOWNLOADINFO.dwDLType
  1286. * determines the type of data being downloaded. It is set to
  1287. * DMUS_DOWNLOADINFO_INSTRUMENT or DMUS_DOWNLOADINFO_INSTRUMENT2
  1288. * for an instrument, DMUS_DOWNLOADINFO_WAVE for a wave. As new data types emerge,
  1289. * identifiers will be allocated for them.
  1290. * DMUS_DOWNLOADINFO.dwDLId holds a unique 32 bit identifier for the object.
  1291. * This identifier is used to connect objects together. For example, it is used
  1292. * to connect waves to instruments.
  1293. * DMUS_DOWNLOADINFO.dwNumOffsetTableEntries describes the number of entries in
  1294. * the DMUS_OFFSETTABLE structure, which follows.
  1295. * Finally, DMUS_DOWNLOADINFO.cbSizeData states the total size of the
  1296. * memory chunk, which follows the offset table.
  1297. *
  1298. * Depending on the synthesizer implementation, it may decide to use the memory
  1299. * in the download chunk. This reduces memory allocation and freeing, since, if enough
  1300. * memory has been allocated to store a wave, that same memory can be used by
  1301. * the synthesizer to store it for playback. So, the synthesizer has the option
  1302. * of hanging on to the memory, returning its decision in the pbFree parameter.
  1303. * If it does keep the memory, then the caller must not free it. Later, the
  1304. * CSynth::Unload command has a callback mechanism to handle asynchronous
  1305. * freeing of the memory once the unload request has been made.
  1306. */
  1307. HRESULT CInstManager::Download(LPHANDLE phDownload, // Download handle, to be returned.
  1308. void * pvData, // Pointer to download data chunk.
  1309. LPBOOL pbFree) // Pointer to boolean whether data can
  1310. // be freed now or held until unload.
  1311. {
  1312. V_INAME(IDirectMusicSynth::Download);
  1313. V_BUFPTR_READ(pvData,sizeof(DMUS_DOWNLOADINFO));
  1314. HRESULT hr = DMUS_E_UNKNOWNDOWNLOAD;
  1315. // We need an array of pointers to reproduce the offset table, which is used to link to
  1316. // specific structures in the download chunk.
  1317. void ** ppvOffsetTable; // Array of pointers to chunks in data.
  1318. // At the head of the download chunk is the download header, in the form of a DMUS_DOWNLOADINFO structure.
  1319. DMUS_DOWNLOADINFO * pInfo = (DMUS_DOWNLOADINFO *) pvData;
  1320. // It is immediately followed by the offset table, so we cast a pointer to that.
  1321. DMUS_OFFSETTABLE* pOffsetTable = (DMUS_OFFSETTABLE *)(((BYTE*)pvData) + sizeof(DMUS_DOWNLOADINFO));
  1322. char *pcData = (char *) pvData;
  1323. V_BUFPTR_READ(pvData,pInfo->cbSize);
  1324. // Return the error code immediately.
  1325. if (0 == pInfo->dwNumOffsetTableEntries)
  1326. {
  1327. return hr;
  1328. }
  1329. // Create a copy of the offset table.
  1330. ppvOffsetTable = new void *[pInfo->dwNumOffsetTableEntries];
  1331. if (ppvOffsetTable) // Create the pointer array and validate.
  1332. {
  1333. // Each index in the offset table is an offset from the beginning of the download chunk to
  1334. // a position in the memory where a specific structure resides.
  1335. // Scan through the table and convert these offsets into actual memory
  1336. // addresses, and store these in the ppvOfsetTable array. These
  1337. // will be used by the parsing code to resolve indexes to actual
  1338. // memory addresses.
  1339. DWORD dwIndex;
  1340. for (dwIndex = 0; dwIndex < pInfo->dwNumOffsetTableEntries; dwIndex++)
  1341. {
  1342. // First, make sure the offset is not out of bounds.
  1343. if (pOffsetTable->ulOffsetTable[dwIndex] >= pInfo->cbSize)
  1344. {
  1345. delete [] ppvOffsetTable;
  1346. return DMUS_E_BADOFFSETTABLE; // Bad!
  1347. }
  1348. // Go ahead and calculate the actual memory address and store it.
  1349. ppvOffsetTable[dwIndex] = (void *) &pcData[pOffsetTable->ulOffsetTable[dwIndex]];
  1350. }
  1351. // Once the offset table is constructed, we can pass it to the appropriate parsing routine.
  1352. // There are three types of download chunks: DMUS_DOWNLOADINFO_INSTRUMENT,
  1353. // DMUS_DOWNLOADINFO_INSTRUMENT2, and DMUS_DOWNLOADINFO_WAVE.
  1354. // The two instrument formats exist because DMUS_DOWNLOADINFO_INSTRUMENT was changed to
  1355. // support a variable articulation to support DLS2 in the DX7 timeframe. In truth,
  1356. // only DMUS_DOWNLOADINFO_INSTRUMENT2 and DMUS_DOWNLOADINFO_WAVE need be supported,
  1357. // but we continue with DMUS_DOWNLOADINFO_INSTRUMENT support in this example.
  1358. // Depending on the type of download, we call the appropriate method, which then
  1359. // parses the data.
  1360. // To let dmusic understand that it does support the DMUS_DOWNLOADINFO_INSTRUMENT2,
  1361. // the synth must respond positively to the KsProperty Query GUID_DMUS_PROP_INSTRUMENT2,
  1362. // request (please see CUserModeSynth::KsProperty() for implementation details.)
  1363. if (pInfo->dwDLType == DMUS_DOWNLOADINFO_INSTRUMENT) // Instrument.
  1364. {
  1365. // Instrument does not need to keep the download chunk allocated, so indicate that
  1366. // the caller can free it.
  1367. *pbFree = TRUE;
  1368. // Call the download instrument method, indicating that this is a DX6 format download.
  1369. hr = DownloadInstrument(phDownload, pInfo, ppvOffsetTable, ppvOffsetTable[0],FALSE);
  1370. }
  1371. if (pInfo->dwDLType == DMUS_DOWNLOADINFO_INSTRUMENT2) // New instrument format.
  1372. {
  1373. *pbFree = TRUE;
  1374. // Call the download instrument method, indicating that this is a DX7 or up format download.
  1375. hr = DownloadInstrument(phDownload, pInfo, ppvOffsetTable, ppvOffsetTable[0],TRUE);
  1376. }
  1377. else if (pInfo->dwDLType == DMUS_DOWNLOADINFO_WAVE) // Wave.
  1378. {
  1379. // Wave does need to keep the download chunk allocated, because it includes the
  1380. // wave data buffer, which it will play directly out of, so indicate that
  1381. // the caller must not free it until it is unloaded.
  1382. *pbFree = FALSE;
  1383. hr = DownloadWave(phDownload, pInfo, ppvOffsetTable, ppvOffsetTable[0]);
  1384. }
  1385. delete [] ppvOffsetTable;
  1386. }
  1387. else
  1388. {
  1389. hr = E_OUTOFMEMORY;
  1390. }
  1391. return hr;
  1392. }
  1393. /*****************************************************************************
  1394. * CInstManager::Unload()
  1395. *****************************************************************************
  1396. * Unload the given previous download. Delete the instruments and waves.
  1397. *
  1398. * The unload method is called when it is unloading a previously downloaded
  1399. * instrument or wave chunk. This instructs the synthesizer to find the object that
  1400. * was downloaded (identified by the handle, hDownload, that was generated by the
  1401. * call to Download) and remove it.
  1402. *
  1403. * If the object was using the original download chunk, it needs to notify the caller
  1404. * when it is done using it so the memory can then be freed. This is not necessarily
  1405. * at the time of the download call because wave data may currently be in use by a
  1406. * performing note. So, a pointer to a callback function is also provided and the
  1407. * synthesizer must call this function at the time the memory is no longer in use.
  1408. */
  1409. HRESULT CInstManager::Unload(
  1410. HANDLE hDownload, // Handle of previously downloaded
  1411. // wave or instrument.
  1412. HRESULT ( CALLBACK *lpFreeHandle)(HANDLE,HANDLE), // Callback function for releasing
  1413. // downloaded memory
  1414. HANDLE hUserData) // Parameter to pass to callback,
  1415. // to indicate which download is freed.
  1416. {
  1417. DWORD dwIndex;
  1418. EnterCriticalSection(&m_CriticalSection);
  1419. // First, check to see if this is an instrument.
  1420. // We keep all the instruments in a hash table to speed up access.
  1421. for (dwIndex = 0; dwIndex < INSTRUMENT_HASH_SIZE; dwIndex++)
  1422. {
  1423. CInstrument *pInstrument = m_InstrumentList[dwIndex].GetHead();
  1424. for (;pInstrument != NULL; pInstrument = pInstrument->GetNext())
  1425. {
  1426. // If the instrument matches the download handle, remove it from the list
  1427. // and delete it. There is no need to callback for releasing the memory because
  1428. // the synthesizer did not hang on to the original downloaded instrument memory.
  1429. if (pInstrument == (CInstrument *) hDownload)
  1430. {
  1431. // To help debug, print the patch number of the unloaded instrument.
  1432. Trace(1,"Unloading instrument %lx\n",pInstrument->m_dwProgram);
  1433. m_InstrumentList[dwIndex].Remove(pInstrument);
  1434. delete pInstrument;
  1435. LeaveCriticalSection(&m_CriticalSection);
  1436. return S_OK;
  1437. }
  1438. }
  1439. }
  1440. // If it wasn't an instrument, try the wave list.
  1441. // Again, they are arranged in a hash table to increase access speed.
  1442. for (dwIndex = 0; dwIndex < WAVE_HASH_SIZE; dwIndex++)
  1443. {
  1444. CWave *pWave = m_WavePool[dwIndex].GetHead();
  1445. for (;pWave != NULL;pWave = pWave->GetNext())
  1446. {
  1447. // If the wave matches the download handle, remove it from the list.
  1448. // Also, store the callback function, lpFreeHandle, and associated instance
  1449. // parameter, hUserData, in the wave. Remove the wave from the wave pool, so
  1450. // it can no longer be connected with another instrument.
  1451. //
  1452. // When the last instance of a voice that is playing the wave finishes,
  1453. // lpFreeHandle will be called and the caller will be able to free the memory.
  1454. // Usually, the wave is not currently being played and this happens instantly.
  1455. if (pWave == (CWave *) hDownload)
  1456. {
  1457. Trace(3,"Unloading wave %ld\n",pWave->m_dwID);
  1458. m_WavePool[dwIndex].Remove(pWave);
  1459. pWave->m_hUserData = hUserData;
  1460. pWave->m_lpFreeHandle = lpFreeHandle;
  1461. pWave->Release();
  1462. LeaveCriticalSection(&m_CriticalSection);
  1463. return S_OK;
  1464. }
  1465. }
  1466. }
  1467. LeaveCriticalSection(&m_CriticalSection);
  1468. return E_FAIL;
  1469. }