1 /*---------------------------------------------------------------------------*\
2
3 FILE........: generate_codebook.c
4 AUTHOR......: Bruce Perens
5 DATE CREATED: 29 Sep 2010
6
7 Generate header files containing quantisers, runs at compile time.
8
9 \*---------------------------------------------------------------------------*/
10
11 /*
12 All rights reserved.
13
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU Lesser General Public License version 2.1, as
16 published by the Free Software Foundation. This program is
17 distributed in the hope that it will be useful, but WITHOUT ANY
18 WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
20 License for more details.
21
22 You should have received a copy of the GNU Lesser General Public License
23 along with this program; if not, see <http://www.gnu.org/licenses/>.
24 */
25
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <ctype.h>
29 #include <math.h>
30
31 static const char usage[] =
32 "Usage: %s filename array_name [filename ...]\n"
33 "\tCreate C code for codebook tables.\n";
34
35 static const char format[] =
36 "The table format must be:\n"
37 "\tTwo integers describing the dimensions of the codebook.\n"
38 "\tThen, enough numbers to fill the specified dimensions.\n";
39
40 static const char header[] =
41 "/* THIS IS A GENERATED FILE. Edit generate_codebook.c and its input */\n\n"
42 "/*\n"
43 " * This intermediary file and the files that used to create it are under \n"
44 " * The LGPL. See the file COPYING.\n"
45 " */\n\n"
46 "#include \"defines.h\"\n\n";
47
48 struct codebook {
49 unsigned int k;
50 unsigned int log2m;
51 unsigned int m;
52 float * cb;
53 };
54
55 static void
dump_array(const struct codebook * b,int index)56 dump_array(const struct codebook * b, int index)
57 {
58 int limit = b->k * b->m;
59 int i;
60
61 printf("#ifdef __EMBEDDED__\n");
62 printf("static const float codes%d[] = {\n", index);
63 printf("#else\n");
64 printf("static float codes%d[] = {\n", index);
65 printf("#endif\n");
66 for ( i = 0; i < limit; i++ ) {
67 printf(" %g", b->cb[i]);
68 if ( i < limit - 1 )
69 printf(",");
70
71 /* organise VQs by rows, looks prettier */
72 if ( ((i+1) % b->k) == 0 )
73 printf("\n");
74 }
75 printf("};\n");
76 }
77
78 static void
dump_structure(const struct codebook * b,int index)79 dump_structure(const struct codebook * b, int index)
80 {
81 printf(" {\n");
82 printf(" %d,\n", b->k);
83 printf(" %d,\n", (int)roundf(log(b->m) / log(2)));
84 printf(" %d,\n", b->m);
85 printf(" codes%d\n", index);
86 printf(" }");
87 }
88
89 float
get_float(FILE * in,const char * name,char ** cursor,char * buffer,int size)90 get_float(FILE * in, const char * name, char * * cursor, char * buffer,
91 int size)
92 {
93 for ( ; ; ) {
94 char * s = *cursor;
95 char c;
96
97 while ( (c = *s) != '\0' && !isdigit(c) && c != '-' && c != '.' )
98 s++;
99
100 /* Comments start with "#" and continue to the end of the line. */
101 if ( c != '\0' && c != '#' ) {
102 char * end = 0;
103 float f = 0;
104
105 f = strtod(s, &end);
106
107 if ( end != s )
108 *cursor = end;
109 return f;
110 }
111
112 if ( fgets(buffer, size, in) == NULL ) {
113 fprintf(stderr, "%s: Format error. %s\n", name, format);
114 exit(1);
115 }
116 *cursor = buffer;
117 }
118 }
119
120 static struct codebook *
load(FILE * file,const char * name)121 load(FILE * file, const char * name)
122 {
123 char line[1024];
124 char * cursor = line;
125 struct codebook * b = malloc(sizeof(struct codebook));
126 int i;
127 int size;
128
129 *cursor = '\0';
130
131 b->k = (int)get_float(file, name, &cursor, line, sizeof(line));
132 b->m = (int)get_float(file, name ,&cursor, line, sizeof(line));
133 size = b->k * b->m;
134
135 b->cb = (float *)malloc(size * sizeof(float));
136
137 for ( i = 0; i < size; i++ )
138 b->cb[i] = get_float(file, name, &cursor, line, sizeof(line));
139
140 return b;
141 }
142
143 int
main(int argc,char ** argv)144 main(int argc, char * * argv)
145 {
146 struct codebook * * cb = malloc(argc * sizeof(struct codebook *));
147 int i;
148
149 if ( argc < 2 ) {
150 fprintf(stderr, usage, argv[0]);
151 fprintf(stderr, format);
152 exit(1);
153 }
154
155 for ( i = 0; i < argc - 2; i++ ) {
156 FILE * in = fopen(argv[i + 2], "r");
157
158 if ( in == NULL ) {
159 perror(argv[i + 2]);
160 exit(1);
161 }
162
163 cb[i] = load(in, argv[i + 2]);
164
165 fclose(in);
166 }
167
168 printf(header);
169 for ( i = 0; i < argc - 2; i++ ) {
170 printf(" /* %s */\n", argv[i + 2]);
171 dump_array(cb[i], i);
172 }
173 printf("\nconst struct lsp_codebook %s[] = {\n", argv[1]);
174 for ( i = 0; i < argc - 2; i++ ) {
175 printf(" /* %s */\n", argv[i + 2]);
176 dump_structure(cb[i], i);
177 printf(",\n");
178 }
179 printf(" { 0, 0, 0, 0 }\n");
180 printf("};\n");
181 for( i = 0; i < argc - 2; i++ ){
182 free(cb[i]->cb);
183 free(cb[i]);
184 }
185 free(cb);
186 return 0;
187 }
188