{"id":24394496,"url":"https://github.com/flyingfathead/audio-bitsqueezer","last_synced_at":"2026-02-13T08:03:18.437Z","repository":{"id":271269918,"uuid":"912479355","full_name":"FlyingFathead/audio-bitsqueezer","owner":"FlyingFathead","description":"Python tool for converting modern audio into 8-bit or 4-bit formats, ideal for Commodore 64  (with or without MSSIAH) and other retro systems.","archived":false,"fork":false,"pushed_at":"2025-01-16T12:30:07.000Z","size":108,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-10T09:50:43.308Z","etag":null,"topics":["4-bit","8-bit","audio","audio-processing","bitsqueeze","c64","commodore-128","commodore-64","commodore64","crunch","dsp","mssiah","retro","retrocomputing"],"latest_commit_sha":null,"homepage":"","language":"Assembly","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/FlyingFathead.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-01-05T17:29:01.000Z","updated_at":"2025-04-08T15:32:23.000Z","dependencies_parsed_at":"2025-01-06T17:49:06.141Z","dependency_job_id":"e5d5d8ca-23fd-4cf5-a1e2-5573f26c0ced","html_url":"https://github.com/FlyingFathead/audio-bitsqueezer","commit_stats":null,"previous_names":["flyingfathead/audio-bitsqueezer"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FlyingFathead%2Faudio-bitsqueezer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FlyingFathead%2Faudio-bitsqueezer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FlyingFathead%2Faudio-bitsqueezer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FlyingFathead%2Faudio-bitsqueezer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/FlyingFathead","download_url":"https://codeload.github.com/FlyingFathead/audio-bitsqueezer/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248418219,"owners_count":21100191,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["4-bit","8-bit","audio","audio-processing","bitsqueeze","c64","commodore-128","commodore-64","commodore64","crunch","dsp","mssiah","retro","retrocomputing"],"created_at":"2025-01-19T19:59:59.351Z","updated_at":"2026-02-13T08:03:13.401Z","avatar_url":"https://github.com/FlyingFathead.png","language":"Assembly","funding_links":[],"categories":[],"sub_categories":[],"readme":"# audio-bitsqueezer\n\n**audio-bitsqueezer** (or just **bitsqueezer**) is a Python utility that converts modern audio files (MP3, WAV, FLAC, etc.) into:\n\n1. **Raw 4-bit nibble data** — great for old-school tricks on machines like the Commodore 64 (volume-register “digis”).  \n2. **MSSIAH-compatible 8-bit WAV** at 6 kHz — the perfect output format if you're using the Commodore 64 [MSSIAH](https://mssiah.com/) cartridge.\n3. **A complete `.prg`** — by merging the 4-bit `.raw` output with a minimal player via `maketoprg.py`, so you can run it directly on the C64 or an emulator, using its audio output.\n\n## How It Works\n\n- **Decode**: Uses [FFmpeg](https://ffmpeg.org/) via [pydub](https://github.com/jiaaro/pydub) to handle nearly any input format (MP3, WAV, AIFF, FLAC, etc.).  \n- **Downmix**: Automatically converts multi-channel audio to mono.  \n- **Resample**: Choose a sample rate (default is **4000 Hz** for 4-bit mode; forced **6 kHz** in MSSIAH mode).  \n- **Quantize \u0026 Pack** (4-bit mode): Maps 16-bit samples to 4 bits (0–15), then packs two samples into each byte for raw nibble data.  \n- **8-bit MSSIAH Mode**: Forces the audio to 6 kHz, 8-bit mono WAV. You can rename it on disk (e.g., `MYFILE    .WAV.PRG`) and load directly into MSSIAH Wave-Player.  \n- **Write**: Outputs either `.raw` (for 4-bit nibble data) or `.wav` (for MSSIAH).\n\n---\n\n- **(Optional)** Merge 4-bit data with a minimal player using **`maketoprg.py`**, yielding a self-contained `.prg` that can be `LOAD`ed and `RUN` on a real Commodore 64 (or emulator).\n\n---\n\n**NOTE:** Keep your audio samples short. The MSSIAH Wave-Player routine can typically handle ~5.5 seconds max. Longer than that may not fit in memory.\n\n## Requirements\n\n- **Python 3.6+**  \n- [**FFmpeg**](https://ffmpeg.org/download.html) installed and on your PATH.  \n  - Linux (Debian/Ubuntu): `sudo apt-get install ffmpeg`  \n  - macOS: `brew install ffmpeg`  \n  - Windows: Download from [ffmpeg.org](https://ffmpeg.org/) and ensure `ffmpeg.exe` is on your PATH.  \n- **pydub** library:  \n  ```bash\n  pip install pydub\n  ```\nIf you wish to use the `maketoprg.py`and run it somewhere, you'll either need i.e. [VICE C64 Emulator](https://vice-emu.sourceforge.io/) or an actual Commodore 64.\n\n## Installation\n\n```bash\ngit clone https://github.com/FlyingFathead/audio-bitsqueezer.git\ncd audio-bitsqueezer\npip install pydub\n```\nMake sure FFmpeg is installed and accessible. Otherwise, bitsqueezer won’t function.\n\n## Usage\n\n```\npython bitsqueezer.py \u003cinfile\u003e [--mode 4bit|mssiah] [--rate SAMPLE_RATE] [--out OUTPUT_FILE]\n```\n\n### Modes\n\n1. **4bit**: Creates raw 4-bit nibble data.  \n2. **mssiah**: Creates an 8-bit, 6 kHz WAV suitable for MSSIAH Wave-Player disk import.\n\n### Examples\n\n1. **Default 4-bit** (no `--out`, rate = **4000 Hz**):\n   ```bash\n   python bitsqueezer.py my_audio.wav --mode 4bit\n   ```\n   - Outputs `my_audio_4bit_4000hz.raw`.\n\n2. **Specify a different sample rate** (still 4-bit):\n   ```bash\n   python bitsqueezer.py my_audio.mp3 --mode 4bit --rate 8000\n   ```\n   - Outputs `my_audio_4bit_8000hz.raw`.\n\n3. **MSSIAH mode** (6 kHz, 8-bit WAV):\n   ```bash\n   python bitsqueezer.py my_audio.flac --mode mssiah\n   ```\n   - Outputs `my_audio_mssiah_6khz.wav`.\n\n4. **Fully specify output**:\n   ```bash\n   python bitsqueezer.py input.wav --mode mssiah --out final_mssiah.wav\n   ```\n   - Writes an 8-bit, 6 kHz WAV to `final_mssiah.wav`.\n\nOnce you have your file:\n- **4-bit `.raw`**: Ideal for direct volume-register playback on retro hardware.  \n- **MSSIAH `.wav`**: Rename to the MSSIAH-required `.WAV.PRG` format, place it on disk (or Savyour/USB), and import it into MSSIAH Wave-Player.\n\n## Creating a Self-Running `.prg` on the C64\n\nAfter you’ve produced a **4-bit `.raw`** file, you can merge it with one of the minimal C64 “player” binaries included in the **asm/** folder. This merging is done via **`makeprg.py`**, which:\n\n1. Reads the existing “player” `.prg` file (which already has a 2-byte load address and references a label for appended sample data).  \n2. Appends your `.raw` data plus a trailing sentinel `0x00`.  \n3. Writes out a single `.prg` that you can load and run on the C64.\n\nUsage example:\n```bash\n# Adjust the `PLAYER_BIN` variable inside makeprg.py to point to\n# the minimal player code you want, e.g. `loopplay.prg` or `loopplay_cia1_irq_16k.prg`.\n\n# Then run:\npython makeprg.py my_audio_4bit_4000hz.raw final.prg\n\n# \"final.prg\" is a complete, executable file for the C64 that\n# auto-plays your 4-bit sample data.\n```\n\nIf you have multiple pre-assembled players (e.g. a 4 kHz vs. 8 kHz vs. 16 kHz version), you can pick which `.prg` to merge your raw data with by editing the `PLAYER_BIN` path near the top of `makeprg.py`.\n\n## 4-Bit Raw Output Details\n\n- **Samples**: Each sample is 4 bits (0–15).  \n- **Two samples per byte**: Low nibble first, then high nibble.  \n- **No header**: Just raw amplitude data.  \n\n**Default rate** is **4000 Hz**. If you want a faster or higher-pitched playback, pass a higher `--rate` (like 8000 or 11025). Bear in mind the C64 routine must match your intended rate.\n\n## Testing on a Modern PC\n\nIf you attempt to directly play the `.raw` file (e.g., with `aplay` or `ffplay`), it will likely:\n- Sound half as long (since each byte has 2 × 4-bit samples).  \n- Sound “quiet” or “distorted,” because typical PCM players expect 8 bits per sample.  \n\n### Quick Workaround\n\nLower the playback rate by half; for example, if bitsqueezer used **4000 Hz**:\n```bash\naplay -f U8 -r 2000 -c 1 my_audio_4bit_4000hz.raw\n```\nThis forces the data to play at half speed in bytes, matching the correct pitch. Not perfect, but quick.\n\n### Proper Approach\n\nTo preview more accurately, **unpack** each 4-bit nibble to a standard 8-bit or 16-bit PCM file:\n1. Read each byte, separate into a low nibble (bits 0–3) and a high nibble (bits 4–7).  \n2. Map those nibbles to, e.g., 8-bit range (multiply by 16).  \n3. Write them out as two consecutive 8-bit samples.  \n4. Play that new file at the original 4 kHz rate.  \n\nOn a real C64, your playback routine is responsible for reading those nibbles at the correct speed, so no special “unpacking” is needed.\n\n## FAQ\n\n### Why 4 bits?\n\nThe C64’s SID volume register trick can’t easily generate true 8-bit PCM. This yields ~4 bits.  **bitsqueezer** automates that conversion for easy retro-audio playback.\n\n### Will It Sound “Good”?\n\nWell... welcome to the crunchy world of 4-bit audio.\n\n### MSSIAH Mode\n\nMSSIAH’s Wave-Player expects an 8-bit, 6 kHz WAV. If you’re using MSSIAH, select `--mode mssiah`. You do not need MSSIAH hardware for normal 4-bit usage though.\n\n## License\n\nUse freely. If you adapt it, a nod to [**FlyingFathead/bitsqueezer**](https://github.com/FlyingFathead/audio-bitsqueezer) is appreciated.\n\n(*Not affiliated with MSSIAH or its creators.*)\n\n## Contributing \u0026 Contact\n\nPull requests, bug reports, suggestions welcome.  \n\nEmail: `flyingfathead@protonmail.com`  \nTwitter/X: [@horsperg](https://x.com/horsperg)\n\n## Changelog\n\n- `v0.12` - telephone filter in `bitsqueezer.py` w/ `--telco` switch\n\n- `v0.11` - added single/dual nibble switches to `makeprg.py`\n\n   You can i.e. **force single nibble:**\n   ```bash\n   python makeprg.py sound_4bit.raw --singlenibble\n   ```\n\n   Or, **force dual nibble:**\n   ```bash\n   python makeprg.py sound_4bit.raw --dualnibble\n   ```\n\n- `v0.1` - initial release\n\n---\n\n**_Enjoy the squeeze_!**","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fflyingfathead%2Faudio-bitsqueezer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fflyingfathead%2Faudio-bitsqueezer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fflyingfathead%2Faudio-bitsqueezer/lists"}