TapeTool2

Tape Tool 2 (aka tapetool2) is a command line utility for converting and repairing Microbee audio tape recordings.

TapeTool2 might also be useful for other retro tape recordings - especially those that are similar to the Kansas City standard but hasn't been tested in these cases.

This is the second version of this program. Version 2 is a complete re-write and the command line arguments aren't compatibile with version 1. The original version can still be found here.

Version 2 improves over version 1 in the following ways:

  • Simpler, easier to understand "filter" model
  • Support for single bit audio files
  • Tracing options for mapping data locations to sample numbers
  • Low-pass, high-pass and band-pass filters

Version 2 can't do some things that version 1 could. In particular version 2 can't repair existing audio files while maintaining as much of the original file as possible. V2 can only render a brand new, clinically clean audio recording.

Also Version 2 doesn't support TRS-80 tapes (yet).

Supported Platforms

TapeTool2 is written is C# and runs on Windows natively (assuming you have .NET installed) and will work on OS X and Linux if Mono is installed.

When using Mono, you need to invoke tapetool2 via mono. eg:

> mono tapetool2.exe --help

(or, you could write a simple shell script to invoke it)

Download

There's no installer for tapetool2, just download the .exe here:

Basic Usage

Tape tool processes audio, binary and other data through a series of filters - starting with a file reader and typically ending with a file writer. Filenames and filters are specified on the command line and are processed in a left to right manner.

For certain known file extensions, the appropriate reader or writer filter is automatically created. For the first file on the command line a file reader is used, for all subsequent file names a file writer is used.

In between file reader and writers you can place filters which perform various manipulations on the data passed to them.

Take the following command line as an example:

> tapetool2 robotf.wav smooth robotf_smoothed.wav

In this example a wave file reader will be used to read the file robotf.wav. The wave data will then be fed to a smooth filter which smoothes the audio signal before passing it to the wave writer filter that writes the smoothed audio data to the file robotf_smoothed.wav.

To get a full list of available filters, use --help (or see bottom of this page).

> tapetool2 --help

Filter Options

Most filters have options which can be set using command line switches after the filter. For example the smooth filter has a period setting which determines the smoothing period. eg:

> tapetool2 robotf.wav smooth --period:10 robotf_smoothed.wav

To determine the available options for a filter, use --help after the filter name. eg:

> tapetool2 smooth --help

will show:

tapetool2 v1.0 - Microbee/TRS-80 Tape Diagnotic Utility
Copyright (C) 2017 Topten Software.

smooth - Smooths audio using a moving average

Input Kind: audio stream
Output Kind: audio stream

Options:
  --period:val                   Smoothing period in samples (default=8)

Filter Data Types

For two filters to be connected the output of one filter needs to match the input of the next. The following example reads and audio file, parses it to a binary data stream using the microbee.audioToBytes filter and then writes it to the file output.bin

> tapetool2 robotf.wav microbee.audioToBytes output.bin

In some cases, tapetool can automatically construct an appropriate chain of filters to get the job done. eg:

> tapetool2 robotf.wav robotf.tap

will automatically use a sequence of filters consisting of:

robotf.wav
	-> waveReader 
	  -> microbee.audioToBytes 
	    -> microbee.bytesToBlocks 
	      -> microbee.blocksToBytes 
	        -> microbee.tapFileWriter
	          -> robotf.tap

Qualified Filter Names

Some filters are qualified with a microbee. prefix indicating the filter is specific to the Microbee platform. To save having to type the microbee prefix on every filter you can use the --microbee switch at the start of the command. eg:

> tapetool2 --microbee robotf.wav audioToBytes bytesToBlocks blocksToBytes robotf.tap

Single Bit Audio

Tapetool2 supports a special audio file format called Single Bit Audio (aka ".sba" files). This format is a compact audio representation for tape audio data and is the tape file format used by FPGABee.

The file format consists of a 16-byte header in little endian format:

#define SBA_SIGNATURE  0x53425054 		// TPBS aka "TaPe Bit Stream"

struct SINGLEBITAUDIOHEADER
{
    uint32_t signature;					
    uint32_t sampleRate;
    uint32_t totalSamples;
    uint32_t reserved;
}

...followed by the audio data with 8 single bit samples packed into each byte. The samples are ordered from least significant bit to most significant bit. ie: bit 0 plays first.

Single bit audio files are single channel (ie: mono) only and typically have a sample rate of 22050Hz which is enough for 1200baud data.

Stereo Audio Files

Most filters in tapetool2 only work with mono signals and if fed a multi-channel signal will use the first channel (ie: left channel) and will ignore the other channels.

There are however filters that can be used to pick out a specific channel, or to multi-cast one channel on two many.

See the filters: channelMultiCast, selectChannel.

Tracing

When attempting to repair tape audio recordings it's extremely handy to be able to map an error location in the conversion to the position in the original recording. To help with this, some of tapetool2's filters support a --trace:true option.

eg:

> tapetool2 --microbee robotf.wav audioToBytes --trace:true

Although typically you'll want to redirect this to a file for review:

> tapetool2 --microbee robotf.wav audioToBytes --trace:true > robotf.trace.txt

When enabled, tracing will cause the filter to output to stdout a verbose log:

Read bit 0 from sample 769
Read bit 0 from sample 832
Read bit 0 from sample 896
Read bit 0 from sample 960
Read bit 0 from sample 1024
Read bit 0 from sample 1088
Read bit 0 from sample 1152
Read bit 0 from sample 1216
Read byte #0 as 00 from sample 713
Read bit 0 from sample 1472
Read bit 0 from sample 1536
Read bit 0 from sample 1600
Read bit 0 from sample 1664
Read bit 0 from sample 1729
Read bit 0 from sample 1793
Read bit 0 from sample 1857
Read bit 0 from sample 1921
Read byte #1 as 00 from sample 1416
Read bit 0 from sample 2177
Read bit 0 from sample 2241
etc...

You can now open the audio file in an audio editing application and navigate to the exact sample where the problem occurs.

Examples

These examples have been split over multiple lines to clarify each filter. Normally you'd type all this on one line.

Converting a .wav file to a .tap file:

> tapetool2 
    robotf.wav 
    robotf.tap

Applying a bandpass filter to a wave file:

> tapetool2 
    robotf.wav 
    bandpass 
    robotf_filters.wav

Converting a .wav file to a .tap file with a 2.8Khz lowpass pass filter of on the input audio

> tapetool2 
    robotf.wav 
    lowpass --freq:2800 
    robotf.tap

Converting a .wav file to a .sba file

> tapetool2 
    robotf.wav 
    robotf.sba

Converting a .tap file to a text representation

> tapetool2 
    robotf.tap 
    robotf.blocks.txt

Packing unchunked binary data and converting to a wav file.

> tapetool2 --microbee 
    mygame.bin 
    packData 
    setHeader --autoStart:255 
    blocksToBytes 
    mygame.wav

Packing unchunked binary data and converting to a wav file with load address options:

> tapetool2 --microbee 
    mygame.bin 
    packData 
    setHeader --autoStart:255 --loadAddr:1024 --startAddr:2048 --filename:"MYGAME" 
    blocksToBytes 
    mygame.wav

Packing unchunked binary data from a file with non-".bin" file extension:

> tapetool2 --microbee 
    binReader --filename:mygame.rom 
    packData 
    setHeader --autoStart:255 
    blocksToBytes 
    mygame.wav

Current List of Supported Filters

Here's the current output from tapetool2 --help.

tapetool2 v1.1 - Microbee/Sorcerer Tape Diagnotic Utility
Copyright (C) 2017-2018 Topten Software.

Usage: tapetool2 [filters...]

Supported Filters:
  analyse                        Analyses an audio stream for tape related characteristics
  bandPass                       Applies a band-pass filter to an audio stream
  binReader                      Binary file reader (*.bin reader)
  binWriter                      Binary file writer (*.bin writer)
  changeRate                     Changes the sample rate of an audio stream without resampling it
  channelMultiCast               Multicasts a single audio channel to multiple identical channels
  dcOffset                       Adjusts the DC offset of an audio stream
  gain                           Adjusts the volume level of an audio stream
  highPass                       Applies a high-pass filter to an audio stream
  kansas.audioToBytes            Parses an Kansas City tape audio stream into a bytes
  kansas.audioToCycleKinds       Generates Kansas City audio cycles from an audio stream
  kansas.audioToHalfCycleKinds   Generates Kansas City audio half-cycles from an audio stream
  kansas.bitsToBytes             Decodes a Kansas City bit stream into byte stream
  kansas.bitsToCycleKinds        Generates Kansas City cycle kinds from a bit stream
  kansas.bitsToHalfCycleKinds    Generates Kansas City half-cycle kinds from a bit stream
  kansas.bytesToBits             Encodes a byte stream into Kansas City bit stream
  kansas.cycleKindsToAudio       Generates Kansas City audio cycles from a cycle kind stream
  kansas.cycleKindsToBits        Parses Kansas City cycle kinds into a bit stream
  kansas.halfCycleKindsToAudio   Generates Kansas City audio from a half-cycle kind stream
  lowPass                        Applies a low-pass filter to an audio stream
  microbee.audioToBytes          Parses an Microbee tape audio stream into a bytes
  microbee.audioToCycleKinds     Generates Microbee audio cycles from an audio stream
  microbee.audioToHalfCycleKinds Generates Microbee audio half-cycles from an audio stream
  microbee.bitsToBytes           Decodes a Microbee bit stream into byte stream
  microbee.bitsToCycleKinds      Generates Microbee cycle kinds from a bit stream
  microbee.blocksToBytes         Encodes a Microbee block stream into bytes
  microbee.bytesToBits           Encodes a byte stream into Microbee bit stream
  microbee.bytesToBlocks         Decodes a Microbee byte stream into blocks
  microbee.bytesToTap            Encodes a byte stream into a Microbee tap stream
  microbee.cycleKindsToAudio     Generates Microbee audio cycles from a cycle kind stream
  microbee.cycleKindsToBits      Parses Microbee cycle kinds into a bit stream
  microbee.halfCycleKindsToAudio Generates Microbee audio from a half-`cycle kind stream
  microbee.packData              Packs binary data into Microbee block format
  microbee.parseAudio            Parses a Microbee audio stream into block stream
  microbee.renderAudio           Parses a Microbee block stream into an audio stream
  microbee.setHeader             Updates the header in a Microbee block stream
  microbee.tapFileReader         Microbee tape file reader (*.tap reader)
  microbee.tapFileWriter         Mirobee tape file writer (*.tap writer)
  microbee.tapToBytes            Decodes a Microbee tap byte stream
  microbee.textBlockStreamReader Text block-stream file reader (*.blocks.txt reader)
  microbee.textBlockStreamWriter Text block-stream file writer (*.blocks.txt writer)
  microbee.unpackData            Unpacks binary data from Microbee block format
  mono                           Mixes a multi-channel audio stream to mono
  resample                       Resamples an audio stream to a new sample rate
  selectChannel                  Selects one channel from a multi-channel audio stream
  singleBitAudioReader           Single bit audio file reader (*.sba reader)
  singleBitAudioWriter           Single bit audio file writer (*.sba writer)
  smooth                         Smooths audio using a moving average
  sorcerer.audioToBytes          Parses an Exidy Sorcerer tape audio stream into a bytes
  sorcerer.audioToHalfCycleKinds Generates Exidy Sorcerer audio half-cycles from an audio stream
  sorcerer.bitsToBytes           Decodes a Exidy Sorcerer bit stream into byte stream
  sorcerer.bitsToHalfCycleKinds  Generates Kansas City half-cycle kinds from a bit stream
  sorcerer.blocksToBytes         Encodes a Exidy Sorcerer block stream into bytes
  sorcerer.bytesToBits           Encodes a byte stream into Exidy Sorcerer bit stream
  sorcerer.bytesToBlocks         Decodes a Exidy Sorcerer byte stream into blocks
  sorcerer.bytesToTap            Encodes a byte stream into a Exidy Sorcerer tap stream
  sorcerer.halfCycleKindsToAudio Generates Exidy Sorcerer audio from a half-cycle kind stream
  sorcerer.packData              Packs binary data into Exidy Sorcerer block format
  sorcerer.parseAudio            Parses a Exidy Sorcerer audio stream into block stream
  sorcerer.renderAudio           Parses a Exidy Sorcerer block stream into an audio stream
  sorcerer.setHeader             Updates the header in a Exidy Sorcerer block stream
  sorcerer.textBlockStreamReader Text block-stream file reader (*.blocks.txt reader)
  sorcerer.textBlockStreamWriter Text block-stream file writer (*.blocks.txt writer)
  sorcerer.unpackData            Unpacks binary data from Exidy Sorcerer block format
  textBitStreamReader            Text bit-stream file reader (*.bits.txt reader)
  textBitStreamWriter            Text bit-stream file writer (*.bits.txt writer)
  textByteStreamReader           Text byte-stream file reader (*.bytes.txt reader)
  textByteStreamWriter           Text byte-stream file writer (*.bytes.txt writer)
  textCycleKindReader            Text cycle-kind file reader (*.cycles.txt reader)
  textCycleKindWriter            Text cycle-kind file writer (*.cycles.txt writer)
  textHalfCycleKindReader        Text half-cycle-kind file reader (*.halfcycles.txt reader)
  textHalfCycleKindWriter        Text half-cycle-kind file writer (*.halfcycles.txt writer)
  waveReader                     Wave file reader (*.wav reader)
  waveWriter                     Wave file writer (*.wav writer)

Options:
  -h | --help                    Show these usage instructions, or use after filter name for help on that filter
  -v | --version                 Show version number
  --kansas                       Use filters 'kansas.*'
  --microbee                     Use filters 'microbee.*'
  --sorcerer                     Use filters 'sorcerer.*'