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