FM Carrier Waveform Comparison (TZFM vs Linear)
FM Carrier Waveform Comparison (TZFM vs Linear)
A plot-register recipe for the 3-panel composite that shows the time-domain difference between non-through-zero linear FM and through-zero linear FM (TZFM) under identical deep modulation.
Pedagogical intent
Transfer curves (f vs V_mod) explain TZFM mathematically but leave most readers thinking “I sort of got it.” What lands is seeing the carrier waveform itself: under deep modulation, regular linear FM freezes for part of every modulator cycle, while TZFM keeps oscillating but reverses direction through the zero crossing. The contrast is immediate, visual, and removes the need to internalize “negative frequency” before getting the lesson.
This diagram lives in the plot register because it is a time-domain curve (carrier amplitude vs time), not a routing graph. A patch-register diagram for the same lesson would show VCO → VCO (TZFM input) → output — complementary, not a substitute.
The target reader is someone who already understands what a carrier and modulator are, and has just been told “TZFM is a kind of linear FM that doesn’t break under deep modulation.” The diagram must show:
- Three vertically stacked panels with a locked, shared time axis:
Carrier(top),Modulator(middle),Result(bottom). - Carrier and modulator panels are identical across the two diagrams (Linear and TZFM) so the only visible difference is in the
Resultpanel. - A subtle red time-window highlight spanning all three panels, marking the segment where instantaneous frequency would dip below zero. The “interesting” region of the modulator cycle is unambiguous.
- In the Linear diagram: the result’s sawtooth ramps flatline inside the red window.
- In the TZFM diagram: the result’s sawtooth ramps invert slope (run downward instead of upward) inside the red window, then resume forward when the window closes.
Visual recipe
- Pair of SVGs, one per FM mode — same canvas, same panel layout, same modulator, same carrier baseline frequency, same FM depth. Only the result-panel synthesis differs.
- Canvas: 800 × 380 (custom; one panel-height taller than
dimensions.tall). Three equal-height panels with ~14 px gap. - Padding:
{ top: 18, right: 30, bottom: 22, left: 80 }— wider left padding because side-tags (Carrier,Modulator,Result) live there. - Grid:
drawGridwithxDivisions: 8,yDivisions: 2,showCenterLine: truefor each bipolar panel. - Side-tags: panel name (
Carrier/Modulator/Result) rendered atplotX - 16, centerY + 4infontSizes.small,rgba(255,255,255,0.55). - Y-axis ticks:
+/0/−at the left edge of each panel. - Time-window highlight rect:
colors.secondaryat ~0.07opacity (faint red, see “Cross-panel decoration primitives” inSKILL.md), drawn UNDER the grid and signals, spanning vertically across all three panels. Width = exact time interval wheresin(2π·t) < −fCarrier/fmDepth— equivalently, the region where the instantaneous frequencyf_inst = fCarrier + fmDepth × sin(2π·t)would go negative for the chosen carrier and FM depth. - Carrier panel: unmodulated sawtooth at
fCarrier(4 cycles across the plot width).colors.tertiary,strokeWidth: 2,strokeLinejoin: 'miter'. - Modulator panel: a 1-cycle reference sine at
rgba(255,255,255,0.6),strokeWidth: 1.8,strokeLinejoin: 'round'. - Result panel: sawtooth synthesized from numerically integrated phase (see “Recipe: rendering FM-modulated carrier waveforms” in
SKILL.md).colors.secondaryfor the Linear variant;colors.primaryfor the TZFM variant.strokeWidth: 2,strokeLinejoin: 'miter'. - Carrier choice — sawtooth, not sine. Slope direction makes phase reversal visible at a glance. The same recipe with a sine carrier renders the TZFM reversal as “the sine retraces its path” — physically correct but visually subtle.
Reuse drawGrid, drawAxes, and theme tokens from src/core/. Do NOT redefine grid styling or inline colors.
Generator call
This generator is not yet canonicalized in sub-packages/synth-svg/. The merged PR (#1787) shipped the SVGs but the generator function still needs to land per step 3 of the Authoring loop (write generateFmCarrierWaveform in src/generators/<topic>.ts — likely a new fm.ts or an extension of spectrum.ts — and register the two output filenames in the matching src/scripts/generate-files.ts or src/generate-spectrum-svgs.ts).
Shape it as:
import { generateFmCarrierWaveform } from '../generators/fm.js';
// Pair of axis-locked composites.
const linearSvg = generateFmCarrierWaveform('linear', {
carrierWave: 'saw',
fmDepth: 6,
});
const tzfmSvg = generateFmCarrierWaveform('tzfm', {
carrierWave: 'saw',
fmDepth: 6,
});
Canonical filenames (already used by the article on main): wpa-2v2-fm-saw-linear.svg, wpa-2v2-fm-saw-tzfm.svg. MDX references: /images/synth-svg/wpa-2v2-fm-saw-{linear,tzfm}.svg.
If a future article wants the same composite for a different module (different baseline frequency, deeper FM index, sine carrier instead of saw), parameterize the generator further rather than copy-pasting.
Source articles
src/mdx/guides/wpa-module-guide-ep1.mdx— Weston Precision Audio 2V2 guide EP.1, TZFM section. The pair of SVGs is the centerpiece of the “TZFM vs regular linear FM” explanation that replaces the original “transfer-curve-first” pedagogy.- Companion transfer-curve diagram:
wpa-2v2-fm-tzfm-transfer.svg(signed-flinear curve through zero). This recipe is the time-domain complement to that frequency-vs-voltage transfer curve. - Any future guide article that compares two FM modes (linear vs TZFM, expo vs linear, etc.) can reuse the same 3-panel template.