Has anyone found a demodulator for CD4 (Quadraphonic) Vinyl

So I have some CD4 vinyl that I would like to convert in to multi channel audio files.

I propose to play them using a Kenwood TRIO KP-5022 turntable and capture it using my sound card.

What I am looking for is a CD4 demodulator plug-in for Audacity to enable me to save all four channels.

I wanted to avoid the purchase of hardware CD4 demodulator as my sound card only has stereo inputs ans it is an add expense.

Has anyone attempted this before and does such a plug-in exist for audacity?

Many thanks in advance,


I’ve not seen a suitable plug-in, but it could be an interesting project to make one using Nyquist.

According to this page the carrier signal was in the range of 30 to 50kHz (30,000Hz to 50,000 Hz), so for this to work your audio equipment must all be capable of handling these very high frequencies. In particular, your sound card must be capable of recording with a sample rate of 192 kHz and must not filter out frequencies between 30 and 50 kHz.

I’ve not found much on the CD-4 specification, but there may be enough information here to work out how to do it: http://en.wikipedia.org/wiki/Quadraphonic_sound#CD-4_.28Compatible_Discrete_4.29_.2F_Quadradisc (though it would be better if we had the full and accurate technical specification)

A good place to start would be to record a short sample recording (WAV format) using a sample rate of 192 kHz so that we can examine it. See here for how to post recordings: https://forum.audacityteam.org/t/how-to-attach-files-to-forum-posts/24026/1

I would love to have this also!! I think there is a script for Adobe Audition, but it would be great to have an option for Audacity!

I’d be happy to help develop a Nyquist plug-in for this, but I don’t have CD4 capable equipment.
I wrote previously: “A good place to start would be to record a short sample recording (WAV format) using a sample rate of 192 kHz so that we can examine it”. I’m still waiting.

Sorry for the delay Steve.

I have attached a short sample in FLAC format as the WAV file was a bit too short, unfortunately its only a 96kHz I hope that will do. I try and get a 192kHz sample and as soon as I do I’ll post it.

Many thanks for your help,


I’ve been searching around for some documentation on CD-4 (Quadradisc) and turned up a PDF of an original document that was pa-portably written by JVC entitled “CD-4 AN INTRODUCTION”.

It goes in to detail about the modulation methods used; specifically that both frequency and phase modulation techniques are utilised. In addition there it goes in to detail about the “Automatic Noise Reduction System” (ANRS) it utilises to prevent interference between the audio signal and the modulated difference signal.

You can download it from here:


I have also analysed the file I sent you and the is a clear peak around 30kHz which is what you expect based on the information we have about the CD-4 format. See attachment showing the graph


OK so I have done some more digging and found some more documents:


All of these go in to further varying levels of detail that may be found to be useful.

Hi TimDog73, Just to say I’m not ignoring you - I’ve just got back from vacation/holiday and I’m working my way through a mountain of e-mail. It’ll be a while 'till I get to reading through the documentation that you posted but I look forward to doing so as soon as possible.

Hi Steve,

No problem, hope you had a good break!

I’ve used this time to try and understand the demodulation steps we have to follow to recreate the four channels and produced the attached diagram (with thanks to my friend Steve for peer reviewing the diagram).

Best regards,
Demodulator Diagram.jpg


I’ve attached a flow diagram for the demodulator with the ANRS expander circuit split in to its filtering components and expansion components. There is also more explanation in this one too.

Demodulator flow diagram.jpg

That’s pretty complex.
The difficult parts are getting the demodulation to work correctly and then handling the dynamic expansion correctly.

As a proof of concept (but dreadful sound quality) we can demodulate the 30 kHz fm component with something like:

(setf s
      (lowpass8 s 30000) 
    (hzosc 30000)))

(defun normalize (sig)
  (mult 0.8 sig (/ (peak sig ny:all))))

(multichan-expand #'normalize s)

The result from your demo file is:

(I said it was awful :wink:)

I’m sure that the demodulation could be improved (though I’m not sure off the top of my head how we would emulate a phase locked loop digitally), but then the dynamic expansion will need to be exactly right in order to achieve correct sum and differencing. I’ve not read all of the pdf files that you posted, but to get that right there’s a lot of parameters that we need to know (both the compression and expansion thresholds, the attack and release times, and the knee radii), and if that was not enough, we also need to maintain the correct phase relationships across the full audio frequency spectrum. If we don’t get all of this right the result will (sadly) be garbage.

In short, it is easy to demonstrate the principle, but to produce a CD4 decoder that sounds anything other than complete rubbish is likely to be very difficult.

Hi Tim,
Steve was so kind to introduce us presently. I’ll try to support you in the plug-in development.
Firstly, I must familiarize myself with the cd4 stuff. Unfortunately is none of your provided material accessible for screen readers. Hence, I must do some OCR with them.
It’s certainly a interesting project and other topics could profit from the outcome as well (Dolby decoding for example).
Best regards

Some more documentation; about a new demodulator 2007/2008.

At least the “sum and difference” part is easy :wink: (it’s about the only part that is)

Yeah, but only if the direct signal (with about 40 ms delay) and the demodulated signal can be properly synchronized.
The low-pass and band-pass filters, along with the equalization and compander section produce serious phase shifts. Even on the original device are 3 to 4 knobs to set up the turntable after each individual cartridge change. It is like solving an equation with 10 unknown variables. Ideally, we had both, a record from tim’s device and the digitally transferred channels from a quadrophonic turntable, e.g. a test disc.

Big question, why does Steve’s code snippet produce such a horrible sound?
Answer: Better ask, why does it produce sound at all?
The code does an AM demodulation, i.e. the message is coded in the instant amplitude of the 30000 Hz carrier.
CD-4 is modulated in “FM PM and SSB-FM” which is very nasty to demodulate.
Frequency modulation only squeezes and expands the wave-form horizontally, that’s why we shouldn’t hear anything after an AM demodulation.
The developers have now decided to adapt the FM-signal to the Main (what you hear on a stereo TT) signal’s amplitude, always about 19 dB below it (so called CLC - Carrier Level Control).
There’s additional noise and the groove in the other wall that modulates the carrier’s amplitude further.
FM-demodulation hinges on a signal of equal amplitude throughout. Hence, the first steps to retrieve the original message are:

  • Highpass filter at 15500 Hz to get the carrier + side bands.
  • Limit the carrier by hard-clipping.
(clip (mult 10000 carrier) 1)
  • Bandpass the result between 20000 and 45000 Hz to remove the square wave harmonics.
  • Actual demodulation with phase lock loop

The PLL from the last step is rather hard to implement because it uses a recursive approach.
I’ve now employed another method that firstly doesn’t need a limiter and secondly needs no lowpass update recursively.
It splits the signal into sine and cosine and keeps tracking the instant phase.
It works at the moment only for short periods because the result is gathered in a fixed array.
That’s the sound of the left channel from the sample Audio above:

I’ve also used an inverse RIAA to bring up the bass a bit. Unfortunately, CD-4 uses an own equalization curve + a expander for the noise reduction. I can’t read the response curves myself, thus…
By the way, the FM signal has only -31 to 36 dB, instead of -19 dB. I therefore assume that a normal stylus has been used.

The snippet first applies a narrow band pass filter at the carrier frequency.
The FM signal frequency has an average frequency equal to the carrier, but is modulated (by the message signal) so that the instantaneous frequency oscillates either side of the carrier frequency.
As the FM signal frequency moves through the narrow filter range, the amplitude will change such that maximum signal occurs when the FM signal frequency matches the filter’s centre frequency. In effect, the narrow pass band filter converts from FM to AM.
The resulting AM signal is then demodulated.
It’s primitive, but simple code and works as a proof of concept.

Excellent - are you doing that with FFT ?

Terrific, great progress :smiley:

No, it doesn’t work with FFT, but it is related to it.
It is a Discreet Fourier transformation that returns for each sample a complex vector, tuned to the carrier frequency. It is basically what I’ve written in my PM.

(setf sig (highpass8 s 15500))
(defun dem (s cf)
  (let* ((ref-osc (osc (hz-to-step cf)))
         (ref-quad  (osc (hz-to-step cf) 1 *table* 90))
         (sn (lowpass8 (mult s ref-osc) 15500))
         (cs (lowpass8 (mult s ref-quad) 15500 )) 
         (out (make-array (truncate len)))
         (c-1 0) (s-1 1))
   (dotimes (i (truncate len)) 
      (let* ((c0 (snd-fetch cs)) (s0 (snd-fetch sn)))
             (setf (aref out i) 
                   (atan (+ (* s-1 c0) (* c-1 s0))
                         (- (* c-1 c0)  (* s-1 s0))))
                   (psetq c-1 c0 s-1 (* -1 s0)))) 
             (setf (aref out 0) 0)
   (snd-from-array 0 *sound-srate* out)))
(setf sig (highpass8 (dem sig 30000) 50))
(mult (/ (peak sig ny:all)) sig)

C0/s0 is the current complex pair and c-1/s-1 is the conjugate of the past one. The atan function returns the instant phase for the pair.
This is normally very slow and therefore replaced with a lookup-table or a curve fitting function.
The code is not yet very refined, it should actually be implemented as object/class.
Please note: it works only with a mono track, stereo gives a nice visual C++ runtime error.

You lost me here:
Where did this equation come from?

  (atan (+ (* s-1 c0) (* c-1 s0))
        (- (* c-1 c0)  (* s-1 s0)))
(psetq c-1 c0 s-1 (* -1 s0))

This would probably be handled OO.