【问题标题】:What is the correct method to upsample?上采样的正确方法是什么?
【发布时间】:2014-11-25 05:28:09
【问题描述】:

我有一组 75 Hz 的样本,我想以 128 Hz 的频率存储它们。如果是 64 赫兹和 128 赫兹,那非常简单,我只需将所有样本加倍。但是,如果采样率不是彼此的一小部分,那么正确的方法是什么?

【问题讨论】:

  • 将所有样本加倍并不是将采样率加倍的正确方法。
  • @interjay 你能详细说明一下吗?
  • 答案已经做了。重复采样会增加噪音。有关正确方法的上采样,请参阅答案或谷歌。
  • 终于完成编辑了。用几何方法为您的问题添加了答案。

标签: c math signal-processing sampling resampling


【解决方案1】:

当您想避免过滤时,您可以:

  1. 将信号处理为一组连接的插值三次曲线

    但这一点与使用线性插值相同。在不了解您的信号和目的的情况下,您无法构建valid 系数(不会破坏信号准确性),例如如何在此处构建这种立方外观:

    在该链接内的项目符号 #3 中是我使用的系数。我认为即使您的目的也足够了,所以您可以尝试一下。如果你想做自定义插值看这里:

  2. 创建一个函数,该函数可以从采样开始的给定时间返回信号中的点

    所以做类似的事情

    double signal(double time);
    

    其中time 是从采样开始算起的时间,以 [s] 为单位。在此函数中计算您需要访问的 4 个样本。

    ix = floor(time*75.0);
    

    为您提供曲线起点样本索引。三次曲线需要 4 个点,一个在曲线之前,一个在曲线之后……所以对于插值三次点 p0,p1,p2,p3 使用样本 ix-1,ix,ix+1,ix+2。计算三次系数a0,a1,a2,a3 并计算三次曲线参数t(我使用范围<0,1>)所以

    t=(time*75.0); t-=floor(t);
    

    • 绿色 - 实际曲线段
    • aqua - 实际曲线段控制点 = 75.0 Hz 样本
    • red - 曲线参数插值参数t
    • 灰色 - 实际时间

    抱歉我忘了画实际的输出信号点应该是绿色和灰色的交点

  3. 只需对采样数据进行 for 循环,时间步长为 1/128 s

    类似这样的:

    double time,duration=samples*75.0,dt=1.0/128.0;
    double signal128[???];
    for (time=0.0,i=0;time<duration;i++,time+=dt)
     signal128[i]=signal(time);
    

    samples 是以 75.0 Hz 采样的样本中的输入信号数组大小

[注释]

  • for/duration 可以在整数上完成...
  • 将信号数据类型更改为您需要的类型
  • signal(time) 内,您需要处理边缘情况(信号的开始和结束)
  • 因为在第一个采样之前和最后一个采样之后的信号中没有定义点。您可以复制它们或镜像下一点(镜像更好)。
  • 整个事情可以更改为连续处理而无需缓冲区只需要记住信号中的最后 4 个点,以便您可以在 RT 中执行此操作。粗略地说,您将延迟 2-3 个 75.0 Hz 样本……当您将所有这些放在一起时,您会发现这是一个 FIR 滤波器:)
  • 如果您需要保留更多,则首先推导添加更多点...

【讨论】:

  • 我会在 for 循环中使用与 i 的比较,这样您就不必担心导致缓冲区溢出的舍入错误。
【解决方案2】:

您不需要先上采样然后再下采样。

相反,可以使用足够宽的低通插值内核(例如加窗 Sinc 函数)以所需的时间间隔对所有新采样点进行插值。这通常通过使用预先计算的多相滤波器组来完成,或者直接使用,或者使用滤波器表的附加线性插值。但如果性能不重要,那么可以直接计算每个插值点的每个系数。

【讨论】:

【解决方案3】:

最简单的方法是将采样率上采样到两个采样率的 LCM,然后进行下采样 - 这样您就可以获得整数上采样/下采样比率。在您的情况下,两个采样率中没有公因子,因此您需要将采样率提高 128 到 9.6 kHz,然后再降低采样率 75 到 128 Hz。对于上采样,您在每个采样之间插入 127 0 个采样,然后应用合适的滤波器(37 Hz LPF,Fs = 9.6 kHz),然后通过每 75 个采样进行下采样。过滤器设计是唯一棘手的部分,但有一些在线工具可以解决这个问题。

或者查看处理重采样的第三方库,例如sox.

【讨论】:

  • 我需要用纯 C 语言实现过滤器,并且我的设备中的 RAM 和 CPU 非常少。不过滤是否可以做到这一点?
  • 这取决于重采样所需的质量和准确性。您可以仅使用线性插值进行粗略的重采样,但会有伪影。我们在这里谈论什么样的信号?
  • 它是一个PPG(体积描记图)通道,它显示脉搏波。通常这是一个 8 位通道,但我有 16 位样本。难道如果我不过滤它(包括伪影),它仍然会比正确上采样的 8 位通道更准确吗?在这种情况下,它没有问题。
  • 我建议只尝试简单的线性插值而不进行任何过滤,但您可能需要了解信号中的哪些特征很重要,以及它们是否被您使用的任何重采样方案降级。您可能希望首先在 MATLAB 或 Octave 等工具中对此进行建模,以确保它能够很好地为您的应用程序工作。
【解决方案4】:

正如@Paul 提到的,您需要使用中间采样频率进行上采样和下采样。另外,需要对每次变换后的信号进行滤波,可以通过线性插值来实现:

% Parameters
F = 2;
Fs1 = 75;
Fs3 = 128;
Fs2 = lcm(Fs1,Fs3);

% Original signal
t1 = 0:1/Fs1:1;
y1 = sin(2*pi*F*t1);

% Up-sampled signal
t2 = 0:1/Fs2:1;
y2 = interp1(t1,y1,t2);

% Down-sampled signal
t3 = 0:1/Fs3:1;
y3 = interp1(t2,y2,t3);

figure;
subplot(3,1,1);
plot(t1,y1,'b*-');
title(['Signal with sampling frequency of ', num2str(Fs1), 'Hz']);
subplot(3,1,2);
plot(t2,y2,'b*-');
title(['Signal with sampling frequency of ', num2str(Fs2), 'Hz']);
subplot(3,1,3);
plot(t3,y3,'b*-');
title(['Signal with sampling frequency of ', num2str(Fs3), 'Hz']);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-24
    • 2015-10-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多