@logue/reverb 1.4.1 → 1.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -87,6 +87,66 @@ sourceNode.connect(ctx.destination);
87
87
  sourceNode.play();
88
88
  ```
89
89
 
90
+ ## Testing
91
+
92
+ This project includes a comprehensive test suite to ensure reliability and code quality.
93
+
94
+ ### Test Coverage
95
+
96
+ - **Statement Coverage**: 100%
97
+ - **Function Coverage**: 100%
98
+ - **Branch Coverage**: 90.56%
99
+ - **Line Coverage**: 100%
100
+
101
+ ### Test Structure
102
+
103
+ The test suite is organized into several categories:
104
+
105
+ - **Unit Tests**: Individual method and property testing
106
+ - `src/__tests__/Reverb.test.ts` - Main Reverb class tests
107
+ - `src/__tests__/NoiseType.test.ts` - Noise type definition tests
108
+ - `src/__tests__/OptionInterface.test.ts` - Configuration interface tests
109
+
110
+ - **Integration Tests**: Component interaction testing
111
+ - `src/__tests__/integration.test.ts` - Cross-component integration tests
112
+
113
+ - **End-to-End Tests**: Real-world usage scenarios
114
+ - `src/__tests__/e2e.test.ts` - Practical implementation scenarios
115
+
116
+ ### Test Features
117
+
118
+ The test suite covers:
119
+
120
+ - ✅ Constructor with default and custom options
121
+ - ✅ Audio node connection and disconnection
122
+ - ✅ Parameter validation and error handling
123
+ - ✅ All reverb parameters (mix, time, decay, delay, reverse)
124
+ - ✅ Filter configurations (type, frequency, Q-factor)
125
+ - ✅ Noise algorithm variations (white, pink, brown, blue, violet, red, green)
126
+ - ✅ Performance testing with multiple instances
127
+ - ✅ Edge cases and boundary conditions
128
+ - ✅ Real-world scenarios (guitar, vocal, drum reverb settings)
129
+
130
+ ### Running Tests
131
+
132
+ ```bash
133
+ # Run all tests
134
+ pnpm test
135
+
136
+ # Run tests once
137
+ pnpm test:run
138
+
139
+ # Run tests with coverage report
140
+ pnpm test:coverage
141
+ ```
142
+
143
+ ### Test Environment
144
+
145
+ - **Vitest** - Fast Vite-based test framework
146
+ - **Happy-DOM** - Browser environment simulation
147
+ - **Web Audio API Mocking** - Complete audio context simulation
148
+ - **TypeScript Support** - Full type checking during tests
149
+
90
150
  ### CDN Usage
91
151
 
92
152
  Not really intended for use with a CDN.
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @logue/reverb
3
+ *
4
+ * @description JavaScript Reverb effect class
5
+ * @author Logue <logue@hotmail.co.jp>
6
+ * @copyright 2019-2025 By Masashi Yoshikawa All rights reserved.
7
+ * @license MIT
8
+ * @version 1.4.1
9
+ * @see {@link https://github.com/logue/Reverb.js}
10
+ */
11
+
12
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var s=require("@thi.ng/colored-noise"),u=require("@thi.ng/transducers"),f=require("@thi.ng/random");const d={version:"1.4.1",date:"2025-07-12T06:07:47.985Z"},m={noise:"white",scale:1,peaks:2,randomAlgorithm:f.SYSTEM,decay:2,delay:0,reverse:!1,time:2,filterType:"allpass",filterFreq:2200,filterQ:1,mix:.5,once:!1};class o{static version=d.version;static build=d.date;ctx;wetGainNode;dryGainNode;filterNode;convolverNode;outputNode;options;isConnected;noise=s.white;noiseMap={blue:s.blue,green:s.green,pink:s.pink,red:s.red,brown:s.red,violet:s.violet,white:s.white};constructor(e,t){this.ctx=e,this.options=Object.assign(m,t),this.wetGainNode=this.ctx.createGain(),this.dryGainNode=this.ctx.createGain(),this.filterNode=this.ctx.createBiquadFilter(),this.convolverNode=this.ctx.createConvolver(),this.outputNode=this.ctx.createGain(),this.isConnected=!1,this.filterType(this.options.filterType),this.setNoise(this.options.noise),this.buildImpulse(),this.mix(this.options.mix)}connect(e){return this.isConnected&&this.options.once?(this.isConnected=!1,this.outputNode):(this.convolverNode.connect(this.filterNode),this.filterNode.connect(this.wetGainNode),e.connect(this.convolverNode),e.connect(this.dryGainNode),e.connect(this.wetGainNode),this.dryGainNode.connect(this.outputNode),this.wetGainNode.connect(this.outputNode),this.isConnected=!0,this.outputNode)}disconnect(e){return this.isConnected&&(this.convolverNode.disconnect(this.filterNode),this.filterNode.disconnect(this.wetGainNode)),this.isConnected=!1,e}mix(e){if(!o.inRange(e,0,1))throw new RangeError("[Reverb.js] Dry/Wet ratio must be between 0 to 1.");this.options.mix=e,this.dryGainNode.gain.value=1-e,this.wetGainNode.gain.value=e}time(e){if(!o.inRange(e,1,50))throw new RangeError("[Reverb.js] Time length of impulse response must be less than 50sec.");this.options.time=e,this.buildImpulse()}decay(e){if(!o.inRange(e,0,100))throw new RangeError("[Reverb.js] Impulse Response decay level must be less than 100.");this.options.decay=e,this.buildImpulse()}delay(e){if(!o.inRange(e,0,100))throw new RangeError("[Reverb.js] Impulse Response delay time must be less than 100.");this.options.delay=e,this.buildImpulse()}reverse(e){this.options.reverse=e,this.buildImpulse()}filterType(e="allpass"){this.filterNode.type=this.options.filterType=e}filterFreq(e){if(!o.inRange(e,20,2e4))throw new RangeError("[Reverb.js] Filter frequrncy must be between 20 and 20000.");this.options.filterFreq=e,this.filterNode.frequency.value=this.options.filterFreq}filterQ(e){if(!o.inRange(e,0,10))throw new RangeError("[Reverb.js] Filter Q value must be between 0 and 10.");this.options.filterQ=e,this.filterNode.Q.value=this.options.filterQ}peaks(e){this.options.peaks=e,this.buildImpulse()}scale(e){this.options.scale=e,this.buildImpulse()}getNoise(e){return[...u.take(e,this.noise({bins:this.options.peaks,scale:this.options.scale,rnd:this.options.randomAlgorithm}))]}setNoise(e){this.options.noise=e,this.noise=this.noiseMap[e]||s.white,this.buildImpulse()}setRandomAlgorithm(e){this.options.randomAlgorithm=e,this.buildImpulse()}static inRange(e,t,n){return e>=t&&e<=n}buildImpulse(){const e=this.ctx.sampleRate,t=Math.max(e*this.options.time,1),n=e*this.options.delay,a=this.ctx.createBuffer(2,t,e),l=new Float32Array(t),h=new Float32Array(t),c=this.getNoise(t),p=this.getNoise(t);for(let i=0;i<t;i++){let r=0;i<n?(l[i]=0,h[i]=0,r=this.options.reverse??!1?t-(i-n):i-n):r=this.options.reverse??!1?t-i:i,l[i]=(c[i]??0)*(1-r/t)**this.options.decay,h[i]=(p[i]??0)*(1-r/t)**this.options.decay}a.getChannelData(0).set(l),a.getChannelData(1).set(h),this.convolverNode.buffer=a}}exports.default=o;
package/dist/Reverb.es.js CHANGED
@@ -14,7 +14,7 @@ import { take as v } from "@thi.ng/transducers";
14
14
  import { SYSTEM as w } from "@thi.ng/random";
15
15
  const c = {
16
16
  version: "1.4.1",
17
- date: "2025-06-22T14:40:43.637Z"
17
+ date: "2025-07-12T06:07:47.985Z"
18
18
  }, y = {
19
19
  noise: "white",
20
20
  scale: 1,
@@ -9,4 +9,4 @@
9
9
  * @see {@link https://github.com/logue/Reverb.js}
10
10
  */
11
11
 
12
- var Reverb=function(a,s,u,p){"use strict";const c={version:"1.4.1",date:"2025-06-22T14:40:43.637Z"},f={noise:"white",scale:1,peaks:2,randomAlgorithm:p.SYSTEM,decay:2,delay:0,reverse:!1,time:2,filterType:"allpass",filterFreq:2200,filterQ:1,mix:.5,once:!1};class n{static version=c.version;static build=c.date;ctx;wetGainNode;dryGainNode;filterNode;convolverNode;outputNode;options;isConnected;noise=s.white;noiseMap={blue:s.blue,green:s.green,pink:s.pink,red:s.red,brown:s.red,violet:s.violet,white:s.white};constructor(e,t){this.ctx=e,this.options=Object.assign(f,t),this.wetGainNode=this.ctx.createGain(),this.dryGainNode=this.ctx.createGain(),this.filterNode=this.ctx.createBiquadFilter(),this.convolverNode=this.ctx.createConvolver(),this.outputNode=this.ctx.createGain(),this.isConnected=!1,this.filterType(this.options.filterType),this.setNoise(this.options.noise),this.buildImpulse(),this.mix(this.options.mix)}connect(e){return this.isConnected&&this.options.once?(this.isConnected=!1,this.outputNode):(this.convolverNode.connect(this.filterNode),this.filterNode.connect(this.wetGainNode),e.connect(this.convolverNode),e.connect(this.dryGainNode),e.connect(this.wetGainNode),this.dryGainNode.connect(this.outputNode),this.wetGainNode.connect(this.outputNode),this.isConnected=!0,this.outputNode)}disconnect(e){return this.isConnected&&(this.convolverNode.disconnect(this.filterNode),this.filterNode.disconnect(this.wetGainNode)),this.isConnected=!1,e}mix(e){if(!n.inRange(e,0,1))throw new RangeError("[Reverb.js] Dry/Wet ratio must be between 0 to 1.");this.options.mix=e,this.dryGainNode.gain.value=1-e,this.wetGainNode.gain.value=e}time(e){if(!n.inRange(e,1,50))throw new RangeError("[Reverb.js] Time length of impulse response must be less than 50sec.");this.options.time=e,this.buildImpulse()}decay(e){if(!n.inRange(e,0,100))throw new RangeError("[Reverb.js] Impulse Response decay level must be less than 100.");this.options.decay=e,this.buildImpulse()}delay(e){if(!n.inRange(e,0,100))throw new RangeError("[Reverb.js] Impulse Response delay time must be less than 100.");this.options.delay=e,this.buildImpulse()}reverse(e){this.options.reverse=e,this.buildImpulse()}filterType(e="allpass"){this.filterNode.type=this.options.filterType=e}filterFreq(e){if(!n.inRange(e,20,2e4))throw new RangeError("[Reverb.js] Filter frequrncy must be between 20 and 20000.");this.options.filterFreq=e,this.filterNode.frequency.value=this.options.filterFreq}filterQ(e){if(!n.inRange(e,0,10))throw new RangeError("[Reverb.js] Filter Q value must be between 0 and 10.");this.options.filterQ=e,this.filterNode.Q.value=this.options.filterQ}peaks(e){this.options.peaks=e,this.buildImpulse()}scale(e){this.options.scale=e,this.buildImpulse()}getNoise(e){return[...u.take(e,this.noise({bins:this.options.peaks,scale:this.options.scale,rnd:this.options.randomAlgorithm}))]}setNoise(e){this.options.noise=e,this.noise=this.noiseMap[e]||s.white,this.buildImpulse()}setRandomAlgorithm(e){this.options.randomAlgorithm=e,this.buildImpulse()}static inRange(e,t,o){return e>=t&&e<=o}buildImpulse(){const e=this.ctx.sampleRate,t=Math.max(e*this.options.time,1),o=e*this.options.delay,h=this.ctx.createBuffer(2,t,e),l=new Float32Array(t),d=new Float32Array(t),m=this.getNoise(t),v=this.getNoise(t);for(let i=0;i<t;i++){let r=0;i<o?(l[i]=0,d[i]=0,r=this.options.reverse??!1?t-(i-o):i-o):r=this.options.reverse??!1?t-i:i,l[i]=(m[i]??0)*(1-r/t)**this.options.decay,d[i]=(v[i]??0)*(1-r/t)**this.options.decay}h.getChannelData(0).set(l),h.getChannelData(1).set(d),this.convolverNode.buffer=h}}return a.default=n,Object.defineProperty(a,"__esModule",{value:!0}),a}({},coloredNoise,transducers,random);
12
+ var Reverb=function(a,s,u,p){"use strict";const c={version:"1.4.1",date:"2025-07-12T06:07:47.985Z"},f={noise:"white",scale:1,peaks:2,randomAlgorithm:p.SYSTEM,decay:2,delay:0,reverse:!1,time:2,filterType:"allpass",filterFreq:2200,filterQ:1,mix:.5,once:!1};class n{static version=c.version;static build=c.date;ctx;wetGainNode;dryGainNode;filterNode;convolverNode;outputNode;options;isConnected;noise=s.white;noiseMap={blue:s.blue,green:s.green,pink:s.pink,red:s.red,brown:s.red,violet:s.violet,white:s.white};constructor(e,t){this.ctx=e,this.options=Object.assign(f,t),this.wetGainNode=this.ctx.createGain(),this.dryGainNode=this.ctx.createGain(),this.filterNode=this.ctx.createBiquadFilter(),this.convolverNode=this.ctx.createConvolver(),this.outputNode=this.ctx.createGain(),this.isConnected=!1,this.filterType(this.options.filterType),this.setNoise(this.options.noise),this.buildImpulse(),this.mix(this.options.mix)}connect(e){return this.isConnected&&this.options.once?(this.isConnected=!1,this.outputNode):(this.convolverNode.connect(this.filterNode),this.filterNode.connect(this.wetGainNode),e.connect(this.convolverNode),e.connect(this.dryGainNode),e.connect(this.wetGainNode),this.dryGainNode.connect(this.outputNode),this.wetGainNode.connect(this.outputNode),this.isConnected=!0,this.outputNode)}disconnect(e){return this.isConnected&&(this.convolverNode.disconnect(this.filterNode),this.filterNode.disconnect(this.wetGainNode)),this.isConnected=!1,e}mix(e){if(!n.inRange(e,0,1))throw new RangeError("[Reverb.js] Dry/Wet ratio must be between 0 to 1.");this.options.mix=e,this.dryGainNode.gain.value=1-e,this.wetGainNode.gain.value=e}time(e){if(!n.inRange(e,1,50))throw new RangeError("[Reverb.js] Time length of impulse response must be less than 50sec.");this.options.time=e,this.buildImpulse()}decay(e){if(!n.inRange(e,0,100))throw new RangeError("[Reverb.js] Impulse Response decay level must be less than 100.");this.options.decay=e,this.buildImpulse()}delay(e){if(!n.inRange(e,0,100))throw new RangeError("[Reverb.js] Impulse Response delay time must be less than 100.");this.options.delay=e,this.buildImpulse()}reverse(e){this.options.reverse=e,this.buildImpulse()}filterType(e="allpass"){this.filterNode.type=this.options.filterType=e}filterFreq(e){if(!n.inRange(e,20,2e4))throw new RangeError("[Reverb.js] Filter frequrncy must be between 20 and 20000.");this.options.filterFreq=e,this.filterNode.frequency.value=this.options.filterFreq}filterQ(e){if(!n.inRange(e,0,10))throw new RangeError("[Reverb.js] Filter Q value must be between 0 and 10.");this.options.filterQ=e,this.filterNode.Q.value=this.options.filterQ}peaks(e){this.options.peaks=e,this.buildImpulse()}scale(e){this.options.scale=e,this.buildImpulse()}getNoise(e){return[...u.take(e,this.noise({bins:this.options.peaks,scale:this.options.scale,rnd:this.options.randomAlgorithm}))]}setNoise(e){this.options.noise=e,this.noise=this.noiseMap[e]||s.white,this.buildImpulse()}setRandomAlgorithm(e){this.options.randomAlgorithm=e,this.buildImpulse()}static inRange(e,t,o){return e>=t&&e<=o}buildImpulse(){const e=this.ctx.sampleRate,t=Math.max(e*this.options.time,1),o=e*this.options.delay,h=this.ctx.createBuffer(2,t,e),l=new Float32Array(t),d=new Float32Array(t),m=this.getNoise(t),v=this.getNoise(t);for(let i=0;i<t;i++){let r=0;i<o?(l[i]=0,d[i]=0,r=this.options.reverse??!1?t-(i-o):i-o):r=this.options.reverse??!1?t-i:i,l[i]=(m[i]??0)*(1-r/t)**this.options.decay,d[i]=(v[i]??0)*(1-r/t)**this.options.decay}h.getChannelData(0).set(l),h.getChannelData(1).set(d),this.convolverNode.buffer=h}}return a.default=n,Object.defineProperty(a,"__esModule",{value:!0}),a}({},coloredNoise,transducers,random);
@@ -9,4 +9,4 @@
9
9
  * @see {@link https://github.com/logue/Reverb.js}
10
10
  */
11
11
 
12
- (function(n,i){typeof exports=="object"&&typeof module<"u"?i(exports,require("@thi.ng/colored-noise"),require("@thi.ng/transducers"),require("@thi.ng/random")):typeof define=="function"&&define.amd?define(["exports","@thi.ng/colored-noise","@thi.ng/transducers","@thi.ng/random"],i):(n=typeof globalThis<"u"?globalThis:n||self,i(n.Reverb={},n.coloredNoise,n.transducers,n.random))})(this,function(n,i,u,p){"use strict";const c={version:"1.4.1",date:"2025-06-22T14:40:43.637Z"},f={noise:"white",scale:1,peaks:2,randomAlgorithm:p.SYSTEM,decay:2,delay:0,reverse:!1,time:2,filterType:"allpass",filterFreq:2200,filterQ:1,mix:.5,once:!1};class o{static version=c.version;static build=c.date;ctx;wetGainNode;dryGainNode;filterNode;convolverNode;outputNode;options;isConnected;noise=i.white;noiseMap={blue:i.blue,green:i.green,pink:i.pink,red:i.red,brown:i.red,violet:i.violet,white:i.white};constructor(e,t){this.ctx=e,this.options=Object.assign(f,t),this.wetGainNode=this.ctx.createGain(),this.dryGainNode=this.ctx.createGain(),this.filterNode=this.ctx.createBiquadFilter(),this.convolverNode=this.ctx.createConvolver(),this.outputNode=this.ctx.createGain(),this.isConnected=!1,this.filterType(this.options.filterType),this.setNoise(this.options.noise),this.buildImpulse(),this.mix(this.options.mix)}connect(e){return this.isConnected&&this.options.once?(this.isConnected=!1,this.outputNode):(this.convolverNode.connect(this.filterNode),this.filterNode.connect(this.wetGainNode),e.connect(this.convolverNode),e.connect(this.dryGainNode),e.connect(this.wetGainNode),this.dryGainNode.connect(this.outputNode),this.wetGainNode.connect(this.outputNode),this.isConnected=!0,this.outputNode)}disconnect(e){return this.isConnected&&(this.convolverNode.disconnect(this.filterNode),this.filterNode.disconnect(this.wetGainNode)),this.isConnected=!1,e}mix(e){if(!o.inRange(e,0,1))throw new RangeError("[Reverb.js] Dry/Wet ratio must be between 0 to 1.");this.options.mix=e,this.dryGainNode.gain.value=1-e,this.wetGainNode.gain.value=e}time(e){if(!o.inRange(e,1,50))throw new RangeError("[Reverb.js] Time length of impulse response must be less than 50sec.");this.options.time=e,this.buildImpulse()}decay(e){if(!o.inRange(e,0,100))throw new RangeError("[Reverb.js] Impulse Response decay level must be less than 100.");this.options.decay=e,this.buildImpulse()}delay(e){if(!o.inRange(e,0,100))throw new RangeError("[Reverb.js] Impulse Response delay time must be less than 100.");this.options.delay=e,this.buildImpulse()}reverse(e){this.options.reverse=e,this.buildImpulse()}filterType(e="allpass"){this.filterNode.type=this.options.filterType=e}filterFreq(e){if(!o.inRange(e,20,2e4))throw new RangeError("[Reverb.js] Filter frequrncy must be between 20 and 20000.");this.options.filterFreq=e,this.filterNode.frequency.value=this.options.filterFreq}filterQ(e){if(!o.inRange(e,0,10))throw new RangeError("[Reverb.js] Filter Q value must be between 0 and 10.");this.options.filterQ=e,this.filterNode.Q.value=this.options.filterQ}peaks(e){this.options.peaks=e,this.buildImpulse()}scale(e){this.options.scale=e,this.buildImpulse()}getNoise(e){return[...u.take(e,this.noise({bins:this.options.peaks,scale:this.options.scale,rnd:this.options.randomAlgorithm}))]}setNoise(e){this.options.noise=e,this.noise=this.noiseMap[e]||i.white,this.buildImpulse()}setRandomAlgorithm(e){this.options.randomAlgorithm=e,this.buildImpulse()}static inRange(e,t,r){return e>=t&&e<=r}buildImpulse(){const e=this.ctx.sampleRate,t=Math.max(e*this.options.time,1),r=e*this.options.delay,a=this.ctx.createBuffer(2,t,e),l=new Float32Array(t),d=new Float32Array(t),m=this.getNoise(t),g=this.getNoise(t);for(let s=0;s<t;s++){let h=0;s<r?(l[s]=0,d[s]=0,h=this.options.reverse??!1?t-(s-r):s-r):h=this.options.reverse??!1?t-s:s,l[s]=(m[s]??0)*(1-h/t)**this.options.decay,d[s]=(g[s]??0)*(1-h/t)**this.options.decay}a.getChannelData(0).set(l),a.getChannelData(1).set(d),this.convolverNode.buffer=a}}n.default=o,Object.defineProperty(n,"__esModule",{value:!0})});
12
+ (function(n,i){typeof exports=="object"&&typeof module<"u"?i(exports,require("@thi.ng/colored-noise"),require("@thi.ng/transducers"),require("@thi.ng/random")):typeof define=="function"&&define.amd?define(["exports","@thi.ng/colored-noise","@thi.ng/transducers","@thi.ng/random"],i):(n=typeof globalThis<"u"?globalThis:n||self,i(n.Reverb={},n.coloredNoise,n.transducers,n.random))})(this,function(n,i,u,p){"use strict";const c={version:"1.4.1",date:"2025-07-12T06:07:47.985Z"},f={noise:"white",scale:1,peaks:2,randomAlgorithm:p.SYSTEM,decay:2,delay:0,reverse:!1,time:2,filterType:"allpass",filterFreq:2200,filterQ:1,mix:.5,once:!1};class o{static version=c.version;static build=c.date;ctx;wetGainNode;dryGainNode;filterNode;convolverNode;outputNode;options;isConnected;noise=i.white;noiseMap={blue:i.blue,green:i.green,pink:i.pink,red:i.red,brown:i.red,violet:i.violet,white:i.white};constructor(e,t){this.ctx=e,this.options=Object.assign(f,t),this.wetGainNode=this.ctx.createGain(),this.dryGainNode=this.ctx.createGain(),this.filterNode=this.ctx.createBiquadFilter(),this.convolverNode=this.ctx.createConvolver(),this.outputNode=this.ctx.createGain(),this.isConnected=!1,this.filterType(this.options.filterType),this.setNoise(this.options.noise),this.buildImpulse(),this.mix(this.options.mix)}connect(e){return this.isConnected&&this.options.once?(this.isConnected=!1,this.outputNode):(this.convolverNode.connect(this.filterNode),this.filterNode.connect(this.wetGainNode),e.connect(this.convolverNode),e.connect(this.dryGainNode),e.connect(this.wetGainNode),this.dryGainNode.connect(this.outputNode),this.wetGainNode.connect(this.outputNode),this.isConnected=!0,this.outputNode)}disconnect(e){return this.isConnected&&(this.convolverNode.disconnect(this.filterNode),this.filterNode.disconnect(this.wetGainNode)),this.isConnected=!1,e}mix(e){if(!o.inRange(e,0,1))throw new RangeError("[Reverb.js] Dry/Wet ratio must be between 0 to 1.");this.options.mix=e,this.dryGainNode.gain.value=1-e,this.wetGainNode.gain.value=e}time(e){if(!o.inRange(e,1,50))throw new RangeError("[Reverb.js] Time length of impulse response must be less than 50sec.");this.options.time=e,this.buildImpulse()}decay(e){if(!o.inRange(e,0,100))throw new RangeError("[Reverb.js] Impulse Response decay level must be less than 100.");this.options.decay=e,this.buildImpulse()}delay(e){if(!o.inRange(e,0,100))throw new RangeError("[Reverb.js] Impulse Response delay time must be less than 100.");this.options.delay=e,this.buildImpulse()}reverse(e){this.options.reverse=e,this.buildImpulse()}filterType(e="allpass"){this.filterNode.type=this.options.filterType=e}filterFreq(e){if(!o.inRange(e,20,2e4))throw new RangeError("[Reverb.js] Filter frequrncy must be between 20 and 20000.");this.options.filterFreq=e,this.filterNode.frequency.value=this.options.filterFreq}filterQ(e){if(!o.inRange(e,0,10))throw new RangeError("[Reverb.js] Filter Q value must be between 0 and 10.");this.options.filterQ=e,this.filterNode.Q.value=this.options.filterQ}peaks(e){this.options.peaks=e,this.buildImpulse()}scale(e){this.options.scale=e,this.buildImpulse()}getNoise(e){return[...u.take(e,this.noise({bins:this.options.peaks,scale:this.options.scale,rnd:this.options.randomAlgorithm}))]}setNoise(e){this.options.noise=e,this.noise=this.noiseMap[e]||i.white,this.buildImpulse()}setRandomAlgorithm(e){this.options.randomAlgorithm=e,this.buildImpulse()}static inRange(e,t,r){return e>=t&&e<=r}buildImpulse(){const e=this.ctx.sampleRate,t=Math.max(e*this.options.time,1),r=e*this.options.delay,a=this.ctx.createBuffer(2,t,e),l=new Float32Array(t),d=new Float32Array(t),m=this.getNoise(t),g=this.getNoise(t);for(let s=0;s<t;s++){let h=0;s<r?(l[s]=0,d[s]=0,h=this.options.reverse??!1?t-(s-r):s-r):h=this.options.reverse??!1?t-s:s,l[s]=(m[s]??0)*(1-h/t)**this.options.decay,d[s]=(g[s]??0)*(1-h/t)**this.options.decay}a.getChannelData(0).set(l),a.getChannelData(1).set(d),this.convolverNode.buffer=a}}n.default=o,Object.defineProperty(n,"__esModule",{value:!0})});
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
3
  "name": "@logue/reverb",
4
- "version": "1.4.1",
4
+ "version": "1.4.3",
5
5
  "description": "JavaScript Reverb effect class",
6
6
  "keywords": [
7
7
  "webaudio",
@@ -34,14 +34,23 @@
34
34
  "exports": {
35
35
  ".": {
36
36
  "import": "./dist/Reverb.es.js",
37
- "types": "./dist/Reverb.d.ts"
38
- }
37
+ "types": "./dist/Reverb.d.ts",
38
+ "require": "./dist/Reverb.cjs.js",
39
+ "default": "./dist/Reverb.es.js"
40
+ },
41
+ "./umd": {
42
+ "default": "./dist/Reverb.umd.js"
43
+ },
44
+ "./iife": {
45
+ "default": "./dist/Reverb.iife.js"
46
+ },
47
+ "./package.json": "./package.json"
39
48
  },
40
49
  "engines": {
41
- "node": ">=22.0.1",
42
- "pnpm": ">=10.3.0"
50
+ "node": "^20.19.0 || >=22.12.0",
51
+ "pnpm": ">=10.2.0"
43
52
  },
44
- "packageManager": "pnpm@10.12.1",
53
+ "packageManager": "pnpm@10.18.3",
45
54
  "sideEffects": false,
46
55
  "scripts": {
47
56
  "dev": "vite",
@@ -54,39 +63,45 @@
54
63
  "build-only": "vite build",
55
64
  "lint": "eslint . --fix --cache --cache-location ./node_modules/.vite/vite-plugin-eslint && prettier . --write",
56
65
  "preview": "vite preview --mode=docs",
57
- "prepare": "husky"
66
+ "prepare": "husky",
67
+ "test": "vitest",
68
+ "test:run": "vitest run",
69
+ "test:coverage": "vitest run --coverage"
58
70
  },
59
- "dependencies": {
60
- "@thi.ng/colored-noise": "^1.0.102",
61
- "@thi.ng/random": "^4.1.20",
62
- "@thi.ng/transducers": "^9.4.2"
71
+ "peerDependencies": {
72
+ "@thi.ng/colored-noise": "^1.0.103",
73
+ "@thi.ng/random": "^4.1.21",
74
+ "@thi.ng/transducers": "^9.5.1"
63
75
  },
64
76
  "devDependencies": {
65
- "@eslint/js": "^9.29.0",
77
+ "@eslint/js": "^9.38.0",
66
78
  "@tsconfig/node-lts": "^22.0.2",
67
- "@types/node": "^24.0.3",
68
- "@typescript-eslint/eslint-plugin": "^8.34.1",
69
- "bootstrap": "^5.3.7",
70
- "eslint": "^9.29.0",
71
- "eslint-config-prettier": "^10.1.5",
79
+ "@types/node": "^24.8.1",
80
+ "@typescript-eslint/eslint-plugin": "^8.46.1",
81
+ "@vitest/coverage-v8": "^3.2.4",
82
+ "bootstrap": "^5.3.8",
83
+ "eslint": "^9.38.0",
84
+ "eslint-config-prettier": "^10.1.8",
72
85
  "eslint-import-resolver-custom-alias": "^1.3.2",
73
- "eslint-import-resolver-typescript": "^4.4.3",
86
+ "eslint-import-resolver-typescript": "^4.4.4",
74
87
  "eslint-plugin-import": "^2.32.0",
75
- "eslint-plugin-yaml": "^1.1.2",
76
- "globals": "^16.2.0",
88
+ "eslint-plugin-yaml": "^1.1.3",
89
+ "globals": "^16.4.0",
90
+ "happy-dom": "^20.0.5",
77
91
  "husky": "^9.1.7",
78
- "jiti": "^2.4.2",
79
- "lint-staged": "^16.1.2",
92
+ "jiti": "^2.6.1",
93
+ "lint-staged": "^16.2.4",
80
94
  "npm-run-all2": "^8.0.4",
81
- "prettier": "^3.5.3",
95
+ "prettier": "^3.6.2",
82
96
  "rimraf": "^6.0.1",
83
- "rollup-plugin-visualizer": "^6.0.3",
84
- "typescript": "^5.8.3",
85
- "typescript-eslint": "^8.34.1",
86
- "vite": "^6.3.5",
97
+ "rollup-plugin-visualizer": "^6.0.5",
98
+ "typescript": "^5.9.3",
99
+ "typescript-eslint": "^8.46.1",
100
+ "vite": "^7.1.10",
87
101
  "vite-plugin-banner": "^0.8.1",
88
- "vite-plugin-checker": "^0.9.3",
89
- "vite-plugin-dts": "^4.5.4"
102
+ "vite-plugin-checker": "^0.11.0",
103
+ "vite-plugin-dts": "^4.5.4",
104
+ "vitest": "^3.2.4"
90
105
  },
91
106
  "husky": {
92
107
  "hooks": {
@@ -101,4 +116,4 @@
101
116
  "json5": ">=2.2.3",
102
117
  "yaml": ">=2.3.2"
103
118
  }
104
- }
119
+ }