125 lines
3.3 KiB
Bash
Executable File
125 lines
3.3 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
|
|
|
|
if [ -z "${AKAIUTIL:-}" ]; then
|
|
if command -v akaiutil &>/dev/null; then
|
|
AKAIUTIL="akaiutil"
|
|
elif [ -x "/DATA/Downloads/akai/akaiutil-4.6.7/akaiutil" ]; then
|
|
AKAIUTIL="/DATA/Downloads/akai/akaiutil-4.6.7/akaiutil"
|
|
else
|
|
echo "error: akaiutil not found — set AKAIUTIL env var" >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
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/"
|