Commit | Line | Data |
---|---|---|
cb21e0a7 | 1 | /* |
4477dedc | 2 | * 8SVX audio decoder |
cb21e0a7 JM |
3 | * Copyright (C) 2008 Jaikrishnan Menon |
4 | * | |
2912e87a | 5 | * This file is part of Libav. |
cb21e0a7 | 6 | * |
2912e87a | 7 | * Libav is free software; you can redistribute it and/or |
cb21e0a7 JM |
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 | * | |
2912e87a | 12 | * Libav is distributed in the hope that it will be useful, |
cb21e0a7 JM |
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 | |
2912e87a | 18 | * License along with Libav; if not, write to the Free Software |
cb21e0a7 JM |
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | */ | |
21 | ||
22 | /** | |
ba87f080 | 23 | * @file |
cb21e0a7 JM |
24 | * 8svx audio decoder |
25 | * @author Jaikrishnan Menon | |
ec679eb4 | 26 | * |
cb21e0a7 JM |
27 | * supports: fibonacci delta encoding |
28 | * : exponential encoding | |
29 | */ | |
30 | ||
31 | #include "avcodec.h" | |
32 | ||
1b41f260 | 33 | /** decoder context */ |
cb21e0a7 JM |
34 | typedef struct EightSvxContext { |
35 | int16_t fib_acc; | |
19998314 | 36 | const int16_t *table; |
cb21e0a7 JM |
37 | } EightSvxContext; |
38 | ||
6dbfb7de | 39 | static const int16_t fibonacci[16] = { -34<<8, -21<<8, -13<<8, -8<<8, -5<<8, -3<<8, -2<<8, -1<<8, |
cb21e0a7 | 40 | 0, 1<<8, 2<<8, 3<<8, 5<<8, 8<<8, 13<<8, 21<<8 }; |
6dbfb7de | 41 | static const int16_t exponential[16] = { -128<<8, -64<<8, -32<<8, -16<<8, -8<<8, -4<<8, -2<<8, -1<<8, |
cb21e0a7 JM |
42 | 0, 1<<8, 2<<8, 4<<8, 8<<8, 16<<8, 32<<8, 64<<8 }; |
43 | ||
ac68607b JR |
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 | ||
1b41f260 | 66 | /** decode a frame */ |
cb21e0a7 | 67 | static int eightsvx_decode_frame(AVCodecContext *avctx, void *data, int *data_size, |
7a00bbad | 68 | AVPacket *avpkt) |
cb21e0a7 | 69 | { |
7a00bbad TB |
70 | const uint8_t *buf = avpkt->data; |
71 | int buf_size = avpkt->size; | |
cb21e0a7 JM |
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 | ||
ac68607b | 88 | delta_decode(out_data, buf, buf_size, &esc->fib_acc, esc->table); |
cb21e0a7 JM |
89 | |
90 | return consumed; | |
91 | } | |
92 | ||
1b41f260 | 93 | /** initialize 8svx decoder */ |
cb21e0a7 JM |
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 | } | |
5d6e4c16 | 108 | avctx->sample_fmt = AV_SAMPLE_FMT_S16; |
cb21e0a7 JM |
109 | return 0; |
110 | } | |
111 | ||
d36beb3f | 112 | AVCodec ff_eightsvx_fib_decoder = { |
99e3913d | 113 | .name = "8svx_fib", |
72415b2a | 114 | .type = AVMEDIA_TYPE_AUDIO, |
cb21e0a7 JM |
115 | .id = CODEC_ID_8SVX_FIB, |
116 | .priv_data_size = sizeof (EightSvxContext), | |
117 | .init = eightsvx_decode_init, | |
118 | .decode = eightsvx_decode_frame, | |
fe4bf374 | 119 | .long_name = NULL_IF_CONFIG_SMALL("8SVX fibonacci"), |
cb21e0a7 JM |
120 | }; |
121 | ||
d36beb3f | 122 | AVCodec ff_eightsvx_exp_decoder = { |
99e3913d | 123 | .name = "8svx_exp", |
72415b2a | 124 | .type = AVMEDIA_TYPE_AUDIO, |
cb21e0a7 JM |
125 | .id = CODEC_ID_8SVX_EXP, |
126 | .priv_data_size = sizeof (EightSvxContext), | |
127 | .init = eightsvx_decode_init, | |
128 | .decode = eightsvx_decode_frame, | |
fe4bf374 | 129 | .long_name = NULL_IF_CONFIG_SMALL("8SVX exponential"), |
cb21e0a7 | 130 | }; |