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.

233 lines
7.4KB

  1. /*
  2. * Carla CLAP utils
  3. * Copyright (C) 2022 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
  16. */
  17. #ifndef CARLA_CLAP_UTILS_HPP_INCLUDED
  18. #define CARLA_CLAP_UTILS_HPP_INCLUDED
  19. #include "CarlaBackend.h"
  20. #include "CarlaUtils.hpp"
  21. #include "clap/entry.h"
  22. #include "clap/plugin-factory.h"
  23. #include "clap/plugin-features.h"
  24. #include "clap/ext/audio-ports.h"
  25. #include "clap/ext/latency.h"
  26. #include "clap/ext/gui.h"
  27. #include "clap/ext/note-ports.h"
  28. #include "clap/ext/params.h"
  29. #include "clap/ext/posix-fd-support.h"
  30. #include "clap/ext/state.h"
  31. #include "clap/ext/timer-support.h"
  32. #if defined(CARLA_OS_WIN)
  33. # define CLAP_WINDOW_API_NATIVE CLAP_WINDOW_API_WIN32
  34. #elif defined(CARLA_OS_MAC)
  35. # define CLAP_WINDOW_API_NATIVE CLAP_WINDOW_API_COCOA
  36. #elif defined(HAVE_X11)
  37. # define CLAP_WINDOW_API_NATIVE CLAP_WINDOW_API_X11
  38. #endif
  39. // --------------------------------------------------------------------------------------------------------------------
  40. extern "C" {
  41. typedef struct clap_audio_buffer_with_offset {
  42. float **data32;
  43. double **data64;
  44. uint32_t channel_count;
  45. uint32_t latency;
  46. uint64_t constant_mask;
  47. uint16_t offset;
  48. bool isMain;
  49. } clap_audio_buffer_with_offset_t;
  50. typedef struct clap_audio_buffer_const_with_offset {
  51. // Either data32 or data64 pointer will be set.
  52. const float* const* data32;
  53. const double* const* data64;
  54. uint32_t channel_count;
  55. uint32_t latency;
  56. uint64_t constant_mask;
  57. uint16_t offset;
  58. bool isMain;
  59. } clap_audio_buffer_const_with_offset_t;
  60. }
  61. // --------------------------------------------------------------------------------------------------------------------
  62. CARLA_BACKEND_START_NAMESPACE
  63. // --------------------------------------------------------------------------------------------------------------------
  64. static inline
  65. PluginCategory getPluginCategoryFromClapFeatures(const char* const* const features) noexcept
  66. {
  67. // 1st pass for main categories
  68. for (uint32_t i=0; features[i] != nullptr; ++i)
  69. {
  70. if (std::strcmp(features[i], CLAP_PLUGIN_FEATURE_INSTRUMENT) == 0)
  71. return PLUGIN_CATEGORY_SYNTH;
  72. if (std::strcmp(features[i], CLAP_PLUGIN_FEATURE_NOTE_EFFECT) == 0)
  73. return PLUGIN_CATEGORY_UTILITY;
  74. if (std::strcmp(features[i], CLAP_PLUGIN_FEATURE_ANALYZER) == 0)
  75. return PLUGIN_CATEGORY_UTILITY;
  76. }
  77. // 2nd pass for FX sub categories
  78. /*
  79. #define CLAP_PLUGIN_FEATURE_DEESSER "de-esser"
  80. #define CLAP_PLUGIN_FEATURE_PHASE_VOCODER "phase-vocoder"
  81. #define CLAP_PLUGIN_FEATURE_GRANULAR "granular"
  82. #define CLAP_PLUGIN_FEATURE_FREQUENCY_SHIFTER "frequency-shifter"
  83. #define CLAP_PLUGIN_FEATURE_PITCH_SHIFTER "pitch-shifter"
  84. #define CLAP_PLUGIN_FEATURE_TREMOLO "tremolo"
  85. #define CLAP_PLUGIN_FEATURE_GLITCH "glitch"
  86. */
  87. for (uint32_t i=0; features[i] != nullptr; ++i)
  88. {
  89. if (std::strcmp(features[i], CLAP_PLUGIN_FEATURE_DELAY) == 0 ||
  90. std::strcmp(features[i], CLAP_PLUGIN_FEATURE_REVERB) == 0)
  91. {
  92. return PLUGIN_CATEGORY_DELAY;
  93. }
  94. if (std::strcmp(features[i], CLAP_PLUGIN_FEATURE_EQUALIZER) == 0)
  95. {
  96. return PLUGIN_CATEGORY_EQ;
  97. }
  98. if (std::strcmp(features[i], CLAP_PLUGIN_FEATURE_FILTER) == 0)
  99. {
  100. return PLUGIN_CATEGORY_FILTER;
  101. }
  102. if (std::strcmp(features[i], CLAP_PLUGIN_FEATURE_DISTORTION) == 0)
  103. {
  104. return PLUGIN_CATEGORY_DISTORTION;
  105. }
  106. if (std::strcmp(features[i], CLAP_PLUGIN_FEATURE_COMPRESSOR) == 0 ||
  107. std::strcmp(features[i], CLAP_PLUGIN_FEATURE_LIMITER) == 0 ||
  108. std::strcmp(features[i], CLAP_PLUGIN_FEATURE_MASTERING) == 0 ||
  109. std::strcmp(features[i], CLAP_PLUGIN_FEATURE_MIXING) == 0 ||
  110. std::strcmp(features[i], CLAP_PLUGIN_FEATURE_TRANSIENT_SHAPER) == 0)
  111. {
  112. return PLUGIN_CATEGORY_DYNAMICS;
  113. }
  114. if (std::strcmp(features[i], CLAP_PLUGIN_FEATURE_CHORUS) == 0 ||
  115. std::strcmp(features[i], CLAP_PLUGIN_FEATURE_FLANGER) == 0 ||
  116. std::strcmp(features[i], CLAP_PLUGIN_FEATURE_PHASER) == 0
  117. )
  118. {
  119. return PLUGIN_CATEGORY_MODULATOR;
  120. }
  121. if (std::strcmp(features[i], CLAP_PLUGIN_FEATURE_PITCH_CORRECTION) == 0 ||
  122. std::strcmp(features[i], CLAP_PLUGIN_FEATURE_RESTORATION) == 0 ||
  123. std::strcmp(features[i], CLAP_PLUGIN_FEATURE_UTILITY) == 0
  124. )
  125. {
  126. return PLUGIN_CATEGORY_UTILITY;
  127. }
  128. }
  129. return PLUGIN_CATEGORY_OTHER;
  130. }
  131. static inline
  132. bool clapFeaturesContainInstrument(const char* const* const features) noexcept
  133. {
  134. if (features == nullptr)
  135. return false;
  136. for (uint32_t i=0; features[i] != nullptr; ++i)
  137. {
  138. if (std::strcmp(features[i], CLAP_PLUGIN_FEATURE_INSTRUMENT) == 0)
  139. return true;
  140. }
  141. return false;
  142. }
  143. // --------------------------------------------------------------------------------------------------------------------
  144. struct clap_istream_impl : clap_istream_t {
  145. const void* buffer;
  146. const uint64_t size;
  147. uint64_t readPos;
  148. clap_istream_impl(const void* const buf, const uint64_t bufsize) noexcept
  149. : buffer(buf),
  150. size(bufsize),
  151. readPos(0)
  152. {
  153. ctx = this;
  154. read = read_impl;
  155. }
  156. static CLAP_ABI int64_t read_impl(const clap_istream_t* const stream, void* const buffer, const uint64_t size) noexcept
  157. {
  158. clap_istream_impl* const self = static_cast<clap_istream_impl*>(stream->ctx);
  159. if (const uint64_t bytesRead = std::min(self->size - self->readPos, size))
  160. {
  161. std::memcpy(buffer, static_cast<const uint8_t*>(self->buffer) + self->readPos, bytesRead);
  162. self->readPos += bytesRead;
  163. return bytesRead;
  164. }
  165. return 0;
  166. }
  167. };
  168. // --------------------------------------------------------------------------------------------------------------------
  169. struct clap_ostream_impl : clap_ostream_t {
  170. void* buffer;
  171. uint64_t size;
  172. clap_ostream_impl() noexcept
  173. : buffer(nullptr),
  174. size(0)
  175. {
  176. ctx = this;
  177. write = write_impl;
  178. }
  179. static CLAP_ABI int64_t write_impl(const clap_ostream* const stream, const void* const buffer, const uint64_t size) noexcept
  180. {
  181. CARLA_SAFE_ASSERT_RETURN(size != 0, 0);
  182. clap_ostream_impl* const self = static_cast<clap_ostream_impl*>(stream->ctx);
  183. void* const oldBuffer = self->buffer;
  184. self->buffer = std::realloc(self->buffer, self->size + size);
  185. if (self->buffer == nullptr)
  186. {
  187. std::free(oldBuffer);
  188. return -1;
  189. }
  190. std::memcpy(static_cast<uint8_t*>(self->buffer) + self->size, buffer, size);
  191. self->size += size;
  192. return size;
  193. }
  194. };
  195. // --------------------------------------------------------------------------------------------------------------------
  196. CARLA_BACKEND_END_NAMESPACE
  197. #endif // CARLA_CLAP_UTILS_HPP_INCLUDED