Audio plugin host https://kx.studio/carla
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.

133 lines
4.4KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2015 - ROLI Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. namespace
  18. {
  19. uint16 generateNoteID (int midiChannel, int midiNoteNumber) noexcept
  20. {
  21. jassert (midiChannel > 0 && midiChannel <= 16);
  22. jassert (midiNoteNumber >= 0 && midiNoteNumber < 128);
  23. return uint16 ((midiChannel << 7) + midiNoteNumber);
  24. }
  25. }
  26. //==============================================================================
  27. MPENote::MPENote (int midiChannel_,
  28. int initialNote_,
  29. MPEValue noteOnVelocity_,
  30. MPEValue pitchbend_,
  31. MPEValue pressure_,
  32. MPEValue timbre_,
  33. KeyState keyState_) noexcept
  34. : noteID (generateNoteID (midiChannel_, initialNote_)),
  35. midiChannel (uint8 (midiChannel_)),
  36. initialNote (uint8 (initialNote_)),
  37. noteOnVelocity (noteOnVelocity_),
  38. pitchbend (pitchbend_),
  39. pressure (pressure_),
  40. timbre (timbre_),
  41. noteOffVelocity (MPEValue::minValue()),
  42. keyState (keyState_)
  43. {
  44. jassert (keyState != MPENote::off);
  45. jassert (isValid());
  46. }
  47. MPENote::MPENote() noexcept
  48. : noteID (0),
  49. midiChannel (0),
  50. initialNote (0),
  51. noteOnVelocity (MPEValue::minValue()),
  52. pitchbend (MPEValue::centreValue()),
  53. pressure (MPEValue::centreValue()),
  54. timbre (MPEValue::centreValue()),
  55. noteOffVelocity (MPEValue::minValue()),
  56. keyState (MPENote::off)
  57. {
  58. }
  59. //==============================================================================
  60. bool MPENote::isValid() const noexcept
  61. {
  62. return midiChannel > 0 && midiChannel <= 16 && initialNote < 128;
  63. }
  64. //==============================================================================
  65. double MPENote::getFrequencyInHertz (double frequencyOfA) const noexcept
  66. {
  67. double pitchInSemitones = double (initialNote) + totalPitchbendInSemitones;
  68. return frequencyOfA * std::pow (2.0, (pitchInSemitones - 69.0) / 12.0);
  69. }
  70. //==============================================================================
  71. bool MPENote::operator== (const MPENote& other) const noexcept
  72. {
  73. jassert (isValid() && other.isValid());
  74. return noteID == other.noteID;
  75. }
  76. bool MPENote::operator!= (const MPENote& other) const noexcept
  77. {
  78. jassert (isValid() && other.isValid());
  79. return noteID != other.noteID;
  80. }
  81. //==============================================================================
  82. //==============================================================================
  83. #if JUCE_UNIT_TESTS
  84. class MPENoteTests : public UnitTest
  85. {
  86. public:
  87. MPENoteTests() : UnitTest ("MPENote class") {}
  88. //==============================================================================
  89. void runTest() override
  90. {
  91. beginTest ("getFrequencyInHertz");
  92. {
  93. MPENote note;
  94. note.initialNote = 60;
  95. note.totalPitchbendInSemitones = -0.5;
  96. expectEqualsWithinOneCent (note.getFrequencyInHertz(), 254.178);
  97. }
  98. }
  99. private:
  100. //==============================================================================
  101. void expectEqualsWithinOneCent (double frequencyInHertzActual,
  102. double frequencyInHertzExpected)
  103. {
  104. double ratio = frequencyInHertzActual / frequencyInHertzExpected;
  105. double oneCent = 1.0005946;
  106. expect (ratio < oneCent);
  107. expect (ratio > 1.0 / oneCent);
  108. }
  109. };
  110. static MPENoteTests MPENoteUnitTests;
  111. #endif // JUCE_UNIT_TESTS