使用 libsoxr 进行确定性抖动
Posted
技术标签:
【中文标题】使用 libsoxr 进行确定性抖动【英文标题】:deterministic dithering with libsoxr 【发布时间】:2020-09-14 23:38:42 【问题描述】:我对某些单元测试代码有疑问,每次执行都会给出不同的结果。 我将其追溯到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()
不存在这个问题(非确定性)。
这是怎么回事?
【问题讨论】:
【参考方案1】:查看代码,我发现在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()
设置的。
我显然在这里遗漏了一些对图书馆有更多了解的人可能能够解释的东西。
【讨论】:
以上是关于使用 libsoxr 进行确定性抖动的主要内容,如果未能解决你的问题,请参考以下文章