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
–
–
–
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.