Понижение частоты дискретизации файла wav с помощью libsox

Я пытаюсь преобразовать 16-битный подписанный волновой файл PCM с 16 кГц в 8-битный mu-кодированный WAV-файл с частотой 8 кГц с помощью программы Sox library C (http://sox.sourceforge.net/). Преобразование из PCM в mu работает нормально. Но когда я применяю эффект понижающей дискретизации, продолжительность выходного файла составляет лишь половину от файла i / p (см. Ниже). Я использовал технику, упомянутую в сообщении Как изменить частоту дискретизации при преобразовании формата библиотеками sox C? но мне это не помогло.

Когда я выполняю приведенный ниже код, я вижу предупреждение

wav: Premature EOF on .wav input file

Вывод:

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

Код:

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;
}

Компиляция и выполнение:

gcc -g -o example3 example3.c `pkg-config --cflags --libs sox`
./example3 text2speech_0.wav out_8k.wav

person Khalandar    schedule 01.08.2014    source источник
comment
Я не знаком с Sox lib, поэтому могут возникнуть глупые вопросы: почему out_8k.wav снова является входным файлом в вашем выводе. Почему это Precision: 16 бит, но вы сказали 8 кГц 8-битный mu-кодированный wav. Почему вы указываете частоту дискретизации вручную для входного файла in->signal.rate = 16000;?   -  person Andriy Tylychko    schedule 01.08.2014
comment
Мы передаем out_8k.wav, чтобы туда записывались данные. Прецизионность используется для преобразования / понижающей дискретизации, не имеет ничего общего с кодировкой (ее фактически 14-битные обновили то же самое в посте). Мне не нужно указывать частоту дискретизации входных данных, я пробовал разные вещи и добавил ее по ошибке. Эту строку можно удалить   -  person Khalandar    schedule 01.08.2014
comment
Я не использовал библиотеку, но из командной строки комбинация -B Bits your out->signal.rate и -e encoding предполагает, что на субдискретизацию может повлиять signed, unsigned, or floating-point хранилище PCM. Я не могу сказать из вашего кода, актуально ли это здесь, но это возможность проверить.   -  person David C. Rankin    schedule 02.08.2014
comment
Я попытался преобразовать беззнаковый WAV-файл PCM с частотой 16 кГц в U-закон с частотой 8 кГц, и результат был таким же. Получение только половины входных данных в выходном файле   -  person Khalandar    schedule 02.08.2014


Ответы (1)


Bellow - это разница для рабочего кода. Я считаю, что основная сделанная ошибка заключается в том, что структура «out» должна быть установлена ​​перед тем, как открывать ее для записи.

+#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);
person Community    schedule 16.11.2014