diff --git a/clitools/exports/toRedis.py b/clitools/exports/toRedis.py index 0ccf208..b98f2eb 100755 --- a/clitools/exports/toRedis.py +++ b/clitools/exports/toRedis.py @@ -17,12 +17,10 @@ by cocoa ''' from __future__ import print_function -import argparse -import ast -import json -import os -import redis import sys +import os +import argparse +import redis import time argsparser = argparse.ArgumentParser(description="Redis exporter LJ") @@ -46,18 +44,15 @@ r=redis.StrictRedis(host=ip, port=port, db=0) try: while True: - line = sys.stdin.readline() - if line == "": - time.sleep(0.01) - line = line.rstrip('\n') - line=line[1:-1] - # Decode as list of lists - pointsList = ast.literal_eval(line) - # convert to list of tuples - pointsList = [tuple(elem) for elem in pointsList] - # Convert to JSON string - line = json.dumps( pointsList ) - if r.set(key,line)==True: + line = sys.stdin.readline() + if line == "": + time.sleep(0.01) + line = line.rstrip('\n') + line=line[1:-1] + line = line.replace("[",'(') + line = line.replace("]",')') + line = "[{}]".format(line) + if r.set(key,line)==True: debug("exports::redis set("+str(key)+") to "+line) except EOFError: debug("break")# no more information diff --git a/clitools/filters/colorcycle.py b/clitools/filters/colorcycle.py index c4e9256..be9f74f 100755 --- a/clitools/filters/colorcycle.py +++ b/clitools/filters/colorcycle.py @@ -28,11 +28,15 @@ name = "filters::cycle" argsparser = argparse.ArgumentParser(description="Redis exporter LJ") argsparser.add_argument("-x","--centerX",help="geometrical center X position",default=300,type=int) argsparser.add_argument("-y","--centerY",help="geometrical center Y position",default=300,type=int) +argsparser.add_argument("-m","--min",help="Lowest value in the range 0-255",default=10,type=int) +argsparser.add_argument("-M","--max",help="Highest value in the range 0-255",default=255,type=int) argsparser.add_argument("-f","--fps",help="Frame Per Second",default=30,type=int) argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose") args = argsparser.parse_args() fps = args.fps +minVal = args.min +maxVal = args.max centerX = args.centerX centerY = args.centerY verbose = args.verbose @@ -60,9 +64,9 @@ def cycleColor( pl ): # debug(name,"pl:{}".format(pl)) value = currentColor[composant] if currentDirection == UP: - target = 255 + target = maxVal else: - target = 0 + target = minVal value += currentDirection currentColor[composant] = value @@ -71,7 +75,7 @@ def cycleColor( pl ): pl[i][2] = rgb2int( currentColor) # change the composant if target reached - if value == target: + if value <= target and currentDirection == DOWN or value >= target and currentDirection == UP : composant = random.randint( 0,2) value = currentColor[composant] if value == 0 : diff --git a/clitools/filters/kaleidoscope.py b/clitools/filters/kaleidoscope.py index 2e68d8d..ed5547c 100755 --- a/clitools/filters/kaleidoscope.py +++ b/clitools/filters/kaleidoscope.py @@ -29,8 +29,8 @@ import time name = "filters::kaleidoscope" argsparser = argparse.ArgumentParser(description="Redis exporter LJ") -argsparser.add_argument("-x","--centerX",help="geometrical center X position",default=300,type=int) -argsparser.add_argument("-y","--centerY",help="geometrical center Y position",default=300,type=int) +argsparser.add_argument("-x","--centerX",help="geometrical center X position",default=400,type=int) +argsparser.add_argument("-y","--centerY",help="geometrical center Y position",default=400,type=int) argsparser.add_argument("-f","--fps",help="Frame Per Second",default=30,type=int) argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose") diff --git a/clitools/filters/redilysis.py b/clitools/filters/redilysis.py new file mode 100755 index 0000000..d6d4d3b --- /dev/null +++ b/clitools/filters/redilysis.py @@ -0,0 +1,193 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# -*- mode: Python -*- + + +''' + +redilysis +v0.1.0 + +A complex effect that depends on redis keys for audio analysis + +see https://git.interhacker.space/teamlase/redilysis for more informations +about the redilysis project + +LICENCE : CC + +by cocoa + + +''' +from __future__ import print_function +import argparse +import ast +import os +import math +import random +import redis +import sys +import time +name = "filters::redilysis" + +def debug(*args, **kwargs): + if( verbose == False ): + return + print(*args, file=sys.stderr, **kwargs) +def now(): + return time.time() * 1000 + +# The list of available modes and the redis keys they need +oModeList = { + "rms_noise": ["rms"], + "rms_size": ["rms"], + "bpm_size": ["bpm"] + } +CHAOS = 1 +REDIS_FREQ = 300 + +# General Args +argsparser = argparse.ArgumentParser(description="Redilysis filter") +argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose") +# Redis Args +argsparser.add_argument("-i","--ip",help="IP address of the Redis server ",default="127.0.0.1",type=str) +argsparser.add_argument("-p","--port",help="Port of the Redis server ",default="6379",type=str) +argsparser.add_argument("-s","--redis-freq",help="Query Redis every x (in milliseconds). Default:{}".format(REDIS_FREQ),default=REDIS_FREQ,type=int) +# General args +argsparser.add_argument("-x","--centerX",help="geometrical center X position",default=400,type=int) +argsparser.add_argument("-y","--centerY",help="geometrical center Y position",default=400,type=int) +argsparser.add_argument("-f","--fps",help="Frame Per Second",default=30,type=int) +# Modes And Common Modes Parameters +argsparser.add_argument("-m","--modelist",required=True,help="Comma separated list of modes to use from: {}".format("i, ".join(oModeList.keys())),type=str) +argsparser.add_argument("--chaos",help="How much disorder to bring. High value = More chaos. Default {}".format(CHAOS), default=CHAOS, type=str) + +args = argsparser.parse_args() +ip = args.ip +port = args.port +redisFreq = args.redis_freq +verbose = args.verbose +fps = args.fps +centerX = args.centerX +centerY = args.centerY +chaos = float(args.chaos) +optimal_looptime = 1 / fps + +modeList = args.modelist.split(",") +redisKeys = [] +for mode in modeList: + if not mode in oModeList: + print("Mode '{}' is invalid. Exiting.".format(mode)) + sys.exit(2) + redisKeys += oModeList[mode] +redisKeys = list(set(redisKeys)) +debug(name,"Redis Keys:{}".format(redisKeys)) +redisData = {} +redisLastHit = now() - redisFreq +r = redis.Redis( + host=ip, + port=port) + +# Records the last bpm +last_bpm = time.time() + +def gauss(x, mu, sigma): + return( math.exp(-math.pow((x-mu),2)/(2*math.pow(sigma,2))/math.sqrt(2*math.pi*math.pow(sigma,2)))) + + +def bpm_size( pl ): + global last_bpm + bpm = float(redisData["bpm"]) + # Milliseconds ber beat + milliSecondsPerBeat = int(60 / bpm * 1000) + # Calculate the intensity based on bpm coming/leaving + # The curb is a gaussian + mu = math.sqrt(milliSecondsPerBeat) + milliTimeToLastBeat = (time.time() - last_bpm) * 1000 + milliTimeToNextBeat = (milliSecondsPerBeat - milliTimeToLastBeat) + intensity = gauss( milliTimeToNextBeat, 0 , mu) + debug(name,"bpm_size","milliSecondsPerBeat:{}\tmu:{}".format(milliSecondsPerBeat, mu)) + debug(name,"bpm_size","milliTimeToLastBeat:{}\tmilliTimeToNextBeat:{}\tintensity:{}".format(milliTimeToLastBeat, milliTimeToNextBeat, intensity)) + if milliTimeToNextBeat <= 0 : + last_bpm = time.time() + for i, point in enumerate(pl): + ref_x = point[0]-centerX + ref_y = point[1]-centerY + #debug(name,"In new ref x:{} y:{}".format(point[0]-centerX,point[1]-centerY)) + angle=math.atan2( point[0] - centerX , point[1] - centerY ) + l = ref_y / math.cos(angle) + new_l = l * intensity + #debug(name,"bpm_size","angle:{} l:{} new_l:{}".format(angle,l,new_l)) + new_x = math.sin(angle) * new_l + centerX + new_y = math.cos(angle) * new_l + centerY + #debug(name,"x,y:({},{}) x',y':({},{})".format(point[0],point[1],new_x,new_y)) + pl[i][0] = new_x + pl[i][1] = new_y + #debug( name,"bpm_noise output:{}".format(pl)) + return pl + +def rms_size( pl ): + rms = float(redisData["rms"]) + for i, point in enumerate(pl): + + ref_x = point[0]-centerX + ref_y = point[1]-centerY + debug(name,"In new ref x:{} y:{}".format(point[0]-centerX,point[1]-centerY)) + angle=math.atan2( point[0] - centerX , point[1] - centerY ) + l = ref_y / math.cos(angle) + debug(name,"angle:{} l:{}".format(angle,l)) + new_l = l + rms * chaos + new_x = math.sin(angle) * new_l + centerX + new_y = math.cos(angle) * new_l + centerY + debug(name,"x,y:({},{}) x',y':({},{})".format(point[0],point[1],new_x,new_y)) + pl[i][0] = new_x + pl[i][1] = new_y + #debug( name,"rms_noise output:{}".format(pl)) + return pl + +def rms_noise( pl ): + rms = float(redisData["rms"]) + debug(name, "pl:{}".format(pl)) + for i, point in enumerate(pl): + #debug(name,"rms_noise chaos:{} rms:{}".format(chaos, rms)) + xRandom = random.uniform(-1,1) * rms * chaos + yRandom = random.uniform(-1,1) * rms * chaos + #debug(name,"rms_noise xRandom:{} yRandom:{}".format(xRandom, yRandom)) + pl[i][0] += xRandom + pl[i][1] += yRandom + #debug( name,"rms_noise output:{}".format(pl)) + return pl + + +def updateRedis(): + global redisLastHit + global redisData + for key in redisKeys: + redisData[key] = r.get(key).decode('ascii') + debug("name","updateRedis key:{} value:{}".format(key,redisData[key])) + if key == 'bpm': + redisData['bpm_ttl'] = r.pttl(key) + debug(name,"redisData:{}".format(redisData)) + +try: + while True: + # it is time to query redis + if now() - redisLastHit > redisFreq: + updateRedis() + start = time.time() + line = sys.stdin.readline() + if line == "": + time.sleep(0.01) + line = line.rstrip('\n') + pointsList = ast.literal_eval(line) + # Do the filter + for mode in modeList: + pointsList = locals()[mode](pointsList) + print( pointsList, flush=True ) + looptime = time.time() - start + # debug(name+" looptime:"+str(looptime)) + if( looptime < optimal_looptime ): + time.sleep( optimal_looptime - looptime) + # debug(name+" micro sleep:"+str( optimal_looptime - looptime)) +except EOFError: + debug(name+" break")# no more information + diff --git a/clitools/generators/dummy.py b/clitools/generators/dummy.py index d827ff3..cf9059d 100644 --- a/clitools/generators/dummy.py +++ b/clitools/generators/dummy.py @@ -41,8 +41,8 @@ debug(name+" optimal looptime "+str(optimal_looptime)) while True: start = time.time() - #print("[(100.0, 100.0, 65280), (100.0, 500.0, 65280), (500.0, 500.0, 65280), (500.0, 100.0, 65280), (100.0, 100.0, 65280)]", flush=True); - print("[[100.0, 100.0, 65280], [110.0, 500.0, 65280], [510.0, 500.0, 65280], [510.0, 100.0, 65280], [100.0, 110.0, 65280]]", flush=True); + print("[[100.0, 100.0, 65280], [100.0, 500.0, 65280], [500.0, 500.0, 65280], [500.0, 100.0, 65280], [100.0, 100.0, 65280]]", flush=True); + #print("[[100.0, 100.0, 65280], [110.0, 500.0, 65280], [510.0, 500.0, 65280], [510.0, 100.0, 65280], [100.0, 110.0, 65280]]", flush=True); looptime = time.time() - start if( looptime < optimal_looptime ): time.sleep( optimal_looptime - looptime) diff --git a/clitools/generators/tunnel.py b/clitools/generators/tunnel.py index d9bd5df..00b220d 100644 --- a/clitools/generators/tunnel.py +++ b/clitools/generators/tunnel.py @@ -17,9 +17,11 @@ by cocoa ''' from __future__ import print_function -import time import argparse +import math +import random import sys +import time name="generator::tunnel" def debug(*args, **kwargs): @@ -29,25 +31,28 @@ def debug(*args, **kwargs): argsparser = argparse.ArgumentParser(description="tunnel generator") -argsparser.add_argument("-x","--centerX",help="geometrical center X position",default=300,type=int) -argsparser.add_argument("-y","--centerY",help="geometrical center Y position",default=300,type=int) -argsparser.add_argument("-s","--speed",help="point per frame progress",default=3,type=int) -argsparser.add_argument("-i","--interval",help="point per form interval",default=30,type=int) -argsparser.add_argument("-m","--max-size",help="maximum size for objects",default=300,type=int) -argsparser.add_argument("-f","--fps",help="Frame Per Second",default=30,type=int) argsparser.add_argument("-c","--color",help="Color",default=65280,type=int) +argsparser.add_argument("-f","--fps",help="Frame Per Second",default=30,type=int) +argsparser.add_argument("-i","--interval",help="point per shape interval",default=30,type=int) +argsparser.add_argument("-m","--max-size",help="maximum size for objects",default=500,type=int) +argsparser.add_argument("-r","--randomize",help="center randomization",default=5,type=int) +argsparser.add_argument("-s","--speed",help="point per frame progress",default=3,type=int) argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose output") +argsparser.add_argument("-x","--centerX",help="geometrical center X position",default=400,type=int) +argsparser.add_argument("-y","--centerY",help="geometrical center Y position",default=400,type=int) args = argsparser.parse_args() -color = args.color -fps = args.fps centerX = args.centerX centerY = args.centerY +color = args.color +fps = args.fps interval = args.interval max_size = args.max_size +randomize = args.randomize speed = args.speed verbose = args.verbose +origSpeed = speed optimal_looptime = 1 / fps square = [ [-1,1], @@ -57,38 +62,71 @@ square = [ [-1,1] ] +shape = square +currentCenter = [centerX, centerY] +centerVector= [0,0] +# tweak random basis +if randomize % 2 == 1: + randomize += 1 +debug(name,"randomize:{}".format(randomize)) +centerRand = int(math.sqrt(randomize) / 4 ) + 1 +debug( name, "centerRand:{}".format(centerRand ) ) class polylineGenerator( object ): def __init__( self ): - self.polylineList = [0] + self.polylineList = [[0,[currentCenter[0],currentCenter[1]]]] self.buf = [] def draw( self ): self.buf = [] - for it_pl, size in enumerate(self.polylineList): - for it_sqr, point in enumerate(square): - x = centerX + point[0]*size - y = centerY + point[1]*size + for it_pl, infoList in enumerate(self.polylineList): + size = infoList[0] + center = infoList[1] + for it_sqr, point in enumerate(shape): + x = center[0] + point[0]*size + y = center[1] + point[1]*size # Add an invisible point in first location if 0 == it_sqr: self.buf.append([x,y,0]) self.buf.append([x,y,color]) - debug( name, "buf size:", str(len(self.buf)) ) + #debug( name, "buf size:", str(len(self.buf)) ) return self.buf def increment(self): + global speed self.buffer = [] min_size = 9999 delList = [] - for i, size in enumerate(self.polylineList): + if randomize : + # Change the vector + centerVector[0] += random.randrange( -centerRand,centerRand ) + centerVector[1] += random.randrange( -centerRand,centerRand ) + # Modify the vector if it is over the limit + if currentCenter[0] + centerVector[0] >= centerX + randomize or currentCenter[0] + centerVector[0] <= centerX - randomize: + centerVector[0] = 0 + if currentCenter[1] + centerVector[1] >= centerY + randomize or currentCenter[1] +centerVector[1] <= centerY - randomize: + centerVector[1] = 0 + currentCenter[0] += centerVector[0] + currentCenter[1] += centerVector[1] + # Change speed + speed += int( random.randrange( int(-origSpeed),origSpeed ) ) + if speed < origSpeed : + speed = origSpeed + elif speed > (origSpeed + randomize / 2) : + speed = origSpeed + randomize / 2 + debug(name, "currentCenter:{} speed:{}".format(currentCenter,speed)) + + for i, shapeInfo in enumerate(self.polylineList): + size = shapeInfo[0] size += speed if size < min_size : min_size = size if size > max_size : delList.append(i) - self.polylineList[i] = size + self.polylineList[i][0] = size for i in delList: del self.polylineList[i] - if min_size >= interval: self.polylineList.append(0) - debug(name, "polyline:",self.polylineList) + if min_size >= interval: self.polylineList.append([0,[currentCenter[0],currentCenter[1]]]) + #debug(name, "polyline:",self.polylineList) + pgen = polylineGenerator() @@ -100,12 +138,13 @@ while True: pgen.increment() # send - print(pgen.draw(), flush=True); - + pl = pgen.draw() + print(pl, flush=True) + debug(name,"output:{}".format(pl)) looptime = time.time() - start if( looptime < optimal_looptime ): time.sleep( optimal_looptime - looptime) - debug(name+" micro sleep:"+str( optimal_looptime - looptime)) + #debug(name+" micro sleep:"+str( optimal_looptime - looptime))