使用 libsox 在不改变速度的情况下改变音频文件的音调
Change audio file pitch without changing tempo using libsox
我开发了一个简单的应用程序,可以使用 libsox(使用 this example)改变音频文件的音高。
这是我的代码。它使用 2 个输入参数 - 输入文件路径和输出文件路径:
#include <sox.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
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];
sox_signalinfo_t interm_signal; /* @ intermediate points in the chain. */
sox_encodinginfo_t out_encoding = {
SOX_ENCODING_SIGN2,
16,
0,
sox_option_default,
sox_option_default,
sox_option_default,
sox_false
};
sox_signalinfo_t out_signal = {
16000,
1,
0,
0,
NULL
};
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], &out_signal, &out_encoding, NULL, NULL, NULL));
chain = sox_create_effects_chain(&in->encoding, &out->encoding);
interm_signal = in->signal; /* NB: deep copy */
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, &interm_signal, &in->signal) == SOX_SUCCESS);
free(e);
e = sox_create_effect(sox_find_effect("pitch"));
args[0] = "1000";
assert(sox_effect_options(e, 1, args) == SOX_SUCCESS);
assert(sox_add_effect(chain, e, &interm_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, &interm_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;
}
但是我从上面的代码得到的结果是一个速度改变的文件。
以下是输入和输出的详细信息:
Input File : 'input.wav'
Channels : 1
Sample Rate : 16000
Precision : 16-bit
Duration : 00:00:11.87 = 189921 samples ~ 890.255 CDDA sectors
Input File : 'output.wav'
Channels : 1
Sample Rate : 16000
Precision : 16-bit
Duration : 00:00:21.15 = 338401 samples ~ 1586.25 CDDA sectors
另一件事,sox 应用程序运行良好。
sox input.wav output_app.wav pitch 1000
它生成一个与输入具有相同持续时间的文件:
Input File : 'output_app.wav'
Channels : 1
Sample Rate : 16000
Precision : 16-bit
Duration : 00:00:11.87 = 189921 samples ~ 890.255 CDDA sectors
这里有人遇到同样的问题吗?还是我必须向 sox_effect 提供任何其他选项才能使此效果正常工作?
找了一段时间,感谢this。我发现为了保持音频节奏,必须在 pitch effect.[=11 之后将 rate effect 添加到效果链中=]
libsox 的 "pitch" 效果会改变音频采样率。
如果您注意到 "pitch" 之后的采样率,您会发现它已被更改。
为了以相同的采样率保存音频文件,您需要在 "pitch" 效果之后添加 "rate" 效果。
像这样:
#include <sox.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
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];
sox_signalinfo_t interm_signal; /* @ intermediate points in the chain. */
sox_encodinginfo_t out_encoding = {
SOX_ENCODING_SIGN2,
16,
0,
sox_option_default,
sox_option_default,
sox_option_default,
sox_false
};
sox_signalinfo_t out_signal = {
16000,
1,
0,
0,
NULL
};
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], &out_signal, &out_encoding, NULL, NULL, NULL));
chain = sox_create_effects_chain(&in->encoding, &out->encoding);
interm_signal = in->signal; /* NB: deep copy */
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, &interm_signal, &in->signal) == SOX_SUCCESS);
free(e);
e = sox_create_effect(sox_find_effect("pitch"));
args[0] = "1000";
assert(sox_effect_options(e, 1, args) == SOX_SUCCESS);
assert(sox_add_effect(chain, e, &interm_signal, &out->signal) == SOX_SUCCESS);
free(e);
// Note: interm_signal.rate changed now, we need to rate it back
e = sox_create_effect(sox_find_effect("rate"));
args[0] = "-m";
assert(sox_effect_options(e, 1, args) == SOX_SUCCESS);
assert(sox_add_effect(chain, e, &interm_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, &interm_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;
}
可选地,您可以在"rate"之后添加一个"dither"效果以获得更好的效果。
我开发了一个简单的应用程序,可以使用 libsox(使用 this example)改变音频文件的音高。 这是我的代码。它使用 2 个输入参数 - 输入文件路径和输出文件路径:
#include <sox.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
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];
sox_signalinfo_t interm_signal; /* @ intermediate points in the chain. */
sox_encodinginfo_t out_encoding = {
SOX_ENCODING_SIGN2,
16,
0,
sox_option_default,
sox_option_default,
sox_option_default,
sox_false
};
sox_signalinfo_t out_signal = {
16000,
1,
0,
0,
NULL
};
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], &out_signal, &out_encoding, NULL, NULL, NULL));
chain = sox_create_effects_chain(&in->encoding, &out->encoding);
interm_signal = in->signal; /* NB: deep copy */
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, &interm_signal, &in->signal) == SOX_SUCCESS);
free(e);
e = sox_create_effect(sox_find_effect("pitch"));
args[0] = "1000";
assert(sox_effect_options(e, 1, args) == SOX_SUCCESS);
assert(sox_add_effect(chain, e, &interm_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, &interm_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;
}
但是我从上面的代码得到的结果是一个速度改变的文件。 以下是输入和输出的详细信息:
Input File : 'input.wav'
Channels : 1
Sample Rate : 16000
Precision : 16-bit
Duration : 00:00:11.87 = 189921 samples ~ 890.255 CDDA sectors
Input File : 'output.wav'
Channels : 1
Sample Rate : 16000
Precision : 16-bit
Duration : 00:00:21.15 = 338401 samples ~ 1586.25 CDDA sectors
另一件事,sox 应用程序运行良好。
sox input.wav output_app.wav pitch 1000
它生成一个与输入具有相同持续时间的文件:
Input File : 'output_app.wav'
Channels : 1
Sample Rate : 16000
Precision : 16-bit
Duration : 00:00:11.87 = 189921 samples ~ 890.255 CDDA sectors
这里有人遇到同样的问题吗?还是我必须向 sox_effect 提供任何其他选项才能使此效果正常工作?
找了一段时间,感谢this。我发现为了保持音频节奏,必须在 pitch effect.[=11 之后将 rate effect 添加到效果链中=]
libsox 的 "pitch" 效果会改变音频采样率。 如果您注意到 "pitch" 之后的采样率,您会发现它已被更改。 为了以相同的采样率保存音频文件,您需要在 "pitch" 效果之后添加 "rate" 效果。 像这样:
#include <sox.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
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];
sox_signalinfo_t interm_signal; /* @ intermediate points in the chain. */
sox_encodinginfo_t out_encoding = {
SOX_ENCODING_SIGN2,
16,
0,
sox_option_default,
sox_option_default,
sox_option_default,
sox_false
};
sox_signalinfo_t out_signal = {
16000,
1,
0,
0,
NULL
};
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], &out_signal, &out_encoding, NULL, NULL, NULL));
chain = sox_create_effects_chain(&in->encoding, &out->encoding);
interm_signal = in->signal; /* NB: deep copy */
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, &interm_signal, &in->signal) == SOX_SUCCESS);
free(e);
e = sox_create_effect(sox_find_effect("pitch"));
args[0] = "1000";
assert(sox_effect_options(e, 1, args) == SOX_SUCCESS);
assert(sox_add_effect(chain, e, &interm_signal, &out->signal) == SOX_SUCCESS);
free(e);
// Note: interm_signal.rate changed now, we need to rate it back
e = sox_create_effect(sox_find_effect("rate"));
args[0] = "-m";
assert(sox_effect_options(e, 1, args) == SOX_SUCCESS);
assert(sox_add_effect(chain, e, &interm_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, &interm_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;
}
可选地,您可以在"rate"之后添加一个"dither"效果以获得更好的效果。