summaryrefslogtreecommitdiffstats
path: root/libmediafork/declpcm.c
blob: 718cf559d7379e61955bd3da1bae78866895de8c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/* $Id: declpcm.c,v 1.8 2005/11/04 14:44:01 titer Exp $

   This file is part of the HandBrake source code.
   Homepage: <http://handbrake.m0k.org/>.
   It may be used under the terms of the GNU General Public License. */

#include "mediafork.h"

int  declpcmInit( hb_work_object_t *, hb_job_t * );
int  declpcmWork( hb_work_object_t *, hb_buffer_t **, hb_buffer_t ** );
void declpcmClose( hb_work_object_t * );

hb_work_object_t hb_declpcm =
{   
    WORK_DECLPCM,
    "LPCM decoder",
    declpcmInit,
    declpcmWork,
    declpcmClose
};

int declpcmInit( hb_work_object_t * w, hb_job_t * job )
{
    return 0;
}

int declpcmWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
                 hb_buffer_t ** buf_out )
{
    hb_buffer_t * in = *buf_in, * out;
    int samplerate = 0;
    int count;
    uint8_t * samples_u8;
    float   * samples_fl32;
    int i;
    uint64_t duration;

    *buf_out = NULL;

    if( in->data[5] != 0x80 )
    {
        hb_log( "no LPCM frame sync (%02x)", in->data[5] );
        return HB_WORK_OK;
    }

    switch( ( in->data[4] >> 4 ) & 0x3 )
    {
        case 0:
            samplerate = 48000;
            break;
        case 1:
            samplerate = 96000;//32000; /* FIXME vlc says it is 96000 */
            break;
        case 2:
            samplerate = 44100;
            break;
        case 3:
            samplerate = 32000;
            break;
    }

    count       = ( in->size - 6 ) / 2;
    out         = hb_buffer_init( count * sizeof( float ) );
    duration    = count * 90000 / samplerate / 2;
    out->start  = in->start;
    out->stop   = out->start + duration;

    samples_u8   = in->data + 6;
    samples_fl32 = (float *) out->data;

    /* Big endian int16 -> float conversion */
    for( i = 0; i < count; i++ )
    {
#ifdef WORDS_BIGENDIAN
        samples_fl32[0] = *( (int16_t *) samples_u8 );
#else
        samples_fl32[0] = (int16_t) ( ( samples_u8[0] << 8 ) | samples_u8[1] );
#endif
        samples_u8   += 2;
        samples_fl32 += 1;
    }

    *buf_out = out;

    return HB_WORK_OK;
}

void declpcmClose( hb_work_object_t * w )
{
}