#!/usr/bin/env python3 # ripsamples.py -- a python script for mass extracting samples from SPC files. # (C) 2018 neoadpcmextract.c (C) 2018 a dinosaur (zlib) import os import subprocess import pathlib import struct import hashlib # Directory constants. SPCDIR = "./spc" ITDIR = "./it" SMPDIR = "./sample" # External programs used by this script. SPC2IT = "spc2it" class Sample: length = 0 loopBeg = 0 loopEnd = 0 rate = 0 data = None def writesmp(smp, path): with open(path, "wb") as wav: # Make sure sample rate is nonzero. #TODO: figure out why this even happens... if smp.rate == 0: smp.rate = 32000 #print(path + " may be corrupted...") writeLoop = True if smp.loopEnd > smp.loopBeg else False # Write RIFF chunk. wav.write(b"RIFF") # Size of entire file following riffSize = 104 if writeLoop else 36 wav.write(struct.pack(" 1024: return if smpNum > 4000: return if insNum > 256: return if patNum > 256: return smpOfsTable = 0xC0 + ordNum + insNum * 4 for i in range(0, smpNum): f.seek(smpOfsTable + i * 4) smpOfs = int.from_bytes(f.read(4), byteorder="little", signed=False) smp = readsmp(f, smpOfs, i + 1) if smp != None: outwav = os.path.join(outpath, smp.hash + ".wav") if not os.path.isfile(outwav): pathlib.Path(outpath).mkdir(parents=True, exist_ok=True) writesmp(smp, outwav) def scanit(srcPath, dstPath): for directory, subdirectories, files in os.walk(srcPath): for file in files: if file.endswith(".it"): path = os.path.join(directory, file) outpath = dstPath + path[len(srcPath):-len(file)] readit(path, outpath) def scanspc(srcPath, dstPath): for directory, subdirectories, files in os.walk(srcPath): # Create output dir for each game. for sub in subdirectories: path = os.path.join(dstPath, sub) pathlib.Path(path).mkdir(parents=True, exist_ok=True) # Convert spc files. for file in files: if file.endswith(".spc"): # Don't convert files that have already been converted. itpath = os.path.join(dstPath + directory[len(srcPath):], file[:-3] + "it") if not os.path.isfile(itpath): path = os.path.join(directory, file) subprocess.call([SPC2IT, path]) path = path[:-3] + "it" if os.path.isfile(path): os.rename(path, itpath) # Actual main stuff. scanspc(SPCDIR, ITDIR) scanit(ITDIR, SMPDIR)