1

我对一些单元测试代码有疑问,每次执行都会给出不同的结果。我将其追踪回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()不会遇到这个问题(非确定性)。

这里发生了什么?

4

1 回答 1

0

查看代码,我看到在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()

我显然在这里错过了一些对图书馆有更多了解的人可能能够解释的东西。

于 2020-09-14T23:38:42.957 回答