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