【问题标题】:Proper way to chain several effects with libSox and read the output data使用 libSox 链接多个效果并读取输出数据的正确方法
【发布时间】:2018-08-18 12:17:48
【问题描述】:

我正在尝试以编程方式对 libSox 应用一些效果,但我目前无法理解我是否做得对。例如,我需要应用速度和增益效果,并在缓冲区中读取生成的音频以进行进一步处理。文档真的很稀缺,谷歌搜索没有成功。 这是我的代码:

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;

我的问题是:

  1. 我是否正确设置了效果链?

  2. 如何读取内存中的音频样本?

    如果我使用速度值

提前感谢您的帮助!

谢谢!

【问题讨论】:

    标签: c++ audio sox libsox


    【解决方案1】:
    1. 您的效果链没有问题,您可以通过将其写入文件来检查它是否提供了正确的输出缓冲区 - 只需在您的代码中替换此行:

    sox_format_t* output = sox_open_memstream_write(&amp;buffer, &amp;buffer_size, &amp;input-&gt;signal, &amp;input-&gt;encoding, "raw", NULL);

    到这个:

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

    1. 关于内存输出缓冲区问题 - 我研究了libsox 代码,似乎它的内存缓冲区处理存在错误。作为一种解决方法,我建议您在读取output 缓冲区之前添加output-&gt;olength = 0;,然后它似乎可以正常工作。

    因此,您的代码将如下所示:

    ...
    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:仅在 tempo &gt;= 1.0 时使用解决方法

    【讨论】:

    • 谢谢你,谢尔盖的回答和你的帮助(我已经失去了希望:))。我仍然观察到一个非常奇怪的行为:如果我将 tempo 设置为 0.5,则缓冲区长度与原始话语相同,但它应该是原来的两倍 :(
    • @EgorLakomkin,是的,这个解决方法存在问题。仅当 tempo factor >= 1.0 时,您才可以尝试应用它
    • 顺便说一句,我报告了这个错误:sourceforge.net/p/sox/bugs/314,但主要的 SoX 存储库似乎已被其维护者抛弃
    猜你喜欢
    • 1970-01-01
    • 2011-07-30
    • 1970-01-01
    • 2013-09-22
    • 1970-01-01
    • 1970-01-01
    • 2011-06-17
    • 2020-07-31
    • 2019-03-02
    相关资源
    最近更新 更多