【问题标题】:How to find envelope of uneven waveform如何找到不均匀波形的包络
【发布时间】:2015-11-20 02:31:18
【问题描述】:

我有一个波形,其中包含从射频收发器获得的相移信息。它不是规则的波形,而是如下图所示的不均匀波形。我已经使用油漆说明了信封,我该如何在 MATLAB 中做到这一点?

我还附上了waveform.csv。在我的 MATLAB 代码中,我已经使用了平均滤波器来平滑原始信号。

Waveform csv file

envelope.m:

clc; clear all; close all;

%% Extract data from .csv
file = '150825_px6_human_rotcw_0to60cm_Ch1.csv';
data = csvread(file, 0, 3);

%% Shift time
shift = data(1,1);
for i = 1:length(data)
    t(i) = data(i,1) - shift;
end

%% Low pass filter
filterlen = 500;
y = myfilter(data(:,2), filterlen);

%% Plot
figure;
plot(data(:,1), data(:,2));
title('Raw signal');

figure;
plot(t(1:end-filterlen+1), y);
title('After low pass filter');

myfilter.m (simple averaging filter):

function y = myfilter(x,a) 
    for i = 1:(length(x)-(a-1))
        y(i) = sum(x(i:(i+a-1)))/a;
    end
    y = y';
end

【问题讨论】:

  • 您想从峰到峰画一条线并使其平滑吗?在这种情况下,您可以使用简单的查找命令来检查一个点是否高于其最近的邻居,将最大值分配给一个单独的数组,对其进行平滑处理,这就是您的信封。

标签: matlab csv signals signal-processing software-defined-radio


【解决方案1】:

一个简单的envelope detector 可以很容易地按照二极管检测器的想法实现:

envelope = data(1,2);
for  i = 2:length(data)
    if (abs(data(i,2)) > envelope)
        envelope = abs(data(i,2));
    else
        envelope  = envelope * decayfactor;
        data(i,2) = envelope;
    end
end

decayfactor 的衰减时间常数应该比不均匀信号的变化要长得多,但要小于预期信号包络带宽的倒数。您可能需要进行一些实验,但 decayfactor=exp(-fmax/fs)(其中 fmax 是包络带宽,fs 是采样频率)应该是一个不错的起始值。

这通常会后跟一个低通滤波器(例如您提供的myfilter)。

作为基于所提供数据的示例执行,使用decayfactor=exp(-5/5000) 和具有 300 个样本窗口的平均滤波器产生以下图(蓝色为原始数据,红色为包络):

【讨论】:

  • 感谢您的建议和编辑。我将尝试使用这种包络检测器方式。
  • 嗨,我也在寻找这个包络算法。要详细了解代码,请查看 TarsosDsp 代码中的此类“EnvelopeFollower.java”(在 github 或 google 上搜索)。由此我们可以理解攻击和释放(计算包络的基础知识)。谢谢
【解决方案2】:

阅读下面的代码。这应该会根据需要得到信封。它的简单代码任何人都可以编写类似的类而不是使用这个实现(它的 GPL 代码),我发布了这个代码以供参考/解释。

/*
*      _______                       _____   _____ _____  
*     |__   __|                     |  __ \ / ____|  __ \ 
*        | | __ _ _ __ ___  ___  ___| |  | | (___ | |__) |
*        | |/ _` | '__/ __|/ _ \/ __| |  | |\___ \|  ___/ 
*        | | (_| | |  \__ \ (_) \__ \ |__| |____) | |     
*        |_|\__,_|_|  |___/\___/|___/_____/|_____/|_|     
*                                                         
* -------------------------------------------------------------
*
* TarsosDSP is developed by Joren Six at IPEM, University Ghent
*  
* -------------------------------------------------------------
*
*  Info: http://0110.be/tag/TarsosDSP
*  Github: https://github.com/JorenSix/TarsosDSP
*  Releases: http://0110.be/releases/TarsosDSP/
*  
*  TarsosDSP includes modified source code by various authors,
*  for credits and info, see README.
* 
*/


package be.tarsos.dsp;

/**
 * An envelope follower follows the envelope of a signal. Sometimes the name
 * envelope detector is used. From wikipedia:
 *  <blockquote> An envelope detector
 * is an electronic circuit that takes a high-frequency signal as input and
 * provides an output which is the envelope of the original signal. The
 * capacitor in the circuit stores up charge on the rising edge, and releases it
 * slowly through the resistor when the signal falls. The diode in series
 * rectifies the incoming signal, allowing current flow only when the positive
 * input terminal is at a higher potential than the negative input terminal.
 * </blockquote>
 * 
 * The resulting envelope is stored in the buffer in the processed AudioEvent. The class can be used thusly:
 * 
 * <pre>
 * EnvelopeFollower follower = new EnvelopeFollower(44100);
 *      
 * AudioDispatcher dispatcher = AudioDispatcher.fromFloatArray(sine, 44100, 1024, 0);
 *  
 *  
 *  dispatcher.addAudioProcessor(follower);
 *  dispatcher.addAudioProcessor(new AudioProcessor() {
 *  
 *      public boolean process(AudioEvent audioEvent) {
 *          //envelope
 *          float buffer[] = audioEvent.getFloatBuffer();
 *          for(int i = 0 ; i < buffer.length ; i++){
 *              System.out.println(buffer[i]);
 *          }
 *          return true;
 *      }
 *          
 *      public void processingFinished() {
 *      }
 *  });
 *  dispatcher.run();
 *  </pre>
 *  
 * 
 * @author Joren Six
 * 
 */
public class EnvelopeFollower implements AudioProcessor {

    /**
     * Defines how fast the envelope raises, defined in seconds.
     */
    private static final double DEFAULT_ATTACK_TIME =  0.0002;//in seconds
    /**
     * Defines how fast the envelope goes down, defined in seconds.
     */
    private static final double DEFAULT_RELEASE_TIME =  0.0004;//in seconds

    float gainAttack ;
    float gainRelease;
    float envelopeOut = 0.0f;

    /**
     * Create a new envelope follower, with a certain sample rate.
     * @param sampleRate The sample rate of the audio signal.
     */
    public EnvelopeFollower(double sampleRate){
        this(sampleRate,DEFAULT_ATTACK_TIME,DEFAULT_RELEASE_TIME);
    }

    /**
     * Create a new envelope follower, with a certain sample rate.
     * @param sampleRate The sample rate of the audio signal.
     * @param attackTime Defines how fast the envelope raises, defined in seconds.
     * @param releaseTime Defines how fast the envelope goes down, defined in seconds.
     */
    public EnvelopeFollower(double sampleRate, double attackTime,double releaseTime){
        gainAttack = (float) Math.exp(-1.0/(sampleRate*attackTime));
        gainRelease = (float) Math.exp(-1.0/(sampleRate*releaseTime));
    }

    @Override
    public boolean process(AudioEvent audioEvent) {
        float[] buffer = audioEvent.getFloatBuffer();
        calculateEnvelope(buffer);
        return true;
    }

    public void calculateEnvelope(float[] buffer){
        for(int i = 0 ; i < buffer.length ; i++){
            float envelopeIn = Math.abs(buffer[i]);
            if(envelopeOut < envelopeIn){
                envelopeOut = envelopeIn + gainAttack * (envelopeOut - envelopeIn);
            } else {
                envelopeOut = envelopeIn + gainRelease * (envelopeOut - envelopeIn);
            }
            buffer[i] = envelopeOut;
        }
    }

    @Override
    public void processingFinished() {

    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-01-26
    • 2022-07-01
    • 2016-10-19
    • 2018-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多