summaryrefslogtreecommitdiff
path: root/rotord/src/nodes_audio_analysis.h
diff options
context:
space:
mode:
authorTim Redfern <tim@eclectronics.org>2013-09-06 15:04:38 +0100
committerTim Redfern <tim@eclectronics.org>2013-09-06 15:04:38 +0100
commit48ec56201e2240dcda68f2c384bacc3bdcb405ba (patch)
tree45611563f1ef74c49b119050cc2cbbfea8ba752a /rotord/src/nodes_audio_analysis.h
parent3dbe8f18642b684db0c8abb60c3f4a7a7e7c5dc4 (diff)
act segmenter v1
Diffstat (limited to 'rotord/src/nodes_audio_analysis.h')
-rw-r--r--rotord/src/nodes_audio_analysis.h86
1 files changed, 75 insertions, 11 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;
+
};
}