]> git.sesse.net Git - vlc/blob - modules/audio_filter/converter/float.c
e2419a6a9d8a6580076810181762b3b64a8cea53
[vlc] / modules / audio_filter / converter / float.c
1 /*****************************************************************************
2  * float.c: Floating point audio format conversions
3  *****************************************************************************
4  * Copyright (C) 2002, 2006 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Jean-Paul Saman <jpsaman _at_ videolan _dot_ org>
8  *          Christophe Massiot <massiot@via.ecp.fr>
9  *          Samuel Hocevar <sam@zoy.org>
10  *          Xavier Maillard <zedek@fxgsproject.org>
11  *          Henri Fallon <henri@videolan.org>
12  *          Gildas Bazin <gbazin@netcourrier.com>
13  *
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2 of the License, or
17  * (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
27  *****************************************************************************/
28
29 /*****************************************************************************
30  * Preamble
31  *****************************************************************************/
32 #ifdef HAVE_CONFIG_H
33 # include "config.h"
34 #endif
35
36 #include <vlc_common.h>
37 #include <vlc_plugin.h>
38
39 #ifdef HAVE_UNISTD_H
40 #   include <unistd.h>
41 #endif
42
43 #include <vlc_aout.h>
44
45 /*****************************************************************************
46  * Local prototypes
47  *****************************************************************************/
48 static int  Create_F32ToFL32 ( vlc_object_t * );
49 static void Do_F32ToFL32( aout_instance_t *, aout_filter_t *, aout_buffer_t *,
50                            aout_buffer_t * );
51 static void Do_FL32ToF32 ( aout_instance_t *, aout_filter_t *, aout_buffer_t *,
52                            aout_buffer_t * );
53
54 static int  Create_FL32ToS16 ( vlc_object_t * );
55 static void Do_FL32ToS16( aout_instance_t *, aout_filter_t *, aout_buffer_t *,
56                            aout_buffer_t * );
57
58 static int  Create_FL32ToS8 ( vlc_object_t * );
59 static void Do_FL32ToS8( aout_instance_t *, aout_filter_t *, aout_buffer_t *,
60                            aout_buffer_t * );
61
62 static int  Create_FL32ToU16 ( vlc_object_t * );
63 static void Do_FL32ToU16( aout_instance_t *, aout_filter_t *, aout_buffer_t *,
64                            aout_buffer_t * );
65
66 static int  Create_FL32ToU8 ( vlc_object_t * );
67 static void Do_FL32ToU8( aout_instance_t *, aout_filter_t *, aout_buffer_t *,
68                            aout_buffer_t * );
69
70 static int  Create_S16ToFL32( vlc_object_t * );
71 static void Do_S16ToFL32( aout_instance_t *, aout_filter_t *, aout_buffer_t *,
72                            aout_buffer_t * );
73 static void Do_S24ToFL32( aout_instance_t *, aout_filter_t *, aout_buffer_t *,
74                            aout_buffer_t * );
75 static void Do_S32ToFL32( aout_instance_t *, aout_filter_t *, aout_buffer_t *,
76                            aout_buffer_t * );
77
78 static int  Create_S16ToFL32_SW( vlc_object_t * );
79 static void Do_S16ToFL32_SW( aout_instance_t *, aout_filter_t *, aout_buffer_t *,
80                            aout_buffer_t * );
81 static void Do_S24ToFL32_SW( aout_instance_t *, aout_filter_t *, aout_buffer_t *,
82                            aout_buffer_t * );
83 static void Do_S32ToFL32_SW( aout_instance_t *, aout_filter_t *, aout_buffer_t *,
84                            aout_buffer_t * );
85
86 static int  Create_S8ToFL32( vlc_object_t * );
87 static void Do_S8ToFL32( aout_instance_t *, aout_filter_t *, aout_buffer_t *,
88                            aout_buffer_t * );
89
90 static int  Create_U8ToFL32( vlc_object_t * );
91 static void Do_U8ToFL32( aout_instance_t *, aout_filter_t *, aout_buffer_t *,
92                            aout_buffer_t * );
93
94 /*****************************************************************************
95  * Module descriptor
96  *****************************************************************************/
97 vlc_module_begin ()
98     set_description( N_("Floating-point audio format conversions") )
99     add_submodule ()
100         set_capability( "audio filter", 10 )
101         set_callbacks( Create_F32ToFL32, NULL )
102     add_submodule ()
103         set_capability( "audio filter", 1 )
104         set_callbacks( Create_FL32ToS16, NULL )
105     add_submodule ()
106         set_capability( "audio filter", 1 )
107         set_callbacks( Create_FL32ToS8, NULL )
108     add_submodule ()
109         set_capability( "audio filter", 1 )
110         set_callbacks( Create_FL32ToU16, NULL )
111     add_submodule ()
112         set_capability( "audio filter", 1 )
113         set_callbacks( Create_FL32ToU8, NULL )
114     add_submodule ()
115         set_capability( "audio filter", 1 )
116         set_callbacks( Create_S16ToFL32, NULL )
117     add_submodule ()
118         set_capability( "audio filter", 1 )
119         set_callbacks( Create_S16ToFL32_SW, NULL ) /* Endianness conversion*/
120     add_submodule ()
121         set_capability( "audio filter", 1 )
122         set_callbacks( Create_S8ToFL32, NULL )
123     add_submodule ()
124         set_capability( "audio filter", 1 )
125         set_callbacks( Create_U8ToFL32, NULL )
126 vlc_module_end ()
127
128 /*****************************************************************************
129  * Fixed 32 to Float 32 and backwards
130  *****************************************************************************/
131 static int Create_F32ToFL32( vlc_object_t *p_this )
132 {
133     aout_filter_t * p_filter = (aout_filter_t *)p_this;
134
135     if( ( p_filter->input.i_format != VLC_FOURCC('f','i','3','2')
136            || p_filter->output.i_format != VLC_FOURCC('f','l','3','2') )
137       && ( p_filter->input.i_format != VLC_FOURCC('f','l','3','2')
138             || p_filter->output.i_format != VLC_FOURCC('f','i','3','2') ) )
139     {
140         return -1;
141     }
142
143     if ( !AOUT_FMTS_SIMILAR( &p_filter->input, &p_filter->output ) )
144     {
145         return -1;
146     }
147
148     if( p_filter->input.i_format == VLC_FOURCC('f','i','3','2') )
149     {
150         p_filter->pf_do_work = Do_F32ToFL32;
151     }
152     else
153     {
154         p_filter->pf_do_work = Do_FL32ToF32;
155     }
156
157     p_filter->b_in_place = 1;
158
159     return 0;
160 }
161
162 static void Do_F32ToFL32( aout_instance_t * p_aout, aout_filter_t * p_filter,
163                           aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
164 {
165     VLC_UNUSED(p_aout);
166     int i;
167     vlc_fixed_t * p_in = (vlc_fixed_t *)p_in_buf->p_buffer;
168     float * p_out = (float *)p_out_buf->p_buffer;
169
170     for ( i = p_in_buf->i_nb_samples
171                * aout_FormatNbChannels( &p_filter->input ) ; i-- ; )
172     {
173         *p_out++ = (float)*p_in++ / (float)FIXED32_ONE;
174     }
175
176     p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
177     p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes;
178 }
179
180 static void Do_FL32ToF32( aout_instance_t * p_aout, aout_filter_t * p_filter,
181                           aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
182 {
183     VLC_UNUSED(p_aout);
184     int i;
185     float * p_in = (float *)p_in_buf->p_buffer;
186     vlc_fixed_t * p_out = (vlc_fixed_t *)p_out_buf->p_buffer;
187
188     for ( i = p_in_buf->i_nb_samples
189                * aout_FormatNbChannels( &p_filter->input ) ; i-- ; )
190     {
191         *p_out++ = (vlc_fixed_t)( *p_in++ * (float)FIXED32_ONE );
192     }
193
194     p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
195     p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes;
196 }
197
198 /*****************************************************************************
199  * FL32 To S16
200  *****************************************************************************/
201 static int Create_FL32ToS16( vlc_object_t *p_this )
202 {
203     aout_filter_t * p_filter = (aout_filter_t *)p_this;
204
205     if ( p_filter->input.i_format != VLC_FOURCC('f','l','3','2')
206           || p_filter->output.i_format != AOUT_FMT_S16_NE )
207     {
208         return -1;
209     }
210
211     if ( !AOUT_FMTS_SIMILAR( &p_filter->input, &p_filter->output ) )
212     {
213         return -1;
214     }
215
216     p_filter->pf_do_work = Do_FL32ToS16;
217     p_filter->b_in_place = 1;
218
219     return 0;
220 }
221
222 static void Do_FL32ToS16( aout_instance_t * p_aout, aout_filter_t * p_filter,
223                           aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
224 {
225     VLC_UNUSED(p_aout);
226     int i;
227     float * p_in = (float *)p_in_buf->p_buffer;
228     int16_t * p_out = (int16_t *)p_out_buf->p_buffer;
229
230     for ( i = p_in_buf->i_nb_samples
231                * aout_FormatNbChannels( &p_filter->input ); i-- ; )
232     {
233 #if 0
234         /* Slow version. */
235         if ( *p_in >= 1.0 ) *p_out = 32767;
236         else if ( *p_in < -1.0 ) *p_out = -32768;
237         else *p_out = *p_in * 32768.0;
238 #else
239         /* This is walken's trick based on IEEE float format. */
240         union { float f; int32_t i; } u;
241         u.f = *p_in + 384.0;
242         if ( u.i > 0x43c07fff ) *p_out = 32767;
243         else if ( u.i < 0x43bf8000 ) *p_out = -32768;
244         else *p_out = u.i - 0x43c00000;
245 #endif
246         p_in++; p_out++;
247     }
248
249     p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
250     p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes / 2;
251 }
252
253 /*****************************************************************************
254  * FL32 To S8
255  *****************************************************************************/
256 static int Create_FL32ToS8( vlc_object_t *p_this )
257 {
258     aout_filter_t * p_filter = (aout_filter_t *)p_this;
259
260     if ( p_filter->input.i_format != VLC_FOURCC('f','l','3','2')
261           || p_filter->output.i_format != VLC_FOURCC('s','8',' ',' ') )
262     {
263         return -1;
264     }
265
266     if ( !AOUT_FMTS_SIMILAR( &p_filter->input, &p_filter->output ) )
267     {
268         return -1;
269     }
270
271     p_filter->pf_do_work = Do_FL32ToS8;
272     p_filter->b_in_place = 1;
273
274     return 0;
275 }
276
277 static void Do_FL32ToS8( aout_instance_t * p_aout, aout_filter_t * p_filter,
278                          aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
279 {
280     VLC_UNUSED(p_aout);
281     int i;
282     float * p_in = (float *)p_in_buf->p_buffer;
283     int8_t * p_out = (int8_t *)p_out_buf->p_buffer;
284
285     for ( i = p_in_buf->i_nb_samples
286                * aout_FormatNbChannels( &p_filter->input ); i-- ; )
287     {
288         if ( *p_in >= 1.0 ) *p_out = 127;
289         else if ( *p_in < -1.0 ) *p_out = -128;
290         else *p_out = (int8_t)(*p_in * 128);
291         p_in++; p_out++;
292     }
293
294     p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
295     p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes / 4;
296 }
297
298 /*****************************************************************************
299  * FL32 To U16
300  *****************************************************************************/
301 static int Create_FL32ToU16( vlc_object_t *p_this )
302 {
303     aout_filter_t * p_filter = (aout_filter_t *)p_this;
304
305     if ( p_filter->input.i_format != VLC_FOURCC('f','l','3','2')
306           || p_filter->output.i_format != AOUT_FMT_U16_NE )
307     {
308         return -1;
309     }
310
311     if ( !AOUT_FMTS_SIMILAR( &p_filter->input, &p_filter->output ) )
312     {
313         return -1;
314     }
315
316     p_filter->pf_do_work = Do_FL32ToU16;
317     p_filter->b_in_place = 1;
318
319     return 0;
320 }
321
322 static void Do_FL32ToU16( aout_instance_t * p_aout, aout_filter_t * p_filter,
323                           aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
324 {
325     VLC_UNUSED(p_aout);
326     int i;
327     float * p_in = (float *)p_in_buf->p_buffer;
328     uint16_t * p_out = (uint16_t *)p_out_buf->p_buffer;
329
330     for ( i = p_in_buf->i_nb_samples
331                * aout_FormatNbChannels( &p_filter->input ); i-- ; )
332     {
333         if ( *p_in >= 1.0 ) *p_out = 65535;
334         else if ( *p_in < -1.0 ) *p_out = 0;
335         else *p_out = (uint16_t)(32768 + *p_in * 32768);
336         p_in++; p_out++;
337     }
338
339     p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
340     p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes / 2;
341 }
342
343 /*****************************************************************************
344  * FL32 To U8
345  *****************************************************************************/
346 static int Create_FL32ToU8( vlc_object_t *p_this )
347 {
348     aout_filter_t * p_filter = (aout_filter_t *)p_this;
349
350     if ( p_filter->input.i_format != VLC_FOURCC('f','l','3','2')
351           || p_filter->output.i_format != VLC_FOURCC('u','8',' ',' ') )
352     {
353         return -1;
354     }
355
356     if ( !AOUT_FMTS_SIMILAR( &p_filter->input, &p_filter->output ) )
357     {
358         return -1;
359     }
360
361     p_filter->pf_do_work = Do_FL32ToU8;
362     p_filter->b_in_place = 1;
363
364     return 0;
365 }
366
367 static void Do_FL32ToU8( aout_instance_t * p_aout, aout_filter_t * p_filter,
368                          aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
369 {
370     VLC_UNUSED(p_aout);
371     int i;
372     float * p_in = (float *)p_in_buf->p_buffer;
373     uint8_t * p_out = (uint8_t *)p_out_buf->p_buffer;
374
375     for ( i = p_in_buf->i_nb_samples
376                * aout_FormatNbChannels( &p_filter->input ); i-- ; )
377     {
378         if ( *p_in >= 1.0 ) *p_out = 255;
379         else if ( *p_in < -1.0 ) *p_out = 0;
380         else *p_out = (uint8_t)(128 + *p_in * 128);
381         p_in++; p_out++;
382     }
383
384     p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
385     p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes / 4;
386 }
387
388 /*****************************************************************************
389  * S16 To Float32
390  *****************************************************************************/
391 static int Create_S16ToFL32( vlc_object_t *p_this )
392 {
393     aout_filter_t * p_filter = (aout_filter_t *)p_this;
394
395     if ( ( p_filter->input.i_format != AOUT_FMT_S16_NE &&
396            p_filter->input.i_format != AOUT_FMT_S24_NE &&
397            p_filter->input.i_format != AOUT_FMT_S32_NE )
398           || p_filter->output.i_format != VLC_FOURCC('f','l','3','2') )
399     {
400         return -1;
401     }
402
403     if ( !AOUT_FMTS_SIMILAR( &p_filter->input, &p_filter->output ) )
404     {
405         return -1;
406     }
407
408     if( p_filter->input.i_format == AOUT_FMT_S32_NE )
409         p_filter->pf_do_work = Do_S32ToFL32;
410     else if( p_filter->input.i_format == AOUT_FMT_S24_NE )
411         p_filter->pf_do_work = Do_S24ToFL32;
412     else
413         p_filter->pf_do_work = Do_S16ToFL32;
414
415     p_filter->b_in_place = true;
416
417     return 0;
418 }
419
420 static void Do_S16ToFL32( aout_instance_t * p_aout, aout_filter_t * p_filter,
421                           aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
422 {
423     VLC_UNUSED(p_aout);
424     int i = p_in_buf->i_nb_samples * aout_FormatNbChannels( &p_filter->input );
425
426     /* We start from the end because b_in_place is true */
427     int16_t * p_in = (int16_t *)p_in_buf->p_buffer + i - 1;
428     float * p_out = (float *)p_out_buf->p_buffer + i - 1;
429
430     while( i-- )
431     {
432 #if 0
433         /* Slow version */
434         *p_out = (float)*p_in / 32768.0;
435 #else
436         /* This is walken's trick based on IEEE float format. On my PIII
437          * this takes 16 seconds to perform one billion conversions, instead
438          * of 19 seconds for the above division. */
439         union { float f; int32_t i; } u;
440         u.i = *p_in + 0x43c00000;
441         *p_out = u.f - 384.0;
442 #endif
443
444         p_in--; p_out--;
445     }
446
447     p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
448     p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes * 4 / 2;
449 }
450
451 static void Do_S24ToFL32( aout_instance_t * p_aout, aout_filter_t * p_filter,
452                           aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
453 {
454     VLC_UNUSED(p_aout);
455     int i = p_in_buf->i_nb_samples * aout_FormatNbChannels( &p_filter->input );
456
457     /* We start from the end because b_in_place is true */
458     uint8_t * p_in = (uint8_t *)p_in_buf->p_buffer + (i - 1) * 3;
459     float * p_out = (float *)p_out_buf->p_buffer + i - 1;
460
461     while( i-- )
462     {
463 #ifdef WORDS_BIGENDIAN
464         *p_out = ((float)( (((int32_t)*(int16_t *)(p_in)) << 8) + p_in[2]))
465 #else
466         *p_out = ((float)( (((int32_t)*(int16_t *)(p_in+1)) << 8) + p_in[0]))
467 #endif
468             / 8388608.0;
469
470         p_in -= 3; p_out--;
471     }
472
473     p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
474     p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes * 4 / 3;
475 }
476
477 static void Do_S32ToFL32( aout_instance_t * p_aout, aout_filter_t * p_filter,
478                           aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
479 {
480     VLC_UNUSED(p_aout);
481     int i = p_in_buf->i_nb_samples * aout_FormatNbChannels( &p_filter->input );
482
483     /* We start from the end because b_in_place is true */
484     int32_t * p_in = (int32_t *)p_in_buf->p_buffer + i - 1;
485     float * p_out = (float *)p_out_buf->p_buffer + i - 1;
486
487     while( i-- )
488     {
489         *p_out-- = (float)*p_in-- / 2147483648.0;
490     }
491
492     p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
493     p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes * 4 / 4;
494 }
495
496 /*****************************************************************************
497  * S16 To Float32 with endianness conversion
498  *****************************************************************************/
499 static int Create_S16ToFL32_SW( vlc_object_t *p_this )
500 {
501     aout_filter_t * p_filter = (aout_filter_t *)p_this;
502
503     if ( !AOUT_FMTS_SIMILAR( &p_filter->input, &p_filter->output ) )
504     {
505         return -1;
506     }
507
508     if ( (p_filter->input.i_format == VLC_FOURCC('s','1','6','l') ||
509          p_filter->input.i_format == VLC_FOURCC('s','1','6','b'))
510          && p_filter->output.i_format == VLC_FOURCC('f','l','3','2')
511          && p_filter->input.i_format != AOUT_FMT_S16_NE )
512     {
513         p_filter->pf_do_work = Do_S16ToFL32_SW;
514         p_filter->b_in_place = true;
515
516         return 0;
517     }
518
519     if ( (p_filter->input.i_format == VLC_FOURCC('s','2','4','l') ||
520          p_filter->input.i_format == VLC_FOURCC('s','2','4','b'))
521          && p_filter->output.i_format == VLC_FOURCC('f','l','3','2')
522          && p_filter->input.i_format != AOUT_FMT_S24_NE )
523     {
524         p_filter->pf_do_work = Do_S24ToFL32_SW;
525         p_filter->b_in_place = true;
526
527         return 0;
528     }
529
530     if ( (p_filter->input.i_format == VLC_FOURCC('s','3','2','l') ||
531          p_filter->input.i_format == VLC_FOURCC('s','3','2','b'))
532          && p_filter->output.i_format == VLC_FOURCC('f','l','3','2')
533          && p_filter->input.i_format != AOUT_FMT_S32_NE )
534     {
535         p_filter->pf_do_work = Do_S32ToFL32_SW;
536         p_filter->b_in_place = true;
537
538         return 0;
539     }
540
541     return -1;
542 }
543
544 static void Do_S16ToFL32_SW( aout_instance_t * p_aout, aout_filter_t * p_filter,
545                              aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
546 {
547     VLC_UNUSED(p_aout);
548     int i = p_in_buf->i_nb_samples * aout_FormatNbChannels( &p_filter->input );
549
550     /* We start from the end because b_in_place is true */
551     int16_t * p_in;
552     float * p_out = (float *)p_out_buf->p_buffer + i - 1;
553
554 #ifdef HAVE_SWAB
555     int16_t p_swabbed[i];
556
557     swab( p_in_buf->p_buffer, p_swabbed, i * sizeof(int16_t) );
558     p_in = p_swabbed + i - 1;
559
560 #else
561     uint8_t p_tmp[2];
562     p_in = (int16_t *)p_in_buf->p_buffer + i - 1;
563 #endif
564
565     while( i-- )
566     {
567 #ifndef HAVE_SWAB
568         p_tmp[0] = ((uint8_t *)p_in)[1];
569         p_tmp[1] = ((uint8_t *)p_in)[0];
570         *p_out = (float)( *(int16_t *)p_tmp ) / 32768.0;
571 #else
572         *p_out = (float)*p_in / 32768.0;
573 #endif
574         p_in--; p_out--;
575     }
576
577     p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
578     p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes * 4 / 2;
579 }
580
581 static void Do_S24ToFL32_SW( aout_instance_t * p_aout, aout_filter_t * p_filter,
582                              aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
583 {
584     VLC_UNUSED(p_aout);
585     int i = p_in_buf->i_nb_samples * aout_FormatNbChannels( &p_filter->input );
586
587     /* We start from the end because b_in_place is true */
588     uint8_t * p_in = (uint8_t *)p_in_buf->p_buffer + (i - 1) * 3;
589     float * p_out = (float *)p_out_buf->p_buffer + i - 1;
590
591     uint8_t p_tmp[3];
592
593     while( i-- )
594     {
595         p_tmp[0] = p_in[2];
596         p_tmp[1] = p_in[1];
597         p_tmp[2] = p_in[0];
598
599 #ifdef WORDS_BIGENDIAN
600         *p_out = ((float)( (((int32_t)*(int16_t *)(p_tmp)) << 8) + p_tmp[2]))
601 #else
602         *p_out = ((float)( (((int32_t)*(int16_t *)(p_tmp+1)) << 8) + p_tmp[0]))
603 #endif
604             / 8388608.0;
605
606         p_in -= 3; p_out--;
607     }
608
609     p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
610     p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes * 4 / 3;
611 }
612
613 static void Do_S32ToFL32_SW( aout_instance_t * p_aout, aout_filter_t * p_filter,
614                              aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
615 {
616     VLC_UNUSED(p_aout);
617     int i = p_in_buf->i_nb_samples * aout_FormatNbChannels( &p_filter->input );
618
619     /* We start from the end because b_in_place is true */
620     int32_t * p_in = (int32_t *)p_in_buf->p_buffer + i - 1;
621     float * p_out = (float *)p_out_buf->p_buffer + i - 1;
622
623     while( i-- )
624     {
625         *p_out-- = (float)*p_in-- / 2147483648.0;
626     }
627
628     p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
629     p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes * 4 / 4;
630 }
631
632
633 /*****************************************************************************
634  * S8 To FL32
635  *****************************************************************************/
636 static int Create_S8ToFL32( vlc_object_t *p_this )
637 {
638     aout_filter_t * p_filter = (aout_filter_t *)p_this;
639
640     if ( p_filter->input.i_format != VLC_FOURCC('s','8',' ',' ')
641           || p_filter->output.i_format != VLC_FOURCC('f','l','3','2') )
642     {
643         return -1;
644     }
645
646     if ( !AOUT_FMTS_SIMILAR( &p_filter->input, &p_filter->output ) )
647     {
648         return -1;
649     }
650
651     p_filter->pf_do_work = Do_S8ToFL32;
652     p_filter->b_in_place = true;
653
654     return 0;
655 }
656
657 static void Do_S8ToFL32( aout_instance_t * p_aout, aout_filter_t * p_filter,
658                          aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
659 {
660     VLC_UNUSED(p_aout);
661     int i = p_in_buf->i_nb_samples * aout_FormatNbChannels( &p_filter->input );
662
663     /* We start from the end because b_in_place is true */
664     int8_t * p_in = (int8_t *)p_in_buf->p_buffer + i - 1;
665     float * p_out = (float *)p_out_buf->p_buffer + i - 1;
666
667     while( i-- )
668     {
669         *p_out = (float)(*p_in) / 128.0;
670         p_in--; p_out--;
671     }
672
673     p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
674     p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes * sizeof(float);
675 }
676
677 /*****************************************************************************
678  * U8 To FL32
679  *****************************************************************************/
680 static int Create_U8ToFL32( vlc_object_t *p_this )
681 {
682     aout_filter_t * p_filter = (aout_filter_t *)p_this;
683
684     if ( p_filter->input.i_format != VLC_FOURCC('u','8',' ',' ')
685           || p_filter->output.i_format != VLC_FOURCC('f','l','3','2') )
686     {
687         return -1;
688     }
689
690     if ( !AOUT_FMTS_SIMILAR( &p_filter->input, &p_filter->output ) )
691     {
692         return -1;
693     }
694
695     p_filter->pf_do_work = Do_U8ToFL32;
696     p_filter->b_in_place = true;
697
698     return 0;
699 }
700
701 static void Do_U8ToFL32( aout_instance_t * p_aout, aout_filter_t * p_filter,
702                          aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
703 {
704     VLC_UNUSED(p_aout);
705     int i = p_in_buf->i_nb_samples * aout_FormatNbChannels( &p_filter->input );
706
707     /* We start from the end because b_in_place is true */
708     uint8_t * p_in = (uint8_t *)p_in_buf->p_buffer + i - 1;
709     float * p_out = (float *)p_out_buf->p_buffer + i - 1;
710
711     while( i-- )
712     {
713         *p_out = ((float)*p_in -128) / 128.0;
714         p_in--; p_out--;
715     }
716
717     p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
718     p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes * sizeof(float);
719 }