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.

1101 lines
33KB

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