|
- #!/usr/bin/python3
- import sys, getopt
-
- def Error(*args):
- print(sys.argv[0]+":", *args, file=sys.stderr)
- sys.exit(1)
-
- if len(sys.argv) > 1:
- Filename = sys.argv[1]
-
- Options, Args = getopt.getopt(sys.argv[1:], "bot:")
-
- def OptionExist(opt):
- global Options
- f = list(filter(lambda x: x[0] == opt, Options))
- return len(f) >= 1
-
- def GetOption(opt):
- global Options
- f = list(filter(lambda x: x[0] == opt, Options))
- if len(f) == 0: return None
- else: return f[0][1]
-
- if len(Args) >= 1:
- Filename = Args[0]
- else:
- Error("no input file")
-
- BinMode = OptionExist("-b")
- DataFile = open(Filename,"r" + ("b" if BinMode else "")) if Filename != "-" else sys.stdin
- # MiOPMdrv sound bank Paramer Ver2002.04.22
- # LFO: LFRQ AMD PMD WF NFRQ
- # @:[Num] [Name]
- # CH: PAN FL CON AMS PMS SLOT NE
- # [OPname]: AR D1R D2R RR D1L TL KS MUL DT1 DT2 AMS-EN
- Data = [] if not BinMode else DataFile.read()
- OpNames = ["M1","C1","M2","C2"]
- OpIdx = [0,2,1,3]
-
- if not BinMode:
- for line in DataFile.readlines():
- for byte in line.strip().split(",")[:16]:
- Data.append(int(byte,16))
-
- def PrintChannel(pan, fl, con, ams, pms, slot, ne):
- print("CH:", pan, fl, con, ams, pms, slot, ne)
-
- def PrintOp(op, ar, d1r, d2r, rr, d1l, tl, ks, mul, dt1, dt2, amsen):
- print(OpNames[op] + ":", ar, d1r, d2r, rr, d1l, tl, ks, mul, dt1, dt2, amsen)
-
- def GetFlCon(b):
- return (b & 0b00111000) >> 3, (b & 0b00000111)
-
- def GetAMSPMS(b):
- return (b & 0b00110000) >> 4, (b & 0b00000111)
-
- def GetDT1Mul(b):
- return (b & 0b01110000) >> 4, (b & 0b00001111)
-
- def GetKSAR(b):
- return (b & 0b11000000) >> 6, (b & 0b00011111)
-
- def GetAmsenD1R(b):
- return (b & 0b10000000) >> 7, (b & 0b00011111)
-
- def GetDT2D2R(b):
- return (b & 0b11000000) >> 6, (b & 0b00011111)
-
- def GetD1LRR(b):
- return (b & 0b11110000) >> 4, (b & 0b00001111)
-
- class RecordGrabber:
- def __init__(self, fields, recordSize, **options):
- self.fields = fields
- self.recordSize = recordSize
- self.instStep = 1
- for k, v in options:
- setattr(self, k, v)
-
- def __call__(self,data):
- f = self.fields
- slot = 120
- pan = 64
- ne = 0
-
- for n in range(0, len(data) // self.recordSize):
- ofs = n * self.recordSize
- print("@:%d %s" % (n, ("Ins%d" % n) if "name" not in f else
- f["name"](data, ofs)))
- print("LFO: 0 0 0 0 0") # the DRY violations will end! ...soon
-
- get = lambda s: data[ofs + f[s]] if s in f else 0
-
- fl, con = GetFlCon(get("flcon"))
- ams, pms = GetAMSPMS(get("amspms"))
-
- PrintChannel(pan, fl, con, ams, pms, slot, ne)
-
- for op in range(4):
- getOp = lambda s: data[ofs + f[s] + OpIdx[op]] if s in f else 0
- dt1, mul = GetDT1Mul(getOp("dt1mul"))
- tl = getOp("tl")
- ks, ar = GetKSAR(getOp("ksar"))
- amsen, d1r = GetAmsenD1R(getOp("amsend1r"))
- dt2, d2r = GetDT2D2R(getOp("dt2d2r"))
- d1l, rr = GetD1LRR(getOp("d1lrr"))
-
- PrintOp(op, ar, d1r, d2r, rr, d1l, tl, ks, mul, dt1, dt2, amsen)
-
-
- def PrintOPM(data):
- ne = (data[0xf] & 0b10000000) >> 7
- slot = 120
- pan = 64
- for i in range(8):
- print("@:%d Ins%d" % (i, i))
-
- print("LFO: 0 0 0 0 0") # no way to get this data... at least for now
-
- meta = data[0x20 + i : 0x3f + i : 8]
-
- fl, con = GetFlCon(meta[0])
-
- pms, ams = GetAMSPMS(meta[3])
-
- PrintChannel(pan, fl, con, ams, pms, slot, ne)
-
- for op in range(4):
- get = lambda x: data[x + i + OpIdx[op]*8]
-
- dt1, mul = GetDT1Mul(get(0x40))
- tl = get(0x60)
- ks, ar = GetKSAR(get(0x80))
- amsen, d1r = GetAmsenD1R(get(0xa0))
- dt2, d2r = GetDT2D2R(get(0xc0))
- d1l, rr = GetD1LRR(get(0xe0))
-
- PrintOp(op, ar, d1r, d2r, rr, d1l, tl, ks, mul, dt1, dt2, amsen)
-
- print()
-
- def PrintOPNBasic(data, opna = False):
- slot = 120
- pan = 64
- ne = 0 # either i'm blind or opn has no noise enable bit (not that i care either way)
- # SR in opn parlance is equivalent to D2R in opm, thanks yamaha
- # likewise, SL -> D1L and DR -> D1R
- ofs = 0x100 if opna else 0
- for i in range(3):
- n = i + (3 if opna else 0)
- print("@:%d Ins%d" % (n, n))
- print("LFO: 0 0 0 0 0") # no way to get this data... at least for now
-
- fl, con = GetFlCon(data[ofs + 0xb0 + i])
-
- ams, pms = GetAMSPMS(data[ofs + 0xb4 + i])
-
- PrintChannel(pan, fl, con, ams, pms, slot, ne)
-
- for op in range(4):
- get = lambda x: data[ofs + x + i + OpIdx[op]*4]
-
- dt1, mul = GetDT1Mul(get(0x30))
- tl = get(0x40)
- ks, ar = GetKSAR(get(0x50))
- amsen, d1r = GetAmsenD1R(get(0x60))
- dt2, d2r = GetDT2D2R(get(0x70))
- d1l, rr = GetD1LRR(get(0x80))
-
- PrintOp(op, ar, d1r, d2r, rr, d1l, tl, ks, mul, dt1, dt2, amsen)
-
- def PrintOPN(data):
- PrintOPNBasic(data)
-
- def PrintOPNA(data):
- PrintOPNBasic(data)
- PrintOPNBasic(data, True)
-
- TypeFuncs = {
- "opn": PrintOPN,
- "opna": PrintOPNA,
- "opm": PrintOPM,
- "raw": RecordGrabber({
- "flcon": 0x18,
- "amspms": 0x19,
- "dt1mul": 0x0,
- "tl": 0x04,
- "ksar": 0x08,
- "amsend1r": 0x0c,
- "dt2d2r": 0x10,
- "d1lrr": 0x14
- }, 0x20),
- "solfeace": RecordGrabber({
- "flcon": 0x00,
- "dt1mul": 0x02,
- "tl": 0x06,
- "ksar": 0x0a,
- "amsend1r": 0x0e,
- "dt2d2r": 0x12,
- "d1lrr": 0x16,
- "name": lambda data, ofs: data[ofs + 0x1a : ofs + 0x20].decode("shift-jis")
- }, 0x20)
- }
-
- Type = GetOption("-t")
- if Type==None:
- Error("no chip type specified")
- if Type not in TypeFuncs:
- Error(Type+":","unknown chip type")
-
- print("// Exported by hootvopm : https://git.lain.church/whut/hootvopm")
- print("// Chip type:",Type)
- TypeFuncs[Type.lower()](Data)
|