Revision d08d7142 libavcodec/dpcm.c

View differences:

libavcodec/dpcm.c
24 24
 * Xan DPCM decoder by Mario Brito (mbrito@student.dei.uc.pt)
25 25
 * for more information on the specific data formats, visit:
26 26
 *   http://www.pcisys.net/~melanson/codecs/simpleaudio.html
27
 * SOL DPCMs implemented by Konstantin Shishkov
27 28
 *
28 29
 * Note about using the Xan DPCM decoder: Xan DPCM is used in AVI files
29 30
 * found in the Wing Commander IV computer game. These AVI files contain
......
39 40
typedef struct DPCMContext {
40 41
    int channels;
41 42
    short roq_square_array[256];
43
    long sample[2];//for SOL_DPCM
44
    int *sol_table;//for SOL_DPCM
42 45
} DPCMContext;
43 46

  
44 47
#define SATURATE_S16(x)  if (x < -32768) x = -32768; \
......
81 84

  
82 85
};
83 86

  
87
static int sol_table_old[16] =
88
    { 0x0,  0x1,  0x2 , 0x3,  0x6,  0xA,  0xF, 0x15,
89
    -0x15, -0xF, -0xA, -0x6, -0x3, -0x2, -0x1, 0x0};
90

  
91
static int sol_table_new[16] =
92
    { 0x0,  0x1,  0x2,  0x3,  0x6,  0xA,  0xF,  0x15,
93
      0x0, -0x1, -0x2, -0x3, -0x6, -0xA, -0xF, -0x15};
94
    
95
static int sol_table_16[128] = {
96
    0x000, 0x008, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070, 0x080,
97
    0x090, 0x0A0, 0x0B0, 0x0C0, 0x0D0, 0x0E0, 0x0F0, 0x100, 0x110, 0x120,
98
    0x130, 0x140, 0x150, 0x160, 0x170, 0x180, 0x190, 0x1A0, 0x1B0, 0x1C0,
99
    0x1D0, 0x1E0, 0x1F0, 0x200, 0x208, 0x210, 0x218, 0x220, 0x228, 0x230,
100
    0x238, 0x240, 0x248, 0x250, 0x258, 0x260, 0x268, 0x270, 0x278, 0x280,
101
    0x288, 0x290, 0x298, 0x2A0, 0x2A8, 0x2B0, 0x2B8, 0x2C0, 0x2C8, 0x2D0,
102
    0x2D8, 0x2E0, 0x2E8, 0x2F0, 0x2F8, 0x300, 0x308, 0x310, 0x318, 0x320,
103
    0x328, 0x330, 0x338, 0x340, 0x348, 0x350, 0x358, 0x360, 0x368, 0x370,
104
    0x378, 0x380, 0x388, 0x390, 0x398, 0x3A0, 0x3A8, 0x3B0, 0x3B8, 0x3C0,
105
    0x3C8, 0x3D0, 0x3D8, 0x3E0, 0x3E8, 0x3F0, 0x3F8, 0x400, 0x440, 0x480,
106
    0x4C0, 0x500, 0x540, 0x580, 0x5C0, 0x600, 0x640, 0x680, 0x6C0, 0x700,
107
    0x740, 0x780, 0x7C0, 0x800, 0x900, 0xA00, 0xB00, 0xC00, 0xD00, 0xE00,
108
    0xF00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000
109
};
110

  
111

  
112

  
84 113
static int dpcm_decode_init(AVCodecContext *avctx)
85 114
{
86 115
    DPCMContext *s = avctx->priv_data;
......
88 117
    short square;
89 118

  
90 119
    s->channels = avctx->channels;
120
    s->sample[0] = s->sample[1] = 0;
91 121

  
92 122
    switch(avctx->codec->id) {
93 123

  
......
100 130
        }
101 131
        break;
102 132

  
133
        
134
    case CODEC_ID_SOL_DPCM:
135
        switch(avctx->codec_tag){
136
        case 1:
137
            s->sol_table=sol_table_old;
138
            s->sample[0] = s->sample[1] = 0x80;
139
            break;
140
        case 2:
141
            s->sol_table=sol_table_new;
142
            s->sample[0] = s->sample[1] = 0x80;
143
            break;
144
        case 3:
145
            s->sol_table=sol_table_16;
146
            break;
147
        default:
148
            av_log(avctx, AV_LOG_ERROR, "Unknown SOL subcodec\n");
149
            return -1;
150
        }
151
        break;
152
     
103 153
    default:
104 154
        break;
105 155
    }
......
203 253
            channel_number ^= s->channels - 1;
204 254
        }
205 255
        break;
256
    case CODEC_ID_SOL_DPCM:
257
        in = 0;
258
        if (avctx->codec_tag != 3) {
259
            while (in < buf_size) {
260
                int n1, n2;
261
                n1 = (buf[in] >> 4) & 0xF;
262
                n2 = buf[in++] & 0xF;
263
                s->sample[0] += s->sol_table[n1];
264
                 if (s->sample[0] < 0) s->sample[0] = 0;
265
                if (s->sample[0] > 255) s->sample[0] = 255;
266
                output_samples[out++] = (s->sample[0] - 128) << 8;
267
                s->sample[s->channels - 1] += s->sol_table[n2];
268
                if (s->sample[s->channels - 1] < 0) s->sample[s->channels - 1] = 0;
269
                if (s->sample[s->channels - 1] > 255) s->sample[s->channels - 1] = 255;
270
                output_samples[out++] = (s->sample[s->channels - 1] - 128) << 8;
271
            }
272
        } else {
273
            while (in < buf_size) {
274
                int n;
275
                n = buf[in++];
276
                if (n & 0x80) s->sample[channel_number] -= s->sol_table[n & 0x7F];
277
                else s->sample[channel_number] += s->sol_table[n & 0x7F];
278
                SATURATE_S16(s->sample[channel_number]);
279
                output_samples[out++] = s->sample[channel_number];
280
                /* toggle channel */
281
                channel_number ^= s->channels - 1;
282
            }
283
        }
284
        break;
206 285
    }
207 286

  
208 287
    *data_size = out * sizeof(short);
......
241 320
    NULL,
242 321
    dpcm_decode_frame,
243 322
};
323

  
324
AVCodec sol_dpcm_decoder = {
325
    "sol_dpcm",
326
    CODEC_TYPE_AUDIO,
327
    CODEC_ID_SOL_DPCM,
328
    sizeof(DPCMContext),
329
    dpcm_decode_init,
330
    NULL,
331
    NULL,
332
    dpcm_decode_frame,
333
};

Also available in: Unified diff