From 336f87c342f7a115d5a92b5fe14d4447c7a62832 Mon Sep 17 00:00:00 2001 From: danigb Date: Mon, 30 Sep 2024 03:01:17 +0200 Subject: [PATCH] feat: simplify ks algorithm --- README.md | 2 + packages/karplus-strong/src/dsp.ts | 170 +++++++++-------------- packages/karplus-strong/src/index.ts | 6 +- packages/karplus-strong/src/processor.ts | 2 +- packages/karplus-strong/src/worklet.ts | 6 +- site/.source/index.js | 64 ++++----- site/examples/KsExample.tsx | 10 +- 7 files changed, 111 insertions(+), 149 deletions(-) diff --git a/README.md b/README.md index a3b0c36..17e6504 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,8 @@ This library wouldn't be possible with all the people writing books, blog posts - [Cmajor](https://github.com/SoundStacks/cmajor) - [VCVRack](https://github.com/VCVRack/Rack) - [The Synthesis ToolKit](https://github.com/thestk/stk) +- [Surge synth](https://github.com/surge-synthesizer/surge) +- [Surge Rust](https://github.com/klebs6/surge-rs) - https://github.com/jd-13/WE-Core - https://github.com/mhetrick/nonlinearcircuits - https://github.com/timowest/analogue diff --git a/packages/karplus-strong/src/dsp.ts b/packages/karplus-strong/src/dsp.ts index 02921f1..eef5959 100644 --- a/packages/karplus-strong/src/dsp.ts +++ b/packages/karplus-strong/src/dsp.ts @@ -1,120 +1,78 @@ export function createKS(sampleRate: number, minFrequency: number) { - let active = false; - let startExciter = false; + const targetAmplitude = 0.001; // Amplitude decays to 0.1% of initial value + const maxDelayLineLength = Math.ceil(sampleRate / minFrequency) + 2; // Extra samples for interpolation - const excite = createExciter(1000); + const delayLine = new Float32Array(maxDelayLineLength); - // Delay line - const maxIndex = Math.floor(sampleRate / minFrequency + 0.5); - const delay = new InterpolatedDelayLine(maxIndex); + let delayInSamples = maxDelayLineLength - 2; + let writeIndex = 0; - // One pole filter for delay - let filterAlpha = 0.99; - let prevFilterOut = 0; + let isPlaying = false; + let prevTrigger = 0; - // Feedback - let lossFactor = 0.99; - - // Param cache - let $freq = 0; - let $damping = 0; - - return function ( + return ( output: Float32Array, trigger: number, frequency: number, - damping: number - ) { - if ($freq !== frequency) { - $freq = frequency; - delay.setDelayLength(sampleRate / frequency); - } - if ($damping !== damping) { - $damping = damping; - lossFactor = damping * 0.2 + 0.792; - filterAlpha = Math.max(0, Math.min(1, damping)); - } - - if (trigger === 1) { - if (!active) { - active = true; - startExciter = true; + decay: number + ) => { + const outputLength = output.length; + + const decayTimeInSamples = decay * sampleRate; + const filterCoefficient = Math.pow(targetAmplitude, 1 / decayTimeInSamples); + + if (trigger > 0 && prevTrigger <= 0) { + delayInSamples = sampleRate / frequency; + delayInSamples = Math.min( + Math.max(delayInSamples, 1), + maxDelayLineLength - 2 + ); + + for (let i = 0; i < maxDelayLineLength; i++) { + delayLine[i] = Math.random() * 2 - 1; } - } else { - active = false; + writeIndex = 0; + isPlaying = true; } - - for (let i = 0; i < output.length; i++) { - const pluck = excite(startExciter); - startExciter = false; - - //const prev = delay.read(delayLength - 1); - const curr = delay.read(); - const filterOut = - curr * 1.0 * filterAlpha + prevFilterOut * (1 - filterAlpha); - prevFilterOut = filterOut; - output[i] = pluck * filterOut * lossFactor; - } - }; -} - -class InterpolatedDelayLine { - buffer: Float32Array; - writeIndex: number; - delayLength: number; - position: number; // - - constructor(public readonly size: number) { - this.buffer = new Float32Array(size); - this.writeIndex = 0; - this.delayLength = 10; - this.position = size - this.delayLength; - } - - setDelayLength(delayLength: number) { - this.delayLength = delayLength; - this.position = this.writeIndex - delayLength; - while (this.position < 0) this.position += this.size; - } - - writeAndUpdateIndex(value: number) { - this.buffer[this.writeIndex] = value; - this.writeIndex++; - if (this.writeIndex >= this.size) this.writeIndex = 0; - this.position++; - if (this.position >= this.size) this.position -= this.size; - } - - read() { - while (this.position < 0) this.position += this.size; - const curr = Math.floor(this.position); - let next = curr + 1; - while (next >= this.size) next -= this.size; - const frac = this.position - curr; - const currVal = this.buffer[curr]; - const nextVal = this.buffer[next]; - return currVal - frac + (nextVal - currVal); - } -} - -function createExciter(durationInSamples: number) { - const window = new Float32Array(durationInSamples); - - // Create a triangular envelope - for (let i = 0; i < durationInSamples; i++) { - window[i] = 1 - Math.abs(i / (durationInSamples / 2) - 1); - } - - let index = window.length; - - return function (start: boolean) { - if (start) index = 0; - if (index < window.length) { - index++; - const noise = Math.random() * 2 - 1; - return noise * window[index]; + prevTrigger = trigger; + + if (isPlaying) { + for (let i = 0; i < outputLength; i++) { + let readIndex = writeIndex - delayInSamples; + if (readIndex < 0) { + readIndex += maxDelayLineLength; + } + + const readIndexInt = Math.floor(readIndex); + const frac = readIndex - readIndexInt; + + // Wrap around the delay line + const index0 = readIndexInt % maxDelayLineLength; + const index1 = (readIndexInt + 1) % maxDelayLineLength; + + // Linear interpolation between two samples + const sample0 = delayLine[index0]; + const sample1 = delayLine[index1]; + const currentSample = sample0 + frac * (sample1 - sample0); + + const nextSample = filterCoefficient * currentSample; + delayLine[writeIndex] = nextSample; + output[i] = currentSample; + + writeIndex = (writeIndex + 1) % maxDelayLineLength; + + // Stop playing if the signal has decayed below a threshold + if (Math.abs(currentSample) < 1e-6) { + isPlaying = false; + for (let j = i + 1; j < outputLength; j++) { + output[j] = 0; + } + break; + } + } } else { - return 0; + // Output silence when not playing + output.fill(0); } }; } diff --git a/packages/karplus-strong/src/index.ts b/packages/karplus-strong/src/index.ts index e9ffe96..bbd7344 100644 --- a/packages/karplus-strong/src/index.ts +++ b/packages/karplus-strong/src/index.ts @@ -13,13 +13,13 @@ export const registerKarplusStrongWorklet = createRegistrar( export type KarplusStrongInputs = { trigger: ParamInput; frequency: ParamInput; - damping: ParamInput; + decay: ParamInput; }; export type KarplusStrongWorkletNode = AudioWorkletNode & { trigger: AudioParam; frequency: AudioParam; - damping: AudioParam; + decay: AudioParam; dispose(): void; }; @@ -28,7 +28,7 @@ export const KarplusStrong = createWorkletConstructor< KarplusStrongInputs >({ processorName: "KsProcessor", - paramNames: ["trigger", "frequency", "damping"], + paramNames: ["trigger", "frequency", "decay"], workletOptions: () => ({ numberOfInputs: 0, numberOfOutputs: 1, diff --git a/packages/karplus-strong/src/processor.ts b/packages/karplus-strong/src/processor.ts index e48b1f4..d623805 100644 --- a/packages/karplus-strong/src/processor.ts +++ b/packages/karplus-strong/src/processor.ts @@ -1 +1 @@ -export const PROCESSOR = `"use strict";(()=>{function w(s,t){let i=!1,e=!1,r=F(1e3),o=Math.floor(s/t+.5),f=new c(o),a=.99,p=0,b=.99,d=0,x=0;return function(g,y,h,n){d!==h&&(d=h,f.setDelayLength(s/h)),x!==n&&(x=n,b=n*.2+.792,a=Math.max(0,Math.min(1,n))),y===1?i||(i=!0,e=!0):i=!1;for(let l=0;l=this.size&&(this.writeIndex=0),this.position++,this.position>=this.size&&(this.position-=this.size)}read(){for(;this.position<0;)this.position+=this.size;let t=Math.floor(this.position),i=t+1;for(;i>=this.size;)i-=this.size;let e=this.position-t,r=this.buffer[t],o=this.buffer[i];return r-e+(o-r)}};function F(s){let t=new Float32Array(s);for(let e=0;e{switch(t.data.type){case"DISPOSE":this.r=!1;break}}}process(t,i,e){let r=i[0][0];return this.g(r,e.trigger[0],e.frequency[0],e.damping[0]),this.r}static get parameterDescriptors(){return[["trigger",0,0,1],["frequency",440,20,2e4],["damping",.1,0,1]].map(([t,i,e,r])=>({name:t,defaultValue:i,minValue:e,maxValue:r,automationRate:"k-rate"}))}};registerProcessor("KsProcessor",u);})();`; +export const PROCESSOR = `"use strict";(()=>{function b(o,n){let e=Math.ceil(o/n)+2,t=new Float32Array(e),i=e-2,a=0,f=!1,h=0;return(c,y,S,A)=>{let g=c.length,I=A*o,M=Math.pow(.001,1/I);if(y>0&&h<=0){i=o/S,i=Math.min(Math.max(i,1),e-2);for(let r=0;r{switch(n.data.type){case"DISPOSE":this.r=!1;break}}}process(n,s,e){let t=s[0][0];return this.g(t,e.trigger[0],e.frequency[0],e.decay[0]),this.r}static get parameterDescriptors(){return[["trigger",0,0,1],["frequency",440,20,2e4],["decay",.1,.01,5]].map(([n,s,e,t])=>({name:n,defaultValue:s,minValue:e,maxValue:t,automationRate:"k-rate"}))}};registerProcessor("KsProcessor",d);})();`; diff --git a/packages/karplus-strong/src/worklet.ts b/packages/karplus-strong/src/worklet.ts index 0aeb71c..ed0361c 100644 --- a/packages/karplus-strong/src/worklet.ts +++ b/packages/karplus-strong/src/worklet.ts @@ -7,7 +7,7 @@ export class KsProcessor extends AudioWorkletProcessor { constructor() { super(); this.r = true; - this.g = createKS(sampleRate, 20); + this.g = createKS(sampleRate, 100); this.port.onmessage = (event) => { switch (event.data.type) { case "DISPOSE": @@ -19,7 +19,7 @@ export class KsProcessor extends AudioWorkletProcessor { process(inputs: Float32Array[][], outputs: Float32Array[][], params: any) { const output = outputs[0][0]; - this.g(output, params.trigger[0], params.frequency[0], params.damping[0]); + this.g(output, params.trigger[0], params.frequency[0], params.decay[0]); return this.r; } @@ -28,7 +28,7 @@ export class KsProcessor extends AudioWorkletProcessor { return [ ["trigger", 0, 0, 1], ["frequency", 440, 20, 20000], - ["damping", 0.1, 0, 1], + ["decay", 0.1, 0.01, 5], ].map(([name, defaultValue, minValue, maxValue]) => ({ name, defaultValue, diff --git a/site/.source/index.js b/site/.source/index.js index a79e87a..157caca 100644 --- a/site/.source/index.js +++ b/site/.source/index.js @@ -1,33 +1,33 @@ import { toRuntime } from "fumadocs-mdx" -import * as file_0 from "../content/docs/dsl.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" -import * as file_1 from "../content/docs/guide.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" -import * as file_2 from "../content/docs/quick-start.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" -import * as file_3 from "../content/docs/synths.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" -import * as file_4 from "../content/docs/troubleshoo.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" -import * as file_5 from "../content/docs/(effects)/chorus-t.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" -import * as file_6 from "../content/docs/(effects)/chorus.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" -import * as file_7 from "../content/docs/(effects)/dattorro.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" -import * as file_8 from "../content/docs/(modifiers)/ad-amp.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" -import * as file_9 from "../content/docs/(modifiers)/adsr-amp.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" -import * as file_10 from "../content/docs/(modifiers)/clip-amp.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" -import * as file_11 from "../content/docs/(modifiers)/state-variable-filter.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" -import * as file_12 from "../content/docs/(modulators)/ad.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" -import * as file_13 from "../content/docs/(modulators)/adsr.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" -import * as file_14 from "../content/docs/(modulators)/lfo.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" -import * as file_15 from "../content/docs/(modulators)/param.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" -import * as file_16 from "../content/docs/(sequencers)/arp.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" -import * as file_17 from "../content/docs/(sequencers)/clock.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" -import * as file_18 from "../content/docs/(sequencers)/euclid.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" -import * as file_19 from "../content/docs/(sources)/impulse.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" -import * as file_20 from "../content/docs/(sources)/ks.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" -import * as file_21 from "../content/docs/(sources)/noise.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" -import * as file_22 from "../content/docs/(sources)/polyblep.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" -import * as file_23 from "../content/docs/(sources)/wavetable.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" -import * as file_24 from "../content/docs/meta.json?collection=meta&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" -import * as file_25 from "../content/docs/(effects)/meta.json?collection=meta&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" -import * as file_26 from "../content/docs/(modifiers)/meta.json?collection=meta&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" -import * as file_27 from "../content/docs/(modulators)/meta.json?collection=meta&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" -import * as file_28 from "../content/docs/(sequencers)/meta.json?collection=meta&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" -import * as file_29 from "../content/docs/(sources)/meta.json?collection=meta&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" -export const docs = [toRuntime("doc", file_0, {"path":"dsl.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/dsl.mdx"}),toRuntime("doc", file_1, {"path":"guide.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/guide.mdx"}),toRuntime("doc", file_2, {"path":"quick-start.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/quick-start.mdx"}),toRuntime("doc", file_3, {"path":"synths.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/synths.mdx"}),toRuntime("doc", file_4, {"path":"troubleshoo.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/troubleshoo.mdx"}),toRuntime("doc", file_5, {"path":"(effects)/chorus-t.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(effects)/chorus-t.mdx"}),toRuntime("doc", file_6, {"path":"(effects)/chorus.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(effects)/chorus.mdx"}),toRuntime("doc", file_7, {"path":"(effects)/dattorro.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(effects)/dattorro.mdx"}),toRuntime("doc", file_8, {"path":"(modifiers)/ad-amp.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(modifiers)/ad-amp.mdx"}),toRuntime("doc", file_9, {"path":"(modifiers)/adsr-amp.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(modifiers)/adsr-amp.mdx"}),toRuntime("doc", file_10, {"path":"(modifiers)/clip-amp.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(modifiers)/clip-amp.mdx"}),toRuntime("doc", file_11, {"path":"(modifiers)/state-variable-filter.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(modifiers)/state-variable-filter.mdx"}),toRuntime("doc", file_12, {"path":"(modulators)/ad.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(modulators)/ad.mdx"}),toRuntime("doc", file_13, {"path":"(modulators)/adsr.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(modulators)/adsr.mdx"}),toRuntime("doc", file_14, {"path":"(modulators)/lfo.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(modulators)/lfo.mdx"}),toRuntime("doc", file_15, {"path":"(modulators)/param.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(modulators)/param.mdx"}),toRuntime("doc", file_16, {"path":"(sequencers)/arp.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(sequencers)/arp.mdx"}),toRuntime("doc", file_17, {"path":"(sequencers)/clock.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(sequencers)/clock.mdx"}),toRuntime("doc", file_18, {"path":"(sequencers)/euclid.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(sequencers)/euclid.mdx"}),toRuntime("doc", file_19, {"path":"(sources)/impulse.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(sources)/impulse.mdx"}),toRuntime("doc", file_20, {"path":"(sources)/ks.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(sources)/ks.mdx"}),toRuntime("doc", file_21, {"path":"(sources)/noise.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(sources)/noise.mdx"}),toRuntime("doc", file_22, {"path":"(sources)/polyblep.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(sources)/polyblep.mdx"}),toRuntime("doc", file_23, {"path":"(sources)/wavetable.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(sources)/wavetable.mdx"})] -export const meta = [toRuntime("meta", file_24, {"path":"meta.json","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/meta.json"}),toRuntime("meta", file_25, {"path":"(effects)/meta.json","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(effects)/meta.json"}),toRuntime("meta", file_26, {"path":"(modifiers)/meta.json","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(modifiers)/meta.json"}),toRuntime("meta", file_27, {"path":"(modulators)/meta.json","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(modulators)/meta.json"}),toRuntime("meta", file_28, {"path":"(sequencers)/meta.json","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(sequencers)/meta.json"}),toRuntime("meta", file_29, {"path":"(sources)/meta.json","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(sources)/meta.json"})] \ No newline at end of file +import * as file_0 from "../content/docs/meta.json?collection=meta&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" +import * as file_1 from "../content/docs/(effects)/meta.json?collection=meta&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" +import * as file_2 from "../content/docs/(modifiers)/meta.json?collection=meta&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" +import * as file_3 from "../content/docs/(modulators)/meta.json?collection=meta&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" +import * as file_4 from "../content/docs/(sequencers)/meta.json?collection=meta&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" +import * as file_5 from "../content/docs/(sources)/meta.json?collection=meta&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" +import * as file_6 from "../content/docs/dsl.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" +import * as file_7 from "../content/docs/guide.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" +import * as file_8 from "../content/docs/quick-start.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" +import * as file_9 from "../content/docs/synths.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" +import * as file_10 from "../content/docs/troubleshoo.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" +import * as file_11 from "../content/docs/(effects)/chorus-t.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" +import * as file_12 from "../content/docs/(effects)/chorus.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" +import * as file_13 from "../content/docs/(effects)/dattorro.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" +import * as file_14 from "../content/docs/(modifiers)/ad-amp.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" +import * as file_15 from "../content/docs/(modifiers)/adsr-amp.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" +import * as file_16 from "../content/docs/(modifiers)/clip-amp.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" +import * as file_17 from "../content/docs/(modifiers)/state-variable-filter.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" +import * as file_18 from "../content/docs/(modulators)/ad.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" +import * as file_19 from "../content/docs/(modulators)/adsr.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" +import * as file_20 from "../content/docs/(modulators)/lfo.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" +import * as file_21 from "../content/docs/(modulators)/param.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" +import * as file_22 from "../content/docs/(sequencers)/arp.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" +import * as file_23 from "../content/docs/(sequencers)/clock.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" +import * as file_24 from "../content/docs/(sequencers)/euclid.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" +import * as file_25 from "../content/docs/(sources)/impulse.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" +import * as file_26 from "../content/docs/(sources)/ks.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" +import * as file_27 from "../content/docs/(sources)/noise.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" +import * as file_28 from "../content/docs/(sources)/polyblep.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" +import * as file_29 from "../content/docs/(sources)/wavetable.mdx?collection=docs&hash=a0e5c83919940bc930420dd0f9f7d68e8c5dbe7f6983d8b3ed42ebccd021e4f6" +export const meta = [toRuntime("meta", file_0, {"path":"meta.json","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/meta.json"}),toRuntime("meta", file_1, {"path":"(effects)/meta.json","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(effects)/meta.json"}),toRuntime("meta", file_2, {"path":"(modifiers)/meta.json","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(modifiers)/meta.json"}),toRuntime("meta", file_3, {"path":"(modulators)/meta.json","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(modulators)/meta.json"}),toRuntime("meta", file_4, {"path":"(sequencers)/meta.json","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(sequencers)/meta.json"}),toRuntime("meta", file_5, {"path":"(sources)/meta.json","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(sources)/meta.json"})] +export const docs = [toRuntime("doc", file_6, {"path":"dsl.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/dsl.mdx"}),toRuntime("doc", file_7, {"path":"guide.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/guide.mdx"}),toRuntime("doc", file_8, {"path":"quick-start.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/quick-start.mdx"}),toRuntime("doc", file_9, {"path":"synths.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/synths.mdx"}),toRuntime("doc", file_10, {"path":"troubleshoo.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/troubleshoo.mdx"}),toRuntime("doc", file_11, {"path":"(effects)/chorus-t.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(effects)/chorus-t.mdx"}),toRuntime("doc", file_12, {"path":"(effects)/chorus.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(effects)/chorus.mdx"}),toRuntime("doc", file_13, {"path":"(effects)/dattorro.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(effects)/dattorro.mdx"}),toRuntime("doc", file_14, {"path":"(modifiers)/ad-amp.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(modifiers)/ad-amp.mdx"}),toRuntime("doc", file_15, {"path":"(modifiers)/adsr-amp.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(modifiers)/adsr-amp.mdx"}),toRuntime("doc", file_16, {"path":"(modifiers)/clip-amp.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(modifiers)/clip-amp.mdx"}),toRuntime("doc", file_17, {"path":"(modifiers)/state-variable-filter.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(modifiers)/state-variable-filter.mdx"}),toRuntime("doc", file_18, {"path":"(modulators)/ad.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(modulators)/ad.mdx"}),toRuntime("doc", file_19, {"path":"(modulators)/adsr.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(modulators)/adsr.mdx"}),toRuntime("doc", file_20, {"path":"(modulators)/lfo.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(modulators)/lfo.mdx"}),toRuntime("doc", file_21, {"path":"(modulators)/param.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(modulators)/param.mdx"}),toRuntime("doc", file_22, {"path":"(sequencers)/arp.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(sequencers)/arp.mdx"}),toRuntime("doc", file_23, {"path":"(sequencers)/clock.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(sequencers)/clock.mdx"}),toRuntime("doc", file_24, {"path":"(sequencers)/euclid.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(sequencers)/euclid.mdx"}),toRuntime("doc", file_25, {"path":"(sources)/impulse.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(sources)/impulse.mdx"}),toRuntime("doc", file_26, {"path":"(sources)/ks.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(sources)/ks.mdx"}),toRuntime("doc", file_27, {"path":"(sources)/noise.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(sources)/noise.mdx"}),toRuntime("doc", file_28, {"path":"(sources)/polyblep.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(sources)/polyblep.mdx"}),toRuntime("doc", file_29, {"path":"(sources)/wavetable.mdx","absolutePath":"/Users/danigb/Projects/Synthlet/site/content/docs/(sources)/wavetable.mdx"})] \ No newline at end of file diff --git a/site/examples/KsExample.tsx b/site/examples/KsExample.tsx index df76ec8..0cf6c4d 100644 --- a/site/examples/KsExample.tsx +++ b/site/examples/KsExample.tsx @@ -29,14 +29,16 @@ function Example() {