3 * Copyright (c) 2001 Fabrice Bellard.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 /* from g711.c by SUN microsystems (unrestricted use) */
29 #define SIGN_BIT (0x80) /* Sign bit for a A-law byte. */
30 #define QUANT_MASK (0xf) /* Quantization field mask. */
31 #define NSEGS (8) /* Number of A-law segments. */
32 #define SEG_SHIFT (4) /* Left shift for segment number. */
33 #define SEG_MASK (0x70) /* Segment field mask. */
35 #define BIAS (0x84) /* Bias for linear code. */
38 * alaw2linear() - Convert an A-law value to 16-bit linear PCM
41 static int alaw2linear(unsigned char a_val
)
48 t
= a_val
& QUANT_MASK
;
49 seg
= ((unsigned)a_val
& SEG_MASK
) >> SEG_SHIFT
;
50 if(seg
) t
= (t
+ t
+ 1 + 32) << (seg
+ 2);
51 else t
= (t
+ t
+ 1 ) << 3;
53 return ((a_val
& SIGN_BIT
) ? t
: -t
);
56 static int ulaw2linear(unsigned char u_val
)
60 /* Complement to obtain normal u-law value. */
64 * Extract and bias the quantization bits. Then
65 * shift up by the segment number and subtract out the bias.
67 t
= ((u_val
& QUANT_MASK
) << 3) + BIAS
;
68 t
<<= ((unsigned)u_val
& SEG_MASK
) >> SEG_SHIFT
;
70 return ((u_val
& SIGN_BIT
) ? (BIAS
- t
) : (t
- BIAS
));
73 /* 16384 entries per table */
74 static uint8_t *linear_to_alaw
= NULL
;
75 static int linear_to_alaw_ref
= 0;
77 static uint8_t *linear_to_ulaw
= NULL
;
78 static int linear_to_ulaw_ref
= 0;
80 static void build_xlaw_table(uint8_t *linear_to_xlaw
,
81 int (*xlaw2linear
)(unsigned char),
89 v1
= xlaw2linear(i
^ mask
);
90 v2
= xlaw2linear((i
+ 1) ^ mask
);
91 v
= (v1
+ v2
+ 4) >> 3;
96 linear_to_xlaw
[8192 + j
] = (i
^ mask
);
98 linear_to_xlaw
[8192 - j
] = (i
^ (mask
^ 0x80));
101 linear_to_xlaw
[0] = linear_to_xlaw
[1];
104 static int pcm_encode_init(AVCodecContext
*avctx
)
106 avctx
->frame_size
= 1;
107 switch(avctx
->codec
->id
) {
108 case CODEC_ID_PCM_ALAW
:
109 if (linear_to_alaw_ref
== 0) {
110 linear_to_alaw
= av_malloc(16384);
113 build_xlaw_table(linear_to_alaw
, alaw2linear
, 0xd5);
115 linear_to_alaw_ref
++;
117 case CODEC_ID_PCM_MULAW
:
118 if (linear_to_ulaw_ref
== 0) {
119 linear_to_ulaw
= av_malloc(16384);
122 build_xlaw_table(linear_to_ulaw
, ulaw2linear
, 0xff);
124 linear_to_ulaw_ref
++;
130 switch(avctx
->codec
->id
) {
131 case CODEC_ID_PCM_S16LE
:
132 case CODEC_ID_PCM_S16BE
:
133 case CODEC_ID_PCM_U16LE
:
134 case CODEC_ID_PCM_U16BE
:
135 avctx
->block_align
= 2 * avctx
->channels
;
137 case CODEC_ID_PCM_S8
:
138 case CODEC_ID_PCM_U8
:
139 case CODEC_ID_PCM_MULAW
:
140 case CODEC_ID_PCM_ALAW
:
141 avctx
->block_align
= avctx
->channels
;
147 avctx
->coded_frame
= avcodec_alloc_frame();
148 avctx
->coded_frame
->key_frame
= 1;
153 static int pcm_encode_close(AVCodecContext
*avctx
)
155 av_freep(&avctx
->coded_frame
);
157 switch(avctx
->codec
->id
) {
158 case CODEC_ID_PCM_ALAW
:
159 if (--linear_to_alaw_ref
== 0)
160 av_free(linear_to_alaw
);
162 case CODEC_ID_PCM_MULAW
:
163 if (--linear_to_ulaw_ref
== 0)
164 av_free(linear_to_ulaw
);
167 /* nothing to free */
173 static int pcm_encode_frame(AVCodecContext
*avctx
,
174 unsigned char *frame
, int buf_size
, void *data
)
176 int n
, sample_size
, v
;
180 switch(avctx
->codec
->id
) {
181 case CODEC_ID_PCM_S16LE
:
182 case CODEC_ID_PCM_S16BE
:
183 case CODEC_ID_PCM_U16LE
:
184 case CODEC_ID_PCM_U16BE
:
191 n
= buf_size
/ sample_size
;
195 switch(avctx
->codec
->id
) {
196 case CODEC_ID_PCM_S16LE
:
204 case CODEC_ID_PCM_S16BE
:
212 case CODEC_ID_PCM_U16LE
:
221 case CODEC_ID_PCM_U16BE
:
230 case CODEC_ID_PCM_S8
:
237 case CODEC_ID_PCM_U8
:
240 dst
[0] = (v
>> 8) + 128;
244 case CODEC_ID_PCM_ALAW
:
247 dst
[0] = linear_to_alaw
[(v
+ 32768) >> 2];
251 case CODEC_ID_PCM_MULAW
:
254 dst
[0] = linear_to_ulaw
[(v
+ 32768) >> 2];
261 //avctx->frame_size = (dst - frame) / (sample_size * avctx->channels);
266 typedef struct PCMDecode
{
270 static int pcm_decode_init(AVCodecContext
* avctx
)
272 PCMDecode
*s
= avctx
->priv_data
;
275 switch(avctx
->codec
->id
) {
276 case CODEC_ID_PCM_ALAW
:
278 s
->table
[i
] = alaw2linear(i
);
280 case CODEC_ID_PCM_MULAW
:
282 s
->table
[i
] = ulaw2linear(i
);
290 static int pcm_decode_frame(AVCodecContext
*avctx
,
291 void *data
, int *data_size
,
292 uint8_t *buf
, int buf_size
)
294 PCMDecode
*s
= avctx
->priv_data
;
302 if(buf_size
> AVCODEC_MAX_AUDIO_FRAME_SIZE
/2)
303 buf_size
= AVCODEC_MAX_AUDIO_FRAME_SIZE
/2;
305 switch(avctx
->codec
->id
) {
306 case CODEC_ID_PCM_S16LE
:
309 *samples
++ = src
[0] | (src
[1] << 8);
313 case CODEC_ID_PCM_S16BE
:
316 *samples
++ = (src
[0] << 8) | src
[1];
320 case CODEC_ID_PCM_U16LE
:
323 *samples
++ = (src
[0] | (src
[1] << 8)) - 0x8000;
327 case CODEC_ID_PCM_U16BE
:
330 *samples
++ = ((src
[0] << 8) | src
[1]) - 0x8000;
334 case CODEC_ID_PCM_S8
:
337 *samples
++ = src
[0] << 8;
341 case CODEC_ID_PCM_U8
:
344 *samples
++ = ((int)src
[0] - 128) << 8;
348 case CODEC_ID_PCM_ALAW
:
349 case CODEC_ID_PCM_MULAW
:
352 *samples
++ = s
->table
[src
[0]];
359 *data_size
= (uint8_t *)samples
- (uint8_t *)data
;
363 #define PCM_CODEC(id, name) \
364 AVCodec name ## _encoder = { \
374 AVCodec name ## _decoder = { \
385 PCM_CODEC(CODEC_ID_PCM_S16LE
, pcm_s16le
);
386 PCM_CODEC(CODEC_ID_PCM_S16BE
, pcm_s16be
);
387 PCM_CODEC(CODEC_ID_PCM_U16LE
, pcm_u16le
);
388 PCM_CODEC(CODEC_ID_PCM_U16BE
, pcm_u16be
);
389 PCM_CODEC(CODEC_ID_PCM_S8
, pcm_s8
);
390 PCM_CODEC(CODEC_ID_PCM_U8
, pcm_u8
);
391 PCM_CODEC(CODEC_ID_PCM_ALAW
, pcm_alaw
);
392 PCM_CODEC(CODEC_ID_PCM_MULAW
, pcm_mulaw
);