Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
335 changes: 335 additions & 0 deletions REVIVAL.md

Large diffs are not rendered by default.

80 changes: 80 additions & 0 deletions docs/tap.fuzz~.maxref.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<?xml-stylesheet href="./_c74_ref.xsl" type="text/xsl"?>

<c74object name="tap.fuzz~" module="msp" category="TapTools, MSP Effects">
<digest>A two-stage tone-stacked fuzz</digest>
<description>
The <o>tap.fuzz~</o> object is a two-stage distortion with a bass / contrast / treble voicing section — the harder, more scooped school that sits beside <o>tap.overdrive~</o> rather than replacing it (that object is a feedback soft-clipper chasing the Tube Screamer lineage). <at>gain</at> sweeps the first stage's drive from a clean boost to wide open, <at>edge</at> sharpens the second stage's knee from a soft limiter toward a hard corner, and <at>asymmetry</at> brings in the even harmonics that a symmetric curve structurally cannot produce. The architecture is the simplified cascade of Yeh, Abel and Smith (DAFx-07): conditioning filter, memoryless nonlinearity, equalization filter — twice. It is a recreation of a circuit <em>class</em>: no component value or corner frequency is claimed as measured from any pedal, and the control names follow that class's conventional layout rather than asserting what any particular unit does.
</description>

<!--METADATA-->
<metadatalist>
<metadata name="author">74 Objects</metadata>
<metadata name="tag">TapTools</metadata>
<metadata name="tag">Audio</metadata>
<metadata name="tag">Effects</metadata>
</metadatalist>

<!--INLETS-->
<inletlist>
<inlet id="0" type="signal">
<digest>Audio input.</digest>
</inlet>
</inletlist>

<!--OUTLETS-->
<outletlist>
<outlet id="0" type="signal">
<digest>The distorted output.</digest>
</outlet>
</outletlist>

<!--MESSAGES-->
<methodlist>
<method name="signal">
<description>Audio to distort.</description>
</method>
<method name="clear">
<description>Flush the filters and the oversampling chain. Parameters are kept.</description>
</method>
</methodlist>

<!--ATTRIBUTES-->
<attributelist>
<attribute name="gain" get="1" set="1" type="float" size="1">
<description>Drive into the first clipping stage (0..1). 0 is a lit-up clean boost, 1 is the pedal wide open. The floor sits below unity on purpose — the second stage carries its own small-signal gain, and a hotter floor would arrive there already saturated, which would leave the knob doing nothing over most of its travel.</description>
</attribute>
<attribute name="edge" get="1" set="1" type="float" size="1">
<description>Knee sharpness of the second stage (0..1): a soft limiter at 0, close to a hard corner at 1. High settings are where a static curve aliases worst — try <at>oversample</at> before blaming the tone controls.</description>
</attribute>
<attribute name="asymmetry" get="1" set="1" type="float" size="1">
<description>Clipping asymmetry (0..1) — the even-harmonic control. A symmetric curve is an odd function and produces odd harmonics only; a real op-amp stage clips lopsided, which is where a pedal's even harmonics come from. It costs no DC: silence stays exactly silent.</description>
</attribute>
<attribute name="bass" get="1" set="1" type="float" size="1">
<description>Low shelf, -1 to 1 (full travel is 12 dB either way). Linear, and entirely outside the nonlinearity.</description>
</attribute>
<attribute name="treble" get="1" set="1" type="float" size="1">
<description>High shelf, -1 to 1 (full travel is 12 dB either way).</description>
</attribute>
<attribute name="contrast" get="1" set="1" type="float" size="1">
<description>Mid-scoop depth (0..1, up to 14 dB at 620 Hz). The scoop is this object's own curve; the control name is the pedal class's.</description>
</attribute>
<attribute name="level" get="1" set="1" type="float" size="1">
<description>Output level in dB (-24..24).</description>
</attribute>
<attribute name="oversample" get="1" set="1" type="int" size="1">
<description>Oversampling factor for the clipper pair: 1, 2, 4 or 8. The default is 4. The clipper runs inside a cascade of 2× resampling stages, one doubling and one 8th-order filter each, which is what makes more oversampling mean less aliasing here — an earlier single-stage chain measured worse at 4× and 8× than at 2×. 2 is kept but is only safe below about 6 kHz, above which one doubling stops moving the clipper's harmonics out of the way; 8 earns its keep on bright material. Changing it reconfigures the filters and is not real-time-safe.</description>
</attribute>
<attribute name="smooth" get="1" set="1" type="float" size="1">
<description>Anti-zipper ramp time for the setters, in milliseconds (0 = instant).</description>
</attribute>
</attributelist>

<!--SEEALSO-->
<seealsolist>
<seealso name="tap.overdrive~"/>
<seealso name="tap.tapecho~"/>
<seealso name="tap.filter~"/>
<seealso name="overdrive~"/>
</seealsolist>
</c74object>
83 changes: 83 additions & 0 deletions docs/tap.metallique~.maxref.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<?xml-stylesheet href="./_c74_ref.xsl" type="text/xsl"?>

<c74object name="tap.metallique~" module="msp" category="TapTools, MSP Effects">
<digest>The Ondes Martenot's gong diffuseur, as a driven resonator</digest>
<description>
The <o>tap.metallique~</o> object is one of the Ondes Martenot's resonating loudspeakers. The instrument does not have a loudspeaker, it has a rack of them, and choosing between them is part of playing it; the <em>métallique</em> (1944–45, patented 1947) is a gong driven by a motor transducer, so everything sent through it picks up the body of a large metal plate. It is <em>driven, not struck</em> — there is no trigger and no strike envelope, and whatever you send in excites the plate continuously while the plate rings at its own rates. The signal order is the instrument's: it reaches the transducer first and the transducer's motion excites the body, so <at>drive</at>, <at>asymmetry</at> and <at>saturation</at> sit upstream of the plate, because driving a distorted waveform into a gong is a different sound from distorting a gong. What is published and what is not: the instrument, its date, its excitation and its moving-iron transducer come from the peer-reviewed sources (Najnudel and colleagues, IEEE/ACM TASLP 28, 2020; Wijnand and colleagues, Forum Acusticum 2023), but no ondes-specific measurement of the body exists in any of them, so the mode ratios are Fletcher and Rossing's free circular plate. This is a recreation of the general physics rather than a model of Martenot's gong, and the kernel header says so too. For multichannel signals, wrap the object in an <o>mc.</o> operator.
</description>

<!--METADATA-->
<metadatalist>
<metadata name="author">74 Objects</metadata>
<metadata name="tag">TapTools</metadata>
<metadata name="tag">Audio</metadata>
<metadata name="tag">Effects</metadata>
</metadatalist>

<!--INLETS-->
<inletlist>
<inlet id="0" type="signal">
<digest>Audio input — drives the transducer, which drives the body.</digest>
</inlet>
</inletlist>

<!--OUTLETS-->
<outletlist>
<outlet id="0" type="signal">
<digest>The body, balanced against the input.</digest>
</outlet>
</outletlist>

<!--MESSAGES-->
<methodlist>
<method name="signal">
<description>Audio to drive the diffuseur with.</description>
</method>
<method name="clear">
<description>Silence the body and reset the driver. Parameters are kept.</description>
</method>
</methodlist>

<!--ATTRIBUTES-->
<attributelist>
<attribute name="pitch" get="1" set="1" type="float" size="1">
<description>Frequency of the plate's (2,0) mode in Hz — the body's perceived pitch. The other seven modes follow at the published free-plate ratios (1 : 1.730 : 2.328 : 3.910 : 4.110 : 6.300 : 6.710 : 7.340), each split into a slowly beating doublet. Retuning moves sixteen resonators, so this is set-and-hold rather than a knob to sweep fast.</description>
</attribute>
<attribute name="decay" get="1" set="1" type="float" size="1">
<description>Ring time of the fundamental in seconds (T60 — the time to fall 60 dB). Long values are a drone; short ones are a plate reverb.</description>
</attribute>
<attribute name="tilt" get="1" set="1" type="float" size="1">
<description>How much faster the upper modes die than the fundamental: their ring time is <at>decay</at> divided by ratio raised to <at>tilt</at>. 0 rings everything equally; 2 is roughly the f-squared radiation damping of a struck bar. The default is 1, because a driven gong's shimmer lives in its upper modes.</description>
</attribute>
<attribute name="brightness" get="1" set="1" type="float" size="1">
<description>Weight on the upper modes, 0 to 1, steepening per mode so the highest partials go first. 1 is the full published weight table; 0 leaves only the fundamental doublet.</description>
</attribute>
<attribute name="drive" get="1" set="1" type="float" size="1">
<description>Linear gain into the transducer, before the body. This is where the object gets loud and dirty, and it is upstream of the plate on purpose.</description>
</attribute>
<attribute name="asymmetry" get="1" set="1" type="float" size="1">
<description>The moving-iron squared term, 0 to 1. In a moving-iron motor the force follows the square of the gap flux, so with a bias current the residual squared term puts a second harmonic on the signal in proportion to level and nothing at the third. 0 is a linear driver — legitimate, but then a documented stage of the instrument is missing. The coefficient is not fitted to a measurement; the source establishes that the driver is nonlinear without handing over a curve.</description>
</attribute>
<attribute name="saturation" get="1" set="1" type="float" size="1">
<description>Soft-clip amount after the squared term; 0 is exactly linear. It is here because a squared law is expansive and something has to bound it — a modelling necessity rather than a measured stage. The output is bounded by 2 divided by this value, not 1 divided by it: removing the DC from a hard-driven squared law doubles the worst-case swing.</description>
</attribute>
<attribute name="mix" get="1" set="1" type="float" size="1">
<description>Balance between the dry input and the diffuseur, 0 to 100, equal-power. The ends are exact: 0 is the input bit for bit, 100 is the body alone.</description>
</attribute>
<attribute name="level" get="1" set="1" type="float" size="1">
<description>Output level, linear.</description>
</attribute>
<attribute name="smooth" get="1" set="1" type="float" size="1">
<description>Anti-zipper ramp time for the transducer, mix and level setters, in milliseconds (0 = instant). The body's own parameters are not ramped.</description>
</attribute>
</attributelist>

<!--SEEALSO-->
<seealsolist>
<seealso name="tap.palme~"/>
<seealso name="tap.touche~"/>
<seealso name="tap.chime~"/>
<seealso name="tap.5comb~"/>
</seealsolist>
</c74object>
89 changes: 89 additions & 0 deletions docs/tap.ondes~.maxref.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<?xml-stylesheet href="./_c74_ref.xsl" type="text/xsl"?>

<c74object name="tap.ondes~" module="msp" category="TapTools, MSP Synthesis">
<digest>The Ondes Martenot voice, minus its loudspeaker</digest>
<description>
The <o>tap.ondes~</o> object is the Ondes Martenot's voice: a heterodyne envelope detector into the demodulator triode into the preamplifier triode into the intensity key. It is a <em>source</em>, not an effect — patch a <o>tap.palme~</o> or a <o>tap.metallique~</o> after it and you have the instrument. It is <em>not</em> a VCO with waveform switches. The Ondes Martenot is heterodyne: two oscillators near 80 kHz, one fixed and one moved by the ribbon, summed into an amplitude-modulated signal whose envelope is the note. Najnudel, Hélie, Roze and Boutin (IEEE/ACM TASLP 28, 2020) measure those oscillators at about 0.03 % second harmonic even coupled to the rest of the circuit, so the character is entirely in what comes after them — and the biggest single part of it is the demodulator, before any valve. The envelope of two equal oscillators is 2|cos|, which puts the second harmonic 14 dB below the fundamental and the third 21 dB down. That is why this object does not synthesize a difference tone; doing so would throw the instrument's timbre away. The carrier is not simulated either: the envelope has a closed form, and running the published 200 µs detector on it matches a full 80 kHz simulation to within a tenth of a dB on every harmonic. The performance surface is the instrument's — <at>ribbon</at> is semitones above A1, because the published ribbon law is linear in semitones, so a hand moving at constant speed makes a constant-rate glissando and nothing quantizes; <at>key</at> is the published intensity-key curve from <o>tap.touche~</o>, whose bottom 45 % of travel is silent because that is the key bending before it reaches the powder bag. Both take signals. What is deliberately missing is the waveform registers: the real instrument has switchable timbres whose filter shapes are in none of the sources obtained, and inventing them is the one thing this object will not do.
</description>

<!--METADATA-->
<metadatalist>
<metadata name="author">74 Objects</metadata>
<metadata name="tag">TapTools</metadata>
<metadata name="tag">Audio</metadata>
<metadata name="tag">Synthesis</metadata>
</metadatalist>

<!--INLETS-->
<inletlist>
<inlet id="0" type="signal">
<digest>Ribbon position, semitones above A1. Overrides the <at>ribbon</at> attribute while connected.</digest>
</inlet>
<inlet id="1" type="signal">
<digest>Intensity key, 0 to 1 of the travel. Overrides the <at>key</at> attribute while connected.</digest>
</inlet>
</inletlist>

<!--OUTLETS-->
<outletlist>
<outlet id="0" type="signal">
<digest>The voice, before any diffuseur.</digest>
</outlet>
</outletlist>

<!--MESSAGES-->
<methodlist>
<method name="signal">
<description>The ribbon position (left inlet) or the intensity key (right inlet).</description>
</method>
<method name="clear">
<description>Silence the detector and every filter. Parameters are kept.</description>
</method>
</methodlist>

<!--ATTRIBUTES-->
<attributelist>
<attribute name="ribbon" get="1" set="1" type="float" size="1">
<description>The note, in semitones above A1 (55 Hz). The circuit paper's Eq. 7 makes the ribbon linear in semitones, so this really is where the hand is: move it linearly and you get a linear glissando. Fractional and unquantized, because the instrument is. Ignored while a signal is connected to the left inlet.</description>
</attribute>
<attribute name="key" get="1" set="1" type="float" size="1">
<description>The intensity key, 0 to 1 over its physical travel — the published curve from <o>tap.touche~</o>. Roughly the bottom 45 % is silent, which is the key bending before it compresses the powder bag rather than a dead spot in the object. Ignored while a signal is connected to the right inlet.</description>
</attribute>
<attribute name="depth" get="1" set="1" type="float" size="1">
<description>Relative amplitude of the second oscillator, 0 to 1. At 1 (the published case, equal amplitudes) the envelope closes completely and the harmonic series is full; below that it never closes and the tone thins toward a sinusoid. A real mismatch between two oscillators, and the cheapest timbre control here.</description>
</attribute>
<attribute name="detect" get="1" set="1" type="float" size="1">
<description>Envelope-detector time constant in milliseconds. The published value is 0.2, from R4 × C21 = 1 MΩ × 200 pF. Longer smooths the envelope and takes the harmonics with it; it is also why the instrument gets purer and quieter as it goes up, since the RC cannot follow a fast envelope back down.</description>
</attribute>
<attribute name="drive" get="1" set="1" type="float" size="1">
<description>Grid drive into the two valve stages, as a multiple of the published nominal — the harmonics control. The circuit paper's own plugin exposes demodulator input gain the same way, a knob the real instrument does not have. Normalized, so it changes the distortion and not the level. Note that at 0 the tone is still harmonically rich, because the demodulator made those harmonics.</description>
</attribute>
<attribute name="keyplacement" get="1" set="1" type="int" size="1">
<description>Where the intensity key sits: 0 after the valves (a clean output law — pressure is level), 1 before them (pressure drives the valves, so soft is clean and hard is dirty). The circuit paper's five stages do not include the key, so this is a choice rather than a reconstruction — and a real one, worth about 0.09 of total harmonic content at a half-press.</description>
</attribute>
<attribute name="polarity" get="1" set="1" type="int" size="1">
<description>Sign of the coupling between the two valve stages, 1 or −1. They are coupled through a transformer whose winding sense is not in the source, and the sign decides which side of the waveform the preamplifier's asymmetry acts on. Audible: the two settings differ by about 0.12 of total harmonic content.</description>
</attribute>
<attribute name="power" get="1" set="1" type="int" size="1">
<description>Run the 2A3 power stage. Off by default, following the circuit paper: they measure almost 5 % second harmonic there but report its contribution as much less important than the two stages before it, and drop it for real-time. Measured here, switching it on moves total harmonic content by about 0.003 — so they were right, and it is a switch rather than a deletion.</description>
</attribute>
<attribute name="level" get="1" set="1" type="float" size="1">
<description>Output level, linear.</description>
</attribute>
<attribute name="oversample" get="1" set="1" type="int" size="1">
<description>Oversampling for the nonlinear chain: 1, 2, 4 or 8. Every doubling is worth about 12 dB of alias rejection up to 4×, and 7–12 dB more at 8× in the top octave. 4× is the default because that is where the cost stops buying uniformly.</description>
</attribute>
<attribute name="smooth" get="1" set="1" type="float" size="1">
<description>Anti-zipper ramp time for the attribute-driven drive, level and key, in milliseconds (0 = instant). The signal inlets are not ramped — a control signal is assumed smooth already.</description>
</attribute>
</attributelist>

<!--SEEALSO-->
<seealsolist>
<seealso name="tap.touche~"/>
<seealso name="tap.palme~"/>
<seealso name="tap.metallique~"/>
<seealso name="tap.triode~"/>
</seealsolist>
</c74object>
Loading
Loading