2

I have a waveform which contains the phase shift information obtained from RF transceiver. It is not a regular waveform, but instead it is uneven as shown in the picture below. I have illustrate the envelope using paint, and how can I do that in MATLAB? enter image description here

I also attached the waveform.csv. In my MATLAB code, I already used an averaging filter to smooth out the raw signal.

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
Marcus Müller
  • 34,677
  • 4
  • 53
  • 94
double_espresso
  • 115
  • 2
  • 12
  • 1
    You want to draw a line from peak to peak and smooth that? In that case you can use a simple find-command to check whether a point is higher than its closest neighbours, assign the maxima to a separate array, smooth that and there's your envelope. – Adriaan Aug 26 '15 at 07:34

2 Answers2

4

A simple envelope detector can be readily implemented following the idea of a diode detector using:

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

The decayfactor should be chosen to have a decay time constant that is much longer than the uneven signal's variation, yet smaller than the reciprocal of the expected signal envelope's bandwidth. You may need to experiment a little bit, but something such as decayfactor=exp(-fmax/fs) (where fmax is your envelope bandwidth, and fs is the sampling frequency) should be a good starting value.

This would typically be followed by a low-pass filter (such as myfilter which you have provided).

As a sample execution based on the provided data, using decayfactor=exp(-5/5000) and an average filter with a 300 samples window yields the following plot (with the original data in blue and the envelope in red):

envelope plot

SleuthEye
  • 14,379
  • 2
  • 32
  • 61
  • Thank you for the suggestion and the edit. I will try it out using this envelope detector way. – double_espresso Aug 28 '15 at 03:18
  • Hi i was looking for this envelope algorithm too. For understanding the code in detail check this class "EnvelopeFollower.java" from TarsosDsp code (search on github or google). From this we can understand attack and release (basics for calculating envelope). Thanks – Diljeet Dec 23 '18 at 08:52
0

Read the code below. This should get the envelope as required. Its simple code anyone can write similar class instead of using this implementation (its GPL code), i posted this code for reference / explanation.

/*
*      _______                       _____   _____ _____  
*     |__   __|                     |  __ \ / ____|  __ \ 
*        | | __ _ _ __ ___  ___  ___| |  | | (___ | |__) |
*        | |/ _` | '__/ __|/ _ \/ __| |  | |\___ \|  ___/ 
*        | | (_| | |  \__ \ (_) \__ \ |__| |____) | |     
*        |_|\__,_|_|  |___/\___/|___/_____/|_____/|_|     
*                                                         
* -------------------------------------------------------------
*
* 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() {

    }
}
Diljeet
  • 1,896
  • 20
  • 24