forked from len0rd/rockbox
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
This commit is contained in:
parent
d44c718e23
commit
e13974820b
1 changed files with 113 additions and 78 deletions
|
|
@ -29,8 +29,8 @@
|
||||||
" -q x Quality, floating point number in the range [0-10], default 8.0\n"\
|
" -q x Quality, floating point number in the range [0-10], default 8.0\n"\
|
||||||
" -c x Complexity, increases quality for a given bitrate, but encodes\n"\
|
" -c x Complexity, increases quality for a given bitrate, but encodes\n"\
|
||||||
" slower, range [0-10], default 3\n"\
|
" slower, range [0-10], default 3\n"\
|
||||||
" -n Enable narrowband mode, will resample input to 8 kHz\n\n"\
|
" -n Enable narrowband mode, will resample input to 8 kHz\n"\
|
||||||
" -v x Volume, amplitude multiplier, default 1.0\n"\
|
" -v x Volume, amplitude multiplier, default 1.0\n\n"\
|
||||||
"rbspeexenc expects a mono 16 bit WAV file as input. Files will be resampled\n"\
|
"rbspeexenc expects a mono 16 bit WAV file as input. Files will be resampled\n"\
|
||||||
"to either 16 kHz by default, or 8 kHz if narrowband mode is enabled.\n"\
|
"to either 16 kHz by default, or 8 kHz if narrowband mode is enabled.\n"\
|
||||||
"WARNING: This tool will create files that are only usable by Rockbox!\n"
|
"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
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
/* We'll eat an entire WAV file here, and encode it with Speex, packing the
|
||||||
|
* bits as tightly as we can. Output is completely raw, with absolutely
|
||||||
|
* nothing to identify the contents. Files are left open, so remember to close
|
||||||
|
* them.
|
||||||
|
*/
|
||||||
|
bool encode_file(FILE *fin, FILE *fout, float quality, int complexity,
|
||||||
|
bool narrowband, float volume, char *errstr, size_t errlen)
|
||||||
{
|
{
|
||||||
FILE *fin, *fout;
|
spx_int16_t *in = NULL, *inpos;
|
||||||
spx_int16_t *in, *inpos;
|
|
||||||
spx_int16_t enc_buf[640]; /* Max frame size */
|
spx_int16_t enc_buf[640]; /* Max frame size */
|
||||||
char cbits[200];
|
char cbits[200];
|
||||||
int nbytes;
|
void *st = NULL;
|
||||||
void *st;
|
|
||||||
SpeexResamplerState *resampler = NULL;
|
SpeexResamplerState *resampler = NULL;
|
||||||
SpeexBits bits;
|
SpeexBits bits;
|
||||||
int i, tmp;
|
int i, tmp, target_sr, numchan, bps, sr, numsamples, frame_size, lookahead;
|
||||||
int complexity = 3;
|
int nbytes;
|
||||||
float quality = 8.f;
|
bool ret = true;
|
||||||
bool narrowband = false;
|
|
||||||
float volume = 1.0f;
|
|
||||||
int target_sr;
|
|
||||||
int numchan, bps, sr, numsamples;
|
|
||||||
int frame_size;
|
|
||||||
int lookahead;
|
|
||||||
|
|
||||||
if (argc < 3) {
|
if (!get_wave_metadata(fin, &numchan, &bps, &sr, &numsamples)) {
|
||||||
printf(USAGE_TEXT);
|
snprintf(errstr, errlen, "invalid WAV file");
|
||||||
return 1;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (numchan != 1) {
|
||||||
i = 1;
|
snprintf(errstr, errlen, "input file must be mono");
|
||||||
while (i < argc - 2) {
|
return false;
|
||||||
if (strncmp(argv[i], "-q", 2) == 0)
|
|
||||||
quality = atof(argv[++i]);
|
|
||||||
else if (strncmp(argv[i], "-c", 2) == 0)
|
|
||||||
complexity = atoi(argv[++i]);
|
|
||||||
else if (strncmp(argv[i], "-v", 2) == 0)
|
|
||||||
volume = atof(argv[++i]);
|
|
||||||
else if (strncmp(argv[i], "-n", 2) == 0)
|
|
||||||
narrowband = true;
|
|
||||||
else {
|
|
||||||
printf("Error: unrecognized option '%s'\n", argv[i]);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
++i;
|
if (bps != 16) {
|
||||||
|
snprintf(errstr, errlen, "samples must be 16 bit");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate an encoder of specified type, defaults to wideband */
|
/* Allocate an encoder of specified type, defaults to wideband */
|
||||||
|
|
@ -159,11 +148,7 @@ int main(int argc, char **argv)
|
||||||
target_sr = 8000;
|
target_sr = 8000;
|
||||||
else
|
else
|
||||||
target_sr = 16000;
|
target_sr = 16000;
|
||||||
|
speex_bits_init(&bits);
|
||||||
/* We'll eat an entire WAV file here, and encode it with Speex, packing the
|
|
||||||
* bits as tightly as we can. Output is completely raw, with absolutely
|
|
||||||
* nothing to identify the contents.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* VBR */
|
/* VBR */
|
||||||
tmp = 1;
|
tmp = 1;
|
||||||
|
|
@ -175,50 +160,35 @@ int main(int argc, char **argv)
|
||||||
speex_encoder_ctl(st, SPEEX_GET_FRAME_SIZE, &frame_size);
|
speex_encoder_ctl(st, SPEEX_GET_FRAME_SIZE, &frame_size);
|
||||||
speex_encoder_ctl(st, SPEEX_GET_LOOKAHEAD, &lookahead);
|
speex_encoder_ctl(st, SPEEX_GET_LOOKAHEAD, &lookahead);
|
||||||
|
|
||||||
fin = fopen(argv[argc - 2], "rb");
|
|
||||||
if (!get_wave_metadata(fin, &numchan, &bps, &sr, &numsamples)) {
|
|
||||||
printf("Error: invalid WAV file\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (sr != target_sr) {
|
|
||||||
resampler = speex_resampler_init(1, sr, target_sr, 10, NULL);
|
|
||||||
speex_resampler_skip_zeros(resampler);
|
|
||||||
}
|
|
||||||
if (numchan != 1) {
|
|
||||||
printf("Error: input file must be mono\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (bps != 16) {
|
|
||||||
printf("Error: samples must be 16 bit\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read input samples into a buffer */
|
/* Read input samples into a buffer */
|
||||||
in = calloc(numsamples + lookahead, sizeof(spx_int16_t));
|
in = calloc(numsamples + lookahead, sizeof(spx_int16_t));
|
||||||
if (in == NULL) {
|
if (in == NULL) {
|
||||||
printf("Error: could not allocate clip memory\n");
|
snprintf(errstr, errlen, "could not allocate clip memory");
|
||||||
return 1;
|
ret = false;
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
if (fread(in, 2, numsamples, fin) != numsamples) {
|
||||||
|
snprintf(errstr, errlen, "could not read input file data");
|
||||||
|
ret = false;
|
||||||
|
goto finish;
|
||||||
}
|
}
|
||||||
fread(in, 2, numsamples, fin);
|
|
||||||
fclose(fin);
|
|
||||||
|
|
||||||
if(volume != 1.0f) {
|
if (volume != 1.0f) {
|
||||||
for(i=0; i<numsamples; i++)
|
for (i = 0; i < numsamples; ++i)
|
||||||
in[i] *= volume;
|
in[i] *= volume;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sr != target_sr) {
|
||||||
|
resampler = speex_resampler_init(1, sr, target_sr, 10, NULL);
|
||||||
|
speex_resampler_skip_zeros(resampler);
|
||||||
|
}
|
||||||
|
|
||||||
/* There will be 'lookahead' samples of zero at the end of the array, to
|
/* There will be 'lookahead' samples of zero at the end of the array, to
|
||||||
* make sure the Speex encoder is allowed to spit out all its data at clip
|
* make sure the Speex encoder is allowed to spit out all its data at clip
|
||||||
* end */
|
* end */
|
||||||
numsamples += lookahead;
|
numsamples += lookahead;
|
||||||
|
|
||||||
speex_bits_init(&bits);
|
|
||||||
inpos = in;
|
inpos = in;
|
||||||
if ((fout = fopen(argv[argc - 1], "wb")) == NULL) {
|
|
||||||
printf("Error: could not open output file\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (numsamples > 0) {
|
while (numsamples > 0) {
|
||||||
int samples = frame_size;
|
int samples = frame_size;
|
||||||
|
|
||||||
|
|
@ -249,27 +219,92 @@ int main(int argc, char **argv)
|
||||||
memset(enc_buf + samples, 0, (frame_size - samples)*2);
|
memset(enc_buf + samples, 0, (frame_size - samples)*2);
|
||||||
|
|
||||||
if (speex_encode_int(st, enc_buf, &bits) < 0) {
|
if (speex_encode_int(st, enc_buf, &bits) < 0) {
|
||||||
printf("Error: encoder error\n");
|
snprintf(errstr, errlen, "encoder error");
|
||||||
return 1;
|
ret = false;
|
||||||
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy the bits to an array of char that can be written */
|
/* Copy the bits to an array of char that can be written */
|
||||||
nbytes = speex_bits_write_whole_bytes(&bits, cbits, 200);
|
nbytes = speex_bits_write_whole_bytes(&bits, cbits, 200);
|
||||||
|
|
||||||
/* Write the compressed data */
|
/* Write the compressed data */
|
||||||
fwrite(cbits, 1, nbytes, fout);
|
if (fwrite(cbits, 1, nbytes, fout) != nbytes) {
|
||||||
|
snprintf(errstr, errlen, "could not write output data");
|
||||||
|
ret = false;
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* Squeeze out the last bits */
|
/* Squeeze out the last bits */
|
||||||
nbytes = speex_bits_write(&bits, cbits, 200);
|
nbytes = speex_bits_write(&bits, cbits, 200);
|
||||||
fwrite(cbits, 1, nbytes, fout);
|
if (fwrite(cbits, 1, nbytes, fout) != nbytes) {
|
||||||
|
snprintf(errstr, errlen, "could not write output data");
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
|
||||||
/*Destroy the encoder state*/
|
finish:
|
||||||
|
if (st != NULL)
|
||||||
speex_encoder_destroy(st);
|
speex_encoder_destroy(st);
|
||||||
/*Destroy the bit-packing struct*/
|
|
||||||
speex_bits_destroy(&bits);
|
speex_bits_destroy(&bits);
|
||||||
if (resampler != NULL)
|
if (resampler != NULL)
|
||||||
speex_resampler_destroy(resampler);
|
speex_resampler_destroy(resampler);
|
||||||
fclose(fout);
|
if (in != NULL)
|
||||||
free(in);
|
free(in);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
char *inname, *outname;
|
||||||
|
FILE *fin, *fout;
|
||||||
|
int i;
|
||||||
|
int complexity = 3;
|
||||||
|
float quality = 8.f, volume = 1.0f;
|
||||||
|
bool narrowband = false;
|
||||||
|
bool ret;
|
||||||
|
char errstr[512];
|
||||||
|
|
||||||
|
if (argc < 3) {
|
||||||
|
printf(USAGE_TEXT);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 1;
|
||||||
|
while (i < argc - 2) {
|
||||||
|
if (strncmp(argv[i], "-q", 2) == 0)
|
||||||
|
quality = atof(argv[++i]);
|
||||||
|
else if (strncmp(argv[i], "-c", 2) == 0)
|
||||||
|
complexity = atoi(argv[++i]);
|
||||||
|
else if (strncmp(argv[i], "-v", 2) == 0)
|
||||||
|
volume = atof(argv[++i]);
|
||||||
|
else if (strncmp(argv[i], "-n", 2) == 0)
|
||||||
|
narrowband = true;
|
||||||
|
else {
|
||||||
|
printf("Error: unrecognized option '%s'\n", argv[i]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
inname = argv[argc - 2];
|
||||||
|
outname = argv[argc - 1];
|
||||||
|
|
||||||
|
if ((fin = fopen(inname, "rb")) == NULL) {
|
||||||
|
printf("Error: could not open input file\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if ((fout = fopen(outname, "wb")) == NULL) {
|
||||||
|
printf("Error: could not open output file\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = encode_file(fin, fout, quality, complexity, narrowband, volume,
|
||||||
|
errstr, sizeof(errstr));
|
||||||
|
fclose(fin);
|
||||||
|
fclose(fout);
|
||||||
|
if (!ret) {
|
||||||
|
/* Attempt to delete unfinished output */
|
||||||
|
printf("Error: %s\n", errstr);
|
||||||
|
remove(outname);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue