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.

ysfx.h 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531
  1. // Copyright 2021 Jean Pierre Cimalando
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. //
  15. // SPDX-License-Identifier: Apache-2.0
  16. //
  17. #pragma once
  18. #if !defined(YSFX_INCLUDED_YSFX_H)
  19. #define YSFX_INCLUDED_YSFX_H
  20. #include <stdio.h>
  21. #include <stddef.h>
  22. #include <stdint.h>
  23. #include <stdbool.h>
  24. #if defined(_WIN32)
  25. # include <wchar.h>
  26. #endif
  27. //------------------------------------------------------------------------------
  28. #ifdef __cplusplus
  29. extern "C" {
  30. #endif
  31. #if !defined(YSFX_API)
  32. # if defined(_WIN32) && defined(YSFX_DLL_BUILD)
  33. # define YSFX_API __declspec(dllexport)
  34. # elif defined(__GNUC__)
  35. # define YSFX_API __attribute__((visibility("default")))
  36. # else
  37. # define YSFX_API
  38. # endif
  39. #endif
  40. //------------------------------------------------------------------------------
  41. // YSFX definitions
  42. typedef double ysfx_real;
  43. enum {
  44. ysfx_max_sliders = 64,
  45. ysfx_max_channels = 64,
  46. ysfx_max_midi_buses = 16,
  47. ysfx_max_triggers = 10,
  48. };
  49. typedef enum ysfx_log_level_e {
  50. ysfx_log_info,
  51. ysfx_log_warning,
  52. ysfx_log_error,
  53. } ysfx_log_level;
  54. typedef void (ysfx_log_reporter_t)(intptr_t userdata, ysfx_log_level level, const char *message);
  55. //------------------------------------------------------------------------------
  56. // YSFX configuration
  57. typedef struct ysfx_config_s ysfx_config_t;
  58. typedef struct ysfx_audio_format_s ysfx_audio_format_t;
  59. // create a new configuration
  60. YSFX_API ysfx_config_t *ysfx_config_new();
  61. // delete a configuration
  62. YSFX_API void ysfx_config_free(ysfx_config_t *config);
  63. // increase the reference counter
  64. YSFX_API void ysfx_config_add_ref(ysfx_config_t *config);
  65. // set the path of the import root, a folder usually named "Effects"
  66. YSFX_API void ysfx_set_import_root(ysfx_config_t *config, const char *root);
  67. // set the path of the data root, a folder usually named "Data"
  68. YSFX_API void ysfx_set_data_root(ysfx_config_t *config, const char *root);
  69. // get the path of the import root, a folder usually named "Effects"
  70. YSFX_API const char *ysfx_get_import_root(ysfx_config_t *config);
  71. // get the path of the data root, a folder usually named "Data"
  72. YSFX_API const char *ysfx_get_data_root(ysfx_config_t *config);
  73. // guess the undefined root folders, based on the path to the JSFX file
  74. YSFX_API void ysfx_guess_file_roots(ysfx_config_t *config, const char *sourcepath);
  75. // register an audio format into the system
  76. YSFX_API void ysfx_register_audio_format(ysfx_config_t *config, ysfx_audio_format_t *afmt);
  77. // register the builtin audio formats (at least WAV file support)
  78. YSFX_API void ysfx_register_builtin_audio_formats(ysfx_config_t *config);
  79. // set the log reporting function
  80. YSFX_API void ysfx_set_log_reporter(ysfx_config_t *config, ysfx_log_reporter_t *reporter);
  81. // set the callback user data
  82. YSFX_API void ysfx_set_user_data(ysfx_config_t *config, intptr_t userdata);
  83. // get a string which textually represents the log level
  84. YSFX_API const char *ysfx_log_level_string(ysfx_log_level level);
  85. //------------------------------------------------------------------------------
  86. // YSFX effect
  87. typedef struct ysfx_s ysfx_t;
  88. // create a new effect, taking a reference to config
  89. YSFX_API ysfx_t *ysfx_new(ysfx_config_t *config);
  90. // delete an effect
  91. YSFX_API void ysfx_free(ysfx_t *fx);
  92. // increase the reference counter
  93. YSFX_API void ysfx_add_ref(ysfx_t *fx);
  94. // get the configuration
  95. YSFX_API ysfx_config_t *ysfx_get_config(ysfx_t *fx);
  96. typedef enum ysfx_load_option_e {
  97. // skip imports; useful just for accessing header information and nothing else
  98. ysfx_load_ignoring_imports = 1,
  99. } ysfx_load_option_t;
  100. // load the source code from file without compiling
  101. YSFX_API bool ysfx_load_file(ysfx_t *fx, const char *filepath, uint32_t loadopts);
  102. // unload the source code and any compiled code
  103. YSFX_API void ysfx_unload(ysfx_t *fx);
  104. // check whether the effect is loaded
  105. YSFX_API bool ysfx_is_loaded(ysfx_t *fx);
  106. // get the name of the effect
  107. YSFX_API const char *ysfx_get_name(ysfx_t *fx);
  108. // get the path of the file which is loaded
  109. YSFX_API const char *ysfx_get_file_path(ysfx_t *fx);
  110. // get the author of the effect
  111. YSFX_API const char *ysfx_get_author(ysfx_t *fx);
  112. // get the number of tags of the effect
  113. #define ysfx_get_num_tags(fx) ysfx_get_tags((fx), NULL, 0)
  114. // get the list of tags of the effect
  115. YSFX_API uint32_t ysfx_get_tags(ysfx_t *fx, const char **dest, uint32_t destsize);
  116. // get a single tag of the effect
  117. YSFX_API const char *ysfx_get_tag(ysfx_t *fx, uint32_t index);
  118. // get the number of inputs
  119. YSFX_API uint32_t ysfx_get_num_inputs(ysfx_t *fx);
  120. // get the number of outputs
  121. YSFX_API uint32_t ysfx_get_num_outputs(ysfx_t *fx);
  122. // get the name of the input
  123. YSFX_API const char *ysfx_get_input_name(ysfx_t *fx, uint32_t index);
  124. // get the name of the output
  125. YSFX_API const char *ysfx_get_output_name(ysfx_t *fx, uint32_t index);
  126. // get whether this effect wants metering
  127. YSFX_API bool ysfx_wants_meters(ysfx_t *fx);
  128. // get requested dimensions of the graphics area; 0 means host should decide
  129. YSFX_API bool ysfx_get_gfx_dim(ysfx_t *fx, uint32_t dim[2]);
  130. typedef enum ysfx_section_type_e {
  131. ysfx_section_init = 1,
  132. ysfx_section_slider = 2,
  133. ysfx_section_block = 3,
  134. ysfx_section_sample = 4,
  135. ysfx_section_gfx = 5,
  136. ysfx_section_serialize = 6,
  137. } ysfx_section_type_t;
  138. // get whether the source has the given section
  139. YSFX_API bool ysfx_has_section(ysfx_t *fx, uint32_t type);
  140. typedef struct ysfx_slider_range_s {
  141. ysfx_real def;
  142. ysfx_real min;
  143. ysfx_real max;
  144. ysfx_real inc;
  145. } ysfx_slider_range_t;
  146. // determine if slider exists; call from 0 to max-1 to scan available ones
  147. YSFX_API bool ysfx_slider_exists(ysfx_t *fx, uint32_t index);
  148. // get the name of a slider
  149. YSFX_API const char *ysfx_slider_get_name(ysfx_t *fx, uint32_t index);
  150. // get the range of a slider
  151. YSFX_API bool ysfx_slider_get_range(ysfx_t *fx, uint32_t index, ysfx_slider_range_t *range);
  152. // get whether the slider is an enumeration
  153. YSFX_API bool ysfx_slider_is_enum(ysfx_t *fx, uint32_t index);
  154. // get the number of labels for the enumeration slider
  155. #define ysfx_slider_get_enum_size(fx, index) ysfx_slider_get_enum_names((fx), (index), NULL, 0)
  156. // get the list of labels for the enumeration slider
  157. YSFX_API uint32_t ysfx_slider_get_enum_names(ysfx_t *fx, uint32_t index, const char **dest, uint32_t destsize);
  158. // get a single label for the enumeration slider
  159. YSFX_API const char *ysfx_slider_get_enum_name(ysfx_t *fx, uint32_t slider_index, uint32_t enum_index);
  160. // get whether the slider is a path (implies enumeration)
  161. YSFX_API bool ysfx_slider_is_path(ysfx_t *fx, uint32_t index);
  162. // get whether the slider is initially visible
  163. YSFX_API bool ysfx_slider_is_initially_visible(ysfx_t *fx, uint32_t index);
  164. // get the value of the slider
  165. YSFX_API ysfx_real ysfx_slider_get_value(ysfx_t *fx, uint32_t index);
  166. // set the value of the slider, and call @slider later if value has changed
  167. YSFX_API void ysfx_slider_set_value(ysfx_t *fx, uint32_t index, ysfx_real value);
  168. typedef enum ysfx_compile_option_e {
  169. // skip compiling the @serialize section
  170. ysfx_compile_no_serialize = 1 << 0,
  171. // skip compiling the @gfx section
  172. ysfx_compile_no_gfx = 1 << 1,
  173. } ysfx_compile_option_t;
  174. // compile the previously loaded source
  175. YSFX_API bool ysfx_compile(ysfx_t *fx, uint32_t compileopts);
  176. // check whether the effect is compiled
  177. YSFX_API bool ysfx_is_compiled(ysfx_t *fx);
  178. // get the block size
  179. YSFX_API uint32_t ysfx_get_block_size(ysfx_t *fx);
  180. // get the sample rate
  181. YSFX_API ysfx_real ysfx_get_sample_rate(ysfx_t *fx);
  182. // update the block size; don't forget to call @init
  183. YSFX_API void ysfx_set_block_size(ysfx_t *fx, uint32_t blocksize);
  184. // update the sample rate; don't forget to call @init
  185. YSFX_API void ysfx_set_sample_rate(ysfx_t *fx, ysfx_real samplerate);
  186. // set the capacity of the MIDI buffer
  187. YSFX_API void ysfx_set_midi_capacity(ysfx_t *fx, uint32_t capacity, bool extensible);
  188. // activate and invoke @init
  189. YSFX_API void ysfx_init(ysfx_t *fx);
  190. // get the output latency
  191. YSFX_API ysfx_real ysfx_get_pdc_delay(ysfx_t *fx);
  192. // get the range of channels where output latency applies (end not included)
  193. YSFX_API void ysfx_get_pdc_channels(ysfx_t *fx, uint32_t channels[2]);
  194. // get whether the output latency applies to MIDI as well
  195. YSFX_API bool ysfx_get_pdc_midi(ysfx_t *fx);
  196. typedef enum ysfx_playback_state_e {
  197. ysfx_playback_error = 0,
  198. ysfx_playback_playing = 1,
  199. ysfx_playback_paused = 2,
  200. ysfx_playback_recording = 5,
  201. ysfx_playback_recording_paused = 6,
  202. } ysfx_playback_state_t;
  203. typedef struct ysfx_time_info_s {
  204. // tempo in beats/minute
  205. ysfx_real tempo;
  206. // state of the playback (ysfx_playback_state_t)
  207. uint32_t playback_state;
  208. // time position in seconds
  209. ysfx_real time_position;
  210. // time position in beats
  211. ysfx_real beat_position;
  212. // time signature in fraction form
  213. uint32_t time_signature[2];
  214. } ysfx_time_info_t;
  215. // update time information; do this before processing the cycle
  216. YSFX_API void ysfx_set_time_info(ysfx_t *fx, const ysfx_time_info_t *info);
  217. typedef struct ysfx_midi_event_s {
  218. // the bus number
  219. uint32_t bus;
  220. // the frame when it happens within the cycle
  221. uint32_t offset;
  222. // the size of the message
  223. uint32_t size;
  224. // the contents of the message
  225. const uint8_t *data;
  226. } ysfx_midi_event_t;
  227. // send MIDI, it will be processed during the cycle
  228. YSFX_API bool ysfx_send_midi(ysfx_t *fx, const ysfx_midi_event_t *event);
  229. // receive MIDI, after having processed the cycle
  230. YSFX_API bool ysfx_receive_midi(ysfx_t *fx, ysfx_midi_event_t *event);
  231. // receive MIDI from a single bus (do not mix with API above, use either)
  232. YSFX_API bool ysfx_receive_midi_from_bus(ysfx_t *fx, uint32_t bus, ysfx_midi_event_t *event);
  233. // send a trigger, it will be processed during the cycle
  234. YSFX_API bool ysfx_send_trigger(ysfx_t *fx, uint32_t index);
  235. // get a bit mask of sliders whose values must be redisplayed, and clear it to zero
  236. YSFX_API uint64_t ysfx_fetch_slider_changes(ysfx_t *fx);
  237. // get a bit mask of sliders whose values must be automated, and clear it to zero
  238. YSFX_API uint64_t ysfx_fetch_slider_automations(ysfx_t *fx);
  239. // get a bit mask of sliders currently visible
  240. YSFX_API uint64_t ysfx_get_slider_visibility(ysfx_t *fx);
  241. // process a cycle in 32-bit float
  242. YSFX_API void ysfx_process_float(ysfx_t *fx, const float *const *ins, float *const *outs, uint32_t num_ins, uint32_t num_outs, uint32_t num_frames);
  243. // process a cycle in 64-bit float
  244. YSFX_API void ysfx_process_double(ysfx_t *fx, const double *const *ins, double *const *outs, uint32_t num_ins, uint32_t num_outs, uint32_t num_frames);
  245. typedef struct ysfx_state_slider_s {
  246. // index of the slider
  247. uint32_t index;
  248. // value of the slider
  249. ysfx_real value;
  250. } ysfx_state_slider_t;
  251. typedef struct ysfx_state_s {
  252. // values of the sliders
  253. ysfx_state_slider_t *sliders;
  254. // number of sliders
  255. uint32_t slider_count;
  256. // serialized data
  257. uint8_t *data;
  258. // size of serialized data
  259. size_t data_size;
  260. } ysfx_state_t;
  261. // load state
  262. YSFX_API bool ysfx_load_state(ysfx_t *fx, ysfx_state_t *state);
  263. // save current state; release this object when done
  264. YSFX_API ysfx_state_t *ysfx_save_state(ysfx_t *fx);
  265. // release a saved state object
  266. YSFX_API void ysfx_state_free(ysfx_state_t *state);
  267. // duplicate a state object
  268. YSFX_API ysfx_state_t *ysfx_state_dup(ysfx_state_t *state);
  269. typedef struct ysfx_preset_s {
  270. // name of the preset
  271. char *name;
  272. // state of the preset
  273. ysfx_state_t *state;
  274. } ysfx_preset_t;
  275. typedef struct ysfx_bank_s {
  276. // name of the bank
  277. char *name;
  278. // list of presets
  279. ysfx_preset_t *presets;
  280. // number of programs
  281. uint32_t preset_count;
  282. } ysfx_bank_t;
  283. // get the path of the RPL preset bank of the loaded JSFX, if present
  284. YSFX_API const char *ysfx_get_bank_path(ysfx_t *fx);
  285. // read a preset bank from RPL file
  286. YSFX_API ysfx_bank_t *ysfx_load_bank(const char *path);
  287. // free a preset bank
  288. YSFX_API void ysfx_bank_free(ysfx_bank_t *bank);
  289. // type of a function which can enumerate VM variables; returning 0 ends the search
  290. typedef int (ysfx_enum_vars_callback_t)(const char *name, ysfx_real *var, void *userdata);
  291. // enumerate all variables currently in the VM
  292. YSFX_API void ysfx_enum_vars(ysfx_t *fx, ysfx_enum_vars_callback_t *callback, void *userdata);
  293. // find a single variable in the VM
  294. YSFX_API ysfx_real *ysfx_find_var(ysfx_t *fx, const char *name);
  295. // read a chunk of virtual memory from the VM
  296. YSFX_API void ysfx_read_vmem(ysfx_t *fx, uint32_t addr, ysfx_real *dest, uint32_t count);
  297. //------------------------------------------------------------------------------
  298. // YSFX graphics
  299. // NOTE: all `ysfx_gfx_*` functions must be invoked from a dedicated UI thread
  300. typedef struct ysfx_gfx_config_s {
  301. // opaque user data passed to callbacks
  302. void *user_data;
  303. // the width of the frame buffer (having the scale factor applied)
  304. uint32_t pixel_width;
  305. // the height of the frame buffer (having the scale factor applied)
  306. uint32_t pixel_height;
  307. // the distance in bytes between lines; if 0, it defaults to (4*width)
  308. // currently it is required to be a multiple of 4
  309. uint32_t pixel_stride;
  310. // the pixel data of the frame buffer, of size (stride*height) bytes
  311. // the byte order in little-endian is 'BGRA', big-endian is 'ARGB'
  312. uint8_t *pixels;
  313. // the scale factor of the display; 1.0 or greater, 2.0 for Retina display
  314. ysfx_real scale_factor;
  315. // show a menu and run it synchronously; returns an item ID >= 1, or 0 if none
  316. int32_t (*show_menu)(void *user_data, const char *menu_spec, int32_t xpos, int32_t ypos);
  317. // change the cursor
  318. void (*set_cursor)(void *user_data, int32_t cursor);
  319. // if index is not -1, get the dropped file at this index (otherwise null)
  320. // if index is -1, clear the list of dropped files, and return null
  321. const char *(*get_drop_file)(void *user_data, int32_t index);
  322. } ysfx_gfx_config_t;
  323. // set up the graphics rendering
  324. YSFX_API void ysfx_gfx_setup(ysfx_t *fx, ysfx_gfx_config_t *gc);
  325. // get whether the current effect is requesting Retina support
  326. YSFX_API bool ysfx_gfx_wants_retina(ysfx_t *fx);
  327. // push a key to the input queue
  328. YSFX_API void ysfx_gfx_add_key(ysfx_t *fx, uint32_t mods, uint32_t key, bool press);
  329. // update mouse information; position is relative to canvas; wheel should be in steps normalized to ±1.0
  330. YSFX_API void ysfx_gfx_update_mouse(ysfx_t *fx, uint32_t mods, int32_t xpos, int32_t ypos, uint32_t buttons, ysfx_real wheel, ysfx_real hwheel);
  331. // invoke @gfx to paint the graphics; returns whether the framer buffer is modified
  332. YSFX_API bool ysfx_gfx_run(ysfx_t *fx);
  333. //------------------------------------------------------------------------------
  334. // YSFX key map
  335. // these key definitions match those of pugl
  336. enum {
  337. ysfx_mod_shift = 1 << 0,
  338. ysfx_mod_ctrl = 1 << 1,
  339. ysfx_mod_alt = 1 << 2,
  340. ysfx_mod_super = 1 << 3,
  341. };
  342. enum {
  343. ysfx_key_backspace = 0x08,
  344. ysfx_key_escape = 0x1b,
  345. ysfx_key_delete = 0x7f,
  346. ysfx_key_f1 = 0xe000,
  347. ysfx_key_f2,
  348. ysfx_key_f3,
  349. ysfx_key_f4,
  350. ysfx_key_f5,
  351. ysfx_key_f6,
  352. ysfx_key_f7,
  353. ysfx_key_f8,
  354. ysfx_key_f9,
  355. ysfx_key_f10,
  356. ysfx_key_f11,
  357. ysfx_key_f12,
  358. ysfx_key_left,
  359. ysfx_key_up,
  360. ysfx_key_right,
  361. ysfx_key_down,
  362. ysfx_key_page_up,
  363. ysfx_key_page_down,
  364. ysfx_key_home,
  365. ysfx_key_end,
  366. ysfx_key_insert,
  367. };
  368. enum {
  369. ysfx_button_left = 1 << 0,
  370. ysfx_button_middle = 1 << 1,
  371. ysfx_button_right = 1 << 2,
  372. };
  373. //------------------------------------------------------------------------------
  374. // YSFX menu
  375. typedef struct ysfx_menu_insn_s ysfx_menu_insn_t;
  376. typedef struct ysfx_menu_s {
  377. // list of instructions to build a menu
  378. ysfx_menu_insn_t *insns;
  379. // number of menu instructions
  380. uint32_t insn_count;
  381. } ysfx_menu_t;
  382. typedef enum ysfx_menu_opcode_e {
  383. // appends an item
  384. ysfx_menu_item,
  385. // appends a separator
  386. ysfx_menu_separator,
  387. // appends a submenu and enters
  388. ysfx_menu_sub,
  389. // terminates a submenu and leaves
  390. ysfx_menu_endsub,
  391. } ysfx_menu_opcode_t;
  392. typedef enum ysfx_menu_item_flag_e {
  393. // whether the item is disabled (grayed out)
  394. ysfx_menu_item_disabled = 1 << 0,
  395. // whether the item is checked
  396. ysfx_menu_item_checked = 1 << 1,
  397. } ysfx_menu_item_flag_t;
  398. typedef struct ysfx_menu_insn_s {
  399. // operation code of this instruction
  400. ysfx_menu_opcode_t opcode;
  401. // unique identifier, greater than 0 (opcodes: item)
  402. uint32_t id;
  403. // name (opcodes: item, sub/endsub)
  404. const char *name;
  405. // combination of item flags (opcodes: item, sub/endsub)
  406. uint32_t item_flags;
  407. } ysfx_menu_insn_t;
  408. // parse a string which describes a popup menu (cf. `gfx_showmenu`)
  409. YSFX_API ysfx_menu_t *ysfx_parse_menu(const char *text);
  410. // free a menu
  411. YSFX_API void ysfx_menu_free(ysfx_menu_t *menu);
  412. //------------------------------------------------------------------------------
  413. // YSFX audio formats
  414. typedef struct ysfx_audio_reader_s ysfx_audio_reader_t;
  415. typedef struct ysfx_audio_file_info_s {
  416. uint32_t channels;
  417. ysfx_real sample_rate;
  418. } ysfx_audio_file_info_t;
  419. typedef struct ysfx_audio_format_s {
  420. // quickly checks if this format would be able to handle the given file
  421. bool (*can_handle)(const char *path);
  422. // open an audio file of this format for reading
  423. ysfx_audio_reader_t *(*open)(const char *path);
  424. // close the audio file
  425. void (*close)(ysfx_audio_reader_t *reader);
  426. // get the sample rate and the channel count
  427. ysfx_audio_file_info_t (*info)(ysfx_audio_reader_t *reader);
  428. // get the number of samples left to read
  429. uint64_t (*avail)(ysfx_audio_reader_t *reader);
  430. // move the read pointer back to the beginning
  431. void (*rewind)(ysfx_audio_reader_t *reader);
  432. // read the next block of samples
  433. uint64_t (*read)(ysfx_audio_reader_t *reader, ysfx_real *samples, uint64_t count);
  434. } ysfx_audio_format_t;
  435. //------------------------------------------------------------------------------
  436. #ifdef __cplusplus
  437. } // extern "C"
  438. #endif
  439. //------------------------------------------------------------------------------
  440. // YSFX RAII helpers
  441. #if defined(__cplusplus) && (__cplusplus >= 201103L || (defined(_MSC_VER) && _MSVC_LANG >= 201103L))
  442. #include <memory>
  443. #define YSFX_DEFINE_AUTO_PTR(aptr, styp, freefn) \
  444. struct aptr##_deleter { \
  445. void operator()(styp *x) const noexcept { freefn(x); } \
  446. }; \
  447. using aptr = std::unique_ptr<styp, aptr##_deleter>
  448. YSFX_DEFINE_AUTO_PTR(ysfx_config_u, ysfx_config_t, ysfx_config_free);
  449. YSFX_DEFINE_AUTO_PTR(ysfx_u, ysfx_t, ysfx_free);
  450. YSFX_DEFINE_AUTO_PTR(ysfx_state_u, ysfx_state_t, ysfx_state_free);
  451. YSFX_DEFINE_AUTO_PTR(ysfx_bank_u, ysfx_bank_t, ysfx_bank_free);
  452. YSFX_DEFINE_AUTO_PTR(ysfx_menu_u, ysfx_menu_t, ysfx_menu_free);
  453. #endif // defined(__cplusplus) && (__cplusplus >= 201103L || (defined(_MSC_VER) && _MSVC_LANG >= 201103L))
  454. //------------------------------------------------------------------------------
  455. #endif // !defined(YSFX_INCLUDED_YSFX_H)