#include "nodes_audio_analysis.h" namespace Rotor{ bool Audio_thumbnailer::init(int _channels,int _bits,int _samples,int _rate) { //base_audio_processor::init(_channels,_bits,_samples); channels=_channels; bits=_bits; samples=_samples; samples_per_column=samples/width; offset=0x1<<(bits-1); //signed audio scale=1.0f/offset; out_sample=0; //sample in whole track sample=0; samples=0; accum=0.0; return true; } int Audio_thumbnailer::process_frame(uint8_t *_data,int samples_in_frame){ //begin by processing remaining samples //samples per column could be larger than a frame! (probably is) //but all we are doing is averaging int bytes=(bits>>3); int stride=channels*bytes; int in_sample=0; while (in_sample0) vdata+=","; vdata+=toString(sample); } XML.addValue("data",vdata); } bool Vamp_node::init(int _channels,int _bits,int _samples, int _rate) { //need these to make sense of data channels=_channels; bits=_bits; samples=_samples; features.clear(); return analyser.init(soname,id,_channels,_bits,_samples,_rate,outputNo,params); //attempt to load vamp plugin and prepare to receive frames of data //should the audio analysis contain a vamphost or should it inherit? //maybe neater to contain it in terms of headers etc } int Vamp_node::process_frame(uint8_t *data,int samples_in_frame) { analyser.process_frame(data,samples_in_frame); return 1; } void Vamp_node::cleanup() { analyser.cleanup(); features=analyser.features; } string Vamp_node::get_features(){ string data; for (auto i: features) { data=data+" ["+toString(i.second.number)+":"+toString(i.first); if (i.second.values.size()) { data+=" ("; bool first=true; for (auto j: i.second.values) { if (first){ first=false; } else data+=","; data=data+toString(j); } data+=") "; } data+="]"; } return data; } bool sortsegments(std::pair i,std::pair j){ return (i.second tempos; vector intensities; vector times; auto g=++analysers["segmenter"].features.begin(); for (auto f=analysers["segmenter"].features.begin();g!=analysers["segmenter"].features.end();f++,g++,i++){ cerr<<"segment "<first<<" to "<first<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 (tempofirst; 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> totals; for (i=0;ivalue)+(intensities[i]*parameters["intensity_weight"]->value))); } //sort and convert to features std::sort(totals.begin(),totals.end(),sortsegments); for (i=0;i bucketoffsets; for (auto t:totals) bucketoffsets.push_back(0.0f); if (parameters["levels"]->value>0.0f&¶meters["levels"]->valuevalue); float numberperbin=((float)numbertoredistribute/totals.size()); float toadd=0.5f; int added=0; for (int j=0;j0) { cerr<<"reducing number of levels by "<