dsp.js 66 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322
  1. /*
  2. * DSP.js - a comprehensive digital signal processing library for javascript
  3. *
  4. * Created by Corban Brook <corbanbrook@gmail.com> on 2010-01-01.
  5. * Copyright 2010 Corban Brook. All rights reserved.
  6. *
  7. */
  8. ////////////////////////////////////////////////////////////////////////////////
  9. // CONSTANTS //
  10. ////////////////////////////////////////////////////////////////////////////////
  11. /**
  12. * DSP is an object which contains general purpose utility functions and constants
  13. */
  14. var DSP = {
  15. // Channels
  16. LEFT: 0,
  17. RIGHT: 1,
  18. MIX: 2,
  19. // Waveforms
  20. SINE: 1,
  21. TRIANGLE: 2,
  22. SAW: 3,
  23. SQUARE: 4,
  24. // Filters
  25. LOWPASS: 0,
  26. HIGHPASS: 1,
  27. BANDPASS: 2,
  28. NOTCH: 3,
  29. // Window functions
  30. BARTLETT: 1,
  31. BARTLETTHANN: 2,
  32. BLACKMAN: 3,
  33. COSINE: 4,
  34. GAUSS: 5,
  35. HAMMING: 6,
  36. HANN: 7,
  37. LANCZOS: 8,
  38. RECTANGULAR: 9,
  39. TRIANGULAR: 10,
  40. // Loop modes
  41. OFF: 0,
  42. FW: 1,
  43. BW: 2,
  44. FWBW: 3,
  45. // Math
  46. TWO_PI: 2*Math.PI
  47. };
  48. // Setup arrays for platforms which do not support byte arrays
  49. function setupTypedArray(name, fallback) {
  50. // check if TypedArray exists
  51. // typeof on Minefield and Chrome return function, typeof on Webkit returns object.
  52. if (typeof this[name] !== "function" && typeof this[name] !== "object") {
  53. // nope.. check if WebGLArray exists
  54. if (typeof this[fallback] === "function" && typeof this[fallback] !== "object") {
  55. this[name] = this[fallback];
  56. } else {
  57. // nope.. set as Native JS array
  58. this[name] = function(obj) {
  59. if (obj instanceof Array) {
  60. return obj;
  61. } else if (typeof obj === "number") {
  62. return new Array(obj);
  63. }
  64. };
  65. }
  66. }
  67. }
  68. setupTypedArray("Float64Array", "WebGLFloatArray");
  69. setupTypedArray("Int32Array", "WebGLIntArray");
  70. setupTypedArray("Uint16Array", "WebGLUnsignedShortArray");
  71. setupTypedArray("Uint8Array", "WebGLUnsignedByteArray");
  72. ////////////////////////////////////////////////////////////////////////////////
  73. // DSP UTILITY FUNCTIONS //
  74. ////////////////////////////////////////////////////////////////////////////////
  75. /**
  76. * Inverts the phase of a signal
  77. *
  78. * @param {Array} buffer A sample buffer
  79. *
  80. * @returns The inverted sample buffer
  81. */
  82. DSP.invert = function(buffer) {
  83. for (var i = 0, len = buffer.length; i < len; i++) {
  84. buffer[i] *= -1;
  85. }
  86. return buffer;
  87. };
  88. /**
  89. * Converts split-stereo (dual mono) sample buffers into a stereo interleaved sample buffer
  90. *
  91. * @param {Array} left A sample buffer
  92. * @param {Array} right A sample buffer
  93. *
  94. * @returns The stereo interleaved buffer
  95. */
  96. DSP.interleave = function(left, right) {
  97. if (left.length !== right.length) {
  98. throw "Can not interleave. Channel lengths differ.";
  99. }
  100. var stereoInterleaved = new Float64Array(left.length * 2);
  101. for (var i = 0, len = left.length; i < len; i++) {
  102. stereoInterleaved[2*i] = left[i];
  103. stereoInterleaved[2*i+1] = right[i];
  104. }
  105. return stereoInterleaved;
  106. };
  107. /**
  108. * Converts a stereo-interleaved sample buffer into split-stereo (dual mono) sample buffers
  109. *
  110. * @param {Array} buffer A stereo-interleaved sample buffer
  111. *
  112. * @returns an Array containing left and right channels
  113. */
  114. DSP.deinterleave = (function() {
  115. var left, right, mix, deinterleaveChannel = [];
  116. deinterleaveChannel[DSP.MIX] = function(buffer) {
  117. for (var i = 0, len = buffer.length/2; i < len; i++) {
  118. mix[i] = (buffer[2*i] + buffer[2*i+1]) / 2;
  119. }
  120. return mix;
  121. };
  122. deinterleaveChannel[DSP.LEFT] = function(buffer) {
  123. for (var i = 0, len = buffer.length/2; i < len; i++) {
  124. left[i] = buffer[2*i];
  125. }
  126. return left;
  127. };
  128. deinterleaveChannel[DSP.RIGHT] = function(buffer) {
  129. for (var i = 0, len = buffer.length/2; i < len; i++) {
  130. right[i] = buffer[2*i+1];
  131. }
  132. return right;
  133. };
  134. return function(channel, buffer) {
  135. left = left || new Float64Array(buffer.length/2);
  136. right = right || new Float64Array(buffer.length/2);
  137. mix = mix || new Float64Array(buffer.length/2);
  138. if (buffer.length/2 !== left.length) {
  139. left = new Float64Array(buffer.length/2);
  140. right = new Float64Array(buffer.length/2);
  141. mix = new Float64Array(buffer.length/2);
  142. }
  143. return deinterleaveChannel[channel](buffer);
  144. };
  145. }());
  146. /**
  147. * Separates a channel from a stereo-interleaved sample buffer
  148. *
  149. * @param {Array} buffer A stereo-interleaved sample buffer
  150. * @param {Number} channel A channel constant (LEFT, RIGHT, MIX)
  151. *
  152. * @returns an Array containing a signal mono sample buffer
  153. */
  154. DSP.getChannel = DSP.deinterleave;
  155. /**
  156. * Helper method (for Reverb) to mix two (interleaved) samplebuffers. It's possible
  157. * to negate the second buffer while mixing and to perform a volume correction
  158. * on the final signal.
  159. *
  160. * @param {Array} sampleBuffer1 Array containing Float values or a Float64Array
  161. * @param {Array} sampleBuffer2 Array containing Float values or a Float64Array
  162. * @param {Boolean} negate When true inverts/flips the audio signal
  163. * @param {Number} volumeCorrection When you add multiple sample buffers, use this to tame your signal ;)
  164. *
  165. * @returns A new Float64Array interleaved buffer.
  166. */
  167. DSP.mixSampleBuffers = function(sampleBuffer1, sampleBuffer2, negate, volumeCorrection){
  168. var outputSamples = new Float64Array(sampleBuffer1);
  169. for(var i = 0; i<sampleBuffer1.length; i++){
  170. outputSamples[i] += (negate ? -sampleBuffer2[i] : sampleBuffer2[i]) / volumeCorrection;
  171. }
  172. return outputSamples;
  173. };
  174. // Biquad filter types
  175. DSP.LPF = 0; // H(s) = 1 / (s^2 + s/Q + 1)
  176. DSP.HPF = 1; // H(s) = s^2 / (s^2 + s/Q + 1)
  177. DSP.BPF_CONSTANT_SKIRT = 2; // H(s) = s / (s^2 + s/Q + 1) (constant skirt gain, peak gain = Q)
  178. DSP.BPF_CONSTANT_PEAK = 3; // H(s) = (s/Q) / (s^2 + s/Q + 1) (constant 0 dB peak gain)
  179. DSP.NOTCH = 4; // H(s) = (s^2 + 1) / (s^2 + s/Q + 1)
  180. DSP.APF = 5; // H(s) = (s^2 - s/Q + 1) / (s^2 + s/Q + 1)
  181. DSP.PEAKING_EQ = 6; // H(s) = (s^2 + s*(A/Q) + 1) / (s^2 + s/(A*Q) + 1)
  182. DSP.LOW_SHELF = 7; // H(s) = A * (s^2 + (sqrt(A)/Q)*s + A)/(A*s^2 + (sqrt(A)/Q)*s + 1)
  183. DSP.HIGH_SHELF = 8; // H(s) = A * (A*s^2 + (sqrt(A)/Q)*s + 1)/(s^2 + (sqrt(A)/Q)*s + A)
  184. // Biquad filter parameter types
  185. DSP.Q = 1;
  186. DSP.BW = 2; // SHARED with BACKWARDS LOOP MODE
  187. DSP.S = 3;
  188. // Find RMS of signal
  189. DSP.RMS = function(buffer) {
  190. var total = 0;
  191. for (var i = 0, n = buffer.length; i < n; i++) {
  192. total += buffer[i] * buffer[i];
  193. }
  194. return Math.sqrt(total / n);
  195. };
  196. // Find Peak of signal
  197. DSP.Peak = function(buffer) {
  198. var peak = 0;
  199. for (var i = 0, n = buffer.length; i < n; i++) {
  200. peak = (Math.abs(buffer[i]) > peak) ? Math.abs(buffer[i]) : peak;
  201. }
  202. return peak;
  203. };
  204. // Fourier Transform Module used by DFT, FFT, RFFT
  205. function FourierTransform(bufferSize, sampleRate) {
  206. this.bufferSize = bufferSize;
  207. this.sampleRate = sampleRate;
  208. this.bandwidth = 2 / bufferSize * sampleRate / 2;
  209. this.spectrum = new Float64Array(bufferSize/2);
  210. this.real = new Float64Array(bufferSize);
  211. this.imag = new Float64Array(bufferSize);
  212. this.peakBand = 0;
  213. this.peak = 0;
  214. /**
  215. * Calculates the *middle* frequency of an FFT band.
  216. *
  217. * @param {Number} index The index of the FFT band.
  218. *
  219. * @returns The middle frequency in Hz.
  220. */
  221. this.getBandFrequency = function(index) {
  222. return this.bandwidth * index + this.bandwidth / 2;
  223. };
  224. this.calculateSpectrum = function() {
  225. var spectrum = this.spectrum,
  226. real = this.real,
  227. imag = this.imag,
  228. bSi = 2 / this.bufferSize,
  229. sqrt = Math.sqrt,
  230. rval,
  231. ival,
  232. mag;
  233. for (var i = 0, N = bufferSize/2; i < N; i++) {
  234. rval = real[i];
  235. ival = imag[i];
  236. mag = bSi * sqrt(rval * rval + ival * ival);
  237. if (mag > this.peak) {
  238. this.peakBand = i;
  239. this.peak = mag;
  240. }
  241. spectrum[i] = mag;
  242. }
  243. };
  244. }
  245. /**
  246. * DFT is a class for calculating the Discrete Fourier Transform of a signal.
  247. *
  248. * @param {Number} bufferSize The size of the sample buffer to be computed
  249. * @param {Number} sampleRate The sampleRate of the buffer (eg. 44100)
  250. *
  251. * @constructor
  252. */
  253. function DFT(bufferSize, sampleRate) {
  254. FourierTransform.call(this, bufferSize, sampleRate);
  255. var N = bufferSize/2 * bufferSize;
  256. var TWO_PI = 2 * Math.PI;
  257. this.sinTable = new Float64Array(N);
  258. this.cosTable = new Float64Array(N);
  259. for (var i = 0; i < N; i++) {
  260. this.sinTable[i] = Math.sin(i * TWO_PI / bufferSize);
  261. this.cosTable[i] = Math.cos(i * TWO_PI / bufferSize);
  262. }
  263. }
  264. /**
  265. * Performs a forward transform on the sample buffer.
  266. * Converts a time domain signal to frequency domain spectra.
  267. *
  268. * @param {Array} buffer The sample buffer
  269. *
  270. * @returns The frequency spectrum array
  271. */
  272. DFT.prototype.forward = function(buffer) {
  273. var real = this.real,
  274. imag = this.imag,
  275. rval,
  276. ival;
  277. for (var k = 0; k < this.bufferSize/2; k++) {
  278. rval = 0.0;
  279. ival = 0.0;
  280. for (var n = 0; n < buffer.length; n++) {
  281. rval += this.cosTable[k*n] * buffer[n];
  282. ival += this.sinTable[k*n] * buffer[n];
  283. }
  284. real[k] = rval;
  285. imag[k] = ival;
  286. }
  287. return this.calculateSpectrum();
  288. };
  289. /**
  290. * FFT is a class for calculating the Discrete Fourier Transform of a signal
  291. * with the Fast Fourier Transform algorithm.
  292. *
  293. * @param {Number} bufferSize The size of the sample buffer to be computed. Must be power of 2
  294. * @param {Number} sampleRate The sampleRate of the buffer (eg. 44100)
  295. *
  296. * @constructor
  297. */
  298. function FFT(bufferSize, sampleRate) {
  299. FourierTransform.call(this, bufferSize, sampleRate);
  300. this.reverseTable = new Uint32Array(bufferSize);
  301. var limit = 1;
  302. var bit = bufferSize >> 1;
  303. var i;
  304. while (limit < bufferSize) {
  305. for (i = 0; i < limit; i++) {
  306. this.reverseTable[i + limit] = this.reverseTable[i] + bit;
  307. }
  308. limit = limit << 1;
  309. bit = bit >> 1;
  310. }
  311. this.sinTable = new Float64Array(bufferSize);
  312. this.cosTable = new Float64Array(bufferSize);
  313. for (i = 0; i < bufferSize; i++) {
  314. this.sinTable[i] = Math.sin(-Math.PI/i);
  315. this.cosTable[i] = Math.cos(-Math.PI/i);
  316. }
  317. }
  318. /**
  319. * Performs a forward transform on the sample buffer.
  320. * Converts a time domain signal to frequency domain spectra.
  321. *
  322. * @param {Array} buffer The sample buffer. Buffer Length must be power of 2
  323. *
  324. * @returns The frequency spectrum array
  325. */
  326. FFT.prototype.forward = function(buffer) {
  327. // Locally scope variables for speed up
  328. var bufferSize = this.bufferSize,
  329. cosTable = this.cosTable,
  330. sinTable = this.sinTable,
  331. reverseTable = this.reverseTable,
  332. real = this.real,
  333. imag = this.imag,
  334. spectrum = this.spectrum;
  335. var k = Math.floor(Math.log(bufferSize) / Math.LN2);
  336. if (Math.pow(2, k) !== bufferSize) { throw "Invalid buffer size, must be a power of 2."; }
  337. if (bufferSize !== buffer.length) { throw "Supplied buffer is not the same size as defined FFT. FFT Size: " + bufferSize + " Buffer Size: " + buffer.length; }
  338. var halfSize = 1,
  339. phaseShiftStepReal,
  340. phaseShiftStepImag,
  341. currentPhaseShiftReal,
  342. currentPhaseShiftImag,
  343. off,
  344. tr,
  345. ti,
  346. tmpReal,
  347. i;
  348. for (i = 0; i < bufferSize; i++) {
  349. real[i] = buffer[reverseTable[i]];
  350. imag[i] = 0;
  351. }
  352. while (halfSize < bufferSize) {
  353. //phaseShiftStepReal = Math.cos(-Math.PI/halfSize);
  354. //phaseShiftStepImag = Math.sin(-Math.PI/halfSize);
  355. phaseShiftStepReal = cosTable[halfSize];
  356. phaseShiftStepImag = sinTable[halfSize];
  357. currentPhaseShiftReal = 1;
  358. currentPhaseShiftImag = 0;
  359. for (var fftStep = 0; fftStep < halfSize; fftStep++) {
  360. i = fftStep;
  361. while (i < bufferSize) {
  362. off = i + halfSize;
  363. tr = (currentPhaseShiftReal * real[off]) - (currentPhaseShiftImag * imag[off]);
  364. ti = (currentPhaseShiftReal * imag[off]) + (currentPhaseShiftImag * real[off]);
  365. real[off] = real[i] - tr;
  366. imag[off] = imag[i] - ti;
  367. real[i] += tr;
  368. imag[i] += ti;
  369. i += halfSize << 1;
  370. }
  371. tmpReal = currentPhaseShiftReal;
  372. currentPhaseShiftReal = (tmpReal * phaseShiftStepReal) - (currentPhaseShiftImag * phaseShiftStepImag);
  373. currentPhaseShiftImag = (tmpReal * phaseShiftStepImag) + (currentPhaseShiftImag * phaseShiftStepReal);
  374. }
  375. halfSize = halfSize << 1;
  376. }
  377. return this.calculateSpectrum();
  378. };
  379. FFT.prototype.inverse = function(real, imag) {
  380. // Locally scope variables for speed up
  381. var bufferSize = this.bufferSize,
  382. cosTable = this.cosTable,
  383. sinTable = this.sinTable,
  384. reverseTable = this.reverseTable,
  385. spectrum = this.spectrum;
  386. real = real || this.real;
  387. imag = imag || this.imag;
  388. var halfSize = 1,
  389. phaseShiftStepReal,
  390. phaseShiftStepImag,
  391. currentPhaseShiftReal,
  392. currentPhaseShiftImag,
  393. off,
  394. tr,
  395. ti,
  396. tmpReal,
  397. i;
  398. for (i = 0; i < bufferSize; i++) {
  399. imag[i] *= -1;
  400. }
  401. var revReal = new Float64Array(bufferSize);
  402. var revImag = new Float64Array(bufferSize);
  403. for (i = 0; i < real.length; i++) {
  404. revReal[i] = real[reverseTable[i]];
  405. revImag[i] = imag[reverseTable[i]];
  406. }
  407. real = revReal;
  408. imag = revImag;
  409. while (halfSize < bufferSize) {
  410. phaseShiftStepReal = cosTable[halfSize];
  411. phaseShiftStepImag = sinTable[halfSize];
  412. currentPhaseShiftReal = 1;
  413. currentPhaseShiftImag = 0;
  414. for (var fftStep = 0; fftStep < halfSize; fftStep++) {
  415. i = fftStep;
  416. while (i < bufferSize) {
  417. off = i + halfSize;
  418. tr = (currentPhaseShiftReal * real[off]) - (currentPhaseShiftImag * imag[off]);
  419. ti = (currentPhaseShiftReal * imag[off]) + (currentPhaseShiftImag * real[off]);
  420. real[off] = real[i] - tr;
  421. imag[off] = imag[i] - ti;
  422. real[i] += tr;
  423. imag[i] += ti;
  424. i += halfSize << 1;
  425. }
  426. tmpReal = currentPhaseShiftReal;
  427. currentPhaseShiftReal = (tmpReal * phaseShiftStepReal) - (currentPhaseShiftImag * phaseShiftStepImag);
  428. currentPhaseShiftImag = (tmpReal * phaseShiftStepImag) + (currentPhaseShiftImag * phaseShiftStepReal);
  429. }
  430. halfSize = halfSize << 1;
  431. }
  432. var buffer = new Float64Array(bufferSize); // this should be reused instead
  433. for (i = 0; i < bufferSize; i++) {
  434. buffer[i] = real[i] / bufferSize;
  435. }
  436. return buffer;
  437. };
  438. /**
  439. * RFFT is a class for calculating the Discrete Fourier Transform of a signal
  440. * with the Fast Fourier Transform algorithm.
  441. *
  442. * This method currently only contains a forward transform but is highly optimized.
  443. *
  444. * @param {Number} bufferSize The size of the sample buffer to be computed. Must be power of 2
  445. * @param {Number} sampleRate The sampleRate of the buffer (eg. 44100)
  446. *
  447. * @constructor
  448. */
  449. // lookup tables don't really gain us any speed, but they do increase
  450. // cache footprint, so don't use them in here
  451. // also we don't use sepearate arrays for real/imaginary parts
  452. // this one a little more than twice as fast as the one in FFT
  453. // however I only did the forward transform
  454. // the rest of this was translated from C, see http://www.jjj.de/fxt/
  455. // this is the real split radix FFT
  456. function RFFT(bufferSize, sampleRate) {
  457. FourierTransform.call(this, bufferSize, sampleRate);
  458. this.trans = new Float64Array(bufferSize);
  459. this.reverseTable = new Uint32Array(bufferSize);
  460. // don't use a lookup table to do the permute, use this instead
  461. this.reverseBinPermute = function (dest, source) {
  462. var bufferSize = this.bufferSize,
  463. halfSize = bufferSize >>> 1,
  464. nm1 = bufferSize - 1,
  465. i = 1, r = 0, h;
  466. dest[0] = source[0];
  467. do {
  468. r += halfSize;
  469. dest[i] = source[r];
  470. dest[r] = source[i];
  471. i++;
  472. h = halfSize << 1;
  473. while (h = h >> 1, !((r ^= h) & h));
  474. if (r >= i) {
  475. dest[i] = source[r];
  476. dest[r] = source[i];
  477. dest[nm1-i] = source[nm1-r];
  478. dest[nm1-r] = source[nm1-i];
  479. }
  480. i++;
  481. } while (i < halfSize);
  482. dest[nm1] = source[nm1];
  483. };
  484. this.generateReverseTable = function () {
  485. var bufferSize = this.bufferSize,
  486. halfSize = bufferSize >>> 1,
  487. nm1 = bufferSize - 1,
  488. i = 1, r = 0, h;
  489. this.reverseTable[0] = 0;
  490. do {
  491. r += halfSize;
  492. this.reverseTable[i] = r;
  493. this.reverseTable[r] = i;
  494. i++;
  495. h = halfSize << 1;
  496. while (h = h >> 1, !((r ^= h) & h));
  497. if (r >= i) {
  498. this.reverseTable[i] = r;
  499. this.reverseTable[r] = i;
  500. this.reverseTable[nm1-i] = nm1-r;
  501. this.reverseTable[nm1-r] = nm1-i;
  502. }
  503. i++;
  504. } while (i < halfSize);
  505. this.reverseTable[nm1] = nm1;
  506. };
  507. this.generateReverseTable();
  508. }
  509. // Ordering of output:
  510. //
  511. // trans[0] = re[0] (==zero frequency, purely real)
  512. // trans[1] = re[1]
  513. // ...
  514. // trans[n/2-1] = re[n/2-1]
  515. // trans[n/2] = re[n/2] (==nyquist frequency, purely real)
  516. //
  517. // trans[n/2+1] = im[n/2-1]
  518. // trans[n/2+2] = im[n/2-2]
  519. // ...
  520. // trans[n-1] = im[1]
  521. RFFT.prototype.forward = function(buffer) {
  522. var n = this.bufferSize,
  523. spectrum = this.spectrum,
  524. x = this.trans,
  525. TWO_PI = 2*Math.PI,
  526. sqrt = Math.sqrt,
  527. i = n >>> 1,
  528. bSi = 2 / n,
  529. n2, n4, n8, nn,
  530. t1, t2, t3, t4,
  531. i1, i2, i3, i4, i5, i6, i7, i8,
  532. st1, cc1, ss1, cc3, ss3,
  533. e,
  534. a,
  535. rval, ival, mag;
  536. this.reverseBinPermute(x, buffer);
  537. /*
  538. var reverseTable = this.reverseTable;
  539. for (var k = 0, len = reverseTable.length; k < len; k++) {
  540. x[k] = buffer[reverseTable[k]];
  541. }
  542. */
  543. for (var ix = 0, id = 4; ix < n; id *= 4) {
  544. for (var i0 = ix; i0 < n; i0 += id) {
  545. //sumdiff(x[i0], x[i0+1]); // {a, b} <--| {a+b, a-b}
  546. st1 = x[i0] - x[i0+1];
  547. x[i0] += x[i0+1];
  548. x[i0+1] = st1;
  549. }
  550. ix = 2*(id-1);
  551. }
  552. n2 = 2;
  553. nn = n >>> 1;
  554. while((nn = nn >>> 1)) {
  555. ix = 0;
  556. n2 = n2 << 1;
  557. id = n2 << 1;
  558. n4 = n2 >>> 2;
  559. n8 = n2 >>> 3;
  560. do {
  561. if(n4 !== 1) {
  562. for(i0 = ix; i0 < n; i0 += id) {
  563. i1 = i0;
  564. i2 = i1 + n4;
  565. i3 = i2 + n4;
  566. i4 = i3 + n4;
  567. //diffsum3_r(x[i3], x[i4], t1); // {a, b, s} <--| {a, b-a, a+b}
  568. t1 = x[i3] + x[i4];
  569. x[i4] -= x[i3];
  570. //sumdiff3(x[i1], t1, x[i3]); // {a, b, d} <--| {a+b, b, a-b}
  571. x[i3] = x[i1] - t1;
  572. x[i1] += t1;
  573. i1 += n8;
  574. i2 += n8;
  575. i3 += n8;
  576. i4 += n8;
  577. //sumdiff(x[i3], x[i4], t1, t2); // {s, d} <--| {a+b, a-b}
  578. t1 = x[i3] + x[i4];
  579. t2 = x[i3] - x[i4];
  580. t1 = -t1 * Math.SQRT1_2;
  581. t2 *= Math.SQRT1_2;
  582. // sumdiff(t1, x[i2], x[i4], x[i3]); // {s, d} <--| {a+b, a-b}
  583. st1 = x[i2];
  584. x[i4] = t1 + st1;
  585. x[i3] = t1 - st1;
  586. //sumdiff3(x[i1], t2, x[i2]); // {a, b, d} <--| {a+b, b, a-b}
  587. x[i2] = x[i1] - t2;
  588. x[i1] += t2;
  589. }
  590. } else {
  591. for(i0 = ix; i0 < n; i0 += id) {
  592. i1 = i0;
  593. i2 = i1 + n4;
  594. i3 = i2 + n4;
  595. i4 = i3 + n4;
  596. //diffsum3_r(x[i3], x[i4], t1); // {a, b, s} <--| {a, b-a, a+b}
  597. t1 = x[i3] + x[i4];
  598. x[i4] -= x[i3];
  599. //sumdiff3(x[i1], t1, x[i3]); // {a, b, d} <--| {a+b, b, a-b}
  600. x[i3] = x[i1] - t1;
  601. x[i1] += t1;
  602. }
  603. }
  604. ix = (id << 1) - n2;
  605. id = id << 2;
  606. } while (ix < n);
  607. e = TWO_PI / n2;
  608. for (var j = 1; j < n8; j++) {
  609. a = j * e;
  610. ss1 = Math.sin(a);
  611. cc1 = Math.cos(a);
  612. //ss3 = sin(3*a); cc3 = cos(3*a);
  613. cc3 = 4*cc1*(cc1*cc1-0.75);
  614. ss3 = 4*ss1*(0.75-ss1*ss1);
  615. ix = 0; id = n2 << 1;
  616. do {
  617. for (i0 = ix; i0 < n; i0 += id) {
  618. i1 = i0 + j;
  619. i2 = i1 + n4;
  620. i3 = i2 + n4;
  621. i4 = i3 + n4;
  622. i5 = i0 + n4 - j;
  623. i6 = i5 + n4;
  624. i7 = i6 + n4;
  625. i8 = i7 + n4;
  626. //cmult(c, s, x, y, &u, &v)
  627. //cmult(cc1, ss1, x[i7], x[i3], t2, t1); // {u,v} <--| {x*c-y*s, x*s+y*c}
  628. t2 = x[i7]*cc1 - x[i3]*ss1;
  629. t1 = x[i7]*ss1 + x[i3]*cc1;
  630. //cmult(cc3, ss3, x[i8], x[i4], t4, t3);
  631. t4 = x[i8]*cc3 - x[i4]*ss3;
  632. t3 = x[i8]*ss3 + x[i4]*cc3;
  633. //sumdiff(t2, t4); // {a, b} <--| {a+b, a-b}
  634. st1 = t2 - t4;
  635. t2 += t4;
  636. t4 = st1;
  637. //sumdiff(t2, x[i6], x[i8], x[i3]); // {s, d} <--| {a+b, a-b}
  638. //st1 = x[i6]; x[i8] = t2 + st1; x[i3] = t2 - st1;
  639. x[i8] = t2 + x[i6];
  640. x[i3] = t2 - x[i6];
  641. //sumdiff_r(t1, t3); // {a, b} <--| {a+b, b-a}
  642. st1 = t3 - t1;
  643. t1 += t3;
  644. t3 = st1;
  645. //sumdiff(t3, x[i2], x[i4], x[i7]); // {s, d} <--| {a+b, a-b}
  646. //st1 = x[i2]; x[i4] = t3 + st1; x[i7] = t3 - st1;
  647. x[i4] = t3 + x[i2];
  648. x[i7] = t3 - x[i2];
  649. //sumdiff3(x[i1], t1, x[i6]); // {a, b, d} <--| {a+b, b, a-b}
  650. x[i6] = x[i1] - t1;
  651. x[i1] += t1;
  652. //diffsum3_r(t4, x[i5], x[i2]); // {a, b, s} <--| {a, b-a, a+b}
  653. x[i2] = t4 + x[i5];
  654. x[i5] -= t4;
  655. }
  656. ix = (id << 1) - n2;
  657. id = id << 2;
  658. } while (ix < n);
  659. }
  660. }
  661. while (--i) {
  662. rval = x[i];
  663. ival = x[n-i-1];
  664. mag = bSi * sqrt(rval * rval + ival * ival);
  665. if (mag > this.peak) {
  666. this.peakBand = i;
  667. this.peak = mag;
  668. }
  669. spectrum[i] = mag;
  670. }
  671. spectrum[0] = bSi * x[0];
  672. return spectrum;
  673. };
  674. function Sampler(file, bufferSize, sampleRate, playStart, playEnd, loopStart, loopEnd, loopMode) {
  675. this.file = file;
  676. this.bufferSize = bufferSize;
  677. this.sampleRate = sampleRate;
  678. this.playStart = playStart || 0; // 0%
  679. this.playEnd = playEnd || 1; // 100%
  680. this.loopStart = loopStart || 0;
  681. this.loopEnd = loopEnd || 1;
  682. this.loopMode = loopMode || DSP.OFF;
  683. this.loaded = false;
  684. this.samples = [];
  685. this.signal = new Float64Array(bufferSize);
  686. this.frameCount = 0;
  687. this.envelope = null;
  688. this.amplitude = 1;
  689. this.rootFrequency = 110; // A2 110
  690. this.frequency = 550;
  691. this.step = this.frequency / this.rootFrequency;
  692. this.duration = 0;
  693. this.samplesProcessed = 0;
  694. this.playhead = 0;
  695. var audio = /* new Audio();*/ document.createElement("AUDIO");
  696. var self = this;
  697. this.loadSamples = function(event) {
  698. var buffer = DSP.getChannel(DSP.MIX, event.frameBuffer);
  699. for ( var i = 0; i < buffer.length; i++) {
  700. self.samples.push(buffer[i]);
  701. }
  702. };
  703. this.loadComplete = function() {
  704. // convert flexible js array into a fast typed array
  705. self.samples = new Float64Array(self.samples);
  706. self.loaded = true;
  707. };
  708. this.loadMetaData = function() {
  709. self.duration = audio.duration;
  710. };
  711. audio.addEventListener("MozAudioAvailable", this.loadSamples, false);
  712. audio.addEventListener("loadedmetadata", this.loadMetaData, false);
  713. audio.addEventListener("ended", this.loadComplete, false);
  714. audio.muted = true;
  715. audio.src = file;
  716. audio.play();
  717. }
  718. Sampler.prototype.applyEnvelope = function() {
  719. this.envelope.process(this.signal);
  720. return this.signal;
  721. };
  722. Sampler.prototype.generate = function() {
  723. var frameOffset = this.frameCount * this.bufferSize;
  724. var loopWidth = this.playEnd * this.samples.length - this.playStart * this.samples.length;
  725. var playStartSamples = this.playStart * this.samples.length; // ie 0.5 -> 50% of the length
  726. var playEndSamples = this.playEnd * this.samples.length; // ie 0.5 -> 50% of the length
  727. var offset;
  728. for ( var i = 0; i < this.bufferSize; i++ ) {
  729. switch (this.loopMode) {
  730. case DSP.OFF:
  731. this.playhead = Math.round(this.samplesProcessed * this.step + playStartSamples);
  732. if (this.playhead < (this.playEnd * this.samples.length) ) {
  733. this.signal[i] = this.samples[this.playhead] * this.amplitude;
  734. } else {
  735. this.signal[i] = 0;
  736. }
  737. break;
  738. case DSP.FW:
  739. this.playhead = Math.round((this.samplesProcessed * this.step) % loopWidth + playStartSamples);
  740. if (this.playhead < (this.playEnd * this.samples.length) ) {
  741. this.signal[i] = this.samples[this.playhead] * this.amplitude;
  742. }
  743. break;
  744. case DSP.BW:
  745. this.playhead = playEndSamples - Math.round((this.samplesProcessed * this.step) % loopWidth);
  746. if (this.playhead < (this.playEnd * this.samples.length) ) {
  747. this.signal[i] = this.samples[this.playhead] * this.amplitude;
  748. }
  749. break;
  750. case DSP.FWBW:
  751. if ( Math.floor(this.samplesProcessed * this.step / loopWidth) % 2 === 0 ) {
  752. this.playhead = Math.round((this.samplesProcessed * this.step) % loopWidth + playStartSamples);
  753. } else {
  754. this.playhead = playEndSamples - Math.round((this.samplesProcessed * this.step) % loopWidth);
  755. }
  756. if (this.playhead < (this.playEnd * this.samples.length) ) {
  757. this.signal[i] = this.samples[this.playhead] * this.amplitude;
  758. }
  759. break;
  760. }
  761. this.samplesProcessed++;
  762. }
  763. this.frameCount++;
  764. return this.signal;
  765. };
  766. Sampler.prototype.setFreq = function(frequency) {
  767. var totalProcessed = this.samplesProcessed * this.step;
  768. this.frequency = frequency;
  769. this.step = this.frequency / this.rootFrequency;
  770. this.samplesProcessed = Math.round(totalProcessed/this.step);
  771. };
  772. Sampler.prototype.reset = function() {
  773. this.samplesProcessed = 0;
  774. this.playhead = 0;
  775. };
  776. /**
  777. * Oscillator class for generating and modifying signals
  778. *
  779. * @param {Number} type A waveform constant (eg. DSP.SINE)
  780. * @param {Number} frequency Initial frequency of the signal
  781. * @param {Number} amplitude Initial amplitude of the signal
  782. * @param {Number} bufferSize Size of the sample buffer to generate
  783. * @param {Number} sampleRate The sample rate of the signal
  784. *
  785. * @contructor
  786. */
  787. function Oscillator(type, frequency, amplitude, bufferSize, sampleRate) {
  788. this.frequency = frequency;
  789. this.amplitude = amplitude;
  790. this.bufferSize = bufferSize;
  791. this.sampleRate = sampleRate;
  792. //this.pulseWidth = pulseWidth;
  793. this.frameCount = 0;
  794. this.waveTableLength = 2048;
  795. this.cyclesPerSample = frequency / sampleRate;
  796. this.signal = new Float64Array(bufferSize);
  797. this.envelope = null;
  798. switch(parseInt(type, 10)) {
  799. case DSP.TRIANGLE:
  800. this.func = Oscillator.Triangle;
  801. break;
  802. case DSP.SAW:
  803. this.func = Oscillator.Saw;
  804. break;
  805. case DSP.SQUARE:
  806. this.func = Oscillator.Square;
  807. break;
  808. default:
  809. case DSP.SINE:
  810. this.func = Oscillator.Sine;
  811. break;
  812. }
  813. this.generateWaveTable = function() {
  814. Oscillator.waveTable[this.func] = new Float64Array(2048);
  815. var waveTableTime = this.waveTableLength / this.sampleRate;
  816. var waveTableHz = 1 / waveTableTime;
  817. for (var i = 0; i < this.waveTableLength; i++) {
  818. Oscillator.waveTable[this.func][i] = this.func(i * waveTableHz/this.sampleRate);
  819. }
  820. };
  821. if ( typeof Oscillator.waveTable === 'undefined' ) {
  822. Oscillator.waveTable = {};
  823. }
  824. if ( typeof Oscillator.waveTable[this.func] === 'undefined' ) {
  825. this.generateWaveTable();
  826. }
  827. this.waveTable = Oscillator.waveTable[this.func];
  828. }
  829. /**
  830. * Set the amplitude of the signal
  831. *
  832. * @param {Number} amplitude The amplitude of the signal (between 0 and 1)
  833. */
  834. Oscillator.prototype.setAmp = function(amplitude) {
  835. if (amplitude >= 0 && amplitude <= 1) {
  836. this.amplitude = amplitude;
  837. } else {
  838. throw "Amplitude out of range (0..1).";
  839. }
  840. };
  841. /**
  842. * Set the frequency of the signal
  843. *
  844. * @param {Number} frequency The frequency of the signal
  845. */
  846. Oscillator.prototype.setFreq = function(frequency) {
  847. this.frequency = frequency;
  848. this.cyclesPerSample = frequency / this.sampleRate;
  849. };
  850. // Add an oscillator
  851. Oscillator.prototype.add = function(oscillator) {
  852. for ( var i = 0; i < this.bufferSize; i++ ) {
  853. //this.signal[i] += oscillator.valueAt(i);
  854. this.signal[i] += oscillator.signal[i];
  855. }
  856. return this.signal;
  857. };
  858. // Add a signal to the current generated osc signal
  859. Oscillator.prototype.addSignal = function(signal) {
  860. for ( var i = 0; i < signal.length; i++ ) {
  861. if ( i >= this.bufferSize ) {
  862. break;
  863. }
  864. this.signal[i] += signal[i];
  865. /*
  866. // Constrain amplitude
  867. if ( this.signal[i] > 1 ) {
  868. this.signal[i] = 1;
  869. } else if ( this.signal[i] < -1 ) {
  870. this.signal[i] = -1;
  871. }
  872. */
  873. }
  874. return this.signal;
  875. };
  876. // Add an envelope to the oscillator
  877. Oscillator.prototype.addEnvelope = function(envelope) {
  878. this.envelope = envelope;
  879. };
  880. Oscillator.prototype.applyEnvelope = function() {
  881. this.envelope.process(this.signal);
  882. };
  883. Oscillator.prototype.valueAt = function(offset) {
  884. return this.waveTable[offset % this.waveTableLength];
  885. };
  886. Oscillator.prototype.generate = function() {
  887. var frameOffset = this.frameCount * this.bufferSize;
  888. var step = this.waveTableLength * this.frequency / this.sampleRate;
  889. var offset;
  890. for ( var i = 0; i < this.bufferSize; i++ ) {
  891. //var step = (frameOffset + i) * this.cyclesPerSample % 1;
  892. //this.signal[i] = this.func(step) * this.amplitude;
  893. //this.signal[i] = this.valueAt(Math.round((frameOffset + i) * step)) * this.amplitude;
  894. offset = Math.round((frameOffset + i) * step);
  895. this.signal[i] = this.waveTable[offset % this.waveTableLength] * this.amplitude;
  896. }
  897. this.frameCount++;
  898. return this.signal;
  899. };
  900. Oscillator.Sine = function(step) {
  901. return Math.sin(DSP.TWO_PI * step);
  902. };
  903. Oscillator.Square = function(step) {
  904. return step < 0.5 ? 1 : -1;
  905. };
  906. Oscillator.Saw = function(step) {
  907. return 2 * (step - Math.round(step));
  908. };
  909. Oscillator.Triangle = function(step) {
  910. return 1 - 4 * Math.abs(Math.round(step) - step);
  911. };
  912. Oscillator.Pulse = function(step) {
  913. // stub
  914. };
  915. function ADSR(attackLength, decayLength, sustainLevel, sustainLength, releaseLength, sampleRate) {
  916. this.sampleRate = sampleRate;
  917. // Length in seconds
  918. this.attackLength = attackLength;
  919. this.decayLength = decayLength;
  920. this.sustainLevel = sustainLevel;
  921. this.sustainLength = sustainLength;
  922. this.releaseLength = releaseLength;
  923. this.sampleRate = sampleRate;
  924. // Length in samples
  925. this.attackSamples = attackLength * sampleRate;
  926. this.decaySamples = decayLength * sampleRate;
  927. this.sustainSamples = sustainLength * sampleRate;
  928. this.releaseSamples = releaseLength * sampleRate;
  929. // Updates the envelope sample positions
  930. this.update = function() {
  931. this.attack = this.attackSamples;
  932. this.decay = this.attack + this.decaySamples;
  933. this.sustain = this.decay + this.sustainSamples;
  934. this.release = this.sustain + this.releaseSamples;
  935. };
  936. this.update();
  937. this.samplesProcessed = 0;
  938. }
  939. ADSR.prototype.noteOn = function() {
  940. this.samplesProcessed = 0;
  941. this.sustainSamples = this.sustainLength * this.sampleRate;
  942. this.update();
  943. };
  944. // Send a note off when using a sustain of infinity to let the envelope enter the release phase
  945. ADSR.prototype.noteOff = function() {
  946. this.sustainSamples = this.samplesProcessed - this.decaySamples;
  947. this.update();
  948. };
  949. ADSR.prototype.processSample = function(sample) {
  950. var amplitude = 0;
  951. if ( this.samplesProcessed <= this.attack ) {
  952. amplitude = 0 + (1 - 0) * ((this.samplesProcessed - 0) / (this.attack - 0));
  953. } else if ( this.samplesProcessed > this.attack && this.samplesProcessed <= this.decay ) {
  954. amplitude = 1 + (this.sustainLevel - 1) * ((this.samplesProcessed - this.attack) / (this.decay - this.attack));
  955. } else if ( this.samplesProcessed > this.decay && this.samplesProcessed <= this.sustain ) {
  956. amplitude = this.sustainLevel;
  957. } else if ( this.samplesProcessed > this.sustain && this.samplesProcessed <= this.release ) {
  958. amplitude = this.sustainLevel + (0 - this.sustainLevel) * ((this.samplesProcessed - this.sustain) / (this.release - this.sustain));
  959. }
  960. return sample * amplitude;
  961. };
  962. ADSR.prototype.value = function() {
  963. var amplitude = 0;
  964. if ( this.samplesProcessed <= this.attack ) {
  965. amplitude = 0 + (1 - 0) * ((this.samplesProcessed - 0) / (this.attack - 0));
  966. } else if ( this.samplesProcessed > this.attack && this.samplesProcessed <= this.decay ) {
  967. amplitude = 1 + (this.sustainLevel - 1) * ((this.samplesProcessed - this.attack) / (this.decay - this.attack));
  968. } else if ( this.samplesProcessed > this.decay && this.samplesProcessed <= this.sustain ) {
  969. amplitude = this.sustainLevel;
  970. } else if ( this.samplesProcessed > this.sustain && this.samplesProcessed <= this.release ) {
  971. amplitude = this.sustainLevel + (0 - this.sustainLevel) * ((this.samplesProcessed - this.sustain) / (this.release - this.sustain));
  972. }
  973. return amplitude;
  974. };
  975. ADSR.prototype.process = function(buffer) {
  976. for ( var i = 0; i < buffer.length; i++ ) {
  977. buffer[i] *= this.value();
  978. this.samplesProcessed++;
  979. }
  980. return buffer;
  981. };
  982. ADSR.prototype.isActive = function() {
  983. if ( this.samplesProcessed > this.release || this.samplesProcessed === -1 ) {
  984. return false;
  985. } else {
  986. return true;
  987. }
  988. };
  989. ADSR.prototype.disable = function() {
  990. this.samplesProcessed = -1;
  991. };
  992. function IIRFilter(type, cutoff, resonance, sampleRate) {
  993. this.sampleRate = sampleRate;
  994. switch(type) {
  995. case DSP.LOWPASS:
  996. case DSP.LP12:
  997. this.func = new IIRFilter.LP12(cutoff, resonance, sampleRate);
  998. break;
  999. }
  1000. }
  1001. IIRFilter.prototype.__defineGetter__('cutoff',
  1002. function() {
  1003. return this.func.cutoff;
  1004. }
  1005. );
  1006. IIRFilter.prototype.__defineGetter__('resonance',
  1007. function() {
  1008. return this.func.resonance;
  1009. }
  1010. );
  1011. IIRFilter.prototype.set = function(cutoff, resonance) {
  1012. this.func.calcCoeff(cutoff, resonance);
  1013. };
  1014. IIRFilter.prototype.process = function(buffer) {
  1015. this.func.process(buffer);
  1016. };
  1017. // Add an envelope to the filter
  1018. IIRFilter.prototype.addEnvelope = function(envelope) {
  1019. if ( envelope instanceof ADSR ) {
  1020. this.func.addEnvelope(envelope);
  1021. } else {
  1022. throw "Not an envelope.";
  1023. }
  1024. };
  1025. IIRFilter.LP12 = function(cutoff, resonance, sampleRate) {
  1026. this.sampleRate = sampleRate;
  1027. this.vibraPos = 0;
  1028. this.vibraSpeed = 0;
  1029. this.envelope = false;
  1030. this.calcCoeff = function(cutoff, resonance) {
  1031. this.w = 2.0 * Math.PI * cutoff / this.sampleRate;
  1032. this.q = 1.0 - this.w / (2.0 * (resonance + 0.5 / (1.0 + this.w)) + this.w - 2.0);
  1033. this.r = this.q * this.q;
  1034. this.c = this.r + 1.0 - 2.0 * Math.cos(this.w) * this.q;
  1035. this.cutoff = cutoff;
  1036. this.resonance = resonance;
  1037. };
  1038. this.calcCoeff(cutoff, resonance);
  1039. this.process = function(buffer) {
  1040. for ( var i = 0; i < buffer.length; i++ ) {
  1041. this.vibraSpeed += (buffer[i] - this.vibraPos) * this.c;
  1042. this.vibraPos += this.vibraSpeed;
  1043. this.vibraSpeed *= this.r;
  1044. /*
  1045. var temp = this.vibraPos;
  1046. if ( temp > 1.0 ) {
  1047. temp = 1.0;
  1048. } else if ( temp < -1.0 ) {
  1049. temp = -1.0;
  1050. } else if ( temp != temp ) {
  1051. temp = 1;
  1052. }
  1053. buffer[i] = temp;
  1054. */
  1055. if (this.envelope) {
  1056. buffer[i] = (buffer[i] * (1 - this.envelope.value())) + (this.vibraPos * this.envelope.value());
  1057. this.envelope.samplesProcessed++;
  1058. } else {
  1059. buffer[i] = this.vibraPos;
  1060. }
  1061. }
  1062. };
  1063. };
  1064. IIRFilter.LP12.prototype.addEnvelope = function(envelope) {
  1065. this.envelope = envelope;
  1066. };
  1067. function IIRFilter2(type, cutoff, resonance, sampleRate) {
  1068. this.type = type;
  1069. this.cutoff = cutoff;
  1070. this.resonance = resonance;
  1071. this.sampleRate = sampleRate;
  1072. this.f = Float64Array(4);
  1073. this.f[0] = 0.0; // lp
  1074. this.f[1] = 0.0; // hp
  1075. this.f[2] = 0.0; // bp
  1076. this.f[3] = 0.0; // br
  1077. this.calcCoeff = function(cutoff, resonance) {
  1078. this.freq = 2 * Math.sin(Math.PI * Math.min(0.25, cutoff/(this.sampleRate*2)));
  1079. this.damp = Math.min(2 * (1 - Math.pow(resonance, 0.25)), Math.min(2, 2/this.freq - this.freq * 0.5));
  1080. };
  1081. this.calcCoeff(cutoff, resonance);
  1082. }
  1083. IIRFilter2.prototype.process = function(buffer) {
  1084. var input, output;
  1085. var f = this.f;
  1086. for ( var i = 0; i < buffer.length; i++ ) {
  1087. input = buffer[i];
  1088. // first pass
  1089. f[3] = input - this.damp * f[2];
  1090. f[0] = f[0] + this.freq * f[2];
  1091. f[1] = f[3] - f[0];
  1092. f[2] = this.freq * f[1] + f[2];
  1093. output = 0.5 * f[this.type];
  1094. // second pass
  1095. f[3] = input - this.damp * f[2];
  1096. f[0] = f[0] + this.freq * f[2];
  1097. f[1] = f[3] - f[0];
  1098. f[2] = this.freq * f[1] + f[2];
  1099. output += 0.5 * f[this.type];
  1100. if (this.envelope) {
  1101. buffer[i] = (buffer[i] * (1 - this.envelope.value())) + (output * this.envelope.value());
  1102. this.envelope.samplesProcessed++;
  1103. } else {
  1104. buffer[i] = output;
  1105. }
  1106. }
  1107. };
  1108. IIRFilter2.prototype.addEnvelope = function(envelope) {
  1109. if ( envelope instanceof ADSR ) {
  1110. this.envelope = envelope;
  1111. } else {
  1112. throw "This is not an envelope.";
  1113. }
  1114. };
  1115. IIRFilter2.prototype.set = function(cutoff, resonance) {
  1116. this.calcCoeff(cutoff, resonance);
  1117. };
  1118. function WindowFunction(type, alpha) {
  1119. this.alpha = alpha;
  1120. switch(type) {
  1121. case DSP.BARTLETT:
  1122. this.func = WindowFunction.Bartlett;
  1123. break;
  1124. case DSP.BARTLETTHANN:
  1125. this.func = WindowFunction.BartlettHann;
  1126. break;
  1127. case DSP.BLACKMAN:
  1128. this.func = WindowFunction.Blackman;
  1129. this.alpha = this.alpha || 0.16;
  1130. break;
  1131. case DSP.COSINE:
  1132. this.func = WindowFunction.Cosine;
  1133. break;
  1134. case DSP.GAUSS:
  1135. this.func = WindowFunction.Gauss;
  1136. this.alpha = this.alpha || 0.25;
  1137. break;
  1138. case DSP.HAMMING:
  1139. this.func = WindowFunction.Hamming;
  1140. break;
  1141. case DSP.HANN:
  1142. this.func = WindowFunction.Hann;
  1143. break;
  1144. case DSP.LANCZOS:
  1145. this.func = WindowFunction.Lanczoz;
  1146. break;
  1147. case DSP.RECTANGULAR:
  1148. this.func = WindowFunction.Rectangular;
  1149. break;
  1150. case DSP.TRIANGULAR:
  1151. this.func = WindowFunction.Triangular;
  1152. break;
  1153. }
  1154. }
  1155. WindowFunction.prototype.process = function(buffer) {
  1156. var length = buffer.length;
  1157. for ( var i = 0; i < length; i++ ) {
  1158. buffer[i] *= this.func(length, i, this.alpha);
  1159. }
  1160. return buffer;
  1161. };
  1162. WindowFunction.Bartlett = function(length, index) {
  1163. return 2 / (length - 1) * ((length - 1) / 2 - Math.abs(index - (length - 1) / 2));
  1164. };
  1165. WindowFunction.BartlettHann = function(length, index) {
  1166. return 0.62 - 0.48 * Math.abs(index / (length - 1) - 0.5) - 0.38 * Math.cos(DSP.TWO_PI * index / (length - 1));
  1167. };
  1168. WindowFunction.Blackman = function(length, index, alpha) {
  1169. var a0 = (1 - alpha) / 2;
  1170. var a1 = 0.5;
  1171. var a2 = alpha / 2;
  1172. return a0 - a1 * Math.cos(DSP.TWO_PI * index / (length - 1)) + a2 * Math.cos(4 * Math.PI * index / (length - 1));
  1173. };
  1174. WindowFunction.Cosine = function(length, index) {
  1175. return Math.cos(Math.PI * index / (length - 1) - Math.PI / 2);
  1176. };
  1177. WindowFunction.Gauss = function(length, index, alpha) {
  1178. return Math.pow(Math.E, -0.5 * Math.pow((index - (length - 1) / 2) / (alpha * (length - 1) / 2), 2));
  1179. };
  1180. WindowFunction.Hamming = function(length, index) {
  1181. return 0.54 - 0.46 * Math.cos(DSP.TWO_PI * index / (length - 1));
  1182. };
  1183. WindowFunction.Hann = function(length, index) {
  1184. return 0.5 * (1 - Math.cos(DSP.TWO_PI * index / (length - 1)));
  1185. };
  1186. WindowFunction.Lanczos = function(length, index) {
  1187. var x = 2 * index / (length - 1) - 1;
  1188. return Math.sin(Math.PI * x) / (Math.PI * x);
  1189. };
  1190. WindowFunction.Rectangular = function(length, index) {
  1191. return 1;
  1192. };
  1193. WindowFunction.Triangular = function(length, index) {
  1194. return 2 / length * (length / 2 - Math.abs(index - (length - 1) / 2));
  1195. };
  1196. function sinh (arg) {
  1197. // Returns the hyperbolic sine of the number, defined as (exp(number) - exp(-number))/2
  1198. //
  1199. // version: 1004.2314
  1200. // discuss at: http://phpjs.org/functions/sinh // + original by: Onno Marsman
  1201. // * example 1: sinh(-0.9834330348825909);
  1202. // * returns 1: -1.1497971402636502
  1203. return (Math.exp(arg) - Math.exp(-arg))/2;
  1204. }
  1205. /*
  1206. * Biquad filter
  1207. *
  1208. * Created by Ricard Marxer <email@ricardmarxer.com> on 2010-05-23.
  1209. * Copyright 2010 Ricard Marxer. All rights reserved.
  1210. *
  1211. */
  1212. // Implementation based on:
  1213. // http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt
  1214. function Biquad(type, sampleRate) {
  1215. this.Fs = sampleRate;
  1216. this.type = type; // type of the filter
  1217. this.parameterType = DSP.Q; // type of the parameter
  1218. this.x_1_l = 0;
  1219. this.x_2_l = 0;
  1220. this.y_1_l = 0;
  1221. this.y_2_l = 0;
  1222. this.x_1_r = 0;
  1223. this.x_2_r = 0;
  1224. this.y_1_r = 0;
  1225. this.y_2_r = 0;
  1226. this.b0 = 1;
  1227. this.a0 = 1;
  1228. this.b1 = 0;
  1229. this.a1 = 0;
  1230. this.b2 = 0;
  1231. this.a2 = 0;
  1232. this.b0a0 = this.b0 / this.a0;
  1233. this.b1a0 = this.b1 / this.a0;
  1234. this.b2a0 = this.b2 / this.a0;
  1235. this.a1a0 = this.a1 / this.a0;
  1236. this.a2a0 = this.a2 / this.a0;
  1237. this.f0 = 3000; // "wherever it's happenin', man." Center Frequency or
  1238. // Corner Frequency, or shelf midpoint frequency, depending
  1239. // on which filter type. The "significant frequency".
  1240. this.dBgain = 12; // used only for peaking and shelving filters
  1241. this.Q = 1; // the EE kind of definition, except for peakingEQ in which A*Q is
  1242. // the classic EE Q. That adjustment in definition was made so that
  1243. // a boost of N dB followed by a cut of N dB for identical Q and
  1244. // f0/Fs results in a precisely flat unity gain filter or "wire".
  1245. this.BW = -3; // the bandwidth in octaves (between -3 dB frequencies for BPF
  1246. // and notch or between midpoint (dBgain/2) gain frequencies for
  1247. // peaking EQ
  1248. this.S = 1; // a "shelf slope" parameter (for shelving EQ only). When S = 1,
  1249. // the shelf slope is as steep as it can be and remain monotonically
  1250. // increasing or decreasing gain with frequency. The shelf slope, in
  1251. // dB/octave, remains proportional to S for all other values for a
  1252. // fixed f0/Fs and dBgain.
  1253. this.coefficients = function() {
  1254. var b = [this.b0, this.b1, this.b2];
  1255. var a = [this.a0, this.a1, this.a2];
  1256. return {b: b, a:a};
  1257. };
  1258. this.setFilterType = function(type) {
  1259. this.type = type;
  1260. this.recalculateCoefficients();
  1261. };
  1262. this.setSampleRate = function(rate) {
  1263. this.Fs = rate;
  1264. this.recalculateCoefficients();
  1265. };
  1266. this.setQ = function(q) {
  1267. this.parameterType = DSP.Q;
  1268. this.Q = Math.max(Math.min(q, 115.0), 0.001);
  1269. this.recalculateCoefficients();
  1270. };
  1271. this.setBW = function(bw) {
  1272. this.parameterType = DSP.BW;
  1273. this.BW = bw;
  1274. this.recalculateCoefficients();
  1275. };
  1276. this.setS = function(s) {
  1277. this.parameterType = DSP.S;
  1278. this.S = Math.max(Math.min(s, 5.0), 0.0001);
  1279. this.recalculateCoefficients();
  1280. };
  1281. this.setF0 = function(freq) {
  1282. this.f0 = freq;
  1283. this.recalculateCoefficients();
  1284. };
  1285. this.setDbGain = function(g) {
  1286. this.dBgain = g;
  1287. this.recalculateCoefficients();
  1288. };
  1289. this.recalculateCoefficients = function() {
  1290. var A;
  1291. if (type === DSP.PEAKING_EQ || type === DSP.LOW_SHELF || type === DSP.HIGH_SHELF ) {
  1292. A = Math.pow(10, (this.dBgain/40)); // for peaking and shelving EQ filters only
  1293. } else {
  1294. A = Math.sqrt( Math.pow(10, (this.dBgain/20)) );
  1295. }
  1296. var w0 = DSP.TWO_PI * this.f0 / this.Fs;
  1297. var cosw0 = Math.cos(w0);
  1298. var sinw0 = Math.sin(w0);
  1299. var alpha = 0;
  1300. switch (this.parameterType) {
  1301. case DSP.Q:
  1302. alpha = sinw0/(2*this.Q);
  1303. break;
  1304. case DSP.BW:
  1305. alpha = sinw0 * sinh( Math.LN2/2 * this.BW * w0/sinw0 );
  1306. break;
  1307. case DSP.S:
  1308. alpha = sinw0/2 * Math.sqrt( (A + 1/A)*(1/this.S - 1) + 2 );
  1309. break;
  1310. }
  1311. /**
  1312. FYI: The relationship between bandwidth and Q is
  1313. 1/Q = 2*sinh(ln(2)/2*BW*w0/sin(w0)) (digital filter w BLT)
  1314. or 1/Q = 2*sinh(ln(2)/2*BW) (analog filter prototype)
  1315. The relationship between shelf slope and Q is
  1316. 1/Q = sqrt((A + 1/A)*(1/S - 1) + 2)
  1317. */
  1318. var coeff;
  1319. switch (this.type) {
  1320. case DSP.LPF: // H(s) = 1 / (s^2 + s/Q + 1)
  1321. this.b0 = (1 - cosw0)/2;
  1322. this.b1 = 1 - cosw0;
  1323. this.b2 = (1 - cosw0)/2;
  1324. this.a0 = 1 + alpha;
  1325. this.a1 = -2 * cosw0;
  1326. this.a2 = 1 - alpha;
  1327. break;
  1328. case DSP.HPF: // H(s) = s^2 / (s^2 + s/Q + 1)
  1329. this.b0 = (1 + cosw0)/2;
  1330. this.b1 = -(1 + cosw0);
  1331. this.b2 = (1 + cosw0)/2;
  1332. this.a0 = 1 + alpha;
  1333. this.a1 = -2 * cosw0;
  1334. this.a2 = 1 - alpha;
  1335. break;
  1336. case DSP.BPF_CONSTANT_SKIRT: // H(s) = s / (s^2 + s/Q + 1) (constant skirt gain, peak gain = Q)
  1337. this.b0 = sinw0/2;
  1338. this.b1 = 0;
  1339. this.b2 = -sinw0/2;
  1340. this.a0 = 1 + alpha;
  1341. this.a1 = -2*cosw0;
  1342. this.a2 = 1 - alpha;
  1343. break;
  1344. case DSP.BPF_CONSTANT_PEAK: // H(s) = (s/Q) / (s^2 + s/Q + 1) (constant 0 dB peak gain)
  1345. this.b0 = alpha;
  1346. this.b1 = 0;
  1347. this.b2 = -alpha;
  1348. this.a0 = 1 + alpha;
  1349. this.a1 = -2*cosw0;
  1350. this.a2 = 1 - alpha;
  1351. break;
  1352. case DSP.NOTCH: // H(s) = (s^2 + 1) / (s^2 + s/Q + 1)
  1353. this.b0 = 1;
  1354. this.b1 = -2*cosw0;
  1355. this.b2 = 1;
  1356. this.a0 = 1 + alpha;
  1357. this.a1 = -2*cosw0;
  1358. this.a2 = 1 - alpha;
  1359. break;
  1360. case DSP.APF: // H(s) = (s^2 - s/Q + 1) / (s^2 + s/Q + 1)
  1361. this.b0 = 1 - alpha;
  1362. this.b1 = -2*cosw0;
  1363. this.b2 = 1 + alpha;
  1364. this.a0 = 1 + alpha;
  1365. this.a1 = -2*cosw0;
  1366. this.a2 = 1 - alpha;
  1367. break;
  1368. case DSP.PEAKING_EQ: // H(s) = (s^2 + s*(A/Q) + 1) / (s^2 + s/(A*Q) + 1)
  1369. this.b0 = 1 + alpha*A;
  1370. this.b1 = -2*cosw0;
  1371. this.b2 = 1 - alpha*A;
  1372. this.a0 = 1 + alpha/A;
  1373. this.a1 = -2*cosw0;
  1374. this.a2 = 1 - alpha/A;
  1375. break;
  1376. case DSP.LOW_SHELF: // H(s) = A * (s^2 + (sqrt(A)/Q)*s + A)/(A*s^2 + (sqrt(A)/Q)*s + 1)
  1377. coeff = sinw0 * Math.sqrt( (A^2 + 1)*(1/this.S - 1) + 2*A );
  1378. this.b0 = A*((A+1) - (A-1)*cosw0 + coeff);
  1379. this.b1 = 2*A*((A-1) - (A+1)*cosw0);
  1380. this.b2 = A*((A+1) - (A-1)*cosw0 - coeff);
  1381. this.a0 = (A+1) + (A-1)*cosw0 + coeff;
  1382. this.a1 = -2*((A-1) + (A+1)*cosw0);
  1383. this.a2 = (A+1) + (A-1)*cosw0 - coeff;
  1384. break;
  1385. case DSP.HIGH_SHELF: // H(s) = A * (A*s^2 + (sqrt(A)/Q)*s + 1)/(s^2 + (sqrt(A)/Q)*s + A)
  1386. coeff = sinw0 * Math.sqrt( (A^2 + 1)*(1/this.S - 1) + 2*A );
  1387. this.b0 = A*((A+1) + (A-1)*cosw0 + coeff);
  1388. this.b1 = -2*A*((A-1) + (A+1)*cosw0);
  1389. this.b2 = A*((A+1) + (A-1)*cosw0 - coeff);
  1390. this.a0 = (A+1) - (A-1)*cosw0 + coeff;
  1391. this.a1 = 2*((A-1) - (A+1)*cosw0);
  1392. this.a2 = (A+1) - (A-1)*cosw0 - coeff;
  1393. break;
  1394. }
  1395. this.b0a0 = this.b0/this.a0;
  1396. this.b1a0 = this.b1/this.a0;
  1397. this.b2a0 = this.b2/this.a0;
  1398. this.a1a0 = this.a1/this.a0;
  1399. this.a2a0 = this.a2/this.a0;
  1400. };
  1401. this.process = function(buffer) {
  1402. //y[n] = (b0/a0)*x[n] + (b1/a0)*x[n-1] + (b2/a0)*x[n-2]
  1403. // - (a1/a0)*y[n-1] - (a2/a0)*y[n-2]
  1404. var len = buffer.length;
  1405. var output = new Float64Array(len);
  1406. for ( var i=0; i<buffer.length; i++ ) {
  1407. output[i] = this.b0a0*buffer[i] + this.b1a0*this.x_1_l + this.b2a0*this.x_2_l - this.a1a0*this.y_1_l - this.a2a0*this.y_2_l;
  1408. this.y_2_l = this.y_1_l;
  1409. this.y_1_l = output[i];
  1410. this.x_2_l = this.x_1_l;
  1411. this.x_1_l = buffer[i];
  1412. }
  1413. return output;
  1414. };
  1415. this.processStereo = function(buffer) {
  1416. //y[n] = (b0/a0)*x[n] + (b1/a0)*x[n-1] + (b2/a0)*x[n-2]
  1417. // - (a1/a0)*y[n-1] - (a2/a0)*y[n-2]
  1418. var len = buffer.length;
  1419. var output = new Float64Array(len);
  1420. for (var i = 0; i < len/2; i++) {
  1421. output[2*i] = this.b0a0*buffer[2*i] + this.b1a0*this.x_1_l + this.b2a0*this.x_2_l - this.a1a0*this.y_1_l - this.a2a0*this.y_2_l;
  1422. this.y_2_l = this.y_1_l;
  1423. this.y_1_l = output[2*i];
  1424. this.x_2_l = this.x_1_l;
  1425. this.x_1_l = buffer[2*i];
  1426. output[2*i+1] = this.b0a0*buffer[2*i+1] + this.b1a0*this.x_1_r + this.b2a0*this.x_2_r - this.a1a0*this.y_1_r - this.a2a0*this.y_2_r;
  1427. this.y_2_r = this.y_1_r;
  1428. this.y_1_r = output[2*i+1];
  1429. this.x_2_r = this.x_1_r;
  1430. this.x_1_r = buffer[2*i+1];
  1431. }
  1432. return output;
  1433. };
  1434. }
  1435. /*
  1436. * Magnitude to decibels
  1437. *
  1438. * Created by Ricard Marxer <email@ricardmarxer.com> on 2010-05-23.
  1439. * Copyright 2010 Ricard Marxer. All rights reserved.
  1440. *
  1441. * @buffer array of magnitudes to convert to decibels
  1442. *
  1443. * @returns the array in decibels
  1444. *
  1445. */
  1446. DSP.mag2db = function(buffer) {
  1447. var minDb = -120;
  1448. var minMag = Math.pow(10.0, minDb / 20.0);
  1449. var log = Math.log;
  1450. var max = Math.max;
  1451. var result = Float64Array(buffer.length);
  1452. for (var i=0; i<buffer.length; i++) {
  1453. result[i] = 20.0*log(max(buffer[i], minMag));
  1454. }
  1455. return result;
  1456. };
  1457. /*
  1458. * Frequency response
  1459. *
  1460. * Created by Ricard Marxer <email@ricardmarxer.com> on 2010-05-23.
  1461. * Copyright 2010 Ricard Marxer. All rights reserved.
  1462. *
  1463. * Calculates the frequency response at the given points.
  1464. *
  1465. * @b b coefficients of the filter
  1466. * @a a coefficients of the filter
  1467. * @w w points (normally between -PI and PI) where to calculate the frequency response
  1468. *
  1469. * @returns the frequency response in magnitude
  1470. *
  1471. */
  1472. DSP.freqz = function(b, a, w) {
  1473. var i, j;
  1474. if (!w) {
  1475. w = Float64Array(200);
  1476. for (i=0;i<w.length; i++) {
  1477. w[i] = DSP.TWO_PI/w.length * i - Math.PI;
  1478. }
  1479. }
  1480. var result = Float64Array(w.length);
  1481. var sqrt = Math.sqrt;
  1482. var cos = Math.cos;
  1483. var sin = Math.sin;
  1484. for (i=0; i<w.length; i++) {
  1485. var numerator = {real:0.0, imag:0.0};
  1486. for (j=0; j<b.length; j++) {
  1487. numerator.real += b[j] * cos(-j*w[i]);
  1488. numerator.imag += b[j] * sin(-j*w[i]);
  1489. }
  1490. var denominator = {real:0.0, imag:0.0};
  1491. for (j=0; j<a.length; j++) {
  1492. denominator.real += a[j] * cos(-j*w[i]);
  1493. denominator.imag += a[j] * sin(-j*w[i]);
  1494. }
  1495. result[i] = sqrt(numerator.real*numerator.real + numerator.imag*numerator.imag) / sqrt(denominator.real*denominator.real + denominator.imag*denominator.imag);
  1496. }
  1497. return result;
  1498. };
  1499. /*
  1500. * Graphical Equalizer
  1501. *
  1502. * Implementation of a graphic equalizer with a configurable bands-per-octave
  1503. * and minimum and maximum frequencies
  1504. *
  1505. * Created by Ricard Marxer <email@ricardmarxer.com> on 2010-05-23.
  1506. * Copyright 2010 Ricard Marxer. All rights reserved.
  1507. *
  1508. */
  1509. function GraphicalEq(sampleRate) {
  1510. this.FS = sampleRate;
  1511. this.minFreq = 40.0;
  1512. this.maxFreq = 16000.0;
  1513. this.bandsPerOctave = 1.0;
  1514. this.filters = [];
  1515. this.freqzs = [];
  1516. this.calculateFreqzs = true;
  1517. this.recalculateFilters = function() {
  1518. var bandCount = Math.round(Math.log(this.maxFreq/this.minFreq) * this.bandsPerOctave/ Math.LN2);
  1519. this.filters = [];
  1520. for (var i=0; i<bandCount; i++) {
  1521. var freq = this.minFreq*(Math.pow(2, i/this.bandsPerOctave));
  1522. var newFilter = new Biquad(DSP.PEAKING_EQ, this.FS);
  1523. newFilter.setDbGain(0);
  1524. newFilter.setBW(1/this.bandsPerOctave);
  1525. newFilter.setF0(freq);
  1526. this.filters[i] = newFilter;
  1527. this.recalculateFreqz(i);
  1528. }
  1529. };
  1530. this.setMinimumFrequency = function(freq) {
  1531. this.minFreq = freq;
  1532. this.recalculateFilters();
  1533. };
  1534. this.setMaximumFrequency = function(freq) {
  1535. this.maxFreq = freq;
  1536. this.recalculateFilters();
  1537. };
  1538. this.setBandsPerOctave = function(bands) {
  1539. this.bandsPerOctave = bands;
  1540. this.recalculateFilters();
  1541. };
  1542. this.setBandGain = function(bandIndex, gain) {
  1543. if (bandIndex < 0 || bandIndex > (this.filters.length-1)) {
  1544. throw "The band index of the graphical equalizer is out of bounds.";
  1545. }
  1546. if (!gain) {
  1547. throw "A gain must be passed.";
  1548. }
  1549. this.filters[bandIndex].setDbGain(gain);
  1550. this.recalculateFreqz(bandIndex);
  1551. };
  1552. this.recalculateFreqz = function(bandIndex) {
  1553. if (!this.calculateFreqzs) {
  1554. return;
  1555. }
  1556. if (bandIndex < 0 || bandIndex > (this.filters.length-1)) {
  1557. throw "The band index of the graphical equalizer is out of bounds. " + bandIndex + " is out of [" + 0 + ", " + this.filters.length-1 + "]";
  1558. }
  1559. if (!this.w) {
  1560. this.w = Float64Array(400);
  1561. for (var i=0; i<this.w.length; i++) {
  1562. this.w[i] = Math.PI/this.w.length * i;
  1563. }
  1564. }
  1565. var b = [this.filters[bandIndex].b0, this.filters[bandIndex].b1, this.filters[bandIndex].b2];
  1566. var a = [this.filters[bandIndex].a0, this.filters[bandIndex].a1, this.filters[bandIndex].a2];
  1567. this.freqzs[bandIndex] = DSP.mag2db(DSP.freqz(b, a, this.w));
  1568. };
  1569. this.process = function(buffer) {
  1570. var output = buffer;
  1571. for (var i = 0; i < this.filters.length; i++) {
  1572. output = this.filters[i].process(output);
  1573. }
  1574. return output;
  1575. };
  1576. this.processStereo = function(buffer) {
  1577. var output = buffer;
  1578. for (var i = 0; i < this.filters.length; i++) {
  1579. output = this.filters[i].processStereo(output);
  1580. }
  1581. return output;
  1582. };
  1583. }
  1584. /**
  1585. * MultiDelay effect by Almer Thie (http://code.almeros.com).
  1586. * Copyright 2010 Almer Thie. All rights reserved.
  1587. * Example: http://code.almeros.com/code-examples/delay-firefox-audio-api/
  1588. *
  1589. * This is a delay that feeds it's own delayed signal back into its circular
  1590. * buffer. Also known as a CombFilter.
  1591. *
  1592. * Compatible with interleaved stereo (or more channel) buffers and
  1593. * non-interleaved mono buffers.
  1594. *
  1595. * @param {Number} maxDelayInSamplesSize Maximum possible delay in samples (size of circular buffer)
  1596. * @param {Number} delayInSamples Initial delay in samples
  1597. * @param {Number} masterVolume Initial master volume. Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify)
  1598. * @param {Number} delayVolume Initial feedback delay volume. Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify)
  1599. *
  1600. * @constructor
  1601. */
  1602. function MultiDelay(maxDelayInSamplesSize, delayInSamples, masterVolume, delayVolume) {
  1603. this.delayBufferSamples = new Float64Array(maxDelayInSamplesSize); // The maximum size of delay
  1604. this.delayInputPointer = delayInSamples;
  1605. this.delayOutputPointer = 0;
  1606. this.delayInSamples = delayInSamples;
  1607. this.masterVolume = masterVolume;
  1608. this.delayVolume = delayVolume;
  1609. }
  1610. /**
  1611. * Change the delay time in samples.
  1612. *
  1613. * @param {Number} delayInSamples Delay in samples
  1614. */
  1615. MultiDelay.prototype.setDelayInSamples = function (delayInSamples) {
  1616. this.delayInSamples = delayInSamples;
  1617. this.delayInputPointer = this.delayOutputPointer + delayInSamples;
  1618. if (this.delayInputPointer >= this.delayBufferSamples.length-1) {
  1619. this.delayInputPointer = this.delayInputPointer - this.delayBufferSamples.length;
  1620. }
  1621. };
  1622. /**
  1623. * Change the master volume.
  1624. *
  1625. * @param {Number} masterVolume Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify)
  1626. */
  1627. MultiDelay.prototype.setMasterVolume = function(masterVolume) {
  1628. this.masterVolume = masterVolume;
  1629. };
  1630. /**
  1631. * Change the delay feedback volume.
  1632. *
  1633. * @param {Number} delayVolume Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify)
  1634. */
  1635. MultiDelay.prototype.setDelayVolume = function(delayVolume) {
  1636. this.delayVolume = delayVolume;
  1637. };
  1638. /**
  1639. * Process a given interleaved or mono non-interleaved float value Array and adds the delayed audio.
  1640. *
  1641. * @param {Array} samples Array containing Float values or a Float64Array
  1642. *
  1643. * @returns A new Float64Array interleaved or mono non-interleaved as was fed to this function.
  1644. */
  1645. MultiDelay.prototype.process = function(samples) {
  1646. // NB. Make a copy to put in the output samples to return.
  1647. var outputSamples = new Float64Array(samples.length);
  1648. for (var i=0; i<samples.length; i++) {
  1649. // delayBufferSamples could contain initial NULL's, return silence in that case
  1650. var delaySample = (this.delayBufferSamples[this.delayOutputPointer] === null ? 0.0 : this.delayBufferSamples[this.delayOutputPointer]);
  1651. // Mix normal audio data with delayed audio
  1652. var sample = (delaySample * this.delayVolume) + samples[i];
  1653. // Add audio data with the delay in the delay buffer
  1654. this.delayBufferSamples[this.delayInputPointer] = sample;
  1655. // Return the audio with delay mix
  1656. outputSamples[i] = sample * this.masterVolume;
  1657. // Manage circulair delay buffer pointers
  1658. this.delayInputPointer++;
  1659. if (this.delayInputPointer >= this.delayBufferSamples.length-1) {
  1660. this.delayInputPointer = 0;
  1661. }
  1662. this.delayOutputPointer++;
  1663. if (this.delayOutputPointer >= this.delayBufferSamples.length-1) {
  1664. this.delayOutputPointer = 0;
  1665. }
  1666. }
  1667. return outputSamples;
  1668. };
  1669. /**
  1670. * SingleDelay effect by Almer Thie (http://code.almeros.com).
  1671. * Copyright 2010 Almer Thie. All rights reserved.
  1672. * Example: See usage in Reverb class
  1673. *
  1674. * This is a delay that does NOT feeds it's own delayed signal back into its
  1675. * circular buffer, neither does it return the original signal. Also known as
  1676. * an AllPassFilter(?).
  1677. *
  1678. * Compatible with interleaved stereo (or more channel) buffers and
  1679. * non-interleaved mono buffers.
  1680. *
  1681. * @param {Number} maxDelayInSamplesSize Maximum possible delay in samples (size of circular buffer)
  1682. * @param {Number} delayInSamples Initial delay in samples
  1683. * @param {Number} delayVolume Initial feedback delay volume. Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify)
  1684. *
  1685. * @constructor
  1686. */
  1687. function SingleDelay(maxDelayInSamplesSize, delayInSamples, delayVolume) {
  1688. this.delayBufferSamples = new Float64Array(maxDelayInSamplesSize); // The maximum size of delay
  1689. this.delayInputPointer = delayInSamples;
  1690. this.delayOutputPointer = 0;
  1691. this.delayInSamples = delayInSamples;
  1692. this.delayVolume = delayVolume;
  1693. }
  1694. /**
  1695. * Change the delay time in samples.
  1696. *
  1697. * @param {Number} delayInSamples Delay in samples
  1698. */
  1699. SingleDelay.prototype.setDelayInSamples = function(delayInSamples) {
  1700. this.delayInSamples = delayInSamples;
  1701. this.delayInputPointer = this.delayOutputPointer + delayInSamples;
  1702. if (this.delayInputPointer >= this.delayBufferSamples.length-1) {
  1703. this.delayInputPointer = this.delayInputPointer - this.delayBufferSamples.length;
  1704. }
  1705. };
  1706. /**
  1707. * Change the return signal volume.
  1708. *
  1709. * @param {Number} delayVolume Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify)
  1710. */
  1711. SingleDelay.prototype.setDelayVolume = function(delayVolume) {
  1712. this.delayVolume = delayVolume;
  1713. };
  1714. /**
  1715. * Process a given interleaved or mono non-interleaved float value Array and
  1716. * returns the delayed audio.
  1717. *
  1718. * @param {Array} samples Array containing Float values or a Float64Array
  1719. *
  1720. * @returns A new Float64Array interleaved or mono non-interleaved as was fed to this function.
  1721. */
  1722. SingleDelay.prototype.process = function(samples) {
  1723. // NB. Make a copy to put in the output samples to return.
  1724. var outputSamples = new Float64Array(samples.length);
  1725. for (var i=0; i<samples.length; i++) {
  1726. // Add audio data with the delay in the delay buffer
  1727. this.delayBufferSamples[this.delayInputPointer] = samples[i];
  1728. // delayBufferSamples could contain initial NULL's, return silence in that case
  1729. var delaySample = this.delayBufferSamples[this.delayOutputPointer];
  1730. // Return the audio with delay mix
  1731. outputSamples[i] = delaySample * this.delayVolume;
  1732. // Manage circulair delay buffer pointers
  1733. this.delayInputPointer++;
  1734. if (this.delayInputPointer >= this.delayBufferSamples.length-1) {
  1735. this.delayInputPointer = 0;
  1736. }
  1737. this.delayOutputPointer++;
  1738. if (this.delayOutputPointer >= this.delayBufferSamples.length-1) {
  1739. this.delayOutputPointer = 0;
  1740. }
  1741. }
  1742. return outputSamples;
  1743. };
  1744. /**
  1745. * Reverb effect by Almer Thie (http://code.almeros.com).
  1746. * Copyright 2010 Almer Thie. All rights reserved.
  1747. * Example: http://code.almeros.com/code-examples/reverb-firefox-audio-api/
  1748. *
  1749. * This reverb consists of 6 SingleDelays, 6 MultiDelays and an IIRFilter2
  1750. * for each of the two stereo channels.
  1751. *
  1752. * Compatible with interleaved stereo buffers only!
  1753. *
  1754. * @param {Number} maxDelayInSamplesSize Maximum possible delay in samples (size of circular buffers)
  1755. * @param {Number} delayInSamples Initial delay in samples for internal (Single/Multi)delays
  1756. * @param {Number} masterVolume Initial master volume. Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify)
  1757. * @param {Number} mixVolume Initial reverb signal mix volume. Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify)
  1758. * @param {Number} delayVolume Initial feedback delay volume for internal (Single/Multi)delays. Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify)
  1759. * @param {Number} dampFrequency Initial low pass filter frequency. 0 to 44100 (depending on your maximum sampling frequency)
  1760. *
  1761. * @constructor
  1762. */
  1763. function Reverb(maxDelayInSamplesSize, delayInSamples, masterVolume, mixVolume, delayVolume, dampFrequency) {
  1764. this.delayInSamples = delayInSamples;
  1765. this.masterVolume = masterVolume;
  1766. this.mixVolume = mixVolume;
  1767. this.delayVolume = delayVolume;
  1768. this.dampFrequency = dampFrequency;
  1769. this.NR_OF_MULTIDELAYS = 6;
  1770. this.NR_OF_SINGLEDELAYS = 6;
  1771. this.LOWPASSL = new IIRFilter2(DSP.LOWPASS, dampFrequency, 0, 44100);
  1772. this.LOWPASSR = new IIRFilter2(DSP.LOWPASS, dampFrequency, 0, 44100);
  1773. this.singleDelays = [];
  1774. var i, delayMultiply;
  1775. for (i = 0; i < this.NR_OF_SINGLEDELAYS; i++) {
  1776. delayMultiply = 1.0 + (i/7.0); // 1.0, 1.1, 1.2...
  1777. this.singleDelays[i] = new SingleDelay(maxDelayInSamplesSize, Math.round(this.delayInSamples * delayMultiply), this.delayVolume);
  1778. }
  1779. this.multiDelays = [];
  1780. for (i = 0; i < this.NR_OF_MULTIDELAYS; i++) {
  1781. delayMultiply = 1.0 + (i/10.0); // 1.0, 1.1, 1.2...
  1782. this.multiDelays[i] = new MultiDelay(maxDelayInSamplesSize, Math.round(this.delayInSamples * delayMultiply), this.masterVolume, this.delayVolume);
  1783. }
  1784. }
  1785. /**
  1786. * Change the delay time in samples as a base for all delays.
  1787. *
  1788. * @param {Number} delayInSamples Delay in samples
  1789. */
  1790. Reverb.prototype.setDelayInSamples = function (delayInSamples){
  1791. this.delayInSamples = delayInSamples;
  1792. var i, delayMultiply;
  1793. for (i = 0; i < this.NR_OF_SINGLEDELAYS; i++) {
  1794. delayMultiply = 1.0 + (i/7.0); // 1.0, 1.1, 1.2...
  1795. this.singleDelays[i].setDelayInSamples( Math.round(this.delayInSamples * delayMultiply) );
  1796. }
  1797. for (i = 0; i < this.NR_OF_MULTIDELAYS; i++) {
  1798. delayMultiply = 1.0 + (i/10.0); // 1.0, 1.1, 1.2...
  1799. this.multiDelays[i].setDelayInSamples( Math.round(this.delayInSamples * delayMultiply) );
  1800. }
  1801. };
  1802. /**
  1803. * Change the master volume.
  1804. *
  1805. * @param {Number} masterVolume Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify)
  1806. */
  1807. Reverb.prototype.setMasterVolume = function (masterVolume){
  1808. this.masterVolume = masterVolume;
  1809. };
  1810. /**
  1811. * Change the reverb signal mix level.
  1812. *
  1813. * @param {Number} mixVolume Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify)
  1814. */
  1815. Reverb.prototype.setMixVolume = function (mixVolume){
  1816. this.mixVolume = mixVolume;
  1817. };
  1818. /**
  1819. * Change all delays feedback volume.
  1820. *
  1821. * @param {Number} delayVolume Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify)
  1822. */
  1823. Reverb.prototype.setDelayVolume = function (delayVolume){
  1824. this.delayVolume = delayVolume;
  1825. var i;
  1826. for (i = 0; i<this.NR_OF_SINGLEDELAYS; i++) {
  1827. this.singleDelays[i].setDelayVolume(this.delayVolume);
  1828. }
  1829. for (i = 0; i<this.NR_OF_MULTIDELAYS; i++) {
  1830. this.multiDelays[i].setDelayVolume(this.delayVolume);
  1831. }
  1832. };
  1833. /**
  1834. * Change the Low Pass filter frequency.
  1835. *
  1836. * @param {Number} dampFrequency low pass filter frequency. 0 to 44100 (depending on your maximum sampling frequency)
  1837. */
  1838. Reverb.prototype.setDampFrequency = function (dampFrequency){
  1839. this.dampFrequency = dampFrequency;
  1840. this.LOWPASSL.set(dampFrequency, 0);
  1841. this.LOWPASSR.set(dampFrequency, 0);
  1842. };
  1843. /**
  1844. * Process a given interleaved float value Array and copies and adds the reverb signal.
  1845. *
  1846. * @param {Array} samples Array containing Float values or a Float64Array
  1847. *
  1848. * @returns A new Float64Array interleaved buffer.
  1849. */
  1850. Reverb.prototype.process = function (interleavedSamples){
  1851. // NB. Make a copy to put in the output samples to return.
  1852. var outputSamples = new Float64Array(interleavedSamples.length);
  1853. // Perform low pass on the input samples to mimick damp
  1854. var leftRightMix = DSP.deinterleave(interleavedSamples);
  1855. this.LOWPASSL.process( leftRightMix[DSP.LEFT] );
  1856. this.LOWPASSR.process( leftRightMix[DSP.RIGHT] );
  1857. var filteredSamples = DSP.interleave(leftRightMix[DSP.LEFT], leftRightMix[DSP.RIGHT]);
  1858. var i;
  1859. // Process MultiDelays in parallel
  1860. for (i = 0; i<this.NR_OF_MULTIDELAYS; i++) {
  1861. // Invert the signal of every even multiDelay
  1862. outputSamples = DSP.mixSampleBuffers(outputSamples, this.multiDelays[i].process(filteredSamples), 2%i === 0, this.NR_OF_MULTIDELAYS);
  1863. }
  1864. // Process SingleDelays in series
  1865. var singleDelaySamples = new Float64Array(outputSamples.length);
  1866. for (i = 0; i<this.NR_OF_SINGLEDELAYS; i++) {
  1867. // Invert the signal of every even singleDelay
  1868. singleDelaySamples = DSP.mixSampleBuffers(singleDelaySamples, this.singleDelays[i].process(outputSamples), 2%i === 0, 1);
  1869. }
  1870. // Apply the volume of the reverb signal
  1871. for (i = 0; i<singleDelaySamples.length; i++) {
  1872. singleDelaySamples[i] *= this.mixVolume;
  1873. }
  1874. // Mix the original signal with the reverb signal
  1875. outputSamples = DSP.mixSampleBuffers(singleDelaySamples, interleavedSamples, 0, 1);
  1876. // Apply the master volume to the complete signal
  1877. for (i = 0; i<outputSamples.length; i++) {
  1878. outputSamples[i] *= this.masterVolume;
  1879. }
  1880. return outputSamples;
  1881. };
  1882. if (typeof module !== 'undefined' && module && module.exports) {
  1883. module.exports = {
  1884. DSP: DSP,
  1885. DFT: DFT,
  1886. FFT: FFT,
  1887. RFFT: RFFT,
  1888. Sampler: Sampler,
  1889. Oscillator: Oscillator,
  1890. ADSR: ADSR,
  1891. IIRFilter: IIRFilter,
  1892. IIRFilter2: IIRFilter2,
  1893. WindowFunction: WindowFunction,
  1894. sinh: sinh,
  1895. Biquad: Biquad,
  1896. GraphicalEq: GraphicalEq,
  1897. MultiDelay: MultiDelay,
  1898. SingleDelay: SingleDelay,
  1899. Reverb: Reverb
  1900. };
  1901. }