@kidlib/web-audio 0.1.2 → 0.1.4
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 +2 -0
- package/dist/index.d.ts +29 -7
- package/dist/index.js +208 -176
- package/dist/processors/processors.js +20 -20
- package/package.json +6 -3
|
@@ -140,7 +140,8 @@ var SamplePlayerProcessor = class extends AudioWorkletProcessor {
|
|
|
140
140
|
}
|
|
141
141
|
constructor() {
|
|
142
142
|
super();
|
|
143
|
-
this.
|
|
143
|
+
this.layers = [];
|
|
144
|
+
this.layerGain = 1;
|
|
144
145
|
this.minZeroCrossing = 0;
|
|
145
146
|
this.maxZeroCrossing = 0;
|
|
146
147
|
this.usePlaybackPosition = false;
|
|
@@ -161,34 +162,31 @@ var SamplePlayerProcessor = class extends AudioWorkletProcessor {
|
|
|
161
162
|
this.#resetState();
|
|
162
163
|
this.port.postMessage({ type: "initialized" });
|
|
163
164
|
}
|
|
165
|
+
/** Authority layer. All range and duration math reads through this. */
|
|
166
|
+
get buffer() {
|
|
167
|
+
return this.layers[0] ?? null;
|
|
168
|
+
}
|
|
164
169
|
#handleMessage(event) {
|
|
165
|
-
const { type, value, buffer, timestamp, durationSeconds, zeroCrossings,
|
|
170
|
+
const { type, value, buffer, layers, timestamp, durationSeconds, zeroCrossings, allowedPeriods, playbackDirection } = event.data;
|
|
166
171
|
switch (type) {
|
|
167
172
|
case "voice:reset":
|
|
168
173
|
this.#resetState();
|
|
169
174
|
this.port.postMessage({ type: "voice:reset" });
|
|
170
175
|
break;
|
|
171
176
|
case "voice:setBuffer":
|
|
177
|
+
case "voice:setLayers":
|
|
172
178
|
this.#resetState();
|
|
173
179
|
this.zeroCrossings = [];
|
|
174
180
|
this.minZeroCrossing = 0;
|
|
175
181
|
this.maxZeroCrossing = 0;
|
|
176
|
-
this.
|
|
177
|
-
this.
|
|
182
|
+
this.layers = (layers ?? (buffer ? [buffer] : [])).filter(Boolean);
|
|
183
|
+
this.layerGain = this.layers.length ? 1 / this.layers.length : 1;
|
|
178
184
|
this.port.postMessage({
|
|
179
185
|
type: "voice:loaded",
|
|
180
186
|
durationSeconds,
|
|
181
187
|
time: currentTime
|
|
182
188
|
});
|
|
183
189
|
break;
|
|
184
|
-
case "transpose":
|
|
185
|
-
this.transpositionPlaybackrate = Math.pow(2, semitones / 12);
|
|
186
|
-
this.port.postMessage({
|
|
187
|
-
type: "voice:transposed",
|
|
188
|
-
semitones,
|
|
189
|
-
time: currentTime
|
|
190
|
-
});
|
|
191
|
-
break;
|
|
192
190
|
case "voice:setZeroCrossings":
|
|
193
191
|
this.zeroCrossings = (zeroCrossings || []).map((timeSec) => timeSec * sampleRate);
|
|
194
192
|
if (this.zeroCrossings.length > 0) {
|
|
@@ -258,7 +256,6 @@ var SamplePlayerProcessor = class extends AudioWorkletProcessor {
|
|
|
258
256
|
this.isPlaying = false;
|
|
259
257
|
this.isReleasing = false;
|
|
260
258
|
this.loopEnabled = false;
|
|
261
|
-
this.transpositionPlaybackrate = 1;
|
|
262
259
|
this.velocitySensitivity = 1;
|
|
263
260
|
this.reversePlayback = false;
|
|
264
261
|
this.playbackPosition = 0;
|
|
@@ -560,7 +557,7 @@ var SamplePlayerProcessor = class extends AudioWorkletProcessor {
|
|
|
560
557
|
const masterGain = parameters.masterGain[0];
|
|
561
558
|
const positionParams = this.#extractPositionParams(parameters);
|
|
562
559
|
const playbackRange = this.#calculatePlaybackRange(positionParams);
|
|
563
|
-
const effectivePlaybackRate = parameters.playbackRate[0]
|
|
560
|
+
const effectivePlaybackRate = parameters.playbackRate[0];
|
|
564
561
|
const tempo = parameters.tempo[0];
|
|
565
562
|
const loopRange = this.#calculateLoopRange(positionParams, playbackRange, parameters.loopDurationDriftAmount[0], tempo, effectivePlaybackRate);
|
|
566
563
|
const amplitudeGain = this.#analyzeLoopAmplitude(loopRange.loopStartSamples, loopRange.loopEndSamples);
|
|
@@ -590,7 +587,7 @@ var SamplePlayerProcessor = class extends AudioWorkletProcessor {
|
|
|
590
587
|
for (let sample = 0; sample < outputChannels[0].length; sample++) {
|
|
591
588
|
const envelopeGain = this.#getSafeParam(parameters.envGain, sample, isConstant.envGain);
|
|
592
589
|
const baseRate = this.#getSafeParam(parameters.playbackRate, sample, isConstant.playbackRate);
|
|
593
|
-
const playbackStep =
|
|
590
|
+
const playbackStep = this.reversePlayback ? -Math.abs(baseRate) : Math.abs(baseRate);
|
|
594
591
|
const canWrapLoop = this.loopEnabled && this.loopCount < parameters.maxLoopCount[0];
|
|
595
592
|
if (canWrapLoop) {
|
|
596
593
|
if (!this.reversePlayback && this.playbackPosition >= loopRange.loopEndSamples) {
|
|
@@ -633,11 +630,14 @@ var SamplePlayerProcessor = class extends AudioWorkletProcessor {
|
|
|
633
630
|
console.warn(`Output channel ${channel} does not exist. Available channels:`, outputChannels.length);
|
|
634
631
|
continue;
|
|
635
632
|
}
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
633
|
+
let interpolatedSample = 0;
|
|
634
|
+
for (let l = 0; l < this.layers.length; l++) {
|
|
635
|
+
const layer = this.layers[l];
|
|
636
|
+
const layerChannel = layer[Math.min(channel, layer.length - 1)];
|
|
637
|
+
const currentSample = layerChannel[currentPosition] || 0;
|
|
638
|
+
const nextSample = layerChannel[nextPosition] || 0;
|
|
639
|
+
interpolatedSample += (currentSample + interpWeight * (nextSample - currentSample)) * this.layerGain;
|
|
640
|
+
}
|
|
641
641
|
if (this.applyClickCompensation) {
|
|
642
642
|
interpolatedSample += this.loopClickCompensation;
|
|
643
643
|
if (this.compensationDecay) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kidlib/web-audio",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "High-level Web Audio primitives for musical instruments and tools.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -30,12 +30,12 @@
|
|
|
30
30
|
"access": "public"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"webmidi": "^3.1.
|
|
33
|
+
"webmidi": "^3.1.16"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
|
+
"@changesets/cli": "3.0.1",
|
|
36
37
|
"@types/audioworklet": "^0.0.72",
|
|
37
38
|
"@types/node": "^24.13.3",
|
|
38
|
-
"@types/webmidi": "^2.1.0",
|
|
39
39
|
"@vitest/browser-playwright": "4.1.10",
|
|
40
40
|
"@vitest/coverage-v8": "4.1.10",
|
|
41
41
|
"concurrently": "^9.1.2",
|
|
@@ -49,6 +49,9 @@
|
|
|
49
49
|
"vitest": "4.1.10"
|
|
50
50
|
},
|
|
51
51
|
"scripts": {
|
|
52
|
+
"changeset": "vp exec changeset",
|
|
53
|
+
"bump": "vp exec changeset version",
|
|
54
|
+
"release": "vp check && vp run test:all && vp exec changeset publish",
|
|
52
55
|
"build:worklets": "vp node build-processors.js",
|
|
53
56
|
"build": "vp run clean && vp build",
|
|
54
57
|
"watch:processors": "vp node watch-processors.js",
|