CSL 5.2

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

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
30 SHARCSpectrum::~SHARCSpectrum() {
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
83 unsigned SHARCSpectrum::count_partials() {
84 return _num_partials;
85 }
86
87 void SHARCSpectrum::dump_example() {
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
105 SHARCInstrument::~SHARCInstrument() {
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
144 char * * SHARCInstrument::spectrum_names(){
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
153 unsigned * SHARCInstrument::spectrum_keys() {
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
162 float * SHARCInstrument::spectrum_frequencies() {
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
171 SHARCSpectrum * SHARCInstrument::spectrum_named(char * name) {
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
180 SHARCSpectrum * SHARCInstrument::spectrum_with_key(unsigned key) {
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
189 SHARCSpectrum * SHARCInstrument::spectrum_with_frequency(float freq) {
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
200 unsigned SHARCInstrument::count_spectra() {
201 return _num_spectra;
202 }
203
204 unsigned SHARCInstrument::count_partials() {
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
215 void SHARCInstrument::dump_example() {
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
224 SHARCLibrary::SHARCLibrary() { }
225
226 SHARCLibrary::~SHARCLibrary() {
227 free(_instruments);
228 }
229
230 // Populating constructor
231
232 SHARCLibrary::SHARCLibrary(char * name) {
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
240 bool SHARCLibrary::read_from_directory(char * folder) {
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
274 char ** SHARCLibrary::instrument_names() {
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
283 SHARCInstrument * SHARCLibrary::instrument_named(char * name) {
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(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
300 void SHARCLibrary::dump_stats() {
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
315 void SHARCLibrary::dump_example() {
316 SHARCInstrument * inst;
317 inst = _instruments[7];
318 inst->dump_example();
319 }
320
321 ///////////////////////////////////////////////////////////////////////////////////////////////////////
322
323 /// Global SHARC library
324
325 SHARCLibrary * SHARCLibrary::sSHARCLib = 0;
326
327 void SHARCLibrary::loadDefault() {
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());
333 sSHARCLib->dump_stats();
334 }
335
336 // Get the global library ptr
337
338 SHARCLibrary * SHARCLibrary::library() {
339 if ( ! sSHARCLib) // initialize lazily
340 loadDefault();
341 return sSHARCLib;
342 }
343
344 // Library and Instrument accessors
345
346 SHARCInstrument * SHARCLibrary::instrument(char * instr) {
347 if ( ! sSHARCLib)
348 loadDefault();
349 return sSHARCLib->instrument_named(instr);
350 }
351
352 SHARCInstrument * SHARCLibrary::instrument(unsigned instr) {
353 if ( ! sSHARCLib)
354 loadDefault();
355 return sSHARCLib->instrument_named(sSHARCLib->instrument_names()[instr]);
356 }
357
358 SHARCSpectrum * SHARCLibrary::spectrum(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(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();
375 SHARCInstrument * inst = sSHARCLib->instrument_named(sSHARCLib->instrument_names()[instr]);
376 return inst->spectrum_with_key(note);
377 }
378
379 // dump
380
381 void SHARCLibrary::dump() {
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 }