diff options
| author | Tim Redfern <tim@eclectronics.org> | 2013-10-30 14:15:47 +0000 |
|---|---|---|
| committer | Tim Redfern <tim@eclectronics.org> | 2013-10-30 14:15:47 +0000 |
| commit | b3abde4531510b7accbc58174ecd9ec27c52ee3a (patch) | |
| tree | 81f33784cea14312f0c2a99700e66d3804d78d46 /rotord/src | |
| parent | 858cb95b8539f5695c5348c340b9f982d8b66719 (diff) | |
intensity segmenter
Diffstat (limited to 'rotord/src')
| -rw-r--r-- | rotord/src/nodes_audio_analysis.cpp | 80 | ||||
| -rw-r--r-- | rotord/src/nodes_audio_analysis.h | 20 |
2 files changed, 85 insertions, 15 deletions
diff --git a/rotord/src/nodes_audio_analysis.cpp b/rotord/src/nodes_audio_analysis.cpp index 1e65668..5318bb1 100644 --- a/rotord/src/nodes_audio_analysis.cpp +++ b/rotord/src/nodes_audio_analysis.cpp @@ -105,4 +105,84 @@ namespace Rotor{ } return data; } + bool sortsegments(std::pair<int,float> i,std::pair<int,float> j){ + return (i.second<j.second); + } + void Intensity_segmenter::cleanup(){ + //algorithm idea: + //get average tempo and intensity for each segment and store them + //scale by the range to get a value from 0.0 to 1.0 + //add tempo and intensity according to a weighting + //score the results (ie 1st place, 2nd place) to end up with a set of integer numbers + + //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 g=++analysers["segmenter"].features.begin(); + int i=0; + float min_tempo=9999999.0f; + float min_intensity=9999999.0f; + float max_tempo=0.0f; + float max_intensity=0.0f; + vector<float> tempos; + vector<float> intensities; + vector<float> times; + for (auto f=analysers["segmenter"].features.begin();g!=analysers["segmenter"].features.end();f++,g++,i++){ + cerr<<"segment "<<i<<": "<<f->first<<" to "<<g->first<<endl; + times.push_back(f->first); + //integrate tempo and intensity algorithmically + float tempo=0; + if (analysers["tempo"].features.size()) { + float pt=f->first; + float pv=analysers["tempo"].get_value(f->first); + for (auto u=analysers["tempo"].features.upper_bound(f->first);u!=analysers["tempo"].features.upper_bound(g->first);u++){ + tempo +=(u->first-pt)*(u->second.values[0]+pv)*0.5f; //area of the slice + pt=u->first; + pv=u->second.values[0]; + } + tempo +=(g->first-pt)*(analysers["tempo"].get_value(g->first)+pv)*0.5f; //area of the last slice + tempo /=g->first-f->first; //average value; + } + if (tempo>max_tempo) max_tempo=tempo; + if (tempo<min_tempo) min_tempo=tempo; + tempos.push_back(tempo); + cerr<<"segment "<<i<<" average tempo: "<<tempo<<endl; + + float intensity=0; + if (analysers["intensity"].features.size()) { + float pt=f->first; + float pv=analysers["intensity"].get_value(f->first); + for (auto u=analysers["intensity"].features.upper_bound(f->first);u!=analysers["intensity"].features.upper_bound(g->first);u++){ + intensity +=(u->first-pt)*(u->second.values[0]+pv)*0.5f; //area of the slice + pt=u->first; + pv=u->second.values[0]; + } + intensity +=(g->first-pt)*(analysers["intensity"].get_value(g->first)+pv)*0.5f; //area of the last slice + intensity /=g->first-f->first; //average value; + } + if (intensity>max_intensity) max_intensity=intensity; + if (intensity<min_intensity) min_intensity=intensity; + intensities.push_back(intensity); + cerr<<"segment "<<i<<" average intensity: "<<intensity<<endl; + } + //make relative scale 0.0-1.0 and save weighted totals + vector< pair<int,float>> totals; + for (i=0;i<tempos.size();i++){ + tempos[i]=(tempos[i]-min_tempo)/(max_tempo-min_tempo); + intensities[i]=(intensities[i]-min_intensity)/(max_intensity-min_intensity); + totals.push_back(make_pair(i,(tempos[i]*parameters["tempo_weight"]->value)+(intensities[i]*parameters["intensity_weight"]->value))); + } + //sort and convert to features + std::sort(totals.begin(),totals.end(),sortsegments); + for (int i=0;i<totals.size();i++){ + vampHost::feature f; + f.values.push_back((float)i); + features[times[totals[i].first]]=f; + } + return true; + } }
\ No newline at end of file diff --git a/rotord/src/nodes_audio_analysis.h b/rotord/src/nodes_audio_analysis.h index 620f277..a3fe5b8 100644 --- a/rotord/src/nodes_audio_analysis.h +++ b/rotord/src/nodes_audio_analysis.h @@ -288,6 +288,8 @@ namespace Rotor { analysers["segmenter"]=vampHost::Analyser(); analysers["tempo"]=vampHost::Analyser(); analysers["intensity"]=vampHost::Analyser(); + create_parameter("intensity_weight","number","intensity weight","Intensity weighting",1.0f); + create_parameter("tempo_weight","number","tempo weight","Tempo weighting",1.0f); }; Intensity_segmenter(map<string,string> &settings):Intensity_segmenter() { base_settings(settings); @@ -306,21 +308,7 @@ namespace Rotor { 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 cleanup(); //all the fun happens here void print_summary(){ cerr<<"Intensity segmenter found "<<features.size()<<" features "<<endl; }; @@ -329,4 +317,6 @@ namespace Rotor { }; } + + #endif |
