diff options
| author | Tim Redfern <tim@eclectronics.org> | 2013-10-29 14:45:49 +0000 |
|---|---|---|
| committer | Tim Redfern <tim@eclectronics.org> | 2013-10-29 14:45:49 +0000 |
| commit | 858cb95b8539f5695c5348c340b9f982d8b66719 (patch) | |
| tree | bed7d5c75de92d4b15d74311f6385aba7bac49da /rotord/src | |
| parent | 9fc8a2e7b770339b72c080cfa510c461706fe43c (diff) | |
making intensity segmenter
Diffstat (limited to 'rotord/src')
| -rw-r--r-- | rotord/src/nodes_audio_analysis.cpp | 4 | ||||
| -rw-r--r-- | rotord/src/nodes_audio_analysis.h | 95 | ||||
| -rw-r--r-- | rotord/src/rendercontext.cpp | 2 | ||||
| -rw-r--r-- | rotord/src/rotor.cpp | 90 | ||||
| -rw-r--r-- | rotord/src/rotor.h | 15 | ||||
| -rw-r--r-- | rotord/src/vampHost.cpp | 35 | ||||
| -rw-r--r-- | rotord/src/vampHost.h | 2 |
7 files changed, 162 insertions, 81 deletions
diff --git a/rotord/src/nodes_audio_analysis.cpp b/rotord/src/nodes_audio_analysis.cpp index 220f14b..1e65668 100644 --- a/rotord/src/nodes_audio_analysis.cpp +++ b/rotord/src/nodes_audio_analysis.cpp @@ -83,11 +83,11 @@ namespace Rotor{ } void Vamp_node::cleanup() { analyser.cleanup(); - //print_features(); + features=analyser.features; } string Vamp_node::get_features(){ string data; - for (auto i: analyser.features) { + for (auto i: features) { data=data+" ["+toString(i.second.number)+":"+toString(i.first); if (i.second.values.size()) { data+=" ("; diff --git a/rotord/src/nodes_audio_analysis.h b/rotord/src/nodes_audio_analysis.h index 44ea3eb..620f277 100644 --- a/rotord/src/nodes_audio_analysis.h +++ b/rotord/src/nodes_audio_analysis.h @@ -9,6 +9,18 @@ namespace Rotor { #define VAMPHOST_Timesteps 2 #define VAMPHOST_Valueline 3 #define VAMPHOST_Values 4 + class Audio_processor: public Signal_node { + public: + virtual Audio_processor(){}; + virtual ~Audio_processor(){}; + virtual int process_frame(uint8_t *data,int samples)=0; + virtual bool init(int _channels,int _bits,int _samples,int _rate)=0; + virtual void cleanup()=0; + virtual void print_summary(){}; + virtual string get_features(){}; + int channels,bits,samples,rate; + }; + //actual nodes------------------------------------------------- class Audio_thumbnailer: public Audio_processor { public: Audio_thumbnailer(){ @@ -43,9 +55,9 @@ namespace Rotor { void cleanup(); int process_frame(uint8_t *data,int samples_in_frame); const float output(const Time_spec &time) { - if (analyser.features.size()) { - auto i=analyser.features.upper_bound(time.time); //the first element in the container whose key is considered to go after k - if (i!=analyser.features.end()){ + if (features.size()) { + auto i=features.upper_bound(time.time); //the first element in the container whose key is considered to go after k + if (i!=features.end()){ float uk=i->first; float v1,v2; v1=v2=0.0f; @@ -72,15 +84,15 @@ namespace Rotor { } string get_features(); void print_summary(){ - cerr<<"vamp plugin "<<id<<" of library "<<soname<<" found "<<analyser.features.size()<<" features "<<endl; + cerr<<"vamp plugin "<<id<<" of library "<<soname<<" found "<<features.size()<<" features "<<endl; }; protected: string soname,id; - int outputNo; - vampHost::Analyser analyser; - private: - //?? + int outputNo; map <string,float> params; + map<float,vampHost::feature> features; + private: + vampHost::Analyser analyser; }; class Audio_analysis: public Vamp_node { //vamp node that allows the user to choose a plugin @@ -170,20 +182,20 @@ namespace Rotor { vector<int> act_count; for (int i=0;i<(int)parameters["acts"]->value;i++) act_count.push_back(0); - if (analyser.features.size()<=(int)parameters["acts"]->value+1){ + if (features.size()<=(int)parameters["acts"]->value+1){ //iteratively split segments and refresh durations //this could work well on the original data //pick the longest and split it in two //refresh durations - this can be a function //keep going //finally copy out - while (analyser.features.size()<(int)parameters["acts"]->value+1){ + while (features.size()<(int)parameters["acts"]->value+1){ map<int,float> durations; map<int,float> times; int i=0; - for (map<float,vampHost::feature>::iterator f=analyser.features.begin();f!=analyser.features.end();++f){ + for (map<float,vampHost::feature>::iterator f=features.begin();f!=features.end();++f){ auto g=f; - if (++g!=analyser.features.end()){ + if (++g!=features.end()){ durations[i]=g->first-f->first; times[i]=f->first; } @@ -197,10 +209,10 @@ namespace Rotor { n=d.first; } } - analyser.features[times[n]+(durations[n]/2)]=analyser.features[times[n]]; + features[times[n]+(durations[n]/2)]=features[times[n]]; } int j=0; - for (auto f: analyser.features){ + for (auto f: features){ f.second.number=j; acts[f.first]=f.second; j++; @@ -216,7 +228,7 @@ namespace Rotor { //start with a set of the segments numbers //(the aim: to access the segment numbers by the time that they start) - map<float,vampHost::feature> segments=analyser.features; + map<float,vampHost::feature> segments=features; segments.erase(--segments.end()); //assign the acts from the beginning and end in towards the middle @@ -260,12 +272,61 @@ namespace Rotor { } } //add last item back on - acts[(*--analyser.features.end()).first]=analyser.features[(*--analyser.features.end()).first]; - analyser.features=acts; + acts[(*--features.end()).first]=features[(*--features.end()).first]; + features=acts; } private: }; + class Intensity_segmenter: public Vamp_node { + //vamp node that applies a ruleset to manage a set of acts via a cycler + public: + Intensity_segmenter(){ + title="Intensity segmenter"; + description="Combines the output of segmentation, tempo, and intensity analysis plugins"; + UID="6ce236b6-4080-11e3-90b7-74d02b29f6a6"; + analysers["segmenter"]=vampHost::Analyser(); + analysers["tempo"]=vampHost::Analyser(); + analysers["intensity"]=vampHost::Analyser(); + }; + Intensity_segmenter(map<string,string> &settings):Intensity_segmenter() { + base_settings(settings); + }; + ~Intensity_segmenter(){}; + Intensity_segmenter* clone(map<string,string> &_settings) { return new Intensity_segmenter(_settings);}; + bool init(int _channels,int _bits,int _samples,int _rate) { + return analysers["segmenter"].init("qm-vamp-plugins","qm-segmenter",_channels,_bits,_samples,_rate,0,params)\ + &&analysers["tempo"].init("qm-vamp-plugins","qm-tempotracker",_channels,_bits,_samples,_rate,2,params)\ + &&analysers["intensity"].init("bbc-vamp-plugins","bbc-intensity",_channels,_bits,_samples,_rate,0,params); + } + int process_frame(uint8_t *data,int samples_in_frame) { + //for (auto a:analysers) a.second.process_frame(data,samples_in_frame); //WHY NOT WORK + analysers["segmenter"].process_frame(data,samples_in_frame); + analysers["tempo"].process_frame(data,samples_in_frame); + analysers["intensity"].process_frame(data,samples_in_frame); + return 1; + } + void cleanup(){ + //for (auto a:analysers) a.second.cleanup(); //WHY NOT WORK - its as if the call is const + analysers["segmenter"].cleanup(); + analysers["tempo"].cleanup(); + analysers["intensity"].cleanup(); + cerr<<analysers["segmenter"].features.size()<<" segments"<<endl; + cerr<<analysers["tempo"].features.size()<<" tempo features"<<endl; + cerr<<analysers["intensity"].features.size()<<" intensity features"<<endl; + //auto f=analysers["segmenter"].features.begin(); + //for (auto g=++analysers["segmenter"].features.begin();g!=analysers["segmenter"].features.end();f++,g++){ + // cerr<<"calculating segment from "<<f.first<<" to "<<g.first<<endl; + // features[f.first]=f.second; + //} + return true; + } + void print_summary(){ + cerr<<"Intensity segmenter found "<<features.size()<<" features "<<endl; + }; + private: + map<string,vampHost::Analyser> analysers; + }; } #endif diff --git a/rotord/src/rendercontext.cpp b/rotord/src/rendercontext.cpp index bba8d31..359116f 100644 --- a/rotord/src/rendercontext.cpp +++ b/rotord/src/rendercontext.cpp @@ -428,7 +428,7 @@ void Render_context::session_command(const Session_command& command,xmlIO& XML,H } else { status=HTTPResponse::HTTP_BAD_REQUEST; - logger.error("ERROR: Could not print features for node "+features_node); + logger.error("ERROR: Could not print features for node /"+features_node+"/"); } } else { diff --git a/rotord/src/rotor.cpp b/rotord/src/rotor.cpp index d3a5486..a4ef055 100644 --- a/rotord/src/rotor.cpp +++ b/rotord/src/rotor.cpp @@ -19,60 +19,61 @@ Node_factory::Node_factory(){ //this can be hard coded also // - category["signals"]=vector<Node*>(); - add_type("time",new Time(),category["signals"]); - add_type("track_time",new Track_time(),category["signals"]); - add_type("at_track_time",new At_track_time(),category["signals"]); + category["Signals"]=vector<Node*>(); + add_type("time",new Time(),category["Signals"]); + add_type("track_time",new Track_time(),category["Signals"]); + add_type("at_track_time",new At_track_time(),category["Signals"]); // add_type("signal_output",new Signal_output()); add_type("testcard",new Testcard()); // - category["channels"]=vector<Node*>(); - add_type("invert",new Invert(),category["channels"]); - add_type("monochrome",new Monochrome(),category["channels"]); - add_type("blend",new Blend(),category["channels"]); - add_type("image_arithmetic",new Image_arithmetic(),category["channels"]); - add_type("alpha_merge",new Alpha_merge(),category["channels"]); - add_type("difference_matte",new Difference_matte(),category["channels"]); - add_type("rgb_levels",new RGB_levels(),category["channels"]); - add_type("luma_levels",new Luma_levels(),category["channels"]); + category["Channels"]=vector<Node*>(); + add_type("invert",new Invert(),category["Channels"]); + add_type("monochrome",new Monochrome(),category["Channels"]); + add_type("blend",new Blend(),category["Channels"]); + add_type("image_arithmetic",new Image_arithmetic(),category["Channels"]); + add_type("alpha_merge",new Alpha_merge(),category["Channels"]); + add_type("difference_matte",new Difference_matte(),category["Channels"]); + add_type("rgb_levels",new RGB_levels(),category["Channels"]); + add_type("luma_levels",new Luma_levels(),category["Channels"]); - category["source"]=vector<Node*>(); - add_type("signal_colour",new Signal_colour(),category["source"]); - add_type("signal_greyscale",new Signal_greyscale(),category["source"]); - add_type("shape",new Shape(),category["source"]); - add_type("text",new Text(),category["source"]); - add_type("waves",new Waves(),category["source"]); - add_type("still_image",new Still_image(),category["source"]); - add_type("video_loader",new Video_loader(),category["source"]); - add_type("svg",new Svg(),category["source"]); + category["Source"]=vector<Node*>(); + add_type("signal_colour",new Signal_colour(),category["Source"]); + add_type("signal_greyscale",new Signal_greyscale(),category["Source"]); + add_type("shape",new Shape(),category["Source"]); + add_type("text",new Text(),category["Source"]); + add_type("waves",new Waves(),category["Source"]); + add_type("still_image",new Still_image(),category["Source"]); + add_type("video_loader",new Video_loader(),category["Source"]); + add_type("svg",new Svg(),category["Source"]); - category["distort"]=vector<Node*>(); - add_type("mirror",new Mirror(),category["distort"]); - add_type("transform",new Transform(),category["distort"]); + category["Distort"]=vector<Node*>(); + add_type("mirror",new Mirror(),category["Distort"]); + add_type("transform",new Transform(),category["Distort"]); - category["editing"]=vector<Node*>(); - add_type("video_cycler",new Video_cycler(),category["editing"]); - add_type("video_output",new Video_output(),category["editing"]); - add_type("act_segmenter",new Act_segmenter(),category["editing"]); + category["Editing"]=vector<Node*>(); + add_type("video_cycler",new Video_cycler(),category["Editing"]); + add_type("video_output",new Video_output(),category["Editing"]); + add_type("act_segmenter",new Act_segmenter(),category["Editing"]); - category["audio"]=vector<Node*>(); - add_type("audio_analysis",new Audio_analysis(),category["audio"]); - add_type("audio_analysis2",new Audio_analysis2(),category["audio"]); + category["Audio"]=vector<Node*>(); + add_type("audio_analysis",new Audio_analysis(),category["Audio"]); + add_type("audio_analysis2",new Audio_analysis2(),category["Audio"]); + add_type("intensity_segmenter",new Intensity_segmenter(),category["Audio"]); - category["maths"]=vector<Node*>(); - add_type("comparison",new Comparison(),category["maths"]); //TODO: alias to symbols - add_type("arithmetic",new Arithmetic(),category["maths"]); //TODO: alias to symbols - add_type("bang",new Is_new_integer(),category["maths"]); - add_type("on_off",new On_off(),category["maths"]); - add_type("random",new Random(),category["maths"]); - add_type("noise",new Noise(),category["maths"]); + category["Maths"]=vector<Node*>(); + add_type("comparison",new Comparison(),category["Maths"]); //TODO: alias to symbols + add_type("arithmetic",new Arithmetic(),category["Maths"]); //TODO: alias to symbols + add_type("bang",new Is_new_integer(),category["Maths"]); + add_type("on_off",new On_off(),category["Maths"]); + add_type("random",new Random(),category["Maths"]); + add_type("noise",new Noise(),category["Maths"]); - category["fx"]=vector<Node*>(); - add_type("blur",new Blur(),category["fx"]); - add_type("vhs",new VHS(),category["fx"]); - add_type("echo_trails",new Echo_trails(),category["fx"]); - add_type("video_feedback",new Video_feedback(),category["fx"]); + category["FX"]=vector<Node*>(); + add_type("blur",new Blur(),category["FX"]); + add_type("vhs",new VHS(),category["FX"]); + add_type("echo_trails",new Echo_trails(),category["FX"]); + add_type("video_feedback",new Video_feedback(),category["FX"]); } bool Signal_input::connect(Node* source) { @@ -209,6 +210,7 @@ void Node_factory::list_categories(Json::Value &JSON){ category["name"]=_category.first; category["nodes"]=Json::arrayValue; for (auto& _node: _category.second){ + cerr<<"Adding "<<_category.first<<":"<<_node->type<<endl; Json::Value node; node["type"]=_node->type; node["title"]=_node->title; diff --git a/rotord/src/rotor.h b/rotord/src/rotor.h index d9ba66d..f179efd 100644 --- a/rotord/src/rotor.h +++ b/rotord/src/rotor.h @@ -342,17 +342,6 @@ namespace Rotor { protected: unsigned char *lut; }; - class Audio_processor: public Signal_node { - public: - virtual Audio_processor(){}; - virtual ~Audio_processor(){}; - virtual int process_frame(uint8_t *data,int samples)=0; - virtual bool init(int _channels,int _bits,int _samples,int _rate)=0; - virtual void cleanup()=0; - virtual void print_summary(){}; - virtual string get_features(){}; - int channels,bits,samples,rate; - }; //actual nodes------------------------------------------------- #define CYCLER_cut 1 #define CYCLER_mix 2 @@ -712,8 +701,8 @@ namespace Rotor { void list_categories(xmlIO XML); void list_categories(Json::Value &JSON); private: - unordered_map<string,Node*> type_map; - unordered_map<string,vector<Rotor::Node*> > category; + map<string,Node*> type_map; + map<string,vector<Rotor::Node*> > category; }; } diff --git a/rotord/src/vampHost.cpp b/rotord/src/vampHost.cpp index 7bdbb0d..2ddc62f 100644 --- a/rotord/src/vampHost.cpp +++ b/rotord/src/vampHost.cpp @@ -275,6 +275,10 @@ bool vampHost::Analyser::init(const string &soname,const string &id,const int &_ return false; } + cerr << "Vamphost Plugin initialised: (channels = " << channels + << ", stepSize = " << stepSize << ", blockSize = " + << blockSize << ")" << endl; + wrapper = dynamic_cast<PluginWrapper *>(plugin); if (wrapper) { // See documentation for @@ -294,6 +298,7 @@ bool vampHost::Analyser::init(const string &soname,const string &id,const int &_ return true; } void vampHost::Analyser::process_frame(uint8_t *data,int samples_in_frame){ + int sample=0; uint16_t *_data=(uint16_t*)data; @@ -317,20 +322,25 @@ void vampHost::Analyser::process_frame(uint8_t *data,int samples_in_frame){ //I /think/ that the vamp plugin keeps processing through the plugbuf until it encounters 0s rt = RealTime::frame2RealTime(currentStep * stepSize, rate); //48000); //setting different rate doesn't affect it + Plugin::FeatureSet feat=plugin->process(plugbuf, rt); + float t; + for (unsigned int i = 0; i < feat[outputNo].size(); ++i) { feature f; f.number=featureNo; f.values=feat[outputNo][i].values; //fix for plugins that don't set timestamp properly - float t=((float)feat[outputNo][i].timestamp.sec)+(((float)feat[outputNo][i].timestamp.nsec)*.000000001); + t=((float)feat[outputNo][i].timestamp.sec)+(((float)feat[outputNo][i].timestamp.nsec)*.000000001); if (t<.01) t=((rt.sec)+(rt.nsec)*.000000001); features[t]=f; featureNo++; } + //if (feat[outputNo].size()>0) cerr<<"vamphost: "<<t<<":"<<features.size()<<" features"<<endl; + //shunt it down for (int i=0;i<blockSize-stepSize;i++){ for (int j=0;j<channels;j++){ @@ -338,13 +348,14 @@ void vampHost::Analyser::process_frame(uint8_t *data,int samples_in_frame){ } } + //if (feat[outputNo].size()>0) cerr<<plugin->getIdentifier()<<" step:"<<currentStep<<" sample:"<<currentStep * stepSize<<" features:"<<features.size()<<endl; + in_block-=stepSize; - currentStep++; + currentStep++; //WTF this number does not increase when called the 2nd way } } } void vampHost::Analyser::cleanup(){ - //process final block while(in_block<blockSize) { for (int i=0;i<channels;i++) { @@ -389,3 +400,21 @@ void vampHost::Analyser::cleanup(){ delete[] plugbuf; delete plugin; } +float vampHost::Analyser::get_value(const float &time) { + if (features.size()) { + auto i=features.upper_bound(time); //the first element in the container whose key is considered to go after k + if (i!=features.end()){ + float uk=i->first; + float v1,v2; + v1=v2=0.0f; + if (i->second.values.size()) v2=i->second.values[0]; + i--; + float lk=i->first; + int ln=i->second.number; + if (i->second.values.size()) v1=i->second.values[0]; + + return ((((time-lk)/(uk-lk))*(v2-v1))+v1); + } + } + return 0.0f; +} diff --git a/rotord/src/vampHost.h b/rotord/src/vampHost.h index 56de901..856a2cc 100644 --- a/rotord/src/vampHost.h +++ b/rotord/src/vampHost.h @@ -64,7 +64,7 @@ namespace vampHost { bool init(const string &soname,const string &id,const int &_channels,const int &_bits,const int &_samples,const int &_rate,int outputNo,const map<string,float> ¶ms); void process_frame(uint8_t *data,int samples_in_frame); void cleanup(); - + float get_value(const float &time); //map<double,int> features; map<float,feature> features; //map<time,featureNo> |
