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.

222 lines
6.4KB

  1. // SPDX-FileCopyrightText: 2011-2024 Filipe Coelho <falktx@falktx.com>
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #ifndef CARLA_ENGINE_UTILS_HPP_INCLUDED
  4. #define CARLA_ENGINE_UTILS_HPP_INCLUDED
  5. #include "CarlaEngine.hpp"
  6. #include "CarlaUtils.hpp"
  7. #include "CarlaMIDI.h"
  8. #include "water/midi/MidiBuffer.h"
  9. CARLA_BACKEND_START_NAMESPACE
  10. // -----------------------------------------------------------------------
  11. // Maximum internal pre-allocated events
  12. const ushort kMaxEngineEventInternalCount = 2048;
  13. // -----------------------------------------------------------------------
  14. static inline
  15. const char* EngineType2Str(const EngineType type) noexcept
  16. {
  17. switch (type)
  18. {
  19. case kEngineTypeNull:
  20. return "kEngineTypeNull";
  21. case kEngineTypeJack:
  22. return "kEngineTypeJack";
  23. case kEngineTypeRtAudio:
  24. return "kEngineTypeRtAudio";
  25. case kEngineTypeSDL:
  26. return "kEngineTypeSDL";
  27. case kEngineTypePlugin:
  28. return "kEngineTypePlugin";
  29. case kEngineTypeBridge:
  30. return "kEngineTypeBridge";
  31. case kEngineTypeDummy:
  32. return "kEngineTypeDummy";
  33. }
  34. carla_stderr("CarlaBackend::EngineType2Str(%i) - invalid type", type);
  35. return nullptr;
  36. }
  37. static inline
  38. const char* EnginePortType2Str(const EnginePortType type) noexcept
  39. {
  40. switch (type)
  41. {
  42. case kEnginePortTypeNull:
  43. return "kEnginePortTypeNull";
  44. case kEnginePortTypeAudio:
  45. return "kEnginePortTypeAudio";
  46. case kEnginePortTypeCV:
  47. return "kEnginePortTypeCV";
  48. case kEnginePortTypeEvent:
  49. return "kEnginePortTypeEvent";
  50. }
  51. carla_stderr("CarlaBackend::EnginePortType2Str(%i) - invalid type", type);
  52. return nullptr;
  53. }
  54. static inline
  55. const char* EngineEventType2Str(const EngineEventType type) noexcept
  56. {
  57. switch (type)
  58. {
  59. case kEngineEventTypeNull:
  60. return "kEngineEventTypeNull";
  61. case kEngineEventTypeControl:
  62. return "kEngineEventTypeControl";
  63. case kEngineEventTypeMidi:
  64. return "kEngineEventTypeMidi";
  65. }
  66. carla_stderr("CarlaBackend::EngineEventType2Str(%i) - invalid type", type);
  67. return nullptr;
  68. }
  69. static inline
  70. const char* EngineControlEventType2Str(const EngineControlEventType type) noexcept
  71. {
  72. switch (type)
  73. {
  74. case kEngineControlEventTypeNull:
  75. return "kEngineNullEvent";
  76. case kEngineControlEventTypeParameter:
  77. return "kEngineControlEventTypeParameter";
  78. case kEngineControlEventTypeMidiBank:
  79. return "kEngineControlEventTypeMidiBank";
  80. case kEngineControlEventTypeMidiProgram:
  81. return "kEngineControlEventTypeMidiProgram";
  82. case kEngineControlEventTypeAllSoundOff:
  83. return "kEngineControlEventTypeAllSoundOff";
  84. case kEngineControlEventTypeAllNotesOff:
  85. return "kEngineControlEventTypeAllNotesOff";
  86. }
  87. carla_stderr("CarlaBackend::EngineControlEventType2Str(%i) - invalid type", type);
  88. return nullptr;
  89. }
  90. // -----------------------------------------------------------------------
  91. static inline
  92. void fillEngineEventsFromWaterMidiBuffer(EngineEvent engineEvents[kMaxEngineEventInternalCount], const water::MidiBuffer& midiBuffer)
  93. {
  94. const uint8_t* midiData;
  95. int numBytes, sampleNumber;
  96. ushort engineEventIndex = 0;
  97. for (ushort i=0; i < kMaxEngineEventInternalCount; ++i)
  98. {
  99. const EngineEvent& engineEvent(engineEvents[i]);
  100. if (engineEvent.type != kEngineEventTypeNull)
  101. continue;
  102. engineEventIndex = i;
  103. break;
  104. }
  105. for (water::MidiBuffer::Iterator midiBufferIterator(midiBuffer); midiBufferIterator.getNextEvent(midiData, numBytes, sampleNumber) && engineEventIndex < kMaxEngineEventInternalCount;)
  106. {
  107. CARLA_SAFE_ASSERT_CONTINUE(numBytes > 0);
  108. CARLA_SAFE_ASSERT_CONTINUE(sampleNumber >= 0);
  109. CARLA_SAFE_ASSERT_CONTINUE(numBytes < 0xFF /* uint8_t max */);
  110. EngineEvent& engineEvent(engineEvents[engineEventIndex++]);
  111. engineEvent.time = static_cast<uint32_t>(sampleNumber);
  112. engineEvent.fillFromMidiData(static_cast<uint8_t>(numBytes), midiData, 0);
  113. }
  114. }
  115. // -----------------------------------------------------------------------
  116. static inline
  117. void fillWaterMidiBufferFromEngineEvents(water::MidiBuffer& midiBuffer, const EngineEvent engineEvents[kMaxEngineEventInternalCount])
  118. {
  119. uint8_t size = 0;
  120. uint8_t mdata[3] = { 0, 0, 0 };
  121. uint8_t mdataTmp[EngineMidiEvent::kDataSize];
  122. const uint8_t* mdataPtr;
  123. for (ushort i=0; i < kMaxEngineEventInternalCount; ++i)
  124. {
  125. const EngineEvent& engineEvent(engineEvents[i]);
  126. /**/ if (engineEvent.type == kEngineEventTypeNull)
  127. {
  128. break;
  129. }
  130. else if (engineEvent.type == kEngineEventTypeControl)
  131. {
  132. const EngineControlEvent& ctrlEvent(engineEvent.ctrl);
  133. size = ctrlEvent.convertToMidiData(engineEvent.channel, mdata);
  134. mdataPtr = mdata;
  135. }
  136. else if (engineEvent.type == kEngineEventTypeMidi)
  137. {
  138. const EngineMidiEvent& midiEvent(engineEvent.midi);
  139. size = midiEvent.size;
  140. CARLA_SAFE_ASSERT_CONTINUE(size > 0);
  141. if (size > EngineMidiEvent::kDataSize)
  142. {
  143. CARLA_SAFE_ASSERT_CONTINUE(midiEvent.dataExt != nullptr);
  144. mdataPtr = midiEvent.dataExt;
  145. }
  146. else
  147. {
  148. // set first byte
  149. mdataTmp[0] = static_cast<uint8_t>(midiEvent.data[0] | (engineEvent.channel & MIDI_CHANNEL_BIT));
  150. if (size > 1)
  151. {
  152. // copy rest
  153. carla_copy<uint8_t>(mdataTmp+1, midiEvent.data+1, size-1U);
  154. }
  155. // done
  156. mdataPtr = mdataTmp;
  157. }
  158. }
  159. else
  160. {
  161. continue;
  162. }
  163. if (size > 0)
  164. midiBuffer.addEvent(mdataPtr, static_cast<int>(size), static_cast<int>(engineEvent.time));
  165. }
  166. }
  167. // -------------------------------------------------------------------
  168. // Helper classes
  169. class ScopedEngineEnvironmentLocker
  170. {
  171. public:
  172. ScopedEngineEnvironmentLocker(CarlaEngine* const engine) noexcept;
  173. ~ScopedEngineEnvironmentLocker() noexcept;
  174. private:
  175. CarlaEngine::ProtectedData* const pData;
  176. CARLA_PREVENT_HEAP_ALLOCATION
  177. CARLA_DECLARE_NON_COPYABLE(ScopedEngineEnvironmentLocker)
  178. };
  179. // -----------------------------------------------------------------------
  180. CARLA_BACKEND_END_NAMESPACE
  181. #endif // CARLA_ENGINE_UTILS_HPP_INCLUDED