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 hooks to all midi devices connected and listen for events.
 | 
				
			||||||
Miredis can optionnaly hook to opensourced Link protocol (200+ music & videos apps) -> "/beat" & "/bpm"
 | 
					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
 | 
					python3 miredis.py -link
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(for cheap midi interface midisport/midiman from audio on Linux : apt-get install midisport-firmware)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## New Features
 | 
					## New Features
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Client example : midicontrol.py
 | 
				
			||||||
- Added verbose mode -v
 | 
					- Added verbose mode -v
 | 
				
			||||||
- Added redis subscribe events
 | 
					- Added redis subscribe events
 | 
				
			||||||
- Added Clitools program selection mode for Launchpads
 | 
					- Added Clitools program selection mode for Launchpads
 | 
				
			||||||
@ -29,6 +32,8 @@ python3 miredis.py -link
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
## OSC
 | 
					## OSC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Following messages will be sent to an outside OSC server :
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/midi/noteon midichannel note velocity
 | 
					/midi/noteon midichannel note velocity
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/midi/noteoff midichannel note 
 | 
					/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
 | 
					LICENCE : CC
 | 
				
			||||||
Sam Neurohack
 | 
					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
 | 
					git clone --recursive https://github.com/gonzaloflirt/link-python.git
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Build:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Make sure python 3 is installed on your system.
 | 
					Make sure python 3 is installed on your system.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mkdir build
 | 
					mkdir build
 | 
				
			||||||
 | 
				
			|||||||
@ -162,7 +162,7 @@ def SendUI(oscaddress,oscargs=''):
 | 
				
			|||||||
        osclientlj.sendto(oscmsg, (TouchOSCIP, TouchOSCPort))
 | 
					        osclientlj.sendto(oscmsg, (TouchOSCIP, TouchOSCPort))
 | 
				
			||||||
        oscmsg.clearData()
 | 
					        oscmsg.clearData()
 | 
				
			||||||
    except:
 | 
					    except:
 | 
				
			||||||
        log.err('Connection to Aurora UI refused : died ?')
 | 
					        log.err('Connection to UI refused : died ?')
 | 
				
			||||||
        pass
 | 
					        pass
 | 
				
			||||||
    #time.sleep(0.001
 | 
					    #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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -107,7 +107,6 @@ if __name__ == '__main__':
 | 
				
			|||||||
    midix.check()
 | 
					    midix.check()
 | 
				
			||||||
    midix.loadConf()
 | 
					    midix.loadConf()
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    midix.toKey("/beats","0.0") 
 | 
					    midix.toKey("/beats","0.0") 
 | 
				
			||||||
    midix.toKey("/bpm",120)
 | 
					    midix.toKey("/bpm",120)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user