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.

1047 lines
34KB

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