plugins/distortion.cracked.js

  1. /**
  2. * Bitcrusher
  3. *
  4. * [See more bitcrusher examples](examples/distortion.html)
  5. *
  6. * @plugin
  7. * @category Distortion
  8. * @function
  9. * @memberof cracked
  10. * @name cracked#bitcrusher
  11. * @param {Object} [params] map of optional values
  12. * @param {Number} [params.frequency=0.1]
  13. * @param {Number} [params.bits=6]
  14. */
  15. cracked.bitcrusher = function (params) {
  16. //adapted from http://noisehack.com/custom-audio-effects-javascript-web-audio-api/
  17. params = params || {};
  18. __.begin("bitcrusher", params);
  19. __.script({
  20. fn: (function (options) {
  21. var bits = options.bits || 6; // between 1 and 16
  22. var normfreq = __.ifUndef(options.frequency, 0.1); // between 0.0 and 1.0
  23. var step = Math.pow(1 / 2, bits);
  24. var phaser = 0;
  25. var last = 0;
  26. function crusher(e) {
  27. var input = e.inputBuffer.getChannelData(0);
  28. var output = e.outputBuffer.getChannelData(0);
  29. for (var i = 0; i < 4096; i++) {
  30. phaser += normfreq;
  31. if (phaser >= 1.0) {
  32. phaser -= 1.0;
  33. last = step * Math.floor(input[i] / step + 0.5);
  34. }
  35. output[i] = last;
  36. }
  37. }
  38. return crusher;
  39. })(params)
  40. });
  41. __.end("bitcrusher");
  42. return cracked;
  43. };
  44. /**
  45. * Ring Modulator
  46. *
  47. * [See more ring modulator examples](examples/distortion.html)
  48. *
  49. * @plugin
  50. * @category Distortion
  51. * @function
  52. * @memberof cracked
  53. * @name cracked#ring
  54. * @param {Object} [params] map of optional values
  55. * @param {Number} [params.distortion=1]
  56. * @param {Number} [params.frequency=30]
  57. */
  58. cracked.ring = function (params) {
  59. //adapted from http://webaudio.prototyping.bbc.co.uk/ring-modulator/
  60. var options = params || {};
  61. var thisCurve = setCurve(__.ifUndef(options.distortion, 1));
  62. __.begin("ring", params);
  63. __.gain({
  64. id: "player"
  65. }).
  66. gain({
  67. id: "vcInverter1",
  68. gain: -1
  69. }).
  70. waveshaper({
  71. id: "vcDiode3",
  72. curve: thisCurve,
  73. mapping: {
  74. "distortion": {
  75. "path": "curve",
  76. "fn": (function () {
  77. return setCurve;
  78. })()
  79. }
  80. }
  81. }).
  82. compressor({
  83. threshold: -12
  84. });
  85. __("#player").
  86. waveshaper({
  87. id: "vInDiode4",
  88. curve: thisCurve,
  89. mapping: {
  90. "distortion": {
  91. "path": "curve",
  92. "fn": (function () {
  93. return setCurve;
  94. })()
  95. }
  96. }
  97. }).
  98. connect("compressor");
  99. __().sine({
  100. id: "vIn",
  101. frequency: options.frequency || 30,
  102. mapping: {
  103. "frequency": "frequency.value"
  104. }
  105. }).
  106. gain({
  107. id: "vInGain",
  108. gain: 0.5
  109. }).
  110. gain({
  111. id: "vInInverter1",
  112. gain: -1
  113. }).
  114. gain({
  115. id: "vInInverter2",
  116. gain: -1
  117. }).
  118. waveshaper({
  119. id: "vInDiode1",
  120. curve: thisCurve,
  121. mapping: {
  122. "distortion": {
  123. "path": "curve",
  124. "fn": (function () {
  125. return setCurve;
  126. })()
  127. }
  128. }
  129. }).
  130. gain({
  131. id: "vInInverter3",
  132. gain: -1
  133. }).
  134. connect("compressor");
  135. __("#vInGain").
  136. connect("#vInDiode4");
  137. __("#vInGain").
  138. connect("#vcInverter1");
  139. __("#vInInverter1").
  140. waveshaper({
  141. id: "vInDiode2",
  142. curve: thisCurve,
  143. mapping: {
  144. "distortion": {
  145. "path": "curve",
  146. "fn": (function () {
  147. return setCurve;
  148. })()
  149. }
  150. }
  151. }).
  152. connect("#vInInverter3");
  153. __("compressor").
  154. gain({
  155. id: "outGain",
  156. gain: 4
  157. });
  158. __.end("ring");
  159. return cracked;
  160. function setCurve(distortion) {
  161. var i, samples, v, value, wsCurve, _i, _ref, vb, vl, h;
  162. vb = 0.2;
  163. vl = 0.4;
  164. h = __.ifUndef(distortion, 1);
  165. samples = 1024;
  166. wsCurve = new Float32Array(samples);
  167. for (i = _i = 0, _ref = wsCurve.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
  168. v = (i - samples / 2) / (samples / 2);
  169. v = Math.abs(v);
  170. if (v <= vb) {
  171. value = 0;
  172. } else if ((vb < v) && (v <= vl)) {
  173. value = h * ((Math.pow(v - vb, 2)) / (2 * vl - 2 * vb));
  174. } else {
  175. value = h * v - h * vl + (h * ((Math.pow(vl - vb, 2)) / (2 * vl - 2 * vb)));
  176. }
  177. wsCurve[i] = value;
  178. }
  179. return wsCurve;
  180. }
  181. };
  182. //adapted from https://github.com/web-audio-components
  183. /**
  184. * Overdrive, waveshaper with additional parameters
  185. *
  186. * [See more overdrive examples](examples/distortion.html)
  187. *
  188. * @plugin
  189. * @category Distortion
  190. * @function
  191. * @memberof cracked
  192. * @name cracked#overdrive
  193. * @param {Object} [params] map of optional values
  194. * @param {Number} [params.drive=0.5]
  195. * @param {Number} [params.color=800]
  196. * @param {Number} [params.postCut=3000]
  197. */
  198. cracked.overdrive = function (params) {
  199. params = params || {};
  200. var drive = __.isObj(params) ? __.ifUndef(params.drive, 0.5) : params;
  201. __.begin("overdrive", params);
  202. __.gain({
  203. id: "input"
  204. }).
  205. bandpass({
  206. frequency: __.ifUndef(params.color, 800),
  207. mapping: {
  208. "color": "frequency.value"
  209. }
  210. }).
  211. waveshaper({
  212. curve: makeCurve(drive),
  213. mapping: {
  214. "drive": {
  215. "path": "curve",
  216. "fn": (function () {
  217. return makeCurve;
  218. })()
  219. }
  220. }
  221. }).
  222. lowpass({
  223. frequency: __.ifUndef(params.postCut, 3000),
  224. mapping: {
  225. "postCut": "frequency.value"
  226. }
  227. }).
  228. gain({
  229. id: "output"
  230. });
  231. __.end("overdrive");
  232. function makeCurve(value) {
  233. var k = value * 100,
  234. n = 22050,
  235. curve = new Float32Array(n),
  236. deg = Math.PI / 180;
  237. for (var i = 0; i < n; i++) {
  238. var x = i * 2 / n - 1;
  239. curve[i] = (3 + k) * x * 20 * deg / (Math.PI + k * Math.abs(x));
  240. }
  241. return curve;
  242. }
  243. return cracked;
  244. };