@audio/shift-pvoc-lock 1.0.0
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/index.js +39 -0
- package/package.json +40 -0
package/index.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { makeStftShift } from '@audio/shift-core/stft'
|
|
2
|
+
import { findPeaks, scatterLocked, makeFrameRatio } from '@audio/shift-core'
|
|
3
|
+
|
|
4
|
+
// Peak-locked phase vocoder (Laroche-Dolson style, adapted to direct bin-shift pitch shifting).
|
|
5
|
+
// Phase coherence across a region of influence is preserved by locking non-peak bins' phase
|
|
6
|
+
// relative to the nearest magnitude peak, rather than advancing every bin independently.
|
|
7
|
+
// Batch and stream share this exact per-frame kernel (see shift-core's scatterLocked energy
|
|
8
|
+
// policy) so no post-hoc gain correction is needed.
|
|
9
|
+
|
|
10
|
+
function process(mag, phase, state, ctx) {
|
|
11
|
+
if (!state.fr) state.fr = makeFrameRatio(ctx.ratioFn || ctx.ratio || 1)
|
|
12
|
+
let { half } = ctx
|
|
13
|
+
let ratio = state.fr.at(ctx.frameStart, ctx.sampleRate)
|
|
14
|
+
if (!state.prev) {
|
|
15
|
+
state.prev = new Float64Array(half + 1)
|
|
16
|
+
state.syn = new Float64Array(half + 1)
|
|
17
|
+
state.newMag = new Float64Array(half + 1)
|
|
18
|
+
state.newPhase = new Float64Array(half + 1)
|
|
19
|
+
state.peakMag = new Float64Array(half + 1)
|
|
20
|
+
state.peakDest = new Int32Array(half)
|
|
21
|
+
state.peakSynPhase = new Float64Array(half)
|
|
22
|
+
state.first = true
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
let { prev, syn, newMag, newPhase, peakMag, peakDest, peakSynPhase } = state
|
|
26
|
+
newMag.fill(0)
|
|
27
|
+
newPhase.fill(0)
|
|
28
|
+
peakMag.fill(0)
|
|
29
|
+
|
|
30
|
+
let peaks = findPeaks(mag, half)
|
|
31
|
+
scatterLocked(mag, phase, prev, state.first, peaks, ratio, ctx, syn, newMag, newPhase, peakDest, peakSynPhase, peakMag)
|
|
32
|
+
|
|
33
|
+
for (let k = 0; k <= half; k++) prev[k] = phase[k]
|
|
34
|
+
state.first = false
|
|
35
|
+
|
|
36
|
+
return { mag: newMag, phase: newPhase }
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export default makeStftShift(process, { post: (out) => out })
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@audio/shift-pvoc-lock",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Peak-locked phase vocoder (Laroche-Dolson) pitch shift",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"main": "index.js",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": "./index.js",
|
|
10
|
+
"./package.json": "./package.json"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"index.js"
|
|
14
|
+
],
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"@audio/shift-core": "^1.0.0"
|
|
17
|
+
},
|
|
18
|
+
"publishConfig": {
|
|
19
|
+
"access": "public"
|
|
20
|
+
},
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"author": "audiojs",
|
|
23
|
+
"homepage": "https://github.com/audiojs/shift/tree/main/packages/shift-pvoc-lock#readme",
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "git+https://github.com/audiojs/shift.git",
|
|
27
|
+
"directory": "packages/shift-pvoc-lock"
|
|
28
|
+
},
|
|
29
|
+
"keywords": [
|
|
30
|
+
"audio",
|
|
31
|
+
"pitch-shift",
|
|
32
|
+
"phase-vocoder",
|
|
33
|
+
"peak-locked",
|
|
34
|
+
"laroche-dolson",
|
|
35
|
+
"dsp"
|
|
36
|
+
],
|
|
37
|
+
"engines": {
|
|
38
|
+
"node": ">=18"
|
|
39
|
+
}
|
|
40
|
+
}
|