diff --git a/clitools/filters/anaglyph.py b/clitools/filters/anaglyph.py
new file mode 100755
index 0000000..b67dc3e
--- /dev/null
+++ b/clitools/filters/anaglyph.py
@@ -0,0 +1,201 @@
+#!/usr/bin/python3
+# -*- coding: utf-8 -*-
+# -*- mode: Python -*-
+
+
+'''
+
+anaglyph
+v0.1.0
+
+Attempts to create a valid 3D-glasses structure
+
+LICENCE : CC
+
+by cocoa
+
+
+'''
+from __future__ import print_function
+import argparse
+import ast
+import math
+import os
+import random
+import sys
+import time
+name = "filters::cycle"
+
+maxDist = 300
+
+argsparser = argparse.ArgumentParser(description="Redis exporter LJ")
+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("-m","--min",help="Minimal displacement (default:2) ",default=1,type=int)
+argsparser.add_argument("-M","--max",help="Maximal displacement (default:20) ",default=5,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
+
+optimal_looptime = 1 / fps
+name = "filters::anaglyph"
+
+def debug(*args, **kwargs):
+ if( verbose == False ):
+ return
+ print(*args, file=sys.stderr, **kwargs)
+
+def rgb2int(rgb):
+ #debug(name,"::rgb2int rbg:{}".format(rgb))
+ return int('0x%02x%02x%02x' % tuple(rgb),0)
+
+def isValidColor( color, intensityColThreshold ):
+ if color[0] + color[1] + color[2] > intensityColThreshold:
+ return True
+ return False
+
+# These are paper colors
+red = (41,24,24)
+white = (95,95,95)
+blue = (0,41,64)
+
+red = (86,0,0)
+blue = (0,55,86)
+white = (125,125,125)
+def anaglyph( pl ):
+
+ debug(name,'--------------- new loop ------------------')
+ # We will send one list after the other to optimize color change
+ blueList = list()
+ redList = list()
+ whiteList = list()
+ out = []
+ out1 = []
+ out2 = []
+ out3 = []
+
+ # The anaglyphic effect will be optained by :
+ # * having close objects appear as white
+ # * having distant objects appear as blue + red
+ # * having in between objects appear as distanceDecreased(white) + blue + red
+ for i, point in enumerate(pl):
+ ref_x = point[0]-centerX
+ ref_y = point[1]-centerY
+ ref_color = point[2]
+ angle = math.atan2( ref_x , ref_y )
+ dist = ref_y / math.cos(angle)
+ white_rvb = (0,0,0)
+ blue_rvb = (0,0,0)
+ red_rvb = (0,0,0)
+
+ # Calculate the point's spread factor (0.0 to 1.0)
+ # The spread is high if the point is close to center
+ """
+ dist = 0 : spread = 1.0
+ dist = maxDist spread = 0.0
+ """
+ if dist == 0:
+ spread = 1.0
+ else :
+ spread =( maxDist - dist ) / maxDist
+ if spread < 0.0:
+ spread = 0.0
+
+ #debug(name,"dist:{} spread:{}".format(dist,spread))
+
+ # White color is high if spread is low, i.e. point away from center
+ """
+ spread = 1.0 : white_c = 0.0
+ spread = 0.0 : whice_c = 1.0
+ """
+ if point[2] == 0:
+ white_color = 0
+ else:
+ white_factor = 1.0 - math.pow(spread,0.5)
+ white_rvb = tuple(map( lambda a: int(white_factor* a), white))
+ white_color = rgb2int( white_rvb)
+ #debug(name,"spread:{}\t white_rvb:{}\t white_color:{}".format(spread, white_rvb, white_color))
+
+ # Blue and Red colors are high if spread is high, i.e. close to center
+ """
+ spread = 1.0 : red_c = 1.0
+ spread = 0.0 : red_c = 0.0
+ """
+ color_factor = math.pow(spread,1)
+ if point[2] == 0:
+ blue_color = 0
+ red_color = 0
+ else:
+ blue_rvb = tuple(map( lambda a: int(color_factor * a), blue))
+ blue_color = rgb2int( blue_rvb)
+ red_rvb = tuple(map( lambda a: int(color_factor * a), red))
+ red_color = rgb2int( red_rvb)
+
+ #debug(name,"color_factor:{}\t\t blue_color:{}\t\t red_color:{}".format(color_factor,blue_color,red_color))
+
+ # Blue-to-Red spatial spread is high when spread is high, i.e. point close to center
+ """
+ spread = 1.0 : spatial_spread = maxVal
+ spread = 0.0 : spatial_spread = minVal
+ """
+ spatial_spread = minVal + spread * (maxVal - minVal)
+ #debug(name,"spatial_spread:{}".format(spatial_spread))
+ red_x = int(point[0] + spatial_spread)
+ blue_x = int(point[0] - spatial_spread )
+ red_y = int(point[1] )
+ blue_y = int(point[1])
+
+ white_point = [point[0], point[1], white_color]
+ blue_point = [blue_x,blue_y,blue_color]
+ red_point = [red_x,red_y,red_color]
+
+ #debug(name,"white[x,y,c]:{}".format(white_point))
+ #debug(name,"blue[x,y,c]:{}".format(blue_point))
+ #debug(name,"red[x,y,c]:{}".format(red_point))
+ # Do not append "black lines" i.e. a color where each composent is below X
+# if isValidColor(white_rvb, 150):
+# out1.append(white_point)
+# if isValidColor(blue_rvb, 50):
+# out2.append(blue_point)
+# if isValidColor(red_rvb, 30):
+# out3.append(red_point)
+ out1.append(white_point)
+ out2.append(blue_point)
+ out3.append(red_point)
+
+ #debug(name,"source pl:{}".format(pl))
+ debug(name,"whiteList:{}".format(out1))
+ debug(name,"blueList:{}".format(out2))
+ debug(name,"redList:{}".format(out3))
+ return out3 + out2
+ return out1 + out3 + out2
+ #return out1 + out2 + out3
+
+
+
+try:
+ while True:
+ 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
+ result = anaglyph( pointsList )
+ print( result, 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/filters/kaleidoscope.py b/clitools/filters/kaleidoscope.py
index ed5547c..0495f23 100755
--- a/clitools/filters/kaleidoscope.py
+++ b/clitools/filters/kaleidoscope.py
@@ -53,7 +53,6 @@ def kaleidoscope( pl ):
quad1 = []
# Iterate trough the segments
for i in range( 0, len(pl) ):
-
#debug(name+" point #", i)
currentpoint = cp = pl[i]
@@ -74,8 +73,8 @@ def kaleidoscope( pl ):
#debug(name+" rect: ", rect,"curr",currentpoint,"next",nextpoint )
# Enumerate the points in rectangle to see
- # how many right / wrong there are to add or skip early
- #
+ # how many right / wrong there are
+ # either to add or skip early
for iterator, p in enumerate(rect):
if p[0] >= centerX and p[1] >= centerY:
right += 1
@@ -118,7 +117,7 @@ def kaleidoscope( pl ):
#print("on x axis, v=",str(v)," and absnewY=",str(absnewY))
crossY = [( absnewY*v[0] + cy ),( absnewY*v[1]+cy ), nc]
# Inject in order
- # If current is valid, Add
+ # If current point is the quadrant, add it
if cx >= centerX and cy >= centerY :
quad1.append( currentpoint )
# If absnewX smaller, it is closest to currentPoint
@@ -128,6 +127,9 @@ def kaleidoscope( pl ):
else :
if None != crossY : quad1.append( crossY )
if None != crossX : quad1.append( crossX )
+ # Add a black point at the end
+ #lastQuad1Point = quad1[-1]
+ #quad1.append( [lastQuad1Point[0],lastQuad1Point[1],0] )
## Stage 2 : Mirror points
#
@@ -144,10 +146,10 @@ def kaleidoscope( pl ):
point = quad3[iterator]
quad4.append([ 2*centerX - point[0], point[1], point[2] ])
- debug(name+" quad1:",quad1)
+ #debug(name+" quad1:",quad1)
#debug(name+" quad2:", quad2 )
- debug(name+" quad3:", quad3 )
- debug(name+" quad4:", quad4 )
+ #debug(name+" quad3:", quad3 )
+ #debug(name+" quad4:", quad4 )
return quad3+quad4
try:
diff --git a/clitools/filters/redilysis.py b/clitools/filters/redilysis.py
index d6d4d3b..00cd61a 100755
--- a/clitools/filters/redilysis.py
+++ b/clitools/filters/redilysis.py
@@ -34,16 +34,18 @@ def debug(*args, **kwargs):
if( verbose == False ):
return
print(*args, file=sys.stderr, **kwargs)
-def now():
- return time.time() * 1000
+def msNow():
+ return time.time()
-# The list of available modes and the redis keys they need
+# The list of available modes => redis keys each requires to run
oModeList = {
"rms_noise": ["rms"],
"rms_size": ["rms"],
- "bpm_size": ["bpm"]
+ "bpm_size": ["bpm"],
+ "bpm_detect_size": ["bpm","bpm_delay","bpm_sample_interval","beats"]
}
CHAOS = 1
+REDISLATENCY = 30
REDIS_FREQ = 300
# General Args
@@ -58,17 +60,19 @@ argsparser.add_argument("-x","--centerX",help="geometrical center X position",de
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("-l","--redisLatency",help="Latency in ms to substract. Default:{}".format(REDISLATENCY),default=REDISLATENCY,type=float)
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
+redisFreq = args.redis_freq / 1000
verbose = args.verbose
fps = args.fps
centerX = args.centerX
centerY = args.centerY
+redisLatency = args.redisLatency
chaos = float(args.chaos)
optimal_looptime = 1 / fps
@@ -82,33 +86,127 @@ for mode in modeList:
redisKeys = list(set(redisKeys))
debug(name,"Redis Keys:{}".format(redisKeys))
redisData = {}
-redisLastHit = now() - redisFreq
+redisLastHit = msNow() - 99999
r = redis.Redis(
host=ip,
port=port)
# Records the last bpm
-last_bpm = time.time()
+tsLastBeat = 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))))
+previousPTTL = 0
+tsNextBeatsList = []
+def bpmDetect( ):
+ """
+ An helper to compute the next beat time in milliseconds
+ Returns True if the cache was updated
+ """
+ global tsNextBeatsList
+ global previousPTTL
+ global redisLastHit
+ global redisLatency
+
+ # Get the redis PTTL value for bpm
+ PTTL = redisData["bpm_pttl"]
-def bpm_size( pl ):
- global last_bpm
+ # Skip early if PTTL < 0
+ if PTTL < 0 :
+ debug(name,"bpmDetect skip detection : PTTL expired for 'bpm' key")
+ return False
+
+ # Skip early if the record hasn't been rewritten
+ if PTTL <= previousPTTL :
+ previousPTTL = PTTL
+ #debug(name,"bpmDetect skip detection : {} <= {}".format(PTTL, previousPTTL))
+ return False
+ debug(name,"bpmDetect running detection : {} > {}".format(PTTL, previousPTTL))
+ previousPTTL = PTTL
+
+ # Skip early if beat list is empty
+ beatsList = ast.literal_eval(redisData["beats"])
+ tsNextBeatsList = []
+ if( len(beatsList) == 0 ):
+ return True
+
+ # Read from redis
bpm = float(redisData["bpm"])
- # Milliseconds ber beat
- milliSecondsPerBeat = int(60 / bpm * 1000)
+ msBpmDelay = float(redisData["bpm_delay"])
+ samplingInterval = float(redisData["bpm_sample_interval"])
+
+ # Calculate some interpolations
+ lastBeatTiming = float(beatsList[len(beatsList) - 1])
+ msPTTLDelta = 2 * samplingInterval - float(PTTL)
+ sPerBeat = 60 / bpm
+ lastBeatDelay = msBpmDelay - lastBeatTiming*1000 + msPTTLDelta
+ countBeatsPast = math.floor( (lastBeatDelay / 1000) / sPerBeat)
+ #debug(name,"bpmDetect lastBeatTiming:{}\tmsPTTLDelta:{}\tsPerBeat:{}".format(lastBeatTiming,msPTTLDelta,sPerBeat))
+ #debug(name,"lastBeatDelay:{}\t countBeatsPast:{}".format(lastBeatDelay, countBeatsPast))
+ for i in range( countBeatsPast, 1000):
+ beatTime = i * sPerBeat - lastBeatTiming
+ if beatTime < 0:
+ continue
+ if beatTime * 1000 > 2 * samplingInterval :
+ break
+ #debug(name, "bpmDetect beat add beatTime:{} redisLastHit:{}".format(beatTime, redisLastHit))
+ tsNextBeatsList.append( redisLastHit + beatTime - redisLatency/1000)
+ debug(name, "bpmDetect new tsNextBeatsList:{}".format(tsNextBeatsList))
+
+ return True
+
+def bpm_detect_size( pl ):
+ bpmDetect()
+
+ # Find the next beat in the list
+ tsNextBeat = 0
+
+ now = time.time()
+ msNearestBeat = None
+ msRelativeNextBTList = list(map( lambda a: abs(now - a) * 1000, tsNextBeatsList))
+ msToBeat = min( msRelativeNextBTList)
+
+ #debug(name,"bpm_detect_size msRelativeNextBTList:{} msToBeat:{}".format(msRelativeNextBTList,msToBeat))
# 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()
+ mu = 15
+ intensity = gauss( msToBeat, 0 , mu)
+ #debug(name,"bpm_size","mu:{}\t msToBeat:{}\tintensity:{}".format(mu, msToBeat, intensity))
+ if msToBeat < 20:
+ debug(name,"bpm_detect_size kick:{}".format(msToBeat))
+ pass
+ 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_detect_size output:{}".format(pl))
+ return( pl );
+
+def bpm_size( pl ):
+ global tsLastBeat
+ bpm = float(redisData["bpm"])
+ # msseconds ber beat
+ msPerBeat = int(60 / bpm * 1000)
+ # Calculate the intensity based on bpm coming/leaving
+ # The curb is a gaussian
+ mu = math.sqrt(msPerBeat)
+ msTimeToLastBeat = (time.time() - tsLastBeat) * 1000
+ msTimeToNextBeat = (msPerBeat - msTimeToLastBeat)
+ intensity = gauss( msTimeToNextBeat, 0 , mu)
+ debug(name,"bpm_size","msPerBeat:{}\tmu:{}".format(msPerBeat, mu))
+ debug(name,"bpm_size","msTimeToLastBeat:{}\tmsTimeToNextBeat:{}\tintensity:{}".format(msTimeToLastBeat, msTimeToNextBeat, intensity))
+ if msTimeToNextBeat <= 0 :
+ tsLastBeat = time.time()
for i, point in enumerate(pl):
ref_x = point[0]-centerX
ref_y = point[1]-centerY
@@ -158,21 +256,30 @@ def rms_noise( pl ):
return pl
-def updateRedis():
+def refreshRedis():
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))
+ # Skip if cache is sufficent
+ diff = msNow() - redisLastHit
+ if diff < redisFreq :
+ #debug(name, "refreshRedis not updating redis, {} < {}".format(diff, redisFreq))
+ pass
+ else:
+ #debug(name, "refreshRedis updating redis, {} > {}".format(diff, redisFreq))
+ redisLastHit = msNow()
+ for key in redisKeys:
+ redisData[key] = r.get(key).decode('ascii')
+ #debug(name,"refreshRedis key:{} value:{}".format(key,redisData[key]))
+ # Only update the TTLs
+ if 'bpm' in redisKeys:
+ redisData['bpm_pttl'] = r.pttl('bpm')
+ #debug(name,"refreshRedis key:bpm_ttl value:{}".format(redisData["bpm_pttl"]))
+ #debug(name,"redisData:{}".format(redisData))
+ return True
try:
while True:
- # it is time to query redis
- if now() - redisLastHit > redisFreq:
- updateRedis()
+ refreshRedis()
start = time.time()
line = sys.stdin.readline()
if line == "":
diff --git a/clitools/generators/tunnel.py b/clitools/generators/tunnel.py
index 00b220d..f324475 100644
--- a/clitools/generators/tunnel.py
+++ b/clitools/generators/tunnel.py
@@ -34,7 +34,7 @@ argsparser = argparse.ArgumentParser(description="tunnel generator")
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("-m","--max-size",help="maximum size for objects",default=400,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")
@@ -77,14 +77,19 @@ class polylineGenerator( object ):
self.polylineList = [[0,[currentCenter[0],currentCenter[1]]]]
self.buf = []
+ def init(self):
+ finished = False
+ while not finished:
+ finished = self.increment()
+ debug(name,"init done:{}".format(self.polylineList))
def draw( self ):
self.buf = []
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
+ x = int( center[0] + point[0]*size )
+ y = int( center[1] + point[1]*size )
# Add an invisible point in first location
if 0 == it_sqr:
self.buf.append([x,y,0])
@@ -114,22 +119,43 @@ class polylineGenerator( object ):
speed = origSpeed
elif speed > (origSpeed + randomize / 2) :
speed = origSpeed + randomize / 2
- debug(name, "currentCenter:{} speed:{}".format(currentCenter,speed))
+ #debug(name, "currentCenter:{} speed:{}".format(currentCenter,speed))
for i, shapeInfo in enumerate(self.polylineList):
size = shapeInfo[0]
- size += speed
+ # Augment speed with size
+ """
+ size = 0 : += sqrt(speed)
+ size = half max size : +=speed
+
+ """
+ if size < max_size / 4:
+ size += math.pow(speed, 0.1)
+ elif size < max_size / 3:
+ size += math.pow(speed, 0.25)
+ elif size < max_size / 2:
+ size += math.pow(speed, 0.5)
+ else:
+ size += math.pow(speed, 1.25)
if size < min_size : min_size = size
if size > max_size : delList.append(i)
self.polylineList[i][0] = size
for i in delList:
del self.polylineList[i]
- if min_size >= interval: self.polylineList.append([0,[currentCenter[0],currentCenter[1]]])
#debug(name, "polyline:",self.polylineList)
+ if min_size >= interval:
+ debug(name, "new shape")
+ self.polylineList.append([0,[currentCenter[0],currentCenter[1]]])
+
+ # Return True if we delete a shape
+
+ if len(delList):
+ return True
+ return False
pgen = polylineGenerator()
-
+pgen.init()
while True:
start = time.time()
@@ -140,7 +166,7 @@ while True:
# send
pl = pgen.draw()
print(pl, flush=True)
- debug(name,"output:{}".format(pl))
+ #debug(name,"output:{}".format(pl))
looptime = time.time() - start
if( looptime < optimal_looptime ):
diff --git a/www/simu.html b/www/simu.html
index a125686..fd2d4f6 100644
--- a/www/simu.html
+++ b/www/simu.html
@@ -10,8 +10,8 @@
-
-
+
+