Code quality checks
This commit is contained in:
12
src/App.tsx
12
src/App.tsx
@ -12,7 +12,7 @@ import { LFOPanel } from './components/LFOPanel'
|
|||||||
import { AudioContextWarning } from './components/AudioContextWarning'
|
import { AudioContextWarning } from './components/AudioContextWarning'
|
||||||
import { HelpModal } from './components/HelpModal'
|
import { HelpModal } from './components/HelpModal'
|
||||||
import { getSampleRateFromIndex } from './config/effects'
|
import { getSampleRateFromIndex } from './config/effects'
|
||||||
import { engineSettings, effectSettings, lfoSettings } from './stores/settings'
|
import { engineSettings, effectSettings, lfoSettings, type LFOConfig } from './stores/settings'
|
||||||
import { exitMappingMode } from './stores/mappingMode'
|
import { exitMappingMode } from './stores/mappingMode'
|
||||||
import { useKeyboardShortcuts } from './hooks/useKeyboardShortcuts'
|
import { useKeyboardShortcuts } from './hooks/useKeyboardShortcuts'
|
||||||
import { useTileParams } from './hooks/useTileParams'
|
import { useTileParams } from './hooks/useTileParams'
|
||||||
@ -118,7 +118,7 @@ function App() {
|
|||||||
const params = newRandomized as TileState
|
const params = newRandomized as TileState
|
||||||
loadTileParams(params)
|
loadTileParams(params)
|
||||||
|
|
||||||
playbackManagerRef.current.setEffects(params.effectParams as any)
|
playbackManagerRef.current.setEffects(params.effectParams)
|
||||||
playbackManagerRef.current.setVariables(
|
playbackManagerRef.current.setVariables(
|
||||||
params.engineParams.a ?? DEFAULT_VARIABLES.a,
|
params.engineParams.a ?? DEFAULT_VARIABLES.a,
|
||||||
params.engineParams.b ?? DEFAULT_VARIABLES.b,
|
params.engineParams.b ?? DEFAULT_VARIABLES.b,
|
||||||
@ -222,7 +222,7 @@ function App() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleEffectChange = (parameterId: string, value: number | boolean | string) => {
|
const handleEffectChange = (parameterId: string, value: number | boolean | string) => {
|
||||||
effectSettings.setKey(parameterId as any, value as any)
|
effectSettings.setKey(parameterId as keyof typeof effectValues, value as never)
|
||||||
saveCurrentTileParams()
|
saveCurrentTileParams()
|
||||||
|
|
||||||
if (playbackManagerRef.current) {
|
if (playbackManagerRef.current) {
|
||||||
@ -230,7 +230,7 @@ function App() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleLFOChange = (lfoIndex: number, config: any) => {
|
const handleLFOChange = (lfoIndex: number, config: LFOConfig) => {
|
||||||
if (playbackManagerRef.current) {
|
if (playbackManagerRef.current) {
|
||||||
playbackManagerRef.current.setLFOConfig(lfoIndex, config)
|
playbackManagerRef.current.setLFOConfig(lfoIndex, config)
|
||||||
}
|
}
|
||||||
@ -453,7 +453,7 @@ function App() {
|
|||||||
loadTileParams(randomized)
|
loadTileParams(randomized)
|
||||||
|
|
||||||
if (playing === PLAYBACK_ID.CUSTOM && playbackManagerRef.current) {
|
if (playing === PLAYBACK_ID.CUSTOM && playbackManagerRef.current) {
|
||||||
playbackManagerRef.current.setEffects(randomized.effectParams as any)
|
playbackManagerRef.current.setEffects(randomized.effectParams)
|
||||||
playbackManagerRef.current.setVariables(
|
playbackManagerRef.current.setVariables(
|
||||||
randomized.engineParams.a ?? DEFAULT_VARIABLES.a,
|
randomized.engineParams.a ?? DEFAULT_VARIABLES.a,
|
||||||
randomized.engineParams.b ?? DEFAULT_VARIABLES.b,
|
randomized.engineParams.b ?? DEFAULT_VARIABLES.b,
|
||||||
@ -483,7 +483,7 @@ function App() {
|
|||||||
loadTileParams(randomized)
|
loadTileParams(randomized)
|
||||||
|
|
||||||
if (playing === tileId && playbackManagerRef.current) {
|
if (playing === tileId && playbackManagerRef.current) {
|
||||||
playbackManagerRef.current.setEffects(randomized.effectParams as any)
|
playbackManagerRef.current.setEffects(randomized.effectParams)
|
||||||
playbackManagerRef.current.setVariables(
|
playbackManagerRef.current.setVariables(
|
||||||
randomized.engineParams.a ?? DEFAULT_VARIABLES.a,
|
randomized.engineParams.a ?? DEFAULT_VARIABLES.a,
|
||||||
randomized.engineParams.b ?? DEFAULT_VARIABLES.b,
|
randomized.engineParams.b ?? DEFAULT_VARIABLES.b,
|
||||||
|
|||||||
@ -50,9 +50,9 @@ export function EffectsBar({ values, onChange, onMapClick, getMappedLFOs }: Effe
|
|||||||
</div>
|
</div>
|
||||||
{effect.bypassable && (
|
{effect.bypassable && (
|
||||||
<Switch
|
<Switch
|
||||||
checked={!Boolean(values[`${effect.id}Bypass`])}
|
checked={!values[`${effect.id}Bypass`]}
|
||||||
onChange={(checked) => onChange(`${effect.id}Bypass`, !checked)}
|
onChange={(checked) => onChange(`${effect.id}Bypass`, !checked)}
|
||||||
label={Boolean(values[`${effect.id}Bypass`]) ? 'OFF' : 'ON'}
|
label={values[`${effect.id}Bypass`] ? 'OFF' : 'ON'}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@ -82,7 +82,7 @@ export function EffectsBar({ values, onChange, onMapClick, getMappedLFOs }: Effe
|
|||||||
<Switch
|
<Switch
|
||||||
checked={Boolean(values[param.id])}
|
checked={Boolean(values[param.id])}
|
||||||
onChange={(checked) => onChange(param.id, checked ? 1 : 0)}
|
onChange={(checked) => onChange(param.id, checked ? 1 : 0)}
|
||||||
label={Boolean(values[param.id]) ? 'ON' : 'OFF'}
|
label={values[param.id] ? 'ON' : 'OFF'}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -21,9 +21,10 @@ export function EngineControls({ values, onChange, onMapClick, getMappedLFOs }:
|
|||||||
return getComplexityLabel(value)
|
return getComplexityLabel(value)
|
||||||
case 'bitDepth':
|
case 'bitDepth':
|
||||||
return getBitDepthLabel(value)
|
return getBitDepthLabel(value)
|
||||||
default:
|
default: {
|
||||||
const param = ENGINE_CONTROLS[0].parameters.find(p => p.id === id)
|
const param = ENGINE_CONTROLS[0].parameters.find(p => p.id === id)
|
||||||
return `${value}${param?.unit || ''}`
|
return `${value}${param?.unit || ''}`
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -23,7 +23,7 @@ export function HelpModal({ onClose, showStartButton = false }: HelpModalProps)
|
|||||||
BRUITISTE
|
BRUITISTE
|
||||||
</h1>
|
</h1>
|
||||||
<p className="font-mono text-sm text-white mb-2 leading-relaxed text-center">
|
<p className="font-mono text-sm text-white mb-2 leading-relaxed text-center">
|
||||||
A harsh noise soundbox
|
Harsh noise soundbox made as a love statement to all weird noises, hums, audio glitches and ominous textures. Be careful, lower your volume! Tweak some parameters!
|
||||||
</p>
|
</p>
|
||||||
<p className="font-mono text-xs text-white mb-6 opacity-70 text-center">
|
<p className="font-mono text-xs text-white mb-6 opacity-70 text-center">
|
||||||
Made by Raphaël Forment (BuboBubo) — <a href="https://raphaelforment.fr" target="_blank" rel="noopener noreferrer" className="underline hover:opacity-100">raphaelforment.fr</a>
|
Made by Raphaël Forment (BuboBubo) — <a href="https://raphaelforment.fr" target="_blank" rel="noopener noreferrer" className="underline hover:opacity-100">raphaelforment.fr</a>
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { useRef, useState, useEffect } from 'react'
|
import { useRef, useState, useEffect, useCallback } from 'react'
|
||||||
import { useStore } from '@nanostores/react'
|
import { useStore } from '@nanostores/react'
|
||||||
import { mappingMode } from '../stores/mappingMode'
|
import { mappingMode } from '../stores/mappingMode'
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ export function Knob({
|
|||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleMouseMove = (e: MouseEvent) => {
|
const handleMouseMove = useCallback((e: MouseEvent) => {
|
||||||
if (!isDragging) return
|
if (!isDragging) return
|
||||||
|
|
||||||
const deltaY = startYRef.current - e.clientY
|
const deltaY = startYRef.current - e.clientY
|
||||||
@ -68,11 +68,11 @@ export function Knob({
|
|||||||
|
|
||||||
const steppedValue = Math.round(newValue / step) * step
|
const steppedValue = Math.round(newValue / step) * step
|
||||||
onChange(steppedValue)
|
onChange(steppedValue)
|
||||||
}
|
}, [isDragging, max, min, step, onChange])
|
||||||
|
|
||||||
const handleMouseUp = () => {
|
const handleMouseUp = useCallback(() => {
|
||||||
setIsDragging(false)
|
setIsDragging(false)
|
||||||
}
|
}, [])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isDragging) {
|
if (isDragging) {
|
||||||
@ -83,7 +83,7 @@ export function Knob({
|
|||||||
window.removeEventListener('mouseup', handleMouseUp)
|
window.removeEventListener('mouseup', handleMouseUp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [isDragging])
|
}, [isDragging, handleMouseMove, handleMouseUp])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative flex flex-col items-center">
|
<div className="relative flex flex-col items-center">
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { useEffect, useRef, useState } from 'react'
|
import { useEffect, useRef, useState, useCallback } from 'react'
|
||||||
import { useStore } from '@nanostores/react'
|
import { useStore } from '@nanostores/react'
|
||||||
import { LFO, type LFOWaveform } from '../domain/modulation/LFO'
|
import { LFO, type LFOWaveform } from '../domain/modulation/LFO'
|
||||||
import { mappingMode } from '../stores/mappingMode'
|
import { mappingMode } from '../stores/mappingMode'
|
||||||
@ -34,6 +34,27 @@ export function LFOScope({ lfoIndex, waveform, frequency, phase, mappings, onCha
|
|||||||
const dragStartRef = useRef<{ x: number; y: number; freq: number; phase: number; moved: boolean } | null>(null)
|
const dragStartRef = useRef<{ x: number; y: number; freq: number; phase: number; moved: boolean } | null>(null)
|
||||||
const mappingModeState = useStore(mappingMode)
|
const mappingModeState = useStore(mappingMode)
|
||||||
|
|
||||||
|
const getLFOValueAtPhase = useCallback((phaseVal: number): number => {
|
||||||
|
const normalizedPhase = phaseVal % 1
|
||||||
|
|
||||||
|
switch (waveform) {
|
||||||
|
case 'sine':
|
||||||
|
return Math.sin(normalizedPhase * 2 * Math.PI)
|
||||||
|
case 'triangle':
|
||||||
|
return normalizedPhase < 0.5
|
||||||
|
? -1 + 4 * normalizedPhase
|
||||||
|
: 3 - 4 * normalizedPhase
|
||||||
|
case 'square':
|
||||||
|
return normalizedPhase < 0.5 ? 1 : -1
|
||||||
|
case 'sawtooth':
|
||||||
|
return 2 * normalizedPhase - 1
|
||||||
|
case 'random':
|
||||||
|
return Math.sin(normalizedPhase * 2 * Math.PI)
|
||||||
|
default:
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}, [waveform])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!lfoRef.current) {
|
if (!lfoRef.current) {
|
||||||
lfoRef.current = new LFO(new AudioContext(), frequency, phase, waveform)
|
lfoRef.current = new LFO(new AudioContext(), frequency, phase, waveform)
|
||||||
@ -98,28 +119,7 @@ export function LFOScope({ lfoIndex, waveform, frequency, phase, mappings, onCha
|
|||||||
cancelAnimationFrame(animationRef.current)
|
cancelAnimationFrame(animationRef.current)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [frequency, waveform, phase])
|
}, [frequency, waveform, phase, getLFOValueAtPhase])
|
||||||
|
|
||||||
const getLFOValueAtPhase = (phase: number): number => {
|
|
||||||
const normalizedPhase = phase % 1
|
|
||||||
|
|
||||||
switch (waveform) {
|
|
||||||
case 'sine':
|
|
||||||
return Math.sin(normalizedPhase * 2 * Math.PI)
|
|
||||||
case 'triangle':
|
|
||||||
return normalizedPhase < 0.5
|
|
||||||
? -1 + 4 * normalizedPhase
|
|
||||||
: 3 - 4 * normalizedPhase
|
|
||||||
case 'square':
|
|
||||||
return normalizedPhase < 0.5 ? 1 : -1
|
|
||||||
case 'sawtooth':
|
|
||||||
return 2 * normalizedPhase - 1
|
|
||||||
case 'random':
|
|
||||||
return Math.sin(normalizedPhase * 2 * Math.PI)
|
|
||||||
default:
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleMouseDown = (e: React.MouseEvent<HTMLCanvasElement>) => {
|
const handleMouseDown = (e: React.MouseEvent<HTMLCanvasElement>) => {
|
||||||
if (e.button === 2) return
|
if (e.button === 2) return
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { EffectsChain } from './effects/EffectsChain'
|
import { EffectsChain } from './effects/EffectsChain'
|
||||||
import { BytebeatSourceEffect } from './effects/BytebeatSourceEffect'
|
import { BytebeatSourceEffect } from './effects/BytebeatSourceEffect'
|
||||||
import { ModulationEngine } from '../modulation/ModulationEngine'
|
import { ModulationEngine } from '../modulation/ModulationEngine'
|
||||||
|
import type { LFOWaveform } from '../modulation/LFO'
|
||||||
import type { EffectValues } from '../../types/effects'
|
import type { EffectValues } from '../../types/effects'
|
||||||
|
|
||||||
export interface AudioPlayerOptions {
|
export interface AudioPlayerOptions {
|
||||||
@ -129,10 +130,10 @@ export class AudioPlayer {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
setLFOConfig(lfoIndex: number, config: { frequency: number; phase: number; waveform: string; mappings: Array<{ targetParam: string; depth: number }> }): void {
|
setLFOConfig(lfoIndex: number, config: { frequency: number; phase: number; waveform: LFOWaveform; mappings: Array<{ targetParam: string; depth: number }> }): void {
|
||||||
if (!this.modulationEngine) return
|
if (!this.modulationEngine) return
|
||||||
|
|
||||||
this.modulationEngine.updateLFO(lfoIndex, config.frequency, config.phase, config.waveform as any)
|
this.modulationEngine.updateLFO(lfoIndex, config.frequency, config.phase, config.waveform)
|
||||||
this.modulationEngine.clearMappings(lfoIndex)
|
this.modulationEngine.clearMappings(lfoIndex)
|
||||||
|
|
||||||
for (const mapping of config.mappings) {
|
for (const mapping of config.mappings) {
|
||||||
|
|||||||
@ -22,7 +22,7 @@ export function generateSamples(
|
|||||||
const value = compiledFormula(t, a, b, c, d)
|
const value = compiledFormula(t, a, b, c, d)
|
||||||
const byteValue = value & 0xFF
|
const byteValue = value & 0xFF
|
||||||
buffer[t] = (byteValue - 128) / 128
|
buffer[t] = (byteValue - 128) / 128
|
||||||
} catch (error) {
|
} catch {
|
||||||
buffer[t] = 0
|
buffer[t] = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -47,7 +47,7 @@ export function generateSamplesWithBitDepth(
|
|||||||
const value = compiledFormula(t, a, b, c, d)
|
const value = compiledFormula(t, a, b, c, d)
|
||||||
const clampedValue = value & maxValue
|
const clampedValue = value & maxValue
|
||||||
buffer[t] = (clampedValue - midPoint) / midPoint
|
buffer[t] = (clampedValue - midPoint) / midPoint
|
||||||
} catch (error) {
|
} catch {
|
||||||
buffer[t] = 0
|
buffer[t] = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,11 +25,11 @@ export class BytebeatSourceEffect implements Effect {
|
|||||||
return this.outputNode
|
return this.outputNode
|
||||||
}
|
}
|
||||||
|
|
||||||
setBypass(_bypass: boolean): void {
|
setBypass(): void {
|
||||||
// Source node doesn't support bypass
|
// Source node doesn't support bypass
|
||||||
}
|
}
|
||||||
|
|
||||||
updateParams(_values: Record<string, number | string>): void {
|
updateParams(): void {
|
||||||
// Parameters handled via specific methods
|
// Parameters handled via specific methods
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -30,11 +30,11 @@ export class OutputLimiter implements Effect {
|
|||||||
return this.outputNode
|
return this.outputNode
|
||||||
}
|
}
|
||||||
|
|
||||||
setBypass(_bypass: boolean): void {
|
setBypass(): void {
|
||||||
// Output limiter is always on
|
// Output limiter is always on
|
||||||
}
|
}
|
||||||
|
|
||||||
updateParams(_values: Record<string, number | string>): void {
|
updateParams(): void {
|
||||||
// Uses default parameters from worklet
|
// Uses default parameters from worklet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,30 +0,0 @@
|
|||||||
import type { Effect } from './Effect.interface'
|
|
||||||
|
|
||||||
export class PassThroughEffect implements Effect {
|
|
||||||
readonly id: string
|
|
||||||
private node: GainNode
|
|
||||||
|
|
||||||
constructor(audioContext: AudioContext, id: string) {
|
|
||||||
this.id = id
|
|
||||||
this.node = audioContext.createGain()
|
|
||||||
this.node.gain.value = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
getInputNode(): AudioNode {
|
|
||||||
return this.node
|
|
||||||
}
|
|
||||||
|
|
||||||
getOutputNode(): AudioNode {
|
|
||||||
return this.node
|
|
||||||
}
|
|
||||||
|
|
||||||
setBypass(_bypass: boolean): void {
|
|
||||||
}
|
|
||||||
|
|
||||||
updateParams(_values: Record<string, number | string>): void {
|
|
||||||
}
|
|
||||||
|
|
||||||
dispose(): void {
|
|
||||||
this.node.disconnect()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -90,8 +90,8 @@ export class ParameterRegistry {
|
|||||||
|
|
||||||
getModulatableParamsByCategory(category: 'engine' | 'effect'): string[] {
|
getModulatableParamsByCategory(category: 'engine' | 'effect'): string[] {
|
||||||
return Array.from(this.metadata.entries())
|
return Array.from(this.metadata.entries())
|
||||||
.filter(([_, meta]) => meta.category === category)
|
.filter(([, meta]) => meta.category === category)
|
||||||
.map(([id, _]) => id)
|
.map(([id]) => id)
|
||||||
}
|
}
|
||||||
|
|
||||||
clampValue(paramId: string, value: number): number {
|
clampValue(paramId: string, value: number): number {
|
||||||
|
|||||||
@ -60,7 +60,7 @@ export function useKeyboardShortcuts(handlers: KeyboardShortcutHandlers) {
|
|||||||
h.onArrowRight?.(e.shiftKey)
|
h.onArrowRight?.(e.shiftKey)
|
||||||
break
|
break
|
||||||
|
|
||||||
case 'Enter':
|
case 'Enter': {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
const now = Date.now()
|
const now = Date.now()
|
||||||
if (now - lastEnterTime < DOUBLE_ENTER_THRESHOLD) {
|
if (now - lastEnterTime < DOUBLE_ENTER_THRESHOLD) {
|
||||||
@ -70,6 +70,7 @@ export function useKeyboardShortcuts(handlers: KeyboardShortcutHandlers) {
|
|||||||
}
|
}
|
||||||
lastEnterTime = now
|
lastEnterTime = now
|
||||||
break
|
break
|
||||||
|
}
|
||||||
|
|
||||||
case 'r':
|
case 'r':
|
||||||
case 'R':
|
case 'R':
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { AudioPlayer } from '../domain/audio/AudioPlayer'
|
import { AudioPlayer } from '../domain/audio/AudioPlayer'
|
||||||
|
import type { LFOWaveform } from '../domain/modulation/LFO'
|
||||||
import type { EffectValues } from '../types/effects'
|
import type { EffectValues } from '../types/effects'
|
||||||
import { DEFAULT_VARIABLES } from '../constants/defaults'
|
import { DEFAULT_VARIABLES } from '../constants/defaults'
|
||||||
|
|
||||||
@ -31,7 +32,7 @@ export class PlaybackManager {
|
|||||||
this.player.updateRealtimeVariables(a, b, c, d)
|
this.player.updateRealtimeVariables(a, b, c, d)
|
||||||
}
|
}
|
||||||
|
|
||||||
setLFOConfig(lfoIndex: number, config: { frequency: number; phase: number; waveform: string; mappings: Array<{ targetParam: string; depth: number }> }): void {
|
setLFOConfig(lfoIndex: number, config: { frequency: number; phase: number; waveform: LFOWaveform; mappings: Array<{ targetParam: string; depth: number }> }): void {
|
||||||
this.player.setLFOConfig(lfoIndex, config)
|
this.player.setLFOConfig(lfoIndex, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -186,9 +186,9 @@ function fillTemplate(pattern: string): string {
|
|||||||
|
|
||||||
function applyParenthesizationRandomization(formula: string): string {
|
function applyParenthesizationRandomization(formula: string): string {
|
||||||
if (Math.random() < 0.2) {
|
if (Math.random() < 0.2) {
|
||||||
const operators = formula.match(/[\+\-\*\/\&\|\^]/g)
|
const operators = formula.match(/[+\-*/&|^]/g)
|
||||||
if (operators && operators.length > 0) {
|
if (operators && operators.length > 0) {
|
||||||
const parts = formula.split(/([+\-*\/&|^])/)
|
const parts = formula.split(/([+\-*/&|^])/)
|
||||||
if (parts.length >= 3) {
|
if (parts.length >= 3) {
|
||||||
const idx = Math.floor(Math.random() * (parts.length - 2) / 2) * 2
|
const idx = Math.floor(Math.random() * (parts.length - 2) / 2) * 2
|
||||||
parts[idx] = `(${parts[idx]})`
|
parts[idx] = `(${parts[idx]})`
|
||||||
|
|||||||
@ -28,16 +28,16 @@ export function createTileStateFromCurrent(formula: string): TileState {
|
|||||||
|
|
||||||
export function loadTileParams(tile: TileState): void {
|
export function loadTileParams(tile: TileState): void {
|
||||||
Object.entries(tile.engineParams).forEach(([key, value]) => {
|
Object.entries(tile.engineParams).forEach(([key, value]) => {
|
||||||
engineSettings.setKey(key as any, value)
|
engineSettings.setKey(key as keyof ReturnType<typeof getDefaultEngineValues>, value)
|
||||||
})
|
})
|
||||||
|
|
||||||
Object.entries(tile.effectParams).forEach(([key, value]) => {
|
Object.entries(tile.effectParams).forEach(([key, value]) => {
|
||||||
effectSettings.setKey(key as any, value as any)
|
effectSettings.setKey(key as never, value as never)
|
||||||
})
|
})
|
||||||
|
|
||||||
if (tile.lfoConfigs) {
|
if (tile.lfoConfigs) {
|
||||||
Object.entries(tile.lfoConfigs).forEach(([key, value]) => {
|
Object.entries(tile.lfoConfigs).forEach(([key, value]) => {
|
||||||
lfoSettings.setKey(key as any, value)
|
lfoSettings.setKey(key as keyof LFOSettings, value)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,7 +21,7 @@ export function generateWaveformData(formula: string, width: number, sampleRate:
|
|||||||
}
|
}
|
||||||
|
|
||||||
return waveform
|
return waveform
|
||||||
} catch (error) {
|
} catch {
|
||||||
return Array(width * 2).fill(0)
|
return Array(width * 2).fill(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user