Skip to main content

An Analog-Style Frequency Shifter

In this post, I will give an overview of a well-known method for designing frequency shifter effects in analog electronics, and some notes on implementing a digital version.

Frequency shifting is a special case of single sideband (SSB) modulation, a device often used in radio electronics. SSB in telecommunications involves shifting audio frequencies by e.g. 10 MHz so they can be transmitted as radio waves, then shifting down 10 MHz at the receiver. For this reason, SSB is well-studied, and there are a few different ways to implement it. This post describes a design that has found use in electronic music applications, where the shift is small (up to ±20 kHz, and often in tiny shifts like 1 Hz). Wikipedia calls it a “Hartley modulator,” but I can’t find any source to corroborate that terminology.

A fantastic reference to look at for the design of an analog frequency shifter is [Haible1996], which provides a full set of schematics of a high-quality real-world analog unit. I’ll only provide details up to an abstract block diagram that can be easily digitized.

This post starts off pretty theoretical, with an attempt to explain how the frequency shifter works. Admittedly, this is an explanation more for myself than it is for others, but I hope it helps. If not, feel free to skip the first two sections and check out the following links which might explain it better: [Smith2007] [Boschen2016] [Boschen2020]

Ring modulation of real signals

A real audio signal \(f(t)\) has a Fourier transform satisfying \(F(-\omega) = F(\omega)^*\), i.e. all negative frequency content is the complex conjugate of the positive frequency content. An individual sine wave \(\cos \theta t\) produces Dirac delta-shaped spikes in the frequency spectrum at \(\theta\) and at \(-\theta\). To illustrate, here is a depiction of the absolute value of such a spectrum vs. angular frequency:

A graph titled "Magnitude spectrum of cos theta t," showing spikes at angular frequencies positive and negative theta. The negative-frequency spike is colored orange, and the positive-frequency spike is colored blue.

The Fourier transform has a convolution theorem, where convolving two signals in the time domain is identical to multiplying them in the frequency domain. Critical to understanding the frequency-domain behavior of ring modulation is the counterpart:

Multiplying two signals in the time domain is identical to convolving them in the frequency domain.

A ring modulator mutliplies a signal \(f(t)\) by a sinusoid \(\cos \theta t\). [1] By performing convolution of these two signals in the frequency domain, we get two sidebands: \(f(t)\) frequency shifted up by \(\theta\), and \(f(t)\) frequency shifted down by \(\theta\). This is because convolution with a shifted Dirac delta function is a horizontal shift.

Here’s what it looks like visually. The left diagram is the magnitude spectrum of some arbitrary real signal, and the right shows the magnitude spectra of the two shifted copies:

Two side-by-side graphs. The first one is titled "Real signal," showing the magnitude spectrum of an arbitrary real signal that is symmetric about dc. The second is titled "Multiplication by cos theta t produces two shifted copies." It shows two copies of the real signal, one shifted to the left by -theta and colored orange, and one shifted to the right by +theta and colored blue.

(Sorry about the goofy-looking diagrams in this post. I wanted to make them more professional, but that took too much work.)

The ring modulator is already almost a frequency shifter, but it produces two shifted copies. What if there was a way for a ring modulator to produce only one sideband? Hmmm…

Frequency shifting of analytic signals

Most audio signal processing concerns real signals, so it’s easy to forget that they are a subset of the larger domain of complex signals. A complex signal \(A + jB\) can be represented in analog or digital environments using two real signals, one for the real part \(A\) and the other for the imaginary part \(B\). In the frequency domain, complex signals are not beholden to the constraint that real signals have on negative frequencies. Their positive spectrum can be completely independent of the negative spectrum.

In frequency shifting, we are interested in a subset of complex signals called the analytic signals. A complex signal \(f\) is analytic if \(F(\omega) = 0\) for all \(\omega < 0\). [Smith2007] That is, the Fourier transform of \(f\) has no negative frequency content.

Why is this useful for frequency shifting? While real signals decompose into real sinusoids of the form \(A \cos(\omega t + \phi)\), the building block of an analytic signal is the complex sinusoid, which has the general form \(A e^{j (\omega t + \phi)} = A \cos(\omega t + \phi) + A j \sin(\omega t + \phi)\), where \(A \geq 0\), \(\omega \geq 0\), and \(0 \leq \phi < 2\pi\). Instead of the dual spikes of the real sinusoid, a complex sinusoid’s spectrum is a single spike at a positive frequency.

A graph titled "Magnitude spectrum of exp j theta t, theta > 0." This has only one spike at a positive angular frequency theta.

Since multiplication in the time domain is convolution in the frequency domain, multiplying by a complex sinusoid \(\cos \omega t + j \sin \omega t\) convolves with a single Dirac delta function at \(\omega\). The lack of negative frequency content means that only the upper sideband is generated. That’s a frequency shift by \(\omega\).

Two side-by-side graphs. The left graph is titled "Analytic signal" shows the magnitude spectrum of an arbitrary analytic signal, which only has frequency content above dc. The second is titled "Multiplication by exp j theta t shifts frequency up by theta," showing the previous analytic signal shifted to the right.

This even works if the complex sinusoid has negative frequency. Although the shifting process crashes into DC and generally produces a non-analytic signal, this isn’t an issue.

Two side-by-side graphs. The left graph is titled "Magnitude spectrum of exp j theta sub 2 t, theta sub 2 < 0," and shows a single Dirac spike at a negative frequency. The second is titled "Multiplication by exp j theta t shifts frequency down by theta sub 2," showing the previous analytic signal shifted to the left and crossing over dc.

A ring modulator multiples a real signal by a real sinusoid, while a frequency shifter (or at least our specific design of it) multiplies an analytic signal by a complex sinusoid.

There is one fundamental property of analytic signals that we need to know before we proceed. The imaginary and real parts of an analytic signal have a special relationship: the imaginary part is the Hilbert transform of the real part of the signal. The Hilbert transform of a signal is a “constant -90-degree phase shift,” or more accurately, a -90-degree phase shift of all positive frequency content and a +90-degree phase shift of all negative frequency content (the latter is to ensure the signal stays real). [2] The Hilbert transform property of analytic signals can be easily proven from the definition of the Fourier transform.

Borrowing terms from telecommunications, analytic signals are often known as “quadrature signals” or “\(I/Q\) signals.” The real part of the signal is denoted \(I\) (for “in-phase”) and the imaginary part \(Q\) (“quadrature”).

Converting between analytic and real signals

So, nice. Analytic signals allow for easy implementation of a frequency shifter. So how do we convert from real to analytic signals and vice versa?

Converting from complex signals back to real signals is trivial. We just drop the imaginary part:

A block diagram titled "Complex-to-real Converter." There are two input signals, I and Q. The I signal has an arrow pointing to the output "Real signal." The Q signal has an arrow pointing to "don't care."

To convert from real to analytic, we can try using a Hilbert transform to construct the imaginary part:

A block diagram titled "Real-to-analytic Converter?" There is a single input signal, "Real signal," which is connected directly to an output I signal. The real signal is also piped into a block named "Hilbert transform," which is output to Q.

Unfortunately, the Hilbert transform is noncausal, with an impulse response that tails infinitely in both directions. In digital settings, FIR filters are a common approach for approximating the Hilbert transform (with some latency that has to be compensated with a delay line in the \(I\) signal). The literature on this is extensive thanks to Software-Defined Radio applications: just search for “Hilbert FIR.”

In the analog domain, an IIR filter method exists for converting a real signal to an analytic one: a “90-degree phase-difference network.” Rather than directly implementing the Hilbert transform as a filter, a phase-difference network takes an input signal X and puts it through two parallel allpass filters, producing two signals A and B such that B is roughly the Hilbert transform of A. “Roughly” means that the phase shift of B relative to A is close to -90 degrees over a useful bandwidth, say 20 Hz to 20 kHz.

A block diagram titled "90-degree Phase Difference Network." The input signal is labeled "Real signal." It splits into two branches, with the upper branch going into a block labeled "Allpass A" and then being output as the I signal. The lower branch goes into a block labeled "Allpass B" and is then output as the Q signal. An arrow from I to Q is labeled "Q is approximately Hilbert transform of I," but it's dotted to indicate that it's not an actual signal flow.

The allpass filters are formed from a cascade of one-pole one-zero allpass filters, each having the following transfer function:

\begin{equation*} H(s) = \frac{s + p}{s - p} \end{equation*}

where \(p\) is real and negative, representing the location of the pole. How do we select the locations of the poles? The mathematics are beyond me, but there is a published algorithm for optimal design of such filters described in [Weaver1953] and elaborated on in a well-known document from ElectroNotes [Hutchins]. The algorithm receives minimum and maximum frequencies to define the operating bandwidth, and you can either specify the number of allpasses (“design a network with \(n\) poles”) or the error in the phase difference (“design a network with less than \(E\) degrees of deviation from 90 degrees”). I wrote up some Python/NumPy code for this, available at the end of the post.

If we specify the operating range as 20 Hz to 20 kHz, a phase difference network with 12 poles, six in each path, can achieve less than 2 degrees of deviation from 90 degrees in the audio frequency range. Here are the locations of the poles that I get (units in radians/second):

Poles, path A:
Poles, path B:

I skipped an important detail. Maybe A and B are almost 90 degrees apart, but how do they relate to the input signal? The relationship isn’t straightforward, so a graph will help. Both branches of the network are allpass filters, meaning that their gain is unity at all frequencies, so only their phase responses are worth looking at. Let’s plot the phase response of Allpass A and Allpass B:

A graph titled "12-pole 90-degree phase-difference network, phase responses" showing the phase response from 10 Hz to 100,000 Hz. The two phase responses are gently sloped and sigmoid-shaped, with one vertically offset from the other.

Here’s the phase difference between Allpass A and Allpass B to show how close we are to -90 degrees:

A graph titled "12-pole 90-degree phase-difference network, phase difference" showing the phase difference from 10 Hz to 100,000 Hz. In the range of 20 Hz to 20,000 Hz, it's about -90 degrees with a little bit of wiggle. Outside of that range, the phase difference goes upward and approaches 0, forming a U shape with a flattened bottom.

Good enough for our needs. (Open question for readers: how low does this error need to be for it to be inaudible in the resulting effect?)

The Complete Frequency Shifter

We’ve now defined conversion processes between analytic and real signals, and we have all the tools needed to complete our frequency shifter:

  • Convert rom a real signal to an analytic signal \(I + jQ\).

  • Multiply by a complex sinusoid.

  • Convert the complex signal back to a real signal.

Note that the modulation step, the multiplication must be complex multiplication. If the input signal is \(I + jQ\), complex multiplication expands as follows:

\begin{equation*} (I + jQ) (\cos \omega t + j \sin \omega t) = I \cos \omega t - Q \sin \omega t + j(I \sin \omega t + Q \cos \omega t) \end{equation*}

But since we’re immediately converting back to a real signal, the imaginary term doesn’t matter, and we just need to compute \(I \cos \omega t - Q \sin \omega t\). That completes the block diagram of our analog frequency shifter:

A block diagram titled "The Complete Frequency Shifter." The input signal is branched into parallel Allpass A and Allpass B filters. The output of Allpass A is multiplied by a signal cos omega t. The output of Allpass B is multiplied by a signal sin omega t, and then inverted in polarity. The two branches are summed to produce the output signal.

This is only a block diagram. Fleshing this out into actual analog schematics is an entirely different story, and I won’t claim any expertise in that. Again, just check out [Haible1996] for yourself.


Analog one-pole filters are simple to digitize using the bilinear transform.

\begin{equation*} H(z) = \frac{k + z^{-1}}{1 + k z^{-1}} \end{equation*}

where \(k = \frac{p + 2f_s}{p - 2f_s}\), where \(f_s\) is the sample rate and \(p\) is the location of the analog pole. Even without pre-warping, this achieves excellent agreement to the analog phase response, and it’s not worth fretting over inaccuracies in my opinion.

Antialiasing is a valid concern when working with digital frequency shifters. With positive frequency shifts, frequency content may be shifted above Nyquist. This can be countered by pre-application of a lowpass filter at \(f_s / 2 - f\) if frequency shifting upward by frequency \(f\).


We have a nice-sounding frequency shifter based on an established algorithm in signal processing. What twists can we add to give it some unique character?

In an analog design, the one-pole allpass filter is typically an active design containing an op-amp. Op-amps can be a source of nonlinearity, so this suggests a “dirty” frequency shifter with waveshaping after each allpass stage. [3] The sine wave modulator signal can also be made non-ideal with harmonic distortion or temperature drift.

I don’t think it’s worthwhile to do exact modeling of every nonlinearity and imperfection in an analog frequency shifter. All I am suggesting here is that effect design doesn’t need to stop at an idealized mathematical model, and that there is a potentially interesting space to explore in deliberately imperfect frequency shifters, especially using imperfections directly inspired by analog circuits.


Python/NumPy code for designing the phase difference networks and making the plots is available on GitHub. Admittedly I haven’t done a lot of work to verify its correctness, so please let me know if you discover errors.

Edit 2020-03-06: I mistakenly claimed that the phase responses of the allpass filters are nearly linear, completely forgetting that the X-axis of the plot is logarithmic. Oops. I’ll put up a graph of the group delay if I have time.



Boschen, Dan. 2016. Answer on DSP StackExchange.


Boschen, Dan. 2020. Answer on DSP StackExchange.


Weaver, Donald K. 1953. “Design of an RC Wide-Band 90-Degree Phase-Difference Network.”


Hutchins, Bernie. “The Design of Wideband Analog 90° Phase Differencing Networks Without A Large Spread of Capacitor Values.”

[Haible1996] (1,2)

Haible, Jürgen. 1996. “JH FS-1 Frequency Shifter.”

[Smith2007] (1,2)

Smith, Julius O. 2007. “Analytic Signals and Hilbert Transform Filters.”