import type { TileState } from '../types/tiles' import { getDefaultEngineValues, getDefaultEffectValues } from '../config/parameters' import { getDefaultLFOValues } from '../stores/settings' export interface FMPatchConfig { algorithm: number feedback: number lfoRates: [number, number, number, number] pitchLFO: { waveform: number depth: number baseRate: number } } export function generateRandomFMPatch(complexity: number = 1): FMPatchConfig { let algorithmRange: number[] switch (complexity) { case 0: algorithmRange = [0, 2, 6, 8, 9, 10] break case 2: algorithmRange = [1, 4, 5, 7, 11, 12, 13, 14, 15] break default: algorithmRange = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] } const algorithm = algorithmRange[Math.floor(Math.random() * algorithmRange.length)] const feedback = Math.floor(Math.random() * 100) const lfoRates: [number, number, number, number] = [ 0.2 + Math.random() * 0.8, 0.3 + Math.random() * 1.0, 0.4 + Math.random() * 1.2, 0.25 + Math.random() * 0.9 ] const pitchLFO = { waveform: Math.floor(Math.random() * 8), depth: Math.random() < 0.4 ? 0.03 + Math.random() * 0.22 : 0, baseRate: 0.1 + Math.random() * 9.9 } return { algorithm, feedback, lfoRates, pitchLFO } } export function createFMTileState(patch: FMPatchConfig): TileState { const formula = JSON.stringify(patch) const pitchValues = [0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 2.0] const randomPitch = pitchValues[Math.floor(Math.random() * pitchValues.length)] return { formula, engineParams: { ...getDefaultEngineValues(), a: Math.floor(Math.random() * 128) + 64, b: Math.floor(Math.random() * 128) + 64, c: Math.floor(Math.random() * 128) + 64, d: Math.floor(Math.random() * 128) + 64, pitch: randomPitch, fmAlgorithm: patch.algorithm, fmFeedback: patch.feedback }, effectParams: getDefaultEffectValues(), lfoConfigs: getDefaultLFOValues() } } export function generateFMTileGrid(size: number, columns: number, complexity: number = 1): TileState[][] { const tiles: TileState[][] = [] const rows = Math.ceil(size / columns) for (let i = 0; i < rows; i++) { const row: TileState[] = [] for (let j = 0; j < columns; j++) { if (i * columns + j < size) { const patch = generateRandomFMPatch(complexity) row.push(createFMTileState(patch)) } } tiles.push(row) } return tiles } export function parseFMPatch(formula: string): FMPatchConfig | null { try { const parsed = JSON.parse(formula) if (typeof parsed.algorithm === 'number' && typeof parsed.feedback === 'number') { return parsed } } catch { // Not a valid FM patch } return null }