miredis/midicontrol.py

203 lines
4.1 KiB
Python

#!/usr/bin/python3
# -*- coding: utf-8 -*-
# -*- mode: Python -*-
'''
Midi controlled skeleton
v0.1.0
Needs miredis (listen to midi devices)
Licensed under GNU GPLv3
by Sam Neurohack
'''
import sys
import traceback
import argparse
import redis
import ast
argsparser = argparse.ArgumentParser(description="Midi/Redis control skeleton")
argsparser.add_argument("-c","--channel",help="Default midi channel (1)",default="1",type=str)
argsparser.add_argument("-m","--mode",help="Default running mode (33)",default="33",type=str)
args = argsparser.parse_args()
cchannel=args.channel
note = args.mode
ip = '127.0.0.1'
port = 6379
rds = redis.Redis(
host=ip,
port=port)
MidiSub = rds.pubsub()
MidiSub.subscribe("/midi/last_event")
print("Midi events subscribed")
cc = [0]*128
bpm = 120
notejump = {"33": "modeA()",
"35": "modeB()",
"44": "sys.exit(0)" # Beware
}
def MidiSubEvent():
global note
msg = MidiSub.get_message()
if msg:
message = str(msg['data'])
# Noteon change main function via notejump
if message.find('noteon') != -1:
noteon = message.split("/")
#print(noteon)
#if noteon[3] == cchannel:
if noteon[4] in notejump:
note = noteon[4]
print(notejump[note])
# Audio Redis keys continuously updated by specredis
def Current():
global data1, data2, data3
# live audio parameters from specredis.py in redis
# if data1 key like "[2.96, 1.01, 4.89, 3.29, 2.53, 2.10, 1.84, 1.66, 1.56, 1.50]"
data1redis = rds.get('levels')
data1 = ast.literal_eval(data1redis.decode('ascii'))
data1width = len(data1)
data2 = float(rds.get('spectrummax'))
data3 = float(rds.get('spectrumsum'))
# 1 CC -> 7 bits number : 0-127
# rerange end value between low high
# midifactor(ccnumber, channel, low, high, default)
def midifactor(ccnumber, channel = cchannel, low =0, high=127, default =1):
ccvalue = rds.get('/midi/cc/'+str(channel)+'/'+str(ccnumber))
if ccvalue is not None:
return rerange(int(ccvalue), 0, 127, low, high)
else:
print('Default value returned. No midi value in redis for channel', channel, 'CC', ccnumber)
return default
# 2 CC -> 14 bits number : 0 - 16383
# rerange end value between low high
# midifactor(ccnumber, channel, low, high, default)
def midifactor14(highcc, lowcc, channel = cchannel, low =0, high=16383, default =1):
lowvalue = rds.get('/midi/cc/'+str(channel)+'/'+str(lowcc))
highvalue = rds.get('/midi/cc/'+str(channel)+'/'+str(highcc))
if lowvalue is not None and highcc is not None:
return rerange((int(highvalue) << 7)+ int(lowvalue), 0, 16383, low, high)
else:
print('Default value returned. No midi value in redis for channel', channel, 'CC', ccnumber)
return default
# increase or decrease value
def Encoder(ccnumber, channel = cchannel):
ccvalue = rds.get('/midi/cc/'+str(channel)+'/'+str(ccnumber))
# encoder turned to right
if ccvalue == 1:
EncoderPlusOne(ccnumber)
# encoder turned to left
if ccvalue == 127:
EncoderMinusOne(ccnumber)
def EncoderPlusOne(ccnumber):
global cc
cc[ccnumber] +=1
print(cc[ccnumber])
def EncoderMinusOne(ccnumber):
global cc
if cc[ccnumber] >0:
cc[ccnumber] -= 1
print(cc[ccnumber])
def rerange(s,a1,a2,b1,b2):
return b1 + ((s - a1) * (b2 - b1) / (a2 - a1))
#
# mode A
#
def modeA():
print(midifactor(0, channel = cchannel, low =0, high=127, default =1))
pass
#
# mode B
#
def modeB():
print(midifactor14(0, 1, channel = cchannel, low =0, high=16383, default =1))
pass
#
# Main loop
#
if __name__ == "__main__":
note = "33"
running = True
try:
if (note in notejump) == False:
print('No function for that note')
sys.exit(0)
print('running', notejump[note])
while running:
# Some redis keys pull
Current()
# /noteon redis subscribe event like noteon -> change mode via eval
MidiSubEvent()
eval(notejump[str(note)])
except Exception:
print(traceback.print_exc())
except KeyboardInterrupt:
sys.exit(0)
finally:
print("End")
sys.exit(0)