UNPKG

u-he-preset-randomizer

Version:

Create random u-he synth presets through randomization and merging of your existing presets.

148 lines (134 loc) 4.34 kB
import { PresetLibrary } from "./presetLibrary.js"; import { SynthNames } from "./utils/detector.js"; export interface ParamsModel { [key: string]: { type: "string" | "float" | "integer"; values: Array<string | number>; distinctValues: Array<string | number>; maxValue?: number; minValue?: number; avgValue?: number; keepStable?: 'always' | 'stable-mode'; } } export interface ParamsModelBySection { [section: string]: { [id: string]: { type: "string" | "float" | "integer"; values: Array<string | number>; distinctValues: Array<string | number>; maxValue?: number; minValue?: number; avgValue?: number; } } } export function analyzeParamsTypeAndRange(presetLibrary: PresetLibrary) { const paramsModel: ParamsModel = {}; for (const preset of presetLibrary.presets) { for (const param of preset.params) { const key = param.id; if (!paramsModel[key]) { if (key.includes('[object Object]')) { // Ignore broken presets, the generator did accidentally create in the past continue; } paramsModel[key] = { type: param.type, values: [param.value], distinctValues: [], }; for (const paramHandling of specialParameterHandling) { if (key.includes(paramHandling.id)) { paramsModel[key].keepStable = paramHandling.keepStable; } } } else { paramsModel[key]!.values.push(param.value); if (paramsModel[key]!.type !== param.type) { if (paramsModel[key]!.type === 'integer') { paramsModel[key]!.type = param.type } else if (paramsModel[key]!.type === 'float' && param.type === 'string') { paramsModel[key]!.type = param.type } } } } } // Post Analytics for (const paramName in paramsModel) { const param = paramsModel[paramName]!; param.distinctValues = [...new Set(param.values)]; if (param.distinctValues.length === 1) { // Save some memory by compacting `values` to a single value if they are the same anyway param.values = param.distinctValues; } if (param.type !== "string") { const values = param.values as number[] param.maxValue = Math.max(...values); param.minValue = Math.min(...values); param.avgValue = average(values); } } return paramsModel; } /** * Returns a list of names, gathered from the preset library */ export function getDictionaryOfNames(presetLibrary: PresetLibrary): string[] { const names: string[] = []; const excludedWords = new Set(["bass", "guitar", "piano", "lead", "unison", "sub", "strings", "keys", "flute", "organ", "brass", "bells", "pluck", "plucked", "epiano", "chorus", "stab", "chord", "chords", "drum", "synth", "kick", "snare", "clap", "hihat", "edit"]); for (const preset of presetLibrary.presets) { const cleanedUpName = preset.presetName.split('_').join(' ') const splitName = cleanedUpName.split(' '); for (const split of splitName) { if ( split.length > 3 && split.toUpperCase() !== split && !split.includes('-') && !split.includes('(') && !split.includes(')') && !excludedWords.has(split.toLowerCase()) ) { names.push(split); } } } return names; } export function convertParamsModelBySection(paramsModel: ParamsModel): ParamsModelBySection { const paramsModelBySection: ParamsModelBySection = {} for (const id in paramsModel) { const split = id.split('/') const section = split[0] if (!paramsModelBySection[section]) { paramsModelBySection[section] = {} } paramsModelBySection[section][id] = paramsModel[id] } return paramsModelBySection; } function average(arr: number[]) { return arr.reduce((p, c) => p + c, 0) / arr.length; } interface SpecialParameterHandling { id: string; keepStable: "always" | "stable-mode"; restrictToSynth?: SynthNames; } const specialParameterHandling: SpecialParameterHandling[] = [{ id: "VCC/Trsp", keepStable: "always", },{ id: "VCC/FTun", keepStable: "always", },{ id: "Tune", keepStable: "stable-mode", },{ id: "main/CcOp", keepStable: "stable-mode", },{ id: "ZMas/Mast", keepStable: "stable-mode", }]