1 // -----------------------------------------------------------------------------
2 //
3 // Copyright (C) 2006-2018 Fons Adriaensen <fons@linuxaudio.org>
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 //
18 // -----------------------------------------------------------------------------
19
20
21 #include <stdlib.h>
22 #include <string.h>
23 #include "impdata.h"
24
25
26 #define HDRSIZE 256
27
28
29 //------------------------------------------------------------------------------------------------------------
30
31
Impdata(void)32 Impdata::Impdata (void) :
33 _vers (0),
34 _type (0),
35 _rate_n (0),
36 _rate_d (1),
37 _n_fram (0),
38 _n_sect (0),
39 _tref_i (0),
40 _tref_n (0),
41 _tref_d (1),
42 _bits (0),
43 _i_fram (0),
44 _i_sect (0),
45 _mode (0),
46 _size (0),
47 _data (0),
48 _aldfile (0),
49 _sndfile (0)
50 {
51 }
52
53
~Impdata(void)54 Impdata::~Impdata (void)
55 {
56 close ();
57 delete[] _data;
58 }
59
60
set_type(uint32_t type)61 int Impdata::set_type (uint32_t type)
62 {
63 if (_mode) return ERR_MODE;
64 _type = type;
65 deall ();
66 return 0;
67 }
68
69
set_n_fram(uint32_t n_fram)70 int Impdata::set_n_fram (uint32_t n_fram)
71 {
72 if (_aldfile) return ERR_MODE;
73 _n_fram = n_fram;
74 deall ();
75 return 0;
76 }
77
78
set_n_sect(uint32_t n_sect)79 int Impdata::set_n_sect (uint32_t n_sect)
80 {
81 if (_aldfile) return ERR_MODE;
82 _n_sect = n_sect;
83 return 0;
84 }
85
86
alloc(void)87 int Impdata::alloc (void)
88 {
89 uint32_t k;
90
91 k = (_type & TYPE__CHAN) * _n_fram;
92 if (k != _size)
93 {
94 delete[] _data;
95 if (k)
96 {
97 _size = k;
98 _data = new float [k];
99 memset (_data, 0, _size * sizeof (float));
100 }
101 else
102 {
103 _size = 0;
104 _data = 0;
105 }
106 }
107 return 0;
108 }
109
110
deall(void)111 int Impdata::deall (void)
112 {
113 delete[] _data;
114 _data = 0;
115 _size = 0;
116 return 0;
117 }
118
119
clear(void)120 int Impdata::clear (void)
121 {
122 if (_data) memset (_data, 0, _size * sizeof (float));
123 return 0;
124 }
125
126
127 //------------------------------------------------------------------------------------------------------------
128
129
open_read(const char * name)130 int Impdata::open_read (const char *name)
131 {
132 char p [HDRSIZE];
133
134 if (_mode) return ERR_MODE;
135 deall ();
136 _type = 0;
137 _n_fram = 0;
138 _n_sect = 0;
139
140 if ((_aldfile = fopen (name, "r")) == 0) return ERR_OPEN;
141
142 if (fread (p, 1, HDRSIZE, _aldfile) != HDRSIZE)
143 {
144 fclose (_aldfile);
145 _aldfile = 0;
146 return ERR_READ;
147 }
148
149 if (strcmp (p, "aliki") || p [6] || p [7])
150 {
151 fclose (_aldfile);
152 _aldfile = 0;
153 return ERR_FORM;
154 }
155
156 _vers = *(uint32_t *)(p + 8);
157 if (_vers == 1)
158 {
159 _type = mapvers1 (*(uint32_t *)(p + 12));
160 _rate_n = *(uint32_t *)(p + 16);
161 _rate_d = 1;
162 _n_sect = *(uint32_t *)(p + 20);
163 _n_fram = *(uint32_t *)(p + 24);
164 _tref_i = *(uint32_t *)(p + 28);
165 _tref_n = 0;
166 _tref_d = 1;
167 _bits = 0;
168 }
169 else if (_vers == 2)
170 {
171 _type = *(uint32_t *)(p + 12);
172 _rate_n = *(uint32_t *)(p + 16);
173 _rate_d = *(uint32_t *)(p + 20);
174 _n_fram = *(uint32_t *)(p + 24);
175 _n_sect = *(uint32_t *)(p + 28);
176 _tref_i = *(uint32_t *)(p + 32);
177 _tref_n = *(uint32_t *)(p + 36);
178 _tref_d = *(uint32_t *)(p + 40);
179 _bits = *(uint32_t *)(p + 44);
180 }
181 else
182 {
183 fclose (_aldfile);
184 _aldfile = 0;
185 return ERR_FORM;
186 }
187
188 if (!_type || !_n_fram || !_n_sect)
189 {
190 fclose (_aldfile);
191 _aldfile = 0;
192 return ERR_FORM;
193 }
194
195 _mode = MODE_READ;
196 _i_sect = 0;
197 _i_fram = 0;
198
199 return 0;
200 }
201
202
open_write(const char * name)203 int Impdata::open_write (const char *name)
204 {
205 char p [HDRSIZE];
206
207 if (_mode || !_type || !_n_fram || !_n_sect) return ERR_MODE;
208
209 if ((_aldfile = fopen (name, "w")) == 0) return ERR_OPEN;
210
211 strcpy (p, "aliki");
212 p [6] = p [7] = 0;
213 *(uint32_t *)(p + 8) = _vers = 2;
214 *(uint32_t *)(p + 12) = _type;
215 *(uint32_t *)(p + 16) = _rate_n;
216 *(uint32_t *)(p + 20) = _rate_d;
217 *(uint32_t *)(p + 24) = _n_fram;
218 *(uint32_t *)(p + 28) = _n_sect;
219 *(uint32_t *)(p + 32) = _tref_i;
220 *(uint32_t *)(p + 36) = _tref_n;
221 *(uint32_t *)(p + 40) = _tref_d;
222 *(uint32_t *)(p + 44) = _bits;
223
224 memset (p + 48, 0, HDRSIZE - 48);
225 if (fwrite (p, 1, HDRSIZE, _aldfile) != HDRSIZE)
226 {
227 fclose (_aldfile);
228 _aldfile = 0;
229 return ERR_WRITE;
230 }
231
232 _mode = MODE_WRITE;
233 _i_sect = 0;
234 _i_fram = 0;
235
236 return 0;
237 }
238
239
sf_open_read(const char * name)240 int Impdata::sf_open_read (const char *name)
241 {
242 SF_INFO I;
243
244 if (_mode) return ERR_MODE;
245 deall ();
246 _type = 0;
247 _n_fram = 0;
248 _n_sect = 0;
249
250 if ((_sndfile = sf_open (name, SFM_READ, &I)) == 0) return ERR_OPEN;
251
252 _type = TYPE_RAW + I.channels;
253 _rate_n = I.samplerate;
254 _rate_d = 1;
255 _n_sect = 1;
256 _n_fram = I.frames;
257 _tref_i = 1;
258 _tref_n = 0;
259 _tref_d = 1;
260 _bits = 0;
261
262 if (sf_command (_sndfile, SFC_WAVEX_GET_AMBISONIC, 0, 0) == SF_AMBISONIC_B_FORMAT)
263 {
264 switch (I.channels)
265 {
266 case 3: _type = TYPE_AMB_B3; break;
267 case 4: _type = TYPE_AMB_B4; break;
268 }
269 }
270
271 if (!_n_fram)
272 {
273 sf_close (_sndfile);
274 _sndfile = 0;
275 return ERR_FORM;
276 }
277
278 _mode = MODE_READ;
279
280 return 0;
281 }
282
283
sf_open_write(const char * name)284 int Impdata::sf_open_write (const char *name)
285 {
286 SF_INFO I;
287
288 if (_mode || !_type || !_n_fram || !_n_sect) return ERR_MODE;
289
290 I.channels = _type & TYPE__CHAN;
291 I.format = (I.channels > 2) ? SF_FORMAT_WAVEX : SF_FORMAT_WAV;
292 I.format |= SF_FORMAT_FLOAT;
293 I.samplerate = _rate_n / _rate_d;
294 I.sections = 1;
295
296 if ((_sndfile = sf_open (name, SFM_WRITE, &I)) == 0) return ERR_OPEN;
297
298 switch (_type)
299 {
300 case TYPE_AMB_B3:
301 case TYPE_AMB_B4:
302 sf_command (_sndfile, SFC_WAVEX_SET_AMBISONIC, 0, SF_AMBISONIC_B_FORMAT);
303 break;
304 }
305
306 _mode = MODE_WRITE;
307 _i_sect = 0;
308 _i_fram = 0;
309
310 return 0;
311 }
312
313
close(void)314 int Impdata::close (void)
315 {
316 if (_aldfile)
317 {
318 fclose (_aldfile);
319 _aldfile = 0;
320 }
321 else if (_sndfile)
322 {
323 sf_close (_sndfile);
324 _sndfile = 0;
325 }
326 _mode = 0;
327 return 0;
328 }
329
330
331 //------------------------------------------------------------------------------------------------------------
332
333
seek_sect(uint32_t i_sect)334 int Impdata::seek_sect (uint32_t i_sect)
335 {
336 if (_aldfile)
337 {
338 if (fseek (_aldfile, HDRSIZE + (_type & TYPE__CHAN) * _n_fram * i_sect * sizeof (float), SEEK_SET)) return ERR_SEEK;
339 _i_sect = i_sect;
340 _i_fram = 0;
341 return 0;
342 }
343 else if (_sndfile)
344 {
345 if (sf_seek (_sndfile, _n_fram * i_sect, SEEK_SET) != _n_fram * i_sect) return ERR_SEEK;
346 _i_sect = i_sect;
347 _i_fram = 0;
348 return 0;
349 }
350 else return ERR_MODE;
351 }
352
353
read_sect(uint32_t i_sect)354 int Impdata::read_sect (uint32_t i_sect)
355 {
356 int r;
357
358 r = locate (i_sect);
359 if (r) return r;
360 return _data ? read_ext (_n_fram, _data) : ERR_DATA;
361 }
362
363
write_sect(uint32_t i_sect)364 int Impdata::write_sect (uint32_t i_sect)
365 {
366 int r;
367
368 r = locate (i_sect);
369 if (r) return r;
370 return _data ? write_ext (_n_fram, _data) : ERR_DATA;
371 }
372
373
seek_ext(uint32_t k)374 int Impdata::seek_ext (uint32_t k)
375 {
376 if (_aldfile)
377 {
378 if (fseek (_aldfile, HDRSIZE + (_type & TYPE__CHAN) * k * sizeof (float), SEEK_SET)) return ERR_SEEK;
379 _i_fram = k;
380 return 0;
381 }
382 else if (_sndfile)
383 {
384 if (sf_seek (_sndfile, k, SEEK_SET) != k) return ERR_SEEK;
385 _i_fram = k;
386 return 0;
387 }
388 else return ERR_MODE;
389 }
390
391
read_ext(uint32_t k,float * p)392 int Impdata::read_ext (uint32_t k, float *p)
393 {
394 if (_mode != MODE_READ) return ERR_MODE;
395 if (k > _n_fram - _i_fram) k = _n_fram - _i_fram;
396 if (_aldfile)
397 {
398 k = fread (p, (_type & TYPE__CHAN) * sizeof (float), k, _aldfile);
399 }
400 else if (_sndfile)
401 {
402 k = sf_readf_float (_sndfile, p, k);
403 }
404 else return ERR_MODE;
405 _i_fram += k;
406 return k;
407 }
408
409
write_ext(uint32_t k,float * p)410 int Impdata::write_ext (uint32_t k, float *p)
411 {
412 if (_mode != MODE_WRITE) return ERR_MODE;
413 if (k > _n_fram - _i_fram) k = _n_fram - _i_fram;
414 if (_aldfile)
415 {
416 k = fwrite (p, (_type & TYPE__CHAN) * sizeof (float), k, _aldfile);
417 }
418 else if (_sndfile)
419 {
420 k = sf_writef_float (_sndfile, p, k);
421 }
422 else return ERR_MODE;
423 _i_fram += k;
424 return k;
425 }
426
427
428 //------------------------------------------------------------------------------------------------------------
429
430
mapvers1(uint32_t type)431 uint32_t Impdata::mapvers1 (uint32_t type)
432 {
433 if (type < 256) return TYPE_RAW | type;
434 switch (type)
435 {
436 case 0x0102: return TYPE_MS;
437 case 0x0202: return TYPE_SWEEP;
438 case 0x0103: return TYPE_AMB_B3;
439 case 0x0104: return TYPE_AMB_B4;
440 }
441 return TYPE_RAW | type;
442 }
443
444
checkext(char * name)445 void Impdata::checkext (char *name)
446 {
447 char *p;
448
449 p = strrchr (name, '.');
450 if (p && ! strcmp (p, ".ald")) return;
451 strcat (name, ".ald");
452 }
453
454
455 char Impdata::_suffix [12];
456 const char *Impdata::_suffix2 [] = { "F", "I" };
457 const char *Impdata::_suffix3 [] = { "L", "R" };
458 const char *Impdata::_suffix4 [] = { "M", "S" };
459 const char *Impdata::_suffix5 [] = { "LF", "RF", "LB", "RB" };
460 const char *Impdata::_suffix7 [] = { "W", "X", "Y", "Z" };
461 const char *Impdata::_suffix8 [] = { "Lin", "A-W", "32", "63", "125", "250", "500", "1k", "2k", "4k", "8k", "16k" };
462
463
channame(uint32_t type,uint32_t chan)464 const char *Impdata::channame (uint32_t type, uint32_t chan)
465 {
466 const char **p;
467
468 if (chan >= (type & TYPE__CHAN)) return 0;
469
470 switch (type & TYPE__TYPE)
471 {
472 case 0x00020000: p = _suffix2; break;
473 case 0x00030000: p = _suffix3; break;
474 case 0x00040000: p = _suffix4; break;
475 case 0x00050000: p = _suffix5; break;
476 case 0x00060000:
477 case 0x00070000: p = _suffix7; break;
478 case 0x00080000: p = _suffix8; break;
479 default: p = 0;
480 }
481
482 if (p) return p [chan];
483 sprintf (_suffix, "%d", chan + 1);
484 return _suffix;
485 }
486
487
488 //------------------------------------------------------------------------------------------------------------
489