Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Layer report

analyze writes layers.json, the report that an agent reads before it writes an edit list. This page lists the fields of version layers/1. The committed JSON Schema, schemas/layers.schema.json, holds the same contract, and the test suite validates every generated report against it.

Top level

FieldValue
schema"layers/1".
sourceThe file name of the stem, without its folder. A run of another stem into the same folder stops unless --force is given.
source_sha256The SHA-256 of the stem file’s bytes, in lower-case hex. A run into the same folder of a stem with the same name and other bytes stops unless --force is given. Such a stem is another stem of that name or a new export of this one. A report without it, from release 0.31 or earlier, is matched by source alone.
synthThe --synth value, "vital" or "serum2". Later mappers pick the synth from it; the layer fields stay synth-neutral.
stemThe stem group below.
transcriptionThe transcriber’s model and settings, the group below. null with --notes, which skips the transcriber.
notesThe final note list of notes.mid, the group below. null without notes.
pitchThe pitch layer group below: glides, pitch drops and vibrato.
voicesThe voices layer group below: the count of voices and the joins of a mono line.
envelopeThe envelope layer group below: the amplitude envelope of the notes and the sidechain pump.
conventionsThe convention of every number in stem and of every record of the layer groups, keyed by its field name, plus frame_size, statistics, spectral and confidence.

The top level takes no other field. notes is no layer group. Each layer adds one group with values, confidence, flags, needs_render, suggested_edits and unrepresentable, and extends the schema in the same change. A group with too little evidence writes values: null and says why in its confidence. values holds plain numbers with the unit in the field name.

suggested_edits is a list of records in the edit-list format, each a param or a route with unit strings, so a route keeps its source, amount and polarity. Each record’s reason is the group’s name. The mapper of the report’s synth fills the list; see Suggested edits.

unrepresentable lists the values of the group that the synth cannot reach:

FieldValue
fieldThe path of the value in the group’s values, with a dot into a list’s records, such as glides.time_s.
wantedThe measured value, {"value": 20.0, "unit": "s"}, or a choice name. The unit is count for a whole number and empty for a stored value without a unit.
nearestThe nearest value the synth reaches, in the same form. Absent when it has none.
reasonabove_range, below_range, no_such_choice, not_in_synth or slot_limit.
residualnearest minus wanted, when both are numbers in one unit.

A synth whose mapper writes no edit for a group leaves both lists empty. Vital writes none for the pitch, voices and envelope groups yet.

The pitch group breaks reports of layers/1 from releases up to 0.23: suggested_edits changed from an object of numbers to a list of records, pitch is a new required top-level key, and conventions requires the keys pitch, glides, drops, sub_band_line and vibrato. A reader of older reports keeps their schema.

The envelope group breaks reports of layers/1 from releases up to 0.25: envelope is a new required top-level key, and conventions requires the keys envelope, note_off, level_spread_db and pump.

The tail breaks reports of layers/1 from releases up to 0.27: values of envelope requires release_s, tail_rt60_s, tail_weight, release_confidence, tail_votes, tail_vote_count and tail_is_reverb, and conventions requires the key tail.

The voices group breaks reports of layers/1 from releases up to 0.26: voices is a new required top-level key, and conventions requires the keys voices and joins.

The mapping lists break reports of layers/1 from releases up to 0.28.x: every group requires unrepresentable, and a suggested_edits record must be a param or a route with a reason.

The notes group breaks reports of layers/1 from releases up to 0.30: notes is a new required top-level key, and conventions requires the key notes.

The checksum breaks reports of layers/1 from releases up to 0.31: source_sha256 is a new required top-level key.

The transcription group

The group records what produced the notes, so a note that flips between two machines can be traced to its settings.

FieldValue
model_sha256The SHA-256 of the bundled model weights, 64 lowercase hex digits.
crate_versionThe version of the transcription crate, "0.1.0".
profileOne of "bass", "lead", "pad" and "detected", the last when the stem chose the settings.
note_paramsEvery decoder parameter by the crate’s own name: onset_threshold, frame_threshold, minimum_note_length_ms, minimum_frequency, maximum_frequency (both in Hz), infer_onsets, melodia_trick, include_pitch_bends, energy_tolerance and bend_offset. Numbers and booleans only.

The notes group

The notes that analyze writes to notes.mid: the cleaned note list rewritten with the pitch, voices and envelope groups. The analyze guide explains the rules.

FieldValue
file"notes.mid".
ticks_per_beat480.
velocity"level" when level_spread_db exceeds 3 dB and each velocity follows the note’s level, else "constant", 100 for every note.
droppedThe notes of a mono line left out because another started on the same tick. Of such notes one stays: a note without the octave flag before one with it, then the longer, then the lower key.
bend_eventsThe pitch-bend events in the file. A note of a mono line whose f0 contour stays 50 cents or more off its key, on one side, for at least the tracker’s reach of the note (a quarter frame plus one period), outside every glide, drop and vibrato span, gets bends, clamped to 2 semitones; every other note gets none. A host must set a bend range of 2 semitones; render reads no bend.
listOne record per written note, by start, then key.

A note record:

FieldUnitRangeValue
onset_sseconds0 or moreThe note-on tick in seconds: round(seconds * bpm / 60 * 480) ticks.
end_ssecondsabove 0The note-off tick in seconds.
list_onset_sseconds0 or moreThe onset in the cleaned note list; the earliest onset of the notes a pitch drop merged.
list_end_ssecondsabove 0The end in the note list; the latest end of the notes a pitch drop merged.
keyMIDI note0 to 127The written key.
velocity1 to 127The written velocity.
end_ruleWhat set the end: knee, no_knee (50 ms before the list end, read without a knee), unread (the same cut for a note the envelope layer skipped), pad (20 dB under the plateau on a polyphonic line, no later than the list end), minimum (the decoder’s minimum length by the BPM rule), next_note (the next note of a mono line) or glide (5 ms after the next note-on, at a glide join).
level_dbdBanyThe note’s full-band level, as level_spread_db defines it; the highest of the notes a pitch drop merged; read from the note’s start to its end before the joins and cuts of a mono line, on a mono line no later than the next later onset, when that span holds no frame. Unlike peak_db, it compares notes on different harmonics. null when neither span holds a frame.
octave_uncertainflagThe transcriber’s octave flag of the note; null when no transcriber ran.

Naming

  • Field names are snake_case ASCII.
  • A field with a unit carries it as a suffix: _hz, _s, _ms, _db, _dbfs, _deg, _st (semitones) or _ct (cents). A field without a suffix is a count, a ratio, a share from 0 to 1, a power, a flag or a tempo in BPM.
  • Integers are written as integers; every other number is a float.

Value objects

A single estimate is {"value": ..., "confidence": ...}. A statistic over active frames is {"median": ..., "iqr": ..., "confidence": ...}, the median and the interquartile range. The value, or the median and the IQR, is null exactly when the confidence states no estimate.

The confidence object follows the units page:

{"level": "high", "reasons": [{"code": "active_frames", "value": 412}], "spread": 310.0, "estimate": true}
  • level is low, medium or high.
  • reasons holds at least one {code, value} pair. The value is a count, a number or a flag.
  • spread is optional, in the unit of the value: the IQR of a statistic, one bin width for the band edge.
  • "estimate": false means no value. Such an object has reasons and neither a level nor a spread.
  • An unknown field is an error.

The stem group

Every statistic over frames, band_share and band_edge_hz need at least 16 active frames; with fewer they give no estimate with the reason too_few_frames. The ranges are those of the unit types and the schema. Each convention is the text that conventions holds under the same key; the pipeline page explains the rules behind them.

FieldUnitRangeShapeConvention
bpmbeats per minute4 to 1000numberThe tempo of the beat grid and of every later step: bpm_refined when its confidence is high, else bpm_given.
bpm_givenbeats per minute4 to 1000numberGiven by --bpm.
bpm_refinedbeats per minute4 to 1000valueThe tempo refined from the onsets, from 2.91 % below to 3.09 % above bpm_given, in 0.01 BPM steps; see the tempo section. Its reasons give tempo_peak, beat_periodicity, sparse_periodicity, onset_sharpness, onsets_per_beat and the whole beats of the stem as cycles_in_span, both counted at the slowest tempo of the search, bpm_given / 1.03. No value with --bpm-exact (bpm_exact), for a stem of fewer than 8 such beats or for one without onsets.
duration_sseconds0 or morenumberDecoded frames over the sample rate.
sample_rate_hzhertz8000 to 192000integerThe native rate of the file; no resampling.
band_edge_hzhertz0 to NyquistvalueThe steepest fall of at least 25 dB per semitone above 2 kHz on a plateau, else the highest bin 30 dB above the floor at low confidence.
hard_limitedflagbooleanFlat runs of at least 1 ms within 1e-5 of the channel peak, entered and left from at least half the peak, cover 0.1 % of one of the first two channels.
peak_dbfsdB re full scale 1.00 or less for unclipped audiovaluePeak of the mono mix over the whole stem.
rms_dbfsdB re full scale 1.0below peak_dbfsvalueRMS of the mono mix over the whole stem; a full-scale sine reads -3.01 dB.
crest_dbdB0 or morevaluepeak_dbfs - rms_dbfs.
centroid_hzhertz0 to NyquiststatisticMagnitude-weighted mean frequency per active frame.
centroid_over_f0ratio0 or morestatistic or nullThe centroid over the median f0 of the note list; null without --notes.
spread_hzhertz0 or morestatisticMagnitude-weighted standard deviation around the centroid.
rolloff85_hzhertz0 to NyquiststatisticFrequency below which 85 % of the frame’s magnitude lies.
rolloff95_hzhertz0 to NyquiststatisticThe same at 95 %.
flatnessratio0 to 1statisticGeometric over arithmetic mean of the magnitude, 100 Hz to 10 kHz, floored at 1e-5.
band_shareshareeach 0 to 1, sum 1value with a listPower per band over active frames divided by the power in the bands reported; each item is {lo_hz, hi_hz, share} for the bands 20, 60, 250 Hz, 1, 4, 10 and 20 kHz. A band at or above the Nyquist frequency is left out, and one that crosses it ends there.
stereoobjectSee below.

stereo holds full, sub (below 120 Hz), low_mid (120 Hz to 1 kHz) and high (above 1 kHz), each {rho, sm_db, ipd_deg}, and one confidence for the screen:

FieldUnitRangeConvention
rhocorrelation-1 to 1Pearson correlation of L and R at zero lag; per band from the 8192-point STFT.
sm_dbdBany20 log10(rms(S) / rms(M)) with M = (L + R) / 2, S = (L - R) / 2.
ipd_degdegrees0 to 180The magnitude-weighted phase difference of L and R at harmonics 1 to 20 of the median f0, averaged over active frames; null without --notes.

A stereo value is null when it does not exist: a one-channel file, a silent channel, or a zero mid or side.

The pitch group

The pitch layer of a monophonic line; the pitch layer page explains each method. Every record carries its own confidence, always an estimate. The group’s own confidence is medium, or low when fewer than half of the track frames inside the notes are voiced within 100 cents of a sounding note, as under noise or DC. Its reasons are voiced_frames, the voiced frames of the f0 track, and note_frames, that share.

values is null when the line plays chords (reason polyphonic_line) or the stem has no notes (reason no_note_list). Otherwise it holds three lists, each in time order and each empty when nothing was found: glides, drops and vibrato. Every time is audio time from the start of the stem.

A glide:

FieldUnitRangeValue
start_sseconds0 or moreThe fitted start of the motion.
interval_stsemitonesanyFrom the start pitch to the end pitch; negative for a glide down.
time_sseconds0.09 or moreThe full 0 to 100 % time.
curvepowerabove 0.21, at most 5p of s(x) = 1 - (1 - x)^p: above 1 starts fast, 1 is linear in pitch. A fit within 5 % of the lower bound 0.2 is no glide; one within 5 % of the upper bound 5, such as an exponential portamento, needs a detected span of at most 2.5 times its fitted time, and reads low with curve_bound.
from_silenceflagThe glide leads into the first stable pitch of a voiced run whose sound starts up to 100 ms before it. That stable pitch has a median level within 40 dB of the loudest frame, and the pitch does not swing back half the lead within 167 ms after it, unless the run’s next stable pitch lies 100 cents or more away and matches another note, and the pitch, once past half the way to it, stays there up to that stable pitch and to the window’s end.

Its reasons are motion_span (seconds), fit_residual (cents), pitch_jitter (cents) and curve_bound (flag). A glide whose motion_span is under 0.09 reads low.

A drop:

FieldUnitRangeValue
onset_sseconds0 or moreThe onset of the strike from the band envelope.
f_end_hzhertzabove 0The settled frequency.
df_stsemitonesabove 2, at most 36The drop at the onset, 12 log2((f_end + df) / f_end).
df_hzhertzabove 0The same in hertz above f_end_hz.
tau_ssecondsabove 0.003The time constant of f_end + df exp(-t / tau), above the 3.04 ms floor of the search.
residualshare0 to 0.15The RMS residual of the fit over the fall it shows from 7 ms on, df_hz exp(-7 ms / tau_s); with tau_s of 0.01 or more, of the error averaged over half a period of f_end_hz, or over a full period when tau_s spans 1.5 periods or more.

Its reasons are fit_residual and attack_time (seconds): the time the band envelope of the strike takes from 10 % to 90 % of its peak. A drop with an attack over 30 ms reads low, and one with tau_s under 0.01 or an attack over 12 ms at most medium.

A vibrato:

FieldUnitRangeValue
start_s, end_sseconds0 or moreThe first and last frame read.
rate_hzhertz2.97 to 12.12The rate, 3 to 12 Hz with 1 % slack.
extent_ctcents10 or moreHalf the peak-to-peak swing, after the correction.
extent_raw_ctcents0 or moreThe same as the f0 track reads it.
extent_factorratioabove 0The correction for the track’s smoothing at this rate; extent_ct = extent_raw_ct * extent_factor.
shareshare0.5 to 1The power the fitted sine explains over the power left after the line alone.

Its reasons are sine_share, cycles_in_span and contour_kurtosis. A vibrato holds 2.5 cycles or more; from 4 it reads high. A kurtosis below 1.25 reads low, since the contour jumps between two levels, as a trill does, and so does a vibrato on a pitch below 100 Hz.

flags holds four booleans: chord_skipped, glide_too_short (a motion between two notes lasted 35 to 90 ms over its fitted time, or over its detected span when the fit failed), weak_fundamental (a low note’s second harmonic exceeded its fundamental by 6 dB, so its drop was not reported) and no_notes. At a sample rate under about 4 times a note’s pitch the second harmonic cannot be measured, and that note is not tested for weak_fundamental. needs_render is false.

The voices group

The count of voices, read on any line, and the joins of a mono line; the voices layer page explains each method. values is null without notes (reason no_note_list) or when no note holds a sounding part in the stem (reason too_few_notes). The group’s confidence reads the share of the held time whose count agrees with the verdict (reason count_agreement). flags is empty and needs_render is false.

FieldUnitRangeMeaning
monomax_polyphony is 1.
max_polyphonycount1 or moreThe most voices that have started by any onset and are held 50 ms after it.
mean_polyphonycount0 or moreThe mean count over the time any note is held; it can exceed max_polyphony.
joinsOne record per join, in time order; empty on a line that is not mono.

A join record:

FieldUnitRangeMeaning
time_sseconds0 or moreThe later note’s onset.
gap_msmillisecondsunder 30The later onset minus the earlier end in the note list; negative when they overlap there.
dip_dbdB0 or moreHow far the level falls at the join under the quieter note; null when neither note has a level beside the join.
centroid_changeratioThe centroid over f0 after the join over the same before it, minus 1; null when either side holds no signal or runs past either end of the stem.
legatodip_db is under 1; null without a dip.
confidenceLow when the verdict is legato (reason level_kept_at_join), no attack was read (no_attack_read), the stem’s edge reaches a level window beside the join (stem_edge_at_join) or the median attack is over 100 ms (attack_hides_join), else medium; no estimate without a dip.

The envelope group

The amplitude envelope over the pooled notes, each read note’s record, and the sidechain pump; the envelope layer page explains each method. values is null when no note was read: the stem has no notes (reason no_note_list) or every note was skipped (reason too_few_notes). The group’s own confidence is medium with 3 or more pooled notes, else low.

FieldUnitRangeValue
attack_sseconds0 or moreStatistic: 1.25 times the 10 to 90 % rise of each pooled note to the attack’s top, its full time for a linear ramp. An upper bound when attack_is_upper_bound is set.
hold_sseconds0 or moreStatistic: the time at the peak before the decay, 0 under 10 ms.
decay_sseconds0 or moreStatistic: the fall from the peak to the sustain level, from the 10 and 90 % shares of the fall in dB.
sustain_dbdB0 or lessStatistic: the level of the last 30 % of the held part, from the peak.
note_off_offset_ssecondsanyStatistic: the note’s end in the note list, or the stem’s end when that comes first, minus its note-off knee, over the pooled notes with a knee.
release_sseconds0 or moreStatistic: the linear release of each pooled note with a tail fit; null when the median tail_weight is over 0.5 (reason tail_weight, a tail too heavy) or the median residual is over 3 dB (reason tail_residual).
tail_rt60_sseconds0 or moreStatistic: the RT60 of the tail, over the notes with a tail_weight of 0.05 or more whose frames span a 15 dB fall of it, leaving out notes that read as heavy and smooth or under what their band shows; null with tail_light, a tail too light, under a median tail_weight of 0.05, and with tail_smooth when the tail is heavy and smooth, as the note’s own exponential release is, and with tail_band when it fades faster than the band of an overlapping note shows.
tail_weightratio0 or moreStatistic: the tail’s level at the note-off over the level before it.
release_confidencemedium, low or nulllow when no release_s is written, the level of release_s otherwise, which reads low with tail_wobble when the level wobbles over the hold and the fit is poor, null when no pooled note has a fit.
tail_votesFive signs that the tail is reverb, each true, false or null when nothing could be read: outlasts_gap, side_grows, flatness_rises, same_rate, high_band_faster.
tail_vote_countcount0 to 5The votes that are true.
tail_is_reverbfalse until a space layer exists.
level_spread_dbdB0 or moreValue: the 90th minus the 10th percentile of the full-band levels of the pooled notes; always low. A note’s full-band level is the peak of the centred RMS of the mono mix over one period of its fundamental, or the fewest whole periods that span 2 ms, on a 1 ms hop, from its onset to its note-off knee, or to 50 ms before its list end without one, never past the next later onset on a mono line, in dB of full-scale power.
ripple_dbdB0 or moreThe median ripple of the sustain window after its line; null without a sustain.
fit_residual_dbdB0 or moreThe median RMS of the held parts against the hold, decay and sustain model.
n_notes_usedcount0 or moreThe pooled notes.
overlap_fractionshare0 to 1The share of the notes in the list that overlap another.
pump_depth_dbdB0 or moreMinus the minimum of the pump curve; null with fewer than 4 counted beats.
pump_recovery_sseconds0 or moreFrom the curve’s minimum back to within 1.5 dB, over the beat’s wrap; null when it does not within a beat.
pump_tau_msmilliseconds0 or morepump_recovery_s over ln(pump_depth_db / 1.5), the one time field in milliseconds; null unless the pump locks to the beat.
pump_locked_tobeat, note, free or none; null without a pump.
pump_beatscount0 or moreThe beats behind the curve.
pump_bpmBPMabove 0The tempo the curve was read at: bpm for a read that stays on the grid, or a fitted tempo up to 2.81 % from it, by the longest run of counted beats, when that read replaced it. A sidechain’s rate follows a fitted tempo closely. A read that stays on the grid says only that the duck locks there: up to 2.56 % off on generated ducks, as the envelope page says. null without a pump.
notesOne record per read note, in note order.

A statistic reads low over fewer than 3 notes or with an interquartile range above half its median. Its reasons are too_few_notes and relative_spread; attack_s adds upper_bound_share, the share of the pooled attacks that are upper bounds. A median of 0 under an interquartile range above 0 has no ratio, so the statistic reads low and writes zero_median, that range in the statistic’s unit, in place of relative_spread.

A note record:

FieldUnitRangeValue
onset_sseconds0 or moreThe onset in the note list.
peak_dbdBanyThe peak power of the note’s amp proxy, the one harmonic it reads; two notes compare directly when they read the same harmonic.
attack_sseconds0 or moreThe note’s attack, as above; null when the rise is not read.
attack_upper_boundflagThe note’s attack is an upper bound.
knee_sseconds0 or moreThe note-off knee; null for a note that decays at one rate.
pooledflagThe pool holds the note.

flags holds three booleans: no_notes, attack_is_upper_bound (more than half the pooled attacks are upper bounds, so a preset should not take the attack) and pump_stripped (the pump locks to the beat over 8 counted beats or more, and its curve was taken out of the note tracks). needs_render is false.

Conventions

KeyHolds
frame_sizeThe STFT frame length of the descriptors and the band edge: at 44.1 kHz 8192 when the note list has a median f0 below 100 Hz, else 4096, and 4096 without a note list; at another rate the power of two nearest, in log, to that length times the rate over 44100 Hz.
statisticsMedian and IQR over active frames, with linear-interpolation quantiles; the active-frame gate.
spectralMagnitude weights for shape, power for band shares; the window and the hop.
confidenceWhat the level, the reasons and the spread mean.
every stem fieldThe convention of that field, as in the tables above.
pitchWhat the pitch layer reads, when values is null, and the time base.
glides, drops, vibratoThe method and the rule of each list of the pitch group.
sub_band_lineThe line the drops read.
envelopeThe tracks, the amp proxy, the stages and the pool of the envelope group.
note_offThe note-off knee and note_off_offset_s.
tailThe release, the tail fit, the write rule and the votes.
level_spread_dbThe level spread.
pumpThe pump’s track, beats, curve, fields and lock, and when it is stripped.
notesThe ticks, the merges, the end rules, the level and the velocity law of the notes group.