Imported Upstream version 3.0
[debian/gnuradio] / gnuradio-core / src / lib / g72x / decode.c
1 /*
2  * decode.c
3  *
4  * CCITT ADPCM decoder
5  *
6  * Usage : decode [-3|4|5] [-a|u|l] < infile > outfile
7  */
8 #include <stdio.h>
9 #include "g72x.h"
10
11
12 /*
13  * Unpack input codes and pass them back as bytes.
14  * Returns 1 if there is residual input, returns -1 if eof, else returns 0.
15  */
16 int
17 unpack_input(
18         unsigned char           *code,
19         int                     bits)
20 {
21         static unsigned int     in_buffer = 0;
22         static int              in_bits = 0;
23         unsigned char           in_byte;
24
25         if (in_bits < bits) {
26                 if (fread(&in_byte, sizeof (char), 1, stdin) != 1) {
27                         *code = 0;
28                         return (-1);
29                 }
30                 in_buffer |= (in_byte << in_bits);
31                 in_bits += 8;
32         }
33         *code = in_buffer & ((1 << bits) - 1);
34         in_buffer >>= bits;
35         in_bits -= bits;
36         return (in_bits > 0);
37 }
38
39
40 main(
41         int                     argc,
42         char                    **argv)
43 {
44         short                   sample;
45         unsigned char           code;
46         int                     n;
47         struct g72x_state       state;
48         int                     out_coding;
49         int                     out_size;
50         int                     (*dec_routine)();
51         int                     dec_bits;
52
53         g72x_init_state(&state);
54         out_coding = AUDIO_ENCODING_ULAW;
55         out_size = sizeof (char);
56         dec_routine = g721_decoder;
57         dec_bits = 4;
58
59         /* Process encoding argument, if any */
60         while ((argc > 1) && (argv[1][0] == '-')) {
61                 switch (argv[1][1]) {
62                 case '3':
63                         dec_routine = g723_24_decoder;
64                         dec_bits = 3;
65                         break;
66                 case '4':
67                         dec_routine = g721_decoder;
68                         dec_bits = 4;
69                         break;
70                 case '5':
71                         dec_routine = g723_40_decoder;
72                         dec_bits = 5;
73                         break;
74                 case 'u':
75                         out_coding = AUDIO_ENCODING_ULAW;
76                         out_size = sizeof (char);
77                         break;
78                 case 'a':
79                         out_coding = AUDIO_ENCODING_ALAW;
80                         out_size = sizeof (char);
81                         break;
82                 case 'l':
83                         out_coding = AUDIO_ENCODING_LINEAR;
84                         out_size = sizeof (short);
85                         break;
86                 default:
87 fprintf(stderr, "CCITT ADPCM Decoder -- usage:\n");
88 fprintf(stderr, "\tdecode [-3|4|5] [-a|u|l] < infile > outfile\n");
89 fprintf(stderr, "where:\n");
90 fprintf(stderr, "\t-3\tProcess G.723 24kbps (3-bit) input data\n");
91 fprintf(stderr, "\t-4\tProcess G.721 32kbps (4-bit) input data [default]\n");
92 fprintf(stderr, "\t-5\tProcess G.723 40kbps (5-bit) input data\n");
93 fprintf(stderr, "\t-a\tGenerate 8-bit A-law data\n");
94 fprintf(stderr, "\t-u\tGenerate 8-bit u-law data [default]\n");
95 fprintf(stderr, "\t-l\tGenerate 16-bit linear PCM data\n");
96                         exit(1);
97                 }
98                 argc--;
99                 argv++;
100         }
101
102         /* Read and unpack input codes and process them */
103         while (unpack_input(&code, dec_bits) >= 0) {
104                 sample = (*dec_routine)(code, out_coding, &state);
105                 if (out_size == 2) {
106                         fwrite(&sample, out_size, 1, stdout);
107                 } else {
108                         code = (unsigned char)sample;
109                         fwrite(&code, out_size, 1, stdout);
110                 }
111         }
112         fclose(stdout);
113 }