/** * Effect Chain System * Manages chains of audio effects with bypass, reordering, and preset support */ import type { PitchShifterParameters, TimeStretchParameters, DistortionParameters, BitcrusherParameters, } from './advanced'; import type { CompressorParameters, LimiterParameters, GateParameters, } from './dynamics'; import type { DelayParameters, ReverbParameters, ChorusParameters, FlangerParameters, PhaserParameters, } from './time-based'; import type { FilterOptions } from './filters'; // Effect type identifier export type EffectType = // Basic | 'normalize' | 'fadeIn' | 'fadeOut' | 'reverse' // Filters | 'lowpass' | 'highpass' | 'bandpass' | 'notch' | 'lowshelf' | 'highshelf' | 'peaking' // Dynamics | 'compressor' | 'limiter' | 'gate' // Time-based | 'delay' | 'reverb' | 'chorus' | 'flanger' | 'phaser' // Advanced | 'pitch' | 'timestretch' | 'distortion' | 'bitcrusher'; // Union of all effect parameter types export type EffectParameters = | FilterOptions | CompressorParameters | LimiterParameters | GateParameters | DelayParameters | ReverbParameters | ChorusParameters | FlangerParameters | PhaserParameters | PitchShifterParameters | TimeStretchParameters | DistortionParameters | BitcrusherParameters | Record; // For effects without parameters // Effect instance in a chain export interface ChainEffect { id: string; type: EffectType; name: string; enabled: boolean; parameters?: EffectParameters; } // Effect chain export interface EffectChain { id: string; name: string; effects: ChainEffect[]; } // Effect preset export interface EffectPreset { id: string; name: string; description?: string; chain: EffectChain; createdAt: number; } /** * Generate a unique ID for effects/chains */ export function generateId(): string { return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; } /** * Create a new effect instance */ export function createEffect( type: EffectType, name: string, parameters?: EffectParameters ): ChainEffect { return { id: generateId(), type, name, enabled: true, parameters, }; } /** * Create a new effect chain */ export function createEffectChain(name: string = 'New Chain'): EffectChain { return { id: generateId(), name, effects: [], }; } /** * Add effect to chain */ export function addEffectToChain( chain: EffectChain, effect: ChainEffect ): EffectChain { return { ...chain, effects: [...chain.effects, effect], }; } /** * Remove effect from chain */ export function removeEffectFromChain( chain: EffectChain, effectId: string ): EffectChain { return { ...chain, effects: chain.effects.filter((e) => e.id !== effectId), }; } /** * Toggle effect enabled state */ export function toggleEffect( chain: EffectChain, effectId: string ): EffectChain { return { ...chain, effects: chain.effects.map((e) => e.id === effectId ? { ...e, enabled: !e.enabled } : e ), }; } /** * Update effect parameters */ export function updateEffectParameters( chain: EffectChain, effectId: string, parameters: EffectParameters ): EffectChain { return { ...chain, effects: chain.effects.map((e) => e.id === effectId ? { ...e, parameters } : e ), }; } /** * Reorder effects in chain */ export function reorderEffects( chain: EffectChain, fromIndex: number, toIndex: number ): EffectChain { const effects = [...chain.effects]; const [removed] = effects.splice(fromIndex, 1); effects.splice(toIndex, 0, removed); return { ...chain, effects, }; } /** * Create a preset from a chain */ export function createPreset( chain: EffectChain, name: string, description?: string ): EffectPreset { return { id: generateId(), name, description, chain: JSON.parse(JSON.stringify(chain)), // Deep clone createdAt: Date.now(), }; } /** * Load preset (returns a new chain) */ export function loadPreset(preset: EffectPreset): EffectChain { return JSON.parse(JSON.stringify(preset.chain)); // Deep clone } /** * Get effect display name */ export const EFFECT_NAMES: Record = { normalize: 'Normalize', fadeIn: 'Fade In', fadeOut: 'Fade Out', reverse: 'Reverse', lowpass: 'Low-Pass Filter', highpass: 'High-Pass Filter', bandpass: 'Band-Pass Filter', notch: 'Notch Filter', lowshelf: 'Low Shelf', highshelf: 'High Shelf', peaking: 'Peaking EQ', compressor: 'Compressor', limiter: 'Limiter', gate: 'Gate/Expander', delay: 'Delay/Echo', reverb: 'Reverb', chorus: 'Chorus', flanger: 'Flanger', phaser: 'Phaser', pitch: 'Pitch Shifter', timestretch: 'Time Stretch', distortion: 'Distortion', bitcrusher: 'Bitcrusher', };