53 lines
1.5 KiB
TypeScript
53 lines
1.5 KiB
TypeScript
import type { AudioProcessor, ProcessorCategory } from "./AudioProcessor";
|
|
|
|
export class OctaveUp implements AudioProcessor {
|
|
getName(): string {
|
|
return "Octave Up";
|
|
}
|
|
|
|
getDescription(): string {
|
|
return "Shifts pitch up one octave by doubling playback rate";
|
|
}
|
|
|
|
getCategory(): ProcessorCategory {
|
|
return 'Pitch';
|
|
}
|
|
|
|
async process(
|
|
leftChannel: Float32Array,
|
|
rightChannel: Float32Array
|
|
): Promise<[Float32Array, Float32Array]> {
|
|
const inputLength = leftChannel.length;
|
|
const outputLength = Math.floor(inputLength / 2);
|
|
|
|
const newLeft = new Float32Array(outputLength);
|
|
const newRight = new Float32Array(outputLength);
|
|
|
|
for (let i = 0; i < outputLength; i++) {
|
|
const sourceIndex = i * 2;
|
|
const lowerIndex = Math.floor(sourceIndex);
|
|
const upperIndex = Math.min(lowerIndex + 1, inputLength - 1);
|
|
const fraction = sourceIndex - lowerIndex;
|
|
|
|
newLeft[i] = leftChannel[lowerIndex] * (1 - fraction) + leftChannel[upperIndex] * fraction;
|
|
newRight[i] = rightChannel[lowerIndex] * (1 - fraction) + rightChannel[upperIndex] * fraction;
|
|
}
|
|
|
|
this.applyFadeOut(newLeft, newRight);
|
|
|
|
return [newLeft, newRight];
|
|
}
|
|
|
|
private applyFadeOut(left: Float32Array, right: Float32Array): void {
|
|
const fadeLength = Math.min(Math.floor(left.length * 0.05), 2205);
|
|
const fadeStart = left.length - fadeLength;
|
|
|
|
for (let i = 0; i < fadeLength; i++) {
|
|
const gain = 1 - (i / fadeLength);
|
|
const index = fadeStart + i;
|
|
left[index] *= gain;
|
|
right[index] *= gain;
|
|
}
|
|
}
|
|
}
|