tap_echo.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
  1. /* -*- linux-c -*-
  2. Copyright (C) 2004 Tom Szilagyi
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  14. $Id: tap_echo.c,v 1.7 2004/12/06 09:32:41 tszilagyi Exp $
  15. */
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <math.h>
  20. #include <ladspa.h>
  21. #include "tap_utils.h"
  22. /* The Unique ID of the plugin: */
  23. #define ID_STEREO 2143
  24. /* The port numbers for the plugin: */
  25. #define DELAYTIME_L 0
  26. #define FEEDBACK_L 1
  27. #define DELAYTIME_R 2
  28. #define FEEDBACK_R 3
  29. #define STRENGTH_L 4
  30. #define STRENGTH_R 5
  31. #define DRYLEVEL 6
  32. #define MODE 7
  33. #define HAAS 8
  34. #define REV_OUTCH 9
  35. #define INPUT_L 10
  36. #define OUTPUT_L 11
  37. #define INPUT_R 12
  38. #define OUTPUT_R 13
  39. /* Total number of ports */
  40. #define PORTCOUNT_STEREO 14
  41. /* Maximum delay (ms) */
  42. #define MAX_DELAY 2000
  43. /* The structure used to hold port connection information and state */
  44. typedef struct {
  45. LADSPA_Data * delaytime_L;
  46. LADSPA_Data * delaytime_R;
  47. LADSPA_Data * feedback_L;
  48. LADSPA_Data * feedback_R;
  49. LADSPA_Data * strength_L;
  50. LADSPA_Data * strength_R;
  51. LADSPA_Data * drylevel;
  52. LADSPA_Data * mode;
  53. LADSPA_Data * haas;
  54. LADSPA_Data * rev_outch;
  55. LADSPA_Data * input_L;
  56. LADSPA_Data * output_L;
  57. LADSPA_Data * input_R;
  58. LADSPA_Data * output_R;
  59. unsigned long sample_rate;
  60. LADSPA_Data mpx_out_L;
  61. LADSPA_Data mpx_out_R;
  62. LADSPA_Data * ringbuffer_L;
  63. LADSPA_Data * ringbuffer_R;
  64. unsigned long * buffer_pos_L;
  65. unsigned long * buffer_pos_R;
  66. LADSPA_Data run_adding_gain;
  67. } Echo;
  68. /* Construct a new plugin instance. */
  69. LADSPA_Handle
  70. instantiate_Echo(const LADSPA_Descriptor * Descriptor,
  71. unsigned long SampleRate) {
  72. LADSPA_Handle * ptr;
  73. if ((ptr = malloc(sizeof(Echo))) != NULL) {
  74. ((Echo *)ptr)->sample_rate = SampleRate;
  75. ((Echo *)ptr)->run_adding_gain = 1.0f;
  76. /* allocate memory for ringbuffers and related dynamic vars */
  77. if ((((Echo *)ptr)->ringbuffer_L =
  78. calloc(MAX_DELAY * ((Echo *)ptr)->sample_rate / 1000,
  79. sizeof(LADSPA_Data))) == NULL)
  80. exit(1);
  81. if ((((Echo *)ptr)->ringbuffer_R =
  82. calloc(MAX_DELAY * ((Echo *)ptr)->sample_rate / 1000,
  83. sizeof(LADSPA_Data))) == NULL)
  84. exit(1);
  85. if ((((Echo *)ptr)->buffer_pos_L = calloc(1, sizeof(unsigned long))) == NULL)
  86. exit(1);
  87. if ((((Echo *)ptr)->buffer_pos_R = calloc(1, sizeof(unsigned long))) == NULL)
  88. exit(1);
  89. *(((Echo *)ptr)->buffer_pos_L) = 0;
  90. *(((Echo *)ptr)->buffer_pos_R) = 0;
  91. return ptr;
  92. }
  93. return NULL;
  94. }
  95. /* activate a plugin instance */
  96. void
  97. activate_Echo(LADSPA_Handle Instance) {
  98. Echo * ptr = (Echo *)Instance;
  99. unsigned int i;
  100. ptr->mpx_out_L = 0;
  101. ptr->mpx_out_R = 0;
  102. *(ptr->buffer_pos_L) = 0;
  103. *(ptr->buffer_pos_R) = 0;
  104. for (i = 0; i < MAX_DELAY * ptr->sample_rate / 1000; i++) {
  105. ptr->ringbuffer_L[i] = 0.0f;
  106. ptr->ringbuffer_R[i] = 0.0f;
  107. }
  108. }
  109. /* Connect a port to a data location. */
  110. void
  111. connect_port_Echo(LADSPA_Handle Instance,
  112. unsigned long Port,
  113. LADSPA_Data * DataLocation) {
  114. Echo * ptr;
  115. ptr = (Echo *)Instance;
  116. switch (Port) {
  117. case DELAYTIME_L:
  118. ptr->delaytime_L = DataLocation;
  119. break;
  120. case DELAYTIME_R:
  121. ptr->delaytime_R = DataLocation;
  122. break;
  123. case FEEDBACK_L:
  124. ptr->feedback_L = DataLocation;
  125. break;
  126. case FEEDBACK_R:
  127. ptr->feedback_R = DataLocation;
  128. break;
  129. case STRENGTH_L:
  130. ptr->strength_L = DataLocation;
  131. break;
  132. case STRENGTH_R:
  133. ptr->strength_R = DataLocation;
  134. break;
  135. case MODE:
  136. ptr->mode = DataLocation;
  137. break;
  138. case HAAS:
  139. ptr->haas = DataLocation;
  140. break;
  141. case REV_OUTCH:
  142. ptr->rev_outch = DataLocation;
  143. break;
  144. case DRYLEVEL:
  145. ptr->drylevel = DataLocation;
  146. break;
  147. case INPUT_L:
  148. ptr->input_L = DataLocation;
  149. break;
  150. case OUTPUT_L:
  151. ptr->output_L = DataLocation;
  152. break;
  153. case INPUT_R:
  154. ptr->input_R = DataLocation;
  155. break;
  156. case OUTPUT_R:
  157. ptr->output_R = DataLocation;
  158. break;
  159. }
  160. }
  161. #define EPS 0.00000001f
  162. static inline float
  163. M(float x) {
  164. if ((x > EPS) || (x < -EPS))
  165. return x;
  166. else
  167. return 0.0f;
  168. }
  169. void
  170. run_Echo(LADSPA_Handle Instance,
  171. unsigned long SampleCount) {
  172. Echo * ptr;
  173. unsigned long sample_index;
  174. LADSPA_Data delaytime_L;
  175. LADSPA_Data delaytime_R;
  176. LADSPA_Data feedback_L;
  177. LADSPA_Data feedback_R;
  178. LADSPA_Data strength_L;
  179. LADSPA_Data strength_R;
  180. LADSPA_Data drylevel;
  181. LADSPA_Data mode;
  182. LADSPA_Data haas;
  183. LADSPA_Data rev_outch;
  184. LADSPA_Data * input_L;
  185. LADSPA_Data * output_L;
  186. LADSPA_Data * input_R;
  187. LADSPA_Data * output_R;
  188. unsigned long sample_rate;
  189. unsigned long buflen_L;
  190. unsigned long buflen_R;
  191. LADSPA_Data out_L = 0;
  192. LADSPA_Data out_R = 0;
  193. LADSPA_Data in_L = 0;
  194. LADSPA_Data in_R = 0;
  195. ptr = (Echo *)Instance;
  196. delaytime_L = LIMIT(*(ptr->delaytime_L),0.0f,2000.0f);
  197. delaytime_R = LIMIT(*(ptr->delaytime_R),0.0f,2000.0f);
  198. feedback_L = LIMIT(*(ptr->feedback_L) / 100.0, 0.0f, 100.0f);
  199. feedback_R = LIMIT(*(ptr->feedback_R) / 100.0, 0.0f, 100.0f);
  200. strength_L = db2lin(LIMIT(*(ptr->strength_L),-70.0f,10.0f));
  201. strength_R = db2lin(LIMIT(*(ptr->strength_R),-70.0f,10.0f));
  202. drylevel = db2lin(LIMIT(*(ptr->drylevel),-70.0f,10.0f));
  203. mode = LIMIT(*(ptr->mode),-2.0f,2.0f);
  204. haas = LIMIT(*(ptr->haas),-2.0f,2.0f);
  205. rev_outch = LIMIT(*(ptr->rev_outch),-2.0f,2.0f);
  206. input_L = ptr->input_L;
  207. output_L = ptr->output_L;
  208. input_R = ptr->input_R;
  209. output_R = ptr->output_R;
  210. sample_rate = ptr->sample_rate;
  211. buflen_L = delaytime_L * sample_rate / 1000;
  212. buflen_R = delaytime_R * sample_rate / 1000;
  213. for (sample_index = 0; sample_index < SampleCount; sample_index++) {
  214. in_L = *(input_L++);
  215. in_R = *(input_R++);
  216. out_L = in_L * drylevel + ptr->mpx_out_L * strength_L;
  217. out_R = in_R * drylevel + ptr->mpx_out_R * strength_R;
  218. if (haas > 0.0f)
  219. in_R = 0.0f;
  220. if (mode <= 0.0f) {
  221. ptr->mpx_out_L =
  222. M(push_buffer(in_L + ptr->mpx_out_L * feedback_L,
  223. ptr->ringbuffer_L, buflen_L, ptr->buffer_pos_L));
  224. ptr->mpx_out_R =
  225. M(push_buffer(in_R + ptr->mpx_out_R * feedback_R,
  226. ptr->ringbuffer_R, buflen_R, ptr->buffer_pos_R));
  227. } else {
  228. ptr->mpx_out_R =
  229. M(push_buffer(in_L + ptr->mpx_out_L * feedback_L,
  230. ptr->ringbuffer_L, buflen_L, ptr->buffer_pos_L));
  231. ptr->mpx_out_L =
  232. M(push_buffer(in_R + ptr->mpx_out_R * feedback_R,
  233. ptr->ringbuffer_R, buflen_R, ptr->buffer_pos_R));
  234. }
  235. if (rev_outch <= 0.0f) {
  236. *(output_L++) = out_L;
  237. *(output_R++) = out_R;
  238. } else {
  239. *(output_L++) = out_R;
  240. *(output_R++) = out_L;
  241. }
  242. }
  243. }
  244. void
  245. set_run_adding_gain(LADSPA_Handle Instance, LADSPA_Data gain){
  246. Echo * ptr;
  247. ptr = (Echo *)Instance;
  248. ptr->run_adding_gain = gain;
  249. }
  250. void
  251. run_adding_gain_Echo(LADSPA_Handle Instance,
  252. unsigned long SampleCount) {
  253. Echo * ptr;
  254. unsigned long sample_index;
  255. LADSPA_Data delaytime_L;
  256. LADSPA_Data delaytime_R;
  257. LADSPA_Data feedback_L;
  258. LADSPA_Data feedback_R;
  259. LADSPA_Data strength_L;
  260. LADSPA_Data strength_R;
  261. LADSPA_Data drylevel;
  262. LADSPA_Data mode;
  263. LADSPA_Data haas;
  264. LADSPA_Data rev_outch;
  265. LADSPA_Data * input_L;
  266. LADSPA_Data * output_L;
  267. LADSPA_Data * input_R;
  268. LADSPA_Data * output_R;
  269. unsigned long sample_rate;
  270. unsigned long buflen_L;
  271. unsigned long buflen_R;
  272. LADSPA_Data out_L = 0;
  273. LADSPA_Data out_R = 0;
  274. LADSPA_Data in_L = 0;
  275. LADSPA_Data in_R = 0;
  276. ptr = (Echo *)Instance;
  277. delaytime_L = LIMIT(*(ptr->delaytime_L),0.0f,2000.0f);
  278. delaytime_R = LIMIT(*(ptr->delaytime_R),0.0f,2000.0f);
  279. feedback_L = LIMIT(*(ptr->feedback_L) / 100.0, 0.0f, 100.0f);
  280. feedback_R = LIMIT(*(ptr->feedback_R) / 100.0, 0.0f, 100.0f);
  281. strength_L = db2lin(LIMIT(*(ptr->strength_L),-70.0f,10.0f));
  282. strength_R = db2lin(LIMIT(*(ptr->strength_R),-70.0f,10.0f));
  283. drylevel = db2lin(LIMIT(*(ptr->drylevel),-70.0f,10.0f));
  284. mode = LIMIT(*(ptr->mode),-2.0f,2.0f);
  285. haas = LIMIT(*(ptr->haas),-2.0f,2.0f);
  286. rev_outch = LIMIT(*(ptr->rev_outch),-2.0f,2.0f);
  287. input_L = ptr->input_L;
  288. output_L = ptr->output_L;
  289. input_R = ptr->input_R;
  290. output_R = ptr->output_R;
  291. sample_rate = ptr->sample_rate;
  292. buflen_L = delaytime_L * sample_rate / 1000;
  293. buflen_R = delaytime_R * sample_rate / 1000;
  294. for (sample_index = 0; sample_index < SampleCount; sample_index++) {
  295. in_L = *(input_L++);
  296. in_R = *(input_R++);
  297. out_L = in_L * drylevel + ptr->mpx_out_L * strength_L;
  298. out_R = in_R * drylevel + ptr->mpx_out_R * strength_R;
  299. if (haas > 0.0f)
  300. in_R = 0.0f;
  301. if (mode <= 0.0f) {
  302. ptr->mpx_out_L =
  303. M(push_buffer(in_L + ptr->mpx_out_L * feedback_L,
  304. ptr->ringbuffer_L, buflen_L, ptr->buffer_pos_L));
  305. ptr->mpx_out_R =
  306. M(push_buffer(in_R + ptr->mpx_out_R * feedback_R,
  307. ptr->ringbuffer_R, buflen_R, ptr->buffer_pos_R));
  308. } else {
  309. ptr->mpx_out_R =
  310. M(push_buffer(in_L + ptr->mpx_out_L * feedback_L,
  311. ptr->ringbuffer_L, buflen_L, ptr->buffer_pos_L));
  312. ptr->mpx_out_L =
  313. M(push_buffer(in_R + ptr->mpx_out_R * feedback_R,
  314. ptr->ringbuffer_R, buflen_R, ptr->buffer_pos_R));
  315. }
  316. if (rev_outch <= 0.0f) {
  317. *(output_L++) += out_L * ptr->run_adding_gain;
  318. *(output_R++) += out_R * ptr->run_adding_gain;
  319. } else {
  320. *(output_L++) += out_R * ptr->run_adding_gain;
  321. *(output_R++) += out_L * ptr->run_adding_gain;
  322. }
  323. }
  324. }
  325. /* Throw away an Echo effect instance. */
  326. void
  327. cleanup_Echo(LADSPA_Handle Instance) {
  328. Echo * ptr = (Echo *)Instance;
  329. free(ptr->ringbuffer_L);
  330. free(ptr->ringbuffer_R);
  331. free(ptr->buffer_pos_L);
  332. free(ptr->buffer_pos_R);
  333. free(Instance);
  334. }
  335. LADSPA_Descriptor * stereo_descriptor = NULL;
  336. /* __attribute__((constructor)) tap_init() is called automatically when the plugin library is first
  337. loaded. */
  338. void
  339. __attribute__((constructor)) tap_init() {
  340. char ** port_names;
  341. LADSPA_PortDescriptor * port_descriptors;
  342. LADSPA_PortRangeHint * port_range_hints;
  343. if ((stereo_descriptor =
  344. (LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor))) == NULL)
  345. exit(1);
  346. /* init the stereo Echo */
  347. stereo_descriptor->UniqueID = ID_STEREO;
  348. stereo_descriptor->Label = strdup("tap_stereo_echo");
  349. stereo_descriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE;
  350. stereo_descriptor->Name = strdup("TAP Stereo Echo");
  351. stereo_descriptor->Maker = strdup("Tom Szilagyi");
  352. stereo_descriptor->Copyright = strdup("GPL");
  353. stereo_descriptor->PortCount = PORTCOUNT_STEREO;
  354. if ((port_descriptors =
  355. (LADSPA_PortDescriptor *)calloc(PORTCOUNT_STEREO, sizeof(LADSPA_PortDescriptor))) == NULL)
  356. exit(1);
  357. stereo_descriptor->PortDescriptors = (const LADSPA_PortDescriptor *)port_descriptors;
  358. port_descriptors[DELAYTIME_L] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
  359. port_descriptors[DELAYTIME_R] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
  360. port_descriptors[FEEDBACK_L] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
  361. port_descriptors[FEEDBACK_R] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
  362. port_descriptors[STRENGTH_L] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
  363. port_descriptors[STRENGTH_R] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
  364. port_descriptors[DRYLEVEL] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
  365. port_descriptors[MODE] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
  366. port_descriptors[HAAS] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
  367. port_descriptors[REV_OUTCH] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
  368. port_descriptors[INPUT_L] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
  369. port_descriptors[OUTPUT_L] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
  370. port_descriptors[INPUT_R] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
  371. port_descriptors[OUTPUT_R] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
  372. if ((port_names =
  373. (char **)calloc(PORTCOUNT_STEREO, sizeof(char *))) == NULL)
  374. exit(1);
  375. stereo_descriptor->PortNames = (const char **)port_names;
  376. port_names[DELAYTIME_L] = strdup("L Delay [ms]");
  377. port_names[DELAYTIME_R] = strdup("R/Haas Delay [ms]");
  378. port_names[FEEDBACK_L] = strdup("L Feedback [%]");
  379. port_names[FEEDBACK_R] = strdup("R/Haas Feedback [%]");
  380. port_names[STRENGTH_L] = strdup("L Echo Level [dB]");
  381. port_names[STRENGTH_R] = strdup("R Echo Level [dB]");
  382. port_names[DRYLEVEL] = strdup("Dry Level [dB]");
  383. port_names[MODE] = strdup("Cross Mode");
  384. port_names[HAAS] = strdup("Haas Effect");
  385. port_names[REV_OUTCH] = strdup("Swap Outputs");
  386. port_names[INPUT_L] = strdup("Input Left");
  387. port_names[OUTPUT_L] = strdup("Output Left");
  388. port_names[INPUT_R] = strdup("Input Right");
  389. port_names[OUTPUT_R] = strdup("Output Right");
  390. if ((port_range_hints =
  391. ((LADSPA_PortRangeHint *)calloc(PORTCOUNT_STEREO, sizeof(LADSPA_PortRangeHint)))) == NULL)
  392. exit(1);
  393. stereo_descriptor->PortRangeHints = (const LADSPA_PortRangeHint *)port_range_hints;
  394. port_range_hints[DELAYTIME_L].HintDescriptor =
  395. (LADSPA_HINT_BOUNDED_BELOW |
  396. LADSPA_HINT_BOUNDED_ABOVE |
  397. LADSPA_HINT_DEFAULT_100);
  398. port_range_hints[DELAYTIME_L].LowerBound = 0;
  399. port_range_hints[DELAYTIME_L].UpperBound = MAX_DELAY;
  400. port_range_hints[DELAYTIME_R].HintDescriptor =
  401. (LADSPA_HINT_BOUNDED_BELOW |
  402. LADSPA_HINT_BOUNDED_ABOVE |
  403. LADSPA_HINT_DEFAULT_100);
  404. port_range_hints[DELAYTIME_R].LowerBound = 0;
  405. port_range_hints[DELAYTIME_R].UpperBound = MAX_DELAY;
  406. port_range_hints[FEEDBACK_L].HintDescriptor =
  407. (LADSPA_HINT_BOUNDED_BELOW |
  408. LADSPA_HINT_BOUNDED_ABOVE |
  409. LADSPA_HINT_DEFAULT_0);
  410. port_range_hints[FEEDBACK_L].LowerBound = 0;
  411. port_range_hints[FEEDBACK_L].UpperBound = 100;
  412. port_range_hints[FEEDBACK_R].HintDescriptor =
  413. (LADSPA_HINT_BOUNDED_BELOW |
  414. LADSPA_HINT_BOUNDED_ABOVE |
  415. LADSPA_HINT_DEFAULT_0);
  416. port_range_hints[FEEDBACK_R].LowerBound = 0;
  417. port_range_hints[FEEDBACK_R].UpperBound = 100;
  418. port_range_hints[STRENGTH_L].HintDescriptor =
  419. (LADSPA_HINT_BOUNDED_BELOW |
  420. LADSPA_HINT_BOUNDED_ABOVE |
  421. LADSPA_HINT_DEFAULT_0);
  422. port_range_hints[STRENGTH_L].LowerBound = -70;
  423. port_range_hints[STRENGTH_L].UpperBound = 10;
  424. port_range_hints[STRENGTH_R].HintDescriptor =
  425. (LADSPA_HINT_BOUNDED_BELOW |
  426. LADSPA_HINT_BOUNDED_ABOVE |
  427. LADSPA_HINT_DEFAULT_0);
  428. port_range_hints[STRENGTH_R].LowerBound = -70;
  429. port_range_hints[STRENGTH_R].UpperBound = 10;
  430. port_range_hints[MODE].HintDescriptor =
  431. (LADSPA_HINT_TOGGLED |
  432. LADSPA_HINT_DEFAULT_0);
  433. port_range_hints[HAAS].HintDescriptor =
  434. (LADSPA_HINT_TOGGLED |
  435. LADSPA_HINT_DEFAULT_0);
  436. port_range_hints[REV_OUTCH].HintDescriptor =
  437. (LADSPA_HINT_TOGGLED |
  438. LADSPA_HINT_DEFAULT_0);
  439. port_range_hints[DRYLEVEL].HintDescriptor =
  440. (LADSPA_HINT_BOUNDED_BELOW |
  441. LADSPA_HINT_BOUNDED_ABOVE |
  442. LADSPA_HINT_DEFAULT_0);
  443. port_range_hints[DRYLEVEL].LowerBound = -70;
  444. port_range_hints[DRYLEVEL].UpperBound = 10;
  445. port_range_hints[INPUT_L].HintDescriptor = 0;
  446. port_range_hints[OUTPUT_L].HintDescriptor = 0;
  447. port_range_hints[INPUT_R].HintDescriptor = 0;
  448. port_range_hints[OUTPUT_R].HintDescriptor = 0;
  449. stereo_descriptor->instantiate = instantiate_Echo;
  450. stereo_descriptor->connect_port = connect_port_Echo;
  451. stereo_descriptor->activate = activate_Echo;
  452. stereo_descriptor->run = run_Echo;
  453. stereo_descriptor->run_adding = run_adding_gain_Echo;
  454. stereo_descriptor->set_run_adding_gain = set_run_adding_gain;
  455. stereo_descriptor->deactivate = NULL;
  456. stereo_descriptor->cleanup = cleanup_Echo;
  457. }
  458. void
  459. delete_descriptor(LADSPA_Descriptor * descriptor) {
  460. unsigned long index;
  461. if (descriptor) {
  462. free((char *)descriptor->Label);
  463. free((char *)descriptor->Name);
  464. free((char *)descriptor->Maker);
  465. free((char *)descriptor->Copyright);
  466. free((LADSPA_PortDescriptor *)descriptor->PortDescriptors);
  467. for (index = 0; index < descriptor->PortCount; index++)
  468. free((char *)(descriptor->PortNames[index]));
  469. free((char **)descriptor->PortNames);
  470. free((LADSPA_PortRangeHint *)descriptor->PortRangeHints);
  471. free(descriptor);
  472. }
  473. }
  474. /* __attribute__((destructor)) tap_fini() is called automatically when the library is unloaded. */
  475. void
  476. __attribute__((destructor)) tap_fini() {
  477. delete_descriptor(stereo_descriptor);
  478. }
  479. /* Return a descriptor of the requested plugin type. */
  480. const
  481. LADSPA_Descriptor *
  482. ladspa_descriptor(unsigned long Index) {
  483. switch (Index) {
  484. case 0:
  485. return stereo_descriptor;
  486. default:
  487. return NULL;
  488. }
  489. }