summaryrefslogtreecommitdiff
path: root/rotord
diff options
context:
space:
mode:
Diffstat (limited to 'rotord')
-rw-r--r--rotord/src/nodes_audio_analysis.h86
-rw-r--r--rotord/src/nodes_drawing.h9
-rwxr-xr-xrotord/src/tinyxml.cpp2
-rw-r--r--rotord/src/vampHost.cpp2
-rw-r--r--rotord/src/vampHost.h2
5 files changed, 84 insertions, 17 deletions
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<string,string> &_settings) { return new Act_segmenter(_settings);};
void cleanup(){
Vamp_node::cleanup();
- //create list of segment durations
- vector<float> durations;
- for (map<double,vampHost::feature>::iterator f=analyser.features.begin();f!=analyser.features.end();++f){
+ map<float,vampHost::feature> acts; //temporary storage for new set of features
+ vector<int> act_count;
+ for (int i=0;i<(int)parameters["acts"]->value;i++) act_count.push_back(0);
+
+ map<float,int> durations; //list of segment durations
+ int i=0;
+ for (map<float,vampHost::feature>::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<float,vampHost::feature> 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]<i)) {
+ act=i;
+ break;
+ }
+ }
+ }
+ else {
+ f=(*--segments.end()).second;
+ t=(*--segments.end()).first;
+ segments.erase(--segments.end());
+ for (int i=(int)parameters["acts"]->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<double,int> acts;
+
};
}
diff --git a/rotord/src/nodes_drawing.h b/rotord/src/nodes_drawing.h
index db1d934..370c0fb 100644
--- a/rotord/src/nodes_drawing.h
+++ b/rotord/src/nodes_drawing.h
@@ -9,6 +9,7 @@ namespace Rotor {
public:
Draw_node(){
create_image_input("image input","Image input");
+ create_attribute("colour","Colour to fill","Colour","FFFFFF");
//no title or description as it isn't intended for the user
};
Draw_node(map<string,string> &settings):Draw_node() {
@@ -39,7 +40,10 @@ namespace Rotor {
cairo_surface_destroy(cs);
return &image;
}
+ protected:
+ Colour colour;
private:
+
};
class Text: public Draw_node {
public:
@@ -51,6 +55,7 @@ namespace Rotor {
};
Text(map<string,string> &settings):Text() {
base_settings(settings);
+ colour=Colour(attributes["colour"]->value);
};
~Text(){};
Text* clone(map<string,string> &_settings) { return new Text(_settings);};
@@ -61,7 +66,7 @@ namespace Rotor {
}
else text=attributes["text"]->value;
cairo_text_extents_t te;
- cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
+ cairo_set_source_rgb(cr, colour.Rfloat(),colour.Gfloat(),colour.Bfloat());
cairo_select_font_face (cr, "Georgia",
CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
cairo_set_font_size (cr, 120);
@@ -84,7 +89,6 @@ namespace Rotor {
create_parameter("y","number","Y coordinate","Y",0.0f);
create_parameter("scale","number","Scale","Scale",1.0f);
create_parameter("rotation","number","Rotation","Rotation",0.0f);
- create_attribute("colour","Colour to fill","Colour","FFFFFF");
create_attribute("shape","Shape to draw","Shape","square",{"circle","square","triangle"});
};
Shape(map<string,string> &settings):Shape() {
@@ -119,7 +123,6 @@ namespace Rotor {
cairo_fill(cr);
}
private:
- Colour colour;
};
class Audio_viz: public Draw_node {
public:
diff --git a/rotord/src/tinyxml.cpp b/rotord/src/tinyxml.cpp
index ef91984..b5d0451 100755
--- a/rotord/src/tinyxml.cpp
+++ b/rotord/src/tinyxml.cpp
@@ -1790,7 +1790,7 @@ bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute
&& element.FirstChild()->ToText()->CDATA() == false )
{
simpleTextPrint = true;
- //DoLineBreak()!
+ //DoLineBreak();
}
else
{
diff --git a/rotord/src/vampHost.cpp b/rotord/src/vampHost.cpp
index b265c3d..3b16173 100644
--- a/rotord/src/vampHost.cpp
+++ b/rotord/src/vampHost.cpp
@@ -731,7 +731,7 @@ bool vampHost::Analyser::init(const string &soname,const string &id,const int &_
blocks_processed=0;
currentStep=0;
- featureNo=1;
+ featureNo=0;
return true;
}
diff --git a/rotord/src/vampHost.h b/rotord/src/vampHost.h
index 241ffce..1f53508 100644
--- a/rotord/src/vampHost.h
+++ b/rotord/src/vampHost.h
@@ -65,7 +65,7 @@ namespace vampHost {
void cleanup();
//map<double,int> features;
- map<double,feature> features;
+ map<float,feature> features;
//map<time,featureNo>
//this is the best way to store features: because map allows to search for the key below and above the present time