9f107b5f80
- fetch: Go CLI tool for searching, downloading, and extracting AKAI sampler ISOs from archive.org - scripts/extract_wavs.sh: Shell script driving akaiutil to convert samples to WAV - Dockerfile: Multi-stage build packaging akaiutil + fetch - third_party/akaiutil: Vendored akaiutil v4.6.7 source (GPLv2) - docs/akaiutil.md: Full akaiutil reference
116 lines
3.0 KiB
Bash
Executable File
116 lines
3.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Extract all AKAI samples as WAV from all volumes in an AKAI disk image.
|
|
# Usage: ./extract_wavs.sh <iso-file> [output-dir]
|
|
# Uses a single akaiutil session to avoid repeated disk rescans.
|
|
|
|
set -euo pipefail
|
|
|
|
AKAIUTIL="${AKAIUTIL:-akaiutil}"
|
|
ISO="${1:?Usage: $0 <iso-file> [output-dir]}"
|
|
OUTPUT="${2:-wavs}"
|
|
|
|
# Derive ISO basename without extension, sanitized for filesystem use
|
|
isobase=$(basename "$ISO")
|
|
isobase="${isobase%.*}"
|
|
isobase=$(echo "$isobase" | sed 's/ /_/g' | sed 's/[^A-Za-z0-9_.-]/_/g' | sed 's/__*/_/g' | sed 's/^[_.]//; s/[_.]$//')
|
|
OUTPUT="$OUTPUT/$isobase"
|
|
|
|
TMPFILE=$(mktemp /tmp/akai_cmds.XXXXXX)
|
|
trap 'rm -f "$TMPFILE"' EXIT
|
|
|
|
mkdir -p "$OUTPUT"
|
|
|
|
# Phase 1: enumerate partitions from df output
|
|
echo "Enumerating partitions and volumes..."
|
|
DF_OUTPUT=$("$AKAIUTIL" -r "$ISO" 2>/dev/null <<< $'df\nq')
|
|
|
|
# Parse partition letters from the partition table in df output
|
|
PARTITIONS=()
|
|
while IFS= read -r line; do
|
|
if [[ "$line" =~ ^[[:space:]]+([A-Z])[[:space:]]+ ]]; then
|
|
PARTITIONS+=("${BASH_REMATCH[1]}")
|
|
fi
|
|
done <<< "$DF_OUTPUT"
|
|
|
|
if [[ ${#PARTITIONS[@]} -eq 0 ]]; then
|
|
echo "No partitions found in ISO. Trying single-partition layout..."
|
|
PARTITIONS=("A")
|
|
fi
|
|
|
|
echo "Found partitions: ${PARTITIONS[*]}"
|
|
|
|
# Scan each partition for volumes
|
|
VOLUME_LIST=$(
|
|
{
|
|
for p in "${PARTITIONS[@]}"; do
|
|
echo "cd /disk0/$p"
|
|
echo "dir"
|
|
done
|
|
echo "q"
|
|
} | "$AKAIUTIL" -r "$ISO" 2>/dev/null
|
|
)
|
|
|
|
# Parse partition-letter:volume-name pairs
|
|
VOLUMES=()
|
|
CURRENT_PART=""
|
|
while IFS= read -r line; do
|
|
for p in "${PARTITIONS[@]}"; do
|
|
if [[ "$line" == *"/disk0/$p >"* ]]; then
|
|
CURRENT_PART="$p"
|
|
fi
|
|
done
|
|
if [[ "$line" =~ ^[[:space:]]+[0-9]+[[:space:]]+(.+)[[:space:]]+-[[:space:]]+ ]]; then
|
|
name="${BASH_REMATCH[1]}"
|
|
name="${name%% -*}"
|
|
name="$(echo "$name" | sed 's/ *$//')"
|
|
if [[ -n "$CURRENT_PART" && -n "$name" ]]; then
|
|
VOLUMES+=("$CURRENT_PART|$name")
|
|
fi
|
|
fi
|
|
done <<< "$VOLUME_LIST"
|
|
|
|
echo "Found ${#VOLUMES[@]} volumes"
|
|
|
|
# Phase 2: build command file and create output dirs
|
|
> "$TMPFILE"
|
|
|
|
for entry in "${VOLUMES[@]}"; do
|
|
IFS='|' read -r part vol_name <<< "$entry"
|
|
|
|
safe_name=$(echo "$vol_name" | sed 's/ /_/g' | sed 's/[^A-Za-z0-9_.-]/_/g' | sed 's/__*/_/g' | sed 's/^[_.]//; s/[_.]$//')
|
|
[[ -z "$safe_name" ]] && safe_name="volume"
|
|
|
|
vol_dir="$OUTPUT/$safe_name"
|
|
mkdir -p "$vol_dir"
|
|
|
|
nav_name="${vol_name// /_}"
|
|
echo "lcd $vol_dir" >> "$TMPFILE"
|
|
echo "cd /disk0/$part/$nav_name" >> "$TMPFILE"
|
|
echo "sample2wavall" >> "$TMPFILE"
|
|
done
|
|
|
|
echo "lcd /" >> "$TMPFILE"
|
|
echo "q" >> "$TMPFILE"
|
|
|
|
# Phase 3: run extraction
|
|
echo "Starting extraction..."
|
|
START=$SECONDS
|
|
"$AKAIUTIL" -r "$ISO" < "$TMPFILE" 2>/dev/null > /tmp/akai_output.txt
|
|
DURATION=$((SECONDS - START))
|
|
|
|
total=0
|
|
while IFS= read -r line; do
|
|
if [[ "$line" =~ exported[[:space:]]+([0-9]+)[[:space:]]+file ]]; then
|
|
count="${BASH_REMATCH[1]}"
|
|
total=$((total + count))
|
|
echo " -> $count WAVs"
|
|
fi
|
|
done < /tmp/akai_output.txt
|
|
|
|
echo ""
|
|
echo "--- Done in ${DURATION}s ---"
|
|
echo "Total WAV files: $total"
|
|
|
|
echo ""
|
|
echo "WAVs are in: $OUTPUT/"
|