Skip to content

Commit 3a803da

Browse files
committed
chore: Align interpolation strategy params, tests, and Storybook docs
1 parent 7c6ff25 commit 3a803da

10 files changed

Lines changed: 193 additions & 101 deletions

File tree

packages/audio-worklet/src/SoundTouchNode.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ describe('SoundTouchNode', () => {
8484
const node = new SoundTouchNode({ context });
8585

8686
node.setInterpolationStrategy('lanczos');
87-
node.setInterpolationStrategyParams({ radius: 6 });
87+
node.setInterpolationStrategyParams({ zeroCrossings: 6 });
8888

8989
const port = (
9090
node as unknown as { port: { postMessage: ReturnType<typeof vi.fn> } }

packages/core/src/RateTransposer.spec.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -492,11 +492,11 @@ describe('RateTransposer', () => {
492492
},
493493
});
494494

495-
expect(rt.strategyParams['radius']).toBe(4);
495+
expect(rt.strategyParams['zeroCrossings']).toBe(4);
496496

497-
rt.setInterpolationStrategyParams({ radius: 7 });
497+
rt.setInterpolationStrategyParams({ zeroCrossings: 7 });
498498

499-
expect(rt.strategyParams['radius']).toBe(7);
499+
expect(rt.strategyParams['zeroCrossings']).toBe(7);
500500
});
501501

502502
it('preserves strategy params when cloned', () => {
@@ -511,7 +511,7 @@ describe('RateTransposer', () => {
511511
const cloned = rt.clone();
512512

513513
expect(cloned.strategy).toBe('lanczos');
514-
expect(cloned.strategyParams['radius']).toBe(5);
514+
expect(cloned.strategyParams['zeroCrossings']).toBe(5);
515515
});
516516
});
517517

packages/core/src/interpolationStrategyRegistry.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export interface InterpolationKernel {
2323
createState?: () => unknown;
2424
}
2525

26-
export type InterpolationStrategyParams = Record<string, number>;
26+
export type InterpolationStrategyParams = Record<string, number | boolean>;
2727

2828
export type RateTransposerInterpolationStrategyId = string;
2929

packages/interpolation-strategy-blackman/src/index.ts

Lines changed: 51 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@ export interface InterpolationStrategyRegistration {
1616
readonly id: string;
1717
readonly baseStrategy?: BuiltInInterpolationStrategy;
1818
readonly kernel?: InterpolationKernel;
19-
readonly defaultParams?: Record<string, number>;
19+
readonly defaultParams?: Record<string, number | boolean>;
2020
readonly normalizeParams?: (
21-
params: Partial<Record<string, number>> | undefined,
22-
defaults: Record<string, number>,
23-
) => Record<string, number>;
21+
params: Partial<Record<string, number | boolean>> | undefined,
22+
defaults: Record<string, number | boolean>,
23+
) => Record<string, number | boolean>;
2424
readonly applyParams?: (
2525
state: unknown,
26-
params: Record<string, number>,
26+
params: Record<string, number | boolean>,
2727
) => void;
2828
}
2929

@@ -39,7 +39,6 @@ interface BlackmanKernelState {
3939
params: BlackmanStrategyParams;
4040
}
4141

42-
4342
/**
4443
* Parameters for the Blackman interpolation strategy.
4544
*
@@ -49,12 +48,15 @@ interface BlackmanKernelState {
4948
* @property beta Blackman window beta coefficient (default: 0.5)
5049
* @property gamma Blackman window gamma coefficient (default: 0.08)
5150
*/
52-
export interface BlackmanStrategyParams extends Record<string, number | boolean> {
51+
export interface BlackmanStrategyParams extends Record<
52+
string,
53+
number | boolean
54+
> {
5355
zeroCrossings: number;
54-
normalize?: boolean;
55-
alpha?: number;
56-
beta?: number;
57-
gamma?: number;
56+
normalize: boolean;
57+
alpha: number;
58+
beta: number;
59+
gamma: number;
5860
}
5961

6062
const BLACKMAN_DEFAULT_PARAMS: BlackmanStrategyParams = {
@@ -75,7 +77,12 @@ function normalizeBlackmanParams(
7577
};
7678
const zeroCrossings = Math.max(
7779
2,
78-
Math.min(8, Math.round(Number(merged['zeroCrossings'] ?? defaults['zeroCrossings'] ?? 4))),
80+
Math.min(
81+
8,
82+
Math.round(
83+
Number(merged['zeroCrossings'] ?? defaults['zeroCrossings'] ?? 4),
84+
),
85+
),
7986
);
8087
const normalize = Boolean(merged['normalize']);
8188
const alpha = Number(merged['alpha'] ?? 0.42);
@@ -93,7 +100,10 @@ function applyBlackmanParams(
93100
}
94101
const record = state as BlackmanKernelState;
95102
record.params = {
96-
zeroCrossings: Math.max(2, Math.round(Number(params['zeroCrossings'] ?? 4))),
103+
zeroCrossings: Math.max(
104+
2,
105+
Math.round(Number(params['zeroCrossings'] ?? 4)),
106+
),
97107
normalize: Boolean(params['normalize']),
98108
alpha: Number(params['alpha'] ?? 0.42),
99109
beta: Number(params['beta'] ?? 0.5),
@@ -129,7 +139,13 @@ function normalizedSinc(x: number): number {
129139
return Math.sin(value) / value;
130140
}
131141

132-
function blackmanWindow(distance: number, radius: number, alpha: number, beta: number, gamma: number): number {
142+
function blackmanWindow(
143+
distance: number,
144+
radius: number,
145+
alpha: number,
146+
beta: number,
147+
gamma: number,
148+
): number {
133149
const absDistance = Math.abs(distance);
134150
if (absDistance >= radius) {
135151
return 0;
@@ -142,11 +158,19 @@ function blackmanWindow(distance: number, radius: number, alpha: number, beta: n
142158
);
143159
}
144160

145-
function blackmanWeight(distance: number, radius: number, alpha: number, beta: number, gamma: number): number {
146-
return normalizedSinc(distance) * blackmanWindow(distance, radius, alpha, beta, gamma);
161+
function blackmanWeight(
162+
distance: number,
163+
radius: number,
164+
alpha: number,
165+
beta: number,
166+
gamma: number,
167+
): number {
168+
return (
169+
normalizedSinc(distance) *
170+
blackmanWindow(distance, radius, alpha, beta, gamma)
171+
);
147172
}
148173

149-
150174
export const blackmanKernel: InterpolationKernel = (
151175
src,
152176
srcOffset,
@@ -158,9 +182,16 @@ export const blackmanKernel: InterpolationKernel = (
158182
const kernelState = state as BlackmanKernelState;
159183
const radius = kernelState.params.zeroCrossings;
160184
const normalize = Boolean(kernelState.params.normalize);
161-
const alpha = typeof kernelState.params.alpha === 'number' ? kernelState.params.alpha : 0.42;
162-
const beta = typeof kernelState.params.beta === 'number' ? kernelState.params.beta : 0.5;
163-
const gamma = typeof kernelState.params.gamma === 'number' ? kernelState.params.gamma : 0.08;
185+
const alpha =
186+
typeof kernelState.params.alpha === 'number'
187+
? kernelState.params.alpha
188+
: 0.42;
189+
const beta =
190+
typeof kernelState.params.beta === 'number' ? kernelState.params.beta : 0.5;
191+
const gamma =
192+
typeof kernelState.params.gamma === 'number'
193+
? kernelState.params.gamma
194+
: 0.08;
164195
const center = Math.floor(position);
165196
const start = center - (radius - 1);
166197
const end = center + radius;

packages/interpolation-strategy-hann/src/index.ts

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@ export interface InterpolationStrategyRegistration {
1616
readonly id: string;
1717
readonly baseStrategy?: BuiltInInterpolationStrategy;
1818
readonly kernel?: InterpolationKernel;
19-
readonly defaultParams?: Record<string, number>;
19+
readonly defaultParams?: Record<string, number | boolean>;
2020
readonly normalizeParams?: (
21-
params: Partial<Record<string, number>> | undefined,
22-
defaults: Record<string, number>,
23-
) => Record<string, number>;
21+
params: Partial<Record<string, number | boolean>> | undefined,
22+
defaults: Record<string, number | boolean>,
23+
) => Record<string, number | boolean>;
2424
readonly applyParams?: (
2525
state: unknown,
26-
params: Record<string, number>,
26+
params: Record<string, number | boolean>,
2727
) => void;
2828
}
2929

@@ -39,7 +39,6 @@ interface HannKernelState {
3939
params: HannStrategyParams;
4040
}
4141

42-
4342
/**
4443
* Parameters for the Hann interpolation strategy.
4544
*
@@ -49,8 +48,8 @@ interface HannKernelState {
4948
*/
5049
export interface HannStrategyParams extends Record<string, number | boolean> {
5150
zeroCrossings: number;
52-
normalize?: boolean;
53-
windowPower?: number;
51+
normalize: boolean;
52+
windowPower: number;
5453
}
5554

5655
const HANN_DEFAULT_PARAMS: HannStrategyParams = {
@@ -69,20 +68,31 @@ function normalizeHannParams(
6968
};
7069
const zeroCrossings = Math.max(
7170
2,
72-
Math.min(8, Math.round(Number(merged['zeroCrossings'] ?? defaults['zeroCrossings'] ?? 4))),
71+
Math.min(
72+
8,
73+
Math.round(
74+
Number(merged['zeroCrossings'] ?? defaults['zeroCrossings'] ?? 4),
75+
),
76+
),
7377
);
7478
const normalize = Boolean(merged['normalize']);
7579
const windowPower = Math.max(0.1, Number(merged['windowPower'] ?? 1));
7680
return { zeroCrossings, normalize, windowPower };
7781
}
7882

79-
function applyHannParams(state: unknown, params: Record<string, number | boolean>): void {
83+
function applyHannParams(
84+
state: unknown,
85+
params: Record<string, number | boolean>,
86+
): void {
8087
if (typeof state !== 'object' || state === null) {
8188
return;
8289
}
8390
const record = state as HannKernelState;
8491
record.params = {
85-
zeroCrossings: Math.max(2, Math.round(Number(params['zeroCrossings'] ?? 4))),
92+
zeroCrossings: Math.max(
93+
2,
94+
Math.round(Number(params['zeroCrossings'] ?? 4)),
95+
),
8696
normalize: Boolean(params['normalize']),
8797
windowPower: Math.max(0.1, Number(params['windowPower'] ?? 1)),
8898
};
@@ -116,7 +126,11 @@ function normalizedSinc(x: number): number {
116126
return Math.sin(value) / value;
117127
}
118128

119-
function hannWindow(distance: number, radius: number, windowPower: number): number {
129+
function hannWindow(
130+
distance: number,
131+
radius: number,
132+
windowPower: number,
133+
): number {
120134
const absDistance = Math.abs(distance);
121135
if (absDistance >= radius) {
122136
return 0;
@@ -125,11 +139,14 @@ function hannWindow(distance: number, radius: number, windowPower: number): numb
125139
return Math.pow(base, windowPower);
126140
}
127141

128-
function hannWeight(distance: number, radius: number, windowPower: number): number {
142+
function hannWeight(
143+
distance: number,
144+
radius: number,
145+
windowPower: number,
146+
): number {
129147
return normalizedSinc(distance) * hannWindow(distance, radius, windowPower);
130148
}
131149

132-
133150
export const hannKernel: InterpolationKernel = (
134151
src,
135152
srcOffset,
@@ -141,7 +158,10 @@ export const hannKernel: InterpolationKernel = (
141158
const kernelState = state as HannKernelState;
142159
const radius = kernelState.params.zeroCrossings;
143160
const normalize = Boolean(kernelState.params.normalize);
144-
const windowPower = typeof kernelState.params.windowPower === 'number' ? kernelState.params.windowPower : 1;
161+
const windowPower =
162+
typeof kernelState.params.windowPower === 'number'
163+
? kernelState.params.windowPower
164+
: 1;
145165
const center = Math.floor(position);
146166
const start = center - (radius - 1);
147167
const end = center + radius;

packages/interpolation-strategy-kaiser/src/index.ts

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@ export interface InterpolationStrategyRegistration {
1616
readonly id: string;
1717
readonly baseStrategy?: BuiltInInterpolationStrategy;
1818
readonly kernel?: InterpolationKernel;
19-
readonly defaultParams?: Record<string, number>;
19+
readonly defaultParams?: Record<string, number | boolean>;
2020
readonly normalizeParams?: (
21-
params: Partial<Record<string, number>> | undefined,
22-
defaults: Record<string, number>,
23-
) => Record<string, number>;
21+
params: Partial<Record<string, number | boolean>> | undefined,
22+
defaults: Record<string, number | boolean>,
23+
) => Record<string, number | boolean>;
2424
readonly applyParams?: (
2525
state: unknown,
26-
params: Record<string, number>,
26+
params: Record<string, number | boolean>,
2727
) => void;
2828
}
2929

@@ -39,7 +39,6 @@ interface KaiserKernelState {
3939
params: KaiserStrategyParams;
4040
}
4141

42-
4342
/**
4443
* Parameters for the Kaiser interpolation strategy.
4544
*
@@ -51,8 +50,8 @@ interface KaiserKernelState {
5150
export interface KaiserStrategyParams extends Record<string, number | boolean> {
5251
zeroCrossings: number;
5352
beta: number;
54-
normalize?: boolean;
55-
windowPower?: number;
53+
normalize: boolean;
54+
windowPower: number;
5655
}
5756

5857
const KAISER_DEFAULT_PARAMS: KaiserStrategyParams = {
@@ -72,7 +71,12 @@ function normalizeKaiserParams(
7271
};
7372
const zeroCrossings = Math.max(
7473
2,
75-
Math.min(16, Math.round(Number(merged['zeroCrossings'] ?? defaults['zeroCrossings'] ?? 4))),
74+
Math.min(
75+
16,
76+
Math.round(
77+
Number(merged['zeroCrossings'] ?? defaults['zeroCrossings'] ?? 4),
78+
),
79+
),
7680
);
7781
const beta = Math.max(0, Math.min(20, Number(merged['beta'] ?? 8.6)));
7882
const normalize = Boolean(merged['normalize']);
@@ -89,7 +93,10 @@ function applyKaiserParams(
8993
}
9094
const record = state as KaiserKernelState;
9195
record.params = {
92-
zeroCrossings: Math.max(2, Math.round(Number(params['zeroCrossings'] ?? 4))),
96+
zeroCrossings: Math.max(
97+
2,
98+
Math.round(Number(params['zeroCrossings'] ?? 4)),
99+
),
93100
beta: Math.max(0, Math.min(20, Number(params['beta'] ?? 8.6))),
94101
normalize: Boolean(params['normalize']),
95102
windowPower: Math.max(0.1, Number(params['windowPower'] ?? 1)),
@@ -163,7 +170,6 @@ function kaiserWindow(
163170
return Math.pow(base, windowPower);
164171
}
165172

166-
167173
export const kaiserKernel: InterpolationKernel = (
168174
src,
169175
srcOffset,

0 commit comments

Comments
 (0)