diff options
| author | Tim Redfern <tim@herge.(none)> | 2013-05-15 15:54:27 +0100 |
|---|---|---|
| committer | Tim Redfern <tim@herge.(none)> | 2013-05-15 15:54:27 +0100 |
| commit | 06848f0cc48de1d7fa0f06636adeb1d30faf10de (patch) | |
| tree | 61bde32b711e81e421cec9788385e69756e1d989 | |
| parent | 92b9ab519a4e7eb0a0d365229835b044d431566c (diff) | |
all ready for new sins render
| -rwxr-xr-x | rotord/01.xml | 2 | ||||
| -rw-r--r-- | rotord/04.xml | 8 | ||||
| -rw-r--r-- | rotord/05.xml | 46 | ||||
| -rw-r--r-- | rotord/06.xml | 29 | ||||
| -rw-r--r-- | rotord/rendercontext.cpp | 4 | ||||
| -rwxr-xr-x | rotord/rotor.cpp | 15 | ||||
| -rwxr-xr-x | rotord/rotor.h | 79 |
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=÷_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=γ + 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=γ + 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{ |
