Added opensource Ableton Link protocol
This commit is contained in:
parent
e023a5ede6
commit
77afd636e8
11
README.md
11
README.md
@ -1,6 +1,7 @@
|
|||||||
# Forward Midi events to redis/OSC
|
# Forward Midi events to redis/OSC
|
||||||
|
|
||||||
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 Link protocol -> "/beats" & "/bpm"
|
||||||
All events are forwarded to a redis server and an OSC server.
|
All events are forwarded to a redis server and an OSC server.
|
||||||
|
|
||||||
Run :
|
Run :
|
||||||
@ -20,6 +21,10 @@ python3 miredis.py -h
|
|||||||
|
|
||||||
"/midi/cc/midichannel/ccnumber" value : "ccvalue"
|
"/midi/cc/midichannel/ccnumber" value : "ccvalue"
|
||||||
|
|
||||||
|
"/beats" value : "beatnumber"
|
||||||
|
|
||||||
|
"/bpm" value : "currentbpm"
|
||||||
|
|
||||||
## OSC
|
## OSC
|
||||||
|
|
||||||
/midi/noteon midichannel note velocity
|
/midi/noteon midichannel note velocity
|
||||||
@ -32,4 +37,8 @@ python3 miredis.py -h
|
|||||||
|
|
||||||
/midi/start
|
/midi/start
|
||||||
|
|
||||||
/midi/stop
|
/midi/stop
|
||||||
|
|
||||||
|
/beats beatnumber
|
||||||
|
|
||||||
|
/bpm bpm
|
||||||
|
Binary file not shown.
135
libs/alink.py
Normal file
135
libs/alink.py
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# -*- mode: Python -*-
|
||||||
|
|
||||||
|
'''
|
||||||
|
|
||||||
|
Ableton Link
|
||||||
|
|
||||||
|
LICENCE : CC
|
||||||
|
Sam Neurohack
|
||||||
|
|
||||||
|
|
||||||
|
Get:
|
||||||
|
|
||||||
|
git clone --recursive https://github.com/gonzaloflirt/link-python.git
|
||||||
|
|
||||||
|
Build:
|
||||||
|
|
||||||
|
Make sure python 3 is installed on your system.
|
||||||
|
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake ..
|
||||||
|
cmake --build .
|
||||||
|
|
||||||
|
'''
|
||||||
|
from libs import midix
|
||||||
|
import sys
|
||||||
|
|
||||||
|
prevphase = 0
|
||||||
|
bpm = 120
|
||||||
|
|
||||||
|
def Start():
|
||||||
|
global lnk
|
||||||
|
from libs import link
|
||||||
|
|
||||||
|
print("Link ENABLED")
|
||||||
|
lnk = link.Link(120)
|
||||||
|
lnk.enabled = True
|
||||||
|
lnk.startStopSyncEnabled = True
|
||||||
|
linked = True
|
||||||
|
|
||||||
|
def RedOSC(tempo_str, beats_str):
|
||||||
|
|
||||||
|
print()
|
||||||
|
print("Link : BPM " +tempo_str+" Beat "+str(beats_str) + ' \r')
|
||||||
|
#sys.stdout.flush()
|
||||||
|
|
||||||
|
|
||||||
|
# redis key : "/beats" value : currentbeat
|
||||||
|
if midix.toKey('/beats', beats_str)==True:
|
||||||
|
print("redis :", '/beats', beats_str)
|
||||||
|
|
||||||
|
# OSC : /midi/cc midichannel ccnumber value
|
||||||
|
midix.SendOSC('/beats', [beats_str])
|
||||||
|
print("osc :",'/beats', [beats_str])
|
||||||
|
|
||||||
|
# redis key : "/bpm" value : newbpm
|
||||||
|
if midix.toKey('/bpm', bpm)==True:
|
||||||
|
print("redis :", '/bpm', bpm)
|
||||||
|
|
||||||
|
# OSC : /bpm newbpm
|
||||||
|
midix.SendOSC('/bpm', [bpm])
|
||||||
|
print("osc :",'/bpm', [bpm])
|
||||||
|
|
||||||
|
|
||||||
|
def BeatEvent():
|
||||||
|
global lnk, prevphase
|
||||||
|
|
||||||
|
|
||||||
|
lnkstr = lnk.captureSessionState()
|
||||||
|
link_time = lnk.clock().micros();
|
||||||
|
tempo_str = '{0:.2f}'.format(lnkstr.tempo())
|
||||||
|
bpm = float(tempo_str)
|
||||||
|
#beatstep.SendOSCUI('/bpm', [bpm])
|
||||||
|
beats_str = '{0:.2f}'.format(lnkstr.beatAtTime(link_time, 0))
|
||||||
|
playing_str = str(lnkstr.isPlaying()) # always False ???
|
||||||
|
phase = lnkstr.phaseAtTime(link_time, 4)
|
||||||
|
|
||||||
|
|
||||||
|
# new beat ?
|
||||||
|
if int(phase) != prevphase:
|
||||||
|
prevphase = int(phase)
|
||||||
|
|
||||||
|
RedOSC(tempo_str, beats_str)
|
||||||
|
currentbeat = float(beats_str)
|
||||||
|
#midix.SendAU('/aurora/beats', beats_str)
|
||||||
|
#AllStatus("Beat "+str(beats_str))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Change current Link Tempo.
|
||||||
|
def newtempo(tempo):
|
||||||
|
global lnk
|
||||||
|
|
||||||
|
#print("val2", val2, "tempo", tempo)
|
||||||
|
|
||||||
|
if linked == True:
|
||||||
|
lnk.enabled = False
|
||||||
|
lnk.startStopSyncEnabled = False
|
||||||
|
lnk = link.Link(tempo)
|
||||||
|
lnk.enabled = True
|
||||||
|
lnk.startStopSyncEnabled = True
|
||||||
|
bpm = tempo
|
||||||
|
print("New BPM to Link", bpm)
|
||||||
|
RedOSC(str(tempo), "0.0")
|
||||||
|
|
||||||
|
'''
|
||||||
|
# redis key : "/bpm" value : newbpm
|
||||||
|
if midix.toKey('/bpm', bpm)==True:
|
||||||
|
print("redis :", '/bpm', bpm)
|
||||||
|
|
||||||
|
# OSC : /bpm newbpm
|
||||||
|
midix.SendOSC('/bpm', [bpm])
|
||||||
|
print("osc :",'/bpm', [bpm])
|
||||||
|
'''
|
||||||
|
|
||||||
|
else:
|
||||||
|
print("Link is disabled")
|
||||||
|
|
||||||
|
|
||||||
|
# increase or decrease BPM
|
||||||
|
def BPMAdj(val1, keyname):
|
||||||
|
|
||||||
|
|
||||||
|
# + 1
|
||||||
|
if val1 == 1:
|
||||||
|
newtempo(bpm+1)
|
||||||
|
|
||||||
|
# -1
|
||||||
|
if val1 == 127 and bpm > 0:
|
||||||
|
newtempo(bpm-1)
|
||||||
|
|
||||||
|
|
||||||
|
|
BIN
libs/link.cpython-35m-x86_64-linux-gnu.so
Normal file
BIN
libs/link.cpython-35m-x86_64-linux-gnu.so
Normal file
Binary file not shown.
BIN
libs/link.cpython-36m-x86_64-linux-gnu.so
Normal file
BIN
libs/link.cpython-36m-x86_64-linux-gnu.so
Normal file
Binary file not shown.
BIN
libs/link.cpython-37m-darwin.so
Normal file
BIN
libs/link.cpython-37m-darwin.so
Normal file
Binary file not shown.
BIN
libs/link.cpython-38-darwin.so
Executable file
BIN
libs/link.cpython-38-darwin.so
Executable file
Binary file not shown.
BIN
libs/link.so
Executable file
BIN
libs/link.so
Executable file
Binary file not shown.
@ -146,7 +146,18 @@ def SendUI(oscaddress,oscargs=''):
|
|||||||
log.err('Connection to Aurora UI refused : died ?')
|
log.err('Connection to Aurora UI refused : died ?')
|
||||||
pass
|
pass
|
||||||
#time.sleep(0.001
|
#time.sleep(0.001
|
||||||
|
# Ask redis for a given key
|
||||||
|
|
||||||
|
def fromKey(keyname):
|
||||||
|
|
||||||
|
return r.get(keyname)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Write to redis key
|
||||||
|
def toKey(keyname,keyvalue):
|
||||||
|
#print(keyname,keyvalue)
|
||||||
|
# Store encoded data in Redis
|
||||||
|
return r.set(keyname,keyvalue)
|
||||||
|
|
||||||
def GetTime():
|
def GetTime():
|
||||||
return time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime())
|
return time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime())
|
||||||
|
15
miredis.py
15
miredis.py
@ -96,7 +96,8 @@ argsparser.add_argument("-p","--port",help="Port of the Redis server ",default="
|
|||||||
# OSC Args
|
# OSC Args
|
||||||
argsparser.add_argument("-o","--oscip",help="IP address of the OSC server to forward midi events.",default="127.0.0.1",type=str)
|
argsparser.add_argument("-o","--oscip",help="IP address of the OSC server to forward midi events.",default="127.0.0.1",type=str)
|
||||||
argsparser.add_argument("-q","--oscport",help="Port of the OSC server ",default="9000",type=str)
|
argsparser.add_argument("-q","--oscport",help="Port of the OSC server ",default="9000",type=str)
|
||||||
|
argsparser.add_argument('-link',help="Enable Ableton Link (disabled by default)", dest='link', action='store_true')
|
||||||
|
argsparser.set_defaults(link=False)
|
||||||
|
|
||||||
args = argsparser.parse_args()
|
args = argsparser.parse_args()
|
||||||
redisIP = args.ip
|
redisIP = args.ip
|
||||||
@ -105,7 +106,15 @@ midix.oscIP = args.oscip
|
|||||||
midix.oscPORT = int(args.oscport)
|
midix.oscPORT = int(args.oscport)
|
||||||
midix.debug = args.verbose
|
midix.debug = args.verbose
|
||||||
|
|
||||||
|
# with Ableton Link
|
||||||
|
if args.link == True:
|
||||||
|
from libs import alink
|
||||||
|
|
||||||
|
alink.Start()
|
||||||
|
linked = True
|
||||||
|
else:
|
||||||
|
print("Link DISABLED")
|
||||||
|
linked = False
|
||||||
|
|
||||||
r = redis.StrictRedis(host=redisIP , port=redisPORT, db=0)
|
r = redis.StrictRedis(host=redisIP , port=redisPORT, db=0)
|
||||||
midix.r = r
|
midix.r = r
|
||||||
@ -122,7 +131,9 @@ if __name__ == '__main__':
|
|||||||
try:
|
try:
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
time.sleep(0.1)
|
time.sleep(0.001)
|
||||||
|
if linked:
|
||||||
|
alink.BeatEvent()
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
Loading…
Reference in New Issue
Block a user