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