import argparse, wave

snes2hex = lambda address: address >> 1 & 0x3F8000 | address & 0x7FFF

def romRead(n = 1):
    return int.from_bytes(rom.read(n), 'little')

argparser = argparse.ArgumentParser(description = 'WAV tools for SPC data.')
argparser.add_argument('rom', type = argparse.FileType('rb'), help = 'Filepath to Super Metroid ROM')
argparser.add_argument('address', type = lambda x: int(x, 0x10), help = 'Address of SPC block (SNES addressing)')
args = argparser.parse_args()
rom = args.rom

def decodeSample(sampleData, i_loop, pitchMultiplier):
    waveform = bytearray()
    lastSamples = [0, 0]
    for i in range(16):
        rom.seek(snes2hex(args.address))
        while True:
            header = romRead()
            loopMode = header & 3
            interpolationMode = header >> 2 & 3
            amplifierAmount = header >> 4
            
            for _ in range(8):
                byte = romRead()
                for sample in (byte >> 4, byte & 0xF):
                    sample -= sample >> 3 << 4
                    sample <<= amplifierAmount
                    sample >>= 1
                    if interpolationMode == 1:
                        sample += int(lastSamples[0] * 0.9375)
                    elif interpolationMode == 2:
                        sample += int(lastSamples[0] * 1.90625 - lastSamples[1] * 0.9375)
                    elif interpolationMode == 3:
                        sample += int(lastSamples[0] * 1.796875 - lastSamples[1] * 0.8125)
                    
                    if i != 0:
                        waveform += int.to_bytes(sample, 2, 'little', signed = True)
                    
                    lastSamples[1] = lastSamples[0]
                    lastSamples[0] = sample
            
            if loopMode & 1:
                break

print(f'N samples = {len(waveform) // 2}')
with wave.open('t.wav', 'wb') as f:
    f.setnchannels(1)
    f.setsampwidth(2)
    f.setframerate((0x0E14 * 2 >> 6 - 3) * 0x110 // 0x100 * 32000 // 0x1000)
    f.writeframes(waveform)

with open('t.bin', 'wb') as f:
    f.write(waveform)



