diff --git a/bin/data/effects/imageEffect/imageShader.frag b/bin/data/effects/imageEffect/imageShader.frag
new file mode 100644
index 0000000..5b5a690
--- /dev/null
+++ b/bin/data/effects/imageEffect/imageShader.frag
@@ -0,0 +1,22 @@
+#version 120
+
+#ifdef GL_ES
+precision highp float;
+#endif
+
+// this is how we receive the texture
+uniform sampler2DRect tex0;
+uniform vec2 imageResolution;
+uniform vec2 canvasResolution;
+
+varying vec2 varyingtexcoord;
+//varying vec4 outputColor;
+
+void main()
+{
+ //vec2 innerPos =
+ //gl_FragCoord = coordinates of current pixel
+ //gl_FragColor = vec4(varyingtexcoord.x,0,0,1);
+ //gl_FragColor = texture2DRect(tex0, gl_FragCoord.xy);//gl_TexCoord[0].st);//varyingtexcoord);
+ gl_FragColor = texture2DRect(tex0, gl_FragCoord.xy);
+}
\ No newline at end of file
diff --git a/bin/data/effects/imageEffect/imageShader.vert b/bin/data/effects/imageEffect/imageShader.vert
new file mode 100644
index 0000000..c7829e5
--- /dev/null
+++ b/bin/data/effects/imageEffect/imageShader.vert
@@ -0,0 +1,35 @@
+#version 120
+
+// these are for the programmable pipeline system and are passed in
+// by default from OpenFrameworks
+uniform mat4 modelViewMatrix;
+uniform mat4 projectionMatrix;
+uniform mat4 textureMatrix;
+uniform mat4 modelViewProjectionMatrix;
+
+attribute vec4 position;
+attribute vec4 color;
+attribute vec4 normal;
+attribute vec2 texcoord;
+// this is the end of the default functionality
+
+// this is something we're creating for this shader
+varying vec2 varyingtexcoord;
+
+// this is coming from our C++ code
+uniform float mouseX;
+
+void main()
+{
+ // vec4 pos = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;
+
+ // here we move the texture coordinates
+ varyingtexcoord = texcoord;//vec2(gl_MultiTexCoord0.x, gl_MultiTexCoord0.y);
+
+ // send the vertices to the fragment shader
+ //gl_Position = modelViewProjectionMatrix * position;
+ //gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;
+
+ gl_TexCoord[0] = gl_MultiTexCoord0;
+ gl_Position = ftransform();
+}
\ No newline at end of file
diff --git a/bin/data/effects/imageEffect/imageShaderGL3.frag b/bin/data/effects/imageEffect/imageShaderGL3.frag
new file mode 100644
index 0000000..5c24988
--- /dev/null
+++ b/bin/data/effects/imageEffect/imageShaderGL3.frag
@@ -0,0 +1,41 @@
+#version 150
+
+#ifdef GL_ES
+precision highp float;
+#endif
+
+// incoming variables
+// no need to declare these, use this as a list
+layout(origin_upper_left) in vec4 gl_FragCoord;// <-- pixel position (layout fixes inverted y)
+// in bool gl_FrontFacing;
+// in vec2 gl_PointCoord;// <-- position of the vertex that created this pixel
+// in float gl_FragDepth;// <-- gl_FragCoord.z, if DEPTH enabled
+
+// these are our textures from OF
+uniform sampler2DRect tex0;
+uniform vec2 tex0Resolution; // w,h
+uniform vec2 fboCanvas; // w,h
+uniform vec4 shapeBoundingBox; // x,y,w,h
+uniform int fitMode; // 0=fit to screen, 1=fit-to-shape, 2=crop-to-shape
+uniform float opacity;
+
+// this comes from the vertex shader
+in vec2 texCoordVarying;
+in vec4 texColor;
+
+// this is the output of the fragment shader
+out vec4 outputColor;
+
+void main(){
+
+ // get rgb from tex0
+ vec2 pos;
+ if(fitMode==1) pos = ((gl_FragCoord.xy-shapeBoundingBox.xy) / floor(shapeBoundingBox.zw) ) * tex0Resolution; // fit tex to shape
+ else pos = ( (gl_FragCoord.xy-shapeBoundingBox.xy) / shapeBoundingBox.zw) * tex0Resolution; // fit tex to screen
+
+ outputColor = vec4(texture(tex0, pos).rgb, texColor.a*opacity);
+
+ //outputColor = vec4(offset.x, offset.y,0,1);
+
+
+}
diff --git a/bin/data/effects/imageEffect/imageShaderGL3.vert b/bin/data/effects/imageEffect/imageShaderGL3.vert
new file mode 100644
index 0000000..8aee9b4
--- /dev/null
+++ b/bin/data/effects/imageEffect/imageShaderGL3.vert
@@ -0,0 +1,46 @@
+#version 150
+
+// reference (GLSL, but still useful)
+// https://www.opengl.org/wiki/Built-in_Variable_%28GLSL%29
+
+// these are for the programmable pipeline system and are passed in
+// by default from OpenFrameworks
+uniform mat4 orientationMatrix;
+uniform mat4 modelViewMatrix;
+uniform mat4 projectionMatrix;
+uniform mat4 textureMatrix;
+uniform mat4 modelViewProjectionMatrix;
+
+// build-in incoming variables
+//in int gl_VertexID;// <-- vertex index
+//in int gl_InstanceID;// <-- not always set
+
+// build-in variables you can alter
+//vec4 gl_Position;// <-- vertex position
+//float gl_PointSize;// <-- size/width (px) of current vertex
+//float gl_ClipDistance[];// <-- clipping stuf
+
+// from of-bound textures
+in vec4 position;
+in vec2 texcoord;
+in vec4 color;
+in vec4 normal;
+
+// texture coordinates are sent to fragment shader
+out vec2 texCoordVarying;
+out vec4 texColor;
+
+void main()
+{
+ // build-in input variables
+ // gl_VertexID
+ // gl_InstanceID
+
+ // Output variables
+ // gl_PointSize
+ // gl_Position
+
+ texColor = color;
+ texCoordVarying = texcoord;
+ gl_Position = modelViewProjectionMatrix * position;
+}
\ No newline at end of file
diff --git a/bin/data/effects/lineEffect/fadeOutAlpha.frag b/bin/data/effects/lineEffect/fadeOutAlpha.frag
new file mode 100644
index 0000000..2a7e661
--- /dev/null
+++ b/bin/data/effects/lineEffect/fadeOutAlpha.frag
@@ -0,0 +1,28 @@
+#version 150
+
+#ifdef GL_ES
+precision highp float;
+#endif
+
+// incoming variables
+// no need to declare these, use this as a list
+layout(pixel_center_integer) in vec4 gl_FragCoord;// <-- pixel position
+// in bool gl_FrontFacing;
+// in vec2 gl_PointCoord;// <-- position of the vertex that created this pixel
+// in float gl_FragDepth;// <-- gl_FragCoord.z, if DEPTH enabled
+
+// these are our textures from OF
+uniform float alphaMultiplier;
+
+// this is the output of the vertex shader
+in vec4 myColor;
+
+out vec4 outputColor;
+
+void main(){
+ //outputColor.a *= 0.1f;
+ //outputColor = vec4(1,0,0,0.99f);
+ //outputColor = vec4(myColor.r, myColor.g, myColor.b, 0);
+ outputColor = vec4(0,1,0,1);
+ //outputColor = ve4(1,0,0,1);
+}
diff --git a/bin/data/effects/lineEffect/fadeOutAlpha.vert b/bin/data/effects/lineEffect/fadeOutAlpha.vert
new file mode 100644
index 0000000..344bd6e
--- /dev/null
+++ b/bin/data/effects/lineEffect/fadeOutAlpha.vert
@@ -0,0 +1,13 @@
+#version 150
+
+uniform mat4 modelViewProjectionMatrix;
+
+in vec4 position;
+in vec4 color;
+
+out vec4 myColor;
+
+void main(void) {
+ myColor = color;
+ gl_Position = modelViewProjectionMatrix * position;
+}
\ No newline at end of file
diff --git a/bin/data/effects/videoEffect/videoShader.frag b/bin/data/effects/videoEffect/videoShader.frag
new file mode 100644
index 0000000..e511b7c
--- /dev/null
+++ b/bin/data/effects/videoEffect/videoShader.frag
@@ -0,0 +1,23 @@
+#version 330
+
+#ifdef GL_ES
+precision highp float;
+#endif
+
+uniform sampler2DRect tex0; // video layer
+uniform vec2 resolution;
+uniform vec2 textureResolution;
+uniform vec2 shapeCenterOffset;
+uniform float textureScale;
+
+in vec2 vertexTexCoord;
+in vec4 gl_FragCoord;
+
+out vec4 outputColor;
+
+void main()
+{
+ //outputColor = vec4( texture(tex0, gl_FragCoord.xy/resolution.xy ).rgb, 1);
+ outputColor = vec4( texture(tex0, mod( (vertexTexCoord-shapeCenterOffset)/resolution*textureResolution*textureScale, textureResolution) ).rgb, 1);//outputColor.a);
+ //outputColor.r += 0.15f; // debugging
+}
diff --git a/bin/data/effects/videoEffect/videoShader.vert b/bin/data/effects/videoEffect/videoShader.vert
new file mode 100644
index 0000000..2c46374
--- /dev/null
+++ b/bin/data/effects/videoEffect/videoShader.vert
@@ -0,0 +1,14 @@
+#version 330
+
+uniform mat4 modelViewProjectionMatrix; // This is provide by openFrameworks
+in vec2 texcoord; // This is provide by openFrameworks
+in vec4 position;
+out vec2 vertexTexCoord;
+
+void main()
+{
+ // Absolute window position: gl_FragCoord.x / windowWidth
+ //gl_Position.xy;//
+ vertexTexCoord = position.xy;
+ gl_Position = modelViewProjectionMatrix * position;
+}
diff --git a/bin/data/saveFiles/Vendome_1500_1200.xml b/bin/data/saveFiles/Vendome_1500_1200.xml
new file mode 100644
index 0000000..92ef5c7
--- /dev/null
+++ b/bin/data/saveFiles/Vendome_1500_1200.xml
@@ -0,0 +1,1056 @@
+
+
+ 750.000000000
+ 600.000000000
+
+ vertexShape
+ 5
+
+
+ -750.000000000
+ -600.000000000
+
+
+ 750.000000000
+ -600.000000000
+
+
+ 750.000000000
+ 600.000000000
+
+
+ -750.000000000
+ 600.000000000
+
+
+
+
+
+ 233.000000000
+ 183.000000000
+
+ vertexShape
+ 3
+
+
+ 54.000000000
+ -72.000000000
+
+
+ 51.000000000
+ 159.000000000
+
+
+ -72.000000000
+ 162.000000000
+
+
+ -71.000000000
+ -74.000000000
+
+
+
+
+
+ 454.000000000
+ 175.000000000
+
+ vertexShape
+ 3
+
+
+ 59.000000000
+ -74.000000000
+
+
+ 59.000000000
+ 157.000000000
+
+
+ -63.000000000
+ 160.000000000
+
+
+ -63.000000000
+ -71.000000000
+
+
+
+
+
+ 744.000000000
+ 167.000000000
+
+ vertexShape
+ 3
+
+
+ 60.000000000
+ -74.000000000
+
+
+ 63.000000000
+ 162.000000000
+
+
+ -63.000000000
+ 165.000000000
+
+
+ -65.000000000
+ -72.000000000
+
+
+
+
+
+ 1037.000000000
+ 169.000000000
+
+ vertexShape
+ 3
+
+
+ 60.000000000
+ -74.000000000
+
+
+ 60.000000000
+ 166.000000000
+
+
+ -60.000000000
+ 166.000000000
+
+
+ -63.000000000
+ -72.000000000
+
+
+
+
+
+ 1037.000000000
+ 565.000000000
+
+ vertexShape
+ 3
+
+
+ 68.000000000
+ -135.000000000
+
+
+ 68.000000000
+ 191.000000000
+
+
+ -59.000000000
+ 194.000000000
+
+
+ -60.000000000
+ -133.000000000
+
+
+
+
+
+ 118.000000000
+ 184.000000000
+
+ vertexShape
+ 0
+
+
+ -15.000000000
+ 81.000000000
+
+
+ -15.000000000
+ -83.000000000
+
+
+ -27.000000000
+ -113.000000000
+
+
+ 22.000000000
+ -115.000000000
+
+
+ 16.000000000
+ -81.000000000
+
+
+ 13.000000000
+ 83.000000000
+
+
+ 21.000000000
+ 100.000000000
+
+
+ 21.000000000
+ 151.000000000
+
+
+ -28.000000000
+ 153.000000000
+
+
+ -28.000000000
+ 94.000000000
+
+
+
+
+
+ 336.000000000
+ 189.000000000
+
+ vertexShape
+ 0
+
+
+ 24.000000000
+ -119.000000000
+
+
+ 18.000000000
+ -91.000000000
+
+
+ 18.000000000
+ 80.000000000
+
+
+ 25.000000000
+ 94.000000000
+
+
+ 25.000000000
+ 145.000000000
+
+
+ -25.000000000
+ 144.000000000
+
+
+ -25.000000000
+ 97.000000000
+
+
+ -18.000000000
+ 83.000000000
+
+
+ -16.000000000
+ -91.000000000
+
+
+ -28.000000000
+ -116.000000000
+
+
+
+
+
+ 564.000000000
+ 192.000000000
+
+ vertexShape
+ 0
+
+
+ -15.000000000
+ 80.000000000
+
+
+ -16.000000000
+ -95.000000000
+
+
+ -27.000000000
+ -122.000000000
+
+
+ 25.000000000
+ -124.000000000
+
+
+ 16.000000000
+ -97.000000000
+
+
+ 13.000000000
+ 81.000000000
+
+
+ 21.000000000
+ 97.000000000
+
+
+ 21.000000000
+ 141.000000000
+
+
+ -24.000000000
+ 141.000000000
+
+
+ -24.000000000
+ 89.000000000
+
+
+
+
+
+ 116.000000000
+ 571.000000000
+
+ vertexShape
+ 0
+
+
+ 22.000000000
+ -147.000000000
+
+
+ -22.000000000
+ -145.000000000
+
+
+ -22.000000000
+ 189.000000000
+
+
+ 22.000000000
+ 192.000000000
+
+
+
+
+
+ 923.000000000
+ 184.000000000
+
+ vertexShape
+ 0
+
+
+ 25.000000000
+ -122.000000000
+
+
+ 16.000000000
+ -95.000000000
+
+
+ 15.000000000
+ 86.000000000
+
+
+ 22.000000000
+ 98.000000000
+
+
+ 24.000000000
+ 144.000000000
+
+
+ -22.000000000
+ 145.000000000
+
+
+ -21.000000000
+ 97.000000000
+
+
+ -13.000000000
+ 84.000000000
+
+
+ -16.000000000
+ -94.000000000
+
+
+ -22.000000000
+ -124.000000000
+
+
+
+
+
+ 928.000000000
+ 554.000000000
+
+ vertexShape
+ 0
+
+
+ 18.000000000
+ -145.000000000
+
+
+ 22.000000000
+ 127.000000000
+
+
+ -19.000000000
+ 122.000000000
+
+
+ -19.000000000
+ -145.000000000
+
+
+
+
+
+ 623.000000000
+ 126.000000000
+
+ vertexShape
+ 2
+
+
+ 19.000000000
+ -33.000000000
+
+
+ 19.000000000
+ 50.000000000
+
+
+ -25.000000000
+ 50.000000000
+
+
+ -25.000000000
+ -33.000000000
+
+
+
+
+
+ 862.000000000
+ 135.000000000
+
+ vertexShape
+ 2
+
+
+ 24.000000000
+ -37.000000000
+
+
+ 24.000000000
+ 36.000000000
+
+
+ -27.000000000
+ 36.000000000
+
+
+ -27.000000000
+ -39.000000000
+
+
+
+
+
+ 621.000000000
+ 554.000000000
+
+ vertexShape
+ 1
+
+
+ 27.000000000
+ -71.000000000
+
+
+ 27.000000000
+ 71.000000000
+
+
+ -28.000000000
+ 71.000000000
+
+
+ -28.000000000
+ -71.000000000
+
+
+
+
+
+ 867.000000000
+ 560.000000000
+
+ vertexShape
+ 1
+
+
+ 24.000000000
+ -83.000000000
+
+
+ 27.000000000
+ 62.000000000
+
+
+ -28.000000000
+ 62.000000000
+
+
+ -28.000000000
+ -83.000000000
+
+
+
+
+
+ 333.000000000
+ 568.000000000
+
+ vertexShape
+ 0
+
+
+ -19.000000000
+ 191.000000000
+
+
+ 25.000000000
+ 192.000000000
+
+
+ 27.000000000
+ -150.000000000
+
+
+ -24.000000000
+ -150.000000000
+
+
+
+
+
+ 561.000000000
+ 565.000000000
+
+ vertexShape
+ 0
+
+
+ -21.000000000
+ 119.000000000
+
+
+ 19.000000000
+ 121.000000000
+
+
+ 19.000000000
+ -151.000000000
+
+
+ -21.000000000
+ -151.000000000
+
+
+
+
+
+ 233.000000000
+ 571.000000000
+
+ vertexShape
+ 3
+
+
+ -65.000000000
+ 191.000000000
+
+
+ 56.000000000
+ 192.000000000
+
+
+ 57.000000000
+ -128.000000000
+
+
+ -65.000000000
+ -128.000000000
+
+
+
+
+
+ 453.000000000
+ 572.000000000
+
+ vertexShape
+ 3
+
+
+ -60.000000000
+ 185.000000000
+
+
+ 60.000000000
+ 183.000000000
+
+
+ 59.000000000
+ -133.000000000
+
+
+ -60.000000000
+ -133.000000000
+
+
+
+
+
+ 746.000000000
+ 565.000000000
+
+ vertexShape
+ 3
+
+
+ -59.000000000
+ 191.000000000
+
+
+ 62.000000000
+ 192.000000000
+
+
+ 62.000000000
+ -127.000000000
+
+
+ -59.000000000
+ -127.000000000
+
+
+
+
+
+ 1263.000000000
+ 166.000000000
+
+ vertexShape
+ 3
+
+
+ -59.000000000
+ 160.000000000
+
+
+ 65.000000000
+ 163.000000000
+
+
+ 63.000000000
+ -74.000000000
+
+
+ -59.000000000
+ -74.000000000
+
+
+
+
+
+ 1272.000000000
+ 568.000000000
+
+ vertexShape
+ 3
+
+
+ -60.000000000
+ 186.000000000
+
+
+ 60.000000000
+ 191.000000000
+
+
+ 62.000000000
+ -135.000000000
+
+
+ -60.000000000
+ -135.000000000
+
+
+
+
+
+ 1151.000000000
+ 183.000000000
+
+ vertexShape
+ 0
+
+
+ -16.000000000
+ -97.000000000
+
+
+ -18.000000000
+ 87.000000000
+
+
+ -21.000000000
+ 100.000000000
+
+
+ -21.000000000
+ 144.000000000
+
+
+ 25.000000000
+ 147.000000000
+
+
+ 25.000000000
+ 100.000000000
+
+
+ 19.000000000
+ 84.000000000
+
+
+ 18.000000000
+ -97.000000000
+
+
+ 25.000000000
+ -122.000000000
+
+
+ -21.000000000
+ -124.000000000
+
+
+
+
+
+ 1157.000000000
+ 565.000000000
+
+ vertexShape
+ 0
+
+
+ -21.000000000
+ 191.000000000
+
+
+ 22.000000000
+ 188.000000000
+
+
+ 22.000000000
+ -153.000000000
+
+
+ -21.000000000
+ -153.000000000
+
+
+
+
+
+ 1387.000000000
+ 565.000000000
+
+ vertexShape
+ 0
+
+
+ -24.000000000
+ 189.000000000
+
+
+ 25.000000000
+ 188.000000000
+
+
+ 24.000000000
+ -151.000000000
+
+
+ -24.000000000
+ -151.000000000
+
+
+
+
+
+ 228.000000000
+ 926.000000000
+
+ vertexShape
+ 3
+
+
+ -66.000000000
+ 177.000000000
+
+
+ 60.000000000
+ 180.000000000
+
+
+ 62.000000000
+ -68.000000000
+
+
+ -65.000000000
+ -68.000000000
+
+
+
+
+
+ 450.000000000
+ 924.000000000
+
+ vertexShape
+ 3
+
+
+ -60.000000000
+ 180.000000000
+
+
+ 60.000000000
+ 180.000000000
+
+
+ 62.000000000
+ -66.000000000
+
+
+ -60.000000000
+ -66.000000000
+
+
+
+
+
+ 1041.000000000
+ 924.000000000
+
+ vertexShape
+ 3
+
+
+ -59.000000000
+ 186.000000000
+
+
+ 69.000000000
+ 186.000000000
+
+
+ 71.000000000
+ -68.000000000
+
+
+ -59.000000000
+ -68.000000000
+
+
+
+
+
+ 1269.000000000
+ 923.000000000
+
+ vertexShape
+ 3
+
+
+ -57.000000000
+ 186.000000000
+
+
+ 71.000000000
+ 186.000000000
+
+
+ 69.000000000
+ -68.000000000
+
+
+ -57.000000000
+ -69.000000000
+
+
+
+
+
+ 749.000000000
+ 1109.000000000
+
+ vertexShape
+ 4
+
+
+ -68.000000000
+ 71.000000000
+
+
+ 68.000000000
+ 71.000000000
+
+
+ 68.000000000
+ -182.000000000
+
+
+ -68.000000000
+ -183.000000000
+
+
+
+
+
+ 106.000000000
+ 958.000000000
+
+ vertexShape
+ 0
+
+
+ -16.000000000
+ 227.000000000
+
+
+ 28.000000000
+ 230.000000000
+
+
+ 25.000000000
+ -122.000000000
+
+
+ -16.000000000
+ -124.000000000
+
+
+
+
+
+ 335.000000000
+ 991.000000000
+
+ vertexShape
+ 0
+
+
+ -18.000000000
+ 197.000000000
+
+
+ 16.000000000
+ 197.000000000
+
+
+ 16.000000000
+ -151.000000000
+
+
+ -18.000000000
+ -151.000000000
+
+
+
+
+
+ 1372.000000000
+ 176.000000000
+
+ vertexShape
+ 0
+
+
+ -16.000000000
+ 154.000000000
+
+
+ 19.000000000
+ 154.000000000
+
+
+ 19.000000000
+ -116.000000000
+
+
+ -16.000000000
+ -116.000000000
+
+
+
+
+
+ 1158.000000000
+ 985.000000000
+
+ vertexShape
+ 0
+
+
+ -22.000000000
+ 203.000000000
+
+
+ 13.000000000
+ 203.000000000
+
+
+ 13.000000000
+ -148.000000000
+
+
+ -22.000000000
+ -148.000000000
+
+
+
+
+
+ 1390.000000000
+ 959.000000000
+
+ vertexShape
+ 0
+
+
+ -15.000000000
+ 226.000000000
+
+
+ 21.000000000
+ 227.000000000
+
+
+ 21.000000000
+ -122.000000000
+
+
+ -19.000000000
+ -124.000000000
+
+
+
diff --git a/bin/data/vendome_daan_v1.0/spores.png b/bin/data/vendome_daan_v1.0/spores.png
new file mode 100644
index 0000000..4d33fe0
Binary files /dev/null and b/bin/data/vendome_daan_v1.0/spores.png differ
diff --git a/bin/data/vendome_full.jpg b/bin/data/vendome_full.jpg
index f8a0362..6f2f74e 100755
Binary files a/bin/data/vendome_full.jpg and b/bin/data/vendome_full.jpg differ
diff --git a/src/core/OSCNode.h b/src/core/OSCNode.h
index 0726b79..4503cf5 100644
--- a/src/core/OSCNode.h
+++ b/src/core/OSCNode.h
@@ -29,7 +29,7 @@ class OSCNode {
virtual bool canHandle( const ofxOscMessage &_msg ) const = 0;
virtual bool handle( const ofxOscMessage &_msg ) = 0;
- virtual void youHaveToDie() = 0;
+ virtual void detachNode() = 0;
protected:
//ofMutex ooscMutex;
diff --git a/src/core/OSCRouter.cpp b/src/core/OSCRouter.cpp
index 9375478..0b71e4c 100644
--- a/src/core/OSCRouter.cpp
+++ b/src/core/OSCRouter.cpp
@@ -52,7 +52,7 @@ OSCRouter::~OSCRouter(){
// inform nodes to detach listeners
for( list::iterator it=nodes.begin(); it!=nodes.end(); it++){
- (*it)->youHaveToDie();
+ (*it)->detachNode();
nodes.erase(it);
}
}
@@ -63,6 +63,8 @@ void OSCRouter::ProcessMessage(const osc::ReceivedMessage &m, const IpEndpointNa
// first part is the same as parent class
// convert the message to an ofxOscMessage
+ // todo: we need a mutex here....
+
// set the address
ofxOscMessage ofMsg;
ofMsg.setAddress( m.AddressPattern() );
@@ -98,7 +100,7 @@ void OSCRouter::ProcessMessage(const osc::ReceivedMessage &m, const IpEndpointNa
for(list::iterator it=nodes.begin(); it!=nodes.end(); it++){
if((*it)->canHandle(ofMsg)){
handled = (*it)->handle(ofMsg);
- if(handled==true) return;
+ //if(handled==true) return;
}
}
@@ -148,6 +150,7 @@ bool OSCRouter::start(int _port){
bool OSCRouter::stop(){
bEnabled = false;
+ ofRemoveListener( ofEvents().update , this, &OSCRouter::update );
ofRemoveListener(gui->newGUIEvent, this, &OSCRouter::guiEvent);
gui->disable();
@@ -156,6 +159,7 @@ bool OSCRouter::stop(){
}
bool OSCRouter::reset(){
+ // how dirty is this ? :p
this->~OSCRouter();
OSCRouter();
}
@@ -171,6 +175,7 @@ bool OSCRouter::removeNode(OSCNode* _node){
for(list::iterator it=nodes.begin(); it!=nodes.end(); it++){
if( _node == *it ){
+ (*it)->detachNode();
nodes.erase( it );
return true;
}
diff --git a/src/core/OSCRouter.h b/src/core/OSCRouter.h
index 89c3068..251c852 100644
--- a/src/core/OSCRouter.h
+++ b/src/core/OSCRouter.h
@@ -48,7 +48,6 @@ class OSCRouter : public ofxOscReceiver {
list nodes;
-
private:
bool bEnabled;
diff --git a/src/core/animationController.cpp b/src/core/animationController.cpp
index d5b84b8..ca05ca2 100644
--- a/src/core/animationController.cpp
+++ b/src/core/animationController.cpp
@@ -7,7 +7,8 @@
//
#include "animationController.h"
-
+#include "ofxVLCRemote.h"
+#include "durationRC.h"
// - - - - - - - -
// CONSTRUCTORS
@@ -74,10 +75,49 @@ bool animationController::start(){
bEnabled = true;
gui->enable();
+ // all black! xD
+ ofSetBackgroundAuto(false);
+ ofClear(0,0,0,255);
+
+ // play music
+ //sound.loadSound("TEST MIX V0.1.wav");
+ //music.load("music.wav");
+ //music.setLoop(true);
+ //music.play();
+
+ // Setup video recording
+ recorder.startRecording("", 1500, 1200);
+
+ {
+ // play music with VLC
+ ofxVLCRemote vlc;
+ vlc.setup("/Users/daan/vlc.sock"); // client-specific... :(
+ vlc.run("repeat on");
+ vlc.run("normal"); // playback speed
+ vlc.run("volume 256"); // 0-1024 (256=normal)
+
+ //vlc.run("adev 7"); // tell VLC to use device 7 (soundflower 2ch)
+ vlc.run("play");
+ vlc.run("prev");
+ //vlc.run("got0 0");
+
+ }
+
+ { // SYNC DURATION
+ durationRC rc;
+ rc.setupOSC();
+ rc.rewindAndPlay();
+ }
+
+
// enable mirOSCReceiver
mirOSCReceiver.start();
oscRouter.addNode( &mirOSCReceiver );
+ // enable durationOSCReceiver
+ durationOSCReceiver.start();
+ oscRouter.addNode( &durationOSCReceiver );
+
// get shape instance
//string type="basicEffect";
//e = stringToShapeClass( type );
@@ -88,33 +128,61 @@ bool animationController::start(){
return;
}*/
- /*{
- basicEffect* e;
- e = new imageBeatEffect();
- e->bindWithShape( server.getRandomShape() );
- effects.push_back(e);
- }*/
+ if(false){ // VIDEO EFFECT
+ basicEffect* e;
+ e = new videoEffect();
+ e->initialise();
+ e->bindWithShape( scene.getRandomShapeByGroup(5) ); // 3 = bg
+ effects.push_back(e);
+ }
- {
- basicShape* sh = scene.getRandomShape();
- basicEffect* e;
- e = new lineEffect();
- e->initialise();
- e->bindWithShape( scene.getRandomShape() );
- e->bindWithShape( scene.getRandomShape() );
- e->bindWithShape( scene.getRandomShape() );
- e->bindWithShape( scene.getRandomShape() );
- e->enable();
- effects.push_back(e);
- } // */
+ //
+ if(true){ // IMAGE EFFECT
+ basicEffect* e;
+ e = new imageEffect();
+ e->initialise();
+ ((imageEffect*) e)->loadImageFromFile("vendome_full_ok.jpg");
+ ((imageEffect*) e)->listenToOscIntensity("bgVendomeOpacity");
+ e->bindWithShape( scene.getRandomShapeByGroup(5) ); // 3 = blue windows
+
+ effects.push_back(e);
+ }
+
+ // no mutexes --> unstable
+ if(true){ // IMAGE BEAT EFFECT
+ basicEffect* e;
+ e = new imageBeatEffect();
+ e->initialise();
+ e->bindWithShapes( scene.getShapesByGroup(3) ); // windows
+ e->enable();
+ effects.push_back(e);
+ }
+
+ if(false){ // BASIC EFFECT
+ basicEffect* e;
+ e = new basicEffect();
+ e->initialise();
+ e->bindWithShapes( scene.getAllShapes() );
+ e->enable();
+ effects.push_back(e);
+ }
+
+ if(false){ // LINE EFFECT
+ basicEffect* e;
+ e = new lineEffect();
+ e->initialise();
+ e->bindWithShapes( scene.getShapesByGroup(3) ); // windows
+ e->bindWithShapes( scene.getShapesByGroup(0) ); // columns
+ e->enable();
+ effects.push_back(e);
+ }
/*{
basicEffect* e;
e = new imageMeltingEffect();
- e->initialise();
+ e->initialise();
e->bindWithShapes( scene.getShapesByGroup(3) );
e->bindWithShapes( scene.getShapesByGroup(1) );
- e->enable(); // should in fact be called once basicShape::isReady();
effects.push_back(e);
}// */
@@ -123,13 +191,24 @@ bool animationController::start(){
e = new imageGrainEffect();
e->initialise();
e->bindWithShapes( scene.getShapesByGroup(1) );
- e->enable(); // should in fact be called once basicShape::isReady();
effects.push_back(e);
} // */
- /*e = new MeshRenderer3D();
- e->bindWithShape( server.getRandomShape() );
- effects.push_back(e);*/
+ /*{ // MESH 3D
+ basicEffect* e;
+ e = new meshRenderer();
+ e->initialise();
+ e->bindWithShapes( scene.getShapesByGroup(1) );
+ effects.push_back(e);
+ } // */
+
+ /*{ // GIF effect
+ basicEffect* e;
+ e = new gifEffect();
+ e->initialise();
+ e->bindWithShapes( scene.getShapesByGroup(1) );
+ effects.push_back(e);
+ }// */
return isEnabled()==true;
}
@@ -140,14 +219,37 @@ bool animationController::stop(){
mirOSCReceiver.stop();
oscRouter.removeNode( &mirOSCReceiver );
+ // disable durationOSCReceiver
+ durationOSCReceiver.stop();
+ oscRouter.removeNode( &durationOSCReceiver );
+
gui->disable();
+ {
+ // play music with VLC
+ ofxVLCRemote vlc;
+ vlc.setup("/Users/daan/vlc.sock"); // client-specific... :(
+ vlc.run("stop");
+ }
+
+ { // SYNC DURATION
+ durationRC rc;
+ rc.setupOSC();
+ rc.stop();
+ }
+
// delete effect pointers
- for(int i=0; i=0;i--){
+ delete effects[i];
+ }
effects.clear();
effects.resize(0);
+ // save recorded file ?
+ recorder.stopRecording();
+
bEnabled = false;
return isEnabled()==false;
}
@@ -178,10 +280,19 @@ void animationController::update(ofEventArgs &event){
void animationController::draw(ofEventArgs& event){
if(!isEnabled()) return;
+ //ofScale(0.5, 0.5); // tmp
+
+ recorder.beginFrame();
+
+ // tmp
+ ofClear(0,1);
+
// draw effects
for(int i=0; irender();
}
+
+ recorder.endFrame(true);
}
void animationController::guiEvent(ofxUIEventArgs &e){
diff --git a/src/core/animationController.h b/src/core/animationController.h
index 4b33d7a..418d16c 100644
--- a/src/core/animationController.h
+++ b/src/core/animationController.h
@@ -17,6 +17,8 @@
#include "ofxUI.h"
#include "oscRouter.h"
#include "mirReceiver.h"
+#include "durationReceiver.h"
+#include "fboRecorder.h"
// todo: an overall mask that hides any unwanted projection zones
@@ -50,9 +52,17 @@ class animationController {
shapesServer& scene;
+ // music
+ ofSoundPlayer music;
+
+
// OSC
OSCRouter& oscRouter;
mirReceiver mirOSCReceiver;
+ durationReceiver durationOSCReceiver;
+
+ // Video recording
+ fboRecorder recorder;
private:
bool bEnabled;
diff --git a/src/core/durationEvents.h b/src/core/durationEvents.h
new file mode 100644
index 0000000..010f2c3
--- /dev/null
+++ b/src/core/durationEvents.h
@@ -0,0 +1,34 @@
+//
+// durationEvents.h
+// karmaMapper
+//
+// Created by Daan on 10/05/15.
+//
+// Include this file in classes communicating with the durationReceiver
+
+#pragma once
+
+struct durationBangEventArgs {
+ string track = "unknown";
+};
+
+struct durationFlagEventArgs {
+ string track = "unknown";
+ string flag = "";
+};
+
+// for trackTypes: curve, lso
+struct durationFloatEventArgs {
+ string track = "unknown";
+ string type = "none";
+ float value = 0;
+};
+
+struct durationSwitchEventArgs {
+ string track = "unknown";
+ bool enabled = false;
+};
+
+// forward declaration
+//class durationReceiver;
+//ofEvent durationReceiver::durationTempoEvent;
diff --git a/src/core/durationRC.cpp b/src/core/durationRC.cpp
new file mode 100644
index 0000000..90f5a63
--- /dev/null
+++ b/src/core/durationRC.cpp
@@ -0,0 +1,66 @@
+//
+// durationRC.cpp
+// karmaMapper
+//
+// Created by Daan de Lange on 10/05/2015.
+// Copyright (c) 2014 __MyCompanyName__. All rights reserved.
+//
+
+#include "durationRC.h"
+
+
+// - - - - - - - -
+// CONSTRUCTORS
+// - - - - - - - -
+durationRC::durationRC( ){
+
+}
+
+durationRC::~durationRC(){
+
+}
+
+bool durationRC::setupOSC(){
+ setup("localhost", 12346);
+ bConnected = true;
+ // (shuts down automatically)
+}
+
+// - - - - - - - -
+// RC COMMANDS - Remote Control Duration
+// - - - - - - - -
+bool durationRC::rewindAndPlay(){
+ if(!isConnected()) return false;
+
+ bool ret = true;
+ ret *= stop();
+
+ ofxOscMessage m;
+ m.setAddress("/duration/seektoposition");
+ m.addFloatArg(0);
+ sendMessage(m);
+
+ ret *= play();
+
+ return ret;
+}
+
+bool durationRC::play(){
+ ofxOscMessage m;
+ m.setAddress("/duration/play");
+ sendMessage(m);
+}
+
+bool durationRC::stop(){
+ ofxOscMessage m;
+ m.setAddress("/duration/stop");
+ sendMessage(m);
+}
+
+// GETTERS
+bool durationRC::isConnected() const {
+ return bConnected;
+}
+
+//mirData durationRC::mirCache;// = mirData();
+
diff --git a/src/core/durationRC.h b/src/core/durationRC.h
new file mode 100644
index 0000000..6fa9748
--- /dev/null
+++ b/src/core/durationRC.h
@@ -0,0 +1,56 @@
+//
+// durationRC
+// karmaMapper
+//
+// Created by Daan de Lange on 10/05/2015.
+//
+//
+//
+
+#pragma once
+
+#include "ofMain.h"
+#include "ofxOsc.h"
+
+// this class sends OSC commands to Duration
+// Thus allowing you to remote control it.
+
+class durationRC : public ofxOscSender {
+
+public:
+ durationRC( );
+ ~durationRC();
+
+ // prevents accidentally creating copies of your singleton
+ durationRC(durationRC const&) = delete;
+ void operator=(durationRC const&) = delete;
+
+ // basic functions
+ bool setupOSC();
+
+ // RC commands
+ bool rewindAndPlay();
+ bool play();
+ bool stop();
+
+ // getters
+ bool isConnected() const;
+
+protected:
+
+ bool bConnected;
+
+ // setting variables
+
+
+ // analysis variables
+
+
+ ofMutex oscMutex; // needed because audioIn() runs on a separate thread
+
+private:
+
+
+};
+
+
diff --git a/src/core/durationReceiver.cpp b/src/core/durationReceiver.cpp
new file mode 100644
index 0000000..4427f41
--- /dev/null
+++ b/src/core/durationReceiver.cpp
@@ -0,0 +1,244 @@
+//
+// durationReceiver.cpp
+// karmaMapper
+//
+// Created by Daan de Lange on 10/05/2015.
+// Copyright (c) 2014 __MyCompanyName__. All rights reserved.
+//
+
+#include "durationReceiver.h"
+
+// forward declarations are needed for event listening
+ofEvent durationReceiver::durationBangEvent;
+ofEvent durationReceiver::durationFlagEvent;
+ofEvent durationReceiver::durationFloatEvent;
+
+// - - - - - - - -
+// CONSTRUCTORS
+// - - - - - - - -
+durationReceiver::durationReceiver( ){
+
+ //
+ bEnabled = false;
+}
+
+durationReceiver::~durationReceiver(){
+ stop();
+}
+
+// - - - - - - - -
+// OSCNode PARENT FUNCTIONS
+// - - - - - - - -
+
+// tell router if a message can be handled by this OSCNode instance
+bool durationReceiver::canHandle(const ofxOscMessage &_msg) const {
+ return (_msg.getAddress().compare(0,DT_PREFIX_LEN,DURATION_TIMELINE_PREFIX) == 0);
+}
+
+// proceed the message
+bool durationReceiver::handle(const ofxOscMessage &_msg) {
+ if( !isEnabled() ) return false;
+
+ // lock mutex
+ ofScopedLock myLock(oscMutex);
+
+ // get incoming track info
+ if( _msg.getAddress().compare("/duration/info") == 0 ){
+
+ // todo: register incomming variable types // tracks and let them be synchronised automatically with inter variables + getters
+
+ return true; // we're done
+ }
+
+ // incoming track data
+ if( canHandle(_msg) ){
+ string track=_msg.getAddress().substr(DT_PREFIX_LEN,_msg.getAddress().npos);
+
+ ofxOscArgType type = OFXOSC_TYPE_NONE;
+ if( _msg.getNumArgs() > 0 ) type = _msg.getArgType(0);
+
+ // - - - - - - - - - -
+ // Notice:
+ // The following message handling are temporary and static.
+ // A system needs to be made for synchronising any track by automatically parsing it. #ofxOscVariable
+ // Hence you can dynamically create new variables and bind them to effect variables
+ // - - - - - - - - - -
+
+ if( track.compare("bang") == 0 && type == OFXOSC_TYPE_NONE ){
+ { // send bangEvent
+ durationBangEventArgs args;
+ args.track=track;
+ ofNotifyEvent(durationBangEvent, args);
+ }
+ }
+ else if( track.compare("test") == 0 ){
+ { // send flagEvent
+ string flag = "";
+ if(_msg.getNumArgs()>0 && type == OFXOSC_TYPE_STRING){
+ flag=_msg.getArgAsString(0);
+ }
+ durationFlagEventArgs args;
+ args.track=track;
+ args.flag="";
+
+ ofNotifyEvent(durationFlagEvent, args);
+ }
+ }
+ else if( track.compare("lineEffectIntensity") == 0 ){
+ { // curve
+ float value = 0;
+ if(_msg.getNumArgs()>0)
+ value=_msg.getArgAsFloat(0);
+ durationFloatEventArgs args;
+ args.track=track;
+ args.type="curve";
+ args.value=value;
+ ofNotifyEvent(durationFloatEvent, args);
+ }
+ }
+ // tmp
+ else if( track.compare("bgVendomeOpacity") == 0 ){
+ { // curve
+ float value = 0;
+ if(_msg.getNumArgs()>0)
+ value=_msg.getArgAsFloat(0);
+ durationFloatEventArgs args;
+ args.track=track;
+ args.type="curve";
+ args.value=value;
+ ofNotifyEvent(durationFloatEvent, args);
+ }
+ }
+
+ else if( track.compare("imageBeatEffectIntensity") == 0 ){
+ { // curve
+ float value = 0;
+ if(_msg.getNumArgs()>0) value=_msg.getArgAsFloat(0);
+ durationFloatEventArgs args;
+ args.track=track;
+ args.type="curve";
+ args.value=value;
+ ofNotifyEvent(durationFloatEvent, args);
+ }
+ }
+ /*{
+ // send bangEvent
+ durationBangEventArgs args;
+ args.what="aubioTempo";
+ ofNotifyEvent(durationBangEvent, args);
+ }
+ {
+ // send bangEvent
+ durationTempoEventArgs args;
+ args.bpm = mirCache.bpm;
+ args.isTempoBis=false;
+ ofNotifyEvent(durationTempoEventArgs, args);
+ }
+ */
+ // unknown track, could not get information
+ else {
+ // todo: try to add the signal here
+ ofLogNotice();
+ }
+ return true;
+ }/*
+ else if( addr.compare("/aubioTempoBis") == 0 ){
+ {
+ // send bangEvent
+ durationBangEventArgs args;
+ args.what="aubioTempoBis";
+ ofNotifyEvent(durationBangEvent, args);
+ }
+ {
+ // send bangEvent
+ durationTempoEventArgs args;
+ args.bpm = mirCache.bpm;
+ args.isTempoBis=true;
+ ofNotifyEvent(durationTempoEventArgs, args);
+ }
+ return true;
+ }
+ else if( addr.compare("/aubioBpm") == 0 ){
+ if(_msg.getNumArgs()>0) mirCache.bpm = _msg.getArgTypeName(0)=="int32"?_msg.getArgAsInt32(0):_msg.getArgAsFloat(0);
+ return true;
+ }
+ else if( addr.compare("/aubioPitch") == 0 ){
+ if(_msg.getNumArgs()>0) mirCache.pitch = _msg.getArgTypeName(0)=="int32"?_msg.getArgAsInt32(0):_msg.getArgAsFloat(0);
+ return true;
+ }
+ else if( addr.compare("/aubioQuiet") == 0 ){
+ if(_msg.getNumArgs()>0) mirCache.silence = (_msg.getArgAsInt32(0)==0)?true:false;
+ return true;
+ }
+ else if( addr.compare("/aubioIsPlaying") == 0 ){
+ if(_msg.getNumArgs()>0) mirCache.isPlaying = (_msg.getArgAsInt32(0)==0)?true:false;
+ return true;
+ }
+ else if( addr.compare("/aubioZcr") == 0 ){
+ if(_msg.getNumArgs()>0) mirCache.zcr = _msg.getArgTypeName(0)=="int32"?_msg.getArgAsInt32(0):_msg.getArgAsFloat(0);
+ return true;
+ }
+ else if( addr.compare("/balance") == 0 ){
+ if(_msg.getNumArgs()>0) mirCache.balance = _msg.getArgTypeName(0)=="int32"?_msg.getArgAsInt32(0):_msg.getArgAsFloat(0);
+ return true;
+ }
+ // Fiddle FFT Equaliser
+ else if( addr.compare(0, 16, "/fiddle_fft/band") == 0 ){ // 16 first chars
+ int band = ofToInt(addr.substr(16));
+
+ if(addr.compare(17, 20, "rms")==0) // rms (volume)
+ mirCache.fiddleFFT[band][0]=_msg.getArgTypeName(0)=="int32"?_msg.getArgAsInt32(0):_msg.getArgAsFloat(0);
+ else // pitch
+ mirCache.fiddleFFT[band][1]=_msg.getArgTypeName(0)=="int32"?_msg.getArgAsInt32(0):_msg.getArgAsFloat(0);
+
+ return true;
+ }
+ else if( addr.compare("") == 0 ){
+
+ return true;
+ }*/
+ else {
+ //cout << "Not recognized OSC = " << _msg.getAddress() << endl;
+ }
+
+ // unrecognized messge
+ return false;
+}
+
+// informs that the nose id gonna be unbound with the node server
+void durationReceiver::detachNode() {
+ stop();
+ // detach events ?
+}
+
+// - - - - - - - -
+// BASIC FUNCTIONS
+// - - - - - - - -
+bool durationReceiver::start(){
+ bEnabled = true;
+
+ // bind events
+ //ofAddListener(, durationReceiver:: *listener, )
+
+ return isEnabled()==true;
+}
+
+bool durationReceiver::stop(){
+ bEnabled = false;
+
+ // unbind events
+
+ return isEnabled()==false;
+}
+
+// - - - - - - - -
+// EVENT LISTENERS
+/*/ - - - - - - - -
+void durationReceiver::oscIn(){
+ // todo
+}//*/
+
+// GETTERS
+bool durationReceiver::isEnabled() const {
+ return bEnabled;
+}
diff --git a/src/core/durationReceiver.h b/src/core/durationReceiver.h
new file mode 100644
index 0000000..d2d9775
--- /dev/null
+++ b/src/core/durationReceiver.h
@@ -0,0 +1,76 @@
+//
+// durationReceiver
+// karmaMapper
+//
+// Created by Daan de Lange on 10/05/2015.
+//
+//
+//
+
+#pragma once
+
+#include "ofMain.h"
+#include "OSCNode.h"
+#include "ofEvents.h"
+#include "durationEvents.h"
+
+// this class handles OSC events comming from Duration and fires internal ofEvents
+// handles OSC adresses prefixed with /duration (name them like that in duration)
+
+// ideas:
+// - enhance duration: add a receiver OF class
+// - enhance duration: add an OSC prefix setting for all tracks
+
+// todo:
+// Use https://github.com/mailiam/ofxOscVariable/ to synchronise variables over osc
+
+// problems compiling this? #MSVC_16 --> http://stackoverflow.com/a/5022140/58565
+#define DURATION_TIMELINE_PREFIX "/dt/"
+#define DT_PREFIX_LEN sizeof(DURATION_TIMELINE_PREFIX)-1
+
+class durationReceiver : public OSCNode {
+
+public:
+ durationReceiver( );
+ ~durationReceiver();
+
+ // prevents accidentally creating copies of your singleton
+ durationReceiver(durationReceiver const&) = delete;
+ void operator=(durationReceiver const&) = delete;
+
+ // Parent functions
+ bool canHandle( const ofxOscMessage &_msg ) const;
+ bool handle( const ofxOscMessage &_msg );
+ void detachNode();
+
+ // basic functions
+ bool start();
+ bool stop();
+
+ // listeners
+ //void oscIn();
+ static ofEvent durationBangEvent;
+ static ofEvent durationFlagEvent;
+ static ofEvent durationFloatEvent;
+
+ // getters
+ bool isEnabled() const;
+
+protected:
+
+ bool bEnabled;
+
+ // setting variables
+
+
+ // analysis variables
+
+
+ ofMutex oscMutex; // needed because audioIn() runs on a separate thread
+
+private:
+
+
+};
+
+
diff --git a/src/core/fboRecorder.cpp b/src/core/fboRecorder.cpp
new file mode 100644
index 0000000..a71e27e
--- /dev/null
+++ b/src/core/fboRecorder.cpp
@@ -0,0 +1,121 @@
+//
+// fboRecorder.cpp
+// karmaMapper
+//
+// Created by Daan de Lange on 10/05/2015.
+// Copyright (c) 2014 __MyCompanyName__. All rights reserved.
+//
+
+#include "fboRecorder.h"
+
+
+// - - - - - - - -
+// CONSTRUCTORS
+// - - - - - - - -
+fboRecorder::fboRecorder( ){
+ bRecording = false;
+ bFrameStarted = false;
+}
+
+fboRecorder::~fboRecorder(){
+ stopRecording();
+}
+
+// - - - - - - - -
+// Recording
+// - - - - - - - -
+
+// filename can be empty (will use timestamp)
+// set _w and _h in px to use a huge off-screen framebuffer if you want
+bool fboRecorder::startRecording(string _fileName, int _w, int _h){
+ if(isRecording()) return;
+
+ if( _w==0 || _h==0 ){
+ _w = ofGetWindowWidth();
+ _h - ofGetWindowHeight();
+ }
+
+ fbo.allocate(_w, _h, GL_RGB, 4); // 4 = anti-aliasing
+ //fbo.getTexture();
+
+ fbo.begin();
+ ofClear(0,0,0);
+ //ofEnableSmoothing(); // makes no difference
+ fbo.end();
+
+ // videoRecorder(ofFilePath::getAbsolutePath("ffmpeg")); // use this is you have ffmpeg installed in your data folder
+
+ // run 'ffmpeg -codecs' to find out what your implementation supports (or -formats on some older versions)
+ ofxVideoRecorder::setVideoCodec("mpeg4");
+ //ofxVideoRecorder::setVideoCodec("h264");
+ ofxVideoRecorder::setVideoBitrate("30000k");
+
+ //videoRecorder.setAudioCodec("mp3");
+ //videoRecorder.setAudioBitrate("192k");
+
+ // tmp
+ string file(_fileName);
+ if(file.compare("")==0) file = "videoRecorder"+ofGetTimestampString()+".mov";
+ ofxVideoRecorder::setup(file, fbo.getWidth(), fbo.getHeight(), 60);
+
+ bRecording = fbo.isAllocated();
+
+ ofLogNotice("fboRecorder") << "Started recording to file «" << file << "»" << endl;
+
+ return bRecording;
+}
+
+bool fboRecorder::stopRecording(){
+ ofxVideoRecorder::close();
+ //ofxVideoRecorder::~ofxVideoRecorder();
+ bRecording=false;
+}
+
+// - - - - - - - -
+// Recording
+// - - - - - - - -
+bool fboRecorder::beginFrame(){
+ if(!isRecording()) return false;
+
+ if(!bFrameStarted){
+ bFrameStarted=true;
+
+ fbo.begin();
+ //ofClear(0);
+
+ /*/ tmp
+ ofSetColor(255,0,0,100);
+ ofFill();
+ ofDrawRectangle(0,0,ofGetWidth(),ofGetHeight());
+ ofSetColor(0,0,255,100);
+ ofNoFill();
+ ofDrawLine(0,0,800,80);*/
+ }
+
+ return true;
+}
+
+bool fboRecorder::endFrame(bool _showBuffer){
+ if(!isRecording()) return false;
+
+ else if(!bFrameStarted) return false;
+
+ fbo.end();
+ //fbo.getTexture().getTextureData().bFlipTexture = false;
+ bFrameStarted=false;
+ if(_showBuffer) fbo.draw(0,0); // show recorded image
+
+ ofPixels pix;
+ pix.allocate(fbo.getWidth(),fbo.getHeight(), ofGetImageTypeFromGLType(GL_RGB));
+ fbo.readToPixels(pix);
+
+ //ofSaveImage(pix, "mahSupahRecoring.png", OF_IMAGE_QUALITY_BEST);
+ ofxVideoRecorder::addFrame(pix);
+
+ return true;
+}
+
+// GETTERS
+bool fboRecorder::isRecording() const {
+ return bRecording;
+}
diff --git a/src/core/fboRecorder.h b/src/core/fboRecorder.h
new file mode 100644
index 0000000..9fdf0a2
--- /dev/null
+++ b/src/core/fboRecorder.h
@@ -0,0 +1,53 @@
+//
+// fboRecorder
+// karmaMapper
+//
+// Created by Daan de Lange on 10/05/2015.
+//
+//
+//
+
+#pragma once
+
+#include "ofMain.h"
+#include "ofxVideoRecorder.h"
+
+// Threaded FBO recording
+
+class fboRecorder : ofxVideoRecorder {
+
+public:
+ fboRecorder( );
+ ~fboRecorder();
+
+ // prevents accidentally creating copies of your singleton
+ ///fboRecorder(fboRecorder const&) = delete;
+ //void operator=(fboRecorder const&) = delete;
+
+ // Enablers
+ bool startRecording(string _fileName="", int _w=0, int _h=0);
+ bool stopRecording();
+
+ // Recording
+ bool beginFrame();
+ bool endFrame(bool _showBuffer=true);
+
+ // getters
+ bool isRecording() const;
+
+protected:
+
+ // recording
+ bool bRecording = false;
+ bool bFrameStarted = false;
+ ofFbo fbo;
+ //ofxVideoRecorder videoRecorder;
+
+ //ofMutex oscMutex; // needed because audioIn() runs on a separate thread
+
+private:
+
+
+};
+
+
diff --git a/src/core/mirEvents.h b/src/core/mirEvents.h
index 0aaa40c..a545983 100644
--- a/src/core/mirEvents.h
+++ b/src/core/mirEvents.h
@@ -4,7 +4,7 @@
//
// Created by Daan on 07/05/15.
//
-//
+// Include this file in classes communicating with the mirReceiver
#pragma once
@@ -29,10 +29,16 @@ class mirData {
}
+ float volumeMono=0;
+ float volumeRigh=0;
+ float volumeLeft=0;
float bpm = 0;
- float pitch = 0;
- float zcr = 0;
+ float pitch = 0; // in hertz (0-1024[?])
+ float balance; // -1+ -> 1+, not limited
+ float zcr = 0; // 0 -> 1+
bool silence = false;
+ bool isPlaying = false;
+ float fiddleFFT[7][2] = {{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}};
};
// forward declaration
diff --git a/src/core/mirReceiver.cpp b/src/core/mirReceiver.cpp
index 2e5279c..74a6213 100644
--- a/src/core/mirReceiver.cpp
+++ b/src/core/mirReceiver.cpp
@@ -39,8 +39,8 @@ bool mirReceiver::canHandle(const ofxOscMessage &_msg) const {
bool mirReceiver::handle(const ofxOscMessage &_msg) {
if( !isEnabled() ) return false;
- // lock mutex
- //ofScopedLock myLock(oscMutex);
+ // lock mutex (threaded execution)
+ ofScopedLock myLock(oscMutex);
string addr = _msg.getAddress();
if( addr.compare("/aubioTempo") == 0 ){
@@ -85,7 +85,7 @@ bool mirReceiver::handle(const ofxOscMessage &_msg) {
return true;
}
else if( addr.compare("/aubioBpm") == 0 ){
- if(_msg.getNumArgs()>0) mirCache.bpm = _msg.getArgAsFloat(0);
+ if(_msg.getNumArgs()>0) mirCache.bpm = _msg.getArgTypeName(0)=="int32"?_msg.getArgAsInt32(0):_msg.getArgAsFloat(0);
return true;
}
else if( addr.compare("/aubioPitch") == 0 ){
@@ -96,10 +96,29 @@ bool mirReceiver::handle(const ofxOscMessage &_msg) {
if(_msg.getNumArgs()>0) mirCache.silence = (_msg.getArgAsInt32(0)==0)?true:false;
return true;
}
+ else if( addr.compare("/aubioIsPlaying") == 0 ){
+ if(_msg.getNumArgs()>0) mirCache.isPlaying = (_msg.getArgAsInt32(0)==0)?true:false;
+ return true;
+ }
else if( addr.compare("/aubioZcr") == 0 ){
if(_msg.getNumArgs()>0) mirCache.zcr = _msg.getArgTypeName(0)=="int32"?_msg.getArgAsInt32(0):_msg.getArgAsFloat(0);
return true;
}
+ else if( addr.compare("/balance") == 0 ){
+ if(_msg.getNumArgs()>0) mirCache.balance = _msg.getArgTypeName(0)=="int32"?_msg.getArgAsInt32(0):_msg.getArgAsFloat(0);
+ return true;
+ }
+ // Fiddle FFT Equaliser
+ else if( addr.compare(0, 16, "/fiddle_fft/band") == 0 ){ // 16 first chars
+ int band = ofToInt(addr.substr(16));
+
+ if(addr.compare(17, 20, "rms")==0) // rms (volume)
+ mirCache.fiddleFFT[band][0]=_msg.getArgTypeName(0)=="int32"?_msg.getArgAsInt32(0):_msg.getArgAsFloat(0);
+ else // pitch
+ mirCache.fiddleFFT[band][1]=_msg.getArgTypeName(0)=="int32"?_msg.getArgAsInt32(0):_msg.getArgAsFloat(0);
+
+ return true;
+ }
else if( addr.compare("") == 0 ){
return true;
@@ -112,9 +131,9 @@ bool mirReceiver::handle(const ofxOscMessage &_msg) {
return false;
}
-// informs that
-void mirReceiver::youHaveToDie() {
-
+// informs that the nose id gonna be unbound with the node server
+void mirReceiver::detachNode() {
+ stop();
// detach events ?
}
diff --git a/src/core/mirReceiver.h b/src/core/mirReceiver.h
index 588fdd0..dc7e99c 100644
--- a/src/core/mirReceiver.h
+++ b/src/core/mirReceiver.h
@@ -36,7 +36,7 @@ class mirReceiver : public OSCNode {
// Parent functions
bool canHandle( const ofxOscMessage &_msg ) const;
bool handle( const ofxOscMessage &_msg );
- void youHaveToDie();
+ void detachNode();
// basic functions
bool start();
diff --git a/src/core/shapesEditor.cpp b/src/core/shapesEditor.cpp
index 8060379..07273ee 100644
--- a/src/core/shapesEditor.cpp
+++ b/src/core/shapesEditor.cpp
@@ -28,6 +28,10 @@ shapesEditor::shapesEditor( shapesServer& _scene ): scene(_scene) {
//gui->disable();
buildMenus();
+ // load image
+ background.load("vendome_full.jpg");
+ //background.load("vendome_daan_v1.0/spores.png");
+
ofAddListener(ofEvents().mousePressed, this, &shapesEditor::_mousePressed);
}
@@ -172,6 +176,10 @@ void shapesEditor::draw() {
// only use computing power if in edit mode.
if( !isInEditMode() ) return;
+ ofSetColor(255);
+ background.draw(0,0);
+
+ // tmp ofScale(0.5, 0.5);
// draw shapes (edit mode)
list& shapes = scene.getShapesRef();
for(shapesServer::shapesIterator it = shapes.begin(); it != shapes.end(); it++){
@@ -193,7 +201,7 @@ void shapesEditor::draw() {
// show bounding box
ofPushStyle();
- ofSetColor(255,60);
+ ofSetColor(255,50);
ofDrawRectangle(multiShapesBoundingBox);
ofSetColor(0);
ofNoFill();
@@ -573,6 +581,7 @@ bool shapesEditor::setEditMode(shapesEditMode _mode){
// show normal GUI ?
else if(editMode!=EDIT_MODE_NORMAL && _mode==EDIT_MODE_NORMAL){
+ ofSetBackgroundAuto(true);
gui->enable();
batchGui->disable();
}
diff --git a/src/core/shapesEditor.h b/src/core/shapesEditor.h
index c28e8ab..bac1e3d 100644
--- a/src/core/shapesEditor.h
+++ b/src/core/shapesEditor.h
@@ -86,7 +86,7 @@ class shapesEditor {
ofRectangle multiShapesBoundingBox;
vector multiPointHandlers;
-
+ ofImage background;
};
diff --git a/src/core/shapesServer.cpp b/src/core/shapesServer.cpp
index 844c20f..bef7b9f 100644
--- a/src/core/shapesServer.cpp
+++ b/src/core/shapesServer.cpp
@@ -197,7 +197,6 @@ bool shapesServer::unloadShapes(){
// - - - - - - - - -
// SHAPE SERVING FUNCTIONS
// - - - - - - - - -
-
basicShape* shapesServer::getRandomShape(){
if(shapes.size()<1){
ofLogError("shapesServer::getRandomShape()", "There are not yet any shapes to serve!");
@@ -206,13 +205,45 @@ basicShape* shapesServer::getRandomShape(){
return NULL;
}
- int offset( round( ofRandom(-.49f, shapes.size()-.51f ) ) );
+ int offset( round( ofRandomuf()-.49f*(shapes.size()-.011f) ) );
list::iterator it = shapes.begin();
std::advance(it,offset);
return *it;
}
+vector shapesServer::getRandomShapes(int _amount, bool _returnExactAmount ) {
+
+ // select unique shapes when possible
+ // todo: add a vector remainingIndexes for optimisation
+ vector selected;
+ vector retShapes;
+ selected.resize(_amount);
+ int numAdded = 0;
+ while(numAdded < _amount && numAdded < getNumShapes() ){
+ int newSh = ofRandom( 0.49f+getNumShapes()-1 );
+ if( std::find( selected.begin(), selected.end(), newSh)==selected.end() ){
+ // found a new one
+ list::iterator it = shapes.begin();
+ std::advance(it,newSh);
+ retShapes.push_back(*it);
+ selected[numAdded]=newSh;
+ numAdded++;
+ //cout << "Rand=" << newSh << "[/"<< getNumShapes() << "]" << endl;
+ }
+ }
+
+ // if there are les shapes then the asked amount, fill them with random duplicates
+ if(_returnExactAmount && numAdded<_amount){
+ while( numAdded!=_amount){
+ retShapes.push_back( getRandomShape() );
+ numAdded++;
+ }
+ }
+
+ return retShapes;
+}
+
// todo: add int _limit restriction param (and randomize)
vector shapesServer::getShapesByType(string _type){
vector ret;
@@ -231,7 +262,7 @@ basicShape* shapesServer::getRandomShapeByType(string _type){
vector ret = getShapesByType(_type);
if(ret.size()<=0) return NULL;
- return ret[-.49f+ofRandomf()*(ret.size()-0.51f)];
+ return ret[round(-.49f+ofRandomuf()*(ret.size()-0.011f))];
}
// todo: add int _limit restriction param (and randomize)
@@ -251,7 +282,20 @@ vector shapesServer::getShapesByGroup(int _group){
basicShape* shapesServer::getRandomShapeByGroup(int _group){
vector ret = getShapesByGroup(_group);
if(ret.size()<=0) return NULL;
- return ret[-.49f+ofRandomf()*(ret.size()-.51f)];
+ return ret[round(-.49f+(ofRandomuf()*(ret.size()-.011f)))];
+}
+
+vector shapesServer::getAllShapes(){
+ vector ret;
+ ret.clear();
+ ret.resize(shapes.size());
+
+ // loop trough shapes and return the wanted ones
+ for(list::iterator it = shapes.begin(); it != shapes.end(); it++){
+ ret.push_back((*it));
+ }
+
+ return ret;
}
// - - - - - - -
diff --git a/src/core/shapesServer.h b/src/core/shapesServer.h
index 9e43d0f..263aaeb 100644
--- a/src/core/shapesServer.h
+++ b/src/core/shapesServer.h
@@ -44,10 +44,12 @@ class shapesServer {
// shape serving functions
list& getShapesRef(){ return shapes; }
basicShape* getRandomShape();
+ vector getRandomShapes(int _amount=1, bool _returnExactAmount = true );
vector getShapesByType(string _type);
basicShape* getRandomShapeByType(string _type);
vector getShapesByGroup(int _group);
basicShape* getRandomShapeByGroup(int _group);
+ vector getAllShapes();
// utilities
const unsigned int getNumShapes() const;
diff --git a/src/effects/basicEffect.cpp b/src/effects/basicEffect.cpp
index e1ee01e..c53203d 100644
--- a/src/effects/basicEffect.cpp
+++ b/src/effects/basicEffect.cpp
@@ -18,7 +18,7 @@
basicEffect::basicEffect(){
- reset();
+ basicEffect::reset();
// effect type must match with class
effectType = "basicEffect";
@@ -38,7 +38,7 @@ basicEffect::~basicEffect(){
// isReady() should return true after this is done. (can take a long time)
bool basicEffect::initialise(){
// init values
- reset();
+ basicEffect::reset();
isLoading = true;
@@ -49,6 +49,8 @@ bool basicEffect::initialise(){
// set this when done
isInitialised = true;
isLoading = false;
+
+ return isInitialised;
}
// todo: update -(handled by)-> animation
@@ -73,12 +75,16 @@ bool basicEffect::render(){
// todo: update should receive parameters like update rate, time variables, etc.
// todo: this should always be called in fact. imageGrainEffect::update() should be called by it.
void basicEffect::update(){
+ ofScopedLock lock(effectMutex);
+
if( !isReady() ) return;
aliveSince = ofGetSystemTime() - startTime;
}
// resets all values
void basicEffect::reset(){
+ effectMutex.lock();
+
// todo: do this in _reset() which then calls reset();
aliveSince=0;
startTime=ofGetSystemTime();
@@ -92,6 +98,8 @@ void basicEffect::reset(){
isLoading = false;
overallBoundingBox = ofRectangle(0,0,0,0);
+
+ effectMutex.unlock();
}
void basicEffect::enable(){
@@ -105,9 +113,9 @@ void basicEffect::disable(){
// - - - - - - -
// EFFECT PROPERTIES
// - - - - - - -
-
+
bool basicEffect::isReady() const{
- return isInitialised && !hasError;
+ return isInitialised && !hasError && !isLoading;
}
bool basicEffect::isType(const string _type) const {
@@ -129,6 +137,7 @@ bool basicEffect::randomizePresets(){
void basicEffect::updateBoundingBox(){
// no shapes ?
if(shapes.size()==0){
+ // todo correctly
// return center if no shapes are selected
overallBoundingBox = ofRectangle( ofGetWidth()/2, ofGetHeight()/2, 0, 0);
return;
@@ -140,6 +149,7 @@ void basicEffect::updateBoundingBox(){
// analyse all contained boundingBoxes
for(int i=shapes.size()-1; i>=0; i--){
+ if( !shapes[i]->isReady() ) continue;
// cache needed vars
ofVec2f tmpLTCorner( shapes[i]->getBoundingBox().x, shapes[i]->getBoundingBox().y);
diff --git a/src/effects/basicEffect.h b/src/effects/basicEffect.h
index 029787b..c437e83 100644
--- a/src/effects/basicEffect.h
+++ b/src/effects/basicEffect.h
@@ -37,7 +37,7 @@
// Should an effect also be able to query available shapes? To ask to be moved to another shape? (This shouldn't be forced by the animator) Can an effect ask to be replaced (progressively?) and die? (ex: create organic lifeforms, create interactive games...), Ask for more effects of a certain type and set their initial params? can they ask not to be destroyed yet? etc? Temporarily forbid the use of certain effects on certain shape types ? Etc.
// Effects preferences ?
// transitions? make a transition system with custom parenting ? Effects handle their own transitions ?
-// Make effects "connect" protocal to them to each other. They can chose to let other appear/die and notify events to eachother. Two connected effects make a transition
+// Make effects "connect" protocol to them to each other. They can chose to let other appear/die and notify events to eachother. Two connected effects make a transition
// How does everything remain connected with eachother ? Maybe 1 main animation class can control the main things and effects can freely move on shapes.
// maybe try { cast class }catch(){ignore}
// maybe compiler can handle this ?
@@ -52,6 +52,8 @@
// todo: isLoading should be isLoaded (or maybe another name) (also for hasError, initialised, etc.. they are unclear.
// todo: shapeType should be a vector so it can contain all shape types it is
+//#define KM_NULL_SHAPE(NULL)
+
class basicEffect {
public:
@@ -89,6 +91,9 @@ class basicEffect {
bool detachFromShape(basicShape* _shape);
int getNumShapes() const;
+ // todo
+ // overallBoundingBox getter
+
// todo: make this read-only
unsigned int aliveSince;
unsigned long long startTime; // to compare against ofGetSystemTime();
@@ -109,7 +114,8 @@ class basicEffect {
vector shapes;
ofRectangle overallBoundingBox; // computes boundingbox containing all shapes
-
+ //ofPlanePrimitive
+ ofMutex effectMutex;
private:
diff --git a/src/effects/effects.h b/src/effects/effects.h
index 462342e..7ff1e04 100644
--- a/src/effects/effects.h
+++ b/src/effects/effects.h
@@ -12,14 +12,14 @@
// add all effect files to this file and they'll all be automatically included in files that need all effects
#include "basicEffect.h"
#include "musicEffect.h"
+#include "imageEffect.h"
#include "imageGrainEffect.h"
#include "imageMeltingEffect.h"
-//#include "imageEffect.h"
//#include "shaderEffect.h"
-//#include "videoEffect.h"
+#include "videoEffect.h"
//#include "gifEffect.h"
#include "lineEffect.h"
-//#include "imageBeatEffect.h"
+#include "imageBeatEffect.h"
//#include "meshRenderer3D.h"
//#include "videoStreamEffect.h"
diff --git a/src/effects/emptyEffect.h b/src/effects/emptyEffect.h
index b83d2cd..d0b133e 100644
--- a/src/effects/emptyEffect.h
+++ b/src/effects/emptyEffect.h
@@ -29,6 +29,9 @@ class emptyEffect : public musicEffect {
// controller functions
virtual bool randomizePresets();
+ // Event listeners
+ // If you use some, make sure to use an ofMutex (http://openframeworks.cc/ofBook/chapters/threads.html)
+
protected:
diff --git a/src/effects/imageBeatEffect.cpp b/src/effects/imageBeatEffect.cpp
new file mode 100644
index 0000000..651bee1
--- /dev/null
+++ b/src/effects/imageBeatEffect.cpp
@@ -0,0 +1,230 @@
+//
+// imageBeatEffect.cpp
+// karmaMapper
+//
+// Created by Daan de Lange on 12/3/14.
+//
+// - - - -
+//
+// Parent class for all effects.
+// Implements some standard methods for overall usage.
+//
+
+#include "imageBeatEffect.h"
+
+imageBeatEffect::imageBeatEffect(){
+ //basicEffect::basicEffect();
+
+ ofScopedLock lock(effectMutex);
+
+ // effect type mutch match with class
+ effectType = "imageBeatEffect";
+
+ beatItemSpeed = 0;
+ intensity=0;
+ totalbeatItemsNb=0;
+
+ beatItems.clear();
+ beatsToAdd.clear();
+}
+
+imageBeatEffect::~imageBeatEffect(){
+ //basicEffect::~basicEffect();
+
+ ofScopedLock lock(effectMutex);
+ cout << "beatEffectMutexLock+unlock ~" << endl;
+
+ /*for(std::list::reverse_iterator it=beatItems.rbegin(); it!= beatItems.rend(); it--){
+ it++;
+ it= std::list::reverse_iterator( beatItems.erase( it.base() ));
+ it--;
+ }*/
+ //beatItems.erase();
+
+ //effectMutex.unlock();
+ //effectMutex.unlock();
+ ofRemoveListener(mirReceiver::mirOnSetEvent, this, &imageBeatEffect::onSetEventListener);
+ ofRemoveListener(durationReceiver::durationFloatEvent, this, &imageBeatEffect::floatListener);
+}
+
+bool imageBeatEffect::initialise(){
+ //bool success = basicEffect::initialise();
+
+ //if(success){ // tmp
+ //effectMutex.lock();
+ cout << "beatEffectMutexLock init" << endl;
+ isLoading = true;
+
+ // do stuff here
+ ofAddListener(mirReceiver::mirOnSetEvent, this, &imageBeatEffect::onSetEventListener);
+ ofAddListener(durationReceiver::durationFloatEvent, this, &imageBeatEffect::floatListener);
+ //ofAddListener(mirReceiver::mirTempoEvent, this, &lineEffect::tempoEventListener);
+
+ isLoading = false;
+ isInitialised=true;
+ //effectMutex.unlock();
+ cout << "beatEffectMutexunLock init" << endl;
+ //}
+
+ return isInitialised;
+}
+
+bool imageBeatEffect::render(){
+ ofScopedLock lock(effectMutex);
+
+ //cout << "beatEffectMutexLock render" << endl;
+ if( !isReady() || shapes.size()==0 ) return;
+
+ for(std::list::iterator it=beatItems.begin(); it!= beatItems.end(); ++it){
+ (*it).render();
+ }
+ //cout << "beatEffectMutexunLock render" << endl;
+}
+
+void imageBeatEffect::update(){
+
+ // you can chose to do the default behaviour too or not by commenting this out
+ //basicEffect::update(); // tmp
+
+ //effectMutex.lock();// lock(effectMutex);
+ //cout << "beatEffectMutexLock upd" << endl;
+
+ ofScopedLock lock(effectMutex);
+ if(!isReady()) return;
+
+ // add items ?
+ int i= beatsToAdd.size()-1;
+ if(i>2) i=2;
+ if(shapes.size()!=0) for(; i>=0;i--){
+ basicShape* beatItem = beatsToAdd[0];
+ beatItems.push_back( getBeatItem( beatItem) );
+ totalbeatItemsNb++;
+ beatsToAdd.pop_back();
+ }
+
+ // check for dead lines
+ for(std::list::reverse_iterator it=beatItems.rbegin(); it!= beatItems.rend(); it--){
+
+ if( !(*it).isAlive() ) {
+ it++;
+ it= std::list::reverse_iterator( beatItems.erase( it.base() ));
+ it--;
+ }
+ }
+ //effectMutex.unlock();
+ //cout << "beatEffectMutexunLock upd" << endl;
+}
+
+// resets all values
+// overrule this function with your own.
+void imageBeatEffect::reset(){
+ basicEffect::reset();
+
+ ofScopedLock lock(effectMutex);
+ cout << "beatEffectMutexLock rst" << endl;
+ beatItems.clear();
+ cout << "beatEffectMutexunLock rst" << endl;
+}
+
+// can be removed ?
+bool imageBeatEffect::grabSomeShapes(){
+ return true;// tmp
+ ofScopedLock lock(effectMutex);
+
+ // clear
+ shapes.clear();
+ shapes.resize(0);
+
+ // we just want all vertex shapes
+ //shapes = shapesHandler::getInstance().getShapesByType("vertexShape");
+
+ // then sort them by group
+ //map groups; //
+ shapeGroups.clear();
+ for(int i=0; igetGroupID();
+
+ // create map entry ?
+ if( shapeGroups.find(group) == shapeGroups.end() ){
+ shapeGroups[group] = vector();
+ }
+
+ shapeGroups[group].push_back(i);
+ }
+
+ // return
+ return shapeGroups.size() > 0;
+}
+
+// to rename : imageBeatItenOnRandomShape
+// note: when you call this function, mutex must be locked
+// ONLY call this from the main thread // GL-thread
+imageBeatEffectItem imageBeatEffect::getRandomBeatItem(){
+ //ofScopedLock lock(effectMutex);
+
+ basicShape* shape = shapes[ round( ofRandom(-0.49f,shapes.size()-0.51f)) ];
+
+ // return
+ return imageBeatEffectItem( shape );
+}
+imageBeatEffectItem imageBeatEffect::getBeatItem(basicShape* _shape){
+ if(_shape==NULL) return; // todo: how to return a right value here ?
+
+ // return
+ return imageBeatEffectItem( _shape );
+}
+
+// - - - - - - - - -
+// EVENT LISTENERS
+// - - - - - - - - -
+void imageBeatEffect::floatListener(durationFloatEventArgs &_args){
+ if( _args.track.compare("imageBeatEffectIntensity")!=0 ) return;
+
+ ofScopedLock lock(effectMutex);
+ intensity = _args.value;
+ //lines.push_back();
+}
+
+/*void imageBeatEffect::noteEventListener(ofx::AbletonLiveSet::LSNoteEvent ¬eEvent){
+ return false;
+ ofScopedLock lock(effectMutex);
+ //lines.push_back();
+}*/
+
+void imageBeatEffect::onSetEventListener(mirOnSetEventArgs &_args){
+ if( _args.source.compare("aubioOnSet")==0 ){
+
+ ofScopedLock lock(effectMutex);
+
+ if(shapes.size()==0 || !isReady() ) return; // not yet bound with a shape
+
+ //cout << "beatEffectMutexLock tmpo" << endl;
+ int amount = round(mirReceiver::mirCache.zcr*100.f*intensity+1.f);
+ //cout << amount<< endl;
+ // spawn some beats
+ if(amount > 20) amount = 20;
+ for(int i=0; i > shapeGroups; // >
+ list beatItems;
+ ofMutex effectMutex;
+ //vector beatsToAdd;
+ vector beatsToAdd;
+
+ //basicShape* fromShape;
+ //basicShape* toShape;
+
+private:
+ float beatItemSpeed;
+ float intensity=1;
+ int totalbeatItemsNb;
+};
diff --git a/src/effects/imageBeatEffectItem.cpp b/src/effects/imageBeatEffectItem.cpp
new file mode 100644
index 0000000..de1c532
--- /dev/null
+++ b/src/effects/imageBeatEffectItem.cpp
@@ -0,0 +1,124 @@
+//
+// imageBeatEffectItem.cpp
+// workshopMappingCyril
+//
+// Created by Daan de Lange on 14/12/2014.
+// Copyright (c) 2014 __MyCompanyName__. All rights reserved.
+//
+
+#include "imageBeatEffectItem.h"
+
+imageBeatEffectItem::imageBeatEffectItem(basicShape* _shape) {
+ if(_shape==NULL) return;
+
+ vertexShape* shape =((vertexShape*)_shape);
+
+ bAlive = true;
+ startTime = ofGetElapsedTimef();
+ center = shape->getCenterPtr();
+ position = *center - ofVec2f( shape->getBoundingBox().x, _shape->getBoundingBox().y );
+
+ // get image from shape
+ ofRectangle size = _shape->getBoundingBox();
+ if( size.width ==0 && size.height ==0 ){
+ bAlive=false;
+ return;
+ }
+ image.allocate(size.width, size.height, GL_RGBA, 1);
+ image.loadScreenData(size.x, size.y, size.width, size.height);
+ /* ofPixels tmp; // tmp
+ //image.readToPixels(tmp);
+
+ // draw shape in an fbo and draw shape mask
+ ofFbo buffer;
+ buffer.allocate(size.width, size.height, GL_RGBA, 1);
+ buffer.begin();
+ ofClear(0,1);
+ ofClearAlpha();
+
+ // draw virtual mask
+ //ofTranslate( *shape->getPositionPtr() * ofVec2f(-1.f,-1.f) +size.width/2); // because shape->render() translates it back
+ ofTranslate(-1*ofVec2f( shape->getBoundingBox().x, _shape->getBoundingBox().y ));
+ shape->render();
+ ofTranslate(ofVec2f( shape->getBoundingBox().x, _shape->getBoundingBox().y ));
+
+ buffer.end();
+
+ // draw texture with alpha mask
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendEquation(GL_FUNC_SUBTRACT);
+ //ofSetColor(255,255);
+ image.draw(-position.x,-position.y);
+ ofDisableAlphaBlending();
+
+ buffer.end();
+
+ //buffer.readToPixels(tmp);
+
+ //ofSaveImage(tmp, "lol.png");
+
+ // get mask pixels
+ ofPixels maskPixels;
+ buffer.readToPixels( maskPixels );
+ image.loadData(maskPixels);
+ //image.
+ //*/
+ //ofPixels tmp;
+ //image.readToPixels(tmp);
+
+ //ofSaveImage(tmp, "lol.png");
+
+ // apply mask opacity to image (3=alpha channel)
+ //for( int i=3; iLEL_LIFE_SPAN) bAlive=false;
+
+ else render( aliveSince/LEL_LIFE_SPAN );
+
+ return true;
+}
+
+void imageBeatEffectItem::render(float state) {
+ if(!bAlive) return;
+
+ //float opacity = abs( (state*2)-1 );
+ float opacity = 1-abs( (state-0.5f)*2 );
+
+ ofPushStyle();
+
+ float scale = 1-state;
+ ofVec2f xy = *center - position*scale;
+ ofVec2f wh = ofVec2f( image.getWidth(), image.getHeight() )*scale;
+ image.draw( xy.x, xy.y, wh.x, wh.y );
+
+ ofPopStyle();
+}
+
+bool imageBeatEffectItem::isAlive() const{
+ return bAlive;
+}
diff --git a/src/effects/imageBeatEffectItem.h b/src/effects/imageBeatEffectItem.h
new file mode 100644
index 0000000..0f7643b
--- /dev/null
+++ b/src/effects/imageBeatEffectItem.h
@@ -0,0 +1,36 @@
+//
+// imageBeatEffectItem.h
+// workshopMappingCyril
+//
+// Created by Daan de Lange on 14/12/2014.
+// Copyright (c) 2014 __MyCompanyName__. All rights reserved.
+//
+
+#pragma once
+
+#include "ofMain.h"
+#include "vertexShape.h"
+
+#define LEL_LIFE_SPAN 1
+
+class imageBeatEffectItem {
+
+public:
+ imageBeatEffectItem(basicShape* _shape);
+ ~imageBeatEffectItem();
+
+ void render();
+ void render(float state);
+ bool isAlive() const;
+
+protected:
+ ofVec2f* center;
+ ofVec2f position;
+ ofTexture image;
+
+ float startTime;
+ bool bAlive = false;
+
+private:
+
+};
diff --git a/src/effects/imageEffect.cpp b/src/effects/imageEffect.cpp
new file mode 100644
index 0000000..5d29100
--- /dev/null
+++ b/src/effects/imageEffect.cpp
@@ -0,0 +1,223 @@
+//
+// imageEffect.cpp
+// karmaMapper
+//
+// Created by Daan de Lange on 12/3/14.
+//
+// - - - -
+//
+// Parent class for all effects.
+// Implements some standard methods for overall usage.
+//
+
+#include "imageEffect.h"
+
+imageEffect::imageEffect(){
+ basicEffect::basicEffect(); // tocheck: can be stripped out?
+
+ // effect type mutch match with class
+ effectType = "imageEffect";
+
+ // init variables
+ reset();
+}
+
+imageEffect::~imageEffect(){
+ //basicEffect::~basicEffect();
+
+ ofScopedLock lock(effectMutex);
+
+ imageShader.unload();
+
+
+ ofRemoveListener(durationReceiver::durationFloatEvent, this, &imageEffect::floatListener);
+}
+
+bool imageEffect::initialise(){
+ bool success = basicEffect::initialise();
+
+ if(success){
+ effectMutex.lock();
+ isLoading = true;
+
+ // set folder and load images
+ //hasError = setFolder("ressources/images/collection1");
+ //cachedImage.allocate(500,500, GL_RGBA, 0);
+ //loadImageFromFile("ressources/images/collection1/Stronium-Tree-highres.jpg");
+ //cachedImage.allocate(ofGetCurrentRenderer()->getViewportWidth(), ofGetCurrentRenderer()->getViewportHeight(), GL_RGB);
+ hasError = false;
+
+ // setup shader
+ if(ofIsGLProgrammableRenderer()) hasError *= imageShader.load("effects/imageEffect/imageShaderGL3");
+ else hasError *= imageShader.load("effects/imageEffect/imageShader");
+
+ if(hasError) isInitialised=false;
+
+ isLoading = false;
+ effectMutex.unlock();
+ }
+
+ return isInitialised;
+}
+
+bool imageEffect::render(){
+ //effectMutex.lock();
+ ofScopedLock lock(effectMutex);
+
+ if( shapes.size()==0 ){
+ //effectMutex.unlock();
+ return true;
+ }
+
+ if(opacity==0){
+ return true;
+ }
+
+ // show image on all available zones
+ for (vector::iterator it=shapes.begin(); it != shapes.end(); it++ ) {
+ if( (*it)->isReady() && imageShader.isLoaded() ){
+ //return true;
+ //cachedImage.draw( it[0]->getBoundingBox() );
+ //it[0]->hasError?ofSetColor(255):ofSetColor(255,0,0);
+ //ofDisableArbTex();
+ //ofEnableTextureEdgeHack();
+
+ //ofTexture &tex0 = cachedImage.getTexture();
+
+ imageShader.begin();
+
+ //hasError?ofSetColor(255):ofSetColor(255,0,0);
+ ofSetColor(255, opacity*255);
+ ofFill();
+
+ //tex0.setTextureWrap(GL_MIRRORED_REPEAT, GL_MIRRORED_REPEAT);
+
+ //imageShader.setUniform2f("tex0Resolution", tex0.getWidth(), tex0.getHeight());
+
+ //cachedImage.getTexture().disableTextureMatrix();
+
+ imageShader.setUniform1i("fitMode", 1);
+ imageShader.setUniform2f("tex0Resolution", cachedImage.getWidth(), cachedImage.getHeight());
+ // todo: use position pointer unstead of boundingBox ?
+ ofRectangle bbox=(*it)->getBoundingBox();
+ imageShader.setUniform4f("shapeBoundingBox", bbox.x, bbox.y, bbox.getWidth(), bbox.getHeight());
+ //bbox=
+ //imageShader.setUniform4f("shapesBoundingBox", bbox.x, bbox.y, bbox.width, bbox.height);
+ imageShader.setUniform2f("fboCanvas", ofGetWidth(),ofGetHeight());
+ imageShader.setUniform1f("opacity", opacity);
+
+ //imageShader.setUniformTexture("tex0", cachedImage.getTexture(), 1);
+
+ //cachedImage.getTexture().setTextureWrap(GL_REPEAT, GL_REPEAT);
+ cachedImage.setTextureWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
+ //cachedImage.getTexture().setTextureWrap(GL_REPEAT, GL_REPEAT);
+ cachedImage.bind();
+ (*it)->render();
+ cachedImage.unbind();
+
+ imageShader.end();
+ }
+ }
+ //effectMutex.unlock();
+}
+
+void imageEffect::update(){
+ // you can chose to do the default behaviour too or not by commenting this out
+
+ basicEffect::update();
+
+ // do your stuff here
+
+ //effectMutex.lock();
+ //effectMutex.unlock();
+
+
+}
+
+// resets all values
+// overrule this function with your own.
+void imageEffect::reset(){
+ basicEffect::reset();
+}
+
+bool imageEffect::loadImageFromFile(string _imagePath){
+ if(_imagePath.compare("")==0) return false;
+
+ // already cached or cache it ?
+ //ofPixels img;
+ if( ofLoadImage( cachedImage, _imagePath ) ){
+ return true;
+ }
+ // fail ?
+ else{
+ ofLogNotice("imageEffect") << "Could not load: "+ _imagePath << endl;
+ hasError = true;
+ }
+
+ return false;
+}
+
+bool imageEffect::listenToOscIntensity(string _OSCPath){
+ if(_OSCPath.compare("")==0) return false;
+
+ listenToIntensity = _OSCPath;
+
+ ofAddListener(durationReceiver::durationFloatEvent, this, &imageEffect::floatListener);
+
+ return true;
+}
+
+/*bool imageEffect::grabSomeShapes(){
+ // clear
+ shapes.clear();
+ shapes.resize(0);
+
+ // we only want vertex shapes
+ //shapes = shapesHandler::getInstance().getShapesByType("vertexShape");
+
+ // select the vertex shapes in the biggest group
+ map groups;
+ groups.clear();
+ for(int i=0; igetGroupID();
+ groups[group]++;
+ }
+
+ // get biggest populated group ID
+ int most = -1;
+ for( std::map::iterator it=groups.begin(); it!= groups.end(); ++it ){
+ if( it->second > groups[most] ) most = it->first;
+ }
+
+ // filter others out
+ for (int i=shapes.size()-1; i>=0; i--) {
+ if( shapes[i]->getGroupID() != most ) shapes.erase( shapes.begin() + i );
+ }
+
+ return true;
+}*/
+
+// - - - - -
+// EVENT LISTENERS
+// - - - - - - - - -
+void imageEffect::floatListener(durationFloatEventArgs &_args){
+ ofScopedLock lock(effectMutex);
+ //cout <<_args.track << endl;
+ if( listenToIntensity.compare("")==0) return;
+ if( _args.track.compare(listenToIntensity)!=0 ) return;
+
+ opacity = _args.value;
+ //lines.push_back();
+}
+
+/*void imageEffect::onSetEventListener(mirOnSetEventArgs &_args){
+ ofScopedLock lock(effectMutex);
+
+ if(shapes.size()<=0) return;
+
+ if(_args.source.compare("aubioOnSet")==0) for(int i=0; i animation
+// overrule this function with your own
+bool imageFolderEffect::render(){
+ if( shapes.size()==0 ) return;
+
+ /*/ image to display ?
+ if( currentImage >=0 && currentImage < cachedImages.size() && cachedImages[currentImage].isUsingTexture() ){
+ cachedImages[currentImage].draw( shapes[0]->getBoundingBox() );
+ }// */
+
+ // show image on all available zones
+ for (vector::iterator it=shapes.begin(); it != shapes.end(); it++ ) {
+ if( (*it)->isReady() && imageShader.isLoaded() ){
+ //return true;
+ //cachedImages[currentImage].draw( it[0]->getBoundingBox() );
+ //it[0]->hasError?ofSetColor(255):ofSetColor(255,0,0);
+ //ofDisableArbTex();
+ //ofEnableTextureEdgeHack();
+
+ //ofTexture &tex0 = cachedImages[currentImage].getTexture();
+
+ imageShader.begin();
+
+ hasError?ofSetColor(255):ofSetColor(255,0,0);
+ ofFill();
+
+ //tex0.setTextureWrap(GL_MIRRORED_REPEAT, GL_MIRRORED_REPEAT);
+
+ //imageShader.setUniform2f("tex0Resolution", tex0.getWidth(), tex0.getHeight());
+
+ //cachedImages[currentImage].getTexture().disableTextureMatrix();
+
+ imageShader.setUniform1i("fitMode", 1);
+ imageShader.setUniform2f("tex0Resolution", cachedImages[currentImage].getWidth(), cachedImages[currentImage].getHeight());
+ // todo: use position pointer unstead of boundingBox ?
+ ofRectangle bbox=(*it)->getBoundingBox();
+ imageShader.setUniform4f("shapeBoundingBox", bbox.x, bbox.y, bbox.getWidth(), bbox.getHeight());
+ //bbox=
+ //imageShader.setUniform4f("shapesBoundingBox", bbox.x, bbox.y, bbox.width, bbox.height);
+ imageShader.setUniform2f("fboCanvas", ofGetWidth(),ofGetHeight());
+
+ //imageShader.setUniformTexture("tex0", cachedImages[currentImage].getTexture(), 1);
+
+ //cachedImages[currentImage].getTexture().setTextureWrap(GL_REPEAT, GL_REPEAT);
+ cachedImages[currentImage].getTexture().setTextureWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
+ //cachedImages[currentImage].getTexture().setTextureWrap(GL_REPEAT, GL_REPEAT);
+ cachedImages[currentImage].getTexture().bind();
+ (*it)->render();
+ cachedImages[currentImage].getTexture().unbind();
+
+ imageShader.end();
+ }
+ }
+
+}
+
+void imageFolderEffect::update(){
+ // you can chose to do the default behaviour too or not by commenting this out
+ basicEffect::update();
+
+ // do your stuff here
+
+ // advance slide ?
+ if(cachedImages.size()>0 ){
+
+ currentImage = floor( (aliveSince%( timePerSlide *cachedImages.size()))/ timePerSlide );
+
+ // increment
+ //currentImage++;
+
+ // rewind ?
+ if( currentImage >= cachedImages.size() ) currentImage=0;
+ }
+}
+
+// resets all values
+// overrule this function with your own.
+void imageFolderEffect::reset(){
+ basicEffect::reset();
+
+ folder = "";
+ currentImage = -1;
+ imageFiles.resize(0);
+ imageFiles.clear();
+ timePerSlide = 500; // time in ms
+}
+
+
+bool imageFolderEffect::setFolder(string _dir){
+ // already set ?
+ if(_dir==folder) return true;
+
+ ofDirectory dir(_dir);
+
+ if( !dir.exists() || !dir.canRead() ){
+ ofLogNotice("imageFolderEffect") << "Unable to load " << _dir << endl;
+ return false;
+ }
+ else{
+ // default image path
+ //if(folder=="") folder="./imageFolderEffect/images/";
+
+ // scan for images
+ dir.allowExt("jpg");
+ dir.allowExt("png");
+ dir.allowExt("jpeg");
+ dir.allowExt("gif");
+ dir.listDir(_dir);
+ dir.sort();
+
+ // todo: change to logverbose
+ if(dir.size()==0){
+ if(!dir.exists()){
+ ofLogNotice("imageFolderEffect") << "Folder «" << _dir << "» doesn't exist." << endl;
+ }
+ else if(!dir.canRead()){
+ ofLogNotice("imageFolderEffect") << "Folder «" << _dir << "» is not readable." << endl;
+ }
+ else if(!dir.isDirectory()){
+ ofLogNotice("imageFolderEffect") << "Folder «" << _dir << "» is not a directory." << endl;
+ }
+ else ofLogNotice("imageFolderEffect") << "Folder «" << _dir << "» contains no images to load. Make sure that there are .mov or .mp4 files." << endl;
+ }
+ else ofLogVerbose("imageFolderEffect") << "Scanning «" << _dir << "» ... Found " << ofToString(dir.size()) << " file(s) (.gif | .jpg | .jpeg | .png) [readable=" << ofToString(dir.canRead()) << "] [isDirectory=" << ofToString(dir.isDirectory()) << "]" << endl;
+
+ // cache images
+ imageFiles.resize(0);
+ cachedImages.resize(0);
+ for(int i=0; i= imageFiles.size() ) return false;
+
+ // already cached or cache it ?
+ string tmp = ofToString(folder+"/"+imageFiles[imageID]);
+ if( cachedImages[imageID].isUsingTexture() || cachedImages[imageID].load( tmp )){
+ currentImage = imageID;
+ return true;
+ }
+ // fail ?
+ else{
+ ofLogNotice("imageFolderEffect") << "Could not load "+ tmp << endl;;
+ hasError = true;
+ return false;
+ }
+}
+
+bool imageFolderEffect::loadImage(string imageName){
+ int found = -1;
+
+ // find imageID by string
+ for(int i=0; i groups;
+ groups.clear();
+ for(int i=0; igetGroupID();
+ groups[group]++;
+ }
+
+ // get biggest populated group ID
+ int most = -1;
+ for( std::map::iterator it=groups.begin(); it!= groups.end(); ++it ){
+ if( it->second > groups[most] ) most = it->first;
+ }
+
+ // filter others out
+ for (int i=shapes.size()-1; i>=0; i--) {
+ if( shapes[i]->getGroupID() != most ) shapes.erase( shapes.begin() + i );
+ }
+
+}
diff --git a/src/effects/imageFolderEffect.h b/src/effects/imageFolderEffect.h
new file mode 100644
index 0000000..595e2fe
--- /dev/null
+++ b/src/effects/imageFolderEffect.h
@@ -0,0 +1,47 @@
+//
+// imageFolderEffect.h
+// karmaMapper
+//
+// Created by Daan de Lange on 12/3/14.
+//
+//
+
+#pragma once
+
+#include "ofMain.h"
+#include "basicEffect.h"
+#include "ofGLProgrammableRenderer.h"
+
+class imageFolderEffect : public basicEffect {
+
+public:
+ imageFolderEffect();
+ ~imageFolderEffect();
+
+ // global effect functions
+ virtual bool initialise();
+ virtual bool render();
+ virtual void update();
+ virtual void reset();
+
+ bool setFolder(string _dir);
+ bool loadRandomImage();
+ bool loadImage(int imageID);
+ bool loadImage(string imageName);
+
+ bool grabSomeShapes();
+
+
+protected:
+
+ // video stuff
+ vector imageFiles;
+ vector cachedImages;
+ ofShader imageShader;
+ string folder;
+ int currentImage;
+ unsigned int timePerSlide;
+
+private:
+
+};
diff --git a/src/effects/imageGrainEffect_bckup.zip b/src/effects/imageGrainEffect_bckup.zip
new file mode 100644
index 0000000..fe66f40
Binary files /dev/null and b/src/effects/imageGrainEffect_bckup.zip differ
diff --git a/src/effects/lineEffect.cpp b/src/effects/lineEffect.cpp
index 681db34..8152454 100644
--- a/src/effects/lineEffect.cpp
+++ b/src/effects/lineEffect.cpp
@@ -13,7 +13,8 @@
#include "lineEffect.h"
lineEffect::lineEffect(){
- basicEffect::basicEffect();
+ //basicEffect::basicEffect();
+ ofScopedLock lock(effectMutex);
// effectType must match the class name
effectType = "lineEffect";
@@ -23,41 +24,116 @@ lineEffect::lineEffect(){
lines.push_back( getRandomLine() );
}*/
-
+
+ fromShape=NULL;
+ toShape=NULL;
+
+ lines.clear();
+ tempoCalls=0;
}
lineEffect::~lineEffect(){
-
- ofRemoveListener(ofx::AbletonLiveSet::EventHandler::noteEvent, this, &lineEffect::noteEventListener);
+ ofRemoveListener(durationReceiver::durationFloatEvent, this, &lineEffect::floatListener);
+ //ofRemoveListener(ofx::AbletonLiveSet::EventHandler::noteEvent, this, &lineEffect::noteEventListener);
ofRemoveListener(mirReceiver::mirTempoEvent, this, &lineEffect::tempoEventListener);
+ ofRemoveListener(mirReceiver::mirOnSetEvent, this, &lineEffect::onSetEventListener);
}
bool lineEffect::initialise(){
basicEffect::initialise();
+ // tmp
+ ofAddListener(durationReceiver::durationFloatEvent, this, &lineEffect::floatListener);
ofAddListener(mirReceiver::mirTempoEvent, this, &lineEffect::tempoEventListener);
+ ofAddListener(mirReceiver::mirOnSetEvent, this, &lineEffect::onSetEventListener);
+ //ofAddListener(ofx::AbletonLiveSet::EventHandler::noteEvent, this, &lineEffect::noteEventListener);
+
+
+ // todo: this could be set to the basicShape::getBoundingBox() size for better performance
+ // tmp
+ //renderer.allocate( ofGetCurrentRenderer()->getViewportWidth(), ofGetCurrentRenderer()->getViewportHeight(), GL_RGBA, 8); // lower this to get better FPS
+ renderer.allocate( 1500, 1200, GL_RGBA, 8);
+ renderer.begin();
+ ofClear(0,0,0,0); // fill with total invisibility! >D
+ //ofEnableSmoothing(); // enables smooth lines (makes no difference)
+ renderer.end();
- ofAddListener(ofx::AbletonLiveSet::EventHandler::noteEvent, this, &lineEffect::noteEventListener);
+ isInitialised = renderer.isAllocated();
- return true;
+ return isInitialised;
}
// update --> animation
// overrule this function with your own
bool lineEffect::render(){
- if( shapes.size()==0 ) return false;
+ effectMutex.lock();
+
+ ofFill();
+ //basicEffect::render();
+
+ if( shapes.size()==0 ){
+ effectMutex.unlock();
+ return false;
+ }
+ effectMutex.unlock();
+
+ // partial frame buffering
+ if(renderer.isAllocated()){
+ renderer.begin();
+
+ // tmp (to re-enable)
+ // fade FBO alpha over time
+ //ofEnableAlphaBlending(); // tmp
+ glEnable(GL_BLEND);
+ glBlendEquation(GL_FUNC_SUBTRACT);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+ ofSetColor(0,0,0,50); // */
+
+ //ofEnableBlendMode(OF_BLENDMODE_MULTIPLY);
+ //ofSetColor(0,0,0, (mirReceiver::mirCache.pitch/1024+2)*255-2); // multiplies current buffer color by this one
+ ofFill();
+ ofDrawRectangle(0,0,renderer.getWidth(), renderer.getHeight());
+ ofDisableBlendMode(); // resets blending modes manually enabled above
+ }
+ effectMutex.lock();
+ ofSetColor(255);
for(std::list::iterator it=lines.begin(); it!= lines.end(); ++it){
(*it).render();
}
+ effectMutex.unlock();
+
+ if(renderer.isAllocated()){
+ renderer.end();
+ renderer.draw(0,0);
+ }
}
void lineEffect::update(){
+ basicEffect::update();
+
+ ofScopedLock lock(effectMutex);
if(!isReady()) return;
- // you can chose to do the default behaviour too or not by commenting this out
- basicEffect::update();
+ // initial shape setup. Dirty to do it here. // todo
+ if(fromShape==NULL) fromShape = shapes[ round( ofRandom(-0.49f, shapes.size()-0.51f) )];
+ if(toShape==NULL) toShape = shapes[ round( ofRandom(-0.49f, -0.51f+shapes.size()) )];
+
+ // tmp
+ /*if(lines.size()==0){
+ basicShape* current;
+ basicShape* prev=shapes[ round( ofRandom(-0.49f, shapes.size()-0.51f) )];
+ for(int i=0; i::reverse_iterator it=lines.rbegin(); it!= lines.rend(); it--){
- lineEffectLine bla = *it;
+ //lineEffectLine bla = *it;
// replace dead one with new one
if( !(*it).isAlive() ) {
@@ -83,7 +159,14 @@ void lineEffect::reset(){
// do everything the basicEffect does
basicEffect::reset();
+ ofScopedLock lock(effectMutex);
+ totalLinesNb = 0;
+ intensity = 0;
+
// do other stuff
+
+ // tmp
+ // lines.clear(); // also properly delete each line ?
}
/*bool lineEffect::grabSomeShapes(){
@@ -113,6 +196,7 @@ void lineEffect::reset(){
}*/
// returns a line from 1 shape vertex to another
+// note: when you call this function, mutex must be locked
lineEffectLine lineEffect::getRandomLine( const bool onSameShape){
basicShape* fromShape = shapes[ round( ofRandom(-0.49f, shapes.size()-0.51f) )];
@@ -120,31 +204,88 @@ lineEffectLine lineEffect::getRandomLine( const bool onSameShape){
if( onSameShape ) toShape = fromShape;
else toShape = shapes[ round( ofRandom(-0.49f, shapes.size()-0.51f) )];
+ return getRandomLine(fromShape, toShape);
+
+}
+
+// returns a line from 1 shape vertex to another
+// note: when you call this function, mutex must be locked
+lineEffectLine lineEffect::getRandomLine(basicShape *_sh1, basicShape *_sh2) {
+
ofVec2f* from;
ofVec2f* to;
- if( !fromShape->isReady() || !toShape->isReady() ){
+ if( !_sh1->isReady() || !_sh2->isReady() ){
from = &basicShape::zeroPoint;
to = &basicShape::zeroPoint;
}
- else if( fromShape->isType("vertexShape") ){
- from = ((vertexShape*) fromShape)->getRandomVertexPtr();
- to = ((vertexShape*) toShape)->getRandomVertexPtr();
+ else if( _sh1->isType("vertexShape") ){
+ from = ((vertexShape*) _sh1)->getRandomVertexPtr();
+ to = ((vertexShape*) _sh2)->getRandomVertexPtr();
+ while( _sh1!=_sh2 && from==to ){
+ to = ((vertexShape*) _sh2)->getRandomVertexPtr();
+ }
}
else {
- from = fromShape->getPositionPtr();
- to = toShape->getPositionPtr();
+ from = _sh1->getPositionPtr();
+ to = _sh2->getPositionPtr();
}
return lineEffectLine( from, to );
}
+void lineEffect::floatListener(durationFloatEventArgs &_args){
+ if( _args.track.compare("lineEffectIntensity")!=0 ) return;
+
+ ofScopedLock lock(effectMutex);
+ intensity = _args.value;
+ //lines.push_back();
+}
+
void lineEffect::noteEventListener(ofx::AbletonLiveSet::LSNoteEvent ¬eEvent){
- ofScopedLock lock(lineEffectMutex);
+ ofScopedLock lock(effectMutex);
//lines.push_back();
}
void lineEffect::tempoEventListener(mirTempoEventArgs &_args){
- ofScopedLock lock(lineEffectMutex);
- for(int i=0; i 22){
+ fromShape = toShape;
+ toShape = shapes[ round( ofRandom(-0.49f, -0.51f+shapes.size()) )];
+ cout << "tempoChange" << endl;
+ }
+ for(int i=0; i > shapeGroups; // >
+ lineEffectLine getRandomLine(basicShape* _sh1, basicShape* _sh2);
+ //map > shapeGroups; // >
list lines;
+ int tempoCalls;
- ofMutex lineEffectMutex;
+ //ofMutex lineEffectMutex;
+ ofFbo renderer;
-private:
+ //void clearWithTransparency(float transparency);
+
+ basicShape* fromShape;
+ basicShape* toShape;
+private:
+ float intensity;
+ int totalLinesNb = 0;
};
diff --git a/src/effects/lineEffectLine.cpp b/src/effects/lineEffectLine.cpp
index 99e160a..39822cf 100644
--- a/src/effects/lineEffectLine.cpp
+++ b/src/effects/lineEffectLine.cpp
@@ -43,6 +43,7 @@ void lineEffectLine::render(){
if(aliveSince>LEL_LIFE_SPAN) bAlive = false;
+ // tmp
else render( aliveSince/LEL_LIFE_SPAN );
}
@@ -68,4 +69,4 @@ void lineEffectLine::render(float state) {
bool lineEffectLine::isAlive() const{
return bAlive;
-}
+}
\ No newline at end of file
diff --git a/src/effects/meshRenderer3D.cpp b/src/effects/meshRenderer3D.cpp
new file mode 100644
index 0000000..9cf6039
--- /dev/null
+++ b/src/effects/meshRenderer3D.cpp
@@ -0,0 +1,203 @@
+//
+// MeshRenderer3D.cpp
+// karmaMapper
+//
+// Created by Daan de Lange on 12/3/14.
+//
+// - - - -
+//
+// Bla bla bla
+//
+
+#include "MeshRenderer3D.h"
+
+MeshRenderer3D::MeshRenderer3D(){
+ basicEffect::basicEffect();
+
+ // effectType must match the class name
+ effectType = "MeshRenderer3D";
+
+ hasError = !grabShape();
+
+ ofAddListener(ofx::AbletonLiveSet::EventHandler::noteEvent, this, &MeshRenderer3D::noteEventListener);
+
+ // tmp
+ hasError = hasError ? true : !loadModel("effects/meshRenderer3D/palm_tree.dae");
+}
+
+MeshRenderer3D::~MeshRenderer3D(){
+ basicEffect::~basicEffect();
+
+ ofRemoveListener(ofx::AbletonLiveSet::EventHandler::noteEvent, this, &MeshRenderer3D::noteEventListener);
+}
+
+// update --> animation
+// overrule this function with your own
+bool MeshRenderer3D::render(){
+ if( shapes.size()==0 || !isReady() ) return;
+
+ // setup 3D drawing environment
+ //ofEnableAntiAliasing();
+ //ofEnableBlendMode(OF_BLENDMODE_ALPHA);
+ //ofEnableAlphaBlending();
+ ofEnableDepthTest();
+ glShadeModel(GL_SMOOTH); //some model / light stuff
+
+ ofSetSmoothLighting(true);
+
+ ofEnableLighting();
+ light.enable();
+ //ofEnableSeparateSpecularLight();
+ ofSetColor(255);
+ ofFill();
+
+ //glEnable(GL_COLOR_MATERIAL); // call after ofEnableLighting || light.enable();
+
+ // rendomize colors
+ vector myColors;
+ for(int i=0; i::iterator it=shapes.begin(); it!=shapes.end(); it++, i++){
+ //(*it)->render();
+
+ ofPushMatrix();
+ ofTranslate( *(*it)->getPositionPtr() );
+
+ ofVec3f meshOffset = min+meshSize/2;
+
+ //ofSetColor(255,0,0,190);
+ //ofDrawRectangle(-2,-2,-.00001f, 4,4);
+
+ ofRotateY(angle);
+
+ ofScale( modelScale[i], -modelScale[i], modelScale[i] );
+ ofTranslate( -meshOffset.x, -meshOffset.y, 0 );
+
+ //ofSetColor(0,255,0,90);
+ //ofDrawRectangle(min, meshSize.x, meshSize.y);
+
+ mesh.draw( OF_MESH_FILL );
+
+ ofPopMatrix();
+ }
+
+ angle += 0.7f;
+
+ //ofDisableSeparateSpecularLight();
+ light.disable();
+ ofDisableLighting();
+ ofDisableDepthTest();
+ //ofDisableAlphaBlending();
+ //ofDisableBlendMode();
+ //ofDisableAntiAliasing();
+
+}
+
+void MeshRenderer3D::update(){
+ // you can chose to do the default behaviour too or not by commenting this out
+ basicEffect::update();
+
+}
+
+// resets all values
+// overrule this function with your own.
+void MeshRenderer3D::reset(){
+ basicEffect::reset();
+}
+
+bool MeshRenderer3D::grabShape(){
+ // clear
+ shapes.clear();
+ shapes.resize(0);
+
+ // we just want all vertex shapes
+ //shapes = shapesHandler::getInstance().getShapesByType("vertexShape");
+
+ // and look for a shapeType id
+ for(vector::reverse_iterator it=shapes.rbegin(); it!=shapes.rend(); it++){
+
+ if( (*it)->getGroupID() != 2 && (*it)->getGroupID() != 1 && (*it)->getGroupID() != 4 ){
+ it = vector::reverse_iterator( shapes.erase( it.base() - 1) );
+ it--;
+ }
+ }
+
+ return shapes.size() > 0;
+}
+
+bool MeshRenderer3D::loadModel(string file){
+ ofxAssimpModelLoader model;
+ mesh.clear();
+
+ if( model.loadModel( file ) && model.hasMeshes() ){
+
+ // calc boundary
+ //model.calculateDimensions();
+ //min= model.getSceneMin();
+ //max= model.getSceneMax();
+ //meshContainer.set( min.+abs(max) );
+
+ // grab biggest mesh from 3D file
+ int biggestMesh = -1;
+ for(int i=0; i biggestMesh) mesh = tmp;
+
+ }
+
+ // calc mesh boundingbox
+ // todo: what if mesh is below origin ?
+ min.set(0,0,0);
+ max.set(0,0,0);
+ for(int i=0; i v->x) min.x = v->x;
+ else if (max.x < v->x) max.x = v->x;
+ if(min.y > v->y) min.y = v->y;
+ else if (max.y < v->y) max.y = v->y;
+ if(min.z > v->z) min.z = v->z;
+ else if (max.z < v->z) max.z = v->z;
+ }
+ meshSize.set( abs(min.x-max.x), abs(min.y-max.y), abs(min.z-max.z) );
+
+ // rendomize colors
+ vector myColors;
+ for(int i=0; igetBoundingBox().width/meshSize.x;
+ float scaleY = shapes[i]->getBoundingBox().height/meshSize.y;
+ modelScale.push_back( scaleX modelScale;
+
+private:
+
+};
diff --git a/src/effects/videoEffect.cpp b/src/effects/videoEffect.cpp
new file mode 100644
index 0000000..2659786
--- /dev/null
+++ b/src/effects/videoEffect.cpp
@@ -0,0 +1,221 @@
+//
+// videoEffect.cpp
+// karmaMapper
+//
+// Created by Daan de Lange on 12/3/14.
+//
+// - - - -
+//
+// Parent class for all effects.
+// Implements some standard methods for overall usage.
+//
+
+#include "videoEffect.h"
+
+videoEffect::videoEffect(){
+
+ // effect type mutch match with class
+ effectType = "videoEffect";
+}
+
+videoEffect::~videoEffect(){
+ //basicEffect::~basicEffect();
+
+ stream.close();
+}
+
+bool videoEffect::initialise(){
+ bool success = basicEffect::initialise();
+
+ if(success){
+ effectMutex.lock();
+ isLoading = true;
+
+ // load movie
+ hasError = stream.load("vendome_daan_v1.0/Montage_Export_v1_SD.mov");
+ stream.play();
+ //cachedImage.allocate(1,1, GL_RGB);
+
+ // setup shader
+ if(ofIsGLProgrammableRenderer()) hasError *= imageShader.load("effects/imageEffect/imageShaderGL3");
+ else hasError *= imageShader.load("effects/imageEffect/imageShader");
+
+ if(hasError) isInitialised=false;
+
+ isLoading = false;
+
+ effectMutex.unlock();
+ }
+
+ return isInitialised;
+}
+
+
+
+bool videoEffect::render(){
+ effectMutex.lock();
+ if( shapes.size()==0 ){
+ effectMutex.unlock();
+ return true;
+ }
+
+ /*/ image to display ?
+ if( currentImage >=0 && currentImage < cachedImages.size() && cachedImage.isUsingTexture() ){
+ cachedImage.draw( shapes[0]->getBoundingBox() );
+ }// */
+
+ // show image on all available zones
+ for (vector::iterator it=shapes.begin(); it != shapes.end(); it++ ) {
+ if( (*it)->isReady() && imageShader.isLoaded() ){
+ //return true;
+ //cachedImage.draw( it[0]->getBoundingBox() );
+ //it[0]->hasError?ofSetColor(255):ofSetColor(255,0,0);
+ //ofDisableArbTex();
+ //ofEnableTextureEdgeHack();
+
+ //ofTexture &tex0 = cachedImage.getTexture();
+
+ imageShader.begin();
+
+ hasError?ofSetColor(255):ofSetColor(255,0,0);
+ ofFill();
+
+ //tex0.setTextureWrap(GL_MIRRORED_REPEAT, GL_MIRRORED_REPEAT);
+
+ //imageShader.setUniform2f("tex0Resolution", tex0.getWidth(), tex0.getHeight());
+
+ //cachedImage.getTexture().disableTextureMatrix();
+
+ imageShader.setUniform1i("fitMode", 1);
+ imageShader.setUniform2f("tex0Resolution", stream.getTexture().getWidth(), stream.getTexture().getHeight());
+ // todo: use position pointer unstead of boundingBox ?
+ ofRectangle bbox=(*it)->getBoundingBox();
+ imageShader.setUniform4f("shapeBoundingBox", bbox.x, bbox.y, bbox.getWidth(), bbox.getHeight());
+ //bbox=
+ //imageShader.setUniform4f("shapesBoundingBox", bbox.x, bbox.y, bbox.width, bbox.height);
+ imageShader.setUniform2f("fboCanvas", ofGetWidth(),ofGetHeight());
+
+ //imageShader.setUniformTexture("tex0", cachedImage.getTexture(), 1);
+
+ //cachedImage.getTexture().setTextureWrap(GL_REPEAT, GL_REPEAT);
+ stream.getTexture().setTextureWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
+ //cachedImage.getTexture().setTextureWrap(GL_REPEAT, GL_REPEAT);
+ stream.getTexture().bind();
+ (*it)->render();
+ stream.getTexture().unbind();
+
+ imageShader.end();
+ }
+ }
+ effectMutex.unlock();
+}//*/
+
+void videoEffect::update(){
+ imageEffect::update();
+
+ stream.update();
+ cachedImage = stream.getTexture();
+}
+
+// resets all values
+// overrule this function with your own.
+void videoEffect::reset(){
+ basicEffect::reset();
+
+
+ stream.setLoopState(OF_LOOP_NORMAL);
+
+}
+
+/*
+bool videoEffect::setDirectory(string _dir){
+ // already set ?
+ if(_dir==directory) return true;
+
+ ofDirectory dir(_dir);
+
+
+ if( !dir.exists() || !dir.canRead() ){
+ ofLogNotice("videoEffect") << "Unable to load " << _dir << endl;
+ return false;
+ }
+ else{
+ // default video path
+ //if(directory=="") directory="./videoEffect/videos/";
+
+ // scan for video files
+ //ofDirectory dir(_dir);
+ //dir.open(_dir);
+ //dir.listDir( _dir );
+ dir.allowExt("mp4");
+ dir.allowExt("mov");
+ dir.sort();
+ dir.listDir(_dir);
+
+
+ // todo: change to logverbose
+ if(dir.size()==0){
+ if(!dir.exists()){
+ ofLogNotice("videoEffect") << "Folder «" << _dir << "» doesn't exist." << endl;
+ }
+ else if(!dir.canRead()){
+ ofLogNotice("videoEffect") << "Folder «" << _dir << "» is not readable." << endl;
+ }
+ else if(!dir.isDirectory()){
+ ofLogNotice("videoEffect") << "Folder «" << _dir << "» is not a directory." << endl;
+ }
+ else ofLogNotice("videoEffect") << "Folder «" << _dir << "» contains no movies to load. Make sure that there are .mov or .mp4 files." << endl;
+ }
+ else ofLogVerbose("videoEffect") << "Scanning «" << _dir << "» ... Found " << ofToString(dir.size()) << " file(s) (.mp4 or .mov) [readable=" << dir.canRead() << "] [isDirectory=" << ofToString(dir.isDirectory()) << "]" << endl;
+
+ // get videos
+ videoFiles.resize(0);
+ for(int i=0; i videoFiles;
+ //string directory;
+ ofVideoPlayer stream;
+ bool isPlaying();
+ //ofShader shader;
+ //float textureScale;
+
+private:
+
+};
diff --git a/src/effects/videoEffectOld.cpp b/src/effects/videoEffectOld.cpp
new file mode 100644
index 0000000..4437161
--- /dev/null
+++ b/src/effects/videoEffectOld.cpp
@@ -0,0 +1,171 @@
+//
+// videoEffect.cpp
+// karmaMapper
+//
+// Created by Daan de Lange on 12/3/14.
+//
+// - - - -
+//
+// Parent class for all effects.
+// Implements some standard methods for overall usage.
+//
+
+#include "videoEffect.h"
+
+videoEffect::videoEffect(){
+ basicEffect::basicEffect();
+
+ // effect type mutch match with class
+ effectType = "videoEffect";
+
+ hasError = shader.load("effects/videoEffect/videoShader");
+}
+
+videoEffect::~videoEffect(){
+ basicEffect::~basicEffect();
+}
+
+// update --> animation
+// overrule this function with your own.
+bool videoEffect::render(){
+ if( shapes.size()==0 || !stream.isLoaded() ) return;
+
+ // load shader
+ shader.begin();
+ shader.setUniformTexture("tex0", stream.getTextureReference(), 0);//stream.getTextureReference().texData.textureID );
+ shader.setUniform2f("resolution", shapes[0]->getBoundingBox().width, shapes[0]->getBoundingBox().height);
+ shader.setUniform2f("textureResolution", stream.getTextureReference().getWidth() , stream.getTextureReference().getHeight() );
+ shader.setUniform2f("shapeCenterOffset", shapes[0]->getBoundingBox().getCenter().x, shapes[0]->getBoundingBox().getCenter().y);
+ shader.setUniform1f("textureScale", textureScale);
+
+ // draw shape so GPU gets their vertex data
+ shapes[0]->render();
+
+ // flush the pipeline! :D
+ shader.end();
+
+ //stream.getTextureReference().draw(0,0);
+}
+
+void videoEffect::update(){
+ basicEffect::update();
+
+ stream.update();
+
+ // tmp
+ if( ofGetKeyPressed('r') ){
+ shader.load("./videoEffect/videoShader");
+ cout << "Shader reloaded"<= videoFiles.size() ) return false;
+ string tmp = ofToString(directory+"/"+videoFiles[videoID]);
+ if( stream.loadMovie( tmp ) ){
+ stream.play();
+ stream.setVolume(0);
+ hasError = false;
+ ofLogVerbose("videoEffect") << "Successfully loaded movie: " << videoFiles[videoID] << endl;
+ return true;
+ }
+ else{
+ ofLogNotice("videoEffect") << "Could not load "+ directory+"/"+videoFiles[videoID] << endl;;
+ hasError = true;
+ return false;
+ }
+}
+
+bool videoEffect::loadVideo(string videoName){
+ int found = -1;
+
+ // find videoID by string
+ for(int i=0; i videoFiles;
+ string directory;
+ ofVideoPlayer stream;
+ ofShader shader;
+ float textureScale;
+
+private:
+
+};
diff --git a/src/effects/videoStreamEffect.cpp b/src/effects/videoStreamEffect.cpp
new file mode 100644
index 0000000..4eff6a7
--- /dev/null
+++ b/src/effects/videoStreamEffect.cpp
@@ -0,0 +1,140 @@
+//
+// videoStreamEffect.cpp
+// karmaMapper
+//
+// Created by Daan de Lange on 12/3/14.
+//
+// - - - -
+//
+// Bla bla bla
+//
+
+#include "videoStreamEffect.h"
+
+videoStreamEffect::videoStreamEffect(){
+ basicEffect::basicEffect();
+
+ // effectType must match the class name
+ effectType = "videoStreamEffect";
+
+}
+
+videoStreamEffect::~videoStreamEffect(){
+ basicEffect::~basicEffect();
+
+ ofRemoveListener(ofx::AbletonLiveSet::EventHandler::noteEvent, this, &videoStreamEffect::noteEventListener);
+}
+
+// update --> animation
+// overrule this function with your own
+bool videoStreamEffect::render(){
+ if( shapes.size()==0 || currentStream < 0 ) return;
+
+
+ ofSetColor(255);
+ ofFill();
+
+ ofTexture texture = grabber.getTexture();
+
+ int i=0;
+ for(vector::iterator it=shapes.begin(); it!=shapes.end(); it++, i++){
+ //(*it)->render();
+
+ ofPushMatrix();
+ ofTranslate( *(*it)->getPositionPtr() );
+
+ // calc scale
+ bool coverMode = true;
+ ofRectangle s = (*it)->getBoundingBox();
+ float scaleH = s.height/grabber.getHeight();
+ float scaleW = s.width/grabber.width;
+ float scale = 1.f;
+
+ ofVec2f offset(0);
+ if(!coverMode){
+ if(scaleH > scaleW) scale = scaleW;
+ else scale = scaleH;
+ }
+ else{
+ if(scaleW > scaleH){
+ scale = scaleW;
+ offset.y = (s.height-grabber.height)/2;
+ }
+ else{
+ scale = scaleH;
+ offset.y = (s.width-grabber.width)/2;
+ }
+ }
+
+ ofScale(scale, scale);
+ // draw
+ //ofDrawRectangle(-grabber.width/2+offset.x,-grabber.height/2, grabber.width-offset.x, grabber.height);
+ //grabber.draw(-grabber.width/2,-grabber.height/2, grabber.width, grabber.height);
+ texture.drawSubsection( -s.getWidth()/2, -s.getHeight()/2, s.getWidth(), s.getHeight(), offset.x, offset.y );
+
+
+ ofPopMatrix();
+ }
+
+}
+
+void videoStreamEffect::update(){
+ // you can chose to do the default behaviour too or not by commenting this out
+ basicEffect::update();
+
+ if( currentStream >= 0 ) grabber.update();
+}
+
+// resets all values
+// overrule this function with your own.
+void videoStreamEffect::reset(){
+ basicEffect::reset();
+}
+
+bool videoStreamEffect::grabShape(){
+ // clear
+ shapes.clear();
+ shapes.resize(0);
+
+ // we just want all vertex shapes
+ //shapes = shapesHandler::getInstance().getShapesByType("vertexShape");
+ return true;
+ // and look for a shapeType id
+ for(vector::reverse_iterator it=shapes.rbegin(); it!=shapes.rend(); it++){
+
+ if( (*it)->getGroupID() != 2 ){
+ it = vector::reverse_iterator( shapes.erase( it.base() - 1) );
+ it--;
+ }
+ }
+
+ return shapes.size() > 0;
+}
+
+bool videoStreamEffect::grabStream(){
+
+ //we can now get back a list of devices.
+ vector devices = grabber.listDevices();
+
+ for(int i = 0; i < devices.size(); i++){
+ cout << devices[i].id << ": " << devices[i].deviceName;
+ if( devices[i].bAvailable ){
+ cout << endl;
+ }else{
+ cout << " - unavailable " << endl;
+ }
+ }
+
+ grabber.setDeviceID(0);
+ grabber.setDesiredFrameRate(60);
+ currentStream = grabber.setup(640,460) ? 0 : -1;
+
+ //videoInverted.allocate(camWidth,camHeight,OF_PIXELS_RGB);
+ //videoTexture.allocate(videoInverted);
+ //ofSetVerticalSync(true);
+}
+
+void videoStreamEffect::noteEventListener(ofx::AbletonLiveSet::LSNoteEvent ¬eEvent){
+ cout << "ok!" << endl;
+}
+
diff --git a/src/effects/videoStreamEffect.h b/src/effects/videoStreamEffect.h
new file mode 100644
index 0000000..62277db
--- /dev/null
+++ b/src/effects/videoStreamEffect.h
@@ -0,0 +1,38 @@
+//
+// videoStreamEffect.h
+// karmaMapper
+//
+// Created by Daan de Lange on 12/3/14.
+//
+//
+
+#pragma once
+
+#include "ofMain.h"
+#include "basicEffect.h"
+#include "ofxAbletonLiveSet.h"
+
+class videoStreamEffect : public basicEffect {
+
+public:
+ videoStreamEffect();
+ ~videoStreamEffect();
+
+ virtual void spawn();
+ virtual bool render();
+ virtual void update();
+ virtual void reset();
+
+ bool grabShape();
+ bool grabStream();
+
+ void noteEventListener(ofx::AbletonLiveSet::LSNoteEvent & noteEvent);
+
+
+protected:
+ ofVideoGrabber grabber;
+ int currentStream = -1;
+
+private:
+
+};
diff --git a/src/main.cpp b/src/main.cpp
index ea0c5f6..ad9a7a4 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,11 +1,28 @@
#include "ofMain.h"
#include "ofApp.h"
//#include "ofAppGlutWindow.h"
+#ifdef TARGET_OPENGLES
+#include "ofGLProgrammableRenderer.h"
+#endif
+
#define KARMAMAPPER_DEBUG true
//========================================================================
int main( ){
- ofSetupOpenGL(700, 700, OF_WINDOW); // <-------- setup the GL context
+ // Useful for debugging shaders and other inner-OF things
+ //ofSetLogLevel(OF_LOG_VERBOSE);
+
+ #ifdef TARGET_OPENGLES
+ ofSetCurrentRenderer(ofGLProgrammableRenderer::TYPE);
+ ofSetupOpenGL(700, 700, OF_WINDOW);// <-------- setup the GL context
+
+ #else
+ ofGLWindowSettings s;
+ s.setGLVersion(3,3);
+ //s.setGLVersion(4,3);
+ ofCreateWindow(s);
+ #endif
+
//ofAppGlutWindow window;
//window.setGlutDisplayString("rgba double depth alpha samples>=4");
//ofSetupOpenGL(&window, 1500,1200,OF_WINDOW); // <-------- setup the GL context
diff --git a/src/ofApp.cpp b/src/ofApp.cpp
index a30e000..ccb40e6 100644
--- a/src/ofApp.cpp
+++ b/src/ofApp.cpp
@@ -23,63 +23,42 @@ void ofApp::setup(){
editor=new shapesEditor(server);
editor->enableEditMode();
- // load image
- //background.load("vendome_de_face.jpg");
- background.load("vendome_full.jpg");
-
- // prepare to record
- recordOutput = false;
- if(recordOutput){
- recorder.allocate((float)background.width, (float)background.height, GL_RGBA);
- }
- else if(recordOutputBis){
- recorder.allocate((float)background.width, (float)background.height, GL_RGBA);
-
- //saver.setCodecType(0); // Animation Codec
- //saver.setCodecQualityLevel(OF_QT_SAVER_CODEC_QUALITY_NORMAL);
- //saver.setup(ofGetWidth(), ofGetHeight(), "recording-" + ofToString(ofGetUnixTime()) + ".mov");
- }
- else {
- //background.resize(background.width*((float)ofGetHeight()/background.height), ofGetHeight());
- }
-
// - - - - - - - - -
// EFFECTS INITIALISATION
// - - - - - - - - -
- //sound.loadSound("TEST MIX V0.1.wav");
- // start liveset decoder
+
+ // start Ableton Liveset Decoder
ofx::AbletonLiveSet::LiveSet LS;
ofx::AbletonLiveSet::Parser parser(LS);
- //if(!parser.open("mappingvendome.xml")) ofLogNotice("ofApp::setup()", "Could not parse ALS file.");
+ if(!parser.open("vendome_daan_v1.0/mappingvendome.als")) ofLogNotice("ofApp::setup()", "Could not parse ALS file.");
//liveSetEvents.enableMetronomEvents(LS);
- //liveSetEvents.enableNoteEvents(LS);
+ liveSetEvents.enableNoteEvents(LS);
// tmp
ofShowCursor();
mouseHidden = false;
// tmp
- server.loadShapes("Vendome_Full_Small.xml");
+ //server.loadShapes("Vendome_Full_Small.xml");
+ server.loadShapes("Vendome_1500_1200.xml");
// sound analysis setup
// streams to default system sound stream
// then map it to a virtual mic ( soundflower , etc )
//ofSoundStreamListDevices();
- soundStream.setDeviceID(7); // 7 = soundflower 2 ch
- soundStream.setup(this, 0, 2, 44100, 256, 4);
- analyser.start();
-
- // play music
- //music.load("music.wav");
- //music.setLoop(true);
- //music.play();
+ //soundStream.setDeviceID(7); // 7 = soundflower 2 ch
+ //soundStream.setup(this, 0, 2, 44100, 256, 4);
+ //analyser.start();
+ ofSoundStreamStop();
// setup the OSC Router
osc.start();
+
+ // tmp
}
//--------------------------------------------------------------
@@ -96,60 +75,35 @@ void ofApp::update(){
//--------------------------------------------------------------
void ofApp::draw(){
- if(recordOutput){
- recorder.begin();
- //glGenFramebuffersEXT(1, &recorder.getFbo());
- //glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, recorder.getFbo() );
- }
- else if(recordOutputBis){
- recorder.begin();
- }
// render shape editor ?
if( editor->isInEditMode() ){
- ofSetColor(255);
- background.draw(0,0);
+ //ofSetColor(255);
editor->draw();
}
- // tmp, should become backgroundEffect
+
else{
ofSetColor(255);
- background.draw(0,0);
- }
-
- if(recordOutput){
-
- ofPixels pix;
- pix.allocate(1500,1200, GL_RGBA);
- recorder.readToPixels(pix);
- ofSaveImage(pix, "blabla.png", OF_IMAGE_QUALITY_BEST);
-
- //glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
- recorder.end();
-
- recorder.draw(0,0);
- }
-
- if(recordOutputBis){
- //recordingImage.grabScreen(0, 0, ofGetWidth(), ofGetHeight());
- ofPixels pix;
- pix.allocate(1500,1200, GL_RGBA);
- recorder.readToPixels(pix);
- //saver.addFrame(pix);
}
+
}
void ofApp::exit(){
+ if( !editor->isInEditMode() ){
+ controller.stop();
+ }
+
ofSoundStreamStop();
osc.stop();
+ //analyser.stop();
}
//--------------------------------------------------------------
// Soon OF will extend audio possibilities and we'll be able to listen to audio events.
// for the moment we have to do it the dirty way (ofApp shouldn't handle this, karmaSoundAnalyser should)
void ofApp::audioIn(float *input, int bufferSize, int nChannels){
- if(analyser.isEnabled()) analyser.getInstance().audioIn( input, bufferSize, nChannels);
+ //if(analyser.isEnabled()) analyser.getInstance().audioIn( input, bufferSize, nChannels);
}
void ofApp::keyPressed(int key){
diff --git a/src/ofApp.h b/src/ofApp.h
index 84a6d09..f0d4e8c 100644
--- a/src/ofApp.h
+++ b/src/ofApp.h
@@ -40,27 +40,17 @@ class ofApp : public ofBaseApp{
void gotMessage(ofMessage msg);
protected:
- ofImage background;
+
private:
ofx::AbletonLiveSet::EventHandler liveSetEvents;
- ofSoundPlayer music;
shapesServer server;
shapesEditor* editor;// todo: move this to shapesServer ?
animationController controller;
- karmaSoundAnalyser analyser;
- ofSoundStream soundStream;
+ //karmaSoundAnalyser analyser;
+ //ofSoundStream soundStream;
OSCRouter osc;
bool mouseHidden = true;
- // recording
- //ofImage fboHack;
- bool recordOutput = false;
- ofFbo recorder;
- GLuint fbo;
-
- bool recordOutputBis = false;
- //ofImage recordingImage;
- //ofxQtVideoSaver saver;
};
diff --git a/src/shapes/basicShape.cpp b/src/shapes/basicShape.cpp
index 927e4eb..27f7ee0 100644
--- a/src/shapes/basicShape.cpp
+++ b/src/shapes/basicShape.cpp
@@ -9,7 +9,7 @@
#include "basicShape.h"
// static
-int basicShape::maxGroupID = 5;
+int basicShape::maxGroupID = 6;
ofVec2f basicShape::zeroPoint = ofVec2f(0,0);
// - - - - - -
@@ -59,6 +59,7 @@ void basicShape::reset(){
// This function simply uploads data to GPU. basicEffect will set styling
// todo: provide another way for this to allow more complex rendering modes ?
// Maybe effects should be able to render from shapeType.getSpecificShapeData();
+// todo: should also have color & translation arguments
void basicShape::render(){
// synch color if maxGroupID changed
@@ -190,6 +191,7 @@ bool basicShape::loadFromXML(ofxXmlSettings& xml){
// - - - - - - -
// ### GETTERS
bool basicShape::isReady() const{
+ //ofScopedLock()
return initialized && !hasError;
}
@@ -199,7 +201,7 @@ const string& basicShape::getShapeType() const {
ofRectangle basicShape::getBoundingBox() const{
if(!initialized){
- ofLogError("basicShape not yet ready");
+ ofLogError("basicShape not yet ready. This message can lead to memory leaks.");
return ofRectangle();
}
return boundingBox.getStandardized();
diff --git a/src/shapes/vertexShape.cpp b/src/shapes/vertexShape.cpp
index 7a553bc..d261067 100644
--- a/src/shapes/vertexShape.cpp
+++ b/src/shapes/vertexShape.cpp
@@ -78,7 +78,8 @@ void vertexShape::render(){
ofTranslate(position);
// if shape has error, draw it in red
- hasError?ofSetHexColor(0xFF0000):ofSetColor(fgColor);
+ // tmp hasError?ofSetHexColor(0xFF0000):ofSetColor(fgColor);
+ ofSetColor(255,255,255,255);
ofBeginShape();
// draw elements
@@ -296,6 +297,10 @@ list & vertexShape::getPoints(){
return points;
}
+int vertexShape::getNumPoints(){
+ return points.size();
+}
+
/*/ ### SETTERS
bool basicShape::putPoints( list& _points ){ // DEPRECIATED
// restrict this to edit mode
@@ -350,6 +355,8 @@ ofVec2f* vertexShape::getRandomVertexPtr(){
}
ofVec2f* vertexShape::getCenterPtr(){
+ return &position;
+
// todo
return &zeroPoint;
}
diff --git a/src/shapes/vertexShape.h b/src/shapes/vertexShape.h
index 3615001..fb51bb5 100644
--- a/src/shapes/vertexShape.h
+++ b/src/shapes/vertexShape.h
@@ -41,6 +41,7 @@ class vertexShape : public basicShape {
// Utilities
//ofVec2f& getRandomVertex();
list & getPoints();
+ int getNumPoints();
ofVec2f* getRandomVertexPtr();
ofVec2f* getCenterPtr();
// idea: add gravity alterable values: point, averagePosition, etc.
diff --git a/utilities/karmaSoundAnalyser/OSCCleanFloat.pd b/utilities/karmaSoundAnalyser/OSCCleanFloat.pd
new file mode 100644
index 0000000..9244619
--- /dev/null
+++ b/utilities/karmaSoundAnalyser/OSCCleanFloat.pd
@@ -0,0 +1,89 @@
+#N canvas 34 132 545 493 10;
+#X obj 182 243 metro \$1;
+#X obj -28 119 inlet;
+#X obj 182 221 != 0;
+#X obj 192 146 \$1;
+#X obj 218 146 loadbang;
+#X text 213 169 Default Frequency (ms);
+#X obj -49 193 tgl 15 0 empty empty Frequency_Controll_[on/off] 17
+7 0 10 -262144 -1 -1 1 1;
+#X obj -82 119 inlet;
+#X text -149 119 Data input;
+#X obj -49 238 != 1;
+#X floatatom 240 244 5 0 0 1 Raw_input - -;
+#X floatatom 324 314 5 0 0 0 Summed_Values - -;
+#X obj 191 342 + 1;
+#X text 60 441 See also resample \, sendmany-osc.pd and lop;
+#X obj 8 278 ==;
+#X obj -97 338 f;
+#X floatatom -85 364 5 0 0 0 - - -;
+#X obj 8 321 sel 0;
+#X obj -97 389 outlet float;
+#X obj 218 321 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 240 208 spigot;
+#X obj 189 298 i;
+#X floatatom 257 384 5 0 0 0 Num_Values - -;
+#X obj 191 320 i;
+#X obj 164 397 /;
+#X floatatom 164 420 5 0 0 0 Averaged_Value - -;
+#X obj -82 262 spigot;
+#X text -151 23 Cleans data flow for OSC output.;
+#X text -151 38 Unchanged values are not re-sent.;
+#X text 147 23 (Tested only for ints and floats);
+#X text -150 52 Too frequent values are sent less frequent and averaged.
+;
+#X text 11 118 Freq.Cont. [on/off];
+#X obj 182 125 inlet;
+#X text 221 124 Set frequency (ms);
+#X text -150 67 Set frequency with \$1 creation argument or 3rd inlet.
+;
+#X obj 129 136 sel 1;
+#X obj 182 367 i;
+#X obj 218 298 +;
+#X obj 205 268 i 0;
+#X obj 182 169 i 16;
+#X text 216 182 16.6666ms for 60FPS;
+#X text 100 256 Todo: disable metro when flow goes slower ?;
+#X connect 0 0 36 0;
+#X connect 0 0 38 0;
+#X connect 1 0 6 0;
+#X connect 1 0 35 0;
+#X connect 2 0 0 0;
+#X connect 3 0 39 0;
+#X connect 4 0 3 0;
+#X connect 6 0 9 0;
+#X connect 6 0 20 1;
+#X connect 7 0 20 0;
+#X connect 7 0 26 0;
+#X connect 9 0 26 1;
+#X connect 10 0 37 0;
+#X connect 11 0 24 1;
+#X connect 12 0 36 1;
+#X connect 12 0 23 1;
+#X connect 14 0 17 0;
+#X connect 15 0 14 1;
+#X connect 15 0 16 0;
+#X connect 15 0 18 0;
+#X connect 17 0 15 0;
+#X connect 19 0 23 0;
+#X connect 20 0 10 0;
+#X connect 21 0 11 0;
+#X connect 21 0 37 1;
+#X connect 23 0 12 0;
+#X connect 24 0 25 0;
+#X connect 25 0 14 0;
+#X connect 25 0 15 1;
+#X connect 26 0 15 1;
+#X connect 26 0 14 0;
+#X connect 32 0 39 0;
+#X connect 35 0 39 0;
+#X connect 35 1 0 0;
+#X connect 36 0 24 0;
+#X connect 36 0 22 0;
+#X connect 37 0 19 0;
+#X connect 37 0 21 0;
+#X connect 38 0 21 1;
+#X connect 38 0 37 1;
+#X connect 39 0 2 0;
+#X connect 39 0 0 1;
diff --git a/utilities/karmaSoundAnalyser/OSCDumpUtility.pd b/utilities/karmaSoundAnalyser/OSCDumpUtility.pd
index 38059fd..f1ec8be 100644
--- a/utilities/karmaSoundAnalyser/OSCDumpUtility.pd
+++ b/utilities/karmaSoundAnalyser/OSCDumpUtility.pd
@@ -5,14 +5,12 @@
1;
#X obj 67 240 print;
#X text 156 202 Enable / Disable;
-#X msg 137 140 stop;
#X text 65 103 Simple utility for displaying incomming OSC data;
#X obj 67 179 udpreceive 12000 localhost;
-#X msg 41 143 status;
+#X msg 67 141 status;
#X connect 0 0 1 0;
#X connect 1 0 3 0;
#X connect 2 0 1 1;
-#X connect 5 0 7 0;
-#X connect 7 0 0 0;
-#X connect 7 1 1 0;
-#X connect 8 0 7 0;
+#X connect 6 0 0 0;
+#X connect 6 1 1 0;
+#X connect 7 0 6 0;
diff --git a/utilities/karmaSoundAnalyser/README.md b/utilities/karmaSoundAnalyser/README.md
new file mode 100644
index 0000000..9a18695
--- /dev/null
+++ b/utilities/karmaSoundAnalyser/README.md
@@ -0,0 +1,25 @@
+karmaSoundAnalyser
+==================
+
+A Puredata real-time music analysis patch using Lib Aubio and OSC communication.
+_dependency_: Aubio pd plugin (v0.3.3)
+
+![Preview](https://secure-b.vimeocdn.com/ts/461/411/461411483_960.jpg)
+[Click here to watch a demo video](https://vimeo.com/84516862)
+
+Details
+=======
+
+It uses lib Aubio for onset and tempo detection.
+I’ve had difficulties compiling the Pd plugin and I got it working using Pd-Extended compiled in 64 bit with Aubio 0.3.3 also in 64 bit.
+Other features include an alternative onSet detection, pitch detection, silence detection and a 5-band equaliser.
+
+Note: not all collected data is yet set to be forwarded trough OSC.
+
+
+- - - -
+
+Lib Aubio: http://aubio.org/
+Puredata: http://puredata.info/
+Made for a [Karma Kusala](http://karma-kusala.com/) project.
+Preview video: http://vimeo.com/84516862
diff --git a/utilities/karmaSoundAnalyser/karmaSoundAnalyser.pd b/utilities/karmaSoundAnalyser/karmaSoundAnalyser.pd
index aeac1f4..e2535b8 100644
--- a/utilities/karmaSoundAnalyser/karmaSoundAnalyser.pd
+++ b/utilities/karmaSoundAnalyser/karmaSoundAnalyser.pd
@@ -1,14 +1,14 @@
-#N canvas 76 23 1254 676 10;
+#N canvas 72 23 1254 676 10;
#X declare -lib mrpeach;
#X obj 17 272 adc~;
-#X msg 159 516 disconnect;
-#X msg 159 439 typetags 1;
-#X msg 159 463 typetags 0;
+#X msg 159 566 disconnect;
+#X msg 159 489 typetags 1;
+#X msg 159 513 typetags 0;
#X obj -48 152 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
1;
#X obj -63 289 *~;
#X obj -63 337 dac~;
-#X obj 88 434 loadbang;
+#X obj 88 484 loadbang;
#X obj 18 25 bng 15 250 50 0 empty empty empty 0 -6 0 10 -262144 -1
-1;
#X msg 18 63 \; pd dsp 1;
@@ -16,12 +16,12 @@
#X obj -49 27 bng 15 250 50 0 empty empty empty 0 -6 0 10 -262144 -1
-1;
#X text -51 -6 Turn On/Off Pd.DSP;
-#N canvas 71 24 898 653 karmaFiddle 0;
+#N canvas 295 23 898 653 karmaFiddle 0;
#X obj -1170 289 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -8 0
-10 -262144 -1 -1 0 256;
+10 -262144 -1 -1 62.8876 256;
#X obj -1115 319 unpack;
#X obj -1115 354 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -8 0
-10 -262144 -1 -1 56.8971 256;
+10 -262144 -1 -1 0 256;
#X obj -1042 336 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -8 0
10 -262144 -1 -1 0 256;
#X obj -1115 378 route 0;
@@ -34,10 +34,10 @@
#X obj -1042 471 timer;
#X floatatom -1041 502 5 0 0 0 - - -;
#X obj -1041 554 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1
-0 1;
+1 1;
#X text -1185 339 Attack;
#X obj -1114 409 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -8 0
-10 -262144 -1 -1 0 256;
+10 -262144 -1 -1 83.5654 256;
#X text -1173 408 Raw Pitch;
#X text -1043 319 Raw Amplitude;
#X text -1093 107 1024 = FFT window size;
@@ -112,7 +112,7 @@ information.;
#X obj -1087 296 s fiddle_amp;
#X obj -1282 109 inlet on_off_switch;
#X obj -1303 114 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1
-0 1;
+1 1;
#X obj -1300 266 spigot~;
#X obj -1171 231 spigot~;
#X obj -1171 430 s fiddle_raw_pitch;
@@ -142,6 +142,15 @@ information.;
#X obj -1283 393 r fiddler_reset;
#X msg -1188 191 auto \$1;
#X obj -639 522 delay 50;
+#X floatatom -581 62 5 0 0 0 Sending_Freq_(ms) - -;
+#X obj -558 111 loadbang;
+#X obj -558 131 i 1;
+#X obj -605 200 i;
+#X obj -567 201 + 1;
+#X floatatom -605 223 5 0 0 0 - - -;
+#X obj -604 152 OSCCleanFloat 100;
+#X obj -590 177 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
#X connect 0 0 43 0;
#X connect 1 0 2 0;
#X connect 1 1 3 0;
@@ -190,6 +199,7 @@ information.;
#X connect 60 0 61 0;
#X connect 60 1 62 0;
#X connect 61 0 65 0;
+#X connect 61 0 104 0;
#X connect 62 0 66 0;
#X connect 63 0 22 0;
#X connect 63 1 25 0;
@@ -242,157 +252,158 @@ information.;
#X connect 95 0 0 0;
#X connect 96 0 64 0;
#X connect 97 0 82 0;
+#X connect 99 0 100 0;
+#X connect 100 0 104 1;
+#X connect 101 0 103 0;
+#X connect 101 0 102 0;
+#X connect 102 0 101 1;
+#X connect 104 0 105 0;
+#X connect 105 0 101 0;
#X restore 157 289 pd karmaFiddle;
-#X text 89 408 OSC SERVER CONFIGURATION;
-#X text -67 408 OSC ROUTING;
-#X obj 969 133 s osc_output;
-#X obj 969 154 s osc_output;
-#X obj 969 177 s osc_output;
-#X obj 968 222 s osc_output;
-#X obj 968 198 s osc_output;
-#X obj 969 243 s osc_output;
-#X obj 968 267 s osc_output;
-#X obj 968 288 s osc_output;
-#X obj 968 312 s osc_output;
-#X obj 968 333 s osc_output;
-#X floatatom 721 116 5 0 0 0 - - -;
-#X floatatom 720 137 5 0 0 0 - - -;
-#X floatatom 720 160 5 0 0 0 - - -;
-#X floatatom 720 181 5 0 0 0 - - -;
-#X floatatom 719 205 5 0 0 0 - - -;
-#X floatatom 719 226 5 0 0 0 - - -;
-#X floatatom 719 250 5 0 0 0 - - -;
-#X floatatom 719 271 5 0 0 0 - - -;
-#X floatatom 720 295 5 0 0 0 - - -;
-#X floatatom 721 316 5 0 0 0 - - -;
-#X msg 756 205 send /fiddle_fft/band3/pitch \$0;
-#X msg 756 226 send /fiddle_fft/band3/rms \$0;
-#X msg 756 250 send /fiddle_fft/band4/pitch \$0;
-#X msg 756 271 send /fiddle_fft/band4/rms \$0;
-#X msg 756 295 send /fiddle_fft/band5/rms \$0;
-#X msg 756 316 send /fiddle_fft/band5/pitch \$0;
-#X msg 757 160 send /fiddle_fft/band2/rms \$0;
-#X msg 756 181 send /fiddle_fft/band2/pitch \$0;
-#X msg 756 137 send /fiddle_fft/band1/rms \$0;
-#X msg 756 116 send /fiddle_fft/band1/pitch \$0;
-#X obj 669 581 s osc_output;
+#X text 89 458 OSC SERVER CONFIGURATION;
+#X text -67 458 OSC ROUTING;
+#X obj 989 133 s osc_output;
+#X obj 989 154 s osc_output;
+#X obj 989 177 s osc_output;
+#X obj 988 222 s osc_output;
+#X obj 988 198 s osc_output;
+#X obj 989 243 s osc_output;
+#X obj 988 267 s osc_output;
+#X obj 988 288 s osc_output;
+#X obj 988 312 s osc_output;
+#X obj 988 333 s osc_output;
+#X floatatom 741 116 5 0 0 0 - - -;
+#X floatatom 740 137 5 0 0 0 - - -;
+#X floatatom 740 160 5 0 0 0 - - -;
+#X floatatom 740 181 5 0 0 0 - - -;
+#X floatatom 739 205 5 0 0 0 - - -;
+#X floatatom 739 226 5 0 0 0 - - -;
+#X floatatom 739 250 5 0 0 0 - - -;
+#X floatatom 739 271 5 0 0 0 - - -;
+#X floatatom 740 295 5 0 0 0 - - -;
+#X floatatom 741 316 5 0 0 0 - - -;
+#X msg 776 205 send /fiddle_fft/band3/pitch \$0;
+#X msg 776 226 send /fiddle_fft/band3/rms \$0;
+#X msg 776 250 send /fiddle_fft/band4/pitch \$0;
+#X msg 776 271 send /fiddle_fft/band4/rms \$0;
+#X msg 776 295 send /fiddle_fft/band5/rms \$0;
+#X msg 776 316 send /fiddle_fft/band5/pitch \$0;
+#X msg 777 160 send /fiddle_fft/band2/rms \$0;
+#X msg 776 181 send /fiddle_fft/band2/pitch \$0;
+#X msg 776 137 send /fiddle_fft/band1/rms \$0;
+#X msg 776 116 send /fiddle_fft/band1/pitch \$0;
+#X obj 689 581 s osc_output;
#X obj -45 191 hsl 100 15 0 1 0 0 0 ¸áÿ¿» 0 0 0 0 4 -262144 -1
--1 0 0;
-#X obj 669 407 r silence;
-#X obj 669 299 r fft5p;
-#X obj 669 278 r fft5a;
-#X obj 669 254 r fft4p;
-#X obj 669 233 r fft4a;
-#X obj 669 209 r fft3p;
-#X obj 669 188 r fft3a;
-#X obj 669 164 r fft2p;
-#X obj 669 143 r fft2a;
-#X obj 670 120 r fft1p;
-#X obj 670 99 r fft1a;
+-1 1500 0;
+#X obj 689 407 r silence;
+#X obj 689 299 r fft5p;
+#X obj 689 278 r fft5a;
+#X obj 689 254 r fft4p;
+#X obj 689 233 r fft4a;
+#X obj 689 209 r fft3p;
+#X obj 689 188 r fft3a;
+#X obj 689 164 r fft2p;
+#X obj 689 143 r fft2a;
+#X obj 690 120 r fft1p;
+#X obj 690 99 r fft1a;
#X text 296 2 ROUTING;
#X text 297 17 - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - -;
-#X text -68 417 - - - - - - - - - - - - - - - - - - - - - - - - - -
+#X text -68 467 - - - - - - - - - - - - - - - - - - - - - - - - - -
;
#X text 657 17 - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - -;
-#X obj 731 407 r fiddle_pitch;
-#X obj 938 407 r fiddle_attack;
-#X obj 938 494 r fiddle_amp;
-#X obj 238 251 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
+#X obj 751 407 r fiddle_pitch;
+#X obj 958 407 r fiddle_attack;
+#X obj 958 494 r fiddle_amp;
+#X obj 238 251 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 1
1;
#X text 183 249 (on/off);
-#X obj 677 429 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
+#X obj 697 429 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 1
1;
-#X floatatom 737 428 5 0 0 0 - - -;
-#X obj 822 407 r fiddle_raw_pitch;
-#X floatatom 829 428 5 0 0 0 - - -;
-#X floatatom 902 515 5 0 0 0 - - -;
-#X floatatom 899 562 5 0 0 0 - - -;
-#X obj 945 429 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+#X floatatom 757 428 5 0 0 0 - - -;
+#X obj 842 407 r fiddle_raw_pitch;
+#X floatatom 849 428 5 0 0 0 - - -;
+#X floatatom 922 515 5 0 0 0 - - -;
+#X floatatom 919 562 5 0 0 0 - - -;
+#X obj 965 429 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
-1 -1;
-#X obj 1038 429 i;
-#X obj 1069 429 + 1;
-#X floatatom 1003 446 5 0 0 0 - - -;
-#X msg 433 241 send /aubioOnSet;
-#X msg 433 195 send /aubioTempo;
+#X obj 1058 429 i;
+#X obj 1089 429 + 1;
+#X floatatom 1023 446 5 0 0 0 - - -;
+#X msg 434 265 send /aubioOnSet;
+#X msg 434 219 send /aubioTempo;
#X obj 298 109 r aubio_pitch;
#X obj 298 132 r aubio_quiet;
-#X obj 937 542 r fiddle_raw_amp;
-#X msg 731 469 send /fiddlePitch \$0;
+#X obj 957 542 r fiddle_raw_amp;
+#X msg 751 469 send /fiddlePitch \$0;
#X obj 61 318 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 1
1;
#X text 80 317 (on/off);
#X obj 414 149 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 1
1;
-#X obj 297 155 r aubio_tempo_bis;
-#X obj 415 172 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+#X obj 298 179 r aubio_tempo_bis;
+#X obj 416 196 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
-1 -1;
-#X obj 297 201 r aubio_bpm;
-#X floatatom 398 218 5 0 0 0 - - -;
-#X obj 297 178 r aubio_tempo;
-#X obj 415 195 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+#X obj 298 225 r aubio_bpm;
+#X floatatom 399 242 5 0 0 0 - - -;
+#X obj 298 202 r aubio_tempo;
+#X obj 416 219 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
-1 -1;
-#X obj 297 224 r aubio_onset;
-#X obj 415 241 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+#X obj 298 248 r aubio_onset;
+#X obj 416 265 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
-1 -1;
#X floatatom -38 213 5 0 0 0 - - -;
-#X floatatom 397 263 5 0 0 0 - - -;
-#X obj 296 246 r aubio_zcr;
+#X floatatom 398 287 5 0 0 0 - - -;
+#X obj 297 270 r aubio_zcr;
#X text 296 28 All analysed data is routed to OSC messages in this
section;
-#X text 668 77 FIDDLE FFT ROUTING;
-#X text 668 385 FIDDLE :: [pitch \, attack \, silence \, amplitude]
+#X text 688 77 FIDDLE FFT ROUTING;
+#X text 688 385 FIDDLE :: [pitch \, attack \, silence \, amplitude]
ROUTING;
#X text 296 81 :: LIB AUBIO ROUTING ::;
#X text -51 132 SOUND OUTPUT;
#X text -26 172 Volume;
#X text -26 151 On/Off;
#X text 17 251 AUDIO SOURCE;
-#X obj 560 166 s osc_output;
-#X obj 560 189 s osc_output;
-#X obj 559 258 s osc_output;
-#X obj 560 280 s osc_output;
-#X msg 433 172 send /aubioTempoBis;
-#X obj 559 212 s osc_output;
-#X msg 432 263 send /aubioZcr \$1;
+#X obj 583 166 s osc_output;
+#X obj 583 282 s osc_output;
+#X msg 434 196 send /aubioTempoBis;
+#X obj 583 236 s osc_output;
+#X msg 433 287 send /aubioZcr \$1;
#X msg 433 149 send /aubioQuiet \$1;
-#X obj 559 235 s osc_output;
#X msg 433 126 send /aubioPitch \$1;
-#X msg 938 515 send /fiddleAmp \$1;
-#X msg 937 562 send /fiddleRawAmp \$1;
-#X msg 822 448 send /fiddleRawPitch \$1;
-#X msg 669 448 send /fiddleSilence \$1;
-#X msg 433 218 send /aubioBpm/1 \$1;
+#X msg 958 515 send /fiddleAmp \$1;
+#X msg 957 562 send /fiddleRawAmp \$1;
+#X msg 842 448 send /fiddleRawPitch \$1;
+#X msg 689 448 send /fiddleSilence \$1;
#X obj 176 234 loadbang;
-#X obj -67 578 import mrpeach;
-#X msg 88 490 connect localhost 12000;
-#X msg 938 468 send /fiddleAttack;
-#X obj -67 533 sendOSC;
-#X obj -67 555 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 1
+#X obj -67 628 import mrpeach;
+#X msg 88 540 connect localhost 12000;
+#X msg 958 468 send /fiddleAttack;
+#X obj -67 583 sendOSC;
+#X obj -67 605 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 1
1;
-#X obj -67 490 spigot;
-#X text 25 551 Alternatively \, you can use UDPsend;
-#X text 26 567 with packOSC instead of sendOSC;
-#X text -46 554 UDP State;
+#X obj -67 540 spigot;
+#X text 25 601 Alternatively \, you can use UDPsend;
+#X text 26 617 with packOSC instead of sendOSC;
+#X text -46 604 UDP State;
#X text 82 336 LIB AUBIO ANALYSIS;
#X text 116 269 FFT & MORE ANALYSIS;
#X obj 61 295 loadbang;
-#X text 25 582 http://en.flossmanuals.net/pure-data/ch065_osc/;
-#N canvas 276 33 837 622 aubio 0;
-#X obj 106 161 aubioonset~;
-#X obj 106 196 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
--1 -1;
-#X obj 422 164 aubiopitch~;
-#X obj 422 211 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -8 0 10
--262144 -1 -1 289.194 256;
-#X obj 193 197 bng 15 50 10 0 empty empty empty 17 7 0 10 -262144 -1
+#X text 25 632 http://en.flossmanuals.net/pure-data/ch065_osc/;
+#N canvas 178 23 997 667 aubio 0;
+#X obj 41 161 aubioonset~;
+#X obj 41 196 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
-1;
-#X obj 280 198 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
--1 -1;
-#X obj 193 163 aubiotempo~ 0.5;
-#X obj 104 90 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -8 0 10
+#X obj 462 164 aubiopitch~;
+#X obj 462 211 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -8 0 10
-262144 -1 -1 0 256;
+#X obj 130 197 bng 15 50 10 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X obj 217 198 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 130 163 aubiotempo~ 0.5;
#X obj 322 348 i;
#X obj 360 349 + 1;
#X floatatom 322 378 5 0 0 0 - - -;
@@ -407,7 +418,6 @@ ROUTING;
#X floatatom 322 453 5 0 0 0 - - -;
#X floatatom 345 474 5 0 0 0 - - -;
#X floatatom 368 454 5 0 0 0 - - -;
-#X text 13 88 Treshold Param;
#N canvas 837 96 511 413 timer_utility 0;
#X obj 101 28 inlet;
#X obj 101 377 outlet;
@@ -420,7 +430,7 @@ ROUTING;
#X obj 101 206 i;
#X obj 143 207 + 1;
#X obj 101 242 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -8 0 10
--262144 -1 -1 1456 256;
+-262144 -1 -1 860 256;
#X obj 101 322 div 4;
#X obj 101 348 + 1;
#X obj 199 350 + 1;
@@ -465,145 +475,351 @@ ROUTING;
#X text 16 13 Uses lib Aubio to get several MIR information;
#X obj 230 69 inlet~ LeftAudio;
#X obj 351 69 inlet~ RightAudio;
-#X obj 321 164 aubioquiet~;
-#X obj 321 198 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
--1 -1;
-#X obj 517 73 inlet on_off_switch;
+#X obj 291 164 aubioquiet~;
+#X obj 517 69 inlet on_off_switch;
#X obj 285 90 spigot~;
#X obj 351 90 spigot~;
#X obj 345 496 hradio 15 1 0 4 empty empty empty 0 -8 0 10 -262144
-1 -1 0;
#X text 325 321 METRONOM;
#X text 173 318 TEMPO // BPM;
-#X obj 496 75 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 1
+#X obj 496 71 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 1
1;
-#X obj 19 257 s aubio_onset;
-#X obj 123 257 s aubio_tempo;
-#X obj 280 257 s aubio_tempo_bis;
-#X obj 321 230 s aubio_quiet;
-#X obj 422 257 s aubio_pitch;
+#X obj 41 257 s aubio_onset;
+#X obj 130 257 s aubio_tempo;
+#X obj 217 257 s aubio_tempo_bis;
+#X obj 291 230 s aubio_quiet;
+#X obj 462 256 s aubio_pitch;
#X obj 310 503 == 0;
#X obj 345 520 tgl 60 0 empty empty empty 17 7 0 10 -262144 -1 -1 1
1;
#X obj 158 544 s aubio_bpm;
-#X obj 636 164 aubiotss~;
-#X obj 636 219 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
--1 -1 8205 1;
-#X obj 636 188 env~;
-#X obj 687 219 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
--1 -1 8234 1;
-#X obj 687 189 env~;
-#X obj 636 141 hsl 100 15 0 1 0 0 empty empty empty -2 -8 0 10 -262144
+#X obj 716 164 aubiotss~;
+#X obj 716 249 vsl 15 100 0 1 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#X obj 716 188 env~;
+#X obj 767 249 vsl 15 100 0 1 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#X obj 767 189 env~;
+#X obj 716 141 hsl 100 15 0 1 0 0 empty empty empty -2 -8 0 10 -262144
-1 -1 0 0;
-#X floatatom 698 164 5 0 0 0 - - -;
-#X text 633 123 Variation Threshold;
-#X obj 527 166 aubiozcr~;
-#X floatatom 527 204 5 0 0 0 - - -;
-#X obj 527 231 s aubio_zcr;
-#X obj 468 372 i 0;
-#X text 468 289 Reset all values;
-#X obj 475 329 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
--1 -1;
-#X obj 475 349 delay 1000;
+#X floatatom 778 164 5 0 0 0 - - -;
+#X text 713 123 Variation Threshold;
+#X obj 577 166 aubiozcr~;
+#X floatatom 577 228 5 0 0 0 - - -;
+#X obj 577 356 s aubio_zcr;
+#X obj 19 526 i 0;
+#X text 19 443 Reset all values;
+#X obj 26 483 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X obj 26 503 delay 1000;
#X obj 517 101 s aubio-off;
-#X obj 468 306 r aubio-off;
-#X obj 497 389 s aubio_reset;
-#X obj 724 195 r aubio_reset;
-#X obj 431 187 r aubio_reset;
+#X obj 19 460 r aubio-off;
+#X obj 48 543 s aubio_reset;
+#X obj 804 230 r aubio_reset;
+#X obj 471 187 r aubio_reset;
#X obj 196 503 r aubio_reset;
#X obj 406 430 r aubio_reset;
-#X obj 422 230 t f;
+#N canvas 775 308 450 300 clean_signal 0;
+#X obj 51 133 ==;
+#X obj 93 116 f;
+#X floatatom 102 139 5 0 0 0 - - -;
+#X text 24 10 SIGNAL CLEANER;
+#X obj 51 68 inlet float;
+#X obj 51 156 sel 0;
+#X obj 93 163 outlet float;
+#X text 25 24 Prevents resending bangs when the float value has not
+changed. (Sort of flood filter);
+#X connect 0 0 5 0;
+#X connect 1 0 0 1;
+#X connect 1 0 2 0;
+#X connect 1 0 6 0;
+#X connect 4 0 1 1;
+#X connect 4 0 0 0;
+#X connect 5 0 1 0;
+#X restore 462 233 pd clean_signal;
+#X floatatom 577 289 5 0 0 0 - - -;
+#X obj 543 305 -;
+#X obj 543 327 abs;
+#X obj 526 396 sqrt;
+#X obj 577 248 average 10;
+#X text 13 65 Treshold Tempo;
+#X text 14 88 Treshold OnSet;
+#X obj 591 268 r aubio_reset;
+#X floatatom 634 227 5 0 20 2 - - -;
+#X text 584 211 Zcr;
+#X text 613 290 Smoothed;
+#N canvas 960 356 450 300 clean_signal 0;
+#X obj 51 133 ==;
+#X obj 93 116 f;
+#X floatatom 102 139 5 0 0 0 - - -;
+#X text 24 10 SIGNAL CLEANER;
+#X obj 51 68 inlet float;
+#X obj 51 156 sel 0;
+#X obj 93 163 outlet float;
+#X text 25 24 Prevents resending bangs when the float value has not
+changed. (Sort of flood filter);
+#X connect 0 0 5 0;
+#X connect 1 0 0 1;
+#X connect 1 0 2 0;
+#X connect 1 0 6 0;
+#X connect 4 0 1 1;
+#X connect 4 0 0 0;
+#X connect 5 0 1 0;
+#X restore 577 332 pd clean_signal;
+#X obj 560 378 r aubio_reset;
+#X obj 580 400 hsl 100 15 0 1 0 0 empty empty empty -2 -8 0 10 -262144
+-1 -1 0 1;
+#X obj 580 418 hsl 100 15 0 1 0 0 empty empty empty -2 -8 0 10 -262144
+-1 -1 0 1;
+#X obj 496 305 hsl 40 15 -0.1 0.1 0 0 empty empty empty -2 -8 0 10
+-262144 -1 -1 0 1;
+#X floatatom 154 68 5 0 0 0 - - -;
+#X text 629 198 Smoothing;
+#X text 630 209 Treshold;
+#X obj 107 68 hsl 40 15 0 10 0 0 empty empty empty -2 -8 0 10 -262144
+-1 -1 0 1;
+#X floatatom 154 88 5 0 0 0 - - -;
+#X obj 107 89 hsl 40 15 0 15 0 0 empty empty empty -2 -8 0 10 -262144
+-1 -1 0 1;
+#X floatatom 506 324 5 0 0 0 - - -;
+#X text 102 46 PARAMETERS;
+#X text 491 288 Treshold;
+#X obj 716 440 <;
+#X obj 722 414 f 0.005;
+#X obj 767 210 / 127;
+#X obj 716 210 / 127;
+#X obj 722 393 loadbang;
+#X obj 787 251 vsl 15 100 -1 1 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 4950 1;
+#X obj 846 324 -;
+#X obj 577 310 * 5;
+#X obj 478 344 -;
+#X text 575 433 ZeroCross Variation;
+#X obj 529 379 * 2;
+#X obj 497 361 average 3;
+#X text 384 579 comment;
+#X obj 767 440 <;
+#X obj 722 376 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 752 466 == 0;
+#X obj 716 491 &;
+#N canvas 775 308 450 300 clean_signal 0;
+#X obj 51 133 ==;
+#X obj 93 116 f;
+#X floatatom 102 139 5 0 0 0 - - -;
+#X text 24 10 SIGNAL CLEANER;
+#X obj 51 68 inlet float;
+#X obj 51 156 sel 0;
+#X obj 93 163 outlet float;
+#X text 25 24 Prevents resending bangs when the float value has not
+changed. (Sort of flood filter);
+#X connect 0 0 5 0;
+#X connect 1 0 0 1;
+#X connect 1 0 2 0;
+#X connect 1 0 6 0;
+#X connect 4 0 1 1;
+#X connect 4 0 0 0;
+#X connect 5 0 1 0;
+#X restore 716 512 pd clean_signal;
+#X obj 291 209 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 1
+1;
+#X obj 291 188 i 1;
+#X obj 716 535 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
+1;
+#X obj 716 467 == 0;
+#X text 737 533 isPlaying;
+#X obj 716 556 s aubio_is_playing;
+#X obj 320 188 r aubio_is_playing;
+#X obj 343 208 sel 1;
+#X obj 311 209 i 0;
+#X obj 846 347 average 30;
+#X obj 846 370 sqrt;
+#X text 810 277 (~Sound similarity indicator);
+#X text 575 447 (~cymbal detection);
+#X floatatom 623 312 5 0 0 0 - - -;
#X connect 0 0 1 0;
-#X connect 1 0 36 0;
+#X connect 1 0 33 0;
#X connect 2 0 3 0;
-#X connect 3 0 66 0;
-#X connect 4 0 8 0;
-#X connect 4 0 11 0;
-#X connect 4 0 37 0;
-#X connect 5 0 38 0;
+#X connect 3 0 63 0;
+#X connect 4 0 7 0;
+#X connect 4 0 10 0;
+#X connect 4 0 34 0;
+#X connect 5 0 35 0;
#X connect 6 0 4 0;
#X connect 6 1 5 0;
-#X connect 7 0 6 1;
-#X connect 7 0 0 1;
-#X connect 8 0 10 0;
-#X connect 8 0 9 0;
-#X connect 9 0 8 1;
-#X connect 10 0 23 0;
+#X connect 7 0 9 0;
+#X connect 7 0 8 0;
+#X connect 8 0 7 1;
+#X connect 9 0 21 0;
+#X connect 10 0 11 0;
+#X connect 10 1 11 1;
#X connect 11 0 12 0;
-#X connect 11 1 12 1;
-#X connect 12 0 13 0;
-#X connect 13 0 15 0;
-#X connect 14 0 43 0;
-#X connect 15 0 18 0;
-#X connect 16 0 14 0;
-#X connect 17 0 16 1;
-#X connect 18 0 16 0;
-#X connect 20 0 32 0;
-#X connect 20 0 41 0;
-#X connect 23 0 19 0;
-#X connect 23 1 20 0;
-#X connect 23 2 21 0;
-#X connect 25 0 30 0;
-#X connect 26 0 31 0;
-#X connect 27 0 28 0;
-#X connect 28 0 39 0;
-#X connect 29 0 35 0;
-#X connect 30 1 6 0;
-#X connect 30 1 0 0;
-#X connect 30 1 27 0;
-#X connect 30 1 2 0;
-#X connect 30 1 44 0;
-#X connect 30 1 52 0;
-#X connect 31 1 2 0;
-#X connect 31 1 27 0;
-#X connect 31 1 6 0;
-#X connect 31 1 0 0;
-#X connect 31 1 44 0;
-#X connect 31 1 52 0;
-#X connect 35 0 31 1;
-#X connect 35 0 30 1;
-#X connect 41 0 42 0;
-#X connect 44 0 46 0;
-#X connect 44 1 48 0;
-#X connect 46 0 45 0;
-#X connect 48 0 47 0;
-#X connect 49 0 44 1;
+#X connect 12 0 14 0;
+#X connect 13 0 40 0;
+#X connect 14 0 17 0;
+#X connect 15 0 13 0;
+#X connect 16 0 15 1;
+#X connect 17 0 15 0;
+#X connect 19 0 29 0;
+#X connect 19 0 38 0;
+#X connect 21 0 18 0;
+#X connect 21 1 19 0;
+#X connect 21 2 20 0;
+#X connect 23 0 27 0;
+#X connect 24 0 28 0;
+#X connect 25 0 108 0;
+#X connect 26 0 32 0;
+#X connect 27 1 6 0;
+#X connect 27 1 0 0;
+#X connect 27 1 25 0;
+#X connect 27 1 2 0;
+#X connect 27 1 41 0;
+#X connect 27 1 49 0;
+#X connect 28 1 2 0;
+#X connect 28 1 25 0;
+#X connect 28 1 6 0;
+#X connect 28 1 0 0;
+#X connect 28 1 41 0;
+#X connect 28 1 49 0;
+#X connect 32 0 28 1;
+#X connect 32 0 27 1;
+#X connect 32 0 56 0;
+#X connect 38 0 39 0;
+#X connect 41 0 43 0;
+#X connect 41 1 45 0;
+#X connect 42 0 95 0;
+#X connect 42 0 89 0;
+#X connect 43 0 92 0;
+#X connect 44 0 95 1;
+#X connect 44 0 102 0;
+#X connect 45 0 91 0;
+#X connect 46 0 41 1;
+#X connect 46 0 47 0;
#X connect 49 0 50 0;
-#X connect 52 0 53 0;
-#X connect 53 0 54 0;
-#X connect 55 0 61 0;
-#X connect 57 0 58 0;
-#X connect 58 0 55 0;
-#X connect 60 0 55 0;
-#X connect 60 0 57 0;
-#X connect 62 0 45 0;
-#X connect 62 0 47 0;
-#X connect 63 0 3 0;
-#X connect 63 0 53 0;
-#X connect 64 0 14 0;
-#X connect 65 0 19 0;
-#X connect 65 0 20 0;
-#X connect 66 0 40 0;
+#X connect 50 0 68 0;
+#X connect 50 0 65 1;
+#X connect 52 0 58 0;
+#X connect 54 0 55 0;
+#X connect 55 0 52 0;
+#X connect 57 0 52 0;
+#X connect 57 0 54 0;
+#X connect 59 0 42 0;
+#X connect 59 0 44 0;
+#X connect 60 0 3 0;
+#X connect 61 0 13 0;
+#X connect 62 0 18 0;
+#X connect 62 0 19 0;
+#X connect 63 0 37 0;
+#X connect 64 0 65 0;
+#X connect 64 0 96 0;
+#X connect 65 0 66 0;
+#X connect 66 0 97 0;
+#X connect 67 0 78 0;
+#X connect 68 0 64 0;
+#X connect 71 0 64 0;
+#X connect 72 0 68 1;
+#X connect 75 0 51 0;
+#X connect 75 0 120 0;
+#X connect 76 0 78 0;
+#X connect 76 0 96 0;
+#X connect 79 0 86 0;
+#X connect 79 0 97 1;
+#X connect 83 0 80 0;
+#X connect 83 0 6 1;
+#X connect 85 0 84 0;
+#X connect 85 0 0 1;
+#X connect 89 0 104 0;
+#X connect 89 0 110 0;
+#X connect 90 0 89 1;
+#X connect 90 0 102 1;
+#X connect 91 0 44 0;
+#X connect 92 0 42 0;
+#X connect 93 0 90 0;
+#X connect 95 0 116 0;
+#X connect 96 0 77 0;
+#X connect 96 0 75 0;
+#X connect 97 0 100 0;
+#X connect 99 0 67 0;
+#X connect 100 0 99 0;
+#X connect 102 0 104 0;
+#X connect 103 0 93 0;
+#X connect 104 0 105 1;
+#X connect 105 0 106 0;
+#X connect 106 0 109 0;
+#X connect 107 0 36 0;
+#X connect 108 0 107 0;
+#X connect 109 0 112 0;
+#X connect 110 0 105 0;
+#X connect 113 0 114 0;
+#X connect 114 0 115 0;
+#X connect 115 0 107 0;
+#X connect 116 0 117 0;
+#X connect 117 0 94 0;
#X restore 16 337 pd aubio;
-#X obj -11 467 spigot;
-#X obj 22 393 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
+#X obj -11 517 spigot;
+#X obj 22 443 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
1;
-#X obj -11 490 print;
+#X obj -11 540 print;
#X floatatom 398 126 5 0 0 0 - - -;
-#X text 40 392 Print Output to Console;
-#X obj 560 143 s osc_output;
-#X obj -67 434 r osc_output;
+#X text 40 442 Print Output to Console;
+#X obj 583 143 s osc_output;
+#X obj 584 213 s osc_output;
+#X msg 434 242 send /aubioBpm \$1;
+#X obj 583 259 s osc_output;
+#X obj 583 190 s osc_output;
+#X obj 584 304 s osc_output;
+#X text 658 7 Todo: - http://forumnet.ircam.fr/product/antescofo/?lang=en
+;
+#X obj 298 156 r aubio_is_playing;
+#X msg 433 173 send /aubioIsPlaying \$1;
+#X obj 415 173 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
+1;
+#X obj 15 368 -~;
+#X floatatom 15 415 5 0 0 0 - - -;
+#X obj 56 414 sqrt;
+#X obj 93 369 vsl 15 60 -1 1 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 2950 1;
+#X text 43 371 Balance;
+#X obj 15 393 average~ 200;
+#X obj -67 484 r osc_output;
+#X obj 113 415 s osc_output;
+#N canvas 775 308 450 300 clean_signal 0;
+#X obj 51 133 ==;
+#X obj 93 116 f;
+#X floatatom 102 139 5 0 0 0 - - -;
+#X text 24 10 SIGNAL CLEANER;
+#X obj 51 68 inlet float;
+#X obj 51 156 sel 0;
+#X obj 93 163 outlet float;
+#X text 25 24 Prevents resending bangs when the float value has not
+changed. (Sort of flood filter);
+#X connect 0 0 5 0;
+#X connect 1 0 0 1;
+#X connect 1 0 2 0;
+#X connect 1 0 6 0;
+#X connect 4 0 1 1;
+#X connect 4 0 0 0;
+#X connect 5 0 1 0;
+#X restore 113 375 pd clean_signal;
+#X msg 113 395 send /balance \$1;
+#X text 275 383 Many OSC optimisation todo here \, frequency and packing
+stuff. See resample.pd and sendmany-osc.pd;
#X connect 0 0 5 0;
#X connect 0 0 13 0;
-#X connect 0 0 135 0;
+#X connect 0 0 131 0;
+#X connect 0 0 147 0;
#X connect 0 1 5 0;
#X connect 0 1 13 1;
-#X connect 0 1 135 1;
-#X connect 1 0 125 0;
+#X connect 0 1 131 1;
+#X connect 0 1 147 1;
+#X connect 1 0 121 0;
+#X connect 2 0 121 0;
+#X connect 3 0 121 0;
#X connect 4 0 47 0;
#X connect 5 0 6 0;
#X connect 5 0 6 1;
-#X connect 7 0 123 0;
+#X connect 7 0 119 0;
#X connect 8 0 9 0;
#X connect 11 0 10 0;
#X connect 36 0 19 0;
@@ -618,7 +834,7 @@ ROUTING;
#X connect 45 0 16 0;
#X connect 47 0 5 1;
#X connect 47 0 95 0;
-#X connect 48 0 119 0;
+#X connect 48 0 116 0;
#X connect 48 0 68 0;
#X connect 49 0 41 0;
#X connect 49 0 35 0;
@@ -642,54 +858,64 @@ ROUTING;
#X connect 58 0 26 0;
#X connect 63 0 83 0;
#X connect 63 0 69 0;
-#X connect 64 0 124 0;
+#X connect 64 0 120 0;
#X connect 64 0 74 0;
-#X connect 65 0 116 0;
+#X connect 65 0 113 0;
#X connect 65 0 72 0;
#X connect 66 0 13 2;
-#X connect 70 0 118 0;
+#X connect 70 0 115 0;
#X connect 70 0 71 0;
#X connect 74 0 75 0;
#X connect 75 0 76 0;
#X connect 75 0 77 0;
#X connect 76 0 75 1;
-#X connect 78 0 108 0;
-#X connect 79 0 111 0;
-#X connect 80 0 139 0;
-#X connect 80 0 115 0;
-#X connect 81 0 113 0;
+#X connect 78 0 107 0;
+#X connect 79 0 109 0;
+#X connect 80 0 135 0;
+#X connect 80 0 112 0;
+#X connect 81 0 111 0;
#X connect 81 0 86 0;
-#X connect 82 0 117 0;
+#X connect 82 0 114 0;
#X connect 82 0 73 0;
#X connect 83 0 46 0;
-#X connect 84 0 135 2;
-#X connect 87 0 110 0;
+#X connect 84 0 131 2;
+#X connect 87 0 108 0;
#X connect 87 0 88 0;
#X connect 89 0 90 0;
-#X connect 89 0 120 0;
+#X connect 89 0 139 0;
#X connect 91 0 92 0;
#X connect 91 0 79 0;
#X connect 93 0 78 0;
#X connect 93 0 94 0;
#X connect 97 0 96 0;
-#X connect 97 0 112 0;
-#X connect 110 0 107 0;
-#X connect 112 0 109 0;
-#X connect 113 0 106 0;
-#X connect 115 0 141 0;
+#X connect 97 0 110 0;
+#X connect 108 0 138 0;
+#X connect 110 0 142 0;
+#X connect 111 0 106 0;
+#X connect 112 0 137 0;
+#X connect 113 0 46 0;
+#X connect 114 0 46 0;
+#X connect 115 0 46 0;
#X connect 116 0 46 0;
-#X connect 117 0 46 0;
-#X connect 118 0 46 0;
-#X connect 119 0 46 0;
-#X connect 120 0 114 0;
-#X connect 121 0 66 0;
-#X connect 123 0 125 0;
-#X connect 124 0 46 0;
-#X connect 125 0 126 0;
-#X connect 126 0 127 1;
-#X connect 127 0 125 0;
-#X connect 127 0 136 0;
-#X connect 133 0 84 0;
-#X connect 136 0 138 0;
-#X connect 137 0 136 1;
-#X connect 142 0 127 0;
+#X connect 117 0 66 0;
+#X connect 119 0 121 0;
+#X connect 120 0 46 0;
+#X connect 121 0 122 0;
+#X connect 122 0 123 1;
+#X connect 123 0 121 0;
+#X connect 123 0 132 0;
+#X connect 129 0 84 0;
+#X connect 132 0 134 0;
+#X connect 133 0 132 1;
+#X connect 139 0 140 0;
+#X connect 144 0 145 0;
+#X connect 144 0 146 0;
+#X connect 145 0 141 0;
+#X connect 147 0 152 0;
+#X connect 148 0 149 0;
+#X connect 149 0 150 0;
+#X connect 150 0 155 0;
+#X connect 152 0 148 0;
+#X connect 153 0 123 0;
+#X connect 155 0 156 0;
+#X connect 156 0 154 0;