I'm trying to convert a 16KHZ 16-bit Signed PCM encoded wave file to 8KHz 8-bit mu-encoded wav file using the Sox library C program (http://sox.sourceforge.net/). The conversion from PCM to mu is working fine. But when I apply the down-sampling effect the output file duration is just half of the i/p file(see below). I used the technique mentioned in the post How to change the samples rates when do the format conversion by sox C libraries? but it didn't help me.
When I execute the below code I see a warning
wav: Premature EOF on .wav input file
Output:
Input File : 'text2speech_0.wav'
Channels : 1
Sample Rate : 16000
Precision : 16-bit
**Duration : 00:00:06.24 = 99777 samples ~ 467.705 CDDA sectors**
File Size : 200k
Bit Rate : 256k
Sample Encoding: 16-bit Signed Integer PCM
Input File : 'out_8k.wav'
Channels : 1
Sample Rate : 8000
Precision : 14-bit
**Duration : 00:00:03.12 = 24945 samples ~ 233.859 CDDA sectors**
File Size : 49.9k
Bit Rate : 128k
Sample Encoding: 8bit u-law
Code:
int main(int argc, char * argv[])
{
static sox_format_t * in, * out; /* input and output files */
sox_effects_chain_t * chain;
sox_effect_t * e;
char * args[10];
assert(argc == 3);
assert(sox_init() == SOX_SUCCESS);
assert(in = sox_open_read(argv[1], NULL, NULL, NULL));
assert(out = sox_open_write(argv[2], &in->signal, NULL, NULL, NULL, NULL));
chain = sox_create_effects_chain(&in->encoding, &out->encoding);
e = sox_create_effect(sox_find_effect("input"));
args[0] = (char *)in, assert(sox_effect_options(e, 1, args) == SOX_SUCCESS);
assert(sox_add_effect(chain, e, &in->signal, &in->signal) == SOX_SUCCESS);
free(e);
out->signal.rate = 8000;
in->signal.rate = 16000;
if (in->signal.rate != out->signal.rate) {
e = sox_create_effect(sox_find_effect("rate"));
args[0] = "16000", assert(sox_effect_options(e, 1, args) == SOX_SUCCESS);
assert(sox_add_effect(chain, e, &in->signal, &out->signal) == SOX_SUCCESS);
free(e);
}
if (in->signal.channels != out->signal.channels) {
e = sox_create_effect(sox_find_effect("channels"));
assert(sox_effect_options(e, 0, NULL) == SOX_SUCCESS);
assert(sox_add_effect(chain, e, &in->signal, &out->signal) == SOX_SUCCESS);
free(e);
}
e = sox_create_effect(sox_find_effect("output"));
args[0] = (char *)out, assert(sox_effect_options(e, 1, args) == SOX_SUCCESS);
assert(sox_add_effect(chain, e, &in->signal, &out->signal) == SOX_SUCCESS);
free(e);
sox_flow_effects(chain, NULL, NULL);
sox_delete_effects_chain(chain);
sox_close(out);
sox_close(in);
sox_quit();
return 0;
}
Compilation & Execution:
gcc -g -o example3 example3.c `pkg-config --cflags --libs sox`
./example3 text2speech_0.wav out_8k.wav
Bellow is a diff for a working code. I believe the main mistake made is that the "out" structure must set before opening it for writing.
+#include <sox.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+ int main(int argc, char * argv[])
+ {
+ static sox_format_t * in, * out; /* input and output files */
+@@ -7,9 +13,15 @@
assert(argc == 3);
assert(sox_init() == SOX_SUCCESS);
assert(in = sox_open_read(argv[1], NULL, NULL, NULL));
+ out= (sox_format_t *) malloc(sizeof (sox_format_t));
+ memcpy(out, in, sizeof (sox_format_t));
+ out->encoding.encoding = SOX_ENCODING_ULAW;
+ out->encoding.bits_per_sample=8;
+ out->signal.rate = 8000;
+ out->signal.precision = 8;
+ out->signal.length = SOX_UNSPEC;
+ assert(out = sox_open_write(argv[2], &out->signal, &out->encoding, NULL, NULL, NULL));
- assert(out = sox_open_write(argv[2- assert(out = sox_open_write(argv[2], &in->signal, NULL, NULL, NULL, NULL));
-
chain = sox_create_effects_chain(&in->encoding, &out->encoding);
e = sox_create_effect(sox_find_effect("input"));
@@ -17,16 +29,14 @@
assert(sox_add_effect(chain, e, &in->signal, &in->signal) == SOX_SUCCESS);
free(e);
- out->signal.rate = 8000;
- in->signal.rate = 16000;
if (in->signal.rate != out->signal.rate) {
e = sox_create_effect(sox_find_effect("rate"));
- args[0] = "16000", assert(sox_effect_options(e, 1, args) == SOX_SUCCESS);
+ assert(sox_effect_options(e, 0, NULL) == SOX_SUCCESS);
+ e->handler.flags |= SOX_EFF_LENGTH;
+
assert(sox_add_effect(chain, e, &in->signal, &out->signal) == SOX_SUCCESS);
free(e);