midinote.cpp
上传用户:qiulin1960
上传日期:2013-10-16
资源大小:2844k
文件大小:9k
源码类别:

Windows CE

开发平台:

Windows_Unix

  1. // -----------------------------------------------------------------------------
  2. //
  3. //      THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  4. //      ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  5. //      THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  6. //      PARTICULAR PURPOSE.
  7. //      Copyright (c) 1995-2000 Microsoft Corporation.  All rights reserved.
  8. //
  9. // -----------------------------------------------------------------------------
  10. #include "wavemain.h"
  11. // x is the desired frequency
  12. #define FREQRATIO(x) (double(x)/double(SAMPLERATE))
  13. #define PITCH(x)    ( (UINT32 ) ( FREQRATIO(x) * double(1i64 << 32)) )
  14. #define EQUAL       (1.059463094359)
  15. #ifdef EUROPE
  16.     #define  A      (442.0)
  17. #else
  18.     #define  A      (440.0)
  19. #endif
  20. #define ASHARP      (A * EQUAL)
  21. #define B           (ASHARP * EQUAL)
  22. #define C           (B * EQUAL / 2.0)
  23. #define CSHARP      (C * EQUAL)
  24. #define DNOTE       (CSHARP * EQUAL)
  25. #define DSHARP      (DNOTE * EQUAL)
  26. #define E           (DSHARP * EQUAL)
  27. #define F           (E * EQUAL)
  28. #define FSHARP      (F * EQUAL)
  29. #define G           (FSHARP * EQUAL)
  30. #define GSHARP      (G * EQUAL)
  31. // pitch values, from middle c to octave above
  32. const UINT32 CMidiNote::PitchTable[ 12 ] =
  33. {
  34.     PITCH(C),
  35.     PITCH(CSHARP),
  36.     PITCH(DNOTE),
  37.     PITCH(DSHARP),
  38.     PITCH(E),
  39.     PITCH(F),
  40.     PITCH(FSHARP),
  41.     PITCH(G),
  42.     PITCH(GSHARP),
  43.     PITCH(A),
  44.     PITCH(ASHARP),
  45.     PITCH(B)
  46. };
  47. const INT16 CMidiNote::SineTable[0x101] =
  48. {
  49. 0,
  50. 804,
  51. 1607,
  52. 2410,
  53. 3211,
  54. 4011,
  55. 4807,
  56. 5601,
  57. 6392,
  58. 7179,
  59. 7961,
  60. 8739,
  61. 9511,
  62. 10278,
  63. 11038,
  64. 11792,
  65. 12539,
  66. 13278,
  67. 14009,
  68. 14732,
  69. 15446,
  70. 16150,
  71. 16845,
  72. 17530,
  73. 18204,
  74. 18867,
  75. 19519,
  76. 20159,
  77. 20787,
  78. 21402,
  79. 22004,
  80. 22594,
  81. 23169,
  82. 23731,
  83. 24278,
  84. 24811,
  85. 25329,
  86. 25831,
  87. 26318,
  88. 26789,
  89. 27244,
  90. 27683,
  91. 28105,
  92. 28510,
  93. 28897,
  94. 29268,
  95. 29621,
  96. 29955,
  97. 30272,
  98. 30571,
  99. 30851,
  100. 31113,
  101. 31356,
  102. 31580,
  103. 31785,
  104. 31970,
  105. 32137,
  106. 32284,
  107. 32412,
  108. 32520,
  109. 32609,
  110. 32678,
  111. 32727,
  112. 32757,
  113. 32767,
  114. 32757,
  115. 32727,
  116. 32678,
  117. 32609,
  118. 32520,
  119. 32412,
  120. 32284,
  121. 32137,
  122. 31970,
  123. 31785,
  124. 31580,
  125. 31356,
  126. 31113,
  127. 30851,
  128. 30571,
  129. 30272,
  130. 29955,
  131. 29621,
  132. 29268,
  133. 28897,
  134. 28510,
  135. 28105,
  136. 27683,
  137. 27244,
  138. 26789,
  139. 26318,
  140. 25831,
  141. 25329,
  142. 24811,
  143. 24278,
  144. 23731,
  145. 23169,
  146. 22594,
  147. 22004,
  148. 21402,
  149. 20787,
  150. 20159,
  151. 19519,
  152. 18867,
  153. 18204,
  154. 17530,
  155. 16845,
  156. 16150,
  157. 15446,
  158. 14732,
  159. 14009,
  160. 13278,
  161. 12539,
  162. 11792,
  163. 11038,
  164. 10278,
  165. 9511,
  166. 8739,
  167. 7961,
  168. 7179,
  169. 6392,
  170. 5601,
  171. 4807,
  172. 4011,
  173. 3211,
  174. 2410,
  175. 1607,
  176. 804,
  177. 0,
  178. -804,
  179. -1607,
  180. -2410,
  181. -3211,
  182. -4011,
  183. -4807,
  184. -5601,
  185. -6392,
  186. -7179,
  187. -7961,
  188. -8739,
  189. -9511,
  190. -10278,
  191. -11038,
  192. -11792,
  193. -12539,
  194. -13278,
  195. -14009,
  196. -14732,
  197. -15446,
  198. -16150,
  199. -16845,
  200. -17530,
  201. -18204,
  202. -18867,
  203. -19519,
  204. -20159,
  205. -20787,
  206. -21402,
  207. -22004,
  208. -22594,
  209. -23169,
  210. -23731,
  211. -24278,
  212. -24811,
  213. -25329,
  214. -25831,
  215. -26318,
  216. -26789,
  217. -27244,
  218. -27683,
  219. -28105,
  220. -28510,
  221. -28897,
  222. -29268,
  223. -29621,
  224. -29955,
  225. -30272,
  226. -30571,
  227. -30851,
  228. -31113,
  229. -31356,
  230. -31580,
  231. -31785,
  232. -31970,
  233. -32137,
  234. -32284,
  235. -32412,
  236. -32520,
  237. -32609,
  238. -32678,
  239. -32727,
  240. -32757,
  241. -32767,
  242. -32757,
  243. -32727,
  244. -32678,
  245. -32609,
  246. -32520,
  247. -32412,
  248. -32284,
  249. -32137,
  250. -31970,
  251. -31785,
  252. -31580,
  253. -31356,
  254. -31113,
  255. -30851,
  256. -30571,
  257. -30272,
  258. -29955,
  259. -29621,
  260. -29268,
  261. -28897,
  262. -28510,
  263. -28105,
  264. -27683,
  265. -27244,
  266. -26789,
  267. -26318,
  268. -25831,
  269. -25329,
  270. -24811,
  271. -24278,
  272. -23731,
  273. -23169,
  274. -22594,
  275. -22004,
  276. -21402,
  277. -20787,
  278. -20159,
  279. -19519,
  280. -18867,
  281. -18204,
  282. -17530,
  283. -16845,
  284. -16150,
  285. -15446,
  286. -14732,
  287. -14009,
  288. -13278,
  289. -12539,
  290. -11792,
  291. -11038,
  292. -10278,
  293. -9511,
  294. -8739,
  295. -7961,
  296. -7179,
  297. -6392,
  298. -5601,
  299. -4807,
  300. -4011,
  301. -3211,
  302. -2410,
  303. -1607,
  304. -804,
  305. 0   // Extra sample here saves 1 instruction in interpolation case
  306. };
  307. void CMidiNote::GainChange()
  308. {
  309.     m_fxpGain = m_pMidiStream->MapNoteGain(m_dwGain);
  310. }
  311. HRESULT CMidiNote::NoteOn(CMidiStream *pMidiStream, UINT32 Note, UINT32 Velocity, UINT32 Channel)
  312. {
  313.     // Save params
  314.     m_pMidiStream = pMidiStream;
  315.     m_Note     = Note;
  316.     m_Channel  = Channel;
  317.     SetVelocity(Velocity);
  318.     // Init pitch
  319.     m_Index = 0;
  320.     if (Channel==FREQCHANNEL)
  321.     {
  322.         m_IndexDelta = (Note * INVSAMPLERATE);
  323.     }
  324.     else
  325.     {
  326.         m_IndexDelta = PitchTable[ Note % 12 ] ;
  327.         // Adjust octave
  328.         int Octave = ((int)(Note/12)) - 5;
  329.         if (Octave>0)
  330.         {
  331.             m_IndexDelta <<= Octave;
  332.         }
  333.         else if (Octave<0)
  334.         {
  335.             m_IndexDelta >>= -Octave;
  336.         }
  337.     }
  338.     return S_OK;
  339. }
  340. HRESULT CMidiNote::NoteOff(UINT32 Velocity)
  341. {
  342.     // Calculate the number of samples left before we cross a 0 boundary at the middle or end of the table
  343.     DWORD SamplesLeft = ( ((0-m_Index)&0x7FFFFFFF) /m_IndexDelta) + 1;
  344.     m_dwBytesLeft = SamplesLeft * sizeof(HWSAMPLE) * OUTCHANNELS;
  345.     DEBUGMSG(1, (TEXT("CMidiNote::NoteOff, m_Index = 0x%x, m_IndexDelta = 0x%x, m_dwBytesLeft = %drn"),m_Index,m_IndexDelta,m_dwBytesLeft));
  346.     // m_pMidiStream->NoteDone(this);
  347.     return S_OK;
  348. }
  349. PBYTE CMidiNote::Render(PBYTE pBuffer, PBYTE pBufferEnd, PBYTE pBufferLast)
  350. {
  351.     DWORD BytesLeft = m_dwBytesLeft;
  352.     // Handle common case first
  353.     if (BytesLeft==(DWORD)-1)
  354.     {
  355.         // Call real inner loop
  356.         return Render2(pBuffer,pBufferEnd,pBufferLast);
  357.     }
  358.     DEBUGMSG(1, (TEXT("CMidiNote::Render, Note in release, m_dwBytesLeft = %drn"),BytesLeft));
  359.     DWORD BytesThisBuf = (pBufferEnd-pBuffer);
  360.     if (BytesLeft > BytesThisBuf)
  361.     {
  362.         // If we can't end during this buffer, just remember where we were
  363.         BytesLeft-=BytesThisBuf;
  364.     }
  365.     else
  366.     {
  367.         // Ok, we end during this buffer. Update pBufferEnd to force the renderer to stop on a 0 crossing.
  368.         pBufferEnd = pBuffer + BytesLeft;
  369.         BytesLeft=0;
  370.     }
  371.     m_dwBytesLeft = BytesLeft;
  372.     // Call real inner loop
  373.     pBufferLast = Render2(pBuffer,pBufferEnd,pBufferLast);
  374.     if (BytesLeft==0)
  375.     {
  376.         // Time to end the note.
  377.         DEBUGMSG(1, (TEXT("CMidiNote::Render, Last index after note done = 0x%xrn"),m_Index));
  378.         m_pMidiStream->NoteDone(this);
  379.     }
  380.     return pBufferLast;
  381. }
  382. // Inner loop of the note renderer.
  383. PBYTE CMidiNote::Render2(PBYTE pBuffer, PBYTE pBufferEnd, PBYTE pBufferLast)
  384. {
  385.     // Cache values so compiler won't worry about aliasing
  386.     UINT32 Index            = m_Index;
  387.     UINT32 IndexDelta       = m_IndexDelta;
  388.     const INT16 * pSineTable = SineTable;
  389.     LONG fxpGain = m_fxpGain;
  390.     while (pBuffer < pBufferEnd)
  391.     {
  392.         // Index is in 8.24 format, where the top 8 bits index into the sine table and
  393.         // the lower 24 bits represent the fraction of where we sit between two adjacent
  394.         // samples, which we can use if we're doing linear interpolation
  395.         // I chose 8.24 format so that wrap around at the top of the table happens
  396.         // automatically without the need to do any ANDing.
  397.         // Get an index into the sine table and look up the sample.
  398.         UINT32 TableIndex = Index>>24;
  399.         INT32 OutSamp0 = pSineTable[TableIndex];
  400. #if MIDI_OPTIMIZE_LINEAR_INTERPOLATE
  401.         // If we're doing linear interpolation, get the next sample also. Note that I don't
  402.         // need to worry about wrap around at the top of the table because the sine table has
  403.         // an extra value tacked onto the end to handle this special case.
  404.         INT32 NextSamp = pSineTable[TableIndex+1];
  405.         // Now do the interpolation, adjusting the index to be in 24.8 format and throwing away
  406.         // the integer part (e.g. interpolate 256 points between samples).
  407.         OutSamp0 += ( (NextSamp - OutSamp0) * ((Index>>16)&0x00FF) ) >> 8;
  408. #endif
  409.         // Increment the index to move to the next sample
  410.         // and keep within the valid range
  411.         Index += IndexDelta;
  412.         // Volume!
  413.         OutSamp0 = (OutSamp0 * fxpGain) >> VOLSHIFT;
  414. #if (OUTCHANNELS==2)
  415.         INT32 OutSamp1;
  416.         OutSamp1=OutSamp0;
  417.         if (pBuffer < pBufferLast)
  418.         {
  419.             OutSamp0 += ((HWSAMPLE *)pBuffer)[0];
  420.             OutSamp1 += ((HWSAMPLE *)pBuffer)[1];
  421. #if USE_MIX_SATURATE
  422.             // Handle saturation
  423.             if (OutSamp0>AUDIO_SAMPLE_MAX)
  424.             {
  425.                 OutSamp0=AUDIO_SAMPLE_MAX;
  426.             }
  427.             else if (OutSamp0<AUDIO_SAMPLE_MIN)
  428.             {
  429.                 OutSamp0=AUDIO_SAMPLE_MIN;
  430.             }
  431.             if (OutSamp1>AUDIO_SAMPLE_MAX)
  432.             {
  433.                 OutSamp1=AUDIO_SAMPLE_MAX;
  434.             }
  435.             else if (OutSamp1<AUDIO_SAMPLE_MIN)
  436.             {
  437.                 OutSamp1=AUDIO_SAMPLE_MIN;
  438.             }
  439. #endif
  440.         }
  441.         ((HWSAMPLE *)pBuffer)[0] = (HWSAMPLE)OutSamp0;
  442.         ((HWSAMPLE *)pBuffer)[1] = (HWSAMPLE)OutSamp1;
  443.         pBuffer += 2*sizeof(HWSAMPLE);
  444. #else
  445.         if (pBuffer<pBufferLast)
  446.         {
  447.             // Store/sum to the output buffer
  448.             OutSamp0 += *(HWSAMPLE *)pBuffer;
  449. #if USE_MIX_SATURATE
  450.             // Handle saturation
  451.             if (OutSamp0>AUDIO_SAMPLE_MAX)
  452.             {
  453.                 OutSamp0=AUDIO_SAMPLE_MAX;
  454.             }
  455.             else if (OutSamp0<AUDIO_SAMPLE_MIN)
  456.             {
  457.                 OutSamp0=AUDIO_SAMPLE_MIN;
  458.             }
  459. #endif
  460.         }
  461.         ((HWSAMPLE *)pBuffer)[0] = (HWSAMPLE)OutSamp0;
  462.         pBuffer+=sizeof(HWSAMPLE);
  463. #endif
  464.     }
  465.     // Save cached settings that might have changed in the inner loop
  466.     m_Index = Index;
  467.     return pBuffer;
  468. }