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.
|
||||||
|
|
||||||
|
|
||||||
![Clitools](https://www.teamlaser.fr/images/miredispad.png)
|
![Clitools](https://www.teamlaser.fr/images/miredispad.png)
|
||||||
@ -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…
Reference in New Issue
Block a user