summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rotord/rotor.cpp6
-rwxr-xr-xrotord/rotor.h16
-rw-r--r--rotord/vampHost.cpp132
-rw-r--r--rotord/vampHost.h14
4 files changed, 65 insertions, 103 deletions
diff --git a/rotord/rotor.cpp b/rotord/rotor.cpp
index 2cd894f..af0bd7e 100644
--- a/rotord/rotor.cpp
+++ b/rotord/rotor.cpp
@@ -567,4 +567,10 @@ int Audio_analysis::process_frame(uint8_t *data,int samples_in_frame) {
}
void Audio_analysis::cleanup() {
analyser.cleanup();
+ //print_features();
}
+void Audio_analysis::print_features(){
+ for (auto i: analyser.features) {
+ cerr<<i.second<<" "<<i.first<<endl;
+ }
+} \ No newline at end of file
diff --git a/rotord/rotor.h b/rotord/rotor.h
index 105ed98..7dbb18d 100755
--- a/rotord/rotor.h
+++ b/rotord/rotor.h
@@ -244,9 +244,21 @@ namespace Rotor {
void cleanup();
int process_frame(uint8_t *data,int samples_in_frame);
float get_output(const float &time) {
- float t=time;
- return t;
+ if (analyser.features.size()) {
+ auto i=analyser.features.lower_bound(time);
+ if (i!=analyser.features.end()){
+ float lk=i->first;
+ int ln=i->second;
+ if (i++!=analyser.features.end()){
+ float uk=i->first;
+ return (((time-lk)/(uk-lk))+ln);
+ }
+ else return (float)ln;
+ }
+ }
+ return 0.0f;
}
+ void print_features();
private:
string soname,id;
int outputNo;
diff --git a/rotord/vampHost.cpp b/rotord/vampHost.cpp
index 21f5db5..2713e38 100644
--- a/rotord/vampHost.cpp
+++ b/rotord/vampHost.cpp
@@ -604,7 +604,7 @@ bool vampHost::Analyser::init(const string &soname,const string &id,const int &_
stride=channels*bytes;
scale=(1.0f/pow(2.0f,bits));
-
+ features[0.0f]=0;
loader = PluginLoader::getInstance();
key = loader->composePluginKey(soname, id);
@@ -643,7 +643,6 @@ bool vampHost::Analyser::init(const string &soname,const string &id,const int &_
currentStep = 0;
finalStepsRemaining = max(1, (blockSize / stepSize) - 1); // at end of file, this many part-silent frames needed after we hit EOF
- filebuf = new float[blockSize * channels];
plugbuf = new float*[channels];
for (int c = 0; c < channels; ++c) plugbuf[c] = new float[blockSize + 2];
@@ -716,7 +715,7 @@ bool vampHost::Analyser::init(const string &soname,const string &id,const int &_
blocks_processed=0;
currentStep=0;
- featureNo=0;
+ featureNo=1;
return true;
}
@@ -725,63 +724,6 @@ void vampHost::Analyser::process_frame(uint8_t *data,int samples_in_frame){
//process the whole frame which may be f>1<f blocks
//when the frame is finished leave the partial block for the next frame
-
- //seems that the vamp plugin needs to be given a block context bigger than the step that it processes
- /*
- each frame that comes in contains samples_in_frame samples (samples*bytes*channels data)
- we may have part of a block remaining from the previous frames/s
-
- filebuf is filled from incoming frames
-
- when filebuf is full, fill plugbuf from filebuf (necessary?)
-
- the point is, each step is smaller than a block, but we manage the steps and blocks- seems a bit stupid
-
- after each processing step, 'shunt down' the data and prepare the pointer to fill the next
-
-
- ///
- int count;
-
- if ((blockSize==stepSize) || (currentStep==0)) {
- // read a full fresh block
- if ((count = sf_readf_float(sndfile, filebuf, blockSize)) < 0) {
- cerr << "ERROR: sf_readf_float failed: " << sf_strerror(sndfile) << endl;
- break;
- }
- if (count != blockSize) --finalStepsRemaining;
- } else {
- // otherwise shunt the existing data down and read the remainder.
- memmove(filebuf, filebuf + (stepSize * channels), overlapSize * channels * sizeof(float));
- if ((count = sf_readf_float(sndfile, filebuf + (overlapSize * channels), stepSize)) < 0) {
- cerr << "ERROR: sf_readf_float failed: " << sf_strerror(sndfile) << endl;
- break;
- }
- if (count != stepSize) --finalStepsRemaining;
- count += overlapSize;
- }
-
- for (int c = 0; c < channels; ++c) {
- int j = 0;
- while (j < count) {
- plugbuf[c][j] = filebuf[j * sfinfo.channels + c];
- ++j;
- }
- while (j < blockSize) {
- plugbuf[c][j] = 0.0f;
- ++j;
- }
- }
-
- rt = RealTime::frame2RealTime(currentStep * stepSize, sfinfo.samplerate);
-
- ///
-
-
- */
-
-
-
while(sample<samples_in_frame) {
while(sample<samples_in_frame&&in_block<blockSize) {
for (int i=0;i<channels;i++) {
@@ -795,6 +737,10 @@ void vampHost::Analyser::process_frame(uint8_t *data,int samples_in_frame){
sample++;
}
if (in_block==blockSize) {
+ //block is ready to be processed
+ //cerr<<plugin->getIdentifier()<<" processed block "<<blocks_processed<<endl;
+
+ //I /think/ that the vamp plugin keeps processing through the plugbuf until it encounters 0s
rt = RealTime::frame2RealTime(currentStep * stepSize, rate);
Plugin::FeatureSet feat=plugin->process(plugbuf, rt);
@@ -804,45 +750,45 @@ void vampHost::Analyser::process_frame(uint8_t *data,int samples_in_frame){
featureNo++;
}
+ //shunt it down
+ for (int i=0;i<blockSize-stepSize;i++){
+ for (int j=0;j<channels;j++){
+ plugbuf[j][i]=plugbuf[j][i+stepSize];
+ }
+ }
+
in_block-=stepSize;
currentStep++;
-
- //shunt down the data
-
- for (int i=0;i<in_block;i++){
- for (int j=0;j<channels;j++){
- plugbuf[j][i]=plugbuf[j][i+stepSize];
- }
- }
}
}
}
void vampHost::Analyser::cleanup(){
-
- //fill remainder of final block with zeroes
- for (int i=in_block;i<blockSize;i++){
- for (int j=0;j<channels;j++){
- plugbuf[j][i]=0.0f;
- }
- }
-
- rt = RealTime::frame2RealTime(currentStep * stepSize, rate);
-
- Plugin::FeatureSet feat=plugin->process(plugbuf, rt);
-
- for (unsigned int i = 0; i < feat[outputNo].size(); ++i) {
- features[((float)feat[outputNo][i].timestamp.sec)+(((float)feat[outputNo][i].timestamp.nsec)*.000000001)]=featureNo;
- featureNo++;
- }
-
- feat = plugin->getRemainingFeatures();
-
- for (unsigned int i = 0; i < feat[outputNo].size(); ++i) {
- features[((float)feat[outputNo][i].timestamp.sec)+(((float)feat[outputNo][i].timestamp.nsec)*.000000001)]=featureNo;
- featureNo++;
- }
-
- cerr<<plugin->getIdentifier()<<" found "<<features.size()<<" features"<<endl;
+
+ //process final block
+ while(in_block<blockSize) {
+ for (int i=0;i<channels;i++) {
+ plugbuf[i][in_block]=0.0f;
+ }
+ in_block++;
+ }
+
+ rt = RealTime::frame2RealTime(currentStep * stepSize, rate);
+
+ Plugin::FeatureSet feat=plugin->process(plugbuf, rt);
+
+ for (unsigned int i = 0; i < feat[outputNo].size(); ++i) {
+ features[((float)feat[outputNo][i].timestamp.sec)+(((float)feat[outputNo][i].timestamp.nsec)*.000000001)]=featureNo;
+ featureNo++;
+ }
+
+ feat=plugin->getRemainingFeatures();
+
+ for (unsigned int i = 0; i < feat[outputNo].size(); ++i) {
+ features[((float)feat[outputNo][i].timestamp.sec)+(((float)feat[outputNo][i].timestamp.nsec)*.000000001)]=featureNo;
+ featureNo++;
+ }
+
+ cerr<<plugin->getIdentifier()<<" found "<<(features.size()-1)<<" features"<<endl;
//deal with left over data?
for (int c = 0; c < channels; ++c) {
delete[] plugbuf[c];
diff --git a/rotord/vampHost.h b/rotord/vampHost.h
index c632e44..3758055 100644
--- a/rotord/vampHost.h
+++ b/rotord/vampHost.h
@@ -59,28 +59,26 @@ namespace vampHost {
bool init(const string &soname,const string &id,const int &_channels,const int &_bits,const int &_samples,const int &_rate,const int &_outputNo=0,const string &_output="");
void process_frame(uint8_t *data,int samples_in_frame);
void cleanup();
+
+ map<float,int> 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
+
private:
PluginLoader *loader;
PluginLoader::PluginKey key;
Plugin *plugin;
+ RealTime rt;
int channels,bits,samples,rate;
int bytes,stride;
float scale;
int blockSize,stepSize,overlapSize,finalStepsRemaining,currentStep,outputNo;
int in_block,blocks_processed;
string output;
- float *filebuf;
float **plugbuf;
- RealTime rt;
int featureNo;
- map<float,int> features;
- //what's the best way to store features?
- //how will it be used?
- //we ask for a signal at a time, return interpolated value representing feature number + fraction
- //is there a quick way to search the keys and return the last one below a given value
-
};
string getQMBeats(const string soundfile);