Voss Connection Detection  1
Detect a connector click using realtime code on Bela hardware
tools.cpp
Go to the documentation of this file.
1 #include <iostream>
2 #include <dirent.h>
3 #include <sys/types.h>
4 #include <sys/stat.h>
5 #include <vector>
6 #include <cmath>
7 #include <Bela.h>
8 #include "tools.h"
9 #include "conndetect.h" // For NUMBER_FEATURES
10 
11 using namespace std;
12 
13 
14 static bool in(const vector<string>& list,const string& key) {
15  for(auto& item: list) {
16  if(item == key) return true;
17  }
18  return false;
19 }
20 
31 static string unique_name(const string& basename, const string& ext) {
32 
33  vector<string> dir_contents = list_dir(".");
34  string full_name, new_basename;
35  string number;
36  int i = 0;
37 
38  do {
39 
40  if(i<10) number = "0" + to_string(i);
41  else number = to_string(i);
42 
43  new_basename = basename + "_" + number;
44  full_name = new_basename + ext;
45 
46  i++;
47 
48  } while(in(dir_contents, full_name));
49 
50  return full_name;
51 }
52 
53 
54 bool StartupSanityChecks(BelaContext *context) {
55 
56  if (NCHANNELS_INPUT_AUDIO != context->audioInChannels) {
57  cerr << "Unexpected number of audio in channels. Given: "
58  << context->analogInChannels
59  << ". But required: " << NCHANNELS_INPUT_ANALOG << endl;
60  return false;
61  }
62 
63  if (NCHANNELS_INPUT_ANALOG != context->analogInChannels) {
64  cerr << "Unexpected number of analog in channels. Given: "
65  << context->analogInChannels
66  << ". But required: " << NCHANNELS_INPUT_ANALOG << endl;
67  return false;
68  }
69 
70  if (context->analogFrames != PERIOD_SIZE) {
71  cerr << "analogFrames should be equal to " << PERIOD_SIZE << "!" << endl;
72  return false;
73  }
74 
75  if (context->audioFrames != context->analogFrames) {
76  cerr << "The number of audio frames should be equal to the number of "
77  "analog frames!"
78  << endl;
79  return false;
80  }
81 
82  if (context->digitalFrames != context->analogFrames) {
83  cerr << "The number of digital frames does not match analog frames! "
84  "Digital is: "
85  << context->digitalFrames << "." << endl;
86  return false;
87  }
88 
89  // Sanity checks for sensors etc.
90  if (fabsf(context->audioSampleRate - SAMPLING_FREQUENCY) > 1e-4) {
91  cerr << "Invalid audio sampling frequency, should be " << SAMPLING_FREQUENCY
92  << ", but is set at: " << context->audioSampleRate << "." << endl;
93  return false;
94  }
95 
96  // Sanity checks for sensors etc.
97  if (fabsf(context->analogSampleRate - SAMPLING_FREQUENCY) > 1e-4) {
98  cerr << "Invalid analog sampling frequency, should be "
100  << ", but is set at: " << context->analogSampleRate << "." << endl;
101  fprintf(stderr, "Diff is: %0.4e]n",
102  (context->analogSampleRate - SAMPLING_FREQUENCY));
103  return false;
104  }
105  return true;
106 }
107 
108 vector<string> list_dir(const char *path) {
109  struct dirent *entry;
110  DIR *dir = opendir(path);
111  vector<string> dir_contents;
112 
113  if (dir == NULL) {
114  return dir_contents;
115  }
116  while ((entry = readdir(dir)) != NULL) {
117  dir_contents.push_back(entry->d_name);
118  }
119  closedir(dir);
120  return dir_contents;
121 }
122 
123 time_t last_modification_time(const std::string& filepath) {
124  struct stat file_stat;
125  if(stat(filepath.c_str(), &file_stat) != 0) {
126  throw std::runtime_error("Cannot stat file!");
127  }
128  return file_stat.st_mtime;
129 }
130 
131 
132 template <us num_cols>
133 LogFile<num_cols>::LogFile(const char* filename, const char* header,bool createUnique) {
134 
135  string str_filename = filename;
136  if(createUnique) {
138  string basename = str_filename.substr(0, str_filename.length() -4);
139  string ext = str_filename.substr(str_filename.length() -4,
140  str_filename.length());
141  str_filename = unique_name(basename, ext);
142  }
143 
144 
145  static_assert(num_cols > 0, "num_cols should be > 0");
149  file = new WriteFile();
150  if(!file) throw std::runtime_error("Could not create logfile!");
151  file->setup(str_filename.c_str(),
152  true, // <==overwrite
153  false // <== append
154  );
155 
156  file->setFileType(kText);
157  string header_str = header;
158  if(header_str[header_str.size()-1] != '\n') {
159  header_str += "\n";
160  }
161 
162  // Create the file format
163  string fileFormat = logFileFormat;
164  for(us col=0; col < num_cols-1; col++) {
165  fileFormat += string(",") + logFileFormat;
166  }
167  fileFormat += "\n";
168  file->setFormat(fileFormat.c_str());
169 
170  // Set the header
171  file->setHeader(header_str.c_str());
172  file->setFooter("");
173 
174 }
175 
176 template <us num_cols>
177 void LogFile<num_cols>::log(const std::array<float, num_cols>& data) {
178  file->log(data.data(), data.size());
179 }
180 
181 template <us num_cols>
183  delete file;
184 }
185 
186 
187 // Explicit instantiation
188 template class LogFile<NUMBER_FEATURES>;
189 
190 
191 static bool existsAndIsNumber(JSONObject& json, const std::wstring& str)
192 {
193  return (json.find(str) != json.end() && json[str]->IsNumber());
194 }
195 double retrieveAsNumber(JSONObject& json, const std::string& str)
196 {
197  std::wstring ws = JSON::s2ws(str);
198  if(existsAndIsNumber(json, ws))
199  {
200  double ret = json[ws]->AsNumber();
201  /* printf("Received parameter \"%s\": %f\n", str.c_str(), ret); */
202  return ret;
203  }
204  else
205  throw(std::runtime_error("Value " + str + "not found\n"));
206 }
207 
208 
209 
LogFile::~LogFile
~LogFile()
Definition: tools.cpp:182
SAMPLING_FREQUENCY
const float SAMPLING_FREQUENCY
This is the exact sampling frequency of the system. Do not change!
Definition: config.h:99
StartupSanityChecks
bool StartupSanityChecks(BelaContext *context)
Perform sanity checks on startup, for the parameters that should be set properly in 'settings'....
Definition: tools.cpp:54
conndetect.h
NCHANNELS_INPUT_AUDIO
const int NCHANNELS_INPUT_AUDIO
These are the amount of channels enabled for audio input on the Bela board. The audio input channels ...
Definition: config.h:87
LogFile< NUMBER_FEATURES >
retrieveAsNumber
double retrieveAsNumber(JSONObject &json, const std::string &str)
Searches for the key str in the JSON object and returns a the number. Throws a runtime error if the k...
Definition: tools.cpp:195
PERIOD_SIZE
const int PERIOD_SIZE
Definition: config.h:49
last_modification_time
time_t last_modification_time(const std::string &filepath)
Determine the last modification time of a file and returns it as a time_t value.
Definition: tools.cpp:123
LogFile::log
void log(const std::array< float, num_cols > &data)
Log the data to the file.
Definition: tools.cpp:177
LogFile::LogFile
LogFile(const char *filename, const char *header, bool createUnique=true)
Initialize a log file.
Definition: tools.cpp:133
list_dir
vector< string > list_dir(const char *path)
List the contents of a directory path, and return the contents.
Definition: tools.cpp:108
us
unsigned int us
Used to much to not abbreviate.
Definition: config.h:38
NCHANNELS_INPUT_ANALOG
const int NCHANNELS_INPUT_ANALOG
These are the amount of channels enabled for analog input on the Bela board. Only for the setting of ...
Definition: config.h:81
logFileFormat
const char *const logFileFormat
The format for representing numbers in the log file. I.e. %3.1f means three number before the decimal...
Definition: config.h:146
tools.h