diff options
| -rw-r--r-- | rotord/05.xml | 2 | ||||
| -rw-r--r-- | rotord/09.xml | 16 | ||||
| -rw-r--r-- | rotord/graph.cpp | 1 | ||||
| -rw-r--r-- | rotord/libavexporter.h | 6 | ||||
| -rw-r--r-- | rotord/rendercontext.cpp | 15 | ||||
| -rwxr-xr-x | rotord/rotor.cpp | 11 | ||||
| -rwxr-xr-x | rotord/rotor.h | 43 | ||||
| -rw-r--r-- | rotord/vampHost.cpp | 12 | ||||
| -rw-r--r-- | rotord/vampHost.h | 2 |
9 files changed, 73 insertions, 35 deletions
diff --git a/rotord/05.xml b/rotord/05.xml index 93191dd..4566be3 100644 --- a/rotord/05.xml +++ b/rotord/05.xml @@ -1,6 +1,6 @@ <?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 ID="01" type="audio_analysis" soname="qm-vamp-plugins" id="qm-barbeattracker" output="signal">beats </node> <node ID="02" type="audio_analysis" soname="qm-vamp-plugins" id="qm-segmenter" output="signal">segmentation </node> diff --git a/rotord/09.xml b/rotord/09.xml index 72ba45c..91bbaf9 100644 --- a/rotord/09.xml +++ b/rotord/09.xml @@ -2,13 +2,19 @@ <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="arithmetic" operator="%" value="2.0" output="signal">signal arithmetic + <node ID="02" type="audio_analysis" soname="qm-vamp-plugins" id="qm-segmenter" output="signal">beats + <parameter name="Feature Type" value="2"/> + </node> + <node ID="02" type="arithmetic" operator="%" value="1.0" output="signal">signal arithmetic <signal_input from="01">signal to operate on</signal_input> </node> - <node ID="03" type="signal_greyscale" output="image">bar greyscale fading - <signal_input from="02">signal to visualise</signal_input> + <node ID="03" type="testcard" output="image">testcard + </node> + <node ID="04" type="image_arithmetic" operator="*" value="1.0" output="image">colour segmentation + <parameter_input parameter="value" from="02">value control</parameter_input> + <image_input from="03">image to operate on</image_input> </node> - <node ID="04" type="video_output">video output - <image_input from="03">image to output</image_input> + <node ID="06" type="video_output">video output + <image_input from="04">image to output</image_input> </node> </patchbay> diff --git a/rotord/graph.cpp b/rotord/graph.cpp index 57cae92..eedcd88 100644 --- a/rotord/graph.cpp +++ b/rotord/graph.cpp @@ -97,6 +97,7 @@ bool Graph::load(string &filename){ } else cerr << "Rotor: linking parameter input " << i4 << " of node: '" << nodeID << "', cannot find target '" << fromID << "'" << endl; } + nodes[nodeID]->link_params(); xml.popTag(); } } diff --git a/rotord/libavexporter.h b/rotord/libavexporter.h index c5e66e3..03b7580 100644 --- a/rotord/libavexporter.h +++ b/rotord/libavexporter.h @@ -459,6 +459,12 @@ namespace libav { ret = 0; } } + + // + // added 22 may in memory leak run + // + sws_freeContext(sws_ctx); //should be done once per render instead of per frame?? + if (ret != 0) { //fprintf(stderr, "Error while writing video frame: %s\n", av_err2str(ret)); exit(1); diff --git a/rotord/rendercontext.cpp b/rotord/rendercontext.cpp index 624b7c1..dec9f34 100644 --- a/rotord/rendercontext.cpp +++ b/rotord/rendercontext.cpp @@ -18,7 +18,7 @@ void Render_context::runTask() { for (auto a: analysers) { processors.push_back(dynamic_cast<Base_audio_processor*>(a)); } - if (_load_audio(audio_filename,processors)) { + if (load_audio(audio_filename,processors)) { audio_loaded=true; state=IDLE; } @@ -268,6 +268,7 @@ Command_response Render_context::session_command(const std::vector<std::string>& } return response; } +/* //http://blog.tomaka17.com/2012/03/libavcodeclibavformat-tutorial/ //great to use c++11 features @@ -289,7 +290,8 @@ bool Render_context::load_audio(const string &filename,vector<Base_audio_process return true; } -bool Render_context::_load_audio(const string &filename,vector<Base_audio_processor*> processors){ +*/ +bool Render_context::load_audio(const string &filename,vector<Base_audio_processor*> processors){ av_register_all(); @@ -358,10 +360,14 @@ bool Render_context::_load_audio(const string &filename,vector<Base_audio_proces graph.duration=((float)formatContext->duration)/AV_TIME_BASE; std::cout << "This stream has " << codecContext->channels << " channels, a sample rate of " << codecContext->sample_rate << "Hz and "<<samples <<" samples" << std::endl; - std::cout << "The data is in format " <<codecContext->sample_fmt<< " (aka "<< av_get_sample_fmt_name(codecContext->sample_fmt) << ") "<<std::endl; + std::cout << "The data is in format " <<codecContext->sample_fmt<< " (aka "<< av_get_sample_fmt_name(codecContext->sample_fmt) << ")"<<std::endl; + //std::cout << "Decoding to format " <<frame->format<< " at "<<frame->sample_rate<<" Hz"<<std::endl; + + //frame->sample_rate=codecContext->sample_rate; + map <std::string,float> params; for (auto p: processors) { - if(!p->init(codecContext->channels,16,samples,codecContext->sample_rate) ){ + if(!p->init(codecContext->channels,16,samples,codecContext->sample_rate,params) ){ cerr<<"Plugin failed to initialse"<<endl; return false; } @@ -438,6 +444,7 @@ bool Render_context::_load_audio(const string &filename,vector<Base_audio_proces // Clean up! for (auto p: processors) { p->cleanup(); + p->print_summary(); } diff --git a/rotord/rotor.cpp b/rotord/rotor.cpp index 18988ed..3450607 100755 --- a/rotord/rotor.cpp +++ b/rotord/rotor.cpp @@ -65,7 +65,7 @@ bool Signal_output::render(const float duration, const float framerate,string &x return true; } -bool Audio_thumbnailer::init(int _channels,int _bits,int _samples,int _rate) { +bool Audio_thumbnailer::init(int _channels,int _bits,int _samples,int _rate,const map<string,float> ¶ms) { //base_audio_processor::init(_channels,_bits,_samples); channels=_channels; bits=_bits; @@ -145,13 +145,13 @@ string Audio_thumbnailer::print(){ delete enc; return output.str(); } -bool Audio_analysis::init(int _channels,int _bits,int _samples, int _rate) { +bool Audio_analysis::init(int _channels,int _bits,int _samples, int _rate, const map<string,float> ¶ms) { //need these to make sense of data channels=_channels; bits=_bits; samples=_samples; - return analyser.init(soname,id,_channels,_bits,_samples,_rate); + return analyser.init(soname,id,_channels,_bits,_samples,_rate,outputNo,params); //attempt to load vamp plugin and prepare to receive frames of data //should the audio analysis contain a vamphost or should it inherit? @@ -164,12 +164,13 @@ int Audio_analysis::process_frame(uint8_t *data,int samples_in_frame) { } void Audio_analysis::cleanup() { analyser.cleanup(); - //print_features(); + print_features(); } void Audio_analysis::print_features(){ for (auto i: analyser.features) { - cerr<<i.second<<" "<<i.first<<endl; + cerr<<" ["<<i.second<<":"<<i.first<<"]"; } + cerr<<endl; } bool Video_output::render(const float duration, const float framerate,const string &output_filename,const string &audio_filename,float& progress){ diff --git a/rotord/rotor.h b/rotord/rotor.h index 137f8ee..6ca5da2 100755 --- a/rotord/rotor.h +++ b/rotord/rotor.h @@ -338,6 +338,7 @@ namespace Rotor { class Node{ public: virtual Node* clone(map<string,string> &_settings)=0; + virtual ~Node(){}; UUID uid; //every usable node has a UUID int id; vector<Signal_input*> inputs; //simple node can have signal inputs, output depends on node type @@ -357,6 +358,7 @@ namespace Rotor { output_type=find_setting(settings,"output"); ID=find_setting(settings,"ID"); } + virtual void link_params(){}; //TODO make param classes that link automatically void update_params(const Time_spec& time); }; class Signal_node: public Node{ @@ -378,8 +380,9 @@ namespace Rotor { class Base_audio_processor: public Signal_node { public: virtual int process_frame(uint8_t *data,int samples)=0; - virtual bool init(int _channels,int _bits,int _samples,int _rate)=0; + virtual bool init(int _channels,int _bits,int _samples,int _rate,const map<string,float> ¶ms)=0; virtual void cleanup()=0; + virtual void print_summary(){}; int channels,bits,samples,rate; }; //actual nodes------------------------------------------------- @@ -390,28 +393,29 @@ namespace Rotor { base_settings(settings); soname=find_setting(settings,"soname"); id=find_setting(settings,"id"); - outputNo=ofToInt(find_setting(settings,"output","0")); + outputNo=find_setting(settings,"outputNo",0); }; Audio_analysis* clone(map<string,string> &_settings) { return new Audio_analysis(_settings);}; - bool init(int _channels,int _bits,int _samples,int _rate); + bool init(int _channels,int _bits,int _samples,int _rate,const map<string,float> ¶ms); 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.lower_bound(time.time); + 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()){ + float uk=i->first; + i--; float lk=i->first; int ln=i->second; - if (i++!=analyser.features.end()){ - float uk=i->first; - return (((time.time-lk)/(uk-lk))+ln); - } - else return (float)ln; + return (((time.time-lk)/(uk-lk))+ln); } } return 0.0f; } void print_features(); + void print_summary(){ + cerr<<"vamp plugin "<<id<<" of library "<<soname<<" found "<<analyser.features.size()<<" features "<<endl; + }; private: string soname,id; int outputNo; @@ -447,6 +451,8 @@ namespace Rotor { 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; } @@ -500,7 +506,10 @@ namespace Rotor { 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; } }; @@ -818,10 +827,15 @@ namespace Rotor { if (_op=="*") op=ARITHMETIC_multiply; if (_op=="/") op=ARITHMETIC_divide; //if (_op=="%") op=ARITHMETIC_modulo; ??what would this even mean? + image=nullptr; + } + void link_params() { for (auto p:parameter_inputs){ - if (p->parameter=="value") p->receiver=&value; + if (p->parameter=="value") { + p->receiver=&value; + } } - image=nullptr; + }; ~Image_arithmetic(){if (image) delete image;}; Image *output(const Frame_spec &frame){ @@ -863,6 +877,8 @@ namespace Rotor { base_settings(settings); levels_settings(settings); image=new Image(); + } + void link_params() { for (auto p:parameter_inputs){ if (p->parameter=="black_in") p->receiver=&black_in; if (p->parameter=="white_in") p->receiver=&white_in; @@ -954,6 +970,8 @@ namespace Rotor { image=new Image(); lastframe=-1; mode=find_setting(settings,"mode",0.0f); + } + void link_params() { for (auto p:parameter_inputs){ if (p->parameter=="black_in") p->receiver=&black_in; if (p->parameter=="white_in") p->receiver=&white_in; @@ -1105,7 +1123,7 @@ namespace Rotor { delete[] data; }; Audio_thumbnailer* clone(map<string,string> &_settings) { return new Audio_thumbnailer();}; - bool init(int _channels,int _bits,int _samples,int _rate); + bool init(int _channels,int _bits,int _samples,int _rate,const map<string,float> ¶ms); void cleanup(){}; int process_frame(uint8_t *data,int samples_in_frame); string print(); @@ -1134,7 +1152,6 @@ namespace Rotor { void cancel(); //interrupt locking process int make_preview(int nodeID, float time); //starts a frame preview - returns status code - how to retrieve? bool load_audio(const string &filename,vector<Base_audio_processor*> processors); - bool _load_audio(const string &filename,vector<Base_audio_processor*> processors); Render_requirements get_requirements(); bool load_video(const string &nodeID,const string &filename);//can be performance or clip private: diff --git a/rotord/vampHost.cpp b/rotord/vampHost.cpp index 56d57db..14a9b35 100644 --- a/rotord/vampHost.cpp +++ b/rotord/vampHost.cpp @@ -588,7 +588,7 @@ float vampHost::QMAnalyser::get_progress(){ mutex.unlock(); return p; } -bool vampHost::Analyser::init(const string &soname,const string &id,const int &_channels,const int &_bits,const int &_samples,const int &_rate,const int &_outputNo,const string &_output){ +bool vampHost::Analyser::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){ //stuff that only happens once channels =_channels; @@ -596,7 +596,7 @@ bool vampHost::Analyser::init(const string &soname,const string &id,const int &_ rate=_rate; bits=_bits; outputNo=_outputNo; - output=_output; + //output=_output; //http://www.mega-nerd.com/libsndfile/api.html#note1 //libsndfile returns -1..1 for fp data @@ -692,7 +692,7 @@ bool vampHost::Analyser::init(const string &soname,const string &id,const int &_ } } od = outputs[outputNo]; - cerr << "Output is: \"" << od.identifier << "\"" << endl; + cerr << "Output number "<<outputNo<<": \"" << od.identifier << "\"" << endl; if (!plugin->initialise(channels, stepSize, blockSize)) { cerr << "ERROR: Plugin initialise (channels = " << channels @@ -741,7 +741,7 @@ void vampHost::Analyser::process_frame(uint8_t *data,int samples_in_frame){ //cerr<<plugin->getIdentifier()<<" processed block "<<blocks_processed<<endl; //I /think/ that the vamp plugin keeps processing through the plugbuf until it encounters 0s - rt = RealTime::frame2RealTime(currentStep * stepSize, rate); + rt = RealTime::frame2RealTime(currentStep * stepSize, rate); //48000); //setting different rate doesn't affect it Plugin::FeatureSet feat=plugin->process(plugbuf, rt); @@ -772,7 +772,7 @@ void vampHost::Analyser::cleanup(){ in_block++; } - rt = RealTime::frame2RealTime(currentStep * stepSize, rate); + rt = RealTime::frame2RealTime(currentStep * stepSize, rate); // //setting different Plugin::FeatureSet feat=plugin->process(plugbuf, rt); @@ -788,7 +788,7 @@ void vampHost::Analyser::cleanup(){ featureNo++; } - cerr<<plugin->getIdentifier()<<" found "<<(features.size()-1)<<" features"<<endl; + //cerr<<plugin->getIdentifier()<<" found "<<(features.size()-1)<<" features"<<endl; //deal with left over data? for (int c = 0; c < channels; ++c) { delete[] plugbuf[c]; diff --git a/rotord/vampHost.h b/rotord/vampHost.h index 3758055..0ba26fd 100644 --- a/rotord/vampHost.h +++ b/rotord/vampHost.h @@ -56,7 +56,7 @@ namespace vampHost { class Analyser{ //can load any vamp analysis plugin and present its data with a unified interface public: - bool init(const string &soname,const string &id,const int &_channels,const int &_bits,const int &_samples,const int &_rate,const int &_outputNo=0,const string &_output=""); + bool init(const string &soname,const string &id,const int &_channels,const int &_bits,const int &_samples,const int &_rate,const int outputNo,const map<string,float> ¶ms); void process_frame(uint8_t *data,int samples_in_frame); void cleanup(); |
