summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThom Johansen <thomj@rockbox.org>2007-12-05 12:27:38 +0000
committerThom Johansen <thomj@rockbox.org>2007-12-05 12:27:38 +0000
commite13974820b80877ba95ec4a9fbfdfe1403524540 (patch)
tree3da7eaef5727fbd196790bfc6d16dbd6cdc82810
parentd44c718e2323fff68abeacd82febf4cda5406e48 (diff)
downloadrockbox-e13974820b80877ba95ec4a9fbfdfe1403524540.tar.gz
rockbox-e13974820b80877ba95ec4a9fbfdfe1403524540.zip
Refactor rbspeexenc code to include an encode_file() function, for later reuse by other programs. Add some more error handling.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15879 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--tools/rbspeex/rbspeexenc.c193
1 files changed, 114 insertions, 79 deletions
diff --git a/tools/rbspeex/rbspeexenc.c b/tools/rbspeex/rbspeexenc.c
index d3c3f7712c..e919bc8990 100644
--- a/tools/rbspeex/rbspeexenc.c
+++ b/tools/rbspeex/rbspeexenc.c
@@ -29,8 +29,8 @@
29" -q x Quality, floating point number in the range [0-10], default 8.0\n"\ 29" -q x Quality, floating point number in the range [0-10], default 8.0\n"\
30" -c x Complexity, increases quality for a given bitrate, but encodes\n"\ 30" -c x Complexity, increases quality for a given bitrate, but encodes\n"\
31" slower, range [0-10], default 3\n"\ 31" slower, range [0-10], default 3\n"\
32" -n Enable narrowband mode, will resample input to 8 kHz\n\n"\ 32" -n Enable narrowband mode, will resample input to 8 kHz\n"\
33" -v x Volume, amplitude multiplier, default 1.0\n"\ 33" -v x Volume, amplitude multiplier, default 1.0\n\n"\
34"rbspeexenc expects a mono 16 bit WAV file as input. Files will be resampled\n"\ 34"rbspeexenc expects a mono 16 bit WAV file as input. Files will be resampled\n"\
35"to either 16 kHz by default, or 8 kHz if narrowband mode is enabled.\n"\ 35"to either 16 kHz by default, or 8 kHz if narrowband mode is enabled.\n"\
36"WARNING: This tool will create files that are only usable by Rockbox!\n" 36"WARNING: This tool will create files that are only usable by Rockbox!\n"
@@ -111,46 +111,35 @@ bool get_wave_metadata(FILE *fd, int *numchan, int *bps, int *sr, int *numsample
111 return true; 111 return true;
112} 112}
113 113
114int main(int argc, char **argv) 114/* We'll eat an entire WAV file here, and encode it with Speex, packing the
115 * bits as tightly as we can. Output is completely raw, with absolutely
116 * nothing to identify the contents. Files are left open, so remember to close
117 * them.
118 */
119bool encode_file(FILE *fin, FILE *fout, float quality, int complexity,
120 bool narrowband, float volume, char *errstr, size_t errlen)
115{ 121{
116 FILE *fin, *fout; 122 spx_int16_t *in = NULL, *inpos;
117 spx_int16_t *in, *inpos;
118 spx_int16_t enc_buf[640]; /* Max frame size */ 123 spx_int16_t enc_buf[640]; /* Max frame size */
119 char cbits[200]; 124 char cbits[200];
120 int nbytes; 125 void *st = NULL;
121 void *st;
122 SpeexResamplerState *resampler = NULL; 126 SpeexResamplerState *resampler = NULL;
123 SpeexBits bits; 127 SpeexBits bits;
124 int i, tmp; 128 int i, tmp, target_sr, numchan, bps, sr, numsamples, frame_size, lookahead;
125 int complexity = 3; 129 int nbytes;
126 float quality = 8.f; 130 bool ret = true;
127 bool narrowband = false;
128 float volume = 1.0f;
129 int target_sr;
130 int numchan, bps, sr, numsamples;
131 int frame_size;
132 int lookahead;
133 131
134 if (argc < 3) { 132 if (!get_wave_metadata(fin, &numchan, &bps, &sr, &numsamples)) {
135 printf(USAGE_TEXT); 133 snprintf(errstr, errlen, "invalid WAV file");
136 return 1; 134 return false;
137 } 135 }
138 136 if (numchan != 1) {
139 i = 1; 137 snprintf(errstr, errlen, "input file must be mono");
140 while (i < argc - 2) { 138 return false;
141 if (strncmp(argv[i], "-q", 2) == 0) 139 }
142 quality = atof(argv[++i]); 140 if (bps != 16) {
143 else if (strncmp(argv[i], "-c", 2) == 0) 141 snprintf(errstr, errlen, "samples must be 16 bit");
144 complexity = atoi(argv[++i]); 142 return false;
145 else if (strncmp(argv[i], "-v", 2) == 0)
146 volume = atof(argv[++i]);
147 else if (strncmp(argv[i], "-n", 2) == 0)
148 narrowband = true;
149 else {
150 printf("Error: unrecognized option '%s'\n", argv[i]);
151 return 1;
152 }
153 ++i;
154 } 143 }
155 144
156 /* Allocate an encoder of specified type, defaults to wideband */ 145 /* Allocate an encoder of specified type, defaults to wideband */
@@ -159,11 +148,7 @@ int main(int argc, char **argv)
159 target_sr = 8000; 148 target_sr = 8000;
160 else 149 else
161 target_sr = 16000; 150 target_sr = 16000;
162 151 speex_bits_init(&bits);
163 /* We'll eat an entire WAV file here, and encode it with Speex, packing the
164 * bits as tightly as we can. Output is completely raw, with absolutely
165 * nothing to identify the contents.
166 */
167 152
168 /* VBR */ 153 /* VBR */
169 tmp = 1; 154 tmp = 1;
@@ -175,50 +160,35 @@ int main(int argc, char **argv)
175 speex_encoder_ctl(st, SPEEX_GET_FRAME_SIZE, &frame_size); 160 speex_encoder_ctl(st, SPEEX_GET_FRAME_SIZE, &frame_size);
176 speex_encoder_ctl(st, SPEEX_GET_LOOKAHEAD, &lookahead); 161 speex_encoder_ctl(st, SPEEX_GET_LOOKAHEAD, &lookahead);
177 162
178 fin = fopen(argv[argc - 2], "rb");
179 if (!get_wave_metadata(fin, &numchan, &bps, &sr, &numsamples)) {
180 printf("Error: invalid WAV file\n");
181 return 1;
182 }
183 if (sr != target_sr) {
184 resampler = speex_resampler_init(1, sr, target_sr, 10, NULL);
185 speex_resampler_skip_zeros(resampler);
186 }
187 if (numchan != 1) {
188 printf("Error: input file must be mono\n");
189 return 1;
190 }
191 if (bps != 16) {
192 printf("Error: samples must be 16 bit\n");
193 return 1;
194 }
195
196 /* Read input samples into a buffer */ 163 /* Read input samples into a buffer */
197 in = calloc(numsamples + lookahead, sizeof(spx_int16_t)); 164 in = calloc(numsamples + lookahead, sizeof(spx_int16_t));
198 if (in == NULL) { 165 if (in == NULL) {
199 printf("Error: could not allocate clip memory\n"); 166 snprintf(errstr, errlen, "could not allocate clip memory");
200 return 1; 167 ret = false;
168 goto finish;
201 } 169 }
202 fread(in, 2, numsamples, fin); 170 if (fread(in, 2, numsamples, fin) != numsamples) {
203 fclose(fin); 171 snprintf(errstr, errlen, "could not read input file data");
204 172 ret = false;
205 if(volume != 1.0f) { 173 goto finish;
206 for(i=0; i<numsamples; i++) 174 }
175
176 if (volume != 1.0f) {
177 for (i = 0; i < numsamples; ++i)
207 in[i] *= volume; 178 in[i] *= volume;
208 } 179 }
209 180
181 if (sr != target_sr) {
182 resampler = speex_resampler_init(1, sr, target_sr, 10, NULL);
183 speex_resampler_skip_zeros(resampler);
184 }
185
210 /* There will be 'lookahead' samples of zero at the end of the array, to 186 /* There will be 'lookahead' samples of zero at the end of the array, to
211 * make sure the Speex encoder is allowed to spit out all its data at clip 187 * make sure the Speex encoder is allowed to spit out all its data at clip
212 * end */ 188 * end */
213 numsamples += lookahead; 189 numsamples += lookahead;
214 190
215 speex_bits_init(&bits);
216 inpos = in; 191 inpos = in;
217 if ((fout = fopen(argv[argc - 1], "wb")) == NULL) {
218 printf("Error: could not open output file\n");
219 return 1;
220 }
221
222 while (numsamples > 0) { 192 while (numsamples > 0) {
223 int samples = frame_size; 193 int samples = frame_size;
224 194
@@ -249,27 +219,92 @@ int main(int argc, char **argv)
249 memset(enc_buf + samples, 0, (frame_size - samples)*2); 219 memset(enc_buf + samples, 0, (frame_size - samples)*2);
250 220
251 if (speex_encode_int(st, enc_buf, &bits) < 0) { 221 if (speex_encode_int(st, enc_buf, &bits) < 0) {
252 printf("Error: encoder error\n"); 222 snprintf(errstr, errlen, "encoder error");
253 return 1; 223 ret = false;
224 goto finish;
254 } 225 }
255 226
256 /* Copy the bits to an array of char that can be written */ 227 /* Copy the bits to an array of char that can be written */
257 nbytes = speex_bits_write_whole_bytes(&bits, cbits, 200); 228 nbytes = speex_bits_write_whole_bytes(&bits, cbits, 200);
258 229
259 /* Write the compressed data */ 230 /* Write the compressed data */
260 fwrite(cbits, 1, nbytes, fout); 231 if (fwrite(cbits, 1, nbytes, fout) != nbytes) {
232 snprintf(errstr, errlen, "could not write output data");
233 ret = false;
234 goto finish;
235 }
261 } 236 }
262 /* Squeeze out the last bits */ 237 /* Squeeze out the last bits */
263 nbytes = speex_bits_write(&bits, cbits, 200); 238 nbytes = speex_bits_write(&bits, cbits, 200);
264 fwrite(cbits, 1, nbytes, fout); 239 if (fwrite(cbits, 1, nbytes, fout) != nbytes) {
240 snprintf(errstr, errlen, "could not write output data");
241 ret = false;
242 }
265 243
266 /*Destroy the encoder state*/ 244finish:
267 speex_encoder_destroy(st); 245 if (st != NULL)
268 /*Destroy the bit-packing struct*/ 246 speex_encoder_destroy(st);
269 speex_bits_destroy(&bits); 247 speex_bits_destroy(&bits);
270 if (resampler != NULL) 248 if (resampler != NULL)
271 speex_resampler_destroy(resampler); 249 speex_resampler_destroy(resampler);
250 if (in != NULL)
251 free(in);
252 return ret;
253}
254
255int main(int argc, char **argv)
256{
257 char *inname, *outname;
258 FILE *fin, *fout;
259 int i;
260 int complexity = 3;
261 float quality = 8.f, volume = 1.0f;
262 bool narrowband = false;
263 bool ret;
264 char errstr[512];
265
266 if (argc < 3) {
267 printf(USAGE_TEXT);
268 return 1;
269 }
270
271 i = 1;
272 while (i < argc - 2) {
273 if (strncmp(argv[i], "-q", 2) == 0)
274 quality = atof(argv[++i]);
275 else if (strncmp(argv[i], "-c", 2) == 0)
276 complexity = atoi(argv[++i]);
277 else if (strncmp(argv[i], "-v", 2) == 0)
278 volume = atof(argv[++i]);
279 else if (strncmp(argv[i], "-n", 2) == 0)
280 narrowband = true;
281 else {
282 printf("Error: unrecognized option '%s'\n", argv[i]);
283 return 1;
284 }
285 ++i;
286 }
287 inname = argv[argc - 2];
288 outname = argv[argc - 1];
289
290 if ((fin = fopen(inname, "rb")) == NULL) {
291 printf("Error: could not open input file\n");
292 return 1;
293 }
294 if ((fout = fopen(outname, "wb")) == NULL) {
295 printf("Error: could not open output file\n");
296 return 1;
297 }
298
299 ret = encode_file(fin, fout, quality, complexity, narrowband, volume,
300 errstr, sizeof(errstr));
301 fclose(fin);
272 fclose(fout); 302 fclose(fout);
273 free(in); 303 if (!ret) {
304 /* Attempt to delete unfinished output */
305 printf("Error: %s\n", errstr);
306 remove(outname);
307 return 1;
308 }
274 return 0; 309 return 0;
275} 310}