summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Redfern <tim@herge.(none)>2013-05-15 15:54:27 +0100
committerTim Redfern <tim@herge.(none)>2013-05-15 15:54:27 +0100
commit06848f0cc48de1d7fa0f06636adeb1d30faf10de (patch)
tree61bde32b711e81e421cec9788385e69756e1d989
parent92b9ab519a4e7eb0a0d365229835b044d431566c (diff)
all ready for new sins render
-rwxr-xr-xrotord/01.xml2
-rw-r--r--rotord/04.xml8
-rw-r--r--rotord/05.xml46
-rw-r--r--rotord/06.xml29
-rw-r--r--rotord/rendercontext.cpp4
-rwxr-xr-xrotord/rotor.cpp15
-rwxr-xr-xrotord/rotor.h79
7 files changed, 151 insertions, 32 deletions
diff --git a/rotord/01.xml b/rotord/01.xml
index 29d709e..dd34ed8 100755
--- a/rotord/01.xml
+++ b/rotord/01.xml
@@ -5,7 +5,7 @@
<node ID="02" type="on_off" output="signal">on off
<signal_input from="01">signal 1 to make on off</signal_input>
</node>
- <node ID="03" type="video_input" output="image">performance video
+ <node ID="03" type="video_loader" output="image">performance video
</node>
<node ID="04" type="invert" output="image">invert video
<signal_input from="02">invert signal</signal_input>
diff --git a/rotord/04.xml b/rotord/04.xml
index 7552ae3..b7b38e5 100644
--- a/rotord/04.xml
+++ b/rotord/04.xml
@@ -2,13 +2,13 @@
<patchbay ID="0f7aa258-7c2f-11e2-abbd-133252267708">Sample template ©Rotor 2013
<node ID="01" type="audio_analysis" soname="qm-vamp-plugins" id="qm-tempotracker" output="signal">beats
</node>
- <node ID="02" type="video_input" output="image">performance video
+ <node ID="02" type="video_loader" output="image">performance video
</node>
- <node ID="03" type="video_input" output="image">performance video
+ <node ID="03" type="video_loader" output="image">performance video
</node>
- <node ID="04" type="video_input" output="image">performance video
+ <node ID="04" type="video_loader" output="image">performance video
</node>
- <node ID="05" type="video_input" output="image">performance video
+ <node ID="05" type="video_loader" output="image">performance video
</node>
<node ID="06" type="video_cycler" output="image">video cycler
<signal_input from="01">switching signal</signal_input>
diff --git a/rotord/05.xml b/rotord/05.xml
new file mode 100644
index 0000000..93191dd
--- /dev/null
+++ b/rotord/05.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<patchbay ID="0f7aa258-7c2f-11e2-abbd-133252267708">Sample template ©Rotor 2013
+ <node ID="01" type="audio_analysis" soname="qm-vamp-plugins" id="qm-tempotracker" output="signal">beats
+ </node>
+ <node ID="02" type="audio_analysis" soname="qm-vamp-plugins" id="qm-segmenter" output="signal">segmentation
+ </node>
+ <node ID="03" type="track_time" output="signal">fraction of audio track
+ </node>
+ <node ID="04" type="comparison" operator=">" value="0.75" output="signal">comparison
+ <signal_input from="03">comparison signal</signal_input>
+ </node>
+ <node ID="05" type="arithmetic" operator="*" value="0.75" output="signal">arithmetic
+ <signal_input from="02">arithmetic signal</signal_input>
+ <parameter_input parameter="value" from="04">value control</parameter_input>
+ </node>
+ <node ID="06" type="comparison" operator=">" value="1.0" output="signal">comparison
+ <signal_input from="05">comparison signal</signal_input>
+ </node>
+ <node ID="07" type="divide" amount="4.0" output="signal">divide
+ <signal_input from="01">signal to divide</signal_input>
+ </node>
+ <node ID="08" type="video_loader" output="image">performance video
+ </node>
+ <node ID="09" type="video_loader" output="image">performance video
+ </node>
+ <node ID="10" type="video_cycler" output="image">video cycler
+ <signal_input from="07">switching signal</signal_input>
+ <image_input from="08">image to switch</image_input>
+ <image_input from="09">image to switch</image_input>
+ </node>
+ <node ID="11" type="echo_trails" number="25" duration="1.0" fadeto="0.0" black_in="0.2" white_in="1.0" gamma="1.0" black_out="0.0" white_out="0.2" mode="0.0" output="image">echo trails
+ <image_input from="10">image input</image_input>
+ <parameter_input parameter="mode" from="06">mode control</parameter_input>
+ </node>
+ <node ID="12" type="divide" amount="16.0" output="signal">divide
+ <signal_input from="01">signal to divide</signal_input>
+ </node>
+ <node ID="13" type="video_cycler" output="image">video cycler
+ <signal_input from="12">switching signal</signal_input>
+ <image_input from="10">image to switch</image_input>
+ <image_input from="11">image to switch</image_input>
+ </node>
+ <node ID="14" type="video_output">video output
+ <image_input from="13">image to output</image_input>
+ </node>
+</patchbay>
diff --git a/rotord/06.xml b/rotord/06.xml
new file mode 100644
index 0000000..1794914
--- /dev/null
+++ b/rotord/06.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<patchbay ID="0f7aa258-7c2f-11e2-abbd-133252267708">Testing parameter controls ©Rotor 2013
+ <node ID="01" type="audio_analysis" soname="qm-vamp-plugins" id="qm-tempotracker" output="signal">beats
+ </node>
+ <node ID="02" type="on_off" output="signal">on off
+ <signal_input from="01">signal 1 to make on off</signal_input>
+ </node>
+ <node ID="03" type="video_loader" output="image">performance video
+ </node>
+ <node ID="04" type="track_time" output="signal">fraction of audio track
+ </node>
+ <node ID="05" type="arithmetic" operator="*" value="0.5" output="signal">arithmetic
+ <signal_input from="02">arithmetic signal</signal_input>
+ </node>
+ <node ID="06" type="arithmetic" operator="*" value="0.5" output="signal">arithmetic
+ <signal_input from="04">arithmetic signal</signal_input>
+ </node>
+ <node ID="07" type="arithmetic" operator="+" value="1.0" output="signal">arithmetic
+ <signal_input from="05">arithmetic signal</signal_input>
+ <parameter_input parameter="value" from="06">value control</parameter_input>
+ </node>
+ <node ID="08" type="luma_levels" black_in="0.0" white_in="1.0" gamma="1.0" black_out="0.0" white_out="1.0" mode="0" output="image">luma levels
+ <image_input from="03">image input</image_input>
+ <parameter_input parameter="white_out" from="07">white_out control</parameter_input>
+ </node>
+ <node ID="09" type="video_output">video output
+ <image_input from="08">image to output</image_input>
+ </node>
+</patchbay>
diff --git a/rotord/rendercontext.cpp b/rotord/rendercontext.cpp
index fc5936b..624b7c1 100644
--- a/rotord/rendercontext.cpp
+++ b/rotord/rendercontext.cpp
@@ -451,8 +451,8 @@ bool Render_context::load_video(const string &nodeID,const string &filename){
//this is a good standard example of how to find
//a node of a specific type by ID and do something
if (graph.nodes.find(nodeID)!=graph.nodes.end()){
- if (graph.nodes[nodeID]->type=="video_input") {
- if (((Video_input*)graph.nodes[nodeID])->load(filename)) {
+ if (graph.nodes[nodeID]->type=="video_loader") {
+ if (((Video_loader*)graph.nodes[nodeID])->load(filename)) {
return true;
}
}
diff --git a/rotord/rotor.cpp b/rotord/rotor.cpp
index 59a1697..52c76df 100755
--- a/rotord/rotor.cpp
+++ b/rotord/rotor.cpp
@@ -12,7 +12,7 @@ Node_factory::Node_factory(){
add_type("signal_output",new Signal_output());
add_type("testcard",new Testcard());
add_type("video_output",new Video_output());
- add_type("video_input",new Video_input());
+ add_type("video_loader",new Video_loader());
add_type("on_off",new On_off());
add_type("invert",new Invert());
add_type("video_cycler",new Video_cycler());
@@ -30,6 +30,11 @@ bool Signal_input::connect(Signal_node* source) {
}
else return false;
}
+void Parameter_input::update(const Time_spec& time){ //gets input and updates variable
+ if (receiver){
+ *receiver=((Signal_node*)connection)->get_output(time);
+ }
+}
bool Image_input::connect(Image_node* source) {
if (source->output_type=="image") {
connection=(Node*)source;
@@ -215,7 +220,7 @@ bool Video_output::render(const float duration, const float framerate,const stri
return false;
}
-bool Video_input::load(const string &filename){
+bool Video_loader::load(const string &filename){
//gstreamer needs absolute paths ALWAYS
//string uri="file:///home/tim/workspace/rotor/rotord/"+filename;
Poco::Path path;
@@ -226,13 +231,13 @@ bool Video_input::load(const string &filename){
player->setPaused(true);
player->setFrameByFrame(true);
player->update();
- cerr<<"Rotor::Video_input loaded "<<filename<<", "<<player->getDuration()<<" seconds "<<", "<<player->getWidth()<<"x"<<player->getHeight()<<endl;
+ cerr<<"Rotor::Video_loader: "<<filename<<", "<<player->getDuration()<<" seconds "<<", "<<player->getWidth()<<"x"<<player->getHeight()<<endl;
image->setup_fromRGB(player->getWidth(),player->getHeight(),(uint8_t*) player->getPixels());
return true;
}
return false;
}
-Image* Video_input::get_output(const Frame_spec &frame){
+Image* Video_loader::output(const Frame_spec &frame){
//wonder about the actual mechanism used by gstreamer
//have to implment callback when seek is ready?
//presume gstreamer caches a loaded frame?
@@ -260,7 +265,7 @@ Image* Video_input::get_output(const Frame_spec &frame){
//}
player->update();
image->RGBdata=player->getPixels(); //don't really know why this is needed every frame
- //cerr<<"Video_input: retrieving frame "<<((int) (frame.time*frame.framerate))<<endl;
+ //cerr<<"Video_loader: retrieving frame "<<((int) (frame.time*frame.framerate))<<endl;
return image;
}
return nullptr;
diff --git a/rotord/rotor.h b/rotord/rotor.h
index d5dc60e..e128fd5 100755
--- a/rotord/rotor.h
+++ b/rotord/rotor.h
@@ -2,6 +2,8 @@
nodes can have many inputs but only 1 output
image nodes that use an image as input can pass on the incoming image only if its unchanged.
+
+TODO - parameter class that automatically links variable to correctly named inputs
*/
#include <unordered_map>
@@ -210,6 +212,18 @@ namespace Rotor {
}
return *this;
}
+ Image & add_wrap(const Image &other) {
+ if (other.w!=w||other.h!=h) {
+ cerr<<"Rotor: cannot add images with different sizes! (wanted "<<w<<"x"<<h<<", got "<<other.w<<"x"<<other.h<<")"<<endl;
+ }
+ else {
+ for (int i=0;i<w*h*3;i++){
+ //creates rainbow overload
+ RGBdata[i]=(unsigned char)(((int)other.RGBdata[i]+(int)RGBdata[i]));
+ }
+ }
+ return *this;
+ }
Image * operator*(const float &amount) {
Image *other=new Image();
other->setup(w,h);
@@ -264,11 +278,7 @@ namespace Rotor {
public:
Parameter_input(const string &_param,const string &_desc): Signal_input(_desc),receiver(nullptr),parameter(_param){};
float *receiver;
- void update(const Time_spec& time){ //gets input and updates variable
- if (receiver){
- *receiver=((Signal_node*)connection)->get_output(time);
- }
- }
+ void update(const Time_spec& time);
string parameter;
};
class Node{
@@ -304,7 +314,8 @@ namespace Rotor {
public:
vector<Image_input*> image_inputs; //image node also has image inputs and outputs
void create_image_input(const string &description) {image_inputs.push_back(new Image_input(description));};
- virtual Image *get_output(const Frame_spec &frame)=0;
+ Image *get_output(const Frame_spec &frame) { update_params((Time_spec)frame); return output(frame); };
+ virtual const Image *output(const Frame_spec &frame)=0;
Image *get_preview(const Frame_spec &frame);
Image *image; //this can be privately allocated or just passed on as the node see fit
private:
@@ -382,6 +393,9 @@ namespace Rotor {
if (_op=="<") op=COMPARISON_Less;
if (_op==">=") op=COMPARISON_Greater_or_equal;
if (_op=="<=") op=COMPARISON_Less_or_equal;
+ for (auto p:parameter_inputs){
+ if (p->parameter=="value") p->receiver=&value;
+ }
};
Comparison* clone(map<string,string> &_settings) { return new Comparison(_settings);};
const float output(const Time_spec &time) {
@@ -432,6 +446,9 @@ namespace Rotor {
if (_op=="*") op=ARITHMETIC_multiply;
if (_op=="/") op=ARITHMETIC_divide;
if (_op=="%") op=ARITHMETIC_modulo;
+ for (auto p:parameter_inputs){
+ if (p->parameter=="value") p->receiver=&value;
+ }
};
Arithmetic* clone(map<string,string> &_settings) { return new Arithmetic(_settings);};
const float output(const Time_spec &time) {
@@ -468,6 +485,9 @@ namespace Rotor {
Signal_divide(map<string,string> &settings) {
base_settings(settings);
divide_amount=ofToFloat(find_setting(settings,"amount"));
+ for (auto p:parameter_inputs){
+ if (p->parameter=="divide_amount") p->receiver=&divide_amount;
+ }
};
Signal_divide* clone(map<string,string> &_settings) { return new Signal_divide(_settings);};
const float output(const Time_spec &time) {
@@ -537,7 +557,7 @@ namespace Rotor {
};
~Testcard(){ delete image;};
Testcard* clone(map<string,string> &_settings) { return new Testcard(_settings);};
- Image *get_output(const Frame_spec &frame){
+ Image *output(const Frame_spec &frame){
if (image->setup(frame.w,frame.h)) {
}
@@ -567,7 +587,7 @@ namespace Rotor {
};
~Invert(){ delete image;};
Invert* clone(map<string,string> &_settings) { return new Invert(_settings);};
- Image *get_output(const Frame_spec &frame){
+ Image *output(const Frame_spec &frame){
if (inputs.size()) {
if (image_inputs[0]->connection){
if (inputs[0]->connection) {
@@ -602,7 +622,7 @@ namespace Rotor {
exporter=new libav::Exporter();
};
~Video_output(){ delete exporter; };
- Image *get_output(const Frame_spec &frame){
+ Image *output(const Frame_spec &frame){
if (image_inputs[0]->connection) {
return ((Image_node*)(image_inputs[0]->connection))->get_output(frame);
}
@@ -616,21 +636,21 @@ namespace Rotor {
libav::Exporter *exporter;
libav::Audioloader audioloader;
};
- class Video_input: public Image_node {
+ class Video_loader: public Image_node {
//video input using gstreamer
//seems slow
//TODO: scaling
public:
- Video_input(){};
- Video_input(map<string,string> &settings) {
+ Video_loader(){};
+ Video_loader(map<string,string> &settings) {
base_settings(settings);
player=new ofGstVideoPlayer();
image=new Image();
};
- ~Video_input(){ delete player; delete image;};
+ ~Video_loader(){ delete player; delete image;};
bool load(const string &filename);
- Image *get_output(const Frame_spec &frame);
- Video_input* clone(map<string,string> &_settings) { return new Video_input(_settings);};
+ Image *output(const Frame_spec &frame);
+ Video_loader* clone(map<string,string> &_settings) { return new Video_loader(_settings);};
private:
ofGstVideoPlayer *player;
Image *image;
@@ -644,7 +664,7 @@ namespace Rotor {
};
~Video_cycler(){};
bool load(const string &filename);
- Image *get_output(const Frame_spec &frame){
+ Image *output(const Frame_spec &frame){
int which_input=0;
if (inputs[0]->connection) {
which_input=((int)((Signal_node*)inputs[0]->connection)->get_output((Time_spec)frame))%image_inputs.size();
@@ -667,6 +687,13 @@ namespace Rotor {
base_settings(settings);
levels_settings(settings);
image=new Image();
+ for (auto p:parameter_inputs){
+ if (p->parameter=="black_in") p->receiver=&black_in;
+ if (p->parameter=="white_in") p->receiver=&white_in;
+ if (p->parameter=="gamma") p->receiver=&gamma;
+ if (p->parameter=="black_out") p->receiver=&black_out;
+ if (p->parameter=="white_out") p->receiver=&white_out;
+ }
};
~Luma_levels(){if (LUT) {delete[] LUT;} if (image) {delete image;} };
void levels_settings(map<string,string> &settings){
@@ -695,7 +722,7 @@ namespace Rotor {
out.RGBdata[i]=LUT[in.RGBdata[i]];
}
}
- Image *get_output(const Frame_spec &frame){
+ Image *output(const Frame_spec &frame){
if (image_inputs.size()) {
if (image_inputs[0]->connection){
if (LUT) {
@@ -710,7 +737,6 @@ namespace Rotor {
protected:
unsigned char *LUT;
Image *image;
- private:
float black_in,white_in,gamma,black_out,white_out;
};
class Echo_trails: public Luma_levels {
@@ -751,9 +777,20 @@ namespace Rotor {
levels_settings(settings);
image=new Image();
lastframe=-1;
+ mode=find_setting(settings,"mode",0.0f);
+ for (auto p:parameter_inputs){
+ if (p->parameter=="black_in") p->receiver=&black_in;
+ if (p->parameter=="white_in") p->receiver=&white_in;
+ if (p->parameter=="gamma") p->receiver=&gamma;
+ if (p->parameter=="black_out") p->receiver=&black_out;
+ if (p->parameter=="white_out") p->receiver=&white_out;
+
+ //TODO: control an integer
+ if (p->parameter=="mode") p->receiver=&mode;
+ }
};
~Echo_trails(){if (image) {delete image;} };
- Image *get_output(const Frame_spec &frame){
+ Image *output(const Frame_spec &frame){
//check if cache is valid
if (frame.w!=image->w||frame.h!=image->h){ //or framerate changed?
//clear cache and start over
@@ -801,7 +838,8 @@ namespace Rotor {
//cerr<<"Rotor: about to apply image ("<<images[absframe].w<<"x"<<images[absframe].h<<")"<<endl;
if (fless(fadeto,1.0f)){
Image *temp=*images[absframe]*((float)number/((fadeto*number)+((1.0-fadeto)*i)));
- (*image)+=*temp;
+ if (mode<0.5) (*image)+=*temp;
+ else (*image)=image->add_wrap(*temp);
delete temp;
}
else (*image)+=*images[absframe];
@@ -824,6 +862,7 @@ namespace Rotor {
int number;
int interval,total,lastframe; //number of frames between displayed echoes
unordered_map<int,Image*> images;
+ float mode; //TODO make int, enum string parameter types
};
//-------------------------------------------------------------------
class Node_factory{