From 87b3d3402407472d16891bd2c509215f5c721c93 Mon Sep 17 00:00:00 2001 From: Denny Sheirer Date: Sun, 21 Nov 2021 04:17:54 -0500 Subject: [PATCH] #1106 Adds half-band filter create to filter factory (#1107) Co-authored-by: Dennis Sheirer --- .../dsheirer/dsp/filter/FilterFactory.java | 90 +++++++++++++------ .../io/github/dsheirer/dsp/filter/Window.java | 57 ++++-------- 2 files changed, 78 insertions(+), 69 deletions(-) diff --git a/src/main/java/io/github/dsheirer/dsp/filter/FilterFactory.java b/src/main/java/io/github/dsheirer/dsp/filter/FilterFactory.java index 235f8581..6c83b7d4 100644 --- a/src/main/java/io/github/dsheirer/dsp/filter/FilterFactory.java +++ b/src/main/java/io/github/dsheirer/dsp/filter/FilterFactory.java @@ -1,25 +1,21 @@ -/******************************************************************************* - * SDR Trunk - * Copyright (C) 2014,2015 Dennis Sheirer +/* + * ***************************************************************************** + * Copyright (C) 2014-2021 Dennis Sheirer * - * Root Raised Cosine filter designer: - * Copyright 2002,2007,2008,2012,2013 Free Software Foundation, Inc. - * http://gnuradio.org/redmine/projects/gnuradio/repository/changes/gr-filter - * /lib/firdes.cc?rev=435b1d166f0c7092bbd5e1f788e75dbb6ade3a4b + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see - ******************************************************************************/ + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + * **************************************************************************** + */ package io.github.dsheirer.dsp.filter; import io.github.dsheirer.dsp.filter.design.FilterDesignException; @@ -31,7 +27,7 @@ import org.jtransforms.fft.FloatFFT_1D; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Arrays; +import java.text.DecimalFormat; import java.util.Set; import java.util.TreeSet; @@ -1001,6 +997,44 @@ public class FilterFactory return coefficients; } + /** + * Creates a symmetrical half-band filter where all odd-indexed coefficients except center are zero + * valued. + * @param length N is odd where m is an integer multiple in the formula: N = 4m + 3 (e.g. 7, 11, 15, etc.) + * @param windowType to apply to the filter. + * @return coefficients + */ + public static double[] getHalfBand(int length, Window.WindowType windowType) + { + if((length - 3) % 4 != 0) + { + throw new IllegalArgumentException("Half Band filter length (N) must be an odd length where m must be an " + + "integer multiple in (N=4m+3), e.g. 7, 11, 15, etc"); + } + + double[] window = Window.getWindow(windowType, length); + double[] taps = new double[length]; + + int halfLength = length / 2; + + for(int x = 0; x < length; x++) + { + int offset = x - halfLength; + + if(offset == 0) + { + taps[x] = 0.5f; //No window here - window coefficient should be 1.0 anyway + } + else if((x % 2) == 0) + { + //Only calculate the even-index taps, leaving odd-index taps at default value of zero + taps[x] = (float)((Math.sin(offset * Math.PI / 2) / (offset * Math.PI)) * window[x]); + } + } + + return taps; + } + /** * Compares two doubles for equals and avoids any rounding error that are present. * @@ -1015,17 +1049,17 @@ public class FilterFactory public static void main(String[] args) { - float[] taps = null; + DecimalFormat df = new DecimalFormat("0.000000"); - try + int length = 15; + + double [] taps = FilterFactory.getHalfBand(length, Window.WindowType.HAMMING); + + for(int x = 0; x < length; x++) { - taps = FilterFactory.getSincM2Channelizer(12500.0, 800, 9, true); - } - catch(FilterDesignException fde) - { - mLog.error("Error", fde); + mLog.debug("Tap: " + x + " Value: " + df.format(taps[x])); } - mLog.debug("Done: " + Arrays.toString(taps)); + mLog.debug("Done!"); } } diff --git a/src/main/java/io/github/dsheirer/dsp/filter/Window.java b/src/main/java/io/github/dsheirer/dsp/filter/Window.java index b67b459a..7ccea3f0 100644 --- a/src/main/java/io/github/dsheirer/dsp/filter/Window.java +++ b/src/main/java/io/github/dsheirer/dsp/filter/Window.java @@ -1,39 +1,22 @@ -/******************************************************************************* - * sdr-trunk - * Copyright (C) 2014-2018 Dennis Sheirer - * - * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program. - * If not, see - * - ******************************************************************************/ - /* - * Kaiser Window design methods: getKaiser(), getKaiserBeta() and getBesselZerothOrder() with minor naming changes were - * adopted from: + * ***************************************************************************** + * Copyright (C) 2014-2021 Dennis Sheirer * - * https://github.com/rjeschke/neetutils-base/blob/master/src/main/java/com/github/rjeschke/neetutils/audio/FIRUtils.java + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Copyright (C) 2012 René Jeschke + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + * **************************************************************************** */ + package io.github.dsheirer.dsp.filter; import org.apache.commons.math3.util.FastMath; @@ -294,13 +277,9 @@ public class Window { double[] coefficients = new double[length]; - double a0 = 0.54; - double a1 = 0.46; - double denominator = length; - for(int x = 0; x < length; x++) { - coefficients[x] = a0 - (a1 * FastMath.cos(TWO_PI * (double)x / denominator)); + coefficients[x] = 0.54 - (0.46 * FastMath.cos((TWO_PI * x) / (length - 1))); } return coefficients; @@ -316,13 +295,9 @@ public class Window { double[] coefficients = new double[length]; - double a0 = 0.5; - double a1 = 0.5; - double denominator = length; - for(int x = 0; x < length; x++) { - coefficients[x] = a0 - (a1 * FastMath.cos(TWO_PI * (double)x / denominator)); + coefficients[x] = 0.5 - (0.5 * FastMath.cos(TWO_PI * (double)x / (length - 1))); } return coefficients;