]> git.sesse.net Git - vlc/blob - modules/audio_filter/converter/float.c
Merge branch 'master' of git@git.videolan.org:vlc
[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     VLC_UNUSED(p_aout);
165     int i;
166     vlc_fixed_t * p_in = (vlc_fixed_t *)p_in_buf->p_buffer;
167     float * p_out = (float *)p_out_buf->p_buffer;
168
169     for ( i = p_in_buf->i_nb_samples
170                * aout_FormatNbChannels( &p_filter->input ) ; i-- ; )
171     {
172         *p_out++ = (float)*p_in++ / (float)FIXED32_ONE;
173     }
174
175     p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
176     p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes;
177 }
178
179 static void Do_FL32ToF32( aout_instance_t * p_aout, aout_filter_t * p_filter,
180                           aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
181 {
182     VLC_UNUSED(p_aout);
183     int i;
184     float * p_in = (float *)p_in_buf->p_buffer;
185     vlc_fixed_t * p_out = (vlc_fixed_t *)p_out_buf->p_buffer;
186
187     for ( i = p_in_buf->i_nb_samples
188                * aout_FormatNbChannels( &p_filter->input ) ; i-- ; )
189     {
190         *p_out++ = (vlc_fixed_t)( *p_in++ * (float)FIXED32_ONE );
191     }
192
193     p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
194     p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes;
195 }
196
197 /*****************************************************************************
198  * FL32 To S16
199  *****************************************************************************/
200 static int Create_FL32ToS16( vlc_object_t *p_this )
201 {
202     aout_filter_t * p_filter = (aout_filter_t *)p_this;
203
204     if ( p_filter->input.i_format != VLC_FOURCC('f','l','3','2')
205           || p_filter->output.i_format != AOUT_FMT_S16_NE )
206     {
207         return -1;
208     }
209
210     if ( !AOUT_FMTS_SIMILAR( &p_filter->input, &p_filter->output ) )
211     {
212         return -1;
213     }
214
215     p_filter->pf_do_work = Do_FL32ToS16;
216     p_filter->b_in_place = 1;
217
218     return 0;
219 }
220
221 static void Do_FL32ToS16( aout_instance_t * p_aout, aout_filter_t * p_filter,
222                           aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
223 {
224     VLC_UNUSED(p_aout);
225     int i;
226     float * p_in = (float *)p_in_buf->p_buffer;
227     int16_t * p_out = (int16_t *)p_out_buf->p_buffer;
228
229     for ( i = p_in_buf->i_nb_samples
230                * aout_FormatNbChannels( &p_filter->input ); i-- ; )
231     {
232 #if 0
233         /* Slow version. */
234         if ( *p_in >= 1.0 ) *p_out = 32767;
235         else if ( *p_in < -1.0 ) *p_out = -32768;
236         else *p_out = *p_in * 32768.0;
237 #else
238         /* This is walken's trick based on IEEE float format. */
239         union { float f; int32_t i; } u;
240         u.f = *p_in + 384.0;
241         if ( u.i > 0x43c07fff ) *p_out = 32767;
242         else if ( u.i < 0x43bf8000 ) *p_out = -32768;
243         else *p_out = u.i - 0x43c00000;
244 #endif
245         p_in++; p_out++;
246     }
247
248     p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
249     p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes / 2;
250 }
251
252 /*****************************************************************************
253  * FL32 To S8
254  *****************************************************************************/
255 static int Create_FL32ToS8( vlc_object_t *p_this )
256 {
257     aout_filter_t * p_filter = (aout_filter_t *)p_this;
258
259     if ( p_filter->input.i_format != VLC_FOURCC('f','l','3','2')
260           || p_filter->output.i_format != VLC_FOURCC('s','8',' ',' ') )
261     {
262         return -1;
263     }
264
265     if ( !AOUT_FMTS_SIMILAR( &p_filter->input, &p_filter->output ) )
266     {
267         return -1;
268     }
269
270     p_filter->pf_do_work = Do_FL32ToS8;
271     p_filter->b_in_place = 1;
272
273     return 0;
274 }
275
276 static void Do_FL32ToS8( aout_instance_t * p_aout, aout_filter_t * p_filter,
277                          aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
278 {
279     VLC_UNUSED(p_aout);
280     int i;
281     float * p_in = (float *)p_in_buf->p_buffer;
282     int8_t * p_out = (int8_t *)p_out_buf->p_buffer;
283
284     for ( i = p_in_buf->i_nb_samples
285                * aout_FormatNbChannels( &p_filter->input ); i-- ; )
286     {
287         if ( *p_in >= 1.0 ) *p_out = 127;
288         else if ( *p_in < -1.0 ) *p_out = -128;
289         else *p_out = (int8_t)(*p_in * 128);
290         p_in++; p_out++;
291     }
292
293     p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
294     p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes / 4;
295 }
296
297 /*****************************************************************************
298  * FL32 To U16
299  *****************************************************************************/
300 static int Create_FL32ToU16( vlc_object_t *p_this )
301 {
302     aout_filter_t * p_filter = (aout_filter_t *)p_this;
303
304     if ( p_filter->input.i_format != VLC_FOURCC('f','l','3','2')
305           || p_filter->output.i_format != AOUT_FMT_U16_NE )
306     {
307         return -1;
308     }
309
310     if ( !AOUT_FMTS_SIMILAR( &p_filter->input, &p_filter->output ) )
311     {
312         return -1;
313     }
314
315     p_filter->pf_do_work = Do_FL32ToU16;
316     p_filter->b_in_place = 1;
317
318     return 0;
319 }
320
321 static void Do_FL32ToU16( aout_instance_t * p_aout, aout_filter_t * p_filter,
322                           aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
323 {
324     VLC_UNUSED(p_aout);
325     int i;
326     float * p_in = (float *)p_in_buf->p_buffer;
327     uint16_t * p_out = (uint16_t *)p_out_buf->p_buffer;
328
329     for ( i = p_in_buf->i_nb_samples
330                * aout_FormatNbChannels( &p_filter->input ); i-- ; )
331     {
332         if ( *p_in >= 1.0 ) *p_out = 65535;
333         else if ( *p_in < -1.0 ) *p_out = 0;
334         else *p_out = (uint16_t)(32768 + *p_in * 32768);
335         p_in++; p_out++;
336     }
337
338     p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
339     p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes / 2;
340 }
341
342 /*****************************************************************************
343  * FL32 To U8
344  *****************************************************************************/
345 static int Create_FL32ToU8( vlc_object_t *p_this )
346 {
347     aout_filter_t * p_filter = (aout_filter_t *)p_this;
348
349     if ( p_filter->input.i_format != VLC_FOURCC('f','l','3','2')
350           || p_filter->output.i_format != VLC_FOURCC('u','8',' ',' ') )
351     {
352         return -1;
353     }
354
355     if ( !AOUT_FMTS_SIMILAR( &p_filter->input, &p_filter->output ) )
356     {
357         return -1;
358     }
359
360     p_filter->pf_do_work = Do_FL32ToU8;
361     p_filter->b_in_place = 1;
362
363     return 0;
364 }
365
366 static void Do_FL32ToU8( aout_instance_t * p_aout, aout_filter_t * p_filter,
367                          aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
368 {
369     VLC_UNUSED(p_aout);
370     int i;
371     float * p_in = (float *)p_in_buf->p_buffer;
372     uint8_t * p_out = (uint8_t *)p_out_buf->p_buffer;
373
374     for ( i = p_in_buf->i_nb_samples
375                * aout_FormatNbChannels( &p_filter->input ); i-- ; )
376     {
377         if ( *p_in >= 1.0 ) *p_out = 255;
378         else if ( *p_in < -1.0 ) *p_out = 0;
379         else *p_out = (uint8_t)(128 + *p_in * 128);
380         p_in++; p_out++;
381     }
382
383     p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
384     p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes / 4;
385 }
386
387 /*****************************************************************************
388  * S16 To Float32
389  *****************************************************************************/
390 static int Create_S16ToFL32( vlc_object_t *p_this )
391 {
392     aout_filter_t * p_filter = (aout_filter_t *)p_this;
393
394     if ( ( p_filter->input.i_format != AOUT_FMT_S16_NE &&
395            p_filter->input.i_format != AOUT_FMT_S24_NE )
396           || p_filter->output.i_format != VLC_FOURCC('f','l','3','2') )
397     {
398         return -1;
399     }
400
401     if ( !AOUT_FMTS_SIMILAR( &p_filter->input, &p_filter->output ) )
402     {
403         return -1;
404     }
405
406     if( p_filter->input.i_format == AOUT_FMT_S24_NE )
407         p_filter->pf_do_work = Do_S16ToFL24;
408     else
409         p_filter->pf_do_work = Do_S16ToFL32;
410
411     p_filter->b_in_place = true;
412
413     return 0;
414 }
415
416 static void Do_S16ToFL32( aout_instance_t * p_aout, aout_filter_t * p_filter,
417                           aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
418 {
419     VLC_UNUSED(p_aout);
420     int i = p_in_buf->i_nb_samples * aout_FormatNbChannels( &p_filter->input );
421
422     /* We start from the end because b_in_place is true */
423     int16_t * p_in = (int16_t *)p_in_buf->p_buffer + i - 1;
424     float * p_out = (float *)p_out_buf->p_buffer + i - 1;
425
426     while( i-- )
427     {
428 #if 0
429         /* Slow version */
430         *p_out = (float)*p_in / 32768.0;
431 #else
432         /* This is walken's trick based on IEEE float format. On my PIII
433          * this takes 16 seconds to perform one billion conversions, instead
434          * of 19 seconds for the above division. */
435         union { float f; int32_t i; } u;
436         u.i = *p_in + 0x43c00000;
437         *p_out = u.f - 384.0;
438 #endif
439
440         p_in--; p_out--;
441     }
442
443     p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
444     p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes * 2;
445 }
446
447 static void Do_S16ToFL24( aout_instance_t * p_aout, aout_filter_t * p_filter,
448                           aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
449 {
450     VLC_UNUSED(p_aout);
451     int i = p_in_buf->i_nb_samples * aout_FormatNbChannels( &p_filter->input );
452
453     /* We start from the end because b_in_place is true */
454     uint8_t * p_in = (uint8_t *)p_in_buf->p_buffer + (i - 1) * 3;
455     float * p_out = (float *)p_out_buf->p_buffer + i - 1;
456
457     while( i-- )
458     {
459 #ifdef WORDS_BIGENDIAN
460         *p_out = ((float)( (((int32_t)*(int16_t *)(p_in)) << 8) + p_in[2]))
461 #else
462         *p_out = ((float)( (((int32_t)*(int16_t *)(p_in+1)) << 8) + p_in[0]))
463 #endif
464             / 8388608.0;
465
466         p_in -= 3; p_out--;
467     }
468
469     p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
470     p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes * 4 / 3;
471 }
472
473 /*****************************************************************************
474  * S16 To Float32 with endianness conversion
475  *****************************************************************************/
476 static int Create_S16ToFL32_SW( vlc_object_t *p_this )
477 {
478     aout_filter_t * p_filter = (aout_filter_t *)p_this;
479
480     if ( !AOUT_FMTS_SIMILAR( &p_filter->input, &p_filter->output ) )
481     {
482         return -1;
483     }
484
485     if ( (p_filter->input.i_format == VLC_FOURCC('s','1','6','l') ||
486          p_filter->input.i_format == VLC_FOURCC('s','1','6','b'))
487          && p_filter->output.i_format == VLC_FOURCC('f','l','3','2')
488          && p_filter->input.i_format != AOUT_FMT_S16_NE )
489     {
490         p_filter->pf_do_work = Do_S16ToFL32_SW;
491         p_filter->b_in_place = true;
492
493         return 0;
494     }
495
496     if ( (p_filter->input.i_format == VLC_FOURCC('s','2','4','l') ||
497          p_filter->input.i_format == VLC_FOURCC('s','2','4','b'))
498          && p_filter->output.i_format == VLC_FOURCC('f','l','3','2')
499          && p_filter->input.i_format != AOUT_FMT_S24_NE )
500     {
501         p_filter->pf_do_work = Do_S16ToFL24_SW;
502         p_filter->b_in_place = true;
503
504         return 0;
505     }
506     return -1;
507 }
508
509 static void Do_S16ToFL32_SW( aout_instance_t * p_aout, aout_filter_t * p_filter,
510                           aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
511 {
512     VLC_UNUSED(p_aout);
513     int i = p_in_buf->i_nb_samples * aout_FormatNbChannels( &p_filter->input );
514
515     /* We start from the end because b_in_place is true */
516     int16_t * p_in;
517     float * p_out = (float *)p_out_buf->p_buffer + i - 1;
518
519 #ifdef HAVE_SWAB
520 #   ifdef HAVE_ALLOCA
521     int16_t * p_swabbed = alloca( i * sizeof(int16_t) );
522 #   else
523     int16_t * p_swabbed = malloc( i * sizeof(int16_t) );
524 #   endif
525
526     swab( p_in_buf->p_buffer, (void *)p_swabbed, i * sizeof(int16_t) );
527     p_in = p_swabbed + i - 1;
528
529 #else
530     byte_t p_tmp[2];
531     p_in = (int16_t *)p_in_buf->p_buffer + i - 1;
532 #endif
533
534     while( i-- )
535     {
536 #ifndef HAVE_SWAB
537         p_tmp[0] = ((byte_t *)p_in)[1];
538         p_tmp[1] = ((byte_t *)p_in)[0];
539         *p_out = (float)( *(int16_t *)p_tmp ) / 32768.0;
540 #else
541         *p_out = (float)*p_in / 32768.0;
542 #endif
543         p_in--; p_out--;
544     }
545
546 #ifdef HAVE_SWAB
547 #   ifndef HAVE_ALLOCA
548     free( p_swabbed );
549 #   endif
550 #endif
551
552     p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
553     p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes * 2;
554 }
555
556 static void Do_S16ToFL24_SW( aout_instance_t * p_aout, aout_filter_t * p_filter,
557                            aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
558 {
559     VLC_UNUSED(p_aout);
560     int i = p_in_buf->i_nb_samples * aout_FormatNbChannels( &p_filter->input );
561
562     /* We start from the end because b_in_place is true */
563     uint8_t * p_in = (uint8_t *)p_in_buf->p_buffer + (i - 1) * 3;
564     float * p_out = (float *)p_out_buf->p_buffer + i - 1;
565
566     byte_t p_tmp[3];
567
568     while( i-- )
569     {
570         p_tmp[0] = p_in[2];
571         p_tmp[1] = p_in[1];
572         p_tmp[2] = p_in[0];
573
574 #ifdef WORDS_BIGENDIAN
575         *p_out = ((float)( (((int32_t)*(int16_t *)(p_tmp)) << 8) + p_tmp[2]))
576 #else
577         *p_out = ((float)( (((int32_t)*(int16_t *)(p_tmp+1)) << 8) + p_tmp[0]))
578 #endif
579             / 8388608.0;
580
581         p_in -= 3; p_out--;
582     }
583
584     p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
585     p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes * 4 / 3;
586 }
587
588 /*****************************************************************************
589  * S8 To FL32
590  *****************************************************************************/
591 static int Create_S8ToFL32( vlc_object_t *p_this )
592 {
593     aout_filter_t * p_filter = (aout_filter_t *)p_this;
594
595     if ( p_filter->input.i_format != VLC_FOURCC('s','8',' ',' ')
596           || p_filter->output.i_format != VLC_FOURCC('f','l','3','2') )
597     {
598         return -1;
599     }
600
601     if ( !AOUT_FMTS_SIMILAR( &p_filter->input, &p_filter->output ) )
602     {
603         return -1;
604     }
605
606     p_filter->pf_do_work = Do_S8ToFL32;
607     p_filter->b_in_place = true;
608
609     return 0;
610 }
611
612 static void Do_S8ToFL32( aout_instance_t * p_aout, aout_filter_t * p_filter,
613                          aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
614 {
615     VLC_UNUSED(p_aout);
616     int i = p_in_buf->i_nb_samples * aout_FormatNbChannels( &p_filter->input );
617
618     /* We start from the end because b_in_place is true */
619     int8_t * p_in = (int8_t *)p_in_buf->p_buffer + i - 1;
620     float * p_out = (float *)p_out_buf->p_buffer + i - 1;
621
622     while( i-- )
623     {
624         *p_out = (float)(*p_in) / 128.0;
625         p_in--; p_out--;
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 * sizeof(float);
630 }
631
632 /*****************************************************************************
633  * U8 To FL32
634  *****************************************************************************/
635 static int Create_U8ToFL32( vlc_object_t *p_this )
636 {
637     aout_filter_t * p_filter = (aout_filter_t *)p_this;
638
639     if ( p_filter->input.i_format != VLC_FOURCC('u','8',' ',' ')
640           || p_filter->output.i_format != VLC_FOURCC('f','l','3','2') )
641     {
642         return -1;
643     }
644
645     if ( !AOUT_FMTS_SIMILAR( &p_filter->input, &p_filter->output ) )
646     {
647         return -1;
648     }
649
650     p_filter->pf_do_work = Do_U8ToFL32;
651     p_filter->b_in_place = true;
652
653     return 0;
654 }
655
656 static void Do_U8ToFL32( aout_instance_t * p_aout, aout_filter_t * p_filter,
657                          aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
658 {
659     VLC_UNUSED(p_aout);
660     int i = p_in_buf->i_nb_samples * aout_FormatNbChannels( &p_filter->input );
661
662     /* We start from the end because b_in_place is true */
663     uint8_t * p_in = (uint8_t *)p_in_buf->p_buffer + i - 1;
664     float * p_out = (float *)p_out_buf->p_buffer + i - 1;
665
666     while( i-- )
667     {
668         *p_out = ((float)*p_in -128) / 128.0;
669         p_in--; p_out--;
670     }
671
672     p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
673     p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes * sizeof(float);
674 }