@k13engineering/rubberband 0.0.6 → 0.0.8
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/dist/lib/index.d.ts +4 -1
- package/dist/lib/index.js +26 -4
- package/dist/lib/options.d.ts +19 -0
- package/dist/lib/options.js +95 -0
- package/package.json +1 -1
package/dist/lib/index.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
import { type TRubberbandOptions } from "./options.js";
|
|
1
2
|
type TRubberbandAudioData = {
|
|
2
3
|
planes: Float32Array[];
|
|
3
4
|
};
|
|
4
|
-
declare const createRubberbandWrapper: ({ sampleRate, channelCount, maxBufferSizeInFrames }: {
|
|
5
|
+
declare const createRubberbandWrapper: ({ sampleRate, channelCount, maxBufferSizeInFrames, options }: {
|
|
5
6
|
sampleRate: number;
|
|
6
7
|
channelCount: number;
|
|
7
8
|
maxBufferSizeInFrames: number;
|
|
9
|
+
options: Partial<TRubberbandOptions>;
|
|
8
10
|
}) => {
|
|
9
11
|
requestPitchScale: ({ pitchScale }: {
|
|
10
12
|
pitchScale: number;
|
|
@@ -16,6 +18,7 @@ declare const createRubberbandWrapper: ({ sampleRate, channelCount, maxBufferSiz
|
|
|
16
18
|
process: ({ audioData }: {
|
|
17
19
|
audioData: TRubberbandAudioData;
|
|
18
20
|
}) => void;
|
|
21
|
+
end: () => void;
|
|
19
22
|
available: () => number;
|
|
20
23
|
latencyInSamples: () => number;
|
|
21
24
|
retrieve: ({ sampleCount }: {
|
package/dist/lib/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { RubberBandInterface } from "rubberband-wasm";
|
|
2
2
|
import { loadRubberbandWasm } from "./rubberband.js";
|
|
3
|
+
import { optionsToBitmask, /*type TRubberbandOptions */} from "./options.js";
|
|
3
4
|
|
|
4
5
|
/*type TRubberbandAudioData = {
|
|
5
6
|
planes: Float32Array[];
|
|
@@ -10,18 +11,21 @@ const rubberbandWasm = await loadRubberbandWasm();
|
|
|
10
11
|
const wasm = await WebAssembly.compile(rubberbandWasm);
|
|
11
12
|
const rubberbandApi = await RubberBandInterface.initialize(wasm);
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
// eslint-disable-next-line max-statements
|
|
15
15
|
const createRubberbandWrapper = ({
|
|
16
16
|
sampleRate,
|
|
17
17
|
channelCount,
|
|
18
|
-
maxBufferSizeInFrames
|
|
18
|
+
maxBufferSizeInFrames,
|
|
19
|
+
options
|
|
19
20
|
}/*: {
|
|
20
21
|
sampleRate: number;
|
|
21
22
|
channelCount: number;
|
|
22
23
|
maxBufferSizeInFrames: number;
|
|
24
|
+
options: Partial<TRubberbandOptions>;
|
|
23
25
|
}*/) => {
|
|
24
26
|
|
|
27
|
+
let ended = false;
|
|
28
|
+
|
|
25
29
|
const channelArrayPtr = rubberbandApi.malloc(channelCount * 4);
|
|
26
30
|
const channelDataPtrs/*: number[]*/ = [];
|
|
27
31
|
for (let channel = 0; channel < channelCount; channel += 1) {
|
|
@@ -30,7 +34,12 @@ const createRubberbandWrapper = ({
|
|
|
30
34
|
rubberbandApi.memWritePtr(channelArrayPtr + channel * 4, bufferPtr);
|
|
31
35
|
}
|
|
32
36
|
|
|
33
|
-
const
|
|
37
|
+
const optionsBitmask = optionsToBitmask({ options });
|
|
38
|
+
const rb = rubberbandApi.rubberband_new(sampleRate, channelCount, optionsBitmask, 1, 1);
|
|
39
|
+
|
|
40
|
+
if (rb === 0) {
|
|
41
|
+
throw Error("failed to create rubberband instance");
|
|
42
|
+
}
|
|
34
43
|
|
|
35
44
|
const requestPitchScale = ({ pitchScale }/*: { pitchScale: number }*/) => {
|
|
36
45
|
rubberbandApi.rubberband_set_pitch_scale(rb, pitchScale);
|
|
@@ -45,6 +54,9 @@ const createRubberbandWrapper = ({
|
|
|
45
54
|
};
|
|
46
55
|
|
|
47
56
|
const process = ({ audioData }/*: { audioData: TRubberbandAudioData }*/) => {
|
|
57
|
+
if (ended) {
|
|
58
|
+
throw Error("already ended");
|
|
59
|
+
}
|
|
48
60
|
|
|
49
61
|
const firstPlane = audioData.planes[0];
|
|
50
62
|
const sampleCount = firstPlane.length;
|
|
@@ -66,6 +78,15 @@ const createRubberbandWrapper = ({
|
|
|
66
78
|
rubberbandApi.rubberband_process(rb, channelArrayPtr, sampleCount, 0);
|
|
67
79
|
};
|
|
68
80
|
|
|
81
|
+
const end = () => {
|
|
82
|
+
if (ended) {
|
|
83
|
+
throw Error("already ended");
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
ended = true;
|
|
87
|
+
rubberbandApi.rubberband_process(rb, channelArrayPtr, 0, 1);
|
|
88
|
+
};
|
|
89
|
+
|
|
69
90
|
const available = ()/*: number*/ => {
|
|
70
91
|
return rubberbandApi.rubberband_available(rb);
|
|
71
92
|
};
|
|
@@ -117,6 +138,7 @@ const createRubberbandWrapper = ({
|
|
|
117
138
|
requestTimeRatio,
|
|
118
139
|
samplesRequired,
|
|
119
140
|
process,
|
|
141
|
+
end,
|
|
120
142
|
available,
|
|
121
143
|
latencyInSamples,
|
|
122
144
|
retrieve
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
type TRubberbandOptions = {
|
|
2
|
+
processMode: "realtime" | "offline";
|
|
3
|
+
stretchMode: "elastic" | "precise";
|
|
4
|
+
transientsMode: "crisp" | "mixed" | "smooth";
|
|
5
|
+
detectorMode: "compound" | "percussive" | "soft";
|
|
6
|
+
phaseMode: "laminar" | "independent";
|
|
7
|
+
threadingMode: "auto" | "never" | "always";
|
|
8
|
+
windowMode: "standard" | "short" | "long";
|
|
9
|
+
smoothing: boolean;
|
|
10
|
+
formantMode: "shifted" | "preserved";
|
|
11
|
+
pitchMode: "highspeed" | "highquality" | "highconsistency";
|
|
12
|
+
channelMode: "apart" | "together";
|
|
13
|
+
engineMode: "faster" | "finer";
|
|
14
|
+
};
|
|
15
|
+
declare const optionsToBitmask: ({ options }: {
|
|
16
|
+
options: Partial<TRubberbandOptions>;
|
|
17
|
+
}) => number;
|
|
18
|
+
export { optionsToBitmask };
|
|
19
|
+
export type { TRubberbandOptions };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
const OptionProcessOffline = 0x00000000;
|
|
2
|
+
const OptionProcessRealTime = 0x00000001;
|
|
3
|
+
const OptionStretchElastic = 0x00000000;
|
|
4
|
+
const OptionStretchPrecise = 0x00000010;
|
|
5
|
+
const OptionTransientsCrisp = 0x00000000;
|
|
6
|
+
const OptionTransientsMixed = 0x00000100;
|
|
7
|
+
const OptionTransientsSmooth = 0x00000200;
|
|
8
|
+
const OptionDetectorCompound = 0x00000000;
|
|
9
|
+
const OptionDetectorPercussive = 0x00000400;
|
|
10
|
+
const OptionDetectorSoft = 0x00000800;
|
|
11
|
+
const OptionPhaseLaminar = 0x00000000;
|
|
12
|
+
const OptionPhaseIndependent = 0x00002000;
|
|
13
|
+
const OptionThreadingAuto = 0x00000000;
|
|
14
|
+
const OptionThreadingNever = 0x00010000;
|
|
15
|
+
const OptionThreadingAlways = 0x00020000;
|
|
16
|
+
const OptionWindowStandard = 0x00000000;
|
|
17
|
+
const OptionWindowShort = 0x00100000;
|
|
18
|
+
const OptionWindowLong = 0x00200000;
|
|
19
|
+
const OptionSmoothingOff = 0x00000000;
|
|
20
|
+
const OptionSmoothingOn = 0x00800000;
|
|
21
|
+
const OptionFormantShifted = 0x00000000;
|
|
22
|
+
const OptionFormantPreserved = 0x01000000;
|
|
23
|
+
const OptionPitchHighSpeed = 0x00000000;
|
|
24
|
+
const OptionPitchHighQuality = 0x02000000;
|
|
25
|
+
const OptionPitchHighConsistency = 0x04000000;
|
|
26
|
+
const OptionChannelsApart = 0x00000000;
|
|
27
|
+
const OptionChannelsTogether = 0x10000000;
|
|
28
|
+
const OptionEngineFaster = 0x00000000;
|
|
29
|
+
const OptionEngineFiner = 0x20000000;
|
|
30
|
+
|
|
31
|
+
/*type TRubberbandOptions = {
|
|
32
|
+
processMode: "realtime" | "offline";
|
|
33
|
+
stretchMode: "elastic" | "precise";
|
|
34
|
+
transientsMode: "crisp" | "mixed" | "smooth";
|
|
35
|
+
detectorMode: "compound" | "percussive" | "soft";
|
|
36
|
+
phaseMode: "laminar" | "independent";
|
|
37
|
+
threadingMode: "auto" | "never" | "always";
|
|
38
|
+
windowMode: "standard" | "short" | "long";
|
|
39
|
+
smoothing: boolean;
|
|
40
|
+
formantMode: "shifted" | "preserved";
|
|
41
|
+
pitchMode: "highspeed" | "highquality" | "highconsistency";
|
|
42
|
+
channelMode: "apart" | "together";
|
|
43
|
+
engineMode: "faster" | "finer";
|
|
44
|
+
};*/
|
|
45
|
+
|
|
46
|
+
// eslint-disable-next-line max-statements
|
|
47
|
+
const optionsToBitmask = ({ options }/*: { options: Partial<TRubberbandOptions> }*/)/*: number*/ => {
|
|
48
|
+
let bitmask = 0;
|
|
49
|
+
|
|
50
|
+
const addIf = ({ condition, value }/*: { condition: boolean; value: number }*/) => {
|
|
51
|
+
if (condition) {
|
|
52
|
+
bitmask |= value;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
addIf({ condition: options.processMode === "realtime", value: OptionProcessRealTime });
|
|
57
|
+
addIf({ condition: options.processMode === "offline", value: OptionProcessOffline });
|
|
58
|
+
addIf({ condition: options.stretchMode === "elastic", value: OptionStretchElastic });
|
|
59
|
+
addIf({ condition: options.stretchMode === "precise", value: OptionStretchPrecise });
|
|
60
|
+
addIf({ condition: options.transientsMode === "mixed", value: OptionTransientsMixed });
|
|
61
|
+
addIf({ condition: options.transientsMode === "crisp", value: OptionTransientsCrisp });
|
|
62
|
+
addIf({ condition: options.transientsMode === "smooth", value: OptionTransientsSmooth });
|
|
63
|
+
addIf({ condition: options.detectorMode === "compound", value: OptionDetectorCompound });
|
|
64
|
+
addIf({ condition: options.detectorMode === "percussive", value: OptionDetectorPercussive });
|
|
65
|
+
addIf({ condition: options.detectorMode === "soft", value: OptionDetectorSoft });
|
|
66
|
+
addIf({ condition: options.phaseMode === "laminar", value: OptionPhaseLaminar });
|
|
67
|
+
addIf({ condition: options.phaseMode === "independent", value: OptionPhaseIndependent });
|
|
68
|
+
addIf({ condition: options.threadingMode === "auto", value: OptionThreadingAuto });
|
|
69
|
+
addIf({ condition: options.threadingMode === "never", value: OptionThreadingNever });
|
|
70
|
+
addIf({ condition: options.threadingMode === "always", value: OptionThreadingAlways });
|
|
71
|
+
addIf({ condition: options.windowMode === "standard", value: OptionWindowStandard });
|
|
72
|
+
addIf({ condition: options.windowMode === "short", value: OptionWindowShort });
|
|
73
|
+
addIf({ condition: options.windowMode === "long", value: OptionWindowLong });
|
|
74
|
+
addIf({ condition: options.smoothing === false, value: OptionSmoothingOff });
|
|
75
|
+
addIf({ condition: options.smoothing === true, value: OptionSmoothingOn });
|
|
76
|
+
addIf({ condition: options.formantMode === "preserved", value: OptionFormantPreserved });
|
|
77
|
+
addIf({ condition: options.formantMode === "shifted", value: OptionFormantShifted });
|
|
78
|
+
addIf({ condition: options.pitchMode === "highspeed", value: OptionPitchHighSpeed });
|
|
79
|
+
addIf({ condition: options.pitchMode === "highquality", value: OptionPitchHighQuality });
|
|
80
|
+
addIf({ condition: options.pitchMode === "highconsistency", value: OptionPitchHighConsistency });
|
|
81
|
+
addIf({ condition: options.channelMode === "apart", value: OptionChannelsApart });
|
|
82
|
+
addIf({ condition: options.channelMode === "together", value: OptionChannelsTogether });
|
|
83
|
+
addIf({ condition: options.engineMode === "faster", value: OptionEngineFaster });
|
|
84
|
+
addIf({ condition: options.engineMode === "finer", value: OptionEngineFiner });
|
|
85
|
+
|
|
86
|
+
return bitmask;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export {
|
|
90
|
+
optionsToBitmask
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
/*export type {
|
|
94
|
+
TRubberbandOptions
|
|
95
|
+
};*/
|
package/package.json
CHANGED