Algorithms_in_C 1.0.0
Set of algorithms implemented in C.
Loading...
Searching...
No Matches
alaw.c File Reference

A-law algorithm for encoding and decoding (16bit pcm <=> a-law). This is the implementation of G.711 in C. More...

#include <assert.h>
#include <inttypes.h>
#include <stdio.h>
Include dependency graph for alaw.c:

Macros

#define LEN   ((size_t)8)
 Linear input code | Compressed code | Linear output code ---------------—+--------------—+----------------— s0000000abcdx | s000abcd | s0000000abcd1 s0000001abcdx | s001abcd | s0000001abcd1 s000001abcdxx | s010abcd | s000001abcd10 s00001abcdxxx | s011abcd | s00001abcd100 s0001abcdxxxx | s100abcd | s0001abcd1000 s001abcdxxxxx | s101abcd | s001abcd10000 s01abcdxxxxxx | s110abcd | s01abcd100000 s1abcdxxxxxxx | s111abcd | s1abcd1000000. More...
 

Functions

void encode (uint8_t *out, int16_t *in, size_t len)
 16bit pcm to 8bit alaw More...
 
void decode (int16_t *out, uint8_t *in, size_t len)
 8bit alaw to 16bit pcm More...
 
static void test (int16_t *pcm, uint8_t *coded, int16_t *decoded, size_t len)
 Self-test implementations. More...
 
int main (int argc, char *argv[])
 Main function. More...
 

Variables

int16_t pcm [LEN] = {1000, -1000, 1234, 3200, -1314, 0, 32767, -32768}
 
uint8_t r_coded [LEN] = {250, 122, 230, 156, 97, 213, 170, 42}
 
int16_t r_decoded [LEN] = {1008, -1008, 1248, 3264, -1312, 8, 32256, -32256}
 

Detailed Description

A-law algorithm for encoding and decoding (16bit pcm <=> a-law). This is the implementation of G.711 in C.

Author
sunzhenliang

Macro Definition Documentation

◆ LEN

#define LEN   ((size_t)8)

Linear input code | Compressed code | Linear output code ---------------—+--------------—+----------------— s0000000abcdx | s000abcd | s0000000abcd1 s0000001abcdx | s001abcd | s0000001abcd1 s000001abcdxx | s010abcd | s000001abcd10 s00001abcdxxx | s011abcd | s00001abcd100 s0001abcdxxxx | s100abcd | s0001abcd1000 s001abcdxxxxx | s101abcd | s001abcd10000 s01abcdxxxxxx | s110abcd | s01abcd100000 s1abcdxxxxxxx | s111abcd | s1abcd1000000.

Compressed code: (s | eee | abcd) for assert for appropriate size int types for IO operations

Function Documentation

◆ decode()

void decode ( int16_t *  out,
uint8_t *  in,
size_t  len 
)

8bit alaw to 16bit pcm

Parameters
outsigned 16bit pcm array
inunsigned 8bit alaw array
lenlength of alaw array
Returns
void
108{
109 uint8_t alaw = 0;
110 int32_t pcm = 0;
111 int32_t sign = 0;
112 int32_t eee = 0;
113 for (size_t i = 0; i < len; i++)
114 {
115 alaw = *in++;
116
117 /* Re-toggle toggled bits */
118 alaw ^= 0xD5;
119
120 /* Get sign bit */
121 sign = alaw & 0x80;
122
123 /* Get eee bits */
124 eee = (alaw & 0x70) >> 4;
125
126 /* Get abcd bits and add 1/2 quantization step */
127 pcm = (alaw & 0x0f) << 4 | 8;
128
129 /* If quantization level > 0, there need `1` bit before abcd bits */
130 pcm += eee ? 0x100 : 0x0;
131
132 /* Left shift according quantization level */
133 pcm <<= eee > 1 ? (eee - 1) : 0;
134
135 /* Use the right sign */
136 *out++ = sign ? -pcm : pcm;
137 }
138}

◆ encode()

void encode ( uint8_t *  out,
int16_t *  in,
size_t  len 
)

16bit pcm to 8bit alaw

Parameters
outunsigned 8bit alaw array
insigned 16bit pcm array
lenlength of pcm array
Returns
void
47{
48 uint8_t alaw = 0;
49 int16_t pcm = 0;
50 int32_t sign = 0;
51 int32_t abcd = 0;
52 int32_t eee = 0;
53 int32_t mask = 0;
54 for (size_t i = 0; i < len; i++)
55 {
56 pcm = *in++;
57 /* 0-7 kinds of quantization level from the table above */
58 eee = 7;
59 mask = 0x4000; /* 0x4000: '0b0100 0000 0000 0000' */
60
61 /* Get sign bit */
62 sign = (pcm & 0x8000) >> 8;
63
64 /* Turn negative pcm to positive */
65 /* The absolute value of a negative number may be larger than the size
66 * of the corresponding positive number, so here needs `-pcm -1` after
67 * taking the opposite number. */
68 pcm = sign ? (-pcm - 1) : pcm;
69
70 /* Get eee and abcd bit */
71 /* Use mask to locate the first `1` bit and quantization level at the
72 * same time */
73 while ((pcm & mask) == 0 && eee > 0)
74 {
75 eee--;
76 mask >>= 1;
77 }
78
79 /* The location of abcd bits is related with quantization level. Check
80 * the table above to determine how many bits to `>>` to get abcd */
81 abcd = (pcm >> (eee ? (eee + 3) : 4)) & 0x0f;
82
83 /* Put the quantization level number at right bit location to get eee
84 * bits */
85 eee <<= 4;
86
87 /* Splice results */
88 alaw = (sign | eee | abcd);
89
90 /* The standard specifies that all resulting even bits (LSB
91 * is even) are inverted before the octet is transmitted. This is to
92 * provide plenty of 0/1 transitions to facilitate the clock recovery
93 * process in the PCM receivers. Thus, a silent A-law encoded PCM
94 * channel has the 8 bit samples coded 0xD5 instead of 0x80 in the
95 * octets. (Reference from wiki above) */
96 *out++ = alaw ^ 0xD5;
97 }
98}

◆ main()

int main ( int  argc,
char *  argv[] 
)

Main function.

Parameters
argccommandline argument count (ignored)
argvcommandline array of arguments (ignored)
Returns
0 on exit
176{
177 /* output alaw encoded by encode() */
178 uint8_t coded[LEN];
179
180 /* output pcm decoded by decode() from coded[LEN] */
181 int16_t decoded[LEN];
182
183 test(pcm, coded, decoded, LEN); // run self-test implementations
184
185 /* print test pcm inputs */
186 printf("inputs: ");
187 for (size_t i = 0; i < LEN; i++)
188 {
189 printf("%d ", pcm[i]);
190 }
191 printf("\n");
192
193 /* print encoded alaw */
194 printf("encode: ");
195 for (size_t i = 0; i < LEN; i++)
196 {
197 printf("%u ", coded[i]);
198 }
199 printf("\n");
200
201 /* print decoded pcm */
202 printf("decode: ");
203 for (size_t i = 0; i < LEN; i++)
204 {
205 printf("%d ", decoded[i]);
206 }
207 printf("\n");
208
209 /* It can be seen that the encoded alaw is smaller than the input PCM, so
210 * the purpose of compression is achieved. And the decoded PCM is almost the
211 * same as the original input PCM, which verifies the correctness of the
212 * decoding. The reason why it is not exactly the same is that there is
213 * precision loss during encode / decode. */
214
215 return 0;
216}
#define LEN
Linear input code | Compressed code | Linear output code ---------------—+--------------—+-----------...
Definition: alaw.c:28
static void test()
Self-test implementations.
Definition: decimal_to_any_base.c:94
Here is the call graph for this function:

◆ test()

static void test ( int16_t *  pcm,
uint8_t *  coded,
int16_t *  decoded,
size_t  len 
)
static

Self-test implementations.

Parameters
pcmsigned 16bit pcm array
codedunsigned 8bit alaw array
decodedsigned 16bit pcm array
lenlength of test array
Returns
void
149{
150 /* run encode */
151 encode(coded, pcm, len);
152
153 /* check encode result */
154 for (size_t i = 0; i < len; i++)
155 {
156 assert(coded[i] == r_coded[i]);
157 }
158
159 /* run decode */
160 decode(decoded, coded, len);
161
162 /* check decode result */
163 for (size_t i = 0; i < len; i++)
164 {
165 assert(decoded[i] == r_decoded[i]);
166 }
167}
void decode(int16_t *out, uint8_t *in, size_t len)
8bit alaw to 16bit pcm
Definition: alaw.c:107
void encode(uint8_t *out, int16_t *in, size_t len)
16bit pcm to 8bit alaw
Definition: alaw.c:46
Here is the call graph for this function: