@k13engineering/rubberband 0.0.2 → 0.0.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.
@@ -0,0 +1,27 @@
1
+ type TRubberbandAudioData = {
2
+ planes: Float32Array[];
3
+ };
4
+ declare const createRubberbandWrapper: ({ sampleRate, channelCount, maxBufferSizeInFrames }: {
5
+ sampleRate: number;
6
+ channelCount: number;
7
+ maxBufferSizeInFrames: number;
8
+ }) => {
9
+ requestPitchScale: ({ pitchScale }: {
10
+ pitchScale: number;
11
+ }) => void;
12
+ requestTimeRatio: ({ timeRatio }: {
13
+ timeRatio: number;
14
+ }) => void;
15
+ samplesRequired: () => any;
16
+ process: ({ audioData }: {
17
+ audioData: TRubberbandAudioData;
18
+ }) => void;
19
+ available: () => number;
20
+ latencyInSamples: () => number;
21
+ retrieve: ({ sampleCount }: {
22
+ sampleCount: number;
23
+ }) => TRubberbandAudioData;
24
+ };
25
+ type TRubberbandWrapper = ReturnType<typeof createRubberbandWrapper>;
26
+ export { createRubberbandWrapper };
27
+ export type { TRubberbandWrapper };
package/dist/lib/index.js CHANGED
@@ -0,0 +1,125 @@
1
+ import { RubberBandInterface } from "rubberband-wasm";
2
+ import { loadRubberbandWasm } from "./rubberband.js";
3
+
4
+ /*type TRubberbandAudioData = {
5
+ planes: Float32Array[];
6
+ };*/
7
+
8
+ const rubberbandWasm = await loadRubberbandWasm();
9
+
10
+ const wasm = await WebAssembly.compile(rubberbandWasm);
11
+ const rubberbandApi = await RubberBandInterface.initialize(wasm);
12
+
13
+ const OptionProcessRealTime = 1;
14
+
15
+ const createRubberbandWrapper = ({
16
+ sampleRate,
17
+ channelCount,
18
+ maxBufferSizeInFrames
19
+ }/*: {
20
+ sampleRate: number;
21
+ channelCount: number;
22
+ maxBufferSizeInFrames: number;
23
+ }*/) => {
24
+
25
+ const channelArrayPtr = rubberbandApi.malloc(channelCount * 4);
26
+ const channelDataPtrs/*: number[]*/ = [];
27
+ for (let channel = 0; channel < channelCount; channel += 1) {
28
+ const bufferPtr = rubberbandApi.malloc(maxBufferSizeInFrames * 4);
29
+ channelDataPtrs.push(bufferPtr);
30
+ rubberbandApi.memWritePtr(channelArrayPtr + channel * 4, bufferPtr);
31
+ }
32
+
33
+ const rb = rubberbandApi.rubberband_new(sampleRate, channelCount, OptionProcessRealTime, 1, 1);
34
+
35
+ const requestPitchScale = ({ pitchScale }/*: { pitchScale: number }*/) => {
36
+ rubberbandApi.rubberband_set_pitch_scale(rb, pitchScale);
37
+ };
38
+
39
+ const requestTimeRatio = ({ timeRatio }/*: { timeRatio: number }*/) => {
40
+ rubberbandApi.rubberband_set_time_ratio(rb, timeRatio);
41
+ };
42
+
43
+ const samplesRequired = () => {
44
+ return rubberbandApi.rubberband_get_samples_required(rb);
45
+ };
46
+
47
+ const process = ({ audioData }/*: { audioData: TRubberbandAudioData }*/) => {
48
+
49
+ const firstPlane = audioData.planes[0];
50
+ const sampleCount = firstPlane.length;
51
+
52
+ audioData.planes.forEach((plane, channelIndex) => {
53
+
54
+ if (plane.length > maxBufferSizeInFrames) {
55
+ throw new Error("plane length exceeds max buffer size");
56
+ }
57
+
58
+ const channelDataPtr = channelDataPtrs[channelIndex];
59
+ rubberbandApi.memWrite(channelDataPtr, plane);
60
+ });
61
+
62
+ rubberbandApi.rubberband_process(rb, channelArrayPtr, sampleCount, 0);
63
+ };
64
+
65
+ const available = ()/*: number*/ => {
66
+ return rubberbandApi.rubberband_available(rb);
67
+ };
68
+
69
+ const latencyInSamples = ()/*: number*/ => {
70
+ return rubberbandApi.rubberband_get_latency(rb);
71
+ };
72
+
73
+ // eslint-disable-next-line complexity
74
+ const retrieve = ({ sampleCount }/*: { sampleCount: number }*/)/*: TRubberbandAudioData*/ => {
75
+
76
+ if (sampleCount > maxBufferSizeInFrames) {
77
+ throw Error(`requested sample count ${sampleCount} exceeds max buffer size ${maxBufferSizeInFrames}`);
78
+ }
79
+
80
+ if (sampleCount > available()) {
81
+ throw Error(`look before you leap: requested ${sampleCount} samples but only ${available()} available`);
82
+ }
83
+
84
+ const samplesReceived = rubberbandApi.rubberband_retrieve(rb, channelArrayPtr, sampleCount);
85
+
86
+ if (samplesReceived > sampleCount) {
87
+ throw Error("BUG: received more samples than requested");
88
+ }
89
+
90
+ if (samplesReceived < sampleCount) {
91
+ throw Error("BUG: received fewer samples than requested");
92
+ }
93
+
94
+ let planes/*: Float32Array[]*/ = [];
95
+
96
+ channelDataPtrs.forEach((channelDataPtr) => {
97
+ const plane = rubberbandApi.memReadF32(channelDataPtr, samplesReceived);
98
+ planes = [...planes, plane];
99
+ });
100
+
101
+ return {
102
+ planes
103
+ };
104
+ };
105
+
106
+ return {
107
+ requestPitchScale,
108
+ requestTimeRatio,
109
+ samplesRequired,
110
+ process,
111
+ available,
112
+ latencyInSamples,
113
+ retrieve
114
+ };
115
+ };
116
+
117
+ /*type TRubberbandWrapper = ReturnType<typeof createRubberbandWrapper>;*/
118
+
119
+ export {
120
+ createRubberbandWrapper
121
+ };
122
+
123
+ /*export type {
124
+ TRubberbandWrapper
125
+ };*/
@@ -0,0 +1,2 @@
1
+ declare const loadRubberbandWasm: () => unknown;
2
+ export { loadRubberbandWasm };
@@ -0,0 +1,14 @@
1
+ /* c8 ignore start */
2
+ import { loadAsBlob } from "esm-resource";
3
+
4
+ const loadRubberbandWasm = async () => {
5
+ const rubberbandBlob = await loadAsBlob({ importMeta: import.meta, filepath: "../../node_modules/rubberband-wasm/dist/rubberband.wasm" });
6
+ const rubberbandWasmArrayBuffer = await rubberbandBlob.arrayBuffer();
7
+ const rubberbandWasm = new Uint8Array(rubberbandWasmArrayBuffer);
8
+ return rubberbandWasm;
9
+ };
10
+
11
+ export {
12
+ loadRubberbandWasm
13
+ };
14
+ /* c8 ignore end */
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.0.2",
2
+ "version": "0.0.3",
3
3
  "name": "@k13engineering/rubberband",
4
4
  "type": "module",
5
5
  "description": "Rubberband wrapper for Node.js",
@@ -17,7 +17,10 @@
17
17
  "npm-check-updates": "^19.3.1",
18
18
  "typescript-eslint": "^8.53.0"
19
19
  },
20
- "dependencies": {},
20
+ "dependencies": {
21
+ "esm-resource": "^0.0.3",
22
+ "rubberband-wasm": "^3.3.0"
23
+ },
21
24
  "publishConfig": {
22
25
  "access": "public"
23
26
  },