根据其样本计算波形的PDF


27

不久前,我尝试了不同的方式来绘制数字波形,而我尝试做的一件事是代替幅度包络线的标准轮廓,将其显示得更像示波器。这是示波器上的正弦波和方波:

在此处输入图片说明

最简单的方法是:

  1. 在输出图像的每个水平像素中将音频文件分成一个块
  2. 计算每个块的样本幅度直方图
  3. 通过亮度将直方图绘制为像素列

它产生如下内容: 在此处输入图片说明

如果每个块中有很多样本,并且信号的频率与采样频率无关,则效果很好。例如,如果信号频率恰好是采样频率的整数倍,则采样将始终在每个周期中以完全相同的幅度发生,并且直方图将只是几个点,即使在这些点之间存在实际的重构信号也是如此。该正弦脉冲应与左上角一样平滑,但这不是因为它正好是1 kHz,并且采样始终出现在相同的点附近:

在此处输入图片说明

我尝试增加采样数以增加点数,但这并不能解决问题,仅在某些情况下有助于解决问题。

因此,我真正想要的是一种从其数字样本(幅度与时间)计算连续重构信号的真实PDF(概率与幅度)的方法。我不知道该使用什么算法。通常,函数的PDF是其反函数的导数。

PDF的sin(x):ddxarcsinx=11x2

但是我不知道如何计算逆函数是多值函数的波,或者如何快速进行计算。将其分解为分支,计算每个的逆,取导数并将它们加在一起?但这很复杂,而且可能有更简单的方法。

该“内插数据的PDF”也适用于我进行GPS轨迹的核密度估计的尝试。它应该是环形的,但是因为它仅查看样本,而没有考虑样本之间的插值点,所以KDE看起来更像是一个驼峰而不是一个圆环。如果我们只知道样本,那么这就是我们所能做的最好的。但是样本并不是我们所知道的。我们也知道样本之间存在一条路径。对于GPS,没有像带宽有限的音频那样完美的Nyquist重建,但是基本思想仍然适用,插值函数有些猜测。


您是否有感兴趣的多值函数示例?您可能必须沿着对您的物理数据最有意义的分支切面进行评估。
Lorem Ipsum

您对绘制此类图的方式是否更感兴趣,或者该图只是有关计算PDF的问题的动机?
datageist

@yoda:好吧,上面的正弦波函数是通过仅取半个周期,求反并取导数来找到的,因为每个半周期的PDF与下一个相同。但是,要获得整个任意音频信号的值,您不能做那个假设。我认为您需要将其划分为“分支剪切”,依次获取每个PDF并将它们汇总在一起?
endlith 2011年

@datageist:嗯。我对绘制这种图的方式很感兴趣,但是这种图 PDF。产生相同或非常相似结果的快捷方式是可以的。
endlith 2011年

@endolith,哦,是的,我明白。只是一个关于重点的问题(即哪种捷径是合理的)。
datageist

Answers:


7

内插到原始速率的几倍(例如8倍过采样)。这使您可以假设分段线性信号。与无限分辨率,波形的连续sin(x)/ x内插相比,该信号的误差很小。

假设每过采样值都有一条从一个值到下一个值的连续线。使用之间的所有值。这为您提供了一个从y1到y2的水平细切片,可以将其累积为任意分辨率PDF。每个矩形概率片都必须缩放到1 / nsamples区域。

即使在采样周期和波形之间存在基本关系的情况下,使用样本之间的线而不是样本本身也可以防止“ spikey” PDF。


我已经为线性插值直方图编写了一个函数,但这很狡猾。您知道与此相关的现有代码吗?
endlith 2011年

即使没有过采样,线性内插对于大多数波形也会产生巨大的差异。1 kHz正弦现在看起来大体上像997 Hz正弦。现在,采样值不再只是水平线,而是它们之间的水平色带。通过过采样,也可以平滑条带。通过FFT重采样以及与相邻块的一些重叠,我应该能够使其达到真实的采样间峰值。我需要使插值直方图代码更快,但是…
endolith 2011年

为此,我完全重写了我的脚本,我想这一次我得到了直方图和抗锯齿功能:gist.github.com/endolith/652d3ba1a68b629ed328
endolith


7

实际上,我要用的是Jason R的“随机重采样器”,而后者又是yoda随机采样的基于预采样信号的实现。

我已经对每个两个样本之间的一个随机点使用了简单三次插值。对于原始合成音(从饱和的,无带宽限制的方形信号+偶次谐波衰减到正弦),它看起来像这样:

随机重采样合成器PDF

让我们将其与更高采样率的版本进行比较,

在此处输入图片说明

和一个具有相同采样率但没有插值的怪异对象。

在此处输入图片说明

此方法的显着伪像是方形区域中的过冲,但这实际上是经过Sinc滤波的信号的PDF(如我所说,我的信号没有带宽限制),并且看起来也更好如果是音频信号,则比峰值高。

代码(Haskell):

cubInterpolate vll vl v vr vrr vrrr x
    = v*lSpline x + vr*rSpline x
      + ((vr-vl) - (vrr-vll)/4)*ldSpline x
      + ((vrr-v) - (vrrr-vl)/4)*rdSpline x
     where lSpline x = rSpline (1-x)
           rSpline x = x*x * (3-2*x)
           ldSpline x = x * (1 + x*(x-2))
           rdSpline x = -ldSpline (1-x)

                   --  rand list   IN samples  OUT samples
stochasticAntiAlias :: [Double] -> [Double] -> [Double]
stochasticAntiAlias rs (lsll:lsl:lsc:lsr:lsrr:[]) = []
stochasticAntiAlias (r:rLst) (lsll:lsl:lsc:lsr:lsrr:lsrrr:t)
    = ( cubInterpolate lsll lsl lsc lsr lsrr lsrrr r )
          : stochasticAntiAlias rLst (lsll:lsl:lsc:lsr:lsrr:lsrrr:t)

rand list 是范围为[0,1]的随机变量的列表。


1
看起来很棒。+1为Haskell代码。
datageist

是的,它应该超出样本值。我实际上还计划为每个像素列都设置一个峰值,可能基于最大样本间峰值而不是仅基于最大样本而得出不同的结果。flic.kr/p/7QAScX之类的波形说明了为什么这样做是必要的。
endlith 2011年

您所说的“高采样版本”是指它是高采样的,但仍然是均匀采样的吗?那就是蓝点?
endolith 2011年

1
@endolith首先,它只是以较高的采样率计算出的原始波形。本质上,像蓝点代表以192 kHz采样的声音,而最下层的黄点则代表24 kHz的天真降采样。上面的黄点是stochasticAntiAlias这个。但是,在两种情况下,较高采样率的版本确实是统一速率。
大约

5

尽管您的方法在理论上是正确的(并且对于非单调函数需要稍作修改),但是要计算泛型函数的逆函数极其困难。正如您所说,您必须处理分支点和分支切口,这是可行的,但是您真的不想这么做。

正如您已经提到的,常规采样对相同的点集进行采样,因此,在不采样的区域(即使满足奈奎斯特标准),很容易受到估计不佳的影响。在这种情况下,较长时间的采样也无济于事。

通常,在处理概率密度函数和直方图时,从随机抽样的角度考虑要比常规抽样更好(请参见链接的答案以获取介绍)。通过随机抽样,可以确保每个点被“命中”的可能性均等,并且是估计pdf的更好方法。

f(x)=sin(20πx)+sin(100πx)fs=1000fN=1001000 每秒采样(均匀分布)(此处我不使用Hz,因为这意味着不同的含义),持续30秒给出了右侧的图(相同的装仓)。

您可以轻松地看到,尽管它很吵,但是它比实际的PDF更好,比右边的PDF更近似,后者在多个间隔中显示零,而在其他多个间隔中则显示较大的误差。通过延长观察时间,您可以减小右侧观察值的方差,最终在大观察值的范围内收敛到精确的PDF(黑色虚线)。

在此处输入图片说明


1
“很难计算一个泛型函数的逆函数”嗯,这不是一个函数,而是一系列样本,因此找到逆函数只是交换样本的x和y坐标,然后重新采样以适合新的坐标系。反正我无法更改采样。我们正在谈论使用统一采样创建的预先存在的数据。
endlith 2011年

4

核密度估计

估计波形PDF的一种方法是使用核密度估计器

x(n)K(x)δ(xx(n))P^

P^(x)=n=0NK(xx(n))

更新:有趣的其他信息。

x(n)n=0,1,...,N1X(k)

X(k)=n=0N1x(n)eȷ2πnk/N

X(k)eȷ2πnk/N

x(n)=1Nk=0N1X(k)eȷ2πnk/N

因此,一个猜测什么你aftermight是卷积每个傅立叶分量在一起的所有PDF文件:

|X(k)|11x2

X(k)x(n)

不过,还需要更多的思考!


我想到了这一点,但是密度估计用于估计未知的概率密度函数。由于有奈奎斯特采样定理,因此整个波形是准确已知的,确切的概率密度函数也应该是已知的。如果可以在速度与准确性之间进行权衡,我可以估算一下,但是必须有一种方法可以从中获得实际的PDF。类似地,可以通过在每个样本上放置一个Sinc函数并将它们相加来生成重构波形。可以使用sinc函数的PDF作为内核来创建PDF吗?我认为它不是那样的。
endlith 2011年

就像,我认为这不能解决信号采样是采样频率的约数的问题。它没有考虑样本之间的重构波形,对吗?它只是模糊了PDF中的每个点以尝试填补空白。尝试对GPS轨迹进行内核密度估计时,我遇到了类似的问题,因为它没有考虑样本之间的值。
endolith 2011年

4

正如您在评论中指出的那样,能够仅使用样本和内插带限信号的Sinc函数的PDF来计算重构信号的直方图将很有吸引力。不幸的是,我认为这是不可能的,因为Sinc的直方图并没有信号本身具有的所有信息。遇到每个值的时域位置上的所有信息都会丢失。这使得无法对Sinc的缩放比例和时延版本的总和建模,这是您想要的,以便在不实际执行信号采样的情况下计算信号的“连续”或上采样版本的直方图上采样。

我认为您将插值作为最佳选择。您确实指出了几个使您不想这样做的问题,我认为可以解决:

  • 计算费用:当然,这始终是一个相对的问题,具体取决于您要用于此目的的特定应用程序。根据您发布到已收集的效果图库的链接,我假设您要执行此操作以可视化音频信号。无论您是对实时应用程序还是脱机应用程序感兴趣,我都建议您为高效的插值器制作原型,并查看它是否真的太昂贵。多相重采样是一种灵活的好方法(您可以使用任何理性因素)。

  • π


但是,如果波形为44.1 /πkHz,该怎么办?:)不过,这是个好建议。是否有随机重采样之类的东西?或者说真的,我猜想最好的方法是对样本进行不均匀的重新采样,以使新样本完全适合y维度的分箱,而不是均匀地分布于x维度。不确定是否有这样做的方法
Endolith 2011年

2
您可以使用Farrow结构轻松实现“随机”重采样器。这种方案允许通过使用多项式(通常为三次多项式)进行插值来实现任意分数采样延迟。您可以维护一个样本间相位累加器,类似于NCO中使用的累加器,对于每个输出(重采样)样本,该累加器将以采样间隔的伪随机分数递增。累加器的值用作Farrow插值器的输入,定义每个输出的分数延迟量。
杰森R

嗯,要澄清一下,Farrow只是常规旧多项式插值的处理器/内存优化版本?
endolith 2011年

1
是。这只是实现基于多项式的任意分数延迟的有效结构。
詹森·R

但是,三次插值只是一个近似值。我想知道真实的样本间峰值,但在极端峰值下似乎效果不佳:stackoverflow.com/questions/1851384/… 实际上,似乎是一个具有[...,-1, 1,-1,1,1,-1,1,-1,...]会产生一个无限的采样间峰值,所以我不确定这在实际中有多重要。
2011年

0

您需要平滑直方图(这将产生与使用核方法相似的结果)。究竟如何执行平滑操作需要进行实验。也许也可以通过插值来完成。除了平滑以外,我相信如果以某种方式对波形进行升采样,即采样频率“显着高于”输入中的最高频率,您也会得到更好的结果。在正弦波与采样频率相关的“棘手”情况下,这应该会有所帮助,使得直方图中只有几个bin会被填充。如果极端的话,足够高的采样率将为您提供良好的绘图而无需平滑。因此,将上采样与某种平滑相结合应能产生更好的图。

您以一个1kHz音调为例,该曲线图与您的预期不符。这是我的建议(Matlab /八度代码)

pixels_vertical = 100;
% This needs to be tuned to your configuration and acceptance
upsampling_factor = 16*(pixels_vertical/100); 
fs_original = 48000;
fsine = 1000; % in Hz
fs_up = upsampling_factor*fs_original;
duration = 1; % in seconds
x = sin(2*pi*fsine*[0:duration*fs_up]/fs_up);
period_in_samples = fs_up/fsine;
hist_points = linspace(-1,1,pixels_vertical);
istart = 1;
iend   = period_in_samples;
pixel_values = hist(x(istart:iend), hist_points);
% smooth pixel values
[b,a] = butter(2,0.2);
pixel_values_smooth = filtfilt(b,a,pixel_values);
figure;hold on;
plot(hist_points, pixel_values);
plot(hist_points, pixel_values_smooth,'r');

为您的1000Hz音调得到 在此处输入图片说明

您需要做的是根据您的喜好调整upsampling_factor表达式。

仍然不能100%确切地确定您的要求是什么。但是,使用上面的上采样和平滑原理,您将获得1kHz音调(由Matlab制作)。请注意,在原始直方图中,有许多零命中的bin。

在此处输入图片说明


是的,它确实需要某种类型的插值作为算法的一部分。仅对直方图进行平滑是无法做到的,因为直方图是离散点,而不是重构波形。进行上采样的唯一方法是,如果采样到的像素数大于垂直像素的采样数,那将是很费力的方法,需要很长时间。
endlith 2011年

或计算作用在输出内插,而无需实际的插值
endolith
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.