goofi v3.0.0

Biotuner

Explore scales, spectra, rhythms, and moving voices with Biotuner and core nodes.

Biotuner — illustrated recipe guide

Five focused experiments using shipped nodes and standard viewers. Every calculation remains visible in the patch, with relevant controls beside the results.

Start here

Enable Biotuner and Signal; recipes 3 and 4 also use Audio. Each download opens in one Explore tab with a patch, two viewers, and controls.

Peaks and tuning calculations use existing nodes. Recipe 2 includes a reusable FmSignal source. Recipe 5 includes PaletteView for labeled swatches and gradients. Recipe 3 includes RhythmView, a reusable display for any rhythm grid, with optional playhead and gate inputs.

Open the first recipe ↓ Bundle setup →

Meet the nodes

Use the node pictures to find the inputs and outputs. Each experiment points to a recipe you can build on.

01 / SIGNAL
TuningReduction py
input
reduced

Choose a smaller scale

Try it. Change mode/n_steps from 5 to 3 and compare the remaining ratios.

Good to know

The output keeps a fixed width. Empty positions are NaN when the input has fewer degrees.

Inputs: input: ARRAY

Outputs: reduced: ARRAY

02 / SIGNAL
TuningMatrix py
input
matrix
metricPerStep
metric

Compare intervals in a scale

Try it. Open matrix as an image and compare dyad_similarity with consonance under matrix/function.

Good to know

These scoring methods have different scales. Compare results within one method.

Inputs: input: ARRAY

Outputs: matrix: ARRAY · metricPerStep: ARRAY · metric: ARRAY

03 / SIGNAL
BioColors py
input
amps
rgb
lightness
chroma
hue
hex

Turn peaks or tuning ratios into an RGB palette.

Try it. In recipe 5, compare two methods on the same tuning, then adjust Interval or BaseHz.

Good to know

Choose tuning for ratios and peaks for frequencies in Hz. Leave calibration at none unless you have fitted calibration data.

Inputs: input: ARRAY · amps: ARRAY

Outputs: rgb: ARRAY · lightness: ARRAY · chroma: ARRAY · hue: ARRAY · hex: STRING

04 / SIGNAL
TimbreControls py
input
gate
partials
amplitudes
weights
brightness
spread
harmonicity
pitch
gain
gate
voices

Shape a set of partials

Try it. Add this node to the linked recipe to explore another way of reading its musical data. Compare one setting at a time.

Good to know

partials is in hertz; pitch uses volts per octave. Normalized brightness needs a range mapping before it controls a filter cutoff.

Inputs: input: ARRAY · gate: ARRAY

Outputs: partials: ARRAY · amplitudes: ARRAY · weights: ARRAY · brightness: ARRAY · spread: ARRAY · harmonicity: ARRAY · pitch: ARRAY · gain: ARRAY · gate: ARRAY · voices: ARRAY

05 / SIGNAL
ScaleForaging py
input
tuning
similarity
changed

Hold a scale until a suitable one arrives

Try it. Add this node to the linked recipe to explore another way of reading its musical data. Compare one setting at a time.

Good to know

foraging/rate sets the minimum time between accepted changes. Reset to accept the next candidate as a fresh start.

Inputs: input: ARRAY

Outputs: tuning: ARRAY · similarity: ARRAY · changed: ARRAY

06 / SIGNAL
MicrotonalKeys py
input
notes
voices
pitch
gate
velocity
freq

Play notes through a tuning

Try it. Add this node to the linked recipe to explore another way of reading its musical data. Compare one setting at a time.

Good to know

This node needs note events as well as a tuning. See its documentation for the notes array format; a ratio list alone does not play notes.

Inputs: input: ARRAY · notes: ARRAY

Outputs: voices: ARRAY · pitch: ARRAY · gate: ARRAY · velocity: ARRAY · freq: ARRAY

07 / SIGNAL
VitalPreset py
input
partials
amplitudes
signal
path
files

Save a tuning as a synth preset

Try it. Add this node to the linked recipe to explore another way of reading its musical data. Compare one setting at a time.

Good to know

Writing creates files in the chosen folder. Load the result in Vital and supply notes to hear it. A periodic wavetable cannot retain every inharmonic pitch exactly.

Inputs: input: ARRAY · partials: ARRAY · amplitudes: ARRAY · signal: ARRAY

Outputs: path: STRING · files: TABLE

08 / SIGNAL
Peaks py
input
peaks
amps

Find the strongest frequencies

Try it. In recipe 02, compare peaks with the known 8, 12, and 16 Hz components of the practice signal.

Good to know

Input is a waveform with sample-rate metadata. amps contains power in dB, and missing peaks are padded with NaN.

Inputs: input: ARRAY

Outputs: peaks: ARRAY · amps: ARRAY

09 / SIGNAL
Tuning py
input
amps
tuning

Build a scale from peaks

Try it. Compare peaks_ratios and harmonic_tuning under tuning/method.

Good to know

Input frequencies are in hertz; output degrees are ratios. diss_curve also requires the aligned amps output from Peaks.

Inputs: input: ARRAY · amps: ARRAY

Outputs: tuning: ARRAY

10 / SIGNAL
Harmonicity py
input
harmsim
tenney
cons
subharmTension

Measure the relationships between peaks

Try it. Add this node to the linked recipe to explore another way of reading its musical data. Compare one setting at a time.

Good to know

Higher harmsim means greater harmonic similarity; higher tenney means greater ratio complexity. They move on different scales.

Inputs: input: ARRAY

Outputs: harmsim: ARRAY · tenney: ARRAY · cons: ARRAY · subharmTension: ARRAY

11 / SIGNAL
HarmonicSpectrum py
input
spectrum
freqs
peaks
peakValues
matrix
harmonicity
complexity
activation
power
waveform
analysis

Find harmonic structure across a spectrum

Try it. Add this node to the linked recipe to explore another way of reading its musical data. Compare one setting at a time.

Good to know

Supply at least sample rate ÷ spectrum/precision samples. peakValues are harmonicity scores, so do not use them as Peaks.amps.

Inputs: input: ARRAY

Outputs: spectrum: ARRAY · freqs: ARRAY · peaks: ARRAY · peakValues: ARRAY · matrix: ARRAY · harmonicity: ARRAY · complexity: ARRAY · activation: ARRAY · power: ARRAY · waveform: ARRAY · analysis: TABLE

12 / SIGNAL
HarmonicObservatory py
analysis
dashboard

See one analysis window as a dashboard

Try it. Add this node to the linked recipe to explore another way of reading its musical data. Compare one setting at a time.

Good to know

Connect HarmonicSpectrum.analysis so all panels describe the same window. Refresh the channel list after changing inputs.

Inputs: analysis: TABLE

Outputs: dashboard: ARRAY

13 / SIGNAL
BioElements py
input
amps
elements
scores
ranked
categories

Explore spectral matches to element line lists

Try it. Add this node to the linked recipe to explore another way of reading its musical data. Compare one setting at a time.

Good to know

These are mathematical matches between spectra. A match does not identify an element in a recording or establish its physical presence.

Inputs: input: ARRAY · amps: ARRAY

Outputs: elements: TABLE · scores: ARRAY · ranked: STRING · categories: STRING

14 / AUDIO
BioFilter rs
input
peaks
amps
out

Use peaks to shape an audio filter

Try it. Add this node to the linked recipe to explore another way of reading its musical data. Compare one setting at a time.

Good to know

peaks and amps are audio ports. Keep peak values in hertz: shift raises the filter centres by octaves. Add Gain and AudioOut when you are ready to listen.

Inputs: input: AUDIO · peaks: AUDIO · amps: AUDIO

Outputs: out: AUDIO

15 / SIGNAL
EuclidRhythm py
input
patterns
steps

Make pulse patterns from ratios

Try it. Add this node to the linked recipe to explore another way of reading its musical data. Compare one setting at a time.

Good to know

Rows may have different lengths. steps tells you the length before padding.

Inputs: input: ARRAY

Outputs: patterns: ARRAY · steps: ARRAY

16 / SIGNAL
Polyrhythm py
input
voices
coincidences
labels
cycle

Put several rhythms on a shared grid

Try it. Compare poly/method values euclid and iso. Watch coincidences for steps where voices meet.

Good to know

poly/cycleCap limits the shared grid. The node may simplify ratios to fit that limit.

Inputs: input: ARRAY

Outputs: voices: ARRAY · coincidences: ARRAY · labels: STRING · cycle: ARRAY

17 / SIGNAL
RhythmPlayer py
input
gate
step
phase

Move through a rhythm at a tempo

Try it. Change player/bpm from 90 to 120 and watch step and gate.

Good to know

Gate values are controls, not sound. player/length changes how much of each step stays on.

Inputs: input: ARRAY

Outputs: gate: ARRAY · step: ARRAY · phase: ARRAY

18 / SIGNAL
RatioSequence py
clock
transition

Move between ratios over time

Try it. Compare sequence/direction values forward and ping-pong. Turn sequence/running off to pause.

Good to know

transition carries endpoints and timing together. Connect it to HarmonicMorph.transition.

Inputs: clock: ARRAY

Outputs: transition: ARRAY

19 / SIGNAL
HarmonicMorph py
a
b
ampsA
ampsB
phasesA
phasesB
mix
transition
harmonic

Move smoothly between chords

Try it. Pause RatioSequence to inspect a chord, then adjust morph/stretch slightly above and below 1.

Good to know

The harmonic output includes ratios, weights, and phases. Use nodes that understand that structure, such as HarmonicVoices.

Inputs: a: ARRAY · b: ARRAY · ampsA: ARRAY · ampsB: ARRAY · phasesA: ARRAY · phasesB: ARRAY · mix: ARRAY · transition: ARRAY

Outputs: harmonic: ARRAY

20 / SIGNAL
HarmonicVoices py
input
pitch
gain

Keep pitch and gain changes together

Try it. Watch pitch and gain while the sequence runs. Set sound/level to 0 and notice that pitches remain while gains become zero.

Good to know

The voice count stays fixed, including silent components. These arrays need an audio control route to make sound.

Inputs: input: ARRAY

Outputs: pitch: ARRAY · gain: ARRAY

Patch recipes

RECIPE 01

Shape a scale

Build a tuning by stacking an interval. Compare its reduced scale with a pairwise similarity matrix.

Shape a scale — example node outputs
Example data from the patch. Open the download to explore it with standard Goofi viewers.

Download patch ↓

  1. Start with Interval at 1.5, a perfect fifth. Read the full and reduced ratios beside the matrix.
  2. Change Interval slightly and watch how the relationships change.
  3. Change KeepDegrees, keeping it no larger than ScaleSize.
Constant.outTuning.input
Tuning.tuningTuningReduction.input
Tuning.tuningTuningMatrix.input
Tuning.tuningBioColors.input

What to look for. Tuning folds stacked intervals into an octave. TuningReduction keeps selected degrees; the matrix scores each pair on the same 0-100 dyad-similarity scale.

Try it

Compare intervals 1.5 and 1.3333 with the same scale size. Expand BioColors in the patch to see the palette generated from the tuning.

ScaleSize counts generator steps, not a fixed equal-tempered division. The Text panel reads the actual node outputs; it does not calculate another tuning.

RECIPE 02

Change the spacing, change the tuning

Explore how frequency modulation changes spectral peaks and the ratios derived from them.

Change the spacing, change the tuning — example node outputs
Example data from the patch. Open the download to explore it with standard Goofi viewers.

Download patch ↓

  1. Allow four seconds for the spectrum to settle. The carrier stays at 18 Hz.
  2. With ModulationDepth at 1.2, compare PeakSpacing at 4, 5, and 7 Hz. Wait four seconds after each change.
  3. Read the detected frequencies and tuning ratios beside the spectrum.
FmSignal.outBuffer.input
Buffer.outPsd.input
Buffer.outPeaks.input
Peaks.peaksTuning.input
Peaks.ampsTuning.amps

What to look for. PeakSpacing controls the modulation frequency: sidebands appear around the carrier at multiples of this spacing. Changing spacing changes their frequency ratios, rather than simply transposing the spectrum.

Try it

Set ModulationDepth to 0 for a single sine wave, then return to 1.2. Depth changes sideband strengths, so Peaks may select a different set of frequencies.

Peaks measures the strongest peaks between 2 and 40 Hz at 0.5 Hz precision. Ratios may change in steps, and fewer peaks may be present than PeakCount. FmSignal is an embedded, reusable FM source; the analysis uses existing nodes.

RECIPE 03

Hear the interlocking rhythms

Hear the first rhythm as a low pulse and the other lanes as a brighter voice, while following their patterns on screen.

Hear the interlocking rhythms — example node outputs
Example data from the patch. Open the download to explore it with standard Goofi viewers.

Download patch ↓

  1. Follow the first lane in RhythmView while listening to the low sine pulse. The other lanes trigger the higher triangle voice.
  2. Change LowTone and HighTone independently. Use LowPitch and HighPitch to separate their registers, and each Decay to shape its attack into a short tick or longer tone.
  3. Change Interval and Pattern to reshape the rhythm. Tempo and Subdivision set the pace; Running pauses playback and Volume sets the level.
Constant.outTuning.input
Tuning.tuningPolyrhythm.input
Polyrhythm.voicesRhythmPlayer.input
RhythmPlayer.gateBuffer.input
Polyrhythm.voicesRhythmView.patterns
RhythmPlayer.stepRhythmView.step
RhythmPlayer.gateRhythmView.gates
RhythmPlayer.gateSelect.input
Select.outSignalIn.input
Osc.outGain.input
Gain.outMixdown.input
RhythmPlayer.gateSelect2.input
Select2.outSignalIn2.input
Osc2.outGain2.input
Gain2.outMixdown.input
Mixdown.outAudioOut.input

What to look for. Select separates the first gate lane from the remaining lanes. Each group has its own SignalIn, Env, Osc, and Gain, so its timbre can change independently. Mixdown combines both groups for AudioOut.

Try it

Keep the rhythm fixed. Compare a low sine with a high square, then swap their tones. Listen for the moments when both groups strike together.

AudioOut uses the default output device; select another in its parameters if needed. Pattern changes can create more lanes: all lanes after the first share the high voice settings. Keep GateLength at 0.5 or above at the fastest settings.

RECIPE 04

Hear one voice move

Listen to a three-note chord: two notes stay fixed while the middle note travels through a ratio sequence.

Hear one voice move — example node outputs
Example data from the patch. Open the download to explore it with standard Goofi viewers.

Download patch ↓

  1. Raise Volume gently from zero to hear the chord. Follow the moving trace beside the two steady pitch traces.
  2. Set Glide to 0 for immediate steps, then 0.9 for smooth movement. StepSeconds sets how long each step lasts.
  3. Try sine for a pure tone or triangle for more harmonics. Room adds reverb, Width spreads the voices, and Octave moves the whole chord up or down.
RatioSequence.transitionHarmonicMorph.transition
HarmonicMorph.harmonicHarmonicVoices.input
HarmonicVoices.pitchBuffer.input
HarmonicVoices.pitchSignalIn.input
HarmonicVoices.gainSignalIn2.input
Osc.outGain.input
Gain.outMixdown.input
Mixdown.outReverb.input
Reverb.outAudioOut.input

What to look for. RatioSequence supplies both endpoint chords and their transition progress through one cable. HarmonicMorph needs only its transition input here; leave its other inputs disconnected. HarmonicVoices supplies the actual pitch and gain for each oscillator voice.

Try it

Set Room to 0 and listen to the changing intervals clearly. Then add a little reverb. Running holds the current chord when switched off; use Volume to silence it.

The patch opens muted. SignalIn.out controls Osc.osc.pitch, and SignalIn2.out controls Gain.gain.gain through parameter references. AudioOut uses your default output device. No custom synthesis node is needed.

RECIPE 05

One tuning, different colors

Compare two ways of turning the same tuning into color. Watch the swatches change together, then freeze the motion and inspect the differences.

One tuning, different colors — example node outputs
Example data from the patch. Open the download to explore it with standard Goofi viewers.

Download patch ↓

  1. Start with spectral on the left and physical on the right. Both BioColors nodes receive the same tuning and base frequency.
  2. Set Motion to 0 to hold a tuning. Change Interval and BaseHz separately, watching which colors respond.
  3. Compare spectral with tonotopic, then consonance with tenney. Restore Motion to 0.08 for a gentle sweep; Speed controls its pace.
Constant.outTuning.input
Tuning.tuningBioColors.input
Tuning.tuningBioColors2.input
BioColors.rgbPaletteView.input
BioColors2.rgbPaletteView2.input

What to look for. The numbered swatches show exact BioColors RGB values, with their hex codes. The ribbon blends those swatches to show how the palette might look as a gradient. The same degree occupies the same position in both panels.

Try it

First compare frequency-based methods: spectral and physical. Then compare interval-based methods: consonance, harmonic, and tenney. Keep all other controls fixed so you can see the effect of the mapping alone.

These are alternative mappings, not a unique natural color for a sound. BaseHz supplies the frequency of ratio 1; some methods respond more to relative intervals. Calibration stays at none. PaletteView only draws the output colors and performs no color mapping.

Working practice

Keep frequencies and ratios distinct

Peaks are measured in hertz. Tuning degrees are relative to a root. Check which one a node expects before connecting it; both use array ports, so the cable colour alone cannot tell you.

Use one source for related changes

Branch a tuning to several views, or share HarmonicMorph’s output with sound and geometry. This keeps each view tied to the same musical change.

Connect an output to a parameter → · All cookbooks