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