summaryrefslogtreecommitdiff
path: root/rotord/src/nodes_audio_analysis.cpp
diff options
context:
space:
mode:
authorTim Redfern <tim@eclectronics.org>2013-08-30 18:27:08 +0100
committerTim Redfern <tim@eclectronics.org>2013-08-30 18:27:08 +0100
commitc5085b5a31c1e25bf83ae910710996863531f8b2 (patch)
tree86bfd31285853f18f5ae436970deb0bc4f3e0fe1 /rotord/src/nodes_audio_analysis.cpp
parentf38cdcf952ac5c631ed285282e1bc2943f199101 (diff)
value output from audio analysis
Diffstat (limited to 'rotord/src/nodes_audio_analysis.cpp')
-rw-r--r--rotord/src/nodes_audio_analysis.cpp135
1 files changed, 135 insertions, 0 deletions
diff --git a/rotord/src/nodes_audio_analysis.cpp b/rotord/src/nodes_audio_analysis.cpp
new file mode 100644
index 0000000..925858f
--- /dev/null
+++ b/rotord/src/nodes_audio_analysis.cpp
@@ -0,0 +1,135 @@
+#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;
+ column=0; //point thumbnail bitmap
+ out_sample=0; //sample in whole track
+ offset=0x1<<(bits-1); //signed audio
+ scale=1.0f/offset;
+ 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_sample<samples_in_frame&&column<width) {
+ //continue the column
+ while (sample<samples_per_column&&in_sample<samples_in_frame) {
+ //accumulate samples for this column until we run out of samples
+ for (int i=0;i<channels;i++) {
+ unsigned int this_val=0;
+ for (int j=0;j<bytes;j++) {
+ this_val+=_data[(in_sample*stride)+(i*bytes)+j]<<(j*8);
+ }
+ //convert from integer data format - i.e s16p - to audio signal in -1..1 range
+ //presume 16 bits for now...
+ double val=((double)((int16_t)this_val))*scale;
+ accum+=val*val;
+ samples++;
+ }
+ in_sample++;
+ sample++;
+ out_sample++;
+ }
+ if (sample==samples_per_column) { //finished a column
+ //get root-mean
+ double mean=pow(accum/samples,0.5);
+ //if (column==0) {
+ // cerr << "first column total: "<< accum << " in " << samples << " samples, average " << (accum/samples)<<endl;
+ //}
+ int colheight=height*mean*0.5;
+ int hh=height>>1;
+ for (int i=0;i<height;i++) {
+ data[i*width+column]=abs(i-hh)<colheight?0xff:0x00;
+ }
+ vectordata[column]=mean;
+ column++;
+ sample=0;
+ samples=0;
+ accum=0.0;
+ }
+ }
+ return out_sample;
+ }
+ string Audio_thumbnailer::print(){
+ //base64 encode the image data output it
+
+ stringstream output;
+ Poco::Base64Encoder *enc=new Poco::Base64Encoder(output);
+
+ enc->write((char*)data,width*height);
+ //tring output;
+ /*
+ for (int j=0;j<height;j++) {
+ for (int i=0;i<width;i++) {
+ output+=data[j*width+i]<0x7f?"0":"1";
+ }
+ output +="\n";
+ }
+ */
+ enc->close();
+ delete enc;
+ return output.str();
+ }
+ void Audio_thumbnailer::print_vector(xmlIO XML){
+ string vdata;
+ for (int i=0;i<width;i++){
+ if (i>0) vdata+=",";
+ vdata+=ofToString(vectordata[i]);
+ }
+ XML.addValue("data",vdata);
+ }
+ bool Audio_analysis::init(int _channels,int _bits,int _samples, int _rate) {
+ //need these to make sense of data
+ channels=_channels;
+ bits=_bits;
+ samples=_samples;
+
+ 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 Audio_analysis::process_frame(uint8_t *data,int samples_in_frame) {
+ analyser.process_frame(data,samples_in_frame);
+ return 1;
+ }
+ void Audio_analysis::cleanup() {
+ analyser.cleanup();
+ //print_features();
+ }
+ string Audio_analysis::get_features(){
+ string data;
+ for (auto i: analyser.features) {
+ data=data+" ["+ofToString(i.second.number)+":"+ofToString(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+ofToString(j);
+ }
+ data+=") ";
+ }
+ data+="]";
+ }
+ return data;
+ }
+} \ No newline at end of file