]> git.sesse.net Git - ffmpeg/blob - libavcodec/8svx.c
8svx: split delta decoding into a separate function.
[ffmpeg] / libavcodec / 8svx.c
1 /*
2  * 8SVX audio decoder
3  * Copyright (C) 2008 Jaikrishnan Menon
4  *
5  * This file is part of Libav.
6  *
7  * Libav is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * Libav is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with Libav; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22 /**
23  * @file
24  * 8svx audio decoder
25  * @author Jaikrishnan Menon
26  *
27  * supports: fibonacci delta encoding
28  *         : exponential encoding
29  */
30
31 #include "avcodec.h"
32
33 /** decoder context */
34 typedef struct EightSvxContext {
35     int16_t fib_acc;
36     const int16_t *table;
37 } EightSvxContext;
38
39 static const int16_t fibonacci[16]   = { -34<<8, -21<<8, -13<<8,  -8<<8, -5<<8, -3<<8, -2<<8, -1<<8,
40                                           0, 1<<8, 2<<8, 3<<8, 5<<8, 8<<8, 13<<8, 21<<8 };
41 static const int16_t exponential[16] = { -128<<8, -64<<8, -32<<8, -16<<8, -8<<8, -4<<8, -2<<8, -1<<8,
42                                           0, 1<<8, 2<<8, 4<<8, 8<<8, 16<<8, 32<<8, 64<<8 };
43
44 /**
45  * Delta decode the compressed values in src, and put the resulting
46  * decoded samples in dst.
47  *
48  * @param[in,out] state starting value. it is saved for use in the next call.
49  */
50 static void delta_decode(int16_t *dst, const uint8_t *src, int src_size,
51                          int16_t *state, const int16_t *table)
52 {
53     int val = *state;
54
55     while (src_size--) {
56         uint8_t d = *src++;
57         val = av_clip_int16(val + table[d & 0xF]);
58         *dst++ = val;
59         val = av_clip_int16(val + table[d >> 4]);
60         *dst++ = val;
61     }
62
63     *state = val;
64 }
65
66 /** decode a frame */
67 static int eightsvx_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
68                                  AVPacket *avpkt)
69 {
70     const uint8_t *buf = avpkt->data;
71     int buf_size = avpkt->size;
72     EightSvxContext *esc = avctx->priv_data;
73     int16_t *out_data = data;
74     int consumed = buf_size;
75     const uint8_t *buf_end = buf + buf_size;
76
77     if((*data_size >> 2) < buf_size)
78         return -1;
79
80     if(avctx->frame_number == 0) {
81         esc->fib_acc = buf[1] << 8;
82         buf_size -= 2;
83         buf += 2;
84     }
85
86     *data_size = buf_size << 2;
87
88     delta_decode(out_data, buf, buf_size, &esc->fib_acc, esc->table);
89
90     return consumed;
91 }
92
93 /** initialize 8svx decoder */
94 static av_cold int eightsvx_decode_init(AVCodecContext *avctx)
95 {
96     EightSvxContext *esc = avctx->priv_data;
97
98     switch(avctx->codec->id) {
99         case CODEC_ID_8SVX_FIB:
100           esc->table = fibonacci;
101           break;
102         case CODEC_ID_8SVX_EXP:
103           esc->table = exponential;
104           break;
105         default:
106           return -1;
107     }
108     avctx->sample_fmt = AV_SAMPLE_FMT_S16;
109     return 0;
110 }
111
112 AVCodec ff_eightsvx_fib_decoder = {
113   .name           = "8svx_fib",
114   .type           = AVMEDIA_TYPE_AUDIO,
115   .id             = CODEC_ID_8SVX_FIB,
116   .priv_data_size = sizeof (EightSvxContext),
117   .init           = eightsvx_decode_init,
118   .decode         = eightsvx_decode_frame,
119   .long_name      = NULL_IF_CONFIG_SMALL("8SVX fibonacci"),
120 };
121
122 AVCodec ff_eightsvx_exp_decoder = {
123   .name           = "8svx_exp",
124   .type           = AVMEDIA_TYPE_AUDIO,
125   .id             = CODEC_ID_8SVX_EXP,
126   .priv_data_size = sizeof (EightSvxContext),
127   .init           = eightsvx_decode_init,
128   .decode         = eightsvx_decode_frame,
129   .long_name      = NULL_IF_CONFIG_SMALL("8SVX exponential"),
130 };