Skip to content

Sine Sweep Deconvolution

Published: at 10:12 AM (5 min read)

Table of Contents

Open Table of Contents

Motivation

In the Northwestern Haptics Group, I’m attempting to characterize the lateral dynamic compliance and viscoelastic parameters of the fingepad in frequencies relevant to touch, which range from 30 to around 350 Hz.

In many systems, we provide an excitation that resembles an impulse (such as striking a baseball bat with a hammer). However, exciting the finger with a sharp impulse is not very practical, since it can be noisy, painful, and provide low SNR.

Instead, a common technique is to use a sine sweep method (linear or exponential), originally developed for acoustics, to obtain clean and artifact-free impulse responses. These sweeps spread energy over time, then mathematically repack it into an IR - while allowing for clean seperation of nonlinear distortion (harmonics) from the linear response. This information is adapted from this paper.

System Models and Signals

In my setup, I’m actuating a carbon fiber pin that indents into my finger, and a voice coil actuates the pin in a lateral motion. My input signal is the force (which I approximate by multiplying the force factor with the current going through the coil), and the output is pin displacement (scaled from LDV). We want to find the IRs of various setups (finger placement, indendation depth, orientation of finger, etc.). Here are some actual outputs:

example

However, the technique can be used to resolve IRs for any system that can be reasonably approximated as LTI for the duration of the sweep, with mild time variance and nonlinearity (ESS is pretty robust to both in practice).

Exponential Sweep

Let the drive signal be the exponential sweep x(t)x(t) of duration TT, starting at ω1=2πf1\omega_1 = 2\pi f_1 and ending at ω2=2πf2\omega_2 = 2\pi f_2:

x(t)=sin ⁣(ω1Tln ⁣(ω2ω1)(etTln(ω2/ω1)1)),0tTx(t) = \sin \!\Bigg( \frac{\omega_1 T}{\ln\!\big(\tfrac{\omega_2}{\omega_1}\big)} \left( e^{\tfrac{t}{T}\ln(\omega_2/\omega_1)} - 1 \right) \Bigg), \quad 0 \le t \le T

The instantaneous frequency is

ω(t)=ω1exp ⁣(tTln(ω2ω1)).\omega(t) = \omega_1 \, \exp\!\Big(\tfrac{t}{T}\ln(\tfrac{\omega_2}{\omega_1})\Big).

Because ω(t)\omega(t) grows exponentially, low frequencies are excited for longer (higher SNR at low ff), while high frequencies sweep quickly. The resulting spectrum is “pink” (about 3dB-3 \,\text{dB}/octave), so the inverse filter must compensate by +3dB+3 \,\text{dB}/octave.

Aperiodic Deconvolution and Inverse Filter

We want the system’s IR h(t)h(t):

h(t)=y(t)f(t),h(t) = y(t) \otimes f(t),

where y(t)y(t) is the measured output (finger displacement) and f(t)f(t) is the inverse filter.

We take advantage of the following:

  1. Aperiodic convolution (not circular), avoiding wrap-around artifacts.
  2. Time-Reversal Mirror (TRM): take the time-reverse of the sweep and apply amplitude correction.

Because the sweep has a pink spectrum, the inverse filter amplitude must grow +3dB\propto +3 \,\text{dB}/oct. Thus:

f(t)=reverse[x(t)]w(t),w(t)et/K,f(t) = \text{reverse}[x(t)] \cdot w(t), \quad w(t) \sim e^{t/K},

with K=T/ln(f2/f1)K = T / \ln(f_2/f_1).

When y(t)y(t) is convolved with f(t)f(t):

Pre-ringing and Bandwidth

If you taper the sweep (fade-out) or truncate bandwidth, the recovered IR looks like a sinc with oscillatory pre-ringing.

pre-ringing

Fixes:

Frequency-domain inversion (Kirkeby filter)

Given a measured IR h(t)h(t), compute its FFT:

H(f)=F{h(t)}.H(f) = \mathcal{F}\{ h(t) \}.

Then build a regularized inverse filter:

C(f)=H(f)H(f)2+ε(f),C(f) = \frac{H^*(f)}{|H(f)|^2 + \varepsilon(f)},

where ε(f)\varepsilon(f) is small inside the sweep band, larger outside.

Inverse transform:

c(t)=F1{C(f)}.c(t) = \mathcal{F}^{-1}\{C(f)\}.

This compacts the IR, reducing pre-ringing and whitening the response.

Practical Usage

Pulsive noise during sweepa

In some cases, there may be pulsive artifacts (like a tool drop). These are described can be described as a broadband click, and they deconvolve into descending sweep artifacts.

The best way to remove these is is to compute the instantaneous frequency at the click time click time tct_c,

finst(tc)=f1exp ⁣(tcTln(f2f1)),f_\text{inst}(t_c) = f_1 \exp\!\Big(\tfrac{t_c}{T}\ln(\tfrac{f_2}{f_1})\Big),

then apply a narrow band-pass filter around finst(tc)f_\text{inst}(t_c) before deconvolution.

Clock Mismatches

If playback and recording clocks drift, the IR skews in the time-frequency plane. There are two fixes to this:

Averaging

It is good practice not to average many short sweeps, as it underestimates the high-frequency tails. Instead, it is recommended to use one long sweeps, and if repeats are necessary (example, skin varies from person to person in my application), average in the frequency domain.

H1(f)=GLR(f)GLL(f),H_1(f) = \frac{G_{LR}(f)}{G_{LL}(f)},

where GLRG_{LR} is the cross-spectrum and GLLG_{LL} the auto-spectrum.

Basic Example

Here’s a basic example of what a deconvolution and seperation of linear IR from its harmonics could look like:

matlab output

clear; clc; close all;

fs = 20000; T = 5; f1 = 10; f2 = 800; pad = 0.5;

t  = (0:1/fs:T)';
K  = T / log(f2/f1);
phi = 2*pi*f1*K*(exp(t/K)-1);
x   = sin(phi);
x   = [x; zeros(round(pad*fs),1)];
t   = (0:numel(x)-1)'/fs;

fade = round(0.01*fs);
x(1:fade) = x(1:fade).*linspace(0,1,fade)';

wCorr  = exp((0:1/fs:T)'/K);
f_inv  = flipud(sin(phi)) ./ wCorr;
f_inv  = [f_inv; zeros(round(pad*fs),1)];

[b,a] = butter(2, [20 500]/(fs/2), 'bandpass');
y_lin = filter(b,a,x);
y = y_lin + 0.06*(y_lin.^2) + 0.03*(y_lin.^3) + 2e-4*randn(size(y_lin));

h_rec = fftfilt(f_inv, y);

[~, i0] = max(abs(h_rec));
i1 = max(1, i0 - round(0.05*fs));
i2 = min(numel(h_rec), i0 + round(0.2*fs));
h_win = h_rec(i1:i2);

subplot(4,1,1);
plot(t, x); title('Input Sweep');

subplot(4,1,2);
plot(t, y); title('Output Signal');

subplot(4,1,3);
plot(h_rec); title('Recovered IR'); hold on
xline(i1,'r--'); xline(i2,'r--');

subplot(4,1,4);
plot(h_win); title('Windowed IR');