source: roaraudio/libroardsp/convert.c @ 1059:dcb32066a3d6

Last change on this file since 1059:dcb32066a3d6 was 1059:dcb32066a3d6, checked in by phi, 15 years ago

added support for conv from bigger to smaller size

File size: 16.6 KB
Line 
1//convert.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008
5 *
6 *  This file is part of libroar a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  libroar is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 *  NOTE for everyone want's to change something and send patches:
24 *  read README and HACKING! There a addition information on
25 *  the license of this document you need to read before you send
26 *  any patches.
27 *
28 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
29 *  or libpulse*:
30 *  The libs libroaresd, libroararts and libroarpulse link this lib
31 *  and are therefore GPL. Because of this it may be illigal to use
32 *  them with any software that uses libesd, libartsc or libpulse*.
33 */
34
35#include "libroar.h"
36
37int roar_conv_bits (void * out, void * in, int samples, int from, int to) {
38 int format;
39
40 if ( from == to ) {
41  if ( in == out )
42   return 0;
43
44  memcpy(out, in, samples * from / 8);
45  return 0;
46 }
47
48 format = ((from / 8) << 4) + (to / 8);
49
50 switch (format) {
51  case 0x12: return roar_conv_bits_8to16( out, in, samples);
52  case 0x14: return roar_conv_bits_8to32( out, in, samples);
53  case 0x21: return roar_conv_bits_16to8( out, in, samples);
54  case 0x24: return roar_conv_bits_16to32(out, in, samples);
55  case 0x41: return roar_conv_bits_32to8( out, in, samples);
56  case 0x42: return roar_conv_bits_32to16(out, in, samples);
57  default:
58   errno = ENOSYS;
59   return -1;
60 }
61
62 return -1;
63}
64
65int roar_conv_bits_8to16 (void * out, void * in, int samples) {
66 char    * ip = (char   *)in;
67 int16_t * op = (int16_t*)out;
68 int i;
69
70 for (i = samples - 1; i >= 0; i--)
71  op[i] = ip[i] << 8;
72
73 return 0;
74}
75
76int roar_conv_bits_8to32  (void * out, void * in, int samples) {
77 char    * ip = (char   *)in;
78 int32_t * op = (int32_t*)out;
79 int i;
80
81 for (i = samples - 1; i >= 0; i--)
82  op[i] = ip[i] << 24;
83
84 return 0;
85}
86
87int roar_conv_bits_16to8 (void * out, void * in, int samples) {
88 int16_t * ip = (int16_t*)in;
89 char    * op = (char   *)out;
90 int i;
91
92 ROAR_DBG("roar_conv_bits_16to8(out=%p, in=%p, samples=%i) = ?", out, in, samples);
93
94 for (i = 0; i < samples; i++)
95  op[i] = ip[i] >> 8;
96
97 return 0;
98}
99
100int roar_conv_bits_16to32 (void * out, void * in, int samples) {
101 int16_t * ip = (int16_t*)in;
102 int32_t * op = (int32_t*)out;
103 int i;
104
105 for (i = samples - 1; i >= 0; i--)
106  op[i] = ip[i] << 16;
107
108 return 0;
109}
110
111int roar_conv_bits_32to8 (void * out, void * in, int samples) {
112 int32_t * ip = (int32_t*)in;
113 char    * op = (char   *)out;
114 int i;
115
116 for (i = 0; i < samples; i++)
117  op[i] = ip[i] >> 24;
118
119 return 0;
120}
121
122int roar_conv_bits_32to16 (void * out, void * in, int samples) {
123 int32_t * ip = (int32_t*)in;
124 int16_t * op = (int16_t*)out;
125 int i;
126
127 for (i = 0; i < samples; i++)
128  op[i] = ip[i] >> 16;
129
130 return 0;
131}
132
133int roar_conv_chans (void * out, void * in, int samples, int from, int to, int bits) {
134 if ( from == to ) {
135  if ( in == out )
136   return 0;
137
138  memcpy(out, in, samples * from * bits / 8);
139  return 0;
140 }
141
142 switch (bits) {
143  case 8:
144   switch (from) {
145    case 1:
146     switch (to) {
147      case  2: return roar_conv_chans_1to28(out, in, samples);
148      default: return roar_conv_chans_1ton8(out, in, samples, to);
149     }
150     break;
151    case 2:
152     switch (to) {
153      case  1: return roar_conv_chans_2to18(out, in, samples);
154      default: return -1;
155     }
156     break;
157    default:
158     switch (to) {
159      case  1: return roar_conv_chans_nto18(out, in, samples, from);
160      default: return -1;
161     }
162   }
163  break;
164  case 16:
165   switch (from) {
166    case 1:
167     switch (to) {
168      case  2: return roar_conv_chans_1to216(out, in, samples);
169      default: return roar_conv_chans_1ton16(out, in, samples, to);
170     }
171     break;
172    case 2:
173     switch (to) {
174      case  1: return roar_conv_chans_2to116(out, in, samples);
175      default: return -1;
176     }
177     break;
178    default:
179     switch (to) {
180      case  1: return roar_conv_chans_nto116(out, in, samples, from);
181      default: return -1;
182     }
183   }
184  break;
185  default: return -1;
186 }
187
188 return -1;
189}
190
191int roar_conv_chans_1ton8  (void * out, void * in, int samples, int to) {
192 char * ip = (char*) in, * op = (char*) out;
193 int i;
194 int c;
195
196 for (i = samples - 1; i >= 0; i--)
197  for (c = to - 1; c >= 0; c--)
198   op[i*to + c] = ip[i];
199
200 return 0;
201}
202
203int roar_conv_chans_1to28  (void * out, void * in, int samples) {
204 char * ip = (char*) in, * op = (char*) out;
205 int i, h;
206
207 samples--;
208
209 for (i = (h = samples) * 2; i >= 0; i -= 2, h--) {
210  op[i + 0] = ip[h];
211  op[i + 1] = ip[h];
212 }
213
214 return 0;
215}
216
217int roar_conv_chans_1ton16 (void * out, void * in, int samples, int to) {
218 int16_t * ip = (int16_t*) in, * op = (int16_t*) out;
219 int i;
220 int c;
221
222 for (i = samples - 1; i >= 0; i--)
223  for (c = to - 1; c >= 0; c--)
224   op[i*to + c] = ip[i];
225
226 return 0;
227}
228
229int roar_conv_chans_1to216 (void * out, void * in, int samples) {
230 int16_t * ip = (int16_t*) in, * op = (int16_t*) out;
231 int i, h;
232
233 samples--;
234
235 for (i = (h = samples) * 2; i >= 0; i -= 2, h--) {
236  op[i + 0] = ip[h];
237  op[i + 1] = ip[h];
238 }
239
240 return 0;
241}
242
243int roar_conv_chans_nto18  (void * out, void * in, int samples, int from) {
244 int8_t * ip = (int8_t*) in, * op = (int8_t*) out;
245 int i;
246 int c;
247 register int s;
248
249 samples /= from;
250
251 for (i = samples - 1; i >= 0; i--) {
252  s  = 0;
253
254  for (c = 0; c < from; c++)
255   s += ip[i*from + c];
256
257  s /= from;
258  op[i] = s;
259 }
260
261 return 0;
262}
263
264int roar_conv_chans_2to18  (void * out, void * in, int samples) {
265 int8_t * ip = (int8_t*) in, * op = (int8_t*) out;
266 int i, h;
267
268 samples -= 2;
269
270 for (h = (i = samples) / 2; i >= 0; i -= 2, h--)
271  op[h] = ((int)ip[i + 0] + (int)ip[i + 1]) / 2;
272
273 return 0;
274}
275
276int roar_conv_chans_nto116 (void * out, void * in, int samples, int from) {
277 int16_t * ip = (int16_t*) in, * op = (int16_t*) out;
278 int i;
279 int c;
280 register int s;
281
282 samples /= from;
283
284 for (i = samples - 1; i >= 0; i--) {
285  s  = 0;
286
287  for (c = 0; c < from; c++)
288   s += ip[i*from + c];
289
290  s /= from;
291  op[i] = s;
292 }
293
294 return 0;
295}
296
297int roar_conv_chans_2to116  (void * out, void * in, int samples) {
298 int16_t * ip = (int16_t*) in, * op = (int16_t*) out;
299 int i, h;
300
301 samples -= 2;
302
303 for (h = (i = samples) / 2; i >= 0; i -= 2, h--)
304  op[h] = ((int)ip[i + 0] + (int)ip[i + 1]) / 2;
305
306 return 0;
307}
308
309int roar_conv_rate (void * out, void * in, int samples, int from, int to, int bits, int channels) {
310 if ( bits == 8  )
311  return roar_conv_rate_8(out, in, samples, from, to, channels);
312
313 if ( bits == 16 )
314  return roar_conv_rate_16(out, in, samples, from, to, channels);
315
316 return -1;
317}
318
319int roar_conv_rate_8  (void * out, void * in, int samples, int from, int to, int channels) {
320 return -1;
321}
322
323int roar_conv_rate_16 (void * out, void * in, int samples, int from, int to, int channels) {
324 if ( channels == 1 ) {
325  printf("roar_conv_rate_16(): samples=%i -> %i, rate=%i -> %i\n", samples*from/to, samples, from, to);
326  return roar_conv_poly4_16s((int16_t*) out, (int16_t*) in, samples, samples*from/to, (float)from/to);
327//  return roar_conv_poly4_16((int16_t*) out, (int16_t*) in, samples*to/from, samples);
328 }
329
330 return -1;
331}
332
333int roar_conv_signedness  (void * out, void * in, int samples, int from, int to, int bits) {
334
335 if ( from != to ) {
336  if ( from && !to ) {
337   switch (bits) {
338    case  8: roar_conv_codec_s2u8( out, in, samples); break;
339    case 16: roar_conv_codec_s2u16(out, in, samples); break;
340    case 32: roar_conv_codec_s2u32(out, in, samples); break;
341    default:
342     errno = ENOSYS;
343     return -1;
344   }
345  } else if ( !from && to ) {
346   switch (bits) {
347    case  8: roar_conv_codec_u2s8( out, in, samples); break;
348    case 16: roar_conv_codec_u2s16(out, in, samples); break;
349    case 32: roar_conv_codec_u2s32(out, in, samples); break;
350    default:
351     errno = ENOSYS;
352     return -1;
353   }
354  } else {
355   return -1;
356  }
357 } else {
358  if ( out == in )
359   return 0;
360
361  memcpy(out, in, samples * bits / 8);
362  return 0;
363 }
364
365 return 0;
366}
367
368int roar_conv_codec (void * out, void * in, int samples, int from, int to, int bits) {
369 int inbo = ROAR_CODEC_BYTE_ORDER(from), outbo = ROAR_CODEC_BYTE_ORDER(to);
370 int ins  = ROAR_CODEC_IS_SIGNED(from),  outs  = ROAR_CODEC_IS_SIGNED(to);
371 void * nin = in;
372
373
374 ROAR_DBG("roar_conv_codec(out=%p, in=%p, samples=%i, from=%i(%s), to=%i(%s), bits=%i) = ?",
375              out, in, samples, from, roar_codec2str(from), to, roar_codec2str(to), bits);
376
377 roar_conv_endian(out, in, samples, inbo, outbo, bits);
378 nin = out;
379
380 return roar_conv_signedness(out, in, samples, ins, outs, bits);
381}
382
383int roar_conv_codec_s2u8 (void * out, void * in, int samples) {
384 char * ip = in;
385 unsigned char * op = out;
386 int i;
387
388 for(i = 0; i < samples; i++)
389  op[i] = ip[i] + 128;
390
391 return 0;
392}
393
394int roar_conv_codec_s2u16 (void * out, void * in, int samples) {
395 int16_t  * ip = in;
396 uint16_t * op = out;
397 int i;
398
399 for(i = 0; i < samples; i++)
400  op[i] = ip[i] + 32768;
401
402 return 0;
403}
404
405int roar_conv_codec_s2u32 (void * out, void * in, int samples) {
406 int32_t  * ip = in;
407 uint32_t * op = out;
408 int i;
409
410 for(i = 0; i < samples; i++)
411  op[i] = ip[i] + 2147483648U;
412
413 return 0;
414}
415
416int roar_conv_codec_u2s8 (void * out, void * in, int samples) {
417 unsigned char * ip = in;
418          char * op = out;
419 int i;
420
421 for(i = 0; i < samples; i++)
422  op[i] = ip[i] - 128;
423
424 return 0;
425}
426
427int roar_conv_codec_u2s16 (void * out, void * in, int samples) {
428 uint16_t  * ip = in;
429 int16_t   * op = out;
430 int i;
431
432 for(i = 0; i < samples; i++)
433  op[i] = ip[i] - 32768;
434
435 return 0;
436}
437
438int roar_conv_codec_u2s32 (void * out, void * in, int samples) {
439 uint32_t  * ip = in;
440 int32_t   * op = out;
441 int i;
442
443 for(i = 0; i < samples; i++)
444  op[i] = ip[i] - 2147483648U;
445
446 return 0;
447}
448
449
450int roar_conv_endian      (void * out, void * in, int samples, int from, int to, int bits) {
451
452 if ( bits == 8 ) {
453  from = to = ROAR_CODEC_NATIVE_ENDIAN;
454
455 } else if ( bits == 16 ) {
456  if ( from  == ROAR_CODEC_PDP )
457   from = ROAR_CODEC_LE;
458  if ( to    == ROAR_CODEC_PDP )
459   to   = ROAR_CODEC_LE;
460 }
461
462 ROAR_DBG("roar_conv_endian(out=%p, in=%p, samples=%i, from=%i, to=%i, bits=%i) = ?", out, in, samples, from, to, bits);
463
464 if ( from == to ) {
465  if ( in != out ) {
466   memcpy(out, in, samples * bits / 8);
467  }
468  return 0;
469 } else {
470  if ( bits == 16 ) {
471   // in this case we can only have LE vs. BE, so, only need to swap:
472   ROAR_DBG("roar_conv_endian(*): Doing 16 bit byteswap");
473   return roar_conv_endian_16(out, in, samples);
474  } else if ( bits == 24 ) {
475   if ( (from == ROAR_CODEC_LE || from == ROAR_CODEC_BE) && (to == ROAR_CODEC_LE || to == ROAR_CODEC_BE) ) {
476    return roar_conv_endian_24(out, in, samples);
477   } else { // what the hell is PDP eddines in 24 bit mode?
478    return -1;
479   }
480  } else if ( bits == 32 ) {
481   if ( (from == ROAR_CODEC_LE || from == ROAR_CODEC_BE) && (to == ROAR_CODEC_LE || to == ROAR_CODEC_BE) ) {
482    return roar_conv_endian_32(out, in, samples);
483   } else { // need to handle 32 PDP eddines here?
484    return -1;
485   }
486  } else {
487   return -1;
488  }
489 }
490
491 return -1;
492}
493
494
495int roar_conv_endian_16   (void * out, void * in, int samples) {
496 char          * ip = in;
497 char          * op = out;
498 register char   c;
499 int             i;
500
501 samples *= 2;
502
503 if ( out != in ) {
504//  printf("out != in\n");
505  for(i = 0; i < samples; i += 2) {
506//   printf("op[%i] = ip[%i]\nop[%i] = ip[%i]\n", i, i+1, i+1, i);
507   op[i  ] = ip[i+1];
508   op[i+1] = ip[i  ];
509  }
510 } else {
511//  printf("out == in\n");
512  for(i = 0; i < samples; i += 2) {
513   c       = ip[i+1];
514   op[i+1] = ip[i  ];
515   op[i  ] = c;
516  }
517 }
518
519 return 0;
520}
521
522int roar_conv_endian_24   (void * out, void * in, int samples) {
523 char          * ip = in;
524 char          * op = out;
525 register char   c;
526 int             i;
527
528 samples *= 3;
529
530 if ( out != in ) {
531//  printf("out != in\n");
532  for(i = 0; i < samples; i += 3) {
533//   printf("op[%i] = ip[%i]\nop[%i] = ip[%i]\n", i, i+1, i+1, i);
534   op[i  ] = ip[i+2];
535   op[i+2] = ip[i  ];
536  }
537 } else {
538//  printf("out == in\n");
539  for(i = 0; i < samples; i += 3) {
540   c       = ip[i+2];
541   op[i+2] = ip[i  ];
542   op[i  ] = c;
543  }
544 }
545
546 return 0;
547}
548
549int roar_conv_endian_32   (void * out, void * in, int samples) {
550 int32_t       * ip = in;
551 int32_t       * op = out;
552 union {
553  int32_t val;
554  char    data[4];
555 }               c, h;
556 int             i;
557
558 // may the holly optimizer save our souls!
559
560 ROAR_DBG("roar_conv_endian_32(out=%p, in=%p, samples=%i) = ?", out, in, samples);
561
562 for (i = 0; i < samples; i++) {
563  c.val     = ip[i];
564  h.data[0] = c.data[3];
565  h.data[1] = c.data[2];
566  h.data[2] = c.data[1];
567  h.data[3] = c.data[0];
568  op[i]     = h.val;
569 }
570
571 return 0;
572}
573
574int roar_conv       (void * out, void * in, int samples, struct roar_audio_info * from, struct roar_audio_info * to) {
575 void * ip = in;
576 void * real_out;
577 size_t from_size, to_size;
578
579 // TODO: decide how to work around both in and out beeing to small to hold all
580 //       data between the steps.
581 //       for the moment: guess out >= in
582
583 from_size = from->channels * from->bits * samples / 8;
584 to_size   =   to->channels *   to->bits * samples / 8;
585
586 if ( to_size < from_size ) {
587  real_out = out;
588
589  if ( (out = malloc(from_size)) == NULL )
590   return -1;
591 }
592
593 ROAR_DBG("roar_conv(*): bo conv: %i->%i(native)", ROAR_CODEC_BYTE_ORDER(from->codec), ROAR_CODEC_NATIVE_ENDIAN);
594
595 if ( ROAR_CODEC_BYTE_ORDER(from->codec) != ROAR_CODEC_NATIVE_ENDIAN ) {
596  ROAR_DBG("roar_conv(*): doing bo input conv");
597  if ( roar_conv_endian(out, ip, samples, ROAR_CODEC_BYTE_ORDER(from->codec), ROAR_CODEC_NATIVE_ENDIAN, from->bits) == -1 ) {
598   if ( to_size < from_size )
599    free(out);
600   return -1;
601  } else {
602   ip = out;
603  }
604 }
605
606 if ( from->bits != to->bits ) {
607  if ( roar_conv_bits(out, ip, samples, from->bits, to->bits) == -1 ) {
608   if ( to_size < from_size )
609    free(out);
610   return -1;
611  } else {
612   ip = out;
613  }
614 }
615
616 if ( ROAR_CODEC_IS_SIGNED(from->codec) != ROAR_CODEC_IS_SIGNED(to->codec) ) {
617  if ( roar_conv_signedness(out, ip, samples, ROAR_CODEC_IS_SIGNED(from->codec), ROAR_CODEC_IS_SIGNED(to->codec), to->bits) == -1 ) {
618   if ( to_size < from_size )
619    free(out);
620   return -1;
621  } else {
622   ip = out;
623  }
624 }
625
626/*
627 if ( from->codec != to->codec ) {
628  if ( roar_conv_codec (out, ip, samples, from->codec, to->codec, to->bits) == -1 )
629   return -1;
630  else
631   ip = out;
632 }
633*/
634
635 if ( from->rate != to->rate ) {
636  if ( roar_conv_rate(out, ip, samples, from->rate, to->rate, to->bits, from->channels) == -1 ) {
637   if ( to_size < from_size )
638    free(out);
639   return -1;
640  } else {
641   ip = out;
642  }
643 }
644
645 if ( from->channels != to->channels ) {
646  if ( roar_conv_chans(out, ip, samples, from->channels, to->channels, to->bits) == -1 ) {
647   if ( to_size < from_size )
648    free(out);
649   return -1;
650  } else {
651   ip = out;
652  }
653 }
654
655 if ( ROAR_CODEC_BYTE_ORDER(to->codec) != ROAR_CODEC_NATIVE_ENDIAN ) {
656  if ( roar_conv_endian(out, ip, samples, ROAR_CODEC_NATIVE_ENDIAN, ROAR_CODEC_BYTE_ORDER(to->codec), to->bits) == -1 ) {
657   if ( to_size < from_size )
658    free(out);
659   return -1;
660  } else {
661   ip = out;
662  }
663 }
664
665 if ( to_size < from_size ) {
666  memcpy(real_out, out, to_size);
667  free(out);
668 }
669
670 return 0;
671}
672
673
674
675int roar_conv_poly4_16 (int16_t * out, int16_t * in, size_t olen, size_t ilen) {
676 return roar_conv_poly4_16s(out, in, olen, ilen, (float)ilen/olen);
677}
678
679int roar_conv_poly4_16s (int16_t * out, int16_t * in, size_t olen, size_t ilen, float step) {
680 float poly[4];
681 float data[4];
682 float t    = 0;
683 int16_t * ci = in;
684 int io, ii = 0;
685 int i;
686
687 printf("step=%f\n", step);
688
689 // we can not make a poly4 with less than 4 points ;)
690 if ( ilen < 4 )
691  return -1;
692
693 for (i = 0; i < 4; i++)
694  data[i] = ci[i];
695 roar_math_mkpoly_4x4(poly, data);
696/*
697 printf("new poly: data[4] = {%f, %f, %f, %f}, poly[4] = {%f, %f, %f, %f}\n",
698         data[0], data[1], data[2], data[3],
699         poly[0], poly[1], poly[2], poly[3]
700       );
701*/
702
703 //0 1 2 3
704
705 for (io = 0; io < olen; io++) {
706//  printf("t=%f\n", t);
707  out[io] = roar_math_cvpoly_4x4(poly, t);
708  t += step;
709  if ( t > 2 ) { // we need a new ploynome
710 //  printf("t > 2, need new data\n");
711   if ( (ii + 4) < ilen ) { // else: end of block.
712    t -= 1;
713//    printf("new data: ii=%i\n", ii);
714    ii++;
715    ci++;
716    for (i = 0; i < 4; i++)
717     data[i] = ci[i];
718    roar_math_mkpoly_4x4(poly, data);
719/*
720   printf("new poly: data[4] = {%f, %f, %f, %f}, poly[4] = {%f, %f, %f, %f}\n",
721           data[0], data[1], data[2], data[3],
722           poly[0], poly[1], poly[2], poly[3]
723          );
724*/
725   }
726  }
727 }
728
729 printf("io=%i\n", io);
730
731 return 0;
732}
733
734//ll
Note: See TracBrowser for help on using the repository browser.