Adding new FM synthesis mode

This commit is contained in:
2025-10-06 13:08:59 +02:00
parent 0110a9760b
commit 324cf9d2ed
13 changed files with 1233 additions and 69 deletions

89
src/utils/fmPatches.ts Normal file
View File

@@ -0,0 +1,89 @@
import type { TileState } from '../types/tiles'
import { getDefaultEngineValues, getDefaultEffectValues } from '../config/effects'
import { getDefaultLFOValues } from '../stores/settings'
export interface FMPatchConfig {
algorithm: number
feedback: number
lfoRates: [number, number, number, 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
]
return { algorithm, feedback, lfoRates }
}
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
}