{"version":3,"sources":["../src/constants.ts","../src/processor.ts","../src/utils.ts"],"sourcesContent":["import type { AudioConfig } from './types';\n\n/**\n * Default configuration for audio processing\n */\nexport const DEFAULT_AUDIO_CONFIG: AudioConfig = {\n bufferSize: 1024,\n skipInitialFrames: 0,\n inputBitsPerSample: 32, // Default 32-bit\n inputChannels: 1, // Default mono\n};\n\n/**\n * Common buffer sizes for audio processing\n */\nexport const COMMON_BUFFER_SIZES = [256, 512, 1024, 2048, 4096, 8192] as const;\n\n/**\n * Audio processing constants\n */\nexport const AUDIO_CONSTANTS = {\n /** Maximum buffer size allowed */\n MAX_BUFFER_SIZE: 16384,\n /** Minimum buffer size allowed */\n MIN_BUFFER_SIZE: 64,\n /** Maximum skip frames allowed */\n MAX_SKIP_FRAMES: 100,\n /** Sample rate normalization factor for 32-bit integers */\n INT32_NORMALIZATION_FACTOR: 1 / 2147483647,\n /** Conversion factor for [-1, 1] to [0, 255] range */\n UINT8_CONVERSION_FACTOR: 127.5,\n} as const;\n","import { AUDIO_CONSTANTS } from './constants';\nimport type { AudioConfig, AudioDataInput, AudioDataPacket } from './types';\n\n/**\n * Simple audio processor with minimal state for skip frames functionality\n */\nexport class AudioProcessor {\n private frameCount = 0;\n private config: AudioConfig;\n\n constructor(config: AudioConfig) {\n this.config = config;\n }\n\n /**\n * Process raw audio data and convert to visualization format\n * Handles skip frames logic internally\n */\n process(rawData: AudioDataInput): AudioDataPacket | null {\n this.frameCount++;\n\n // Skip initial frames if configured\n if (this.config.skipInitialFrames && this.frameCount <= this.config.skipInitialFrames) {\n return null; // Skip this frame\n }\n\n try {\n let timeDomainData: Uint8Array;\n\n if (rawData instanceof Buffer) {\n // Use new one-step conversion function\n timeDomainData = convertBufferToWaveData(\n rawData,\n this.config.inputBitsPerSample || 32,\n this.config.inputChannels || 1,\n this.config.bufferSize\n );\n } else {\n // Float32Array input (Web Audio, etc.)\n const samples = rawData as Float32Array;\n timeDomainData = new Uint8Array(samples.length);\n for (let i = 0; i < samples.length; i++) {\n const normalized = Math.max(-1, Math.min(1, samples[i]));\n timeDomainData[i] = Math.floor(128 + normalized * 127);\n }\n }\n\n return {\n timeDomainData,\n timestamp: Date.now(),\n bufferSize: this.config.bufferSize,\n };\n } catch (error) {\n console.error('Error processing audio data:', error);\n return null;\n }\n }\n\n /**\n * Reset frame counter (call when starting new audio stream)\n */\n reset(): void {\n this.frameCount = 0;\n }\n\n /**\n * Update configuration\n */\n updateConfig(config: AudioConfig): void {\n this.config = config;\n }\n}\n\n/**\n * Stateless audio processing function (for cases without skip frames)\n *\n * @param rawData - Raw audio data (Buffer or Float32Array)\n * @param config - Audio processing configuration\n * @returns Processed audio packet or null if processing fails\n */\nexport function process(rawData: AudioDataInput, config: AudioConfig): AudioDataPacket | null {\n try {\n let timeDomainData: Uint8Array;\n\n if (rawData instanceof Buffer) {\n // Use new one-step conversion function\n timeDomainData = convertBufferToWaveData(\n rawData,\n config.inputBitsPerSample || 32,\n config.inputChannels || 1,\n config.bufferSize\n );\n } else {\n // Float32Array input (Web Audio, etc.)\n const samples = rawData as Float32Array;\n timeDomainData = new Uint8Array(samples.length);\n for (let i = 0; i < samples.length; i++) {\n const normalized = Math.max(-1, Math.min(1, samples[i]));\n timeDomainData[i] = Math.floor(128 + normalized * 127);\n }\n }\n\n return {\n timeDomainData,\n timestamp: Date.now(),\n bufferSize: config.bufferSize,\n };\n } catch (error) {\n console.error('Error processing audio data:', error);\n return null;\n }\n}\n\n/**\n * Convert Buffer directly to wave data (Uint8Array) for AudioWave visualization\n * One-step conversion: format parsing + channel mixing + resampling + amplitude mapping\n */\nexport function convertBufferToWaveData(\n buffer: Buffer,\n bitsPerSample: number,\n channels: number,\n targetSize: number\n): Uint8Array {\n const bytesPerSample = bitsPerSample / 8;\n const sourceSamples = buffer.length / (bytesPerSample * channels);\n const result = new Uint8Array(targetSize);\n const maxValue = 2 ** (bitsPerSample - 1) - 1;\n const samplesPerBin = sourceSamples / targetSize;\n\n for (let i = 0; i < targetSize; i++) {\n const startIndex = Math.floor(i * samplesPerBin);\n const endIndex = Math.min(Math.floor((i + 1) * samplesPerBin), sourceSamples);\n\n let maxAmplitude = 0;\n let representativeSample = 0;\n\n // Find maximum amplitude (suitable for waveform display)\n for (let j = startIndex; j < endIndex; j++) {\n let mixedSample = 0;\n\n // Mix channels\n for (let ch = 0; ch < channels; ch++) {\n const byteIndex = (j * channels + ch) * bytesPerSample;\n let sample = 0;\n\n switch (bitsPerSample) {\n case 8:\n sample = buffer.readInt8(byteIndex);\n break;\n case 16:\n sample = buffer.readInt16LE(byteIndex);\n break;\n case 32:\n sample = buffer.readInt32LE(byteIndex);\n break;\n default:\n throw new Error(`Unsupported bits per sample: ${bitsPerSample}`);\n }\n\n mixedSample += sample;\n }\n\n mixedSample = mixedSample / channels;\n const amplitude = Math.abs(mixedSample);\n\n if (amplitude > maxAmplitude) {\n maxAmplitude = amplitude;\n representativeSample = mixedSample;\n }\n }\n\n // Convert to AudioWave format: 128 as center, symmetric mapping\n const normalized = representativeSample / maxValue; // [-1, 1]\n result[i] = Math.floor(128 + normalized * 127);\n }\n\n return result;\n}\n\n/**\n * Validate audio configuration\n */\nexport function validateAudioConfig(config: AudioConfig): boolean {\n if (!config || typeof config !== 'object') {\n return false;\n }\n\n if (\n typeof config.bufferSize !== 'number' ||\n config.bufferSize < AUDIO_CONSTANTS.MIN_BUFFER_SIZE ||\n config.bufferSize > AUDIO_CONSTANTS.MAX_BUFFER_SIZE\n ) {\n return false;\n }\n\n if (\n config.skipInitialFrames !== undefined &&\n (typeof config.skipInitialFrames !== 'number' ||\n config.skipInitialFrames < 0 ||\n config.skipInitialFrames > AUDIO_CONSTANTS.MAX_SKIP_FRAMES)\n ) {\n return false;\n }\n\n return true;\n}\n","import { DEFAULT_AUDIO_CONFIG } from './constants';\nimport type { AudioConfig } from './types';\n\n/**\n * Create audio configuration with defaults\n */\nexport function createAudioConfig(config: Partial = {}): AudioConfig {\n return {\n ...DEFAULT_AUDIO_CONFIG,\n ...config,\n };\n}\n\n/**\n * Check if buffer size is a power of 2 (recommended for FFT)\n */\nexport function isPowerOfTwo(n: number): boolean {\n return n > 0 && (n & (n - 1)) === 0;\n}\n\n/**\n * Get the nearest power of 2 buffer size\n */\nexport function getNearestPowerOfTwo(size: number): number {\n return 2 ** Math.round(Math.log2(size));\n}\n\n/**\n * Validate buffer data format for 32-bit samples\n */\nexport function isValidAudioBuffer(buffer: Buffer): boolean {\n return buffer.length % 4 === 0;\n}\n"],"mappings":"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","names":[]}