Fix a bug with preferences
[vlc.git] / modules / audio_filter / format.c
1 /*****************************************************************************
2  * format.c : PCM format converter
3  *****************************************************************************
4  * Copyright (C) 2002 VideoLAN
5  * $Id$
6  *
7  * Authors: Christophe Massiot <massiot@via.ecp.fr>
8  *          Gildas Bazin <gbazin@videolan.org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include <stdlib.h>                                      /* malloc(), free() */
29 #include <string.h>
30
31 #include <vlc/vlc.h>
32 #include <vlc/decoder.h>
33 #include "vlc_filter.h"
34
35 #ifdef WORDS_BIGENDIAN
36 #   define AOUT_FMT_S16_IE VLC_FOURCC('s','1','6','l')
37 #   define AOUT_FMT_U16_IE VLC_FOURCC('u','1','6','l')
38 #else
39 #   define AOUT_FMT_S16_IE VLC_FOURCC('s','1','6','b')
40 #   define AOUT_FMT_U16_IE VLC_FOURCC('u','1','6','b')
41 #endif
42
43
44 /*****************************************************************************
45  * Local prototypes
46  *****************************************************************************/
47 static int  Open ( vlc_object_t * );
48
49 static block_t *Float32toS16( filter_t *, block_t * );
50 static block_t *Float32toU16( filter_t *, block_t * );
51 static block_t *Float32toS8 ( filter_t *, block_t * );
52 static block_t *Float32toU8 ( filter_t *, block_t * );
53
54 static block_t *S16toFloat32( filter_t *, block_t * );
55 static block_t *S16toS8     ( filter_t *p_filter, block_t *p_block );
56 static block_t *S16toU8     ( filter_t *p_filter, block_t *p_block );
57 static block_t *S16toU16    ( filter_t *p_filter, block_t *p_block );
58
59 static block_t *U16toFloat32( filter_t *, block_t * );
60 static block_t *U16toS8     ( filter_t *p_filter, block_t *p_block );
61 static block_t *U16toU8     ( filter_t *p_filter, block_t *p_block );
62 static block_t *U16toS16    ( filter_t *p_filter, block_t *p_block );
63
64 static block_t *Float32toS16Invert( filter_t *, block_t * );
65 static block_t *Float32toU16Invert( filter_t *, block_t * );
66
67 static block_t *S16InverttoFloat32( filter_t *, block_t * );
68 static block_t *S16InverttoS8( filter_t *p_filter, block_t *p_block );
69 static block_t *S16InverttoU8( filter_t *p_filter, block_t *p_block );
70 static block_t *S16InverttoU16( filter_t *p_filter, block_t *p_block );
71
72 static block_t *U16InverttoFloat32( filter_t *, block_t * );
73 static block_t *U16InverttoS8( filter_t *p_filter, block_t *p_block );
74 static block_t *U16InverttoU8( filter_t *p_filter, block_t *p_block );
75 static block_t *U16InverttoS16( filter_t *p_filter, block_t *p_block );
76
77 static block_t *S8toFloat32( filter_t *, block_t * );
78 static block_t *S8toS16( filter_t *, block_t * );
79 static block_t *S8toU16( filter_t *, block_t * );
80 static block_t *S8toU8( filter_t *, block_t * );
81 static block_t *S8toS16Invert( filter_t *, block_t * );
82 static block_t *S8toU16Invert( filter_t *, block_t * );
83
84 static block_t *U8toFloat32( filter_t *, block_t * );
85 static block_t *U8toFloat32( filter_t *, block_t * );
86 static block_t *U8toS16( filter_t *, block_t * );
87 static block_t *U8toU16( filter_t *, block_t * );
88 static block_t *U8toS8( filter_t *, block_t * );
89 static block_t *U8toS16Invert( filter_t *, block_t * );
90 static block_t *U8toU16Invert( filter_t *, block_t * );
91
92
93 static block_t *U8toS8( filter_t *, block_t * );
94 static block_t *S8toU8( filter_t *, block_t * );
95
96
97 static block_t *Swap16   ( filter_t *, block_t * );
98
99 static struct
100 {
101     vlc_fourcc_t i_src;
102     vlc_fourcc_t i_dst;
103     block_t *(*pf_convert)( filter_t *, block_t *);
104 } ConvertTable[] =
105 {
106     /* From fl32 */
107     { VLC_FOURCC('f','l','3','2'), AOUT_FMT_S16_NE, Float32toS16 },
108     { VLC_FOURCC('f','l','3','2'), AOUT_FMT_U16_NE, Float32toU16 },
109     { VLC_FOURCC('f','l','3','2'), AOUT_FMT_S16_IE, Float32toS16Invert },
110     { VLC_FOURCC('f','l','3','2'), AOUT_FMT_U16_IE, Float32toU16Invert },
111     { VLC_FOURCC('f','l','3','2'), VLC_FOURCC('s','8',' ',' '), Float32toS8 },
112     { VLC_FOURCC('f','l','3','2'), VLC_FOURCC('u','8',' ',' '), Float32toU8 },
113
114     /* From s16 */
115     { AOUT_FMT_S16_NE, VLC_FOURCC('f','l','3','2'), S16toFloat32 },
116     { AOUT_FMT_S16_NE, AOUT_FMT_S16_IE,            Swap16 },
117     { AOUT_FMT_S16_NE, AOUT_FMT_U16_IE,            S16toU16 },
118     { AOUT_FMT_S16_NE, VLC_FOURCC('s','8',' ',' '), S16toS8 },
119     { AOUT_FMT_S16_NE, VLC_FOURCC('u','8',' ',' '), S16toU8 },
120
121     /* From u16 */
122     { AOUT_FMT_U16_NE, VLC_FOURCC('f','l','3','2'), U16toFloat32 },
123     { AOUT_FMT_U16_NE, AOUT_FMT_U16_IE,            Swap16 },
124     { AOUT_FMT_U16_NE, AOUT_FMT_S16_IE,            U16toS16 },
125     { AOUT_FMT_U16_NE, VLC_FOURCC('s','8',' ',' '), U16toS8 },
126     { AOUT_FMT_U16_NE, VLC_FOURCC('u','8',' ',' '), U16toU8 },
127
128     /* From s8 */
129     { VLC_FOURCC('s','8',' ',' '), VLC_FOURCC('f','l','3','2'), S8toFloat32 },
130     { VLC_FOURCC('s','8',' ',' '), AOUT_FMT_S16_NE,             S8toS16 },
131     { VLC_FOURCC('s','8',' ',' '), AOUT_FMT_S16_IE,             S8toS16Invert },
132     { VLC_FOURCC('s','8',' ',' '), AOUT_FMT_U16_NE,             S8toU16 },
133     { VLC_FOURCC('s','8',' ',' '), AOUT_FMT_U16_IE,             S8toU16Invert },
134     { VLC_FOURCC('s','8',' ',' '), VLC_FOURCC('u','8',' ',' '), S8toU8 },
135     
136     /* From u8 */
137     { VLC_FOURCC('u','8',' ',' '), VLC_FOURCC('f','l','3','2'), U8toFloat32 },
138     { VLC_FOURCC('u','8',' ',' '), AOUT_FMT_S16_NE,             U8toS16 },
139     { VLC_FOURCC('u','8',' ',' '), AOUT_FMT_S16_IE,             U8toS16Invert },
140     { VLC_FOURCC('u','8',' ',' '), AOUT_FMT_U16_NE,             U8toU16 },
141     { VLC_FOURCC('u','8',' ',' '), AOUT_FMT_U16_IE,             U8toU16Invert },
142     { VLC_FOURCC('u','8',' ',' '), VLC_FOURCC('s','8',' ',' '), U8toS8 },
143
144     /* From s16 invert */
145     { AOUT_FMT_S16_IE, VLC_FOURCC('f','l','3','2'), S16InverttoFloat32 },
146     { AOUT_FMT_S16_IE, AOUT_FMT_S16_NE,            Swap16 },
147     { AOUT_FMT_S16_IE, AOUT_FMT_U16_NE,            S16InverttoU16 },
148     { AOUT_FMT_S16_IE, VLC_FOURCC('s','8',' ',' '), S16InverttoS8 },
149     { AOUT_FMT_S16_IE, VLC_FOURCC('u','8',' ',' '), S16InverttoU8 },
150
151     /* From u16 invert */
152     { AOUT_FMT_U16_IE, VLC_FOURCC('f','l','3','2'), U16InverttoFloat32 },
153     { AOUT_FMT_U16_IE, AOUT_FMT_U16_NE,            Swap16 },
154     { AOUT_FMT_U16_IE, AOUT_FMT_S16_NE,            U16InverttoS16 },
155     { AOUT_FMT_U16_IE, VLC_FOURCC('s','8',' ',' '), U16InverttoS8 },
156     { AOUT_FMT_U16_IE, VLC_FOURCC('u','8',' ',' '), U16InverttoU8 },
157
158     { 0, 0, NULL },
159 };
160
161
162 /*****************************************************************************
163  * Module descriptor
164  *****************************************************************************/
165 vlc_module_begin();
166     set_description( _("audio filter for PCM format conversion") );
167     set_capability( "audio filter2", 1 );
168     set_callbacks( Open, NULL );
169 vlc_module_end();
170
171 /*****************************************************************************
172  * Open:
173  *****************************************************************************/
174 static int Open( vlc_object_t *p_this )
175 {
176     filter_t *p_filter = (filter_t *)p_this;
177     int i;
178
179     for( i = 0; ConvertTable[i].pf_convert != NULL; i++ )
180     {
181         if( ConvertTable[i].i_src == p_filter->fmt_in.i_codec &&
182             ConvertTable[i].i_dst == p_filter->fmt_out.i_codec )
183             break;
184     }
185     if( ConvertTable[i].pf_convert == NULL )
186         return VLC_EGENERIC;
187
188     
189     p_filter->pf_audio_filter = ConvertTable[i].pf_convert;
190
191     msg_Dbg( p_this, "%4.4s->%4.4s, bits per sample: %i",
192              (char *)&p_filter->fmt_in.i_codec,
193              (char *)&p_filter->fmt_out.i_codec,
194              p_filter->fmt_in.audio.i_bitspersample );
195
196     return VLC_SUCCESS;
197 }
198
199 /*****************************************************************************
200  * Convert a buffer
201  *****************************************************************************/
202 static block_t *Float32toS16( filter_t *p_filter, block_t *p_block )
203 {
204     int i;
205     float *p_in = (float *)p_block->p_buffer;
206     int16_t *p_out = (int16_t *)p_in;
207
208     for( i = p_block->i_buffer*8/p_filter->fmt_in.audio.i_bitspersample; i--; )
209     {
210 #if 0
211         /* Slow version. */
212         if ( *p_in >= 1.0 ) *p_out = 32767;
213         else if ( *p_in < -1.0 ) *p_out = -32768;
214         else *p_out = *p_in * 32768.0;
215 #else
216         /* This is walken's trick based on IEEE float format. */
217         union { float f; int32_t i; } u;
218         u.f = *p_in + 384.0;
219         if ( u.i > 0x43c07fff ) *p_out = 32767;
220         else if ( u.i < 0x43bf8000 ) *p_out = -32768;
221         else *p_out = u.i - 0x43c00000;
222 #endif
223         p_in++; p_out++;
224     }
225
226     p_block->i_buffer /= 2;
227     return p_block;
228 }
229
230 static block_t *Float32toU16( filter_t *p_filter, block_t *p_block )
231 {
232     int i;
233     float *p_in = (float *)p_block->p_buffer;
234     uint16_t *p_out = (uint16_t *)p_in;
235
236     for( i = p_block->i_buffer*8/p_filter->fmt_in.audio.i_bitspersample; i--; )
237     {
238         if ( *p_in >= 1.0 ) *p_out = 65535;
239         else if ( *p_in < -1.0 ) *p_out = 0;
240         else *p_out = (uint16_t)(32768 + *p_in * 32768);
241         p_in++; p_out++;
242     }
243
244     p_block->i_buffer /= 2;
245     return p_block;
246 }
247
248 static block_t *S16toFloat32( filter_t *p_filter, block_t *p_block )
249 {
250     block_t *p_block_out;
251     int16_t *p_in;
252     float *p_out;
253     int i;
254
255     p_block_out =
256         p_filter->pf_audio_buffer_new( p_filter, p_block->i_buffer*2 );
257     if( !p_block_out )
258     {
259         msg_Warn( p_filter, "can't get output buffer" );
260         return NULL;
261     }
262
263     p_in = (int16_t *)p_block->p_buffer;
264     p_out = (float *)p_block_out->p_buffer;
265
266     for( i = p_block->i_buffer*8/p_filter->fmt_in.audio.i_bitspersample; i--; )
267     {
268 #if 0
269         /* Slow version */
270         *p_out = (float)*p_in / 32768.0;
271 #else
272         /* This is walken's trick based on IEEE float format. On my PIII
273          * this takes 16 seconds to perform one billion conversions, instead
274          * of 19 seconds for the above division. */
275         union { float f; int32_t i; } u;
276         u.i = *p_in + 0x43c00000;
277         *p_out = u.f - 384.0;
278 #endif
279
280         p_in++; p_out++;
281     }
282
283     p_block_out->i_samples = p_block->i_samples;
284     p_block_out->i_dts = p_block->i_dts;
285     p_block_out->i_pts = p_block->i_pts;
286     p_block_out->i_length = p_block->i_length;
287     p_block_out->i_rate = p_block->i_rate;
288
289     p_block->pf_release( p_block );
290     return p_block_out;
291 }
292
293 static block_t *U16toFloat32( filter_t *p_filter, block_t *p_block )
294 {
295     block_t *p_block_out;
296     int16_t *p_in;
297     float *p_out;
298     int i;
299
300     p_block_out =
301         p_filter->pf_audio_buffer_new( p_filter, p_block->i_buffer*2 );
302     if( !p_block_out )
303     {
304         msg_Warn( p_filter, "can't get output buffer" );
305         return NULL;
306     }
307
308     p_in = (int16_t *)p_block->p_buffer;
309     p_out = (float *)p_block_out->p_buffer;
310
311     for( i = p_block->i_buffer*8/p_filter->fmt_in.audio.i_bitspersample; i--; )
312     {
313         *p_out++ = (float)(*p_in++ - 32768) / 32768.0;
314     }
315
316     p_block_out->i_samples = p_block->i_samples;
317     p_block_out->i_dts = p_block->i_dts;
318     p_block_out->i_pts = p_block->i_pts;
319     p_block_out->i_length = p_block->i_length;
320     p_block_out->i_rate = p_block->i_rate;
321
322     p_block->pf_release( p_block );
323     return p_block_out;
324 }
325
326 static block_t *S16toS8( filter_t *p_filter, block_t *p_block )
327 {
328     int i;
329     int16_t *p_in = (int16_t *)p_block->p_buffer;
330     int8_t *p_out = (int8_t *)p_in;
331
332     for( i = p_block->i_buffer*8/p_filter->fmt_in.audio.i_bitspersample; i--; )
333         *p_out++ = (*p_in++) >> 8;
334
335     p_block->i_buffer /= 2;
336     return p_block;
337 }
338 static block_t *S16toU8( filter_t *p_filter, block_t *p_block )
339 {
340     int i;
341     int16_t *p_in = (int16_t *)p_block->p_buffer;
342     uint8_t *p_out = (uint8_t *)p_in;
343
344     for( i = p_block->i_buffer*8/p_filter->fmt_in.audio.i_bitspersample; i--; )
345         *p_out++ = ((*p_in++) + 32768) >> 8;
346
347     p_block->i_buffer /= 2;
348     return p_block;
349 }
350 static block_t *S16toU16( filter_t *p_filter, block_t *p_block )
351 {
352     int i;
353     int16_t *p_in = (int16_t *)p_block->p_buffer;
354     uint16_t *p_out = (uint16_t *)p_in;
355
356     for( i = p_block->i_buffer*8/p_filter->fmt_in.audio.i_bitspersample; i--; )
357         *p_out++ = (*p_in++) + 32768;
358
359     return p_block;
360 }
361
362 static block_t *U16toS8( filter_t *p_filter, block_t *p_block )
363 {
364     int i;
365     uint16_t *p_in = (uint16_t *)p_block->p_buffer;
366     int8_t *p_out = (int8_t *)p_in;
367
368     for( i = p_block->i_buffer*8/p_filter->fmt_in.audio.i_bitspersample; i--; )
369         *p_out++ = ((int)(*p_in++) - 32768) >> 8;
370
371     p_block->i_buffer /= 2;
372     return p_block;
373 }
374 static block_t *U16toU8( filter_t *p_filter, block_t *p_block )
375 {
376     int i;
377     uint16_t *p_in = (uint16_t *)p_block->p_buffer;
378     uint8_t *p_out = (uint8_t *)p_in;
379
380     for( i = p_block->i_buffer*8/p_filter->fmt_in.audio.i_bitspersample; i--; )
381         *p_out++ = (*p_in++) >> 8;
382
383     p_block->i_buffer /= 2;
384     return p_block;
385 }
386 static block_t *U16toS16( filter_t *p_filter, block_t *p_block )
387 {
388     int i;
389     int16_t *p_in = (int16_t *)p_block->p_buffer;
390     uint16_t *p_out = (uint16_t *)p_in;
391
392     for( i = p_block->i_buffer*8/p_filter->fmt_in.audio.i_bitspersample; i--; )
393         *p_out++ = (int)(*p_in++) - 32768;
394
395     return p_block;
396 }
397
398 static block_t *S8toU8( filter_t *p_filter, block_t *p_block )
399 {
400     int i;
401     int8_t *p_in = (int8_t *)p_block->p_buffer;
402     uint8_t *p_out = (uint8_t *)p_in;
403
404     for( i = p_block->i_buffer*8/p_filter->fmt_in.audio.i_bitspersample; i--; )
405         *p_out++ = ((*p_in++) + 128);
406
407     return p_block;
408 }
409 static block_t *U8toS8( filter_t *p_filter, block_t *p_block )
410 {
411     int i;
412     uint8_t *p_in = (uint8_t *)p_block->p_buffer;
413     int8_t *p_out = (int8_t *)p_in;
414
415     for( i = p_block->i_buffer*8/p_filter->fmt_in.audio.i_bitspersample; i--; )
416         *p_out++ = ((*p_in++) - 128);
417
418     return p_block;
419 }
420
421 /* */
422 static block_t *S8toU16( filter_t *p_filter, block_t *p_block )
423 {
424     block_t *p_block_out;
425     int8_t *p_in;
426     uint16_t *p_out;
427     int i;
428
429     p_block_out =
430         p_filter->pf_audio_buffer_new( p_filter, p_block->i_buffer*2 );
431     if( !p_block_out )
432     {
433         msg_Warn( p_filter, "can't get output buffer" );
434         return NULL;
435     }
436
437     p_in = (int8_t *)p_block->p_buffer;
438     p_out = (uint16_t *)p_block_out->p_buffer;
439
440     for( i = p_block->i_buffer*8/p_filter->fmt_in.audio.i_bitspersample; i--; )
441         *p_out++ = ((*p_in++) + 128) << 8;
442
443     p_block_out->i_samples = p_block->i_samples;
444     p_block_out->i_dts = p_block->i_dts;
445     p_block_out->i_pts = p_block->i_pts;
446     p_block_out->i_length = p_block->i_length;
447     p_block_out->i_rate = p_block->i_rate;
448
449     p_block->pf_release( p_block );
450     return p_block_out;
451 }
452
453 static block_t *U8toS16( filter_t *p_filter, block_t *p_block )
454 {
455     block_t *p_block_out;
456     uint8_t *p_in;
457     int16_t *p_out;
458     int i;
459
460     p_block_out =
461         p_filter->pf_audio_buffer_new( p_filter, p_block->i_buffer*2 );
462     if( !p_block_out )
463     {
464         msg_Warn( p_filter, "can't get output buffer" );
465         return NULL;
466     }
467
468     p_in = (uint8_t *)p_block->p_buffer;
469     p_out = (int16_t *)p_block_out->p_buffer;
470
471     for( i = p_block->i_buffer*8/p_filter->fmt_in.audio.i_bitspersample; i--; )
472         *p_out++ = ((*p_in++) - 128) << 8;
473
474     p_block_out->i_samples = p_block->i_samples;
475     p_block_out->i_dts = p_block->i_dts;
476     p_block_out->i_pts = p_block->i_pts;
477     p_block_out->i_length = p_block->i_length;
478     p_block_out->i_rate = p_block->i_rate;
479
480     p_block->pf_release( p_block );
481     return p_block_out;
482 }
483
484
485 static block_t *S8toS16( filter_t *p_filter, block_t *p_block )
486 {
487     block_t *p_block_out;
488     int8_t *p_in;
489     int16_t *p_out;
490     int i;
491
492     p_block_out =
493         p_filter->pf_audio_buffer_new( p_filter, p_block->i_buffer*2 );
494     if( !p_block_out )
495     {
496         msg_Warn( p_filter, "can't get output buffer" );
497         return NULL;
498     }
499
500     p_in = (int8_t *)p_block->p_buffer;
501     p_out = (int16_t *)p_block_out->p_buffer;
502
503     for( i = p_block->i_buffer*8/p_filter->fmt_in.audio.i_bitspersample; i--; )
504         *p_out++ = (*p_in++) << 8;
505
506     p_block_out->i_samples = p_block->i_samples;
507     p_block_out->i_dts = p_block->i_dts;
508     p_block_out->i_pts = p_block->i_pts;
509     p_block_out->i_length = p_block->i_length;
510     p_block_out->i_rate = p_block->i_rate;
511
512     p_block->pf_release( p_block );
513     return p_block_out;
514 }
515
516 static block_t *U8toU16( filter_t *p_filter, block_t *p_block )
517 {
518     block_t *p_block_out;
519     uint8_t *p_in;
520     uint16_t *p_out;
521     int i;
522
523     p_block_out =
524         p_filter->pf_audio_buffer_new( p_filter, p_block->i_buffer*2 );
525     if( !p_block_out )
526     {
527         msg_Warn( p_filter, "can't get output buffer" );
528         return NULL;
529     }
530
531     p_in = (uint8_t *)p_block->p_buffer;
532     p_out = (uint16_t *)p_block_out->p_buffer;
533
534     for( i = p_block->i_buffer*8/p_filter->fmt_in.audio.i_bitspersample; i--; )
535         *p_out++ = (*p_in++) << 8;
536
537     p_block_out->i_samples = p_block->i_samples;
538     p_block_out->i_dts = p_block->i_dts;
539     p_block_out->i_pts = p_block->i_pts;
540     p_block_out->i_length = p_block->i_length;
541     p_block_out->i_rate = p_block->i_rate;
542
543     p_block->pf_release( p_block );
544     return p_block_out;
545 }
546
547 /*****************************************************************************
548  * Swap a buffer of word
549  *****************************************************************************/
550 static block_t *Swap16( filter_t *p_filter, block_t *p_block )
551 {
552     int i;
553     uint8_t *p_in = (uint8_t *)p_block->p_buffer;
554     uint8_t tmp;
555
556     for( i = 0; i < p_block->i_buffer / 2; i++ )
557     {
558         tmp = p_in[0];
559         p_in[0] = p_in[1];
560         p_in[1] = tmp;
561         p_in += 2;
562     }
563
564     return p_block;
565 }
566
567 #define CONVERT_NN( func, f_in, f_out, b_pre_invert, b_post_invert ) \
568 static block_t *func( filter_t *p_filter, block_t *p_block ) \
569 {                                                   \
570     if( b_pre_invert )                              \
571         Swap16( p_filter, p_block );                \
572                                                     \
573     p_block = f_in##to##f_out( p_filter, p_block ); \
574                                                     \
575     if( b_post_invert )                             \
576         Swap16( p_filter, p_block );                \
577                                                     \
578     return p_block;                                 \
579 }
580
581 CONVERT_NN( Float32toS16Invert, Float32, S16, 0, 1 )
582 CONVERT_NN( Float32toU16Invert, Float32, U16, 0, 1 )
583
584 CONVERT_NN( S16InverttoFloat32, S16, Float32, 1, 0 )
585 CONVERT_NN( S16InverttoS8,      S16, S8,      1, 0 )
586 CONVERT_NN( S16InverttoU8,      S16, U8,      1, 0 )
587 CONVERT_NN( S16InverttoU16,     S16, U16,     1, 0 )
588
589 CONVERT_NN( U16InverttoFloat32, U16, Float32, 1, 0 )
590 CONVERT_NN( U16InverttoS8,      U16, S8,      1, 0 )
591 CONVERT_NN( U16InverttoU8,      U16, U8,      1, 0 )
592 CONVERT_NN( U16InverttoS16,     U16, S16,     1, 0 )
593
594 #undef CONVERT_NN
595
596 #define CONVERT_INDIRECT( func, f_in, f_mid, f_out )                    \
597 static block_t *func( filter_t *p_filter, block_t *p_block )            \
598 {                                                                       \
599     return f_mid##to##f_out( p_filter,                                  \
600                              f_in##to##f_mid( p_filter, p_block ) );    \
601 }
602
603 CONVERT_INDIRECT( Float32toS8,   Float32, S16, U8 )
604 CONVERT_INDIRECT( Float32toU8,   Float32, U16, U8 )
605 CONVERT_INDIRECT( S8toFloat32,   S8,      S16, Float32 )
606 CONVERT_INDIRECT( U8toFloat32,   U8,      U16, Float32 )
607
608 #define S16toS16Invert Swap16
609 #define U16toU16Invert Swap16
610
611 CONVERT_INDIRECT( U8toS16Invert, U8,      S16, S16Invert )
612 CONVERT_INDIRECT( S8toU16Invert, S8,      U16, U16Invert )
613
614 CONVERT_INDIRECT( U8toU16Invert, U8,      U16, U16Invert )
615 CONVERT_INDIRECT( S8toS16Invert, S8,      S16, S16Invert )
616
617 #undef CONVERT_INDIRECT
618
619
620