├── .babelrc ├── .eslintrc ├── .gitignore ├── .travis.yml ├── README.md ├── package.json ├── src ├── Constants.js ├── DefaultConfig.js ├── SCContext.js ├── SCGraphNode.js ├── SCGraphNodeDoneAction.js ├── SCRate.js ├── SCSynth.js ├── SCSynthBuilder.js ├── SCUnit.js ├── SCUnitRepository.js ├── index.js ├── unit │ ├── SCUnitA2K.js │ ├── SCUnitAPF.js │ ├── SCUnitAllpassC.js │ ├── SCUnitAllpassL.js │ ├── SCUnitAllpassN.js │ ├── SCUnitAmpComp.js │ ├── SCUnitAmpCompA.js │ ├── SCUnitAmplitude.js │ ├── SCUnitBPF.js │ ├── SCUnitBPZ2.js │ ├── SCUnitBRF.js │ ├── SCUnitBRZ2.js │ ├── SCUnitBalance2.js │ ├── SCUnitBinaryOpUGen.js │ ├── SCUnitBlip.js │ ├── SCUnitBrownNoise.js │ ├── SCUnitClip.js │ ├── SCUnitClipNoise.js │ ├── SCUnitCoinGate.js │ ├── SCUnitCombC.js │ ├── SCUnitCombL.js │ ├── SCUnitCombN.js │ ├── SCUnitCompander.js │ ├── SCUnitControl.js │ ├── SCUnitControlDur.js │ ├── SCUnitControlRate.js │ ├── SCUnitCrackle.js │ ├── SCUnitDC.js │ ├── SCUnitDbrown.js │ ├── SCUnitDecay.js │ ├── SCUnitDecay2.js │ ├── SCUnitDelay1.js │ ├── SCUnitDelay2.js │ ├── SCUnitDelayC.js │ ├── SCUnitDelayL.js │ ├── SCUnitDelayN.js │ ├── SCUnitDemand.js │ ├── SCUnitDemandEnvGen.js │ ├── SCUnitDetectSilence.js │ ├── SCUnitDgeom.js │ ├── SCUnitDibrown.js │ ├── SCUnitDiwhite.js │ ├── SCUnitDrand.js │ ├── SCUnitDreset.js │ ├── SCUnitDseq.js │ ├── SCUnitDser.js │ ├── SCUnitDseries.js │ ├── SCUnitDshuf.js │ ├── SCUnitDstutter.js │ ├── SCUnitDswitch.js │ ├── SCUnitDswitch1.js │ ├── SCUnitDust.js │ ├── SCUnitDust2.js │ ├── SCUnitDuty.js │ ├── SCUnitDwhite.js │ ├── SCUnitDwrand.js │ ├── SCUnitDxrand.js │ ├── SCUnitEnvGen.js │ ├── SCUnitExpRand.js │ ├── SCUnitFOS.js │ ├── SCUnitFSinOsc.js │ ├── SCUnitFold.js │ ├── SCUnitFormlet.js │ ├── SCUnitFreeVerb.js │ ├── SCUnitFreeVerb2.js │ ├── SCUnitGate.js │ ├── SCUnitGrayNoise.js │ ├── SCUnitHPF.js │ ├── SCUnitHPZ1.js │ ├── SCUnitHPZ2.js │ ├── SCUnitHasher.js │ ├── SCUnitIRand.js │ ├── SCUnitImpulse.js │ ├── SCUnitIn.js │ ├── SCUnitInRange.js │ ├── SCUnitInRect.js │ ├── SCUnitIntegrator.js │ ├── SCUnitK2A.js │ ├── SCUnitKeyState.js │ ├── SCUnitKlang.js │ ├── SCUnitKlank.js │ ├── SCUnitLFClipNoise.js │ ├── SCUnitLFCub.js │ ├── SCUnitLFDClipNoise.js │ ├── SCUnitLFDNoise0.js │ ├── SCUnitLFDNoise1.js │ ├── SCUnitLFDNoise3.js │ ├── SCUnitLFNoise0.js │ ├── SCUnitLFNoise1.js │ ├── SCUnitLFNoise2.js │ ├── SCUnitLFPar.js │ ├── SCUnitLFPulse.js │ ├── SCUnitLFSaw.js │ ├── SCUnitLFTri.js │ ├── SCUnitLPF.js │ ├── SCUnitLPZ1.js │ ├── SCUnitLPZ2.js │ ├── SCUnitLag.js │ ├── SCUnitLag2.js │ ├── SCUnitLag2UD.js │ ├── SCUnitLag3.js │ ├── SCUnitLag3UD.js │ ├── SCUnitLagControl.js │ ├── SCUnitLagUD.js │ ├── SCUnitLastValue.js │ ├── SCUnitLatch.js │ ├── SCUnitLeakDC.js │ ├── SCUnitLeastChange.js │ ├── SCUnitLimiter.js │ ├── SCUnitLinExp.js │ ├── SCUnitLinLin.js │ ├── SCUnitLinPan2.js │ ├── SCUnitLinRand.js │ ├── SCUnitLinXFade2.js │ ├── SCUnitLine.js │ ├── SCUnitLinen.js │ ├── SCUnitLogistic.js │ ├── SCUnitMantissaMask.js │ ├── SCUnitMedian.js │ ├── SCUnitMidEQ.js │ ├── SCUnitModDif.js │ ├── SCUnitMostChange.js │ ├── SCUnitMouseButton.js │ ├── SCUnitMouseX.js │ ├── SCUnitMouseY.js │ ├── SCUnitMulAdd.js │ ├── SCUnitNRand.js │ ├── SCUnitNormalizer.js │ ├── SCUnitNumAudioBuses.js │ ├── SCUnitNumControlBuses.js │ ├── SCUnitNumInputBuses.js │ ├── SCUnitNumOutputBuses.js │ ├── SCUnitOffsetOut.js │ ├── SCUnitOnePole.js │ ├── SCUnitOneZero.js │ ├── SCUnitOut.js │ ├── SCUnitPan2.js │ ├── SCUnitPeak.js │ ├── SCUnitPeakFollower.js │ ├── SCUnitPhasor.js │ ├── SCUnitPinkNoise.js │ ├── SCUnitPulse.js │ ├── SCUnitPulseCount.js │ ├── SCUnitPulseDivider.js │ ├── SCUnitRHPF.js │ ├── SCUnitRLPF.js │ ├── SCUnitRadiansPerSample.js │ ├── SCUnitRamp.js │ ├── SCUnitRand.js │ ├── SCUnitReplaceOut.js │ ├── SCUnitResonz.js │ ├── SCUnitRingz.js │ ├── SCUnitRotate2.js │ ├── SCUnitRunningMax.js │ ├── SCUnitRunningMin.js │ ├── SCUnitSOS.js │ ├── SCUnitSampleDur.js │ ├── SCUnitSampleRate.js │ ├── SCUnitSaw.js │ ├── SCUnitSchmidt.js │ ├── SCUnitSelect.js │ ├── SCUnitSetResetFF.js │ ├── SCUnitSinOsc.js │ ├── SCUnitSinOscFB.js │ ├── SCUnitSlew.js │ ├── SCUnitSlope.js │ ├── SCUnitStepper.js │ ├── SCUnitSubsampleOffset.js │ ├── SCUnitSum3.js │ ├── SCUnitSum4.js │ ├── SCUnitSweep.js │ ├── SCUnitSyncSaw.js │ ├── SCUnitT2A.js │ ├── SCUnitT2K.js │ ├── SCUnitTDuty.js │ ├── SCUnitTExpRand.js │ ├── SCUnitTIRand.js │ ├── SCUnitTRand.js │ ├── SCUnitTWindex.js │ ├── SCUnitTimer.js │ ├── SCUnitToggleFF.js │ ├── SCUnitTrig.js │ ├── SCUnitTrig1.js │ ├── SCUnitTrigControl.js │ ├── SCUnitTrigImpulse.js │ ├── SCUnitTwoPole.js │ ├── SCUnitTwoZero.js │ ├── SCUnitUnaryOpUGen.js │ ├── SCUnitVarLag.js │ ├── SCUnitWhiteNoise.js │ ├── SCUnitWrap.js │ ├── SCUnitXFade2.js │ ├── SCUnitXLine.js │ ├── SCUnitXOut.js │ ├── SCUnitZeroCrossing.js │ ├── _delay.js │ ├── _demand.js │ ├── _sine.js │ └── index.js └── util │ ├── clamp.js │ ├── fill.js │ ├── fillRange.js │ ├── index.js │ ├── sc_cubicinterp.js │ ├── sc_exprandrange.js │ ├── sc_fold.js │ ├── sc_randrange.js │ ├── sc_wrap.js │ ├── toNumber.js │ ├── toPowerOfTwo.js │ ├── toValidBlockSize.js │ ├── toValidNumberOfAudioBus.js │ ├── toValidNumberOfChannels.js │ ├── toValidNumberOfControlBus.js │ └── toValidSampleRate.js └── test ├── build.js ├── doneAction.js ├── graph.js ├── state.js ├── synth.js ├── unit ├── SCUnitA2K.js ├── SCUnitAPF.js ├── SCUnitAmpComp.js ├── SCUnitAmpCompA.js ├── SCUnitAmplitude.js ├── SCUnitBPF.js ├── SCUnitBRF.js ├── SCUnitBalance2.js ├── SCUnitBinaryOpUGen.js ├── SCUnitBrownNoise.js ├── SCUnitClipNoise.js ├── SCUnitCoinGate.js ├── SCUnitCompander.js ├── SCUnitCrackle.js ├── SCUnitDbrown.js ├── SCUnitDelay1.js ├── SCUnitDelay2.js ├── SCUnitDgeom.js ├── SCUnitDibrown.js ├── SCUnitDiwhite.js ├── SCUnitDrand.js ├── SCUnitDreset.js ├── SCUnitDseq.js ├── SCUnitDser.js ├── SCUnitDseries.js ├── SCUnitDshuf.js ├── SCUnitDstutter.js ├── SCUnitDswitch.js ├── SCUnitDswitch1.js ├── SCUnitDust.js ├── SCUnitDust2.js ├── SCUnitDwhite.js ├── SCUnitDwrand.js ├── SCUnitDxrand.js ├── SCUnitEnvGen.js ├── SCUnitExpRand.js ├── SCUnitFSinOsc.js ├── SCUnitFormlet.js ├── SCUnitFreeVerb.js ├── SCUnitFreeVerb2.js ├── SCUnitGrayNoise.js ├── SCUnitHPF.js ├── SCUnitHasher.js ├── SCUnitIRand.js ├── SCUnitIn.js ├── SCUnitK2A.js ├── SCUnitKlang.js ├── SCUnitKlank.js ├── SCUnitLFClipNoise.js ├── SCUnitLFCub.js ├── SCUnitLFNoise0.js ├── SCUnitLFNoise1.js ├── SCUnitLFNoise2.js ├── SCUnitLFPar.js ├── SCUnitLFPulse.js ├── SCUnitLFSaw.js ├── SCUnitLFTri.js ├── SCUnitLPF.js ├── SCUnitLastValue.js ├── SCUnitLatch.js ├── SCUnitLeastChange.js ├── SCUnitLimiter.js ├── SCUnitLinPan2.js ├── SCUnitLinRand.js ├── SCUnitLogistic.js ├── SCUnitMantissaMask.js ├── SCUnitMedian.js ├── SCUnitMostChange.js ├── SCUnitMulAdd.js ├── SCUnitNRand.js ├── SCUnitNormalizer.js ├── SCUnitOffsetOut.js ├── SCUnitOut.js ├── SCUnitPan2.js ├── SCUnitPinkNoise.js ├── SCUnitRHPF.js ├── SCUnitRLPF.js ├── SCUnitRand.js ├── SCUnitReplaceOut.js ├── SCUnitRotate2.js ├── SCUnitSchmidt.js ├── SCUnitSinOsc.js ├── SCUnitSinOscFB.js ├── SCUnitSum3.js ├── SCUnitSum4.js ├── SCUnitT2A.js ├── SCUnitT2K.js ├── SCUnitTExpRand.js ├── SCUnitTIRand.js ├── SCUnitTRand.js ├── SCUnitUnaryOpUGen.js ├── SCUnitWhiteNoise.js ├── SCUnitXOut.js └── index.js └── util.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "production": { 4 | "only": [ "src" ], 5 | "presets": [ 6 | "babel-preset-es2015" 7 | ], 8 | "plugins": [ 9 | [ "babel-plugin-unassert" ] 10 | ] 11 | }, 12 | "development": { 13 | "only": [ "test" ], 14 | "presets": [ 15 | "babel-preset-power-assert" 16 | ] 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ "node" ], 3 | "env": { 4 | "es6": true, 5 | "node": true 6 | }, 7 | "rules": { 8 | "no-use-before-define": ["error", { "functions": false, "classes": true } ], 9 | "node/no-unsupported-features": [ 2, { "version": 6 } ] 10 | }, 11 | "extends": "eslint:recommended" 12 | } 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_STORE 2 | .nyc_output 3 | npm-debug.log 4 | node_modules/ 5 | coverage/ 6 | lib/ 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | sudo: false 3 | node_js: 4 | - "6.0" 5 | cache: 6 | directories: 7 | - node_modules 8 | script: 9 | - npm run travis 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # scsynth 2 | [![Build Status](http://img.shields.io/travis/mohayonao/scsynth.svg?style=flat-square)](https://travis-ci.org/mohayonao/scsynth) 3 | [![NPM Version](http://img.shields.io/npm/v/scsynth.svg?style=flat-square)](https://www.npmjs.org/package/scsynth) 4 | [![License](http://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](http://mohayonao.mit-license.org/) 5 | 6 | > sound processing like SuperCollider in JavaScript 7 | 8 | :construction_worker: :zzz: 9 | 10 | ## Installation 11 | 12 | ``` 13 | npm install --save scsynth 14 | ``` 15 | 16 | ## Example 17 | 18 | ```js 19 | const scsynth = require("scsynth"); 20 | 21 | const context = new scsynth.SCContext(); 22 | const synth = context.createSynth({ 23 | name: "sine", 24 | consts: [ 0 ], 25 | paramValues: [ 0.5, 440 ], 26 | paramIndices: { amp: { index: 0, length: 1 }, freq: { index: 1, length: 1 } }, 27 | units: [ 28 | [ "Control" , 1, 0, [ ], [ 1, 1 ] ], 29 | [ "SinOsc" , 2, 0, [ [ 0, 1 ], [ -1, 0 ] ], [ 2 ] ], 30 | [ "BinaryOpUGen", 2, 2, [ [ 1, 0 ], [ 0, 0 ] ], [ 2 ] ], 31 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 2, 0 ], [ 2, 0 ] ], [ ] ] 32 | ] 33 | }); 34 | 35 | context.append(synth); 36 | 37 | for (let i = 0; i < 256; i++) { 38 | synth.$freq = 440 * Math.pow(2, i / 256); 39 | synth.$amp = 1 - (i / 256); 40 | synth.process(); 41 | 42 | console.log("L:", context.outputs[0]); 43 | console.log("R:", context.outputs[1]); 44 | } 45 | ``` 46 | 47 | ## See Also 48 | 49 | - [UGen Implementation List](https://github.com/mohayonao/scsynth/wiki/UGen-Implementation-List) 50 | - [synthdef-decoder](https://github.com/mohayonao/synthdef-decoder) 51 | - decode SuperCollider Synth Definition File Format and convert to JSON 52 | 53 | ## License 54 | 55 | MIT 56 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "scsynth", 3 | "description": "sound processing like SuperCollider in JavaScript", 4 | "version": "0.0.23", 5 | "author": "Nao Yonamine ", 6 | "bugs": { 7 | "url": "https://github.com/mohayonao/scsynth/issues" 8 | }, 9 | "dependencies": { 10 | "nmap": "^0.9.0", 11 | "shuffle-array": "^1.0.0" 12 | }, 13 | "devDependencies": { 14 | "babel-cli": "^6.11.4", 15 | "babel-plugin-unassert": "^2.1.1", 16 | "babel-preset-es2015": "^6.9.0", 17 | "babel-preset-power-assert": "^1.0.0", 18 | "eater": "^3.0.0-5", 19 | "eatest": "^0.4.0", 20 | "eslint": "^3.2.2", 21 | "eslint-plugin-node": "^2.0.0", 22 | "npm-run-all": "^2.3.0", 23 | "nyc": "^7.1.0", 24 | "power-assert": "^1.4.1", 25 | "sc-random": "^1.0.0", 26 | "sinon": "^1.17.5" 27 | }, 28 | "engines": { 29 | "node": ">= 4.0.0" 30 | }, 31 | "files": [ 32 | "package.json", 33 | "README.md", 34 | "src", 35 | "lib" 36 | ], 37 | "homepage": "https://github.com/mohayonao/scsynth/", 38 | "keywords": [ 39 | "dsp", 40 | "sound", 41 | "supercollider", 42 | "synthdef" 43 | ], 44 | "license": "MIT", 45 | "main": "lib/index.js", 46 | "repository": { 47 | "type": "git", 48 | "url": "https://github.com/mohayonao/scsynth.git" 49 | }, 50 | "scripts": { 51 | "build": "npm-run-all build:*", 52 | "build:to5": "BABEL_ENV=production babel --out-dir=lib src", 53 | "clean": "rm -rf lib coverage .nyc_output npm-debug.log", 54 | "cover": "nyc --reporter text --reporter html eater", 55 | "eater": "eater", 56 | "lint": "eslint src test", 57 | "postversion": "git push && git push --tags && npm run clean", 58 | "prepublish": "npm-run-all clean lint eater build", 59 | "preversion": "npm-run-all clean lint eater", 60 | "test": "eater --require babel-register", 61 | "travis": "npm-run-all lint eater" 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/Constants.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports.RATE_SCALAR = 0; 4 | module.exports.RATE_CONTROL = 1; 5 | module.exports.RATE_AUDIO = 2; 6 | module.exports.RATE_DEMAND = 3; 7 | 8 | module.exports.UI_KEY_STATE = 0; 9 | module.exports.UI_MOUSE_BUTTON = 1; 10 | module.exports.UI_MOUSE_X = 2; 11 | module.exports.UI_MOUSE_Y = 3; 12 | -------------------------------------------------------------------------------- /src/DefaultConfig.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports = { 4 | sampleRate: 44100, 5 | blockSize: 64, 6 | numberOfChannels: 2, 7 | numberOfAudioBus: 16, 8 | numberOfControlBus: 128 9 | }; 10 | -------------------------------------------------------------------------------- /src/SCRate.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | class SCRate { 4 | constructor(sampleRate, bufferLength) { 5 | this.sampleRate = sampleRate; 6 | this.sampleDur = 1 / sampleRate; 7 | this.radiansPerSample = (Math.PI * 2) / sampleRate; 8 | this.bufferLength = bufferLength; 9 | this.bufferDuration = bufferLength / sampleRate; 10 | this.bufferRate = 1 / this.bufferDuration; 11 | this.slopeFactor = 1 / bufferLength; 12 | this.filterLoops = (bufferLength / 3)|0; 13 | this.filterRemain = (bufferLength % 3)|0; 14 | if (this.filterLoops === 0) { 15 | this.filterSlope = 0; 16 | } else { 17 | this.filterSlope = 1 / this.filterLoops; 18 | } 19 | } 20 | } 21 | 22 | module.exports = SCRate; 23 | -------------------------------------------------------------------------------- /src/SCUnit.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | class SCUnit { 4 | constructor(synth, unitSpec) { 5 | this.context = synth.context; 6 | this.synth = synth; 7 | this.name = unitSpec[0]; 8 | this.calcRate = unitSpec[1]; 9 | this.specialIndex = unitSpec[2]; 10 | this.inputs = new Array(unitSpec[3].length); 11 | this.outputs = new Array(unitSpec[4].length); 12 | this.inputSpecs = unitSpec[3].map(() => ({ rate: 0, unit: null })); 13 | this.outputSpecs = unitSpec[4].map(() => ({ rate: 0 })); 14 | this.bufferLength = 0; 15 | this.dspProcess = null; 16 | this.done = false; 17 | } 18 | 19 | initialize() {} 20 | 21 | doneAction(action) { 22 | this.synth.doneAction(action); 23 | } 24 | } 25 | 26 | module.exports = SCUnit; 27 | -------------------------------------------------------------------------------- /src/SCUnitRepository.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const db = {}; 4 | 5 | class SCUnitRepository { 6 | static createSCUnit(synth, unitSpec) { 7 | const name = unitSpec[0]; 8 | 9 | if (!db.hasOwnProperty(name)) { 10 | throw new TypeError(`SCUnit is not defined: ${ name }`); 11 | } 12 | 13 | return new (db[name])(synth, unitSpec); 14 | } 15 | 16 | static registerSCUnitClass(name, SCUnitClass) { 17 | db[name] = SCUnitClass; 18 | } 19 | 20 | static unregisterSCUnitClass(name) { 21 | delete db[name]; 22 | } 23 | } 24 | 25 | module.exports = SCUnitRepository; 26 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const Constants = require("./Constants"); 4 | const SCContext = require("./SCContext"); 5 | const SCGraphNode = require("./SCGraphNode"); 6 | const SCSynth = require("./SCSynth"); 7 | const SCUnit = require("./SCUnit"); 8 | const SCUnitRepository = require("./SCUnitRepository"); 9 | const unit = require("./unit"); 10 | 11 | module.exports = { Constants, SCContext, SCGraphNode, SCSynth, SCUnit, SCUnitRepository, unit }; 12 | -------------------------------------------------------------------------------- /src/unit/SCUnitA2K.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const SCUnit = require("../SCUnit"); 4 | const SCUnitRepository = require("../SCUnitRepository"); 5 | const dspProcess = {}; 6 | 7 | class SCUnitA2K extends SCUnit { 8 | initialize() { 9 | this.dspProcess = dspProcess["a"]; 10 | } 11 | } 12 | 13 | dspProcess["a"] = function() { 14 | this.outputs[0][0] = this.inputs[0][0]; 15 | }; 16 | 17 | SCUnitRepository.registerSCUnitClass("A2K", SCUnitA2K); 18 | 19 | module.exports = SCUnitA2K; 20 | -------------------------------------------------------------------------------- /src/unit/SCUnitAmpComp.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const C = require("../Constants"); 5 | const SCUnit = require("../SCUnit"); 6 | const SCUnitRepository = require("../SCUnitRepository"); 7 | const dspProcess = {}; 8 | 9 | class SCUnitAmpComp extends SCUnit { 10 | initialize() { 11 | assert(this.inputs.length === 3); 12 | assert(this.calcRate !== C.RATE_AUDIO || this.inputSpecs[0].rate === C.RATE_AUDIO); 13 | 14 | if (this.inputSpecs[1].rate === C.RATE_SCALAR && this.inputSpecs[2].rate === C.RATE_SCALAR) { 15 | this.dspProcess = dspProcess["aii"]; 16 | 17 | const exp = this.inputs[2][0]; 18 | 19 | this._rootmul = Math.pow(this.inputs[1][0], exp) || 0; 20 | this._exponent = -1 * exp; 21 | } else { 22 | this.dspProcess = dspProcess["akk"]; 23 | } 24 | 25 | this.dspProcess(1); 26 | } 27 | } 28 | 29 | dspProcess["akk"] = function(inNumSamples) { 30 | const out = this.outputs[0]; 31 | const freqIn = this.inputs[0]; 32 | const root = this.inputs[1][0]; 33 | const xb = this.inputs[2][0]; 34 | 35 | for (let i = 0; i < inNumSamples; i++) { 36 | const xa = (root / freqIn[i]); 37 | 38 | out[i] = xa >= 0 ? Math.pow(xa, xb) : -Math.pow(-xa, xb); 39 | } 40 | }; 41 | 42 | dspProcess["aii"] = function(inNumSamples) { 43 | const out = this.outputs[0]; 44 | const freqIn = this.inputs[0]; 45 | const rootmul = this._rootmul; 46 | const xb = this._exponent; 47 | 48 | for (let i = 0; i < inNumSamples; i++) { 49 | const xa = freqIn[i]; 50 | 51 | out[i] = (xa >= 0 ? Math.pow(xa, xb) : -Math.pow(-xa, xb)) * rootmul; 52 | } 53 | }; 54 | 55 | SCUnitRepository.registerSCUnitClass("AmpComp", SCUnitAmpComp); 56 | 57 | module.exports = SCUnitAmpComp; 58 | -------------------------------------------------------------------------------- /src/unit/SCUnitAmpCompA.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const C = require("../Constants"); 5 | const SCUnit = require("../SCUnit"); 6 | const SCUnitRepository = require("../SCUnitRepository"); 7 | const dspProcess = {}; 8 | 9 | const AMPCOMP_K = 3.5041384 * 10e15; 10 | const AMPCOMP_C1 = 20.598997 * 20.598997; 11 | const AMPCOMP_C2 = 107.65265 * 107.65265; 12 | const AMPCOMP_C3 = 737.86223 * 737.86223; 13 | const AMPCOMP_C4 = 12194.217 * 12194.217; 14 | const AMPCOMP_MINLEVEL = -0.1575371167435; 15 | 16 | class SCUnitAmpCompA extends SCUnit { 17 | initialize() { 18 | assert(this.inputs.length === 4); 19 | assert(this.calcRate !== C.RATE_AUDIO || this.inputSpecs[0].rate === C.RATE_AUDIO); 20 | 21 | this.dspProcess = dspProcess["aiii"]; 22 | 23 | const rootFreq = this.inputs[1][0]; 24 | const rootLevel = calcLevel(rootFreq); 25 | const minLevel = this.inputs[2][0]; 26 | 27 | this._scale = (this.inputs[3][0] - minLevel) / (rootLevel - AMPCOMP_MINLEVEL); 28 | this._offset = minLevel - this._scale * AMPCOMP_MINLEVEL; 29 | 30 | this.dspProcess(1); 31 | } 32 | } 33 | 34 | function calcLevel(freq) { 35 | const r = freq * freq; 36 | const n1 = AMPCOMP_C1 + r; 37 | const n2 = AMPCOMP_C4 + r; 38 | 39 | let level = (AMPCOMP_K * r * r * r * r); 40 | 41 | level = level / (n1 * n1 * (AMPCOMP_C2 + r) * (AMPCOMP_C3 + r) * n2 * n2); 42 | level = 1 - Math.sqrt(level); 43 | 44 | return level; 45 | } 46 | 47 | dspProcess["aiii"] = function(inNumSamples) { 48 | const out = this.outputs[0]; 49 | const freqIn = this.inputs[0]; 50 | const scale = this._scale; 51 | const offset = this._offset; 52 | 53 | for (let i = 0; i < inNumSamples; i++) { 54 | out[i] = calcLevel(freqIn[i]) * scale + offset; 55 | } 56 | }; 57 | 58 | SCUnitRepository.registerSCUnitClass("AmpCompA", SCUnitAmpCompA); 59 | 60 | module.exports = SCUnitAmpCompA; 61 | -------------------------------------------------------------------------------- /src/unit/SCUnitBPZ2.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const SCUnit = require("../SCUnit"); 3 | const SCUnitRepository = require("../SCUnitRepository"); 4 | const dspProcess = {}; 5 | class SCUnitBPZ2 extends SCUnit { 6 | initialize() { 7 | this.dspProcess = dspProcess["next"]; 8 | this._x1 = this.inputs[0][0]; 9 | this._x2 = this.inputs[0][0]; 10 | this.dspProcess(1); 11 | } 12 | } 13 | dspProcess["next"] = function (inNumSamples) { 14 | const out = this.outputs[0]; 15 | const inIn = this.inputs[0]; 16 | let x1 = this._x1; 17 | let x2 = this._x2; 18 | for (let i = 0; i < inNumSamples; i++) { 19 | const x0 = inIn[i]; 20 | out[i] = (x0 - x2) * 0.25; 21 | x2 = x1; 22 | x1 = x0; 23 | } 24 | this._x1 = x1; 25 | this._x2 = x2; 26 | }; 27 | SCUnitRepository.registerSCUnitClass("BPZ2", SCUnitBPZ2); 28 | module.exports = SCUnitBPZ2; 29 | -------------------------------------------------------------------------------- /src/unit/SCUnitBRZ2.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const SCUnit = require("../SCUnit"); 3 | const SCUnitRepository = require("../SCUnitRepository"); 4 | const dspProcess = {}; 5 | class SCUnitBRZ2 extends SCUnit { 6 | initialize() { 7 | this.dspProcess = dspProcess["next"]; 8 | this._x1 = this.inputs[0][0]; 9 | this._x2 = this.inputs[0][0]; 10 | this.dspProcess(1); 11 | } 12 | } 13 | dspProcess["next"] = function (inNumSamples) { 14 | const out = this.outputs[0]; 15 | const inIn = this.inputs[0]; 16 | let x1 = this._x1; 17 | let x2 = this._x2; 18 | for (let i = 0; i < inNumSamples; i++) { 19 | const x0 = inIn[i]; 20 | out[i] = (x0 + x2) * 0.25; 21 | x2 = x1; 22 | x1 = x0; 23 | } 24 | this._x1 = x1; 25 | this._x2 = x2; 26 | }; 27 | SCUnitRepository.registerSCUnitClass("BRZ2", SCUnitBRZ2); 28 | module.exports = SCUnitBRZ2; 29 | -------------------------------------------------------------------------------- /src/unit/SCUnitBrownNoise.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const SCUnit = require("../SCUnit"); 4 | const SCUnitRepository = require("../SCUnitRepository"); 5 | const dspProcess = {}; 6 | 7 | class SCUnitBrownNoise extends SCUnit { 8 | initialize() { 9 | this.dspProcess = dspProcess["next"]; 10 | 11 | this._level = Math.random() * 2 - 1; 12 | 13 | this.outputs[0][0] = this._level; 14 | } 15 | } 16 | 17 | dspProcess["next"] = function(inNumSamples) { 18 | const out = this.outputs[0]; 19 | 20 | let level = this._level; 21 | 22 | for (let i = 0; i < inNumSamples; i++) { 23 | level += Math.random() * 0.25 - 0.125; 24 | if (1 < level) { 25 | level = 2 - level; 26 | } else if (level < -1) { 27 | level = -2 - level; 28 | } 29 | out[i] = level; 30 | } 31 | 32 | this._level = level; 33 | }; 34 | 35 | SCUnitRepository.registerSCUnitClass("BrownNoise", SCUnitBrownNoise); 36 | 37 | module.exports = SCUnitBrownNoise; 38 | -------------------------------------------------------------------------------- /src/unit/SCUnitClip.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const C = require("../Constants"); 3 | const SCUnit = require("../SCUnit"); 4 | const SCUnitRepository = require("../SCUnitRepository"); 5 | const dspProcess = {}; 6 | class SCUnitClip extends SCUnit { 7 | initialize(rate) { 8 | if (this.inputSpecs[1].rate === C.RATE_AUDIO && this.inputSpecs[2].rate === C.RATE_AUDIO) { 9 | this.dspProcess = dspProcess["next_aa"]; 10 | } else { 11 | this.dspProcess = dspProcess["next_kk"]; 12 | } 13 | this._slopeFactor = rate.slopeFactor; 14 | this._lo = this.inputs[1][0]; 15 | this._hi = this.inputs[2][0]; 16 | this.dspProcess(1); 17 | } 18 | } 19 | dspProcess["next_aa"] = function (inNumSamples) { 20 | const out = this.outputs[0]; 21 | const inIn = this.inputs[0]; 22 | const loIn = this.inputs[1]; 23 | const hiIn = this.inputs[2]; 24 | for (let i = 0; i < inNumSamples; i++) { 25 | out[i] = Math.max(loIn[i], Math.min(inIn[i], hiIn[i])); 26 | } 27 | }; 28 | dspProcess["next_kk"] = function (inNumSamples) { 29 | const out = this.outputs[0]; 30 | const inIn = this.inputs[0]; 31 | const next_lo = this.inputs[1][0]; 32 | const next_hi = this.inputs[2][0]; 33 | const lo = this._lo; 34 | const hi = this._hi; 35 | if (next_lo === lo && next_hi === hi) { 36 | for (let i = 0; i < inNumSamples; i++) { 37 | out[i] = Math.max(lo, Math.min(inIn[i], hi)); 38 | } 39 | } else { 40 | const lo_slope = (next_lo - lo) * this._slopeFactor; 41 | const hi_slope = (next_hi - hi) * this._slopeFactor; 42 | for (let i = 0; i < inNumSamples; i++) { 43 | out[i] = Math.max(lo + lo_slope * i, Math.min(inIn[i], hi + hi_slope * i)); 44 | } 45 | this._lo = next_lo; 46 | this._hi = next_hi; 47 | } 48 | }; 49 | SCUnitRepository.registerSCUnitClass("Clip", SCUnitClip); 50 | module.exports = SCUnitClip; 51 | -------------------------------------------------------------------------------- /src/unit/SCUnitClipNoise.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const SCUnit = require("../SCUnit"); 4 | const SCUnitRepository = require("../SCUnitRepository"); 5 | const dspProcess = {}; 6 | 7 | class SCUnitClipNoise extends SCUnit { 8 | initialize() { 9 | this.dspProcess = dspProcess["next"]; 10 | this.dspProcess(1); 11 | } 12 | } 13 | 14 | dspProcess["next"] = function(inNumSamples) { 15 | const out = this.outputs[0]; 16 | 17 | for (let i = 0; i < inNumSamples; i++) { 18 | out[i] = Math.random() < 0.5 ? -1 : +1; 19 | } 20 | }; 21 | 22 | SCUnitRepository.registerSCUnitClass("ClipNoise", SCUnitClipNoise); 23 | 24 | module.exports = SCUnitClipNoise; 25 | -------------------------------------------------------------------------------- /src/unit/SCUnitCoinGate.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const C = require("../Constants"); 4 | const SCUnit = require("../SCUnit"); 5 | const SCUnitRepository = require("../SCUnitRepository"); 6 | const dspProcess = {}; 7 | 8 | class SCUnitCoinGate extends SCUnit { 9 | initialize() { 10 | if (this.inputSpecs[1].rate === C.RATE_AUDIO) { 11 | this.dspProcess = dspProcess["ka"]; 12 | } else { 13 | this.dspProcess = dspProcess["kk"]; 14 | } 15 | 16 | this._trig = this.inputs[1][0]; 17 | } 18 | } 19 | 20 | dspProcess["ka"] = function(inNumSamples) { 21 | const out = this.outputs[0]; 22 | const trigIn = this.inputs[1]; 23 | const prob = this.inputs[0][0]; 24 | 25 | let trig = this._trig; 26 | 27 | for (let i = 0; i < inNumSamples; i++) { 28 | const trig_next = trigIn[i]; 29 | 30 | let value = 0; 31 | 32 | if (trig <= 0 && 0 < trig_next) { 33 | if (Math.random() < prob) { 34 | value = trig_next; 35 | } 36 | } 37 | 38 | out[i] = value; 39 | trig = trig_next; 40 | } 41 | 42 | this._trig = trig; 43 | }; 44 | 45 | dspProcess["kk"] = function(inNumSamples) { 46 | const out = this.outputs[0]; 47 | const trig_next = this.inputs[1][0]; 48 | const trig = this._trig; 49 | 50 | let value = 0; 51 | 52 | if (trig <= 0 && 0 < trig_next) { 53 | if (Math.random() < this.inputs[0][0]) { 54 | value = trig_next; 55 | } 56 | } 57 | 58 | out[0] = value; 59 | 60 | for (let i = 1; i < inNumSamples; i++) { 61 | out[i] = 0; 62 | } 63 | 64 | this._trig = trig_next; 65 | }; 66 | 67 | SCUnitRepository.registerSCUnitClass("CoinGate", SCUnitCoinGate); 68 | 69 | module.exports = SCUnitCoinGate; 70 | -------------------------------------------------------------------------------- /src/unit/SCUnitControl.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const SCUnit = require("../SCUnit"); 3 | const SCUnitRepository = require("../SCUnitRepository"); 4 | const dspProcess = {}; 5 | class SCUnitControl extends SCUnit { 6 | initialize() { 7 | if (this.outputs.length === 1) { 8 | this.dspProcess = dspProcess["1"]; 9 | } else { 10 | this.dspProcess = dspProcess["k"]; 11 | } 12 | this._controls = this.synth.params; 13 | this.dspProcess(1); 14 | } 15 | } 16 | dspProcess["1"] = function () { 17 | this.outputs[0][0] = this._controls[this.specialIndex]; 18 | }; 19 | dspProcess["k"] = function () { 20 | const controls = this._controls; 21 | const outputs = this.outputs; 22 | const numerOfOutputs = outputs.length; 23 | const specialIndex = this.specialIndex; 24 | for (let i = 0; i < numerOfOutputs; i++) { 25 | outputs[i][0] = controls[specialIndex + i]; 26 | } 27 | }; 28 | SCUnitRepository.registerSCUnitClass("Control", SCUnitControl); 29 | module.exports = SCUnitControl; 30 | -------------------------------------------------------------------------------- /src/unit/SCUnitControlDur.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const SCUnit = require("../SCUnit"); 3 | const SCUnitRepository = require("../SCUnitRepository"); 4 | class SCUnitControlDur extends SCUnit { 5 | initialize() { 6 | this.outputs[0][0] = this.context.kRate.sampleDur; 7 | } 8 | } 9 | SCUnitRepository.registerSCUnitClass("ControlDur", SCUnitControlDur); 10 | module.exports = SCUnitControlDur; 11 | -------------------------------------------------------------------------------- /src/unit/SCUnitControlRate.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const SCUnit = require("../SCUnit"); 3 | const SCUnitRepository = require("../SCUnitRepository"); 4 | class SCUnitControlRate extends SCUnit { 5 | initialize() { 6 | this.outputs[0][0] = this.context.kRate.sampleRate; 7 | } 8 | } 9 | SCUnitRepository.registerSCUnitClass("ControlRate", SCUnitControlRate); 10 | module.exports = SCUnitControlRate; 11 | -------------------------------------------------------------------------------- /src/unit/SCUnitCrackle.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const SCUnit = require("../SCUnit"); 4 | const SCUnitRepository = require("../SCUnitRepository"); 5 | const dspProcess = {}; 6 | 7 | class SCUnitCrackle extends SCUnit { 8 | initialize() { 9 | this.dspProcess = dspProcess["k"]; 10 | this._y1 = Math.random(); 11 | this._y2 = 0; 12 | this.dspProcess(1); 13 | } 14 | } 15 | 16 | dspProcess["k"] = function(inNumSamples) { 17 | const out = this.outputs[0]; 18 | const paramf = this.inputs[0][0]; 19 | 20 | let y1 = this._y1; 21 | let y2 = this._y2; 22 | 23 | for (let i = 0; i < inNumSamples; i++) { 24 | const y0 = Math.abs(y1 * paramf - y2 - 0.05); 25 | 26 | out[i] = y0; 27 | y2 = y1; 28 | y1 = y0; 29 | } 30 | 31 | this._y1 = y1; 32 | this._y2 = y2; 33 | }; 34 | 35 | SCUnitRepository.registerSCUnitClass("Crackle", SCUnitCrackle); 36 | 37 | module.exports = SCUnitCrackle; 38 | -------------------------------------------------------------------------------- /src/unit/SCUnitDC.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const SCUnit = require("../SCUnit"); 4 | const SCUnitRepository = require("../SCUnitRepository"); 5 | const fill = require("../util/fill"); 6 | 7 | class SCUnitDC extends SCUnit { 8 | initialize() { 9 | fill(this.outputs[0], this.inputs[0][0]); 10 | } 11 | } 12 | 13 | SCUnitRepository.registerSCUnitClass("DC", SCUnitDC); 14 | 15 | module.exports = SCUnitDC; 16 | -------------------------------------------------------------------------------- /src/unit/SCUnitDecay.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const SCUnit = require("../SCUnit"); 3 | const SCUnitRepository = require("../SCUnitRepository"); 4 | const dspProcess = {}; 5 | const log001 = Math.log(0.001); 6 | class SCUnitDecay extends SCUnit { 7 | initialize(rate) { 8 | this.dspProcess = dspProcess["next"]; 9 | this._sampleRate = rate.sampleRate; 10 | this._slopeFactor = rate.slopeFactor; 11 | this._decayTime = NaN; 12 | this._b1 = 0; 13 | this._y1 = 0; 14 | this.dspProcess(1); 15 | } 16 | } 17 | dspProcess["next"] = function (inNumSamples) { 18 | const out = this.outputs[0]; 19 | const inIn = this.inputs[0]; 20 | const decayTime = this.inputs[1][0]; 21 | let b1 = this._b1; 22 | let y1 = this._y1; 23 | if (decayTime === this._decayTime) { 24 | for (let i = 0; i < inNumSamples; i++) { 25 | out[i] = y1 = inIn[i] + b1 * y1; 26 | } 27 | } else { 28 | const next_b1 = decayTime !== 0 ? Math.exp(log001 / (decayTime * this._sampleRate)) : 0; 29 | const b1_slope = (next_b1 - b1) * this._slopeFactor; 30 | for (let i = 0; i < inNumSamples; i++) { 31 | out[i] = y1 = inIn[i] + (b1 + b1_slope * i) * y1; 32 | } 33 | this._b1 = next_b1; 34 | this._decayTime = decayTime; 35 | } 36 | this._y1 = y1; 37 | }; 38 | SCUnitRepository.registerSCUnitClass("Decay", SCUnitDecay); 39 | module.exports = SCUnitDecay; 40 | -------------------------------------------------------------------------------- /src/unit/SCUnitDelay1.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const SCUnit = require("../SCUnit"); 4 | const SCUnitRepository = require("../SCUnitRepository"); 5 | const dspProcess = {}; 6 | 7 | class SCUnitDelay1 extends SCUnit { 8 | initialize() { 9 | if (this.bufferLength === 1) { 10 | this.dspProcess = dspProcess["next_1"]; 11 | } else { 12 | this.dspProcess = dspProcess["next"]; 13 | } 14 | this._x1 = 0; 15 | 16 | this.dspProcess(1); 17 | } 18 | } 19 | 20 | dspProcess["next"] = function(inNumSamples) { 21 | const out = this.outputs[0]; 22 | const inIn = this.inputs[0]; 23 | 24 | let x1 = this._x1; 25 | 26 | for (let i = 0; i < inNumSamples; i++) { 27 | out[i] = x1; 28 | x1 = inIn[i]; 29 | } 30 | 31 | this._x1 = x1; 32 | }; 33 | 34 | dspProcess["next_1"] = function () { 35 | this.outputs[0][0] = this._x1; 36 | this._x1 = this.inputs[0][0]; 37 | }; 38 | 39 | SCUnitRepository.registerSCUnitClass("Delay1", SCUnitDelay1); 40 | 41 | module.exports = SCUnitDelay1; 42 | -------------------------------------------------------------------------------- /src/unit/SCUnitDelay2.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const SCUnit = require("../SCUnit"); 4 | const SCUnitRepository = require("../SCUnitRepository"); 5 | const dspProcess = {}; 6 | 7 | class SCUnitDelay2 extends SCUnit { 8 | initialize() { 9 | if (this.bufferLength === 1) { 10 | this.dspProcess = dspProcess["next_1"]; 11 | } else { 12 | this.dspProcess = dspProcess["next"]; 13 | } 14 | 15 | this._x1 = 0; 16 | this._x2 = 0; 17 | 18 | this.dspProcess(1); 19 | } 20 | } 21 | 22 | 23 | dspProcess["next"] = function(inNumSamples) { 24 | const out = this.outputs[0]; 25 | const inIn = this.inputs[0]; 26 | 27 | let x1 = this._x1; 28 | let x2 = this._x2; 29 | 30 | for (let i = 0; i < inNumSamples; i++) { 31 | out[i] = x1; 32 | x1 = x2; 33 | x2 = inIn[i]; 34 | } 35 | 36 | this._x1 = x1; 37 | this._x2 = x2; 38 | }; 39 | 40 | dspProcess["next_1"] = function() { 41 | this.outputs[0][0] = this._x1; 42 | this._x1 = this._x2; 43 | this._x2 = this.inputs[0][0]; 44 | }; 45 | 46 | SCUnitRepository.registerSCUnitClass("Delay2", SCUnitDelay2); 47 | 48 | module.exports = SCUnitDelay2; 49 | -------------------------------------------------------------------------------- /src/unit/SCUnitDetectSilence.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const SCUnit = require("../SCUnit"); 3 | const SCUnitRepository = require("../SCUnitRepository"); 4 | const dspProcess = {}; 5 | class SCUnitDetectSilence extends SCUnit { 6 | initialize(rate) { 7 | this.dspProcess = dspProcess["next"]; 8 | this._thresh = this.inputs[1][0]; 9 | this._endCounter = rate.sampleRate * this.inputs[2][0] | 0; 10 | this._counter = -1; 11 | } 12 | } 13 | dspProcess["next"] = function (inNumSamples) { 14 | const out = this.outputs[0]; 15 | const inIn = this.inputs[0]; 16 | const thresh = this._thresh; 17 | let counter = this._counter; 18 | for (let i = 0; i < inNumSamples; i++) { 19 | const val = Math.abs(inIn[i]); 20 | if (val > thresh) { 21 | counter = 0; 22 | out[i] = 0; 23 | } else if (counter >= 0) { 24 | counter += 1; 25 | if (counter >= this._endCounter) { 26 | this.doneAction(this.inputs[3][0] | 0); 27 | out[i] = 1; 28 | } else { 29 | out[i] = 0; 30 | } 31 | } else { 32 | out[i] = 0; 33 | } 34 | } 35 | this._counter = counter; 36 | }; 37 | SCUnitRepository.registerSCUnitClass("DetectSilence", SCUnitDetectSilence); 38 | module.exports = SCUnitDetectSilence; 39 | -------------------------------------------------------------------------------- /src/unit/SCUnitDgeom.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const C = require("../Constants"); 5 | const SCUnit = require("../SCUnit"); 6 | const SCUnitRepository = require("../SCUnitRepository"); 7 | const demand = require("./_demand"); 8 | const dspProcess = {}; 9 | 10 | class SCUnitDgeom extends SCUnit { 11 | initialize() { 12 | assert( 13 | this.calcRate === C.RATE_DEMAND && this.inputs.length === 3 14 | ); 15 | 16 | this.dspProcess = dspProcess["d"]; 17 | 18 | this._grow = 1; 19 | this._value = 0; 20 | 21 | this.reset(); 22 | } 23 | 24 | reset() { 25 | this._repeats = -1; 26 | this._repeatCount = 0; 27 | } 28 | } 29 | 30 | dspProcess["d"] = function(inNumSamples) { 31 | if (inNumSamples === 0) { 32 | return this.reset(); 33 | } 34 | 35 | const out = this.outputs[0]; 36 | const grow = demand.next(this, 2, inNumSamples); 37 | 38 | if (!Number.isNaN(grow)) { 39 | this._grow = grow; 40 | } 41 | if (this._repeats < 0) { 42 | const x = demand.next(this, 0, inNumSamples); 43 | 44 | this._repeats = Math.floor(x); 45 | this._value = demand.next(this, 1, inNumSamples); 46 | } 47 | 48 | if (this._repeats <= this._repeatCount) { 49 | out[0] = NaN; 50 | return; 51 | } 52 | 53 | out[0] = this._value; 54 | this._value *= this._grow; 55 | this._repeatCount += 1; 56 | }; 57 | 58 | SCUnitRepository.registerSCUnitClass("Dgeom", SCUnitDgeom); 59 | 60 | module.exports = SCUnitDgeom; 61 | -------------------------------------------------------------------------------- /src/unit/SCUnitDiwhite.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const C = require("../Constants"); 5 | const SCUnit = require("../SCUnit"); 6 | const SCUnitRepository = require("../SCUnitRepository"); 7 | const demand = require("./_demand"); 8 | const dspProcess = {}; 9 | 10 | class SCUnitDiwhite extends SCUnit { 11 | initialize() { 12 | assert( 13 | this.calcRate === C.RATE_DEMAND && this.inputs.length === 3 14 | ); 15 | 16 | this.dspProcess = dspProcess["d"]; 17 | 18 | this._lo = 0; 19 | this._range = 0; 20 | 21 | this.reset(); 22 | } 23 | 24 | reset() { 25 | this._repeats = -1; 26 | this._repeatCount = 0; 27 | } 28 | } 29 | 30 | dspProcess["d"] = function(inNumSamples) { 31 | if (inNumSamples === 0) { 32 | return this.reset(); 33 | } 34 | 35 | if (this._repeats < 0) { 36 | const x = demand.next(this, 0, inNumSamples); 37 | 38 | this._repeats = Number.isNaN(x) ? 0 : Math.max(0, Math.floor(x + 0.5)); 39 | } 40 | 41 | const out = this.outputs[0]; 42 | 43 | if (this._repeats <= this._repeatCount) { 44 | out[0] = NaN; 45 | return; 46 | } 47 | 48 | this._repeatCount += 1; 49 | 50 | const lo = demand.next(this, 1, inNumSamples); 51 | const hi = demand.next(this, 2, inNumSamples); 52 | 53 | if (!Number.isNaN(lo)) { 54 | this._lo = lo; 55 | } 56 | if (!Number.isNaN(hi)) { 57 | this._range = hi - this._lo + 1; 58 | } 59 | 60 | out[0] = Math.floor(Math.random() * this._range + this._lo); 61 | }; 62 | 63 | SCUnitRepository.registerSCUnitClass("Diwhite", SCUnitDiwhite); 64 | 65 | module.exports = SCUnitDiwhite; 66 | -------------------------------------------------------------------------------- /src/unit/SCUnitDrand.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const C = require("../Constants"); 5 | const SCUnit = require("../SCUnit"); 6 | const SCUnitRepository = require("../SCUnitRepository"); 7 | const demand = require("./_demand"); 8 | const dspProcess = {}; 9 | 10 | class SCUnitDrand extends SCUnit { 11 | initialize() { 12 | assert( 13 | this.calcRate === C.RATE_DEMAND && 2 <= this.inputs.length 14 | ); 15 | 16 | this.dspProcess = dspProcess["d"]; 17 | this.reset(); 18 | } 19 | 20 | reset() { 21 | this._repeats = -1; 22 | this._repeatCount = 0; 23 | this._needToResetChild = true; 24 | } 25 | } 26 | 27 | dspProcess["d"] = function(inNumSamples) { 28 | if (inNumSamples === 0) { 29 | return this.reset(); 30 | } 31 | 32 | if (this._repeats < 0) { 33 | const x = demand.next(this, 0, inNumSamples); 34 | 35 | this._repeats = Number.isNaN(x) ? 0 : Math.max(0, Math.floor(x + 0.5)); 36 | } 37 | 38 | const out = this.outputs[0]; 39 | 40 | for (;;) { 41 | if (this._repeats <= this._repeatCount) { 42 | out[0] = NaN; 43 | return; 44 | } 45 | 46 | const index = Math.floor(Math.random() * (this.inputs.length - 1)) + 1; 47 | 48 | if (!demand.isDemand(this, index)) { 49 | out[0] = demand.next(this, index, inNumSamples); 50 | this._repeatCount += 1; 51 | this._needToResetChild = true; 52 | return; 53 | } 54 | 55 | if (this._needToResetChild) { 56 | this._needToResetChild = false; 57 | demand.reset(this, index); 58 | } 59 | 60 | const x = demand.next(this, index, inNumSamples); 61 | 62 | if (Number.isNaN(x)) { 63 | this._repeatCount += 1; 64 | this._needToResetChild = true; 65 | } else { 66 | out[0] = x; 67 | return; 68 | } 69 | } 70 | }; 71 | 72 | SCUnitRepository.registerSCUnitClass("Drand", SCUnitDrand); 73 | 74 | module.exports = SCUnitDrand; 75 | -------------------------------------------------------------------------------- /src/unit/SCUnitDreset.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const C = require("../Constants"); 5 | const SCUnit = require("../SCUnit"); 6 | const SCUnitRepository = require("../SCUnitRepository"); 7 | const demand = require("./_demand"); 8 | const dspProcess = {}; 9 | 10 | class SCUnitDreset extends SCUnit { 11 | initialize() { 12 | assert( 13 | this.calcRate === C.RATE_DEMAND && this.inputs.length === 2 14 | ); 15 | 16 | this._prev_reset = 0; 17 | 18 | this.dspProcess = dspProcess["d"]; 19 | } 20 | 21 | reset() { 22 | demand.reset(this, 0); 23 | } 24 | } 25 | 26 | dspProcess["d"] = function(inNumSamples) { 27 | if (inNumSamples === 0) { 28 | return this.reset(); 29 | } 30 | 31 | const out = this.outputs[0]; 32 | const x = demand.next(this, 0, inNumSamples); 33 | const reset = demand.next(this, 1, inNumSamples); 34 | 35 | if (Number.isNaN(x)) { 36 | out[0] = NaN; 37 | return; 38 | } 39 | 40 | if (0 < reset && this._prev_reset <= 0) { 41 | demand.reset(this, 0); 42 | } 43 | this._prev_reset = reset; 44 | 45 | out[0] = x; 46 | }; 47 | 48 | SCUnitRepository.registerSCUnitClass("Dreset", SCUnitDreset); 49 | 50 | module.exports = SCUnitDreset; 51 | -------------------------------------------------------------------------------- /src/unit/SCUnitDseries.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const C = require("../Constants"); 5 | const SCUnit = require("../SCUnit"); 6 | const SCUnitRepository = require("../SCUnitRepository"); 7 | const demand = require("./_demand"); 8 | const dspProcess = {}; 9 | 10 | class SCUnitDseries extends SCUnit { 11 | initialize() { 12 | assert( 13 | this.calcRate === C.RATE_DEMAND && this.inputs.length === 3 14 | ); 15 | 16 | this.dspProcess = dspProcess["d"]; 17 | 18 | this._step = 0; 19 | this._value = 0; 20 | 21 | this.reset(); 22 | } 23 | 24 | reset() { 25 | this._repeats = -1; 26 | this._repeatCount = 0; 27 | } 28 | } 29 | 30 | dspProcess["d"] = function(inNumSamples) { 31 | if (inNumSamples === 0) { 32 | return this.reset(); 33 | } 34 | 35 | const out = this.outputs[0]; 36 | const step = demand.next(this, 2, inNumSamples); 37 | 38 | if (!Number.isNaN(step)) { 39 | this._step = step; 40 | } 41 | if (this._repeats < 0) { 42 | const x = demand.next(this, 0, inNumSamples); 43 | 44 | this._repeats = Math.floor(x); 45 | this._value = demand.next(this, 1, inNumSamples); 46 | } 47 | 48 | if (this._repeats <= this._repeatCount) { 49 | out[0] = NaN; 50 | return; 51 | } 52 | 53 | out[0] = this._value; 54 | this._value += this._step; 55 | this._repeatCount += 1; 56 | }; 57 | 58 | SCUnitRepository.registerSCUnitClass("Dseries", SCUnitDseries); 59 | 60 | module.exports = SCUnitDseries; 61 | -------------------------------------------------------------------------------- /src/unit/SCUnitDstutter.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const C = require("../Constants"); 5 | const SCUnit = require("../SCUnit"); 6 | const SCUnitRepository = require("../SCUnitRepository"); 7 | const demand = require("./_demand"); 8 | const dspProcess = {}; 9 | 10 | class SCUnitDstutter extends SCUnit { 11 | initialize() { 12 | assert( 13 | this.calcRate === C.RATE_DEMAND && this.inputs.length === 2 14 | ); 15 | 16 | this.dspProcess = dspProcess["d"]; 17 | 18 | this.reset(); 19 | } 20 | 21 | reset() { 22 | this._repeats = -1; 23 | this._repeatCount = 0; 24 | demand.reset(this, 0); 25 | demand.reset(this, 1); 26 | } 27 | } 28 | 29 | dspProcess["d"] = function(inNumSamples) { 30 | if (inNumSamples === 0) { 31 | return this.reset(); 32 | } 33 | 34 | const out = this.outputs[0]; 35 | 36 | if (this._repeats <= this._repeatCount) { 37 | const value = demand.next(this, 1, inNumSamples); 38 | const repeats = demand.next(this, 0, inNumSamples); 39 | 40 | if (Number.isNaN(value) || Number.isNaN(repeats)) { 41 | out[0] = NaN; 42 | return; 43 | } 44 | 45 | this._value = value; 46 | this._repeats = Math.max(0, Math.floor(repeats + 0.5)); 47 | this._repeatCount = 0; 48 | } 49 | 50 | out[0] = this._value; 51 | this._repeatCount += 1; 52 | }; 53 | 54 | SCUnitRepository.registerSCUnitClass("Dstutter", SCUnitDstutter); 55 | 56 | module.exports = SCUnitDstutter; 57 | -------------------------------------------------------------------------------- /src/unit/SCUnitDswitch.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const C = require("../Constants"); 5 | const SCUnit = require("../SCUnit"); 6 | const SCUnitRepository = require("../SCUnitRepository"); 7 | const demand = require("./_demand"); 8 | const dspProcess = {}; 9 | 10 | class SCUnitDswitch extends SCUnit { 11 | initialize() { 12 | assert( 13 | this.calcRate === C.RATE_DEMAND && 2 <= this.inputs.length 14 | ); 15 | 16 | this._index = computeIndex(demand.next(this, 0, 1), this.inputs.length); 17 | 18 | this.dspProcess = dspProcess["d"]; 19 | } 20 | 21 | reset() { 22 | for (let i = 0, imax = this.inputs.length; i < imax; i++) { 23 | demand.reset(this, i); 24 | } 25 | this._index = computeIndex(demand.next(this, 0, 1), this.inputs.length); 26 | } 27 | } 28 | 29 | function computeIndex(index, length) { 30 | index = index = (index|0) % (length - 1); 31 | if (index < 0) { 32 | index += length - 1; 33 | } 34 | return index + 1; 35 | } 36 | 37 | dspProcess["d"] = function(inNumSamples) { 38 | if (inNumSamples === 0) { 39 | return this.reset(); 40 | } 41 | 42 | const out = this.outputs[0]; 43 | 44 | let val = demand.next(this, this._index, inNumSamples); 45 | 46 | if (Number.isNaN(val)) { 47 | const ival = demand.next(this, 0, inNumSamples); 48 | 49 | if (Number.isNaN(ival)) { 50 | val = NaN; 51 | } else { 52 | const index = computeIndex(ival, this.inputs.length); 53 | 54 | val = demand.next(this, index, inNumSamples); 55 | demand.reset(this, this._index); 56 | 57 | this._index = index; 58 | } 59 | } 60 | 61 | out[0] = val; 62 | }; 63 | 64 | SCUnitRepository.registerSCUnitClass("Dswitch", SCUnitDswitch); 65 | 66 | module.exports = SCUnitDswitch; 67 | -------------------------------------------------------------------------------- /src/unit/SCUnitDswitch1.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const C = require("../Constants"); 5 | const SCUnit = require("../SCUnit"); 6 | const SCUnitRepository = require("../SCUnitRepository"); 7 | const demand = require("./_demand"); 8 | const dspProcess = {}; 9 | 10 | class SCUnitDswitch1 extends SCUnit { 11 | initialize() { 12 | assert( 13 | this.calcRate === C.RATE_DEMAND && 2 <= this.inputs.length 14 | ); 15 | 16 | this.dspProcess = dspProcess["d"]; 17 | } 18 | 19 | reset() { 20 | for (let i = 0, imax = this.inputs.length; i < imax; i++) { 21 | demand.reset(this, i); 22 | } 23 | } 24 | } 25 | 26 | dspProcess["d"] = function(inNumSamples) { 27 | if (inNumSamples === 0) { 28 | return this.reset(); 29 | } 30 | 31 | const out = this.outputs[0]; 32 | const x = demand.next(this, 0); 33 | 34 | if (Number.isNaN(x)) { 35 | out[0] = NaN; 36 | return; 37 | } 38 | 39 | const index = (Math.floor(x + 0.5) % (this.inputs.length - 1)) + 1; 40 | 41 | out[0] = demand.next(this, index, inNumSamples); 42 | }; 43 | 44 | SCUnitRepository.registerSCUnitClass("Dswitch1", SCUnitDswitch1); 45 | 46 | module.exports = SCUnitDswitch1; 47 | -------------------------------------------------------------------------------- /src/unit/SCUnitDust.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const SCUnit = require("../SCUnit"); 4 | const SCUnitRepository = require("../SCUnitRepository"); 5 | const dspProcess = {}; 6 | 7 | class SCUnitDust extends SCUnit { 8 | initialize(rate) { 9 | this.dspProcess = dspProcess["k"]; 10 | 11 | this._sampleDur = rate.sampleDur; 12 | this._density = 0; 13 | this._scale = 0; 14 | this._thresh = 0; 15 | 16 | this.dspProcess(1); 17 | } 18 | } 19 | 20 | dspProcess["k"] = function(inNumSamples) { 21 | const out = this.outputs[0]; 22 | const density_next = this.inputs[0][0]; 23 | const density = this._density; 24 | 25 | if (density !== density_next) { 26 | this._thresh = density_next * this._sampleDur; 27 | this._scale = (0 < this._thresh) ? 1 / this._thresh : 0; 28 | this._density = density_next; 29 | } 30 | 31 | const thresh = this._thresh; 32 | const scale = this._scale; 33 | 34 | for (let i = 0; i < inNumSamples; i++) { 35 | const z = Math.random(); 36 | 37 | out[i] = z < thresh ? z * scale : 0; 38 | } 39 | }; 40 | 41 | SCUnitRepository.registerSCUnitClass("Dust", SCUnitDust); 42 | 43 | module.exports = SCUnitDust; 44 | -------------------------------------------------------------------------------- /src/unit/SCUnitDust2.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const SCUnit = require("../SCUnit"); 4 | const SCUnitRepository = require("../SCUnitRepository"); 5 | const dspProcess = {}; 6 | 7 | class SCUnitDust2 extends SCUnit { 8 | initialize(rate) { 9 | this.dspProcess = dspProcess["k"]; 10 | 11 | this._sampleDur = rate.sampleDur; 12 | this._density = 0; 13 | this._scale = 0; 14 | this._thresh = 0; 15 | 16 | this.dspProcess(1); 17 | } 18 | } 19 | 20 | dspProcess["k"] = function (inNumSamples) { 21 | const out = this.outputs[0]; 22 | const density_next = this.inputs[0][0]; 23 | const density = this._density; 24 | 25 | if (density !== density_next) { 26 | this._thresh = density_next * this._sampleDur; 27 | this._scale = (0 < this._thresh) ? 2 / this._thresh : 0; 28 | this._density = density_next; 29 | } 30 | 31 | const thresh = this._thresh; 32 | const scale = this._scale; 33 | 34 | for (let i = 0; i < inNumSamples; i++) { 35 | const z = Math.random(); 36 | 37 | out[i] = z < thresh ? z * scale - 1 : 0; 38 | } 39 | }; 40 | 41 | SCUnitRepository.registerSCUnitClass("Dust2", SCUnitDust2); 42 | 43 | module.exports = SCUnitDust2; 44 | -------------------------------------------------------------------------------- /src/unit/SCUnitDwhite.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const C = require("../Constants"); 5 | const SCUnit = require("../SCUnit"); 6 | const SCUnitRepository = require("../SCUnitRepository"); 7 | const demand = require("./_demand"); 8 | const dspProcess = {}; 9 | 10 | class SCUnitDwhite extends SCUnit { 11 | initialize() { 12 | assert( 13 | this.calcRate === C.RATE_DEMAND && this.inputs.length === 3 14 | ); 15 | 16 | this.dspProcess = dspProcess["d"]; 17 | 18 | this._lo = 0; 19 | this._range = 0; 20 | 21 | this.reset(); 22 | } 23 | 24 | reset() { 25 | this._repeats = -1; 26 | this._repeatCount = 0; 27 | } 28 | } 29 | 30 | dspProcess["d"] = function(inNumSamples) { 31 | if (inNumSamples === 0) { 32 | return this.reset(); 33 | } 34 | 35 | if (this._repeats < 0) { 36 | const x = demand.next(this, 0, inNumSamples); 37 | 38 | this._repeats = Number.isNaN(x) ? 0 : Math.max(0, Math.floor(x + 0.5)); 39 | } 40 | 41 | const out = this.outputs[0]; 42 | 43 | if (this._repeats <= this._repeatCount) { 44 | out[0] = NaN; 45 | return; 46 | } 47 | 48 | this._repeatCount += 1; 49 | 50 | const lo = demand.next(this, 1, inNumSamples); 51 | const hi = demand.next(this, 2, inNumSamples); 52 | 53 | if (!Number.isNaN(lo)) { 54 | this._lo = lo; 55 | } 56 | if (!Number.isNaN(hi)) { 57 | this._range = hi - this._lo; 58 | } 59 | 60 | out[0] = Math.random() * this._range + this._lo; 61 | }; 62 | 63 | SCUnitRepository.registerSCUnitClass("Dwhite", SCUnitDwhite); 64 | 65 | module.exports = SCUnitDwhite; 66 | -------------------------------------------------------------------------------- /src/unit/SCUnitExpRand.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const SCUnit = require("../SCUnit"); 4 | const SCUnitRepository = require("../SCUnitRepository"); 5 | 6 | class SCUnitExpRand extends SCUnit { 7 | initialize() { 8 | const lo = this.inputs[0][0] || 0.01; 9 | const hi = this.inputs[1][0]; 10 | const ratio = hi / lo; 11 | 12 | this.outputs[0][0] = Math.pow(ratio, Math.random()) * lo; 13 | } 14 | } 15 | 16 | SCUnitRepository.registerSCUnitClass("ExpRand", SCUnitExpRand); 17 | 18 | module.exports = SCUnitExpRand; 19 | -------------------------------------------------------------------------------- /src/unit/SCUnitFold.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const C = require("../Constants"); 3 | const SCUnit = require("../SCUnit"); 4 | const SCUnitRepository = require("../SCUnitRepository"); 5 | const sc_fold = require("../util/sc_fold"); 6 | const dspProcess = {}; 7 | class SCUnitFold extends SCUnit { 8 | initialize(rate) { 9 | if (this.inputSpecs[1].rate === C.RATE_AUDIO && this.inputSpecs[2].rate === C.RATE_AUDIO) { 10 | this.dspProcess = dspProcess["next_aa"]; 11 | } else { 12 | this.dspProcess = dspProcess["next_kk"]; 13 | } 14 | this._slopeFactor = rate.slopeFactor; 15 | this._lo = this.inputs[1][0]; 16 | this._hi = this.inputs[2][0]; 17 | this.dspProcess(1); 18 | } 19 | } 20 | dspProcess["next_aa"] = function (inNumSamples) { 21 | const out = this.outputs[0]; 22 | const inIn = this.inputs[0]; 23 | const loIn = this.inputs[1]; 24 | const hiIn = this.inputs[2]; 25 | for (let i = 0; i < inNumSamples; i++) { 26 | out[i] = sc_fold(inIn[i], loIn[i], hiIn[i]); 27 | } 28 | }; 29 | dspProcess["next_kk"] = function (inNumSamples) { 30 | const out = this.outputs[0]; 31 | const inIn = this.inputs[0]; 32 | const next_lo = this.inputs[1][0]; 33 | const next_hi = this.inputs[2][0]; 34 | const lo = this._lo; 35 | const hi = this._hi; 36 | if (next_lo === lo && next_hi === hi) { 37 | for (let i = 0; i < inNumSamples; i++) { 38 | out[i] = sc_fold(inIn[i], lo, hi); 39 | } 40 | } else { 41 | const lo_slope = (next_lo - lo) * this._slopeFactor; 42 | const hi_slope = (next_hi - hi) * this._slopeFactor; 43 | for (let i = 0; i < inNumSamples; i++) { 44 | out[i] = sc_fold(inIn[i], lo + lo_slope * i, hi + hi_slope * i); 45 | } 46 | this._lo = next_lo; 47 | this._hi = next_hi; 48 | } 49 | }; 50 | SCUnitRepository.registerSCUnitClass("Fold", SCUnitFold); 51 | module.exports = SCUnitFold; 52 | -------------------------------------------------------------------------------- /src/unit/SCUnitGate.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const C = require("../Constants"); 3 | const SCUnit = require("../SCUnit"); 4 | const SCUnitRepository = require("../SCUnitRepository"); 5 | const fillRange = require("../util/fillRange"); 6 | const dspProcess = {}; 7 | class SCUnitGate extends SCUnit { 8 | initialize() { 9 | if (this.inputSpecs[1].rate === C.RATE_AUDIO) { 10 | this.dspProcess = dspProcess["next_aa"]; 11 | } else { 12 | this.dspProcess = dspProcess["next_ak"]; 13 | } 14 | this._level = 0; 15 | this.outputs[0][0] = 0; 16 | } 17 | } 18 | dspProcess["next_aa"] = function (inNumSamples) { 19 | const out = this.outputs[0]; 20 | const inIn = this.inputs[0]; 21 | const trigIn = this.inputs[1]; 22 | let level = this._level; 23 | for (let i = 0; i < inNumSamples; i++) { 24 | const curTrig = trigIn[i]; 25 | if (curTrig > 0) { 26 | level = inIn[i]; 27 | } 28 | out[i] = level; 29 | } 30 | this._level = level; 31 | }; 32 | dspProcess["next_ak"] = function (inNumSamples) { 33 | const out = this.outputs[0]; 34 | const inIn = this.inputs[0]; 35 | const trig = this.inputs[1][0]; 36 | if (trig > 0) { 37 | out.set(inIn.subarray(0, inNumSamples)); 38 | this._level = inIn[inNumSamples - 1]; 39 | } else { 40 | fillRange(out, this._level, 0, inNumSamples); 41 | } 42 | }; 43 | SCUnitRepository.registerSCUnitClass("Gate", SCUnitGate); 44 | module.exports = SCUnitGate; 45 | -------------------------------------------------------------------------------- /src/unit/SCUnitGrayNoise.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const SCUnit = require("../SCUnit"); 4 | const SCUnitRepository = require("../SCUnitRepository"); 5 | const dspProcess = {}; 6 | 7 | class SCUnitGrayNoise extends SCUnit { 8 | initialize() { 9 | this.dspProcess = dspProcess["next"]; 10 | 11 | this._counter = 0; 12 | 13 | this.dspProcess(1); 14 | } 15 | } 16 | 17 | dspProcess["next"] = function(inNumSamples) { 18 | const out = this.outputs[0]; 19 | 20 | let counter = this._counter|0; 21 | 22 | for (let i = 0; i < inNumSamples; i++) { 23 | counter ^= 1 << (Math.random() * 32); 24 | out[i] = counter * 4.656612873077393e-10; 25 | } 26 | 27 | this._counter = counter; 28 | }; 29 | 30 | SCUnitRepository.registerSCUnitClass("GrayNoise", SCUnitGrayNoise); 31 | 32 | module.exports = SCUnitGrayNoise; 33 | -------------------------------------------------------------------------------- /src/unit/SCUnitHPZ1.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const SCUnit = require("../SCUnit"); 3 | const SCUnitRepository = require("../SCUnitRepository"); 4 | const dspProcess = {}; 5 | class SCUnitHPZ1 extends SCUnit { 6 | initialize() { 7 | this.dspProcess = dspProcess["next"]; 8 | this._x1 = this.inputs[0][0]; 9 | this.dspProcess(1); 10 | } 11 | } 12 | dspProcess["next"] = function (inNumSamples) { 13 | const out = this.outputs[0]; 14 | const inIn = this.inputs[0]; 15 | let x1 = this._x1; 16 | for (let i = 0; i < inNumSamples; i++) { 17 | const x0 = inIn[i]; 18 | out[i] = 0.5 * (x0 - x1); 19 | x1 = x0; 20 | } 21 | this._x1 = x1; 22 | }; 23 | SCUnitRepository.registerSCUnitClass("HPZ1", SCUnitHPZ1); 24 | module.exports = SCUnitHPZ1; 25 | -------------------------------------------------------------------------------- /src/unit/SCUnitHPZ2.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const SCUnit = require("../SCUnit"); 3 | const SCUnitRepository = require("../SCUnitRepository"); 4 | const dspProcess = {}; 5 | class SCUnitHPZ2 extends SCUnit { 6 | initialize() { 7 | this.dspProcess = dspProcess["next"]; 8 | this._x1 = this.inputs[0][0]; 9 | this._x2 = this.inputs[0][0]; 10 | this.dspProcess(1); 11 | } 12 | } 13 | dspProcess["next"] = function (inNumSamples) { 14 | const out = this.outputs[0]; 15 | const inIn = this.inputs[0]; 16 | let x1 = this._x1; 17 | let x2 = this._x2; 18 | for (let i = 0; i < inNumSamples; i++) { 19 | const x0 = inIn[i]; 20 | out[i] = (x0 - 2 * x1 + x2) * 0.25; 21 | x2 = x1; 22 | x1 = x0; 23 | } 24 | this._x1 = x1; 25 | this._x2 = x2; 26 | }; 27 | SCUnitRepository.registerSCUnitClass("HPZ2", SCUnitHPZ2); 28 | module.exports = SCUnitHPZ2; 29 | -------------------------------------------------------------------------------- /src/unit/SCUnitHasher.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const SCUnit = require("../SCUnit"); 5 | const SCUnitRepository = require("../SCUnitRepository"); 6 | 7 | const f32 = new Float32Array(1); 8 | const i32 = new Int32Array(f32.buffer); 9 | const dspProcess = {}; 10 | 11 | class SCUnitHasher extends SCUnit { 12 | initialize() { 13 | assert(this.inputs.length === 1); 14 | this.dspProcess = dspProcess["a"]; 15 | this.dspProcess(1); 16 | } 17 | } 18 | 19 | dspProcess["a"] = function(inNumSamples) { 20 | const out = this.outputs[0]; 21 | const inIn = this.inputs[0]; 22 | 23 | for (let i = 0; i < inNumSamples; i++) { 24 | f32[0] = inIn[i]; 25 | i32[0] = 0x40000000 | (hash(i32[0]) >>> 9); 26 | out[i] = f32[0] - 3; 27 | } 28 | }; 29 | 30 | function hash(hash) { 31 | hash += ~(hash << 15); 32 | hash ^= hash >> 10; 33 | hash += hash << 3; 34 | hash ^= hash >> 6; 35 | hash += ~(hash << 11); 36 | hash ^= hash >> 16; 37 | return hash; 38 | } 39 | 40 | SCUnitRepository.registerSCUnitClass("Hasher", SCUnitHasher); 41 | 42 | module.exports = SCUnitHasher; 43 | -------------------------------------------------------------------------------- /src/unit/SCUnitIRand.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const SCUnit = require("../SCUnit"); 4 | const SCUnitRepository = require("../SCUnitRepository"); 5 | 6 | class SCUnitIRand extends SCUnit { 7 | initialize() { 8 | const lo = this.inputs[0][0]|0; 9 | const hi = this.inputs[1][0]|0; 10 | 11 | this.outputs[0][0] = Math.floor(Math.random() * (hi - lo) + lo); 12 | } 13 | } 14 | 15 | SCUnitRepository.registerSCUnitClass("IRand", SCUnitIRand); 16 | 17 | module.exports = SCUnitIRand; 18 | -------------------------------------------------------------------------------- /src/unit/SCUnitIn.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const C = require("../Constants"); 5 | const SCUnit = require("../SCUnit"); 6 | const SCUnitRepository = require("../SCUnitRepository"); 7 | 8 | const dspProcess = {}; 9 | 10 | class SCUnitIn extends SCUnit { 11 | initialize() { 12 | assert(this.inputs.length === 1); 13 | if (this.calcRate === C.RATE_AUDIO) { 14 | this.dspProcess = dspProcess["a"]; 15 | this._buses = this.context.audioBuses; 16 | } else { 17 | this.dspProcess = dspProcess["k"]; 18 | this._buses = this.context.controlBuses; 19 | } 20 | } 21 | } 22 | 23 | dspProcess["a"] = function () { 24 | const outputs = this.outputs; 25 | const buses = this._buses; 26 | const firstBusChannel = this.inputs[0][0]|0; 27 | 28 | for (let ch = 0, chmax = outputs.length; ch < chmax; ch++) { 29 | outputs[ch].set(buses[firstBusChannel + ch]); 30 | } 31 | }; 32 | 33 | dspProcess["k"] = function () { 34 | const outputs = this.outputs; 35 | const buses = this._buses; 36 | const firstBusChannel = this.inputs[0][0]|0; 37 | 38 | for (let ch = 0, chmax = outputs.length; ch < chmax; ch++) { 39 | outputs[ch][0] = buses[firstBusChannel + ch][0]; 40 | } 41 | }; 42 | 43 | SCUnitRepository.registerSCUnitClass("In", SCUnitIn); 44 | 45 | module.exports = SCUnitIn; 46 | -------------------------------------------------------------------------------- /src/unit/SCUnitInRange.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const SCUnit = require("../SCUnit"); 3 | const SCUnitRepository = require("../SCUnitRepository"); 4 | const dspProcess = {}; 5 | class SCUnitInRange extends SCUnit { 6 | initialize() { 7 | this.dspProcess = dspProcess["next"]; 8 | this.dspProcess(1); 9 | } 10 | } 11 | dspProcess["next"] = function (inNumSamples) { 12 | const out = this.outputs[0]; 13 | const inIn = this.inputs[0]; 14 | const loIn = this.inputs[1]; 15 | const hiIn = this.inputs[2]; 16 | for (let i = 0; i < inNumSamples; i++) { 17 | const _in = inIn[i]; 18 | out[i] = loIn[i] <= _in && _in <= hiIn[i] ? 1 : 0; 19 | } 20 | }; 21 | SCUnitRepository.registerSCUnitClass("InRange", SCUnitInRange); 22 | module.exports = SCUnitInRange; 23 | -------------------------------------------------------------------------------- /src/unit/SCUnitInRect.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const SCUnit = require("../SCUnit"); 5 | const SCUnitRepository = require("../SCUnitRepository"); 6 | const dspProcess = {}; 7 | 8 | class SCUnitInRect extends SCUnit { 9 | initialize() { 10 | assert(this.inputs.length === 6); 11 | assert(this.inputSpecs[0].rate === this.inputSpecs[1].rate); 12 | this.dspProcess = dspProcess["aakkkk"]; 13 | } 14 | } 15 | 16 | dspProcess["aakkkk"] = function(inNumSamples) { 17 | const out = this.outputs[0]; 18 | const xIn = this.inputs[0]; 19 | const yIn = this.inputs[1]; 20 | const left = this.inputs[2][0]; 21 | const top = this.inputs[3][0]; 22 | const right = this.inputs[4][0]; 23 | const bottom = this.inputs[5][0]; 24 | 25 | for (let i = 0; i < inNumSamples; i++) { 26 | const x = xIn[i]; 27 | const y = yIn[i]; 28 | 29 | out[i] = (left <= x && x <= right) && (top <= y && y <= bottom) ? 1 : 0; 30 | } 31 | }; 32 | 33 | SCUnitRepository.registerSCUnitClass("InRect", SCUnitInRect); 34 | 35 | module.exports = SCUnitInRect; 36 | -------------------------------------------------------------------------------- /src/unit/SCUnitIntegrator.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const SCUnit = require("../SCUnit"); 3 | const SCUnitRepository = require("../SCUnitRepository"); 4 | const dspProcess = {}; 5 | class SCUnitIntegrator extends SCUnit { 6 | initialize(rate) { 7 | this.dspProcess = dspProcess["next"]; 8 | this._slopeFactor = rate.slopeFactor; 9 | this._b1 = this.inputs[1][0]; 10 | this._y1 = 0; 11 | this.dspProcess(1); 12 | } 13 | } 14 | dspProcess["next"] = function (inNumSamples) { 15 | const out = this.outputs[0]; 16 | const inIn = this.inputs[0]; 17 | const next_b1 = this.inputs[1][0]; 18 | const b1 = this._b1; 19 | let y1 = this._y1; 20 | if (b1 === next_b1) { 21 | for (let i = 0; i < inNumSamples; i++) { 22 | out[i] = y1 = inIn[i] + b1 * y1; 23 | } 24 | } else { 25 | const b1_slope = (next_b1 - b1) * this._slopeFactor; 26 | for (let i = 0; i < inNumSamples; i++) { 27 | out[i] = y1 = inIn[i] + (b1 + b1_slope * i) * y1; 28 | } 29 | this._b1 = next_b1; 30 | } 31 | this._y1 = y1; 32 | }; 33 | SCUnitRepository.registerSCUnitClass("Integrator", SCUnitIntegrator); 34 | module.exports = SCUnitIntegrator; 35 | -------------------------------------------------------------------------------- /src/unit/SCUnitK2A.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const SCUnit = require("../SCUnit"); 4 | const SCUnitRepository = require("../SCUnitRepository"); 5 | const fillRange = require("../util/fillRange"); 6 | const dspProcess = {}; 7 | 8 | class SCUnitK2A extends SCUnit { 9 | initialize() { 10 | this.dspProcess = dspProcess["a"]; 11 | } 12 | } 13 | 14 | dspProcess["a"] = function(inNumSamples) { 15 | fillRange(this.outputs[0], this.inputs[0][0], 0, inNumSamples); 16 | }; 17 | 18 | SCUnitRepository.registerSCUnitClass("K2A", SCUnitK2A); 19 | 20 | module.exports = SCUnitK2A; 21 | -------------------------------------------------------------------------------- /src/unit/SCUnitKeyState.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const C = require("../Constants"); 3 | const SCUnit = require("../SCUnit"); 4 | const SCUnitRepository = require("../SCUnitRepository"); 5 | const dspProcess = {}; 6 | const log001 = Math.log(0.001); 7 | class SCUnitKeyState extends SCUnit { 8 | initialize(rate) { 9 | this.dspProcess = dspProcess["next"]; 10 | this._sampleRate = rate.sampleRate; 11 | this._y1 = 0; 12 | this._b1 = 0; 13 | this._lag = 0; 14 | this._pointVal = this.context.uiValues.subarray(C.UI_KEY_STATE, C.UI_KEY_STATE + 1); 15 | this.dspProcess(1); 16 | } 17 | } 18 | dspProcess["next"] = function () { 19 | let keyState = this.inputs[0][0]; 20 | let minval = this.inputs[1][0]; 21 | let maxval = this.inputs[2][0]; 22 | let lag = this.inputs[3][0]; 23 | let y1 = this._y1; 24 | let b1 = this._b1; 25 | if (lag !== this._lag) { 26 | this._b1 = lag === 0 ? 0 : Math.exp(log001 / (lag * this._sampleRate)); 27 | this._lag = lag; 28 | } 29 | let y0 = (keyState | 0) === this._pointVal[0] ? maxval : minval; 30 | this.outputs[0][0] = y1 = y0 + b1 * (y1 - y0); 31 | this._y1 = y1; 32 | }; 33 | SCUnitRepository.registerSCUnitClass("KeyState", SCUnitKeyState); 34 | module.exports = SCUnitKeyState; 35 | -------------------------------------------------------------------------------- /src/unit/SCUnitLFClipNoise.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const SCUnit = require("../SCUnit"); 4 | const SCUnitRepository = require("../SCUnitRepository"); 5 | const dspProcess = {}; 6 | 7 | class SCUnitLFClipNoise extends SCUnit { 8 | initialize(rate) { 9 | this.dspProcess = dspProcess["next"]; 10 | 11 | this._sampleRate = rate.sampleRate; 12 | this._counter = 0; 13 | this._level = 0; 14 | 15 | this.dspProcess(1); 16 | } 17 | } 18 | 19 | dspProcess["next"] = function(inNumSamples) { 20 | const out = this.outputs[0]; 21 | const freq = Math.max(0.001, this.inputs[0][0]); 22 | 23 | let level = this._level; 24 | let counter = this._counter; 25 | let remain = inNumSamples; 26 | let j = 0; 27 | 28 | do { 29 | if (counter <= 0) { 30 | counter = Math.max(1, (this._sampleRate / freq)|0); 31 | level = Math.random() < 0.5 ? -1 : +1; 32 | } 33 | 34 | const nsmps = Math.min(remain, counter); 35 | 36 | for (let i = 0; i < nsmps; i++) { 37 | out[j++] = level; 38 | } 39 | 40 | remain -= nsmps; 41 | counter -= nsmps; 42 | } while (remain); 43 | 44 | this._level = level; 45 | this._counter = counter; 46 | }; 47 | 48 | SCUnitRepository.registerSCUnitClass("LFClipNoise", SCUnitLFClipNoise); 49 | 50 | module.exports = SCUnitLFClipNoise; 51 | -------------------------------------------------------------------------------- /src/unit/SCUnitLFCub.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const SCUnit = require("../SCUnit"); 4 | const SCUnitRepository = require("../SCUnitRepository"); 5 | const dspProcess = {}; 6 | 7 | class SCUnitLFCub extends SCUnit { 8 | initialize(rate) { 9 | this.dspProcess = dspProcess["ki"]; 10 | 11 | this._cpstoinc = 2 * rate.sampleDur; 12 | this._phase = this.inputs[1][0] + 0.5; 13 | 14 | this.dspProcess(1); 15 | } 16 | } 17 | 18 | dspProcess["ki"] = function(inNumSamples) { 19 | const out = this.outputs[0]; 20 | const phase_slope = this.inputs[0][0] * this._cpstoinc; 21 | 22 | let phase = this._phase; 23 | let z; 24 | 25 | for (let i = 0; i < inNumSamples; i++) { 26 | if (phase < 1) { 27 | z = phase; 28 | } else if (phase < 2) { 29 | z = 2 - phase; 30 | } else { 31 | phase -= 2; 32 | z = phase; 33 | } 34 | 35 | out[i] = z * z * (6 - 4 * z) - 1; 36 | phase += phase_slope; 37 | } 38 | 39 | this._phase = phase; 40 | }; 41 | 42 | SCUnitRepository.registerSCUnitClass("LFCub", SCUnitLFCub); 43 | 44 | module.exports = SCUnitLFCub; 45 | -------------------------------------------------------------------------------- /src/unit/SCUnitLFDClipNoise.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const C = require("../Constants"); 3 | const SCUnit = require("../SCUnit"); 4 | const SCUnitRepository = require("../SCUnitRepository"); 5 | const dspProcess = {}; 6 | class SCUnitLFDClipNoise extends SCUnit { 7 | initialize(rate) { 8 | if (this.inputSpecs[0].rate === C.RATE_AUDIO) { 9 | this.dspProcess = dspProcess["next"]; 10 | } else { 11 | this.dspProcess = dspProcess["next_k"]; 12 | } 13 | this._sampleDur = rate.sampleDur; 14 | this._level = 0; 15 | this._phase = 0; 16 | this.dspProcess(1); 17 | } 18 | } 19 | dspProcess["next"] = function (inNumSamples) { 20 | const out = this.outputs[0]; 21 | const freqIn = this.inputs[0]; 22 | const smpdur = this._sampleDur; 23 | let level = this._level; 24 | let phase = this._phase; 25 | for (let i = 0; i < inNumSamples; i++) { 26 | phase -= freqIn[i] * smpdur; 27 | if (phase < 0) { 28 | phase = 1 + phase % 1; 29 | level = Math.random() < 0.5 ? -1 : +1; 30 | } 31 | out[i] = level; 32 | } 33 | this._level = level; 34 | this._phase = phase; 35 | }; 36 | dspProcess["next_k"] = function (inNumSamples) { 37 | const out = this.outputs[0]; 38 | const freq = this.inputs[0][0]; 39 | const smpdur = this._sampleDur; 40 | const dphase = smpdur * freq; 41 | let level = this._level; 42 | let phase = this._phase; 43 | for (let i = 0; i < inNumSamples; i++) { 44 | phase -= dphase; 45 | if (phase < 0) { 46 | phase = 1 + phase % 1; 47 | level = Math.random() < 0.5 ? -1 : +1; 48 | } 49 | out[i] = level; 50 | } 51 | this._level = level; 52 | this._phase = phase; 53 | }; 54 | SCUnitRepository.registerSCUnitClass("LFDClipNoise", SCUnitLFDClipNoise); 55 | module.exports = SCUnitLFDClipNoise; 56 | -------------------------------------------------------------------------------- /src/unit/SCUnitLFDNoise0.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const C = require("../Constants"); 3 | const SCUnit = require("../SCUnit"); 4 | const SCUnitRepository = require("../SCUnitRepository"); 5 | const dspProcess = {}; 6 | class SCUnitLFDNoise0 extends SCUnit { 7 | initialize(rate) { 8 | if (this.inputSpecs[0].rate === C.RATE_AUDIO) { 9 | this.dspProcess = dspProcess["next"]; 10 | } else { 11 | this.dspProcess = dspProcess["next_k"]; 12 | } 13 | this._sampleDur = rate.sampleDur; 14 | this._level = 0; 15 | this._phase = 0; 16 | this.dspProcess(1); 17 | } 18 | } 19 | dspProcess["next"] = function (inNumSamples) { 20 | const out = this.outputs[0]; 21 | const freqIn = this.inputs[0]; 22 | const smpdur = this._sampleDur; 23 | let level = this._level; 24 | let phase = this._phase; 25 | for (let i = 0; i < inNumSamples; i++) { 26 | phase -= freqIn[i] * smpdur; 27 | if (phase < 0) { 28 | phase = 1 + phase % 1; 29 | level = Math.random() * 2 - 1; 30 | } 31 | out[i] = level; 32 | } 33 | this._level = level; 34 | this._phase = phase; 35 | }; 36 | dspProcess["next_k"] = function (inNumSamples) { 37 | const out = this.outputs[0]; 38 | const freq = this.inputs[0][0]; 39 | const smpdur = this._sampleDur; 40 | const dphase = smpdur * freq; 41 | let level = this._level; 42 | let phase = this._phase; 43 | for (let i = 0; i < inNumSamples; i++) { 44 | phase -= dphase; 45 | if (phase < 0) { 46 | phase = 1 + phase % 1; 47 | level = Math.random() * 2 - 1; 48 | } 49 | out[i] = level; 50 | } 51 | this._level = level; 52 | this._phase = phase; 53 | }; 54 | SCUnitRepository.registerSCUnitClass("LFDNoise0", SCUnitLFDNoise0); 55 | module.exports = SCUnitLFDNoise0; 56 | -------------------------------------------------------------------------------- /src/unit/SCUnitLFNoise0.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const SCUnit = require("../SCUnit"); 4 | const SCUnitRepository = require("../SCUnitRepository"); 5 | const dspProcess = {}; 6 | 7 | class SCUnitLFNoise0 extends SCUnit { 8 | initialize(rate) { 9 | this.dspProcess = dspProcess["next"]; 10 | 11 | this._sampleRate = rate.sampleRate; 12 | this._level = 0; 13 | this._counter = 0; 14 | 15 | this.dspProcess(1); 16 | } 17 | } 18 | 19 | dspProcess["next"] = function(inNumSamples) { 20 | const out = this.outputs[0]; 21 | const freq = Math.max(0.001, this.inputs[0][0]); 22 | 23 | let level = this._level; 24 | let counter = this._counter; 25 | let remain = inNumSamples; 26 | let j = 0; 27 | 28 | do { 29 | if (counter <= 0) { 30 | counter = Math.max(1, (this._sampleRate / freq)|0); 31 | level = Math.random() * 2 - 1; 32 | } 33 | 34 | const nsmps = Math.min(remain, counter); 35 | 36 | for (let i = 0; i < nsmps; i++) { 37 | out[j++] = level; 38 | } 39 | 40 | remain -= nsmps; 41 | counter -= nsmps; 42 | } while (remain); 43 | 44 | this._level = level; 45 | this._counter = counter; 46 | }; 47 | 48 | SCUnitRepository.registerSCUnitClass("LFNoise0", SCUnitLFNoise0); 49 | 50 | module.exports = SCUnitLFNoise0; 51 | -------------------------------------------------------------------------------- /src/unit/SCUnitLFNoise1.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const SCUnit = require("../SCUnit"); 4 | const SCUnitRepository = require("../SCUnitRepository"); 5 | const dspProcess = {}; 6 | 7 | class SCUnitLFNoise1 extends SCUnit { 8 | initialize(rate) { 9 | this.dspProcess = dspProcess["next"]; 10 | 11 | this._sampleRate = rate.sampleRate; 12 | this._level = Math.random() * 2 - 1; 13 | this._counter = 0; 14 | this._slope = 0; 15 | 16 | this.dspProcess(1); 17 | } 18 | } 19 | 20 | dspProcess["next"] = function(inNumSamples) { 21 | const out = this.outputs[0]; 22 | const freq = Math.max(0.001, this.inputs[0][0]); 23 | 24 | let level = this._level; 25 | let slope = this._slope; 26 | let counter = this._counter; 27 | let remain = inNumSamples; 28 | let j = 0; 29 | 30 | do { 31 | if (counter <= 0) { 32 | counter = Math.max(1, (this._sampleRate / freq)|0); 33 | slope = ((Math.random() * 2 - 1) - level) / counter; 34 | } 35 | 36 | const nsmps = Math.min(remain, counter); 37 | 38 | for (let i = 0; i < nsmps; i++) { 39 | out[j++] = level; 40 | level += slope; 41 | } 42 | 43 | remain -= nsmps; 44 | counter -= nsmps; 45 | } while (remain); 46 | 47 | this._level = level; 48 | this._slope = slope; 49 | this._counter = counter; 50 | }; 51 | 52 | SCUnitRepository.registerSCUnitClass("LFNoise1", SCUnitLFNoise1); 53 | 54 | module.exports = SCUnitLFNoise1; 55 | -------------------------------------------------------------------------------- /src/unit/SCUnitLFNoise2.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const SCUnit = require("../SCUnit"); 4 | const SCUnitRepository = require("../SCUnitRepository"); 5 | const dspProcess = {}; 6 | 7 | class SCUnitLFNoise2 extends SCUnit { 8 | initialize(rate) { 9 | this.dspProcess = dspProcess["next"]; 10 | 11 | this._sampleRate = rate.sampleRate; 12 | this._level = 0; 13 | this._counter = 0; 14 | this._slope = 0; 15 | this._curve = 0; 16 | this._nextValue = Math.random() * 2 - 1; 17 | this._nextMidPt = this._nextValue * 0.5; 18 | 19 | this.dspProcess(1); 20 | } 21 | } 22 | 23 | dspProcess["next"] = function (inNumSamples) { 24 | const out = this.outputs[0]; 25 | const freq = Math.max(0.001, this.inputs[0][0]); 26 | 27 | let level = this._level; 28 | let slope = this._slope; 29 | let curve = this._curve; 30 | let counter = this._counter; 31 | let remain = inNumSamples; 32 | let j = 0; 33 | 34 | do { 35 | if (counter <= 0) { 36 | const value = this._nextValue; 37 | 38 | this._nextValue = Math.random() * 2 - 1; 39 | 40 | level = this._nextMidPt; 41 | 42 | this._nextMidPt = (this._nextValue + value) * 0.5; 43 | counter = Math.max(2, (this._sampleRate / freq)|0); 44 | 45 | const fseglen = counter; 46 | 47 | curve = 2 * (this._nextMidPt - level - fseglen * slope) / (fseglen * fseglen + fseglen); 48 | } 49 | 50 | const nsmps = Math.min(remain, counter); 51 | 52 | for (let i = 0; i < nsmps; i++) { 53 | out[j++] = level; 54 | slope += curve; 55 | level += slope; 56 | } 57 | 58 | remain -= nsmps; 59 | counter -= nsmps; 60 | } while (remain); 61 | 62 | this._level = level; 63 | this._slope = slope; 64 | this._curve = curve; 65 | this._counter = counter; 66 | }; 67 | 68 | SCUnitRepository.registerSCUnitClass("LFNoise2", SCUnitLFNoise2); 69 | 70 | module.exports = SCUnitLFNoise2; 71 | -------------------------------------------------------------------------------- /src/unit/SCUnitLFPar.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const SCUnit = require("../SCUnit"); 4 | const SCUnitRepository = require("../SCUnitRepository"); 5 | const dspProcess = {}; 6 | 7 | class SCUnitLFPar extends SCUnit { 8 | initialize(rate) { 9 | this.dspProcess = dspProcess["ki"]; 10 | 11 | this._cpstoinc = 4 * rate.sampleDur; 12 | this._phase = this.inputs[1][0]; 13 | 14 | this.dspProcess(1); 15 | } 16 | } 17 | 18 | dspProcess["ki"] = function(inNumSamples) { 19 | const out = this.outputs[0]; 20 | const phase_slope = this.inputs[0][0] * this._cpstoinc; 21 | 22 | let phase = this._phase; 23 | let z, y; 24 | 25 | for (let i = 0; i < inNumSamples; i++) { 26 | if (phase < 1) { 27 | z = phase; 28 | y = 1 - z * z; 29 | } else if (phase < 3) { 30 | z = phase - 2; 31 | y = z * z - 1; 32 | } else { 33 | phase -= 4; 34 | z = phase; 35 | y = 1 - z * z; 36 | } 37 | 38 | out[i] = y; 39 | phase += phase_slope; 40 | } 41 | 42 | this._phase = phase; 43 | }; 44 | 45 | SCUnitRepository.registerSCUnitClass("LFPar", SCUnitLFPar); 46 | 47 | module.exports = SCUnitLFPar; 48 | -------------------------------------------------------------------------------- /src/unit/SCUnitLFPulse.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const SCUnit = require("../SCUnit"); 4 | const SCUnitRepository = require("../SCUnitRepository"); 5 | const dspProcess = {}; 6 | 7 | class SCUnitLFPulse extends SCUnit { 8 | initialize(rate) { 9 | this.dspProcess = dspProcess["kik"]; 10 | this._cpstoinc = rate.sampleDur; 11 | this._phase = this.inputs[1][0]; 12 | this._duty = this.inputs[2][0]; 13 | this.dspProcess(1); 14 | } 15 | } 16 | 17 | dspProcess["kik"] = function(inNumSamples) { 18 | const out = this.outputs[0]; 19 | const phase_slope = this.inputs[0][0] * this._cpstoinc; 20 | const next_duty = this.inputs[2][0]; 21 | 22 | let duty = this._duty; 23 | let phase = this._phase; 24 | let z; 25 | 26 | for (let i = 0; i < inNumSamples; i++) { 27 | if (phase > 1) { 28 | phase -= 1; 29 | duty = next_duty; 30 | z = duty < 0.5 ? 1 : 0; 31 | } else { 32 | z = phase < duty ? 1 : 0; 33 | } 34 | 35 | out[i] = z; 36 | phase += phase_slope; 37 | } 38 | 39 | this._duty = duty; 40 | this._phase = phase; 41 | }; 42 | 43 | SCUnitRepository.registerSCUnitClass("LFPulse", SCUnitLFPulse); 44 | 45 | module.exports = SCUnitLFPulse; 46 | -------------------------------------------------------------------------------- /src/unit/SCUnitLFSaw.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const SCUnit = require("../SCUnit"); 4 | const SCUnitRepository = require("../SCUnitRepository"); 5 | const dspProcess = {}; 6 | 7 | class SCUnitLFSaw extends SCUnit { 8 | initialize(rate) { 9 | this.dspProcess = dspProcess["ki"]; 10 | 11 | this._cpstoinc = 2 * rate.sampleDur; 12 | this._phase = this.inputs[1][0]; 13 | 14 | this.dspProcess(1); 15 | } 16 | } 17 | 18 | dspProcess["ki"] = function(inNumSamples) { 19 | const out = this.outputs[0]; 20 | const phase_slope = this.inputs[0][0] * this._cpstoinc; 21 | 22 | let phase = this._phase; 23 | 24 | if (0 <= phase_slope) { 25 | for (let i = 0; i < inNumSamples; i++) { 26 | out[i] = phase; 27 | phase += phase_slope; 28 | if (1 <= phase) { 29 | phase -= 2; 30 | } 31 | } 32 | } else { 33 | for (let i = 0; i < inNumSamples; i++) { 34 | out[i] = phase; 35 | phase += phase_slope; 36 | if (phase <= -1) { 37 | phase += 2; 38 | } 39 | } 40 | } 41 | 42 | this._phase = phase; 43 | }; 44 | 45 | SCUnitRepository.registerSCUnitClass("LFSaw", SCUnitLFSaw); 46 | 47 | module.exports = SCUnitLFSaw; 48 | -------------------------------------------------------------------------------- /src/unit/SCUnitLFTri.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const SCUnit = require("../SCUnit"); 4 | const SCUnitRepository = require("../SCUnitRepository"); 5 | const dspProcess = {}; 6 | 7 | class SCUnitLFTri extends SCUnit { 8 | initialize(rate) { 9 | this.dspProcess = dspProcess["ki"]; 10 | 11 | this._cpstoinc = 4 * rate.sampleDur; 12 | this._phase = this.inputs[1][0]; 13 | 14 | this.dspProcess(1); 15 | } 16 | } 17 | 18 | dspProcess["ki"] = function(inNumSamples) { 19 | const out = this.outputs[0]; 20 | const phase_slope = this.inputs[0][0] * this._cpstoinc; 21 | 22 | let phase = this._phase; 23 | 24 | for (let i = 0; i < inNumSamples; i++) { 25 | out[i] = 1 < phase ? 2 - phase : phase; 26 | phase += phase_slope; 27 | if (phase >= 3) { 28 | phase -= 4; 29 | } 30 | } 31 | 32 | this._phase = phase; 33 | }; 34 | 35 | SCUnitRepository.registerSCUnitClass("LFTri", SCUnitLFTri); 36 | 37 | module.exports = SCUnitLFTri; 38 | -------------------------------------------------------------------------------- /src/unit/SCUnitLPZ1.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const SCUnit = require("../SCUnit"); 3 | const SCUnitRepository = require("../SCUnitRepository"); 4 | const dspProcess = {}; 5 | class SCUnitLPZ1 extends SCUnit { 6 | initialize() { 7 | this.dspProcess = dspProcess["next"]; 8 | this._x1 = this.inputs[0][0]; 9 | this.dspProcess(1); 10 | } 11 | } 12 | dspProcess["next"] = function (inNumSamples) { 13 | const out = this.outputs[0]; 14 | const inIn = this.inputs[0]; 15 | let x1 = this._x1; 16 | for (let i = 0; i < inNumSamples; i++) { 17 | const x0 = inIn[i]; 18 | out[i] = 0.5 * (x0 + x1); 19 | x1 = x0; 20 | } 21 | this._x1 = x1; 22 | }; 23 | SCUnitRepository.registerSCUnitClass("LPZ1", SCUnitLPZ1); 24 | module.exports = SCUnitLPZ1; 25 | -------------------------------------------------------------------------------- /src/unit/SCUnitLPZ2.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const SCUnit = require("../SCUnit"); 3 | const SCUnitRepository = require("../SCUnitRepository"); 4 | const dspProcess = {}; 5 | class SCUnitLPZ2 extends SCUnit { 6 | initialize() { 7 | this.dspProcess = dspProcess["next"]; 8 | this._x1 = this.inputs[0][0]; 9 | this._x2 = this.inputs[0][0]; 10 | this.dspProcess(1); 11 | } 12 | } 13 | dspProcess["next"] = function (inNumSamples) { 14 | const out = this.outputs[0]; 15 | const inIn = this.inputs[0]; 16 | let x1 = this._x1; 17 | let x2 = this._x2; 18 | for (let i = 0; i < inNumSamples; i++) { 19 | const x0 = inIn[i]; 20 | out[i] = (x0 + 2 * x1 + x2) * 0.25; 21 | x2 = x1; 22 | x1 = x0; 23 | } 24 | this._x1 = x1; 25 | this._x2 = x2; 26 | }; 27 | SCUnitRepository.registerSCUnitClass("LPZ2", SCUnitLPZ2); 28 | module.exports = SCUnitLPZ2; 29 | -------------------------------------------------------------------------------- /src/unit/SCUnitLag.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const SCUnit = require("../SCUnit"); 3 | const SCUnitRepository = require("../SCUnitRepository"); 4 | const dspProcess = {}; 5 | const log001 = Math.log(0.001); 6 | class SCUnitLag extends SCUnit { 7 | initialize(rate) { 8 | if (this.bufferLength === 1) { 9 | this.dspProcess = dspProcess["next_1"]; 10 | } else { 11 | this.dspProcess = dspProcess["next"]; 12 | } 13 | this._sampleRate = rate.sampleRate; 14 | this._slopeFactor = rate.slopeFactor; 15 | this._lag = NaN; 16 | this._b1 = 0; 17 | this._y1 = this.inputs[0][0]; 18 | this.dspProcess(1); 19 | } 20 | } 21 | dspProcess["next"] = function (inNumSamples) { 22 | const out = this.outputs[0]; 23 | const inIn = this.inputs[0]; 24 | const lag = this.inputs[1][0]; 25 | let y1 = this._y1; 26 | let b1 = this._b1; 27 | if (lag === this._lag) { 28 | for (let i = 0; i < inNumSamples; i++) { 29 | const y0 = inIn[i]; 30 | out[i] = y1 = y0 + b1 * (y1 - y0); 31 | } 32 | } else { 33 | this._b1 = lag === 0 ? 0 : Math.exp(log001 / (lag * this._sampleRate)); 34 | this._lag = lag; 35 | const b1_slope = (this._b1 - b1) * this._slopeFactor; 36 | for (let i = 0; i < inNumSamples; i++) { 37 | const y0 = inIn[i]; 38 | out[i] = y1 = y0 + (b1 + b1_slope * i) * (y1 - y0); 39 | } 40 | } 41 | this._y1 = y1; 42 | }; 43 | dspProcess["next_1"] = function () { 44 | const out = this.outputs[0]; 45 | const lag = this.inputs[1][0]; 46 | let y1 = this._y1; 47 | let b1 = this._b1; 48 | if (lag !== this._lag) { 49 | this._b1 = b1 = lag === 0 ? 0 : Math.exp(log001 / (lag * this._sampleRate)); 50 | this._lag = lag; 51 | } 52 | const y0 = this.inputs[0][0]; 53 | out[0] = y1 = y0 + b1 * (y1 - y0); 54 | this._y1 = y1; 55 | }; 56 | SCUnitRepository.registerSCUnitClass("Lag", SCUnitLag); 57 | module.exports = SCUnitLag; 58 | -------------------------------------------------------------------------------- /src/unit/SCUnitLagControl.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const SCUnit = require("../SCUnit"); 3 | const SCUnitRepository = require("../SCUnitRepository"); 4 | const dspProcess = {}; 5 | const log001 = Math.log(0.001); 6 | class SCUnitLagControl extends SCUnit { 7 | initialize(rate) { 8 | if (this.outputs.length === 1) { 9 | this.dspProcess = dspProcess["1"]; 10 | } else { 11 | this.dspProcess = dspProcess["k"]; 12 | } 13 | const numberOfOutputs = this.outputs.length; 14 | const sampleRate = rate.sampleRate; 15 | this._controls = this.synth.params; 16 | this._y1 = new Float32Array(numberOfOutputs); 17 | this._b1 = new Float32Array(numberOfOutputs); 18 | for (let i = 0; i < numberOfOutputs; i++) { 19 | const lag = this.inputs[i][0]; 20 | this._y1[i] = this._controls[i]; 21 | this._b1[i] = lag === 0 ? 0 : Math.exp(log001 / (lag * sampleRate)); 22 | } 23 | this.dspProcess(1); 24 | } 25 | } 26 | dspProcess["1"] = function () { 27 | const y1 = this._y1; 28 | const b1 = this._b1; 29 | const z = this._controls[this.specialIndex]; 30 | const x = z + b1[0] * (y1[0] - z); 31 | this.outputs[0][0] = y1[0] = x; 32 | }; 33 | dspProcess["k"] = function () { 34 | const controls = this._controls; 35 | const outputs = this.outputs; 36 | const numberOfOutputs = this.outputs.length; 37 | const specialIndex = this.specialIndex; 38 | const y1 = this._y1; 39 | const b1 = this._b1; 40 | for (let i = 0; i < numberOfOutputs; i++) { 41 | const z = controls[specialIndex + i]; 42 | const x = z + b1[i] * (y1[i] - z); 43 | outputs[i][0] = y1[i] = x; 44 | } 45 | }; 46 | SCUnitRepository.registerSCUnitClass("LagControl", SCUnitLagControl); 47 | module.exports = SCUnitLagControl; 48 | -------------------------------------------------------------------------------- /src/unit/SCUnitLagUD.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const SCUnit = require("../SCUnit"); 3 | const SCUnitRepository = require("../SCUnitRepository"); 4 | const dspProcess = {}; 5 | const log001 = Math.log(0.001); 6 | class SCUnitLagUD extends SCUnit { 7 | initialize(rate) { 8 | this.dspProcess = dspProcess["next"]; 9 | this._sampleRate = rate.sampleRate; 10 | this._slopeFactor = rate.slopeFactor; 11 | this._lagu = NaN; 12 | this._lagd = NaN; 13 | this._b1u = 0; 14 | this._b1d = 0; 15 | this._y1 = this.inputs[0][0]; 16 | this.dspProcess(1); 17 | } 18 | } 19 | dspProcess["next"] = function (inNumSamples) { 20 | const out = this.outputs[0]; 21 | const inIn = this.inputs[0]; 22 | const lagu = this.inputs[1][0]; 23 | const lagd = this.inputs[2][0]; 24 | const b1u = this._b1u; 25 | const b1d = this._b1d; 26 | let y1 = this._y1; 27 | if (lagu === this._lagu && lagd === this._lagd) { 28 | for (let i = 0; i < inNumSamples; i++) { 29 | const y0 = inIn[i]; 30 | if (y0 > y1) { 31 | out[i] = y1 = y0 + b1u * (y1 - y0); 32 | } else { 33 | out[i] = y1 = y0 + b1d * (y1 - y0); 34 | } 35 | } 36 | } else { 37 | this._b1u = lagu === 0 ? 0 : Math.exp(log001 / (lagu * this._sampleRate)); 38 | this._b1d = lagd === 0 ? 0 : Math.exp(log001 / (lagd * this._sampleRate)); 39 | this._lagu = lagu; 40 | this._lagd = lagd; 41 | const b1u_slope = (this._b1u - b1u) * this._slopeFactor; 42 | const b1d_slope = (this._b1d - b1d) * this._slopeFactor; 43 | for (let i = 0; i < inNumSamples; i++) { 44 | const y0 = inIn[i]; 45 | if (y0 > y1) { 46 | out[i] = y1 = y0 + (b1u + b1u_slope * i) * (y1 - y0); 47 | } else { 48 | out[i] = y1 = y0 + (b1d + b1d_slope * i) * (y1 - y0); 49 | } 50 | } 51 | } 52 | this._y1 = y1; 53 | }; 54 | SCUnitRepository.registerSCUnitClass("LagUD", SCUnitLagUD); 55 | module.exports = SCUnitLagUD; 56 | -------------------------------------------------------------------------------- /src/unit/SCUnitLastValue.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const C = require("../Constants"); 5 | const SCUnit = require("../SCUnit"); 6 | const SCUnitRepository = require("../SCUnitRepository"); 7 | const fill = require("../util/fill"); 8 | 9 | const dspProcess = {}; 10 | 11 | class SCUnitLastValue extends SCUnit { 12 | initialize() { 13 | assert(this.inputs.length === 2); 14 | 15 | if (this.inputSpecs[0].rate === C.RATE_AUDIO) { 16 | this.dspProcess = dspProcess["ak"]; 17 | } else { 18 | this.dspProcess = dspProcess["kk"]; 19 | } 20 | 21 | this._prev = this.inputs[0][0]; 22 | this._curr = this.inputs[0][0]; 23 | } 24 | } 25 | 26 | dspProcess["ak"] = function(inNumSamples) { 27 | const out = this.outputs[0]; 28 | const inIn = this.inputs[0]; 29 | const delta = this.inputs[1][0]; 30 | 31 | let prev = this._prev; 32 | let curr = this._curr; 33 | 34 | for (let i = 0; i < inNumSamples; i++) { 35 | const inval = inIn[i]; 36 | const diff = Math.abs(inval - curr); 37 | 38 | if (delta <= diff) { 39 | prev = curr; 40 | curr = inval; 41 | } 42 | out[i] = prev; 43 | } 44 | 45 | this._prev = prev; 46 | this._curr = curr; 47 | }; 48 | 49 | dspProcess["kk"] = function() { 50 | const out = this.outputs[0]; 51 | const inval = this.inputs[0][0]; 52 | const delta = this.inputs[1][0]; 53 | 54 | let prev = this._prev; 55 | let curr = this._curr; 56 | 57 | const diff = Math.abs(inval - curr); 58 | 59 | if (delta <= diff) { 60 | prev = curr; 61 | curr = inval; 62 | } 63 | 64 | fill(out, prev); 65 | 66 | this._prev = prev; 67 | this._curr = curr; 68 | }; 69 | 70 | SCUnitRepository.registerSCUnitClass("LastValue", SCUnitLastValue); 71 | 72 | module.exports = SCUnitLastValue; 73 | -------------------------------------------------------------------------------- /src/unit/SCUnitLatch.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const C = require("../Constants"); 4 | const SCUnit = require("../SCUnit"); 5 | const SCUnitRepository = require("../SCUnitRepository"); 6 | const fill = require("../util/fill"); 7 | const dspProcess = {}; 8 | 9 | class SCUnitLatch extends SCUnit { 10 | initialize() { 11 | if (this.inputSpecs[1].rate === C.RATE_AUDIO) { 12 | this.dspProcess = dspProcess["aa"]; 13 | } else { 14 | this.dspProcess = dspProcess["ak"]; 15 | } 16 | const level = this.inputs[0][0]; 17 | const trig = this.inputs[1][0]; 18 | 19 | this._trig = 0; 20 | this._level = 0; 21 | 22 | this.outputs[0][0] = 0 < trig ? level : 0; 23 | } 24 | } 25 | 26 | dspProcess["aa"] = function(inNumSamples) { 27 | const out = this.outputs[0]; 28 | const inIn = this.inputs[0]; 29 | const trigIn = this.inputs[1]; 30 | 31 | let trig = this._trig; 32 | let level = this._level; 33 | 34 | for (let i = 0; i < inNumSamples; i++) { 35 | const curtrig = trigIn[i]; 36 | 37 | if (trig <= 0 && 0 < curtrig) { 38 | level = inIn[i]; 39 | } 40 | 41 | out[i] = level; 42 | trig = curtrig; 43 | } 44 | 45 | this._trig = trig; 46 | this._level = level; 47 | }; 48 | 49 | dspProcess["ak"] = function() { 50 | const out = this.outputs[0]; 51 | const trig = this.inputs[1][0]; 52 | 53 | let level = this._level; 54 | 55 | if (this._trig <= 0 && 0 < trig) { 56 | level = this.inputs[0][0]; 57 | } 58 | 59 | fill(out, level); 60 | 61 | this._trig = trig; 62 | this._level = level; 63 | }; 64 | 65 | SCUnitRepository.registerSCUnitClass("Latch", SCUnitLatch); 66 | 67 | module.exports = SCUnitLatch; 68 | -------------------------------------------------------------------------------- /src/unit/SCUnitLinRand.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const SCUnit = require("../SCUnit"); 4 | const SCUnitRepository = require("../SCUnitRepository"); 5 | 6 | class SCUnitLinRand extends SCUnit { 7 | initialize() { 8 | const lo = this.inputs[0][0]; 9 | const hi = this.inputs[1][0]; 10 | const n = this.inputs[2][0]|0; 11 | const range = hi - lo; 12 | const a = Math.random(); 13 | const b = Math.random(); 14 | 15 | if (n <= 0) { 16 | this.outputs[0][0] = Math.min(a, b) * range + lo; 17 | } else { 18 | this.outputs[0][0] = Math.max(a, b) * range + lo; 19 | } 20 | } 21 | } 22 | 23 | SCUnitRepository.registerSCUnitClass("LinRand", SCUnitLinRand); 24 | 25 | module.exports = SCUnitLinRand; 26 | -------------------------------------------------------------------------------- /src/unit/SCUnitLine.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const SCUnit = require("../SCUnit"); 3 | const SCUnitRepository = require("../SCUnitRepository"); 4 | const dspProcess = {}; 5 | class SCUnitLine extends SCUnit { 6 | initialize(rate) { 7 | this.dspProcess = dspProcess["next"]; 8 | let start = this.inputs[0][0]; 9 | let end = this.inputs[1][0]; 10 | let dur = this.inputs[2][0]; 11 | let counter = Math.round(dur * rate.sampleRate); 12 | this._counter = Math.max(1, counter); 13 | if (counter === 0) { 14 | this._level = end; 15 | this._slope = 0; 16 | } else { 17 | this._slope = (end - start) / this._counter; 18 | this._level = start + this._slope; 19 | } 20 | this._endLevel = end; 21 | this._doneAction = this.inputs[3][0]; 22 | this.outputs[0][0] = this._level; 23 | } 24 | } 25 | dspProcess["next"] = function (inNumSamples) { 26 | const out = this.outputs[0]; 27 | const slope = this._slope; 28 | let level = this._level; 29 | let counter = this._counter; 30 | let remain = inNumSamples; 31 | let j = 0; 32 | do { 33 | if (counter === 0) { 34 | const endLevel = this._endLevel; 35 | for (let i = 0; i < remain; i++) { 36 | out[j++] = endLevel; 37 | } 38 | remain = 0; 39 | } else { 40 | const nsmps = Math.min(remain, counter); 41 | counter -= nsmps; 42 | remain -= nsmps; 43 | for (let i = 0; i < nsmps; i++) { 44 | out[j++] = level; 45 | level += slope; 46 | } 47 | if (counter === 0) { 48 | this.doneAction(this._doneAction); 49 | } 50 | } 51 | } while (remain); 52 | this._counter = counter; 53 | this._level = level; 54 | }; 55 | SCUnitRepository.registerSCUnitClass("Line", SCUnitLine); 56 | module.exports = SCUnitLine; 57 | -------------------------------------------------------------------------------- /src/unit/SCUnitLogistic.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const SCUnit = require("../SCUnit"); 4 | const SCUnitRepository = require("../SCUnitRepository"); 5 | const dspProcess = {}; 6 | 7 | class SCUnitLogistic extends SCUnit { 8 | initialize(rate) { 9 | this.dspProcess = dspProcess["kki"]; 10 | 11 | this._sampleRate = rate.sampleRate; 12 | this._y1 = this.inputs[2][0]; 13 | this._counter = 0; 14 | 15 | this.dspProcess(1); 16 | } 17 | } 18 | 19 | dspProcess["kki"] = function(inNumSamples) { 20 | const out = this.outputs[0]; 21 | const paramf = this.inputs[0][0]; 22 | const freq = this.inputs[1][0]; 23 | const sampleRate = this._sampleRate; 24 | 25 | let y1 = +this._y1; 26 | let counter = this._counter|0; 27 | let remain = inNumSamples; 28 | let j = 0; 29 | 30 | do { 31 | if (counter <= 0) { 32 | counter = Math.max(1, sampleRate / Math.max(0.001, freq))|0; 33 | y1 = paramf * y1 * (1 - y1); 34 | } 35 | const nsmps = Math.min(counter, remain); 36 | 37 | counter -= nsmps; 38 | remain -= nsmps; 39 | 40 | for (let i = 0; i < nsmps; i++) { 41 | out[j++] = y1; 42 | } 43 | } while (remain); 44 | 45 | this._y1 = y1; 46 | this._counter = counter; 47 | }; 48 | 49 | SCUnitRepository.registerSCUnitClass("Logistic", SCUnitLogistic); 50 | 51 | module.exports = SCUnitLogistic; 52 | -------------------------------------------------------------------------------- /src/unit/SCUnitMantissaMask.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const SCUnit = require("../SCUnit"); 5 | const SCUnitRepository = require("../SCUnitRepository"); 6 | 7 | const f32 = new Float32Array(1); 8 | const i32 = new Int32Array(f32.buffer); 9 | const dspProcess = {}; 10 | 11 | class SCUnitMantissaMask extends SCUnit { 12 | initialize() { 13 | assert(this.inputs.length === 2); 14 | this.dspProcess = dspProcess["ak"]; 15 | this.dspProcess(1); 16 | } 17 | } 18 | 19 | dspProcess["ak"] = function(inNumSamples) { 20 | const out = this.outputs[0]; 21 | const inIn = this.inputs[0]; 22 | const bits = this.inputs[0][1]|0; 23 | const mask = -1 << (23 - bits); 24 | 25 | for (let i = 0; i < inNumSamples; i++) { 26 | f32[0] = inIn[i]; 27 | i32[0] = mask & i32[0]; 28 | out[i] = f32[0]; 29 | } 30 | }; 31 | 32 | SCUnitRepository.registerSCUnitClass("MantissaMask", SCUnitMantissaMask); 33 | 34 | module.exports = SCUnitMantissaMask; 35 | -------------------------------------------------------------------------------- /src/unit/SCUnitMouseButton.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const C = require("../Constants"); 3 | const SCUnit = require("../SCUnit"); 4 | const SCUnitRepository = require("../SCUnitRepository"); 5 | const dspProcess = {}; 6 | const log001 = Math.log(0.001); 7 | class SCUnitMouseButton extends SCUnit { 8 | initialize(rate) { 9 | this.dspProcess = dspProcess["next"]; 10 | this._sampleRate = rate.sampleRate; 11 | this._y1 = 0; 12 | this._b1 = 0; 13 | this._lag = 0; 14 | this._pointVal = this.context.uiValues.subarray(C.UI_MOUSE_BUTTON, C.UI_MOUSE_BUTTON + 1); 15 | this.dspProcess(1); 16 | } 17 | } 18 | dspProcess["next"] = function () { 19 | let minval = this.inputs[0][0]; 20 | let maxval = this.inputs[1][0]; 21 | let lag = this.inputs[2][0]; 22 | let y1 = this._y1; 23 | let b1 = this._b1; 24 | if (lag !== this._lag) { 25 | this._b1 = lag === 0 ? 0 : Math.exp(log001 / (lag * this.ç)); 26 | this._lag = lag; 27 | } 28 | let y0 = this._pointVal[0] ? maxval : minval; 29 | this.outputs[0][0] = y1 = y0 + b1 * (y1 - y0); 30 | this._y1 = y1; 31 | }; 32 | SCUnitRepository.registerSCUnitClass("MouseButton", SCUnitMouseButton); 33 | module.exports = SCUnitMouseButton; 34 | -------------------------------------------------------------------------------- /src/unit/SCUnitMouseX.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const C = require("../Constants"); 3 | const SCUnit = require("../SCUnit"); 4 | const SCUnitRepository = require("../SCUnitRepository"); 5 | const dspProcess = {}; 6 | const log001 = Math.log(0.001); 7 | class SCUnitMouseX extends SCUnit { 8 | initialize(rate) { 9 | this.dspProcess = dspProcess["next"]; 10 | this._sampleRate = rate.sampleRate; 11 | this._y1 = 0; 12 | this._b1 = 0; 13 | this._lag = 0; 14 | this._pointVal = this.context.uiValues.subarray(C.UI_MOUSE_X, C.UI_MOUSE_X + 1); 15 | this.dspProcess(1); 16 | } 17 | } 18 | dspProcess["next"] = function () { 19 | let minval = this.inputs[0][0] || 0.01; 20 | let maxval = this.inputs[1][0]; 21 | let warp = this.inputs[2][0]; 22 | let lag = this.inputs[3][0]; 23 | let y1 = this._y1; 24 | let b1 = this._b1; 25 | if (lag !== this._lag) { 26 | this._b1 = lag === 0 ? 0 : Math.exp(log001 / (lag * this._sampleRate)); 27 | this._lag = lag; 28 | } 29 | let y0 = this._pointVal[0]; 30 | if (warp === 0) { 31 | y0 = (maxval - minval) * y0 + minval; 32 | } else { 33 | y0 = Math.pow(maxval / minval, y0) * minval; 34 | if (isNaN(y0)) { 35 | y0 = 0; 36 | } 37 | } 38 | this.outputs[0][0] = y1 = y0 + b1 * (y1 - y0); 39 | this._y1 = y1; 40 | }; 41 | SCUnitRepository.registerSCUnitClass("MouseX", SCUnitMouseX); 42 | module.exports = SCUnitMouseX; 43 | -------------------------------------------------------------------------------- /src/unit/SCUnitMouseY.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const C = require("../Constants"); 3 | const SCUnit = require("../SCUnit"); 4 | const SCUnitRepository = require("../SCUnitRepository"); 5 | const dspProcess = {}; 6 | const log001 = Math.log(0.001); 7 | class SCUnitMouseY extends SCUnit { 8 | initialize(rate) { 9 | this.dspProcess = dspProcess["next"]; 10 | this._sampleRate = rate.sampleRate; 11 | this._y1 = 0; 12 | this._b1 = 0; 13 | this._lag = 0; 14 | this._pointVal = this.context.uiValues.subarray(C.UI_MOUSE_Y, C.UI_MOUSE_Y + 1); 15 | this.dspProcess(1); 16 | } 17 | } 18 | dspProcess["next"] = function () { 19 | let minval = this.inputs[0][0] || 0.01; 20 | let maxval = this.inputs[1][0]; 21 | let warp = this.inputs[2][0]; 22 | let lag = this.inputs[3][0]; 23 | let y1 = this._y1; 24 | let b1 = this._b1; 25 | if (lag !== this._lag) { 26 | this._b1 = lag === 0 ? 0 : Math.exp(log001 / (lag * this._sampleRate)); 27 | this._lag = lag; 28 | } 29 | let y0 = this._pointVal[0]; 30 | if (warp === 0) { 31 | y0 = (maxval - minval) * y0 + minval; 32 | } else { 33 | y0 = Math.pow(maxval / minval, y0) * minval; 34 | if (isNaN(y0)) { 35 | y0 = 0; 36 | } 37 | } 38 | this.outputs[0][0] = y1 = y0 + b1 * (y1 - y0); 39 | this._y1 = y1; 40 | }; 41 | SCUnitRepository.registerSCUnitClass("MouseY", SCUnitMouseY); 42 | module.exports = SCUnitMouseY; 43 | -------------------------------------------------------------------------------- /src/unit/SCUnitNRand.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const SCUnit = require("../SCUnit"); 4 | const SCUnitRepository = require("../SCUnitRepository"); 5 | 6 | class SCUnitNRand extends SCUnit { 7 | initialize() { 8 | const lo = this.inputs[0][0]; 9 | const hi = this.inputs[1][0]; 10 | const n = this.inputs[2][0]|0; 11 | const range = hi - lo; 12 | 13 | if (n) { 14 | let sum = 0; 15 | for (let i = 0; i < n; i++) { 16 | sum += Math.random(); 17 | } 18 | this.outputs[0][0] = (sum / n) * range + lo; 19 | } 20 | } 21 | } 22 | 23 | SCUnitRepository.registerSCUnitClass("NRand", SCUnitNRand); 24 | 25 | module.exports = SCUnitNRand; 26 | -------------------------------------------------------------------------------- /src/unit/SCUnitNumAudioBuses.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const SCUnit = require("../SCUnit"); 3 | const SCUnitRepository = require("../SCUnitRepository"); 4 | class SCUnitNumAudioBuses extends SCUnit { 5 | initialize() { 6 | this.outputs[0][0] = this.context.numberOfAudioBus; 7 | } 8 | } 9 | SCUnitRepository.registerSCUnitClass("NumAudioBuses", SCUnitNumAudioBuses); 10 | module.exports = SCUnitNumAudioBuses; 11 | -------------------------------------------------------------------------------- /src/unit/SCUnitNumControlBuses.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const SCUnit = require("../SCUnit"); 3 | const SCUnitRepository = require("../SCUnitRepository"); 4 | class SCUnitNumControlBuses extends SCUnit { 5 | initialize() { 6 | this.outputs[0][0] = this.context.numberOfControlBus; 7 | } 8 | } 9 | SCUnitRepository.registerSCUnitClass("NumControlBuses", SCUnitNumControlBuses); 10 | module.exports = SCUnitNumControlBuses; 11 | -------------------------------------------------------------------------------- /src/unit/SCUnitNumInputBuses.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const SCUnit = require("../SCUnit"); 3 | const SCUnitRepository = require("../SCUnitRepository"); 4 | class SCUnitNumInputBuses extends SCUnit { 5 | initialize() { 6 | this.outputs[0][0] = this.context.numberOfChannels; 7 | } 8 | } 9 | SCUnitRepository.registerSCUnitClass("NumInputBuses", SCUnitNumInputBuses); 10 | module.exports = SCUnitNumInputBuses; 11 | -------------------------------------------------------------------------------- /src/unit/SCUnitNumOutputBuses.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const SCUnit = require("../SCUnit"); 3 | const SCUnitRepository = require("../SCUnitRepository"); 4 | class SCUnitNumOutputBuses extends SCUnit { 5 | initialize() { 6 | this.outputs[0][0] = this.context.numberOfChannels; 7 | } 8 | } 9 | SCUnitRepository.registerSCUnitClass("NumOutputBuses", SCUnitNumOutputBuses); 10 | module.exports = SCUnitNumOutputBuses; 11 | -------------------------------------------------------------------------------- /src/unit/SCUnitOffsetOut.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const C = require("../Constants"); 5 | const SCUnit = require("../SCUnit"); 6 | const SCUnitRepository = require("../SCUnitRepository"); 7 | const dspProcess = {}; 8 | 9 | // TODO: use the sample offset ?? 10 | // Now, SCUnitOffsetOut == SCUnitOut 11 | 12 | class SCUnitOffsetOut extends SCUnit { 13 | initialize() { 14 | assert(2 <= this.inputs.length); 15 | if (this.calcRate === C.RATE_AUDIO) { 16 | assert( 17 | this.inputSpecs.slice(1).every( 18 | (spec) => spec.rate === C.RATE_AUDIO 19 | ) 20 | ); 21 | this.dspProcess = dspProcess["a"]; 22 | this._buses = this.context.audioBuses; 23 | } else { 24 | this.dspProcess = dspProcess["k"]; 25 | this._buses = this.context.controlBuses; 26 | } 27 | } 28 | } 29 | 30 | dspProcess["a"] = function(inNumSamples) { 31 | const inputs = this.inputs; 32 | const buses = this._buses; 33 | const firstBusChannel = inputs[0][0]|0; 34 | 35 | for (let ch = 0, chmax = inputs.length - 1; ch < chmax; ch++) { 36 | const out = buses[firstBusChannel + ch]; 37 | const inIn = inputs[ch + 1]; 38 | 39 | for (let i = 0; i < inNumSamples; i++) { 40 | out[i] += inIn[i]; 41 | } 42 | } 43 | }; 44 | 45 | dspProcess["k"] = function() { 46 | const inputs = this.inputs; 47 | const buses = this._buses; 48 | const firstBusChannel = inputs[0][0]|0; 49 | 50 | for (let ch = 0, chmax = inputs.length - 1; ch < chmax; ch++) { 51 | const out = buses[firstBusChannel + ch]; 52 | const _in = inputs[ch + 1][0]; 53 | 54 | out[0] += _in; 55 | } 56 | }; 57 | 58 | SCUnitRepository.registerSCUnitClass("OffsetOut", SCUnitOffsetOut); 59 | 60 | module.exports = SCUnitOffsetOut; 61 | -------------------------------------------------------------------------------- /src/unit/SCUnitOnePole.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const SCUnit = require("../SCUnit"); 3 | const SCUnitRepository = require("../SCUnitRepository"); 4 | const dspProcess = {}; 5 | class SCUnitOnePole extends SCUnit { 6 | initialize(rate) { 7 | this.dspProcess = dspProcess["next"]; 8 | this._slopeFactor = rate.slopeFactor; 9 | this._b1 = this.inputs[1][0]; 10 | this._y1 = 0; 11 | this.dspProcess(1); 12 | } 13 | } 14 | dspProcess["next"] = function (inNumSamples) { 15 | const out = this.outputs[0]; 16 | const inIn = this.inputs[0]; 17 | const b1 = this._b1; 18 | const next_b1 = Math.max(-1, Math.min(this.inputs[1][0], 1)); 19 | let y1 = this._y1; 20 | if (b1 !== next_b1) { 21 | let b1_slope = (next_b1 - b1) * this._slopeFactor; 22 | if (b1 > 0 && next_b1 >= 0) { 23 | for (let i = 0; i < inNumSamples; i++) { 24 | const y0 = inIn[i]; 25 | out[i] = y1 = y0 + (b1 + b1_slope * i) * (y1 - y0); 26 | } 27 | } else if (b1 <= 0 && next_b1 <= 0) { 28 | for (let i = 0; i < inNumSamples; i++) { 29 | const y0 = inIn[i]; 30 | out[i] = y1 = y0 + (b1 + b1_slope * i) * (y1 + y0); 31 | } 32 | } else { 33 | for (let i = 0; i < inNumSamples; i++) { 34 | const y0 = inIn[i]; 35 | out[i] = y1 = (1 - Math.abs(b1 + b1_slope * i)) * y0 + b1 * y1; 36 | } 37 | } 38 | this._b1 = next_b1; 39 | } else { 40 | if (b1 >= 0) { 41 | for (let i = 0; i < inNumSamples; i++) { 42 | const y0 = inIn[i]; 43 | out[i] = y1 = y0 + b1 * (y1 - y0); 44 | } 45 | } else { 46 | for (let i = 0; i < inNumSamples; i++) { 47 | const y0 = inIn[i]; 48 | out[i] = y1 = y0 + b1 * (y1 + y0); 49 | } 50 | } 51 | } 52 | this._y1 = y1; 53 | }; 54 | SCUnitRepository.registerSCUnitClass("OnePole", SCUnitOnePole); 55 | module.exports = SCUnitOnePole; 56 | -------------------------------------------------------------------------------- /src/unit/SCUnitOut.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const C = require("../Constants"); 5 | const SCUnit = require("../SCUnit"); 6 | const SCUnitRepository = require("../SCUnitRepository"); 7 | const dspProcess = {}; 8 | 9 | class SCUnitOut extends SCUnit { 10 | initialize() { 11 | assert(2 <= this.inputs.length); 12 | if (this.calcRate === C.RATE_AUDIO) { 13 | assert( 14 | this.inputSpecs.slice(1).every( 15 | (spec) => spec.rate === C.RATE_AUDIO 16 | ) 17 | ); 18 | this.dspProcess = dspProcess["a"]; 19 | this._buses = this.context.audioBuses; 20 | } else { 21 | this.dspProcess = dspProcess["k"]; 22 | this._buses = this.context.controlBuses; 23 | } 24 | } 25 | } 26 | 27 | dspProcess["a"] = function(inNumSamples) { 28 | const inputs = this.inputs; 29 | const buses = this._buses; 30 | const firstBusChannel = inputs[0][0]|0; 31 | 32 | for (let ch = 0, chmax = inputs.length - 1; ch < chmax; ch++) { 33 | const out = buses[firstBusChannel + ch]; 34 | const inIn = inputs[ch + 1]; 35 | 36 | for (let i = 0; i < inNumSamples; i++) { 37 | out[i] += inIn[i]; 38 | } 39 | } 40 | }; 41 | 42 | dspProcess["k"] = function() { 43 | const inputs = this.inputs; 44 | const buses = this._buses; 45 | const firstBusChannel = inputs[0][0]|0; 46 | 47 | for (let ch = 0, chmax = inputs.length - 1; ch < chmax; ch++) { 48 | const out = buses[firstBusChannel + ch]; 49 | const _in = inputs[ch + 1][0]; 50 | 51 | out[0] += _in; 52 | } 53 | }; 54 | 55 | SCUnitRepository.registerSCUnitClass("Out", SCUnitOut); 56 | 57 | module.exports = SCUnitOut; 58 | -------------------------------------------------------------------------------- /src/unit/SCUnitPeakFollower.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const SCUnit = require("../SCUnit"); 3 | const SCUnitRepository = require("../SCUnitRepository"); 4 | const dspProcess = {}; 5 | class SCUnitPeakFollower extends SCUnit { 6 | initialize(rate) { 7 | this.dspProcess = dspProcess["next"]; 8 | this._slopeFactor = rate.slopeFactor; 9 | this._decay = this.inputs[1][0]; 10 | this.outputs[0][0] = this._level = this.inputs[0][0]; 11 | } 12 | } 13 | dspProcess["next"] = function (inNumSamples) { 14 | const out = this.outputs[0]; 15 | const inIn = this.inputs[0]; 16 | const decay = this.inputs[1][0]; 17 | let level = this._level; 18 | if (decay === this._decay) { 19 | for (let i = 0; i < inNumSamples; i++) { 20 | const inlevel = Math.abs(inIn[i]); 21 | if (inlevel >= level) { 22 | level = inlevel; 23 | } else { 24 | level = inlevel + decay * (level - inlevel); 25 | } 26 | out[i] = level; 27 | } 28 | } else { 29 | let decay_slope = (decay - this._decay) * this._slopeFactor; 30 | for (let i = 0; i < inNumSamples; i++) { 31 | const inlevel = Math.abs(inIn[i]); 32 | if (inlevel >= level) { 33 | level = inlevel; 34 | } else { 35 | level = (1 - Math.abs(decay + decay_slope * i)) * inlevel + decay * level; 36 | } 37 | out[i] = level; 38 | } 39 | } 40 | this._level = level; 41 | this._decay = decay; 42 | }; 43 | SCUnitRepository.registerSCUnitClass("PeakFollower", SCUnitPeakFollower); 44 | module.exports = SCUnitPeakFollower; 45 | -------------------------------------------------------------------------------- /src/unit/SCUnitPhasor.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const SCUnit = require("../SCUnit"); 3 | const SCUnitRepository = require("../SCUnitRepository"); 4 | const sc_wrap = require("../util/sc_wrap"); 5 | const dspProcess = {}; 6 | class SCUnitPhasor extends SCUnit { 7 | initialize() { 8 | this.dspProcess = dspProcess["next"]; 9 | this._prevtrig = this.inputs[0][0]; 10 | this.outputs[0][0] = this._level = this.inputs[2][0]; 11 | } 12 | } 13 | dspProcess["next"] = function (inNumSamples) { 14 | const out = this.outputs[0]; 15 | const trigIn = this.inputs[0]; 16 | const rate = this.inputs[1][0]; 17 | const start = this.inputs[2][0]; 18 | const end = this.inputs[3][0]; 19 | const resetPos = this.inputs[4][0]; 20 | let prevtrig = this._prevtrig; 21 | let level = this._level; 22 | for (let i = 0; i < inNumSamples; i++) { 23 | const curtrig = trigIn[i]; 24 | if (prevtrig <= 0 && curtrig > 0) { 25 | const frac = 1 - prevtrig / (curtrig - prevtrig); 26 | level = resetPos + frac * rate; 27 | } 28 | out[i] = level; 29 | level += rate; 30 | level = sc_wrap(level, start, end); 31 | prevtrig = curtrig; 32 | } 33 | this._prevtrig = prevtrig; 34 | this._level = level; 35 | }; 36 | SCUnitRepository.registerSCUnitClass("Phasor", SCUnitPhasor); 37 | module.exports = SCUnitPhasor; 38 | -------------------------------------------------------------------------------- /src/unit/SCUnitPinkNoise.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const SCUnit = require("../SCUnit"); 4 | const SCUnitRepository = require("../SCUnitRepository"); 5 | const dspProcess = {}; 6 | const MAX_KEY = 31; 7 | 8 | class SCUnitPinkNoise extends SCUnit { 9 | initialize() { 10 | const whites = new Uint8Array(5); 11 | 12 | for (let i = 0; i < 5; i++) { 13 | whites[i] = (Math.random() * 1073741824) % 25; 14 | } 15 | 16 | this.dspProcess = dspProcess["next"]; 17 | 18 | this._whites = whites; 19 | this._key = 0; 20 | 21 | this.dspProcess(1); 22 | } 23 | } 24 | 25 | dspProcess["next"] = function(inNumSamples) { 26 | const out = this.outputs[0]; 27 | const whites = this._whites; 28 | 29 | let key = this._key|0; 30 | 31 | for (let i = 0; i < inNumSamples; i++) { 32 | const last_key = key++; 33 | if (MAX_KEY < key) { 34 | key = 0; 35 | } 36 | const diff = last_key ^ key; 37 | 38 | let sum = 0; 39 | 40 | for (let j = 0; j < 5; j++) { 41 | if (diff & 1 << j) { 42 | whites[j] = (Math.random() * 1073741824) % 25; 43 | } 44 | sum += whites[j]; 45 | } 46 | out[i] = sum * 0.016666666666666666 - 1; 47 | } 48 | 49 | this._key = key; 50 | }; 51 | 52 | SCUnitRepository.registerSCUnitClass("PinkNoise", SCUnitPinkNoise); 53 | 54 | module.exports = SCUnitPinkNoise; 55 | -------------------------------------------------------------------------------- /src/unit/SCUnitPulseDivider.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const SCUnit = require("../SCUnit"); 3 | const SCUnitRepository = require("../SCUnitRepository"); 4 | const dspProcess = {}; 5 | class SCUnitPulseDivider extends SCUnit { 6 | initialize() { 7 | this.dspProcess = dspProcess["next"]; 8 | this._prevtrig = 0; 9 | this._level = 0; 10 | this._counter = Math.floor(this.inputs[2][0] + 0.5); 11 | this.outputs[0][0] = 0; 12 | } 13 | } 14 | dspProcess["next"] = function (inNumSamples) { 15 | const out = this.outputs[0]; 16 | const trigIn = this.inputs[0]; 17 | const div = this.inputs[1][0] | 0; 18 | let prevtrig = this._prevtrig; 19 | let counter = this._counter; 20 | let z; 21 | for (let i = 0; i < inNumSamples; i++) { 22 | const curtrig = trigIn[i]; 23 | if (prevtrig <= 0 && curtrig > 0) { 24 | counter += 1; 25 | if (counter >= div) { 26 | counter = 0; 27 | z = 1; 28 | } else { 29 | z = 0; 30 | } 31 | } else { 32 | z = 0; 33 | } 34 | out[i] = z; 35 | prevtrig = curtrig; 36 | } 37 | this._counter = counter; 38 | this._prevtrig = prevtrig; 39 | }; 40 | SCUnitRepository.registerSCUnitClass("PulseDivider", SCUnitPulseDivider); 41 | module.exports = SCUnitPulseDivider; 42 | -------------------------------------------------------------------------------- /src/unit/SCUnitRadiansPerSample.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const SCUnit = require("../SCUnit"); 3 | const SCUnitRepository = require("../SCUnitRepository"); 4 | class SCUnitRadiansPerSample extends SCUnit { 5 | initialize() { 6 | this.outputs[0][0] = this.context.aRate.radiansPerSample; 7 | } 8 | } 9 | SCUnitRepository.registerSCUnitClass("RadiansPerSample", SCUnitRadiansPerSample); 10 | module.exports = SCUnitRadiansPerSample; 11 | -------------------------------------------------------------------------------- /src/unit/SCUnitRand.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const SCUnit = require("../SCUnit"); 4 | const SCUnitRepository = require("../SCUnitRepository"); 5 | 6 | class SCUnitRand extends SCUnit { 7 | initialize() { 8 | const lo = this.inputs[0][0]; 9 | const hi = this.inputs[1][0]; 10 | 11 | this.outputs[0][0] = Math.random() * (hi - lo) + lo; 12 | } 13 | } 14 | 15 | SCUnitRepository.registerSCUnitClass("Rand", SCUnitRand); 16 | 17 | module.exports = SCUnitRand; 18 | -------------------------------------------------------------------------------- /src/unit/SCUnitReplaceOut.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const C = require("../Constants"); 5 | const SCUnit = require("../SCUnit"); 6 | const SCUnitRepository = require("../SCUnitRepository"); 7 | const dspProcess = {}; 8 | 9 | class SCUnitReplaceOut extends SCUnit { 10 | initialize() { 11 | assert(2 <= this.inputs.length); 12 | if (this.calcRate === C.RATE_AUDIO) { 13 | assert( 14 | this.inputSpecs.slice(1).every( 15 | (spec) => spec.rate === C.RATE_AUDIO 16 | ) 17 | ); 18 | this.dspProcess = dspProcess["a"]; 19 | this._buses = this.context.audioBuses; 20 | } else { 21 | this.dspProcess = dspProcess["k"]; 22 | this._buses = this.context.controlBuses; 23 | } 24 | } 25 | } 26 | 27 | dspProcess["a"] = function() { 28 | const inputs = this.inputs; 29 | const buses = this._buses; 30 | const firstBusChannel = inputs[0][0]|0; 31 | 32 | for (let ch = 0, chmax = inputs.length - 1; ch < chmax; ch++) { 33 | const out = buses[firstBusChannel + ch]; 34 | const inIn = inputs[ch + 1]; 35 | 36 | out.set(inIn); 37 | } 38 | }; 39 | 40 | dspProcess["k"] = function () { 41 | const inputs = this.inputs; 42 | const buses = this._buses; 43 | const firstBusChannel = inputs[0][0]|0; 44 | 45 | for (let ch = 0, chmax = inputs.length - 1; ch < chmax; ch++) { 46 | const out = buses[firstBusChannel + ch]; 47 | const _in = inputs[ch + 1][0]; 48 | 49 | out[0] = _in; 50 | } 51 | }; 52 | 53 | SCUnitRepository.registerSCUnitClass("ReplaceOut", SCUnitReplaceOut); 54 | 55 | module.exports = SCUnitReplaceOut; 56 | -------------------------------------------------------------------------------- /src/unit/SCUnitSampleDur.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const SCUnit = require("../SCUnit"); 3 | const SCUnitRepository = require("../SCUnitRepository"); 4 | class SCUnitSampleDur extends SCUnit { 5 | initialize() { 6 | this.outputs[0][0] = this.context.aRate.sampleDur; 7 | } 8 | } 9 | SCUnitRepository.registerSCUnitClass("SampleDur", SCUnitSampleDur); 10 | module.exports = SCUnitSampleDur; 11 | -------------------------------------------------------------------------------- /src/unit/SCUnitSampleRate.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const SCUnit = require("../SCUnit"); 3 | const SCUnitRepository = require("../SCUnitRepository"); 4 | class SCUnitSampleRate extends SCUnit { 5 | initialize() { 6 | this.outputs[0][0] = this.context.aRate.sampleRate; 7 | } 8 | } 9 | SCUnitRepository.registerSCUnitClass("SampleRate", SCUnitSampleRate); 10 | module.exports = SCUnitSampleRate; 11 | -------------------------------------------------------------------------------- /src/unit/SCUnitSchmidt.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const SCUnit = require("../SCUnit"); 5 | const SCUnitRepository = require("../SCUnitRepository"); 6 | const dspProcess = {}; 7 | 8 | class SCUnitSchmidt extends SCUnit { 9 | initialize() { 10 | assert(this.inputs.length === 3); 11 | 12 | this.dspProcess = dspProcess["akk"]; 13 | 14 | this._level = 0; 15 | 16 | this.dspProcess(1); 17 | } 18 | } 19 | 20 | dspProcess["akk"] = function(inNumSamples) { 21 | const out = this.outputs[0]; 22 | const inIn = this.inputs[0]; 23 | const lo = this.inputs[1][0]; 24 | const hi = this.inputs[2][0]; 25 | 26 | let level = this._level; 27 | 28 | for (let i = 0; i < inNumSamples; i++) { 29 | const zin = inIn[i]; 30 | 31 | if (level === 1) { 32 | if (zin < lo) { 33 | level = 0; 34 | } 35 | } else { 36 | if (hi < zin) { 37 | level = 1; 38 | } 39 | } 40 | out[i] = level; 41 | } 42 | 43 | this._level = level; 44 | }; 45 | 46 | SCUnitRepository.registerSCUnitClass("Schmidt", SCUnitSchmidt); 47 | 48 | module.exports = SCUnitSchmidt; 49 | -------------------------------------------------------------------------------- /src/unit/SCUnitSelect.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const C = require("../Constants"); 3 | const SCUnit = require("../SCUnit"); 4 | const SCUnitRepository = require("../SCUnitRepository"); 5 | const dspProcess = {}; 6 | class SCUnitSelect extends SCUnit { 7 | initialize() { 8 | if (this.bufferLength === 1) { 9 | this.dspProcess = dspProcess["next_1"]; 10 | } else if (this.inputSpecs[0].rate === C.RATE_AUDIO) { 11 | this.dspProcess = dspProcess["next_a"]; 12 | } else { 13 | this.dspProcess = dspProcess["next_k"]; 14 | } 15 | this._maxIndex = this.inputs.length - 1; 16 | this.dspProcess(1); 17 | } 18 | } 19 | dspProcess["next_a"] = function (inNumSamples) { 20 | const out = this.outputs[0]; 21 | const inputs = this.inputs; 22 | const whichIn = inputs[0]; 23 | const maxIndex = this._maxIndex; 24 | for (let i = 0; i < inNumSamples; i++) { 25 | const index = Math.max(1, Math.min((whichIn[i] | 0) + 1, maxIndex)); 26 | out[i] = inputs[index][i]; 27 | } 28 | }; 29 | dspProcess["next_k"] = function () { 30 | const index = Math.max(1, Math.min((this.inputs[0][0] | 0) + 1, this._maxIndex)); 31 | this.outputs[0].set(this.inputs[index]); 32 | }; 33 | dspProcess["next_1"] = function () { 34 | const index = Math.max(1, Math.min((this.inputs[0][0] | 0) + 1, this._maxIndex)); 35 | this.outputs[0][0] = this.inputs[index][0]; 36 | }; 37 | SCUnitRepository.registerSCUnitClass("Select", SCUnitSelect); 38 | module.exports = SCUnitSelect; 39 | -------------------------------------------------------------------------------- /src/unit/SCUnitSlew.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const SCUnit = require("../SCUnit"); 3 | const SCUnitRepository = require("../SCUnitRepository"); 4 | const dspProcess = {}; 5 | class SCUnitSlew extends SCUnit { 6 | initialize(rate) { 7 | this.dspProcess = dspProcess["next"]; 8 | this._sampleDur = rate.sampleDur; 9 | this._level = this.inputs[0][0]; 10 | this.dspProcess(1); 11 | } 12 | } 13 | dspProcess["next"] = function (inNumSamples) { 14 | const out = this.outputs[0]; 15 | const inIn = this.inputs[0]; 16 | const upf = +this.inputs[1][0] * this._sampleDur; 17 | const dnf = -this.inputs[2][0] * this._sampleDur; 18 | let level = this._level; 19 | for (let i = 0; i < inNumSamples; i++) { 20 | const slope = inIn[i] - level; 21 | level += Math.max(dnf, Math.min(slope, upf)); 22 | out[i] = level; 23 | } 24 | this._level = level; 25 | }; 26 | SCUnitRepository.registerSCUnitClass("Slew", SCUnitSlew); 27 | module.exports = SCUnitSlew; 28 | -------------------------------------------------------------------------------- /src/unit/SCUnitSlope.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const SCUnit = require("../SCUnit"); 3 | const SCUnitRepository = require("../SCUnitRepository"); 4 | const dspProcess = {}; 5 | class SCUnitSlope extends SCUnit { 6 | initialize(rate) { 7 | this.dspProcess = dspProcess["next"]; 8 | this._sr = rate.sampleRate; 9 | this._x1 = this.inputs[0][0]; 10 | this.dspProcess(1); 11 | } 12 | } 13 | dspProcess["next"] = function (inNumSamples) { 14 | const out = this.outputs[0]; 15 | const inIn = this.inputs[0]; 16 | const sr = this._sr; 17 | let x1 = this._x1; 18 | for (let i = 0; i < inNumSamples; i++) { 19 | const x0 = inIn[i]; 20 | out[i] = sr * (x0 - x1); 21 | x1 = x0; 22 | } 23 | this._x1 = x1; 24 | }; 25 | SCUnitRepository.registerSCUnitClass("Slope", SCUnitSlope); 26 | module.exports = SCUnitSlope; 27 | -------------------------------------------------------------------------------- /src/unit/SCUnitSubsampleOffset.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const SCUnit = require("../SCUnit"); 3 | const SCUnitRepository = require("../SCUnitRepository"); 4 | class SCUnitSubsampleOffset extends SCUnit { 5 | initialize() { 6 | this.outputs[0][0] = 0; 7 | } 8 | } 9 | SCUnitRepository.registerSCUnitClass("SubsampleOffset", SCUnitSubsampleOffset); 10 | module.exports = SCUnitSubsampleOffset; 11 | -------------------------------------------------------------------------------- /src/unit/SCUnitSweep.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const SCUnit = require("../SCUnit"); 3 | const SCUnitRepository = require("../SCUnitRepository"); 4 | const dspProcess = {}; 5 | class SCUnitSweep extends SCUnit { 6 | initialize(rate) { 7 | this.dspProcess = dspProcess["next"]; 8 | this._sampleDur = rate.sampleDur; 9 | this._prevtrig = this.inputs[0][0]; 10 | this._level = 0; 11 | } 12 | } 13 | dspProcess["next"] = function (inNumSamples) { 14 | const out = this.outputs[0]; 15 | const trigIn = this.inputs[0]; 16 | const rate = this.inputs[1][0] * this._sampleDur; 17 | let prevtrig = this._prevtrig; 18 | let level = this._level; 19 | for (let i = 0; i < inNumSamples; i++) { 20 | const curtrig = trigIn[i]; 21 | if (prevtrig <= 0 && curtrig > 0) { 22 | const frac = -prevtrig / (curtrig - prevtrig); 23 | level = frac * rate; 24 | } else { 25 | level += rate; 26 | } 27 | out[i] = level; 28 | prevtrig = curtrig; 29 | } 30 | this._prevtrig = prevtrig; 31 | this._level = level; 32 | }; 33 | SCUnitRepository.registerSCUnitClass("Sweep", SCUnitSweep); 34 | module.exports = SCUnitSweep; 35 | -------------------------------------------------------------------------------- /src/unit/SCUnitT2A.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const SCUnit = require("../SCUnit"); 5 | const SCUnitRepository = require("../SCUnitRepository"); 6 | const fill = require("../util/fill"); 7 | const dspProcess = {}; 8 | 9 | class SCUnitT2A extends SCUnit { 10 | initialize() { 11 | assert(this.inputs.length === 2); 12 | this.dspProcess = dspProcess["ak"]; 13 | 14 | this._level = 0; 15 | 16 | this.dspProcess(1); 17 | } 18 | } 19 | 20 | dspProcess["ak"] = function() { 21 | const out = this.outputs[0]; 22 | const level = this.inputs[0][0]; 23 | 24 | fill(out, 0); 25 | 26 | if (this._level <= 0 && 0 < level) { 27 | this.outputs[0][this.inputs[1][0]|0] = level; 28 | } 29 | 30 | this._level = level; 31 | }; 32 | 33 | SCUnitRepository.registerSCUnitClass("T2A", SCUnitT2A); 34 | 35 | module.exports = SCUnitT2A; 36 | -------------------------------------------------------------------------------- /src/unit/SCUnitT2K.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const SCUnit = require("../SCUnit"); 5 | const SCUnitRepository = require("../SCUnitRepository"); 6 | const dspProcess = {}; 7 | 8 | class SCUnitT2K extends SCUnit { 9 | initialize() { 10 | assert(this.inputs.length === 1); 11 | this.dspProcess = dspProcess["a"]; 12 | this.outputs[0][0] = this.inputs[0][0]; 13 | } 14 | } 15 | 16 | dspProcess["a"] = function () { 17 | const inIn = this.inputs[0]; 18 | 19 | let out = 0; 20 | 21 | for (let i = 0, imax = inIn.length; i < imax; i++) { 22 | out = Math.max(out, inIn[i]); 23 | } 24 | 25 | this.outputs[0][0] = out; 26 | }; 27 | 28 | SCUnitRepository.registerSCUnitClass("T2K", SCUnitT2K); 29 | 30 | module.exports = SCUnitT2K; 31 | -------------------------------------------------------------------------------- /src/unit/SCUnitTRand.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const C = require("../Constants"); 4 | const SCUnit = require("../SCUnit"); 5 | const SCUnitRepository = require("../SCUnitRepository"); 6 | const dspProcess = {}; 7 | 8 | class SCUnitTRand extends SCUnit { 9 | initialize() { 10 | if (this.inputSpecs[2].rate === C.RATE_AUDIO) { 11 | this.dspProcess = dspProcess["kka"]; 12 | } else { 13 | this.dspProcess = dspProcess["kkk"]; 14 | } 15 | 16 | const lo = this.inputs[0][0]; 17 | const hi = this.inputs[1][0]; 18 | 19 | this._trig = this.inputs[2][0]; 20 | this._value = Math.random() * (hi - lo) + lo; 21 | 22 | this.outputs[0][0] = this._value; 23 | } 24 | } 25 | 26 | dspProcess["kka"] = function(inNumSamples) { 27 | const out = this.outputs[0]; 28 | const trigIn = this.inputs[2]; 29 | 30 | let value = this._value; 31 | let trig = this._trig; 32 | 33 | for (let i = 0; i < inNumSamples; i++) { 34 | const trig_next = trigIn[i]; 35 | 36 | if (trig <= 0 && 0 < trig_next) { 37 | const lo = this.inputs[0][0]; 38 | const hi = this.inputs[1][0]; 39 | 40 | value = Math.random() * (hi - lo) + lo; 41 | } 42 | 43 | out[i] = value; 44 | trig = trig_next; 45 | } 46 | 47 | this._trig = trig; 48 | this._value = value; 49 | }; 50 | 51 | dspProcess["kkk"] = function(inNumSamples) { 52 | const out = this.outputs[0]; 53 | const trig_next = this.inputs[2][0]; 54 | const trig = this._trig; 55 | 56 | if (trig <= 0 && 0 < trig_next) { 57 | const lo = this.inputs[0][0]; 58 | const hi = this.inputs[1][0]; 59 | 60 | this._value = Math.random() * (hi - lo) + lo; 61 | } 62 | 63 | const value = this._value; 64 | 65 | for (let i = 0; i < inNumSamples; i++) { 66 | out[i] = value; 67 | } 68 | 69 | this._trig = trig_next; 70 | }; 71 | 72 | SCUnitRepository.registerSCUnitClass("TRand", SCUnitTRand); 73 | 74 | module.exports = SCUnitTRand; 75 | -------------------------------------------------------------------------------- /src/unit/SCUnitTimer.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const SCUnit = require("../SCUnit"); 3 | const SCUnitRepository = require("../SCUnitRepository"); 4 | const dspProcess = {}; 5 | class SCUnitTimer extends SCUnit { 6 | initialize(rate) { 7 | this.dspProcess = dspProcess["next"]; 8 | this._sampleDur = rate.sampleDur; 9 | this._prevfrac = 0; 10 | this._previn = this.inputs[0][0]; 11 | this._counter = 0; 12 | this.outputs[0][0] = this._level = 0; 13 | } 14 | } 15 | dspProcess["next"] = function (inNumSamples) { 16 | const out = this.outputs[0]; 17 | const inIn = this.inputs[0]; 18 | const sampleDur = this._sampleDur; 19 | let previn = this._previn; 20 | let prevfrac = this._prevfrac; 21 | let level = this._level; 22 | let counter = this._counter; 23 | for (let i = 0; i < inNumSamples; i++) { 24 | const curin = inIn[i]; 25 | counter += 1; 26 | if (previn <= 0 && curin > 0) { 27 | const frac = -previn / (curin - previn); 28 | level = sampleDur * (frac + counter - prevfrac); 29 | prevfrac = frac; 30 | counter = 0; 31 | } 32 | out[i] = level; 33 | previn = curin; 34 | } 35 | this._previn = previn; 36 | this._prevfrac = prevfrac; 37 | this._level = level; 38 | this._counter = counter; 39 | }; 40 | SCUnitRepository.registerSCUnitClass("Timer", SCUnitTimer); 41 | module.exports = SCUnitTimer; 42 | -------------------------------------------------------------------------------- /src/unit/SCUnitToggleFF.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const SCUnit = require("../SCUnit"); 3 | const SCUnitRepository = require("../SCUnitRepository"); 4 | const dspProcess = {}; 5 | class SCUnitToggleFF extends SCUnit { 6 | initialize() { 7 | this.dspProcess = dspProcess["next"]; 8 | this._prevtrig = 0; 9 | this._level = 0; 10 | this.outputs[0][0] = 0; 11 | } 12 | } 13 | dspProcess["next"] = function (inNumSamples) { 14 | const out = this.outputs[0]; 15 | const trigIn = this.inputs[0]; 16 | let prevtrig = this._prevtrig; 17 | let level = this._level; 18 | let curtrig; 19 | for (let i = 0; i < inNumSamples; i++) { 20 | curtrig = trigIn[i]; 21 | if (prevtrig <= 0 && curtrig > 0) { 22 | level = 1 - level; 23 | } 24 | out[i] = level; 25 | prevtrig = curtrig; 26 | } 27 | this._prevtrig = prevtrig; 28 | this._level = level; 29 | }; 30 | SCUnitRepository.registerSCUnitClass("ToggleFF", SCUnitToggleFF); 31 | module.exports = SCUnitToggleFF; 32 | -------------------------------------------------------------------------------- /src/unit/SCUnitTrigControl.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const SCUnit = require("../SCUnit"); 3 | const SCUnitRepository = require("../SCUnitRepository"); 4 | const dspProcess = {}; 5 | class SCUnitTrigControl extends SCUnit { 6 | initialize() { 7 | if (this.outputs.length === 1) { 8 | this.dspProcess = dspProcess["1"]; 9 | } else { 10 | this.dspProcess = dspProcess["k"]; 11 | } 12 | this._controls = this.synth.params; 13 | this.dspProcess(1); 14 | } 15 | } 16 | dspProcess["1"] = function () { 17 | const controls = this._controls; 18 | const specialIndex = this.specialIndex; 19 | this.outputs[0][0] = controls[specialIndex]; 20 | controls[specialIndex] = 0; 21 | }; 22 | dspProcess["k"] = function () { 23 | const controls = this._controls; 24 | const outputs = this.outputs; 25 | const numberOfChannels = outputs.length; 26 | const specialIndex = this.specialIndex; 27 | for (let i = 0; i < numberOfChannels; i++) { 28 | outputs[i][0] = controls[specialIndex + i]; 29 | controls[specialIndex + i] = 0; 30 | } 31 | }; 32 | SCUnitRepository.registerSCUnitClass("TrigControl", SCUnitTrigControl); 33 | module.exports = SCUnitTrigControl; 34 | -------------------------------------------------------------------------------- /src/unit/SCUnitTwoPole.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const SCUnit = require("../SCUnit"); 3 | const SCUnitRepository = require("../SCUnitRepository"); 4 | const dspProcess = {}; 5 | class SCUnitTwoPole extends SCUnit { 6 | initialize(rate) { 7 | this.dspProcess = dspProcess["next"]; 8 | this._radiansPerSample = rate.radiansPerSample; 9 | this._slopeFactor = rate.slopeFactor; 10 | this._b1 = 0; 11 | this._b2 = 0; 12 | this._y1 = 0; 13 | this._y2 = 0; 14 | this._freq = NaN; 15 | this._reson = NaN; 16 | this.dspProcess(1); 17 | } 18 | } 19 | dspProcess["next"] = function (inNumSamples) { 20 | const out = this.outputs[0]; 21 | const inIn = this.inputs[0]; 22 | const freq = this.inputs[1][0]; 23 | const reson = Math.max(0, Math.min(this.inputs[2][0], 1)); 24 | const b1 = this._b1; 25 | const b2 = this._b2; 26 | let y1 = this._y1; 27 | let y2 = this._y2; 28 | if (freq !== this._freq || reson !== this._reson) { 29 | const b1_next = 2 * reson * Math.cos(freq * this._radiansPerSample); 30 | const b2_next = -(reson * reson); 31 | const b1_slope = (b1_next - b1) * this._slopeFactor; 32 | const b2_slope = (b2_next - b2) * this._slopeFactor; 33 | for (let i = 0; i < inNumSamples; i++) { 34 | const y0 = inIn[i] + (b1 + b1_slope * i) * y1 + (b2 + b2_slope * i) * y2; 35 | out[i] = y0; 36 | y2 = y1; 37 | y1 = y0; 38 | } 39 | this._freq = freq; 40 | this._reson = reson; 41 | this._b1 = b1_next; 42 | this._b2 = b2_next; 43 | } else { 44 | for (let i = 0; i < inNumSamples; i++) { 45 | const y0 = inIn[i] + b1 * y1 + b2 * y2; 46 | out[i] = y0; 47 | y2 = y1; 48 | y1 = y0; 49 | } 50 | } 51 | this._y1 = y1; 52 | this._y2 = y2; 53 | }; 54 | SCUnitRepository.registerSCUnitClass("TwoPole", SCUnitTwoPole); 55 | module.exports = SCUnitTwoPole; 56 | -------------------------------------------------------------------------------- /src/unit/SCUnitTwoZero.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const SCUnit = require("../SCUnit"); 3 | const SCUnitRepository = require("../SCUnitRepository"); 4 | const dspProcess = {}; 5 | class SCUnitTwoZero extends SCUnit { 6 | initialize(rate) { 7 | this.dspProcess = dspProcess["next"]; 8 | this._radiansPerSample = rate.radiansPerSample; 9 | this._slopeFactor = rate.slopeFactor; 10 | this._b1 = 0; 11 | this._b2 = 0; 12 | this._x1 = 0; 13 | this._x2 = 0; 14 | this._freq = NaN; 15 | this._reson = NaN; 16 | this.dspProcess(1); 17 | } 18 | } 19 | dspProcess["next"] = function (inNumSamples) { 20 | const out = this.outputs[0]; 21 | const inIn = this.inputs[0]; 22 | const freq = this.inputs[1][0]; 23 | const reson = Math.max(0, Math.min(this.inputs[2][0], 1)); 24 | const b1 = this._b1; 25 | const b2 = this._b2; 26 | let x1 = this._x1; 27 | let x2 = this._x2; 28 | if (freq !== this._freq || reson !== this._reson) { 29 | const b1_next = -2 * reson * Math.cos(freq * this._radiansPerSample); 30 | const b2_next = reson * reson; 31 | const b1_slope = (b1_next - b1) * this._slopeFactor; 32 | const b2_slope = (b2_next - b2) * this._slopeFactor; 33 | for (let i = 0; i < inNumSamples; i++) { 34 | const x0 = inIn[i]; 35 | out[i] = x0 + (b1 + b1_slope * i) * x1 + (b2 + b2_slope * i) * x2; 36 | x2 = x1; 37 | x1 = x0; 38 | } 39 | this._freq = freq; 40 | this._reson = reson; 41 | this._b1 = b1_next; 42 | this._b2 = b2_next; 43 | } else { 44 | for (let i = 0; i < inNumSamples; i++) { 45 | const x0 = inIn[i]; 46 | out[i] = x0 + b1 * x1 + b2 * x2; 47 | x2 = x1; 48 | x1 = x0; 49 | } 50 | } 51 | this._x1 = x1; 52 | this._x2 = x2; 53 | }; 54 | SCUnitRepository.registerSCUnitClass("TwoZero", SCUnitTwoZero); 55 | module.exports = SCUnitTwoZero; 56 | -------------------------------------------------------------------------------- /src/unit/SCUnitWhiteNoise.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const SCUnit = require("../SCUnit"); 4 | const SCUnitRepository = require("../SCUnitRepository"); 5 | const dspProcess = {}; 6 | 7 | class SCUnitWhiteNoise extends SCUnit { 8 | initialize() { 9 | this.dspProcess = dspProcess["next"]; 10 | this.dspProcess(1); 11 | } 12 | } 13 | 14 | dspProcess["next"] = function(inNumSamples) { 15 | const out = this.outputs[0]; 16 | 17 | for (let i = 0; i < inNumSamples; i++) { 18 | out[i] = Math.random() * 2 - 1; 19 | } 20 | }; 21 | 22 | SCUnitRepository.registerSCUnitClass("WhiteNoise", SCUnitWhiteNoise); 23 | 24 | module.exports = SCUnitWhiteNoise; 25 | -------------------------------------------------------------------------------- /src/unit/SCUnitWrap.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const C = require("../Constants"); 3 | const SCUnit = require("../SCUnit"); 4 | const SCUnitRepository = require("../SCUnitRepository"); 5 | const sc_wrap = require("../util/sc_wrap"); 6 | const dspProcess = {}; 7 | class SCUnitWrap extends SCUnit { 8 | initialize(rate) { 9 | if (this.inputSpecs[1].rate === C.RATE_AUDIO && this.inputSpecs[2].rate === C.RATE_AUDIO) { 10 | this.dspProcess = dspProcess["next_aa"]; 11 | } else { 12 | this.dspProcess = dspProcess["next_kk"]; 13 | } 14 | this._slopeFactor = rate.slopeFactor; 15 | this._lo = this.inputs[1][0]; 16 | this._hi = this.inputs[2][0]; 17 | this.dspProcess(1); 18 | } 19 | } 20 | dspProcess["next_aa"] = function (inNumSamples) { 21 | const out = this.outputs[0]; 22 | const inIn = this.inputs[0]; 23 | const loIn = this.inputs[1]; 24 | const hiIn = this.inputs[2]; 25 | for (let i = 0; i < inNumSamples; i++) { 26 | out[i] = sc_wrap(inIn[i], loIn[i], hiIn[i]); 27 | } 28 | }; 29 | dspProcess["next_kk"] = function (inNumSamples) { 30 | const out = this.outputs[0]; 31 | const inIn = this.inputs[0]; 32 | const next_lo = this.inputs[1][0]; 33 | const next_hi = this.inputs[2][0]; 34 | const lo = this._lo; 35 | const hi = this._hi; 36 | if (next_lo === lo && next_hi === hi) { 37 | for (let i = 0; i < inNumSamples; i++) { 38 | out[i] = sc_wrap(inIn[i], lo, hi); 39 | } 40 | } else { 41 | const lo_slope = (next_lo - lo) * this._slopeFactor; 42 | const hi_slope = (next_hi - hi) * this._slopeFactor; 43 | for (let i = 0; i < inNumSamples; i++) { 44 | out[i] = sc_wrap(inIn[i], lo + lo_slope * i, hi + hi_slope * i); 45 | } 46 | this._lo = next_lo; 47 | this._hi = next_hi; 48 | } 49 | }; 50 | SCUnitRepository.registerSCUnitClass("Wrap", SCUnitWrap); 51 | module.exports = SCUnitWrap; 52 | -------------------------------------------------------------------------------- /src/unit/SCUnitXLine.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const SCUnit = require("../SCUnit"); 3 | const SCUnitRepository = require("../SCUnitRepository"); 4 | const dspProcess = {}; 5 | class SCUnitXLine extends SCUnit { 6 | initialize(rate) { 7 | this.dspProcess = dspProcess["next"]; 8 | const start = this.inputs[0][0] || 0.001; 9 | const end = this.inputs[1][0] || 0.001; 10 | const dur = this.inputs[2][0]; 11 | const counter = Math.round(dur * rate.sampleRate); 12 | if (counter === 0) { 13 | this._level = end; 14 | this._counter = 0; 15 | this._growth = 0; 16 | } else { 17 | this._counter = counter; 18 | this._growth = Math.pow(end / start, 1 / counter); 19 | this._level = start * this._growth; 20 | } 21 | this._endLevel = end; 22 | this._doneAction = this.inputs[3][0]; 23 | this.outputs[0][0] = this._level; 24 | } 25 | } 26 | dspProcess["next"] = function (inNumSamples) { 27 | const out = this.outputs[0]; 28 | const growth = this._growth; 29 | let level = this._level; 30 | let counter = this._counter; 31 | let remain = inNumSamples; 32 | let j = 0; 33 | do { 34 | if (counter === 0) { 35 | const endLevel = this._endLevel; 36 | for (let i = 0; i < remain; i++) { 37 | out[j++] = endLevel; 38 | } 39 | remain = 0; 40 | } else { 41 | const nsmps = Math.min(remain, counter); 42 | counter -= nsmps; 43 | remain -= nsmps; 44 | for (let i = 0; i < nsmps; i++) { 45 | out[j++] = level; 46 | level *= growth; 47 | } 48 | if (counter === 0) { 49 | this.doneAction(this._doneAction); 50 | } 51 | } 52 | } while (remain); 53 | this._counter = counter; 54 | this._level = level; 55 | }; 56 | SCUnitRepository.registerSCUnitClass("XLine", SCUnitXLine); 57 | module.exports = SCUnitXLine; 58 | -------------------------------------------------------------------------------- /src/unit/SCUnitZeroCrossing.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const SCUnit = require("../SCUnit"); 3 | const SCUnitRepository = require("../SCUnitRepository"); 4 | const dspProcess = {}; 5 | class SCUnitZeroCrossing extends SCUnit { 6 | initialize(rate) { 7 | this.dspProcess = dspProcess["next"]; 8 | this._sampleRate = rate.sampleRate; 9 | this._prevfrac = 0; 10 | this._previn = this.inputs[0][0]; 11 | this._counter = 0; 12 | this.outputs[0][0] = this._level = 0; 13 | } 14 | } 15 | dspProcess["next"] = function (inNumSamples) { 16 | const out = this.outputs[0]; 17 | const inIn = this.inputs[0]; 18 | const sampleRate = this._sampleRate; 19 | let previn = this._previn; 20 | let prevfrac = this._prevfrac; 21 | let level = this._level; 22 | let counter = this._counter; 23 | for (let i = 0; i < inNumSamples; i++) { 24 | const curin = inIn[i]; 25 | counter += 1; 26 | if (counter > 4 && previn <= 0 && curin > 0) { 27 | const frac = -previn / (curin - previn); 28 | level = sampleRate / (frac + counter - prevfrac); 29 | prevfrac = frac; 30 | counter = 0; 31 | } 32 | out[i] = level; 33 | previn = curin; 34 | } 35 | this._previn = previn; 36 | this._prevfrac = prevfrac; 37 | this._level = level; 38 | this._counter = counter; 39 | }; 40 | SCUnitRepository.registerSCUnitClass("ZeroCrossing", SCUnitZeroCrossing); 41 | module.exports = SCUnitZeroCrossing; 42 | -------------------------------------------------------------------------------- /src/unit/_delay.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const log001 = Math.log(0.001); 4 | 5 | function feedback(delaytime, decaytime) { 6 | if (delaytime === 0 || decaytime === 0) { 7 | return 0; 8 | } 9 | if (decaytime > 0) { 10 | return +Math.exp(log001 * delaytime / +decaytime); 11 | } else { 12 | return -Math.exp(log001 * delaytime / -decaytime); 13 | } 14 | } 15 | 16 | module.exports = { feedback }; 17 | -------------------------------------------------------------------------------- /src/unit/_demand.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const C = require("../Constants"); 4 | 5 | function isDemand(unit, index) { 6 | const fromUnit = unit.inputSpecs[index].unit; 7 | 8 | return fromUnit && fromUnit.calcRate === C.RATE_DEMAND; 9 | } 10 | 11 | function next(unit, index, inNumSamples) { 12 | const fromUnit = unit.inputSpecs[index].unit; 13 | 14 | if (fromUnit) { 15 | switch (fromUnit.calcRate) { 16 | case C.RATE_AUDIO: 17 | return unit.inputs[index][inNumSamples - 1]; 18 | case C.RATE_DEMAND: 19 | fromUnit.dspProcess(inNumSamples); 20 | /* fall through */ 21 | } 22 | } 23 | 24 | return unit.inputs[index][0]; 25 | } 26 | 27 | function reset(unit, index) { 28 | const fromUnit = unit.inputSpecs[index].unit; 29 | 30 | if (fromUnit && fromUnit.calcRate === C.RATE_DEMAND) { 31 | fromUnit.dspProcess(0); 32 | } 33 | } 34 | 35 | module.exports = { isDemand, next, reset }; 36 | -------------------------------------------------------------------------------- /src/unit/_sine.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const kSineSize = 8192; 4 | const kSineMask = kSineSize - 1; 5 | const kBadValue = new Float32Array([ 1e20 ])[0]; 6 | const gSine = new Float32Array(kSineSize + 1); 7 | const gInvSine = new Float32Array(kSineSize + 1); 8 | const gSineWavetable = new Float32Array(kSineSize * 2); 9 | 10 | function makeSine() { 11 | for (let i = 0; i < kSineSize; i++) { 12 | const d = Math.sin((i / kSineSize) * 2 * Math.PI); 13 | 14 | gSine[i] = d; 15 | gInvSine[i] = 1 / d; 16 | } 17 | gSine[kSineSize] = gSine[0]; 18 | gInvSine[0] = gInvSine[kSineSize >> 1] = gInvSine[kSineSize] = kBadValue; 19 | 20 | const sz1 = kSineSize; 21 | const sz2 = sz1 >> 1; 22 | 23 | for (let i = 1; i <= 8; i++) { 24 | gInvSine[i] = gInvSine[sz1 - i] = gInvSine[sz2 - i] = gInvSine[sz2 + i] = kBadValue; 25 | } 26 | } 27 | 28 | function makeSineWaveTable() { 29 | let val1, val2; 30 | let j = 0; 31 | 32 | for (let i = 0; i < kSineSize - 1; i++) { 33 | val1 = gSine[i]; 34 | val2 = gSine[i + 1]; 35 | gSineWavetable[j++] = 2 * val1 - val2; 36 | gSineWavetable[j++] = val2 - val1; 37 | } 38 | 39 | val1 = gSine[kSineSize - 1]; 40 | val2 = gSine[0]; 41 | gSineWavetable[j++] = 2 * val1 - val2; 42 | gSineWavetable[j++] = val2 - val1; 43 | } 44 | 45 | makeSine(); 46 | makeSineWaveTable(); 47 | 48 | module.exports = { kSineSize, kSineMask, kBadValue, gSine, gInvSine, gSineWavetable }; 49 | -------------------------------------------------------------------------------- /src/util/clamp.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function clamp(value, minValue, maxValue) { 4 | return Math.max(minValue, Math.min(value, maxValue)); 5 | } 6 | 7 | module.exports = clamp; 8 | -------------------------------------------------------------------------------- /src/util/fill.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function fill(list, value) { 4 | if (list.fill) { 5 | return list.fill(value); 6 | } 7 | 8 | for (let i = 0, imax = list.length; i < imax; i++) { 9 | list[i] = value; 10 | } 11 | 12 | return list; 13 | } 14 | 15 | module.exports = fill; 16 | -------------------------------------------------------------------------------- /src/util/fillRange.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function fillRange(list, value, start, end) { 4 | if (list.fill) { 5 | return list.fill(value, start, end); 6 | } 7 | 8 | for (let i = start; i < end; i++) { 9 | list[i] = value; 10 | } 11 | 12 | return list; 13 | } 14 | 15 | module.exports = fillRange; 16 | -------------------------------------------------------------------------------- /src/util/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports.clamp = require("./clamp"); 4 | module.exports.fill = require("./fill"); 5 | module.exports.fillRange = require("./fillRange"); 6 | module.exports.sc_cubicinterp = require("./sc_cubicinterp"); 7 | module.exports.sc_exprandrange = require("./sc_exprandrange"); 8 | module.exports.sc_fold = require("./sc_fold"); 9 | module.exports.sc_randrange = require("./sc_randrange"); 10 | module.exports.sc_wrap = require("./sc_wrap"); 11 | module.exports.toNumber = require("./toNumber"); 12 | module.exports.toPowerOfTwo = require("./toPowerOfTwo"); 13 | module.exports.toValidBlockSize = require("./toValidBlockSize"); 14 | module.exports.toValidNumberOfAudioBus = require("./toValidNumberOfAudioBus"); 15 | module.exports.toValidNumberOfChannels = require("./toValidNumberOfChannels"); 16 | module.exports.toValidNumberOfControlBus = require("./toValidNumberOfControlBus"); 17 | module.exports.toValidSampleRate = require("./toValidSampleRate"); 18 | -------------------------------------------------------------------------------- /src/util/sc_cubicinterp.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function cubicinterp(x, y0, y1, y2, y3) { 4 | const c0 = y1; 5 | const c1 = 0.5 * (y2 - y0); 6 | const c2 = y0 - 2.5 * y1 + 2 * y2 - 0.5 * y3; 7 | const c3 = 0.5 * (y3 - y0) + 1.5 * (y1 - y2); 8 | 9 | return ((c3 * x + c2) * x + c1) * x + c0; 10 | } 11 | 12 | module.exports = cubicinterp; 13 | -------------------------------------------------------------------------------- /src/util/sc_exprandrange.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function sc_exprandrange(a, b) { 4 | if (a < b) { 5 | return a * Math.exp(Math.log(b / a) * Math.random()); 6 | } 7 | return b * Math.exp(Math.log(a / b) * Math.random()); 8 | } 9 | 10 | module.exports = sc_exprandrange; 11 | -------------------------------------------------------------------------------- /src/util/sc_fold.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function fold(val, lo, hi) { 4 | if (hi === lo) { 5 | return lo; 6 | } 7 | 8 | if (val >= hi) { 9 | val = (hi * 2) - val; 10 | if (val >= lo) { 11 | return val; 12 | } 13 | } else if (val < lo) { 14 | val = (lo * 2) - val; 15 | if (val < hi) { 16 | return val; 17 | } 18 | } else { 19 | return val; 20 | } 21 | 22 | const range1 = hi - lo; 23 | const range2 = range1 * 2; 24 | 25 | let x = (val - lo); 26 | 27 | x -= range2 * Math.floor(x / range2); 28 | 29 | if (x >= range1) { 30 | return range2 - x + lo; 31 | } 32 | 33 | return x + lo; 34 | } 35 | 36 | module.exports = fold; 37 | -------------------------------------------------------------------------------- /src/util/sc_randrange.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function sc_randrange(a, b) { 4 | if (a < b) { 5 | return Math.random() * (b - a) + a; 6 | } 7 | return Math.random() * (a - b) + b; 8 | } 9 | 10 | module.exports = sc_randrange; 11 | -------------------------------------------------------------------------------- /src/util/sc_wrap.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function wrap(val, lo, hi) { 4 | if (hi === lo) { 5 | return lo; 6 | } 7 | 8 | const range = (hi - lo); 9 | 10 | if (val >= hi) { 11 | val -= range; 12 | if (val < hi) { 13 | return val; 14 | } 15 | } else if (val < lo) { 16 | val += range; 17 | if (val >= lo) { 18 | return val; 19 | } 20 | } else { 21 | return val; 22 | } 23 | 24 | return val - range * Math.floor((val - lo) / range); 25 | } 26 | 27 | module.exports = wrap; 28 | -------------------------------------------------------------------------------- /src/util/toNumber.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function toNumber(value) { 4 | return +value || 0; 5 | } 6 | 7 | module.exports = toNumber; 8 | -------------------------------------------------------------------------------- /src/util/toPowerOfTwo.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function toPowerOfTwo(value, round) { 4 | round = round || Math.round; 5 | return 1 << round(Math.log(value) / Math.log(2)); 6 | } 7 | 8 | module.exports = toPowerOfTwo; 9 | -------------------------------------------------------------------------------- /src/util/toValidBlockSize.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const clamp = require("./clamp"); 4 | const toPowerOfTwo = require("./toPowerOfTwo"); 5 | const MIN_BLOCK_SIZE = 8; 6 | const MAX_BLOCK_SIZE = 1024; 7 | 8 | function toValidBlockSize(value) { 9 | return clamp(toPowerOfTwo(value), MIN_BLOCK_SIZE, MAX_BLOCK_SIZE); 10 | } 11 | 12 | module.exports = toValidBlockSize; 13 | -------------------------------------------------------------------------------- /src/util/toValidNumberOfAudioBus.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const toNumber = require("./toNumber"); 4 | const clamp = require("./clamp"); 5 | 6 | const MIN_NUMBER_OF_AUDIO_BUS = 2; 7 | const MAX_NUMBER_OF_AUDIO_BUS = 1024; 8 | 9 | function toValidNumberOfAudioBus(value) { 10 | return clamp(toNumber(value), MIN_NUMBER_OF_AUDIO_BUS, MAX_NUMBER_OF_AUDIO_BUS)|0; 11 | } 12 | 13 | module.exports = toValidNumberOfAudioBus; 14 | -------------------------------------------------------------------------------- /src/util/toValidNumberOfChannels.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const toNumber = require("./toNumber"); 4 | const clamp = require("./clamp"); 5 | 6 | const MAX_NUMBER_OF_CHANNELS = 32; 7 | 8 | function toValidNumberOfChannels(value) { 9 | return clamp(toNumber(value), 1, MAX_NUMBER_OF_CHANNELS)|0; 10 | } 11 | 12 | module.exports = toValidNumberOfChannels; 13 | -------------------------------------------------------------------------------- /src/util/toValidNumberOfControlBus.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const toNumber = require("./toNumber"); 4 | const clamp = require("./clamp"); 5 | 6 | const MIN_NUMBER_OF_AUDIO_BUS = 2; 7 | const MAX_NUMBER_OF_AUDIO_BUS = 1024; 8 | 9 | function toValidNumberOfControlBus(value) { 10 | return clamp(toNumber(value), MIN_NUMBER_OF_AUDIO_BUS, MAX_NUMBER_OF_AUDIO_BUS)|0; 11 | } 12 | 13 | module.exports = toValidNumberOfControlBus; 14 | -------------------------------------------------------------------------------- /src/util/toValidSampleRate.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const toNumber = require("./toNumber"); 4 | const clamp = require("./clamp"); 5 | 6 | const MIN_SAMPLERATE = 3000; 7 | const MAX_SAMPLERATE = 192000; 8 | 9 | function toValidSampleRate(value) { 10 | return clamp(toNumber(value), MIN_SAMPLERATE, MAX_SAMPLERATE)|0; 11 | } 12 | 13 | module.exports = toValidSampleRate; 14 | -------------------------------------------------------------------------------- /test/synth.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const scsynth = require("../src"); 6 | 7 | const synthdef = { 8 | name: "sine", 9 | consts: [], 10 | paramValues: [ 0.5, 440, 880 ], 11 | paramIndices: { amp: { index: 0, length: 1 }, freq: { index: 1, length: 2 } }, 12 | units: [] 13 | }; 14 | 15 | const context = new scsynth.SCContext(); 16 | const synth = context.createSynth(synthdef); 17 | 18 | test("get param", () => { 19 | assert(synth.$amp === 0.5); 20 | assert.deepEqual(synth.$freq, [ 440, 880 ]); 21 | }); 22 | 23 | test("set param", () => { 24 | synth.$amp = 0.25; 25 | synth.$freq = [ 330, 660 ]; 26 | 27 | assert(synth.$amp === 0.25); 28 | assert.deepEqual(synth.$freq, [ 330, 660 ]); 29 | assert.deepEqual(synth.params, [ 0.25, 330, 660 ]); 30 | 31 | synth.$freq[1] = 440; 32 | assert.deepEqual(synth.params, [ 0.25, 330, 440 ]); 33 | }); 34 | -------------------------------------------------------------------------------- /test/unit/SCUnitA2K.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const nmap = require("nmap"); 6 | const scsynth = require("../../src"); 7 | 8 | test("a", () => { 9 | const context = new scsynth.SCContext({ blockSize: 64 }); 10 | const noise0 = new Float32Array(nmap(64, Math.random)); 11 | const synthdef = { 12 | name: "A2KTest", 13 | consts: [ 0 ], 14 | paramValues: {}, 15 | paramIndices: {}, 16 | units: [ 17 | [ "DC" , 2, 0, [ [ -1, 0 ] ], [ 2 ] ], 18 | [ "A2K", 1, 0, [ [ 0, 0 ] ], [ 1 ] ], 19 | [ "Out", 1, 0, [ [ -1, 0 ], [ 1, 0 ] ], [ ] ] 20 | ] 21 | }; 22 | const synth = context.createSynth(synthdef).appendTo(context); 23 | const actual = context.controlBuses[0]; 24 | 25 | { 26 | synth.unitList[0].outputs[0].set(noise0); // in 27 | context.process(); 28 | 29 | const expected = new Float32Array([ noise0[0] ]); 30 | 31 | // for (let i = 0; i < 1; i++) { 32 | // console.log(actual[i]); 33 | // } 34 | 35 | assert.deepEqual(actual, expected); 36 | } 37 | }); 38 | -------------------------------------------------------------------------------- /test/unit/SCUnitAPF.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const nmap = require("nmap"); 6 | const scsynth = require("../../src"); 7 | 8 | test("akk", () => { 9 | const context = new scsynth.SCContext({ blockSize: 64 }); 10 | const noise0 = new Float32Array(nmap(64, Math.random)); 11 | const synthdef = { 12 | name: "APFTest", 13 | consts: [ 0, 0, 350, 1 ], 14 | paramValues: {}, 15 | paramIndices: {}, 16 | units: [ 17 | [ "DC" , 2, 0, [ [ -1, 1 ] ], [ 2 ] ], 18 | [ "DC" , 1, 0, [ [ -1, 2 ] ], [ 1 ] ], 19 | [ "DC" , 1, 0, [ [ -1, 3 ] ], [ 1 ] ], 20 | [ "APF", 2, 0, [ [ 0, 0 ], [ 1, 0 ], [ 2, 0 ] ], [ 2 ] ], 21 | [ "Out", 2, 0, [ [ -1, 0 ], [ 3, 0 ] ], [ ] ] 22 | ] 23 | }; 24 | const synth = context.createSynth(synthdef).appendTo(context); 25 | const actual = context.audioBuses[0]; 26 | 27 | { 28 | synth.unitList[0].outputs[0].set(noise0); // in 29 | context.process(); 30 | 31 | const expected = x => Math.abs(x) < 1 + 1e-6; 32 | 33 | // for (let i = 0; i < 64; i++) { 34 | // console.log(actual[i]); 35 | // } 36 | 37 | assert(actual.every(expected)); 38 | } 39 | }); 40 | -------------------------------------------------------------------------------- /test/unit/SCUnitBPF.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const nmap = require("nmap"); 6 | const scsynth = require("../../src"); 7 | 8 | test("akk", () => { 9 | const context = new scsynth.SCContext({ blockSize: 64 }); 10 | const noise0 = new Float32Array(nmap(64, Math.random)); 11 | const synthdef = { 12 | name: "BPFTest", 13 | consts: [ 0, 0, 350, 1 ], 14 | paramValues: {}, 15 | paramIndices: {}, 16 | units: [ 17 | [ "DC" , 2, 0, [ [ -1, 1 ] ], [ 2 ] ], 18 | [ "DC" , 1, 0, [ [ -1, 2 ] ], [ 1 ] ], 19 | [ "DC" , 1, 0, [ [ -1, 3 ] ], [ 1 ] ], 20 | [ "BPF", 2, 0, [ [ 0, 0 ], [ 1, 0 ], [ 2, 0 ] ], [ 2 ] ], 21 | [ "Out", 2, 0, [ [ -1, 0 ], [ 3, 0 ] ], [ ] ] 22 | ] 23 | }; 24 | const synth = context.createSynth(synthdef).appendTo(context); 25 | const actual = context.audioBuses[0]; 26 | 27 | { 28 | synth.unitList[0].outputs[0].set(noise0); // in 29 | context.process(); 30 | 31 | const expected = x => Math.abs(x) < 1 + 1e-6; 32 | 33 | // for (let i = 0; i < 64; i++) { 34 | // console.log(actual[i]); 35 | // } 36 | 37 | assert(actual.every(expected)); 38 | } 39 | }); 40 | -------------------------------------------------------------------------------- /test/unit/SCUnitBRF.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const nmap = require("nmap"); 6 | const scsynth = require("../../src"); 7 | 8 | test("akk", () => { 9 | const context = new scsynth.SCContext({ blockSize: 64 }); 10 | const noise0 = new Float32Array(nmap(64, Math.random)); 11 | const synthdef = { 12 | name: "BRFTest", 13 | consts: [ 0, 0, 350, 1 ], 14 | paramValues: {}, 15 | paramIndices: {}, 16 | units: [ 17 | [ "DC" , 2, 0, [ [ -1, 1 ] ], [ 2 ] ], 18 | [ "DC" , 1, 0, [ [ -1, 2 ] ], [ 1 ] ], 19 | [ "DC" , 1, 0, [ [ -1, 3 ] ], [ 1 ] ], 20 | [ "BRF", 2, 0, [ [ 0, 0 ], [ 1, 0 ], [ 2, 0 ] ], [ 2 ] ], 21 | [ "Out", 2, 0, [ [ -1, 0 ], [ 3, 0 ] ], [ ] ] 22 | ] 23 | }; 24 | const synth = context.createSynth(synthdef).appendTo(context); 25 | const actual = context.audioBuses[0]; 26 | 27 | { 28 | synth.unitList[0].outputs[0].set(noise0); // in 29 | context.process(); 30 | 31 | const expected = x => Math.abs(x) < 1 + 1e-6; 32 | 33 | // for (let i = 0; i < 64; i++) { 34 | // console.log(actual[i]); 35 | // } 36 | 37 | assert(actual.every(expected)); 38 | } 39 | }); 40 | -------------------------------------------------------------------------------- /test/unit/SCUnitBrownNoise.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const scsynth = require("../../src"); 6 | 7 | test("a", () => { 8 | const context = new scsynth.SCContext({ blockSize: 64 }); 9 | const synthdef = { 10 | name: "BrownNoiseTest", 11 | consts: [ 0 ], 12 | paramValues: {}, 13 | paramIndices: {}, 14 | units: [ 15 | [ "BrownNoise", 2, 0, [ ], [ 2 ] ], 16 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 0, 0 ] ], [ ] ] 17 | ] 18 | }; 19 | const synth = context.createSynth(synthdef).appendTo(context); 20 | const actual = context.audioBuses[0]; 21 | 22 | { 23 | synth.unitList[0].outputs[0]; 24 | context.process(); 25 | 26 | const expected = x => -1 <= x && x <= 1; 27 | 28 | // for (let i = 0; i < 64; i++) { 29 | // console.log(actual[i]); 30 | // } 31 | 32 | assert(actual.every(expected)); 33 | } 34 | }); 35 | -------------------------------------------------------------------------------- /test/unit/SCUnitClipNoise.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const scsynth = require("../../src"); 6 | 7 | test("a", () => { 8 | const context = new scsynth.SCContext({ blockSize: 64 }); 9 | const synthdef = { 10 | name: "ClipNoiseTest", 11 | consts: [ 0 ], 12 | paramValues: {}, 13 | paramIndices: {}, 14 | units: [ 15 | [ "ClipNoise", 2, 0, [ ], [ 2 ] ], 16 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 0, 0 ] ], [ ] ] 17 | ] 18 | }; 19 | const synth = context.createSynth(synthdef).appendTo(context); 20 | const actual = context.audioBuses[0]; 21 | 22 | { 23 | synth.unitList[0].outputs[0]; 24 | context.process(); 25 | 26 | const expected = x => x === -1 || x === +1; 27 | 28 | // for (let i = 0; i < 64; i++) { 29 | // console.log(actual[i]); 30 | // } 31 | 32 | assert(actual.every(expected)); 33 | } 34 | }); 35 | -------------------------------------------------------------------------------- /test/unit/SCUnitCrackle.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const scsynth = require("../../src"); 6 | 7 | test("k", () => { 8 | const context = new scsynth.SCContext({ blockSize: 64 }); 9 | const synthdef = { 10 | name: "CrackleTest", 11 | consts: [ 0, 2 ], 12 | paramValues: {}, 13 | paramIndices: {}, 14 | units: [ 15 | [ "DC" , 1, 0, [ [ -1, 1 ] ], [ 1 ] ], 16 | [ "Crackle", 2, 0, [ [ 0, 0 ] ], [ 2 ] ], 17 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 1, 0 ] ], [ ] ] 18 | ] 19 | }; 20 | const synth = context.createSynth(synthdef).appendTo(context); 21 | const actual = context.audioBuses[0]; 22 | 23 | for (let n = 0; n < 10; n++) { 24 | synth.unitList[0].outputs[0]; 25 | context.process(); 26 | 27 | const expected = Number.isFinite; 28 | 29 | // for (let i = 0; i < 64; i++) { 30 | // console.log(actual[i]); 31 | // } 32 | 33 | assert(actual.every(expected)); 34 | } 35 | }); 36 | -------------------------------------------------------------------------------- /test/unit/SCUnitDelay1.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const nmap = require("nmap"); 6 | const scsynth = require("../../src"); 7 | 8 | test("akk", () => { 9 | const context = new scsynth.SCContext({ blockSize: 64 }); 10 | const noise0 = new Float32Array(nmap(64, Math.random)); 11 | const synthdef = { 12 | name: "Delay1Test", 13 | consts: [ 0, 0 ], 14 | paramValues: {}, 15 | paramIndices: {}, 16 | units: [ 17 | [ "DC" , 2, 0, [ [ -1, 1 ] ], [ 2 ] ], 18 | [ "Delay1", 2, 0, [ [ 0, 0 ] ], [ 2 ] ], 19 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 1, 0 ] ], [ ] ] 20 | ] 21 | }; 22 | const synth = context.createSynth(synthdef).appendTo(context); 23 | const actual = context.audioBuses[0]; 24 | 25 | { 26 | synth.unitList[0].outputs[0].set(noise0); // in 27 | context.process(); 28 | 29 | const expected = (x, i) => i < 1 ? true : x === noise0[i - 1]; 30 | 31 | // for (let i = 0; i < 64; i++) { 32 | // console.log(actual[i]); 33 | // } 34 | 35 | assert(actual.every(expected)); 36 | } 37 | }); 38 | -------------------------------------------------------------------------------- /test/unit/SCUnitDelay2.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const nmap = require("nmap"); 6 | const scsynth = require("../../src"); 7 | 8 | test("akk", () => { 9 | const context = new scsynth.SCContext({ blockSize: 64 }); 10 | const noise0 = new Float32Array(nmap(64, Math.random)); 11 | const synthdef = { 12 | name: "Delay2Test", 13 | consts: [ 0, 0 ], 14 | paramValues: {}, 15 | paramIndices: {}, 16 | units: [ 17 | [ "DC" , 2, 0, [ [ -1, 1 ] ], [ 2 ] ], 18 | [ "Delay2", 2, 0, [ [ 0, 0 ] ], [ 2 ] ], 19 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 1, 0 ] ], [ ] ] 20 | ] 21 | }; 22 | const synth = context.createSynth(synthdef).appendTo(context); 23 | const actual = context.audioBuses[0]; 24 | 25 | { 26 | synth.unitList[0].outputs[0].set(noise0); // in 27 | context.process(); 28 | 29 | const expected = (x, i) => i < 2 ? true : x === noise0[i - 2]; 30 | 31 | // for (let i = 0; i < 64; i++) { 32 | // console.log(actual[i]); 33 | // } 34 | 35 | assert(actual.every(expected)); 36 | } 37 | }); 38 | -------------------------------------------------------------------------------- /test/unit/SCUnitDgeom.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const SCRandom = require("sc-random"); 6 | const scsynth = require("../../src"); 7 | 8 | test.fork("d", () => { 9 | Math.random = new SCRandom(12345).random; 10 | 11 | const context = new scsynth.SCContext({ blockSize: 8 }); 12 | const synthdef = { 13 | name: "DgeomTest", 14 | consts: [ 0, 7, 3, 2 ], 15 | paramValues: {}, 16 | paramIndices: {}, 17 | units: [ 18 | [ "DC" , 2, 0, [ [ -1, 0 ] ], [ 2 ] ], 19 | [ "Dgeom" , 3, 0, [ [ -1, 1 ], [ -1, 2 ], [ -1, 3 ] ], [ 3 ] ], 20 | [ "Demand", 2, 0, [ [ 0, 0 ], [ -1, 0 ], [ 1, 0 ] ], [ 2 ] ], 21 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 2, 0 ], ], [ ] ] 22 | ] 23 | }; 24 | const synth = context.createSynth(synthdef).appendTo(context); 25 | const actual = context.audioBuses[0]; 26 | 27 | { 28 | synth.unitList[0].outputs[0].set([ 1, 0, 1, 0, 1, 0, 1, 0 ]); 29 | context.process(); 30 | 31 | const expected = new Float32Array([ 3, 3, 6, 6, 12, 12, 24, 24 ]); 32 | 33 | // for (let i = 0; i < 8; i++) { 34 | // console.log(actual[i]); 35 | // } 36 | 37 | assert.deepEqual(actual, expected); 38 | } 39 | { 40 | synth.unitList[0].outputs[0].set([ 1, 0, 1, 0, 1, 0, 1, 0 ]); 41 | context.process(); 42 | 43 | const expected = new Float32Array([ 48, 48, 96, 96, 192, 192, 192, 192 ]); 44 | 45 | // for (let i = 0; i < 8; i++) { 46 | // console.log(actual[i]); 47 | // } 48 | 49 | assert.deepEqual(actual, expected); 50 | } 51 | }); 52 | -------------------------------------------------------------------------------- /test/unit/SCUnitDreset.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const SCRandom = require("sc-random"); 6 | const scsynth = require("../../src"); 7 | 8 | test.fork("d", () => { 9 | Math.random = new SCRandom(12345).random; 10 | 11 | const context = new scsynth.SCContext({ blockSize: 8 }); 12 | const synthdef = { 13 | name: "DresetTest", 14 | consts: [ 0, Infinity, 1, 2, 3 ], 15 | paramValues: {}, 16 | paramIndices: {}, 17 | units: [ 18 | [ "DC" , 2, 0, [ [ -1, 0 ] ], [ 2 ] ], 19 | [ "DC" , 1, 0, [ [ -1, 0 ] ], [ 1 ] ], 20 | [ "Dser" , 3, 0, [ [ -1, 1 ], [ -1, 2 ], [ -1, 3 ], [ -1, 4 ] ], [ 3 ] ], 21 | [ "Dreset", 3, 0, [ [ 2, 0 ], [ 1, 0 ] ], [ 3 ] ], 22 | [ "Demand", 2, 0, [ [ 0, 0 ], [ -1, 0 ], [ 3, 0 ] ], [ 2 ] ], 23 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 4, 0 ], ], [ ] ] 24 | ] 25 | }; 26 | const synth = context.createSynth(synthdef).appendTo(context); 27 | const actual = context.audioBuses[0]; 28 | 29 | { 30 | synth.unitList[0].outputs[0].set([ 1, 0, 1, 0, 1, 0, 1, 0 ]); 31 | synth.unitList[1].outputs[0].set([ 0 ]); 32 | context.process(); 33 | 34 | const expected = new Float32Array([ 1, 1, 2, 2, 3, 3, 1, 1 ]); 35 | 36 | // for (let i = 0; i < 8; i++) { 37 | // console.log(actual[i]); 38 | // } 39 | 40 | assert.deepEqual(actual, expected); 41 | } 42 | { 43 | synth.unitList[0].outputs[0].set([ 1, 0, 1, 0, 1, 0, 1, 0 ]); 44 | synth.unitList[1].outputs[0].set([ 1 ]); 45 | context.process(); 46 | 47 | const expected = new Float32Array([ 2, 2, 1, 1, 2, 2, 3, 3 ]); 48 | 49 | // for (let i = 0; i < 8; i++) { 50 | // console.log(actual[i]); 51 | // } 52 | 53 | assert.deepEqual(actual, expected); 54 | } 55 | }); 56 | -------------------------------------------------------------------------------- /test/unit/SCUnitDseries.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const SCRandom = require("sc-random"); 6 | const scsynth = require("../../src"); 7 | 8 | test.fork("d", () => { 9 | Math.random = new SCRandom(12345).random; 10 | 11 | const context = new scsynth.SCContext({ blockSize: 8 }); 12 | const synthdef = { 13 | name: "DseriesTest", 14 | consts: [ 0, 7, 10, 4 ], 15 | paramValues: {}, 16 | paramIndices: {}, 17 | units: [ 18 | [ "DC" , 2, 0, [ [ -1, 0 ] ], [ 2 ] ], 19 | [ "Dseries", 3, 0, [ [ -1, 1 ], [ -1, 2 ], [ -1, 3 ] ], [ 3 ] ], 20 | [ "Demand" , 2, 0, [ [ 0, 0 ], [ -1, 0 ], [ 1, 0 ] ], [ 2 ] ], 21 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 2, 0 ], ], [ ] ] 22 | ] 23 | }; 24 | const synth = context.createSynth(synthdef).appendTo(context); 25 | const actual = context.audioBuses[0]; 26 | 27 | { 28 | synth.unitList[0].outputs[0].set([ 1, 0, 1, 0, 1, 0, 1, 0 ]); 29 | context.process(); 30 | 31 | const expected = new Float32Array([ 10, 10, 14, 14, 18, 18, 22, 22 ]); 32 | 33 | // for (let i = 0; i < 8; i++) { 34 | // console.log(actual[i]); 35 | // } 36 | 37 | assert.deepEqual(actual, expected); 38 | } 39 | { 40 | synth.unitList[0].outputs[0].set([ 1, 0, 1, 0, 1, 0, 1, 0 ]); 41 | context.process(); 42 | 43 | const expected = new Float32Array([ 26, 26, 30, 30, 34, 34, 34, 34 ]); 44 | 45 | // for (let i = 0; i < 8; i++) { 46 | // console.log(actual[i]); 47 | // } 48 | 49 | assert.deepEqual(actual, expected); 50 | } 51 | }); 52 | -------------------------------------------------------------------------------- /test/unit/SCUnitDstutter.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const SCRandom = require("sc-random"); 6 | const scsynth = require("../../src"); 7 | 8 | test.fork("d", () => { 9 | Math.random = new SCRandom(12345).random; 10 | 11 | const context = new scsynth.SCContext({ blockSize: 8 }); 12 | const synthdef = { 13 | name: "DstutterTest", 14 | consts: [ 0, 6, 1, 2, 3 ], 15 | paramValues: {}, 16 | paramIndices: {}, 17 | units: [ 18 | [ "DC" , 2, 0, [ [ -1, 0 ] ], [ 2 ] ], 19 | [ "DC" , 1, 0, [ [ -1, 0 ] ], [ 1 ] ], 20 | [ "Dser" , 3, 0, [ [ -1, 1 ], [ -1, 2 ], [ -1, 3 ], [ -1, 4 ] ], [ 3 ] ], 21 | [ "Dstutter", 3, 0, [ [ 1, 0 ], [ 2, 0 ] ], [ 3 ] ], 22 | [ "Demand" , 2, 0, [ [ 0, 0 ], [ -1, 0 ], [ 3, 0 ] ], [ 2 ] ], 23 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 4, 0 ], ], [ ] ] 24 | ] 25 | }; 26 | const synth = context.createSynth(synthdef).appendTo(context); 27 | const actual = context.audioBuses[0]; 28 | 29 | { 30 | synth.unitList[0].outputs[0].set([ 1, 0, 1, 0, 1, 0, 1, 0 ]); 31 | synth.unitList[1].outputs[0].set([ 2 ]); 32 | context.process(); 33 | 34 | const expected = new Float32Array([ 1, 1, 1, 1, 2, 2, 2, 2 ]); 35 | 36 | // for (let i = 0; i < 8; i++) { 37 | // console.log(actual[i]); 38 | // } 39 | 40 | assert.deepEqual(actual, expected); 41 | } 42 | { 43 | synth.unitList[0].outputs[0].set([ 1, 0, 1, 0, 1, 0, 1, 0 ]); 44 | synth.unitList[1].outputs[0].set([ 1 ]); 45 | context.process(); 46 | 47 | const expected = new Float32Array([ 3, 3, 1, 1, 2, 2, 3, 3 ]); 48 | 49 | // for (let i = 0; i < 8; i++) { 50 | // console.log(actual[i]); 51 | // } 52 | 53 | assert.deepEqual(actual, expected); 54 | } 55 | }); 56 | -------------------------------------------------------------------------------- /test/unit/SCUnitDswitch.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const scsynth = require("../../src"); 6 | 7 | test("d", () => { 8 | const context = new scsynth.SCContext({ blockSize: 8 }); 9 | const synthdef = { 10 | name: "OutTest", 11 | consts: [ 0, 6, 1, 2, 3, 4, 5, 6 ], 12 | paramValues: {}, 13 | paramIndices: {}, 14 | units: [ 15 | [ "DC" , 2, 0, [ [ -1, 0 ] ], [ 2 ] ], 16 | [ "DC" , 1, 0, [ [ -1, 0 ] ], [ 1 ] ], 17 | [ "Dser" , 3, 0, [ [ -1, 1 ], [ -1, 2 ], [ -1, 3 ], [ -1, 4 ] ], [ 3 ] ], 18 | [ "Dser" , 3, 0, [ [ -1, 1 ], [ -1, 5 ], [ -1, 6 ], [ -1, 7 ] ], [ 3 ] ], 19 | [ "Dswitch", 3, 0, [ [ 1, 0 ], [ 2, 0 ], [ 3, 0 ] ], [ 3 ] ], 20 | [ "Demand" , 2, 0, [ [ 0, 0 ], [ -1, 0 ], [ 4, 0 ] ], [ 2 ] ], 21 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 5, 0 ], ], [ ] ] 22 | ] 23 | }; 24 | const synth = context.createSynth(synthdef).appendTo(context); 25 | const actual = context.audioBuses[0]; 26 | 27 | { 28 | synth.unitList[0].outputs[0].set([ 1, 0, 1, 0, 1, 0, 1, 0 ]); 29 | synth.unitList[1].outputs[0].set([ 0 ]); 30 | context.process(); 31 | 32 | const expected = new Float32Array([ 1, 1, 2, 2, 3, 3, 1, 1 ]); 33 | 34 | // for (let i = 0; i < 8; i++) { 35 | // console.log(actual[i]); 36 | // } 37 | 38 | assert.deepEqual(actual, expected); 39 | } 40 | { 41 | synth.unitList[0].outputs[0].set([ 1, 0, 1, 0, 1, 0, 1, 0 ]); 42 | synth.unitList[1].outputs[0].set([ 1 ]); 43 | context.process(); 44 | 45 | const expected = new Float32Array([ 2, 2, 3, 3, 4, 4, 5, 5 ]); 46 | 47 | // for (let i = 0; i < 8; i++) { 48 | // console.log(actual[i]); 49 | // } 50 | 51 | assert.deepEqual(actual, expected); 52 | } 53 | }); 54 | -------------------------------------------------------------------------------- /test/unit/SCUnitDswitch1.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const scsynth = require("../../src"); 6 | 7 | test("d", () => { 8 | const context = new scsynth.SCContext({ blockSize: 8 }); 9 | const synthdef = { 10 | name: "OutTest", 11 | consts: [ 0, Infinity, 1, 2, 3, 4, 5, 6 ], 12 | paramValues: {}, 13 | paramIndices: {}, 14 | units: [ 15 | [ "DC" , 2, 0, [ [ -1, 0 ] ], [ 2 ] ], 16 | [ "DC" , 1, 0, [ [ -1, 0 ] ], [ 1 ] ], 17 | [ "Dser" , 3, 0, [ [ -1, 1 ], [ -1, 2 ], [ -1, 3 ], [ -1, 4 ] ], [ 3 ] ], 18 | [ "Dser" , 3, 0, [ [ -1, 1 ], [ -1, 5 ], [ -1, 6 ], [ -1, 7 ] ], [ 3 ] ], 19 | [ "Dswitch1", 3, 0, [ [ 1, 0 ], [ 2, 0 ], [ 3, 0 ] ], [ 3 ] ], 20 | [ "Demand" , 2, 0, [ [ 0, 0 ], [ -1, 0 ], [ 4, 0 ] ], [ 2 ] ], 21 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 5, 0 ], ], [ ] ] 22 | ] 23 | }; 24 | const synth = context.createSynth(synthdef).appendTo(context); 25 | const actual = context.audioBuses[0]; 26 | 27 | { 28 | synth.unitList[0].outputs[0].set([ 1, 0, 1, 0, 1, 0, 1, 0 ]); 29 | synth.unitList[1].outputs[0].set([ 0 ]); 30 | context.process(); 31 | 32 | const expected = new Float32Array([ 1, 1, 2, 2, 3, 3, 1, 1 ]); 33 | 34 | // for (let i = 0; i < 8; i++) { 35 | // console.log(actual[i]); 36 | // } 37 | 38 | assert.deepEqual(actual, expected); 39 | } 40 | { 41 | synth.unitList[0].outputs[0].set([ 1, 0, 1, 0, 1, 0, 1, 0 ]); 42 | synth.unitList[1].outputs[0].set([ 1 ]); 43 | context.process(); 44 | 45 | const expected = new Float32Array([ 4, 4, 5, 5, 6, 6, 4, 4 ]); 46 | 47 | // for (let i = 0; i < 8; i++) { 48 | // console.log(actual[i]); 49 | // } 50 | 51 | assert.deepEqual(actual, expected); 52 | } 53 | }); 54 | -------------------------------------------------------------------------------- /test/unit/SCUnitDust.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const scsynth = require("../../src"); 6 | 7 | test("k", () => { 8 | const context = new scsynth.SCContext({ blockSize: 64 }); 9 | const synthdef = { 10 | name: "DustTest", 11 | consts: [ 0, 350 ], 12 | paramValues: {}, 13 | paramIndices: {}, 14 | units: [ 15 | [ "DC" , 1, 0, [ [ -1, 1 ] ], [ 1 ] ], 16 | [ "Dust", 2, 0, [ [ 0, 0 ] ], [ 2 ] ], 17 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 1, 0 ] ], [ ] ] 18 | ] 19 | }; 20 | const synth = context.createSynth(synthdef).appendTo(context); 21 | const actual = context.audioBuses[0]; 22 | 23 | for (let n = 0; n < 10; n++) { 24 | synth.unitList[0].outputs[0]; 25 | context.process(); 26 | 27 | const expected = x => 0 <= x && x <= 1; 28 | 29 | // for (let i = 0; i < 64; i++) { 30 | // console.log(actual[i]); 31 | // } 32 | 33 | assert(actual.every(expected)); 34 | } 35 | }); 36 | -------------------------------------------------------------------------------- /test/unit/SCUnitDust2.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const scsynth = require("../../src"); 6 | 7 | test("k", () => { 8 | const context = new scsynth.SCContext({ blockSize: 64 }); 9 | const synthdef = { 10 | name: "Dust2Test", 11 | consts: [ 0, 350 ], 12 | paramValues: {}, 13 | paramIndices: {}, 14 | units: [ 15 | [ "DC" , 1, 0, [ [ -1, 1 ] ], [ 1 ] ], 16 | [ "Dust2", 2, 0, [ [ 0, 0 ] ], [ 2 ] ], 17 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 1, 0 ] ], [ ] ] 18 | ] 19 | }; 20 | const synth = context.createSynth(synthdef).appendTo(context); 21 | const actual = context.audioBuses[0]; 22 | 23 | for (let n = 0; n < 10; n++) { 24 | synth.unitList[0].outputs[0]; 25 | context.process(); 26 | 27 | const expected = x => -1 <= x && x <= 1; 28 | 29 | // for (let i = 0; i < 64; i++) { 30 | // console.log(actual[i]); 31 | // } 32 | 33 | assert(actual.every(expected)); 34 | } 35 | }); 36 | -------------------------------------------------------------------------------- /test/unit/SCUnitDwrand.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const SCRandom = require("sc-random"); 6 | const scsynth = require("../../src"); 7 | 8 | test.fork("d", () => { 9 | Math.random = new SCRandom(12345).random; 10 | 11 | const context = new scsynth.SCContext({ blockSize: 8 }); 12 | const synthdef = { 13 | name: "DwrandTest", 14 | consts: [ 0, 7, 3, 0.4, 0.35, 0.25, 5, 6, 7 ], 15 | paramValues: {}, 16 | paramIndices: {}, 17 | units: [ 18 | [ "DC" , 2, 0, [ [ -1, 0 ] ], [ 2 ] ], 19 | [ "Dwrand", 3, 0, [ [ -1, 1 ], [ -1, 2 ], [ -1, 3 ], [ -1, 4 ], [ -1, 5 ], [ -1, 6 ], [ -1, 7 ], [ -1, 8 ] ], [ 3 ] ], 20 | [ "Demand", 2, 0, [ [ 0, 0 ], [ -1, 0 ], [ 1, 0 ] ], [ 2 ] ], 21 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 2, 0 ], ], [ ] ] 22 | ] 23 | }; 24 | const synth = context.createSynth(synthdef).appendTo(context); 25 | const actual = context.audioBuses[0]; 26 | 27 | { 28 | synth.unitList[0].outputs[0].set([ 1, 0, 1, 0, 1, 0, 1, 0 ]); 29 | context.process(); 30 | 31 | const expected = new Float32Array([ 5, 5, 5, 5, 7, 7, 5, 5 ]); 32 | 33 | // for (let i = 0; i < 8; i++) { 34 | // console.log(actual[i]); 35 | // } 36 | 37 | assert.deepEqual(actual, expected); 38 | } 39 | { 40 | synth.unitList[0].outputs[0].set([ 1, 0, 1, 0, 1, 0, 1, 0 ]); 41 | context.process(); 42 | 43 | const expected = new Float32Array([ 5, 5, 5, 5, 6, 6, 6, 6 ]); 44 | 45 | // for (let i = 0; i < 8; i++) { 46 | // console.log(actual[i]); 47 | // } 48 | 49 | assert.deepEqual(actual, expected); 50 | } 51 | }); 52 | -------------------------------------------------------------------------------- /test/unit/SCUnitExpRand.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const scsynth = require("../../src"); 6 | 7 | test("ii", () => { 8 | const context = new scsynth.SCContext({ blockSize: 64 }); 9 | const synthdef = { 10 | name: "ExpRandTest", 11 | consts: [ 0, 10, 20 ], 12 | paramValues: {}, 13 | paramIndices: {}, 14 | units: [ 15 | [ "DC" , 1, 0, [ [ -1, 1 ] ], [ 1 ] ], 16 | [ "DC" , 1, 0, [ [ -1, 2 ] ], [ 1 ] ], 17 | [ "ExpRand", 0, 0, [ [ 0, 0 ], [ 1, 0 ] ], [ 0 ] ], 18 | [ "K2A" , 2, 0, [ [ 2, 0 ] ], [ 2 ] ], 19 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 3, 0 ] ], [ ] ] 20 | ] 21 | }; 22 | const synth = context.createSynth(synthdef).appendTo(context); 23 | const actual = context.audioBuses[0]; 24 | 25 | const expected = (x, i, list) => i === 0 ? (x === list[0]) : (10 <= x && x < 20); 26 | 27 | { 28 | synth.unitList[0].outputs[0]; 29 | context.process(); 30 | 31 | // for (let i = 0; i < 1; i++) { 32 | // console.log(actual[i]); 33 | // } 34 | 35 | assert(actual.every(expected)); 36 | } 37 | }); 38 | -------------------------------------------------------------------------------- /test/unit/SCUnitFreeVerb.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const nmap = require("nmap"); 6 | const scsynth = require("../../src"); 7 | 8 | test("akkk", () => { 9 | const context = new scsynth.SCContext({ blockSize: 64 }); 10 | const noise0 = new Float32Array(nmap(64, Math.random)); 11 | const synthdef = { 12 | name: "FreeVerbTest", 13 | consts: [ 0, 0.33, 0.5, 0.5 ], 14 | paramValues: {}, 15 | paramIndices: {}, 16 | units: [ 17 | [ "DC" , 2, 0, [ [ -1, 0 ] ], [ 2 ] ], 18 | [ "DC" , 1, 0, [ [ -1, 1 ] ], [ 1 ] ], 19 | [ "DC" , 1, 0, [ [ -1, 2 ] ], [ 1 ] ], 20 | [ "DC" , 1, 0, [ [ -1, 3 ] ], [ 1 ] ], 21 | [ "FreeVerb", 2, 0, [ [ 0, 0 ], [ 1, 0 ], [ 2, 0 ], [ 3, 0 ] ], [ 2 ] ], 22 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 4, 0 ] ], [ ] ] 23 | ] 24 | }; 25 | const synth = context.createSynth(synthdef).appendTo(context); 26 | const actual = context.audioBuses[0]; 27 | 28 | { 29 | synth.unitList[0].outputs[0].set(noise0); // in 30 | 31 | for (let i = 0; i < 64; i++) { 32 | context.process(); 33 | } 34 | 35 | const expected = Number.isFinite; 36 | 37 | // for (let i = 0; i < 64; i++) { 38 | // console.log(actual[i]); 39 | // } 40 | 41 | assert(actual.every(expected)); 42 | } 43 | }); 44 | -------------------------------------------------------------------------------- /test/unit/SCUnitGrayNoise.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const scsynth = require("../../src"); 6 | 7 | test("a", () => { 8 | const context = new scsynth.SCContext({ blockSize: 64 }); 9 | const synthdef = { 10 | name: "GrayNoiseTest", 11 | consts: [ 0 ], 12 | paramValues: {}, 13 | paramIndices: {}, 14 | units: [ 15 | [ "GrayNoise", 2, 0, [ ], [ 2 ] ], 16 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 0, 0 ] ], [ ] ] 17 | ] 18 | }; 19 | const synth = context.createSynth(synthdef).appendTo(context); 20 | const actual = context.audioBuses[0]; 21 | 22 | { 23 | synth.unitList[0].outputs[0]; 24 | context.process(); 25 | 26 | const expected = x => -1 <= x && x <= 1; 27 | 28 | // for (let i = 0; i < 64; i++) { 29 | // console.log(actual[i]); 30 | // } 31 | 32 | assert(actual.every(expected)); 33 | } 34 | }); 35 | -------------------------------------------------------------------------------- /test/unit/SCUnitHPF.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const nmap = require("nmap"); 6 | const scsynth = require("../../src"); 7 | 8 | test("akk", () => { 9 | const context = new scsynth.SCContext({ blockSize: 64 }); 10 | const noise0 = new Float32Array(nmap(64, Math.random)); 11 | const synthdef = { 12 | name: "HPFTest", 13 | consts: [ 0, 0, 350 ], 14 | paramValues: {}, 15 | paramIndices: {}, 16 | units: [ 17 | [ "DC" , 2, 0, [ [ -1, 1 ] ], [ 2 ] ], 18 | [ "DC" , 1, 0, [ [ -1, 2 ] ], [ 1 ] ], 19 | [ "HPF", 2, 0, [ [ 0, 0 ], [ 1, 0 ] ], [ 2 ] ], 20 | [ "Out", 2, 0, [ [ -1, 0 ], [ 2, 0 ] ], [ ] ] 21 | ] 22 | }; 23 | const synth = context.createSynth(synthdef).appendTo(context); 24 | const actual = context.audioBuses[0]; 25 | 26 | { 27 | synth.unitList[0].outputs[0].set(noise0); // in 28 | context.process(); 29 | 30 | const expected = x => Math.abs(x) < 1 + 1e-6; 31 | 32 | // for (let i = 0; i < 64; i++) { 33 | // console.log(actual[i]); 34 | // } 35 | 36 | assert(actual.every(expected)); 37 | } 38 | }); 39 | -------------------------------------------------------------------------------- /test/unit/SCUnitHasher.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const nmap = require("nmap"); 6 | const scsynth = require("../../src"); 7 | 8 | test("a", () => { 9 | const context = new scsynth.SCContext({ blockSize: 64 }); 10 | const noise0 = new Float32Array(nmap(64, Math.random)); 11 | const synthdef = { 12 | name: "HasherTest", 13 | consts: [ 0 ], 14 | paramValues: {}, 15 | paramIndices: {}, 16 | units: [ 17 | [ "DC" , 2, 0, [ [ -1, 0 ] ], [ 2 ] ], 18 | [ "Hasher", 2, 0, [ [ 0, 0 ] ], [ 2 ] ], 19 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 1, 0 ] ], [ ] ] 20 | ] 21 | }; 22 | const synth = context.createSynth(synthdef).appendTo(context); 23 | const actual = context.audioBuses[0]; 24 | 25 | { 26 | synth.unitList[0].outputs[0].set(noise0); // in 27 | context.process(); 28 | 29 | const expected = Number.isFinite; 30 | 31 | // for (let i = 0; i < 64; i++) { 32 | // console.log(actual[i]); 33 | // } 34 | 35 | assert(actual.every(expected)); 36 | } 37 | }); 38 | -------------------------------------------------------------------------------- /test/unit/SCUnitIRand.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const scsynth = require("../../src"); 6 | 7 | test("ii", () => { 8 | const context = new scsynth.SCContext({ blockSize: 64 }); 9 | const synthdef = { 10 | name: "IRandTest", 11 | consts: [ 0, 10, 20 ], 12 | paramValues: {}, 13 | paramIndices: {}, 14 | units: [ 15 | [ "DC" , 1, 0, [ [ -1, 1 ] ], [ 1 ] ], 16 | [ "DC" , 1, 0, [ [ -1, 2 ] ], [ 1 ] ], 17 | [ "IRand", 0, 0, [ [ 0, 0 ], [ 1, 0 ] ], [ 0 ] ], 18 | [ "K2A" , 2, 0, [ [ 2, 0 ] ], [ 2 ] ], 19 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 3, 0 ] ], [ ] ] 20 | ] 21 | }; 22 | const synth = context.createSynth(synthdef).appendTo(context); 23 | const actual = context.audioBuses[0]; 24 | 25 | const expected = (x, i, list) => i === 0 ? (x === list[0]) : (10 <= x && x < 20) && x % 1 === 0; 26 | 27 | { 28 | synth.unitList[0].outputs[0]; 29 | context.process(); 30 | 31 | // for (let i = 0; i < 1; i++) { 32 | // console.log(actual[i]); 33 | // } 34 | 35 | assert(actual.every(expected)); 36 | } 37 | }); 38 | -------------------------------------------------------------------------------- /test/unit/SCUnitK2A.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const nmap = require("nmap"); 6 | const scsynth = require("../../src"); 7 | 8 | test("a", () => { 9 | const context = new scsynth.SCContext({ blockSize: 64 }); 10 | const noise0 = new Float32Array(nmap(1, Math.random)); 11 | const synthdef = { 12 | name: "K2ATest", 13 | consts: [ 0 ], 14 | paramValues: {}, 15 | paramIndices: {}, 16 | units: [ 17 | [ "DC" , 1, 0, [ [ -1, 0 ] ], [ 1 ] ], 18 | [ "K2A", 2, 0, [ [ 0, 0 ] ], [ 2 ] ], 19 | [ "Out", 2, 0, [ [ -1, 0 ], [ 1, 0 ] ], [ ] ] 20 | ] 21 | }; 22 | const synth = context.createSynth(synthdef).appendTo(context); 23 | const actual = context.audioBuses[0]; 24 | 25 | { 26 | synth.unitList[0].outputs[0].set(noise0); // in 27 | context.process(); 28 | 29 | const expected = new Float32Array(64).fill(noise0[0]); 30 | 31 | // for (let i = 0; i < 64; i++) { 32 | // console.log(actual[i]); 33 | // } 34 | 35 | assert.deepEqual(actual, expected); 36 | } 37 | }); 38 | -------------------------------------------------------------------------------- /test/unit/SCUnitLFClipNoise.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const scsynth = require("../../src"); 6 | 7 | test("a", () => { 8 | const context = new scsynth.SCContext({ blockSize: 64 }); 9 | const synthdef = { 10 | name: "LFClipNoiseTest", 11 | consts: [ 0, 250 ], 12 | paramValues: {}, 13 | paramIndices: {}, 14 | units: [ 15 | [ "DC" , 1, 0, [ [ -1, 1 ] ], [ 1 ] ], 16 | [ "LFClipNoise", 2, 0, [ [ 0, 0 ] ], [ 2 ] ], 17 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 1, 0 ] ], [ ] ] 18 | ] 19 | }; 20 | const synth = context.createSynth(synthdef).appendTo(context); 21 | const actual = context.audioBuses[0]; 22 | 23 | for (let n = 0; n < 10; n++) { 24 | synth.unitList[1].outputs[0]; 25 | context.process(); 26 | 27 | const expected = x => x === -1 || x === +1; 28 | 29 | // for (let i = 0; i < 64; i++) { 30 | // console.log(actual[i]); 31 | // } 32 | 33 | assert(actual.every(expected)); 34 | } 35 | }); 36 | -------------------------------------------------------------------------------- /test/unit/SCUnitLFCub.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const scsynth = require("../../src"); 6 | 7 | test("ki", () => { 8 | const context = new scsynth.SCContext({ blockSize: 64 }); 9 | const synthdef = { 10 | name: "LFCubTest", 11 | consts: [ 0, 10, 0 ], 12 | paramValues: {}, 13 | paramIndices: {}, 14 | units: [ 15 | [ "DC" , 2, 0, [ [ -1, 1 ] ], [ 2 ] ], 16 | [ "DC" , 1, 0, [ [ -1, 2 ] ], [ 1 ] ], 17 | [ "LFCub", 2, 0, [ [ 0, 0 ], [ 1, 0 ] ], [ 2 ] ], 18 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 2, 0 ] ], [ ] ] 19 | ] 20 | }; 21 | const synth = context.createSynth(synthdef).appendTo(context); 22 | const actual = context.audioBuses[0]; 23 | 24 | for (let n = 0; n < 10; n++) { 25 | synth.unitList[0].outputs[0].fill(10); // freq 26 | context.process(); 27 | 28 | const expected = x => Math.abs(x) < 1 + 1e-6; 29 | 30 | // for (let i = 0; i < 64; i++) { 31 | // console.log(actual[i]); 32 | // } 33 | 34 | assert(actual.every(expected)); 35 | } 36 | }); 37 | -------------------------------------------------------------------------------- /test/unit/SCUnitLFNoise0.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const scsynth = require("../../src"); 6 | 7 | test("a", () => { 8 | const context = new scsynth.SCContext({ blockSize: 64 }); 9 | const synthdef = { 10 | name: "LFNoise0Test", 11 | consts: [ 0, 250 ], 12 | paramValues: {}, 13 | paramIndices: {}, 14 | units: [ 15 | [ "DC" , 1, 0, [ [ -1, 1 ] ], [ 1 ] ], 16 | [ "LFNoise0", 2, 0, [ [ 0, 0 ] ], [ 2 ] ], 17 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 1, 0 ] ], [ ] ] 18 | ] 19 | }; 20 | const synth = context.createSynth(synthdef).appendTo(context); 21 | const actual = context.audioBuses[0]; 22 | 23 | for (let n = 0; n < 10; n++) { 24 | synth.unitList[1].outputs[0]; 25 | context.process(); 26 | 27 | const expected = x => -1 <= x && x < +1; 28 | 29 | // for (let i = 0; i < 64; i++) { 30 | // console.log(actual[i]); 31 | // } 32 | 33 | assert(actual.every(expected)); 34 | } 35 | }); 36 | -------------------------------------------------------------------------------- /test/unit/SCUnitLFNoise1.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const scsynth = require("../../src"); 6 | 7 | test("a", () => { 8 | const context = new scsynth.SCContext({ blockSize: 64 }); 9 | const synthdef = { 10 | name: "LFNoise1Test", 11 | consts: [ 0, 250 ], 12 | paramValues: {}, 13 | paramIndices: {}, 14 | units: [ 15 | [ "DC" , 1, 0, [ [ -1, 1 ] ], [ 1 ] ], 16 | [ "LFNoise1", 2, 0, [ [ 0, 0 ] ], [ 2 ] ], 17 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 1, 0 ] ], [ ] ] 18 | ] 19 | }; 20 | const synth = context.createSynth(synthdef).appendTo(context); 21 | const actual = context.audioBuses[0]; 22 | 23 | for (let n = 0; n < 10; n++) { 24 | synth.unitList[1].outputs[0]; 25 | context.process(); 26 | 27 | const expected = x => -1 <= x && x < +1; 28 | 29 | // for (let i = 0; i < 64; i++) { 30 | // console.log(actual[i]); 31 | // } 32 | 33 | assert(actual.every(expected)); 34 | } 35 | }); 36 | -------------------------------------------------------------------------------- /test/unit/SCUnitLFNoise2.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const scsynth = require("../../src"); 6 | 7 | test("a", () => { 8 | const context = new scsynth.SCContext({ blockSize: 64 }); 9 | const synthdef = { 10 | name: "LFNoise2Test", 11 | consts: [ 0, 250 ], 12 | paramValues: {}, 13 | paramIndices: {}, 14 | units: [ 15 | [ "DC" , 1, 0, [ [ -1, 1 ] ], [ 1 ] ], 16 | [ "LFNoise2", 2, 0, [ [ 0, 0 ] ], [ 2 ] ], 17 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 1, 0 ] ], [ ] ] 18 | ] 19 | }; 20 | const synth = context.createSynth(synthdef).appendTo(context); 21 | const actual = context.audioBuses[0]; 22 | 23 | for (let n = 0; n < 10; n++) { 24 | synth.unitList[1].outputs[0]; 25 | context.process(); 26 | 27 | const expected = x => -1 <= x && x < +1; 28 | 29 | // for (let i = 0; i < 64; i++) { 30 | // console.log(actual[i]); 31 | // } 32 | 33 | assert(actual.every(expected)); 34 | } 35 | }); 36 | -------------------------------------------------------------------------------- /test/unit/SCUnitLFPar.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const scsynth = require("../../src"); 6 | 7 | test("ki", () => { 8 | const context = new scsynth.SCContext({ blockSize: 64 }); 9 | const synthdef = { 10 | name: "LFParTest", 11 | consts: [ 0, 10, 0 ], 12 | paramValues: {}, 13 | paramIndices: {}, 14 | units: [ 15 | [ "DC" , 2, 0, [ [ -1, 1 ] ], [ 2 ] ], 16 | [ "DC" , 1, 0, [ [ -1, 2 ] ], [ 1 ] ], 17 | [ "LFPar", 2, 0, [ [ 0, 0 ], [ 1, 0 ] ], [ 2 ] ], 18 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 2, 0 ] ], [ ] ] 19 | ] 20 | }; 21 | const synth = context.createSynth(synthdef).appendTo(context); 22 | const actual = context.audioBuses[0]; 23 | 24 | for (let n = 0; n < 10; n++) { 25 | synth.unitList[0].outputs[0].fill(10); // freq 26 | context.process(); 27 | 28 | const expected = x => Math.abs(x) < 1 + 1e-6; 29 | 30 | // for (let i = 0; i < 64; i++) { 31 | // console.log(actual[i]); 32 | // } 33 | 34 | assert(actual.every(expected)); 35 | } 36 | }); 37 | -------------------------------------------------------------------------------- /test/unit/SCUnitLFPulse.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const scsynth = require("../../src"); 6 | 7 | test("kik", () => { 8 | const context = new scsynth.SCContext({ blockSize: 64 }); 9 | const synthdef = { 10 | name: "LFPulseTest", 11 | consts: [ 0, 10, 0, 0.25 ], 12 | paramValues: {}, 13 | paramIndices: {}, 14 | units: [ 15 | [ "DC" , 2, 0, [ [ -1, 1 ] ], [ 2 ] ], 16 | [ "DC" , 1, 0, [ [ -1, 2 ] ], [ 1 ] ], 17 | [ "DC" , 1, 0, [ [ -1, 3 ] ], [ 1 ] ], 18 | [ "LFPulse", 2, 0, [ [ 0, 0 ], [ 1, 0 ], [ 2, 0 ] ], [ 2 ] ], 19 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 3, 0 ] ], [ ] ] 20 | ] 21 | }; 22 | const synth = context.createSynth(synthdef).appendTo(context); 23 | const actual = context.audioBuses[0]; 24 | 25 | for (let n = 0; n < 10; n++) { 26 | synth.unitList[0].outputs[0].fill(10); // freq 27 | context.process(); 28 | 29 | const expected = x => Math.abs(x) < 1 + 1e-6; 30 | 31 | // for (let i = 0; i < 64; i++) { 32 | // console.log(actual[i]); 33 | // } 34 | 35 | assert(actual.every(expected)); 36 | } 37 | }); 38 | -------------------------------------------------------------------------------- /test/unit/SCUnitLFSaw.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const scsynth = require("../../src"); 6 | 7 | test("ki", () => { 8 | const context = new scsynth.SCContext({ blockSize: 64 }); 9 | const synthdef = { 10 | name: "LFSawTest", 11 | consts: [ 0, 10, 0 ], 12 | paramValues: {}, 13 | paramIndices: {}, 14 | units: [ 15 | [ "DC" , 2, 0, [ [ -1, 1 ] ], [ 2 ] ], 16 | [ "DC" , 1, 0, [ [ -1, 2 ] ], [ 1 ] ], 17 | [ "LFSaw", 2, 0, [ [ 0, 0 ], [ 1, 0 ] ], [ 2 ] ], 18 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 2, 0 ] ], [ ] ] 19 | ] 20 | }; 21 | const synth = context.createSynth(synthdef).appendTo(context); 22 | const actual = context.audioBuses[0]; 23 | 24 | for (let n = 0; n < 10; n++) { 25 | synth.unitList[0].outputs[0].fill(10); // freq 26 | context.process(); 27 | 28 | const expected = x => Math.abs(x) < 1 + 1e-6; 29 | 30 | // for (let i = 0; i < 64; i++) { 31 | // console.log(actual[i]); 32 | // } 33 | 34 | assert(actual.every(expected)); 35 | } 36 | }); 37 | -------------------------------------------------------------------------------- /test/unit/SCUnitLFTri.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const scsynth = require("../../src"); 6 | 7 | test("ki", () => { 8 | const context = new scsynth.SCContext({ blockSize: 64 }); 9 | const synthdef = { 10 | name: "LFTriTest", 11 | consts: [ 0, 10, 0 ], 12 | paramValues: {}, 13 | paramIndices: {}, 14 | units: [ 15 | [ "DC" , 2, 0, [ [ -1, 1 ] ], [ 2 ] ], 16 | [ "DC" , 1, 0, [ [ -1, 2 ] ], [ 1 ] ], 17 | [ "LFTri", 2, 0, [ [ 0, 0 ], [ 1, 0 ] ], [ 2 ] ], 18 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 2, 0 ] ], [ ] ] 19 | ] 20 | }; 21 | const synth = context.createSynth(synthdef).appendTo(context); 22 | const actual = context.audioBuses[0]; 23 | 24 | for (let n = 0; n < 10; n++) { 25 | synth.unitList[0].outputs[0].fill(10); // freq 26 | context.process(); 27 | 28 | const expected = x => Math.abs(x) < 1 + 1e-6; 29 | 30 | // for (let i = 0; i < 64; i++) { 31 | // console.log(actual[i]); 32 | // } 33 | 34 | assert(actual.every(expected)); 35 | } 36 | }); 37 | -------------------------------------------------------------------------------- /test/unit/SCUnitLPF.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const nmap = require("nmap"); 6 | const scsynth = require("../../src"); 7 | 8 | test("akk", () => { 9 | const context = new scsynth.SCContext({ blockSize: 64 }); 10 | const noise0 = new Float32Array(nmap(64, Math.random)); 11 | const synthdef = { 12 | name: "LPFTest", 13 | consts: [ 0, 0, 350 ], 14 | paramValues: {}, 15 | paramIndices: {}, 16 | units: [ 17 | [ "DC" , 2, 0, [ [ -1, 1 ] ], [ 2 ] ], 18 | [ "DC" , 1, 0, [ [ -1, 2 ] ], [ 1 ] ], 19 | [ "LPF", 2, 0, [ [ 0, 0 ], [ 1, 0 ] ], [ 2 ] ], 20 | [ "Out", 2, 0, [ [ -1, 0 ], [ 2, 0 ] ], [ ] ] 21 | ] 22 | }; 23 | const synth = context.createSynth(synthdef).appendTo(context); 24 | const actual = context.audioBuses[0]; 25 | 26 | { 27 | synth.unitList[0].outputs[0].set(noise0); // in 28 | context.process(); 29 | 30 | const expected = x => Math.abs(x) < 1 + 1e-6; 31 | 32 | // for (let i = 0; i < 64; i++) { 33 | // console.log(actual[i]); 34 | // } 35 | 36 | assert(actual.every(expected)); 37 | } 38 | }); 39 | -------------------------------------------------------------------------------- /test/unit/SCUnitLimiter.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const nmap = require("nmap"); 6 | const scsynth = require("../../src"); 7 | 8 | test("aki", () => { 9 | const context = new scsynth.SCContext({ blockSize: 64 }); 10 | const noise0 = new Float32Array(nmap(64, Math.random)); 11 | const synthdef = { 12 | name: "LimiterTest", 13 | consts: [ 0, 0.001 ], 14 | paramValues: {}, 15 | paramIndices: {}, 16 | units: [ 17 | [ "DC" , 2, 0, [ [ -1, 0 ] ], [ 2 ] ], 18 | [ "DC" , 2, 0, [ [ -1, 0 ] ], [ 2 ] ], 19 | [ "Limiter", 2, 0, [ [ 0, 0 ], [ 1, 0 ], [ -1, 1 ] ], [ 2 ] ], 20 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 2, 0 ] ], [ ] ] 21 | ] 22 | }; 23 | const synth = context.createSynth(synthdef).appendTo(context); 24 | const actual = context.audioBuses[0]; 25 | 26 | { 27 | synth.unitList[0].outputs[0].set(noise0); // in 28 | synth.unitList[1].outputs[0].fill(0.5); // level 29 | 30 | for (let i = 0; i < 5; i++) { 31 | context.process(); 32 | } 33 | 34 | const expected = x => Math.abs(x) <= 0.51; 35 | 36 | // for (let i = 0; i < 64; i++) { 37 | // console.log(actual[i]); 38 | // } 39 | 40 | assert(actual.some(x => x)); 41 | assert(actual.every(expected)); 42 | } 43 | { 44 | synth.unitList[1].outputs[0].fill(0.1); // level 45 | 46 | for (let i = 0; i < 5; i++) { 47 | context.process(); 48 | } 49 | 50 | const expected = x => Math.abs(x) <= 0.11; 51 | 52 | // for (let i = 0; i < 64; i++) { 53 | // console.log(actual[i]); 54 | // } 55 | 56 | assert(actual.some(x => x)); 57 | assert(actual.every(expected)); 58 | } 59 | }); 60 | -------------------------------------------------------------------------------- /test/unit/SCUnitLinRand.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const scsynth = require("../../src"); 6 | 7 | test("iii", () => { 8 | const context = new scsynth.SCContext({ blockSize: 64 }); 9 | const synthdef = { 10 | name: "LinRandTest", 11 | consts: [ 0, 10, 20, 0 ], 12 | paramValues: {}, 13 | paramIndices: {}, 14 | units: [ 15 | [ "DC" , 1, 0, [ [ -1, 1 ] ], [ 1 ] ], 16 | [ "DC" , 1, 0, [ [ -1, 2 ] ], [ 1 ] ], 17 | [ "DC" , 1, 0, [ [ -1, 3 ] ], [ 1 ] ], 18 | [ "LinRand", 0, 0, [ [ 0, 0 ], [ 1, 0 ], [ 2, 0 ] ], [ 0 ] ], 19 | [ "K2A" , 2, 0, [ [ 3, 0 ] ], [ 2 ] ], 20 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 4, 0 ] ], [ ] ] 21 | ] 22 | }; 23 | const synth = context.createSynth(synthdef).appendTo(context); 24 | const actual = context.audioBuses[0]; 25 | 26 | const expected = (x, i, list) => i === 0 ? (x === list[0]) : (10 <= x && x < 20); 27 | 28 | { 29 | synth.unitList[0].outputs[0]; 30 | context.process(); 31 | 32 | // for (let i = 0; i < 1; i++) { 33 | // console.log(actual[i]); 34 | // } 35 | 36 | assert(actual.every(expected)); 37 | } 38 | }); 39 | -------------------------------------------------------------------------------- /test/unit/SCUnitLogistic.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const scsynth = require("../../src"); 6 | 7 | test("kki", () => { 8 | const context = new scsynth.SCContext({ blockSize: 64 }); 9 | const synthdef = { 10 | name: "LogisticTest", 11 | consts: [ 0, 3, 350, 0.5 ], 12 | paramValues: {}, 13 | paramIndices: {}, 14 | units: [ 15 | [ "DC" , 1, 0, [ [ -1, 1 ] ], [ 1 ] ], 16 | [ "DC" , 1, 0, [ [ -1, 2 ] ], [ 1 ] ], 17 | [ "DC" , 1, 0, [ [ -1, 3 ] ], [ 1 ] ], 18 | [ "Logistic", 2, 0, [ [ 0, 0 ], [ 1, 0 ], [ 2, 0 ] ], [ 2 ] ], 19 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 3, 0 ] ], [ ] ] 20 | ] 21 | }; 22 | const synth = context.createSynth(synthdef).appendTo(context); 23 | const actual = context.audioBuses[0]; 24 | 25 | for (let n = 0; n < 10; n++) { 26 | synth.unitList[0].outputs[0]; 27 | context.process(); 28 | 29 | const expected = x => 0 <= x && x <= 1; 30 | 31 | // for (let i = 0; i < 64; i++) { 32 | // console.log(actual[i]); 33 | // } 34 | 35 | assert(actual.every(expected)); 36 | } 37 | }); 38 | -------------------------------------------------------------------------------- /test/unit/SCUnitMantissaMask.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const nmap = require("nmap"); 6 | const scsynth = require("../../src"); 7 | 8 | test("a", () => { 9 | const context = new scsynth.SCContext({ blockSize: 64 }); 10 | const noise0 = new Float32Array(nmap(64, Math.random)); 11 | const synthdef = { 12 | name: "MantissaMaskTest", 13 | consts: [ 0, 3 ], 14 | paramValues: {}, 15 | paramIndices: {}, 16 | units: [ 17 | [ "DC" , 2, 0, [ [ -1, 0 ] ], [ 2 ] ], 18 | [ "DC" , 1, 0, [ [ -1, 1 ] ], [ 1 ] ], 19 | [ "MantissaMask", 2, 0, [ [ 0, 0 ], [ 1, 0 ] ], [ 2 ] ], 20 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 2, 0 ] ], [ ] ] 21 | ] 22 | }; 23 | const synth = context.createSynth(synthdef).appendTo(context); 24 | const actual = context.audioBuses[0]; 25 | 26 | { 27 | synth.unitList[0].outputs[0].set(noise0); // in 28 | context.process(); 29 | 30 | const expected = Number.isFinite; 31 | 32 | // for (let i = 0; i < 64; i++) { 33 | // console.log(actual[i]); 34 | // } 35 | 36 | assert(actual.every(expected)); 37 | } 38 | }); 39 | -------------------------------------------------------------------------------- /test/unit/SCUnitMedian.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const nmap = require("nmap"); 6 | const scsynth = require("../../src"); 7 | 8 | test("ia", () => { 9 | const context = new scsynth.SCContext({ blockSize: 64 }); 10 | const noise0 = new Float32Array(nmap(64, Math.random)); 11 | const synthdef = { 12 | name: "MedianTest", 13 | consts: [ 0, noise0[0], 5 ], 14 | paramValues: {}, 15 | paramIndices: {}, 16 | units: [ 17 | [ "DC" , 2, 0, [ [ -1, 1 ] ], [ 2 ] ], 18 | [ "Median", 2, 0, [ [ -1, 2 ], [ 0, 0 ] ], [ 2 ] ], 19 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 1, 0 ] ], [ ] ] 20 | ] 21 | }; 22 | const synth = context.createSynth(synthdef).appendTo(context); 23 | const actual = context.audioBuses[0]; 24 | 25 | { 26 | synth.unitList[0].outputs[0].set(noise0); // in 27 | 28 | context.process(); 29 | 30 | const expected = x => noise0.includes(x); 31 | const expected16 = noise0.subarray(16 - 4, 16 + 1).sort()[2]; 32 | const expected32 = noise0.subarray(32 - 4, 32 + 1).sort()[2]; 33 | const expected48 = noise0.subarray(48 - 4, 48 + 1).sort()[2]; 34 | 35 | // for (let i = 0; i < 64; i++) { 36 | // console.log(actual[i]); 37 | // } 38 | 39 | assert(actual.every(expected)); 40 | assert(actual[16] === expected16); 41 | assert(actual[32] === expected32); 42 | assert(actual[48] === expected48); 43 | } 44 | }); 45 | -------------------------------------------------------------------------------- /test/unit/SCUnitNRand.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const scsynth = require("../../src"); 6 | 7 | test("iii", () => { 8 | const context = new scsynth.SCContext({ blockSize: 64 }); 9 | const synthdef = { 10 | name: "NRandTest", 11 | consts: [ 0, 10, 20, 5 ], 12 | paramValues: {}, 13 | paramIndices: {}, 14 | units: [ 15 | [ "DC" , 1, 0, [ [ -1, 1 ] ], [ 1 ] ], 16 | [ "DC" , 1, 0, [ [ -1, 2 ] ], [ 1 ] ], 17 | [ "DC" , 1, 0, [ [ -1, 3 ] ], [ 1 ] ], 18 | [ "NRand", 0, 0, [ [ 0, 0 ], [ 1, 0 ], [ 2, 0 ] ], [ 0 ] ], 19 | [ "K2A" , 2, 0, [ [ 3, 0 ] ], [ 2 ] ], 20 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 4, 0 ] ], [ ] ] 21 | ] 22 | }; 23 | const synth = context.createSynth(synthdef).appendTo(context); 24 | const actual = context.audioBuses[0]; 25 | 26 | const expected = (x, i, list) => i === 0 ? (x === list[0]) : (10 <= x && x < 20); 27 | 28 | { 29 | synth.unitList[0].outputs[0]; 30 | context.process(); 31 | 32 | // for (let i = 0; i < 1; i++) { 33 | // console.log(actual[i]); 34 | // } 35 | 36 | assert(actual.every(expected)); 37 | } 38 | }); 39 | -------------------------------------------------------------------------------- /test/unit/SCUnitNormalizer.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const nmap = require("nmap"); 6 | const scsynth = require("../../src"); 7 | 8 | test("aki", () => { 9 | const context = new scsynth.SCContext({ blockSize: 64 }); 10 | const noise0 = new Float32Array(nmap(64, Math.random)); 11 | const synthdef = { 12 | name: "NormalizerTest", 13 | consts: [ 0, 0.001 ], 14 | paramValues: {}, 15 | paramIndices: {}, 16 | units: [ 17 | [ "DC" , 2, 0, [ [ -1, 0 ] ], [ 2 ] ], 18 | [ "DC" , 2, 0, [ [ -1, 0 ] ], [ 2 ] ], 19 | [ "Normalizer", 2, 0, [ [ 0, 0 ], [ 1, 0 ], [ -1, 1 ] ], [ 2 ] ], 20 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 2, 0 ] ], [ ] ] 21 | ] 22 | }; 23 | const synth = context.createSynth(synthdef).appendTo(context); 24 | const actual = context.audioBuses[0]; 25 | 26 | { 27 | synth.unitList[0].outputs[0].set(noise0); // in 28 | synth.unitList[1].outputs[0].fill(0.5); // level 29 | 30 | for (let i = 0; i < 5; i++) { 31 | context.process(); 32 | } 33 | 34 | const expected = x => Math.abs(x) <= 0.51; 35 | 36 | // for (let i = 0; i < 64; i++) { 37 | // console.log(actual[i]); 38 | // } 39 | 40 | assert(actual.some(x => x)); 41 | assert(actual.every(expected)); 42 | } 43 | { 44 | synth.unitList[1].outputs[0].fill(0.1); // level 45 | 46 | for (let i = 0; i < 5; i++) { 47 | context.process(); 48 | } 49 | 50 | const expected = x => Math.abs(x) <= 0.11; 51 | 52 | // for (let i = 0; i < 64; i++) { 53 | // console.log(actual[i]); 54 | // } 55 | 56 | assert(actual.some(x => x)); 57 | assert(actual.every(expected)); 58 | } 59 | }); 60 | -------------------------------------------------------------------------------- /test/unit/SCUnitPinkNoise.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const scsynth = require("../../src"); 6 | 7 | test("a", () => { 8 | const context = new scsynth.SCContext({ blockSize: 64 }); 9 | const synthdef = { 10 | name: "PinkNoiseTest", 11 | consts: [ 0 ], 12 | paramValues: {}, 13 | paramIndices: {}, 14 | units: [ 15 | [ "PinkNoise", 2, 0, [ ], [ 2 ] ], 16 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 0, 0 ] ], [ ] ] 17 | ] 18 | }; 19 | const synth = context.createSynth(synthdef).appendTo(context); 20 | const actual = context.audioBuses[0]; 21 | 22 | { 23 | synth.unitList[0].outputs[0]; 24 | context.process(); 25 | 26 | const expected = x => -1 <= x && x <= 1; 27 | 28 | // for (let i = 0; i < 64; i++) { 29 | // console.log(actual[i]); 30 | // } 31 | 32 | assert(actual.every(expected)); 33 | } 34 | }); 35 | -------------------------------------------------------------------------------- /test/unit/SCUnitRHPF.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const nmap = require("nmap"); 6 | const scsynth = require("../../src"); 7 | 8 | test("akk", () => { 9 | const context = new scsynth.SCContext({ blockSize: 64 }); 10 | const noise0 = new Float32Array(nmap(64, Math.random)); 11 | const synthdef = { 12 | name: "RHPFTest", 13 | consts: [ 0, 0, 350, 1 ], 14 | paramValues: {}, 15 | paramIndices: {}, 16 | units: [ 17 | [ "DC" , 2, 0, [ [ -1, 1 ] ], [ 2 ] ], 18 | [ "DC" , 1, 0, [ [ -1, 2 ] ], [ 1 ] ], 19 | [ "DC" , 1, 0, [ [ -1, 3 ] ], [ 1 ] ], 20 | [ "RHPF", 2, 0, [ [ 0, 0 ], [ 1, 0 ], [ 2, 0 ] ], [ 2 ] ], 21 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 3, 0 ] ], [ ] ] 22 | ] 23 | }; 24 | const synth = context.createSynth(synthdef).appendTo(context); 25 | const actual = context.audioBuses[0]; 26 | 27 | { 28 | synth.unitList[0].outputs[0].set(noise0); // in 29 | context.process(); 30 | 31 | const expected = x => Math.abs(x) < 1 + 1e-6; 32 | 33 | // for (let i = 0; i < 64; i++) { 34 | // console.log(actual[i]); 35 | // } 36 | 37 | assert(actual.every(expected)); 38 | } 39 | }); 40 | -------------------------------------------------------------------------------- /test/unit/SCUnitRLPF.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const nmap = require("nmap"); 6 | const scsynth = require("../../src"); 7 | 8 | test("akk", () => { 9 | const context = new scsynth.SCContext({ blockSize: 64 }); 10 | const noise0 = new Float32Array(nmap(64, Math.random)); 11 | const synthdef = { 12 | name: "RLPFTest", 13 | consts: [ 0, 0, 350, 1 ], 14 | paramValues: {}, 15 | paramIndices: {}, 16 | units: [ 17 | [ "DC" , 2, 0, [ [ -1, 1 ] ], [ 2 ] ], 18 | [ "DC" , 1, 0, [ [ -1, 2 ] ], [ 1 ] ], 19 | [ "DC" , 1, 0, [ [ -1, 3 ] ], [ 1 ] ], 20 | [ "RLPF", 2, 0, [ [ 0, 0 ], [ 1, 0 ], [ 2, 0 ] ], [ 2 ] ], 21 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 3, 0 ] ], [ ] ] 22 | ] 23 | }; 24 | const synth = context.createSynth(synthdef).appendTo(context); 25 | const actual = context.audioBuses[0]; 26 | 27 | { 28 | synth.unitList[0].outputs[0].set(noise0); // in 29 | context.process(); 30 | 31 | const expected = x => Math.abs(x) < 1 + 1e-6; 32 | 33 | // for (let i = 0; i < 64; i++) { 34 | // console.log(actual[i]); 35 | // } 36 | 37 | assert(actual.every(expected)); 38 | } 39 | }); 40 | -------------------------------------------------------------------------------- /test/unit/SCUnitRand.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const scsynth = require("../../src"); 6 | 7 | test("ii", () => { 8 | const context = new scsynth.SCContext({ blockSize: 64 }); 9 | const synthdef = { 10 | name: "RandTest", 11 | consts: [ 0, 0.5, 1.5 ], 12 | paramValues: {}, 13 | paramIndices: {}, 14 | units: [ 15 | [ "DC" , 1, 0, [ [ -1, 1 ] ], [ 1 ] ], 16 | [ "DC" , 1, 0, [ [ -1, 2 ] ], [ 1 ] ], 17 | [ "Rand", 0, 0, [ [ 0, 0 ], [ 1, 0 ] ], [ 0 ] ], 18 | [ "K2A" , 2, 0, [ [ 2, 0 ] ], [ 2 ] ], 19 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 3, 0 ] ], [ ] ] 20 | ] 21 | }; 22 | const synth = context.createSynth(synthdef).appendTo(context); 23 | const actual = context.audioBuses[0]; 24 | 25 | const expected = (x, i, list) => i === 0 ? (x === list[0]) : (0.5 <= x && x <= 1.5); 26 | 27 | { 28 | synth.unitList[0].outputs[0]; 29 | context.process(); 30 | 31 | // for (let i = 0; i < 1; i++) { 32 | // console.log(actual[i]); 33 | // } 34 | 35 | assert(actual.every(expected)); 36 | } 37 | }); 38 | -------------------------------------------------------------------------------- /test/unit/SCUnitRotate2.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const nmap = require("nmap"); 6 | const scsynth = require("../../src"); 7 | 8 | test("aak", () => { 9 | const context = new scsynth.SCContext({ blockSize: 64 }); 10 | const noise0 = new Float32Array(nmap(64, Math.random)); 11 | const noise1 = new Float32Array(nmap(64, Math.random)); 12 | const synthdef = { 13 | name: "Pan2Test", 14 | consts: [ 0, 1 ], 15 | paramValues: {}, 16 | paramIndices: {}, 17 | units: [ 18 | [ "DC" , 2, 0, [ [ -1, 0 ] ], [ 2 ] ], 19 | [ "DC" , 2, 0, [ [ -1, 0 ] ], [ 2 ] ], 20 | [ "DC" , 1, 0, [ [ -1, 1 ] ], [ 1 ] ], 21 | [ "Pan2", 2, 0, [ [ 0, 0 ], [ 1, 0 ], [ 2, 0 ] ], [ 2, 2 ] ], 22 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 3, 0 ], [ 3, 1 ] ], [ ] ] 23 | ] 24 | }; 25 | const synth = context.createSynth(synthdef).appendTo(context); 26 | const actualL = context.audioBuses[0]; 27 | const actualR = context.audioBuses[1]; 28 | 29 | { 30 | synth.unitList[0].outputs[0].set(noise0); // x 31 | synth.unitList[1].outputs[0].set(noise1); // y 32 | synth.unitList[2].outputs[0].fill(-1); // pos 33 | context.process(); 34 | 35 | const expectedL = Number.isFinite; 36 | const expectedR = Number.isFinite; 37 | 38 | // for (let i = 0; i < 64; i++) { 39 | // console.log(actualL[i], actualR[i]); 40 | // } 41 | 42 | assert(actualL.every(expectedL)); 43 | assert(actualR.every(expectedR)); 44 | } 45 | { 46 | context.process(); 47 | 48 | const expectedL = Number.isFinite; 49 | const expectedR = Number.isFinite; 50 | 51 | // for (let i = 0; i < 64; i++) { 52 | // console.log(actualL[i], actualR[i]); 53 | // } 54 | 55 | assert(actualL.every(expectedL)); 56 | assert(actualR.every(expectedR)); 57 | } 58 | }); 59 | -------------------------------------------------------------------------------- /test/unit/SCUnitSchmidt.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const nmap = require("nmap"); 6 | const scsynth = require("../../src"); 7 | 8 | test("akk", () => { 9 | const context = new scsynth.SCContext({ blockSize: 64 }); 10 | const noise0 = new Float32Array(nmap(64, Math.random)); 11 | const synthdef = { 12 | name: "SchmidtTest", 13 | consts: [ 0, 0.5, 0.75 ], 14 | paramValues: {}, 15 | paramIndices: {}, 16 | units: [ 17 | [ "DC" , 2, 0, [ [ -1, 0 ] ], [ 2 ] ], 18 | [ "DC" , 1, 0, [ [ -1, 1 ] ], [ 1 ] ], 19 | [ "DC" , 1, 0, [ [ -1, 2 ] ], [ 1 ] ], 20 | [ "Schmidt", 2, 0, [ [ 0, 0 ], [ 1, 0 ], [ 2, 0 ] ], [ 2 ] ], 21 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 3, 0 ] ], [ ] ] 22 | ] 23 | }; 24 | const synth = context.createSynth(synthdef).appendTo(context); 25 | const actual = context.audioBuses[0]; 26 | 27 | { 28 | synth.unitList[0].outputs[0].set(noise0); // in 29 | context.process(); 30 | 31 | const expected = Number.isFinite; 32 | 33 | // for (let i = 0; i < 64; i++) { 34 | // console.log(actual[i]); 35 | // } 36 | 37 | assert(actual.every(expected)); 38 | } 39 | }); 40 | -------------------------------------------------------------------------------- /test/unit/SCUnitSinOscFB.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const scsynth = require("../../src"); 6 | 7 | test("kk", () => { 8 | const context = new scsynth.SCContext({ blockSize: 64 }); 9 | const synthdef = { 10 | name: "SinOscTest", 11 | consts: [ 0, 440, 0 ], 12 | paramValues: {}, 13 | paramIndices: {}, 14 | units: [ 15 | [ "DC" , 1, 0, [ [ -1, 1 ] ], [ 1 ] ], 16 | [ "DC" , 1, 0, [ [ -1, 2 ] ], [ 1 ] ], 17 | [ "SinOscFB", 2, 0, [ [ 0, 0 ], [ 1, 0 ] ], [ 2 ] ], 18 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 2, 0 ] ], [ ] ] 19 | ] 20 | }; 21 | const synth = context.createSynth(synthdef).appendTo(context); 22 | const actual = context.audioBuses[0]; 23 | 24 | for (let n = 0; n < 12; n++) { 25 | if (n % 2 === 0) { 26 | synth.unitList[0].outputs[0].fill(440 * Math.pow(2, n / 12)); // freq 27 | } 28 | if (n % 2 === 1) { 29 | synth.unitList[1].outputs[0].fill(Math.random()); // feedback 30 | } 31 | context.process(); 32 | 33 | const expected = x => Math.abs(x) <= 1 + 1e-6; 34 | 35 | // for (let i = 0; i < 64; i++) { 36 | // console.log(actual[i]); 37 | // } 38 | 39 | assert(actual.every(expected)); 40 | } 41 | }); 42 | -------------------------------------------------------------------------------- /test/unit/SCUnitT2A.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const scsynth = require("../../src"); 6 | 7 | test("a", () => { 8 | const context = new scsynth.SCContext({ blockSize: 64 }); 9 | const synthdef = { 10 | name: "T2ATest", 11 | consts: [ 0, 0 ], 12 | paramValues: {}, 13 | paramIndices: {}, 14 | units: [ 15 | [ "DC" , 2, 0, [ [ -1, 0 ] ], [ 2 ] ], 16 | [ "DC" , 1, 0, [ [ -1, 1 ] ], [ 1 ] ], 17 | [ "T2A", 2, 0, [ [ 0, 0 ], [ 1, 0 ] ], [ 2 ] ], 18 | [ "Out", 2, 0, [ [ -1, 0 ], [ 2, 0 ] ], [ ] ] 19 | ] 20 | }; 21 | const synth = context.createSynth(synthdef).appendTo(context); 22 | const actual = context.audioBuses[0]; 23 | 24 | { 25 | synth.unitList[0].outputs[0].fill(0); 26 | context.process(); 27 | 28 | const expected = new Float32Array(64); 29 | 30 | // for (let i = 0; i < 64; i++) { 31 | // console.log(actual[i]); 32 | // } 33 | 34 | assert.deepEqual(actual, expected); 35 | } 36 | { 37 | synth.unitList[0].outputs[0][0] = 0.5; 38 | synth.unitList[1].outputs[0][0] = 8; 39 | context.process(); 40 | 41 | const expected = new Float32Array(64); 42 | 43 | expected[8] = 0.5; 44 | 45 | // for (let i = 0; i < 64; i++) { 46 | // console.log(actual[i]); 47 | // } 48 | 49 | assert.deepEqual(actual, expected); 50 | } 51 | }); 52 | -------------------------------------------------------------------------------- /test/unit/SCUnitT2K.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const scsynth = require("../../src"); 6 | 7 | test("a", () => { 8 | const context = new scsynth.SCContext({ blockSize: 64 }); 9 | const synthdef = { 10 | name: "T2KTest", 11 | consts: [ 0 ], 12 | paramValues: {}, 13 | paramIndices: {}, 14 | units: [ 15 | [ "DC" , 2, 0, [ [ -1, 0 ] ], [ 2 ] ], 16 | [ "T2K", 1, 0, [ [ 0, 0 ] ], [ 1 ] ], 17 | [ "Out", 1, 0, [ [ -1, 0 ], [ 1, 0 ] ], [ ] ] 18 | ] 19 | }; 20 | const synth = context.createSynth(synthdef).appendTo(context); 21 | const actual = context.controlBuses[0]; 22 | 23 | { 24 | synth.unitList[0].outputs[0].fill(0); 25 | context.process(); 26 | 27 | const expected = new Float32Array([ 0 ]); 28 | 29 | // for (let i = 0; i < 64; i++) { 30 | // console.log(actual[i]); 31 | // } 32 | 33 | assert.deepEqual(actual, expected); 34 | } 35 | { 36 | synth.unitList[0].outputs[0][16] = 0.5; 37 | synth.unitList[0].outputs[0][32] = 0.8; 38 | synth.unitList[0].outputs[0][48] = 0.2; 39 | context.process(); 40 | 41 | const expected = new Float32Array([ 0.8 ]); 42 | 43 | // for (let i = 0; i < 64; i++) { 44 | // console.log(actual[i]); 45 | // } 46 | 47 | assert.deepEqual(actual, expected); 48 | } 49 | }); 50 | -------------------------------------------------------------------------------- /test/unit/SCUnitWhiteNoise.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const test = require("eatest"); 5 | const scsynth = require("../../src"); 6 | 7 | test("a", () => { 8 | const context = new scsynth.SCContext({ blockSize: 64 }); 9 | const synthdef = { 10 | name: "WhiteNoiseTest", 11 | consts: [ 0 ], 12 | paramValues: {}, 13 | paramIndices: {}, 14 | units: [ 15 | [ "WhiteNoise", 2, 0, [ ], [ 2 ] ], 16 | [ "Out" , 2, 0, [ [ -1, 0 ], [ 0, 0 ] ], [ ] ] 17 | ] 18 | }; 19 | const synth = context.createSynth(synthdef).appendTo(context); 20 | const actual = context.audioBuses[0]; 21 | 22 | { 23 | synth.unitList[0].outputs[0]; 24 | context.process(); 25 | 26 | const expected = x => -1 <= x && x <= 1; 27 | 28 | // for (let i = 0; i < 64; i++) { 29 | // console.log(actual[i]); 30 | // } 31 | 32 | assert(actual.every(expected)); 33 | } 34 | }); 35 | -------------------------------------------------------------------------------- /test/unit/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const assert = require("assert"); 4 | const path = require("path"); 5 | const fs = require("fs"); 6 | const unitClassIndices = require("../../src/unit"); 7 | 8 | const unitClasses = fs.readdirSync(path.join(__dirname, "../../src/unit")) 9 | .filter(filename => /^SCUnit\w+\.js$/.test(filename)) 10 | .map(filename => filename.replace(/\.js$/, "")); 11 | 12 | unitClasses.forEach((unitClass) => { 13 | const exportedClass = unitClassIndices[unitClass]; 14 | const requiredClass = require(path.join(__dirname, "../../src/unit", unitClass)); 15 | 16 | assert(exportedClass === requiredClass, `${ unitClass } is not exported`); 17 | }); 18 | --------------------------------------------------------------------------------