tap_pinknoise.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  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_pinknoise.c,v 1.2 2004/08/13 18:34:31 tszilagyi Exp $
  15. */
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <math.h>
  20. #include <time.h>
  21. #include <ladspa.h>
  22. #include "tap_utils.h"
  23. /* The Unique ID of the plugin: */
  24. #define ID_MONO 2155
  25. /* The port numbers for the plugin: */
  26. #define HURST 0
  27. #define SIGNAL 1
  28. #define NOISE 2
  29. #define INPUT 3
  30. #define OUTPUT 4
  31. /* Total number of ports */
  32. #define PORTCOUNT_MONO 5
  33. #define NOISE_LEN 1024
  34. /* The structure used to hold port connection information and state */
  35. typedef struct {
  36. LADSPA_Data * hurst;
  37. LADSPA_Data * signal;
  38. LADSPA_Data * noise;
  39. LADSPA_Data * input;
  40. LADSPA_Data * output;
  41. LADSPA_Data * ring;
  42. unsigned long buflen;
  43. unsigned long pos;
  44. unsigned long sample_rate;
  45. LADSPA_Data run_adding_gain;
  46. } Pinknoise;
  47. /* generate fractal pattern using Midpoint Displacement Method
  48. * v: buffer of floats to output fractal pattern to
  49. * N: length of v, MUST be integer power of 2 (ie 128, 256, ...)
  50. * H: Hurst constant, between 0 and 0.9999 (fractal dimension)
  51. */
  52. void
  53. fractal(LADSPA_Data * v, int N, float H) {
  54. int l = N;
  55. int k;
  56. float r = 2.0f * H*H + 0.3f;
  57. int c;
  58. v[0] = 0;
  59. while (l > 1) {
  60. k = N / l;
  61. for (c = 0; c < k; c++) {
  62. v[c*l + l/2] = (v[c*l] + v[((c+1) * l) % N]) / 2.0f +
  63. 2.0f * r * (rand() - (float)RAND_MAX/2.0f) / (float)RAND_MAX;
  64. v[c*l + l/2] = LIMIT(v[c*l + l/2], -1.0f, 1.0f);
  65. }
  66. l /= 2;
  67. r /= powf(2, H);
  68. }
  69. }
  70. /* Construct a new plugin instance. */
  71. LADSPA_Handle
  72. instantiate_Pinknoise(const LADSPA_Descriptor * Descriptor,
  73. unsigned long SampleRate) {
  74. LADSPA_Handle * ptr;
  75. if ((ptr = malloc(sizeof(Pinknoise))) != NULL) {
  76. ((Pinknoise *)ptr)->sample_rate = SampleRate;
  77. ((Pinknoise *)ptr)->run_adding_gain = 1.0;
  78. if ((((Pinknoise *)ptr)->ring =
  79. calloc(NOISE_LEN, sizeof(LADSPA_Data))) == NULL)
  80. return NULL;
  81. ((Pinknoise *)ptr)->buflen = NOISE_LEN;
  82. ((Pinknoise *)ptr)->pos = 0;
  83. return ptr;
  84. }
  85. return NULL;
  86. }
  87. /* Connect a port to a data location. */
  88. void
  89. connect_port_Pinknoise(LADSPA_Handle Instance,
  90. unsigned long Port,
  91. LADSPA_Data * data) {
  92. Pinknoise * ptr;
  93. ptr = (Pinknoise *)Instance;
  94. switch (Port) {
  95. case HURST:
  96. ptr->hurst = data;
  97. break;
  98. case SIGNAL:
  99. ptr->signal = data;
  100. break;
  101. case NOISE:
  102. ptr->noise = data;
  103. break;
  104. case INPUT:
  105. ptr->input = data;
  106. break;
  107. case OUTPUT:
  108. ptr->output = data;
  109. break;
  110. }
  111. }
  112. void
  113. run_Pinknoise(LADSPA_Handle Instance,
  114. unsigned long SampleCount) {
  115. Pinknoise * ptr = (Pinknoise *)Instance;
  116. LADSPA_Data * input = ptr->input;
  117. LADSPA_Data * output = ptr->output;
  118. LADSPA_Data hurst = LIMIT(*(ptr->hurst), 0.0f, 1.0f);
  119. LADSPA_Data signal = db2lin(LIMIT(*(ptr->signal), -90.0f, 20.0f));
  120. LADSPA_Data noise = db2lin(LIMIT(*(ptr->noise), -90.0f, 20.0f));
  121. unsigned long sample_index;
  122. for (sample_index = 0; sample_index < SampleCount; sample_index++) {
  123. if (!ptr->pos)
  124. fractal(ptr->ring, NOISE_LEN, hurst);
  125. *(output++) = signal * *(input++) +
  126. noise * push_buffer(0.0f, ptr->ring, ptr->buflen, &(ptr->pos));
  127. }
  128. }
  129. void
  130. set_run_adding_gain_Pinknoise(LADSPA_Handle Instance, LADSPA_Data gain) {
  131. Pinknoise * ptr;
  132. ptr = (Pinknoise *)Instance;
  133. ptr->run_adding_gain = gain;
  134. }
  135. void
  136. run_adding_Pinknoise(LADSPA_Handle Instance,
  137. unsigned long SampleCount) {
  138. Pinknoise * ptr = (Pinknoise *)Instance;
  139. LADSPA_Data * input = ptr->input;
  140. LADSPA_Data * output = ptr->output;
  141. LADSPA_Data hurst = LIMIT(*(ptr->hurst), 0.0f, 1.0f);
  142. LADSPA_Data signal = db2lin(LIMIT(*(ptr->signal), -90.0f, 20.0f));
  143. LADSPA_Data noise = db2lin(LIMIT(*(ptr->noise), -90.0f, 20.0f));
  144. unsigned long sample_index;
  145. for (sample_index = 0; sample_index < SampleCount; sample_index++) {
  146. if (!ptr->pos)
  147. fractal(ptr->ring, NOISE_LEN, hurst);
  148. *(output++) += ptr->run_adding_gain * (signal * *(input++) +
  149. noise * push_buffer(0.0f, ptr->ring,
  150. ptr->buflen, &(ptr->pos)));
  151. }
  152. }
  153. /* Throw away a Pinknoise effect instance. */
  154. void
  155. cleanup_Pinknoise(LADSPA_Handle Instance) {
  156. Pinknoise * ptr = (Pinknoise *)Instance;
  157. free(ptr->ring);
  158. free(Instance);
  159. }
  160. LADSPA_Descriptor * mono_descriptor = NULL;
  161. /* __attribute__((constructor)) tap_init() is called automatically when the plugin library is first
  162. loaded. */
  163. void
  164. __attribute__((constructor)) tap_init() {
  165. char ** port_names;
  166. LADSPA_PortDescriptor * port_descriptors;
  167. LADSPA_PortRangeHint * port_range_hints;
  168. if ((mono_descriptor =
  169. (LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor))) == NULL)
  170. exit(1);
  171. /* initialize RNG */
  172. // srand(time(0));
  173. mono_descriptor->UniqueID = ID_MONO;
  174. mono_descriptor->Label = strdup("tap_pinknoise");
  175. mono_descriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE;
  176. mono_descriptor->Name = strdup("TAP Pink/Fractal Noise");
  177. mono_descriptor->Maker = strdup("Tom Szilagyi");
  178. mono_descriptor->Copyright = strdup("GPL");
  179. mono_descriptor->PortCount = PORTCOUNT_MONO;
  180. if ((port_descriptors =
  181. (LADSPA_PortDescriptor *)calloc(PORTCOUNT_MONO, sizeof(LADSPA_PortDescriptor))) == NULL)
  182. exit(1);
  183. mono_descriptor->PortDescriptors = (const LADSPA_PortDescriptor *)port_descriptors;
  184. port_descriptors[HURST] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
  185. port_descriptors[SIGNAL] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
  186. port_descriptors[NOISE] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
  187. port_descriptors[INPUT] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
  188. port_descriptors[OUTPUT] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
  189. if ((port_names =
  190. (char **)calloc(PORTCOUNT_MONO, sizeof(char *))) == NULL)
  191. exit(1);
  192. mono_descriptor->PortNames = (const char **)port_names;
  193. port_names[HURST] = strdup("Fractal Dimension");
  194. port_names[SIGNAL] = strdup("Signal Level [dB]");
  195. port_names[NOISE] = strdup("Noise Level [dB]");
  196. port_names[INPUT] = strdup("Input");
  197. port_names[OUTPUT] = strdup("Output");
  198. if ((port_range_hints =
  199. ((LADSPA_PortRangeHint *)calloc(PORTCOUNT_MONO, sizeof(LADSPA_PortRangeHint)))) == NULL)
  200. exit(1);
  201. mono_descriptor->PortRangeHints = (const LADSPA_PortRangeHint *)port_range_hints;
  202. port_range_hints[HURST].HintDescriptor =
  203. (LADSPA_HINT_BOUNDED_BELOW |
  204. LADSPA_HINT_BOUNDED_ABOVE |
  205. LADSPA_HINT_DEFAULT_MIDDLE);
  206. port_range_hints[SIGNAL].HintDescriptor =
  207. (LADSPA_HINT_BOUNDED_BELOW |
  208. LADSPA_HINT_BOUNDED_ABOVE |
  209. LADSPA_HINT_DEFAULT_0);
  210. port_range_hints[NOISE].HintDescriptor =
  211. (LADSPA_HINT_BOUNDED_BELOW |
  212. LADSPA_HINT_BOUNDED_ABOVE |
  213. LADSPA_HINT_DEFAULT_MINIMUM);
  214. port_range_hints[HURST].LowerBound = 0.0f;
  215. port_range_hints[HURST].UpperBound = 1.0f;
  216. port_range_hints[SIGNAL].LowerBound = -90.0f;
  217. port_range_hints[SIGNAL].UpperBound = 20.0f;
  218. port_range_hints[NOISE].LowerBound = -90.0f;
  219. port_range_hints[NOISE].UpperBound = 20.0f;
  220. port_range_hints[INPUT].HintDescriptor = 0;
  221. port_range_hints[OUTPUT].HintDescriptor = 0;
  222. mono_descriptor->instantiate = instantiate_Pinknoise;
  223. mono_descriptor->connect_port = connect_port_Pinknoise;
  224. mono_descriptor->activate = NULL;
  225. mono_descriptor->run = run_Pinknoise;
  226. mono_descriptor->run_adding = run_adding_Pinknoise;
  227. mono_descriptor->set_run_adding_gain = set_run_adding_gain_Pinknoise;
  228. mono_descriptor->deactivate = NULL;
  229. mono_descriptor->cleanup = cleanup_Pinknoise;
  230. }
  231. void
  232. delete_descriptor(LADSPA_Descriptor * descriptor) {
  233. unsigned long index;
  234. if (descriptor) {
  235. free((char *)descriptor->Label);
  236. free((char *)descriptor->Name);
  237. free((char *)descriptor->Maker);
  238. free((char *)descriptor->Copyright);
  239. free((LADSPA_PortDescriptor *)descriptor->PortDescriptors);
  240. for (index = 0; index < descriptor->PortCount; index++)
  241. free((char *)(descriptor->PortNames[index]));
  242. free((char **)descriptor->PortNames);
  243. free((LADSPA_PortRangeHint *)descriptor->PortRangeHints);
  244. free(descriptor);
  245. }
  246. }
  247. /* __attribute__((destructor)) tap_fini() is called automatically when the library is unloaded. */
  248. void
  249. __attribute__((destructor)) tap_fini() {
  250. delete_descriptor(mono_descriptor);
  251. }
  252. /* Return a descriptor of the requested plugin type. */
  253. const LADSPA_Descriptor *
  254. ladspa_descriptor(unsigned long Index) {
  255. switch (Index) {
  256. case 0:
  257. return mono_descriptor;
  258. default:
  259. return NULL;
  260. }
  261. }