This is a very simple generator for JSFX scripts that remap CC numbers. The main idea is that when you have a synth that takes controls like filter frequency on certain CC's, and you have a controller like a Midimix, which generates fixed CC numbers for each knob, this allows you to create a mapper between the two. Very quick and dirty. The main intended use are the Ostirus and Nodal Red emulations of the Virus TI and Nord Rack 2X respectively, or indeed the hardware Rack 2X I have lying around.
Input File
Example
mr_flibble_says_hi
10 50
40 55
# comment
5 6 # other comment
The first line is the name (output is name.jsfx, desc line is desc: name).
The remaining lines, after # comments are stripped, consist of two numbers.
These can be integers like 42 or hex values like 0x42.
Example output:
desc: mr_flibble_says_hi
@block
while (
midirecv(ts,msg1,msg2,msg3) ?
(
c = msg1 & 0xF;
s = msg1 >> 4;
( s == 0xB ) ? (
cc = msg2;
val = msg3;
( cc == 5 ) ? ( cc = 6 ) :
( cc == 10 ) ? ( cc = 50 ) :
( cc == 64 ) ? ( cc = 55 );
midisend(ts,msg1,cc,val);
) : (
midisend(ts,msg1,msg2,msg3);
);
));
Python Script
#!/usr/bin/env python
import argparse
def main():
parser = argparse.ArgumentParser(prog="cc_map_gen",
description="CC Mapper JSFX Generator")
parser.add_argument("files",nargs="+")
ns = parser.parse_args()
for fn in ns.files:
proc(fn)
def decodehex(x):
try:
if x.startswith("0x"):
return int(x[2:],16)
return int(x)
except ValueError as e:
raise ValueError(f"Failed to parse as int or hex: {x}")
def proc(fn):
try:
with open(fn) as f:
lines = f.read().rstrip().splitlines()
except Exception as e:
print("#Exception",type(e),e,fn)
return
name = lines.pop(0)
d = {}
ks = set()
for line in lines:
line = line.split("#")[0].strip()
xs = line.split(" ")
if len(xs) != 2:
continue
try:
xs = [ decodehex(x) for x in xs ]
except ValueError as e:
print("#Exception",e)
continue
s,t = xs
ks.add(s)
d[s] = t
ks = sorted(ks)
"""
( cc == {s} ) ? ( cc = {t} ) :
( cc == {s} ) ? ( cc = {t} )
"""
out_lines = [ f" ( cc == {s} ) ? ( cc = {d[s]} )" for s in ks ]
out = " : \n".join(out_lines) + ";"
ofn = name + ".jsfx"
jsfx = gen_jsfx(name,out)
with open(ofn,"wt") as f:
print(jsfx,file=f)
print("Written",ofn)
def gen_jsfx(name,payload):
return f"""desc: {name}
@block
while (
midirecv(ts,msg1,msg2,msg3) ?
(
c = msg1 & 0xF;
s = msg1 >> 4;
( s == 0xB ) ? (
cc = msg2;
val = msg3;
{payload}
midisend(ts,msg1,cc,val);
) : (
midisend(ts,msg1,msg2,msg3);
);
));
"""
if __name__ == "__main__":
main()