├── docs ├── element-list ├── module-search-index.js ├── resources │ ├── x.png │ └── glass.png ├── tag-search-index.js ├── package-search-index.js ├── type-search-index.js ├── index.html ├── legal │ ├── ASSEMBLY_EXCEPTION │ ├── jqueryUI.md │ ├── ADDITIONAL_LICENSE_INFO │ └── jquery.md ├── jquery-ui.overrides.css ├── script-dir │ └── jquery-ui.min.css ├── uk │ └── me │ │ └── berndporr │ │ └── iirj │ │ ├── class-use │ │ ├── ChebyshevI.html │ │ ├── SOSCascade.html │ │ ├── Butterworth.html │ │ ├── ChebyshevII.html │ │ ├── DirectFormI.html │ │ ├── DirectFormII.html │ │ ├── MathSupplement.html │ │ ├── LowPassTransform.html │ │ ├── BandPassTransform.html │ │ ├── BandStopTransform.html │ │ ├── HighPassTransform.html │ │ ├── BiquadPoleState.html │ │ ├── DirectFormAbstract.html │ │ ├── ComplexPair.html │ │ ├── Biquad.html │ │ ├── Cascade.html │ │ ├── PoleZeroPair.html │ │ └── LayoutBase.html │ │ ├── package-use.html │ │ └── package-tree.html ├── allpackages-index.html ├── constant-values.html ├── script.js └── overview-tree.html ├── gendoc.sh ├── filtertest.png ├── python-design ├── .gitignore ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── .gitattributes ├── app │ ├── src │ │ ├── test │ │ │ └── java │ │ │ │ └── elliptic │ │ │ │ └── AppTest.java │ │ └── main │ │ │ └── java │ │ │ └── elliptic │ │ │ └── App.java │ └── build.gradle ├── settings.gradle ├── README.md ├── elliptic_design.py ├── plot_impulse_fresponse.py └── gradlew.bat ├── .gitignore ├── pom.xml.asc ├── src ├── test │ ├── java │ │ └── uk │ │ │ └── me │ │ │ └── berndporr │ │ │ └── iirj │ │ │ ├── create_custom_test_coeff.py │ │ │ ├── DoubleSignal.java │ │ │ ├── DetectorTest.java │ │ │ ├── CustomTest.java │ │ │ ├── BesselTest.java │ │ │ ├── ChebyshevITest.java │ │ │ ├── ChebyshevIITest.java │ │ │ ├── ButterworthTest.java │ │ │ └── ParameterChecksTest.java │ └── resources │ │ └── scipy │ │ └── AnalogFilterTest.py └── main │ └── java │ └── uk │ └── me │ └── berndporr │ └── iirj │ ├── BiquadPoleState.java │ ├── DirectFormAbstract.java │ ├── PoleZeroPair.java │ ├── DirectFormII.java │ ├── DirectFormI.java │ ├── ComplexPair.java │ ├── MathSupplement.java │ ├── LowPassTransform.java │ ├── HighPassTransform.java │ ├── SOSCascade.java │ ├── LayoutBase.java │ ├── BandPassTransform.java │ ├── BandStopTransform.java │ ├── Biquad.java │ └── Cascade.java ├── plot_impulse_fresponse.py ├── README.md └── pom.xml /docs/element-list: -------------------------------------------------------------------------------- 1 | uk.me.berndporr.iirj 2 | -------------------------------------------------------------------------------- /docs/module-search-index.js: -------------------------------------------------------------------------------- 1 | moduleSearchIndex = [];updateSearchResults(); -------------------------------------------------------------------------------- /gendoc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | mvn javadoc:javadoc 3 | cd docs 4 | git add . 5 | -------------------------------------------------------------------------------- /filtertest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berndporr/iirj/HEAD/filtertest.png -------------------------------------------------------------------------------- /docs/resources/x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berndporr/iirj/HEAD/docs/resources/x.png -------------------------------------------------------------------------------- /docs/resources/glass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berndporr/iirj/HEAD/docs/resources/glass.png -------------------------------------------------------------------------------- /docs/tag-search-index.js: -------------------------------------------------------------------------------- 1 | tagSearchIndex = [{"l":"Constant Field Values","h":"","u":"constant-values.html"}];updateSearchResults(); -------------------------------------------------------------------------------- /python-design/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore Gradle project-specific cache directory 2 | .gradle 3 | 4 | # Ignore Gradle build output directory 5 | build 6 | -------------------------------------------------------------------------------- /python-design/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berndporr/iirj/HEAD/python-design/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /docs/package-search-index.js: -------------------------------------------------------------------------------- 1 | packageSearchIndex = [{"l":"All Packages","u":"allpackages-index.html"},{"l":"uk.me.berndporr.iirj"}];updateSearchResults(); -------------------------------------------------------------------------------- /python-design/.gitattributes: -------------------------------------------------------------------------------- 1 | # 2 | # https://help.github.com/articles/dealing-with-line-endings/ 3 | # 4 | # These are explicitly windows files and should use crlf 5 | *.bat text eol=crlf 6 | 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Mobile Tools for Java (J2ME) 4 | .mtj.tmp/ 5 | 6 | # Package Files # 7 | *.war 8 | *.ear 9 | 10 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 11 | hs_err_pid* 12 | 13 | target 14 | 15 | -------------------------------------------------------------------------------- /python-design/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /pom.xml.asc: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP SIGNATURE----- 2 | Version: GnuPG v1 3 | 4 | iJwEAAECAAYFAlgVQx4ACgkQO/ok6/1qXDuS0AP9HsZrJr9xt48wI1ASd0wmALF5 5 | C7QhsxvF/lesCPy1DK+VH4iGt+1pmBtheSbGHm6hEfWkIilGuTQtFhC2hFl+QvmO 6 | Ar4MfMosyWN1m4YwHVQKlAB8VEGVJK/i8Gzq5EdwzOb52OhAOeSNmM7SIxfTiVAH 7 | cx+be4HEMuV7anA0U6c= 8 | =BXX1 9 | -----END PGP SIGNATURE----- 10 | -------------------------------------------------------------------------------- /python-design/app/src/test/java/elliptic/AppTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This Java source file was generated by the Gradle 'init' task. 3 | */ 4 | package elliptic; 5 | 6 | import org.junit.Test; 7 | import static org.junit.Assert.*; 8 | 9 | public class AppTest { 10 | @Test public void appHasAGreeting() { 11 | App classUnderTest = new App(); 12 | assertNotNull("app should exist", classUnderTest); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /python-design/settings.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * This file was generated by the Gradle 'init' task. 3 | * 4 | * The settings file is used to specify which projects to include in your build. 5 | * 6 | * Detailed information about configuring a multi-project build in Gradle can be found 7 | * in the user manual at https://docs.gradle.org/7.3/userguide/multi_project_builds.html 8 | */ 9 | 10 | rootProject.name = 'elliptic' 11 | include('app') 12 | -------------------------------------------------------------------------------- /src/test/java/uk/me/berndporr/iirj/create_custom_test_coeff.py: -------------------------------------------------------------------------------- 1 | import scipy.signal as signal 2 | import numpy as np 3 | 4 | sos = signal.butter(2, 0.1, output='sos') 5 | print(sos) 6 | 7 | x = np.array([-1,0.5,1,0.5,0.3,-77,1E-5]) 8 | 9 | y = signal.sosfilt(sos, x) 10 | 11 | print(y) 12 | 13 | print("----------------------") 14 | 15 | sos = signal.butter(4, 0.15, output='sos') 16 | print(sos) 17 | 18 | x = np.array([-1,0.5,-1,0.5,-0.3,3,-1E-5]) 19 | y = signal.sosfilt(sos, x) 20 | 21 | print(y) 22 | -------------------------------------------------------------------------------- /python-design/README.md: -------------------------------------------------------------------------------- 1 | # Calculating the filter coefficients with Python 2 | 3 | Shows how to design IIRJ filters with scipy-commands. In this demo the 4 | filter coefficients of an elliptic filter were generated with 5 | `elliptic_design.py` and then added to the java application. 6 | 7 | ## Compilation 8 | 9 | ``` 10 | gradle build 11 | ``` 12 | 13 | ## Run the code 14 | 15 | `gradle run` calculates the impulse response and writes it 16 | to `app/elliptic.dat`. 17 | 18 | ## Plot the frequency response 19 | 20 | ``` 21 | python3 plot_impulse_fresponse.py 22 | ``` 23 | -------------------------------------------------------------------------------- /python-design/elliptic_design.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | # Calculates the coefficients for an elliptic filter 4 | 5 | from scipy import signal 6 | # sampling rate 7 | fs = 1000 8 | # cutoff 9 | f0 = 100 10 | # order 11 | order = 4 12 | # passband ripple 13 | pr = 5 14 | # minimum stopband rejection 15 | sr = 40 16 | sos = signal.ellip(order, pr, sr, f0/fs*2, 'low', output='sos') 17 | for s in sos: 18 | print("{",end="") 19 | n = 0 20 | for c in s: 21 | print("%.18e" % c,end="") 22 | n=n+1 23 | if n<6: 24 | print(",",end="") 25 | print("},") 26 | -------------------------------------------------------------------------------- /src/test/java/uk/me/berndporr/iirj/DoubleSignal.java: -------------------------------------------------------------------------------- 1 | package uk.me.berndporr.iirj; 2 | 3 | class DoubleSignal 4 | { 5 | private final double[] xValues; 6 | private final double[] values; 7 | private final String name; 8 | 9 | DoubleSignal(int length, String name) { 10 | xValues = new double[length]; 11 | values = new double[length]; 12 | this.name = name; 13 | } 14 | 15 | void setValue(int index, double time, double value) { 16 | xValues[index] = time; 17 | values[index] = value; 18 | } 19 | 20 | double getValue(int index) { 21 | return values[index]; 22 | } 23 | 24 | double getXValue(int index) { 25 | return xValues[index]; 26 | } 27 | 28 | double[] getxValues() { 29 | return xValues; 30 | } 31 | 32 | double[] getValues() { 33 | return values; 34 | } 35 | 36 | int getSize() { 37 | return values.length; 38 | } 39 | 40 | String getName() { 41 | return this.name; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /docs/type-search-index.js: -------------------------------------------------------------------------------- 1 | typeSearchIndex = [{"l":"All Classes and Interfaces","u":"allclasses-index.html"},{"p":"uk.me.berndporr.iirj","l":"BandPassTransform"},{"p":"uk.me.berndporr.iirj","l":"BandStopTransform"},{"p":"uk.me.berndporr.iirj","l":"Bessel"},{"p":"uk.me.berndporr.iirj","l":"Biquad"},{"p":"uk.me.berndporr.iirj","l":"BiquadPoleState"},{"p":"uk.me.berndporr.iirj","l":"Butterworth"},{"p":"uk.me.berndporr.iirj","l":"Cascade"},{"p":"uk.me.berndporr.iirj","l":"ChebyshevI"},{"p":"uk.me.berndporr.iirj","l":"ChebyshevII"},{"p":"uk.me.berndporr.iirj","l":"ComplexPair"},{"p":"uk.me.berndporr.iirj","l":"DirectFormAbstract"},{"p":"uk.me.berndporr.iirj","l":"DirectFormI"},{"p":"uk.me.berndporr.iirj","l":"DirectFormII"},{"p":"uk.me.berndporr.iirj","l":"HighPassTransform"},{"p":"uk.me.berndporr.iirj","l":"LayoutBase"},{"p":"uk.me.berndporr.iirj","l":"LowPassTransform"},{"p":"uk.me.berndporr.iirj","l":"MathSupplement"},{"p":"uk.me.berndporr.iirj","l":"PoleZeroPair"},{"p":"uk.me.berndporr.iirj","l":"SOSCascade"}];updateSearchResults(); -------------------------------------------------------------------------------- /python-design/app/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * This file was generated by the Gradle 'init' task. 3 | * 4 | * This generated file contains a sample Java application project to get you started. 5 | * For more details take a look at the 'Building Java & JVM projects' chapter in the Gradle 6 | * User Manual available at https://docs.gradle.org/7.3/userguide/building_java_projects.html 7 | */ 8 | 9 | plugins { 10 | // Apply the application plugin to add support for building a CLI application in Java. 11 | id 'application' 12 | } 13 | 14 | repositories { 15 | // Use Maven Central for resolving dependencies. 16 | mavenCentral() 17 | } 18 | 19 | dependencies { 20 | // Use JUnit test framework. 21 | testImplementation 'junit:junit:4.13.2' 22 | 23 | // This dependency is used by the application. 24 | implementation 'com.google.guava:guava:30.1.1-jre' 25 | 26 | implementation group: 'uk.me.berndporr', name:'iirj', version: '1.5' 27 | } 28 | 29 | application { 30 | // Define the main class for the application. 31 | mainClass = 'elliptic.App' 32 | } 33 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | uk.me.berndporr:iirj 1.7 API 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 17 | 18 | 19 |
20 | 23 |

uk/me/berndporr/iirj/package-summary.html

24 |
25 | 26 | 27 | -------------------------------------------------------------------------------- /python-design/plot_impulse_fresponse.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import matplotlib.pyplot as plt 4 | import scipy 5 | import numpy as np 6 | 7 | # Plots the impulse response of the Bandstop and its frequency response 8 | 9 | def plot_if(name,figtitle,fs = 1000): 10 | plt.suptitle(figtitle) 11 | y = np.loadtxt(name); 12 | plt.subplot(311) 13 | plt.title("Impulse response") 14 | plt.plot(y); 15 | # 16 | # Fourier Transform 17 | yf = np.fft.fft(y) 18 | plt.subplot(312) 19 | fx = np.linspace(0,fs,len(yf)) 20 | plt.plot(fx,20*np.log10(abs(yf))) 21 | plt.xlim(0,fs/2) 22 | plt.title("Frequency response") 23 | plt.ylabel("gain/dB") 24 | 25 | plt.subplot(313) 26 | p = -np.diff(np.unwrap(np.angle(yf))) / np.diff(fx * 2 * np.pi) 27 | plt.plot(np.linspace(0,fs,len(yf)-1),p) 28 | plt.xlim(0,fs/2) 29 | plt.title("Phase response") 30 | if fs == 1: 31 | plt.xlabel("f/1/samples") 32 | plt.ylabel("delay/samples") 33 | plt.ylim(-200,200) 34 | else: 35 | plt.ylim(-0.075,0.075) 36 | plt.xlabel("f/Hz") 37 | plt.ylabel("delay/secs") 38 | 39 | plot_if("app/elliptic.dat","Elliptic filter") 40 | 41 | plt.show() 42 | -------------------------------------------------------------------------------- /plot_impulse_fresponse.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import matplotlib.pyplot as plt 4 | import numpy as np 5 | import sys 6 | 7 | # Plots the impulse response of the Bandstop and its frequency response 8 | 9 | def plot_if(figno,name,figtitle): 10 | plt.figure(figno) 11 | plt.suptitle(figtitle) 12 | fs = 250 13 | y = np.loadtxt(name); 14 | plt.subplot(311) 15 | plt.title("Impulse response") 16 | plt.plot(y); 17 | # 18 | # Fourier Transform 19 | yf = np.fft.fft(y) 20 | plt.subplot(312) 21 | fx = np.linspace(0,fs,len(yf)) 22 | plt.plot(fx,20*np.log10(abs(yf))) 23 | plt.xlim(0,fs/2) 24 | plt.title("Frequency response") 25 | plt.xlabel("f/Hz") 26 | plt.ylabel("gain/dB") 27 | 28 | plt.subplot(313) 29 | p = -np.diff(np.unwrap(np.angle(yf))) / np.diff(fx * 2 * np.pi) 30 | plt.plot(np.linspace(0,fs,len(yf)-1),p) 31 | plt.xlim(0,fs/2) 32 | plt.ylim(-0.075,0.075) 33 | plt.title("Phase response") 34 | plt.xlabel("f/Hz") 35 | plt.ylabel("delay/secs") 36 | 37 | if len(sys.argv) < 2: 38 | print("Specify which filter shall be plotted: butterworth, bessel, chebyshevI, chebyshevII.") 39 | quit() 40 | 41 | prefix = "target/surefire-reports/"+sys.argv[1]+"/" 42 | 43 | plot_if(1,prefix+"lp.txt","Lowpass") 44 | 45 | plot_if(2,prefix+"hp.txt","Highpass") 46 | 47 | plot_if(3,prefix+"bs.txt","Bandstop") 48 | 49 | plot_if(4,prefix+"bp.txt","Bandpass") 50 | 51 | plt.show() 52 | -------------------------------------------------------------------------------- /src/main/java/uk/me/berndporr/iirj/BiquadPoleState.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | * Copyright (c) 2009 by Vinnie Falco 18 | * Copyright (c) 2016 by Bernd Porr 19 | */ 20 | 21 | package uk.me.berndporr.iirj; 22 | 23 | 24 | import org.apache.commons.math3.complex.Complex; 25 | 26 | /** 27 | * PoleZeroPair with gain factor 28 | */ 29 | public class BiquadPoleState extends PoleZeroPair { 30 | 31 | 32 | public BiquadPoleState(Complex p, Complex z) { 33 | super(p, z); 34 | } 35 | 36 | public BiquadPoleState(Complex p1, Complex z1, 37 | Complex p2, Complex z2) { 38 | super(p1, z1, p2, z2); 39 | } 40 | 41 | double gain; 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/uk/me/berndporr/iirj/DirectFormAbstract.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | * Copyright (c) 2009 by Vinnie Falco 18 | * Copyright (c) 2016 by Bernd Porr 19 | */ 20 | 21 | package uk.me.berndporr.iirj; 22 | 23 | /** 24 | * Abstract form of the a filter which can have different state variables 25 | * 26 | * Direct form I or II is derived from it 27 | */ 28 | public abstract class DirectFormAbstract { 29 | 30 | public DirectFormAbstract () { 31 | reset(); 32 | } 33 | 34 | public abstract void reset(); 35 | 36 | public abstract double process1 (double in, Biquad s); 37 | 38 | public static final int DIRECT_FORM_I = 0; 39 | public static final int DIRECT_FORM_II = 1; 40 | 41 | }; 42 | -------------------------------------------------------------------------------- /docs/legal/ASSEMBLY_EXCEPTION: -------------------------------------------------------------------------------- 1 | 2 | OPENJDK ASSEMBLY EXCEPTION 3 | 4 | The OpenJDK source code made available by Oracle America, Inc. (Oracle) at 5 | openjdk.java.net ("OpenJDK Code") is distributed under the terms of the GNU 6 | General Public License version 2 7 | only ("GPL2"), with the following clarification and special exception. 8 | 9 | Linking this OpenJDK Code statically or dynamically with other code 10 | is making a combined work based on this library. Thus, the terms 11 | and conditions of GPL2 cover the whole combination. 12 | 13 | As a special exception, Oracle gives you permission to link this 14 | OpenJDK Code with certain code licensed by Oracle as indicated at 15 | http://openjdk.java.net/legal/exception-modules-2007-05-08.html 16 | ("Designated Exception Modules") to produce an executable, 17 | regardless of the license terms of the Designated Exception Modules, 18 | and to copy and distribute the resulting executable under GPL2, 19 | provided that the Designated Exception Modules continue to be 20 | governed by the licenses under which they were offered by Oracle. 21 | 22 | As such, it allows licensees and sublicensees of Oracle's GPL2 OpenJDK Code 23 | to build an executable that includes those portions of necessary code that 24 | Oracle could not provide under GPL2 (or that Oracle has provided under GPL2 25 | with the Classpath exception). If you modify or add to the OpenJDK code, 26 | that new GPL2 code may still be combined with Designated Exception Modules 27 | if the new code is made subject to this exception by its copyright holder. 28 | -------------------------------------------------------------------------------- /docs/jquery-ui.overrides.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | 26 | .ui-state-active, 27 | .ui-widget-content .ui-state-active, 28 | .ui-widget-header .ui-state-active, 29 | a.ui-button:active, 30 | .ui-button:active, 31 | .ui-button.ui-state-active:hover { 32 | /* Overrides the color of selection used in jQuery UI */ 33 | background: #F8981D; 34 | border: 1px solid #F8981D; 35 | } 36 | -------------------------------------------------------------------------------- /docs/script-dir/jquery-ui.min.css: -------------------------------------------------------------------------------- 1 | /*! jQuery UI - v1.13.1 - 2022-05-12 2 | * http://jqueryui.com 3 | * Includes: core.css, autocomplete.css, menu.css 4 | * Copyright jQuery Foundation and other contributors; Licensed MIT */ 5 | 6 | .ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;-ms-filter:"alpha(opacity=0)"}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important;pointer-events:none}.ui-icon{display:inline-block;vertical-align:middle;margin-top:-.25em;position:relative;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-icon-block{left:50%;margin-left:-8px;display:block}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-menu{list-style:none;padding:0;margin:0;display:block;outline:0}.ui-menu .ui-menu{position:absolute}.ui-menu .ui-menu-item{margin:0;cursor:pointer;list-style-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7")}.ui-menu .ui-menu-item-wrapper{position:relative;padding:3px 1em 3px .4em}.ui-menu .ui-menu-divider{margin:5px 0;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-state-focus,.ui-menu .ui-state-active{margin:-1px}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item-wrapper{padding-left:2em}.ui-menu .ui-icon{position:absolute;top:0;bottom:0;left:.2em;margin:auto 0}.ui-menu .ui-menu-icon{left:auto;right:0} -------------------------------------------------------------------------------- /src/main/java/uk/me/berndporr/iirj/PoleZeroPair.java: -------------------------------------------------------------------------------- 1 | package uk.me.berndporr.iirj; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * 19 | * Copyright (c) 2009 by Vinnie Falco 20 | * Copyright (c) 2016 by Bernd Porr 21 | */ 22 | 23 | import org.apache.commons.math3.complex.Complex; 24 | 25 | /** 26 | * 27 | * It's written on the tin. 28 | * 29 | */ 30 | public class PoleZeroPair { 31 | 32 | public ComplexPair poles; 33 | public ComplexPair zeros; 34 | 35 | // single pole/zero 36 | public PoleZeroPair(Complex p, Complex z) { 37 | poles = new ComplexPair(p); 38 | zeros = new ComplexPair(z); 39 | } 40 | 41 | // pole/zero pair 42 | public PoleZeroPair(Complex p1, Complex z1, Complex p2, Complex z2) { 43 | poles = new ComplexPair(p1, p2); 44 | zeros = new ComplexPair(z1, z2); 45 | } 46 | 47 | public boolean isSinglePole() { 48 | return poles.second.equals(new Complex(0, 0)) 49 | && zeros.second.equals(new Complex(0, 0)); 50 | } 51 | 52 | public boolean is_nan() { 53 | return poles.is_nan() || zeros.is_nan(); 54 | } 55 | }; 56 | -------------------------------------------------------------------------------- /src/main/java/uk/me/berndporr/iirj/DirectFormII.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | * Copyright (c) 2009 by Vinnie Falco 18 | * Copyright (c) 2016 by Bernd Porr 19 | */ 20 | 21 | package uk.me.berndporr.iirj; 22 | 23 | /** 24 | * 25 | * Implementation of a Direct Form II filter with its states. The coefficients 26 | * are supplied from the outside. 27 | * 28 | */ 29 | 30 | public class DirectFormII extends DirectFormAbstract { 31 | 32 | public DirectFormII() { 33 | reset(); 34 | } 35 | 36 | public void reset() { 37 | m_v1 = 0; 38 | m_v2 = 0; 39 | } 40 | 41 | public double process1(double in, 42 | Biquad s) { 43 | if (s != null) { 44 | double w = in - s.m_a1 * m_v1 - s.m_a2 * m_v2; 45 | double out = s.m_b0 * w + s.m_b1 * m_v1 + s.m_b2 * m_v2; 46 | 47 | m_v2 = m_v1; 48 | m_v1 = w; 49 | 50 | return out; 51 | } else { 52 | return in; 53 | } 54 | } 55 | 56 | double m_v1; // v[-1] 57 | double m_v2; // v[-2] 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/uk/me/berndporr/iirj/DirectFormI.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | * Copyright (c) 2009 by Vinnie Falco 18 | * Copyright (c) 2016 by Bernd Porr 19 | */ 20 | 21 | package uk.me.berndporr.iirj; 22 | 23 | /** 24 | * 25 | * Implementation of a Direct Form I filter with its states. The coefficients 26 | * are supplied from the outside. 27 | * 28 | */ 29 | public class DirectFormI extends DirectFormAbstract { 30 | 31 | public DirectFormI() { 32 | reset(); 33 | } 34 | 35 | public void reset() { 36 | m_x1 = 0; 37 | m_x2 = 0; 38 | m_y1 = 0; 39 | m_y2 = 0; 40 | } 41 | 42 | public double process1(double in, Biquad s) { 43 | 44 | double out = s.m_b0 * in + s.m_b1 * m_x1 + s.m_b2 * m_x2 45 | - s.m_a1 * m_y1 - s.m_a2 * m_y2; 46 | m_x2 = m_x1; 47 | m_y2 = m_y1; 48 | m_x1 = in; 49 | m_y1 = out; 50 | 51 | return out; 52 | } 53 | 54 | double m_x2; // x[n-2] 55 | double m_y2; // y[n-2] 56 | double m_x1; // x[n-1] 57 | double m_y1; // y[n-1] 58 | }; 59 | -------------------------------------------------------------------------------- /python-design/app/src/main/java/elliptic/App.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This Java source file was generated by the Gradle 'init' task. 3 | */ 4 | package elliptic; 5 | 6 | import uk.me.berndporr.iirj.*; 7 | import java.io.*; 8 | 9 | public class App { 10 | 11 | /** 12 | * elliptic_design.py: 13 | * 14 | * from scipy import signal 15 | * # sampling rate 16 | * fs = 1000 17 | * # cutoff 18 | * f0 = 100 19 | * # order 20 | * order = 4 21 | * # passband ripple 22 | * pr = 5 23 | * # minimum stopband rejection 24 | * sr = 40 25 | * coeff = signal.ellip(order, pr, sr, f0/fs*2, 'low', output='sos') 26 | * 27 | * The contents of coeff have been copied into coeff2 below. 28 | **/ 29 | 30 | final double[][] coeff2 = 31 | { 32 | {1.665778210826693306e-02, 33 | -3.926235536821644570e-03, 34 | 1.665778210826693653e-02, 35 | 1.000000000000000000e+00, 36 | -1.715406458784182631e+00, 37 | 8.100524568939508896e-01}, 38 | {1.000000000000000000e+00, 39 | -1.369802526921778174e+00, 40 | 9.999999999999997780e-01, 41 | 1.000000000000000000e+00, 42 | -1.605880898184007588e+00, 43 | 9.538687377533192624e-01} 44 | }; 45 | 46 | /** 47 | * Calculates the impulse response of the filter and writes it to elliptic.dat. 48 | **/ 49 | public void calcImpulse() { 50 | try { 51 | FileOutputStream os = new FileOutputStream("elliptic.dat"); 52 | SOSCascade cust = new SOSCascade(); 53 | cust.setup(coeff2); 54 | PrintStream bp = new PrintStream(os); 55 | // let's do an impulse response 56 | for (int i = 0; i < 500; i++) { 57 | double v = 0; 58 | if (i == 10) 59 | v = 1; 60 | v = cust.filter(v); 61 | bp.println("" + v); 62 | } 63 | os.close(); 64 | } catch (FileNotFoundException e) { 65 | e.printStackTrace(); 66 | } catch (IOException e){ 67 | e.printStackTrace(); 68 | } 69 | } 70 | 71 | public static void main(String[] args) { 72 | new App().calcImpulse(); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /docs/legal/jqueryUI.md: -------------------------------------------------------------------------------- 1 | ## jQuery UI v1.12.1 2 | 3 | ### jQuery UI License 4 | ``` 5 | Copyright jQuery Foundation and other contributors, https://jquery.org/ 6 | 7 | This software consists of voluntary contributions made by many 8 | individuals. For exact contribution history, see the revision history 9 | available at https://github.com/jquery/jquery-ui 10 | 11 | The following license applies to all parts of this software except as 12 | documented below: 13 | 14 | ==== 15 | 16 | Permission is hereby granted, free of charge, to any person obtaining 17 | a copy of this software and associated documentation files (the 18 | "Software"), to deal in the Software without restriction, including 19 | without limitation the rights to use, copy, modify, merge, publish, 20 | distribute, sublicense, and/or sell copies of the Software, and to 21 | permit persons to whom the Software is furnished to do so, subject to 22 | the following conditions: 23 | 24 | The above copyright notice and this permission notice shall be 25 | included in all copies or substantial portions of the Software. 26 | 27 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 28 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 29 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 30 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 31 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 32 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 33 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 34 | 35 | ==== 36 | 37 | Copyright and related rights for sample code are waived via CC0. Sample 38 | code is defined as all source code contained within the demos directory. 39 | 40 | CC0: http://creativecommons.org/publicdomain/zero/1.0/ 41 | 42 | ==== 43 | 44 | All files located in the node_modules and external directories are 45 | externally maintained libraries used by this software which have their 46 | own licenses; we recommend you read them, as their terms may differ from 47 | the terms above. 48 | 49 | ``` 50 | -------------------------------------------------------------------------------- /docs/legal/ADDITIONAL_LICENSE_INFO: -------------------------------------------------------------------------------- 1 | ADDITIONAL INFORMATION ABOUT LICENSING 2 | 3 | Certain files distributed by Oracle America, Inc. and/or its affiliates are 4 | subject to the following clarification and special exception to the GPLv2, 5 | based on the GNU Project exception for its Classpath libraries, known as the 6 | GNU Classpath Exception. 7 | 8 | Note that Oracle includes multiple, independent programs in this software 9 | package. Some of those programs are provided under licenses deemed 10 | incompatible with the GPLv2 by the Free Software Foundation and others. 11 | For example, the package includes programs licensed under the Apache 12 | License, Version 2.0 and may include FreeType. Such programs are licensed 13 | to you under their original licenses. 14 | 15 | Oracle facilitates your further distribution of this package by adding the 16 | Classpath Exception to the necessary parts of its GPLv2 code, which permits 17 | you to use that code in combination with other independent modules not 18 | licensed under the GPLv2. However, note that this would not permit you to 19 | commingle code under an incompatible license with Oracle's GPLv2 licensed 20 | code by, for example, cutting and pasting such code into a file also 21 | containing Oracle's GPLv2 licensed code and then distributing the result. 22 | 23 | Additionally, if you were to remove the Classpath Exception from any of the 24 | files to which it applies and distribute the result, you would likely be 25 | required to license some or all of the other code in that distribution under 26 | the GPLv2 as well, and since the GPLv2 is incompatible with the license terms 27 | of some items included in the distribution by Oracle, removing the Classpath 28 | Exception could therefore effectively compromise your ability to further 29 | distribute the package. 30 | 31 | Failing to distribute notices associated with some files may also create 32 | unexpected legal consequences. 33 | 34 | Proceed with caution and we recommend that you obtain the advice of a lawyer 35 | skilled in open source matters before removing the Classpath Exception or 36 | making modifications to this package which may subsequently be redistributed 37 | and/or involve the use of third party software. 38 | -------------------------------------------------------------------------------- /src/main/java/uk/me/berndporr/iirj/ComplexPair.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | * Copyright (c) 2009 by Vinnie Falco 18 | * Copyright (c) 2016 by Bernd Porr 19 | */ 20 | 21 | 22 | package uk.me.berndporr.iirj; 23 | 24 | import org.apache.commons.math3.complex.Complex; 25 | 26 | /** 27 | * 28 | * A complex pair 29 | * 30 | */ 31 | public class ComplexPair { 32 | 33 | public Complex first; 34 | public Complex second; 35 | 36 | ComplexPair (Complex c1, 37 | Complex c2) { 38 | first = c1; 39 | second = c2; 40 | } 41 | 42 | ComplexPair (Complex c1) { 43 | first = c1; 44 | second = new Complex(0,0); 45 | } 46 | 47 | boolean isConjugate () { 48 | return second.equals(first.conjugate()); 49 | } 50 | 51 | boolean isReal () { 52 | return first.getImaginary() == 0 && second.getImaginary() == 0; 53 | } 54 | 55 | // Returns true if this is either a conjugate pair, 56 | // or a pair of reals where neither is zero. 57 | boolean isMatchedPair () { 58 | if (first.getImaginary() != 0) 59 | return second.equals(first.conjugate()); 60 | else 61 | return second.getImaginary() == 0 && 62 | second.getReal() != 0 && 63 | first.getReal() != 0; 64 | } 65 | 66 | boolean is_nan() 67 | { 68 | return first.isNaN() || second.isNaN(); 69 | } 70 | }; 71 | -------------------------------------------------------------------------------- /src/main/java/uk/me/berndporr/iirj/MathSupplement.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | * Copyright (c) 2009 by Vinnie Falco 18 | * Copyright (c) 2016 by Bernd Porr 19 | */ 20 | 21 | package uk.me.berndporr.iirj; 22 | 23 | import org.apache.commons.math3.complex.Complex; 24 | 25 | /** 26 | * 27 | * Useful math functions which come back over and over again 28 | * 29 | */ 30 | public class MathSupplement { 31 | 32 | public static double doubleLn10 =2.3025850929940456840179914546844; 33 | 34 | public static Complex solve_quadratic_1(double a, double b, double c) { 35 | return (new Complex(-b).add(new Complex(b * b - 4 * a * c, 0)).sqrt()) 36 | .divide(2. * a); 37 | } 38 | 39 | public static Complex solve_quadratic_2(double a, double b, double c) { 40 | return (new Complex(-b).subtract(new Complex(b * b - 4 * a * c, 0)) 41 | .sqrt()).divide(2. * a); 42 | } 43 | 44 | public static Complex adjust_imag(Complex c) { 45 | if (Math.abs(c.getImaginary()) < 1e-30) 46 | return new Complex(c.getReal(), 0); 47 | else 48 | return c; 49 | } 50 | 51 | public static Complex addmul(Complex c, double v, Complex c1) { 52 | return new Complex(c.getReal() + v * c1.getReal(), c.getImaginary() + v 53 | * c1.getImaginary()); 54 | } 55 | 56 | public static Complex recip(Complex c) { 57 | double n = 1.0 / (c.abs() * c.abs()); 58 | 59 | return new Complex(n * c.getReal(), n * c.getImaginary()); 60 | } 61 | 62 | public static double asinh(double x) { 63 | return Math.log(x + Math.sqrt(x * x + 1)); 64 | } 65 | 66 | public static double acosh(double x) { 67 | return Math.log(x + Math.sqrt(x * x - 1)); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/uk/me/berndporr/iirj/LowPassTransform.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | * Copyright (c) 2009 by Vinnie Falco 18 | * Copyright (c) 2016 by Bernd Porr 19 | */ 20 | 21 | 22 | package uk.me.berndporr.iirj; 23 | 24 | import org.apache.commons.math3.complex.Complex; 25 | 26 | /** 27 | * Transforms from an analogue lowpass filter to a digital lowpass filter 28 | */ 29 | public class LowPassTransform { 30 | 31 | private double f; 32 | 33 | private Complex transform(Complex c) { 34 | if (c.isInfinite()) 35 | return new Complex(-1, 0); 36 | 37 | // frequency transform 38 | c = c.multiply(f); 39 | 40 | Complex one = new Complex(1, 0); 41 | 42 | // bilinear low pass transform 43 | return (one.add(c)).divide(one.subtract(c)); 44 | } 45 | 46 | public LowPassTransform(double fc, LayoutBase digital, LayoutBase analog) { 47 | digital.reset(); 48 | 49 | if (fc < 0) { 50 | throw new ArithmeticException("Cutoff frequency cannot be negative."); 51 | } 52 | 53 | if (!(fc < 0.5)) { 54 | throw new ArithmeticException("Cutoff frequency must be less than the Nyquist frequency."); 55 | } 56 | 57 | // prewarp 58 | f = Math.tan(Math.PI * fc); 59 | 60 | int numPoles = analog.getNumPoles(); 61 | int pairs = numPoles / 2; 62 | for (int i = 0; i < pairs; ++i) { 63 | PoleZeroPair pair = analog.getPair(i); 64 | digital.addPoleZeroConjugatePairs(transform(pair.poles.first), 65 | transform(pair.zeros.first)); 66 | } 67 | 68 | if ((numPoles & 1) == 1) { 69 | PoleZeroPair pair = analog.getPair(pairs); 70 | digital.add(transform(pair.poles.first), 71 | transform(pair.zeros.first)); 72 | } 73 | 74 | digital.setNormal(analog.getNormalW(), analog.getNormalGain()); 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/uk/me/berndporr/iirj/HighPassTransform.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | * Copyright (c) 2009 by Vinnie Falco 18 | * Copyright (c) 2016 by Bernd Porr 19 | */ 20 | 21 | package uk.me.berndporr.iirj; 22 | 23 | import org.apache.commons.math3.complex.Complex; 24 | 25 | /** 26 | * Transforms from an analogue lowpass filter to a digital highpass filter 27 | */ 28 | public class HighPassTransform { 29 | 30 | double f; 31 | 32 | public HighPassTransform(double fc, LayoutBase digital, LayoutBase analog) { 33 | digital.reset(); 34 | 35 | if (fc < 0) { 36 | throw new ArithmeticException("Cutoff frequency cannot be negative."); 37 | } 38 | 39 | if (!(fc < 0.5)) { 40 | throw new ArithmeticException("Cutoff frequency must be less than the Nyquist frequency."); 41 | } 42 | 43 | // prewarp 44 | f = 1. / Math.tan(Math.PI * fc); 45 | 46 | int numPoles = analog.getNumPoles(); 47 | int pairs = numPoles / 2; 48 | for (int i = 0; i < pairs; ++i) { 49 | PoleZeroPair pair = analog.getPair(i); 50 | digital.addPoleZeroConjugatePairs(transform(pair.poles.first), 51 | transform(pair.zeros.first)); 52 | } 53 | 54 | if ((numPoles & 1) == 1) { 55 | PoleZeroPair pair = analog.getPair(pairs); 56 | digital.add(transform(pair.poles.first), 57 | transform(pair.zeros.first)); 58 | } 59 | 60 | digital.setNormal(Math.PI - analog.getNormalW(), analog.getNormalGain()); 61 | } 62 | 63 | private Complex transform(Complex c) { 64 | if (c.isInfinite()) 65 | return new Complex(1, 0); 66 | 67 | // frequency transform 68 | c = c.multiply(f); 69 | 70 | // bilinear high pass transform 71 | return new Complex(-1).multiply((new Complex(1)).add(c)).divide( 72 | (new Complex(1)).subtract(c)); 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/uk/me/berndporr/iirj/SOSCascade.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | * Copyright (c) 2009 by Vinnie Falco 18 | * Copyright (c) 2021 by Bernd Porr 19 | */ 20 | 21 | 22 | package uk.me.berndporr.iirj; 23 | 24 | import org.apache.commons.math3.complex.Complex; 25 | import org.apache.commons.math3.complex.ComplexUtils; 26 | 27 | /** 28 | * User facing class which contains two methods 29 | * to create Custom SOS filters, in particular where 30 | * the filter coefficients have been generated by 31 | * Python's scipy signal library for example: 32 | * sos = signal.butter(4, 0.1, output='sos'). 33 | * Call one of the setup() methods below to 34 | * set the SOS coefficients. See the unit 35 | * test for examples how to set the coefficients. 36 | */ 37 | public class SOSCascade extends Cascade { 38 | 39 | /** 40 | * Sets directly the coefficients of the chain of 41 | * 2nd order filters. The layout of the array is 42 | * excatly how the scipy python design functions 43 | * output the sos coeffcients: 44 | * [b0,b1,b2,a0,a1,a2],[b0,b1,b2,a0,a1,a2],... 45 | * The filter type can be either DirectFormAbstract.DIRECT_FORM_II 46 | * or DirectFormAbstract.DIRECT_FORM_I. 47 | * @param sosCoefficients SOS coefficients 48 | * @param directFormType Direct form type (I or II). 49 | **/ 50 | public void setup(final double[][] sosCoefficients, 51 | final int directFormType) { 52 | setSOScoeff(sosCoefficients,directFormType); 53 | } 54 | 55 | /** 56 | * Sets directly the coefficients of the chain of 57 | * 2nd order filters. The layout of the array is 58 | * excatly how the scipy python design functions 59 | * output the coeffcients: 60 | * [b0,b1,b2,a0,a1,a2],[b0,b1,b2,a0,a1,a2],... 61 | * The filter type is DIRECT_FORM_II. 62 | * @param sosCoefficients SOS coefficients 63 | **/ 64 | public void setup(final double[][] sosCoefficients) { 65 | setSOScoeff(sosCoefficients,DirectFormAbstract.DIRECT_FORM_II); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /docs/uk/me/berndporr/iirj/class-use/ChebyshevI.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Uses of Class uk.me.berndporr.iirj.ChebyshevI (uk.me.berndporr:iirj 1.7 API) 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 24 |
25 | 48 |
49 |
50 |
51 |

Uses of Class
uk.me.berndporr.iirj.ChebyshevI

52 |
53 | No usage of uk.me.berndporr.iirj.ChebyshevI
54 |
55 |
56 | 57 |
58 |
59 |
60 | 61 | 62 | -------------------------------------------------------------------------------- /docs/uk/me/berndporr/iirj/class-use/SOSCascade.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Uses of Class uk.me.berndporr.iirj.SOSCascade (uk.me.berndporr:iirj 1.7 API) 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 24 |
25 | 48 |
49 |
50 |
51 |

Uses of Class
uk.me.berndporr.iirj.SOSCascade

52 |
53 | No usage of uk.me.berndporr.iirj.SOSCascade
54 |
55 |
56 | 57 |
58 |
59 |
60 | 61 | 62 | -------------------------------------------------------------------------------- /docs/uk/me/berndporr/iirj/class-use/Butterworth.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Uses of Class uk.me.berndporr.iirj.Butterworth (uk.me.berndporr:iirj 1.7 API) 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 24 |
25 | 48 |
49 |
50 |
51 |

Uses of Class
uk.me.berndporr.iirj.Butterworth

52 |
53 | No usage of uk.me.berndporr.iirj.Butterworth
54 |
55 |
56 | 57 |
58 |
59 |
60 | 61 | 62 | -------------------------------------------------------------------------------- /docs/uk/me/berndporr/iirj/class-use/ChebyshevII.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Uses of Class uk.me.berndporr.iirj.ChebyshevII (uk.me.berndporr:iirj 1.7 API) 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 24 |
25 | 48 |
49 |
50 |
51 |

Uses of Class
uk.me.berndporr.iirj.ChebyshevII

52 |
53 | No usage of uk.me.berndporr.iirj.ChebyshevII
54 |
55 |
56 | 57 |
58 |
59 |
60 | 61 | 62 | -------------------------------------------------------------------------------- /docs/uk/me/berndporr/iirj/class-use/DirectFormI.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Uses of Class uk.me.berndporr.iirj.DirectFormI (uk.me.berndporr:iirj 1.7 API) 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 24 |
25 | 48 |
49 |
50 |
51 |

Uses of Class
uk.me.berndporr.iirj.DirectFormI

52 |
53 | No usage of uk.me.berndporr.iirj.DirectFormI
54 |
55 |
56 | 57 |
58 |
59 |
60 | 61 | 62 | -------------------------------------------------------------------------------- /docs/uk/me/berndporr/iirj/class-use/DirectFormII.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Uses of Class uk.me.berndporr.iirj.DirectFormII (uk.me.berndporr:iirj 1.7 API) 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 24 |
25 | 48 |
49 |
50 |
51 |

Uses of Class
uk.me.berndporr.iirj.DirectFormII

52 |
53 | No usage of uk.me.berndporr.iirj.DirectFormII
54 |
55 |
56 | 57 |
58 |
59 |
60 | 61 | 62 | -------------------------------------------------------------------------------- /docs/uk/me/berndporr/iirj/class-use/MathSupplement.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Uses of Class uk.me.berndporr.iirj.MathSupplement (uk.me.berndporr:iirj 1.7 API) 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 24 |
25 | 48 |
49 |
50 |
51 |

Uses of Class
uk.me.berndporr.iirj.MathSupplement

52 |
53 | No usage of uk.me.berndporr.iirj.MathSupplement
54 |
55 |
56 | 57 |
58 |
59 |
60 | 61 | 62 | -------------------------------------------------------------------------------- /docs/uk/me/berndporr/iirj/class-use/LowPassTransform.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Uses of Class uk.me.berndporr.iirj.LowPassTransform (uk.me.berndporr:iirj 1.7 API) 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 24 |
25 | 48 |
49 |
50 |
51 |

Uses of Class
uk.me.berndporr.iirj.LowPassTransform

52 |
53 | No usage of uk.me.berndporr.iirj.LowPassTransform
54 |
55 |
56 | 57 |
58 |
59 |
60 | 61 | 62 | -------------------------------------------------------------------------------- /docs/uk/me/berndporr/iirj/class-use/BandPassTransform.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Uses of Class uk.me.berndporr.iirj.BandPassTransform (uk.me.berndporr:iirj 1.7 API) 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 24 |
25 | 48 |
49 |
50 |
51 |

Uses of Class
uk.me.berndporr.iirj.BandPassTransform

52 |
53 | No usage of uk.me.berndporr.iirj.BandPassTransform
54 |
55 |
56 | 57 |
58 |
59 |
60 | 61 | 62 | -------------------------------------------------------------------------------- /docs/uk/me/berndporr/iirj/class-use/BandStopTransform.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Uses of Class uk.me.berndporr.iirj.BandStopTransform (uk.me.berndporr:iirj 1.7 API) 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 24 |
25 | 48 |
49 |
50 |
51 |

Uses of Class
uk.me.berndporr.iirj.BandStopTransform

52 |
53 | No usage of uk.me.berndporr.iirj.BandStopTransform
54 |
55 |
56 | 57 |
58 |
59 |
60 | 61 | 62 | -------------------------------------------------------------------------------- /docs/uk/me/berndporr/iirj/class-use/HighPassTransform.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Uses of Class uk.me.berndporr.iirj.HighPassTransform (uk.me.berndporr:iirj 1.7 API) 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 24 |
25 | 48 |
49 |
50 |
51 |

Uses of Class
uk.me.berndporr.iirj.HighPassTransform

52 |
53 | No usage of uk.me.berndporr.iirj.HighPassTransform
54 |
55 |
56 | 57 |
58 |
59 |
60 | 61 | 62 | -------------------------------------------------------------------------------- /src/main/java/uk/me/berndporr/iirj/LayoutBase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | * Copyright (c) 2009 by Vinnie Falco 18 | * Copyright (c) 2016 by Bernd Porr 19 | */ 20 | 21 | package uk.me.berndporr.iirj; 22 | 23 | import org.apache.commons.math3.complex.Complex; 24 | 25 | /** 26 | * 27 | * Digital/analogue filter coefficient storage space organising the 28 | * storage as PoleZeroPairs so that we have as always a 2nd order filter 29 | * 30 | */ 31 | public class LayoutBase { 32 | 33 | private int m_numPoles; 34 | private PoleZeroPair[] m_pair; 35 | private double m_normalW; 36 | private double m_normalGain; 37 | 38 | public LayoutBase(PoleZeroPair[] pairs) { 39 | m_numPoles = pairs.length * 2; 40 | m_pair = pairs; 41 | } 42 | 43 | public LayoutBase(int numPoles) { 44 | m_numPoles = 0; 45 | if ((numPoles % 2) == 1) { 46 | m_pair = new PoleZeroPair[numPoles / 2 + 1]; 47 | } else { 48 | m_pair = new PoleZeroPair[numPoles / 2]; 49 | } 50 | } 51 | 52 | public void reset() { 53 | m_numPoles = 0; 54 | } 55 | 56 | public int getNumPoles() { 57 | return m_numPoles; 58 | } 59 | 60 | public void add(Complex pole, Complex zero) { 61 | m_pair[m_numPoles / 2] = new PoleZeroPair(pole, zero); 62 | ++m_numPoles; 63 | } 64 | 65 | public void addPoleZeroConjugatePairs(Complex pole, Complex zero) { 66 | if (pole == null) System.out.println("LayoutBase addConj() pole == null"); 67 | if (zero == null) System.out.println("LayoutBase addConj() zero == null"); 68 | if (m_pair == null) System.out.println("LayoutBase addConj() m_pair == null"); 69 | m_pair[m_numPoles / 2] = new PoleZeroPair(pole, zero, pole.conjugate(), 70 | zero.conjugate()); 71 | m_numPoles += 2; 72 | } 73 | 74 | public void add(ComplexPair poles, ComplexPair zeros) { 75 | m_pair[m_numPoles / 2] = new PoleZeroPair(poles.first, zeros.first, 76 | poles.second, zeros.second); 77 | m_numPoles += 2; 78 | } 79 | 80 | public PoleZeroPair getPair(int pairIndex) { 81 | return m_pair[pairIndex]; 82 | } 83 | 84 | public double getNormalW() { 85 | return m_normalW; 86 | } 87 | 88 | public double getNormalGain() { 89 | return m_normalGain; 90 | } 91 | 92 | public void setNormal(double w, double g) { 93 | m_normalW = w; 94 | m_normalGain = g; 95 | } 96 | }; 97 | -------------------------------------------------------------------------------- /docs/allpackages-index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | All Packages (uk.me.berndporr:iirj 1.7 API) 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 24 |
25 | 48 |
49 |
50 |
51 |

All Packages

52 |
53 |
Package Summary
54 |
55 |
Package
56 |
Description
57 | 58 |
 
59 |
60 |
61 |
62 |
63 | 64 |
65 |
66 |
67 | 68 | 69 | -------------------------------------------------------------------------------- /python-design/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # iirj 2 | 3 | An IIR filter library written in JAVA. 4 | 5 | Highpass, lowpass, bandpass and bandstop as 6 | Butterworth, Bessel and Chebyshev Type I/II. 7 | 8 | You can also calculate the filter coefficients with Python's 9 | scipy and then create your custom IIR filter. 10 | See the `python-design` subdirectory. 11 | 12 | It's based on the IIR1 library [https://github.com/berndporr/iir1] 13 | which in turn is based on Vinnie Falco's DSPFilters [https://github.com/vinniefalco/DSPFilters]. 14 | 15 | ![alt tag](filtertest.png) 16 | 17 | ## Usage 18 | 19 | `import uk.me.berndporr.iirj.*;` 20 | 21 | ### Constructor 22 | 23 | `Butterworth butterworth = new Butterworth();` 24 | 25 | ### Initialisation 26 | 1. Bandstop 27 | 28 | `butterworth.bandStop(order,Samplingfreq,Center freq,Width in frequ);` 29 | 30 | 2. Bandpass 31 | 32 | `butterworth.bandPass(order,Samplingfreq,Center freq,Width in frequ);` 33 | 34 | 3. Lowpass 35 | 36 | `butterworth.lowPass(order,Samplingfreq,Cutoff frequ);` 37 | 38 | 4. Highpass 39 | 40 | `butterworth.highPass(order,Samplingfreq,Cutoff frequ);` 41 | 42 | ### Filtering 43 | Sample by sample for realtime processing: 44 | 45 | ``` 46 | v = butterworth.filter(v) 47 | ``` 48 | 49 | ## Coding examples 50 | See the `*Test.java` files for complete examples 51 | for all filter types. Run them with `mvn test`. These test programs 52 | write the different impulse responses of the filters to text files. 53 | 54 | ## Installation 55 | 56 | ## Local install 57 | - Clone this repository 58 | - Run `mvn install` to add it to your local maven respository 59 | 60 | ## Maven central 61 | 62 | At [![Maven Central](https://img.shields.io/maven-central/v/uk.me.berndporr/iirj.svg?label=Maven%20Central)](https://central.sonatype.com/artifact/uk.me.berndporr/iirj) 63 | click on the iirj version number and then choose the appropriate installation option, for 64 | example for Android studio. 65 | 66 | ## Android Studio 67 | ``` 68 | dependencies { 69 | implementation group: 'uk.me.berndporr', name:'iirj', version: '1.7' 70 | } 71 | ``` 72 | Android studio will automatically notify you if a new IIR library is available. 73 | 74 | ## Documentation 75 | * Online: https://berndporr.github.io/iirj/ 76 | * `mvn javadoc:javadoc` generates the JavaDocs 77 | * `mvn site` generates the web pages containing the documentation 78 | under `target/site` describing all commands in detail. 79 | 80 | ## Testing 81 | `mvn test` creates impulse responses in the subdirectories 82 | for the different filters: `target/surefire-reports`. 83 | 84 | To see the impulse and frequency responses run: 85 | ``` 86 | python3 ./plot_impulse_fresponse.py 87 | ``` 88 | where is is butterworth, bessel, chebyshevI or chebyshevII. 89 | 90 | The script DetectorTest uses a bandpass filter to detect the 91 | heartbeats of an ECG recording faking a matched filter which could 92 | be also seen as a 1st approximation of a wavelet. The heartrate is 93 | stored in hr.txt. 94 | 95 | 96 | 97 | Have fun 98 | 99 | /Bernd Porr 100 | [http://www.berndporr.me.uk] 101 | 102 | -------------------------------------------------------------------------------- /docs/legal/jquery.md: -------------------------------------------------------------------------------- 1 | ## jQuery v3.6.0 2 | 3 | ### jQuery License 4 | ``` 5 | jQuery v 3.6.0 6 | Copyright OpenJS Foundation and other contributors, https://openjsf.org/ 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining 9 | a copy of this software and associated documentation files (the 10 | "Software"), to deal in the Software without restriction, including 11 | without limitation the rights to use, copy, modify, merge, publish, 12 | distribute, sublicense, and/or sell copies of the Software, and to 13 | permit persons to whom the Software is furnished to do so, subject to 14 | the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be 17 | included in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 23 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 24 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 25 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | 27 | ****************************************** 28 | 29 | The jQuery JavaScript Library v3.6.0 also includes Sizzle.js 30 | 31 | Sizzle.js includes the following license: 32 | 33 | Copyright JS Foundation and other contributors, https://js.foundation/ 34 | 35 | This software consists of voluntary contributions made by many 36 | individuals. For exact contribution history, see the revision history 37 | available at https://github.com/jquery/sizzle 38 | 39 | The following license applies to all parts of this software except as 40 | documented below: 41 | 42 | ==== 43 | 44 | Permission is hereby granted, free of charge, to any person obtaining 45 | a copy of this software and associated documentation files (the 46 | "Software"), to deal in the Software without restriction, including 47 | without limitation the rights to use, copy, modify, merge, publish, 48 | distribute, sublicense, and/or sell copies of the Software, and to 49 | permit persons to whom the Software is furnished to do so, subject to 50 | the following conditions: 51 | 52 | The above copyright notice and this permission notice shall be 53 | included in all copies or substantial portions of the Software. 54 | 55 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 56 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 57 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 58 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 59 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 60 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 61 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 62 | 63 | ==== 64 | 65 | All files located in the node_modules and external directories are 66 | externally maintained libraries used by this software which have their 67 | own licenses; we recommend you read them, as their terms may differ from 68 | the terms above. 69 | 70 | ********************* 71 | 72 | ``` 73 | -------------------------------------------------------------------------------- /src/test/java/uk/me/berndporr/iirj/DetectorTest.java: -------------------------------------------------------------------------------- 1 | package uk.me.berndporr.iirj; 2 | /* 3 | * Licensed to the Apache Software Foundation (ASF) under one or more 4 | * contributor license agreements. See the NOTICE file distributed with 5 | * this work for additional information regarding copyright ownership. 6 | * The ASF licenses this file to You under the Apache License, Version 2.0 7 | * (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | 20 | 21 | import java.io.File; 22 | import java.io.PrintStream; 23 | import java.io.FileOutputStream; 24 | import java.util.Scanner; 25 | 26 | import uk.me.berndporr.iirj.Butterworth; 27 | 28 | import org.junit.Assert; 29 | import org.junit.Test; 30 | 31 | // Detect the heartbeat in an ECG 32 | // The idea is to create a matched filter for ECG which in turn is 33 | // a bandpass and which in turn could be understood as a wavelet. 34 | // The center and bandwidth here are experimental results so that the 35 | // impulse response resembles the timing of an R peak. 36 | public class DetectorTest { 37 | 38 | static String prefix="target/surefire-reports/detector/"; 39 | 40 | void createDir() { 41 | File dir = new File(prefix); 42 | dir.mkdirs(); 43 | } 44 | 45 | 46 | @Test 47 | public void detTest() throws Exception { 48 | createDir(); 49 | 50 | Butterworth butterworth = new Butterworth(); 51 | // this fakes an R peak so we have a matched filter! 52 | butterworth.bandPass(2,250,20,15); 53 | 54 | FileOutputStream os = new FileOutputStream(prefix+"det.txt"); 55 | PrintStream bp = new PrintStream(os); 56 | 57 | FileOutputStream heartrate = new FileOutputStream(prefix+"hr.txt"); 58 | PrintStream hr = new PrintStream(heartrate); 59 | 60 | Scanner is = new Scanner(new File("src/test/resources/ecg.dat")); 61 | 62 | double max = 0; 63 | double t1=0,t2=0; 64 | int notDet = 0; 65 | double time = 0; 66 | int ignore = 100; 67 | int sampleno = 0; 68 | 69 | // let's do an impulse response 70 | while(is.hasNextLine()) { 71 | double v=0; 72 | time = time + 1.0/125.0; 73 | String data = is.nextLine(); 74 | v = Double.parseDouble(data); 75 | v = butterworth.filter(v); 76 | v = v*v; 77 | bp.println(""+v); 78 | if (ignore>0) { 79 | ignore--; 80 | } else { 81 | if (v > max) { 82 | max = v; 83 | } 84 | } 85 | if (notDet>0) { 86 | notDet--; 87 | } else { 88 | if (v > 0.5*max) { 89 | t1 = time; 90 | notDet = 50; 91 | int r = (int)Math.round((t1-t2)*60); 92 | if (r>30) { 93 | hr.println(String.format("%d %d",sampleno,r)); 94 | Assert.assertTrue((r>60)&&(r<160)); 95 | } 96 | t2 = t1; 97 | } 98 | } 99 | sampleno++; 100 | } 101 | 102 | os.close(); 103 | heartrate.close(); 104 | is.close(); 105 | 106 | } 107 | 108 | 109 | public void main(String args[]) { 110 | try { 111 | detTest(); 112 | } catch (Exception e) {}; 113 | } 114 | 115 | } 116 | -------------------------------------------------------------------------------- /src/main/java/uk/me/berndporr/iirj/BandPassTransform.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | * Copyright (c) 2009 by Vinnie Falco 18 | * Copyright (c) 2016 by Bernd Porr 19 | */ 20 | 21 | 22 | package uk.me.berndporr.iirj; 23 | 24 | import org.apache.commons.math3.complex.Complex; 25 | 26 | /** 27 | * Transforms from an analogue bandpass filter to a digital bandstop filter 28 | */ 29 | public class BandPassTransform { 30 | 31 | private double wc2; 32 | private double wc; 33 | private double a, b; 34 | private double a2, b2; 35 | private double ab, ab_2; 36 | 37 | public BandPassTransform(double fc, double fw, LayoutBase digital, 38 | LayoutBase analog) { 39 | 40 | digital.reset(); 41 | 42 | if (fc < 0) { 43 | throw new ArithmeticException("Cutoff frequency cannot be negative."); 44 | } 45 | 46 | if (!(fc < 0.5)) { 47 | throw new ArithmeticException("Cutoff frequency must be less than the Nyquist frequency."); 48 | } 49 | 50 | double ww = 2 * Math.PI * fw; 51 | 52 | // pre-calcs 53 | wc2 = 2 * Math.PI * fc - (ww / 2); 54 | wc = wc2 + ww; 55 | 56 | // what is this crap? 57 | if (wc2 < 1e-8) 58 | wc2 = 1e-8; 59 | if (wc > Math.PI - 1e-8) 60 | wc = Math.PI - 1e-8; 61 | 62 | a = Math.cos((wc + wc2) * 0.5) / Math.cos((wc - wc2) * 0.5); 63 | b = 1 / Math.tan((wc - wc2) * 0.5); 64 | a2 = a * a; 65 | b2 = b * b; 66 | ab = a * b; 67 | ab_2 = 2 * ab; 68 | 69 | int numPoles = analog.getNumPoles(); 70 | int pairs = numPoles / 2; 71 | for (int i = 0; i < pairs; ++i) { 72 | PoleZeroPair pair = analog.getPair(i); 73 | ComplexPair p1 = transform(pair.poles.first); 74 | ComplexPair z1 = transform(pair.zeros.first); 75 | 76 | digital.addPoleZeroConjugatePairs(p1.first, z1.first); 77 | digital.addPoleZeroConjugatePairs(p1.second, z1.second); 78 | } 79 | 80 | if ((numPoles & 1) == 1) { 81 | ComplexPair poles = transform(analog.getPair(pairs).poles.first); 82 | ComplexPair zeros = transform(analog.getPair(pairs).zeros.first); 83 | 84 | digital.add(poles, zeros); 85 | } 86 | 87 | double wn = analog.getNormalW(); 88 | digital.setNormal( 89 | 2 * Math.atan(Math.sqrt(Math.tan((wc + wn) * 0.5) 90 | * Math.tan((wc2 + wn) * 0.5))), analog.getNormalGain()); 91 | } 92 | 93 | private ComplexPair transform(Complex c) { 94 | if (c.isInfinite()) { 95 | return new ComplexPair(new Complex(-1), new Complex(1)); 96 | } 97 | 98 | c = ((new Complex(1)).add(c)).divide((new Complex(1)).subtract(c)); // bilinear 99 | 100 | Complex v = new Complex(0); 101 | v = MathSupplement.addmul(v, 4 * (b2 * (a2 - 1) + 1), c); 102 | v = v.add(8 * (b2 * (a2 - 1) - 1)); 103 | v = v.multiply(c); 104 | v = v.add(4 * (b2 * (a2 - 1) + 1)); 105 | v = v.sqrt(); 106 | 107 | Complex u = v.multiply(-1); 108 | u = MathSupplement.addmul(u, ab_2, c); 109 | u = u.add(ab_2); 110 | 111 | v = MathSupplement.addmul(v, ab_2, c); 112 | v = v.add(ab_2); 113 | 114 | Complex d = new Complex(0); 115 | d = MathSupplement.addmul(d, 2 * (b - 1), c).add(2 * (1 + b)); 116 | 117 | return new ComplexPair(u.divide(d), v.divide(d)); 118 | } 119 | 120 | } 121 | -------------------------------------------------------------------------------- /src/test/java/uk/me/berndporr/iirj/CustomTest.java: -------------------------------------------------------------------------------- 1 | package uk.me.berndporr.iirj; 2 | /* 3 | * Licensed to the Apache Software Foundation (ASF) under one or more 4 | * contributor license agreements. See the NOTICE file distributed with 5 | * this work for additional information regarding copyright ownership. 6 | * The ASF licenses this file to You under the Apache License, Version 2.0 7 | * (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | 20 | import java.io.PrintStream; 21 | import java.io.FileOutputStream; 22 | import java.io.File; 23 | 24 | import uk.me.berndporr.iirj.Butterworth; 25 | 26 | import org.junit.Assert; 27 | import org.junit.Test; 28 | 29 | // Tests if the Cascade works, the filter stages and 30 | // if the custom parameters are properly transmitted. 31 | public class CustomTest { 32 | 33 | static String prefix="target/surefire-reports/custom/"; 34 | 35 | final double[][] coeff1 = 36 | {{ 0.02008337, 0.04016673, 0.02008337, 37 | 1, -1.56101808, 0.64135154}}; 38 | 39 | final double[] input1 = { 40 | -1.0, 41 | 0.5, 42 | 1.0}; 43 | 44 | final double[] result1 = { 45 | -2.00833656e-02, 46 | -6.14755450e-02, 47 | -6.30005740e-02}; 48 | 49 | final double[][] coeff2 = 50 | {{1.78260999e-03, 3.56521998e-03, 1.78260999e-03, 51 | 1.00000000e+00, -1.25544047e+00, 4.09013783e-01}, 52 | {1.00000000e+00, 2.00000000e+00, 1.00000000e+00, 53 | 1.00000000e+00, -1.51824184e+00, 7.03962657e-01}}; 54 | 55 | final double[] input2 = { 56 | -1,0.5,-1,0.5,-0.3,3,-1E-5 57 | }; 58 | 59 | final double[] result2 = { 60 | -0.00178261, -0.01118353, -0.03455084, -0.07277369, -0.11973872, -0.158864, 61 | -0.15873629 62 | }; 63 | 64 | final double delta = 1E-5; 65 | 66 | @Test 67 | public void test1() throws Exception { 68 | 69 | SOSCascade cust = new SOSCascade(); 70 | cust.setup(coeff1); 71 | int i = 0; 72 | for(double v:input1) { 73 | Assert.assertEquals(cust.filter(v),result1[i++],delta); 74 | } 75 | 76 | } 77 | 78 | @Test 79 | public void test2() throws Exception { 80 | 81 | SOSCascade cust = new SOSCascade(); 82 | cust.setup(coeff1,DirectFormAbstract.DIRECT_FORM_I); 83 | int i = 0; 84 | for(double v:input1) { 85 | Assert.assertEquals(cust.filter(v),result1[i++],delta); 86 | } 87 | 88 | } 89 | 90 | @Test 91 | public void test3() throws Exception { 92 | 93 | SOSCascade cust = new SOSCascade(); 94 | cust.setup(coeff2); 95 | int i = 0; 96 | for(double v:input2) { 97 | Assert.assertEquals(cust.filter(v),result2[i++],delta); 98 | } 99 | 100 | } 101 | 102 | @Test 103 | public void test4() throws Exception { 104 | 105 | SOSCascade cust = new SOSCascade(); 106 | cust.setup(coeff2,DirectFormAbstract.DIRECT_FORM_I); 107 | int i = 0; 108 | for(double v:input2) { 109 | Assert.assertEquals(cust.filter(v),result2[i++],delta); 110 | } 111 | 112 | } 113 | 114 | @Test 115 | public void lowPassTest() throws Exception { 116 | SOSCascade cust = new SOSCascade(); 117 | cust.setup(coeff2); 118 | 119 | File dir = new File(prefix); 120 | dir.mkdirs(); 121 | FileOutputStream os = new FileOutputStream(prefix+"lp.txt"); 122 | PrintStream bp = new PrintStream(os); 123 | 124 | // let's do an impulse response 125 | for (int i = 0; i < 500; i++) { 126 | double v = 0; 127 | if (i == 10) 128 | v = 1; 129 | v = cust.filter(v); 130 | bp.println("" + v); 131 | } 132 | Assert.assertTrue(Math.abs(cust.filter(0))<1E-30); 133 | Assert.assertTrue(Math.abs(cust.filter(0))!=0.0); 134 | Assert.assertTrue(Math.abs(cust.filter(0))!=Double.NaN); 135 | 136 | os.close(); 137 | } 138 | 139 | } 140 | -------------------------------------------------------------------------------- /src/main/java/uk/me/berndporr/iirj/BandStopTransform.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | * Copyright (c) 2009 by Vinnie Falco 18 | * Copyright (c) 2016 by Bernd Porr 19 | */ 20 | 21 | package uk.me.berndporr.iirj; 22 | import org.apache.commons.math3.complex.Complex; 23 | 24 | /** 25 | * Transforms from an analogue lowpass filter to a digital bandstop filter 26 | */ 27 | public class BandStopTransform { 28 | 29 | 30 | private double wc; 31 | private double wc2; 32 | private double a; 33 | private double b; 34 | private double a2; 35 | private double b2; 36 | 37 | 38 | public BandStopTransform(double fc, 39 | double fw, 40 | LayoutBase digital, 41 | LayoutBase analog) { 42 | digital.reset(); 43 | 44 | if (fc < 0) { 45 | throw new ArithmeticException("Cutoff frequency cannot be negative."); 46 | } 47 | 48 | if (!(fc < 0.5)) { 49 | throw new ArithmeticException("Cutoff frequency must be less than the Nyquist frequency."); 50 | } 51 | 52 | double ww = 2 * Math.PI * fw; 53 | 54 | wc2 = 2 * Math.PI * fc - (ww / 2); 55 | wc = wc2 + ww; 56 | 57 | // this is crap 58 | if (wc2 < 1e-8) 59 | wc2 = 1e-8; 60 | if (wc > Math.PI - 1e-8) 61 | wc = Math.PI - 1e-8; 62 | 63 | a = Math.cos((wc + wc2) * .5) / 64 | Math.cos((wc - wc2) * .5); 65 | b = Math.tan((wc - wc2) * .5); 66 | a2 = a * a; 67 | b2 = b * b; 68 | 69 | int numPoles = analog.getNumPoles(); 70 | int pairs = numPoles / 2; 71 | for (int i = 0; i < pairs; i++) { 72 | PoleZeroPair pair = analog.getPair(i); 73 | ComplexPair p = transform(pair.poles.first); 74 | ComplexPair z = transform(pair.zeros.first); 75 | digital.addPoleZeroConjugatePairs(p.first, z.first); 76 | digital.addPoleZeroConjugatePairs(p.second, z.second); 77 | } 78 | 79 | if ((numPoles & 1) == 1) { 80 | ComplexPair poles = transform(analog.getPair(pairs).poles.first); 81 | ComplexPair zeros = transform(analog.getPair(pairs).zeros.first); 82 | 83 | digital.add(poles, zeros); 84 | } 85 | 86 | if (fc < 0.25) 87 | digital.setNormal(Math.PI, analog.getNormalGain()); 88 | else 89 | digital.setNormal(0, analog.getNormalGain()); 90 | } 91 | 92 | private ComplexPair transform(Complex c) { 93 | if (c.isInfinite()) 94 | c = new Complex(-1); 95 | else 96 | c = ((new Complex(1)).add(c)).divide((new Complex(1)).subtract(c)); // bilinear 97 | 98 | Complex u = new Complex(0); 99 | u = MathSupplement.addmul(u, 4 * (b2 + a2 - 1), c); 100 | u = u.add(8 * (b2 - a2 + 1)); 101 | u = u.multiply(c); 102 | u = u.add(4 * (a2 + b2 - 1)); 103 | u = u.sqrt(); 104 | 105 | Complex v = u.multiply(-.5); 106 | v = v.add(a); 107 | v = MathSupplement.addmul(v, -a, c); 108 | 109 | u = u.multiply(.5); 110 | u = u.add(a); 111 | u = MathSupplement.addmul(u, -a, c); 112 | 113 | Complex d = new Complex(b + 1); 114 | d = MathSupplement.addmul(d, b - 1, c); 115 | 116 | return new ComplexPair(u.divide(d), v.divide(d)); 117 | } 118 | 119 | } 120 | -------------------------------------------------------------------------------- /docs/uk/me/berndporr/iirj/class-use/BiquadPoleState.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Uses of Class uk.me.berndporr.iirj.BiquadPoleState (uk.me.berndporr:iirj 1.7 API) 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 24 |
25 | 48 |
49 |
50 |
51 |

Uses of Class
uk.me.berndporr.iirj.BiquadPoleState

52 |
53 |
54 | 70 |
71 |
72 |
73 |
74 | 75 |
76 |
77 |
78 | 79 | 80 | -------------------------------------------------------------------------------- /src/test/java/uk/me/berndporr/iirj/BesselTest.java: -------------------------------------------------------------------------------- 1 | package uk.me.berndporr.iirj; 2 | /* 3 | * Licensed to the Apache Software Foundation (ASF) under one or more 4 | * contributor license agreements. See the NOTICE file distributed with 5 | * this work for additional information regarding copyright ownership. 6 | * The ASF licenses this file to You under the Apache License, Version 2.0 7 | * (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import java.io.File; 20 | import java.io.FileOutputStream; 21 | import java.io.PrintStream; 22 | 23 | import org.junit.Assert; 24 | import org.junit.Test; 25 | 26 | // Various impulse responses written out to files so that you can plot them 27 | public class BesselTest 28 | { 29 | 30 | static String prefix="target/surefire-reports/bessel/"; 31 | 32 | void createDir() throws Exception { 33 | File dir = new File(prefix); 34 | dir.mkdirs(); 35 | } 36 | 37 | @Test 38 | public void lowPassTest() throws Exception { 39 | Bessel bessel = new Bessel(); 40 | bessel.lowPass(4, 250, 50); 41 | 42 | createDir(); 43 | FileOutputStream os = new FileOutputStream(prefix+"lp.txt"); 44 | PrintStream bp = new PrintStream(os); 45 | 46 | // let's do an impulse response 47 | for (int i = 0; i < 500; i++) { 48 | double v = 0; 49 | if (i == 10) 50 | v = 1; 51 | v = bessel.filter(v); 52 | bp.println("" + v); 53 | } 54 | Assert.assertTrue(Math.abs(bessel.filter(0))<1E-90); 55 | Assert.assertTrue(Math.abs(bessel.filter(0))!=0.0); 56 | Assert.assertTrue(Math.abs(bessel.filter(0))!=Double.NaN); 57 | 58 | os.close(); 59 | } 60 | 61 | @Test 62 | public void bandPassTest() throws Exception { 63 | Bessel bessel = new Bessel(); 64 | bessel.bandPass(2, 250, 50, 5); 65 | 66 | createDir(); 67 | FileOutputStream os = new FileOutputStream(prefix+"bp.txt"); 68 | PrintStream bp = new PrintStream(os); 69 | 70 | // let's do an impulse response 71 | for (int i = 0; i < 500; i++) { 72 | double v = 0; 73 | if (i == 10) 74 | v = 1; 75 | v = bessel.filter(v); 76 | bp.println("" + v); 77 | } 78 | Assert.assertTrue(Math.abs(bessel.filter(0))<1E-13); 79 | Assert.assertTrue(Math.abs(bessel.filter(0))!=0.0); 80 | Assert.assertFalse(Double.isNaN(bessel.filter(0))); 81 | 82 | os.close(); 83 | } 84 | 85 | @Test 86 | public void bandStopTest() throws Exception { 87 | 88 | Bessel bessel = new Bessel(); 89 | bessel.bandStop(2, 250, 50, 5); 90 | 91 | createDir(); 92 | FileOutputStream os = new FileOutputStream(prefix+"bs.txt"); 93 | PrintStream bp = new PrintStream(os); 94 | 95 | // let's do an impulse response 96 | for (int i = 0; i < 500; i++) { 97 | double v = 0; 98 | if (i == 10) 99 | v = 1; 100 | v = bessel.filter(v); 101 | bp.println("" + v); 102 | } 103 | Assert.assertTrue(Math.abs(bessel.filter(0))<1E-7); 104 | Assert.assertTrue(Math.abs(bessel.filter(0))!=0.0); 105 | Assert.assertTrue(Math.abs(bessel.filter(0))!=Double.NaN); 106 | 107 | os.close(); 108 | } 109 | 110 | @Test 111 | public void highPassTest() throws Exception { 112 | 113 | Bessel bessel = new Bessel(); 114 | bessel.highPass(4, 250, 50); 115 | 116 | createDir(); 117 | FileOutputStream os = new FileOutputStream(prefix+"hp.txt"); 118 | PrintStream bp = new PrintStream(os); 119 | 120 | // let's do an impulse response 121 | for (int i = 0; i < 500; i++) { 122 | double v = 0; 123 | if (i == 10) 124 | v = 1; 125 | v = bessel.filter(v); 126 | bp.println("" + v); 127 | } 128 | Assert.assertTrue(Math.abs(bessel.filter(0))<1E-50); 129 | Assert.assertTrue(Math.abs(bessel.filter(0))!=0.0); 130 | Assert.assertTrue(Math.abs(bessel.filter(0))!=Double.NaN); 131 | 132 | os.close(); 133 | } 134 | 135 | public void main(String args[]) { 136 | try { 137 | lowPassTest(); 138 | highPassTest(); 139 | bandPassTest(); 140 | bandStopTest(); 141 | } catch (Exception e) { 142 | } 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /docs/uk/me/berndporr/iirj/class-use/DirectFormAbstract.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Uses of Class uk.me.berndporr.iirj.DirectFormAbstract (uk.me.berndporr:iirj 1.7 API) 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 24 |
25 | 48 |
49 |
50 |
51 |

Uses of Class
uk.me.berndporr.iirj.DirectFormAbstract

52 |
53 |
54 | 77 |
78 |
79 |
80 |
81 | 82 |
83 |
84 |
85 | 86 | 87 | -------------------------------------------------------------------------------- /src/test/resources/scipy/AnalogFilterTest.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from scipy.signal import butter, lfilter, bessel, cheby1, cheby2, sosfilt 3 | import matplotlib.pyplot as plt 4 | 5 | 6 | def showSignals(time, signal, filtered_signal): 7 | plt.plot(time, signal, label='Original Signal') 8 | plt.plot(time, filtered_signal, label='Filtered Signal (Butterworth, 350 Hz lowpass)') 9 | plt.xlabel('Time (s)') 10 | plt.ylabel('Amplitude') 11 | plt.legend() 12 | plt.show() 13 | 14 | 15 | def show_fft(time, signal, filtered_signal, sample_rate): 16 | N = len(signal) 17 | fft_original = np.fft.fft(signal) 18 | fft_filtered = np.fft.fft(filtered_signal) 19 | freqs = np.fft.fftfreq(N, 1 / sample_rate) 20 | 21 | # Only take the positive frequencies (up to the Nyquist frequency) 22 | positive_freqs = freqs[:N // 2] 23 | fft_original_positive = np.abs(fft_original[:N // 2]) 24 | fft_filtered_positive = np.abs(fft_filtered[:N // 2]) 25 | 26 | plt.figure() 27 | plt.plot(positive_freqs, fft_original_positive, label='Original Signal') 28 | plt.plot(positive_freqs, fft_filtered_positive, label='Filtered Signal') 29 | plt.xlabel('Frequency (Hz)') 30 | plt.ylabel('Amplitude') 31 | plt.title('FFT of Original and Filtered Signals') 32 | plt.legend() 33 | plt.show() 34 | 35 | 36 | def export_to_csv(time, filtered_signal, path): 37 | with open(path, 'w') as file: 38 | # Write the header row 39 | file.write('time;signal\n') 40 | # Write the data rows 41 | for t, s in zip(time, filtered_signal): 42 | file.write(f'{t:.4f};{s:.5f}\n') 43 | 44 | 45 | def readData(filename): 46 | # Read the data 47 | data = np.loadtxt(fname=filename, delimiter=';') 48 | time = data[:, 0] 49 | signal = data[:, 1] 50 | return time, signal 51 | 52 | 53 | def filterAndExport(sos, signal, exportName): 54 | # Apply the filter to the signal (using lfilter for one-pass filtering) 55 | filtered_signal = sosfilt(sos, signal) 56 | # Export the result to a CSV file 57 | export_to_csv(time, filtered_signal, exportName) 58 | print(f"Filtered signal has been saved to {exportName}") 59 | 60 | def createFileNameFromFilter(filtertype, btype, lc, hc, order): 61 | return str(filtertype + "-" + btype + "-LC_" + str(lc) + "-HC_" + str(hc) + "-Order_" + str(order) + ".csv") 62 | 63 | time, signal = readData('signal.txt') 64 | 65 | # Calculate the sample rate 66 | sample_rate = 1 / (time[1] - time[0]) 67 | lc = 200 68 | hc = 300 69 | 70 | filtertypes = ['Butterworth', 'Bessel', 'Chebychev1', 'Chebychev2'] 71 | btypes = ['lowpass', 'highpass', 'bandpass', 'bandstop'] 72 | orders = [1,2,4,5,10] 73 | 74 | ########################################################################### 75 | 76 | for filtertype in filtertypes: 77 | for btype in btypes: 78 | for order in orders: 79 | # Handle different critical frequencies for lowpass/highpass vs bandpass/bandstop 80 | if btype in ['lowpass', 'highpass']: 81 | Wn = hc if btype == 'lowpass' else lc 82 | else: 83 | Wn = [lc, hc] 84 | 85 | if filtertype == "Butterworth": 86 | sos = butter(N=order, Wn=Wn, fs=sample_rate, btype=btype, output='sos') 87 | elif filtertype == "Bessel": 88 | sos = bessel(N=order, Wn=Wn, fs=sample_rate, btype=btype, output='sos') 89 | elif filtertype == "Chebychev1": 90 | sos = cheby1(N=order, rp=1, Wn=Wn, fs=sample_rate, btype=btype, output='sos') 91 | elif filtertype == "Chebychev2": 92 | sos = cheby2(N=order, rs=1, Wn=Wn, fs=sample_rate, btype=btype, output='sos') 93 | 94 | filename = createFileNameFromFilter(filtertype.lower(), btype, lc, hc, order) 95 | filterAndExport(sos, signal, filename) 96 | 97 | 98 | ############################################################################ 99 | 100 | 101 | #b, a = butter(N=2, Wn=lc, fs=sample_rate, btype='lowpass') 102 | #filterAndExport(b, a, signal, "Butterworth-Lowcut-350Hz-2.Order.txt") 103 | 104 | #b, a = butter(N=1, Wn=hc, fs=sample_rate, btype='highpass')# 105 | #filterAndExport(b, a, signal, "Butterworth-Highcut-450Hz-1.Order.txt") 106 | 107 | #b, a = butter(N=2, Wn=hc, fs=sample_rate, btype='highpass') 108 | #filterAndExport(b, a, signal, "Butterworth-Highcut-450Hz-2.Order.txt") 109 | 110 | 111 | # Plot the original and filtered signals 112 | # showSignals(time, signal, filtered_signal) 113 | 114 | # Show the FFT of both signals 115 | # show_fft(time, signal, filtered_signal, sample_rate) 116 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | ${project.groupId}:${project.artifactId} 4 | A selection of standard IIR filters such as Butterworth, Bessel and Chebyshev which 5 | are set up with a single command and then can be used for realtime processing: outsample = filter(insample). 6 | 7 | https://github.com/berndporr/iirj 8 | uk.me.berndporr 9 | iirj 10 | jar 11 | 1.7 12 | 13 | 14 | UTF-8 15 | UTF-8 16 | 1.8 17 | 1.8 18 | 19 | 4.0.0 20 | 21 | 22 | 23 | org.apache.commons 24 | commons-math3 25 | 3.6.1 26 | 27 | 28 | junit 29 | junit 30 | 4.13.2 31 | test 32 | 33 | 34 | 35 | 36 | 37 | Bernd Porr 38 | mail@berndporr.me.uk 39 | http://www.berndporr.me.uk 40 | 41 | 42 | 43 | 44 | 45 | The Apache License, Version 2.0 46 | http://www.apache.org/licenses/LICENSE-2.0.txt 47 | 48 | 49 | 50 | 51 | scm:git:git@github.com:berndporr/iirj.git 52 | scm:git:git@github.com:berndporr/iirj.git 53 | https://github.com/berndporr/iirj 54 | 55 | 56 | 57 | 58 | 59 | org.apache.maven.plugins 60 | maven-project-info-reports-plugin 61 | 2.9 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | ossrh 70 | https://oss.sonatype.org/content/repositories/snapshots 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | org.sonatype.plugins 79 | nexus-staging-maven-plugin 80 | 1.6.13 81 | true 82 | 83 | ossrh 84 | https://oss.sonatype.org/ 85 | true 86 | 87 | 88 | 89 | 90 | org.apache.maven.plugins 91 | maven-source-plugin 92 | 3.3.0 93 | 94 | 95 | attach-sources 96 | 97 | jar-no-fork 98 | 99 | 100 | 101 | 102 | 103 | 104 | org.apache.maven.plugins 105 | maven-javadoc-plugin 106 | 107 | 8 108 | . 109 | docs 110 | 111 | 3.5.0 112 | 113 | 114 | attach-javadocs 115 | 116 | jar 117 | 118 | 119 | 120 | 121 | 122 | 123 | org.apache.maven.plugins 124 | maven-gpg-plugin 125 | 3.1.0 126 | 127 | 128 | sign-artifacts 129 | verify 130 | 131 | sign 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | -------------------------------------------------------------------------------- /src/test/java/uk/me/berndporr/iirj/ChebyshevITest.java: -------------------------------------------------------------------------------- 1 | package uk.me.berndporr.iirj; 2 | /* 3 | * Licensed to the Apache Software Foundation (ASF) under one or more 4 | * contributor license agreements. See the NOTICE file distributed with 5 | * this work for additional information regarding copyright ownership. 6 | * The ASF licenses this file to You under the Apache License, Version 2.0 7 | * (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | 20 | import java.io.PrintStream; 21 | import java.io.FileOutputStream; 22 | import java.io.File; 23 | 24 | import uk.me.berndporr.iirj.ChebyshevI; 25 | 26 | import org.junit.Assert; 27 | import org.junit.Test; 28 | 29 | // Various impulse responses written out to files so that you can plot them 30 | public class ChebyshevITest { 31 | 32 | static double ripple = 0.1; // db 33 | 34 | static String prefix="target/surefire-reports/chebyshevI/"; 35 | 36 | void createDir() throws Exception { 37 | File dir = new File(prefix); 38 | dir.mkdirs(); 39 | } 40 | 41 | @Test 42 | public void lowPassTest() throws Exception { 43 | ChebyshevI chebyshevI = new ChebyshevI(); 44 | chebyshevI.lowPass(4, 250, 50, ripple); 45 | 46 | createDir(); 47 | 48 | FileOutputStream os = new FileOutputStream(prefix+"lp.txt"); 49 | PrintStream bp = new PrintStream(os); 50 | 51 | // let's do an impulse response 52 | for (int i = 0; i < 500; i++) { 53 | double v = 0; 54 | if (i == 10) 55 | v = 1; 56 | v = chebyshevI.filter(v); 57 | bp.println("" + v); 58 | } 59 | Assert.assertTrue(Math.abs(chebyshevI.filter(0))<1E-49); 60 | Assert.assertTrue(Math.abs(chebyshevI.filter(0))!=0.0); 61 | Assert.assertTrue(Math.abs(chebyshevI.filter(0))!=Double.NaN); 62 | 63 | os.close(); 64 | } 65 | 66 | @Test 67 | public void bandPassTest() throws Exception { 68 | ChebyshevI chebyshevI = new ChebyshevI(); 69 | chebyshevI.bandPass(2, 250, 50, 5, ripple); 70 | 71 | createDir(); 72 | 73 | FileOutputStream os = new FileOutputStream(prefix+"bp.txt"); 74 | PrintStream bp = new PrintStream(os); 75 | 76 | // let's do an impulse response 77 | for (int i = 0; i < 500; i++) { 78 | double v = 0; 79 | if (i == 10) 80 | v = 1; 81 | v = chebyshevI.filter(v); 82 | bp.println("" + v); 83 | } 84 | Assert.assertTrue(Math.abs(chebyshevI.filter(0))<1E-15); 85 | Assert.assertTrue(Math.abs(chebyshevI.filter(0))!=0.0); 86 | Assert.assertTrue(Math.abs(chebyshevI.filter(0))!=Double.NaN); 87 | 88 | os.close(); 89 | } 90 | 91 | @Test 92 | public void bandStopTest() throws Exception { 93 | ChebyshevI chebyshevI = new ChebyshevI(); 94 | chebyshevI.bandStop(2, 250, 50, 5, ripple); 95 | 96 | createDir(); 97 | 98 | FileOutputStream os = new FileOutputStream(prefix+"bs.txt"); 99 | PrintStream bp = new PrintStream(os); 100 | 101 | // let's do an impulse response 102 | for (int i = 0; i < 500; i++) { 103 | double v = 0; 104 | if (i == 10) 105 | v = 1; 106 | v = chebyshevI.filter(v); 107 | bp.println("" + v); 108 | } 109 | Assert.assertTrue(Math.abs(chebyshevI.filter(0))<1E-5); 110 | Assert.assertTrue(Math.abs(chebyshevI.filter(0))!=0.0); 111 | Assert.assertTrue(Math.abs(chebyshevI.filter(0))!=Double.NaN); 112 | 113 | os.close(); 114 | } 115 | 116 | @Test 117 | public void highPassTest() throws Exception { 118 | ChebyshevI chebyshevI = new ChebyshevI(); 119 | chebyshevI.highPass(4, 250, 50, ripple); 120 | 121 | createDir(); 122 | FileOutputStream os = new FileOutputStream(prefix+"hp.txt"); 123 | PrintStream bp = new PrintStream(os); 124 | 125 | // let's do an impulse response 126 | for (int i = 0; i < 500; i++) { 127 | double v = 0; 128 | if (i == 10) 129 | v = 1; 130 | v = chebyshevI.filter(v); 131 | bp.println("" + v); 132 | } 133 | Assert.assertTrue(Math.abs(chebyshevI.filter(0))<1E-44); 134 | Assert.assertTrue(Math.abs(chebyshevI.filter(0))!=0.0); 135 | Assert.assertTrue(Math.abs(chebyshevI.filter(0))!=Double.NaN); 136 | 137 | os.close(); 138 | } 139 | 140 | public void main(String args[]) { 141 | try { 142 | lowPassTest(); 143 | highPassTest(); 144 | bandPassTest(); 145 | bandStopTest(); 146 | } catch (Exception e) { 147 | } 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /src/test/java/uk/me/berndporr/iirj/ChebyshevIITest.java: -------------------------------------------------------------------------------- 1 | package uk.me.berndporr.iirj; 2 | /* 3 | * Licensed to the Apache Software Foundation (ASF) under one or more 4 | * contributor license agreements. See the NOTICE file distributed with 5 | * this work for additional information regarding copyright ownership. 6 | * The ASF licenses this file to You under the Apache License, Version 2.0 7 | * (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | 20 | import java.io.PrintStream; 21 | import java.io.FileOutputStream; 22 | import java.io.File; 23 | 24 | import uk.me.berndporr.iirj.ChebyshevII; 25 | 26 | import org.junit.Assert; 27 | import org.junit.Test; 28 | 29 | // Various impulse responses written out to files so that you can plot them 30 | public class ChebyshevIITest { 31 | 32 | static double ripple = 10; // db 33 | 34 | static String prefix="target/surefire-reports/chebyshevII/"; 35 | 36 | void createDir() throws Exception { 37 | File dir = new File(prefix); 38 | dir.mkdirs(); 39 | } 40 | 41 | @Test 42 | public void lowPassTest() throws Exception { 43 | ChebyshevII chebyshevII = new ChebyshevII(); 44 | chebyshevII.lowPass(4, 250, 50, ripple); 45 | 46 | createDir(); 47 | 48 | FileOutputStream os = new FileOutputStream(prefix+"lp.txt"); 49 | PrintStream bp = new PrintStream(os); 50 | 51 | // let's do an impulse response 52 | for (int i = 0; i < 500; i++) { 53 | double v = 0; 54 | if (i == 10) 55 | v = 1; 56 | v = chebyshevII.filter(v); 57 | bp.println("" + v); 58 | } 59 | Assert.assertTrue(Math.abs(chebyshevII.filter(0))<1E-35); 60 | Assert.assertTrue(Math.abs(chebyshevII.filter(0))!=0.0); 61 | Assert.assertTrue(Math.abs(chebyshevII.filter(0))!=Double.NaN); 62 | 63 | os.close(); 64 | } 65 | 66 | @Test 67 | public void bandPassTest() throws Exception { 68 | ChebyshevII chebyshevII = new ChebyshevII(); 69 | chebyshevII.bandPass(2, 250, 50, 5, ripple); 70 | 71 | createDir(); 72 | 73 | FileOutputStream os = new FileOutputStream(prefix+"bp.txt"); 74 | PrintStream bp = new PrintStream(os); 75 | 76 | // let's do an impulse response 77 | for (int i = 0; i < 500; i++) { 78 | double v = 0; 79 | if (i == 10) 80 | v = 1; 81 | v = chebyshevII.filter(v); 82 | bp.println("" + v); 83 | } 84 | Assert.assertTrue(Math.abs(chebyshevII.filter(0))<1E-7); 85 | Assert.assertTrue(Math.abs(chebyshevII.filter(0))!=0.0); 86 | Assert.assertTrue(Math.abs(chebyshevII.filter(0))!=Double.NaN); 87 | 88 | os.close(); 89 | } 90 | 91 | @Test 92 | public void bandStopTest() throws Exception { 93 | ChebyshevII chebyshevII = new ChebyshevII(); 94 | chebyshevII.bandStop(2, 250, 50, 5, ripple); 95 | 96 | createDir(); 97 | 98 | FileOutputStream os = new FileOutputStream(prefix+"bs.txt"); 99 | PrintStream bp = new PrintStream(os); 100 | 101 | // let's do an impulse response 102 | for (int i = 0; i < 500; i++) { 103 | double v = 0; 104 | if (i == 10) 105 | v = 1; 106 | v = chebyshevII.filter(v); 107 | bp.println("" + v); 108 | } 109 | Assert.assertTrue(Math.abs(chebyshevII.filter(0))<1E-10); 110 | Assert.assertTrue(Math.abs(chebyshevII.filter(0))!=0.0); 111 | Assert.assertTrue(Math.abs(chebyshevII.filter(0))!=Double.NaN); 112 | 113 | os.close(); 114 | } 115 | 116 | @Test 117 | public void highPassTest() throws Exception { 118 | ChebyshevII chebyshevII = new ChebyshevII(); 119 | chebyshevII.highPass(4, 250, 50, ripple); 120 | 121 | createDir(); 122 | FileOutputStream os = new FileOutputStream(prefix+"hp.txt"); 123 | PrintStream bp = new PrintStream(os); 124 | 125 | // let's do an impulse response 126 | for (int i = 0; i < 500; i++) { 127 | double v = 0; 128 | if (i == 10) 129 | v = 1; 130 | v = chebyshevII.filter(v); 131 | bp.println("" + v); 132 | } 133 | Assert.assertTrue(Math.abs(chebyshevII.filter(0))<1E-34); 134 | Assert.assertTrue(Math.abs(chebyshevII.filter(0))!=0.0); 135 | Assert.assertTrue(Math.abs(chebyshevII.filter(0))!=Double.NaN); 136 | 137 | os.close(); 138 | } 139 | 140 | public void main(String args[]) { 141 | try { 142 | lowPassTest(); 143 | highPassTest(); 144 | bandPassTest(); 145 | bandStopTest(); 146 | } catch (Exception e) { 147 | } 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /docs/constant-values.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Constant Field Values (uk.me.berndporr:iirj 1.7 API) 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 24 |
25 | 48 |
49 |
50 |
51 |

Constant Field Values

52 |
53 |

Contents

54 | 57 |
58 |
59 |
60 |

uk.me.*

61 |
    62 |
  • 63 |
    uk.me.berndporr.iirj.Bessel
    64 |
    65 |
    Modifier and Type
    66 |
    Constant Field
    67 |
    Value
    68 |
    public static final int
    69 | 70 |
    24
    71 |
    72 |
  • 73 |
  • 74 |
    uk.me.berndporr.iirj.DirectFormAbstract
    75 |
    76 |
    Modifier and Type
    77 |
    Constant Field
    78 |
    Value
    79 |
    public static final int
    80 | 81 |
    0
    82 |
    public static final int
    83 | 84 |
    1
    85 |
    86 |
  • 87 |
88 |
89 |
90 |
91 |
92 | 93 |
94 |
95 |
96 | 97 | 98 | -------------------------------------------------------------------------------- /src/test/java/uk/me/berndporr/iirj/ButterworthTest.java: -------------------------------------------------------------------------------- 1 | package uk.me.berndporr.iirj; 2 | /* 3 | * Licensed to the Apache Software Foundation (ASF) under one or more 4 | * contributor license agreements. See the NOTICE file distributed with 5 | * this work for additional information regarding copyright ownership. 6 | * The ASF licenses this file to You under the Apache License, Version 2.0 7 | * (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | 20 | import java.io.PrintStream; 21 | import java.io.FileOutputStream; 22 | import java.io.File; 23 | 24 | import uk.me.berndporr.iirj.Butterworth; 25 | 26 | import org.junit.Assert; 27 | import org.junit.Test; 28 | 29 | // Various impulse responses written out to files so that you can plot them 30 | public class ButterworthTest { 31 | 32 | static String prefix="target/surefire-reports/butterworth/"; 33 | 34 | static double fs = 250; 35 | static double fc = 10; 36 | static int order = 6; 37 | static int nSteps = 10000; 38 | 39 | void createDir() throws Exception { 40 | File dir = new File(prefix); 41 | dir.mkdirs(); 42 | } 43 | 44 | @Test 45 | public void lowPassTest() throws Exception { 46 | 47 | Butterworth butterworth = new Butterworth(); 48 | butterworth.lowPass(order, fs, fc); 49 | 50 | createDir(); 51 | FileOutputStream os = new FileOutputStream(prefix+"lp.txt"); 52 | PrintStream bp = new PrintStream(os); 53 | 54 | // let's do an impulse response 55 | double v = 0; 56 | for (int i = 0; i < nSteps; i++) { 57 | v = 0; 58 | if (i == 10) 59 | v = 1; 60 | v = butterworth.filter(v); 61 | bp.println("" + v); 62 | } 63 | System.out.println("Lowpass filter output = "+v); 64 | Assert.assertTrue(v < 1E-80); 65 | Assert.assertTrue(v != 0.0); 66 | Assert.assertTrue(v != Double.NaN); 67 | 68 | os.close(); 69 | } 70 | 71 | @Test 72 | public void bandPassTest() throws Exception { 73 | Butterworth butterworth = new Butterworth(); 74 | butterworth.bandPass(order, fs, fc, fc/4); 75 | 76 | createDir(); 77 | FileOutputStream os = new FileOutputStream(prefix+"bp.txt"); 78 | PrintStream bp = new PrintStream(os); 79 | 80 | // let's do an impulse response 81 | double v = 0; 82 | for (int i = 0; i < nSteps; i++) { 83 | v = 0; 84 | if (i == 10) 85 | v = 1; 86 | v = butterworth.filter(v); 87 | bp.println("" + v); 88 | } 89 | System.out.println("Bandpass filter output = "+v); 90 | Assert.assertTrue(v < 1E-10); 91 | Assert.assertTrue(v != 0.0); 92 | Assert.assertTrue(v != Double.NaN); 93 | 94 | os.close(); 95 | } 96 | 97 | @Test 98 | public void bandStopTest() throws Exception { 99 | Butterworth butterworth = new Butterworth(); 100 | butterworth.bandStop(order, fs, fc, fc/4); 101 | 102 | createDir(); 103 | FileOutputStream os = new FileOutputStream(prefix+"bs.txt"); 104 | PrintStream bp = new PrintStream(os); 105 | 106 | // let's do an impulse response 107 | double v = 0; 108 | for (int i = 0; i < nSteps; i++) { 109 | v = 0; 110 | if (i == 10) 111 | v = 1; 112 | v = butterworth.filter(v); 113 | bp.println("" + v); 114 | } 115 | System.out.println("Bandstop filter output = "+v); 116 | Assert.assertTrue(v < 1E-10); 117 | Assert.assertTrue(v != 0.0); 118 | Assert.assertTrue(v != Double.NaN); 119 | 120 | os.close(); 121 | } 122 | 123 | @Test 124 | public void highPassTest() throws Exception { 125 | Butterworth butterworth = new Butterworth(); 126 | butterworth.highPass(order, fs, fc); 127 | 128 | createDir(); 129 | FileOutputStream os = new FileOutputStream(prefix+"hp.txt"); 130 | PrintStream bp = new PrintStream(os); 131 | 132 | // let's do an impulse response 133 | double v = 0; 134 | for (int i = 0; i < nSteps; i++) { 135 | v = 0; 136 | if (i == 10) 137 | v = 1; 138 | v = butterworth.filter(v); 139 | bp.println("" + v); 140 | } 141 | System.out.println("Highpass filter output = "+v); 142 | Assert.assertTrue(v < 1E-80); 143 | Assert.assertTrue(v != 0.0); 144 | Assert.assertTrue(v != Double.NaN); 145 | 146 | os.close(); 147 | } 148 | 149 | public void main(String args[]) { 150 | try { 151 | lowPassTest(); 152 | highPassTest(); 153 | bandPassTest(); 154 | bandStopTest(); 155 | } catch (Exception e) { 156 | Assert.fail("Exception while executing the filtering op:"+e.getMessage()); 157 | } 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /docs/uk/me/berndporr/iirj/package-use.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Uses of Package uk.me.berndporr.iirj (uk.me.berndporr:iirj 1.7 API) 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 24 |
25 | 48 |
49 |
50 |
51 |

Uses of Package
uk.me.berndporr.iirj

52 |
53 |
54 |
    55 |
  • 56 |
    57 | 58 |
    59 |
    Class
    60 |
    Description
    61 | 62 |
    63 |
    Contains the coefficients of a 2nd order digital filter with two poles and two zeros
    64 |
    65 | 66 |
    67 |
    PoleZeroPair with gain factor
    68 |
    69 | 70 |
    71 |
    The mother of all filters.
    72 |
    73 | 74 |
    75 |
    A complex pair
    76 |
    77 | 78 |
    79 |
    Abstract form of the a filter which can have different state variables 80 | 81 | Direct form I or II is derived from it
    82 |
    83 | 84 |
    85 |
    Digital/analogue filter coefficient storage space organising the 86 | storage as PoleZeroPairs so that we have as always a 2nd order filter
    87 |
    88 | 89 |
    90 |
    It's written on the tin.
    91 |
    92 |
    93 |
    94 |
  • 95 |
96 |
97 |
98 |
99 |
100 | 101 |
102 |
103 |
104 | 105 | 106 | -------------------------------------------------------------------------------- /src/main/java/uk/me/berndporr/iirj/Biquad.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | * Copyright (c) 2009 by Vinnie Falco 18 | * Copyright (c) 2016 by Bernd Porr 19 | */ 20 | 21 | package uk.me.berndporr.iirj; 22 | 23 | import org.apache.commons.math3.complex.Complex; 24 | import org.apache.commons.math3.complex.ComplexUtils; 25 | 26 | /** 27 | * Contains the coefficients of a 2nd order digital filter with two poles and two zeros 28 | */ 29 | public class Biquad { 30 | 31 | double m_a0; 32 | double m_a1; 33 | double m_a2; 34 | double m_b1; 35 | double m_b2; 36 | double m_b0; 37 | 38 | public double getA0() { 39 | return m_a0; 40 | } 41 | 42 | public double getA1() { 43 | return m_a1 * m_a0; 44 | } 45 | 46 | public double getA2() { 47 | return m_a2 * m_a0; 48 | } 49 | 50 | public double getB0() { 51 | return m_b0 * m_a0; 52 | } 53 | 54 | public double getB1() { 55 | return m_b1 * m_a0; 56 | } 57 | 58 | public double getB2() { 59 | return m_b2 * m_a0; 60 | } 61 | 62 | public Complex response(double normalizedFrequency) { 63 | double a0 = getA0(); 64 | double a1 = getA1(); 65 | double a2 = getA2(); 66 | double b0 = getB0(); 67 | double b1 = getB1(); 68 | double b2 = getB2(); 69 | 70 | double w = 2 * Math.PI * normalizedFrequency; 71 | Complex czn1 = ComplexUtils.polar2Complex(1., -w); 72 | Complex czn2 = ComplexUtils.polar2Complex(1., -2 * w); 73 | Complex ch = new Complex(1); 74 | Complex cbot = new Complex(1); 75 | 76 | Complex ct = new Complex(b0 / a0); 77 | Complex cb = new Complex(1); 78 | ct = MathSupplement.addmul(ct, b1 / a0, czn1); 79 | ct = MathSupplement.addmul(ct, b2 / a0, czn2); 80 | cb = MathSupplement.addmul(cb, a1 / a0, czn1); 81 | cb = MathSupplement.addmul(cb, a2 / a0, czn2); 82 | ch = ch.multiply(ct); 83 | cbot = cbot.multiply(cb); 84 | 85 | return ch.divide(cbot); 86 | } 87 | 88 | public void setCoefficients(double a0, double a1, double a2, 89 | double b0, double b1, double b2) { 90 | m_a0 = a0; 91 | m_a1 = a1 / a0; 92 | m_a2 = a2 / a0; 93 | m_b0 = b0 / a0; 94 | m_b1 = b1 / a0; 95 | m_b2 = b2 / a0; 96 | } 97 | 98 | public void setOnePole(Complex pole, Complex zero) { 99 | double a0 = 1; 100 | double a1 = -pole.getReal(); 101 | double a2 = 0; 102 | double b0 = 1; 103 | double b1 = -zero.getReal(); 104 | double b2 = 0; 105 | setCoefficients(a0, a1, a2, b0, b1, b2); 106 | } 107 | 108 | public void setTwoPole(Complex pole1, Complex zero1, 109 | Complex pole2, Complex zero2) { 110 | double a0 = 1; 111 | double a1; 112 | double a2; 113 | 114 | if (pole1.getImaginary() != 0) { 115 | 116 | a1 = -2 * pole1.getReal(); 117 | a2 = pole1.abs() * pole1.abs(); 118 | } else { 119 | 120 | a1 = -(pole1.getReal() + pole2.getReal()); 121 | a2 = pole1.getReal() * pole2.getReal(); 122 | } 123 | 124 | double b0 = 1; 125 | double b1; 126 | double b2; 127 | 128 | if (zero1.getImaginary() != 0) { 129 | 130 | b1 = -2 * zero1.getReal(); 131 | b2 = zero1.abs() * zero1.abs(); 132 | } else { 133 | 134 | b1 = -(zero1.getReal() + zero2.getReal()); 135 | b2 = zero1.getReal() * zero2.getReal(); 136 | } 137 | 138 | setCoefficients(a0, a1, a2, b0, b1, b2); 139 | } 140 | 141 | public void setPoleZeroForm(BiquadPoleState bps) { 142 | setPoleZeroPair(bps); 143 | applyScale(bps.gain); 144 | } 145 | 146 | public void setIdentity() { 147 | setCoefficients(1, 0, 0, 1, 0, 0); 148 | } 149 | 150 | public void applyScale(double scale) { 151 | m_b0 *= scale; 152 | m_b1 *= scale; 153 | m_b2 *= scale; 154 | } 155 | 156 | 157 | public void setPoleZeroPair(PoleZeroPair pair) { 158 | if (pair.isSinglePole()) { 159 | setOnePole(pair.poles.first, pair.zeros.first); 160 | } else { 161 | setTwoPole(pair.poles.first, pair.zeros.first, 162 | pair.poles.second, pair.zeros.second); 163 | } 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /src/main/java/uk/me/berndporr/iirj/Cascade.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | * Copyright (c) 2009 by Vinnie Falco 18 | * Copyright (c) 2016 by Bernd Porr 19 | */ 20 | 21 | 22 | package uk.me.berndporr.iirj; 23 | 24 | import org.apache.commons.math3.complex.Complex; 25 | import org.apache.commons.math3.complex.ComplexUtils; 26 | 27 | /** 28 | * 29 | * The mother of all filters. It contains the coefficients of all 30 | * filter stages as a sequence of 2nd order filters and the states 31 | * of the 2nd order filters which also imply if it's direct form I or II 32 | * 33 | */ 34 | public class Cascade { 35 | 36 | // coefficients 37 | private Biquad[] m_biquads; 38 | 39 | // the states of the filters 40 | private DirectFormAbstract[] m_states; 41 | 42 | // number of biquads in the system 43 | private int m_numBiquads; 44 | 45 | private int numPoles; 46 | 47 | public int getNumBiquads() { 48 | return m_numBiquads; 49 | } 50 | 51 | public Biquad getBiquad(int index) { 52 | return m_biquads[index]; 53 | } 54 | 55 | public Cascade() { 56 | m_numBiquads = 0; 57 | m_biquads = null; 58 | m_states = null; 59 | } 60 | 61 | public void reset() { 62 | for (int i = 0; i < m_numBiquads; i++) 63 | m_states[i].reset(); 64 | } 65 | 66 | public double filter(double in) { 67 | double out = in; 68 | for (int i = 0; i < m_numBiquads; i++) { 69 | if (m_states[i] != null) { 70 | out = m_states[i].process1(out, m_biquads[i]); 71 | } 72 | } 73 | return out; 74 | } 75 | 76 | public Complex response(double normalizedFrequency) { 77 | double w = 2 * Math.PI * normalizedFrequency; 78 | Complex czn1 = ComplexUtils.polar2Complex(1., -w); 79 | Complex czn2 = ComplexUtils.polar2Complex(1., -2 * w); 80 | Complex ch = new Complex(1); 81 | Complex cbot = new Complex(1); 82 | 83 | for (int i = 0; i < m_numBiquads; i++) { 84 | Biquad stage = m_biquads[i]; 85 | Complex cb = new Complex(1); 86 | Complex ct = new Complex(stage.getB0() / stage.getA0()); 87 | ct = MathSupplement.addmul(ct, stage.getB1() / stage.getA0(), czn1); 88 | ct = MathSupplement.addmul(ct, stage.getB2() / stage.getA0(), czn2); 89 | cb = MathSupplement.addmul(cb, stage.getA1() / stage.getA0(), czn1); 90 | cb = MathSupplement.addmul(cb, stage.getA2() / stage.getA0(), czn2); 91 | ch = ch.multiply(ct); 92 | cbot = cbot.multiply(cb); 93 | } 94 | 95 | return ch.divide(cbot); 96 | } 97 | 98 | public void applyScale(double scale) { 99 | // For higher order filters it might be helpful 100 | // to spread this factor between all the stages. 101 | if (m_biquads.length>0) { 102 | m_biquads[0].applyScale(scale); 103 | } 104 | } 105 | 106 | private void createStates(int filterTypes) { 107 | switch (filterTypes) { 108 | case DirectFormAbstract.DIRECT_FORM_I: 109 | m_states = new DirectFormI[m_numBiquads]; 110 | for (int i = 0; i < m_numBiquads; i++) { 111 | m_states[i] = new DirectFormI(); 112 | } 113 | break; 114 | case DirectFormAbstract.DIRECT_FORM_II: 115 | default: 116 | m_states = new DirectFormII[m_numBiquads]; 117 | for (int i = 0; i < m_numBiquads; i++) { 118 | m_states[i] = new DirectFormII(); 119 | } 120 | break; 121 | } 122 | } 123 | 124 | public void setLayout(LayoutBase proto, int filterTypes) { 125 | numPoles = proto.getNumPoles(); 126 | m_numBiquads = (numPoles + 1) / 2; 127 | m_biquads = new Biquad[m_numBiquads]; 128 | createStates(filterTypes); 129 | for (int i = 0; i < m_numBiquads; ++i) { 130 | PoleZeroPair p = proto.getPair(i); 131 | m_biquads[i] = new Biquad(); 132 | m_biquads[i].setPoleZeroPair(p); 133 | } 134 | applyScale(proto.getNormalGain() 135 | / ((response(proto.getNormalW() / (2 * Math.PI)))).abs()); 136 | } 137 | 138 | public void setSOScoeff(final double[][] sosCoefficients, 139 | final int stateTypes) { 140 | m_numBiquads = sosCoefficients.length; 141 | m_biquads = new Biquad[m_numBiquads]; 142 | createStates(stateTypes); 143 | for (int i = 0; i < m_numBiquads; ++i) { 144 | m_biquads[i] = new Biquad(); 145 | m_biquads[i].setCoefficients( 146 | sosCoefficients[i][3], 147 | sosCoefficients[i][4], 148 | sosCoefficients[i][5], 149 | sosCoefficients[i][0], 150 | sosCoefficients[i][1], 151 | sosCoefficients[i][2] 152 | ); 153 | } 154 | applyScale(1); 155 | } 156 | 157 | 158 | }; 159 | -------------------------------------------------------------------------------- /docs/uk/me/berndporr/iirj/class-use/ComplexPair.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Uses of Class uk.me.berndporr.iirj.ComplexPair (uk.me.berndporr:iirj 1.7 API) 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 24 |
25 | 48 |
49 |
50 |
51 |

Uses of Class
uk.me.berndporr.iirj.ComplexPair

52 |
53 |
54 | 83 |
84 |
85 |
86 |
87 | 88 |
89 |
90 |
91 | 92 | 93 | -------------------------------------------------------------------------------- /docs/script.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | 26 | var moduleSearchIndex; 27 | var packageSearchIndex; 28 | var typeSearchIndex; 29 | var memberSearchIndex; 30 | var tagSearchIndex; 31 | function loadScripts(doc, tag) { 32 | createElem(doc, tag, 'search.js'); 33 | 34 | createElem(doc, tag, 'module-search-index.js'); 35 | createElem(doc, tag, 'package-search-index.js'); 36 | createElem(doc, tag, 'type-search-index.js'); 37 | createElem(doc, tag, 'member-search-index.js'); 38 | createElem(doc, tag, 'tag-search-index.js'); 39 | } 40 | 41 | function createElem(doc, tag, path) { 42 | var script = doc.createElement(tag); 43 | var scriptElement = doc.getElementsByTagName(tag)[0]; 44 | script.src = pathtoroot + path; 45 | scriptElement.parentNode.insertBefore(script, scriptElement); 46 | } 47 | 48 | function show(tableId, selected, columns) { 49 | if (tableId !== selected) { 50 | document.querySelectorAll('div.' + tableId + ':not(.' + selected + ')') 51 | .forEach(function(elem) { 52 | elem.style.display = 'none'; 53 | }); 54 | } 55 | document.querySelectorAll('div.' + selected) 56 | .forEach(function(elem, index) { 57 | elem.style.display = ''; 58 | var isEvenRow = index % (columns * 2) < columns; 59 | elem.classList.remove(isEvenRow ? oddRowColor : evenRowColor); 60 | elem.classList.add(isEvenRow ? evenRowColor : oddRowColor); 61 | }); 62 | updateTabs(tableId, selected); 63 | } 64 | 65 | function updateTabs(tableId, selected) { 66 | document.querySelector('div#' + tableId +' .summary-table') 67 | .setAttribute('aria-labelledby', selected); 68 | document.querySelectorAll('button[id^="' + tableId + '"]') 69 | .forEach(function(tab, index) { 70 | if (selected === tab.id || (tableId === selected && index === 0)) { 71 | tab.className = activeTableTab; 72 | tab.setAttribute('aria-selected', true); 73 | tab.setAttribute('tabindex',0); 74 | } else { 75 | tab.className = tableTab; 76 | tab.setAttribute('aria-selected', false); 77 | tab.setAttribute('tabindex',-1); 78 | } 79 | }); 80 | } 81 | 82 | function switchTab(e) { 83 | var selected = document.querySelector('[aria-selected=true]'); 84 | if (selected) { 85 | if ((e.keyCode === 37 || e.keyCode === 38) && selected.previousSibling) { 86 | // left or up arrow key pressed: move focus to previous tab 87 | selected.previousSibling.click(); 88 | selected.previousSibling.focus(); 89 | e.preventDefault(); 90 | } else if ((e.keyCode === 39 || e.keyCode === 40) && selected.nextSibling) { 91 | // right or down arrow key pressed: move focus to next tab 92 | selected.nextSibling.click(); 93 | selected.nextSibling.focus(); 94 | e.preventDefault(); 95 | } 96 | } 97 | } 98 | 99 | var updateSearchResults = function() {}; 100 | 101 | function indexFilesLoaded() { 102 | return moduleSearchIndex 103 | && packageSearchIndex 104 | && typeSearchIndex 105 | && memberSearchIndex 106 | && tagSearchIndex; 107 | } 108 | 109 | // Workaround for scroll position not being included in browser history (8249133) 110 | document.addEventListener("DOMContentLoaded", function(e) { 111 | var contentDiv = document.querySelector("div.flex-content"); 112 | window.addEventListener("popstate", function(e) { 113 | if (e.state !== null) { 114 | contentDiv.scrollTop = e.state; 115 | } 116 | }); 117 | window.addEventListener("hashchange", function(e) { 118 | history.replaceState(contentDiv.scrollTop, document.title); 119 | }); 120 | contentDiv.addEventListener("scroll", function(e) { 121 | var timeoutID; 122 | if (!timeoutID) { 123 | timeoutID = setTimeout(function() { 124 | history.replaceState(contentDiv.scrollTop, document.title); 125 | timeoutID = null; 126 | }, 100); 127 | } 128 | }); 129 | if (!location.hash) { 130 | history.replaceState(contentDiv.scrollTop, document.title); 131 | } 132 | }); 133 | -------------------------------------------------------------------------------- /src/test/java/uk/me/berndporr/iirj/ParameterChecksTest.java: -------------------------------------------------------------------------------- 1 | package uk.me.berndporr.iirj; 2 | /* 3 | * Licensed to the Apache Software Foundation (ASF) under one or more 4 | * contributor license agreements. See the NOTICE file distributed with 5 | * this work for additional information regarding copyright ownership. 6 | * The ASF licenses this file to You under the Apache License, Version 2.0 7 | * (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | 20 | import java.io.PrintStream; 21 | import java.io.FileOutputStream; 22 | import java.io.File; 23 | 24 | import uk.me.berndporr.iirj.Butterworth; 25 | 26 | import org.junit.Assert; 27 | import org.junit.Test; 28 | 29 | // Various impulse responses written out to files so that you can plot them 30 | public class ParameterChecksTest { 31 | 32 | static String prefix="target/surefire-reports/parameter_checks/"; 33 | 34 | void createDir() throws Exception { 35 | File dir = new File(prefix); 36 | dir.mkdirs(); 37 | } 38 | 39 | @Test 40 | public void correctFsTest() throws Exception { 41 | 42 | Butterworth butterworth1 = new Butterworth(); 43 | butterworth1.lowPass(4, 250, 50); 44 | 45 | Butterworth butterworth2 = new Butterworth(); 46 | butterworth2.bandPass(2, 250, 50, 5); 47 | 48 | Butterworth butterworth3 = new Butterworth(); 49 | butterworth3.bandStop(2, 250, 50, 5); 50 | 51 | Butterworth butterworth4 = new Butterworth(); 52 | butterworth4.highPass(4, 250, 50); 53 | } 54 | 55 | @Test 56 | public void wrongFcTestLowpass() throws Exception { 57 | Butterworth butterworth = new Butterworth(); 58 | try { 59 | butterworth.lowPass(4, 250, 125); 60 | Assert.fail("Exception not generated for wrong fc."); 61 | } catch (Exception e) { 62 | System.out.println("Lowpass exception for fc = 0.5: "+e.getMessage()); 63 | } 64 | } 65 | 66 | @Test 67 | public void wrongFcTestHighpass() throws Exception { 68 | Butterworth butterworth = new Butterworth(); 69 | try { 70 | butterworth.highPass(4, 250, 125); 71 | Assert.fail("Exception not generated for wrong fc."); 72 | } catch (Exception e) { 73 | System.out.println("Highpass exception for fc = 0.5: "+e.getMessage()); 74 | } 75 | } 76 | 77 | @Test 78 | public void wrongFcTestBandpass() throws Exception { 79 | Butterworth butterworth = new Butterworth(); 80 | try { 81 | butterworth.bandPass(2, 250, 125, 5); 82 | Assert.fail("Exception not generated for wrong fc."); 83 | } catch (Exception e) { 84 | System.out.println("Bandpass exception for fc = 0.5: "+e.getMessage()); 85 | } 86 | } 87 | 88 | @Test 89 | public void wrongFcTestBandstop() throws Exception { 90 | Butterworth butterworth = new Butterworth(); 91 | try { 92 | butterworth.bandStop(2, 250, 125, 5); 93 | Assert.fail("Exception not generated for wrong fc."); 94 | } catch (Exception e) { 95 | System.out.println("Bandstop exception for fc = 0.5: "+e.getMessage()); 96 | } 97 | } 98 | 99 | @Test 100 | public void negFcTestLowpass() throws Exception { 101 | Butterworth butterworth = new Butterworth(); 102 | try { 103 | butterworth.lowPass(4, 250, -1); 104 | Assert.fail("Exception not generated for wrong fc."); 105 | } catch (Exception e) { 106 | System.out.println("Lowpass exception for fc < 0: "+e.getMessage()); 107 | } 108 | } 109 | 110 | @Test 111 | public void negFcTestHighpass() throws Exception { 112 | Butterworth butterworth = new Butterworth(); 113 | try { 114 | butterworth.highPass(4, 250, -1); 115 | Assert.fail("Exception not generated for wrong fc."); 116 | } catch (Exception e) { 117 | System.out.println("Highpass exception for fc < 0: "+e.getMessage()); 118 | } 119 | } 120 | 121 | @Test 122 | public void negFcTestBandpass() throws Exception { 123 | Butterworth butterworth = new Butterworth(); 124 | try { 125 | butterworth.bandPass(2, 250, -1, 5); 126 | Assert.fail("Exception not generated for wrong fc."); 127 | } catch (Exception e) { 128 | System.out.println("Bandpass exception for fc < 0: "+e.getMessage()); 129 | } 130 | } 131 | 132 | @Test 133 | public void negFcTestBandstop() throws Exception { 134 | Butterworth butterworth = new Butterworth(); 135 | try { 136 | butterworth.bandStop(2, 250, -1, 5); 137 | Assert.fail("Exception not generated for wrong fc."); 138 | } catch (Exception e) { 139 | System.out.println("Bandstop exception for fc < 0: "+e.getMessage()); 140 | } 141 | } 142 | 143 | @Test 144 | public void bessorderOutOfRange() throws Exception { 145 | final int orderTooHigh = Bessel.MAX_ORDER+1; 146 | try { 147 | Bessel bessel = new Bessel(); 148 | bessel.lowPass(orderTooHigh, 250, 50); 149 | Assert.fail("Exception not generated for out of range order."); 150 | } catch (Exception e) { 151 | System.out.println("Bessel exception for order at "+orderTooHigh+": "+e.getMessage()); 152 | } 153 | } 154 | 155 | public void main(String args[]) { 156 | try { 157 | correctFsTest(); 158 | wrongFcTestLowpass(); 159 | wrongFcTestHighpass(); 160 | wrongFcTestBandpass(); 161 | wrongFcTestBandstop(); 162 | negFcTestLowpass(); 163 | negFcTestHighpass(); 164 | negFcTestBandpass(); 165 | negFcTestBandstop(); 166 | } catch (Exception e) { 167 | } 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /docs/uk/me/berndporr/iirj/class-use/Biquad.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Uses of Class uk.me.berndporr.iirj.Biquad (uk.me.berndporr:iirj 1.7 API) 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 24 |
25 | 48 |
49 |
50 |
51 |

Uses of Class
uk.me.berndporr.iirj.Biquad

52 |
53 |
54 | 88 |
89 |
90 |
91 |
92 | 93 |
94 |
95 |
96 | 97 | 98 | -------------------------------------------------------------------------------- /docs/uk/me/berndporr/iirj/package-tree.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | uk.me.berndporr.iirj Class Hierarchy (uk.me.berndporr:iirj 1.7 API) 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 24 |
25 | 48 |
49 |
50 |
51 |

Hierarchy For Package uk.me.berndporr.iirj

52 |
53 |
54 |

Class Hierarchy

55 | 89 |
90 |
91 |
92 |
93 | 94 |
95 |
96 |
97 | 98 | 99 | -------------------------------------------------------------------------------- /docs/uk/me/berndporr/iirj/class-use/Cascade.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Uses of Class uk.me.berndporr.iirj.Cascade (uk.me.berndporr:iirj 1.7 API) 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 24 |
25 | 48 |
49 |
50 |
51 |

Uses of Class
uk.me.berndporr.iirj.Cascade

52 |
53 |
54 |
    55 |
  • 56 |
    57 |

    Uses of Cascade in uk.me.berndporr.iirj

    58 |
    Subclasses of Cascade in uk.me.berndporr.iirj
    59 |
    60 |
    Modifier and Type
    61 |
    Class
    62 |
    Description
    63 |
    class 
    64 | 65 |
    66 |
    User facing class which contains all the methods the user uses to create 67 | Bessel filters.
    68 |
    69 |
    class 
    70 | 71 |
    72 |
    User facing class which contains all the methods the user uses 73 | to create Butterworth filters.
    74 |
    75 |
    class 
    76 | 77 |
    78 |
    User facing class which contains all the methods the user uses to create 79 | ChebyshevI filters.
    80 |
    81 |
    class 
    82 | 83 |
    84 |
    User facing class which contains all the methods the user uses to create 85 | ChebyshevI filters.
    86 |
    87 |
    class 
    88 | 89 |
    90 |
    User facing class which contains two methods 91 | to create Custom SOS filters, in particular where 92 | the filter coefficients have been generated by 93 | Python's scipy signal library for example: 94 | sos = signal.butter(4, 0.1, output='sos').
    95 |
    96 |
    97 |
    98 |
  • 99 |
100 |
101 |
102 |
103 |
104 | 105 |
106 |
107 |
108 | 109 | 110 | -------------------------------------------------------------------------------- /docs/overview-tree.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Class Hierarchy (uk.me.berndporr:iirj 1.7 API) 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 24 |
25 | 48 |
49 |
50 |
51 |

Hierarchy For All Packages

52 | Package Hierarchies: 53 | 56 |
57 |
58 |

Class Hierarchy

59 | 93 |
94 |
95 |
96 |
97 | 98 |
99 |
100 |
101 | 102 | 103 | -------------------------------------------------------------------------------- /docs/uk/me/berndporr/iirj/class-use/PoleZeroPair.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Uses of Class uk.me.berndporr.iirj.PoleZeroPair (uk.me.berndporr:iirj 1.7 API) 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 24 |
25 | 48 |
49 |
50 |
51 |

Uses of Class
uk.me.berndporr.iirj.PoleZeroPair

52 |
53 |
54 | 99 |
100 |
101 |
102 |
103 | 104 |
105 |
106 |
107 | 108 | 109 | -------------------------------------------------------------------------------- /docs/uk/me/berndporr/iirj/class-use/LayoutBase.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Uses of Class uk.me.berndporr.iirj.LayoutBase (uk.me.berndporr:iirj 1.7 API) 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 24 |
25 | 48 |
49 |
50 |
51 |

Uses of Class
uk.me.berndporr.iirj.LayoutBase

52 |
53 |
54 | 99 |
100 |
101 | 105 |
106 |
107 | 108 | 109 | --------------------------------------------------------------------------------