diff --git a/packages/karplus-strong/src/dsp.ts b/packages/karplus-strong/src/dsp.ts index eef5959..3b9bd33 100644 --- a/packages/karplus-strong/src/dsp.ts +++ b/packages/karplus-strong/src/dsp.ts @@ -18,10 +18,11 @@ export function createKS(sampleRate: number, minFrequency: number) { ) => { const outputLength = output.length; - const decayTimeInSamples = decay * sampleRate; + const decayTimeInSamples = 0.1 * decay * sampleRate; const filterCoefficient = Math.pow(targetAmplitude, 1 / decayTimeInSamples); - if (trigger > 0 && prevTrigger <= 0) { + if (trigger >= 1 && prevTrigger < 0.9) { + // Some hysterisis to avoid double triggering delayInSamples = sampleRate / frequency; delayInSamples = Math.min( Math.max(delayInSamples, 1), @@ -62,7 +63,7 @@ export function createKS(sampleRate: number, minFrequency: number) { writeIndex = (writeIndex + 1) % maxDelayLineLength; // Stop playing if the signal has decayed below a threshold - if (Math.abs(currentSample) < 1e-6) { + if (Math.abs(currentSample) < 1e-8) { isPlaying = false; for (let j = i + 1; j < outputLength; j++) { output[j] = 0; diff --git a/packages/karplus-strong/src/processor.ts b/packages/karplus-strong/src/processor.ts index d623805..7cb29d8 100644 --- a/packages/karplus-strong/src/processor.ts +++ b/packages/karplus-strong/src/processor.ts @@ -1 +1 @@ -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);})();`; +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=.1*A*o,M=Math.pow(.001,1/I);if(y>=1&&h<.9){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/site/content/docs/(sources)/ks.mdx b/site/content/docs/(sources)/ks.mdx index 840c730..28e595e 100644 --- a/site/content/docs/(sources)/ks.mdx +++ b/site/content/docs/(sources)/ks.mdx @@ -7,7 +7,7 @@ description: A Karplus-Strong source node import KsExample from "../../../examples/KsExample"; -A source generator based on the Karplus-Strong algorithm. +A (currently) very simple Karplus-Strong source node: ```ts import { registerKarplusStrongWorklet, KarplusStrong } from "synthlet"; @@ -26,19 +26,6 @@ osc.trigger.value = 1; ## Parameters -- `type`: The type of noise to generate. Can be one of: - - 0 `KsType.White`: White noise that uses `Math.rand` for random numbers. - - 10: `KsType.Pink`: Pink noise based on this [Larry Trammel algorithm](https://www.ridgerat-tech.us/pink/newpink.htm) - -Since type is an audio param, any arbitrary value can be used, but only the above values are valid. If you suply an invalid value, a warning will be printed and the noise will default to white random. - -## References - -- https://en.wikipedia.org/wiki/Colors_of_noise -- Voss-McCartney algorithm: - - https://www.firstpr.com.au/dsp/pink-noise/ - - https://dsp.stackexchange.com/questions/62342/understanding-voss-mccartney-pink-noise-generation-algorithm -- Larry-Trammel algorithm: - - https://www.ridgerat-tech.us/pink/newpink.htm -- Mathlab pink noise implementation: https://ccrma.stanford.edu/~jos/sasp/Example_Synthesis_1_F_Ks.html -- https://github.com/Stenzel/newshadeofpink +- `trigger`: A trigger to start the sound (1 means start) +- `frequency`: The frequency of the generated sound. +- `decay`: The decay time of the generated sound.