diff options
| -rw-r--r-- | rotord/07.xml | 11 | ||||
| -rw-r--r-- | rotord/08.xml | 20 | ||||
| -rwxr-xr-x | rotord/rotor.cpp | 3 | ||||
| -rwxr-xr-x | rotord/rotor.h | 185 |
4 files changed, 217 insertions, 2 deletions
diff --git a/rotord/07.xml b/rotord/07.xml new file mode 100644 index 0000000..5744bb5 --- /dev/null +++ b/rotord/07.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> +<patchbay ID="0f7aa258-7c2f-11e2-abbd-133252267708">Testing parameter controls ©Rotor 2013 + <node ID="01" type="video_loader" output="image">performance video + </node> + <node ID="02" type="echo_trails" number="12" duration="1.0" fadeto="0.0" black_in="0.2" white_in="1.0" gamma="1.2" black_out="0.0" white_out="0.2" mode="0.0" output="image">echo trails + <image_input from="01">image input</image_input> + </node> + <node ID="03" type="video_output">video output + <image_input from="02">image to output</image_input> + </node> +</patchbay> diff --git a/rotord/08.xml b/rotord/08.xml new file mode 100644 index 0000000..bbc8479 --- /dev/null +++ b/rotord/08.xml @@ -0,0 +1,20 @@ +<?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="audio_analysis" soname="qm-vamp-plugins" id="qm-segmenter" output="signal">segmentation + </node> + <node ID="03" type="signal_colour" palette="2FCE03FDF23EFF3D84FA80A7FFBF35" output="image">colour segmentation + <signal_input from="02">signal to visualise</signal_input> + </node> + <node ID="04" type="arithmetic" operator="%" value="1.0" output="signal">signal arithmetic + <signal_input from="01">signal to operate on</signal_input> + </node> + <node ID="05" type="image_arithmetic" operator="*" value="1.0" output="image">colour segmentation + <parameter_input parameter="value" from="04">value control</parameter_input> + <image_input from="03">image to operate on</image_input> + </node> + <node ID="06" type="video_output">video output + <image_input from="05">image to output</image_input> + </node> +</patchbay> diff --git a/rotord/rotor.cpp b/rotord/rotor.cpp index 00fd465..18988ed 100755 --- a/rotord/rotor.cpp +++ b/rotord/rotor.cpp @@ -21,6 +21,9 @@ Node_factory::Node_factory(){ add_type("track_time",new Track_time()); add_type("comparison",new Comparison()); //TODO: alias to symbols add_type("arithmetic",new Arithmetic()); //TODO: alias to symbols + add_type("signal_colour",new Signal_colour()); + add_type("signal_greyscale",new Signal_greyscale()); + add_type("image_arithmetic",new Image_arithmetic()); } bool Signal_input::connect(Signal_node* source) { diff --git a/rotord/rotor.h b/rotord/rotor.h index fe0f7d9..137f8ee 100755 --- a/rotord/rotor.h +++ b/rotord/rotor.h @@ -141,6 +141,23 @@ namespace Rotor { return (int)((time*framerate)+0.5); //rounded to the nearest frame } }; + class Colour{ + public: + Colour(){ + r=g=b=0; + } + Colour(int c){ + r=c&0xFF; + g=(c&0xFF00)>>8; + b=(c&0xFF0000)>>16; + } + Colour(std::string s){ + r=(uint8_t)ofHexToChar(s.substr(0,2)); + g=(uint8_t)ofHexToChar(s.substr(2,2)); + b=(uint8_t)ofHexToChar(s.substr(4,2)); + } + uint8_t r,g,b; + }; class Image{ public: Image(){ @@ -237,6 +254,42 @@ namespace Rotor { } return other; } + Image * operator+(const float &amount) { + Image *other=new Image(); + other->setup(w,h); + uint8_t *LUT=new uint8_t[0xFF]; + for (int i=0;i<0xFF;i++) { + LUT[i]=(uint8_t)min(0xFF,max(0,(int)(i+amount))); //should normalise to 0-255? + } + for (int i=0;i<w*h*3;i++){ + other->RGBdata[i]=LUT[RGBdata[i]]; + } + return other; + } + Image * operator-(const float &amount) { + Image *other=new Image(); + other->setup(w,h); + uint8_t *LUT=new uint8_t[0xFF]; + for (int i=0;i<0xFF;i++) { + LUT[i]=(uint8_t)min(0xFF,max(0,(int)(i-amount))); //should normalise to 0-255? + } + for (int i=0;i<w*h*3;i++){ + other->RGBdata[i]=LUT[RGBdata[i]]; + } + return other; + } + Image * operator/(const float &amount) { + Image *other=new Image(); + other->setup(w,h); + uint8_t *LUT=new uint8_t[0xFF]; + for (int i=0;i<0xFF;i++) { + LUT[i]=(uint8_t)min(0xFF,max(0,(int)(i/amount))); //should normalise to 0-255? + } + for (int i=0;i<w*h*3;i++){ + other->RGBdata[i]=LUT[RGBdata[i]]; + } + return other; + } uint8_t *RGBdata; uint8_t *Adata; uint16_t *Zdata; @@ -678,6 +731,130 @@ namespace Rotor { Video_cycler* clone(map<string,string> &_settings) { return new Video_cycler(_settings);}; private: }; + class Signal_colour: public Image_node { + //cycles through video inputs in order + public: + Signal_colour(){}; + Signal_colour(map<string,string> &settings) { + base_settings(settings); + string colours=find_setting(settings,"palette",""); + for (int i=0;i<colours.size()/6;i++){ + palette.push_back(Colour(colours.substr(i*6,6))); + } + for (auto i: palette) { + cerr << "Signal_colour found palette colour: "<<(int)i.r<<" "<<(int)i.g<<" "<<(int)i.b<<endl; + } + prevcol=-1; + }; + ~Signal_colour(){}; + Image *output(const Frame_spec &frame){ + if (palette.size()) { + if (inputs.size()) { + if (inputs[0]->connection){ + int col= ((int)(((Signal_node*)inputs[0]->connection)->get_output(frame)))%palette.size(); + if (col!=prevcol||image.w!=frame.w||image.h!=frame.h){ + image.setup(frame.w,frame.h); + for (int i=0;i<image.w*image.h;i++){ + image.RGBdata[i*3]=palette[col].r; + image.RGBdata[i*3+1]=palette[col].g; + image.RGBdata[i*3+2]=palette[col].b; + } + prevcol=col; + } + return ℑ + } + } + } + return nullptr; + } + Signal_colour* clone(map<string,string> &_settings) { return new Signal_colour(_settings);}; + private: + vector<Rotor::Colour> palette; + Image image; + int prevcol; + }; + class Signal_greyscale: public Image_node { + //Draws signal bars in greyscale + public: + Signal_greyscale(){}; + Signal_greyscale(map<string,string> &settings) { + base_settings(settings); + prevcol=-1; + }; + ~Signal_greyscale(){}; + Image *output(const Frame_spec &frame){ + if (inputs.size()) { + if (inputs[0]->connection){ + float sig= ((((Signal_node*)inputs[0]->connection)->get_output(frame))); + float seg=fmod(sig,(int)sig); + uint8_t col=255-((uint8_t)(seg*255.0f)); + if (col!=prevcol||image.w!=frame.w||image.h!=frame.h){ + image.setup(frame.w,frame.h); + for (int i=0;i<image.w*image.h*3;i++){ + image.RGBdata[i]=col; + } + prevcol=col; + } + return ℑ + } + } + return nullptr; + } + Signal_greyscale* clone(map<string,string> &_settings) { return new Signal_greyscale(_settings);}; + private: + Image image; + uint8_t prevcol; + }; + class Image_arithmetic: public Image_node { + //Draws signal bars in greyscale + public: + Image_arithmetic(){}; + Image_arithmetic(map<string,string> &settings) { + base_settings(settings); + value=find_setting(settings,"value",0.0f); + string _op=find_setting(settings,"operator","+"); + if (_op=="+") op=ARITHMETIC_plus; + if (_op=="-") op=ARITHMETIC_minus; + if (_op=="*") op=ARITHMETIC_multiply; + if (_op=="/") op=ARITHMETIC_divide; + //if (_op=="%") op=ARITHMETIC_modulo; ??what would this even mean? + for (auto p:parameter_inputs){ + if (p->parameter=="value") p->receiver=&value; + } + image=nullptr; + }; + ~Image_arithmetic(){if (image) delete image;}; + Image *output(const Frame_spec &frame){ + if (image_inputs.size()) { + if (image_inputs[0]->connection){ + if (image) delete image; + Image *in=(((Image_node*)image_inputs[0]->connection)->get_output(frame)); + switch (op) { + case ARITHMETIC_plus: + image=(*in)+value; + break; + case ARITHMETIC_minus: + image=(*in)-value; + break; + case ARITHMETIC_multiply: + image=(*in)*value; + break; + case ARITHMETIC_divide: + image=(*in)/value; + break; + } + return image; + } + } + return nullptr; + } + Image_arithmetic* clone(map<string,string> &_settings) { return new Image_arithmetic(_settings);}; + private: + Image *image; + float value; + int op; + }; + class Luma_levels: public Image_node { //applies LUT To RGB channels equally public: @@ -839,8 +1016,12 @@ namespace Rotor { if (fless(1.0f,fadeto)){ float amount=((((float)number-i)/number)*(1.0f-fadeto))+(1.0f-fadeto); Image *temp=*images[absframe]*amount; - if (mode<0.5) (*image)+=*temp; - else (*image)=image->add_wrap(*temp); + if (mode<0.5) { + (*image)+=*temp; + } + else { + image->add_wrap(*temp); + } delete temp; } else { |
