diff options
| -rw-r--r-- | rotord/src/nodes_maths.h | 241 | ||||
| -rwxr-xr-x | rotord/src/rotor.cpp | 2 | ||||
| -rwxr-xr-x | rotord/src/rotor.h | 242 |
3 files changed, 255 insertions, 230 deletions
diff --git a/rotord/src/nodes_maths.h b/rotord/src/nodes_maths.h index f8b6cd9..4b080d4 100644 --- a/rotord/src/nodes_maths.h +++ b/rotord/src/nodes_maths.h @@ -4,7 +4,246 @@ #include "rotor.h" namespace Rotor { - +#define COMPARISON_Equal 1 +#define COMPARISON_Not_equal 2 +#define COMPARISON_Greater 3 +#define COMPARISON_Less 4 +#define COMPARISON_Greater_or_equal 5 +#define COMPARISON_Less_or_equal 6 + class Comparison: public Signal_node { + public: + Comparison(){}; + Comparison(map<string,string> &settings) { + base_settings(settings); + value=find_setting(settings,"value",0.0f); + string _op=find_setting(settings,"operator","=="); + if (_op=="==") op=COMPARISON_Equal; + if (_op=="!=") op=COMPARISON_Not_equal; + if (_op==">") op=COMPARISON_Greater; + if (_op=="<") op=COMPARISON_Less; + if (_op==">=") op=COMPARISON_Greater_or_equal; + if (_op=="<=") op=COMPARISON_Less_or_equal; + } + void link_params() { + 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) { + if (inputs.size()) { //there should there be a way to specify number of inputs in the code rather than in xml + if (inputs[0]->connection) { + float in= (((Signal_node*)inputs[0]->connection)->get_output(time)); + switch (op) { + case COMPARISON_Equal: + return fequal(value,in)?1.0f:0.0f; + break; + case COMPARISON_Not_equal: + return fequal(value,in)?0.0f:1.0f; + break; + case COMPARISON_Greater: + return fgreater(value,in)?1.0f:0.0f; + break; + case COMPARISON_Less: + return fless(value,in)?1.0f:0.0f; + break; + case COMPARISON_Greater_or_equal: + return fgreater_or_equal(value,in)?1.0f:0.0f; + break; + case COMPARISON_Less_or_equal: + return fless_or_equal(value,in)?1.0f:0.0f; + break; + } + } + } + return 0.0f; + } + int op; + float value; + }; +#define ARITHMETIC_plus 1 +#define ARITHMETIC_minus 2 +#define ARITHMETIC_multiply 3 +#define ARITHMETIC_divide 4 +#define ARITHMETIC_modulo 5 +#define ARITHMETIC_pow 6 +#define ARITHMETIC_sin 7 +#define ARITHMETIC_cos 8 +#define ARITHMETIC_ease 9 + class Arithmetic: public Signal_node { + public: + Arithmetic(){}; + Arithmetic(map<string,string> &settings) { + base_settings(settings); + value=find_setting(settings,"value",0.0f); + string _op=find_setting(settings,"operator","+"); + if (_op=="+"||_op=="plus"||_op=="add") op=ARITHMETIC_plus; + if (_op=="-"||_op=="minus"||_op=="subtract") op=ARITHMETIC_minus; + if (_op=="*"||_op=="x"||_op=="multiply") op=ARITHMETIC_multiply; + if (_op=="/"||_op=="divide") op=ARITHMETIC_divide; + if (_op=="%"||_op=="mod"||_op=="modulo"||_op=="modulus") op=ARITHMETIC_modulo; + if (_op=="^"||_op=="power") op=ARITHMETIC_pow; + if (_op=="sin"||_op=="sine") op=ARITHMETIC_sin; + if (_op=="cos"||_op=="cos") op=ARITHMETIC_cos; + if (_op=="ease") op=ARITHMETIC_ease; + } + void link_params() { + for (auto p:parameter_inputs){ + p->receiver=nullptr; + if (p->parameter=="value") p->receiver=&value; + } + }; + Arithmetic* clone(map<string,string> &_settings) { return new Arithmetic(_settings);}; + const float output(const Time_spec &time) { + if (op==ARITHMETIC_divide||op==ARITHMETIC_modulo){ + if (value==0.0f) { + Logger& logger = Logger::get("Rotor"); + logger.error("Arithmetic node: caught division by zero, frame "+time.frame()); + return 0.0f; + } + } + if (inputs.size()) { //there should there be a way to specify number of inputs in the code rather than in xml + if (inputs[0]->connection) { + float in= (((Signal_node*)inputs[0]->connection)->get_output(time)); + switch (op) { + case ARITHMETIC_plus: + return in+value; + break; + case ARITHMETIC_minus: + return in-value; + break; + case ARITHMETIC_multiply: + return in*value; + break; + case ARITHMETIC_divide: + return in/value; + break; + case ARITHMETIC_modulo: + return fmod(in,value); + break; + case ARITHMETIC_pow: + return pow(in,value); + break; + case ARITHMETIC_sin: + return sin(in); + break; + case ARITHMETIC_cos: + return cos(in); + break; + case ARITHMETIC_ease: + return sin(in*M_PI); + break; + } + } + } + return 0.0f; + } + int op; + float value; + }; + class Signal_divide: public Signal_node { + public: + Signal_divide(){}; + Signal_divide(map<string,string> &settings) { + base_settings(settings); + divide_amount=ofToFloat(find_setting(settings,"amount")); + for (auto p:parameter_inputs){ + if (p->parameter=="amount") p->receiver=÷_amount; + } + }; + Signal_divide* clone(map<string,string> &_settings) { return new Signal_divide(_settings);}; + const float output(const Time_spec &time) { + if (inputs.size()) { //there should there be a way to specify number of inputs in the code rather than in xml + if (inputs[0]->connection) { + return (((Signal_node*)inputs[0]->connection)->get_output(time))/divide_amount; + } + } + return 0.0f; + } + float divide_amount; + }; + class Is_new_integer: public Signal_node { + public: + Is_new_integer(){}; + Is_new_integer(map<string,string> &settings) { + base_settings(settings); + }; + Is_new_integer* clone(map<string,string> &_settings) { return new Is_new_integer(_settings);}; + const float output(const Time_spec &time) { + if (inputs[0]->connection) { + float s1=(((Signal_node*)(inputs[0]->connection))->get_output(time)); + float s2=(((Signal_node*)(inputs[0]->connection))->get_output(time.lastframe())); + if (((int)s1)>((int)s2)) { + return 1.0f; + } + } + return 0.0f; + } + }; + class On_off: public Signal_node { + public: + On_off(){}; + On_off(map<string,string> &settings) { + base_settings(settings); + }; + On_off* clone(map<string,string> &_settings) { return new On_off(_settings);}; + const float output(const Time_spec &time) { + if (inputs[0]->connection) { + float s1=(((Signal_node*)(inputs[0]->connection))->get_output(time)); + if ((int)s1%2) return 1.0f; + } + return 0.0f; + } + }; + //pseudo random repeatable hash function + //http://create.stephan-brumme.com/fnv-hash/ + const uint32_t Prime = 0x01000193; // 16777619 + const uint32_t Seed = 0x811C9DC5; // 2166136261 + /// hash a byte + inline uint32_t fnv1a(unsigned char oneByte, uint32_t hash = Seed) + { + return (oneByte ^ hash) * Prime; + } + /// hash a short (two bytes) + inline uint32_t fnv1a(unsigned short twoBytes, uint32_t hash = Seed) + { + const unsigned char* ptr = (const unsigned char*) &twoBytes; + hash = fnv1a(*ptr++, hash); + return fnv1a(*ptr , hash); + } + /// hash a 32 bit integer (four bytes) + inline uint32_t fnv1a(uint32_t fourBytes, uint32_t hash = Seed) + { + const unsigned char* ptr = (const unsigned char*) &fourBytes; + hash = fnv1a(*ptr++, hash); + hash = fnv1a(*ptr++, hash); + hash = fnv1a(*ptr++, hash); + return fnv1a(*ptr , hash); + } + class Random: public Signal_node { + public: + Random(){}; + Random(map<string,string> &settings) { + base_settings(settings); + seed=(Seed+find_setting(settings,"seed",0)); + cerr<<"random:: seed "<<seed<<" ("<<Seed<<")"<<endl; + }; + Random* clone(map<string,string> &_settings) { return new Random(_settings);}; + const float output(const Time_spec &time) { + if (inputs.size()) { + if (inputs[0]->connection) { + + //hash the integer part and add the fractional part back on + float o=(((Signal_node*)inputs[0]->connection)->get_output(time)); + uint32_t m=(int)o; + return ((float)(fnv1a(m,seed)%((uint32_t)time.duration)))+(o-m); + } + } + return 0.0f; + } + uint32_t seed; + private: + }; } #endif
\ No newline at end of file diff --git a/rotord/src/rotor.cpp b/rotord/src/rotor.cpp index 7580fee..f3449fa 100755 --- a/rotord/src/rotor.cpp +++ b/rotord/src/rotor.cpp @@ -1,6 +1,7 @@ #include "rotor.h" #include "nodes_audio_analysis.h" #include "nodes_drawing.h" +#include "nodes_maths.h" using namespace Rotor; Node_factory::Node_factory(){ @@ -226,7 +227,6 @@ bool Video_output::render(const float duration, const float framerate,const stri //insert audio frames until we are ahead of the video exporter.encodeFrame(audioloader.get_samples(exporter.get_audio_framesize())); af+=exporter.get_audio_step(); - } } diff --git a/rotord/src/rotor.h b/rotord/src/rotor.h index f704a1d..f9cafa2 100755 --- a/rotord/src/rotor.h +++ b/rotord/src/rotor.h @@ -142,6 +142,9 @@ namespace Rotor { Time_spec lastframe() const{ return Time_spec(time-(1.0f/framerate),framerate,duration); } + int frame(){ + return (int)((time*framerate)+0.5); //rounded to the nearest frame + } }; class Frame_spec: public Time_spec{ public: @@ -155,9 +158,6 @@ namespace Rotor { //Frame_spec lastframe(){ // return Frame_spec(time-(1.0f/framerate),framerate,w,h); //} - int frame(){ - return (int)((time*framerate)+0.5); //rounded to the nearest frame - } }; class Colour{ public: @@ -302,225 +302,6 @@ namespace Rotor { return time.time/time.duration; } }; -#define COMPARISON_Equal 1 -#define COMPARISON_Not_equal 2 -#define COMPARISON_Greater 3 -#define COMPARISON_Less 4 -#define COMPARISON_Greater_or_equal 5 -#define COMPARISON_Less_or_equal 6 - class Comparison: public Signal_node { - public: - Comparison(){}; - Comparison(map<string,string> &settings) { - base_settings(settings); - value=find_setting(settings,"value",0.0f); - string _op=find_setting(settings,"operator","=="); - if (_op=="==") op=COMPARISON_Equal; - if (_op=="!=") op=COMPARISON_Not_equal; - if (_op==">") op=COMPARISON_Greater; - if (_op=="<") op=COMPARISON_Less; - if (_op==">=") op=COMPARISON_Greater_or_equal; - if (_op=="<=") op=COMPARISON_Less_or_equal; - } - void link_params() { - 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) { - if (inputs.size()) { //there should there be a way to specify number of inputs in the code rather than in xml - if (inputs[0]->connection) { - float in= (((Signal_node*)inputs[0]->connection)->get_output(time)); - switch (op) { - case COMPARISON_Equal: - return fequal(value,in)?1.0f:0.0f; - break; - case COMPARISON_Not_equal: - return fequal(value,in)?0.0f:1.0f; - break; - case COMPARISON_Greater: - return fgreater(value,in)?1.0f:0.0f; - break; - case COMPARISON_Less: - return fless(value,in)?1.0f:0.0f; - break; - case COMPARISON_Greater_or_equal: - return fgreater_or_equal(value,in)?1.0f:0.0f; - break; - case COMPARISON_Less_or_equal: - return fless_or_equal(value,in)?1.0f:0.0f; - break; - } - } - } - return 0.0f; - } - int op; - float value; - }; -#define ARITHMETIC_plus 1 -#define ARITHMETIC_minus 2 -#define ARITHMETIC_multiply 3 -#define ARITHMETIC_divide 4 -#define ARITHMETIC_modulo 5 - class Arithmetic: public Signal_node { - public: - Arithmetic(){}; - 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; - } - void link_params() { - for (auto p:parameter_inputs){ - p->receiver=nullptr; - if (p->parameter=="value") p->receiver=&value; - } - }; - Arithmetic* clone(map<string,string> &_settings) { return new Arithmetic(_settings);}; - const float output(const Time_spec &time) { - if (op==ARITHMETIC_divide||op==ARITHMETIC_modulo){ - if (value==0.0f) { - cerr<<"Arithmetic: caught division by zero"<<endl; - return 0.0f; - } - } - if (inputs.size()) { //there should there be a way to specify number of inputs in the code rather than in xml - if (inputs[0]->connection) { - float in= (((Signal_node*)inputs[0]->connection)->get_output(time)); - switch (op) { - case ARITHMETIC_plus: - return in+value; - break; - case ARITHMETIC_minus: - return in-value; - break; - case ARITHMETIC_multiply: - return in*value; - break; - case ARITHMETIC_divide: - return in/value; - break; - case ARITHMETIC_modulo: - return fmod(in,value); - break; - } - } - } - return 0.0f; - } - int op; - float value; - }; - class Signal_divide: public Signal_node { - public: - Signal_divide(){}; - Signal_divide(map<string,string> &settings) { - base_settings(settings); - divide_amount=ofToFloat(find_setting(settings,"amount")); - for (auto p:parameter_inputs){ - if (p->parameter=="amount") p->receiver=÷_amount; - } - }; - Signal_divide* clone(map<string,string> &_settings) { return new Signal_divide(_settings);}; - const float output(const Time_spec &time) { - if (inputs.size()) { //there should there be a way to specify number of inputs in the code rather than in xml - if (inputs[0]->connection) { - return (((Signal_node*)inputs[0]->connection)->get_output(time))/divide_amount; - } - } - return 0.0f; - } - float divide_amount; - }; - class Is_new_integer: public Signal_node { - public: - Is_new_integer(){}; - Is_new_integer(map<string,string> &settings) { - base_settings(settings); - }; - Is_new_integer* clone(map<string,string> &_settings) { return new Is_new_integer(_settings);}; - const float output(const Time_spec &time) { - if (inputs[0]->connection) { - float s1=(((Signal_node*)(inputs[0]->connection))->get_output(time)); - float s2=(((Signal_node*)(inputs[0]->connection))->get_output(time.lastframe())); - if (((int)s1)>((int)s2)) { - return 1.0f; - } - } - return 0.0f; - } - }; - class On_off: public Signal_node { - public: - On_off(){}; - On_off(map<string,string> &settings) { - base_settings(settings); - }; - On_off* clone(map<string,string> &_settings) { return new On_off(_settings);}; - const float output(const Time_spec &time) { - if (inputs[0]->connection) { - float s1=(((Signal_node*)(inputs[0]->connection))->get_output(time)); - if ((int)s1%2) return 1.0f; - } - return 0.0f; - } - }; - //pseudo random repeatable hash function - //http://create.stephan-brumme.com/fnv-hash/ - const uint32_t Prime = 0x01000193; // 16777619 - const uint32_t Seed = 0x811C9DC5; // 2166136261 - /// hash a byte - inline uint32_t fnv1a(unsigned char oneByte, uint32_t hash = Seed) - { - return (oneByte ^ hash) * Prime; - } - /// hash a short (two bytes) - inline uint32_t fnv1a(unsigned short twoBytes, uint32_t hash = Seed) - { - const unsigned char* ptr = (const unsigned char*) &twoBytes; - hash = fnv1a(*ptr++, hash); - return fnv1a(*ptr , hash); - } - /// hash a 32 bit integer (four bytes) - inline uint32_t fnv1a(uint32_t fourBytes, uint32_t hash = Seed) - { - const unsigned char* ptr = (const unsigned char*) &fourBytes; - hash = fnv1a(*ptr++, hash); - hash = fnv1a(*ptr++, hash); - hash = fnv1a(*ptr++, hash); - return fnv1a(*ptr , hash); - } - class Random: public Signal_node { - public: - Random(){}; - Random(map<string,string> &settings) { - base_settings(settings); - seed=(Seed+find_setting(settings,"seed",0)); - cerr<<"random:: seed "<<seed<<" ("<<Seed<<")"<<endl; - }; - Random* clone(map<string,string> &_settings) { return new Random(_settings);}; - const float output(const Time_spec &time) { - if (inputs.size()) { - if (inputs[0]->connection) { - - //hash the integer part and add the fractional part back on - float o=(((Signal_node*)inputs[0]->connection)->get_output(time)); - uint32_t m=(int)o; - return ((float)(fnv1a(m,seed)%((uint32_t)time.duration)))+(o-m); - } - } - return 0.0f; - } - uint32_t seed; - private: - }; class Signal_output: public Signal_node { public: Signal_output(){}; @@ -700,6 +481,11 @@ namespace Rotor { Image image; uint8_t prevcol; }; +#define ARITHMETIC_plus 1 +#define ARITHMETIC_minus 2 +#define ARITHMETIC_multiply 3 +#define ARITHMETIC_divide 4 +#define ARITHMETIC_modulo 5 class Image_arithmetic: public Image_node { //Draws signal bars in greyscale public: @@ -708,13 +494,12 @@ namespace Rotor { 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? + if (_op=="+"||_op=="plus"||_op=="add") op=ARITHMETIC_plus; + if (_op=="-"||_op=="minus"||_op=="subtract") op=ARITHMETIC_minus; + if (_op=="*"||_op=="x"||_op=="multiply") op=ARITHMETIC_multiply; + if (_op=="/"||_op=="divide") op=ARITHMETIC_divide; + //if (_op=="%"||_op=="mod"||_op=="modulo"||_op=="modulus") op=ARITHMETIC_modulo; ??what would this even mean? image=nullptr; - cerr<<"image_arithmetic: mode "<<op<<", value "<<value<<endl; } void link_params() { for (auto p:parameter_inputs){ @@ -1414,6 +1199,7 @@ namespace Rotor { media_dir=xml.getAttribute("Rotor","media_dir","",0); output_dir=xml.getAttribute("Rotor","output_dir","",0); } + else cerr<<"Rotor: settings.xml not found, using defaults"<<endl; }; ~Render_context(){delete audio_thumb;}; |
