Added opensource Ableton Link protocol

This commit is contained in:
sam 2020-10-06 15:37:34 +02:00
parent e023a5ede6
commit 77afd636e8
10 changed files with 169 additions and 3 deletions

View File

@ -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

135
libs/alink.py Normal file
View 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)

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
libs/link.cpython-38-darwin.so Executable file

Binary file not shown.

BIN
libs/link.so Executable file

Binary file not shown.

View File

@ -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())

View File

@ -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()