diff options
| author | Tim Redfern <tim@herge.(none)> | 2013-04-10 16:31:40 +0100 |
|---|---|---|
| committer | Tim Redfern <tim@herge.(none)> | 2013-04-10 16:31:40 +0100 |
| commit | a29217ecc368cdeee7e908fc7db3c717cc51fd70 (patch) | |
| tree | 1f6447cfecc19c90a98ff86cb575ad7109371267 | |
| parent | 6275e8f15b63f85c2206f0acb64023610c711f24 (diff) | |
signal and audio stuff working
| -rw-r--r-- | rotord/rotor.cpp | 23 | ||||
| -rwxr-xr-x | rotord/rotor.h | 35 | ||||
| -rwxr-xr-x | rotord/rotord.cpp | 37 |
3 files changed, 35 insertions, 60 deletions
diff --git a/rotord/rotor.cpp b/rotord/rotor.cpp index af0bd7e..360b75e 100644 --- a/rotord/rotor.cpp +++ b/rotord/rotor.cpp @@ -54,11 +54,12 @@ bool Signal_input::connect(Signal_node* source) { }; bool Signal_output::render(const float duration, const float framerate,string &xml_out){ + //testing signal routes cerr << "Rotor: Signal_output rendering " << duration << " seconds at " << framerate << " frames per second" << endl; float step=1.0f/framerate; float v=0.0f; for (float f=0.0f;f<duration;f+=step) { - float u=get_output(f); + float u=get_output(Time_spec(f,framerate)); if (!fequal(u,v)) { xml_out+=("<signal time='"+ofToString(f)+"'>"+ofToString(u)+"</signal>\n"); v=u; @@ -68,18 +69,18 @@ bool Signal_output::render(const float duration, const float framerate,string &x } Command_response Render_context::session_command(const std::vector<std::string>& command){ - //method,id,command1,{command2,}{body} - //here we allow the controlling server to communicate with running tasks + //method,id,command1,{command2,}{body} + //here we allow the controlling server to communicate with running tasks Command_response response; response.status=HTTPResponse::HTTP_BAD_REQUEST; if (command[2]=="audio") { - if (command[0]=="PUT") { //get audio file location and initiate analysis + if (command[0]=="PUT") { //get audio file location and initiate analysis if (command.size()>2) { if (state==IDLE) { - //check file exists + //check file exists Poco::File f=Poco::File(command[3]); if (f.exists()) { - //pass to worker thread ??if engine is ready?? ??what if engine has finished but results aren't read?? + //pass to worker thread ??if engine is ready?? ??what if engine has finished but results aren't read?? audio_filename=command[3]; //for now, store session variables in memory add_queue(ANALYSE_AUDIO); response.description="<status context='"+command[1]+"'>Starting audio analysis: "+command[3]+"</status>\n"; @@ -133,10 +134,10 @@ Command_response Render_context::session_command(const std::vector<std::string>& response.description="<status>Rotor: graph not loaded</status>\n"; } } - if (command[0]=="PUT") { //get new graph from file + if (command[0]=="PUT") { //get new graph from file if (command.size()>2) { - //should interrupt whatever is happening? - //before begining to load from xml + //should interrupt whatever is happening? + //before begining to load from xml if (state==IDLE) { //eventually not like this Poco::File f=Poco::File(command[3]); if (f.exists()) { @@ -173,7 +174,7 @@ Command_response Render_context::session_command(const std::vector<std::string>& if (command[0]=="GET") { //generate xml from 1st signal output if (state==IDLE) { //direct call for testing - float framerate=0.0f; + float framerate=25.0f; if (command.size()>2) { framerate=ofToFloat(command[3]); } @@ -324,6 +325,7 @@ bool Render_context::load_audio(const string &filename,vector<Base_audio_process av_dump_format(formatContext, 0, 0, false); //avformat.h line 1256 int samples = ((formatContext->duration + 5000)*codecContext->sample_rate)/AV_TIME_BASE; + 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; @@ -407,6 +409,7 @@ bool Render_context::load_audio(const string &filename,vector<Base_audio_process p->cleanup(); } + av_free(frame); avcodec_close(codecContext); av_close_input_file(formatContext); diff --git a/rotord/rotor.h b/rotord/rotor.h index 7dbb18d..36ef0aa 100755 --- a/rotord/rotor.h +++ b/rotord/rotor.h @@ -139,7 +139,15 @@ namespace Rotor { AVPacket packet; }; - + class Time_spec{ + public: + Time_spec(float _seconds,float _framerate){ seconds=_seconds; framerate=_framerate; }; + float seconds; + float framerate; + const Time_spec lastframe(){ + return Time_spec(seconds-(1.0f/framerate),framerate); + } + }; class Render_status{ public: int id; @@ -196,7 +204,7 @@ namespace Rotor { }; class Signal_node: public Node{ public: - virtual float get_output(const float &time) { return 0.0f; }; + virtual float get_output(const Time_spec &time) { return 0.0f; }; /*{ //default is to pass through first input, if disconnected returns 0 cerr << "getting output for " << type << "," << ID << endl; @@ -210,14 +218,14 @@ namespace Rotor { class Image_node: public Node{ public: vector<Image_input> image_inputs; //image node also has image inputs and outputs - Image* get_output(float time){ //sample implementation + Image* get_output(const Time_spec &time){ //sample implementation //do something with the inputs //and then return ((Image_node*)image_inputs[0].connection)->get_output(time); } - void get_preview(float time); + void get_preview(const Time_spec &time); Image* image; //this can be privately allocated or just passed on as the node see fit private: float image_time; @@ -243,15 +251,15 @@ namespace Rotor { bool init(int _channels,int _bits,int _samples,int _rate); void cleanup(); int process_frame(uint8_t *data,int samples_in_frame); - float get_output(const float &time) { + float get_output(const Time_spec &time) { if (analyser.features.size()) { - auto i=analyser.features.lower_bound(time); + auto i=analyser.features.lower_bound(time.seconds); if (i!=analyser.features.end()){ float lk=i->first; int ln=i->second; if (i++!=analyser.features.end()){ float uk=i->first; - return (((time-lk)/(uk-lk))+ln); + return (((time.seconds-lk)/(uk-lk))+ln); } else return (float)ln; } @@ -273,7 +281,7 @@ namespace Rotor { divide_amount=ofToFloat(check(settings,"amount")); }; Signal_divide* clone(map<string,string> &_settings) { return new Signal_divide(_settings);}; - float get_output(const float &time) { + float get_output(const Time_spec &time) { if (inputs[0]->connection) { return (((Signal_node*)inputs[0]->connection)->get_output(time))/divide_amount; } @@ -282,7 +290,8 @@ namespace Rotor { float divide_amount; }; class Is_new_integer: public Signal_node { - //does this require knowing what the framerate is? + //outputs a 1 every time a signal passes a new integer, otherwise a 0. + //this requires knowing what the framerate is? how to do this? //for now, assume 25 //what to cache? for now, don't cache public: @@ -291,10 +300,10 @@ namespace Rotor { base_settings(settings); }; Is_new_integer* clone(map<string,string> &_settings) { return new Is_new_integer(_settings);}; - float get_output(const float &time) { + float get_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-.04)); + float s2=(((Signal_node*)(inputs[0]->connection))->get_output(time.lastframe())); if (((int)s1)>((int)s2)) { return 1.0f; } @@ -310,7 +319,7 @@ namespace Rotor { }; Signal_output* clone(map<string,string> &_settings) { return new Signal_output(_settings);}; bool render(const float duration, const float framerate,string &xml_out); - float get_output(const float &time) { + float get_output(const Time_spec &time) { if (inputs[0]->connection) { return ((Signal_node*)(inputs[0]->connection))->get_output(time); } @@ -369,11 +378,11 @@ namespace Rotor { bool load(string &graph_filename); UUID save(); //save to DB, returns UUID of saved graph bool loaded; + float duration; const string toString(); private: Node_factory factory; float framerate; - float duration; xmlIO xml; }; class Audio_thumbnailer: public Base_audio_processor { diff --git a/rotord/rotord.cpp b/rotord/rotord.cpp index 734e159..a919a0b 100755 --- a/rotord/rotord.cpp +++ b/rotord/rotord.cpp @@ -124,43 +124,6 @@ HTTPRequestHandler* RotorRequestHandlerFactory::createRequestHandler(const HTTPS os<<request.stream().rdbuf(); body=os.str(); - - /* - if (segments.size() == 0) { - return new RotorRequestHandler(_format); - } - else if (segments[0]=="vamp"&&segments.size()>3) { - // vamp/plugin/filter/filename - // how do deal with error condition? - - //Settings(string _so="",string _filter="",string _id="",string _input=""); - return new AudioAnalyserHandler(vampHost::Settings(segments[1],segments[2],segments[3])); - //string audioData=runPlugin(string myname, string soname, string id, - // string output, int outputNo, string wavname, - // string outfilename, bool useFrames); - return 0; - } - else if (segments[0]=="new") { - // create a new render context - - return 0; - } - else { - return 0; - } - */ - - - //at this point we are within app - //making a new contexthandler? - //how will this have access to the thread that it refers to - //how will messages be passed - //we need to do testing etc here and - - //what does the handler do? - //it gets passed the response- gets to set response code - - if (command.size()) { if (command[0]=="new") { if (request.getMethod()=="GET") { |
