CSL  6.0
SHARC.cpp
Go to the documentation of this file.
1 //
2 // SHARC.cpp -- SHARC timbre database sample classes
3 // See the copyright notice and acknowledgment of authors in the file COPYRIGHT
4 //
5 #include "SHARC.h"
6 
7 #include <math.h>
8 #include <stdlib.h>
9 #include <unistd.h>
10 #include <sys/stat.h>
11 #include <dirent.h>
12 #include <stdio.h>
13 #include <string.h>
14 
15 using namespace csl;
16 
17 // SHARCSpectrum implementation
18 // Populating constructor
19 
20 SHARCSpectrum::SHARCSpectrum(char * folder, char * name, unsigned m_key,
21  float n_pitch, float a_pitch, unsigned m_amp, unsigned n_partials) :
22  _midi_key(m_key), _nom_pitch(n_pitch), _actual_pitch(a_pitch),
23  _max_amp(m_amp), _num_partials(n_partials) {
24  _note_name = (char *) malloc(strlen(name) + 1);
25  strcpy(_note_name, name);
26  _partials = (Partial **) malloc(n_partials * (sizeof(char *)));
27  this->read_from_file(folder, name);
28 }
29 
31  free(_note_name);
32  free(_partials);
33 }
34 
35 // File reader
36 
37 bool SHARCSpectrum::SHARCSpectrum::read_from_file(char * folder, char * name) {
38  FILE * inp;
39  char cmd[CSL_NAME_LEN];
40  char f_name[CSL_NAME_LEN];
41  float amp, phas;
42  Partial * harm;
43  unsigned p_count = 0;
44 
45  sprintf(cmd, "ls %s/*%s.spect", folder, name);
46  inp = popen(cmd, "r");
47  if (inp == NULL) {
48  printf("\tError reading command %s\n", cmd);
49  return false;
50  }
51  char * retC = fgets(f_name, CSL_NAME_LEN, inp);
52  pclose(inp);
53  unsigned len = strlen(f_name);
54  if ((retC == NULL) || (len < 2)) {
55  printf("\tError finding file %s\n", cmd);
56  return false;
57  }
58  if (f_name[len - 1] == '\n')
59  f_name[len - 1] = 0;
60  inp = fopen(f_name, "r");
61  if (inp == NULL) {
62  printf("\tError opening file %s\n", f_name);
63  return false;
64  }
65  while( ! feof(inp)) {
66  fscanf(inp, "%f %f\n", &amp, &phas);
67  harm = (Partial *) malloc(sizeof(Partial));
68  harm->number = p_count + 1;
69  // Scale the negative dB value to the range 0-1
70  harm->amplitude = (float) pow(10.0, (((double) amp) / 20.0));
71  harm->phase = phas;
72  _partials[p_count++] = harm;
73  }
74 // printf("\tRead %d harmonics (exp %d) for spectrum %s\n", p_count, _num_partials, name);
75  fclose(inp);
76  if (p_count != _num_partials) {
77  printf("\tError: number of partials found (%d) not what I expected (%d) for %s in %s\n", p_count, _num_partials, name, folder);
78 // return false;
79  }
80  return true;
81 }
82 
84  return _num_partials;
85 }
86 
88  Partial * harm;
89  printf("\tFR @ AMP @ PHA\n");
90  for (unsigned i = 0; i < _num_partials; i++) {
91  harm = _partials[i];
92  printf("\t%d @ %.5f @ %.5f\n", ((int) harm->number), harm->amplitude, harm->phase);
93  }
94 }
95 
96 // SHARCInstrument implementation
97 // Constructor, etc
98 
99 SHARCInstrument::SHARCInstrument(char * folder, char * name) {
100  _num_spectra = 0;
101  _spectra = (SHARCSpectrum **) malloc(MAX_SPECTRA * (sizeof(char *)));
102  this->read_from_TOC(folder, name);
103 }
104 
106  free(_spectra);
107 }
108 
109 // Load all the samples described in the given CONTENTS file
110 
111 bool SHARCInstrument::read_from_TOC(char * folder, char * name) {
112  FILE * input;
113  float real_freq, nom_freq, dur, start, centroid;
114  unsigned note_num, num_harm, m1, m2, m3, max_amp;
115  char note_name[8], f_name[256];
116  SHARCSpectrum * spect;
117  _name = (char *) malloc(strlen(name) + 1);
118  strcpy(_name, name);
119  _num_spectra = 0;
120  sprintf(f_name, "%s/%s/CONTENTS", folder, name);
121  // Open the instrument's contents file
122  input = fopen(f_name, "r");
123  if (input == NULL) {
124  printf("\tError opening file %s\n", f_name);
125  return false;
126  }
127  sprintf(f_name, "%s/%s", folder, name);
128  // Read through it line by line, loading the spectra described by the lines
129  while( ! feof(input)) {
130  fscanf(input, "%s %d %d %d %f %f %d %d %d %f %f %f\n",
131  note_name, &note_num, &num_harm, &max_amp, &nom_freq, &real_freq,
132  &m1, &m2, &m3, &dur, &start, &centroid);
133  spect = new SHARCSpectrum(f_name, note_name, note_num, nom_freq, real_freq,
134  max_amp, num_harm);
135  _spectra[_num_spectra++] = spect;
136  }
137 // printf("\tRead %d spectra for sample %s\n", _num_spectra, _name);
138  fclose(input);
139  return true;
140 }
141 
142 // Accessing utilities
143 
145  char * * names = (char * *) malloc(_num_spectra * (sizeof(char *)));
146 
147  for (unsigned i = 0; i < _num_spectra; i++) {
148  names[i] = _spectra[i]->_note_name;
149  }
150  return names;
151 }
152 
154  unsigned * names = (unsigned *) malloc(_num_spectra * (sizeof(unsigned)));
155 
156  for (unsigned i = 0; i < _num_spectra; i++) {
157  names[i] = _spectra[i]->_midi_key;
158  }
159  return names;
160 }
161 
163  float * names = (float *) malloc(_num_spectra * (sizeof(float)));
164 
165  for (unsigned i = 0; i < _num_spectra; i++) {
166  names[i] = _spectra[i]->_actual_pitch;
167  }
168  return names;
169 }
170 
172  for (unsigned i = 0; i < _num_spectra; i++) {
173  if ( ! strcmp(_spectra[i]->_note_name, name)) {
174  return _spectra[i];
175  }
176  }
177  return (SHARCSpectrum *) 0;
178 }
179 
181  for (unsigned i = 0; i < _num_spectra; i++) {
182  if (_spectra[i]->_midi_key == key) {
183  return _spectra[i];
184  }
185  }
186  return (SHARCSpectrum *) 0;
187 }
188 
190  for (unsigned i = 0; i < _num_spectra; i++) {
191  if (_spectra[i]->_actual_pitch == freq) {
192  return _spectra[i];
193  }
194  }
195  return (SHARCSpectrum *) 0;
196 }
197 
198 // Debugging functions
199 
201  return _num_spectra;
202 }
203 
205  unsigned part_c;
206  SHARCSpectrum * spect;
207  part_c = 0;
208  for (unsigned i = 0; i < _num_spectra; i++) {
209  spect = _spectra[i];
210  part_c += spect->count_partials();
211  }
212  return part_c;
213 }
214 
216  SHARCSpectrum * spect;
217  spect = _spectra[2];
218  printf("\tSample spectrum for instrument %s sample %s\n", _name, spect->_note_name);
219  spect->dump_example();
220 }
221 
222 // SHARCLibrary implementation
223 
225 
227  free(_instruments);
228 }
229 
230 // Populating constructor
231 
233  _num_instruments = 0;
234  _instruments = (SHARCInstrument ** ) malloc(MAX_INSTRUMENTS * (sizeof(char *)));
235  this->read_from_directory(name);
236 }
237 
238 // File reader -- open the named directory and load all subdirectories
239 
241  SHARCInstrument * inst;
242  DIR * dir_p;
243  struct stat stat_p;
244  struct dirent * entry_p;
245  char f_name[256];
246  // Iterate over the given folder and its sub-folders
247  fprintf(stderr, "Loading SHARC database from folder %s\n", folder);
248  dir_p = opendir(folder);
249  while(NULL != (entry_p = readdir(dir_p))) {
250  if (entry_p->d_name[0] != '.') { // ignore . and ..
251  // printf("Examining %s \t", entry_p->d_name);
252  sprintf(f_name, "%s/%s", folder, entry_p->d_name);
253  // Stat the file, check if it's a directory
254  if (stat (f_name, &stat_p) < 0) {
255  printf("\tError checking file %s\n", f_name);
256  return false;
257  }
258  // If yes, load the instrument in the subdirectory
259  if (S_ISDIR(stat_p.st_mode)) {
260  inst = new SHARCInstrument(folder, entry_p->d_name);
261  _instruments[_num_instruments++] = inst;
262  //} else {
263  // printf("\tFile %s is not a directory\n", f_name);
264  }
265  }
266  }
267  closedir(dir_p);
268 // printf("Read %d instruments %s\n", _num_instruments, folder);
269  return true;
270 }
271 
272 // Accessing utilities
273 
275  char * * names = (char * *) malloc(_num_instruments * (sizeof(char *)));
276 
277  for (unsigned i = 0; i < _num_instruments; i++) {
278  names[i] = _instruments[i]->_name;
279  }
280  return names;
281 }
282 
284  for (unsigned i = 0; i < _num_instruments; i++) {
285  if ( ! strcmp(_instruments[i]->_name, name)) {
286  return _instruments[i];
287  }
288  }
289  return (SHARCInstrument *) 0;
290 }
291 
292 SHARCSpectrum * SHARCLibrary::spectrum_named(const char * inst, char * spect) {
293  SHARCInstrument * in = this->instrument_named(inst);
294  if (in == NULL) return (SHARCSpectrum *) 0;
295  return (in->spectrum_named(spect));
296 }
297 
298 // Print out the library sizes
299 
301  unsigned inst_c, spect_c, part_c;
302  SHARCInstrument * inst;
303  inst_c = spect_c = part_c = 0;
304  for (unsigned i = 0; i < _num_instruments; i++) {
305  inst = _instruments[i];
306  inst_c++;
307  spect_c += inst->count_spectra();
308  part_c += inst->count_partials();
309  }
310  logMsg("Loaded SHARC library = %d instruments, %d spectra, %d partials\n", inst_c, spect_c, part_c);
311 }
312 
313 // Dump an example spectrum
314 
316  SHARCInstrument * inst;
317  inst = _instruments[7];
318  inst->dump_example();
319 }
320 
321 ///////////////////////////////////////////////////////////////////////////////////////////////////////
322 
323 /// Global SHARC library
324 
326 
328  if (sSHARCLib)
329  return;
330  string folder(CGestalt::dataFolder());
331  folder += "SHARC"; // load the SHARC library
332  sSHARCLib = new SHARCLibrary((char *)folder.c_str());
334 }
335 
336 // Get the global library ptr
337 
339  if ( ! sSHARCLib) // initialize lazily
340  loadDefault();
341  return sSHARCLib;
342 }
343 
344 // Library and Instrument accessors
345 
347  if ( ! sSHARCLib)
348  loadDefault();
349  return sSHARCLib->instrument_named(instr);
350 }
351 
353  if ( ! sSHARCLib)
354  loadDefault();
356 }
357 
358 SHARCSpectrum * SHARCLibrary::spectrum(const char * instr, char * note) {
359  if ( ! sSHARCLib)
360  loadDefault();
361  SHARCInstrument * inst = sSHARCLib->instrument_named(instr);
362  return inst->spectrum_named(note);
363 }
364 
365 SHARCSpectrum * SHARCLibrary::spectrum(const char * instr, unsigned note) {
366  if ( ! sSHARCLib)
367  loadDefault();
368  SHARCInstrument * inst = sSHARCLib->instrument_named(instr);
369  return inst->spectrum_with_key(note);
370 }
371 
372 SHARCSpectrum * SHARCLibrary::spectrum(unsigned instr, unsigned note) {
373  if ( ! sSHARCLib)
374  loadDefault();
376  return inst->spectrum_with_key(note);
377 }
378 
379 // dump
380 
382  SHARCInstrument * inst;
383  char ** i_names, ** s_names;
384  unsigned i;
385  i_names = instrument_names();
386 
387  printf("Names of instruments:\n"); // print the list of instruments
388  for (i = 0; i < _num_instruments; i++)
389  printf("\t%s\n", i_names[i]);
390  inst = instrument_named(i_names[7]);
391 
392  printf("Names of samples in instrument %s:\n", inst->_name);
393  s_names = inst->spectrum_names(); // print the notes in a selected instrument
394  for (i = 0; i < inst->_num_spectra; i++)
395  printf("\t%s\n", s_names[i]);
396 }
static void loadDefault()
Definition: SHARC.cpp:327
void logMsg(const char *format,...)
These are the public logging messages.
Definition: CGestalt.cpp:292
unsigned count_partials()
Definition: SHARC.cpp:204
unsigned * spectrum_keys()
Definition: SHARC.cpp:153
bool read_from_directory(char *name)
Definition: SHARC.cpp:240
AdditiveInstrument.h – Sum-of-sines synthesis instrument class.
Definition: Accessor.h:17
static SHARCInstrument * instrument(char *instr)
Definition: SHARC.cpp:346
char ** instrument_names()
Definition: SHARC.cpp:274
float * spectrum_frequencies()
Definition: SHARC.cpp:162
unsigned _midi_key
Definition: SHARC.h:80
SHARCSpectrum ** _spectra
Definition: SHARC.h:105
Partial ** _partials
Definition: SHARC.h:85
void dump_example()
Definition: SHARC.cpp:315
static SHARCLibrary * library()
Definition: SHARC.cpp:338
unsigned _num_instruments
Definition: SHARC.h:133
SHARC library class.
Definition: SHARC.h:130
bool read_from_TOC(char *folder, char *name)
Definition: SHARC.cpp:111
SHARCInstrument * instrument_named(const char *name)
Definition: SHARC.cpp:283
float _actual_pitch
Definition: SHARC.h:82
char ** spectrum_names()
Definition: SHARC.cpp:144
#define CSL_NAME_LEN
default string length
Definition: CSL_Types.h:121
void dump_example()
Definition: SHARC.cpp:87
static SHARCSpectrum * spectrum(const char *instr, char *note)
Definition: SHARC.cpp:358
Struct for partial overtones.
Definition: Oscillator.h:164
unsigned count_partials()
Definition: SHARC.cpp:83
SHARC instrument class.
Definition: SHARC.h:100
unsigned _num_partials
Definition: SHARC.h:84
char * _note_name
Definition: SHARC.h:79
static unsigned len
Definition: fft_N.c:39
SHARCSpectrum * spectrum_with_frequency(float freq)
Definition: SHARC.cpp:189
SHARCSpectrum(char *folder, char *name, unsigned m_key, float n_pitch, float a_pitch, unsigned m_amp, unsigned n_partials)
Definition: SHARC.cpp:20
SHARCInstrument(char *folder, char *name)
Definition: SHARC.cpp:99
#define MAX_INSTRUMENTS
Definition: SHARC.h:68
float amplitude
Definition: Oscillator.h:166
static SHARCLibrary * sSHARCLib
The protected single instance of the HRTF Database.
Definition: SHARC.h:149
bool read_from_file(char *folder, char *name)
unsigned count_spectra()
Definition: SHARC.cpp:200
SHARCInstrument ** _instruments
Definition: SHARC.h:134
void dump_stats()
Definition: SHARC.cpp:300
SHARCSpectrum * spectrum_named(char *name)
Definition: SHARC.cpp:171
#define MAX_SPECTRA
Definition: SHARC.h:67
SHARCSpectrum * spectrum_named(const char *inst, char *spect)
Definition: SHARC.cpp:292
float number
Definition: Oscillator.h:165
SHARCSpectrum * spectrum_with_key(unsigned key)
Definition: SHARC.cpp:180
unsigned _num_spectra
Definition: SHARC.h:104
SHARC spectrum class.
Definition: SHARC.h:76
static std::string dataFolder()
the default directory for test data
Definition: CGestalt.cpp:71