├── .clang-format ├── .gitattributes ├── .github └── workflows │ ├── build.yml │ └── wheels.yml ├── .gitignore ├── CHANGELOG.md ├── CMakeLists.txt ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── auxiliary ├── cibuildwheel │ ├── .gitignore │ ├── make-macos-x86-arm64.sh │ ├── make-raspberry-pi-aarch64.sh │ └── make-windows-amd64.py ├── libs │ ├── signalflow-stubs │ │ ├── __init__.py │ │ └── signalflow.pyi │ ├── signalflow │ │ └── __init__.py │ ├── signalflow_analysis │ │ ├── __init__.py │ │ └── audio_feature_buffer.py │ ├── signalflow_cli │ │ └── __init__.py │ ├── signalflow_examples │ │ ├── __init__.py │ │ └── signalflow_examples.py │ ├── signalflow_midi │ │ ├── __init__.py │ │ └── signalflow_midi.py │ └── signalflow_visualisation │ │ ├── __init__.py │ │ ├── buffer.py │ │ ├── node.py │ │ └── patch_structure.py ├── prototypes │ ├── README.md │ └── kdtree │ │ └── kdtree.py └── scripts │ └── auto-generator.py ├── docs ├── CNAME ├── buffer │ ├── access.md │ ├── creating.md │ ├── exporting.md │ ├── index.md │ ├── input.md │ ├── operators.md │ └── properties.md ├── code-of-conduct.md ├── examples.md ├── graph │ ├── config.md │ ├── creating.md │ ├── index.md │ ├── properties.md │ ├── recording.md │ └── stopping.md ├── howto │ ├── index.md │ └── midi.md ├── images │ └── sinewave.svg ├── index.md ├── installation │ ├── command-line.md │ ├── easy.md │ ├── index.md │ └── next-steps.md ├── library │ ├── analysis │ │ ├── crosscorrelate │ │ │ └── index.md │ │ ├── index.md │ │ ├── nearestneighbour │ │ │ └── index.md │ │ ├── onsetdetector │ │ │ └── index.md │ │ └── vampanalysis │ │ │ └── index.md │ ├── buffer │ │ ├── beatcutter │ │ │ └── index.md │ │ ├── bufferlooper │ │ │ └── index.md │ │ ├── bufferplayer │ │ │ └── index.md │ │ ├── bufferrecorder │ │ │ └── index.md │ │ ├── feedbackbufferreader │ │ │ └── index.md │ │ ├── feedbackbufferwriter │ │ │ └── index.md │ │ ├── grainsegments │ │ │ └── index.md │ │ ├── granulation │ │ │ ├── granulator │ │ │ │ └── index.md │ │ │ ├── index.md │ │ │ └── segmentedgranulator │ │ │ │ └── index.md │ │ ├── granulator │ │ │ └── index.md │ │ ├── historybufferwriter │ │ │ └── index.md │ │ ├── index.md │ │ └── segmentplayer │ │ │ └── index.md │ ├── control │ │ ├── index.md │ │ ├── mousedown │ │ │ ├── example-0.py │ │ │ ├── example-1.py │ │ │ └── index.md │ │ ├── mousex │ │ │ ├── example-0.py │ │ │ ├── example-1.py │ │ │ └── index.md │ │ └── mousey │ │ │ ├── example-0.py │ │ │ ├── example-1.py │ │ │ └── index.md │ ├── envelope │ │ ├── accumulator │ │ │ └── index.md │ │ ├── adsrenvelope │ │ │ └── index.md │ │ ├── asrenvelope │ │ │ ├── example-0.py │ │ │ ├── example-1.py │ │ │ └── index.md │ │ ├── detectsilence │ │ │ └── index.md │ │ ├── envelope │ │ │ └── index.md │ │ ├── index.md │ │ ├── line │ │ │ ├── example-0.py │ │ │ ├── example-1.py │ │ │ └── index.md │ │ └── rectangularenvelope │ │ │ └── index.md │ ├── fft │ │ ├── fft │ │ │ └── index.md │ │ ├── fftbufferplayer │ │ │ └── index.md │ │ ├── fftcontinuousphasevocoder │ │ │ └── index.md │ │ ├── fftcontrast │ │ │ └── index.md │ │ ├── fftconvolve │ │ │ └── index.md │ │ ├── fftcrossfade │ │ │ └── index.md │ │ ├── fftfindpeaks │ │ │ └── index.md │ │ ├── fftflipspectrum │ │ │ └── index.md │ │ ├── fftlfo │ │ │ └── index.md │ │ ├── fftlpf │ │ │ └── index.md │ │ ├── fftmagnitudephasearray │ │ │ └── index.md │ │ ├── fftnoisegate │ │ │ └── index.md │ │ ├── fftphasevocoder │ │ │ └── index.md │ │ ├── fftrandomphase │ │ │ └── index.md │ │ ├── fftscalemagnitudes │ │ │ └── index.md │ │ ├── ffttonality │ │ │ └── index.md │ │ ├── ffttransform │ │ │ └── index.md │ │ ├── fftzerophase │ │ │ └── index.md │ │ ├── ifft │ │ │ └── index.md │ │ └── index.md │ ├── index.md │ ├── operators │ │ ├── abs │ │ │ └── index.md │ │ ├── add │ │ │ └── index.md │ │ ├── amplitudetodecibels │ │ │ └── index.md │ │ ├── bus │ │ │ └── index.md │ │ ├── channelarray │ │ │ ├── example-0.py │ │ │ └── index.md │ │ ├── channelcrossfade │ │ │ └── index.md │ │ ├── channelmixer │ │ │ └── index.md │ │ ├── channeloffset │ │ │ └── index.md │ │ ├── channelselect │ │ │ └── index.md │ │ ├── cos │ │ │ └── index.md │ │ ├── decibelstoamplitude │ │ │ └── index.md │ │ ├── divide │ │ │ └── index.md │ │ ├── equal │ │ │ └── index.md │ │ ├── frequencytomidinote │ │ │ └── index.md │ │ ├── greaterthan │ │ │ └── index.md │ │ ├── greaterthanorequal │ │ │ └── index.md │ │ ├── if │ │ │ └── index.md │ │ ├── index.md │ │ ├── lessthan │ │ │ └── index.md │ │ ├── lessthanorequal │ │ │ └── index.md │ │ ├── midinotetofrequency │ │ │ └── index.md │ │ ├── modulo │ │ │ └── index.md │ │ ├── multiply │ │ │ └── index.md │ │ ├── notequal │ │ │ └── index.md │ │ ├── pow │ │ │ └── index.md │ │ ├── round │ │ │ └── index.md │ │ ├── roundtoscale │ │ │ └── index.md │ │ ├── scalelinexp │ │ │ └── index.md │ │ ├── scalelinlin │ │ │ └── index.md │ │ ├── selectinput │ │ │ └── index.md │ │ ├── sin │ │ │ └── index.md │ │ ├── subtract │ │ │ └── index.md │ │ ├── sum │ │ │ └── index.md │ │ ├── tan │ │ │ └── index.md │ │ ├── tanh │ │ │ └── index.md │ │ ├── timeshift │ │ │ └── index.md │ │ └── triggermult │ │ │ └── index.md │ ├── oscillators │ │ ├── constant │ │ │ └── index.md │ │ ├── impulse │ │ │ ├── example-0.py │ │ │ └── index.md │ │ ├── index.md │ │ ├── sawlfo │ │ │ ├── example-0.py │ │ │ └── index.md │ │ ├── sawoscillator │ │ │ ├── example-0.py │ │ │ └── index.md │ │ ├── sinelfo │ │ │ ├── example-0.py │ │ │ └── index.md │ │ ├── sineoscillator │ │ │ ├── example-0.py │ │ │ └── index.md │ │ ├── squarelfo │ │ │ ├── example-0.py │ │ │ └── index.md │ │ ├── squareoscillator │ │ │ ├── example-0.py │ │ │ └── index.md │ │ ├── trianglelfo │ │ │ ├── example-0.py │ │ │ └── index.md │ │ ├── triangleoscillator │ │ │ ├── example-0.py │ │ │ └── index.md │ │ ├── wavetable │ │ │ └── index.md │ │ └── wavetable2d │ │ │ └── index.md │ ├── processors │ │ ├── clip │ │ │ └── index.md │ │ ├── delays │ │ │ ├── allpassdelay │ │ │ │ ├── example-0.py │ │ │ │ ├── example-1.py │ │ │ │ └── index.md │ │ │ ├── combdelay │ │ │ │ ├── example-0.py │ │ │ │ └── index.md │ │ │ ├── index.md │ │ │ ├── onetapdelay │ │ │ │ ├── example-0.py │ │ │ │ ├── example-1.py │ │ │ │ └── index.md │ │ │ └── stutter │ │ │ │ └── index.md │ │ ├── distortion │ │ │ ├── index.md │ │ │ ├── resample │ │ │ │ ├── example-0.py │ │ │ │ └── index.md │ │ │ ├── sampleandhold │ │ │ │ └── index.md │ │ │ ├── squiz │ │ │ │ └── index.md │ │ │ └── waveshaper │ │ │ │ ├── example-0.py │ │ │ │ ├── example-1.py │ │ │ │ └── index.md │ │ ├── dynamics │ │ │ ├── compressor │ │ │ │ └── index.md │ │ │ ├── gate │ │ │ │ └── index.md │ │ │ ├── index.md │ │ │ ├── maximiser │ │ │ │ └── index.md │ │ │ └── rms │ │ │ │ └── index.md │ │ ├── filters │ │ │ ├── biquadfilter │ │ │ │ └── index.md │ │ │ ├── dcfilter │ │ │ │ └── index.md │ │ │ ├── eq │ │ │ │ ├── example-0.py │ │ │ │ └── index.md │ │ │ ├── index.md │ │ │ ├── moogvcf │ │ │ │ └── index.md │ │ │ └── svfilter │ │ │ │ ├── example-0.py │ │ │ │ ├── example-1.py │ │ │ │ └── index.md │ │ ├── fold │ │ │ └── index.md │ │ ├── index.md │ │ ├── panning │ │ │ ├── azimuthpanner │ │ │ │ └── index.md │ │ │ ├── channelpanner │ │ │ │ └── index.md │ │ │ ├── index.md │ │ │ ├── spatialpanner │ │ │ │ └── index.md │ │ │ ├── stereobalance │ │ │ │ ├── example-0.py │ │ │ │ └── index.md │ │ │ ├── stereopanner │ │ │ │ ├── example-0.py │ │ │ │ ├── example-1.py │ │ │ │ └── index.md │ │ │ └── stereowidth │ │ │ │ ├── example-0.py │ │ │ │ └── index.md │ │ ├── smooth │ │ │ └── index.md │ │ ├── wetdry │ │ │ └── index.md │ │ └── wrap │ │ │ └── index.md │ ├── sequencing │ │ ├── clockdivider │ │ │ ├── example-0.py │ │ │ └── index.md │ │ ├── counter │ │ │ └── index.md │ │ ├── euclidean │ │ │ └── index.md │ │ ├── flipflop │ │ │ └── index.md │ │ ├── impulsesequence │ │ │ └── index.md │ │ ├── index.md │ │ ├── index │ │ │ └── index.md │ │ ├── latch │ │ │ └── index.md │ │ ├── sequence │ │ │ ├── example-0.py │ │ │ └── index.md │ │ ├── triggermult │ │ │ └── index.md │ │ └── triggerroundrobin │ │ │ └── index.md │ └── stochastic │ │ ├── index.md │ │ ├── logistic │ │ └── index.md │ │ ├── pinknoise │ │ └── index.md │ │ ├── randombrownian │ │ └── index.md │ │ ├── randomchoice │ │ └── index.md │ │ ├── randomcoin │ │ └── index.md │ │ ├── randomexponential │ │ └── index.md │ │ ├── randomexponentialdist │ │ └── index.md │ │ ├── randomgaussian │ │ └── index.md │ │ ├── randomimpulse │ │ └── index.md │ │ ├── randomimpulsesequence │ │ └── index.md │ │ ├── randomuniform │ │ └── index.md │ │ └── whitenoise │ │ ├── example-0.py │ │ ├── example-1.py │ │ └── index.md ├── license.md ├── node │ ├── developing.md │ ├── index.md │ ├── inputs.md │ ├── multichannel.md │ ├── operators.md │ ├── playback.md │ ├── properties.md │ └── stochastic.md ├── patch │ ├── auto-free.md │ ├── defining.md │ ├── exporting.md │ ├── index.md │ ├── inputs.md │ ├── operators.md │ ├── playback.md │ └── properties.md ├── robots.txt └── troubleshooting │ ├── device_not_found_exception.md │ ├── index.md │ ├── installation.md │ ├── insufficient_buffer_size_exception.md │ ├── node_already_playing_exception.md │ └── node_not_playing_exception.md ├── examples ├── audio-through-example.py ├── audio │ ├── gliss.aif │ └── stereo-count.wav ├── buffer-play-example.py ├── chaotic-feedback-example.py ├── euclidean-rhythm-example.py ├── granulation-example.py ├── hello-world-example.py ├── karplus-strong-example.py ├── midi-fm-voicer-example.py ├── midi-keyboard-example.py ├── modulation-example.py ├── notebooks │ ├── 01. Hello World.ipynb │ └── 02. Patch Example.ipynb ├── patches │ ├── kick-drum.json │ ├── sine-env-delay.json │ └── sine.json ├── sequencing-example.py └── wavetable-2d-example.py ├── mkdocs.yml ├── pyproject.toml ├── setup.cfg ├── setup.py ├── source ├── include │ └── signalflow │ │ ├── buffer │ │ ├── buffer.h │ │ ├── buffer2d.h │ │ ├── envelope-buffer.h │ │ ├── fftbuffer.h │ │ ├── ringbuffer.h │ │ ├── waveshaper-buffer.h │ │ └── wavetable-buffer.h │ │ ├── core │ │ ├── config.h │ │ ├── constants.h │ │ ├── core.h │ │ ├── exceptions.h │ │ ├── graph-monitor.h │ │ ├── graph.h │ │ ├── kdtree.h │ │ ├── platform.h │ │ ├── property.h │ │ ├── random.h │ │ ├── renderer.h │ │ ├── util.h │ │ └── version.h │ │ ├── node │ │ ├── analysis │ │ │ ├── cross-correlate.h │ │ │ ├── nearest-neighbour.h │ │ │ ├── onset-detector.h │ │ │ └── vamp.h │ │ ├── buffer │ │ │ ├── beat-cutter.h │ │ │ ├── buffer-looper.h │ │ │ ├── buffer-player.h │ │ │ ├── buffer-recorder.h │ │ │ ├── feedback-buffer-reader.h │ │ │ ├── feedback-buffer-writer.h │ │ │ ├── granulation │ │ │ │ ├── grain.h │ │ │ │ ├── grainsegments.h │ │ │ │ └── granulator.h │ │ │ ├── history-buffer-writer.h │ │ │ └── segment-player.h │ │ ├── control │ │ │ └── mouse.h │ │ ├── envelope │ │ │ ├── accumulator.h │ │ │ ├── adsr.h │ │ │ ├── asr.h │ │ │ ├── detect-silence.h │ │ │ ├── envelope.h │ │ │ ├── line.h │ │ │ └── rect.h │ │ ├── fft │ │ │ ├── continuous-pv.h │ │ │ ├── convolve.h │ │ │ ├── fft-buffer-player.h │ │ │ ├── fft-contrast.h │ │ │ ├── fft-cross-fade.h │ │ │ ├── fft-lfo.h │ │ │ ├── fft-magnitude-phase-array.h │ │ │ ├── fft-random-phase.h │ │ │ ├── fft-scale-magnitudes.h │ │ │ ├── fft-transform.h │ │ │ ├── fft.h │ │ │ ├── fftnode.h │ │ │ ├── find-peaks.h │ │ │ ├── ifft.h │ │ │ ├── lpf.h │ │ │ ├── noise-gate.h │ │ │ ├── phase-vocoder.h │ │ │ ├── tonality.h │ │ │ └── zero_phase.h │ │ ├── io │ │ │ ├── input │ │ │ │ ├── abstract.h │ │ │ │ └── miniaudio.h │ │ │ └── output │ │ │ │ ├── abstract.h │ │ │ │ ├── dummy.h │ │ │ │ └── miniaudio.h │ │ ├── node-monitor.h │ │ ├── node.h │ │ ├── operators │ │ │ ├── add.h │ │ │ ├── amplitude-to-decibels.h │ │ │ ├── bus.h │ │ │ ├── channel-array.h │ │ │ ├── channel-crossfade.h │ │ │ ├── channel-mixer.h │ │ │ ├── channel-offset.h │ │ │ ├── channel-select.h │ │ │ ├── comparison.h │ │ │ ├── divide.h │ │ │ ├── frequency-to-midi-note.h │ │ │ ├── midi-note-to-frequency.h │ │ │ ├── multiply.h │ │ │ ├── pow.h │ │ │ ├── round-to-scale.h │ │ │ ├── round.h │ │ │ ├── scale.h │ │ │ ├── select-input.h │ │ │ ├── subtract.h │ │ │ ├── sum.h │ │ │ ├── time-shift.h │ │ │ └── trigonometry.h │ │ ├── oscillators │ │ │ ├── constant.h │ │ │ ├── impulse.h │ │ │ ├── lfo.h │ │ │ ├── saw-lfo.h │ │ │ ├── saw.h │ │ │ ├── sine-lfo.h │ │ │ ├── sine.h │ │ │ ├── square-lfo.h │ │ │ ├── square.h │ │ │ ├── triangle-lfo.h │ │ │ ├── triangle.h │ │ │ └── wavetable.h │ │ ├── physical │ │ │ └── maraca.h │ │ ├── processors │ │ │ ├── clip.h │ │ │ ├── delays │ │ │ │ ├── allpass.h │ │ │ │ ├── comb.h │ │ │ │ ├── onetap.h │ │ │ │ └── stutter.h │ │ │ ├── distortion │ │ │ │ ├── resample.h │ │ │ │ ├── sample-and-hold.h │ │ │ │ ├── squiz.h │ │ │ │ └── waveshaper.h │ │ │ ├── dynamics │ │ │ │ ├── compressor.h │ │ │ │ ├── gate.h │ │ │ │ ├── maximiser.h │ │ │ │ └── rms.h │ │ │ ├── filters │ │ │ │ ├── biquad.h │ │ │ │ ├── dc.h │ │ │ │ ├── eq.h │ │ │ │ ├── moog.h │ │ │ │ └── svf.h │ │ │ ├── fold.h │ │ │ ├── panning │ │ │ │ ├── azimuth-panner.h │ │ │ │ ├── channel-panner.h │ │ │ │ ├── spatial-environment.h │ │ │ │ ├── stereo-balance.h │ │ │ │ ├── stereo-panner.h │ │ │ │ └── stereo-width.h │ │ │ ├── smooth.h │ │ │ ├── wetdry.h │ │ │ └── wrap.h │ │ ├── registry.h │ │ ├── sequencing │ │ │ ├── block-counter.h │ │ │ ├── clock-divider.h │ │ │ ├── counter.h │ │ │ ├── euclidean.h │ │ │ ├── flipflop.h │ │ │ ├── impulse-sequence.h │ │ │ ├── index.h │ │ │ ├── latch.h │ │ │ ├── sequence.h │ │ │ ├── trigger-mult.h │ │ │ └── trigger-round-robin.h │ │ └── stochastic │ │ │ ├── logistic.h │ │ │ ├── pink-noise.h │ │ │ ├── random-brownian.h │ │ │ ├── random-choice.h │ │ │ ├── random-coin.h │ │ │ ├── random-exponential-dist.h │ │ │ ├── random-exponential.h │ │ │ ├── random-gaussian.h │ │ │ ├── random-impulse-sequence.h │ │ │ ├── random-impulse.h │ │ │ ├── random-uniform.h │ │ │ ├── stochastic-node.h │ │ │ └── white-noise.h │ │ ├── patch │ │ ├── patch-node-spec.h │ │ ├── patch-registry.h │ │ ├── patch-spec.h │ │ └── patch.h │ │ ├── python │ │ └── python.h │ │ └── signalflow.h ├── lib │ ├── json11 │ │ ├── LICENSE.txt │ │ ├── json11.cpp │ │ └── json11.hpp │ └── pybind11 │ │ ├── attr.h │ │ ├── buffer_info.h │ │ ├── cast.h │ │ ├── chrono.h │ │ ├── common.h │ │ ├── complex.h │ │ ├── detail │ │ ├── class.h │ │ ├── common.h │ │ ├── descr.h │ │ ├── init.h │ │ ├── internals.h │ │ ├── type_caster_base.h │ │ └── typeid.h │ │ ├── eigen.h │ │ ├── eigen │ │ ├── matrix.h │ │ └── tensor.h │ │ ├── embed.h │ │ ├── eval.h │ │ ├── functional.h │ │ ├── gil.h │ │ ├── iostream.h │ │ ├── numpy.h │ │ ├── operators.h │ │ ├── options.h │ │ ├── pybind11.h │ │ ├── pytypes.h │ │ ├── stl.h │ │ ├── stl │ │ └── filesystem.h │ │ └── stl_bind.h └── src │ ├── CMakeLists.txt │ ├── buffer │ ├── buffer.cpp │ ├── buffer2d.cpp │ ├── envelope-buffer.cpp │ ├── fftbuffer.cpp │ ├── waveshaper-buffer.cpp │ └── wavetable-buffer.cpp │ ├── bus │ └── bus.cpp │ ├── core │ ├── config.cpp │ ├── core.cpp │ ├── graph-monitor.cpp │ ├── graph.cpp │ ├── kdtree.cpp │ ├── random.cpp │ ├── renderer.cpp │ └── util.cpp │ ├── node │ ├── analysis │ │ ├── cross-correlate.cpp │ │ ├── nearest-neighbour.cpp │ │ ├── onset-detector.cpp │ │ └── vamp.cpp │ ├── buffer │ │ ├── beat-cutter.cpp │ │ ├── buffer-looper.cpp │ │ ├── buffer-player.cpp │ │ ├── buffer-recorder.cpp │ │ ├── feedback-buffer-reader.cpp │ │ ├── feedback-buffer-writer.cpp │ │ ├── granulation │ │ │ ├── grain.cpp │ │ │ ├── grainsegments.cpp │ │ │ └── granulator.cpp │ │ ├── history-buffer-writer.cpp │ │ └── segment-player.cpp │ ├── control │ │ └── mouse.mm │ ├── envelope │ │ ├── accumulator.cpp │ │ ├── adsr.cpp │ │ ├── asr.cpp │ │ ├── detect-silence.cpp │ │ ├── envelope.cpp │ │ ├── line.cpp │ │ └── rect.cpp │ ├── fft │ │ ├── continuous-pv.cpp │ │ ├── convolve.cpp │ │ ├── fft-buffer-player.cpp │ │ ├── fft-contrast.cpp │ │ ├── fft-cross-fade.cpp │ │ ├── fft-lfo.cpp │ │ ├── fft-magnitude-phase-array.cpp │ │ ├── fft-random-phase.cpp │ │ ├── fft-scale-magnitudes.cpp │ │ ├── fft-transform.cpp │ │ ├── fft.cpp │ │ ├── fftnode.cpp │ │ ├── find-peaks.cpp │ │ ├── ifft.cpp │ │ ├── lpf.cpp │ │ ├── noise-gate.cpp │ │ ├── phase-vocoder.cpp │ │ └── tonality.cpp │ ├── io │ │ ├── input │ │ │ ├── abstract.cpp │ │ │ └── miniaudio.cpp │ │ └── output │ │ │ ├── abstract.cpp │ │ │ ├── dummy.cpp │ │ │ └── miniaudio.cpp │ ├── node-monitor.cpp │ ├── node.cpp │ ├── operators │ │ ├── add.cpp │ │ ├── amplitude-to-decibels.cpp │ │ ├── bus.cpp │ │ ├── channel-array.cpp │ │ ├── channel-crossfade.cpp │ │ ├── channel-mixer.cpp │ │ ├── channel-offset.cpp │ │ ├── channel-select.cpp │ │ ├── comparison.cpp │ │ ├── divide.cpp │ │ ├── frequency-to-midi-note.cpp │ │ ├── midi-note-to-frequency.cpp │ │ ├── multiply.cpp │ │ ├── pow.cpp │ │ ├── round-to-scale.cpp │ │ ├── round.cpp │ │ ├── scale.cpp │ │ ├── select-input.cpp │ │ ├── subtract.cpp │ │ ├── sum.cpp │ │ ├── time-shift.cpp │ │ └── trigonometry.cpp │ ├── oscillators │ │ ├── constant.cpp │ │ ├── impulse.cpp │ │ ├── lfo │ │ │ ├── lfo.cpp │ │ │ ├── saw-lfo.cpp │ │ │ ├── sine-lfo.cpp │ │ │ ├── square-lfo.cpp │ │ │ └── triangle-lfo.cpp │ │ ├── saw.cpp │ │ ├── sine.cpp │ │ ├── square.cpp │ │ ├── triangle.cpp │ │ └── wavetable.cpp │ ├── physical │ │ └── maraca.cpp │ ├── processors │ │ ├── clip.cpp │ │ ├── delays │ │ │ ├── allpass.cpp │ │ │ ├── comb.cpp │ │ │ ├── onetap.cpp │ │ │ └── stutter.cpp │ │ ├── distortion │ │ │ ├── resample.cpp │ │ │ ├── sample-and-hold.cpp │ │ │ ├── squiz.cpp │ │ │ └── waveshaper.cpp │ │ ├── dynamics │ │ │ ├── compressor.cpp │ │ │ ├── gate.cpp │ │ │ ├── maximiser.cpp │ │ │ └── rms.cpp │ │ ├── filters │ │ │ ├── biquad.cpp │ │ │ ├── dc.cpp │ │ │ ├── eq.cpp │ │ │ ├── moog.cpp │ │ │ └── svf.cpp │ │ ├── fold.cpp │ │ ├── panning │ │ │ ├── azimuth-panner.cpp │ │ │ ├── channel-panner.cpp │ │ │ ├── spatial-environment.cpp │ │ │ ├── stereo-balance.cpp │ │ │ ├── stereo-panner.cpp │ │ │ └── stereo-width.cpp │ │ ├── smooth.cpp │ │ ├── wetdry.cpp │ │ └── wrap.cpp │ ├── registry.cpp │ ├── sequencing │ │ ├── block-counter.cpp │ │ ├── clock-divider.cpp │ │ ├── counter.cpp │ │ ├── euclidean.cpp │ │ ├── flipflop.cpp │ │ ├── impulse-sequence.cpp │ │ ├── index.cpp │ │ ├── latch.cpp │ │ ├── sequence.cpp │ │ ├── trigger-mult.cpp │ │ └── trigger-round-robin.cpp │ └── stochastic │ │ ├── logistic.cpp │ │ ├── pink-noise.cpp │ │ ├── random-brownian.cpp │ │ ├── random-choice.cpp │ │ ├── random-coin.cpp │ │ ├── random-exponential-dist.cpp │ │ ├── random-exponential.cpp │ │ ├── random-gaussian.cpp │ │ ├── random-impulse-sequence.cpp │ │ ├── random-impulse.cpp │ │ ├── random-uniform.cpp │ │ ├── stochastic-node.cpp │ │ └── white-noise.cpp │ ├── patch │ ├── patch-node-spec.cpp │ ├── patch-registry.cpp │ ├── patch-spec.cpp │ └── patch.cpp │ └── python │ ├── buffer.cpp │ ├── config.cpp │ ├── constants.cpp │ ├── exceptions.cpp │ ├── graph.cpp │ ├── node.cpp │ ├── nodes.cpp │ ├── patch.cpp │ ├── python.cpp │ └── util.cpp └── tests ├── __init__.py ├── audio └── 440hz.wav ├── test_buffer.py ├── test_config.py ├── test_examples.py ├── test_graph.py ├── test_kdtree.py ├── test_node.py ├── test_node_multichannel_expansion.py ├── test_node_operators.py ├── test_node_registry.py ├── test_nodes_buffer.py ├── test_nodes_delays.py ├── test_nodes_envelope.py ├── test_nodes_fft.py ├── test_nodes_granulator.py ├── test_nodes_oscillators.py ├── test_nodes_oscillators_lfo.py ├── test_nodes_processors_multichannel.py ├── test_nodes_sequencing.py ├── test_nodes_stochastic.py ├── test_patch.py └── test_util.py /.clang-format: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------ 2 | # Code formatting rules for SignalFlow 3 | #------------------------------------------------------------------------ 4 | --- 5 | BasedOnStyle: WebKit 6 | BreakBeforeBraces: Allman 7 | UseTab: Never 8 | TabWidth: 4 9 | IndentWidth: 4 10 | PointerAlignment: Right 11 | AlignAfterOpenBracket: true 12 | AlignTrailingComments: true 13 | BreakConstructorInitializersBeforeComma: false 14 | ConstructorInitializerAllOnOneLineOrOnePerLine: true 15 | IndentCaseLabels: true 16 | SpaceAfterCStyleCast: true 17 | 18 | # Not supported by CLion clang-format 19 | # AllowAllConstructorInitializersOnNextLine: true 20 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | #-------------------------------------------------------------------------------- 2 | # Configure clean and smudge filters to apply when checking code in and out 3 | # of git respectively. 4 | # 5 | # To use these rules, the clang-format filter must be first be set up adding 6 | # to .gitconfig: 7 | # 8 | # git config --global filter.clang-format.clean clang-format 9 | # git config --global filter.clang-format.smudge cat 10 | #-------------------------------------------------------------------------------- 11 | *.cpp filter=clang-format 12 | *.h filter=clang-format 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.build/ 3 | build/ 4 | dev/ 5 | examples/audio 6 | examples-dev/ 7 | recordings/ 8 | _site/ 9 | site/ 10 | TODO.md 11 | NOTES.md 12 | *.swp 13 | *-test 14 | *-test.cpp 15 | test-*.cpp 16 | *.dSYM 17 | *.o 18 | .lock* 19 | .waf* 20 | docs/html 21 | signal/local.h 22 | .idea 23 | *.so 24 | *.dylib 25 | *.egg-info 26 | .eggs 27 | __pycache__ 28 | dist 29 | .cmake-* 30 | .coverage 31 | .ipynb_checkpoints 32 | wheelhouse/ 33 | .vscode 34 | .vs 35 | miniaudio-library.h 36 | -------------------------------------------------------------------------------- /auxiliary/cibuildwheel/.gitignore: -------------------------------------------------------------------------------- 1 | wheelhouse 2 | -------------------------------------------------------------------------------- /auxiliary/libs/signalflow-stubs/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Stubs for type hinting and inline documentation. 3 | See PEP 561: https://peps.python.org/pep-0561/ 4 | 5 | The stub file imported below is autogenerated by pybind11-stubgen. 6 | """ 7 | 8 | from .signalflow import * 9 | -------------------------------------------------------------------------------- /auxiliary/libs/signalflow/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | This package is used on Windows only, as a container for the .pyd file and 3 | platform-specific DLLs. 4 | 5 | On Linux and macOS, the bare .so file is copied. 6 | """ 7 | from .signalflow import * 8 | -------------------------------------------------------------------------------- /auxiliary/libs/signalflow_analysis/__init__.py: -------------------------------------------------------------------------------- 1 | from .audio_feature_buffer import AudioFeatureBuffer -------------------------------------------------------------------------------- /auxiliary/libs/signalflow_examples/__init__.py: -------------------------------------------------------------------------------- 1 | from .signalflow_examples import download_examples, download_notebooks 2 | -------------------------------------------------------------------------------- /auxiliary/libs/signalflow_midi/__init__.py: -------------------------------------------------------------------------------- 1 | from .signalflow_midi import * 2 | -------------------------------------------------------------------------------- /auxiliary/libs/signalflow_visualisation/__init__.py: -------------------------------------------------------------------------------- 1 | from .patch_structure import visualise_patch_structure 2 | from .node import plot_node_output 3 | from .buffer import plot_buffer -------------------------------------------------------------------------------- /auxiliary/libs/signalflow_visualisation/node.py: -------------------------------------------------------------------------------- 1 | from signalflow import Node 2 | import matplotlib.pyplot as plt 3 | import numpy as np 4 | 5 | def plot_node_output(node: Node, duration: float = 1.0): 6 | # TODO: Replace with graph.render_subgraph_to_new_buffer(node) when this is implemented 7 | num_frames = int(duration * node.graph.sample_rate) 8 | output = np.zeros(num_frames) 9 | num_chunks = int(np.ceil(num_frames / node.graph.output_buffer_size)) 10 | for n in range(0, num_chunks): 11 | offset_start = n * node.graph.output_buffer_size 12 | offset_end = (n + 1) * node.graph.output_buffer_size 13 | offset_end = min(num_frames, offset_end) 14 | chunk_length = offset_end - offset_start 15 | node.graph.reset_subgraph(node) 16 | node.graph.render_subgraph(node) 17 | output[offset_start:offset_end] = node.output_buffer[0][:chunk_length] 18 | plt.plot(output) 19 | plt.show() -------------------------------------------------------------------------------- /auxiliary/prototypes/README.md: -------------------------------------------------------------------------------- 1 | # Prototypes 2 | 3 | This directory contains Python prototypes of algorithms implemented within SignalFlow. 4 | 5 | - [kdtree](kdtree): A kd-tree, used for nearest neighbour search 6 | -------------------------------------------------------------------------------- /docs/CNAME: -------------------------------------------------------------------------------- 1 | signalflow.dev 2 | -------------------------------------------------------------------------------- /docs/buffer/exporting.md: -------------------------------------------------------------------------------- 1 | # Saving and exporting a buffer 2 | 3 | ## Saving to a sound file 4 | 5 | To export a buffer's audio contents to a sound file, use the `save()` method: 6 | 7 | ```python 8 | import numpy as np 9 | buf = Buffer(np.sin(np.linspace(0, 1, graph.sample_rate) * 440 * np.pi * 2)) 10 | buf.save("buffer.wav") 11 | ``` 12 | 13 | The output format will be automatically detected from the filename extension. Supported formats are presently `wav`, `aif` and `flac`. 14 | 15 | --- 16 | 17 | [→ Next: Passing a buffer as an input to a node or patch](input.md) -------------------------------------------------------------------------------- /docs/buffer/input.md: -------------------------------------------------------------------------------- 1 | # Passing a buffer as an input to a node or patch 2 | 3 | See: 4 | 5 | - [Node: Buffer inputs](../node/inputs.md#buffer-inputs) 6 | - [Patch: Buffer inputs](../patch/inputs.md#buffer-inputs) 7 | 8 | --- 9 | 10 | [→ Next: Accessing a buffer's data in memory](access.md) -------------------------------------------------------------------------------- /docs/buffer/operators.md: -------------------------------------------------------------------------------- 1 | # Arithmetic operators 2 | 3 | Buffers, [like nodes](../node/operators.md), can be manipulated using Python's standard arithmetic operators. 4 | 5 | For example, to attenuate a buffer, it can be multiplied by a constant value. A new `Buffer` object is returned, with the same dimensions as the original, scaled by the coefficient. 6 | 7 | ```python 8 | input_buffer = Buffer("input.wav") 9 | scaled_buffer = input_buffer * 0.5 10 | # `scaled_buffer` now contains an attenuated version of `input_buffer` 11 | ``` 12 | 13 | Below is a full list of operators supported by SignalFlow `Buffer` objects. 14 | 15 | | Operator | Node class | 16 | |----------|------------| 17 | | `+` | Add | 18 | | `-` | Subtract | 19 | | `*` | Multiply | 20 | | `/` | Divide | 21 | 22 | --- 23 | 24 | [→ Next: Buffer properties](properties.md) -------------------------------------------------------------------------------- /docs/examples.md: -------------------------------------------------------------------------------- 1 | # Examples 2 | 3 | For code examples using SignalFlow, see [GitHub](https://github.com/ideoforms/signalflow/tree/master/examples). 4 | 5 | To download the `examples` folder locally, execute `signalflow download-examples` on the command line, or run the below code: 6 | 7 | ```python3 8 | import signalflow_examples 9 | 10 | signalflow_examples.download_examples() 11 | ``` 12 | -------------------------------------------------------------------------------- /docs/graph/creating.md: -------------------------------------------------------------------------------- 1 | # The AudioGraph 2 | 3 | ## Creating the graph 4 | 5 | Creating the graph is simple: `graph = AudioGraph()` 6 | 7 | By default, a new `AudioGraph` immediately connects to the system's default audio hardware device (via the integrated `libsoundio` library), using the system's default sample rate and buffer size. 8 | 9 | !!! info 10 | Note that the AudioGraph is a singleton object: only one AudioGraph can be created, which is shared globally. 11 | 12 | To prevent the graph from starting instantly (for example, if you want to use the graph in offline mode), pass `start=False` to the constructor. 13 | 14 | To configure graph playback or recording parameters, see [AudioGraph: Configuration](config.md). 15 | 16 | --- 17 | 18 | [→ Next: Graph configuration](config.md) 19 | -------------------------------------------------------------------------------- /docs/graph/index.md: -------------------------------------------------------------------------------- 1 | # The AudioGraph 2 | 3 | `AudioGraph` is the global audio processing system that schedules and performs audio processing. It is comprised of an interconnected network of [Node](../node/index.md) and [Patch](../patch/index.md) objects, which audio flows through. 4 | 5 | Each time a new block of audio is requested by the system audio I/O layer, the `AudioGraph` object is responsible for traversing the tree of nodes and generating new samples by calling each `Node`'s `process` method. 6 | 7 | !!! info "Why 'Graph'?" 8 | You may be more familiar with "graph" being used to mean a data visualisation. In signal processing and discrete mathematics, the term "graph" is also used to denote a system of nodes related by connections. Read more: [Graph Theory Basics](https://courses.lumenlearning.com/wmopen-mathforliberalarts/chapter/introduction-graph-theory/) (Lumen Learning). 9 | 10 | --- 11 | 12 | [→ Next: Creating the graph](creating.md) 13 | -------------------------------------------------------------------------------- /docs/graph/stopping.md: -------------------------------------------------------------------------------- 1 | # The AudioGraph 2 | 3 | ## Clearing and stopping the graph 4 | 5 | To clear all nodes and patches from the graph but leave it running for further audio synthesis: 6 | 7 | ``` 8 | >>> graph.clear() 9 | ``` 10 | 11 | To stop the graph and pause audio I/O: 12 | 13 | ``` 14 | >>> graph.stop() 15 | ``` 16 | 17 | To permanently destroy the graph: 18 | 19 | ``` 20 | >>> graph.destroy() 21 | ``` -------------------------------------------------------------------------------- /docs/howto/index.md: -------------------------------------------------------------------------------- 1 | # Howto 2 | 3 | !!! warning 4 | This documentation is a work-in-progress and may have sections that are missing or incomplete. 5 | 6 | Tutorials on common tasks with SignalFlow. 7 | -------------------------------------------------------------------------------- /docs/howto/midi.md: -------------------------------------------------------------------------------- 1 | # Howto: MIDI control 2 | 3 | -------------------------------------------------------------------------------- /docs/installation/next-steps.md: -------------------------------------------------------------------------------- 1 | ## Next steps 2 | 3 | - **Examples**: [Several example scripts](../examples.md) are available for SignalFlow, covering simple control and modulation, FM synthesis, sample granulation, MIDI control, chaotic functions, etc. 4 | - **Configuration**: To configure your audio hardware, see [AudioGraph configuration](../graph/config.md). 5 | - **Tutorials**: Coming soon 6 | -------------------------------------------------------------------------------- /docs/library/analysis/crosscorrelate/index.md: -------------------------------------------------------------------------------- 1 | title: CrossCorrelate node documentation 2 | description: CrossCorrelate: Outputs the cross-correlation of the input signal with the given buffer. If hop_size is zero, calculates the cross-correlation every sample. 3 | 4 | [Reference library](../../index.md) > [Analysis](../index.md) > [CrossCorrelate](index.md) 5 | 6 | # CrossCorrelate 7 | 8 | ```python 9 | CrossCorrelate(input=None, buffer=None, hop_size=0) 10 | ``` 11 | 12 | Outputs the cross-correlation of the input signal with the given buffer. If hop_size is zero, calculates the cross-correlation every sample. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/analysis/index.md: -------------------------------------------------------------------------------- 1 | [Reference library](../index.md) > [Analysis](index.md) 2 | 3 | # Analysis 4 | 5 | - **[CrossCorrelate](crosscorrelate/index.md)**: Outputs the cross-correlation of the input signal with the given buffer. If hop_size is zero, calculates the cross-correlation every sample. 6 | - **[NearestNeighbour](nearestneighbour/index.md)**: Nearest Neighbour. 7 | - **[OnsetDetector](onsetdetector/index.md)**: Simple time-domain onset detector: outputs an impulse when an onset is detected in the input. 8 | - **[VampAnalysis](vampanalysis/index.md)**: Feature extraction using the Vamp plugin toolkit. 9 | -------------------------------------------------------------------------------- /docs/library/analysis/nearestneighbour/index.md: -------------------------------------------------------------------------------- 1 | title: NearestNeighbour node documentation 2 | description: NearestNeighbour: Nearest Neighbour. 3 | 4 | [Reference library](../../index.md) > [Analysis](../index.md) > [NearestNeighbour](index.md) 5 | 6 | # NearestNeighbour 7 | 8 | ```python 9 | NearestNeighbour(buffer=None, target=0.0) 10 | ``` 11 | 12 | Nearest Neighbour. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/analysis/onsetdetector/index.md: -------------------------------------------------------------------------------- 1 | title: OnsetDetector node documentation 2 | description: OnsetDetector: Simple time-domain onset detector: outputs an impulse when an onset is detected in the input. 3 | 4 | [Reference library](../../index.md) > [Analysis](../index.md) > [OnsetDetector](index.md) 5 | 6 | # OnsetDetector 7 | 8 | ```python 9 | OnsetDetector(input=0.0, threshold=2.0, min_interval=0.1) 10 | ``` 11 | 12 | Simple time-domain onset detector: outputs an impulse when an onset is detected in the input. 13 | 14 | Maintains short-time and long-time averages. An onset is registered when the short-time average is threshold x the long-time average. min_interval is the minimum interval between onsets, in seconds. 15 | 16 | -------------------------------------------------------------------------------- /docs/library/analysis/vampanalysis/index.md: -------------------------------------------------------------------------------- 1 | title: VampAnalysis node documentation 2 | description: VampAnalysis: Feature extraction using the Vamp plugin toolkit. 3 | 4 | [Reference library](../../index.md) > [Analysis](../index.md) > [VampAnalysis](index.md) 5 | 6 | # VampAnalysis 7 | 8 | ```python 9 | VampAnalysis(input=0.0, plugin_id="vamp-example-plugins:spectralcentroid:linearcentroid") 10 | ``` 11 | 12 | Feature extraction using the Vamp plugin toolkit. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/buffer/beatcutter/index.md: -------------------------------------------------------------------------------- 1 | title: BeatCutter node documentation 2 | description: BeatCutter: Cuts a buffer into segment_count segments, and stutters/jumps with the given probabilities. 3 | 4 | [Reference library](../../index.md) > [Buffer](../index.md) > [BeatCutter](index.md) 5 | 6 | # BeatCutter 7 | 8 | ```python 9 | BeatCutter(buffer=None, segment_count=8, stutter_probability=0.0, stutter_count=1, jump_probability=0.0, duty_cycle=1.0, rate=1.0, segment_rate=1.0) 10 | ``` 11 | 12 | Cuts a buffer into segment_count segments, and stutters/jumps with the given probabilities. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/buffer/bufferlooper/index.md: -------------------------------------------------------------------------------- 1 | title: BufferLooper node documentation 2 | description: BufferLooper: Read and write from a buffer concurrently, with controllable overdub. 3 | 4 | [Reference library](../../index.md) > [Buffer](../index.md) > [BufferLooper](index.md) 5 | 6 | # BufferLooper 7 | 8 | ```python 9 | BufferLooper(buffer=None, input=0.0, feedback=0.0, loop_playback=0, loop_record=0, start_time=None, end_time=None, looper_level=1.0, playthrough_level=0.0) 10 | ``` 11 | 12 | Read and write from a buffer concurrently, with controllable overdub. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/buffer/bufferplayer/index.md: -------------------------------------------------------------------------------- 1 | title: BufferPlayer node documentation 2 | description: BufferPlayer: Plays the contents of the given buffer. `start_time`/`end_time` are in seconds. When a `clock` signal is received, rewinds to the `start_time`. 3 | 4 | [Reference library](../../index.md) > [Buffer](../index.md) > [BufferPlayer](index.md) 5 | 6 | # BufferPlayer 7 | 8 | ```python 9 | BufferPlayer(buffer=None, rate=1.0, loop=0, start_time=None, end_time=None, clock=None) 10 | ``` 11 | 12 | Plays the contents of the given buffer. `start_time`/`end_time` are in seconds. When a `clock` signal is received, rewinds to the `start_time`. 13 | 14 | Set `clock` to `0` to prevent the buffer from being triggered immediately. 15 | 16 | -------------------------------------------------------------------------------- /docs/library/buffer/bufferrecorder/index.md: -------------------------------------------------------------------------------- 1 | title: BufferRecorder node documentation 2 | description: BufferRecorder: Records the input to a buffer. feedback controls overdub. 3 | 4 | [Reference library](../../index.md) > [Buffer](../index.md) > [BufferRecorder](index.md) 5 | 6 | # BufferRecorder 7 | 8 | ```python 9 | BufferRecorder(buffer=None, input=0.0, feedback=0.0, loop=false) 10 | ``` 11 | 12 | Records the input to a buffer. feedback controls overdub. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/buffer/feedbackbufferreader/index.md: -------------------------------------------------------------------------------- 1 | title: FeedbackBufferReader node documentation 2 | description: FeedbackBufferReader: Counterpart to FeedbackBufferWriter. 3 | 4 | [Reference library](../../index.md) > [Buffer](../index.md) > [FeedbackBufferReader](index.md) 5 | 6 | # FeedbackBufferReader 7 | 8 | ```python 9 | FeedbackBufferReader(buffer=None) 10 | ``` 11 | 12 | Counterpart to FeedbackBufferWriter. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/buffer/feedbackbufferwriter/index.md: -------------------------------------------------------------------------------- 1 | title: FeedbackBufferWriter node documentation 2 | description: FeedbackBufferWriter: Counterpart to FeedbackBufferReader. 3 | 4 | [Reference library](../../index.md) > [Buffer](../index.md) > [FeedbackBufferWriter](index.md) 5 | 6 | # FeedbackBufferWriter 7 | 8 | ```python 9 | FeedbackBufferWriter(buffer=None, input=0.0, delay_time=0.1) 10 | ``` 11 | 12 | Counterpart to FeedbackBufferReader. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/buffer/grainsegments/index.md: -------------------------------------------------------------------------------- 1 | title: GrainSegments node documentation 2 | description: GrainSegments: GrainSegments 3 | 4 | [Reference library](../../index.md) > [Buffer](../index.md) > [GrainSegments](index.md) 5 | 6 | # GrainSegments 7 | 8 | ```python 9 | GrainSegments(buffer=None, clock=0, target=0, offsets={}, values={}, durations={}) 10 | ``` 11 | 12 | GrainSegments 13 | 14 | -------------------------------------------------------------------------------- /docs/library/buffer/granulation/index.md: -------------------------------------------------------------------------------- 1 | [Reference library](../index.md) > [Buffer: Granulation](index.md) 2 | 3 | # Buffer: Granulation 4 | 5 | - **[SegmentedGranulator](segmentedgranulator/index.md)**: Segmented Granulator. 6 | - **[Granulator](granulator/index.md)**: Granulator. Generates a grain from the given buffer each time a trigger is received on the `clock` input. Each new grain uses the given `duration`, `amplitude`, `pan` and `rate` values presented at each input at the moment the grain is created. The input buffer can be mono or stereo. If `wrap` is true, grain playback can wrap around the end/start of the buffer. 7 | -------------------------------------------------------------------------------- /docs/library/buffer/granulation/segmentedgranulator/index.md: -------------------------------------------------------------------------------- 1 | title: SegmentedGranulator node documentation 2 | description: SegmentedGranulator: Segmented Granulator. 3 | 4 | [Reference library](../../index.md) > [Buffer: Granulation](../index.md) > [SegmentedGranulator](index.md) 5 | 6 | # SegmentedGranulator 7 | 8 | ```python 9 | SegmentedGranulator(buffer=None, onset_times={}, durations={}, index=0.0, rate=1.0, clock=0, max_grains=2048) 10 | ``` 11 | 12 | Segmented Granulator. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/buffer/granulator/index.md: -------------------------------------------------------------------------------- 1 | title: Granulator node documentation 2 | description: Granulator: Granulator. Generates a grain from the given buffer each time a clock signal is received, with the given duration/rate/pan parameters. The input buffer can be mono or stereo. 3 | 4 | [Reference library](../../index.md) > [Buffer](../index.md) > [Granulator](index.md) 5 | 6 | # Granulator 7 | 8 | ```python 9 | Granulator(buffer=None, clock=0, pos=0, duration=0.1, pan=0.0, rate=1.0, max_grains=2048) 10 | ``` 11 | 12 | Granulator. Generates a grain from the given buffer each time a clock signal is received, with the given duration/rate/pan parameters. The input buffer can be mono or stereo. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/buffer/historybufferwriter/index.md: -------------------------------------------------------------------------------- 1 | title: HistoryBufferWriter node documentation 2 | description: HistoryBufferWriter: Writes a rolling history buffer of a given duration. At a given moment in time, the contents of the buffer will be equal to the past N seconds of the audio generated by `input`. 3 | 4 | [Reference library](../../index.md) > [Buffer](../index.md) > [HistoryBufferWriter](index.md) 5 | 6 | # HistoryBufferWriter 7 | 8 | ```python 9 | HistoryBufferWriter(buffer=None, input=0.0, downsample=1) 10 | ``` 11 | 12 | Writes a rolling history buffer of a given duration. At a given moment in time, the contents of the buffer will be equal to the past N seconds of the audio generated by `input`. 13 | 14 | This is useful for (e.g.) a visual display of a rolling waveform or LFO window. `downsample` can be used to downsample the input; for example, with `downsample` of 10, a 1-second buffer can be used to display 10 seconds of historical audio. 15 | 16 | -------------------------------------------------------------------------------- /docs/library/buffer/segmentplayer/index.md: -------------------------------------------------------------------------------- 1 | title: SegmentPlayer node documentation 2 | description: SegmentPlayer: Trigger segments of `buffer` at the given list of `onsets` positions, in seconds. 3 | 4 | [Reference library](../../index.md) > [Buffer](../index.md) > [SegmentPlayer](index.md) 5 | 6 | # SegmentPlayer 7 | 8 | ```python 9 | SegmentPlayer(buffer=None, onsets={}, index=None, rate=1.0, start_offset=None, clock=None, continue_after_segment=0) 10 | ``` 11 | 12 | Trigger segments of `buffer` at the given list of `onsets` positions, in seconds. 13 | 14 | `index` determines the index of the onset to play back at, which can also be passed as an argument to trigger(). `rate` determines the playback rate, and `clock` can be used to retrigger based on the output of another Node. If `continue_after_segment` is non-zero, playback will continue after the subsequent onset. 15 | 16 | -------------------------------------------------------------------------------- /docs/library/control/index.md: -------------------------------------------------------------------------------- 1 | [Reference library](../index.md) > [Control](index.md) 2 | 3 | # Control 4 | 5 | - **[MouseX](mousex/index.md)**: Outputs the normalised cursor X position, from 0 to 1. Currently only supported on macOS. 6 | - **[MouseY](mousey/index.md)**: Outputs the normalised cursor Y position, from 0 to 1. Currently only supported on macOS. 7 | - **[MouseDown](mousedown/index.md)**: Outputs 1 if the left mouse button is down, 0 otherwise. Currently only supported on macOS. 8 | -------------------------------------------------------------------------------- /docs/library/control/mousedown/example-0.py: -------------------------------------------------------------------------------- 1 | from signalflow import * 2 | graph = AudioGraph() 3 | 4 | #------------------------------------------------------------------------------- 5 | # When the left mouse button is clicked, as detected by MouseDown(), an LFO is 6 | # applied to the oscillator's frequency. 7 | #------------------------------------------------------------------------------- 8 | lfo = SineLFO(5, 100, 600) 9 | frequency = If(MouseDown(), lfo, 100) 10 | osc = TriangleOscillator(frequency) 11 | osc.play() 12 | graph.wait() -------------------------------------------------------------------------------- /docs/library/control/mousedown/example-1.py: -------------------------------------------------------------------------------- 1 | from signalflow import * 2 | graph = AudioGraph() 3 | 4 | #------------------------------------------------------------------------------- 5 | # A simple wobbling synthesiser controlled using the mouse. When the mouse is 6 | # clicked, as detected by MouseDown(), an LFO is activated and affects the 7 | # oscillator's frequency. MouseX position changes the rate of the LFO. MouseY 8 | # position changes the upper frequency limit, affecting pitch. 9 | #------------------------------------------------------------------------------- 10 | rate = MouseX() * 10 11 | upper_limit = MouseY() * 1500 12 | lfo = SineLFO(rate, 100, upper_limit) 13 | frequency = If(MouseDown(), lfo, 100) 14 | osc = TriangleOscillator(frequency) 15 | osc.play() 16 | graph.wait() -------------------------------------------------------------------------------- /docs/library/control/mousex/example-0.py: -------------------------------------------------------------------------------- 1 | from signalflow import * 2 | graph = AudioGraph() 3 | 4 | #------------------------------------------------------------------------------- 5 | # Using the MouseX position to change the rate of an LFO, which is modulating an 6 | # oscillator's frequency. 7 | #------------------------------------------------------------------------------- 8 | lfo_rate = MouseX() * 10 9 | frequency = SineLFO(lfo_rate, 100, 600) 10 | osc = TriangleOscillator(frequency) 11 | osc.play() 12 | graph.wait() -------------------------------------------------------------------------------- /docs/library/control/mousex/example-1.py: -------------------------------------------------------------------------------- 1 | from signalflow import * 2 | graph = AudioGraph() 3 | 4 | #------------------------------------------------------------------------------- 5 | # A simple wobbling synthesiser controlled using the mouse. When the mouse is 6 | # clicked, as detected by MouseDown(), an LFO is activated and affects the 7 | # oscillator's frequency. MouseX position changes the rate of the LFO. MouseY 8 | # position changes the upper frequency limit, affecting pitch. 9 | #------------------------------------------------------------------------------- 10 | rate = MouseX() * 10 11 | upper_limit = MouseY() * 1500 12 | lfo = SineLFO(rate, 100, upper_limit) 13 | frequency = If(MouseDown(), lfo, 100) 14 | osc = TriangleOscillator(frequency) 15 | osc.play() 16 | graph.wait() -------------------------------------------------------------------------------- /docs/library/control/mousey/example-0.py: -------------------------------------------------------------------------------- 1 | from signalflow import * 2 | graph = AudioGraph() 3 | 4 | #------------------------------------------------------------------------------- 5 | # Using the MouseY position to change the frequency of an oscillator. 6 | #------------------------------------------------------------------------------- 7 | frequency = MouseY() * 1000 8 | osc = TriangleOscillator(frequency) 9 | osc.play() 10 | graph.wait() -------------------------------------------------------------------------------- /docs/library/control/mousey/example-1.py: -------------------------------------------------------------------------------- 1 | from signalflow import * 2 | graph = AudioGraph() 3 | 4 | #------------------------------------------------------------------------------- 5 | # A simple wobbling synthesiser controlled using the mouse. When the mouse is 6 | # clicked, as detected by MouseDown(), an LFO is activated and affects the 7 | # oscillator's frequency. MouseX position changes the rate of the LFO. MouseY 8 | # position changes the upper frequency limit, affecting pitch. 9 | #------------------------------------------------------------------------------- 10 | rate = MouseX() * 10 11 | upper_limit = MouseY() * 1500 12 | lfo = SineLFO(rate, 100, upper_limit) 13 | frequency = If(MouseDown(), lfo, 100) 14 | osc = TriangleOscillator(frequency) 15 | osc.play() 16 | graph.wait() -------------------------------------------------------------------------------- /docs/library/envelope/accumulator/index.md: -------------------------------------------------------------------------------- 1 | title: Accumulator node documentation 2 | description: Accumulator: Accumulator with decay. 3 | 4 | [Reference library](../../index.md) > [Envelope](../index.md) > [Accumulator](index.md) 5 | 6 | # Accumulator 7 | 8 | ```python 9 | Accumulator(strike_force=0.5, decay_coefficient=0.9999, trigger=None) 10 | ``` 11 | 12 | Accumulator with decay. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/envelope/adsrenvelope/index.md: -------------------------------------------------------------------------------- 1 | title: ADSREnvelope node documentation 2 | description: ADSREnvelope: Attack-decay-sustain-release envelope. Sustain portion is held until gate is zero. 3 | 4 | [Reference library](../../index.md) > [Envelope](../index.md) > [ADSREnvelope](index.md) 5 | 6 | # ADSREnvelope 7 | 8 | ```python 9 | ADSREnvelope(attack=0.1, decay=0.1, sustain=0.5, release=0.1, gate=0) 10 | ``` 11 | 12 | Attack-decay-sustain-release envelope. Sustain portion is held until gate is zero. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/envelope/asrenvelope/example-0.py: -------------------------------------------------------------------------------- 1 | from signalflow import * 2 | graph = AudioGraph() 3 | 4 | #------------------------------------------------------------------------------- 5 | # Using an ASR Envelope to shape a square wave oscillator 6 | #------------------------------------------------------------------------------- 7 | osc = SquareOscillator(500) 8 | envelope = ASREnvelope(0.1, 0.0, 0.5) 9 | output = osc * envelope 10 | output.play() 11 | graph.wait() 12 | -------------------------------------------------------------------------------- /docs/library/envelope/detectsilence/index.md: -------------------------------------------------------------------------------- 1 | title: DetectSilence node documentation 2 | description: DetectSilence: Detects blocks of silence below the threshold value. Used as an auto-free node to terminate a Patch after processing is complete. 3 | 4 | [Reference library](../../index.md) > [Envelope](../index.md) > [DetectSilence](index.md) 5 | 6 | # DetectSilence 7 | 8 | ```python 9 | DetectSilence(input=None, threshold=0.00001) 10 | ``` 11 | 12 | Detects blocks of silence below the threshold value. Used as an auto-free node to terminate a Patch after processing is complete. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/envelope/envelope/index.md: -------------------------------------------------------------------------------- 1 | title: Envelope node documentation 2 | description: Envelope: Generic envelope constructor, given an array of levels, times and curves. 3 | 4 | [Reference library](../../index.md) > [Envelope](../index.md) > [Envelope](index.md) 5 | 6 | # Envelope 7 | 8 | ```python 9 | Envelope(levels=std::vector ( ), times=std::vector ( ), curves=std::vector ( ), clock=None, loop=false) 10 | ``` 11 | 12 | Generic envelope constructor, given an array of levels, times and curves. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/envelope/index.md: -------------------------------------------------------------------------------- 1 | [Reference library](../index.md) > [Envelope](index.md) 2 | 3 | # Envelope 4 | 5 | - **[Accumulator](accumulator/index.md)**: Accumulator with decay. 6 | - **[ADSREnvelope](adsrenvelope/index.md)**: Attack-decay-sustain-release envelope. Sustain portion is held until gate is zero. 7 | - **[ASREnvelope](asrenvelope/index.md)**: Attack-sustain-release envelope. 8 | - **[DetectSilence](detectsilence/index.md)**: Detects blocks of silence below the threshold value. Used as an auto-free node to terminate a Patch after processing is complete. 9 | - **[Envelope](envelope/index.md)**: Generic envelope constructor, given an array of levels, times and curves. 10 | - **[Line](line/index.md)**: Line segment with the given start/end values, and duration (in seconds). If loop is true, repeats indefinitely. Retriggers on a clock signal. 11 | - **[RectangularEnvelope](rectangularenvelope/index.md)**: Rectangular envelope with the given sustain duration. 12 | -------------------------------------------------------------------------------- /docs/library/envelope/line/example-0.py: -------------------------------------------------------------------------------- 1 | from signalflow import * 2 | graph = AudioGraph() 3 | 4 | #------------------------------------------------------------------------------- 5 | # Using a line to control the gain of an oscillator, emulating a sidechain 6 | # ducking effect. 7 | #------------------------------------------------------------------------------- 8 | clock = Impulse(frequency=1.0) 9 | line = Line(0.0, 0.5, 0.5, False, clock) 10 | osc = SawOscillator(200) 11 | output = StereoPanner(osc * line) 12 | output.play() 13 | graph.wait() -------------------------------------------------------------------------------- /docs/library/envelope/line/example-1.py: -------------------------------------------------------------------------------- 1 | from signalflow import * 2 | graph = AudioGraph() 3 | 4 | #------------------------------------------------------------------------------- 5 | # Using Line to repeatedly alter the release value of an envelope applied to the 6 | # main synth voice, in time with the music. 7 | #------------------------------------------------------------------------------- 8 | clock = Impulse(8.0) 9 | CMaj7 = [ 60, 64, 67, 71, 74, 76 ] * 8 10 | FMaj9 = [ 65, 69, 72, 76, 77, 81 ] * 8 11 | arpeggios = CMaj7 + FMaj9 12 | sequence = Sequence(arpeggios, clock) 13 | frequency = MidiNoteToFrequency(sequence) 14 | 15 | oscillator = TriangleOscillator(frequency) 16 | release = Line(0.1, 0.5, 6, True) 17 | envelope = ASREnvelope(0.0, 0.0, release, 1.0, clock) 18 | voice = oscillator * envelope 19 | 20 | pan = SineLFO(0.1667, -1.0, 1.0) 21 | output = StereoPanner(voice, pan) 22 | output.play() 23 | graph.wait() -------------------------------------------------------------------------------- /docs/library/envelope/rectangularenvelope/index.md: -------------------------------------------------------------------------------- 1 | title: RectangularEnvelope node documentation 2 | description: RectangularEnvelope: Rectangular envelope with the given sustain duration. 3 | 4 | [Reference library](../../index.md) > [Envelope](../index.md) > [RectangularEnvelope](index.md) 5 | 6 | # RectangularEnvelope 7 | 8 | ```python 9 | RectangularEnvelope(sustain_duration=1.0, clock=None) 10 | ``` 11 | 12 | Rectangular envelope with the given sustain duration. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/fft/fft/index.md: -------------------------------------------------------------------------------- 1 | title: FFT node documentation 2 | description: FFT: Fast Fourier Transform. Takes a time-domain input, and generates a frequency-domain (FFT) output. 3 | 4 | [Reference library](../../index.md) > [FFT](../index.md) > [FFT](index.md) 5 | 6 | # FFT 7 | 8 | ```python 9 | FFT(input=0.0, fft_size=SIGNALFLOW_DEFAULT_FFT_SIZE, hop_size=SIGNALFLOW_DEFAULT_FFT_HOP_SIZE, window_size=0, do_window=true) 10 | ``` 11 | 12 | Fast Fourier Transform. Takes a time-domain input, and generates a frequency-domain (FFT) output. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/fft/fftbufferplayer/index.md: -------------------------------------------------------------------------------- 1 | title: FFTBufferPlayer node documentation 2 | description: FFTBufferPlayer: FFTBufferPlayer. Plays from a buffer of audio spectra in mag/phase format. 3 | 4 | [Reference library](../../index.md) > [FFT](../index.md) > [FFTBufferPlayer](index.md) 5 | 6 | # FFTBufferPlayer 7 | 8 | ```python 9 | FFTBufferPlayer(buffer=None, rate=1.0) 10 | ``` 11 | 12 | FFTBufferPlayer. Plays from a buffer of audio spectra in mag/phase format. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/fft/fftcontinuousphasevocoder/index.md: -------------------------------------------------------------------------------- 1 | title: FFTContinuousPhaseVocoder node documentation 2 | description: FFTContinuousPhaseVocoder: Continuous phase vocoder. Requires an FFT* input. 3 | 4 | [Reference library](../../index.md) > [FFT](../index.md) > [FFTContinuousPhaseVocoder](index.md) 5 | 6 | # FFTContinuousPhaseVocoder 7 | 8 | ```python 9 | FFTContinuousPhaseVocoder(input=None, rate=1.0) 10 | ``` 11 | 12 | Continuous phase vocoder. Requires an FFT* input. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/fft/fftcontrast/index.md: -------------------------------------------------------------------------------- 1 | title: FFTContrast node documentation 2 | description: FFTContrast: FFT Contrast. Requires an FFT* input. 3 | 4 | [Reference library](../../index.md) > [FFT](../index.md) > [FFTContrast](index.md) 5 | 6 | # FFTContrast 7 | 8 | ```python 9 | FFTContrast(input=0, contrast=1) 10 | ``` 11 | 12 | FFT Contrast. Requires an FFT* input. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/fft/fftconvolve/index.md: -------------------------------------------------------------------------------- 1 | title: FFTConvolve node documentation 2 | description: FFTConvolve: Frequency-domain convolution, using overlap-add. Useful for convolution reverb, with the input buffer containing an impulse response. Requires an FFT* input. 3 | 4 | [Reference library](../../index.md) > [FFT](../index.md) > [FFTConvolve](index.md) 5 | 6 | # FFTConvolve 7 | 8 | ```python 9 | FFTConvolve(input=None, buffer=None) 10 | ``` 11 | 12 | Frequency-domain convolution, using overlap-add. Useful for convolution reverb, with the input buffer containing an impulse response. Requires an FFT* input. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/fft/fftcrossfade/index.md: -------------------------------------------------------------------------------- 1 | title: FFTCrossFade node documentation 2 | description: FFTCrossFade: FFT FFTCrossFade. Requires two FFT* inputs. 3 | 4 | [Reference library](../../index.md) > [FFT](../index.md) > [FFTCrossFade](index.md) 5 | 6 | # FFTCrossFade 7 | 8 | ```python 9 | FFTCrossFade(inputA=0, inputB=0, crossfade=0.0) 10 | ``` 11 | 12 | FFT FFTCrossFade. Requires two FFT* inputs. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/fft/fftfindpeaks/index.md: -------------------------------------------------------------------------------- 1 | title: FFTFindPeaks node documentation 2 | description: FFTFindPeaks: Find peaks in the FFT magnitude spectrum. Requires an FFT* input. 3 | 4 | [Reference library](../../index.md) > [FFT](../index.md) > [FFTFindPeaks](index.md) 5 | 6 | # FFTFindPeaks 7 | 8 | ```python 9 | FFTFindPeaks(input=0, prominence=1, threshold=0.000001, count=SIGNALFLOW_MAX_CHANNELS, interpolate=true) 10 | ``` 11 | 12 | Find peaks in the FFT magnitude spectrum. Requires an FFT* input. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/fft/fftflipspectrum/index.md: -------------------------------------------------------------------------------- 1 | title: FFTFlipSpectrum node documentation 2 | description: FFTFlipSpectrum: Flips the FFT magnitude spectrum in the X axis. Requires an FFT* input. 3 | 4 | [Reference library](../../index.md) > [FFT](../index.md) > [FFTFlipSpectrum](index.md) 5 | 6 | # FFTFlipSpectrum 7 | 8 | ```python 9 | FFTFlipSpectrum(input=0, flip=0, rotate=0) 10 | ``` 11 | 12 | Flips the FFT magnitude spectrum in the X axis. Requires an FFT* input. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/fft/fftlfo/index.md: -------------------------------------------------------------------------------- 1 | title: FFTLFO node documentation 2 | description: FFTLFO: FFT LFO. Requires an FFT* input. 3 | 4 | [Reference library](../../index.md) > [FFT](../index.md) > [FFTLFO](index.md) 5 | 6 | # FFTLFO 7 | 8 | ```python 9 | FFTLFO(input=0, frequency=1.0, spectral_cycles=1.0) 10 | ``` 11 | 12 | FFT LFO. Requires an FFT* input. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/fft/fftlpf/index.md: -------------------------------------------------------------------------------- 1 | title: FFTLPF node documentation 2 | description: FFTLPF: FFT-based brick wall low pass filter. Requires an FFT* input. 3 | 4 | [Reference library](../../index.md) > [FFT](../index.md) > [FFTLPF](index.md) 5 | 6 | # FFTLPF 7 | 8 | ```python 9 | FFTLPF(input=0, frequency=2000) 10 | ``` 11 | 12 | FFT-based brick wall low pass filter. Requires an FFT* input. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/fft/fftmagnitudephasearray/index.md: -------------------------------------------------------------------------------- 1 | title: FFTMagnitudePhaseArray node documentation 2 | description: FFTMagnitudePhaseArray: Fixed mag/phase array. 3 | 4 | [Reference library](../../index.md) > [FFT](../index.md) > [FFTMagnitudePhaseArray](index.md) 5 | 6 | # FFTMagnitudePhaseArray 7 | 8 | ```python 9 | FFTMagnitudePhaseArray(input=0, magnitudes={}, phases={}) 10 | ``` 11 | 12 | Fixed mag/phase array. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/fft/fftnoisegate/index.md: -------------------------------------------------------------------------------- 1 | title: FFTNoiseGate node documentation 2 | description: FFTNoiseGate: FFT-based noise gate. Requires an FFT* input. 3 | 4 | [Reference library](../../index.md) > [FFT](../index.md) > [FFTNoiseGate](index.md) 5 | 6 | # FFTNoiseGate 7 | 8 | ```python 9 | FFTNoiseGate(input=0, threshold=0.5, invert=0.0) 10 | ``` 11 | 12 | FFT-based noise gate. Requires an FFT* input. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/fft/fftphasevocoder/index.md: -------------------------------------------------------------------------------- 1 | title: FFTPhaseVocoder node documentation 2 | description: FFTPhaseVocoder: Phase vocoder. Requires an FFT* input. 3 | 4 | [Reference library](../../index.md) > [FFT](../index.md) > [FFTPhaseVocoder](index.md) 5 | 6 | # FFTPhaseVocoder 7 | 8 | ```python 9 | FFTPhaseVocoder(input=None) 10 | ``` 11 | 12 | Phase vocoder. Requires an FFT* input. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/fft/fftrandomphase/index.md: -------------------------------------------------------------------------------- 1 | title: FFTRandomPhase node documentation 2 | description: FFTRandomPhase: Randomise phase values. 3 | 4 | [Reference library](../../index.md) > [FFT](../index.md) > [FFTRandomPhase](index.md) 5 | 6 | # FFTRandomPhase 7 | 8 | ```python 9 | FFTRandomPhase(input=0, level=1.0) 10 | ``` 11 | 12 | Randomise phase values. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/fft/fftscalemagnitudes/index.md: -------------------------------------------------------------------------------- 1 | title: FFTScaleMagnitudes node documentation 2 | description: FFTScaleMagnitudes: Randomise phase values. 3 | 4 | [Reference library](../../index.md) > [FFT](../index.md) > [FFTScaleMagnitudes](index.md) 5 | 6 | # FFTScaleMagnitudes 7 | 8 | ```python 9 | FFTScaleMagnitudes(input=0, scale={}) 10 | ``` 11 | 12 | Randomise phase values. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/fft/ffttonality/index.md: -------------------------------------------------------------------------------- 1 | title: FFTTonality node documentation 2 | description: FFTTonality: Tonality filter. Requires an FFT* input. 3 | 4 | [Reference library](../../index.md) > [FFT](../index.md) > [FFTTonality](index.md) 5 | 6 | # FFTTonality 7 | 8 | ```python 9 | FFTTonality(input=0, level=0.5, smoothing=0.9) 10 | ``` 11 | 12 | Tonality filter. Requires an FFT* input. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/fft/ffttransform/index.md: -------------------------------------------------------------------------------- 1 | title: FFTTransform node documentation 2 | description: FFTTransform: Transforms the FFT magnitude spectrum in the X axis. Requires an FFT* input. 3 | 4 | [Reference library](../../index.md) > [FFT](../index.md) > [FFTTransform](index.md) 5 | 6 | # FFTTransform 7 | 8 | ```python 9 | FFTTransform(input=0, flip=0, rotate=0) 10 | ``` 11 | 12 | Transforms the FFT magnitude spectrum in the X axis. Requires an FFT* input. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/fft/fftzerophase/index.md: -------------------------------------------------------------------------------- 1 | title: FFTZeroPhase node documentation 2 | description: FFTZeroPhase: Remove phase information from a frequency-domain input. Requires an FFT* input. 3 | 4 | [Reference library](../../index.md) > [FFT](../index.md) > [FFTZeroPhase](index.md) 5 | 6 | # FFTZeroPhase 7 | 8 | ```python 9 | FFTZeroPhase(input=0) 10 | ``` 11 | 12 | Remove phase information from a frequency-domain input. Requires an FFT* input. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/fft/ifft/index.md: -------------------------------------------------------------------------------- 1 | title: IFFT node documentation 2 | description: IFFT: Inverse Fast Fourier Transform. Requires an FFT* input, generates a time-domain output. 3 | 4 | [Reference library](../../index.md) > [FFT](../index.md) > [IFFT](index.md) 5 | 6 | # IFFT 7 | 8 | ```python 9 | IFFT(input=None, do_window=false) 10 | ``` 11 | 12 | Inverse Fast Fourier Transform. Requires an FFT* input, generates a time-domain output. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/operators/abs/index.md: -------------------------------------------------------------------------------- 1 | title: Abs node documentation 2 | description: Abs: Outputs the absolute value of a, per sample. Can also be written as abs(a) 3 | 4 | [Reference library](../../index.md) > [Operators](../index.md) > [Abs](index.md) 5 | 6 | # Abs 7 | 8 | ```python 9 | Abs(a=0) 10 | ``` 11 | 12 | Outputs the absolute value of a, per sample. Can also be written as abs(a) 13 | 14 | -------------------------------------------------------------------------------- /docs/library/operators/add/index.md: -------------------------------------------------------------------------------- 1 | title: Add node documentation 2 | description: Add: Add each sample of a to each sample of b. Can also be written as a + b 3 | 4 | [Reference library](../../index.md) > [Operators](../index.md) > [Add](index.md) 5 | 6 | # Add 7 | 8 | ```python 9 | Add(a=0, b=0) 10 | ``` 11 | 12 | Add each sample of a to each sample of b. Can also be written as a + b 13 | 14 | -------------------------------------------------------------------------------- /docs/library/operators/amplitudetodecibels/index.md: -------------------------------------------------------------------------------- 1 | title: AmplitudeToDecibels node documentation 2 | description: AmplitudeToDecibels: Map a linear amplitude value to decibels. 3 | 4 | [Reference library](../../index.md) > [Operators](../index.md) > [AmplitudeToDecibels](index.md) 5 | 6 | # AmplitudeToDecibels 7 | 8 | ```python 9 | AmplitudeToDecibels(a=0) 10 | ``` 11 | 12 | Map a linear amplitude value to decibels. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/operators/bus/index.md: -------------------------------------------------------------------------------- 1 | title: Bus node documentation 2 | description: Bus: Bus is a node with a fixed number of input channels and arbitrary number of inputs, used to aggregate multiple sources. It is similar to Sum, but with a defined channel count that does not adapt to its inputs. 3 | 4 | [Reference library](../../index.md) > [Operators](../index.md) > [Bus](index.md) 5 | 6 | # Bus 7 | 8 | ```python 9 | Bus(num_channels=1) 10 | ``` 11 | 12 | Bus is a node with a fixed number of input channels and arbitrary number of inputs, used to aggregate multiple sources. It is similar to Sum, but with a defined channel count that does not adapt to its inputs. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/operators/channelarray/example-0.py: -------------------------------------------------------------------------------- 1 | from signalflow import * 2 | graph = AudioGraph() 3 | 4 | #------------------------------------------------------------------------------- 5 | # Using ChannelArray to pan a low tone to the left and a high tone to the right. 6 | #------------------------------------------------------------------------------- 7 | low = TriangleOscillator(220) 8 | high = TriangleOscillator(660) 9 | panned = ChannelArray([low, high]) * 0.3 10 | panned.play() 11 | graph.wait() -------------------------------------------------------------------------------- /docs/library/operators/channelarray/index.md: -------------------------------------------------------------------------------- 1 | title: ChannelArray node documentation 2 | description: ChannelArray: Takes an array of inputs and spreads them across multiple channels of output. 3 | 4 | [Reference library](../../index.md) > [Operators](../index.md) > [ChannelArray](index.md) 5 | 6 | # ChannelArray 7 | 8 | ```python 9 | ChannelArray() 10 | ``` 11 | 12 | Takes an array of inputs and spreads them across multiple channels of output. 13 | 14 | ### Examples 15 | 16 | ```python 17 | 18 | #------------------------------------------------------------------------------- 19 | # Using ChannelArray to pan a low tone to the left and a high tone to the right. 20 | #------------------------------------------------------------------------------- 21 | low = TriangleOscillator(220) 22 | high = TriangleOscillator(660) 23 | panned = ChannelArray([low, high]) * 0.3 24 | panned.play() 25 | 26 | ``` 27 | 28 | -------------------------------------------------------------------------------- /docs/library/operators/channelcrossfade/index.md: -------------------------------------------------------------------------------- 1 | title: ChannelCrossfade node documentation 2 | description: ChannelCrossfade: Given a multichannel input, crossfades between channels based on the given position within the virtual array, producing a single-channel output. 3 | 4 | [Reference library](../../index.md) > [Operators](../index.md) > [ChannelCrossfade](index.md) 5 | 6 | # ChannelCrossfade 7 | 8 | ```python 9 | ChannelCrossfade(input=None, index=None, num_output_channels=1) 10 | ``` 11 | 12 | Given a multichannel input, crossfades between channels based on the given position within the virtual array, producing a single-channel output. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/operators/channelmixer/index.md: -------------------------------------------------------------------------------- 1 | title: ChannelMixer node documentation 2 | description: ChannelMixer: Downmix a multichannel input to a lower-channel output. If num_channels is greater than one, spreads the input channels across the field. If amplitude_compensation is enabled, scale down the amplitude based on the ratio of input to output channels. 3 | 4 | [Reference library](../../index.md) > [Operators](../index.md) > [ChannelMixer](index.md) 5 | 6 | # ChannelMixer 7 | 8 | ```python 9 | ChannelMixer(num_channels=1, input=0, amplitude_compensation=true) 10 | ``` 11 | 12 | Downmix a multichannel input to a lower-channel output. If num_channels is greater than one, spreads the input channels across the field. If amplitude_compensation is enabled, scale down the amplitude based on the ratio of input to output channels. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/operators/channeloffset/index.md: -------------------------------------------------------------------------------- 1 | title: ChannelOffset node documentation 2 | description: ChannelOffset: Offsets the input by a specified number of channels. With an N-channel input and an offset of M, the output will have M+N channels. 3 | 4 | [Reference library](../../index.md) > [Operators](../index.md) > [ChannelOffset](index.md) 5 | 6 | # ChannelOffset 7 | 8 | ```python 9 | ChannelOffset(offset=0, input=None) 10 | ``` 11 | 12 | Offsets the input by a specified number of channels. With an N-channel input and an offset of M, the output will have M+N channels. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/operators/channelselect/index.md: -------------------------------------------------------------------------------- 1 | title: ChannelSelect node documentation 2 | description: ChannelSelect: Select a subset of channels from a multichannel input, starting at offset, up to a maximum of maximum, with the given step. 3 | 4 | [Reference library](../../index.md) > [Operators](../index.md) > [ChannelSelect](index.md) 5 | 6 | # ChannelSelect 7 | 8 | ```python 9 | ChannelSelect(input=None, offset=0, maximum=0, step=1) 10 | ``` 11 | 12 | Select a subset of channels from a multichannel input, starting at offset, up to a maximum of maximum, with the given step. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/operators/cos/index.md: -------------------------------------------------------------------------------- 1 | title: Cos node documentation 2 | description: Cos: Outputs cos(a), per sample. 3 | 4 | [Reference library](../../index.md) > [Operators](../index.md) > [Cos](index.md) 5 | 6 | # Cos 7 | 8 | ```python 9 | Cos(a=0) 10 | ``` 11 | 12 | Outputs cos(a), per sample. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/operators/decibelstoamplitude/index.md: -------------------------------------------------------------------------------- 1 | title: DecibelsToAmplitude node documentation 2 | description: DecibelsToAmplitude: DecibelsToAmplitude 3 | 4 | [Reference library](../../index.md) > [Operators](../index.md) > [DecibelsToAmplitude](index.md) 5 | 6 | # DecibelsToAmplitude 7 | 8 | ```python 9 | DecibelsToAmplitude(a=0) 10 | ``` 11 | 12 | DecibelsToAmplitude 13 | 14 | -------------------------------------------------------------------------------- /docs/library/operators/divide/index.md: -------------------------------------------------------------------------------- 1 | title: Divide node documentation 2 | description: Divide: Divide each sample of a by each sample of b. Can also be written as a / b 3 | 4 | [Reference library](../../index.md) > [Operators](../index.md) > [Divide](index.md) 5 | 6 | # Divide 7 | 8 | ```python 9 | Divide(a=1, b=1) 10 | ``` 11 | 12 | Divide each sample of a by each sample of b. Can also be written as a / b 13 | 14 | -------------------------------------------------------------------------------- /docs/library/operators/equal/index.md: -------------------------------------------------------------------------------- 1 | title: Equal node documentation 2 | description: Equal: Compares the output of a to the output of b. Outputs 1 when equal, 0 otherwise. Can also be written as a == b 3 | 4 | [Reference library](../../index.md) > [Operators](../index.md) > [Equal](index.md) 5 | 6 | # Equal 7 | 8 | ```python 9 | Equal(a=0, b=0) 10 | ``` 11 | 12 | Compares the output of a to the output of b. Outputs 1 when equal, 0 otherwise. Can also be written as a == b 13 | 14 | -------------------------------------------------------------------------------- /docs/library/operators/frequencytomidinote/index.md: -------------------------------------------------------------------------------- 1 | title: FrequencyToMidiNote node documentation 2 | description: FrequencyToMidiNote: Map a frequency to a MIDI note (where 440Hz = A4 = 69), with floating-point output. 3 | 4 | [Reference library](../../index.md) > [Operators](../index.md) > [FrequencyToMidiNote](index.md) 5 | 6 | # FrequencyToMidiNote 7 | 8 | ```python 9 | FrequencyToMidiNote(a=0) 10 | ``` 11 | 12 | Map a frequency to a MIDI note (where 440Hz = A4 = 69), with floating-point output. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/operators/greaterthan/index.md: -------------------------------------------------------------------------------- 1 | title: GreaterThan node documentation 2 | description: GreaterThan: Compares the output of a to the output of b. Outputs 1 when a > b, 0 otherwise. Can also be written as a > b 3 | 4 | [Reference library](../../index.md) > [Operators](../index.md) > [GreaterThan](index.md) 5 | 6 | # GreaterThan 7 | 8 | ```python 9 | GreaterThan(a=0, b=0) 10 | ``` 11 | 12 | Compares the output of a to the output of b. Outputs 1 when a > b, 0 otherwise. Can also be written as a > b 13 | 14 | -------------------------------------------------------------------------------- /docs/library/operators/greaterthanorequal/index.md: -------------------------------------------------------------------------------- 1 | title: GreaterThanOrEqual node documentation 2 | description: GreaterThanOrEqual: Compares the output of a to the output of b. Outputs 1 when a >= b, 0 otherwise. Can also be written as a >= b 3 | 4 | [Reference library](../../index.md) > [Operators](../index.md) > [GreaterThanOrEqual](index.md) 5 | 6 | # GreaterThanOrEqual 7 | 8 | ```python 9 | GreaterThanOrEqual(a=0, b=0) 10 | ``` 11 | 12 | Compares the output of a to the output of b. Outputs 1 when a >= b, 0 otherwise. Can also be written as a >= b 13 | 14 | -------------------------------------------------------------------------------- /docs/library/operators/if/index.md: -------------------------------------------------------------------------------- 1 | title: If node documentation 2 | description: If: Outputs value_if_true for each non-zero value of a, value_if_false for all other values. 3 | 4 | [Reference library](../../index.md) > [Operators](../index.md) > [If](index.md) 5 | 6 | # If 7 | 8 | ```python 9 | If(a=0, value_if_true=0, value_if_false=0) 10 | ``` 11 | 12 | Outputs value_if_true for each non-zero value of a, value_if_false for all other values. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/operators/lessthan/index.md: -------------------------------------------------------------------------------- 1 | title: LessThan node documentation 2 | description: LessThan: Compares the output of a to the output of b. Outputs 1 when a < b, 0 otherwise. Can also be written as a < b 3 | 4 | [Reference library](../../index.md) > [Operators](../index.md) > [LessThan](index.md) 5 | 6 | # LessThan 7 | 8 | ```python 9 | LessThan(a=0, b=0) 10 | ``` 11 | 12 | Compares the output of a to the output of b. Outputs 1 when a < b, 0 otherwise. Can also be written as a < b 13 | 14 | -------------------------------------------------------------------------------- /docs/library/operators/lessthanorequal/index.md: -------------------------------------------------------------------------------- 1 | title: LessThanOrEqual node documentation 2 | description: LessThanOrEqual: Compares the output of a to the output of b. Outputs 1 when a <= b, 0 otherwise. Can also be written as a <= b 3 | 4 | [Reference library](../../index.md) > [Operators](../index.md) > [LessThanOrEqual](index.md) 5 | 6 | # LessThanOrEqual 7 | 8 | ```python 9 | LessThanOrEqual(a=0, b=0) 10 | ``` 11 | 12 | Compares the output of a to the output of b. Outputs 1 when a <= b, 0 otherwise. Can also be written as a <= b 13 | 14 | -------------------------------------------------------------------------------- /docs/library/operators/midinotetofrequency/index.md: -------------------------------------------------------------------------------- 1 | title: MidiNoteToFrequency node documentation 2 | description: MidiNoteToFrequency: Map a MIDI note to a frequency (where 440Hz = A4 = 69), supporting floating-point input. 3 | 4 | [Reference library](../../index.md) > [Operators](../index.md) > [MidiNoteToFrequency](index.md) 5 | 6 | # MidiNoteToFrequency 7 | 8 | ```python 9 | MidiNoteToFrequency(a=0) 10 | ``` 11 | 12 | Map a MIDI note to a frequency (where 440Hz = A4 = 69), supporting floating-point input. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/operators/modulo/index.md: -------------------------------------------------------------------------------- 1 | title: Modulo node documentation 2 | description: Modulo: Outputs the value of a modulo b, per sample. Supports fractional values. Can also be written as a % b 3 | 4 | [Reference library](../../index.md) > [Operators](../index.md) > [Modulo](index.md) 5 | 6 | # Modulo 7 | 8 | ```python 9 | Modulo(a=0, b=0) 10 | ``` 11 | 12 | Outputs the value of a modulo b, per sample. Supports fractional values. Can also be written as a % b 13 | 14 | -------------------------------------------------------------------------------- /docs/library/operators/multiply/index.md: -------------------------------------------------------------------------------- 1 | title: Multiply node documentation 2 | description: Multiply: Multiply each sample of a by each sample of b. Can also be written as a * b 3 | 4 | [Reference library](../../index.md) > [Operators](../index.md) > [Multiply](index.md) 5 | 6 | # Multiply 7 | 8 | ```python 9 | Multiply(a=1.0, b=1.0) 10 | ``` 11 | 12 | Multiply each sample of a by each sample of b. Can also be written as a * b 13 | 14 | -------------------------------------------------------------------------------- /docs/library/operators/notequal/index.md: -------------------------------------------------------------------------------- 1 | title: NotEqual node documentation 2 | description: NotEqual: Compares the output of a to the output of b. Outputs 0 when equal, 1 otherwise. Can also be written as a != b 3 | 4 | [Reference library](../../index.md) > [Operators](../index.md) > [NotEqual](index.md) 5 | 6 | # NotEqual 7 | 8 | ```python 9 | NotEqual(a=0, b=0) 10 | ``` 11 | 12 | Compares the output of a to the output of b. Outputs 0 when equal, 1 otherwise. Can also be written as a != b 13 | 14 | -------------------------------------------------------------------------------- /docs/library/operators/pow/index.md: -------------------------------------------------------------------------------- 1 | title: Pow node documentation 2 | description: Pow: Outputs a to the power of b, per sample. Can also be written as a ** b 3 | 4 | [Reference library](../../index.md) > [Operators](../index.md) > [Pow](index.md) 5 | 6 | # Pow 7 | 8 | ```python 9 | Pow(a=0, b=0) 10 | ``` 11 | 12 | Outputs a to the power of b, per sample. Can also be written as a ** b 13 | 14 | -------------------------------------------------------------------------------- /docs/library/operators/round/index.md: -------------------------------------------------------------------------------- 1 | title: Round node documentation 2 | description: Round: Round the input to the nearest integer value. 3 | 4 | [Reference library](../../index.md) > [Operators](../index.md) > [Round](index.md) 5 | 6 | # Round 7 | 8 | ```python 9 | Round(a=0) 10 | ``` 11 | 12 | Round the input to the nearest integer value. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/operators/roundtoscale/index.md: -------------------------------------------------------------------------------- 1 | title: RoundToScale node documentation 2 | description: RoundToScale: Given a frequency input, generates a frequency output that is rounded to the nearest MIDI note. (TODO: Not very well named) 3 | 4 | [Reference library](../../index.md) > [Operators](../index.md) > [RoundToScale](index.md) 5 | 6 | # RoundToScale 7 | 8 | ```python 9 | RoundToScale(a=0) 10 | ``` 11 | 12 | Given a frequency input, generates a frequency output that is rounded to the nearest MIDI note. (TODO: Not very well named) 13 | 14 | -------------------------------------------------------------------------------- /docs/library/operators/scalelinexp/index.md: -------------------------------------------------------------------------------- 1 | title: ScaleLinExp node documentation 2 | description: ScaleLinExp: Scales the input from a linear range (between a and b) to an exponential range (between c and d). 3 | 4 | [Reference library](../../index.md) > [Operators](../index.md) > [ScaleLinExp](index.md) 5 | 6 | # ScaleLinExp 7 | 8 | ```python 9 | ScaleLinExp(input=0, a=0, b=1, c=1, d=10) 10 | ``` 11 | 12 | Scales the input from a linear range (between a and b) to an exponential range (between c and d). 13 | 14 | -------------------------------------------------------------------------------- /docs/library/operators/scalelinlin/index.md: -------------------------------------------------------------------------------- 1 | title: ScaleLinLin node documentation 2 | description: ScaleLinLin: Scales the input from a linear range (between a and b) to a linear range (between c and d). 3 | 4 | [Reference library](../../index.md) > [Operators](../index.md) > [ScaleLinLin](index.md) 5 | 6 | # ScaleLinLin 7 | 8 | ```python 9 | ScaleLinLin(input=0, a=0, b=1, c=1, d=10) 10 | ``` 11 | 12 | Scales the input from a linear range (between a and b) to a linear range (between c and d). 13 | 14 | -------------------------------------------------------------------------------- /docs/library/operators/selectinput/index.md: -------------------------------------------------------------------------------- 1 | title: SelectInput node documentation 2 | description: SelectInput: Pass through the output of one or more `inputs`, based on the integer input index specified in `index`. Unlike `ChannelSelect`, inputs may be multichannel, and `index` can be modulated in real time. 3 | 4 | [Reference library](../../index.md) > [Operators](../index.md) > [SelectInput](index.md) 5 | 6 | # SelectInput 7 | 8 | ```python 9 | SelectInput(index=0) 10 | ``` 11 | 12 | Pass through the output of one or more `inputs`, based on the integer input index specified in `index`. Unlike `ChannelSelect`, inputs may be multichannel, and `index` can be modulated in real time. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/operators/sin/index.md: -------------------------------------------------------------------------------- 1 | title: Sin node documentation 2 | description: Sin: Outputs sin(a), per sample. 3 | 4 | [Reference library](../../index.md) > [Operators](../index.md) > [Sin](index.md) 5 | 6 | # Sin 7 | 8 | ```python 9 | Sin(a=0) 10 | ``` 11 | 12 | Outputs sin(a), per sample. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/operators/subtract/index.md: -------------------------------------------------------------------------------- 1 | title: Subtract node documentation 2 | description: Subtract: Subtract each sample of b from each sample of a. Can also be written as a - b 3 | 4 | [Reference library](../../index.md) > [Operators](../index.md) > [Subtract](index.md) 5 | 6 | # Subtract 7 | 8 | ```python 9 | Subtract(a=0, b=0) 10 | ``` 11 | 12 | Subtract each sample of b from each sample of a. Can also be written as a - b 13 | 14 | -------------------------------------------------------------------------------- /docs/library/operators/sum/index.md: -------------------------------------------------------------------------------- 1 | title: Sum node documentation 2 | description: Sum: Sums the output of all of the input nodes, by sample. 3 | 4 | [Reference library](../../index.md) > [Operators](../index.md) > [Sum](index.md) 5 | 6 | # Sum 7 | 8 | ```python 9 | Sum() 10 | ``` 11 | 12 | Sums the output of all of the input nodes, by sample. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/operators/tan/index.md: -------------------------------------------------------------------------------- 1 | title: Tan node documentation 2 | description: Tan: Outputs tan(a), per sample. 3 | 4 | [Reference library](../../index.md) > [Operators](../index.md) > [Tan](index.md) 5 | 6 | # Tan 7 | 8 | ```python 9 | Tan(a=0) 10 | ``` 11 | 12 | Outputs tan(a), per sample. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/operators/tanh/index.md: -------------------------------------------------------------------------------- 1 | title: Tanh node documentation 2 | description: Tanh: Outputs tanh(a), per sample. Can be used as a soft clipper. 3 | 4 | [Reference library](../../index.md) > [Operators](../index.md) > [Tanh](index.md) 5 | 6 | # Tanh 7 | 8 | ```python 9 | Tanh(a=0) 10 | ``` 11 | 12 | Outputs tanh(a), per sample. Can be used as a soft clipper. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/operators/timeshift/index.md: -------------------------------------------------------------------------------- 1 | title: TimeShift node documentation 2 | description: TimeShift: TimeShift 3 | 4 | [Reference library](../../index.md) > [Operators](../index.md) > [TimeShift](index.md) 5 | 6 | # TimeShift 7 | 8 | ```python 9 | TimeShift(a=0) 10 | ``` 11 | 12 | TimeShift 13 | 14 | -------------------------------------------------------------------------------- /docs/library/operators/triggermult/index.md: -------------------------------------------------------------------------------- 1 | title: TriggerMult node documentation 2 | description: TriggerMult: Distribute any triggers to all output nodes. 3 | 4 | [Reference library](../../index.md) > [Operators](../index.md) > [TriggerMult](index.md) 5 | 6 | # TriggerMult 7 | 8 | ```python 9 | TriggerMult(a=0) 10 | ``` 11 | 12 | Distribute any triggers to all output nodes. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/oscillators/constant/index.md: -------------------------------------------------------------------------------- 1 | title: Constant node documentation 2 | description: Constant: Produces a constant value. 3 | 4 | [Reference library](../../index.md) > [Oscillators](../index.md) > [Constant](index.md) 5 | 6 | # Constant 7 | 8 | ```python 9 | Constant(value=0) 10 | ``` 11 | 12 | Produces a constant value. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/oscillators/impulse/example-0.py: -------------------------------------------------------------------------------- 1 | from signalflow import * 2 | graph = AudioGraph() 3 | 4 | #------------------------------------------------------------------------------- 5 | # Using an Impulse node as a clock to trigger an envelope once per second. 6 | #------------------------------------------------------------------------------- 7 | clock = Impulse(1.0) 8 | osc = TriangleOscillator(250) 9 | envelope = ASREnvelope(0.01, 0.0, 0.5, 1.0, clock) 10 | output = StereoPanner(osc * envelope) 11 | output.play() 12 | graph.wait() -------------------------------------------------------------------------------- /docs/library/oscillators/sawlfo/example-0.py: -------------------------------------------------------------------------------- 1 | from signalflow import * 2 | graph = AudioGraph() 3 | 4 | #------------------------------------------------------------------------------- 5 | # Siren effect, using a sawtooth LFO to modulate a sinewave's frequency 6 | #------------------------------------------------------------------------------- 7 | lfo = SawLFO(1, 200, 1000) 8 | sine = SineOscillator(lfo) 9 | output = StereoPanner(sine) * 0.5 10 | output.play() 11 | graph.wait() 12 | -------------------------------------------------------------------------------- /docs/library/oscillators/sawlfo/index.md: -------------------------------------------------------------------------------- 1 | title: SawLFO node documentation 2 | description: SawLFO: Produces a sawtooth LFO at the given `frequency` and `phase` offset, with output ranging from `min` to `max`. 3 | 4 | [Reference library](../../index.md) > [Oscillators](../index.md) > [SawLFO](index.md) 5 | 6 | # SawLFO 7 | 8 | ```python 9 | SawLFO(frequency=1.0, min=0.0, max=1.0, phase=0.0) 10 | ``` 11 | 12 | Produces a sawtooth LFO at the given `frequency` and `phase` offset, with output ranging from `min` to `max`. 13 | 14 | ### Examples 15 | 16 | ```python 17 | 18 | #------------------------------------------------------------------------------- 19 | # Siren effect, using a sawtooth LFO to modulate a sinewave's frequency 20 | #------------------------------------------------------------------------------- 21 | lfo = SawLFO(1, 200, 1000) 22 | sine = SineOscillator(lfo) 23 | output = StereoPanner(sine) * 0.5 24 | output.play() 25 | 26 | ``` 27 | 28 | -------------------------------------------------------------------------------- /docs/library/oscillators/sawoscillator/example-0.py: -------------------------------------------------------------------------------- 1 | from signalflow import * 2 | graph = AudioGraph() 3 | 4 | #------------------------------------------------------------------------------- 5 | # Simple saw wave oscillator shaped by an envelope 6 | #------------------------------------------------------------------------------- 7 | saw = SawOscillator(440) 8 | envelope = ASREnvelope(0.05, 0.1, 0.5) 9 | output = StereoPanner(saw * envelope) * 0.5 10 | output.play() 11 | graph.wait() -------------------------------------------------------------------------------- /docs/library/oscillators/sinelfo/example-0.py: -------------------------------------------------------------------------------- 1 | from signalflow import * 2 | graph = AudioGraph() 3 | 4 | #------------------------------------------------------------------------------- 5 | # Siren effect, using a sinewave LFO to modulate a sawtooth's frequency 6 | #------------------------------------------------------------------------------- 7 | lfo = SineLFO(1, 200, 1000) 8 | saw = SawOscillator(lfo) 9 | output = StereoPanner(saw) * 0.3 10 | output.play() 11 | graph.wait() 12 | -------------------------------------------------------------------------------- /docs/library/oscillators/sinelfo/index.md: -------------------------------------------------------------------------------- 1 | title: SineLFO node documentation 2 | description: SineLFO: Produces a sinusoidal LFO at the given `frequency` and `phase` offset, with output ranging from `min` to `max`. 3 | 4 | [Reference library](../../index.md) > [Oscillators](../index.md) > [SineLFO](index.md) 5 | 6 | # SineLFO 7 | 8 | ```python 9 | SineLFO(frequency=1.0, min=0.0, max=1.0, phase=0.0) 10 | ``` 11 | 12 | Produces a sinusoidal LFO at the given `frequency` and `phase` offset, with output ranging from `min` to `max`. 13 | 14 | ### Examples 15 | 16 | ```python 17 | 18 | #------------------------------------------------------------------------------- 19 | # Siren effect, using a sinewave LFO to modulate a sawtooth's frequency 20 | #------------------------------------------------------------------------------- 21 | lfo = SineLFO(1, 200, 1000) 22 | saw = SawOscillator(lfo) 23 | output = StereoPanner(saw) * 0.3 24 | output.play() 25 | 26 | ``` 27 | 28 | -------------------------------------------------------------------------------- /docs/library/oscillators/sineoscillator/example-0.py: -------------------------------------------------------------------------------- 1 | from signalflow import * 2 | graph = AudioGraph() 3 | 4 | #------------------------------------------------------------------------------- 5 | # Simple sine wave oscillator shaped by an envelope 6 | #------------------------------------------------------------------------------- 7 | sine = SineOscillator(440) 8 | envelope = ASREnvelope(0.1, 0.1, 0.5) 9 | output = StereoPanner(sine * envelope) * 0.5 10 | output.play() 11 | graph.wait() -------------------------------------------------------------------------------- /docs/library/oscillators/sineoscillator/index.md: -------------------------------------------------------------------------------- 1 | title: SineOscillator node documentation 2 | description: SineOscillator: Produces a sine wave at the given `frequency`. 3 | 4 | [Reference library](../../index.md) > [Oscillators](../index.md) > [SineOscillator](index.md) 5 | 6 | # SineOscillator 7 | 8 | ```python 9 | SineOscillator(frequency=440, phase_offset=None, reset=None) 10 | ``` 11 | 12 | Produces a sine wave at the given `frequency`. 13 | 14 | ### Examples 15 | 16 | ```python 17 | 18 | #------------------------------------------------------------------------------- 19 | # Simple sine wave oscillator shaped by an envelope 20 | #------------------------------------------------------------------------------- 21 | sine = SineOscillator(440) 22 | envelope = ASREnvelope(0.1, 0.1, 0.5) 23 | output = StereoPanner(sine * envelope) * 0.5 24 | output.play() 25 | 26 | ``` 27 | 28 | -------------------------------------------------------------------------------- /docs/library/oscillators/squarelfo/example-0.py: -------------------------------------------------------------------------------- 1 | from signalflow import * 2 | graph = AudioGraph() 3 | 4 | #------------------------------------------------------------------------------- 5 | # Alarm effect, using a pulse wave LFO to modulate a sinewave's frequency 6 | #------------------------------------------------------------------------------- 7 | lfo = SquareLFO(1, 200, 400) 8 | sine = SineOscillator(lfo) 9 | output = StereoPanner(sine) * 0.5 10 | output.play() 11 | graph.wait() -------------------------------------------------------------------------------- /docs/library/oscillators/squareoscillator/example-0.py: -------------------------------------------------------------------------------- 1 | from signalflow import * 2 | graph = AudioGraph() 3 | 4 | #------------------------------------------------------------------------------- 5 | # Simple square wave oscillator shaped by an envelope 6 | #------------------------------------------------------------------------------- 7 | square = SquareOscillator(440) 8 | envelope = ASREnvelope(0, 0.1, 0.5) 9 | output = StereoPanner(square * envelope) * 0.5 10 | output.play() 11 | graph.wait() -------------------------------------------------------------------------------- /docs/library/oscillators/trianglelfo/example-0.py: -------------------------------------------------------------------------------- 1 | from signalflow import * 2 | graph = AudioGraph() 3 | 4 | #----------------------------------------------------------------------------------- 5 | # Pacman ghost sound, using a triangle wave LFO to modulate a sine wave's frequency 6 | #----------------------------------------------------------------------------------- 7 | lfo = TriangleLFO(3, 200, 900) 8 | sine = SineOscillator(lfo) 9 | output = StereoPanner(sine) * 0.5 10 | output.play() 11 | graph.wait() -------------------------------------------------------------------------------- /docs/library/oscillators/triangleoscillator/example-0.py: -------------------------------------------------------------------------------- 1 | from signalflow import * 2 | graph = AudioGraph() 3 | 4 | #------------------------------------------------------------------------------- 5 | # Simple triangle wave oscillator shaped by an envelope 6 | #------------------------------------------------------------------------------- 7 | tri = TriangleOscillator(440) 8 | envelope = ASREnvelope(0.1, 0.1, 0.5) 9 | output = StereoPanner(tri * envelope) * 0.5 10 | output.play() 11 | graph.wait() -------------------------------------------------------------------------------- /docs/library/oscillators/triangleoscillator/index.md: -------------------------------------------------------------------------------- 1 | title: TriangleOscillator node documentation 2 | description: TriangleOscillator: Produces a triangle wave with the given `frequency`. 3 | 4 | [Reference library](../../index.md) > [Oscillators](../index.md) > [TriangleOscillator](index.md) 5 | 6 | # TriangleOscillator 7 | 8 | ```python 9 | TriangleOscillator(frequency=440) 10 | ``` 11 | 12 | Produces a triangle wave with the given `frequency`. 13 | 14 | ### Examples 15 | 16 | ```python 17 | 18 | #------------------------------------------------------------------------------- 19 | # Simple triangle wave oscillator shaped by an envelope 20 | #------------------------------------------------------------------------------- 21 | tri = TriangleOscillator(440) 22 | envelope = ASREnvelope(0.1, 0.1, 0.5) 23 | output = StereoPanner(tri * envelope) * 0.5 24 | output.play() 25 | 26 | ``` 27 | 28 | -------------------------------------------------------------------------------- /docs/library/oscillators/wavetable/index.md: -------------------------------------------------------------------------------- 1 | title: Wavetable node documentation 2 | description: Wavetable: Plays the wavetable stored in buffer at the given `frequency` and `phase` offset. `sync` can be used to provide a hard sync input, which resets the wavetable's phase at each zero-crossing. 3 | 4 | [Reference library](../../index.md) > [Oscillators](../index.md) > [Wavetable](index.md) 5 | 6 | # Wavetable 7 | 8 | ```python 9 | Wavetable(buffer=None, frequency=440, phase_offset=0, sync=0, phase_map=None) 10 | ``` 11 | 12 | Plays the wavetable stored in buffer at the given `frequency` and `phase` offset. `sync` can be used to provide a hard sync input, which resets the wavetable's phase at each zero-crossing. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/oscillators/wavetable2d/index.md: -------------------------------------------------------------------------------- 1 | title: Wavetable2D node documentation 2 | description: Wavetable2D: Wavetable2D 3 | 4 | [Reference library](../../index.md) > [Oscillators](../index.md) > [Wavetable2D](index.md) 5 | 6 | # Wavetable2D 7 | 8 | ```python 9 | Wavetable2D(buffer=None, frequency=440, crossfade=0.0, phase_offset=0.0, sync=0) 10 | ``` 11 | 12 | Wavetable2D 13 | 14 | -------------------------------------------------------------------------------- /docs/library/processors/clip/index.md: -------------------------------------------------------------------------------- 1 | title: Clip node documentation 2 | description: Clip: Clip the input to `min`/`max`. 3 | 4 | [Reference library](../../index.md) > [Processors](../index.md) > [Clip](index.md) 5 | 6 | # Clip 7 | 8 | ```python 9 | Clip(input=None, min=-1.0, max=1.0) 10 | ``` 11 | 12 | Clip the input to `min`/`max`. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/processors/delays/allpassdelay/example-0.py: -------------------------------------------------------------------------------- 1 | from signalflow import * 2 | graph = AudioGraph() 3 | 4 | #------------------------------------------------------------------------------- 5 | # Using AllpassDelay to add a delay effect to a simple melodic sequence. 6 | # The original oscillator can be heard in the left channel. 7 | # The delay effect can be heard in the right channel. 8 | #------------------------------------------------------------------------------- 9 | clock = Impulse(1.0) 10 | sequence = Sequence([ 60, 62, 64, 65, 67, 69, 71, 72 ], clock) 11 | frequency = MidiNoteToFrequency(sequence) 12 | 13 | oscillator = TriangleOscillator(frequency) 14 | envelope = ASREnvelope(0, 0.2, 0.3, 1.0, clock) 15 | voice = oscillator * envelope 16 | delayed = AllpassDelay(input=voice, 17 | delay_time=0.4, 18 | feedback=0.8) 19 | 20 | output = ChannelArray([ voice, delayed ]) * 0.75 21 | output.play() 22 | graph.wait() -------------------------------------------------------------------------------- /docs/library/processors/delays/combdelay/example-0.py: -------------------------------------------------------------------------------- 1 | from signalflow import * 2 | graph = AudioGraph() 3 | 4 | #------------------------------------------------------------------------------- 5 | # Using CombDelay to change the character of a saw wave oscillator. 6 | #------------------------------------------------------------------------------- 7 | clock = Impulse(4) 8 | arpeggio = [60, 62, 64, 66, 68, 70, 9 | 72, 70, 68, 66, 64, 62] 10 | sequence = Sequence(arpeggio, clock) 11 | frequency = MidiNoteToFrequency(sequence) 12 | 13 | oscillator = SawOscillator(frequency) 14 | envelope = ASREnvelope(0.1, 0, 0.2, 1.0, clock) 15 | voice = oscillator * envelope 16 | comb = CombDelay(input=voice, 17 | delay_time=0.09, 18 | feedback=0.6, 19 | max_delay_time=0.9) 20 | 21 | output = StereoPanner(comb) * 0.5 22 | output.play() 23 | graph.wait() -------------------------------------------------------------------------------- /docs/library/processors/delays/index.md: -------------------------------------------------------------------------------- 1 | [Reference library](../index.md) > [Processors: Delays](index.md) 2 | 3 | # Processors: Delays 4 | 5 | - **[AllpassDelay](allpassdelay/index.md)**: All-pass delay, with `feedback` between 0 and 1. `delay_time` must be less than or equal to `max_delay_time`. 6 | - **[CombDelay](combdelay/index.md)**: Comb delay, with `feedback` between 0 and 1. `delay_time` must be less than or equal to `max_delay_time`. 7 | - **[OneTapDelay](onetapdelay/index.md)**: Single-tap delay line. `delay_time` must be less than or equal to `max_delay_time`. 8 | - **[Stutter](stutter/index.md)**: Stutters the input whenever a trigger is received on `clock`. Generates `stutter_count` repeats, with duration of `stutter_time`. 9 | -------------------------------------------------------------------------------- /docs/library/processors/delays/onetapdelay/example-0.py: -------------------------------------------------------------------------------- 1 | from signalflow import * 2 | graph = AudioGraph() 3 | 4 | #------------------------------------------------------------------------------- 5 | # Using OneTapDelay to create a delay effect with no feedback. 6 | # The original sound is heard in the left channel, and the delayed sound in the 7 | # right channel. 8 | #------------------------------------------------------------------------------- 9 | clock = Impulse(1) 10 | oscillator = TriangleOscillator(440) 11 | envelope = ASREnvelope(0.001, 0, 0.3, 1.0, clock) 12 | voice = oscillator * envelope 13 | delayed = OneTapDelay(voice, 0.25) * 0.5 14 | output = ChannelArray([voice, delayed]) * 0.5 15 | output.play() 16 | graph.wait() -------------------------------------------------------------------------------- /docs/library/processors/delays/onetapdelay/example-1.py: -------------------------------------------------------------------------------- 1 | from signalflow import * 2 | graph = AudioGraph() 3 | 4 | #------------------------------------------------------------------------------- 5 | # Using OneTapDelay to bring controlled rhythmic interest to a melodic sequence 6 | #------------------------------------------------------------------------------- 7 | clock = Impulse(3.5) 8 | Dm = [ 62, 65, 69 ] * 2 9 | Bdim = [ 59, 62, 65 ] * 2 10 | Gm = [55, 58, 62 ] * 2 11 | Bb = [77, 74, 70 ] 12 | A = [ 76, 73, 69 ] 13 | 14 | arpeggios = Dm + Bdim + Gm + Bb + A 15 | sequence = Sequence(arpeggios, clock) 16 | frequency = MidiNoteToFrequency(sequence) 17 | 18 | oscillator = SquareOscillator(frequency) 19 | envelope = ASREnvelope(0.1, 0, 0.2, 1.0, clock) 20 | voice = oscillator * envelope 21 | filtered = SVFilter(voice, "low_pass", 4000, 0.3) 22 | delayed = filtered + OneTapDelay(filtered, 0.4) * 0.5 23 | 24 | output = StereoPanner(delayed) * 0.3 25 | output.play() 26 | graph.wait() -------------------------------------------------------------------------------- /docs/library/processors/delays/stutter/index.md: -------------------------------------------------------------------------------- 1 | title: Stutter node documentation 2 | description: Stutter: Stutters the input whenever a trigger is received on `clock`. Generates `stutter_count` repeats, with duration of `stutter_time`. 3 | 4 | [Reference library](../../index.md) > [Processors: Delays](../index.md) > [Stutter](index.md) 5 | 6 | # Stutter 7 | 8 | ```python 9 | Stutter(input=0.0, stutter_time=0.1, stutter_count=1, stutter_probability=1.0, stutter_advance_time=0.0, clock=None, max_stutter_time=1.0) 10 | ``` 11 | 12 | Stutters the input whenever a trigger is received on `clock`. Generates `stutter_count` repeats, with duration of `stutter_time`. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/processors/distortion/index.md: -------------------------------------------------------------------------------- 1 | [Reference library](../index.md) > [Processors: Distortion](index.md) 2 | 3 | # Processors: Distortion 4 | 5 | - **[Resample](resample/index.md)**: Resampler and bit crusher. `sample_rate` is in Hz, `bit_rate` is an integer between 0 and 16. 6 | - **[SampleAndHold](sampleandhold/index.md)**: Samples and holds the input each time a trigger is received on `clock`. 7 | - **[Squiz](squiz/index.md)**: Implementation of Dan Stowell's Squiz algorithm, a kind of downsampler. 8 | - **[WaveShaper](waveshaper/index.md)**: Applies wave-shaping as described in the WaveShaperBuffer `buffer`. 9 | -------------------------------------------------------------------------------- /docs/library/processors/distortion/resample/example-0.py: -------------------------------------------------------------------------------- 1 | from signalflow import * 2 | graph = AudioGraph() 3 | 4 | #------------------------------------------------------------------------------- 5 | # Using Resample to distort a sine wave. 6 | #------------------------------------------------------------------------------- 7 | sine = SineOscillator(440) 8 | crushed = Resample(sine, 11025, 4) 9 | output = StereoPanner(crushed) * 0.3 10 | output.play() 11 | graph.wait() -------------------------------------------------------------------------------- /docs/library/processors/distortion/resample/index.md: -------------------------------------------------------------------------------- 1 | title: Resample node documentation 2 | description: Resample: Resampler and bit crusher. `sample_rate` is in Hz, `bit_rate` is an integer between 0 and 16. 3 | 4 | [Reference library](../../index.md) > [Processors: Distortion](../index.md) > [Resample](index.md) 5 | 6 | # Resample 7 | 8 | ```python 9 | Resample(input=0, sample_rate=44100, bit_rate=16) 10 | ``` 11 | 12 | Resampler and bit crusher. `sample_rate` is in Hz, `bit_rate` is an integer between 0 and 16. 13 | 14 | ### Examples 15 | 16 | ```python 17 | 18 | #------------------------------------------------------------------------------- 19 | # Using Resample to distort a sine wave. 20 | #------------------------------------------------------------------------------- 21 | sine = SineOscillator(440) 22 | crushed = Resample(sine, 11025, 4) 23 | output = StereoPanner(crushed) * 0.3 24 | output.play() 25 | 26 | ``` 27 | 28 | -------------------------------------------------------------------------------- /docs/library/processors/distortion/sampleandhold/index.md: -------------------------------------------------------------------------------- 1 | title: SampleAndHold node documentation 2 | description: SampleAndHold: Samples and holds the input each time a trigger is received on `clock`. 3 | 4 | [Reference library](../../index.md) > [Processors: Distortion](../index.md) > [SampleAndHold](index.md) 5 | 6 | # SampleAndHold 7 | 8 | ```python 9 | SampleAndHold(input=None, clock=None) 10 | ``` 11 | 12 | Samples and holds the input each time a trigger is received on `clock`. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/processors/distortion/squiz/index.md: -------------------------------------------------------------------------------- 1 | title: Squiz node documentation 2 | description: Squiz: Implementation of Dan Stowell's Squiz algorithm, a kind of downsampler. 3 | 4 | [Reference library](../../index.md) > [Processors: Distortion](../index.md) > [Squiz](index.md) 5 | 6 | # Squiz 7 | 8 | ```python 9 | Squiz(input=0.0, rate=2.0, chunk_size=1) 10 | ``` 11 | 12 | Implementation of Dan Stowell's Squiz algorithm, a kind of downsampler. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/processors/distortion/waveshaper/example-0.py: -------------------------------------------------------------------------------- 1 | from signalflow import * 2 | graph = AudioGraph() 3 | 4 | #------------------------------------------------------------------------------- 5 | # Create a waveshaper buffer that silences any samples with amplitude < 0.5 6 | #------------------------------------------------------------------------------- 7 | buf = WaveShaperBuffer(lambda n: 0 if abs(n) < 0.5 else n) 8 | sine = SineOscillator(120) 9 | waveshaper = WaveShaper(sine, buf) 10 | attenuated = waveshaper * 0.1 11 | attenuated.play() 12 | 13 | graph.wait() 14 | -------------------------------------------------------------------------------- /docs/library/processors/dynamics/compressor/index.md: -------------------------------------------------------------------------------- 1 | title: Compressor node documentation 2 | description: Compressor: Dynamic range compression, with optional `sidechain` input. When the input amplitude is above `threshold`, compresses the amplitude with the given `ratio`, following the given `attack_time` and `release_time` in seconds. 3 | 4 | [Reference library](../../index.md) > [Processors: Dynamics](../index.md) > [Compressor](index.md) 5 | 6 | # Compressor 7 | 8 | ```python 9 | Compressor(input=0.0, threshold=0.1, ratio=2, attack_time=0.01, release_time=0.1, sidechain=None) 10 | ``` 11 | 12 | Dynamic range compression, with optional `sidechain` input. When the input amplitude is above `threshold`, compresses the amplitude with the given `ratio`, following the given `attack_time` and `release_time` in seconds. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/processors/dynamics/gate/index.md: -------------------------------------------------------------------------------- 1 | title: Gate node documentation 2 | description: Gate: Outputs the input value when it is above the given `threshold`, otherwise zero. 3 | 4 | [Reference library](../../index.md) > [Processors: Dynamics](../index.md) > [Gate](index.md) 5 | 6 | # Gate 7 | 8 | ```python 9 | Gate(input=0.0, threshold=0.1) 10 | ``` 11 | 12 | Outputs the input value when it is above the given `threshold`, otherwise zero. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/processors/dynamics/index.md: -------------------------------------------------------------------------------- 1 | [Reference library](../index.md) > [Processors: Dynamics](index.md) 2 | 3 | # Processors: Dynamics 4 | 5 | - **[Compressor](compressor/index.md)**: Dynamic range compression, with optional `sidechain` input. When the input amplitude is above `threshold`, compresses the amplitude with the given `ratio`, following the given `attack_time` and `release_time` in seconds. 6 | - **[Gate](gate/index.md)**: Outputs the input value when it is above the given `threshold`, otherwise zero. 7 | - **[Maximiser](maximiser/index.md)**: Gain maximiser. 8 | - **[RMS](rms/index.md)**: Outputs the root-mean-squared value of the input, in buffers equal to the graph's current buffer size. 9 | -------------------------------------------------------------------------------- /docs/library/processors/dynamics/maximiser/index.md: -------------------------------------------------------------------------------- 1 | title: Maximiser node documentation 2 | description: Maximiser: Gain maximiser. 3 | 4 | [Reference library](../../index.md) > [Processors: Dynamics](../index.md) > [Maximiser](index.md) 5 | 6 | # Maximiser 7 | 8 | ```python 9 | Maximiser(input=0.0, ceiling=0.5, attack_time=1.0, release_time=1.0) 10 | ``` 11 | 12 | Gain maximiser. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/processors/dynamics/rms/index.md: -------------------------------------------------------------------------------- 1 | title: RMS node documentation 2 | description: RMS: Outputs the root-mean-squared value of the input, in buffers equal to the graph's current buffer size. 3 | 4 | [Reference library](../../index.md) > [Processors: Dynamics](../index.md) > [RMS](index.md) 5 | 6 | # RMS 7 | 8 | ```python 9 | RMS(input=0.0) 10 | ``` 11 | 12 | Outputs the root-mean-squared value of the input, in buffers equal to the graph's current buffer size. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/processors/filters/biquadfilter/index.md: -------------------------------------------------------------------------------- 1 | title: BiquadFilter node documentation 2 | description: BiquadFilter: Biquad filter. filter_type can be 'low_pass', 'band_pass', 'high_pass', 'notch', 'peak', 'low_shelf', 'high_shelf'. Not recommended for real-time modulation; for this, use SVFilter. 3 | 4 | [Reference library](../../index.md) > [Processors: Filters](../index.md) > [BiquadFilter](index.md) 5 | 6 | # BiquadFilter 7 | 8 | ```python 9 | BiquadFilter(input=0.0, filter_type=SIGNALFLOW_FILTER_TYPE_LOW_PASS, cutoff=440, resonance=0.0, peak_gain=0.0) 10 | ``` 11 | 12 | Biquad filter. filter_type can be 'low_pass', 'band_pass', 'high_pass', 'notch', 'peak', 'low_shelf', 'high_shelf'. Not recommended for real-time modulation; for this, use SVFilter. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/processors/filters/dcfilter/index.md: -------------------------------------------------------------------------------- 1 | title: DCFilter node documentation 2 | description: DCFilter: Remove low-frequency and DC content from a signal. 3 | 4 | [Reference library](../../index.md) > [Processors: Filters](../index.md) > [DCFilter](index.md) 5 | 6 | # DCFilter 7 | 8 | ```python 9 | DCFilter(input=0.0) 10 | ``` 11 | 12 | Remove low-frequency and DC content from a signal. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/processors/filters/eq/example-0.py: -------------------------------------------------------------------------------- 1 | from signalflow import * 2 | graph = AudioGraph() 3 | 4 | #------------------------------------------------------------------------------- 5 | # Using EQ to shape white noise. The low band (below 500Hz) is reduced. The mid 6 | # band is boosted. The high band (above 2000Hz) is reduced drastically. 7 | #------------------------------------------------------------------------------- 8 | noise = WhiteNoise() 9 | eq = EQ(input=noise, 10 | low_gain=0.0, 11 | mid_gain=1.5, 12 | high_gain=0.2, 13 | low_freq=1000, 14 | high_freq=2000) 15 | output = StereoPanner(eq) * 0.5 16 | output.play() 17 | graph.wait() -------------------------------------------------------------------------------- /docs/library/processors/filters/index.md: -------------------------------------------------------------------------------- 1 | [Reference library](../index.md) > [Processors: Filters](index.md) 2 | 3 | # Processors: Filters 4 | 5 | - **[BiquadFilter](biquadfilter/index.md)**: Biquad filter. filter_type can be 'low_pass', 'band_pass', 'high_pass', 'notch', 'peak', 'low_shelf', 'high_shelf'. Not recommended for real-time modulation; for this, use SVFilter. 6 | - **[DCFilter](dcfilter/index.md)**: Remove low-frequency and DC content from a signal. 7 | - **[EQ](eq/index.md)**: Three-band EQ. 8 | - **[MoogVCF](moogvcf/index.md)**: Simulation of the Moog ladder low-pass filter. `cutoff` sets the cutoff frequency; `resonance` should typically be between 0..1. 9 | - **[SVFilter](svfilter/index.md)**: State variable filter. `filter_type` can be 'low_pass', 'band_pass', 'high_pass', 'notch', 'peak', 'low_shelf', 'high_shelf'. `resonance` should be between `[0..1]`. 10 | -------------------------------------------------------------------------------- /docs/library/processors/filters/moogvcf/index.md: -------------------------------------------------------------------------------- 1 | title: MoogVCF node documentation 2 | description: MoogVCF: Simulation of the Moog ladder low-pass filter. `cutoff` sets the cutoff frequency; `resonance` should typically be between 0..1. 3 | 4 | [Reference library](../../index.md) > [Processors: Filters](../index.md) > [MoogVCF](index.md) 5 | 6 | # MoogVCF 7 | 8 | ```python 9 | MoogVCF(input=0.0, cutoff=200.0, resonance=0.0) 10 | ``` 11 | 12 | Simulation of the Moog ladder low-pass filter. `cutoff` sets the cutoff frequency; `resonance` should typically be between 0..1. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/processors/filters/svfilter/example-0.py: -------------------------------------------------------------------------------- 1 | from signalflow import * 2 | graph = AudioGraph() 3 | 4 | #------------------------------------------------------------------------------- 5 | # Using SVFilter as a low-pass filter on white noise. 6 | #------------------------------------------------------------------------------- 7 | noise = WhiteNoise() 8 | filtered = SVFilter(input=noise, 9 | filter_type="low_pass", 10 | cutoff=1000, 11 | resonance=0.6) 12 | output = StereoPanner(filtered) 13 | output.play() 14 | graph.wait() -------------------------------------------------------------------------------- /docs/library/processors/fold/index.md: -------------------------------------------------------------------------------- 1 | title: Fold node documentation 2 | description: Fold: Fold the input beyond `min`/`max`, reflecting the excess back. 3 | 4 | [Reference library](../../index.md) > [Processors](../index.md) > [Fold](index.md) 5 | 6 | # Fold 7 | 8 | ```python 9 | Fold(input=None, min=-1.0, max=1.0) 10 | ``` 11 | 12 | Fold the input beyond `min`/`max`, reflecting the excess back. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/processors/index.md: -------------------------------------------------------------------------------- 1 | [Reference library](../index.md) > [Processors](index.md) 2 | 3 | # Processors 4 | 5 | - **[Clip](clip/index.md)**: Clip the input to `min`/`max`. 6 | - **[Fold](fold/index.md)**: Fold the input beyond `min`/`max`, reflecting the excess back. 7 | - **[Smooth](smooth/index.md)**: Smooth the input with a given smoothing coefficient. When `smooth` = 0, applies no smoothing. 8 | - **[WetDry](wetdry/index.md)**: Takes `wet` and `dry` inputs, and outputs a mix determined by `wetness`. 9 | - **[Wrap](wrap/index.md)**: Wrap the input beyond `min`/`max`. 10 | -------------------------------------------------------------------------------- /docs/library/processors/panning/azimuthpanner/index.md: -------------------------------------------------------------------------------- 1 | title: AzimuthPanner node documentation 2 | description: AzimuthPanner: Pan input around an equally-spaced ring of `num_channels` speakers. `pan` is the pan position from -1..+1, where 0 = centre front. `width` is the source's width, where 1.0 spans exactly between an adjacent pair of channels. 3 | 4 | [Reference library](../../index.md) > [Processors: Panning](../index.md) > [AzimuthPanner](index.md) 5 | 6 | # AzimuthPanner 7 | 8 | ```python 9 | AzimuthPanner(num_channels=2, input=0, pan=0.0, width=1.0) 10 | ``` 11 | 12 | Pan input around an equally-spaced ring of `num_channels` speakers. `pan` is the pan position from -1..+1, where 0 = centre front. `width` is the source's width, where 1.0 spans exactly between an adjacent pair of channels. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/processors/panning/channelpanner/index.md: -------------------------------------------------------------------------------- 1 | title: ChannelPanner node documentation 2 | description: ChannelPanner: Pan the input between a linear series of channels, where `pan` 0 = channel 0, 1 = channel 1, etc. No wrapping is applied. 3 | 4 | [Reference library](../../index.md) > [Processors: Panning](../index.md) > [ChannelPanner](index.md) 5 | 6 | # ChannelPanner 7 | 8 | ```python 9 | ChannelPanner(num_channels=2, input=0, pan=0.0, width=1.0) 10 | ``` 11 | 12 | Pan the input between a linear series of channels, where `pan` 0 = channel 0, 1 = channel 1, etc. No wrapping is applied. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/processors/panning/spatialpanner/index.md: -------------------------------------------------------------------------------- 1 | title: SpatialPanner node documentation 2 | description: SpatialPanner: Implements a spatial panning algorithm, applied to a given SpatialEnvironment. Currently, only DBAP is supported. 3 | 4 | [Reference library](../../index.md) > [Processors: Panning](../index.md) > [SpatialPanner](index.md) 5 | 6 | # SpatialPanner 7 | 8 | ```python 9 | SpatialPanner(env=None, input=0.0, x=0.0, y=0.0, z=0.0, radius=1.0, use_delays=1.0, algorithm="dbap") 10 | ``` 11 | 12 | Implements a spatial panning algorithm, applied to a given SpatialEnvironment. Currently, only DBAP is supported. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/processors/panning/stereobalance/example-0.py: -------------------------------------------------------------------------------- 1 | from signalflow import * 2 | graph = AudioGraph() 3 | 4 | #------------------------------------------------------------------------------- 5 | # Demonstrating the effects of StereoBalance. First a low tone is assigned to 6 | # the left channel and a high tone is assigned to the right channel. 7 | # Setting StereoBalance's balance value to 0.0 will mean both tones are heard 8 | # equally. A value of -1.0 will result in only the left channel being heard. 9 | # A value of 1.0 will result in only the right channel being heard. 10 | # In this example, an LFO is modulating the balance value between -1.0 and 1.0. 11 | #------------------------------------------------------------------------------- 12 | low = TriangleOscillator(220) 13 | high = TriangleOscillator(660) 14 | panned = ChannelArray([low, high]) 15 | balanced = StereoBalance(panned, TriangleLFO(0.2, -1, 1)) * 0.5 16 | balanced.play() 17 | graph.wait() -------------------------------------------------------------------------------- /docs/library/processors/panning/stereopanner/example-0.py: -------------------------------------------------------------------------------- 1 | from signalflow import * 2 | graph = AudioGraph() 3 | 4 | #------------------------------------------------------------------------------- 5 | # Using StereoPanner to pan a low pitch to the left and a high pitch to the 6 | # right. 7 | #------------------------------------------------------------------------------- 8 | low = TriangleOscillator(220) 9 | high = TriangleOscillator(660) 10 | 11 | left = StereoPanner(low, -0.8) 12 | right = StereoPanner(high, 0.8) 13 | 14 | output = (left + right) * 0.5 15 | output.play() 16 | graph.wait() -------------------------------------------------------------------------------- /docs/library/processors/panning/stereopanner/example-1.py: -------------------------------------------------------------------------------- 1 | from signalflow import * 2 | graph = AudioGraph() 3 | 4 | #------------------------------------------------------------------------------- 5 | # Using StereoPanner to repeatedly pan an arpeggiating oscillator between the 6 | # left and right channels. 7 | #------------------------------------------------------------------------------- 8 | clock = Impulse(8.0) 9 | CMaj7 = [ 60, 64, 67, 71, 74, 76 ] * 8 10 | FMaj9 = [ 65, 69, 72, 76, 77, 81 ] * 8 11 | arpeggios = CMaj7 + FMaj9 12 | sequence = Sequence(arpeggios, clock) 13 | frequency = MidiNoteToFrequency(sequence) 14 | 15 | oscillator = TriangleOscillator(frequency) 16 | release = Line(0.1, 0.5, 12, True) 17 | envelope = ASREnvelope(0.0, 0.0, release, 1.0, clock) 18 | voice = oscillator * envelope 19 | 20 | pan = SineLFO(0.1667, -1.0, 1.0) 21 | output = StereoPanner(voice, pan) 22 | output.play() 23 | graph.wait() -------------------------------------------------------------------------------- /docs/library/processors/panning/stereowidth/example-0.py: -------------------------------------------------------------------------------- 1 | from signalflow import * 2 | graph = AudioGraph() 3 | 4 | #------------------------------------------------------------------------------- 5 | # Using StereoWidth to continuously alter the width of a stereo signal. 6 | #------------------------------------------------------------------------------- 7 | low = TriangleOscillator(220) 8 | high = TriangleOscillator(660) 9 | panned = ChannelArray([low, high]) 10 | width = StereoWidth(panned, TriangleLFO(0.5, 0, 1)) * 0.3 11 | width.play() 12 | graph.wait() -------------------------------------------------------------------------------- /docs/library/processors/smooth/index.md: -------------------------------------------------------------------------------- 1 | title: Smooth node documentation 2 | description: Smooth: Smooth the input with a given smoothing coefficient. When `smooth` = 0, applies no smoothing. 3 | 4 | [Reference library](../../index.md) > [Processors](../index.md) > [Smooth](index.md) 5 | 6 | # Smooth 7 | 8 | ```python 9 | Smooth(input=None, smooth=0.99) 10 | ``` 11 | 12 | Smooth the input with a given smoothing coefficient. When `smooth` = 0, applies no smoothing. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/processors/wetdry/index.md: -------------------------------------------------------------------------------- 1 | title: WetDry node documentation 2 | description: WetDry: Takes `wet` and `dry` inputs, and outputs a mix determined by `wetness`. 3 | 4 | [Reference library](../../index.md) > [Processors](../index.md) > [WetDry](index.md) 5 | 6 | # WetDry 7 | 8 | ```python 9 | WetDry(dry_input=None, wet_input=None, wetness=0.0) 10 | ``` 11 | 12 | Takes `wet` and `dry` inputs, and outputs a mix determined by `wetness`. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/processors/wrap/index.md: -------------------------------------------------------------------------------- 1 | title: Wrap node documentation 2 | description: Wrap: Wrap the input beyond `min`/`max`. 3 | 4 | [Reference library](../../index.md) > [Processors](../index.md) > [Wrap](index.md) 5 | 6 | # Wrap 7 | 8 | ```python 9 | Wrap(input=None, min=-1.0, max=1.0) 10 | ``` 11 | 12 | Wrap the input beyond `min`/`max`. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/sequencing/counter/index.md: -------------------------------------------------------------------------------- 1 | title: Counter node documentation 2 | description: Counter: Count upwards from `min` to `max`, driven by `clock`. 3 | 4 | [Reference library](../../index.md) > [Sequencing](../index.md) > [Counter](index.md) 5 | 6 | # Counter 7 | 8 | ```python 9 | Counter(clock=0, min=0, max=2147483647) 10 | ``` 11 | 12 | Count upwards from `min` to `max`, driven by `clock`. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/sequencing/euclidean/index.md: -------------------------------------------------------------------------------- 1 | title: Euclidean node documentation 2 | description: Euclidean: Euclidean rhythm as described by Toussaint, with `sequence_length` (n) and `num_events` (k), driven by `clock`. 3 | 4 | [Reference library](../../index.md) > [Sequencing](../index.md) > [Euclidean](index.md) 5 | 6 | # Euclidean 7 | 8 | ```python 9 | Euclidean(clock=0, sequence_length=0, num_events=0) 10 | ``` 11 | 12 | Euclidean rhythm as described by Toussaint, with `sequence_length` (n) and `num_events` (k), driven by `clock`. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/sequencing/flipflop/index.md: -------------------------------------------------------------------------------- 1 | title: FlipFlop node documentation 2 | description: FlipFlop: Flips from 0/1 on each `clock`. 3 | 4 | [Reference library](../../index.md) > [Sequencing](../index.md) > [FlipFlop](index.md) 5 | 6 | # FlipFlop 7 | 8 | ```python 9 | FlipFlop(clock=0) 10 | ``` 11 | 12 | Flips from 0/1 on each `clock`. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/sequencing/impulsesequence/index.md: -------------------------------------------------------------------------------- 1 | title: ImpulseSequence node documentation 2 | description: ImpulseSequence: Each time a `clock` or trigger is received, outputs the next value in `sequence`. At all other times, outputs zero. 3 | 4 | [Reference library](../../index.md) > [Sequencing](../index.md) > [ImpulseSequence](index.md) 5 | 6 | # ImpulseSequence 7 | 8 | ```python 9 | ImpulseSequence(sequence=std::vector ( ), clock=None) 10 | ``` 11 | 12 | Each time a `clock` or trigger is received, outputs the next value in `sequence`. At all other times, outputs zero. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/sequencing/index/index.md: -------------------------------------------------------------------------------- 1 | title: Index node documentation 2 | description: Index: Outputs the value in `list` corresponding to `index`. 3 | 4 | [Reference library](../../index.md) > [Sequencing](../index.md) > [Index](index.md) 5 | 6 | # Index 7 | 8 | ```python 9 | Index(list={}, index=0) 10 | ``` 11 | 12 | Outputs the value in `list` corresponding to `index`. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/sequencing/latch/index.md: -------------------------------------------------------------------------------- 1 | title: Latch node documentation 2 | description: Latch: Initially outputs 0. When a trigger is received at `set`, outputs 1. When a trigger is subsequently received at `reset`, outputs 0, until the next `set`. 3 | 4 | [Reference library](../../index.md) > [Sequencing](../index.md) > [Latch](index.md) 5 | 6 | # Latch 7 | 8 | ```python 9 | Latch(set=0, reset=0) 10 | ``` 11 | 12 | Initially outputs 0. When a trigger is received at `set`, outputs 1. When a trigger is subsequently received at `reset`, outputs 0, until the next `set`. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/sequencing/sequence/example-0.py: -------------------------------------------------------------------------------- 1 | from signalflow import * 2 | graph = AudioGraph() 3 | 4 | #------------------------------------------------------------------------------- 5 | # Creating a sequence using the MIDI note values of a C Major scale, starting on 6 | # middle C. 7 | #------------------------------------------------------------------------------- 8 | clock = Impulse(2.0) 9 | sequence = Sequence([ 60, 62, 64, 65, 67, 69, 71, 72 ], clock) 10 | frequency = MidiNoteToFrequency(sequence) 11 | oscillator = TriangleOscillator(frequency) 12 | oscillator.play() 13 | graph.wait() -------------------------------------------------------------------------------- /docs/library/sequencing/triggermult/index.md: -------------------------------------------------------------------------------- 1 | title: TriggerMult node documentation 2 | description: TriggerMult: Distribute any triggers to all output nodes. 3 | 4 | [Reference library](../../index.md) > [Sequencing](../index.md) > [TriggerMult](index.md) 5 | 6 | # TriggerMult 7 | 8 | ```python 9 | TriggerMult(a=0) 10 | ``` 11 | 12 | Distribute any triggers to all output nodes. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/sequencing/triggerroundrobin/index.md: -------------------------------------------------------------------------------- 1 | title: TriggerRoundRobin node documentation 2 | description: TriggerRoundRobin: Relay trigger() events to a single node from the list of connected outputs, with `direction` determining the direction: 1 (or above) = move forwards by N, -1 = move backwards by N, 0 = stationary. 3 | 4 | [Reference library](../../index.md) > [Sequencing](../index.md) > [TriggerRoundRobin](index.md) 5 | 6 | # TriggerRoundRobin 7 | 8 | ```python 9 | TriggerRoundRobin(direction=1) 10 | ``` 11 | 12 | Relay trigger() events to a single node from the list of connected outputs, with `direction` determining the direction: 1 (or above) = move forwards by N, -1 = move backwards by N, 0 = stationary. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/stochastic/logistic/index.md: -------------------------------------------------------------------------------- 1 | title: Logistic node documentation 2 | description: Logistic: Logistic noise. 3 | 4 | [Reference library](../../index.md) > [Stochastic](../index.md) > [Logistic](index.md) 5 | 6 | # Logistic 7 | 8 | ```python 9 | Logistic(chaos=3.7, frequency=0.0) 10 | ``` 11 | 12 | Logistic noise. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/stochastic/pinknoise/index.md: -------------------------------------------------------------------------------- 1 | title: PinkNoise node documentation 2 | description: PinkNoise: Pink noise, with specified low/high cutoffs. 3 | 4 | [Reference library](../../index.md) > [Stochastic](../index.md) > [PinkNoise](index.md) 5 | 6 | # PinkNoise 7 | 8 | ```python 9 | PinkNoise(low_cutoff=20.0, high_cutoff=20000.0, reset=None) 10 | ``` 11 | 12 | Pink noise, with specified low/high cutoffs. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/stochastic/randombrownian/index.md: -------------------------------------------------------------------------------- 1 | title: RandomBrownian node documentation 2 | description: RandomBrownian: Outputs Brownian noise between min/max, with a mean change of delta between samples. If a clock is passed, only generates a new value on a clock tick. To generate and hold an unchanging random value, pass clock=0. 3 | 4 | [Reference library](../../index.md) > [Stochastic](../index.md) > [RandomBrownian](index.md) 5 | 6 | # RandomBrownian 7 | 8 | ```python 9 | RandomBrownian(min=-1.0, max=1.0, delta=0.01, clock=None, reset=None) 10 | ``` 11 | 12 | Outputs Brownian noise between min/max, with a mean change of delta between samples. If a clock is passed, only generates a new value on a clock tick. To generate and hold an unchanging random value, pass clock=0. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/stochastic/randomchoice/index.md: -------------------------------------------------------------------------------- 1 | title: RandomChoice node documentation 2 | description: RandomChoice: Pick a random value from the given array. If a clock is passed, only picks a new value on a clock tick. To generate and hold an unchanging random value, pass clock=0. 3 | 4 | [Reference library](../../index.md) > [Stochastic](../index.md) > [RandomChoice](index.md) 5 | 6 | # RandomChoice 7 | 8 | ```python 9 | RandomChoice(values=std::vector ( ), clock=None, reset=None) 10 | ``` 11 | 12 | Pick a random value from the given array. If a clock is passed, only picks a new value on a clock tick. To generate and hold an unchanging random value, pass clock=0. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/stochastic/randomcoin/index.md: -------------------------------------------------------------------------------- 1 | title: RandomCoin node documentation 2 | description: RandomCoin: Flip a coin with the given probability. If a clock is passed, only picks a new value on a clock tick. To generate and hold an unchanging random value, pass clock=0. 3 | 4 | [Reference library](../../index.md) > [Stochastic](../index.md) > [RandomCoin](index.md) 5 | 6 | # RandomCoin 7 | 8 | ```python 9 | RandomCoin(probability=0.5, clock=None, reset=None) 10 | ``` 11 | 12 | Flip a coin with the given probability. If a clock is passed, only picks a new value on a clock tick. To generate and hold an unchanging random value, pass clock=0. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/stochastic/randomexponential/index.md: -------------------------------------------------------------------------------- 1 | title: RandomExponential node documentation 2 | description: RandomExponential: Generate an random exponential value between min/max. If a clock is passed, only picks a new value on a clock tick. To generate and hold an unchanging random value, pass clock=0. 3 | 4 | [Reference library](../../index.md) > [Stochastic](../index.md) > [RandomExponential](index.md) 5 | 6 | # RandomExponential 7 | 8 | ```python 9 | RandomExponential(min=0.001, max=1.0, clock=None, reset=None) 10 | ``` 11 | 12 | Generate an random exponential value between min/max. If a clock is passed, only picks a new value on a clock tick. To generate and hold an unchanging random value, pass clock=0. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/stochastic/randomexponentialdist/index.md: -------------------------------------------------------------------------------- 1 | title: RandomExponentialDist node documentation 2 | description: RandomExponentialDist: Generate an random value following the exponential distribution. If a clock is passed, only picks a new value on a clock tick. To generate and hold an unchanging random value, pass clock=0. 3 | 4 | [Reference library](../../index.md) > [Stochastic](../index.md) > [RandomExponentialDist](index.md) 5 | 6 | # RandomExponentialDist 7 | 8 | ```python 9 | RandomExponentialDist(scale=0.0, clock=None, reset=None) 10 | ``` 11 | 12 | Generate an random value following the exponential distribution. If a clock is passed, only picks a new value on a clock tick. To generate and hold an unchanging random value, pass clock=0. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/stochastic/randomgaussian/index.md: -------------------------------------------------------------------------------- 1 | title: RandomGaussian node documentation 2 | description: RandomGaussian: Generate an random Gaussian value, with given mean and sigma. If a clock is passed, only picks a new value on a clock tick. To generate and hold an unchanging random value, pass clock=0. 3 | 4 | [Reference library](../../index.md) > [Stochastic](../index.md) > [RandomGaussian](index.md) 5 | 6 | # RandomGaussian 7 | 8 | ```python 9 | RandomGaussian(mean=0.0, sigma=0.0, clock=None, reset=None) 10 | ``` 11 | 12 | Generate an random Gaussian value, with given mean and sigma. If a clock is passed, only picks a new value on a clock tick. To generate and hold an unchanging random value, pass clock=0. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/stochastic/randomimpulse/index.md: -------------------------------------------------------------------------------- 1 | title: RandomImpulse node documentation 2 | description: RandomImpulse: Generate random impulses at the given frequency, with either uniform or poisson distribution. 3 | 4 | [Reference library](../../index.md) > [Stochastic](../index.md) > [RandomImpulse](index.md) 5 | 6 | # RandomImpulse 7 | 8 | ```python 9 | RandomImpulse(frequency=1.0, distribution=SIGNALFLOW_EVENT_DISTRIBUTION_UNIFORM, reset=None) 10 | ``` 11 | 12 | Generate random impulses at the given frequency, with either uniform or poisson distribution. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/stochastic/randomuniform/index.md: -------------------------------------------------------------------------------- 1 | title: RandomUniform node documentation 2 | description: RandomUniform: Generates a uniformly random value between min/max. If a clock is passed, only picks a new value on a clock tick. To generate and hold an unchanging random value, pass clock=0. 3 | 4 | [Reference library](../../index.md) > [Stochastic](../index.md) > [RandomUniform](index.md) 5 | 6 | # RandomUniform 7 | 8 | ```python 9 | RandomUniform(min=0.0, max=1.0, clock=None, reset=None) 10 | ``` 11 | 12 | Generates a uniformly random value between min/max. If a clock is passed, only picks a new value on a clock tick. To generate and hold an unchanging random value, pass clock=0. 13 | 14 | -------------------------------------------------------------------------------- /docs/library/stochastic/whitenoise/example-0.py: -------------------------------------------------------------------------------- 1 | from signalflow import * 2 | graph = AudioGraph() 3 | 4 | #------------------------------------------------------------------------------- 5 | # Using white noise to control the pitch of an oscillator. 6 | # A new pitch is determined once every second. Interpolation is turned off so 7 | # that the oscillator jumps to the new pitch instead of smoothly moving to it. 8 | # Random interval is turned off so that pitch changes occur at a regular rate. 9 | #------------------------------------------------------------------------------- 10 | frequency = WhiteNoise( frequency=1, 11 | min=100, 12 | max=1000, 13 | interpolate=False, 14 | random_interval=False) 15 | oscillator = SineOscillator(frequency) 16 | output = StereoPanner(oscillator) * 0.5 17 | output.play() 18 | graph.wait() -------------------------------------------------------------------------------- /docs/library/stochastic/whitenoise/example-1.py: -------------------------------------------------------------------------------- 1 | from signalflow import * 2 | graph = AudioGraph() 3 | 4 | #------------------------------------------------------------------------------- 5 | # Using white noise to simulate the sound of wind. 6 | # White noise is generated at audio rate and passed into a band-pass filter. 7 | # The cutoff of the filter is controlled by another white noise generator, which 8 | # generates a new value between 100 and 300 at randomly-spaced intervals every 9 | # second, and smoothly interpolates between these values. 10 | #------------------------------------------------------------------------------- 11 | noise = WhiteNoise() 12 | cutoff = WhiteNoise(1, 100, 300, True, True) 13 | filtered = SVFilter(input=noise, 14 | filter_type= "band_pass", 15 | cutoff=cutoff, 16 | resonance=0.8) 17 | output = StereoPanner(filtered) * 0.5 18 | output.play() 19 | graph.wait() -------------------------------------------------------------------------------- /docs/license.md: -------------------------------------------------------------------------------- 1 | # License 2 | 3 | ## Within Python 4 | 5 | Use of the SignalFlow library with a Python interpreter, script or notebook is licensed under the free and permissive [MIT License](https://opensource.org/license/mit). 6 | 7 | This means that you are welcome to use it for any purpose, including commercial usage, but must include the copyright notice above in any copies or derivative works. 8 | 9 | ## Embedding SignalFlow within a binary 10 | 11 | Use of SignalFlow or its components outside of a Python environment (for example, embedded within a binary object) is subject to a separate agreement. Please [get in touch](https://danieljohnjones.com/contact/) to learn more. 12 | 13 | Please do [let me know](https://danieljohnjones.com/contact/) what you use it for! 14 | 15 | --- -------------------------------------------------------------------------------- /docs/node/developing.md: -------------------------------------------------------------------------------- 1 | # Nodes 2 | 3 | ## Developing new Node classes 4 | 5 | See [CONTRIBUTING.md](https://github.com/ideoforms/signalflow/blob/master/CONTRIBUTING.md) -------------------------------------------------------------------------------- /docs/patch/auto-free.md: -------------------------------------------------------------------------------- 1 | # Patch 2 | 3 | ## Auto-free and memory management 4 | 5 | Auto-free. 6 | 7 | --- 8 | -------------------------------------------------------------------------------- /docs/patch/exporting.md: -------------------------------------------------------------------------------- 1 | # Patch 2 | 3 | ## Exporting and importing patches 4 | 5 | A Patch can be exported or imported. 6 | 7 | --- 8 | 9 | [→ Next: Auto-free and memory management](auto-free.md) 10 | -------------------------------------------------------------------------------- /docs/patch/operators.md: -------------------------------------------------------------------------------- 1 | # Patch 2 | 3 | ## Operators 4 | 5 | The output of a Patch can be amplified, attenuated, combined, modulated and compared using Python operators, in much the same way as [Node](../node/operators.md): 6 | 7 | ```python 8 | patch = Patch(patch_spec) 9 | output = patch * 0.5 10 | ``` 11 | 12 | For a full list of the operators that can be applied to a `Patch`, see [Node operators](../node/operators.md). 13 | 14 | --- 15 | 16 | [→ Next: Patch properties](properties.md) 17 | -------------------------------------------------------------------------------- /docs/patch/properties.md: -------------------------------------------------------------------------------- 1 | # Patch 2 | 3 | ## Patch properties 4 | 5 | | Property | Type | Description | 6 | |----------|------|-----------------------------------------------------------| 7 | | nodes | list | A list of all of the Node objects that make up this Patch | 8 | | inputs | dict | A dict of key-value pairs corresponding to all of the (audio rate) inputs within the Patch | 9 | | state | int | The Patch's current playback state, which can be `SIGNALFLOW_PATCH_STATE_ACTIVE` or `SIGNALFLOW_PATCH_STATE_STOPPED`. | 10 | | graph | AudioGraph | A reference to the AudioGraph that the Patch is part of | 11 | 12 | --- 13 | 14 | [→ Next: Exporting and importing patches](exporting.md) 15 | -------------------------------------------------------------------------------- /docs/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Sitemap: https://signalflow.dev/sitemap.xml 3 | -------------------------------------------------------------------------------- /docs/troubleshooting/index.md: -------------------------------------------------------------------------------- 1 | # Troubleshooting 2 | 3 | ## Exceptions 4 | 5 | - [InsufficientBufferSizeException](insufficient_buffer_size_exception.md) 6 | - [DeviceNotFoundException](device_not_found_exception.md) 7 | - [NodeNotPlayingException](node_not_playing_exception.md) 8 | - [NodeAlreadyPlayingException](node_already_playing_exception.md) 9 | -------------------------------------------------------------------------------- /docs/troubleshooting/insufficient_buffer_size_exception.md: -------------------------------------------------------------------------------- 1 | # Troubleshooting: InsufficientBufferSizeException 2 | 3 | ## Example 4 | 5 | ``` 6 | Exception in AudioGraph: Node audioout-soundio cannot render because output 7 | buffer size is insufficient (8192 samples requested, buffer size = 2048). 8 | Increase the buffer size. 9 | ``` 10 | 11 | ## Description 12 | 13 | This exception occurs because the audio hardware is requesting more samples than a node has currently allocated. This allocation is controlled by SignalFlow's `output_buffer_size` config parameter. 14 | 15 | ## Solution 16 | 17 | Increase the `output_buffer_size` within your [SignalFlow configuration](../graph/config.md). This can be done by adding the below to your `~/.signalflow/config` file: 18 | 19 | ``` 20 | [audio] 21 | output_buffer_size = 8192 22 | ``` 23 | -------------------------------------------------------------------------------- /docs/troubleshooting/node_not_playing_exception.md: -------------------------------------------------------------------------------- 1 | # Troubleshooting: NodeNotPlayingException 2 | 3 | ## Example 4 | 5 | ``` 6 | signalflow.NodeNotPlayingException: Node cannot be played as it is already 7 | playing 8 | ``` 9 | 10 | ## Description 11 | 12 | This exception occurs when `stop()` is called on a `Node` object that has not yet been played. 13 | 14 | ## Solution 15 | 16 | Calling `stop()` on a `Node` object that is not connected to an output is invalid, and should be avoided. 17 | 18 | If you want to check whether a `Node` is connected before stopping it, you can check the boolean `is_playing` property. -------------------------------------------------------------------------------- /examples/audio/gliss.aif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ideoforms/signalflow/b5fc3c931995ddabe8bc963ee00a5c02ea7888c3/examples/audio/gliss.aif -------------------------------------------------------------------------------- /examples/audio/stereo-count.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ideoforms/signalflow/b5fc3c931995ddabe8bc963ee00a5c02ea7888c3/examples/audio/stereo-count.wav -------------------------------------------------------------------------------- /examples/patches/sine.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sine", 3 | "nodes" : [ 4 | { 5 | "node" : "sine", 6 | "id" : 0, 7 | "is_output" : true, 8 | "inputs": { 9 | "frequency" : 60 10 | } 11 | } 12 | ], 13 | "inputs": [ 14 | { 15 | "patch_input_name": "frequency", 16 | "node_input_name": "frequency", 17 | "node_id": 0 18 | } 19 | ], 20 | "buffer_inputs": [] 21 | } 22 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools", "wheel", "setuptools_scm", "cmake", "scikit-build"] 3 | build-backend = "setuptools.build_meta" 4 | -------------------------------------------------------------------------------- /source/include/signalflow/core/graph-monitor.h: -------------------------------------------------------------------------------- 1 | #include "signalflow/core/graph.h" 2 | 3 | #include 4 | #include 5 | 6 | namespace signalflow 7 | { 8 | 9 | class AudioGraphMonitor 10 | { 11 | public: 12 | AudioGraphMonitor(AudioGraphRef graph, float frequency); 13 | 14 | void start(); 15 | void stop(); 16 | void set_frequency(float frequency); 17 | bool is_running(); 18 | 19 | private: 20 | void run_thread(); 21 | AudioGraphRef graph; 22 | float frequency; 23 | bool running; 24 | std::thread thread; 25 | }; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /source/include/signalflow/core/random.h: -------------------------------------------------------------------------------- 1 | /*--------------------------------------------------------------------* 2 | * random.h: Random number generation 3 | *--------------------------------------------------------------------*/ 4 | 5 | #pragma once 6 | 7 | namespace signalflow 8 | { 9 | 10 | void random_init(); 11 | void random_seed(long seed); 12 | 13 | double random_gaussian(double mean, double sd); 14 | double random_gaussian(); 15 | double random_uniform(); 16 | double random_uniform(double from, double to); 17 | unsigned long random_integer(unsigned long from, unsigned long to); 18 | bool random_coin(double limit); 19 | void random_shuffle(int *values, int count); 20 | float random_exponential(float from, float to); 21 | float random_exponential_dist(float mu); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /source/include/signalflow/core/renderer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/core/graph.h" 4 | #include "signalflow/node/node.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | namespace signalflow 11 | { 12 | 13 | class GraphRenderer 14 | { 15 | public: 16 | GraphRenderer(); 17 | void render(AudioGraphRef graph); 18 | void render_node(NodeRef node); 19 | 20 | std::stringstream nodestream; 21 | std::stringstream edgestream; 22 | std::set rendered_nodes; 23 | }; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /source/include/signalflow/core/version.h: -------------------------------------------------------------------------------- 1 | #define SIGNALFLOW_BUILD 1504 2 | -------------------------------------------------------------------------------- /source/include/signalflow/node/analysis/cross-correlate.h: -------------------------------------------------------------------------------- 1 | #include "signalflow/node/node.h" 2 | 3 | namespace signalflow 4 | { 5 | 6 | /**--------------------------------------------------------------------------------* 7 | * Outputs the cross-correlation of the input signal with the given buffer. 8 | * If hop_size is zero, calculates the cross-correlation every sample. 9 | *---------------------------------------------------------------------------------*/ 10 | class CrossCorrelate : public UnaryOpNode 11 | { 12 | public: 13 | CrossCorrelate(NodeRef input = nullptr, BufferRef buffer = nullptr, int hop_size = 0); 14 | 15 | BufferRef buffer; 16 | int hop_size = 0; 17 | 18 | virtual void process(Buffer &out, int num_frames); 19 | 20 | private: 21 | SampleRingBuffer *ring_buffer; 22 | }; 23 | 24 | REGISTER(CrossCorrelate, "cross-correlate") 25 | } 26 | -------------------------------------------------------------------------------- /source/include/signalflow/node/analysis/nearest-neighbour.h: -------------------------------------------------------------------------------- 1 | #include "signalflow/core/kdtree.h" 2 | #include "signalflow/node/node.h" 3 | 4 | namespace signalflow 5 | { 6 | /**--------------------------------------------------------------------------------* 7 | * Nearest Neighbour. 8 | *---------------------------------------------------------------------------------*/ 9 | class NearestNeighbour : public Node 10 | { 11 | public: 12 | NearestNeighbour(BufferRef buffer = nullptr, NodeRef target = 0.0); 13 | 14 | virtual void set_buffer(std::string name, BufferRef buffer); 15 | virtual void process(Buffer &out, int num_frames); 16 | 17 | private: 18 | BufferRef buffer; 19 | NodeRef target; 20 | KDTree *kdtree; 21 | }; 22 | 23 | REGISTER(NearestNeighbour, "nearest-neighbour") 24 | } 25 | -------------------------------------------------------------------------------- /source/include/signalflow/node/buffer/feedback-buffer-reader.h: -------------------------------------------------------------------------------- 1 | #include "signalflow/buffer/buffer.h" 2 | #include "signalflow/core/constants.h" 3 | #include "signalflow/node/node.h" 4 | 5 | namespace signalflow 6 | { 7 | 8 | /**--------------------------------------------------------------------------------* 9 | * Counterpart to FeedbackBufferWriter. 10 | *---------------------------------------------------------------------------------*/ 11 | class FeedbackBufferReader : public Node 12 | { 13 | public: 14 | FeedbackBufferReader(BufferRef buffer = nullptr); 15 | 16 | virtual void set_buffer(std::string, BufferRef buffer); 17 | virtual void process(Buffer &out, int num_frames); 18 | 19 | private: 20 | BufferRef buffer; 21 | double phase; 22 | double rate_scale_factor; 23 | }; 24 | 25 | REGISTER(FeedbackBufferReader, "feedback-buffer-reader") 26 | } 27 | -------------------------------------------------------------------------------- /source/include/signalflow/node/buffer/feedback-buffer-writer.h: -------------------------------------------------------------------------------- 1 | #include "signalflow/buffer/buffer.h" 2 | #include "signalflow/core/constants.h" 3 | #include "signalflow/node/node.h" 4 | 5 | namespace signalflow 6 | { 7 | 8 | /**--------------------------------------------------------------------------------* 9 | * Counterpart to FeedbackBufferReader. 10 | *---------------------------------------------------------------------------------*/ 11 | class FeedbackBufferWriter : public Node 12 | { 13 | public: 14 | FeedbackBufferWriter(BufferRef buffer = nullptr, NodeRef input = 0.0, NodeRef delay_time = 0.1); 15 | virtual void process(Buffer &out, int num_frames); 16 | 17 | private: 18 | BufferRef buffer; 19 | NodeRef input; 20 | NodeRef delay_time; 21 | float phase; 22 | }; 23 | 24 | REGISTER(FeedbackBufferWriter, "feedback-buffer-writer") 25 | } 26 | -------------------------------------------------------------------------------- /source/include/signalflow/node/envelope/accumulator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/core/constants.h" 4 | #include "signalflow/node/node.h" 5 | 6 | namespace signalflow 7 | { 8 | 9 | /**--------------------------------------------------------------------------------* 10 | * Accumulator with decay. 11 | *---------------------------------------------------------------------------------*/ 12 | class Accumulator : public Node 13 | { 14 | public: 15 | Accumulator(NodeRef strike_force = 0.5, NodeRef decay_coefficient = 0.9999, NodeRef trigger = nullptr); 16 | virtual void trigger(std::string name = SIGNALFLOW_DEFAULT_TRIGGER, float value = SIGNALFLOW_NULL_FLOAT) override; 17 | virtual void process(Buffer &out, int num_frames) override; 18 | 19 | private: 20 | NodeRef strike_force; 21 | NodeRef decay_coefficient; 22 | NodeRef _trigger; 23 | double current_value; 24 | }; 25 | 26 | REGISTER(Accumulator, "accumulator") 27 | 28 | } 29 | -------------------------------------------------------------------------------- /source/include/signalflow/node/envelope/detect-silence.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/core/constants.h" 4 | #include "signalflow/node/node.h" 5 | 6 | namespace signalflow 7 | { 8 | 9 | /**--------------------------------------------------------------------------------* 10 | * Detects blocks of silence below the threshold value. Used as an auto-free 11 | * node to terminate a Patch after processing is complete. 12 | *---------------------------------------------------------------------------------*/ 13 | class DetectSilence : public UnaryOpNode 14 | { 15 | public: 16 | DetectSilence(NodeRef input = nullptr, NodeRef threshold = 0.00001); 17 | virtual void process(Buffer &out, int num_frames) override; 18 | 19 | private: 20 | NodeRef threshold; 21 | }; 22 | 23 | REGISTER(DetectSilence, "detect-silence") 24 | 25 | } 26 | -------------------------------------------------------------------------------- /source/include/signalflow/node/envelope/rect.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/core/constants.h" 4 | #include "signalflow/node/node.h" 5 | 6 | namespace signalflow 7 | { 8 | 9 | /**--------------------------------------------------------------------------------* 10 | * Rectangular envelope with the given sustain duration. 11 | *---------------------------------------------------------------------------------*/ 12 | class RectangularEnvelope : public Node 13 | { 14 | public: 15 | RectangularEnvelope(NodeRef sustain_duration = 1.0, NodeRef clock = nullptr); 16 | 17 | virtual void trigger(std::string name = SIGNALFLOW_DEFAULT_TRIGGER, float value = 1.0) override; 18 | virtual void process(Buffer &out, int num_frames) override; 19 | 20 | private: 21 | NodeRef sustain_duration; 22 | NodeRef clock; 23 | 24 | std::vector phase; 25 | }; 26 | 27 | REGISTER(RectangularEnvelope, "rectangular-envelope") 28 | 29 | } 30 | -------------------------------------------------------------------------------- /source/include/signalflow/node/fft/continuous-pv.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/node/fft/fftnode.h" 4 | 5 | namespace signalflow 6 | { 7 | 8 | /**--------------------------------------------------------------------------------* 9 | * Continuous phase vocoder. 10 | * Requires an FFT* input. 11 | *---------------------------------------------------------------------------------*/ 12 | class FFTContinuousPhaseVocoder : public FFTNode 13 | { 14 | public: 15 | FFTContinuousPhaseVocoder(NodeRef input = nullptr, float rate = 1.0); 16 | 17 | virtual void process(Buffer &out, int num_frames); 18 | virtual void trigger(std::string name, float value); 19 | 20 | sample *magnitude_buffer; 21 | sample *phase_buffer; 22 | sample *phase_deriv; 23 | 24 | NodeRef input; 25 | float rate; 26 | 27 | bool prefilled_fft_buffer; 28 | }; 29 | 30 | REGISTER(FFTContinuousPhaseVocoder, "fft-continuous-pv") 31 | } 32 | -------------------------------------------------------------------------------- /source/include/signalflow/node/fft/fft-contrast.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/node/fft/fftnode.h" 4 | 5 | namespace signalflow 6 | { 7 | 8 | /**--------------------------------------------------------------------------------* 9 | * FFT Contrast. 10 | * Requires an FFT* input. 11 | *---------------------------------------------------------------------------------*/ 12 | class FFTContrast : public FFTOpNode 13 | { 14 | public: 15 | FFTContrast(NodeRef input = 0, NodeRef contrast = 1); 16 | virtual void process(Buffer &out, int num_frames); 17 | 18 | private: 19 | NodeRef contrast; 20 | float mags[SIGNALFLOW_MAX_FFT_SIZE / 2]; 21 | }; 22 | 23 | REGISTER(FFTContrast, "fft-contrast") 24 | 25 | } 26 | -------------------------------------------------------------------------------- /source/include/signalflow/node/fft/fft-cross-fade.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/node/fft/fftnode.h" 4 | 5 | namespace signalflow 6 | { 7 | 8 | /**--------------------------------------------------------------------------------* 9 | * FFT FFTCrossFade. 10 | * Requires two FFT* inputs. 11 | *---------------------------------------------------------------------------------*/ 12 | class FFTCrossFade : public FFTOpNode 13 | { 14 | public: 15 | FFTCrossFade(NodeRef inputA = 0, NodeRef inputB = 0, NodeRef crossfade = 0.0); 16 | virtual void process(Buffer &out, int num_frames); 17 | 18 | private: 19 | NodeRef inputB; 20 | NodeRef crossfade; 21 | }; 22 | 23 | REGISTER(FFTCrossFade, "fft-cross-fade") 24 | 25 | } 26 | -------------------------------------------------------------------------------- /source/include/signalflow/node/fft/fft-lfo.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/node/fft/fftnode.h" 4 | 5 | namespace signalflow 6 | { 7 | 8 | /**--------------------------------------------------------------------------------* 9 | * FFT LFO. 10 | * Requires an FFT* input. 11 | *---------------------------------------------------------------------------------*/ 12 | class FFTLFO : public FFTOpNode 13 | { 14 | public: 15 | FFTLFO(NodeRef input = 0, NodeRef frequency = 1.0, NodeRef spectral_cycles = 1.0); 16 | virtual void process(Buffer &out, int num_frames); 17 | 18 | private: 19 | NodeRef frequency; 20 | NodeRef spectral_cycles; 21 | double phase; 22 | }; 23 | 24 | REGISTER(FFTLFO, "fft-lfo") 25 | 26 | } 27 | -------------------------------------------------------------------------------- /source/include/signalflow/node/fft/fft-magnitude-phase-array.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/node/fft/fftnode.h" 4 | 5 | namespace signalflow 6 | { 7 | 8 | /**--------------------------------------------------------------------------------* 9 | * Fixed mag/phase array. 10 | *---------------------------------------------------------------------------------*/ 11 | class FFTMagnitudePhaseArray : public FFTOpNode 12 | { 13 | public: 14 | FFTMagnitudePhaseArray(NodeRef input = 0, 15 | std::vector magnitudes = {}, 16 | std::vector phases = {}); 17 | virtual void process(Buffer &out, int num_frames); 18 | 19 | void set_magnitudes(std::vector &magnitudes); 20 | void set_phases(std::vector &phases); 21 | }; 22 | 23 | REGISTER(FFTMagnitudePhaseArray, "fft-magnitude-phase-array") 24 | 25 | } 26 | -------------------------------------------------------------------------------- /source/include/signalflow/node/fft/fft-random-phase.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/node/fft/fftnode.h" 4 | 5 | namespace signalflow 6 | { 7 | 8 | /**--------------------------------------------------------------------------------* 9 | * Randomise phase values. 10 | *---------------------------------------------------------------------------------*/ 11 | class FFTRandomPhase : public FFTOpNode 12 | { 13 | public: 14 | FFTRandomPhase(NodeRef input = 0, NodeRef level = 1.0); 15 | virtual void process(Buffer &out, int num_frames); 16 | 17 | protected: 18 | NodeRef level; 19 | }; 20 | 21 | REGISTER(FFTRandomPhase, "fft-random-phase") 22 | 23 | } 24 | -------------------------------------------------------------------------------- /source/include/signalflow/node/fft/fft-scale-magnitudes.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/node/fft/fftnode.h" 4 | 5 | namespace signalflow 6 | { 7 | 8 | /**--------------------------------------------------------------------------------* 9 | * Randomise phase values. 10 | *---------------------------------------------------------------------------------*/ 11 | class FFTScaleMagnitudes : public FFTOpNode 12 | { 13 | public: 14 | FFTScaleMagnitudes(NodeRef input = 0, std::vector scale = {}); 15 | virtual void process(Buffer &out, int num_frames); 16 | 17 | protected: 18 | std::vector scale; 19 | }; 20 | 21 | REGISTER(FFTScaleMagnitudes, "fft-scale-magnitudes") 22 | 23 | } 24 | -------------------------------------------------------------------------------- /source/include/signalflow/node/fft/fft-transform.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/node/fft/fftnode.h" 4 | 5 | namespace signalflow 6 | { 7 | 8 | /**--------------------------------------------------------------------------------* 9 | * Transforms the FFT magnitude spectrum in the X axis. 10 | * Requires an FFT* input. 11 | *---------------------------------------------------------------------------------*/ 12 | class FFTTransform : public FFTOpNode 13 | { 14 | public: 15 | FFTTransform(NodeRef input = 0, NodeRef flip = 0, NodeRef rotate = 0); 16 | virtual void process(Buffer &out, int num_frames); 17 | 18 | private: 19 | NodeRef flip; 20 | NodeRef rotate; 21 | }; 22 | 23 | REGISTER(FFTTransform, "fft-transform") 24 | 25 | } 26 | -------------------------------------------------------------------------------- /source/include/signalflow/node/fft/fftnode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/node/node.h" 4 | 5 | namespace signalflow 6 | { 7 | class FFTNode : public Node 8 | { 9 | public: 10 | FFTNode(int fft_size, int hop_size, int window_size, bool do_window); 11 | ~FFTNode(); 12 | 13 | std::vector get_magnitudes(); 14 | std::vector get_phases(); 15 | 16 | sample **magnitudes; 17 | sample **phases; 18 | int fft_size; 19 | int hop_size; 20 | int num_bins; 21 | int num_hops; 22 | int window_size; 23 | bool do_window; 24 | }; 25 | 26 | class FFTOpNode : public FFTNode 27 | { 28 | public: 29 | FFTOpNode(NodeRef input = nullptr); 30 | 31 | virtual void set_input(std::string name, const NodeRef &node); 32 | 33 | NodeRef input; 34 | }; 35 | } 36 | -------------------------------------------------------------------------------- /source/include/signalflow/node/fft/find-peaks.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/node/fft/fftnode.h" 4 | 5 | namespace signalflow 6 | { 7 | 8 | /**--------------------------------------------------------------------------------* 9 | * Find peaks in the FFT magnitude spectrum. 10 | * Requires an FFT* input. 11 | *---------------------------------------------------------------------------------*/ 12 | class FFTFindPeaks : public FFTOpNode 13 | { 14 | public: 15 | FFTFindPeaks(NodeRef input = 0, 16 | NodeRef prominence = 1, NodeRef threshold = 0.000001, 17 | int count = SIGNALFLOW_MAX_CHANNELS, bool interpolate = true); 18 | virtual void process(Buffer &out, int num_frames); 19 | 20 | NodeRef prominence = nullptr; 21 | NodeRef threshold = nullptr; 22 | int count; 23 | bool interpolate; 24 | }; 25 | 26 | REGISTER(FFTFindPeaks, "fft-find-peaks") 27 | 28 | } 29 | -------------------------------------------------------------------------------- /source/include/signalflow/node/fft/lpf.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/node/fft/fftnode.h" 4 | 5 | namespace signalflow 6 | { 7 | 8 | /**--------------------------------------------------------------------------------* 9 | * FFT-based brick wall low pass filter. 10 | * Requires an FFT* input. 11 | *---------------------------------------------------------------------------------*/ 12 | class FFTLPF : public FFTOpNode 13 | { 14 | public: 15 | FFTLPF(NodeRef input = 0, NodeRef frequency = 2000); 16 | virtual void process(Buffer &out, int num_frames); 17 | 18 | NodeRef frequency; 19 | }; 20 | 21 | REGISTER(FFTLPF, "fft-lpf") 22 | } 23 | -------------------------------------------------------------------------------- /source/include/signalflow/node/fft/noise-gate.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/node/fft/fftnode.h" 4 | 5 | namespace signalflow 6 | { 7 | 8 | /**--------------------------------------------------------------------------------* 9 | * FFT-based noise gate. 10 | * Requires an FFT* input. 11 | *---------------------------------------------------------------------------------*/ 12 | class FFTNoiseGate : public FFTOpNode 13 | { 14 | public: 15 | FFTNoiseGate(NodeRef input = 0, NodeRef threshold = 0.5, NodeRef invert = 0.0); 16 | virtual void process(Buffer &out, int num_frames); 17 | 18 | NodeRef threshold = nullptr; 19 | NodeRef invert = nullptr; 20 | 21 | private: 22 | float mags[SIGNALFLOW_MAX_FFT_SIZE / 2]; 23 | }; 24 | 25 | REGISTER(FFTNoiseGate, "fft_noise_gate") 26 | 27 | } 28 | -------------------------------------------------------------------------------- /source/include/signalflow/node/fft/phase-vocoder.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/node/fft/fftnode.h" 4 | 5 | namespace signalflow 6 | { 7 | 8 | /**--------------------------------------------------------------------------------* 9 | * Phase vocoder. 10 | * Requires an FFT* input. 11 | *---------------------------------------------------------------------------------*/ 12 | class FFTPhaseVocoder : public FFTOpNode 13 | { 14 | public: 15 | FFTPhaseVocoder(NodeRef input = nullptr); 16 | 17 | virtual void trigger(std::string name = SIGNALFLOW_DEFAULT_TRIGGER, float value = 1); 18 | virtual void process(Buffer &out, int num_frames); 19 | 20 | sample *magnitude_buffer; 21 | sample *phase_buffer; 22 | sample *phase_deriv; 23 | bool frozen; 24 | bool just_frozen; 25 | 26 | NodeRef clock = nullptr; 27 | }; 28 | 29 | REGISTER(FFTPhaseVocoder, "fft_phase_vocoder") 30 | } 31 | -------------------------------------------------------------------------------- /source/include/signalflow/node/fft/tonality.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/node/fft/fftnode.h" 4 | 5 | namespace signalflow 6 | { 7 | 8 | /**--------------------------------------------------------------------------------* 9 | * Tonality filter. 10 | * Requires an FFT* input. 11 | *---------------------------------------------------------------------------------*/ 12 | class FFTTonality : public FFTOpNode 13 | { 14 | public: 15 | FFTTonality(NodeRef input = 0, NodeRef level = 0.5, NodeRef smoothing = 0.9); 16 | virtual void process(Buffer &out, int num_frames); 17 | 18 | NodeRef level = nullptr; 19 | NodeRef smoothing = nullptr; 20 | 21 | private: 22 | float mags_smoothed[SIGNALFLOW_MAX_FFT_SIZE / 2]; 23 | }; 24 | 25 | REGISTER(FFTTonality, "fft-tonality") 26 | 27 | } 28 | -------------------------------------------------------------------------------- /source/include/signalflow/node/fft/zero_phase.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/node/fft/fftnode.h" 4 | 5 | namespace signalflow 6 | { 7 | 8 | /**--------------------------------------------------------------------------------* 9 | * Remove phase information from a frequency-domain input. 10 | * Requires an FFT* input. 11 | *---------------------------------------------------------------------------------*/ 12 | class FFTZeroPhase : public UnaryOpNode 13 | { 14 | public: 15 | FFTZeroPhase(NodeRef input = 0); 16 | 17 | virtual void process(Buffer &out, int num_frames); 18 | }; 19 | 20 | REGISTER(FFTZeroPhase, "zero_phase") 21 | } 22 | -------------------------------------------------------------------------------- /source/include/signalflow/node/io/input/abstract.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/core/graph.h" 4 | #include "signalflow/node/node.h" 5 | 6 | #include 7 | 8 | namespace signalflow 9 | { 10 | 11 | class AudioIn_Abstract : public Node 12 | { 13 | public: 14 | AudioIn_Abstract(); 15 | 16 | virtual void init() = 0; 17 | virtual void start() = 0; 18 | virtual void stop() = 0; 19 | virtual void destroy() = 0; 20 | 21 | virtual void process(Buffer &out, int num_samples) = 0; 22 | }; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /source/include/signalflow/node/io/input/miniaudio.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "abstract.h" 6 | 7 | #include "../output/miniaudio-library.h" 8 | #include "signalflow/core/graph.h" 9 | 10 | namespace signalflow 11 | { 12 | 13 | class AudioIn : public AudioIn_Abstract 14 | { 15 | public: 16 | AudioIn(unsigned int num_channels = 1); 17 | virtual ~AudioIn() override; 18 | virtual void init() override; 19 | virtual void start() override; 20 | virtual void stop() override; 21 | virtual void destroy() override; 22 | virtual void process(Buffer &out, int num_samples) override; 23 | 24 | private: 25 | std::string backend_name; 26 | std::string device_name; 27 | ma_context context; 28 | ma_device device; 29 | unsigned int num_channels; 30 | }; 31 | 32 | } 33 | -------------------------------------------------------------------------------- /source/include/signalflow/node/io/output/dummy.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/core/constants.h" 4 | #include "signalflow/node/io/output/abstract.h" 5 | 6 | namespace signalflow 7 | { 8 | 9 | class AudioOut_Dummy : public AudioOut_Abstract 10 | { 11 | public: 12 | AudioOut_Dummy(unsigned int num_channels = 2, 13 | unsigned int sample_rate = SIGNALFLOW_DEFAULT_SAMPLE_RATE, 14 | unsigned int buffer_size = SIGNALFLOW_DEFAULT_BLOCK_SIZE); 15 | 16 | virtual void init() {} 17 | virtual void start() {} 18 | virtual void stop() {} 19 | virtual void destroy() {} 20 | }; 21 | 22 | REGISTER(AudioOut_Dummy, "audioout-dummy") 23 | 24 | } // namespace signalflow 25 | -------------------------------------------------------------------------------- /source/include/signalflow/node/operators/add.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/core/constants.h" 4 | #include "signalflow/node/node.h" 5 | 6 | namespace signalflow 7 | { 8 | 9 | /**--------------------------------------------------------------------------------* 10 | * Add each sample of a to each sample of b. 11 | * Can also be written as a + b 12 | *---------------------------------------------------------------------------------*/ 13 | class Add : public BinaryOpNode 14 | { 15 | 16 | public: 17 | Add(NodeRef a = 0, NodeRef b = 0); 18 | 19 | virtual void process(Buffer &out, int num_frames); 20 | }; 21 | 22 | REGISTER(Add, "add") 23 | 24 | } 25 | -------------------------------------------------------------------------------- /source/include/signalflow/node/operators/amplitude-to-decibels.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/core/constants.h" 4 | #include "signalflow/node/node.h" 5 | 6 | namespace signalflow 7 | { 8 | 9 | /**--------------------------------------------------------------------------------* 10 | * Map a linear amplitude value to decibels. 11 | *---------------------------------------------------------------------------------*/ 12 | class AmplitudeToDecibels : public UnaryOpNode 13 | { 14 | public: 15 | AmplitudeToDecibels(NodeRef a = 0); 16 | virtual void process(Buffer &out, int num_frames) override; 17 | }; 18 | 19 | class DecibelsToAmplitude : public UnaryOpNode 20 | { 21 | public: 22 | DecibelsToAmplitude(NodeRef a = 0); 23 | virtual void process(Buffer &out, int num_frames) override; 24 | }; 25 | 26 | REGISTER(AmplitudeToDecibels, "amplitude-to-decibels") 27 | REGISTER(DecibelsToAmplitude, "decibels-to-amplitude") 28 | 29 | } 30 | -------------------------------------------------------------------------------- /source/include/signalflow/node/operators/bus.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/core/constants.h" 4 | #include "signalflow/node/node.h" 5 | 6 | #include 7 | 8 | namespace signalflow 9 | { 10 | 11 | /**--------------------------------------------------------------------------------* 12 | * Bus is a node with a fixed number of input channels and arbitrary number of 13 | * inputs, used to aggregate multiple sources. It is similar to Sum, but with 14 | * a defined channel count that does not adapt to its inputs. 15 | *---------------------------------------------------------------------------------*/ 16 | class Bus : public VariableInputNode 17 | { 18 | 19 | public: 20 | Bus(unsigned int num_channels = 1); 21 | virtual void process(Buffer &out, int num_frames); 22 | }; 23 | 24 | REGISTER(Bus, "bus") 25 | 26 | } 27 | -------------------------------------------------------------------------------- /source/include/signalflow/node/operators/channel-offset.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/core/constants.h" 4 | #include "signalflow/node/node.h" 5 | 6 | #include 7 | 8 | namespace signalflow 9 | { 10 | 11 | /**--------------------------------------------------------------------------------* 12 | * Offsets the input by a specified number of channels. With an N-channel input 13 | * and an offset of M, the output will have M+N channels. 14 | *---------------------------------------------------------------------------------*/ 15 | class ChannelOffset : public UnaryOpNode 16 | { 17 | 18 | public: 19 | ChannelOffset(int offset = 0, NodeRef input = nullptr); 20 | 21 | virtual void process(Buffer &out, int num_frames); 22 | 23 | private: 24 | PropertyRef offset; 25 | }; 26 | 27 | REGISTER(ChannelOffset, "channel-offset") 28 | 29 | } 30 | -------------------------------------------------------------------------------- /source/include/signalflow/node/operators/channel-select.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/core/constants.h" 4 | #include "signalflow/node/node.h" 5 | 6 | #include 7 | 8 | namespace signalflow 9 | { 10 | 11 | /**--------------------------------------------------------------------------------* 12 | * Select a subset of channels from a multichannel input, starting at offset, 13 | * up to a maximum of maximum, with the given step. 14 | *---------------------------------------------------------------------------------*/ 15 | class ChannelSelect : public UnaryOpNode 16 | { 17 | 18 | public: 19 | ChannelSelect(NodeRef input = nullptr, int offset = 0, int maximum = 0, int step = 1); 20 | 21 | virtual void process(Buffer &out, int num_frames); 22 | 23 | private: 24 | PropertyRef offset; 25 | PropertyRef maximum; 26 | PropertyRef step; 27 | }; 28 | 29 | REGISTER(ChannelSelect, "channel-select") 30 | 31 | } 32 | -------------------------------------------------------------------------------- /source/include/signalflow/node/operators/divide.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/core/constants.h" 4 | #include "signalflow/node/node.h" 5 | 6 | namespace signalflow 7 | { 8 | 9 | /**--------------------------------------------------------------------------------* 10 | * Divide each sample of a by each sample of b. 11 | * Can also be written as a / b 12 | *---------------------------------------------------------------------------------*/ 13 | class Divide : public BinaryOpNode 14 | { 15 | 16 | public: 17 | Divide(NodeRef a = 1, NodeRef b = 1); 18 | 19 | virtual void process(Buffer &out, int num_frames); 20 | }; 21 | 22 | REGISTER(Divide, "divide") 23 | 24 | } 25 | -------------------------------------------------------------------------------- /source/include/signalflow/node/operators/frequency-to-midi-note.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/core/constants.h" 4 | #include "signalflow/node/node.h" 5 | 6 | namespace signalflow 7 | { 8 | 9 | /**--------------------------------------------------------------------------------* 10 | * Map a frequency to a MIDI note (where 440Hz = A4 = 69), with floating-point 11 | * output. 12 | *---------------------------------------------------------------------------------*/ 13 | class FrequencyToMidiNote : public UnaryOpNode 14 | { 15 | 16 | public: 17 | FrequencyToMidiNote(NodeRef a = 0); 18 | 19 | virtual void process(Buffer &out, int num_frames) override; 20 | }; 21 | 22 | REGISTER(FrequencyToMidiNote, "frequency-to-midi-note") 23 | 24 | } 25 | -------------------------------------------------------------------------------- /source/include/signalflow/node/operators/midi-note-to-frequency.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/core/constants.h" 4 | #include "signalflow/node/node.h" 5 | 6 | namespace signalflow 7 | { 8 | 9 | /**--------------------------------------------------------------------------------* 10 | * Map a MIDI note to a frequency (where 440Hz = A4 = 69), supporting floating-point 11 | * input. 12 | *---------------------------------------------------------------------------------*/ 13 | class MidiNoteToFrequency : public UnaryOpNode 14 | { 15 | 16 | public: 17 | MidiNoteToFrequency(NodeRef a = 0); 18 | 19 | virtual void process(Buffer &out, int num_frames) override; 20 | }; 21 | 22 | REGISTER(MidiNoteToFrequency, "midi-note-to-frequency") 23 | 24 | } 25 | -------------------------------------------------------------------------------- /source/include/signalflow/node/operators/multiply.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/core/constants.h" 4 | #include "signalflow/node/node.h" 5 | 6 | namespace signalflow 7 | { 8 | 9 | /**--------------------------------------------------------------------------------* 10 | * Multiply each sample of a by each sample of b. 11 | * Can also be written as a * b 12 | *---------------------------------------------------------------------------------*/ 13 | class Multiply : public BinaryOpNode 14 | { 15 | 16 | public: 17 | Multiply(NodeRef a = 1.0, NodeRef b = 1.0); 18 | 19 | virtual void process(Buffer &out, int num_frames); 20 | }; 21 | 22 | REGISTER(Multiply, "multiply") 23 | 24 | } 25 | -------------------------------------------------------------------------------- /source/include/signalflow/node/operators/pow.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/core/constants.h" 4 | #include "signalflow/node/node.h" 5 | 6 | namespace signalflow 7 | { 8 | 9 | /**--------------------------------------------------------------------------------* 10 | * Outputs a to the power of b, per sample. 11 | * Can also be written as a ** b 12 | *---------------------------------------------------------------------------------*/ 13 | class Pow : public BinaryOpNode 14 | { 15 | 16 | public: 17 | Pow(NodeRef a = 0, NodeRef b = 0); 18 | 19 | virtual void process(Buffer &out, int num_frames); 20 | }; 21 | 22 | REGISTER(Pow, "pow") 23 | 24 | } 25 | -------------------------------------------------------------------------------- /source/include/signalflow/node/operators/round-to-scale.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/core/constants.h" 4 | #include "signalflow/node/node.h" 5 | 6 | namespace signalflow 7 | { 8 | 9 | /**--------------------------------------------------------------------------------* 10 | * Given a frequency input, generates a frequency output that is rounded to the nearest MIDI note. 11 | * (TODO: Not very well named) 12 | *---------------------------------------------------------------------------------*/ 13 | class RoundToScale : public UnaryOpNode 14 | { 15 | 16 | public: 17 | RoundToScale(NodeRef a = 0); 18 | 19 | virtual void process(Buffer &out, int num_frames) override; 20 | }; 21 | 22 | REGISTER(RoundToScale, "round-to-scale") 23 | 24 | } 25 | -------------------------------------------------------------------------------- /source/include/signalflow/node/operators/round.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/core/constants.h" 4 | #include "signalflow/node/node.h" 5 | 6 | namespace signalflow 7 | { 8 | 9 | /**--------------------------------------------------------------------------------* 10 | * Round the input to the nearest integer value. 11 | *---------------------------------------------------------------------------------*/ 12 | class Round : public UnaryOpNode 13 | { 14 | 15 | public: 16 | Round(NodeRef a = 0); 17 | 18 | virtual void process(Buffer &out, int num_frames) override; 19 | }; 20 | 21 | REGISTER(Round, "round") 22 | 23 | } 24 | -------------------------------------------------------------------------------- /source/include/signalflow/node/operators/subtract.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/core/constants.h" 4 | #include "signalflow/node/node.h" 5 | 6 | namespace signalflow 7 | { 8 | 9 | /**--------------------------------------------------------------------------------* 10 | * Subtract each sample of b from each sample of a. 11 | * Can also be written as a - b 12 | *---------------------------------------------------------------------------------*/ 13 | class Subtract : public BinaryOpNode 14 | { 15 | 16 | public: 17 | Subtract(NodeRef a = 0, NodeRef b = 0); 18 | 19 | virtual void process(Buffer &out, int num_frames); 20 | }; 21 | 22 | REGISTER(Subtract, "subtract") 23 | 24 | } 25 | -------------------------------------------------------------------------------- /source/include/signalflow/node/operators/sum.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/core/constants.h" 4 | #include "signalflow/node/node.h" 5 | 6 | #include 7 | 8 | namespace signalflow 9 | { 10 | 11 | /**--------------------------------------------------------------------------------* 12 | * Sums the output of all of the input nodes, by sample. 13 | *---------------------------------------------------------------------------------*/ 14 | class Sum : public VariableInputNode 15 | { 16 | 17 | public: 18 | Sum(); 19 | Sum(std::initializer_list inputs); 20 | Sum(std::vector inputs); 21 | Sum(std::vector inputs); 22 | Sum(std::vector inputs); 23 | 24 | virtual void process(Buffer &out, int num_frames); 25 | 26 | private: 27 | void init(); 28 | }; 29 | 30 | REGISTER(Sum, "sum") 31 | 32 | } 33 | -------------------------------------------------------------------------------- /source/include/signalflow/node/operators/time-shift.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/core/constants.h" 4 | #include "signalflow/node/node.h" 5 | 6 | namespace signalflow 7 | { 8 | 9 | /**--------------------------------------------------------------------------------* 10 | * TimeShift 11 | *---------------------------------------------------------------------------------*/ 12 | class TimeShift : public UnaryOpNode 13 | { 14 | 15 | public: 16 | TimeShift(NodeRef a = 0); 17 | 18 | virtual void process(Buffer &out, int num_frames) override; 19 | virtual void trigger(std::string = SIGNALFLOW_DEFAULT_TRIGGER, float value = 0.0) override; 20 | 21 | protected: 22 | int num_shifts_queued = 0; 23 | }; 24 | 25 | REGISTER(TimeShift, "time-shift") 26 | 27 | } 28 | -------------------------------------------------------------------------------- /source/include/signalflow/node/oscillators/constant.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/node/node.h" 4 | 5 | namespace signalflow 6 | { 7 | /**--------------------------------------------------------------------------------* 8 | * Produces a constant value. 9 | *---------------------------------------------------------------------------------*/ 10 | class Constant : public Node 11 | { 12 | public: 13 | Constant(sample value = 0); 14 | 15 | float value; 16 | virtual float get_value() override; 17 | virtual void set_value(float value) override; 18 | 19 | virtual void process(Buffer &out, int num_frames) override; 20 | }; 21 | 22 | REGISTER(Constant, "constant") 23 | } 24 | -------------------------------------------------------------------------------- /source/include/signalflow/node/oscillators/impulse.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/node/node.h" 4 | 5 | namespace signalflow 6 | { 7 | 8 | /**--------------------------------------------------------------------------------* 9 | * Produces a value of 1 at the given `frequency`, with output of 0 at all other times. 10 | * If frequency is 0, produces a single impulse. 11 | *---------------------------------------------------------------------------------*/ 12 | class Impulse : public Node 13 | { 14 | public: 15 | Impulse(NodeRef frequency = 1.0); 16 | 17 | virtual void alloc() override; 18 | virtual void process(Buffer &out, int num_frames) override; 19 | 20 | NodeRef frequency; 21 | 22 | private: 23 | std::vector steps_remaining; 24 | }; 25 | 26 | REGISTER(Impulse, "impulse") 27 | 28 | } 29 | -------------------------------------------------------------------------------- /source/include/signalflow/node/oscillators/lfo.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/node/node.h" 4 | 5 | namespace signalflow 6 | { 7 | class LFO : public Node 8 | { 9 | public: 10 | LFO(NodeRef frequency = 1.0, NodeRef min = 0.0, NodeRef max = 1.0, NodeRef phase = 0.0); 11 | virtual void alloc() override; 12 | 13 | protected: 14 | std::vector current_phase; 15 | NodeRef frequency; 16 | NodeRef min; 17 | NodeRef max; 18 | NodeRef phase; 19 | }; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /source/include/signalflow/node/oscillators/saw-lfo.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/node/oscillators/lfo.h" 4 | 5 | namespace signalflow 6 | { 7 | /**--------------------------------------------------------------------------------* 8 | * Produces a sawtooth LFO at the given `frequency` and `phase` offset, with output ranging from `min` to `max`. 9 | *---------------------------------------------------------------------------------*/ 10 | class SawLFO : public LFO 11 | { 12 | public: 13 | SawLFO(NodeRef frequency = 1.0, NodeRef min = 0.0, NodeRef max = 1.0, NodeRef phase = 0.0); 14 | virtual void process(Buffer &out, int num_frames) override; 15 | virtual void trigger(std::string name = SIGNALFLOW_DEFAULT_TRIGGER, float value = 1.0) override; 16 | }; 17 | 18 | REGISTER(SawLFO, "saw-lfo") 19 | } 20 | -------------------------------------------------------------------------------- /source/include/signalflow/node/oscillators/sine-lfo.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/node/oscillators/lfo.h" 4 | 5 | namespace signalflow 6 | { 7 | /**--------------------------------------------------------------------------------* 8 | * Produces a sinusoidal LFO at the given `frequency` and `phase` offset, 9 | * with output ranging from `min` to `max`. 10 | *---------------------------------------------------------------------------------*/ 11 | class SineLFO : public LFO 12 | { 13 | public: 14 | SineLFO(NodeRef frequency = 1.0, NodeRef min = 0.0, NodeRef max = 1.0, NodeRef phase = 0.0); 15 | virtual void process(Buffer &out, int num_frames) override; 16 | }; 17 | 18 | REGISTER(SineLFO, "sine-lfo") 19 | } 20 | -------------------------------------------------------------------------------- /source/include/signalflow/node/oscillators/sine.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/node/node.h" 4 | 5 | namespace signalflow 6 | { 7 | /**--------------------------------------------------------------------------------* 8 | * Produces a sine wave at the given `frequency`. 9 | *---------------------------------------------------------------------------------*/ 10 | class SineOscillator : public Node 11 | { 12 | public: 13 | SineOscillator(NodeRef frequency = 440, NodeRef phase_offset = nullptr, NodeRef reset = nullptr); 14 | 15 | virtual void process(Buffer &out, int num_frames) override; 16 | virtual void alloc() override; 17 | 18 | NodeRef frequency; 19 | NodeRef phase_offset; 20 | NodeRef reset; 21 | 22 | private: 23 | std::vector phase; 24 | }; 25 | 26 | REGISTER(SineOscillator, "sine") 27 | } 28 | -------------------------------------------------------------------------------- /source/include/signalflow/node/oscillators/square-lfo.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/node/oscillators/lfo.h" 4 | 5 | namespace signalflow 6 | { 7 | /**--------------------------------------------------------------------------------* 8 | * Produces a pulse wave LFO with the given `frequency` and pulse `width`, 9 | * ranging from `min` to `max`, where `width` of `0.5` is a square wave and 10 | * other values produce a rectangular wave. 11 | *---------------------------------------------------------------------------------*/ 12 | class SquareLFO : public LFO 13 | { 14 | public: 15 | SquareLFO(NodeRef frequency = 1.0, NodeRef min = 0.0, NodeRef max = 1.0, NodeRef width = 0.5, NodeRef phase = 0.0); 16 | virtual void process(Buffer &out, int num_frames) override; 17 | 18 | protected: 19 | NodeRef width; 20 | }; 21 | 22 | REGISTER(SquareLFO, "square-lfo") 23 | } 24 | -------------------------------------------------------------------------------- /source/include/signalflow/node/oscillators/square.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/node/node.h" 4 | 5 | namespace signalflow 6 | { 7 | /**--------------------------------------------------------------------------------* 8 | * Produces a pulse wave with the given `frequency` and pulse `width`, 9 | * where `width` of `0.5` is a square wave and other values produce a 10 | * rectangular wave. 11 | *---------------------------------------------------------------------------------*/ 12 | class SquareOscillator : public Node 13 | { 14 | public: 15 | SquareOscillator(NodeRef frequency = 440, NodeRef width = 0.5); 16 | 17 | NodeRef frequency; 18 | NodeRef width; 19 | 20 | virtual void alloc() override; 21 | virtual void process(Buffer &out, int num_frames) override; 22 | 23 | private: 24 | std::vector phase; 25 | }; 26 | 27 | REGISTER(SquareOscillator, "square") 28 | } 29 | -------------------------------------------------------------------------------- /source/include/signalflow/node/oscillators/triangle-lfo.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/node/oscillators/lfo.h" 4 | 5 | namespace signalflow 6 | { 7 | /**--------------------------------------------------------------------------------* 8 | * Produces a triangle LFO with the given `frequency` and `phase` offset, 9 | * ranging from `min` to `max`. 10 | *---------------------------------------------------------------------------------*/ 11 | class TriangleLFO : public LFO 12 | { 13 | public: 14 | TriangleLFO(NodeRef frequency = 1.0, NodeRef min = 0.0, NodeRef max = 1.0, NodeRef phase = 0.0); 15 | virtual void process(Buffer &out, int num_frames) override; 16 | }; 17 | 18 | REGISTER(TriangleLFO, "triangle-lfo") 19 | } 20 | -------------------------------------------------------------------------------- /source/include/signalflow/node/oscillators/triangle.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/node/node.h" 4 | 5 | namespace signalflow 6 | { 7 | /**--------------------------------------------------------------------------------* 8 | * Produces a triangle wave with the given `frequency`. 9 | *---------------------------------------------------------------------------------*/ 10 | class TriangleOscillator : public Node 11 | { 12 | public: 13 | TriangleOscillator(NodeRef frequency = 440); 14 | 15 | NodeRef frequency; 16 | 17 | virtual void alloc() override; 18 | virtual void process(Buffer &out, int num_frames) override; 19 | 20 | private: 21 | std::vector phase; 22 | }; 23 | 24 | REGISTER(TriangleOscillator, "triangle") 25 | } 26 | -------------------------------------------------------------------------------- /source/include/signalflow/node/processors/clip.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/core/constants.h" 4 | #include "signalflow/node/node.h" 5 | 6 | namespace signalflow 7 | { 8 | /**--------------------------------------------------------------------------------* 9 | * Clip the input to `min`/`max`. 10 | *---------------------------------------------------------------------------------*/ 11 | class Clip : public UnaryOpNode 12 | { 13 | public: 14 | Clip(NodeRef input = nullptr, NodeRef min = -1.0, NodeRef max = 1.0); 15 | 16 | virtual void process(Buffer &out, int num_frames) override; 17 | 18 | private: 19 | NodeRef min; 20 | NodeRef max; 21 | }; 22 | 23 | REGISTER(Clip, "clip") 24 | } 25 | -------------------------------------------------------------------------------- /source/include/signalflow/node/processors/delays/onetap.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/buffer/ringbuffer.h" 4 | #include "signalflow/core/constants.h" 5 | #include "signalflow/node/node.h" 6 | 7 | #include 8 | 9 | namespace signalflow 10 | { 11 | /**--------------------------------------------------------------------------------* 12 | * Single-tap delay line. 13 | * `delay_time` must be less than or equal to `max_delay_time`. 14 | *---------------------------------------------------------------------------------*/ 15 | class OneTapDelay : public UnaryOpNode 16 | { 17 | public: 18 | OneTapDelay(NodeRef input = 0.0, NodeRef delay_time = 0.1, float max_delay_time = 0.5); 19 | ~OneTapDelay() override; 20 | 21 | virtual void process(Buffer &out, int num_frames) override; 22 | 23 | private: 24 | NodeRef delay_time; 25 | 26 | std::vector buffers; 27 | }; 28 | 29 | REGISTER(OneTapDelay, "one-tap-delay") 30 | } 31 | -------------------------------------------------------------------------------- /source/include/signalflow/node/processors/distortion/resample.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/core/constants.h" 4 | #include "signalflow/node/node.h" 5 | 6 | namespace signalflow 7 | { 8 | /**--------------------------------------------------------------------------------* 9 | * Resampler and bit crusher. `sample_rate` is in Hz, `bit_rate` is an integer 10 | * between 0 and 16. 11 | *---------------------------------------------------------------------------------*/ 12 | class Resample : public UnaryOpNode 13 | { 14 | public: 15 | Resample(NodeRef input = 0, NodeRef sample_rate = 44100, NodeRef bit_rate = 16); 16 | 17 | virtual void alloc() override; 18 | virtual void process(Buffer &out, int num_frames) override; 19 | 20 | private: 21 | NodeRef sample_rate; 22 | NodeRef bit_rate; 23 | 24 | float phase; 25 | float phase_last; 26 | std::vector sample_last; 27 | }; 28 | 29 | REGISTER(Resample, "resample") 30 | } 31 | -------------------------------------------------------------------------------- /source/include/signalflow/node/processors/distortion/sample-and-hold.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/core/constants.h" 4 | #include "signalflow/node/node.h" 5 | 6 | namespace signalflow 7 | { 8 | /**--------------------------------------------------------------------------------* 9 | * Samples and holds the input each time a trigger is received on `clock`. 10 | *---------------------------------------------------------------------------------*/ 11 | class SampleAndHold : public UnaryOpNode 12 | { 13 | public: 14 | SampleAndHold(NodeRef input = nullptr, NodeRef clock = nullptr); 15 | 16 | virtual void alloc() override; 17 | virtual void process(Buffer &out, int num_frames) override; 18 | virtual void trigger(std::string name = SIGNALFLOW_DEFAULT_TRIGGER, float value = 1.0) override; 19 | 20 | private: 21 | NodeRef clock; 22 | std::vector values; 23 | }; 24 | 25 | REGISTER(SampleAndHold, "sample-and-hold") 26 | } 27 | -------------------------------------------------------------------------------- /source/include/signalflow/node/processors/distortion/waveshaper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/core/constants.h" 4 | #include "signalflow/node/node.h" 5 | 6 | namespace signalflow 7 | { 8 | /**--------------------------------------------------------------------------------* 9 | * Applies wave-shaping as described in the WaveShaperBuffer `buffer`. 10 | *---------------------------------------------------------------------------------*/ 11 | class WaveShaper : public UnaryOpNode 12 | { 13 | public: 14 | WaveShaper(NodeRef input = 0.0, BufferRef buffer = nullptr); 15 | 16 | virtual void process(Buffer &out, int num_frames) override; 17 | 18 | private: 19 | BufferRef buffer; 20 | }; 21 | 22 | REGISTER(WaveShaper, "waveshaper") 23 | } 24 | -------------------------------------------------------------------------------- /source/include/signalflow/node/processors/dynamics/gate.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/core/constants.h" 4 | #include "signalflow/node/node.h" 5 | 6 | namespace signalflow 7 | { 8 | /**--------------------------------------------------------------------------------* 9 | * Outputs the input value when it is above the given `threshold`, otherwise zero. 10 | *---------------------------------------------------------------------------------*/ 11 | class Gate : public UnaryOpNode 12 | { 13 | public: 14 | Gate(NodeRef input = 0.0, NodeRef threshold = 0.1); 15 | 16 | virtual void process(Buffer &out, int num_frames); 17 | 18 | NodeRef threshold; 19 | 20 | private: 21 | float level; 22 | }; 23 | 24 | REGISTER(Gate, "gate") 25 | } 26 | -------------------------------------------------------------------------------- /source/include/signalflow/node/processors/dynamics/maximiser.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/core/constants.h" 4 | #include "signalflow/node/node.h" 5 | 6 | namespace signalflow 7 | { 8 | /**--------------------------------------------------------------------------------* 9 | * Gain maximiser. 10 | *---------------------------------------------------------------------------------*/ 11 | class Maximiser : public UnaryOpNode 12 | { 13 | public: 14 | Maximiser(NodeRef input = 0.0, 15 | NodeRef ceiling = 0.5, 16 | NodeRef attack_time = 1.0, 17 | NodeRef release_time = 1.0); 18 | 19 | virtual void process(Buffer &out, int num_frames); 20 | 21 | NodeRef ceiling; 22 | NodeRef attack_time; 23 | NodeRef release_time; 24 | 25 | private: 26 | float gain; 27 | }; 28 | 29 | REGISTER(Maximiser, "maximiser") 30 | } 31 | -------------------------------------------------------------------------------- /source/include/signalflow/node/processors/dynamics/rms.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/core/constants.h" 4 | #include "signalflow/node/node.h" 5 | 6 | namespace signalflow 7 | { 8 | /**--------------------------------------------------------------------------------* 9 | * Outputs the root-mean-squared value of the input, in buffers equal to the 10 | * graph's current buffer size. 11 | *---------------------------------------------------------------------------------*/ 12 | class RMS : public UnaryOpNode 13 | { 14 | public: 15 | RMS(NodeRef input = 0.0); 16 | 17 | virtual void process(Buffer &out, int num_frames); 18 | }; 19 | 20 | REGISTER(RMS, "rms") 21 | 22 | } 23 | -------------------------------------------------------------------------------- /source/include/signalflow/node/processors/filters/dc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/core/constants.h" 4 | #include "signalflow/node/node.h" 5 | 6 | namespace signalflow 7 | { 8 | /**--------------------------------------------------------------------------------* 9 | * Remove low-frequency and DC content from a signal. 10 | *---------------------------------------------------------------------------------*/ 11 | class DCFilter : public UnaryOpNode 12 | { 13 | public: 14 | DCFilter(NodeRef input = 0.0); 15 | 16 | virtual void process(Buffer &out, int num_frames) override; 17 | virtual void alloc() override; 18 | 19 | private: 20 | float R; 21 | std::vector previous_input; 22 | std::vector previous_output; 23 | }; 24 | 25 | REGISTER(DCFilter, "dc-filter") 26 | } 27 | -------------------------------------------------------------------------------- /source/include/signalflow/node/processors/fold.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/core/constants.h" 4 | #include "signalflow/node/node.h" 5 | 6 | namespace signalflow 7 | { 8 | /**--------------------------------------------------------------------------------* 9 | * Fold the input beyond `min`/`max`, reflecting the excess back. 10 | *---------------------------------------------------------------------------------*/ 11 | class Fold : public UnaryOpNode 12 | { 13 | public: 14 | Fold(NodeRef input = nullptr, NodeRef min = -1.0, NodeRef max = 1.0); 15 | 16 | virtual void process(Buffer &out, int num_frames) override; 17 | 18 | private: 19 | NodeRef min; 20 | NodeRef max; 21 | }; 22 | 23 | REGISTER(Fold, "fold") 24 | } 25 | -------------------------------------------------------------------------------- /source/include/signalflow/node/processors/panning/channel-panner.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/node/node.h" 4 | 5 | namespace signalflow 6 | { 7 | /**--------------------------------------------------------------------------------* 8 | * Pan the input between a linear series of channels, where `pan` 0 = channel 0, 9 | * 1 = channel 1, etc. No wrapping is applied. 10 | *---------------------------------------------------------------------------------*/ 11 | class ChannelPanner : public Node 12 | { 13 | public: 14 | ChannelPanner(int num_channels = 2, NodeRef input = 0, NodeRef pan = 0.0, NodeRef width = 1.0); 15 | 16 | virtual void process(Buffer &out, int num_frames) override; 17 | virtual void set_property(std::string name, const PropertyRef &value) override; 18 | 19 | PropertyRef num_channels; 20 | NodeRef input; 21 | NodeRef pan; 22 | NodeRef width; 23 | }; 24 | 25 | REGISTER(ChannelPanner, "channel-panner") 26 | } 27 | -------------------------------------------------------------------------------- /source/include/signalflow/node/processors/panning/stereo-balance.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/node/node.h" 4 | 5 | namespace signalflow 6 | { 7 | /**--------------------------------------------------------------------------------* 8 | * Takes a stereo input and rebalances it, where `balance` of `0` is unchanged, 9 | * `-1` is hard left, and `1` is hard right. 10 | *---------------------------------------------------------------------------------*/ 11 | class StereoBalance : public UnaryOpNode 12 | { 13 | public: 14 | StereoBalance(NodeRef input = 0, NodeRef balance = 0); 15 | virtual void process(Buffer &out, int num_frames); 16 | 17 | NodeRef balance; 18 | }; 19 | 20 | REGISTER(StereoBalance, "stereo-balance") 21 | } 22 | -------------------------------------------------------------------------------- /source/include/signalflow/node/processors/panning/stereo-panner.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/node/node.h" 4 | 5 | namespace signalflow 6 | { 7 | /**--------------------------------------------------------------------------------* 8 | * Pans a mono input to a stereo output. `pan` should be between -1 (hard left) to 9 | * +1 (hard right), with 0 = centre. 10 | *---------------------------------------------------------------------------------*/ 11 | class StereoPanner : public Node 12 | { 13 | public: 14 | StereoPanner(NodeRef input = 0, NodeRef pan = 0.0); 15 | 16 | virtual void process(Buffer &out, int num_frames) override; 17 | 18 | NodeRef input; 19 | NodeRef pan; 20 | }; 21 | 22 | REGISTER(StereoPanner, "stereo-panner") 23 | } 24 | -------------------------------------------------------------------------------- /source/include/signalflow/node/processors/panning/stereo-width.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/node/node.h" 4 | 5 | namespace signalflow 6 | { 7 | /**--------------------------------------------------------------------------------* 8 | * Reduces the width of a stereo signal. 9 | * When `width` = 1, input is unchanged. 10 | * When `width` = 0, outputs a pair of identical channels both containing L+R. 11 | *---------------------------------------------------------------------------------*/ 12 | class StereoWidth : public UnaryOpNode 13 | { 14 | public: 15 | StereoWidth(NodeRef input = 0, NodeRef width = 1); 16 | virtual void process(Buffer &out, int num_frames); 17 | 18 | NodeRef width; 19 | }; 20 | 21 | REGISTER(StereoWidth, "stereo-width") 22 | } 23 | -------------------------------------------------------------------------------- /source/include/signalflow/node/processors/smooth.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/core/constants.h" 4 | #include "signalflow/node/node.h" 5 | #include 6 | 7 | namespace signalflow 8 | { 9 | /**--------------------------------------------------------------------------------* 10 | * Smooth the input with a given smoothing coefficient. 11 | * When `smooth` = 0, applies no smoothing. 12 | *---------------------------------------------------------------------------------*/ 13 | class Smooth : public UnaryOpNode 14 | { 15 | public: 16 | Smooth(NodeRef input = nullptr, NodeRef smooth = 0.99); 17 | 18 | virtual void alloc() override; 19 | virtual void process(Buffer &out, int num_frames) override; 20 | 21 | private: 22 | NodeRef smooth; 23 | std::vector values; 24 | }; 25 | 26 | REGISTER(Smooth, "smooth") 27 | } 28 | -------------------------------------------------------------------------------- /source/include/signalflow/node/processors/wetdry.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/core/constants.h" 4 | #include "signalflow/node/node.h" 5 | 6 | namespace signalflow 7 | { 8 | /**--------------------------------------------------------------------------------* 9 | * Takes `wet` and `dry` inputs, and outputs a mix determined by `wetness`. 10 | *---------------------------------------------------------------------------------*/ 11 | class WetDry : public Node 12 | { 13 | public: 14 | WetDry(NodeRef dry_input = nullptr, 15 | NodeRef wet_input = nullptr, 16 | NodeRef wetness = 0.0); 17 | 18 | virtual void process(Buffer &out, int num_frames) override; 19 | 20 | private: 21 | NodeRef dry_input; 22 | NodeRef wet_input; 23 | NodeRef wetness; 24 | }; 25 | 26 | REGISTER(WetDry, "wetdry") 27 | } 28 | -------------------------------------------------------------------------------- /source/include/signalflow/node/processors/wrap.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/core/constants.h" 4 | #include "signalflow/node/node.h" 5 | 6 | namespace signalflow 7 | { 8 | /**--------------------------------------------------------------------------------* 9 | * Wrap the input beyond `min`/`max`. 10 | *---------------------------------------------------------------------------------*/ 11 | class Wrap : public UnaryOpNode 12 | { 13 | public: 14 | Wrap(NodeRef input = nullptr, NodeRef min = -1.0, NodeRef max = 1.0); 15 | 16 | virtual void process(Buffer &out, int num_frames) override; 17 | 18 | private: 19 | NodeRef min; 20 | NodeRef max; 21 | }; 22 | 23 | REGISTER(Wrap, "wrap") 24 | } 25 | -------------------------------------------------------------------------------- /source/include/signalflow/node/sequencing/block-counter.h: -------------------------------------------------------------------------------- 1 | #include "signalflow/core/constants.h" 2 | #include "signalflow/node/node.h" 3 | 4 | namespace signalflow 5 | { 6 | 7 | /**--------------------------------------------------------------------------------* 8 | * Increments by one for each audio block processed. 9 | *---------------------------------------------------------------------------------*/ 10 | class BlockCounter : public Node 11 | { 12 | 13 | public: 14 | BlockCounter(); 15 | 16 | virtual void process(Buffer &out, int num_frames) override; 17 | 18 | private: 19 | unsigned int counter; 20 | }; 21 | 22 | REGISTER(BlockCounter, "block-counter") 23 | 24 | } 25 | -------------------------------------------------------------------------------- /source/include/signalflow/node/sequencing/counter.h: -------------------------------------------------------------------------------- 1 | #include "signalflow/core/constants.h" 2 | #include "signalflow/node/node.h" 3 | 4 | namespace signalflow 5 | { 6 | 7 | /**--------------------------------------------------------------------------------* 8 | * Count upwards from `min` to `max`, driven by `clock`. 9 | *---------------------------------------------------------------------------------*/ 10 | class Counter : public Node 11 | { 12 | 13 | public: 14 | Counter(NodeRef clock = 0, NodeRef min = 0, NodeRef max = 2147483647); 15 | 16 | virtual void alloc() override; 17 | virtual void process(Buffer &out, int num_frames) override; 18 | virtual void trigger(std::string name = SIGNALFLOW_DEFAULT_TRIGGER, float value = 1.0) override; 19 | 20 | NodeRef clock; 21 | NodeRef min; 22 | NodeRef max; 23 | 24 | private: 25 | std::vector counter; 26 | }; 27 | 28 | REGISTER(Counter, "counter") 29 | 30 | } 31 | -------------------------------------------------------------------------------- /source/include/signalflow/node/sequencing/flipflop.h: -------------------------------------------------------------------------------- 1 | #include "signalflow/core/constants.h" 2 | #include "signalflow/node/node.h" 3 | 4 | namespace signalflow 5 | { 6 | 7 | /**--------------------------------------------------------------------------------* 8 | * Flips from 0/1 on each `clock`. 9 | *---------------------------------------------------------------------------------*/ 10 | class FlipFlop : public Node 11 | { 12 | 13 | public: 14 | FlipFlop(NodeRef clock = 0); 15 | 16 | virtual void alloc() override; 17 | virtual void process(Buffer &out, int num_frames) override; 18 | virtual void trigger(std::string name = SIGNALFLOW_DEFAULT_TRIGGER, float value = 1.0) override; 19 | 20 | NodeRef clock; 21 | 22 | private: 23 | std::vector value; 24 | }; 25 | 26 | REGISTER(FlipFlop, "flipflop") 27 | 28 | } 29 | -------------------------------------------------------------------------------- /source/include/signalflow/node/sequencing/index.h: -------------------------------------------------------------------------------- 1 | #include "signalflow/core/constants.h" 2 | #include "signalflow/node/node.h" 3 | 4 | namespace signalflow 5 | { 6 | 7 | /**--------------------------------------------------------------------------------* 8 | * Outputs the value in `list` corresponding to `index`. 9 | *---------------------------------------------------------------------------------*/ 10 | class Index : public Node 11 | { 12 | 13 | public: 14 | Index(std::vector list = {}, NodeRef index = 0); 15 | 16 | virtual void process(Buffer &out, int num_frames); 17 | 18 | PropertyRef list; 19 | NodeRef index; 20 | }; 21 | 22 | REGISTER(Index, "index") 23 | 24 | } 25 | -------------------------------------------------------------------------------- /source/include/signalflow/node/sequencing/sequence.h: -------------------------------------------------------------------------------- 1 | #include "signalflow/core/constants.h" 2 | #include "signalflow/node/node.h" 3 | 4 | namespace signalflow 5 | { 6 | 7 | /**--------------------------------------------------------------------------------* 8 | * Outputs the elements in `sequence`, incrementing position on each `clock`. 9 | *---------------------------------------------------------------------------------*/ 10 | class Sequence : public Node 11 | { 12 | 13 | public: 14 | Sequence(std::vector sequence = std::vector(), NodeRef clock = nullptr); 15 | 16 | virtual void alloc() override; 17 | virtual void process(Buffer &out, int num_frames) override; 18 | virtual void trigger(std::string name = SIGNALFLOW_DEFAULT_TRIGGER, float value = 1.0) override; 19 | 20 | private: 21 | std::vector sequence; 22 | std::vector position; 23 | NodeRef clock; 24 | }; 25 | 26 | REGISTER(Sequence, "sequence") 27 | 28 | } 29 | -------------------------------------------------------------------------------- /source/include/signalflow/node/sequencing/trigger-mult.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/core/constants.h" 4 | #include "signalflow/node/node.h" 5 | 6 | namespace signalflow 7 | { 8 | 9 | /**--------------------------------------------------------------------------------* 10 | * Distribute any triggers to all output nodes. 11 | *---------------------------------------------------------------------------------*/ 12 | class TriggerMult : public UnaryOpNode 13 | { 14 | 15 | public: 16 | TriggerMult(NodeRef a = 0); 17 | 18 | virtual void process(Buffer &out, int num_frames) override; 19 | virtual void trigger(std::string = SIGNALFLOW_DEFAULT_TRIGGER, 20 | float value = SIGNALFLOW_NULL_FLOAT) override; 21 | }; 22 | 23 | REGISTER(TriggerMult, "trigger-mult") 24 | 25 | } 26 | -------------------------------------------------------------------------------- /source/include/signalflow/node/stochastic/logistic.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/node/node.h" 4 | 5 | namespace signalflow 6 | { 7 | 8 | /**--------------------------------------------------------------------------------* 9 | * Logistic noise. 10 | *---------------------------------------------------------------------------------*/ 11 | class Logistic : public Node 12 | { 13 | public: 14 | Logistic(NodeRef chaos = 3.7, NodeRef frequency = 0.0); 15 | 16 | virtual void alloc() override; 17 | virtual void process(Buffer &out, int num_frames) override; 18 | 19 | private: 20 | NodeRef chaos; 21 | NodeRef frequency; 22 | 23 | std::vector value; 24 | std::vector steps_remaining; 25 | }; 26 | 27 | REGISTER(Logistic, "logistic") 28 | } 29 | -------------------------------------------------------------------------------- /source/include/signalflow/node/stochastic/pink-noise.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/node/stochastic/stochastic-node.h" 4 | 5 | namespace signalflow 6 | { 7 | 8 | /**--------------------------------------------------------------------------------* 9 | * Pink noise, with specified low/high cutoffs. 10 | *---------------------------------------------------------------------------------*/ 11 | class PinkNoise : public StochasticNode 12 | { 13 | public: 14 | PinkNoise(float low_cutoff = 20.0, float high_cutoff = 20000.0, NodeRef reset = nullptr); 15 | 16 | virtual void alloc() override; 17 | virtual void process(Buffer &out, int num_frames) override; 18 | 19 | private: 20 | std::vector> value; 21 | std::vector> steps_remaining; 22 | 23 | int num_octaves; 24 | int initial_octave; 25 | }; 26 | 27 | REGISTER(PinkNoise, "pinknoise") 28 | } 29 | -------------------------------------------------------------------------------- /source/include/signalflow/patch/patch-registry.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "signalflow/patch/patch-spec.h" 4 | #include "signalflow/patch/patch.h" 5 | #include 6 | 7 | namespace signalflow 8 | { 9 | class PatchRegistry 10 | { 11 | public: 12 | PatchRegistry(); 13 | static PatchRegistry *global(); 14 | 15 | PatchRef create(std::string name); 16 | void add(std::string name, PatchSpecRef patchspec); 17 | PatchSpecRef get(std::string name); 18 | 19 | std::unordered_map patchspecs; 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /source/lib/pybind11/common.h: -------------------------------------------------------------------------------- 1 | #include "detail/common.h" 2 | #warning "Including 'common.h' is deprecated. It will be removed in v3.0. Use 'pybind11.h'." 3 | -------------------------------------------------------------------------------- /source/lib/pybind11/eigen.h: -------------------------------------------------------------------------------- 1 | /* 2 | pybind11/eigen.h: Transparent conversion for dense and sparse Eigen matrices 3 | 4 | Copyright (c) 2016 Wenzel Jakob 5 | 6 | All rights reserved. Use of this source code is governed by a 7 | BSD-style license that can be found in the LICENSE file. 8 | */ 9 | 10 | #pragma once 11 | 12 | #include "eigen/matrix.h" 13 | -------------------------------------------------------------------------------- /source/src/buffer/waveshaper-buffer.cpp: -------------------------------------------------------------------------------- 1 | #include "signalflow/buffer/waveshaper-buffer.h" 2 | 3 | namespace signalflow 4 | { 5 | 6 | WaveShaperBuffer::WaveShaperBuffer(int length) 7 | : Buffer(1, length) 8 | { 9 | /*------------------------------------------------------------------------- 10 | * Initialise to a 1-to-1 linear mapping. 11 | *-----------------------------------------------------------------------*/ 12 | this->fill([](float input) { return input; }); 13 | } 14 | 15 | WaveShaperBuffer::WaveShaperBuffer(const std::function f) 16 | : Buffer(1, 1024) 17 | { 18 | this->fill(f); 19 | } 20 | 21 | double WaveShaperBuffer::offset_to_frame(double offset) 22 | { 23 | return signalflow_scale_lin_lin(offset, -1, 1, 0, this->num_frames - 1); 24 | } 25 | 26 | double WaveShaperBuffer::frame_to_offset(double frame) 27 | { 28 | return signalflow_scale_lin_lin(frame, 0, this->num_frames - 1, -1, 1); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /source/src/bus/bus.cpp: -------------------------------------------------------------------------------- 1 | #include "signalflow/bus/bus.h" 2 | 3 | namespace signalflow 4 | { 5 | 6 | Bus::Bus(int num_channels) 7 | { 8 | this->num_channels = num_channels; 9 | } 10 | 11 | int Bus::get_num_channels() 12 | { 13 | return this->num_channels; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /source/src/node/io/input/abstract.cpp: -------------------------------------------------------------------------------- 1 | #include "signalflow/node/io/input/abstract.h" 2 | 3 | namespace signalflow 4 | { 5 | 6 | AudioIn_Abstract::AudioIn_Abstract() 7 | { 8 | this->name = "audioin"; 9 | this->set_channels(0, 1); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /source/src/node/io/output/dummy.cpp: -------------------------------------------------------------------------------- 1 | #include "signalflow/node/io/output/dummy.h" 2 | 3 | namespace signalflow 4 | { 5 | 6 | AudioOut_Dummy::AudioOut_Dummy(unsigned int num_channels, 7 | unsigned int sample_rate, 8 | unsigned int buffer_size) 9 | : AudioOut_Abstract() 10 | { 11 | this->name = "audioout-dummy"; 12 | this->set_channels(num_channels, 0); 13 | this->sample_rate = sample_rate; 14 | this->buffer_size = buffer_size; 15 | } 16 | 17 | } // namespace signalflow 18 | -------------------------------------------------------------------------------- /source/src/node/operators/add.cpp: -------------------------------------------------------------------------------- 1 | #include "signalflow/node/operators/add.h" 2 | 3 | namespace signalflow 4 | { 5 | 6 | Add::Add(NodeRef a, NodeRef b) 7 | : BinaryOpNode(a, b) 8 | { 9 | this->name = "add"; 10 | } 11 | 12 | void Add::process(Buffer &out, int num_frames) 13 | { 14 | for (int channel = 0; channel < this->num_output_channels; channel++) 15 | { 16 | #ifdef __APPLE__ 17 | vDSP_vadd(input0->out[channel], 1, input1->out[channel], 1, out[channel], 1, num_frames); 18 | #else 19 | for (int frame = 0; frame < num_frames; frame++) 20 | { 21 | out[channel][frame] = input0->out[channel][frame] + input1->out[channel][frame]; 22 | } 23 | #endif 24 | } 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /source/src/node/operators/divide.cpp: -------------------------------------------------------------------------------- 1 | #include "signalflow/node/operators/divide.h" 2 | 3 | namespace signalflow 4 | { 5 | 6 | Divide::Divide(NodeRef a, NodeRef b) 7 | : BinaryOpNode(a, b) 8 | { 9 | this->name = "divide"; 10 | } 11 | 12 | void Divide::process(Buffer &out, int num_frames) 13 | { 14 | for (int frame = 0; frame < num_frames; frame++) 15 | { 16 | for (int channel = 0; channel < this->num_output_channels; channel++) 17 | { 18 | out[channel][frame] = input0->out[channel][frame] / input1->out[channel][frame]; 19 | } 20 | } 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /source/src/node/operators/frequency-to-midi-note.cpp: -------------------------------------------------------------------------------- 1 | #include "signalflow/core/util.h" 2 | #include "signalflow/node/operators/frequency-to-midi-note.h" 3 | 4 | namespace signalflow 5 | { 6 | 7 | FrequencyToMidiNote::FrequencyToMidiNote(NodeRef a) 8 | : UnaryOpNode(a) 9 | { 10 | this->name = "frequency-to-midi-note"; 11 | } 12 | 13 | void FrequencyToMidiNote::process(Buffer &out, int num_frames) 14 | { 15 | for (int channel = 0; channel < this->num_output_channels; channel++) 16 | { 17 | for (int frame = 0; frame < num_frames; frame++) 18 | { 19 | float value = this->input->out[channel][frame]; 20 | float midi = signalflow_frequency_to_midi_note(value); 21 | out[channel][frame] = midi; 22 | } 23 | } 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /source/src/node/operators/midi-note-to-frequency.cpp: -------------------------------------------------------------------------------- 1 | #include "signalflow/core/util.h" 2 | #include "signalflow/node/operators/midi-note-to-frequency.h" 3 | 4 | namespace signalflow 5 | { 6 | 7 | MidiNoteToFrequency::MidiNoteToFrequency(NodeRef a) 8 | : UnaryOpNode(a) 9 | { 10 | this->name = "midi-note-to-frequency"; 11 | } 12 | 13 | void MidiNoteToFrequency::process(Buffer &out, int num_frames) 14 | { 15 | for (int channel = 0; channel < this->num_output_channels; channel++) 16 | { 17 | for (int frame = 0; frame < num_frames; frame++) 18 | { 19 | float value = this->input->out[channel][frame]; 20 | float midi = signalflow_midi_note_to_frequency(value); 21 | out[channel][frame] = midi; 22 | } 23 | } 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /source/src/node/operators/multiply.cpp: -------------------------------------------------------------------------------- 1 | #include "signalflow/node/operators/multiply.h" 2 | 3 | namespace signalflow 4 | { 5 | 6 | Multiply::Multiply(NodeRef a, NodeRef b) 7 | : BinaryOpNode(a, b) 8 | { 9 | this->name = "multiply"; 10 | } 11 | 12 | void Multiply::process(Buffer &out, int num_frames) 13 | { 14 | for (int channel = 0; channel < this->num_output_channels; channel++) 15 | { 16 | #ifdef __APPLE__ 17 | vDSP_vmul(input0->out[channel], 1, input1->out[channel], 1, out[channel], 1, num_frames); 18 | #else 19 | for (int frame = 0; frame < num_frames; frame++) 20 | out[channel][frame] = input0->out[channel][frame] * input1->out[channel][frame]; 21 | #endif 22 | } 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /source/src/node/operators/pow.cpp: -------------------------------------------------------------------------------- 1 | #include "signalflow/node/operators/pow.h" 2 | 3 | namespace signalflow 4 | { 5 | 6 | Pow::Pow(NodeRef a, NodeRef b) 7 | : BinaryOpNode(a, b) 8 | { 9 | this->name = "pow"; 10 | } 11 | 12 | void Pow::process(Buffer &out, int num_frames) 13 | { 14 | for (int channel = 0; channel < this->num_output_channels; channel++) 15 | { 16 | #ifdef __APPLE__ 17 | vvpowf(out[channel], input1->out[channel], input0->out[channel], &num_frames); 18 | #else 19 | for (int frame = 0; frame < num_frames; frame++) 20 | { 21 | out[channel][frame] = powf(input0->out[channel][frame], input1->out[channel][frame]); 22 | } 23 | #endif 24 | } 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /source/src/node/operators/round-to-scale.cpp: -------------------------------------------------------------------------------- 1 | #include "signalflow/node/operators/round-to-scale.h" 2 | 3 | namespace signalflow 4 | { 5 | 6 | RoundToScale::RoundToScale(NodeRef a) 7 | : UnaryOpNode(a) 8 | { 9 | this->name = "round-to-scale"; 10 | } 11 | 12 | void RoundToScale::process(Buffer &out, int num_frames) 13 | { 14 | for (int channel = 0; channel < this->num_output_channels; channel++) 15 | { 16 | for (int frame = 0; frame < num_frames; frame++) 17 | { 18 | float value = this->input->out[channel][frame]; 19 | float midi = signalflow_frequency_to_midi_note(value); 20 | float midi_rounded = roundf(midi); 21 | float freq = signalflow_midi_note_to_frequency(midi_rounded); 22 | out[channel][frame] = freq; 23 | } 24 | } 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /source/src/node/operators/round.cpp: -------------------------------------------------------------------------------- 1 | #include "signalflow/node/operators/round.h" 2 | #include 3 | 4 | namespace signalflow 5 | { 6 | 7 | Round::Round(NodeRef a) 8 | : UnaryOpNode(a) 9 | { 10 | this->name = "round"; 11 | } 12 | 13 | void Round::process(Buffer &out, int num_frames) 14 | { 15 | for (int channel = 0; channel < this->num_output_channels; channel++) 16 | { 17 | for (int frame = 0; frame < num_frames; frame++) 18 | { 19 | float value = this->input->out[channel][frame]; 20 | out[channel][frame] = roundf(value); 21 | } 22 | } 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /source/src/node/operators/subtract.cpp: -------------------------------------------------------------------------------- 1 | #include "signalflow/node/operators/subtract.h" 2 | 3 | namespace signalflow 4 | { 5 | 6 | Subtract::Subtract(NodeRef a, NodeRef b) 7 | : BinaryOpNode(a, b) 8 | { 9 | this->name = "subtract"; 10 | } 11 | 12 | void Subtract::process(Buffer &out, int num_frames) 13 | { 14 | for (int channel = 0; channel < this->num_output_channels; channel++) 15 | { 16 | #ifdef __APPLE__ 17 | vDSP_vsub(input1->out[channel], 1, input0->out[channel], 1, out[channel], 1, num_frames); 18 | #else 19 | for (int frame = 0; frame < num_frames; frame++) 20 | { 21 | out[channel][frame] = input0->out[channel][frame] - input1->out[channel][frame]; 22 | } 23 | #endif 24 | } 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /source/src/node/oscillators/lfo/lfo.cpp: -------------------------------------------------------------------------------- 1 | #include "signalflow/core/graph.h" 2 | #include "signalflow/node/oscillators/lfo.h" 3 | 4 | namespace signalflow 5 | { 6 | 7 | LFO::LFO(NodeRef frequency, NodeRef min, NodeRef max, NodeRef phase) 8 | : frequency(frequency), min(min), max(max), phase(phase) 9 | { 10 | SIGNALFLOW_CHECK_GRAPH(); 11 | this->create_input("frequency", this->frequency); 12 | this->create_input("min", this->min); 13 | this->create_input("max", this->max); 14 | this->create_input("phase", this->phase); 15 | this->alloc(); 16 | } 17 | 18 | void LFO::alloc() 19 | { 20 | this->current_phase.resize(this->num_output_channels_allocated); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /source/src/node/processors/clip.cpp: -------------------------------------------------------------------------------- 1 | #include "signalflow/node/processors/clip.h" 2 | 3 | namespace signalflow 4 | { 5 | 6 | Clip::Clip(NodeRef input, NodeRef min, NodeRef max) 7 | : UnaryOpNode(input), min(min), max(max) 8 | { 9 | this->name = "clip"; 10 | this->create_input("min", this->min); 11 | this->create_input("max", this->max); 12 | } 13 | 14 | void Clip::process(Buffer &out, int num_frames) 15 | { 16 | for (int channel = 0; channel < this->num_output_channels; channel++) 17 | { 18 | for (int frame = 0; frame < num_frames; frame++) 19 | { 20 | out[channel][frame] = signalflow_clip(input->out[channel][frame], 21 | this->min->out[channel][frame], 22 | this->max->out[channel][frame]); 23 | } 24 | } 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /source/src/node/processors/distortion/waveshaper.cpp: -------------------------------------------------------------------------------- 1 | #include "signalflow/node/processors/distortion/waveshaper.h" 2 | 3 | namespace signalflow 4 | { 5 | 6 | WaveShaper::WaveShaper(NodeRef input, BufferRef buffer) 7 | : UnaryOpNode(input), buffer(buffer) 8 | { 9 | this->name = "waveshaper"; 10 | this->create_buffer("buffer", this->buffer); 11 | } 12 | 13 | void WaveShaper::process(Buffer &out, int num_frames) 14 | { 15 | for (int channel = 0; channel < this->num_output_channels; channel++) 16 | { 17 | for (int frame = 0; frame < num_frames; frame++) 18 | { 19 | float input = this->input->out[channel][frame]; 20 | out[channel][frame] = this->buffer->get(0, input); 21 | } 22 | } 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /source/src/node/processors/dynamics/rms.cpp: -------------------------------------------------------------------------------- 1 | #include "signalflow/node/processors/dynamics/rms.h" 2 | 3 | namespace signalflow 4 | { 5 | 6 | RMS::RMS(NodeRef input) 7 | : UnaryOpNode(input) 8 | { 9 | this->name = "rms"; 10 | } 11 | 12 | void RMS::process(Buffer &out, int num_frames) 13 | { 14 | for (int channel = 0; channel < this->num_output_channels; channel++) 15 | { 16 | double sum_squared = 0; 17 | for (int frame = 0; frame < num_frames; frame++) 18 | { 19 | sum_squared += input->out[channel][frame] * input->out[channel][frame]; 20 | } 21 | double mean_squared = sum_squared / num_frames; 22 | double rms = sqrt(mean_squared); 23 | 24 | for (int frame = 0; frame < num_frames; frame++) 25 | { 26 | out[channel][frame] = rms; 27 | } 28 | } 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /source/src/node/processors/fold.cpp: -------------------------------------------------------------------------------- 1 | #include "signalflow/core/util.h" 2 | #include "signalflow/node/processors/fold.h" 3 | 4 | namespace signalflow 5 | { 6 | 7 | Fold::Fold(NodeRef input, NodeRef min, NodeRef max) 8 | : UnaryOpNode(input), min(min), max(max) 9 | { 10 | this->name = "fold"; 11 | this->create_input("min", this->min); 12 | this->create_input("max", this->max); 13 | } 14 | 15 | void Fold::process(Buffer &out, int num_frames) 16 | { 17 | for (int channel = 0; channel < this->num_output_channels; channel++) 18 | { 19 | for (int frame = 0; frame < num_frames; frame++) 20 | { 21 | out[channel][frame] = signalflow_fold(input->out[channel][frame], 22 | this->min->out[channel][frame], 23 | this->max->out[channel][frame]); 24 | } 25 | } 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /source/src/node/processors/panning/stereo-balance.cpp: -------------------------------------------------------------------------------- 1 | #include "signalflow/node/processors/panning/stereo-balance.h" 2 | 3 | namespace signalflow 4 | { 5 | 6 | StereoBalance::StereoBalance(NodeRef input, NodeRef balance) 7 | : UnaryOpNode(input), balance(balance) 8 | { 9 | this->name = "stereo-balance"; 10 | this->create_input("stereo-balance", this->balance); 11 | this->set_channels(2, 2); 12 | } 13 | 14 | void StereoBalance::process(Buffer &out, int num_frames) 15 | { 16 | for (int frame = 0; frame < num_frames; frame++) 17 | { 18 | sample balance = this->balance->out[0][frame]; 19 | sample left = this->input->out[0][frame]; 20 | sample right = this->input->out[1][frame]; 21 | 22 | balance = 0.5 + (0.5 * balance); 23 | left = left * sqrtf(1 - balance); 24 | right = right * sqrtf(balance); 25 | 26 | out[0][frame] = left; 27 | out[1][frame] = right; 28 | } 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /source/src/node/processors/panning/stereo-panner.cpp: -------------------------------------------------------------------------------- 1 | #include "signalflow/node/processors/panning/stereo-panner.h" 2 | 3 | namespace signalflow 4 | { 5 | 6 | StereoPanner::StereoPanner(NodeRef input, NodeRef pan) 7 | : input(input), pan(pan) 8 | { 9 | this->name = "stereo-panner"; 10 | 11 | this->set_channels(1, 2); 12 | this->create_input("input", this->input); 13 | this->create_input("pan", this->pan); 14 | } 15 | 16 | void StereoPanner::process(Buffer &out, int num_frames) 17 | { 18 | for (int frame = 0; frame < num_frames; frame++) 19 | { 20 | sample pan = this->pan->out[0][frame]; 21 | sample in = this->input->out[0][frame]; 22 | 23 | if (pan < -1) 24 | pan = -1.0f; 25 | if (pan > 1) 26 | pan = 1.0; 27 | 28 | pan = pan * 0.5 + 0.5; 29 | out[0][frame] = in * sqrtf((1.0 - pan)); 30 | out[1][frame] = in * sqrtf(pan); 31 | } 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /source/src/node/processors/wrap.cpp: -------------------------------------------------------------------------------- 1 | #include "signalflow/core/util.h" 2 | #include "signalflow/node/processors/wrap.h" 3 | 4 | namespace signalflow 5 | { 6 | 7 | Wrap::Wrap(NodeRef input, NodeRef min, NodeRef max) 8 | : UnaryOpNode(input), min(min), max(max) 9 | { 10 | this->name = "wrap"; 11 | this->create_input("min", this->min); 12 | this->create_input("max", this->max); 13 | } 14 | 15 | void Wrap::process(Buffer &out, int num_frames) 16 | { 17 | for (int channel = 0; channel < this->num_output_channels; channel++) 18 | { 19 | for (int frame = 0; frame < num_frames; frame++) 20 | { 21 | out[channel][frame] = signalflow_wrap(input->out[channel][frame], 22 | this->min->out[channel][frame], 23 | this->max->out[channel][frame]); 24 | } 25 | } 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /source/src/node/registry.cpp: -------------------------------------------------------------------------------- 1 | #include "signalflow/node/registry.h" 2 | #include "signalflow/patch/patch-spec.h" 3 | #include "signalflow/patch/patch.h" 4 | 5 | #include 6 | 7 | namespace signalflow 8 | { 9 | 10 | static NodeRegistry *registry; 11 | 12 | NodeRegistry::NodeRegistry() 13 | { 14 | } 15 | 16 | NodeRegistry::~NodeRegistry() 17 | { 18 | if (this == registry) 19 | { 20 | registry = 0; 21 | } 22 | } 23 | 24 | NodeRegistry *NodeRegistry::global() 25 | { 26 | if (!registry) 27 | registry = new NodeRegistry(); 28 | return registry; 29 | } 30 | 31 | Node *NodeRegistry::create(std::string name) 32 | { 33 | if (!registry->classes[name]) 34 | { 35 | throw std::runtime_error("Could not instantiate Node (unknown type: " + name + ")"); 36 | } 37 | Node *node = registry->classes[name](); 38 | return node; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /source/src/node/sequencing/block-counter.cpp: -------------------------------------------------------------------------------- 1 | #include "signalflow/node/sequencing/block-counter.h" 2 | 3 | #include 4 | 5 | namespace signalflow 6 | { 7 | 8 | BlockCounter::BlockCounter() 9 | : Node() 10 | { 11 | this->name = "block-counter"; 12 | this->counter = 0; 13 | } 14 | 15 | void BlockCounter::process(Buffer &out, int num_frames) 16 | { 17 | for (int channel = 0; channel < this->num_output_channels; channel++) 18 | { 19 | for (int frame = 0; frame < num_frames; frame++) 20 | { 21 | out[channel][frame] = this->counter; 22 | } 23 | } 24 | this->counter += 1; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /source/src/node/sequencing/index.cpp: -------------------------------------------------------------------------------- 1 | #include "signalflow/node/sequencing/index.h" 2 | 3 | namespace signalflow 4 | { 5 | 6 | Index::Index(std::vector list, NodeRef index) 7 | : Node(), list(list), index(index) 8 | { 9 | this->name = "index"; 10 | 11 | this->create_input("index", this->index); 12 | this->create_property("list", this->list); 13 | } 14 | 15 | void Index::process(Buffer &out, int num_frames) 16 | { 17 | std::vector list = this->list->float_array_value(); 18 | 19 | for (int frame = 0; frame < num_frames; frame++) 20 | { 21 | for (int channel = 0; channel < this->num_output_channels; channel++) 22 | { 23 | int index = (int) this->index->out[channel][frame]; 24 | out[channel][frame] = list[index]; 25 | } 26 | } 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /source/src/node/sequencing/trigger-mult.cpp: -------------------------------------------------------------------------------- 1 | #include "signalflow/node/sequencing/trigger-mult.h" 2 | #include 3 | 4 | namespace signalflow 5 | { 6 | 7 | TriggerMult::TriggerMult(NodeRef a) 8 | : UnaryOpNode(a) 9 | { 10 | this->name = "trigger-mult"; 11 | } 12 | 13 | void TriggerMult::process(Buffer &out, int num_frames) 14 | { 15 | for (int channel = 0; channel < this->num_output_channels; channel++) 16 | { 17 | for (int frame = 0; frame < num_frames; frame++) 18 | { 19 | out[channel][frame] = this->input->out[channel][frame]; 20 | } 21 | } 22 | } 23 | 24 | void TriggerMult::trigger(std::string name, float value) 25 | { 26 | for (auto output : this->get_outputs()) 27 | { 28 | auto output_node = output.first; 29 | output_node->trigger(name, value); 30 | } 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /source/src/patch/patch-registry.cpp: -------------------------------------------------------------------------------- 1 | #include "signalflow/patch/patch-registry.h" 2 | #include "signalflow/patch/patch.h" 3 | 4 | namespace signalflow 5 | { 6 | 7 | PatchRegistry::PatchRegistry() 8 | { 9 | } 10 | 11 | PatchRegistry *PatchRegistry::global() 12 | { 13 | static PatchRegistry *registry; 14 | if (!registry) 15 | registry = new PatchRegistry(); 16 | return registry; 17 | } 18 | 19 | void PatchRegistry::add(std::string name, PatchSpecRef patchspec) 20 | { 21 | this->patchspecs[name] = patchspec; 22 | } 23 | 24 | PatchSpecRef PatchRegistry::get(std::string name) 25 | { 26 | return this->patchspecs[name]; 27 | } 28 | 29 | PatchRef PatchRegistry::create(std::string name) 30 | { 31 | if (!this->patchspecs[name]) 32 | { 33 | throw std::runtime_error("Could not instantiate patch (unknown name: " + name + ")"); 34 | } 35 | PatchRef patch = new Patch(this->patchspecs[name]); 36 | return patch; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /tests/audio/440hz.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ideoforms/signalflow/b5fc3c931995ddabe8bc963ee00a5c02ea7888c3/tests/audio/440hz.wav -------------------------------------------------------------------------------- /tests/test_config.py: -------------------------------------------------------------------------------- 1 | from signalflow import AudioGraph, AudioGraphConfig 2 | from . import graph 3 | import pytest 4 | 5 | def test_config(graph): 6 | assert graph.config.sample_rate >= 0 7 | --------------------------------------------------------------------------------