The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
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.

1131 lines
33KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-7 by Raw Material Software ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the
  7. GNU General Public License, as published by the Free Software Foundation;
  8. either version 2 of the License, or (at your option) any later version.
  9. JUCE is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with JUCE; if not, visit www.gnu.org/licenses or write to the
  15. Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  16. Boston, MA 02111-1307 USA
  17. ------------------------------------------------------------------------------
  18. If you'd like to release a closed-source product which uses JUCE, commercial
  19. licenses are also available: visit www.rawmaterialsoftware.com/juce for
  20. more information.
  21. ==============================================================================
  22. */
  23. #include "../../../juce_core/basics/juce_StandardHeader.h"
  24. BEGIN_JUCE_NAMESPACE
  25. #include "juce_MidiMessage.h"
  26. #include "../../../juce_core/containers/juce_MemoryBlock.h"
  27. //==============================================================================
  28. int MidiMessage::readVariableLengthVal (const uint8* data,
  29. int& numBytesUsed) throw()
  30. {
  31. numBytesUsed = 0;
  32. int v = 0;
  33. int i;
  34. do
  35. {
  36. i = (int) *data++;
  37. if (++numBytesUsed > 6)
  38. break;
  39. v = (v << 7) + (i & 0x7f);
  40. } while (i & 0x80);
  41. return v;
  42. }
  43. int MidiMessage::getMessageLengthFromFirstByte (const uint8 firstByte) throw()
  44. {
  45. // this method only works for valid starting bytes of a short midi message
  46. jassert (firstByte >= 0x80
  47. && firstByte != 0xff
  48. && firstByte != 0xf0
  49. && firstByte != 0xf7);
  50. static const char messageLengths[] =
  51. {
  52. 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  53. 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  54. 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  55. 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  56. 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  57. 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  58. 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  59. 1, 2, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
  60. };
  61. return messageLengths [firstByte & 0x7f];
  62. }
  63. //==============================================================================
  64. MidiMessage::MidiMessage (const uint8* const d,
  65. const int dataSize,
  66. const double t) throw()
  67. : timeStamp (t),
  68. message (0),
  69. size (dataSize)
  70. {
  71. jassert (dataSize > 0);
  72. if (dataSize <= 4)
  73. data = (uint8*) &message;
  74. else
  75. data = (uint8*) juce_malloc (dataSize);
  76. memcpy (data, d, dataSize);
  77. // check that the length matches the data..
  78. jassert (size > 3 || getMessageLengthFromFirstByte (*d) == size);
  79. }
  80. MidiMessage::MidiMessage (const int byte1,
  81. const double t) throw()
  82. : timeStamp (t),
  83. data ((uint8*) &message),
  84. size (1)
  85. {
  86. data[0] = (uint8) byte1;
  87. // check that the length matches the data..
  88. jassert (getMessageLengthFromFirstByte ((uint8) byte1) == 1);
  89. }
  90. MidiMessage::MidiMessage (const int byte1,
  91. const int byte2,
  92. const double t) throw()
  93. : timeStamp (t),
  94. data ((uint8*) &message),
  95. size (2)
  96. {
  97. data[0] = (uint8) byte1;
  98. data[1] = (uint8) byte2;
  99. // check that the length matches the data..
  100. jassert (getMessageLengthFromFirstByte ((uint8) byte1) == 2);
  101. }
  102. MidiMessage::MidiMessage (const int byte1,
  103. const int byte2,
  104. const int byte3,
  105. const double t) throw()
  106. : timeStamp (t),
  107. data ((uint8*) &message),
  108. size (3)
  109. {
  110. data[0] = (uint8) byte1;
  111. data[1] = (uint8) byte2;
  112. data[2] = (uint8) byte3;
  113. // check that the length matches the data..
  114. jassert (getMessageLengthFromFirstByte ((uint8) byte1) == 3);
  115. }
  116. MidiMessage::MidiMessage (const MidiMessage& other) throw()
  117. : timeStamp (other.timeStamp),
  118. message (other.message),
  119. size (other.size)
  120. {
  121. if (other.data != (uint8*) &other.message)
  122. {
  123. data = (uint8*) juce_malloc (size);
  124. memcpy (data, other.data, size);
  125. }
  126. else
  127. {
  128. data = (uint8*) &message;
  129. }
  130. }
  131. MidiMessage::MidiMessage (const MidiMessage& other,
  132. const double newTimeStamp) throw()
  133. : timeStamp (newTimeStamp),
  134. message (other.message),
  135. size (other.size)
  136. {
  137. if (other.data != (uint8*) &other.message)
  138. {
  139. data = (uint8*) juce_malloc (size);
  140. memcpy (data, other.data, size);
  141. }
  142. else
  143. {
  144. data = (uint8*) &message;
  145. }
  146. }
  147. MidiMessage::MidiMessage (const uint8* src,
  148. int sz,
  149. int& numBytesUsed,
  150. const uint8 lastStatusByte,
  151. double t) throw()
  152. : timeStamp (t),
  153. data ((uint8*) &message),
  154. message (0)
  155. {
  156. unsigned int byte = (unsigned int) *src;
  157. if (byte < 0x80)
  158. {
  159. byte = (unsigned int) (uint8) lastStatusByte;
  160. numBytesUsed = -1;
  161. }
  162. else
  163. {
  164. numBytesUsed = 0;
  165. --sz;
  166. ++src;
  167. }
  168. if (byte >= 0x80)
  169. {
  170. if (byte == 0xf0)
  171. {
  172. const uint8* d = (const uint8*) src;
  173. while (d < src + sz)
  174. {
  175. if (*d >= 0x80) // stop if we hit a status byte, and don't include it in this message
  176. {
  177. if (*d == 0xf7) // include an 0xf7 if we hit one
  178. ++d;
  179. break;
  180. }
  181. ++d;
  182. }
  183. size = 1 + (int) (d - src);
  184. data = (uint8*) juce_malloc (size);
  185. *data = (uint8) byte;
  186. memcpy (data + 1, src, size - 1);
  187. }
  188. else if (byte == 0xff)
  189. {
  190. int n;
  191. const int bytesLeft = readVariableLengthVal (src + 1, n);
  192. size = jmin (sz + 1, n + 2 + bytesLeft);
  193. data = (uint8*) juce_malloc (size);
  194. *data = (uint8) byte;
  195. memcpy (data + 1, src, size - 1);
  196. }
  197. else
  198. {
  199. size = getMessageLengthFromFirstByte ((uint8) byte);
  200. *data = (uint8) byte;
  201. if (size > 1)
  202. {
  203. data[1] = src[0];
  204. if (size > 2)
  205. data[2] = src[1];
  206. }
  207. }
  208. numBytesUsed += size;
  209. }
  210. else
  211. {
  212. message = 0;
  213. size = 0;
  214. }
  215. }
  216. const MidiMessage& MidiMessage::operator= (const MidiMessage& other) throw()
  217. {
  218. if (this == &other)
  219. return *this;
  220. timeStamp = other.timeStamp;
  221. size = other.size;
  222. message = other.message;
  223. if (data != (uint8*) &message)
  224. juce_free (data);
  225. if (other.data != (uint8*) &other.message)
  226. {
  227. data = (uint8*) juce_malloc (size);
  228. memcpy (data, other.data, size);
  229. }
  230. else
  231. {
  232. data = (uint8*) &message;
  233. }
  234. return *this;
  235. }
  236. MidiMessage::~MidiMessage() throw()
  237. {
  238. if (data != (uint8*) &message)
  239. juce_free (data);
  240. }
  241. int MidiMessage::getChannel() const throw()
  242. {
  243. if ((data[0] & 0xf0) != 0xf0)
  244. return (data[0] & 0xf) + 1;
  245. else
  246. return 0;
  247. }
  248. bool MidiMessage::isForChannel (const int channel) const throw()
  249. {
  250. return ((data[0] & 0xf) == channel - 1)
  251. && ((data[0] & 0xf0) != 0xf0);
  252. }
  253. void MidiMessage::setChannel (const int channel) throw()
  254. {
  255. if ((data[0] & 0xf0) != (uint8) 0xf0)
  256. data[0] = (uint8) ((data[0] & (uint8)0xf0)
  257. | (uint8)(channel - 1));
  258. }
  259. bool MidiMessage::isNoteOn() const throw()
  260. {
  261. return ((data[0] & 0xf0) == 0x90)
  262. && (data[2] != 0);
  263. }
  264. bool MidiMessage::isNoteOff() const throw()
  265. {
  266. return ((data[0] & 0xf0) == 0x80)
  267. || ((data[2] == 0) && ((data[0] & 0xf0) == 0x90));
  268. }
  269. bool MidiMessage::isNoteOnOrOff() const throw()
  270. {
  271. const int d = data[0] & 0xf0;
  272. return (d == 0x90) || (d == 0x80);
  273. }
  274. int MidiMessage::getNoteNumber() const throw()
  275. {
  276. return data[1];
  277. }
  278. void MidiMessage::setNoteNumber (const int newNoteNumber) throw()
  279. {
  280. if (isNoteOnOrOff())
  281. data[1] = (uint8) jlimit (0, 127, newNoteNumber);
  282. }
  283. uint8 MidiMessage::getVelocity() const throw()
  284. {
  285. if (isNoteOnOrOff())
  286. return data[2];
  287. else
  288. return 0;
  289. }
  290. float MidiMessage::getFloatVelocity() const throw()
  291. {
  292. return getVelocity() * (1.0f / 127.0f);
  293. }
  294. void MidiMessage::setVelocity (const float newVelocity) throw()
  295. {
  296. if (isNoteOnOrOff())
  297. data[2] = (uint8) jlimit (0, 0x7f, roundFloatToInt (newVelocity * 127.0f));
  298. }
  299. void MidiMessage::multiplyVelocity (const float scaleFactor) throw()
  300. {
  301. if (isNoteOnOrOff())
  302. data[2] = (uint8) jlimit (0, 0x7f, roundFloatToInt (scaleFactor * data[2]));
  303. }
  304. bool MidiMessage::isAftertouch() const throw()
  305. {
  306. return (data[0] & 0xf0) == 0xa0;
  307. }
  308. int MidiMessage::getAfterTouchValue() const throw()
  309. {
  310. return data[2];
  311. }
  312. const MidiMessage MidiMessage::aftertouchChange (const int channel,
  313. const int noteNum,
  314. const int aftertouchValue) throw()
  315. {
  316. jassert (channel > 0 && channel <= 16);
  317. jassert (noteNum >= 0 && noteNum <= 127);
  318. jassert (aftertouchValue >= 0 && aftertouchValue <= 127);
  319. return MidiMessage (0xa0 | jlimit (0, 15, channel - 1),
  320. noteNum & 0x7f,
  321. aftertouchValue & 0x7f);
  322. }
  323. bool MidiMessage::isChannelPressure() const throw()
  324. {
  325. return (data[0] & 0xf0) == 0xd0;
  326. }
  327. int MidiMessage::getChannelPressureValue() const throw()
  328. {
  329. jassert (isChannelPressure());
  330. return data[1];
  331. }
  332. const MidiMessage MidiMessage::channelPressureChange (const int channel,
  333. const int pressure) throw()
  334. {
  335. jassert (channel > 0 && channel <= 16);
  336. jassert (pressure >= 0 && pressure <= 127);
  337. return MidiMessage (0xd0 | jlimit (0, 15, channel - 1),
  338. pressure & 0x7f);
  339. }
  340. bool MidiMessage::isProgramChange() const throw()
  341. {
  342. return (data[0] & 0xf0) == 0xc0;
  343. }
  344. int MidiMessage::getProgramChangeNumber() const throw()
  345. {
  346. return data[1];
  347. }
  348. const MidiMessage MidiMessage::programChange (const int channel,
  349. const int programNumber) throw()
  350. {
  351. jassert (channel > 0 && channel <= 16);
  352. return MidiMessage (0xc0 | jlimit (0, 15, channel - 1),
  353. programNumber & 0x7f);
  354. }
  355. bool MidiMessage::isPitchWheel() const throw()
  356. {
  357. return (data[0] & 0xf0) == 0xe0;
  358. }
  359. int MidiMessage::getPitchWheelValue() const throw()
  360. {
  361. return data[1] | (data[2] << 7);
  362. }
  363. const MidiMessage MidiMessage::pitchWheel (const int channel,
  364. const int position) throw()
  365. {
  366. jassert (channel > 0 && channel <= 16);
  367. jassert (position >= 0 && position <= 0x3fff);
  368. return MidiMessage (0xe0 | jlimit (0, 15, channel - 1),
  369. position & 127,
  370. (position >> 7) & 127);
  371. }
  372. bool MidiMessage::isController() const throw()
  373. {
  374. return (data[0] & 0xf0) == 0xb0;
  375. }
  376. int MidiMessage::getControllerNumber() const throw()
  377. {
  378. jassert (isController());
  379. return data[1];
  380. }
  381. int MidiMessage::getControllerValue() const throw()
  382. {
  383. jassert (isController());
  384. return data[2];
  385. }
  386. const MidiMessage MidiMessage::controllerEvent (const int channel,
  387. const int controllerType,
  388. const int value) throw()
  389. {
  390. jassert (channel > 0 && channel <= 16);
  391. return MidiMessage (0xb0 | jlimit (0, 15, channel - 1),
  392. controllerType & 127,
  393. value & 127);
  394. }
  395. const MidiMessage MidiMessage::noteOn (const int channel,
  396. const int noteNumber,
  397. const float velocity) throw()
  398. {
  399. return noteOn (channel, noteNumber, (uint8)(velocity * 127.0f));
  400. }
  401. const MidiMessage MidiMessage::noteOn (const int channel,
  402. const int noteNumber,
  403. const uint8 velocity) throw()
  404. {
  405. jassert (channel > 0 && channel <= 16);
  406. jassert (noteNumber >= 0 && noteNumber <= 127);
  407. return MidiMessage (0x90 | jlimit (0, 15, channel - 1),
  408. noteNumber & 127,
  409. jlimit (0, 127, roundFloatToInt (velocity)));
  410. }
  411. const MidiMessage MidiMessage::noteOff (const int channel,
  412. const int noteNumber) throw()
  413. {
  414. jassert (channel > 0 && channel <= 16);
  415. jassert (noteNumber >= 0 && noteNumber <= 127);
  416. return MidiMessage (0x80 | jlimit (0, 15, channel - 1), noteNumber & 127, 0);
  417. }
  418. const MidiMessage MidiMessage::allNotesOff (const int channel) throw()
  419. {
  420. jassert (channel > 0 && channel <= 16);
  421. return controllerEvent (channel, 123, 0);
  422. }
  423. bool MidiMessage::isAllNotesOff() const throw()
  424. {
  425. return (data[0] & 0xf0) == 0xb0
  426. && data[1] == 123;
  427. }
  428. const MidiMessage MidiMessage::allSoundOff (const int channel) throw()
  429. {
  430. return controllerEvent (channel, 120, 0);
  431. }
  432. bool MidiMessage::isAllSoundOff() const throw()
  433. {
  434. return (data[0] & 0xf0) == 0xb0
  435. && data[1] == 120;
  436. }
  437. const MidiMessage MidiMessage::allControllersOff (const int channel) throw()
  438. {
  439. return controllerEvent (channel, 121, 0);
  440. }
  441. const MidiMessage MidiMessage::masterVolume (const float volume) throw()
  442. {
  443. const int vol = jlimit (0, 0x3fff, roundFloatToInt (volume * 0x4000));
  444. uint8 buf[8];
  445. buf[0] = 0xf0;
  446. buf[1] = 0x7f;
  447. buf[2] = 0x7f;
  448. buf[3] = 0x04;
  449. buf[4] = 0x01;
  450. buf[5] = (uint8) (vol & 0x7f);
  451. buf[6] = (uint8) (vol >> 7);
  452. buf[7] = 0xf7;
  453. return MidiMessage (buf, 8);
  454. }
  455. //==============================================================================
  456. bool MidiMessage::isSysEx() const throw()
  457. {
  458. return *data == 0xf0;
  459. }
  460. const MidiMessage MidiMessage::createSysExMessage (const uint8* sysexData,
  461. const int dataSize) throw()
  462. {
  463. MemoryBlock mm (dataSize + 2);
  464. uint8* const m = (uint8*) mm.getData();
  465. m[0] = 0xf0;
  466. memcpy (m + 1, sysexData, dataSize);
  467. m[dataSize + 1] = 0xf7;
  468. return MidiMessage (m, dataSize + 2);
  469. }
  470. const uint8* MidiMessage::getSysExData() const throw()
  471. {
  472. return (isSysEx()) ? getRawData() + 1
  473. : 0;
  474. }
  475. int MidiMessage::getSysExDataSize() const throw()
  476. {
  477. return (isSysEx()) ? size - 2
  478. : 0;
  479. }
  480. bool MidiMessage::isMetaEvent() const throw()
  481. {
  482. return *data == 0xff;
  483. }
  484. bool MidiMessage::isActiveSense() const throw()
  485. {
  486. return *data == 0xfe;
  487. }
  488. //==============================================================================
  489. int MidiMessage::getMetaEventType() const throw()
  490. {
  491. if (*data != 0xff)
  492. return -1;
  493. else
  494. return data[1];
  495. }
  496. int MidiMessage::getMetaEventLength() const throw()
  497. {
  498. if (*data == 0xff)
  499. {
  500. int n;
  501. return jmin (size - 2, readVariableLengthVal (data + 2, n));
  502. }
  503. return 0;
  504. }
  505. const uint8* MidiMessage::getMetaEventData() const throw()
  506. {
  507. int n;
  508. const uint8* d = data + 2;
  509. readVariableLengthVal (d, n);
  510. return d + n;
  511. }
  512. bool MidiMessage::isTrackMetaEvent() const throw()
  513. {
  514. return getMetaEventType() == 0;
  515. }
  516. bool MidiMessage::isEndOfTrackMetaEvent() const throw()
  517. {
  518. return getMetaEventType() == 47;
  519. }
  520. bool MidiMessage::isTextMetaEvent() const throw()
  521. {
  522. const int t = getMetaEventType();
  523. return t > 0 && t < 16;
  524. }
  525. const String MidiMessage::getTextFromTextMetaEvent() const throw()
  526. {
  527. return String ((const char*) getMetaEventData(),
  528. getMetaEventLength());
  529. }
  530. bool MidiMessage::isTrackNameEvent() const throw()
  531. {
  532. return (data[1] == 3)
  533. && (*data == 0xff);
  534. }
  535. bool MidiMessage::isTempoMetaEvent() const throw()
  536. {
  537. return (data[1] == 81)
  538. && (*data == 0xff);
  539. }
  540. bool MidiMessage::isMidiChannelMetaEvent() const throw()
  541. {
  542. return (data[1] == 0x20)
  543. && (*data == 0xff)
  544. && (data[2] == 1);
  545. }
  546. int MidiMessage::getMidiChannelMetaEventChannel() const throw()
  547. {
  548. return data[3] + 1;
  549. }
  550. double MidiMessage::getTempoSecondsPerQuarterNote() const throw()
  551. {
  552. if (! isTempoMetaEvent())
  553. return 0.0;
  554. const uint8* const d = getMetaEventData();
  555. return (((unsigned int) d[0] << 16)
  556. | ((unsigned int) d[1] << 8)
  557. | d[2])
  558. / 1000000.0;
  559. }
  560. double MidiMessage::getTempoMetaEventTickLength (const short timeFormat) const throw()
  561. {
  562. if (timeFormat > 0)
  563. {
  564. if (! isTempoMetaEvent())
  565. return 0.5 / timeFormat;
  566. return getTempoSecondsPerQuarterNote() / timeFormat;
  567. }
  568. else
  569. {
  570. const int frameCode = (-timeFormat) >> 8;
  571. double framesPerSecond;
  572. switch (frameCode)
  573. {
  574. case 24: framesPerSecond = 24.0; break;
  575. case 25: framesPerSecond = 25.0; break;
  576. case 29: framesPerSecond = 29.97; break;
  577. case 30: framesPerSecond = 30.0; break;
  578. default: framesPerSecond = 30.0; break;
  579. }
  580. return (1.0 / framesPerSecond) / (timeFormat & 0xff);
  581. }
  582. }
  583. const MidiMessage MidiMessage::tempoMetaEvent (int microsecondsPerQuarterNote) throw()
  584. {
  585. uint8 d[8];
  586. d[0] = 0xff;
  587. d[1] = 81;
  588. d[2] = 3;
  589. d[3] = (uint8) (microsecondsPerQuarterNote >> 16);
  590. d[4] = (uint8) ((microsecondsPerQuarterNote >> 8) & 0xff);
  591. d[5] = (uint8) (microsecondsPerQuarterNote & 0xff);
  592. return MidiMessage (d, 6, 0.0);
  593. }
  594. bool MidiMessage::isTimeSignatureMetaEvent() const throw()
  595. {
  596. return (data[1] == 0x58)
  597. && (*data == (uint8) 0xff);
  598. }
  599. void MidiMessage::getTimeSignatureInfo (int& numerator,
  600. int& denominator) const throw()
  601. {
  602. if (isTimeSignatureMetaEvent())
  603. {
  604. const uint8* const d = getMetaEventData();
  605. numerator = d[0];
  606. denominator = 1 << d[1];
  607. }
  608. else
  609. {
  610. numerator = 4;
  611. denominator = 4;
  612. }
  613. }
  614. const MidiMessage MidiMessage::timeSignatureMetaEvent (const int numerator,
  615. const int denominator) throw()
  616. {
  617. uint8 d[8];
  618. d[0] = 0xff;
  619. d[1] = 0x58;
  620. d[2] = 0x04;
  621. d[3] = (uint8) numerator;
  622. int n = 1;
  623. int powerOfTwo = 0;
  624. while (n < denominator)
  625. {
  626. n <<= 1;
  627. ++powerOfTwo;
  628. }
  629. d[4] = (uint8) powerOfTwo;
  630. d[5] = 0x01;
  631. d[6] = 96;
  632. return MidiMessage (d, 7, 0.0);
  633. }
  634. const MidiMessage MidiMessage::midiChannelMetaEvent (const int channel) throw()
  635. {
  636. uint8 d[8];
  637. d[0] = 0xff;
  638. d[1] = 0x20;
  639. d[2] = 0x01;
  640. d[3] = (uint8) jlimit (0, 0xff, channel - 1);
  641. return MidiMessage (d, 4, 0.0);
  642. }
  643. bool MidiMessage::isKeySignatureMetaEvent() const throw()
  644. {
  645. return getMetaEventType() == 89;
  646. }
  647. int MidiMessage::getKeySignatureNumberOfSharpsOrFlats() const throw()
  648. {
  649. return (int)(*getMetaEventData());
  650. }
  651. const MidiMessage MidiMessage::endOfTrack() throw()
  652. {
  653. return MidiMessage (0xff, 0x2f, 0, 0.0);
  654. }
  655. //==============================================================================
  656. bool MidiMessage::isSongPositionPointer() const throw()
  657. {
  658. return *data == 0xf2;
  659. }
  660. int MidiMessage::getSongPositionPointerMidiBeat() const throw()
  661. {
  662. return data[1] | (data[2] << 7);
  663. }
  664. const MidiMessage MidiMessage::songPositionPointer (const int positionInMidiBeats) throw()
  665. {
  666. return MidiMessage (0xf2,
  667. positionInMidiBeats & 127,
  668. (positionInMidiBeats >> 7) & 127);
  669. }
  670. bool MidiMessage::isMidiStart() const throw()
  671. {
  672. return *data == 0xfa;
  673. }
  674. const MidiMessage MidiMessage::midiStart() throw()
  675. {
  676. return MidiMessage (0xfa);
  677. }
  678. bool MidiMessage::isMidiContinue() const throw()
  679. {
  680. return *data == 0xfb;
  681. }
  682. const MidiMessage MidiMessage::midiContinue() throw()
  683. {
  684. return MidiMessage (0xfb);
  685. }
  686. bool MidiMessage::isMidiStop() const throw()
  687. {
  688. return *data == 0xfc;
  689. }
  690. const MidiMessage MidiMessage::midiStop() throw()
  691. {
  692. return MidiMessage (0xfc);
  693. }
  694. bool MidiMessage::isMidiClock() const throw()
  695. {
  696. return *data == 0xf8;
  697. }
  698. const MidiMessage MidiMessage::midiClock() throw()
  699. {
  700. return MidiMessage (0xf8);
  701. }
  702. bool MidiMessage::isQuarterFrame() const throw()
  703. {
  704. return *data == 0xf1;
  705. }
  706. int MidiMessage::getQuarterFrameSequenceNumber() const throw()
  707. {
  708. return ((int) data[1]) >> 4;
  709. }
  710. int MidiMessage::getQuarterFrameValue() const throw()
  711. {
  712. return ((int) data[1]) & 0x0f;
  713. }
  714. const MidiMessage MidiMessage::quarterFrame (const int sequenceNumber,
  715. const int value) throw()
  716. {
  717. return MidiMessage (0xf1, (sequenceNumber << 4) | value);
  718. }
  719. bool MidiMessage::isFullFrame() const throw()
  720. {
  721. return data[0] == 0xf0
  722. && data[1] == 0x7f
  723. && size >= 10
  724. && data[3] == 0x01
  725. && data[4] == 0x01;
  726. }
  727. void MidiMessage::getFullFrameParameters (int& hours,
  728. int& minutes,
  729. int& seconds,
  730. int& frames,
  731. MidiMessage::SmpteTimecodeType& timecodeType) const throw()
  732. {
  733. jassert (isFullFrame());
  734. timecodeType = (SmpteTimecodeType) (data[5] >> 5);
  735. hours = data[5] & 0x1f;
  736. minutes = data[6];
  737. seconds = data[7];
  738. frames = data[8];
  739. }
  740. const MidiMessage MidiMessage::fullFrame (const int hours,
  741. const int minutes,
  742. const int seconds,
  743. const int frames,
  744. MidiMessage::SmpteTimecodeType timecodeType)
  745. {
  746. uint8 d[10];
  747. d[0] = 0xf0;
  748. d[1] = 0x7f;
  749. d[2] = 0x7f;
  750. d[3] = 0x01;
  751. d[4] = 0x01;
  752. d[5] = (uint8) ((hours & 0x01f) | (timecodeType << 5));
  753. d[6] = (uint8) minutes;
  754. d[7] = (uint8) seconds;
  755. d[8] = (uint8) frames;
  756. d[9] = 0xf7;
  757. return MidiMessage (d, 10, 0.0);
  758. }
  759. bool MidiMessage::isMidiMachineControlMessage() const throw()
  760. {
  761. return data[0] == 0xf0
  762. && data[1] == 0x7f
  763. && data[3] == 0x06
  764. && size > 5;
  765. }
  766. MidiMessage::MidiMachineControlCommand MidiMessage::getMidiMachineControlCommand() const throw()
  767. {
  768. jassert (isMidiMachineControlMessage());
  769. return (MidiMachineControlCommand) data[4];
  770. }
  771. const MidiMessage MidiMessage::midiMachineControlCommand (MidiMessage::MidiMachineControlCommand command)
  772. {
  773. uint8 d[6];
  774. d[0] = 0xf0;
  775. d[1] = 0x7f;
  776. d[2] = 0x00;
  777. d[3] = 0x06;
  778. d[4] = (uint8) command;
  779. d[5] = 0xf7;
  780. return MidiMessage (d, 6, 0.0);
  781. }
  782. //==============================================================================
  783. bool MidiMessage::isMidiMachineControlGoto (int& hours,
  784. int& minutes,
  785. int& seconds,
  786. int& frames) const throw()
  787. {
  788. if (size >= 12
  789. && data[0] == 0xf0
  790. && data[1] == 0x7f
  791. && data[3] == 0x06
  792. && data[4] == 0x44
  793. && data[5] == 0x06
  794. && data[6] == 0x01)
  795. {
  796. hours = data[7] % 24; // (that some machines send out hours > 24)
  797. minutes = data[8];
  798. seconds = data[9];
  799. frames = data[10];
  800. return true;
  801. }
  802. return false;
  803. }
  804. const MidiMessage MidiMessage::midiMachineControlGoto (int hours,
  805. int minutes,
  806. int seconds,
  807. int frames)
  808. {
  809. uint8 d[12];
  810. d[0] = 0xf0;
  811. d[1] = 0x7f;
  812. d[2] = 0x00;
  813. d[3] = 0x06;
  814. d[4] = 0x44;
  815. d[5] = 0x06;
  816. d[6] = 0x01;
  817. d[7] = (uint8) hours;
  818. d[8] = (uint8) minutes;
  819. d[9] = (uint8) seconds;
  820. d[10] = (uint8) frames;
  821. d[11] = 0xf7;
  822. return MidiMessage (d, 12, 0.0);
  823. }
  824. //==============================================================================
  825. const String MidiMessage::getMidiNoteName (int note,
  826. bool useSharps,
  827. bool includeOctaveNumber,
  828. int octaveNumForMiddleC) throw()
  829. {
  830. static const char* const sharpNoteNames[] = { "C", "C#", "D", "D#", "E",
  831. "F", "F#", "G", "G#", "A",
  832. "A#", "B" };
  833. static const char* const flatNoteNames[] = { "C", "Db", "D", "Eb", "E",
  834. "F", "Gb", "G", "Ab", "A",
  835. "Bb", "B" };
  836. if (note >= 0 && note < 128)
  837. {
  838. const String s ((useSharps) ? sharpNoteNames [note % 12]
  839. : flatNoteNames [note % 12]);
  840. if (includeOctaveNumber)
  841. return s + String (note / 12 + (octaveNumForMiddleC - 5));
  842. else
  843. return s;
  844. }
  845. return String::empty;
  846. }
  847. const double MidiMessage::getMidiNoteInHertz (int noteNumber) throw()
  848. {
  849. noteNumber -= 12 * 6 + 9; // now 0 = A440
  850. return 440.0 * pow (2.0, noteNumber / 12.0);
  851. }
  852. const String MidiMessage::getGMInstrumentName (int n) throw()
  853. {
  854. const char *names[] =
  855. {
  856. "Acoustic Grand Piano", "Bright Acoustic Piano", "Electric Grand Piano", "Honky-tonk Piano",
  857. "Electric Piano 1", "Electric Piano 2", "Harpsichord", "Clavinet", "Celesta", "Glockenspiel",
  858. "Music Box", "Vibraphone", "Marimba", "Xylophone", "Tubular Bells", "Dulcimer", "Drawbar Organ",
  859. "Percussive Organ", "Rock Organ", "Church Organ", "Reed Organ", "Accordion", "Harmonica",
  860. "Tango Accordion", "Acoustic Guitar (nylon)", "Acoustic Guitar (steel)", "Electric Guitar (jazz)",
  861. "Electric Guitar (clean)", "Electric Guitar (mute)", "Overdriven Guitar", "Distortion Guitar",
  862. "Guitar Harmonics", "Acoustic Bass", "Electric Bass (finger)", "Electric Bass (pick)",
  863. "Fretless Bass", "Slap Bass 1", "Slap Bass 2", "Synth Bass 1", "Synth Bass 2", "Violin",
  864. "Viola", "Cello", "Contrabass", "Tremolo Strings", "Pizzicato Strings", "Orchestral Harp",
  865. "Timpani", "String Ensemble 1", "String Ensemble 2", "SynthStrings 1", "SynthStrings 2",
  866. "Choir Aahs", "Voice Oohs", "Synth Voice", "Orchestra Hit", "Trumpet", "Trombone", "Tuba",
  867. "Muted Trumpet", "French Horn", "Brass Section", "SynthBrass 1", "SynthBrass 2", "Soprano Sax",
  868. "Alto Sax", "Tenor Sax", "Baritone Sax", "Oboe", "English Horn", "Bassoon", "Clarinet",
  869. "Piccolo", "Flute", "Recorder", "Pan Flute", "Blown Bottle", "Shakuhachi", "Whistle",
  870. "Ocarina", "Lead 1 (square)", "Lead 2 (sawtooth)", "Lead 3 (calliope)", "Lead 4 (chiff)",
  871. "Lead 5 (charang)", "Lead 6 (voice)", "Lead 7 (fifths)", "Lead 8 (bass+lead)", "Pad 1 (new age)",
  872. "Pad 2 (warm)", "Pad 3 (polysynth)", "Pad 4 (choir)", "Pad 5 (bowed)", "Pad 6 (metallic)",
  873. "Pad 7 (halo)", "Pad 8 (sweep)", "FX 1 (rain)", "FX 2 (soundtrack)", "FX 3 (crystal)",
  874. "FX 4 (atmosphere)", "FX 5 (brightness)", "FX 6 (goblins)", "FX 7 (echoes)", "FX 8 (sci-fi)",
  875. "Sitar", "Banjo", "Shamisen", "Koto", "Kalimba", "Bag pipe", "Fiddle", "Shanai", "Tinkle Bell",
  876. "Agogo", "Steel Drums", "Woodblock", "Taiko Drum", "Melodic Tom", "Synth Drum", "Reverse Cymbal",
  877. "Guitar Fret Noise", "Breath Noise", "Seashore", "Bird Tweet", "Telephone Ring", "Helicopter",
  878. "Applause", "Gunshot"
  879. };
  880. return (n >= 0 && n < 128) ? names[n]
  881. : (const char*)0;
  882. }
  883. const String MidiMessage::getGMInstrumentBankName (int n) throw()
  884. {
  885. const char* names[] =
  886. {
  887. "Piano", "Chromatic Percussion", "Organ", "Guitar",
  888. "Bass", "Strings", "Ensemble", "Brass",
  889. "Reed", "Pipe", "Synth Lead", "Synth Pad",
  890. "Synth Effects", "Ethnic", "Percussive", "Sound Effects"
  891. };
  892. return (n >= 0 && n <= 15) ? names[n]
  893. : (const char*)0;
  894. }
  895. const String MidiMessage::getRhythmInstrumentName (int n) throw()
  896. {
  897. const char* names[] =
  898. {
  899. "Acoustic Bass Drum", "Bass Drum 1", "Side Stick", "Acoustic Snare",
  900. "Hand Clap", "Electric Snare", "Low Floor Tom", "Closed Hi-Hat", "High Floor Tom",
  901. "Pedal Hi-Hat", "Low Tom", "Open Hi-Hat", "Low-Mid Tom", "Hi-Mid Tom", "Crash Cymbal 1",
  902. "High Tom", "Ride Cymbal 1", "Chinese Cymbal", "Ride Bell", "Tambourine", "Splash Cymbal",
  903. "Cowbell", "Crash Cymbal 2", "Vibraslap", "Ride Cymbal 2", "Hi Bongo", "Low Bongo",
  904. "Mute Hi Conga", "Open Hi Conga", "Low Conga", "High Timbale", "Low Timbale", "High Agogo",
  905. "Low Agogo", "Cabasa", "Maracas", "Short Whistle", "Long Whistle", "Short Guiro",
  906. "Long Guiro", "Claves", "Hi Wood Block", "Low Wood Block", "Mute Cuica", "Open Cuica",
  907. "Mute Triangle", "Open Triangle"
  908. };
  909. return (n >= 35 && n <= 81) ? names [n - 35]
  910. : (const char*)0;
  911. }
  912. const String MidiMessage::getControllerName (int n) throw()
  913. {
  914. const char* names[] =
  915. {
  916. "Bank Select", "Modulation Wheel (coarse)", "Breath controller (coarse)",
  917. 0, "Foot Pedal (coarse)", "Portamento Time (coarse)",
  918. "Data Entry (coarse)", "Volume (coarse)", "Balance (coarse)",
  919. 0, "Pan position (coarse)", "Expression (coarse)", "Effect Control 1 (coarse)",
  920. "Effect Control 2 (coarse)", 0, 0, "General Purpose Slider 1", "General Purpose Slider 2",
  921. "General Purpose Slider 3", "General Purpose Slider 4", 0, 0, 0, 0, 0, 0, 0, 0,
  922. 0, 0, 0, 0, "Bank Select (fine)", "Modulation Wheel (fine)", "Breath controller (fine)",
  923. 0, "Foot Pedal (fine)", "Portamento Time (fine)", "Data Entry (fine)", "Volume (fine)",
  924. "Balance (fine)", 0, "Pan position (fine)", "Expression (fine)", "Effect Control 1 (fine)",
  925. "Effect Control 2 (fine)", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  926. "Hold Pedal (on/off)", "Portamento (on/off)", "Sustenuto Pedal (on/off)", "Soft Pedal (on/off)",
  927. "Legato Pedal (on/off)", "Hold 2 Pedal (on/off)", "Sound Variation", "Sound Timbre",
  928. "Sound Release Time", "Sound Attack Time", "Sound Brightness", "Sound Control 6",
  929. "Sound Control 7", "Sound Control 8", "Sound Control 9", "Sound Control 10",
  930. "General Purpose Button 1 (on/off)", "General Purpose Button 2 (on/off)",
  931. "General Purpose Button 3 (on/off)", "General Purpose Button 4 (on/off)",
  932. 0, 0, 0, 0, 0, 0, 0, "Reverb Level", "Tremolo Level", "Chorus Level", "Celeste Level",
  933. "Phaser Level", "Data Button increment", "Data Button decrement", "Non-registered Parameter (fine)",
  934. "Non-registered Parameter (coarse)", "Registered Parameter (fine)", "Registered Parameter (coarse)",
  935. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "All Sound Off", "All Controllers Off",
  936. "Local Keyboard (on/off)", "All Notes Off", "Omni Mode Off", "Omni Mode On", "Mono Operation",
  937. "Poly Operation"
  938. };
  939. return (n >= 0 && n < 128) ? names[n]
  940. : (const char*)0;
  941. }
  942. END_JUCE_NAMESPACE