osctools/oscplayer/oscplayer.py
2022-05-10 17:09:22 +02:00

228 lines
7.3 KiB
Python

import argparse
import random
from sqlite3 import TimeFromTicks
import time
from pythonosc import udp_client
import csv
import numpy as np
'''
0: t=0s bis t=20s keine ausgabe per osc
1: t=20s bis t=60s einmal die strophe triggern (also nachricht /3/oscplayer/strophe 1) "zufällig"(=basierend auf heartrate daten) zwischen t=20 und t=60
0: t=60s bis t=70s passiert nichts
2: t=70s bis t=120s nachricht /3/oscplayer/satz/<1-4> 1 . "zufällig" auf heartrate daten basierend triggern (muss nicht im beat sein), nicht zu häufig. ca alle 5-10s einmal
0: t=120s bis t=150s nichts, vorheriges hört auf
3: t=150s bis t=5*60s daten laufen pro zeile als 1/8 bei tempo 50 =0,6s/beat. schnelles durchalufen wie gehabt. mit zufälligen pausen
'''
midiChannel=3 #<- Change This Manually
scenetimes=[0,20,60,70,120,150,300] #definition of times
scenetimes=[0,2,4,5,6,10,300] #definition of times FASTER FOR TESTING
scenes =[0,1, 0, 2, 0, 3, 0] #definition of scenes
currentScene=-1 #keeps track of current scene
timemultiplier=1.0 #current time multiplier for speed changes
topicScene=['','','','']
valueScene=['','','','']
valueSceneOff=[0,0,0,0]
timemultiplierScene=[1,1,1,1]
#Scene 0
#Scene 1
topicScene[1]="/"+str(midiChannel)+"/oscplayer/strophe"
valueScene[1]=1
stropheTriggered=False #keep track if it is already triggered once
#Scene 2
topicScene[2]="/"+str(midiChannel)+"/oscplayer/satz/?"
valueScene[2]=1
valueCommulative=0
#Scene 3
topicScene[3]="/"+str(midiChannel)+"/oscplayer/value/?"
valueScene[3]=1
timemultiplierScene[3]=60.0 / 50 / 2
header=None
rows=None
rowid=0
time_start=0
client=None
lastvalue=[]
minvalues=[]
maxvalues=[]
meanvalues=[]
def init():
parser = argparse.ArgumentParser()
parser.add_argument("--ip", default="127.0.0.1", help="The ip of the OSC server")
parser.add_argument("--port", type=int, default=7000, help="The port the OSC server is listening on")
args = parser.parse_args()
global client
client = udp_client.SimpleUDPClient(args.ip, args.port)
csvlist=None
with open('heart_cluster_max.csv', newline='') as csvfile:
csvreader = csv.reader(csvfile, delimiter=',', quotechar='|')
csvlist = list(csvreader)
'''for row in csvreader:
if header is None:
header=row
else:
rows.vstack(row)
'''
global header
header=csvlist[0]
global rows
rows=csvlist[1:]
global rowid
rowid=0 #waiting for this row to send
global lastvalue
lastvalue=np.zeros(len(rows)-1)
global minvalues
global maxvalues
global meanvalues
minvalues=[float(min(x)) for x in filterEmpty(rows)]
maxvalues=[float(max(x)) for x in filterEmpty(rows)]
#print(np.mean(np.array((filterEmpty(rows))),axis=1)) #TODO: mittelwert ausrechnen funktioniert noch nicht
#exit()
#meanvalues=[float(np.mean(x)) for x in filterEmpty(rows)]
global time_start
time_start = time.time()
def getSceneFromTime(t):
i=0
while i<len(scenetimes) and t>=scenetimes[i]:
i+=1
return scenes[i-1]
def update(ctime):
global minvalues
global maxvalues
global meanvalues
global rowid
global client
global lastvalue
global timemultiplier
global currentScene
global stropheTriggered
global valueCommulative
timeFromStart=ctime-time_start
if currentScene!=getSceneFromTime(timeFromStart): #scene changed
currentScene=getSceneFromTime(timeFromStart)
timemultiplier=timemultiplierScene[currentScene] #update speed
_rowidBefore=rowid
rowid=0
while timeFromStart>=(float(rows[rowid%len(rows)][0])+float(rows[len(rows)-1][0])*int(rowid/len(rows)))*timemultiplier: #fast forward rowid
rowid+=1
'''if rowid>=len(rows): #ended?
rowid=0'''
rowid-=1
if _rowidBefore!=rowid:
print("Updated Row Id from "+str(_rowidBefore)+" to "+str(rowid)+" of "+str(len(rows)))
print("t="+str(timeFromStart)+"s: Changed Scene to "+str(currentScene)+". timemultiplier="+str(timemultiplier))
'''if rowid>=len(rows): #ended?
rowid=0 #when finished csv start from beginning
#return False
'''
if timeFromStart>=(float(rows[rowid%len(rows)][0])+float(rows[len(rows)-1][0])*int(rowid/len(rows)))*timemultiplier:
#print(rows[rowid])
crow=rows[rowid%len(rows)]
for i in range(len(header)-1):
if len(crow[i+1])>0: #value not empty
value=float(crow[i+1])
if (i==0): #were only using the first column of the csv file
if currentScene==1:
if not stropheTriggered:
_threshold=(minvalues[i]+(maxvalues[i]-minvalues[i])*0.2)
print("waiting for "+str(value)+"<"+str(_threshold))
if value<_threshold or getSceneFromTime(timeFromStart+1)!=currentScene: #trigger "randomly" or when scene is about to change
print("OSC: "+topicScene[currentScene]+": "+str(valueScene[currentScene]))
client.send_message(topicScene[currentScene], valueScene[currentScene])
client.send_message(topicScene[currentScene], valueSceneOff[currentScene])
stropheTriggered=True
if currentScene==2:
print("waiting. diff="+str(abs(maxvalues[i]-value))+" commulative="+str(valueCommulative))
valueCommulative+=abs(maxvalues[i]-value)
if valueCommulative>100:
valueCommulative=0 #reset
sendvalue=int(mapRange(value,minvalues[i],maxvalues[i],1,4+1))
print("OSC: "+topicScene[currentScene].replace('?',str(sendvalue))+": "+str(valueScene[currentScene]))
client.send_message(topicScene[currentScene].replace('?',str(sendvalue)), valueScene[currentScene])
client.send_message(topicScene[currentScene].replace('?',str(sendvalue)), valueSceneOff[currentScene])
if currentScene==3:
sendvalue=int(mapRange(value,minvalues[i],maxvalues[i],1,40+1))
print("OSC: "+str(rowid)+"/"+str(len(rows))+" t="+str(round(timeFromStart,2))+" "+topicScene[currentScene].replace('?',str(sendvalue))+": "+str(valueScene[currentScene]))
client.send_message(topicScene[currentScene].replace('?',str(sendvalue)), valueScene[currentScene])
client.send_message(topicScene[currentScene].replace('?',str(sendvalue)), valueSceneOff[currentScene])
lastvalue[i]=value #save last value
rowid+=1
return True
def filterEmpty(rows):
m=[np.array(rows)[:,i+1] for i in range(np.shape(np.array(rows))[1]-1)]
n=[[x if len(x)>0 else None for x in y] for y in m]
n=[list(filter(None, x)) for x in n]
return n
def mapRange(value, inMin, inMax, outMin, outMax):
return outMin + (((value - inMin) / (inMax - inMin)) * (outMax - outMin))
if __name__ == "__main__":
init()
res=True
while res:
res=update(time.time())