Voss Connection Detection  1
Detect a connector click using realtime code on Bela hardware
conndetect.cpp
Go to the documentation of this file.
1 #include "conndetect.h"
2 #include "config.h"
3 #include "conndetect_features.h"
4 #include "leds.h"
5 #include "thresholds_config.h"
6 #include "timedelay.h"
7 #include "tools.h"
8 #include <iostream>
9 #include "classifier.h"
10 #include <math.h>
11 
15 #define WRITE_TO_DISK 1
16 
21 const float WAMP_LT = 0.005;
26 const float WAMP_LW = 0.005;
31 const float WAMP_LVPU = 0.001;
32 
37 const float ZC_T = 0.01;
38 
43 const float ZC_W = 0.01;
44 
49 const float ZC_VPU = 0.005;
50 
51 using std::cerr;
52 using std::cout;
53 using std::endl;
54 
55 // Keep these values in sync with LEDColors in sketch.js
56 /* const int GUI_LED_COLOR_WHITE = 0; */
57 /* const int GUI_LED_COLOR_RED = 1; */
58 /* const int GUI_LED_COLOR_GREEN = 2; */
59 
60 typedef unsigned int us;
61 #define max(a, b) (((a) > (b) ? a : b))
62 
63 void raw_conndetect_auxtask_callback(void *raw_ptr) {
64  ConnDetect *conndetect = static_cast<ConnDetect *>(raw_ptr);
65  conndetect->auxTaskCallback();
66 }
67 
68 ConnDetect::ConnDetect(BelaContext *context) {
69  _features = new Features(context->analogSampleRate);
70  if(!_features) throw std::runtime_error("Unallocated features");
71 
72  // Assumed to be already halfly filled
73  _bufs[0] = new FilteredDataBuffer(SAMPLING_FREQUENCY, true);
74  // Comes a bit later
75  _bufs[1] = new FilteredDataBuffer(SAMPLING_FREQUENCY);
76  _bufs[1]->timeStamp = 1;
77 
78  _timedelay = new TimeDelay(context->analogSampleRate);
79  /* Initialize logging */
80 #if WRITE_TO_DISK == 1
81  _logfile = new LogFile<NUMBER_FEATURES>(
83  if(!_logfile) throw std::runtime_error("Could not create log file");
84 
85 #endif
86 
87  _detect_task = Bela_createAuxiliaryTask(raw_conndetect_auxtask_callback, 55,
88  "Conndetect_auxtask_callback", this);
89 }
91 
92  delete _bufs[0];
93  delete _bufs[1];
94  delete _features;
95 #if WRITE_TO_DISK == 1
96  delete _logfile;
97 #endif
98  delete _timedelay;
99 }
100 
102 
103  int nbufs_full = 0;
104  for (auto buf : _bufs) {
105  if (!(buf->full())) {
106  buf->addFilteredFrame(frame);
107  } else {
108  nbufs_full++;
109  }
110  }
111  if(nbufs_full == 1) {
112  Bela_scheduleAuxiliaryTask(_detect_task);
113  }
114  else if (nbufs_full == 2) {
115  std::cerr << "Two buffers full. Houston we have too much load!" << endl;
116  Bela_requestStop();
117  }
118 }
119 
120 bool ConnDetect::connectionDetected() { return _connDetected; }
121 
122 void ConnDetect::auxTaskCallback() {
123  for (auto buf : _bufs) {
124  if (buf->full()) {
125  processFullBuffer((buf->data));
126  buf->clear();
127  }
128  }
129 }
130 void ConnDetect::processFullBuffer(const FilteredData &data) {
131 
136  typedef FeatureType f;
137  /* cerr << "P" << endl; */
138  ComputedFeatures ft;
140  /* std::fill(ft.begin(), ft.end(), -8000); */
141 
143  _features->setChannel(data[FILT_HP8k_MICT]);
144  ft[(int) f::HP_8k_PEAKdB_MICT] = _features->peak_dB();
145 
146  _features->setChannel(data[FILT_HP8k_MICW]);
147  ft[(int) f::HP_8k_PEAKdB_MICW] = _features->peak_dB();
148 
149  _features->setChannel(data[FILT_LP500_MICT]);
150  ft[(int) f::LP_500_PEAKdB_MICT] = _features->peak_dB();
151 
152  _features->setChannel(data[FILT_LP500_MICW]);
153  ft[(int) f::LP_500_PEAKdB_MICW] = _features->peak_dB();
154 
155  _features->setChannel(data[FILT_HP2k_VPU]);
156  ft[(int) f::HP_2k_PEAKdB_VPU] = _features->peak_dB();
157 
158  _features->setChannel(data[FILT_LP500_VPU]);
159  ft[(int) f::LP_500_PEAKdB_VPU] = _features->peak_dB();
160 
161  _features->setChannel(data[FILT_HP2k_MICT]);
162  ft[(int) f::HP_2k_PEAKFREQ_MICT] = _features->peak_freq();
163 
165  _features->setChannel(data[FILT_RAW_MICT]);
166  ft[(int) f::KURTOSIS_MICT] = _features->kurtosis();
167  ft[(int) f::INVERSE_FREQ_VARIANCE_MICT] = _features->inverse_variance();
168  ft[(int) f::TM3_MICT] = _features->TM3();
169  /* ft[(int) f::TM5_MICT] = _features->TM5(); */
170  ft[(int) f::WAMP_MICT] = _features->wamp(WAMP_LT);
171  ft[(int) f::ZC_MICT] = _features->zc(ZC_T);
172 
174  _features->setChannel(data[FILT_RAW_MICW]);
175  ft[(int) f::KURTOSIS_MICW] = _features->kurtosis();
176  ft[(int) f::INVERSE_FREQ_VARIANCE_MICW] = _features->inverse_variance();
177  ft[(int) f::TM3_MICW] = _features->TM3();
178  /* ft[(int) f::TM5_MICW] = _features->TM5(); */
179  ft[(int) f::WAMP_MICW] = _features->wamp(WAMP_LW);
180  ft[(int) f::ZC_MICW] = _features->zc(ZC_W);
181 
183  _features->setChannel(data[FILT_RAW_VPU]);
184  ft[(int) f::KURTOSIS_VPU] = _features->kurtosis();
185  /* ft[(int) f::INVERSE_FREQ_VARIANCE_VPU] = _features->inverse_variance(); */
186  ft[(int) f::TM3_VPU] = _features->TM3();
187  /* ft[(int) f::TM5_VPU] = _features->TM5(); */
188  ft[(int) f::WAMP_VPU] = _features->wamp(WAMP_LVPU);
189  ft[(int) f::ZC_VPU] = _features->zc(ZC_VPU);
190 
191  ft[(int) f::TIMEDELAY_MICW_MICT] = _timedelay->determineDelay(
192  data[FILT_RAW_MICT], data[FILT_RAW_MICW]);
193 
194  /*/1** IMU sensor average values *1/ */
195  ft[(int) f::AVG_IMU_ABS_ROT] = SimpleFeatures::average(data[FILT_IMU_ROT]);
196  ft[(int) f::MAX_IMU_ABS_HP_ACC] = SimpleFeatures::maximum(data[FILT_HP_IMU_ACC]);
197 
199  float pedal = SimpleFeatures::hasNonZero(data[FILT_PEDAL]);
200  if(pedal) {
201  cerr << "Detected pedal push" << _connDetected << endl;
202  }
203  ft[(int) f::PEDAL] = pedal;
204 
206  _connDetected = _classifier->classify(ft);
207  ft[(int) f::CLASS] = _connDetected;
208  if(_connDetected) {
209  cerr << "Detected connection" << endl;
210  }
211 
212 #if WRITE_TO_DISK == 1
213  _logfile->log(ft);
214 #else
215 
216 #endif
217 
218 }
logFileHeader
const char *const logFileHeader
Please be VERY SURE to keep this in sync with the list above, otherwise LARGE MISTAKES will be made.
Definition: conndetect.h:74
Classifier::classify
bool classify(const ComputedFeatures &ft)
Perform classification, i.e. detect the threshold.
Definition: classifier.cpp:7
FILT_HP2k_VPU
const us FILT_HP2k_VPU
Definition: filter.h:88
WAMP_LT
const float WAMP_LT
Willson amplitude L-definition. For the thumb mic.
Definition: conndetect.cpp:21
conndetect_features.h
ConnDetect::ConnDetect
ConnDetect(BelaContext *context)
Initalize the connection detector.
Definition: conndetect.cpp:68
ConnDetect::addFilteredFrame
void addFilteredFrame(const FilteredFrame &filteredframe)
Add a new filtered frame of data to the buffer the detector.
Definition: conndetect.cpp:101
ConnDetect::connectionDetected
bool connectionDetected()
The write task.
Definition: conndetect.cpp:120
FeatureType
FeatureType
These are the features extracted from the filtered data. They should be self-explaining regarding the...
Definition: conndetect.h:32
FILT_IMU_ROT
const us FILT_IMU_ROT
Definition: filter.h:91
Features::TM3
float TM3()
Temporal moment 3, defined as.
Definition: conndetect_features.cpp:164
SAMPLING_FREQUENCY
const float SAMPLING_FREQUENCY
This is the exact sampling frequency of the system. Do not change!
Definition: config.h:99
thresholds_config.h
Configuration parameters for connection detection based on thresholds. Note that these values are "in...
FILT_LP500_MICW
const us FILT_LP500_MICW
Definition: filter.h:85
conndetect.h
TimeDelay
Time delay determination between two signals, based on cross-correlation and windowing of the data.
Definition: timedelay.h:12
leds.h
LogFile< NUMBER_FEATURES >
FILT_RAW_MICT
const us FILT_RAW_MICT
The number of buffers that require some processing. This is not equal to the number of sensors,...
Definition: filter.h:78
Features::wamp
float wamp(float wampl)
Willson amplitude. Counts the number of difss in amplitude that have an absolute change in value larg...
Definition: conndetect_features.cpp:143
SimpleFeatures::maximum
static float maximum(const Channel &i)
Find the maximum value in a strictly positive array. No checks on positiveness are done!
Definition: conndetect_features.h:231
FILT_HP8k_MICT
const us FILT_HP8k_MICT
Definition: filter.h:79
ConnDetect::raw_conndetect_auxtask_callback
friend void raw_conndetect_auxtask_callback(void *)
Definition: conndetect.cpp:63
ConnDetect
The main connection detection class.
Definition: conndetect.h:83
FILT_RAW_MICW
const us FILT_RAW_MICW
Definition: filter.h:83
Features::inverse_variance
float inverse_variance()
Inverse of the variance in the center frequency, defined as:
Definition: conndetect_features.cpp:179
WAMP_LW
const float WAMP_LW
Willson amplitude L-definition. For the wrist mic.
Definition: conndetect.cpp:26
FILT_LP500_MICT
const us FILT_LP500_MICT
Definition: filter.h:81
FilteredFrame
array< float, NUMBER_FILTERED_CHANNELS > FilteredFrame
An array containing data with length corresponding to a single processed frame. Its length correspond...
Definition: filter.h:102
us
unsigned int us
Definition: conndetect.cpp:60
timedelay.h
Features::peak_freq
float peak_freq()
Compute the frequency at which the spectrum has the most power. It is defined as:
Definition: conndetect_features.cpp:129
FILT_PEDAL
const us FILT_PEDAL
Definition: filter.h:93
LogFile::log
void log(const std::array< float, num_cols > &data)
Log the data to the file.
Definition: tools.cpp:177
FILT_RAW_VPU
const us FILT_RAW_VPU
Definition: filter.h:87
ComputedFeatures
std::array< float,(us) NUMBER_FEATURES > ComputedFeatures
Definition: conndetect.h:78
FeatureType::ZC_VPU
@ ZC_VPU
FilteredData
array< Channel, NUMBER_FILTERED_CHANNELS > FilteredData
Definition: buffer.h:16
classifier.h
ZC_T
const float ZC_T
Zero-crossings L-definition. For the thumb mic.
Definition: conndetect.cpp:37
FILT_HP_IMU_ACC
const us FILT_HP_IMU_ACC
Definition: filter.h:92
Features::setChannel
void setChannel(const Channel &channel)
Set channel data to operate on. BORROWS the data on which it operates, be carefull not to delete the ...
Definition: conndetect_features.cpp:43
Features
This class provides the calculations of single-signal features, computed from a single channel with l...
Definition: conndetect_features.h:18
ConnDetect::~ConnDetect
~ConnDetect()
Definition: conndetect.cpp:90
TimeDelay::determineDelay
float determineDelay(const Channel &mic1, const Channel &mic2)
Determine the delay between two microphone signals. A positive signal means that mic 1 comes [t] time...
Definition: timedelay.cpp:37
config.h
Configuration parameters for connection detection.
WAMP_LVPU
const float WAMP_LVPU
Willson amplitude L-definition. For the VPU.
Definition: conndetect.cpp:31
FilteredDataBuffer
Class containing filtered data. It is responsible for aggregating signal samples at the full audio sa...
Definition: buffer.h:24
FilteredDataBuffer::timeStamp
us timeStamp
Storage for statistics data.
Definition: buffer.h:48
FILT_LP500_VPU
const us FILT_LP500_VPU
Definition: filter.h:89
Features::kurtosis
float kurtosis()
Compute the kurtosis , scaled. It is defined as:
Definition: conndetect_features.cpp:70
ZC_VPU
const float ZC_VPU
Zero-crossings L-definition. For the VPU.
Definition: conndetect.cpp:49
raw_conndetect_auxtask_callback
void raw_conndetect_auxtask_callback(void *raw_ptr)
Definition: conndetect.cpp:63
tools.h
logFileName
const char *const logFileName
The filename containing logged data. If you change this, please also update the file ....
Definition: config.h:153
FILT_HP8k_MICW
const us FILT_HP8k_MICW
Definition: filter.h:84
FILT_HP2k_MICT
const us FILT_HP2k_MICT
Definition: filter.h:80
Features::zc
float zc(float zc_l)
Compute zero-crossings with a difference larger than zcl.
Definition: conndetect_features.cpp:153
SimpleFeatures::hasNonZero
static float hasNonZero(const Channel &i)
Find a nonzero in the array.
Definition: conndetect_features.h:219
Features::peak_dB
float peak_dB()
Compute the peak level in dB (full scale, normalized to 1). The equation is:
Definition: conndetect_features.cpp:55
ZC_W
const float ZC_W
Zero-crossings L-definition. For the wrist mic.
Definition: conndetect.cpp:43
SimpleFeatures::average
static float average(const Channel &i)
Compute the average of a channel value.
Definition: conndetect_features.h:209