1 /*---------------------------------------------------------------------------*\
2 
3   FILE........: c2enc.c
4   AUTHOR......: David Rowe
5   DATE CREATED: 23/8/2010
6 
7   Encodes a file of raw speech samples using codec2 and outputs a file
8   of bits.
9 
10 \*---------------------------------------------------------------------------*/
11 
12 /*
13   Copyright (C) 2010 David Rowe
14 
15   All rights reserved.
16 
17   This program is free software; you can redistribute it and/or modify
18   it under the terms of the GNU Lesser General Public License version 2.1, as
19   published by the Free Software Foundation.  This program is
20   distributed in the hope that it will be useful, but WITHOUT ANY
21   WARRANTY; without even the implied warranty of MERCHANTABILITY or
22   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
23   License for more details.
24 
25   You should have received a copy of the GNU Lesser General Public License
26   along with this program; if not, see <http://www.gnu.org/licenses/>.
27 */
28 
29 #include "codec2.h"
30 #include "c2file.h"
31 
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <errno.h>
36 #include <math.h>
37 
main(int argc,char * argv[])38 int main(int argc, char *argv[])
39 {
40     int            mode;
41     void          *codec2;
42     FILE          *fin;
43     FILE          *fout;
44     short         *buf;
45     unsigned char *bits;
46     int            nsam, nbit, nbyte, gray, softdec, bitperchar;
47     float         *unpacked_bits_float;
48     char          *unpacked_bits_char;
49     int            bit, byte,i;
50     int            report_var = 0;
51     int            eq = 0;
52 
53     if (argc < 4) {
54 	printf("usage: c2enc 3200|2400|1600|1400|1300|1200|700C|450|450PWB InputRawspeechFile OutputBitFile [--natural] [--softdec] [--bitperchar] [--mlfeat f32File modelFile] [--loadcb stageNum Filename] [--var] [--eq]\n");
55 	printf("e.g. (headerless)    c2enc 1300 ../raw/hts1a.raw hts1a.bin\n");
56 	printf("e.g. (with header to detect mode)   c2enc 1300 ../raw/hts1a.raw hts1a.c2\n");
57 	exit(1);
58     }
59 
60     if (strcmp(argv[1],"3200") == 0)
61 	mode = CODEC2_MODE_3200;
62     else if (strcmp(argv[1],"2400") == 0)
63 	mode = CODEC2_MODE_2400;
64     else if (strcmp(argv[1],"1600") == 0)
65 	mode = CODEC2_MODE_1600;
66     else if (strcmp(argv[1],"1400") == 0)
67 	mode = CODEC2_MODE_1400;
68     else if (strcmp(argv[1],"1300") == 0)
69 	mode = CODEC2_MODE_1300;
70     else if (strcmp(argv[1],"1200") == 0)
71 	mode = CODEC2_MODE_1200;
72     else if (strcmp(argv[1],"700C") == 0)
73 	mode = CODEC2_MODE_700C;
74     else if (strcmp(argv[1],"450") == 0)
75 	mode = CODEC2_MODE_450;
76     else if (strcmp(argv[1],"450PWB") == 0)
77 	mode = CODEC2_MODE_450;
78     else {
79 	fprintf(stderr, "Error in mode: %s.  Must be 3200, 2400, 1600, 1400, 1300, 1200, 700C, 450, 450PWB or WB\n", argv[1]);
80 	exit(1);
81     }
82 
83     if (strcmp(argv[2], "-")  == 0) fin = stdin;
84     else if ( (fin = fopen(argv[2],"rb")) == NULL ) {
85 	fprintf(stderr, "Error opening input speech file: %s: %s.\n",
86          argv[2], strerror(errno));
87 	exit(1);
88     }
89 
90     if (strcmp(argv[3], "-") == 0) fout = stdout;
91     else if ( (fout = fopen(argv[3],"wb")) == NULL ) {
92 	fprintf(stderr, "Error opening output compressed bit file: %s: %s.\n",
93          argv[3], strerror(errno));
94 	exit(1);
95     }
96 
97     // Write a header if we're writing to a .c2 file
98     char *ext = strrchr(argv[3], '.');
99     if (ext != NULL) {
100         if (strcmp(ext, ".c2") == 0) {
101             struct c2_header out_hdr;
102             memcpy(out_hdr.magic,c2_file_magic,sizeof(c2_file_magic));
103             out_hdr.mode = mode;
104             out_hdr.version_major = CODEC2_VERSION_MAJOR;
105             out_hdr.version_minor = CODEC2_VERSION_MINOR;
106             // TODO: Handle flags (this block needs to be moved down)
107             out_hdr.flags = 0;
108             fwrite(&out_hdr,sizeof(out_hdr),1,fout);
109         };
110     };
111 
112     codec2 = codec2_create(mode);
113     nsam = codec2_samples_per_frame(codec2);
114     nbit = codec2_bits_per_frame(codec2);
115     buf = (short*)malloc(nsam*sizeof(short));
116     nbyte = (nbit + 7) / 8;
117 
118     bits = (unsigned char*)malloc(nbyte*sizeof(char));
119     unpacked_bits_float = (float*)malloc(nbit*sizeof(float));
120     unpacked_bits_char = (char*)malloc(nbit*sizeof(char));
121 
122     gray = 1; softdec = 0; bitperchar = 0;
123     for (i=4; i<argc; i++) {
124         if (strcmp(argv[i], "--natural") == 0) {
125             gray = 0;
126         }
127         if (strcmp(argv[i], "--softdec") == 0) {
128             softdec = 1;
129         }
130         if (strcmp(argv[i], "--bitperchar") == 0) {
131             bitperchar = 1;
132         }
133         if (strcmp(argv[i], "--mlfeat") == 0) {
134             /* dump machine learning features (700C only) */
135             codec2_open_mlfeat(codec2, argv[i+1], argv[i+2]);
136         }
137         if (strcmp(argv[i], "--loadcb") == 0) {
138             /* load VQ stage (700C only) */
139             codec2_load_codebook(codec2, atoi(argv[i+1])-1, argv[i+2]);
140         }
141         if (strcmp(argv[i], "--var") == 0) {
142             report_var = 1;
143         }
144         if (strcmp(argv[i], "--eq") == 0) {
145             eq = 1;
146         }
147 
148     }
149     codec2_set_natural_or_gray(codec2, gray);
150     codec2_700c_eq(codec2, eq);
151 
152     //fprintf(stderr,"gray: %d softdec: %d\n", gray, softdec);
153 
154     while(fread(buf, sizeof(short), nsam, fin) == (size_t)nsam) {
155 
156 	codec2_encode(codec2, bits, buf);
157 
158 	if (softdec || bitperchar) {
159             /* unpack bits, MSB first, send as soft decision float */
160 
161             bit = 7; byte = 0;
162             for(i=0; i<nbit; i++) {
163                 unpacked_bits_float[i] = 1.0 - 2.0*((bits[byte] >> bit) & 0x1);
164                 unpacked_bits_char[i] = (bits[byte] >> bit) & 0x1;
165                 bit--;
166                 if (bit < 0) {
167                     bit = 7;
168                     byte++;
169                 }
170             }
171             if (softdec) {
172                 fwrite(unpacked_bits_float, sizeof(float), nbit, fout);
173             }
174             if (bitperchar) {
175                 fwrite(unpacked_bits_char, sizeof(char), nbit, fout);
176             }
177         }
178         else
179             fwrite(bits, sizeof(char), nbyte, fout);
180 
181 	    // if this is in a pipeline, we probably don't want the usual
182         // buffering to occur
183 
184         if (fout == stdout) fflush(stdout);
185     }
186 
187     if (report_var) {
188         float var = codec2_get_var(codec2);
189         fprintf(stderr, "%s var: %5.2f std: %5.2f\n", argv[2], var, sqrt(var));
190     }
191     codec2_destroy(codec2);
192 
193     free(buf);
194     free(bits);
195     free(unpacked_bits_float);
196     free(unpacked_bits_char);
197     fclose(fin);
198     fclose(fout);
199 
200     return 0;
201 }
202