tascam-dp008ex-sd-audio-extractor
Extract master mixes and multitrack stems from Tascam DP-008EX SD card images as standard WAV files — read-only, stdlib only, no recorder export needed.
Tested on DP-008EX only. The DP-006 / DP-008 / DP-24SD family is not verified — sibling models may shift the header fields. Verify with the
verifycommand before trusting any extraction.
The DP-008EX stores songs in an undocumented proprietary "BFS" format on a raw
MTR partition. This tool decodes the alloc table, walks the extent chains, and
renders both the stereo master chains and the per-track stem timelines straight
from a dd card image.
Install
pip install tascam-dp008ex-sd-audio-extractor
Or from source:
git clone https://github.com/juanmanueldaza/tascam-dp008ex-sd-audio-extractor
cd tascam-dp008ex-sd-audio-extractor
pip install .
Use
tascam-dp008ex-sd-audio-extractor devices # what cards are attached?
tascam-dp008ex-sd-audio-extractor image /dev/sdb -o card.img # card -> image, verified
tascam-dp008ex-sd-audio-extractor list card.img # MBR/MTR/BFS/songs/masters
tascam-dp008ex-sd-audio-extractor extract-all card.img # master chains -> mono WAVs
tascam-dp008ex-sd-audio-extractor stems card.img # stem timelines -> WAVs
tascam-dp008ex-sd-audio-extractor verify card.img # cross-check model (exit 0 = PASS)
Also runnable as python3 -m tascam_dp008ex_sd_audio_extractor .... Every read
command (list, carve, extract-all, stems, verify) accepts either a
whole block device or an image file.
Working with SD cards directly
The DP-008EX stores songs in an undeclared region after partition 0 — the multitrack audio is not on any filesystem. That is why a mounted card looks empty, and why copying files off it (or the recorder's own USB export) recovers nothing. You have to read the whole device.
# 1. what did we plug in? (judge by CONTENTS, not by REMOVABLE)
tascam-dp008ex-sd-audio-extractor devices
# /dev/mmcblk0 3.7 GiB no 6 master chain(s), 16 stem chain(s) <- your card
# 2. image it (read-only source; verified by re-reading the image)
sudo tascam-dp008ex-sd-audio-extractor image /dev/mmcblk0 -o ~/card.img
# 3. work on the image at leisure
tascam-dp008ex-sd-audio-extractor verify ~/card.img
tascam-dp008ex-sd-audio-extractor extract-all ~/card.img --out-dir ~/out
Or skip the image and read the card directly (needs privileges for the device):
sudo tascam-dp008ex-sd-audio-extractor stems /dev/mmcblk0 --out-dir ~/out
Guard rails — the two easy mistakes are handled for you:
-
Partition nodes are refused.
/dev/sdb1,/dev/disk2s1andD:\exit with an error naming the device you should use instead, because imaging one produces an empty-looking card and you would never know songs were missing. -
A mounted card is called out. If the desktop has already mounted the card,
deviceslists the mountpoint and says where the songs really are:MOUNTED VOLUMES on candidate devices /run/media/you/DP-008EX (vfat, /dev/mmcblk0p1) labelled like a DP-008EX: the songs are on /dev/mmcblk0, not in this mountpointDo not copy WAVs out of that mountpoint, and do not point the tool at it: the
WAVE/andBACKUP/folders there are exports and backups, not the songs. -
imagewill not overwrite the card it is reading, will not write to a device node, and will not clobber an existing file without--overwrite. An interrupted image continues with--resume. -
Reading raw devices needs root or the
diskgroup. The tool never writes to a card, and the card never needs to be mounted.
On macOS use the whole disk (/dev/rdisk2, faster than /dev/disk2); on
Windows use \\.\PhysicalDriveN. Both are recognised. devices reports what it
can see — including an honest "unreadable (needs root or the disk group)" — and
the table above is explicit about which platform has been tested against real
hardware.
list prints: MBR + MTR bounds, header checks (magic, self-ptr, mtr-start, bitmap),
BFS ROOT hits, song slots (Sxxx/SONGxxx, 250 slots on empty card), alloc-table
flag histogram + master/inode/extent counts.
What the commands do
- extract-all — walks the master extent chains (
0x90010006, even/odd cluster stereo interleave) and concatenates each chain in boff order into a WAV. Pairs share identical boff spans = one stereo song each. - stems — the second extent family (
0x90000006/0x90000005, raw 512B sector addressing) rendered as 44.1kHz mono timelines with each 16,384-sample fragment pasted at its boff. Sparse punch-in timelines (coverage ~1/18); import all stems of a song starting at 0 in your DAW. - verify — image-only cross-check of the render model: size-field pairing, master boundary smoothness (full vs half-cluster model), duplicate-block scan, stem durations vs song size fields, fragment packing adjacency, sparse-coverage sanity. Exit code 0 = PASS.
Layout learned (2026-09-26, 31GB image, empty card)
- MBR: 1× FAT32
0x0BLBA63 ×8385867; MTR = raw after p0 (MTR_BASE=0xFFEB1400, 26.7GB) - Header @MTR+0x800: magic
0x38974989, BE-u32, sector 512, reserved 192s; self +0x08, mtr-start +0x38, bitmap +0x3C, BFS ptr +0x68, backup root +0x74 (DP-03 has BFS ptr at +0x60 — 8B shift here) - BFS ROOT @MTR sector 200 (
0xFFECA400, +88 in sector), marker08EX - Song slots @MTR+~35.7MB (
0x1000D9428), stride 0x24, 250 entries - Alloc @MTR+0x288000 (1MiB, 16384×64B): pool
0x80040003/0x80104900×256, no0x80030000masters /0x9001000xinodes on empty card
Platform support — and what is actually verified
Being straight about the evidence, because "works on Linux, macOS and Windows" is a claim that deserves receipts:
| Linux | macOS | Windows | |
|---|---|---|---|
| Read a real card or image | verified on hardware | not yet executed | verified in CI |
devices discovery |
sysfs (size/removable) | /dev/disk* + diskutil |
\\.\PhysicalDriveN via CreateFileW/DeviceIoControl |
| Mounted-card warning | /proc/self/mounts |
mount output |
removable drive letters |
| Tested on | a 4GB Tascam DP-008EX card | nothing yet | CI runner's \\.\PhysicalDrive0 |
| Python versions exercised | 3.10, 3.12, 3.14 | 3.12 | 3.10, 3.12, 3.14 |
- Linux is the only platform with real hardware behind it. Everything below was
read from an actual card (
/dev/mmcblk0), andstems /dev/mmcblk0produces output byte-identical to rendering the same card from an image. - Windows runs for real in CI, where the runner's own
\\.\PhysicalDrive0is opened and queried. That is how two bugs in the ctypes backend were caught: theSTORAGE_PROPERTY_QUERYbuffer was undersized, so Windows rejected the query and the removable flag silently came back unknown. A removable drive letter is reported but deliberately not mapped to a physical drive — that needs a device-stack walk, and guessing would be worse than saying so. Use\\.\PhysicalDrive0, notE:\;E:\is a partition and is refused. Reading a physical drive needs an Administrator shell. - macOS is the weakest link, and this table says so. The code paths are
implemented (
diskutil info -plistfor size and removable state,mountfor volumes,/dev/rdisk*for the raw node) and type-check against a Darwin target, but the CI leg has been stuck in GitHub's macOS runner queue for hours at a time and has never executed; that leg is thereforecontinue-on-error, so a saturated runner pool cannot block releases. Nothing macOS-specific has been run against real hardware either. Use/dev/rdisk2, not/dev/disk2— the raw node skips the disk-arbiter cache and is several times faster. - Multi-partition cards are warned about, not silently mis-parsed: only
partition 0 is used to locate the MTR, so
verify/listwarn if a card declares more than one. A real DP-008EX always has exactly one.
Extract (card2, 2026-09-26) — songs recovered
Card2 (4GB): 2× 0x80030000/0x80030001 masters, 2× 0x90010001 inodes, 2062×
0x90010006 extents in 6 chains (heads = prev not in A-set). No 0x90010005
on this device — DP-008EX differs from DP-03 here.
Per-pair contribution = the whole 0x18000 cluster, concatenated in boff order
(boundary-discontinuity ratio ~1.0 full vs ~10–16 for the half-cluster model;
zero duplicate 4KB blocks; master boff step = 0xC000 samples = half a cluster,
unused by render). Alloc size fields (0x6ee44c6, 0xa9e5d72, 0x9d706a on
0x8003000x w11/w12) are sample counts: /44100 = 43.9/67.3/3.9min ≈ rendered
43.8/67.2/3.9min.
Output (mono 16-bit/44.1kHz): chain0/1 = 43.8min (song A), chain2/3 = 67.2min (song B), chain4/5 = 3.9min — identical boff spans within each pair, so each pair is one stereo song (even/odd cluster interleave, DP-03 style).
Stems (card2): format proof (2026-09-27)
Second extent family (0x90000006 ×402 + 0x90000005 ×12, 16 chains) uses
RAW 512B sector addressing:
- fragment = 64 sectors =
0x8000B = 16,384 samples: other fragments pack against it at exactly ±0x8000(2475/2484), so longer extents would overlap on disk; energy and sample-continuity hold across the whole0x8000. - boff = sample offset on the mono 44.1kHz track timeline (uniform stride
0x48000samples, fragment =0x4000samples → sparse punch-ins; boff_max matches the master size fields) → paste at byte offset boff×2. - chain pairs are simultaneous stereo/dual-mono takes: identical boff schedules, interleaved on disk (dense pairs sit same-boff back to back).
Rendered as silent timelines with fragments pasted (dense coverage 0.056 = 1/18 duty cycle). Durations match the masters: B 67.3, A 43.9, short 3.9min. rms-0 chains = unrecorded tracks.
Carve survey (2026-09-26, empty-card image)
Classifier per 96KiB cluster: zeros / near-silent / pcm-like / pcm-possible / noise (rms + silent-fraction + peak + zero-crossings). Stride-64 full pool (4243 clusters) → 1 false-positive pcm-like; stride-8 half-pool → isolated singles only, never consecutive runs. Verdict: fragments at most, no recoverable songs on the empty card.
Tests
python3 -m pytest tests/
Synthetic-data unit tests (no image needed) for extent parsing, chain walking, and both renderers (full-cluster concat, stem boff×2 paste at FRAG=0x8000).
Platform discovery is tested per platform rather than mocked: CI runs the
devices command on every runner, so the sysfs, diskutil and
CreateFileW/DeviceIoControl branches are all executed against real disks
instead of only being type-checked.
License
MIT — see LICENSE.
Metadata
Release files for tascam-dp008ex-sd-audio-extractor 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| tascam_dp008ex_sd_audio_extractor-0.2.0.tar.gz | 48.7 kB | With provenance | Details for tascam_dp008ex_sd_audio_extractor-0.2.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| tascam_dp008ex_sd_audio_extractor-0.2.0-py3-none-any.whl | Python 3 | none | any | Details for tascam_dp008ex_sd_audio_extractor-0.2.0-py3-none-any.whl |
Total release size: 79.6 kB
Release files / tascam_dp008ex_sd_audio_extractor-0.2.0.tar.gz
| Download URL | tascam_dp008ex_sd_audio_extractor-0.2.0.tar.gz |
|---|---|
| Size | 48.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
53b417bf72cdea419a674a3ece87a099981671f9d26a03d7f48042166a2849f6
|
|
BLAKE2b-256 checksum How to use checksums |
7d445197dbcdfc14c7ba8a49013dfa401747407e1b9790e22260afdf1d256d20
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.
Transparency logRelease files / tascam_dp008ex_sd_audio_extractor-0.2.0-py3-none-any.whl
| Download URL | tascam_dp008ex_sd_audio_extractor-0.2.0-py3-none-any.whl |
|---|---|
| Size | 30.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1679ce3010d3a205b5185736ccf97e413dfff0dfe9a01328c48841b7bcc0018c
|
|
BLAKE2b-256 checksum How to use checksums |
d5768e536aedbe6244895c54049cfd4683132660bb8587d2504edec12faee186
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.
Transparency logSecurity for tascam-dp008ex-sd-audio-extractor 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for tascam_dp008ex_sd_audio_extractor-0.2.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.