Skip to main content

Convert WAV recordings of Commodore 64 cassette tapes into emulator-readable TAP files.

Project description

wav2tapsp

CI

Converts WAV files (recordings of Commodore 64 cassette tapes) into C64 .tap files an emulator can read.

Hardly unique, but also somewhat easier to experiment with than having to hack ancient C code...

Install

$ pip install .

or, once released, pip install wav2tapsp.

Command line

$ wav2tapsp recording.wav        # writes recording.tap
$ wav2tapsp --cpufreq 1022727 recording.wav   # NTSC

(python -m wav2tapsp recording.wav works too.)

Library

import scipy.io.wavfile
import wav2tapsp

sr, samples = scipy.io.wavfile.read('recording.wav')
tap_bytes = wav2tapsp.wav_to_tap(samples, sr)          # bytes of a .tap file
pulses = wav2tapsp.wav_to_pulses(samples, sr)          # raw TAP pulse lengths

It works by finding rising zero crossings in the audio and emitting the time between them as TAP pulse lengths (CPU cycles / 8).

C64 tape formats

The package can synthesise and decode real C64 tape formats end to end (used by the tests, and handy for generating test tapes):

  • Standard ROM / Kernal loader — three pulse lengths, two pulses per bit, odd parity, per-block checksum, two block copies. c64tape.py.

  • Fast / turbo loaders — two pulse lengths, one pulse per bit (a short pulse for 0, a long pulse for 1). formats.py models the pulse-timing scheme of several real loaders using their documented pulse widths:

    Loader short / long pulse (TAP, cycles) reference
    Firebird T1 $44 / $7E (544 / 1008) FinalTAP ft[]
    Novaload $24 / $56 (288 / 688) FinalTAP docs
    Freeload $24 / $42 (288 / 528) FinalTAP docs
    Turbo Tape 250 $1A / $28 (208 / 320) FinalTAP docs / c64-wiki
    Turrican $1B / $27 (216 / 312) FinalTAP ft[]

References: the TAP format (pulse byte = CPU cycles / 8), PAL/NTSC CPU clocks (985248 / 1022727 Hz), the ROM loader timing ($30/$42/$56), and the FinalTAP loader database (per-loader pulse widths, the de-facto reference).

Testing

Tests run in CI across Python 3.10–3.13. To run them yourself:

$ pip install -e .[test]
$ pytest -v

The headline test is a full, emulator-free round trip that proves wav2tapsp preserves tape timing well enough to recover the original program:

PRG  ->  TAP  ->  WAV  --(wav2tapsp)-->  TAP  ->  PRG

A real C64 BASIC program is generated, encoded as a .tap, rendered to a .wav, run back through wav2tapsp, and decoded; the recovered PRG must be byte-identical to the original and still a structurally valid, runnable BASIC program. The same round trip runs for every fast-loader format above.

Minimum sample rate and resolution, from first principles

wav2tapsp recovers a pulse by counting samples between rising zero crossings: recovered_cycles = Δsamples × cpufreq / SR. Two bounds follow (derived in analysis.py, checked per format in the tests):

  • Sample rate. A pulse is one wave cycle of frequency cpufreq / pulse, so representing the shortest pulse needs SR ≥ 2·cpufreq/short (Nyquist). To keep a pulse on the correct side of the short/long threshold despite ±2 samples of crossing jitter needs SR > 4·cpufreq/gap, where gap is the cycle distance between the two pulse widths. The reliable minimum is 2 × max(...). Because gap dominates, the requirement scales like 1/gap — faster loaders need proportionally higher sample rates (PAL, safety ×2):

    Loader gap (cycles) reliable min sample rate
    Firebird T1 464 ~17.0 kHz
    Novaload 400 ~19.7 kHz
    Freeload 240 ~32.8 kHz
    C64 ROM 144 ~54.7 kHz
    Turbo Tape 250 112 ~70.4 kHz
    Turrican 96 ~82.1 kHz

    The tests confirm each loader fails below Nyquist and decodes at its reliable rate, and that the measured minimum is bracketed between the two.

  • Resolution (bit depth). Zero-crossing detection depends only on the sign of the signal, so one bit (the sign) is enough for a clean recording; amplitude resolution barely matters. The tests verify the round trip survives 1-bit quantisation of a sine wave for every loader. Sample rate, not bit depth, is the real constraint.

Layout

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

wav2tapsp-0.2.0.tar.gz (22.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

wav2tapsp-0.2.0-py3-none-any.whl (18.6 kB view details)

Uploaded Python 3

File details

Details for the file wav2tapsp-0.2.0.tar.gz.

File metadata

  • Download URL: wav2tapsp-0.2.0.tar.gz
  • Upload date:
  • Size: 22.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for wav2tapsp-0.2.0.tar.gz
Algorithm Hash digest
SHA256 39d727305e38ba0dae384dcb8124cf9b5a84c2ae0f3635738dc0aaa2aecbd681
MD5 d136d0041f4abf50dda932d43260d3eb
BLAKE2b-256 f150033fdfe021c2dd58029fa68c8d018ca5d20f5d346c7024a963c9231308e0

See more details on using hashes here.

Provenance

The following attestation bundles were made for wav2tapsp-0.2.0.tar.gz:

Publisher: publish.yml on anarkiwi/wav2tapsp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file wav2tapsp-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: wav2tapsp-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 18.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for wav2tapsp-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d2068ed847b1f48f478258ee0fb6be560ccf55a6fe974292fe021d05e2bdc2b9
MD5 e1cfa5d5e2d02c96024c9d53009b934f
BLAKE2b-256 42da6b1db347725da3c131ba44e115881280866274fdf679ef887270601f98d9

See more details on using hashes here.

Provenance

The following attestation bundles were made for wav2tapsp-0.2.0-py3-none-any.whl:

Publisher: publish.yml on anarkiwi/wav2tapsp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page