midicontrol example
This commit is contained in:
		
							parent
							
								
									fe6a56efaa
								
							
						
					
					
						commit
						dcaa716d29
					
				@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
Miredis hooks to all midi devices connected and listen for events.
 | 
			
		||||
Miredis can optionnaly hook to opensourced Link protocol (200+ music & videos apps) -> "/beat" & "/bpm"
 | 
			
		||||
All events are forwarded to a redis server and an OSC server.
 | 
			
		||||
All events are forwarded to your redis server and your OSC server. 
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
@ -19,8 +19,11 @@ To enable Link :
 | 
			
		||||
 | 
			
		||||
python3 miredis.py -link
 | 
			
		||||
 | 
			
		||||
(for cheap midi interface midisport/midiman from audio on Linux : apt-get install midisport-firmware)
 | 
			
		||||
 | 
			
		||||
## New Features
 | 
			
		||||
 | 
			
		||||
- Client example : midicontrol.py
 | 
			
		||||
- Added verbose mode -v
 | 
			
		||||
- Added redis subscribe events
 | 
			
		||||
- Added Clitools program selection mode for Launchpads
 | 
			
		||||
@ -29,6 +32,8 @@ python3 miredis.py -link
 | 
			
		||||
 | 
			
		||||
## OSC
 | 
			
		||||
 | 
			
		||||
Following messages will be sent to an outside OSC server :
 | 
			
		||||
 | 
			
		||||
/midi/noteon midichannel note velocity
 | 
			
		||||
 | 
			
		||||
/midi/noteoff midichannel note 
 | 
			
		||||
 | 
			
		||||
@ -4,17 +4,18 @@
 | 
			
		||||
 | 
			
		||||
'''
 | 
			
		||||
 | 
			
		||||
Ableton Link with bridge to OSC & Redis
 | 
			
		||||
alink v0.2
 | 
			
		||||
Ableton Link bridge to OSC & Redis
 | 
			
		||||
 | 
			
		||||
LICENCE : CC
 | 
			
		||||
Sam Neurohack
 | 
			
		||||
 | 
			
		||||
Get:
 | 
			
		||||
Needs link.cpython library. Comes with some precompiled libraries. 
 | 
			
		||||
 | 
			
		||||
To build it :
 | 
			
		||||
 | 
			
		||||
git clone --recursive https://github.com/gonzaloflirt/link-python.git
 | 
			
		||||
 | 
			
		||||
Build:
 | 
			
		||||
 | 
			
		||||
Make sure python 3 is installed on your system.
 | 
			
		||||
 | 
			
		||||
mkdir build
 | 
			
		||||
 | 
			
		||||
@ -162,7 +162,7 @@ def SendUI(oscaddress,oscargs=''):
 | 
			
		||||
        osclientlj.sendto(oscmsg, (TouchOSCIP, TouchOSCPort))
 | 
			
		||||
        oscmsg.clearData()
 | 
			
		||||
    except:
 | 
			
		||||
        log.err('Connection to Aurora UI refused : died ?')
 | 
			
		||||
        log.err('Connection to UI refused : died ?')
 | 
			
		||||
        pass
 | 
			
		||||
    #time.sleep(0.001
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										202
									
								
								midicontrol.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										202
									
								
								midicontrol.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,202 @@
 | 
			
		||||
#!/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)
 | 
			
		||||
 | 
			
		||||
@ -106,7 +106,6 @@ if __name__ == '__main__':
 | 
			
		||||
 | 
			
		||||
    midix.check()
 | 
			
		||||
    midix.loadConf()
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    midix.toKey("/beats","0.0") 
 | 
			
		||||
    midix.toKey("/bpm",120)
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user