Skip to content

Latest commit

 

History

History
344 lines (278 loc) · 24.8 KB

MANUAL.md

File metadata and controls

344 lines (278 loc) · 24.8 KB

CassetteFlow Comprehensive User & Developer Manual


1. System Overview & Architecture

CassetteFlow is a hybrid analog-digital audio system that bridges physical compact cassette tapes with digital audio playback. By recording an inaudible or dedicated-track Frequency Shift Keying (FSK) timecode and metadata stream onto an analog cassette tape, CassetteFlow decodes the tape head position in real time using DSP demodulation and synchronizes lossless digital audio playback (MP3, FLAC, WAV) locally or across a local network.

High-Level Architecture

+-----------------------------------------------------------------------------------+
|                              CassetteFlow Core Engine                              |
|                                                                                   |
|  [ Line-In / Mic ] ──► JMinimodem (1200 Baud FSK Demodulator / DSP)               |
|                                │                                                  |
|                                ▼                                                  |
|                        Tape Decoder Engine                                        |
|                     (Timecode / Track Hash Sync)                                  |
|                                │                                                  |
|            ┌───────────────────┴───────────────────┐                              |
|            ▼                                       ▼                              |
|   Local Playback Engine                Built-in CassetteFlowServer                |
|   (WavPlayer / JavaSound)                     (Port 8192)                         |
|                                ┌───────────────────┼───────────────────┐          |
|                                ▼                   ▼                   ▼          |
|                           /music/*              /raw &              /player       |
|                         (HTTP 206           /dcs_lite Telemetry    (Web App)      |
|                       Audio Streaming)             │                   │          |
+────────────────────────────────────────────────────┼───────────────────┼──────────+
                                                     ▼                   ▼
                                       ┌───────────────────────────────────┐
                                       | Any Browser / Phone / M5Core / PC |
                                       |     (http://<host>:8192/player)   |
                                       └───────────────────────────────────┘

2. Desktop Application & GUI Tabs

The CassetteFlow desktop interface is organized into distinct workflow tabs:

2.1. ENCODE Tab

  • Multi-Function Directory & Smart Search/Import Input: The text field at the top of the ENCODE tab (defaulting to C:\mp3files) serves as an interactive multi-purpose command and input bar with 4 distinct operational modes:
    1. Audio Directory Path & Indexing:
      • Displays and sets the active working audio library directory (currentAudioDirectory).
      • Typing a directory path and loading will recursively scan, parse ID3 tags, and index all audio files.
      • Designates the base storage directory for generated tape data files (<AudioDir>\TapeFiles).
    2. Live Library Keyword Filter:
      • Typing any search string (e.g. artist name, song title, album, or filename) and pressing Enter (or clicking the (F) filter button) instantly filters the library list in real time.
      • Clearing the text field and pressing Enter clears the filter and restores the full library list and directory display.
    3. Spotify Playlist & Track Importer:
      • Pasting a Spotify URL or URI and pressing Enter automatically detects the media type via the integrated Spotify connector and loads tracks directly into the track list:
        • https://open.spotify.com/playlist/<id> $\to$ Loads entire Spotify playlist.
        • https://open.spotify.com/album/<id> $\to$ Loads full Spotify album tracks.
        • https://open.spotify.com/track/<id> $\to$ Imports a single Spotify track.
        • spotify:... URI $\to$ Imports active Spotify player queue.
    4. YouTube & DeckCast Playlist Importer:
      • Pasting a YouTube playlist URL (e.g. https://www.youtube.com/playlist?list=...) or a youtube:... URI and pressing Enter communicates with the DeckCast connector to automatically extract and populate video audio tracks into the playlist builder.
  • Audio Library Browser:
    • Scans your configured audio directory and displays all indexed MP3 and FLAC tracks.
    • Shows track duration, bitrate, filename, and ID3 tags (Title, Artist, Album, Year, Genre).
  • Side A & Side B Tracklist Builder:
    • Add selected tracks to Side A or Side B with dedicated controls.
    • Displays total running time for each side and compares it against standard tape lengths (C-46, C-60, C-90, C-120) with remaining minute/second indicators.
    • Allows reordering tracks and setting custom inter-track mute padding (default 4 seconds).
  • Dynamic Content Track (DCT) vs. Standard FSK:
    • Standard FSK: Encodes individual track hashes, track numbers, and playback seconds directly onto the tape.
    • DCT (Dynamic Content Track): Encodes a continuous 29-character tape timecode (DCT0A_01_aaaaaaaaaa_0945_0945), allowing the tape to be mapped dynamically to any playlist in software without re-recording the analog data track.
  • J-Card Generator & Export:
    • Generates formatted J-Card cassette inserts matching the exact tracklist, timings, and tape side distributions.
    • Integrates with J-Card templates for clean printing and cassette jewel case inserts.
    • Exports tracklist and tape configurations to JSON and text formats (template.jcard.json, tracklist.txt).
    • Open J-Card opens the J-Card template app bundled with CassetteFlow (/jcard?tape=<id>) with that tape's sides already filled in, and Save Template downloads the same .jcard.json for offline use. See 6.2 Bundled J-Card Template.

2.2. DECODE Tab

The DECODE tab provides live tape decoding, DSP demodulation, and automated digital playback synchronization.

  • JMinimodem Demodulator:
    • Captures line-in audio from your tape deck and decodes 1200-baud Bell 202 FSK audio tones directly in software without external modem hardware.
  • Live Speed & Telemetry Monitoring:
    • Instantaneous Baud Rate: Real-time edge-transition tracking (smoothed to ~1200 Baud).
    • Speed Offset / Drift ($\pm%$ ): Measures exact tape motor speed variation relative to nominal speed (e.g. +0.8% or -1.2%).
    • Modem SNR (Confidence Ratio): Measures signal-to-noise ratio in decibels (dB) to evaluate tape head alignment and signal quality.
    • Signal Strength (%): Displays incoming audio carrier amplitude percentage.
  • Tape Synchronization & Playback Controls:
    • START: Initializes the line-in audio stream and begins continuous decoding.
    • STOP: Halts decoding and pauses audio playback.
    • RESET: Clears telemetry counters, error tallies, and carrier holdover timers.
    • Carrier Detect: Detects active FSK carrier tone and automatically manages holdover timers during inter-track pauses or head lifts.

2.3. STREAM PLAY Tab

The STREAM PLAY tab enables synchronization between physical cassette tape playback and online/network streaming sources.

  • DeckCast & Spotify Integration:
    • Connects tape timecode offsets to online streams and local streaming daemons.
    • Synchronizes Spotify track selection and playback position directly from tape head timecode.
  • Stream Controls:
    • Supports dynamic stream offsets, track jumping, and remote streaming endpoints.

2.4. SETUP / CONSOLE Tab

The SETUP / CONSOLE tab configures hardware devices, directory paths, modem parameters, and provides raw system diagnostic logs.

  • Audio Hardware Configuration:
    • Input Mixer (Microphone / Line-In): Selects the audio input device capturing the cassette deck output.
    • Output Mixer: Selects the sound card or speaker output for digital audio playback.
  • Modem Parameters:
    • Configures nominal baud rate (default: 1200), mark frequency (1200 Hz), and space frequency (2200 Hz).
  • Directory & Property Management:
    • Configure default audio directory path (audio.directory in cassetteFlow.properties).
    • Set log file paths and external service URLs.
  • Console Monitor:
    • Live terminal logging showing raw FSK records, tape timecodes, decoded metadata, and HTTP server events.

3. Integrated Utilities & Standalone Tools

3.1. Tape Deck Tester (TapeDeckTester)

A dedicated diagnostic tool designed to test, measure, and calibrate cassette deck hardware.

  • Capabilities:
    • Measures motor speed accuracy, drift, and wow & flutter over time.
    • Computes real-time modem confidence ratio (SNR) to test azimuth and head cleanliness.
    • Interactive CLI console commands:
      • [S] - Display comprehensive speed & telemetry statistics.
      • [R] - Reset statistical accumulators.
      • [X] - Exit tester.
  • Synthetic Stream Calibration (DurationInputStream):
    • Generates test DCT audio streams of precise durations for calibration and loopback verification.

3.2. Tape Database Manager (TapeDatabaseFrame) & Track Finder (TrackFinderFrame)

  • TapeDatabaseFrame: Inspects, edits, and manages multi-tape collections saved in tapedb.txt.
  • TrackFinderFrame: Searches indexed tracks across large offline libraries and matches them against tape playlists.

4. Headless & Command-Line Interface (CLI) Mode

CassetteFlow can run completely headless without a graphical user interface—ideal for Raspberry Pi, home servers, or background services.

Running in CLI Mode

# Basic CLI mode (Headless server & streamer, local host audio muted by default)
java -jar dist/CassetteFlow.jar -cli

# CLI mode with local host speaker audio playback enabled on device 0
java -jar dist/CassetteFlow.jar -cli -play -d 0

# Headless mode with audio index rebuilt on startup
java -jar dist/CassetteFlow.jar -cli -index

CLI Command Options

Flag Parameter Description
-cli None Runs in Command Line Interface (headless) mode
-play, -audio None Enables local speaker audio playback on host machine
-noaudio, -mute None Disables local speaker audio playback on host machine (default in CLI)
-d, --device <index> Selects audio output mixer by numeric index (e.g. -d 0)
-index None Scans audio directory and rebuilds audiodb.bin & audiodb.txt
-dir <path> Loads audio files from specified custom directory
-dct <tapeId> Maps DCT timecode stream to a specific Tape ID (e.g. -dct CS00)
-dct-load None Explicitly loads saved tape.dct file on startup
-nodct None Explicitly disables DCT loading (clean raw stream mode)
-h, --help None Displays CLI help message

Monitoring CLI Resource Usage

  • Windows (PowerShell Live Monitor):
    while($true) { Clear-Host; Get-Process java | Select-Object Id, CPU, @{Name="RAM (MB)"; Expression={[math]::round($_.CPU, 1)}}, @{Name="RAM (MB)"; Expression={[math]::round($_.WorkingSet64/1MB, 1)}}; Start-Sleep 2 }
  • Linux / Raspberry Pi:
    htop -p $(pgrep -f CassetteFlow)

5. Built-in Web Server & REST API (CassetteFlowServer - Port 8192)

CassetteFlow includes a high-performance, multithreaded embedded HTTP server (CassetteFlowServer.java) listening on port 8192. It serves the web player, streams audio with byte-range seek support, and exposes REST endpoints for microcontrollers (ESP32, M5Core) and web clients.

API Endpoint Reference Table

Endpoint Method Response Format Description
/player GET text/html Serves the single-page CassetteFlow Web Player
/player.html GET text/html Web player alias
/library GET text/html Serves the Library & Tape Builder web app (web version of the ENCODE tab, playback only)
/library.html, /encode GET text/html Library app aliases
/api/library GET application/json (gzip) Audio library with tag metadata (id, ids, name, title, artist, album, genre, year, length, lengthAsTime, bitrate, file, sd, root, noFile). audioInfoDB stores most files under two hashes — the current relative-path hash plus an alias of the older filename hash kept for backward compatibility — so the endpoint collapses each file into one row (same rule as the desktop Track Finder) and returns the extra hashes in ids so old tape records still resolve. root marks files in the default audio directory, noFile marks stream/title-only records with no playable file, and indexKeys reports the raw hash count. Gzipped when the client sends Accept-Encoding: gzip
/api/tapedb POST application/json Stores a tape record into tapedb.txt. Body: {"tapeId":"0042","sideA":["hash",…],"sideB":[…],"overwrite":false,"backup":true}. Returns 400 (bad tape id / unknown hash), 409 (record exists and overwrite is false) or 200 with the written record keys
/jcard/template GET application/json The default J-Card template — the same template.jcard.json the desktop application loads
/jcard, /jcard/ GET text/html Serves the bundled J-Card Template web app (vendored from ed7n/jcard-template, BSD 2-Clause). Add ?tape=0042 (optionally &combine=1, &title=…, &artist=…) to open it with that tape's card already filled in, or ?data=<base64url json> to pass a card built by another page
/jcard/res/**, /jcard/cf-bridge.js GET CSS/JS/fonts/images The vendored J-Card assets and the CassetteFlow bridge that fills the card in
/api/jcard?tape=0042[&combine=1][&title=…][&artist=…] GET application/json The J-Card data for a tape: template fields plus titleUpper, titleLower, noteLower, sideALabel, sideBLabel, sideAContents, sideBContents. Returns 400 when no tape id is supplied
/music/* GET, HEAD Audio (audio/mpeg, audio/flac, etc.) HTTP 206 Partial Content audio stream supporting byte-range scrubbing and seek (Range: bytes=start-end)
/music?id=<hash> GET Audio Streams audio track resolved directly by 10-character hash
/raw GET text/plain (Chunked) Real-time persistent stream of raw decoded FSK line records
/rawdct GET text/plain (Chunked) Real-time persistent stream of raw FSK records with DCT translation
/dcs_lite GET application/json Compact telemetry JSON for ESP32/web clients (baud, speedOffset, snr, sig, data_errors, total_recs)
/dcs GET application/json Full decode state JSON including track lists and playback status
/api/status GET application/json Alias for /dcs_lite providing unified telemetry
/diag GET text/plain Formatted tape diagnostics and speed telemetry summary
/audiodb.txt GET text/plain 5-column standard audio database (from disk or memory)
/tapedb.txt GET text/plain Tape collection database (from disk or memory)
/tracklist.txt GET text/plain Current active tracklist
/dcc?command=<cmd> GET text/plain Executes remote decoder commands (start, stop, reset)
/playing GET, POST application/json Client Now Playing synchronization (receives track title/artist/hash on track change)
/play?track=<num> GET text/plain Triggers playback of specified track
/stop GET text/plain Stops playback

6. Embedded Web Player (player.html)

Access the player by navigating to http://localhost:8192/player (or http://<server-ip>:8192/player) on any device on your network.

Player Features

  1. Cassette Visualizer: Animated vintage cassette reels that turn dynamically with tape playback state.
  2. Tracks View: View active Side A, Side B, or Combined tracklists with track numbers, titles, artists, and durations.
  3. Tape DB View: Switch between any tape in your collection (Tape CS00, Tape EX01, etc.) and preview sides.
  4. Node Folders View: Browse albums and subfolders naturally. The Root folder isolates top-level test tracks, while nested albums appear in clean folder groupings.
  5. Modem & Signal Telemetry:
    • Baud Rate: Live instantaneous modem baud rate.
    • Speed Drift: Live percentage offset ($\pm%$).
    • Modem SNR: Live carrier SNR in dB.
    • Decode Errors: Displays errors / total_records (e.g. 0 / 142).
  6. Built-in Terminal: Live scrollable terminal logging every incoming raw FSK line record, side auto-flips, and drift adjustments.

6.1 Library & Tape Builder (library.html)

Access it at http://localhost:8192/library. This is the web equivalent of the desktop ENCODE tab, but for audio playback only — it does not perform any FSK encoding, DCT creation or waveform generation.

Library & Tape Builder Features

  1. Track List: On load it lists only the audio files sitting in the default audio directory (same as the desktop ENCODE tab) instead of the whole index, so the list stays short and fast. Default reloads that directory list, Filter narrows it by substring and Clear empties the working list.
  2. Find Dialog: Searches the complete audio index by Title, Artist, Genre, Album, Year or Folder with an ALL/MP3/FLAC format filter, a metadata preview pane and View All grouping (artist/genre/album/year/folder). Add To Track List appends the results to the working list (duplicates are skipped) and leaves the dialog open so several searches can be added in a row.
  3. Side A / Side B Builder: Add, Remove, Remove All, Shuffle (fills the side up to the selected tape length, skipping tracks already on the other side), Move Up / Move Down and Check for duplicate detection. The Play Time label turns red with *** Max Time Exceeded *** when a side is too long.
  4. Playback: Play plays the selected library track, Play Side plays a whole side in order and honours the Mute (s) setting as a countdown gap between tracks. Clicking another file in the track list while audio is already playing switches to it immediately (same behaviour as the desktop audioJListValueChanged); Ctrl/Shift-click only builds a selection and does not interrupt playback. Playback uses /music byte-range streaming and reports Now Playing to /playing.
  5. View Tape DB Dialog: Browse and filter tapedb.txt records, preview both sides (including tracklist sub-tracks for long mixes) with total play time, optionally Combine A&B, then Load Tape into the builder.
  6. Store Dialog: Writes the current Side A/B into tapedb.txt via POST /api/tapedb, with overwrite confirmation, tapedb.txt.bak backup and automatic refresh of the tape list.
  7. J-Card Dialog: The web version of the desktop "Copy/Export Track List" tab. Load/Refresh builds the SIDE A / SIDE B list from the current sides using each track's basic name (AudioInfo.getBasicName()), Open Template loads an existing .jcard.json as the base, Save Template fills in titleUpper / titleLower / noteLower (today's date) plus sideAContents / sideBContents and downloads the pretty printed JSON, and Open J-Card launches the J-Card template app that ships with CassetteFlow with the card already loaded.
    • Open J-Card passes the card to /jcard?data=<base64url json>; the bundled app reads no card data from its query string, so a small bridge injects it and the card renders ready to print — no file dialog, no internet connection. See 6.2 Bundled J-Card Template.

The browser caches audiodb.txt/tapedb.txt and the library JSON in IndexedDB, so reloads are instant; press ⟳-style reload (Default or a forced refresh) after re-indexing the music library.


6.2 Bundled J-Card Template (/jcard)

Open http://localhost:8192/jcard for the J-Card template app, or http://localhost:8192/jcard?tape=0042 to have tape 0042 already filled in. Both the library app (Open J-Card) and the desktop J-Card tab (Open J-Card) point here, so neither needs the public site or a manual file round trip any more.

  • Offline: every asset the page needs — stylesheets, module scripts and fonts — is served by CassetteFlow from src/jcard/, so the page renders and prints with no internet connection and sends nothing to a third party.
  • How the card gets in: upstream accepts no card data via URL. CassetteFlow serves the page with window.CF_JCARD_DATA (built by CassetteFlow.buildJCardData(…)) and a <base href="/jcard/">, then /jcard/cf-bridge.js fills the app's own form entries and refreshes the card. ?data=<base64url json> is the equivalent for a card built elsewhere (the library dialog).
  • /api/jcard?tape=… returns the same JSON for scripts, e.g. curl "http://localhost:8192/api/jcard?tape=0010".
  • combine=1 joins side A and B into a single side, matching the desktop Combine A&B option.

Credits and licence

The bundled app (src/jcard/, everything under res/) is a verbatim copy of ed7n/jcard-template at commit ffa66b7, with only three changes (relative stylesheet paths, and the Switch Interface and Offline Access/PWA sections removed). See src/jcard/VENDOR.md for the full provenance, the licence breakdown (BSD 2-Clause for the app and the freeware font, CC BY-SA 4.0 for the six EDEN Online portal stylesheets copied in for offline use) and the re-sync procedure (tools/fetch-jcard.ps1).


7. Data Formats & Protocol Specifications

7.1. FSK Line Record Formats

Standard Track Record (5 Underscore-Delimited Fields)

EX01A_01_a516a5e955_012_012
 │    │       │      │   └─ Total tape elapsed seconds (012)
 │    │       │      └───── Track playback seconds (012, or 012M for mute)
 │    │       └──────────── 10-character track hash ID
 │    └──────────────────── Track number (01)
 └───────────────────────── Tape ID and Side (EX01 Side A)

Dynamic Content Track (DCT) Record (29 Characters)

DCT0A_01_aaaaaaaaaa_0945_0945
 │    │       │       │    └─ Total tape elapsed seconds (4 digits: 0945)
 │    │       │       └────── Side elapsed seconds (4 digits: 0945)
 │    │       └────────────── 10-character dummy placeholder hash (aaaaaaaaaa)
 │    └────────────────────── Track indicator / segment number (2 digits: 01)
 └─────────────────────────── DCT Header & Side (DCT0A = Side A, DCT0B = Side B)

Carrier Loss / Noise Identifiers

  • ### NOCARRIER ### - Carrier tone dropped (head lifted, tape stopped, or end of side).
  • ### NOISY ### - Signal degraded below demodulation threshold.

7.2. Database Formats

audiodb.txt (5-Column Tab-Delimited Standard)

<Hash10C>\t<DurationSec>\t<Bitrate>\t/sdcard/<SDFilename>\t<RelativePath>
  • Example:
    a516a5e955	245	320	/sdcard/01_Song.mp3	Rock/Led Zeppelin/IV/01_Song.mp3
    

tapedb.txt (Tab-Delimited Tape Sides)

<TapeSideID>\t<Hash1>\t<Hash2>\t<Hash3>...
  • Example:
    EX01A	a516a5e955	b627c8f102	c938d4e311
    EX01B	d149e5f422	e250f6a533	f361a7b644
    

8. Configuration File Reference (cassetteFlow.properties)

# CassetteFlow Global Configuration
audio.directory=C\:\\mp3files
baud.rate=1200
download.server=http\://192.168.1.45/~pi/mp3/
jcard.site=http\://localhost\:8192/jcard
minimodem.log.file=C\:\\mp3files\\TapeFiles\\tape.log
Key Purpose
audio.directory Where the audio files and the audiodb/tapedb/tracklist databases live
jcard.site Base URL the desktop Open J-Card button opens (the tape id is appended as ?tape=<id>). Defaults to the bundled app at http\://localhost\:8192/jcard; set it to another host to use a different J-Card template