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; } } }