c8c921414eadf116d6412f49b66409b9ffa644e6
[vlc.git] / modules / codec / araw.c
1 /*****************************************************************************
2  * araw.c: Pseudo audio decoder; for raw pcm data
3  *****************************************************************************
4  * Copyright (C) 2001, 2003 VLC authors and VideoLAN
5  *
6  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation; either version 2.1 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21  *****************************************************************************/
22
23 /*****************************************************************************
24  * Preamble
25  *****************************************************************************/
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <math.h>
31 #include <assert.h>
32
33 #include <vlc_common.h>
34 #include <vlc_plugin.h>
35 #include <vlc_codec.h>
36 #include <vlc_aout.h>
37
38 /*****************************************************************************
39  * Module descriptor
40  *****************************************************************************/
41 static int  DecoderOpen ( vlc_object_t * );
42
43 #ifdef ENABLE_SOUT
44 static int  EncoderOpen ( vlc_object_t * );
45 #endif
46
47 vlc_module_begin ()
48     /* audio decoder module */
49     set_description( N_("Raw/Log Audio decoder") )
50     set_capability( "audio decoder", 100 )
51     set_category( CAT_INPUT )
52     set_subcategory( SUBCAT_INPUT_ACODEC )
53     set_callback( DecoderOpen )
54
55 #ifdef ENABLE_SOUT
56     /* audio encoder submodule */
57     add_submodule ()
58     set_description( N_("Raw audio encoder") )
59     set_capability( "encoder", 150 )
60     set_callback( EncoderOpen )
61 #endif
62 vlc_module_end ()
63
64 /*****************************************************************************
65  * Local prototypes
66  *****************************************************************************/
67 static int DecodeBlock( decoder_t *, block_t * );
68 static void Flush( decoder_t * );
69
70 typedef struct
71 {
72     void (*decode) (void *, const uint8_t *, unsigned);
73     size_t framebits;
74     date_t end_date;
75 } decoder_sys_t;
76
77 static void S8Decode( void *, const uint8_t *, unsigned );
78 static void U16BDecode( void *, const uint8_t *, unsigned );
79 static void U16LDecode( void *, const uint8_t *, unsigned );
80 static void S16IDecode( void *, const uint8_t *, unsigned );
81 static void S20BDecode( void *, const uint8_t *, unsigned );
82 static void U24BDecode( void *, const uint8_t *, unsigned );
83 static void U24LDecode( void *, const uint8_t *, unsigned );
84 static void S24BDecode( void *, const uint8_t *, unsigned );
85 static void S24LDecode( void *, const uint8_t *, unsigned );
86 static void S24B32Decode( void *, const uint8_t *, unsigned );
87 static void S24L32Decode( void *, const uint8_t *, unsigned );
88 static void U32BDecode( void *, const uint8_t *, unsigned );
89 static void U32LDecode( void *, const uint8_t *, unsigned );
90 static void S32IDecode( void *, const uint8_t *, unsigned );
91 static void F32NDecode( void *, const uint8_t *, unsigned );
92 static void F32IDecode( void *, const uint8_t *, unsigned );
93 static void F64NDecode( void *, const uint8_t *, unsigned );
94 static void F64IDecode( void *, const uint8_t *, unsigned );
95 static void DAT12Decode( void *, const uint8_t *, unsigned );
96
97 /*****************************************************************************
98  * DecoderOpen: probe the decoder and return score
99  *****************************************************************************/
100 static int DecoderOpen( vlc_object_t *p_this )
101 {
102     decoder_t *p_dec = (decoder_t*)p_this;
103     vlc_fourcc_t format = p_dec->fmt_in.i_codec;
104
105     switch( p_dec->fmt_in.i_codec )
106     {
107     case VLC_FOURCC('a','r','a','w'):
108     case VLC_FOURCC('a','f','l','t'):
109     /* _signed_ big endian samples (mov) */
110     case VLC_FOURCC('t','w','o','s'):
111     /* _signed_ little endian samples (mov) */
112     case VLC_FOURCC('s','o','w','t'):
113         format =
114             vlc_fourcc_GetCodecAudio( p_dec->fmt_in.i_codec,
115                                       p_dec->fmt_in.audio.i_bitspersample );
116         if( !format )
117         {
118             msg_Err( p_dec, "bad parameters(bits/sample)" );
119             return VLC_EGENERIC;
120         }
121         break;
122     }
123
124     void (*decode) (void *, const uint8_t *, unsigned) = NULL;
125     uint_fast8_t bits;
126
127     switch( format )
128     {
129 #ifdef WORDS_BIGENDIAN
130     case VLC_CODEC_F64L:
131 #else
132     case VLC_CODEC_F64B:
133 #endif
134         format = VLC_CODEC_FL64;
135         decode = F64IDecode;
136         bits = 64;
137         break;
138     case VLC_CODEC_FL64:
139         decode = F64NDecode;
140         bits = 64;
141         break;
142 #ifdef WORDS_BIGENDIAN
143     case VLC_CODEC_F32L:
144 #else
145     case VLC_CODEC_F32B:
146 #endif
147         format = VLC_CODEC_FL32;
148         decode = F32IDecode;
149         bits = 32;
150         break;
151     case VLC_CODEC_FL32:
152         decode = F32NDecode;
153         bits = 32;
154         break;
155     case VLC_CODEC_U32B:
156         format = VLC_CODEC_S32N;
157         decode = U32BDecode;
158         bits = 32;
159         break;
160     case VLC_CODEC_U32L:
161         format = VLC_CODEC_S32N;
162         decode = U32LDecode;
163         bits = 32;
164         break;
165     case VLC_CODEC_S32I:
166         format = VLC_CODEC_S32N;
167         decode = S32IDecode;
168         /* fall through */
169     case VLC_CODEC_S32N:
170         bits = 32;
171         break;
172     case VLC_CODEC_S24B32:
173         format = VLC_CODEC_S32N;
174         decode = S24B32Decode;
175         bits = 32;
176         break;
177     case VLC_CODEC_S24L32:
178         format = VLC_CODEC_S32N;
179         decode = S24L32Decode;
180         bits = 32;
181         break;
182     case VLC_CODEC_U24B:
183         format = VLC_CODEC_S32N;
184         decode = U24BDecode;
185         bits = 24;
186         break;
187     case VLC_CODEC_U24L:
188         format = VLC_CODEC_S32N;
189         decode = U24LDecode;
190         bits = 24;
191         break;
192     case VLC_CODEC_S24B:
193         format = VLC_CODEC_S32N;
194         decode = S24BDecode;
195         bits = 24;
196         break;
197     case VLC_CODEC_S24L:
198         format = VLC_CODEC_S32N;
199         decode = S24LDecode;
200         bits = 24;
201         break;
202     case VLC_CODEC_S20B:
203         format = VLC_CODEC_S32N;
204         decode = S20BDecode;
205         bits = 20;
206         break;
207     case VLC_CODEC_U16B:
208         format = VLC_CODEC_S16N;
209         decode = U16BDecode;
210         bits = 16;
211         break;
212     case VLC_CODEC_U16L:
213         format = VLC_CODEC_S16N;
214         decode = U16LDecode;
215         bits = 16;
216         break;
217     case VLC_CODEC_S16I:
218         format = VLC_CODEC_S16N;
219         decode = S16IDecode;
220         /* fall through */
221     case VLC_CODEC_S16N:
222         bits = 16;
223         break;
224     case VLC_CODEC_DAT12:
225         format = VLC_CODEC_S16N;
226         decode = DAT12Decode;
227         bits = 12;
228         break;
229     case VLC_CODEC_S8:
230         decode = S8Decode;
231         format = VLC_CODEC_U8;
232         /* fall through */
233     case VLC_CODEC_U8:
234         bits = 8;
235         break;
236     default:
237         return VLC_EGENERIC;
238     }
239
240     if( p_dec->fmt_in.audio.i_channels == 0 ||
241         p_dec->fmt_in.audio.i_channels > INPUT_CHAN_MAX )
242     {
243         msg_Err( p_dec, "bad channels count (1-%i): %i",
244                  AOUT_CHAN_MAX, p_dec->fmt_in.audio.i_channels );
245         return VLC_EGENERIC;
246     }
247
248     if( p_dec->fmt_in.audio.i_rate == 0 || p_dec->fmt_in.audio.i_rate > 384000 )
249     {
250         msg_Err( p_dec, "bad samplerate: %d Hz", p_dec->fmt_in.audio.i_rate );
251         return VLC_EGENERIC;
252     }
253
254     msg_Dbg( p_dec, "samplerate:%dHz channels:%d bits/sample:%d",
255              p_dec->fmt_in.audio.i_rate, p_dec->fmt_in.audio.i_channels,
256              p_dec->fmt_in.audio.i_bitspersample );
257
258     /* Allocate the memory needed to store the decoder's structure */
259     decoder_sys_t *p_sys = vlc_obj_malloc(p_this, sizeof(*p_sys));
260     if( unlikely(p_sys == NULL) )
261         return VLC_ENOMEM;
262
263     /* Set output properties */
264     p_dec->fmt_out.i_codec = format;
265     p_dec->fmt_out.audio.channel_type = p_dec->fmt_in.audio.channel_type;
266     p_dec->fmt_out.audio.i_format = format;
267     p_dec->fmt_out.audio.i_rate = p_dec->fmt_in.audio.i_rate;
268     if( p_dec->fmt_in.audio.i_channels < ARRAY_SIZE(vlc_chan_maps) )
269     {
270         if( p_dec->fmt_in.audio.i_physical_channels )
271             p_dec->fmt_out.audio.i_physical_channels =
272                                            p_dec->fmt_in.audio.i_physical_channels;
273         else
274             p_dec->fmt_out.audio.i_physical_channels =
275                 vlc_chan_maps[p_dec->fmt_in.audio.i_channels];
276     }
277     else
278     {
279         /* Unknown channel map, let the aout/filters decide what to do */
280         p_dec->fmt_out.audio.i_channels = p_dec->fmt_in.audio.i_channels;
281         p_dec->fmt_out.audio.i_physical_channels = 0;
282     }
283     aout_FormatPrepare( &p_dec->fmt_out.audio );
284
285     p_sys->decode = decode;
286     p_sys->framebits = bits * p_dec->fmt_out.audio.i_channels;
287     assert( p_sys->framebits );
288
289     date_Init( &p_sys->end_date, p_dec->fmt_out.audio.i_rate, 1 );
290
291     p_dec->pf_decode = DecodeBlock;
292     p_dec->pf_flush  = Flush;
293     p_dec->p_sys = p_sys;
294
295     return VLC_SUCCESS;
296 }
297
298 /*****************************************************************************
299  * Flush:
300  *****************************************************************************/
301 static void Flush( decoder_t *p_dec )
302 {
303     decoder_sys_t *p_sys = p_dec->p_sys;
304
305     date_Set( &p_sys->end_date, VLC_TICK_INVALID );
306 }
307
308 /****************************************************************************
309  * DecodeBlock: the whole thing
310  ****************************************************************************
311  * This function must be fed with whole samples (see nBlockAlign).
312  ****************************************************************************/
313 static int DecodeBlock( decoder_t *p_dec, block_t *p_block )
314 {
315     decoder_sys_t *p_sys = p_dec->p_sys;
316     if( p_block == NULL ) /* No Drain */
317         return VLCDEC_SUCCESS;
318
319     if( p_block->i_flags & (BLOCK_FLAG_CORRUPTED|BLOCK_FLAG_DISCONTINUITY) )
320     {
321         Flush( p_dec );
322         if( p_block->i_flags & BLOCK_FLAG_CORRUPTED )
323             goto skip;
324     }
325
326     if( p_block->i_pts != VLC_TICK_INVALID &&
327         p_block->i_pts != date_Get( &p_sys->end_date ) )
328     {
329         date_Set( &p_sys->end_date, p_block->i_pts );
330     }
331     else if( date_Get( &p_sys->end_date ) == VLC_TICK_INVALID )
332         /* We've just started the stream, wait for the first PTS. */
333         goto skip;
334
335     unsigned samples = (8 * p_block->i_buffer) / p_sys->framebits;
336     if( samples == 0 )
337         goto skip;
338
339     if( p_sys->decode != NULL )
340     {
341         if( decoder_UpdateAudioFormat( p_dec ) )
342             goto skip;
343         block_t *p_out = decoder_NewAudioBuffer( p_dec, samples );
344         if( p_out == NULL )
345             goto skip;
346
347         p_sys->decode( p_out->p_buffer, p_block->p_buffer,
348                        samples * p_dec->fmt_in.audio.i_channels );
349         block_Release( p_block );
350         p_block = p_out;
351     }
352     else
353     {
354         if( decoder_UpdateAudioFormat( p_dec ) )
355             goto skip;
356         p_block->i_nb_samples = samples;
357         p_block->i_buffer = samples * (p_sys->framebits / 8);
358     }
359
360     p_block->i_pts = date_Get( &p_sys->end_date );
361     p_block->i_length = date_Increment( &p_sys->end_date, samples )
362                       - p_block->i_pts;
363     decoder_QueueAudio( p_dec, p_block );
364     return VLCDEC_SUCCESS;
365 skip:
366     block_Release( p_block );
367     return VLCDEC_SUCCESS;
368 }
369
370 static void S8Decode( void *outp, const uint8_t *in, unsigned samples )
371 {
372     uint8_t *out = outp;
373
374     for( size_t i = 0; i < samples; i++ )
375         out[i] = in[i] ^ 0x80;
376 }
377
378 static void U16BDecode( void *outp, const uint8_t *in, unsigned samples )
379 {
380     uint16_t *out = outp;
381
382     for( size_t i = 0; i < samples; i++ )
383     {
384         *(out++) = GetWBE( in ) - 0x8000;
385         in += 2;
386     }
387 }
388
389 static void U16LDecode( void *outp, const uint8_t *in, unsigned samples )
390 {
391     uint16_t *out = outp;
392
393     for( size_t i = 0; i < samples; i++ )
394     {
395         *(out++) = GetWLE( in ) - 0x8000;
396         in += 2;
397     }
398 }
399
400 static void S16IDecode( void *out, const uint8_t *in, unsigned samples )
401 {
402     swab( in, out, samples * 2 );
403 }
404
405 static void S20BDecode( void *outp, const uint8_t *in, unsigned samples )
406 {
407     int32_t *out = outp;
408
409     while( samples >= 2 )
410     {
411         uint32_t dw = U32_AT(in);
412         in += 4;
413         *(out++) = dw & ~0xFFF;
414         *(out++) = (dw << 20) | (*in << 12);
415         in++;
416         samples -= 2;
417     }
418
419     /* No U32_AT() for the last odd sample: avoid off-by-one overflow! */
420     if( samples )
421         *(out++) = (U16_AT(in) << 16) | ((in[2] & 0xF0) << 8);
422 }
423
424 static void U24BDecode( void *outp, const uint8_t *in, unsigned samples )
425 {
426     uint32_t *out = outp;
427
428     for( size_t i = 0; i < samples; i++ )
429     {
430         uint32_t s = ((in[0] << 24) | (in[1] << 16) | (in[2] << 8)) - 0x80000000;
431         *(out++) = s;
432         in += 3;
433     }
434 }
435
436 static void U24LDecode( void *outp, const uint8_t *in, unsigned samples )
437 {
438     uint32_t *out = outp;
439
440     for( size_t i = 0; i < samples; i++ )
441     {
442         uint32_t s = ((in[2] << 24) | (in[1] << 16) | (in[0] << 8)) - 0x80000000;
443         *(out++) = s;
444         in += 3;
445     }
446 }
447
448 static void S24BDecode( void *outp, const uint8_t *in, unsigned samples )
449 {
450     uint32_t *out = outp;
451
452     for( size_t i = 0; i < samples; i++ )
453     {
454         uint32_t s = ((in[0] << 24) | (in[1] << 16) | (in[2] << 8));
455         *(out++) = s;
456         in += 3;
457     }
458 }
459
460 static void S24LDecode( void *outp, const uint8_t *in, unsigned samples )
461 {
462     uint32_t *out = outp;
463
464     for( size_t i = 0; i < samples; i++ )
465     {
466         uint32_t s = ((in[2] << 24) | (in[1] << 16) | (in[0] << 8));
467         *(out++) = s;
468         in += 3;
469     }
470 }
471
472 static void S24B32Decode( void *outp, const uint8_t *in, unsigned samples )
473 {
474     uint32_t *out = outp;
475
476     for( size_t i = 0; i < samples; i++ )
477     {
478         *(out++) = GetDWBE( in ) << 8;
479         in += 4;
480     }
481 }
482
483 static void S24L32Decode( void *outp, const uint8_t *in, unsigned samples )
484 {
485     uint32_t *out = outp;
486
487     for( size_t i = 0; i < samples; i++ )
488     {
489         *(out++) = GetDWLE( in ) << 8;
490         in += 4;
491     }
492 }
493
494 static void U32BDecode( void *outp, const uint8_t *in, unsigned samples )
495 {
496     uint32_t *out = outp;
497
498     for( size_t i = 0; i < samples; i++ )
499     {
500         *(out++) = GetDWBE( in ) - 0x80000000;
501         in += 4;
502     }
503 }
504
505 static void U32LDecode( void *outp, const uint8_t *in, unsigned samples )
506 {
507     uint32_t *out = outp;
508
509     for( size_t i = 0; i < samples; i++ )
510     {
511         *(out++) = GetDWLE( in ) - 0x80000000;
512         in += 4;
513     }
514 }
515
516 static void S32IDecode( void *outp, const uint8_t *in, unsigned samples )
517 {
518     int32_t *out = outp;
519
520     for( size_t i = 0; i < samples; i++ )
521     {
522 #ifdef WORDS_BIGENDIAN
523         *(out++) = GetDWLE( in );
524 #else
525         *(out++) = GetDWBE( in );
526 #endif
527         in += 4;
528     }
529 }
530
531 static void F32NDecode( void *outp, const uint8_t *in, unsigned samples )
532 {
533     float *out = outp;
534
535     for( size_t i = 0; i < samples; i++ )
536     {
537         memcpy( out, in, sizeof(float) );
538         if( unlikely(!isfinite(*out)) )
539             *out = 0.f;
540         out++;
541         in += sizeof(float);
542     }
543 }
544
545 static void F32IDecode( void *outp, const uint8_t *in, unsigned samples )
546 {
547     float *out = outp;
548
549     for( size_t i = 0; i < samples; i++ )
550     {
551         union { float f; uint32_t u; } s;
552
553 #ifdef WORDS_BIGENDIAN
554         s.u = GetDWLE( in );
555 #else
556         s.u = GetDWBE( in );
557 #endif
558         if( unlikely(!isfinite(s.f)) )
559             s.f = 0.f;
560         *(out++) = s.f;
561         in += 4;
562     }
563 }
564
565 static void F64NDecode( void *outp, const uint8_t *in, unsigned samples )
566 {
567     double *out = outp;
568
569     for( size_t i = 0; i < samples; i++ )
570     {
571         memcpy( out, in, sizeof(double) );
572         if( unlikely(!isfinite( *out )) )
573             *out = 0.;
574         out++;
575         in += sizeof(double);
576     }
577 }
578
579 static void F64IDecode( void *outp, const uint8_t *in, unsigned samples )
580 {
581     double *out = outp;
582
583     for( size_t i = 0; i < samples; i++ )
584     {
585         union { double d; uint64_t u; } s;
586
587 #ifdef WORDS_BIGENDIAN
588         s.u = GetQWLE( in );
589 #else
590         s.u = GetQWBE( in );
591 #endif
592         if( unlikely(!isfinite( s.d )) )
593             s.d = 0.;
594         *(out++) = s.d;
595         in += 8;
596     }
597 }
598
599 static int_fast16_t dat12tos16( uint_fast16_t y )
600 {
601     static const int16_t diff[16] = {
602        0x0000, 0x0000, 0x0100, 0x0200, 0x0300, 0x0400, 0x0500, 0x0600,
603        0x0A00, 0x0B00, 0x0C00, 0x0D00, 0x0E00, 0x0F00, 0x1000, 0x1000,
604     };
605     static const uint8_t shift[16] = {
606         0, 0, 1, 2, 3, 4, 5, 6, 6, 5, 4, 3, 2, 1, 0, 0
607     };
608
609     assert(y < 0x1000);
610
611     int d = y >> 8;
612     return ((int)y - diff[d]) << shift[d];
613 }
614
615 static void DAT12Decode( void *outp, const uint8_t *in, unsigned samples )
616 {
617     int16_t *out = outp;
618
619     while( samples >= 2 )
620     {
621         *(out++) = dat12tos16(U16_AT(in) >> 4);
622         *(out++) = dat12tos16(U16_AT(in + 1) & ~0xF000);
623         in += 3;
624         samples -= 2;
625     }
626
627     if( samples )
628         *(out++) = dat12tos16(U16_AT(in) >> 4);
629 }
630
631 #ifdef ENABLE_SOUT
632 /* NOTE: Output buffers are always aligned since they are allocated by the araw plugin.
633  * Contrary to the decoder, the encoder can also assume that input buffers are aligned,
634  * since decoded audio blocks must always be aligned. */
635
636 static void U16IEncode( void *outp, const uint8_t *inp, unsigned samples )
637 {
638     const uint16_t *in = (const uint16_t *)inp;
639     uint16_t *out = outp;
640
641     for( size_t i = 0; i < samples; i++ )
642         *(out++) =  vlc_bswap16( *(in++) + 0x8000 );
643 }
644
645 static void U16NEncode( void *outp, const uint8_t *inp, unsigned samples )
646 {
647     const uint16_t *in = (const uint16_t *)inp;
648     uint16_t *out = outp;
649
650     for( size_t i = 0; i < samples; i++ )
651         *(out++) =  *(in++) + 0x8000;
652 }
653
654 static void U24BEncode( void *outp, const uint8_t *inp, unsigned samples )
655 {
656     const uint32_t *in = (const uint32_t *)inp;
657     uint8_t *out = outp;
658
659     for( size_t i = 0; i < samples; i++ )
660     {
661         uint32_t s = *(in++);
662         *(out++) = (s >> 24) + 0x80;
663         *(out++) = (s >> 16);
664         *(out++) = (s >>  8);
665     }
666 }
667
668 static void U24LEncode( void *outp, const uint8_t *inp, unsigned samples )
669 {
670     const uint32_t *in = (const uint32_t *)inp;
671     uint8_t *out = outp;
672
673     for( size_t i = 0; i < samples; i++ )
674     {
675         uint32_t s = *(in++);
676         *(out++) = (s >>  8);
677         *(out++) = (s >> 16);
678         *(out++) = (s >> 24) + 0x80;
679     }
680 }
681
682 static void S24BEncode( void *outp, const uint8_t *inp, unsigned samples )
683 {
684     const uint32_t *in = (const uint32_t *)inp;
685     uint8_t *out = outp;
686
687     for( size_t i = 0; i < samples; i++ )
688     {
689         uint32_t s = *(in++);
690         *(out++) = (s >> 24);
691         *(out++) = (s >> 16);
692         *(out++) = (s >>  8);
693     }
694 }
695
696 static void S24LEncode( void *outp, const uint8_t *inp, unsigned samples )
697 {
698     const uint32_t *in = (const uint32_t *)inp;
699     uint8_t *out = outp;
700
701     for( size_t i = 0; i < samples; i++ )
702     {
703         uint32_t s = *(in++);
704         *(out++) = (s >>  8);
705         *(out++) = (s >> 16);
706         *(out++) = (s >> 24);
707     }
708 }
709
710 static void U32IEncode( void *outp, const uint8_t *inp, unsigned samples )
711 {
712     const uint32_t *in = (const uint32_t *)inp;
713     uint32_t *out = outp;
714
715     for( size_t i = 0; i < samples; i++ )
716         *(out++) =  vlc_bswap32( *(in++) + 0x80000000 );
717 }
718
719 static void U32NEncode( void *outp, const uint8_t *inp, unsigned samples )
720 {
721     const uint32_t *in = (const uint32_t *)inp;
722     uint32_t *out = outp;
723
724     for( size_t i = 0; i < samples; i++ )
725         *(out++) =  *(in++) + 0x80000000;
726 }
727
728 static void S32IEncode( void *outp, const uint8_t *inp, unsigned samples )
729 {
730     const int32_t *in = (const int32_t *)inp;
731     int32_t *out = outp;
732
733     for( size_t i = 0; i < samples; i++ )
734         *(out++) = vlc_bswap32( *(in++) );
735 }
736
737 static void F32IEncode( void *outp, const uint8_t *inp, unsigned samples )
738 {
739     const float *in = (const float *)inp;
740     uint8_t *out = outp;
741
742     for( size_t i = 0; i < samples; i++ )
743     {
744         union { float f; uint32_t u; char b[4]; } s;
745
746         s.f = *(in++);
747         s.u = vlc_bswap32( s.u );
748         memcpy( out, s.b, 4 );
749         out += 4;
750     }
751 }
752
753 static void F64IEncode( void *outp, const uint8_t *inp, unsigned samples )
754 {
755     const double *in = (const double *)inp;
756     uint8_t *out = outp;
757
758     for( size_t i = 0; i < samples; i++ )
759     {
760         union { double d; uint64_t u; char b[8]; } s;
761
762         s.d = *(in++);
763         s.u = vlc_bswap64( s.u );
764         memcpy( out, s.b, 8 );
765         out += 8;
766     }
767 }
768
769 static block_t *Encode( encoder_t *enc, block_t *in )
770 {
771     if( in == NULL )
772         return NULL;
773
774     block_t *out = block_Alloc( in->i_nb_samples
775                                 * enc->fmt_out.audio.i_bytes_per_frame );
776     if( unlikely(out == NULL) )
777         return NULL;
778
779     out->i_flags      = in->i_flags;
780     out->i_nb_samples = in->i_nb_samples;
781     out->i_dts        = in->i_dts;
782     out->i_pts        = in->i_pts;
783     out->i_length     = in->i_length;
784
785     void (*encode)(void *, const uint8_t *, unsigned) = (void *)enc->p_sys;
786     if( encode != NULL )
787         encode( out->p_buffer, in->p_buffer, in->i_nb_samples
788                                              * enc->fmt_out.audio.i_channels );
789     else {
790         assert( out->i_buffer >= in->i_buffer );
791         memcpy( out->p_buffer, in->p_buffer, in->i_buffer );
792     }
793     return out;
794 }
795
796 /**
797  * Probes the PCM audio encoder.
798  */
799 static int EncoderOpen( vlc_object_t *p_this )
800 {
801     encoder_t *p_enc = (encoder_t *)p_this;
802     void (*encode)(void *, const uint8_t *, unsigned) = NULL;
803
804     switch( p_enc->fmt_out.i_codec )
805     {
806     case VLC_CODEC_S8:
807         encode = S8Decode;
808         /* fall through */
809     case VLC_CODEC_U8:
810         p_enc->fmt_in.i_codec = VLC_CODEC_U8;
811         p_enc->fmt_out.audio.i_bitspersample = 8;
812         break;
813     case VLC_CODEC_U16I:
814         encode = U16IEncode;
815         p_enc->fmt_in.i_codec = VLC_CODEC_S16N;
816         p_enc->fmt_out.audio.i_bitspersample = 16;
817         break;
818     case VLC_CODEC_U16N:
819         encode = U16NEncode;
820         p_enc->fmt_in.i_codec = VLC_CODEC_S16N;
821         p_enc->fmt_out.audio.i_bitspersample = 16;
822         break;
823     case VLC_CODEC_S16I:
824         encode = S16IDecode;
825         /* fall through */
826     case VLC_CODEC_S16N:
827         p_enc->fmt_in.i_codec = VLC_CODEC_S16N;
828         p_enc->fmt_out.audio.i_bitspersample = 16;
829         break;
830     case VLC_CODEC_U24B:
831         encode = U24BEncode;
832         p_enc->fmt_in.i_codec = VLC_CODEC_S32N;
833         p_enc->fmt_out.audio.i_bitspersample = 24;
834         break;
835     case VLC_CODEC_U24L:
836         encode = U24LEncode;
837         p_enc->fmt_in.i_codec = VLC_CODEC_S32N;
838         p_enc->fmt_out.audio.i_bitspersample = 24;
839         break;
840     case VLC_CODEC_S24B:
841         encode = S24BEncode;
842         p_enc->fmt_in.i_codec = VLC_CODEC_S32N;
843         p_enc->fmt_out.audio.i_bitspersample = 24;
844         break;
845     case VLC_CODEC_S24L:
846         encode = S24LEncode;
847         p_enc->fmt_in.i_codec = VLC_CODEC_S32N;
848         p_enc->fmt_out.audio.i_bitspersample = 24;
849         break;
850     case VLC_CODEC_U32I:
851         encode = U32IEncode;
852         p_enc->fmt_in.i_codec = VLC_CODEC_S32N;
853         p_enc->fmt_out.audio.i_bitspersample = 32;
854         break;
855     case VLC_CODEC_U32N:
856         encode = U32NEncode;
857         p_enc->fmt_in.i_codec = VLC_CODEC_S32N;
858         p_enc->fmt_out.audio.i_bitspersample = 32;
859         break;
860     case VLC_CODEC_S32I:
861         encode = S32IEncode;
862         /* fall through */
863     case VLC_CODEC_S32N:
864         p_enc->fmt_in.i_codec = VLC_CODEC_S32N;
865         p_enc->fmt_out.audio.i_bitspersample = 32;
866         break;
867 #ifdef WORDS_BIGENDIAN
868     case VLC_CODEC_F32L:
869 #else
870     case VLC_CODEC_F32B:
871 #endif
872         encode = F32IEncode;
873         /* fall through */
874     case VLC_CODEC_FL32:
875         p_enc->fmt_in.i_codec = VLC_CODEC_FL32;
876         p_enc->fmt_out.audio.i_bitspersample = 32;
877         break;
878 #ifdef WORDS_BIGENDIAN
879     case VLC_CODEC_F64L:
880 #else
881     case VLC_CODEC_F64B:
882 #endif
883         encode = F64IEncode;
884         /* fall through */
885     case VLC_CODEC_FL64:
886         p_enc->fmt_in.i_codec = VLC_CODEC_FL64;
887         p_enc->fmt_out.audio.i_bitspersample = 64;
888         break;
889     default:
890         return VLC_EGENERIC;
891     }
892
893     p_enc->p_sys = (void *)encode;
894     p_enc->pf_encode_audio = Encode;
895     p_enc->fmt_out.audio.i_bytes_per_frame =
896         (p_enc->fmt_out.audio.i_bitspersample / 8) *
897         p_enc->fmt_in.audio.i_channels;
898     p_enc->fmt_out.i_bitrate =
899         p_enc->fmt_in.audio.i_channels *
900         p_enc->fmt_in.audio.i_rate *
901         p_enc->fmt_out.audio.i_bitspersample;
902
903     msg_Dbg( p_enc, "samplerate:%dHz channels:%d bits/sample:%d",
904              p_enc->fmt_out.audio.i_rate, p_enc->fmt_out.audio.i_channels,
905              p_enc->fmt_out.audio.i_bitspersample );
906
907     return VLC_SUCCESS;
908 }
909 #endif /* ENABLE_SOUT */