#!/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)