问题描述
我对某些单元测试代码有疑问,每次执行都会给它们不同的结果。 我将其追溯到libsoxr(0.1.3),发现其取决于抖动选项:
也就是说,如果使用以下命令调用soxr_create()
:
soxr_io_spec_t soxIoSpec = soxr_io_spec(SOXR_INT16_I,SOXR_INT16_I);
sxIoSpec.flags |= SOXR_NO_DITHER;
soxr_process()的输出是确定性的。
但是,如果不添加SOXR_NO_DITHER
标志,则每次执行的输出都会略有不同。
关于图书馆的另一件事使我感到惊讶。
soxr_oneshot()
不受此问题(不确定性)的困扰。
这是怎么回事?
解决方法
查看代码,我发现在soxr.c
中,抖动使用了伪随机数生成器
但是种子是从以下时间生成的实现细节:
p->seed = (unsigned long)time(0) ^ (unsigned long)(size_t)p;
该库似乎没有公开它,因此可以防止您设置特定的种子,否则每次运行测试都可以获得相同的结果。
我建议对API进行一些次要的改进,如下所示, 尽管对图书馆有更多了解的人也许可以提出更好的方法。
在Soxr.h
中添加:
typedef unsigned long soxr_seed_t;
// set or retrieve the random seed used by the dithering function
void soxr_setseed(soxr_t resampler,soxr_seed_t new_seed);
soxr_seed_t soxr_getseed(soxr_t* resampler);
在Soxr.c
中添加:
void soxr_setseed(soxr_t resampler,soxr_seed_t new_seed)
{
resampler->seed = new_seed;
}
soxr_seed_t soxr_getseed(soxr_t resampler)
{
return resampler->seed;
}
关于图书馆的一件事仍然令我惊讶的是
soxr_oneshot()
不受此问题(非确定性)的困扰。
我看不到种子如何固定或通过内部调用SOXR_NO_DITHER
设置的soxr_create()
。
我显然在这里错过了一些对图书馆有更多了解的人可以解释的东西。