ShannonWavelet.java
package com.morphiqlabs.wavelet.cwt;
import com.morphiqlabs.wavelet.api.ContinuousWavelet;
import com.morphiqlabs.wavelet.exception.InvalidArgumentException;
/**
* Classical Shannon wavelet (sinc function).
*
* The Shannon wavelet is the sinc function, which has perfect
* band-pass characteristics in the frequency domain (rectangular window).
*
* ψ(t) = sinc(t) * cos(3πt/2)
*
* Properties:
* - Perfect frequency localization (rectangular in frequency)
* - Poor time localization (infinite support)
* - Gibbs phenomenon at discontinuities
*/
public final class ShannonWavelet implements ContinuousWavelet {
private final double fb; // Bandwidth parameter
private final double fc; // Center frequency
private final String name;
/**
* Create Shannon wavelet with default parameters.
* Default: fb=1, fc=1.5
*/
public ShannonWavelet() {
this(1.0, 1.5);
}
/**
* Create Shannon wavelet with specified parameters.
*
* @param fb bandwidth parameter (> 0)
* @param fc center frequency (> 0)
*/
public ShannonWavelet(double fb, double fc) {
if (fb <= 0) {
throw new IllegalArgumentException(
"Bandwidth must be positive, got: " + fb);
}
if (fc <= 0) {
throw new IllegalArgumentException(
"Center frequency must be positive, got: " + fc);
}
this.fb = fb;
this.fc = fc;
this.name = String.format("shan%.1f-%.1f", fb, fc);
}
@Override
public String name() {
return name;
}
@Override
public String description() {
return String.format("Shannon wavelet (fb=%.1f, fc=%.1f)", fb, fc);
}
@Override
public double psi(double t) {
// Shannon wavelet: sinc(fb*t) * cos(2π*fc*t)
double sinc = (Math.abs(fb * t) < 1e-10) ? 1.0 :
Math.sin(Math.PI * fb * t) / (Math.PI * fb * t);
return Math.sqrt(fb) * sinc * Math.cos(2 * Math.PI * fc * t);
}
@Override
public double centerFrequency() {
return fc;
}
@Override
public double bandwidth() {
return fb;
}
@Override
public boolean isComplex() {
return false;
}
@Override
public double[] discretize(int length) {
if (length <= 0) {
throw new InvalidArgumentException("Length must be positive");
}
double[] samples = new double[length];
int center = length / 2;
// Effective support: [-8, 8] for good approximation
double support = 8.0;
for (int i = 0; i < length; i++) {
double t = (i - center) * 2.0 * support / length;
samples[i] = psi(t);
}
return samples;
}
/**
* Gets the bandwidth parameter.
*
* @return the bandwidth parameter
*/
public double getBandwidthParameter() {
return fb;
}
/**
* Gets the center frequency parameter.
*
* @return the center frequency parameter
*/
public double getCenterFrequencyParameter() {
return fc;
}
}