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