I am digitizing about 40 tapes with programs for the ZX Spectrum. I am somewhat puzzled by the waveform after digitization. The signal of most cassettes is meander-shaped. meander-shaped meander-shaped meander-shaped One of the cassettes can be downloaded from DropBox.

Some cassettes have a sinusoidal signal. This is an example of a cassette with a bad record. This cassette has an unstable amplitude. sine wave sine wave This cassette can be downloaded from DropBox

Sometimes there are records with "dancing" short pulses. short pulses

Questions: 1. What shape should the pulses be for successfully decoding programs recorded on these tapes?

  1. What programs can help in decoding or preparing audio files for processing?

  2. Any hacks for successful processing of tapes.

P.S. After some experiments with adjusting the signal level and the tape recorder head, I came to the conclusion that this is important for some audio tapes. And returning to the topic - the waveform must be sinusoidal.

Demonstration of the same piece of tape as an example (this files can be downloaded from Dropbox.):

Before adjust the tape recorder head enter image description here

...after adjust the tape recorder head enter image description here

  • 3
    Are these commercial tapes, or 'home' (AKA pirated duplicate) recordings? Have you tried adjusting head azimuth on the weak recordings? What do the clipped 'meander' waveforms look like if you reduce the playback volume? Nov 17, 2019 at 10:09
  • 1
    These are commercial pirate tapes. Covers - dropbox.com/sh/t6uqlmwctsrhhi1/AABd-g8GODhJpNRmHQrDuIlia?dl=0 I do not plan to adjusting head azimuth until I digitize all the tapes, then I plan to return to those tapes that have problems. I can not yet reduce the playback volume. To do this, I need to disassemble the tape recorder.
    – A. Rumlin
    Nov 17, 2019 at 12:31
  • 4
    The 'sinusoidal' tape with unstable amplitude sounds like an analog copy recorded through the mic input (or perhaps even with a mic) with ALC (automatic level control) turned on. This explains the varying amplitude ('breathing') poor bandwidth and noise in the gaps. ie. a typical amateur pirate copy. Might be readable if the amplitude is increased until clipping. Nov 18, 2019 at 3:08
  • 3
    If by "decoding" you mean reconstructing the data stored on the tape (rather than being able to read the tape on original or reproduction hardware), then the important characteristic to look for when decoding is the time delay between zero-crossings (where the signal crosses the red horizontal line in your pictures). Alternatively, it may work better to measure the time delay between points where the curve has maximum slope versus minimum slope but this requires more math and may only help with particularly bad recordings. lvd's answer lists the expected time delays you need to fit data to.
    – Ken Gober
    Nov 18, 2019 at 14:47

7 Answers 7


Those variable amplitudes looks like electronics problem like failing caps somewhere along the way (recording/playback) or unshielded too long cables or partial remagnetization or even HW bug (some recorders like ELTA have a bug in writing head circuitry that corrupted tapes a bit each time it was played ...)

the correct output should be a rectangular signal with 2 levels of amplitude.

I do not know any tools for tapes but audio people are using AUDACITY

However writing own SW recognizing pulses and correcting the signal should be easy to do...

Here is captured GIF from mine emulator executing:

SAVE "xxx" CODE 0,16384

SAVE capture

On the left is border and on the right is Oscillogram of the SOUND output going to Soundcard...


I finally had some time/mood for this. I made an win32 app for filtering the wav files in manner I described in my comments. Here it is:

  • My Win32 ZX_emu 1.56 + tape wav filter app

    both apps are win32 standalone no need to install anything. Read the readme.txt inside zip to know how to use it ... I included also full source code for the filtering app (Borland/Embarcadero BDS 2006 Turbo C++)

    The filter sum all channels into mono and find local min/max peaks and center it around 0 and also rescale to uniform amplitude ... +/- some noise detection/handling. The filter itself is in


    source file in case you want to tweak it ...

I applied it on your GORR30_BallBreaker_A.wav here screenshot so you see the signal change after filtering:

filter preview

Your original wav does not load into my emulator. It does not go pass the first file header (no sync and no error). After filtering It got pass the file header:


but error while code:


so loader code is not correctly loaded (due to too much corruption of the tape):


So try to adjust the tape recorder head (with screw driver) first until you hear more clear sound, then play with volume ... digitize apply filter and try to load

Heh FUXOFT :) he had nice games, brings up memories

  • 1
    PS the last image does not look demagnetized to me its more likely just a problem with higher frequency not passing correctly through the audio path so it has smaller amplitude... so either wrong cap or even not good metalic layer material for that bandwith or even not strong enough writing head as higher frequency needs more energy to magnetize
    – Spektre
    Nov 17, 2019 at 10:16
  • 1
    What an emulator saves as a digital waveform is irrelevant for comparing with what a real (cheap and nasty) tape recorder saved on to real (cheap and nasty) tape - which is what the original spectrum decoder was designed to handle!
    – alephzero
    Nov 17, 2019 at 15:11
  • 1
    @alephzero You missed my point I just wanted to show there is no nasty PWM technique used by native BASIC SAVE commands only simple FM modulation with 2 frequencies on data and 3th on sync (start) so amplitude of signal is irelevant ... and not some nasty encoding technique
    – Spektre
    Nov 17, 2019 at 16:06
  • 1
    @Spektre There are many utilities for converting MP3 to WAV, like ffmpeg. There is a fundamental difference in uploading and downloading files of different sizes to a file hosting service. In WAV - 1Gb, In MP3 - 150Mb.
    – A. Rumlin
    Nov 17, 2019 at 16:37
  • 1
    @A.Rumlin had some time to play with this today. It took me while to implement loading from wavs into my emulator but it finally works (till now it uses tap file and audio input but your recording is bad for going through DAC/ADC again). After sharpening the pulses the result is much better (hearable and also loading sripes apear as should) but still not good enough for sucesfull load so I need to test the centering of signal (center the peaks around zero and then amplify cut off ...) will get back with results but have no clue when as this week is full already...
    – Spektre
    Nov 18, 2019 at 18:22

Check this Spectrum tape interface:


A 'pulse' here is either a mark or a space, so 2 pulses makes a complete square wave cycle.

Pilot tone: before each block is a sequence of 8063 (header) or 3223 (data) pulses, each of length 2168 T-states.

Sync pulses: the pilot tone is followed by two sync pulses of 667 and 735 T-states resp.

A '0' bit is encoded as 2 pulses of 855 T-states each.

A '1' bit is encoded as 2 pulses of 1710 T-states each (ie. twice the length of a '0')

The initial polarity of the signal does not matter - everything in the ROM loader is edge-triggered rather than level-triggered.

  • 3
    With the potential caveat: tape input is achieved through the Z80 in a busy loop, constantly polling a 1-bit conversion of the input wave. So a commercial title can do pretty much anything it wants as to bit encoding and baud rate.
    – Tommy
    Nov 17, 2019 at 21:31
  • How does this answer the question about waveforms? Sep 13, 2021 at 14:10


The shape is not as important as it looks. The Spectrum uses a primitive FSK decoding, so the amplitude of the audio signal is not used, nor if it is sinusoidal or squared. The key thing is "zero crossing points": the signal must be so that its level goes up and down the zero volts level and stay in either area the same time. During the decoding phase, the Spectrum detects edges (from low to high, or high to low) and measure how much time the signal stays in one half or the other.

So, any audio signal that meets this criteria, and has enough amplitude (about 3Vpp) so that the input can drive the small trigger schmitt input at the ULA should work. Ideally, edges should be as sharp as possible.


Any decent audio editor. Audacity can help you. I use Sound Forge more, and I've found the touch pencil tool to be extremely useful to perform fine editings to restore audio levels where the volume dropped out.


Use, when possible, a mono cassette, not a stereo one (the coil and aperture at the magnetic head is a little bigger and will help you to capture a better signal). Of course, demagnetize the reading head and adjust it. The Spectrum +2/+3 has a service mode in which a small utility to calibrate tape heads is available.


A possible tool is eightbitjim/cassette-nibbler: Data recovery from 8-bit computer cassette tapes (Commodore 64, Vic 20, ZX Spectrum, etc). I'm not sure how well it reads nonstandard loaders, but in listing mode (-destination=listing) it gave me this for the GORR34 tape converted to wav:

java -jar ../cassette-nibbler-0.1.jar -destination=listing ../GORR34_Firetrap_Carlos_Sainz.wav 
cassette-nibbler v0.1
Allow incorrect frame checksums : ON
Allow incorrect file checksums  : ON
Attempt to recover partial files: ON
Platforms enabled: commodore commodore16+4 c64-turbotape acorn300 acorn1200 spectrum oric1 oricatmos msx2400 msx1200 trs80 dragon32 apple2 amstrad atari 
(15) headless.data length 1796
0 FIRETRAP 1.bytes.4b3104c.ERR.zxspectrum.bin: 25190 bytes 
1 DR. BREE.program.5ac6307a.zxspectrum.bin: 1028 bytes 
2 D_BREED1.bytes.c1cbb19d.zxspectrum.bin: 2872 bytes 
3 LORNA.1.bytes.527e6822.zxspectrum.bin: 3663 bytes 
4 LORNA.2.incomplete.bytes.6c060aeb.ERR.zxspectrum.bin: 1 bytes 
5 CARLOS.program.b12f74ba.zxspectrum.bin: 527 bytes 
6 CARLOS.1.bytes.450493bd.zxspectrum.bin: 4217 bytes 
7 CARLOS.3.bytes.33b07286.zxspectrum.bin: 887 bytes 
8 INDY.program.d828517a.zxspectrum.bin: 255 bytes 
9 lucas.bytes.6728795d.zxspectrum.bin: 5120 bytes 
10 loader.bytes.d1d4554e.zxspectrum.bin: 256 bytes 
11 headlessFile95.incomplete.unknown.279f866f.ERR.zxspectrum.bin: 17421 bytes 
12 headlessFile114.incomplete.unknown.348fe7c0.ERR.zxspectrum.bin: 5039 bytes 
Processed 58 minutes 0 seconds (57.0x realtime)--------------------------------
(15) headless.data length 1796

FIRETRAP seems to be a cracked copy of R-Type 2, from the loader information dumped by cassette-nibbler. By running the program with no special options then converting the CARLOS* TAP files to wav, joining them, then running the whole mess through fuse, I at least got a loading screen: Carlos Sainz loading screen, via cassette-nibbler With some more intelligent use than mine, I'm sure you could recover something.

Alternatively there's audio2tape from fuse-utils. It's very slow, and didn't do as good a job.

  • Unfortunately this does not work for me in Windows7: java -jar d:\Games\ZX\cassette-nibbler-master\target\cassette-nibbler-0.3.jar -destination=listing GORR34_Firetrap_Carlos_Sainz.wav cassette-nibbler v0.3 Allow incorrect frame checksums : ON Allow incorrect file checksums : ON Attempt to recover partial files: ON 100%: GORR34_Firetrap_Carlos_Sainz.wav (0 files extracted): GORR34_Firetrap_Car No files found Processed 57 minutes 59 seconds (24.0x realtime) (0 files extracted): Pro
    – A. Rumlin
    May 7, 2021 at 5:03
  • I meant to say: I split the file to separate channels. Stereo computer audio seldom works
    – scruss
    May 7, 2021 at 23:05

I did recover a GORR30_BallBreaker_A.wav, and, yes this record is initially broken. There are twenty seven (27) bits missed in middle of it. The broken part is marked with yellow circle on screenshot: GORR30_BallBreaker_A.wav

To repair a wav file, I had used my program ZXTapeReviver (64-bit Windows version 3)

You can freely try to use it to repair your ZX Spectrum tape records. But, please, keep in mind, that this program is in early development stage and can contain some bugs.

Program overview and how-to-use video you can watch here: https://youtu.be/i3FRRAro8hA

Recovered TAP file you can download here: https://cloud.mail.ru/public/uDTo/SoLjm4sf8

  • the program not worked in Win7x64. Error 0xc0000005
    – A. Rumlin
    Sep 12, 2021 at 4:36
  • Windows 7 is outdated for now, please consider to use recent OS, such a Windows 10 or higher or modern linux distribution. Additionally, you can try to manually build the app from sources under your Windows 7 installation (I'm not sure about Qt support of Windows 7, so maybe you'll be get failed), as I do not have Windows 7 on my PC and can't do that.
    – mdaemon
    Sep 15, 2021 at 14:00

Waveform like on image #3 (https://i.stack.imgur.com/AmFn5.png) should work.

The perfect audio signal looks like this:

enter image description here

The procedure to achieve perfect copy:

  1. load original signal to PC (use Audacity free);
  2. correct signal if needed (Audacity);
  3. convert audio to digital TAP format (open in emulator, save as TAP);
  4. convert TAP to WAV for use on real Spectrum (Tap2Wav free).

If input audio signal is bad, try to tune audio head on cassette player by listening tone on headphones. Also, try to lower volume to 75%, as high amplification can make it sound worse. Don't bother saving games that you can download from some of the ZX Spectrum archives.

  • 4
    That's not the waveform you'd get out of a cassette, though: what you're showing there is the theoretically perfect square wave output from a program like tap2wav. Real tapes are much messier, and the OP is asking about existing tapes they wish to digitize, not ones they wish to create. So you're not really answering the question.
    – scruss
    Apr 9, 2020 at 16:28

Just my 2 cents on this. The Spectrum tapes you are looking at use Frequency Modulation (FM) instead of Amplitude Modulation (AM). This makes them incredibly resilient to amplitude noise, such as you are showing a lot of. So, the actual data values are not encoded by the amplitude of the signal, rather the frequency of it.

I assume that you'd need a frequency demodulator, either software or hardware.

But that's only half of your problem. The other half is that I assume that whatever data you have on there needs to run on a spectrum emulator, so you need to piece it back together correctly. Simply capturing the signal won't work, so I'd look for an emulator that has the ability to load from audio files, then save a snapshot of the memory right after loading.

I listened to some of the tapes you attached, and for the fun of it, I manually decoded the first header of the GORR11_A_SDII_B_TLL, it looks something like this:

01010011 S
01010010 R
01001001 I
01001001 I
00100000 space
00100000 space
00100000 space
00100000 space
00100000 space
00100000 space
-> Title seems to be SRII

10100100 164 
00000010 2
-> 676 bytes

-> to load at 0?


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .