home

Amplitude vs Frequency Modulation

Creator: Petar Veličković

Transmit the same message by changing one property of a fast carrier. Read each column from the message at the top to the transmitted signal at the bottom.

Original illustrations: Amplitude Modulation, Frequency Modulation.


Amplitude vs Frequency Modulation

Download

PNG PNG (HD) PDF SVG

Code

amplitude-vs-frequency-modulation.typ (137 lines)

#import "@preview/cetz-plot:0.1.4": plot
#import "@preview/cetz:0.5.2": canvas, draw

#set page(width: 780pt, height: auto, margin: 22pt, fill: none)
#set text(font: "Avenir Next", size: 10.5pt, fill: rgb("#19324f"))
#set par(leading: 0.55em)

#let card-grid(columns: 2, ..cards) = layout(size => {
  let rows = cards
    .pos()
    .chunks(columns)
    .map(row => {
      let ratios = row.map(card => {
        let bounds = measure(card.at(1))
        bounds.width / bounds.height
      })
      let available = size.width - 12pt * (row.len() - 1) - 24pt * row.len()
      grid(
        columns: ratios.map(ratio => 24pt + available * ratio / ratios.sum()),
        gutter: 12pt,
        ..row.map(((title, body, caption)) => block(
          width: 100%,
          inset: 12pt,
          radius: 8pt,
          fill: rgb("#cdd3da"),
          breakable: false,
        )[
          #text(size: 13pt, weight: "bold", title)
          #v(8pt)
          // Fill the available width; each drawing keeps its own aspect ratio.
          #layout(size => std.scale(
            size.width / measure(body).width * 100%,
            reflow: true,
            body,
          ))
          #v(7pt)
          #caption
        ]),
      )
    })
  stack(dir: ttb, spacing: 12pt, ..rows)
})
#let takeaway = block.with(
  width: 100%,
  inset: 12pt,
  radius: 6pt,
  fill: rgb("#c6d8d2"),
  breakable: false,
)

#let plot-height = 1.6

// `y` is the height of the panel's t-axis; the curve is shifted so that the zero of
// `y-range` lands on it, which is what lets panels with different scales line up.
#let signal-row(name, y, title, func, color, y-range, samples: 1600) = {
  let (y-min, y-max) = y-range
  let arrow = (mark: (end: "stealth", fill: black, scale: .55), stroke: .8pt)
  let (x-axis, y-axis) = (name + "-x-axis", name + "-y-axis")

  draw.line((0, y), (10.5, y), ..arrow, name: x-axis)
  draw.line((0, y - .95), (0, y + 1.15), ..arrow, name: y-axis)
  draw.content(x-axis + ".end", $t$, anchor: "west", padding: 2pt)
  draw.content(
    (rel: (.14, -.15), to: y-axis + ".end"),
    text(fill: color, title),
    anchor: "south-west",
  )

  draw.group({
    draw.translate((0, y - (0 - y-min) / (y-max - y-min) * plot-height))
    plot.plot(
      size: (10.0, plot-height),
      axis-style: none,
      y-min: y-min,
      y-max: y-max,
      plot.add(style: (stroke: color + 1.3pt), domain: (0, 1), samples: samples, func),
    )
  })
}


// === AM: change the envelope ===
#let figure-0 = [
  #let domain-x(x) = 11 * calc.pi * x
  #let msg(x) = 2 * calc.sin(.5 * domain-x(x))
  #let carrier(x) = 2 * calc.sin(6 * domain-x(x))
  #let am(x) = (2.5 + msg(x)) * carrier(x)

  #canvas({
    draw.set-style(legend: (fill: rgb("#cdd3da")))
    signal-row("msg", 4.6, $x(t)$, msg, black, (-2.4, 2.4))
    signal-row("carrier", 2.05, [carrier wave], carrier, blue, (-2.4, 2.4))
    signal-row("am", -.6, [AM wave], am, red, (-9.5, 9.5))
  })
]

// === FM: change the spacing ===
#let figure-1 = [
  #let domain-x(x) = 11 * x
  #let msg(x) = 2 * calc.sin(2 * calc.pi * .25 * domain-x(x))
  #let carrier(x) = 2 * calc.sin(6 * calc.pi * domain-x(x))
  // Frequency modulation: integrate the message into the carrier phase.
  #let fm(x) = (
    2
      * calc.sin(
        2 * calc.pi * 3 * domain-x(x) - 8 * calc.cos(2 * calc.pi * .25 * domain-x(x)),
      )
  )

  #canvas({
    draw.set-style(legend: (fill: rgb("#cdd3da")))
    let green = green.darken(15%)
    signal-row("msg", 4.6, $x(t)$, msg, black, (-2.4, 2.4))
    signal-row("carrier", 2.05, [carrier wave], carrier, blue, (-2.4, 2.4))
    signal-row("fm", -.6, [FM wave], fm, green, (-2.4, 2.4))
  })
]

#text(size: 27pt, weight: "bold")[Amplitude vs Frequency Modulation]
#v(5pt)
Transmit the same message by changing one property of a fast carrier. Read each column from the message at the top to the transmitted signal at the bottom.
#v(14pt)
#card-grid(
  (
    [AM: change the envelope],
    figure-0,
    [The carrier’s amplitude follows the message; its rapid oscillation rate stays fixed. The envelope is easiest to see in the peaks.],
  ),
  (
    [FM: change the spacing],
    figure-1,
    [The instantaneous frequency follows the message; the amplitude stays fixed. Closely spaced peaks mean a higher frequency.],
  ),
)
#v(12pt)
#takeaway[*Memory aid: AM changes height; FM changes spacing.* The carrier is the fast oscillation. The message is the slower signal we want to convey.]