summaryrefslogtreecommitdiff
path: root/rotord/src/nodes_audio_analysis.h
diff options
context:
space:
mode:
authorTim Redfern <tim@eclectronics.org>2013-10-29 14:45:49 +0000
committerTim Redfern <tim@eclectronics.org>2013-10-29 14:45:49 +0000
commit858cb95b8539f5695c5348c340b9f982d8b66719 (patch)
treebed7d5c75de92d4b15d74311f6385aba7bac49da /rotord/src/nodes_audio_analysis.h
parent9fc8a2e7b770339b72c080cfa510c461706fe43c (diff)
making intensity segmenter
Diffstat (limited to 'rotord/src/nodes_audio_analysis.h')
-rw-r--r--rotord/src/nodes_audio_analysis.h95
1 files changed, 78 insertions, 17 deletions
diff --git a/rotord/src/nodes_audio_analysis.h b/rotord/src/nodes_audio_analysis.h
index 44ea3eb..620f277 100644
--- a/rotord/src/nodes_audio_analysis.h
+++ b/rotord/src/nodes_audio_analysis.h
@@ -9,6 +9,18 @@ namespace Rotor {
#define VAMPHOST_Timesteps 2
#define VAMPHOST_Valueline 3
#define VAMPHOST_Values 4
+ class Audio_processor: public Signal_node {
+ public:
+ virtual Audio_processor(){};
+ virtual ~Audio_processor(){};
+ virtual int process_frame(uint8_t *data,int samples)=0;
+ virtual bool init(int _channels,int _bits,int _samples,int _rate)=0;
+ virtual void cleanup()=0;
+ virtual void print_summary(){};
+ virtual string get_features(){};
+ int channels,bits,samples,rate;
+ };
+ //actual nodes-------------------------------------------------
class Audio_thumbnailer: public Audio_processor {
public:
Audio_thumbnailer(){
@@ -43,9 +55,9 @@ namespace Rotor {
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.upper_bound(time.time); //the first element in the container whose key is considered to go after k
- if (i!=analyser.features.end()){
+ if (features.size()) {
+ auto i=features.upper_bound(time.time); //the first element in the container whose key is considered to go after k
+ if (i!=features.end()){
float uk=i->first;
float v1,v2;
v1=v2=0.0f;
@@ -72,15 +84,15 @@ namespace Rotor {
}
string get_features();
void print_summary(){
- cerr<<"vamp plugin "<<id<<" of library "<<soname<<" found "<<analyser.features.size()<<" features "<<endl;
+ cerr<<"vamp plugin "<<id<<" of library "<<soname<<" found "<<features.size()<<" features "<<endl;
};
protected:
string soname,id;
- int outputNo;
- vampHost::Analyser analyser;
- private:
- //??
+ int outputNo;
map <string,float> params;
+ map<float,vampHost::feature> features;
+ private:
+ vampHost::Analyser analyser;
};
class Audio_analysis: public Vamp_node {
//vamp node that allows the user to choose a plugin
@@ -170,20 +182,20 @@ namespace Rotor {
vector<int> act_count;
for (int i=0;i<(int)parameters["acts"]->value;i++) act_count.push_back(0);
- if (analyser.features.size()<=(int)parameters["acts"]->value+1){
+ if (features.size()<=(int)parameters["acts"]->value+1){
//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
- while (analyser.features.size()<(int)parameters["acts"]->value+1){
+ while (features.size()<(int)parameters["acts"]->value+1){
map<int,float> durations;
map<int,float> times;
int i=0;
- for (map<float,vampHost::feature>::iterator f=analyser.features.begin();f!=analyser.features.end();++f){
+ for (map<float,vampHost::feature>::iterator f=features.begin();f!=features.end();++f){
auto g=f;
- if (++g!=analyser.features.end()){
+ if (++g!=features.end()){
durations[i]=g->first-f->first;
times[i]=f->first;
}
@@ -197,10 +209,10 @@ namespace Rotor {
n=d.first;
}
}
- analyser.features[times[n]+(durations[n]/2)]=analyser.features[times[n]];
+ features[times[n]+(durations[n]/2)]=features[times[n]];
}
int j=0;
- for (auto f: analyser.features){
+ for (auto f: features){
f.second.number=j;
acts[f.first]=f.second;
j++;
@@ -216,7 +228,7 @@ namespace Rotor {
//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;
+ map<float,vampHost::feature> segments=features;
segments.erase(--segments.end());
//assign the acts from the beginning and end in towards the middle
@@ -260,12 +272,61 @@ namespace Rotor {
}
}
//add last item back on
- acts[(*--analyser.features.end()).first]=analyser.features[(*--analyser.features.end()).first];
- analyser.features=acts;
+ acts[(*--features.end()).first]=features[(*--features.end()).first];
+ features=acts;
}
private:
};
+ class Intensity_segmenter: public Vamp_node {
+ //vamp node that applies a ruleset to manage a set of acts via a cycler
+ public:
+ Intensity_segmenter(){
+ title="Intensity segmenter";
+ description="Combines the output of segmentation, tempo, and intensity analysis plugins";
+ UID="6ce236b6-4080-11e3-90b7-74d02b29f6a6";
+ analysers["segmenter"]=vampHost::Analyser();
+ analysers["tempo"]=vampHost::Analyser();
+ analysers["intensity"]=vampHost::Analyser();
+ };
+ Intensity_segmenter(map<string,string> &settings):Intensity_segmenter() {
+ base_settings(settings);
+ };
+ ~Intensity_segmenter(){};
+ Intensity_segmenter* clone(map<string,string> &_settings) { return new Intensity_segmenter(_settings);};
+ bool init(int _channels,int _bits,int _samples,int _rate) {
+ return analysers["segmenter"].init("qm-vamp-plugins","qm-segmenter",_channels,_bits,_samples,_rate,0,params)\
+ &&analysers["tempo"].init("qm-vamp-plugins","qm-tempotracker",_channels,_bits,_samples,_rate,2,params)\
+ &&analysers["intensity"].init("bbc-vamp-plugins","bbc-intensity",_channels,_bits,_samples,_rate,0,params);
+ }
+ int process_frame(uint8_t *data,int samples_in_frame) {
+ //for (auto a:analysers) a.second.process_frame(data,samples_in_frame); //WHY NOT WORK
+ analysers["segmenter"].process_frame(data,samples_in_frame);
+ analysers["tempo"].process_frame(data,samples_in_frame);
+ analysers["intensity"].process_frame(data,samples_in_frame);
+ return 1;
+ }
+ void cleanup(){
+ //for (auto a:analysers) a.second.cleanup(); //WHY NOT WORK - its as if the call is const
+ analysers["segmenter"].cleanup();
+ analysers["tempo"].cleanup();
+ analysers["intensity"].cleanup();
+ cerr<<analysers["segmenter"].features.size()<<" segments"<<endl;
+ cerr<<analysers["tempo"].features.size()<<" tempo features"<<endl;
+ cerr<<analysers["intensity"].features.size()<<" intensity features"<<endl;
+ //auto f=analysers["segmenter"].features.begin();
+ //for (auto g=++analysers["segmenter"].features.begin();g!=analysers["segmenter"].features.end();f++,g++){
+ // cerr<<"calculating segment from "<<f.first<<" to "<<g.first<<endl;
+ // features[f.first]=f.second;
+ //}
+ return true;
+ }
+ void print_summary(){
+ cerr<<"Intensity segmenter found "<<features.size()<<" features "<<endl;
+ };
+ private:
+ map<string,vampHost::Analyser> analysers;
+ };
}
#endif