Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I am trying programmatically apply few effects with libSox and I currently cannot understand if I am doing it right. For example, I need to apply tempo and gain effects and read the resulting audio in a buffer for a further processing. The documentation is really scarce and googling did not work out. Here is my code:

sox_format_t* input = sox_open_read("<file.wav>", NULL, NULL, NULL);
//sox_format_t* out;
sox_format_t* output = sox_open_memstream_write(&buffer, &buffer_size,
                                             &input->signal, &input->encoding, "raw", NULL);
//assert(output = sox_open_write("/home/egor/hello_processed.wav", &input->signal, NULL, NULL, NULL, NULL));
sox_effects_chain_t* chain = sox_create_effects_chain(&input->encoding, &output->encoding);
char* sox_args[10];
//input effect
sox_effect_t* e = sox_create_effect(sox_find_effect("input"));
sox_args[0] = (char*)input;
assert(sox_effect_options(e, 1, sox_args) == SOX_SUCCESS);
assert(sox_add_effect(chain, e, &input->signal, &input->signal) ==
       SOX_SUCCESS);
free(e);
e = sox_create_effect(sox_find_effect("tempo"));
std::string tempo_str = "1.01";
sox_args[0] = (char*)tempo_str.c_str();
assert(sox_effect_options(e, 1, sox_args) == SOX_SUCCESS);
assert(sox_add_effect(chain, e, &input->signal,&input->signal) ==
       SOX_SUCCESS);
free(e);
e = sox_create_effect(sox_find_effect("output"));
sox_args[0] = (char*)output;
assert(sox_effect_options(e, 1, sox_args) == SOX_SUCCESS);
assert(sox_add_effect(chain, e, &input->signal, &input->signal) ==
       SOX_SUCCESS);
free(e);
sox_flow_effects(chain, NULL, NULL);
static const size_t maxSamples=4096;
sox_sample_t samples[maxSamples];
std::vector<sox_sample_t> audio_buffer;
for (size_t r; 0 != (r=sox_read(output,samples,maxSamples));)
    for(int i=0;i<r ;i++)
        audio_buffer.push_back(samples[i]);
std::cout << audio_buffer.size() << std::endl;

My questions are:

  • Do I correctly set up the effect chain?

  • How to read in-memory resulting audio samples?

    If I use tempo values < 1 I get the correct number of samples (in audio_buffer) from the output, but if I change it for example to 1.2 I suddenly get a very small number of sample and 0 if I use the value of 1.0. I am wondering if there is a bug in my chain configuration or data reading from the output? It is my first experience with libsox and I tried to follow examples, but I got stuck here.

  • Thank you in advance for the help!

    Thank you!

  • Your effect chain is ok and you can check that it gives correct output buffer by writing it to file - just replace this line in your code:
  • sox_format_t* output = sox_open_memstream_write(&buffer, &buffer_size, &input->signal, &input->encoding, "raw", NULL);

    to this one:

    sox_format_t* output = sox_open_write("2.wav", &input->signal, &input->encoding, "raw", NULL, NULL);

  • Regarding the memory output buffer issue - I studied libsox code, it seems there is a bug in its memory buffer treatment. As a workaround I would suggest you to add output->olength = 0; before reading output buffer, then it seems to work correctly.
  • So, your code will look like this:

    if (std::stof(tempo_str) >= 1.0) { // use workaround only if tempo >= 1.0 output->olength = 0; std::vector<sox_sample_t> audio_buffer; for (size_t r; 0 != (r=sox_read(output,samples,maxSamples));) for(int i=0;i<r ;i++) audio_buffer.push_back(samples[i]);

    UPD: use workaround only when tempo >= 1.0

    Thank you, Sergey for the answer and your help (I lost hope already :) ). I still observer quite a weird behavior: if I set tempo to 0.5 the buffer length is the same as the original utterance, but it should be twice as long :( – Egor Lakomkin Aug 29, 2018 at 11:07 @EgorLakomkin, yes, there is the problem with this workaround. You could try to apply it only if the tempo factor is >= 1.0 – SergeyLebedev Aug 29, 2018 at 12:02 BTW I reported this bug: sourceforge.net/p/sox/bugs/314, however main SoX repository seems to be abandoned by its maintainers – SergeyLebedev Aug 29, 2018 at 14:35

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.