From 48ec56201e2240dcda68f2c384bacc3bdcb405ba Mon Sep 17 00:00:00 2001 From: Tim Redfern Date: Fri, 6 Sep 2013 15:04:38 +0100 Subject: act segmenter v1 --- rotord/src/nodes_audio_analysis.h | 86 ++++++++++++++++++++++++++++++++++----- 1 file changed, 75 insertions(+), 11 deletions(-) (limited to 'rotord/src/nodes_audio_analysis.h') diff --git a/rotord/src/nodes_audio_analysis.h b/rotord/src/nodes_audio_analysis.h index de90d13..7a0ed9e 100644 --- a/rotord/src/nodes_audio_analysis.h +++ b/rotord/src/nodes_audio_analysis.h @@ -12,6 +12,9 @@ namespace Rotor { class Vamp_node: public Audio_processor { //base class for vamp plugin hosts public: + Vamp_node(){ + create_attribute("mode","Data output mode","Mode","timeline",{"timeline","timesteps","valueline","values"}); + }; bool init(int _channels,int _bits,int _samples,int _rate); void cleanup(); int process_frame(uint8_t *data,int samples_in_frame); @@ -25,7 +28,7 @@ namespace Rotor { if (i->second.values.size()) v2=i->second.values[0]; i--; float lk=i->first; - int ln=i->second.number-1; //vamp numbers the first segment 0 + int ln=i->second.number; if (i->second.values.size()) v1=i->second.values[0]; int m=attributes["mode"]->intVal; // @@ -62,7 +65,6 @@ namespace Rotor { //create_attribute("soname","Plugin library to use","Plugin library","vamp-example-plugins",{"horiz","vert","horizR","vertR"}); //create_attribute("id","ID of Plugin to use","Plugin ID","percussiononsets",{"horiz","vert","horizR","vertR"}); create_attribute("analyser","Analyser Plugin to use","Analyser plugin","barbeattracker",{"barbeattracker","segmenter"}); - create_attribute("mode","Data output mode","Mode","timeline",{"timeline","timesteps","valueline","values"}); create_parameter("outputNo","number","Plugin output to use","Output number",0.0f); title="Audio analysis"; description="Analyse audio and output"; @@ -82,7 +84,7 @@ namespace Rotor { public: Act_segmenter(){ create_parameter("outputNo","number","Plugin output to use","Output number",0.0f); - create_parameter("acts","number","Number of acts defined","Acts",0.0f); + create_parameter("acts","number","Number of acts defined","Acts",1.0f); title="Act manager"; description="Applies a ruleset to manage acts based on segments"; }; @@ -96,29 +98,91 @@ namespace Rotor { Act_segmenter* clone(map &_settings) { return new Act_segmenter(_settings);}; void cleanup(){ Vamp_node::cleanup(); - //create list of segment durations - vector durations; - for (map::iterator f=analyser.features.begin();f!=analyser.features.end();++f){ + map acts; //temporary storage for new set of features + vector act_count; + for (int i=0;i<(int)parameters["acts"]->value;i++) act_count.push_back(0); + + map durations; //list of segment durations + int i=0; + for (map::iterator f=analyser.features.begin();f!=analyser.features.end();++f){ auto g=f; if (++g!=analyser.features.end()){ - durations.push_back(g->first-f->first); + durations[g->first-f->first]=i; } + i++; } //distribute acts amongst segments; if (analyser.features.size()==(int)parameters["acts"]->value+1){ for (auto f: analyser.features){ - acts[f.first]=f.second.number; + acts[f.first]=f.second; } } else if (analyser.features.size()<(int)parameters["acts"]->value+1){ - //find longest segment + //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 + } - else { //extra segments to distribute + else { //there are extra segments to assign to acts + //assign act numbers to segments + + //work through the segments + //have a list of segments that are to be filled + //start at the ends and work inwards + //have a list of how many times each segment has been used + //start with a set of the segments numbers + //(the aim: to access the segment numbers by the time that they start) + map segments=analyser.features; + segments.erase(--segments.end()); + + //assign the acts from the beginning and end in towards the middle + bool take_start=true; + while (segments.size()){ + int act=-1; + vampHost::feature f; + float t; + if (take_start){ + f=(*segments.begin()).second; + t=(*segments.begin()).first; + segments.erase(segments.begin()); + for (int i=0;i<(int)parameters["acts"]->value-1;i++) { + if (act_count[i]==0||(act_count[i+1]>act_count[i]&&act_count[i]value-1;i>0;i--) { + if (act_count[i]==0||(act_count[i-1]>act_count[i]&&act_count[i]<(int)parameters["acts"]->value-i)) { + act=i; + break; + } + } + + } + if (act==-1){ //all slots are filled equally + act=(int)parameters["acts"]->value/2; + } + act_count[act]++; + f.number=act; + acts[t]=f; + take_start=!take_start; + } } + //add last item back on + acts[(*--analyser.features.end()).first]=analyser.features[(*--analyser.features.end()).first]; + analyser.features=acts; } private: - map acts; + }; } -- cgit v1.2.3