Apply a digital filter (direct form II transposed): Difference between revisions
Apply a digital filter (direct form II transposed) (view source)
Revision as of 11:18, 6 November 2023
, 7 months ago→{{header|Wren}}: Minor tidy
(Added Algol 68) |
m (→{{header|Wren}}: Minor tidy) |
||
(8 intermediate revisions by 6 users not shown) | |||
Line 8:
The signal that needs filtering is the following vector: [-0.917843918645, 0.141984778794, 1.20536903482, 0.190286794412, -0.662370894973, -1.00700480494, -0.404707073677 ,0.800482325044, 0.743500089861, 1.01090520172, 0.741527555207, 0.277841675195, 0.400833448236, -0.2085993586, -0.172842103641, -0.134316096293, 0.0259303398477, 0.490105989562, 0.549391221511, 0.9047198589]
;See also:
[[https://en.wikipedia.org/wiki/Butterworth_filter Wikipedia on Butterworth filters]]
=={{header|11l}}==
{{trans|Nim}}
<
V result = [0.0] * signal.len
L(i) 0 .< signal.len
Line 36 ⟶ 40:
L(r) result
print(‘#2.8’.format(r), end' ‘’)
print(I (L.index + 1) % 5 != 0 {‘, ’} E "\n", end' ‘’)</
{{out}}
Line 47 ⟶ 51:
=={{header|Ada}}==
<
procedure Apply_Filter is
Line 106 ⟶ 110:
Ada.Text_IO.New_Line;
end loop;
end Apply_Filter;</
=={{header|ALGOL 68}}==
{{Trans|C++}} ... via Yabasic<br>
... with the "j" loops transformed to not needlessly iterate beyond i.<br>
The default lower bound in Algol 68 arrays is 1, so the loops/subscripts have been adjusted accordingly.
<syntaxhighlight lang
BEGIN # apply a digital filter #
# the lower bounds of a, b, signal and result must all be equal #
PROC filter = ( []REAL a, b, signal, REF[]REAL result )VOID:
IF LWB a /= LWB b OR LWB a /= LWB signal OR LWB a /= LWB result THEN
print( ( "Array lower bounds must be equal for filter", newline ) );
stop
ELSE
FOR i FROM LWB result TO UPB result DO result[ i ] := 0 OD;
FOR i FROM LWB signal TO UPB signal DO
REAL tmp := 0;
FOR j FROM LWB b TO IF i > UPB b THEN UPB b ELSE i FI DO
OD;
FOR j FROM LWB a + 1 TO IF i > UPB a THEN UPB a ELSE i FI DO
OD;
result[ i ] := tmp / a[ LWB a ]
OD
[ 4 ]REAL a := []REAL( 1, -2.77555756e-16, 3.33333333e-01, -1.85037171e-17 );
[ 4 ]REAL b := []REAL( 0.16666667, 0.5, 0.5, 0.16666667 );
Line 141 ⟶ 151:
IF i MOD 5 /= 0 THEN print( ( ", " ) ) ELSE print( ( newline ) ) FI
OD
END
</syntaxhighlight>
{{out}}
<pre>
Line 149 ⟶ 160:
-0.211722, -0.174746, 0.069258, 0.385446, 0.651771
</pre>
=={{header|AppleScript}}==
{{trans|Julia}} — except that j starts from 2 in the second inner repeat, there being no point in fetching and performing math with the zero about to be overwritten. This change in turn allows the result list to be populated on the fly instead of being pre-populated with zeros.
<
if (b < a) then return b
return a
Line 185 ⟶ 197:
0.400833448236, -0.2085993586, -0.172842103641, -0.134316096293, ¬
0.025930339848, 0.490105989562, 0.549391221511, 0.9047198589}
DF2TFilter(acoef, bcoef, signal)</
{{output}}
<
=={{header|C}}==
Given the number of values a coefficient or signal vector can have and the number of digits, this implementation reads data from a file and prints it to the console if no output file is specified or writes to the specified output file. Usage printed on incorrect invocation.
<syntaxhighlight lang="c">
#include<stdlib.h>
#include<string.h>
Line 306 ⟶ 318:
return 0;
}
</syntaxhighlight>
Input file, 3 lines containing first ( a ) and second ( b ) coefficient followed by the signal, all values should be separated by a single space:
<pre>
Line 325 ⟶ 337:
=={{header|C sharp|C#}}==
{{trans|Java}}
<
namespace ApplyDigitalFilter {
Line 366 ⟶ 378:
}
}
}</
{{out}}
<pre>-0.15297399, -0.43525783, -0.13604340, 0.69750333, 0.65644469
Line 377 ⟶ 389:
This uses the C++11 method of initializing vectors. In g++, use the -std=c++0x compiler switch.
<
#include <iostream>
using namespace std;
Line 428 ⟶ 440:
return 0;
}</
{{out}}
Line 435 ⟶ 447:
=={{header|Common Lisp}}==
{{trans|zkl}}
<
(defparameter b #(0.16666667L0 0.50000000L0 0.50000000L0 0.16666667L0))
(defparameter s #(-0.917843918645 0.141984778794 1.20536903482 0.190286794412 -0.662370894973
Line 450 ⟶ 462:
when (>= i j) sum (* (svref a j) (svref out (- i j)))))
(svref a 0)))
(format t "~%~16,8F" (svref out i)))</
{{out}}
<pre> -0.15297399
Line 476 ⟶ 488:
=={{header|D}}==
{{trans|Kotlin}}
<
alias T = real;
Line 522 ⟶ 534:
}
}
}</
{{out}}
Line 532 ⟶ 544:
=={{header|FreeBASIC}}==
{{trans|Yabasic}}
<
Dim As Integer j, k
Dim As Double tmp
Line 579 ⟶ 591:
Data 0.0259303398477, 0.490105989562, 0.549391221511, 0.9047198589
Sleep</
{{out}}
<pre>
Line 589 ⟶ 601:
=={{header|Go}}==
<
import "fmt"
Line 639 ⟶ 651:
fmt.Printf("%9.6f\n", v)
}
}</
{{out}}
<pre>
Line 666 ⟶ 678:
=={{header|Groovy}}==
{{trans|Java}}
<
private static double[] filter(double[] a, double[] b, double[] signal) {
double[] result = new double[signal.length]
Line 702 ⟶ 714:
}
}
}</
{{out}}
<pre>-0.15297399, -0.43525783, -0.13604340, 0.69750333, 0.65644469
Line 711 ⟶ 723:
=={{header|Haskell}}==
The solution is based not on the explicit loops, as in strict imperative languages, but on lazy recursive trick known as "tying a knot".
<
-- lazy convolution of a list by given kernel
Line 724 ⟶ 736:
dFilter (a0:a) b s = tail res
where
res = (/ a0) <$> 0 : zipWith (-) (conv b s) (conv a res)</
=== Examples ===
Line 753 ⟶ 765:
There's probably a nicer way to do this:
<
t=. (#n) +/ .*&(|.n)\(}.n*0),y
A=.|.}.m
Line 780 ⟶ 792:
_0.435482 _1.08924 _0.537677 0.51705 1.05225
0.961854 0.69569 0.424356 0.196262 _0.0278351
_0.211722 _0.174746 0.0692584 0.385446 0.651771</
=={{header|Java}}==
{{trans|Kotlin}}
<
private static double[] filter(double[] a, double[] b, double[] signal) {
double[] result = new double[signal.length];
Line 821 ⟶ 833:
}
}
}</
{{out}}
<pre>-0.15297399, -0.43525783, -0.13604340, 0.69750333, 0.65644469
Line 830 ⟶ 842:
=={{header|Julia}}==
{{trans|zkl}}
<
rst = zeros(sig)
for i in eachindex(sig)
Line 847 ⟶ 859:
0.400833448236, -0.2085993586, -0.172842103641, -0.134316096293,
0.0259303398477, 0.490105989562, 0.549391221511, 0.9047198589]
@show DF2TFilter(acoef, bcoef, signal)</
{{output}}<pre>DF2TFilter(acoef, bcoef, signal) = [-0.152974, -0.435258, -0.136043, 0.697503, 0.656445, -0.435482, -1.08924, -0.537677, 0.51705, 1.05225, 0.961854, 0.69569, 0.424356, 0.196262, -0.0278351, -0.211722, -0.174746, 0.0692584, 0.385446, 0.651771]</pre>
=={{header|Kotlin}}==
{{trans|C++}}
<
fun filter(a: DoubleArray, b: DoubleArray, signal: DoubleArray): DoubleArray {
Line 889 ⟶ 901:
print(if ((i + 1) % 5 != 0) ", " else "\n")
}
}</
{{out}}
Line 901 ⟶ 913:
=={{header|Lua}}==
{{trans|C++}}
<
local out = {}
for i=1,table.getn(input) do
Line 951 ⟶ 963:
end
main()</
{{out}}
<pre>-0.15297398950031, -0.43525782905022, -0.13604339698849, 0.69750332654796, 0.65644469246903, -0.43548245325611, -1.0892394611529, -0.53767654956275, 0.51704999231321, 1.0522497471554, 0.96185430037364, 0.6956900940096, 0.42435629509553, 0.19626223182179, -0.027835124463393, -0.21172191545012, -0.17474556222276, 0.069258408901195, 0.38544587430744, 0.65177083881931,</pre>
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<
a = {1.00000000, -2.77555756*^-16, 3.33333333*^-01, -1.85037171*^-17};
signal = {-0.917843918645, 0.141984778794, 1.20536903482, 0.190286794412, -0.662370894973, -1.00700480494, -0.404707073677, 0.800482325044, 0.743500089861, 1.01090520172, 0.741527555207, 0.277841675195, 0.400833448236, -0.2085993586, -0.172842103641, -0.134316096293, 0.0259303398477, 0.490105989562, 0.549391221511, 0.9047198589};
RecurrenceFilter[{a, b}, signal]</
{{out}}
<pre>{-0.152974,-0.435258,-0.136043,0.697503,0.656445,-0.435482,-1.08924,-0.537677,0.51705,1.05225,0.961854,0.69569,0.424356,0.196262,-0.0278351,-0.211722,-0.174746,0.0692584,0.385446,0.651771}</pre>
Line 965 ⟶ 977:
=={{header|MATLAB}}==
MATLAB is commonly used for filter design and implementation. To implement this filter, and display the original signal and the filtered result:
<syntaxhighlight lang="matlab">
signal = [-0.917843918645, 0.141984778794, 1.20536903482, 0.190286794412, -0.662370894973, -1.00700480494, -0.404707073677 ,0.800482325044, 0.743500089861, 1.01090520172, 0.741527555207, 0.277841675195, 0.400833448236, -0.2085993586, -0.172842103641, -0.134316096293, 0.0259303398477, 0.490105989562, 0.549391221511, 0.9047198589];
a = [1.00000000, -2.77555756e-16, 3.33333333e-01, -1.85037171e-17];
Line 982 ⟶ 994:
xlabel('n')
title('Filtered Signal')
</syntaxhighlight>
{{out}}
Line 999 ⟶ 1,011:
=={{header|Nim}}==
{{trans|Kotlin}}
<syntaxhighlight lang="nim">
import strformat
Line 1,029 ⟶ 1,041:
for i in 0..result.high:
stdout.write fmt"{result[i]: .8f}"
stdout.write if (i + 1) mod 5 != 0: ", " else: "\n"</
{{out}}
Line 1,039 ⟶ 1,051:
=={{header|Objeck}}==
{{trans|Java}}
<
function : Main(args : String[]) ~ Nil {
a := [1.00000000, -2.77555756e-16, 3.33333333e-01, -1.85037171e-17];
Line 1,079 ⟶ 1,091:
return result;
}
}</
{{output}}
Line 1,090 ⟶ 1,102:
=={{header|ooRexx}}==
<
a=.array~of(1.00000000, -2.77555756e-16, 3.33333333e-01, -1.85037171e-17)
b=.array~of(0.16666667, 0.5, 0.5, 0.16666667)
Line 1,126 ⟶ 1,138:
::OPTIONS digits 24 /* Numeric Digits 24, everywhere */
</syntaxhighlight>
{{out|output}}
<pre> 1 -0.152973989500
Line 1,151 ⟶ 1,163:
=={{header|Perl}}==
{{trans|Raku}}
<
use List::AllUtils 'natatime';
Line 1,182 ⟶ 1,194:
printf(' %10.6f' x 5 . "\n", @values);
}
</syntaxhighlight>
{{out}}
<pre> -0.152974 -0.435258 -0.136043 0.697503 0.656445
Line 1,193 ⟶ 1,205:
Note however that the a[j]* starts from index 2, unlike Julia/C/Raku/Rust/Sidef/zkl,
but the same as C++/C#/D/Java/Kotlin - and it does not seem to make any difference...
<!--<
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">direct_form_II_transposed_filter</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">signal</span><span style="color: #0000FF;">)</span>
Line 1,214 ⟶ 1,226:
<span style="color: #7060A8;">pp</span><span style="color: #0000FF;">(</span><span style="color: #000000;">direct_form_II_transposed_filter</span><span style="color: #0000FF;">(</span><span style="color: #000000;">acoef</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">bcoef</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">signal</span><span style="color: #0000FF;">),{</span><span style="color: #004600;">pp_FltFmt</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%9.6f"</span><span style="color: #0000FF;">,</span><span style="color: #004600;">pp_Maxlen</span><span style="color: #0000FF;">,</span><span style="color: #000000;">110</span><span style="color: #0000FF;">})</span>
<!--</
{{out}}
<pre>
Line 1,223 ⟶ 1,235:
=={{header|Phixmonti}}==
{{trans|Phix}}
<
( 1.00000000 -2.77555756e-16 3.33333333e-01 -1.85037171e-17 ) var a
Line 1,246 ⟶ 1,258:
ps> a 1 get nip / ps> swap i set >ps
endfor
drop ps> ?</
{{out}}
<pre>[-0.152973989500313, -0.435257829050217, -0.13604339698849, 0.697503326547963, 0.656444692469029, -0.435482453256106, -1.089239461152929, -0.537676549562755, 0.517049992313214, 1.052249747155353, 0.961854300373645, 0.695690094009605, 0.424356295095532, 0.196262231821789, -0.0278351244633933, -0.211721915450118, -0.174745562222761, 0.0692584089011949, 0.385445874307439, 0.651770838819305]
Line 1,254 ⟶ 1,266:
=={{header|Python}}==
<
from __future__ import print_function
from scipy import signal
Line 1,276 ⟶ 1,288:
plt.plot(sig, 'b')
plt.plot(filt, 'r--')
plt.show()</
{{out}}
Line 1,287 ⟶ 1,299:
{{trans|C}} Strangely, C was more informative than Common Lisp in helping figure out what was going on here.
<
(define a (vector 1.00000000E0 -2.77555756E-16 3.33333333E-01 -1.85037171E-17))
Line 1,309 ⟶ 1,321:
filtered-signal)
(filter-signal-direct-form-ii-transposed a b s)</
{{out}}
Line 1,338 ⟶ 1,350:
{{trans|zkl}}
<syntaxhighlight lang="raku"
my @out = 0 xx @signal;
for ^@signal -> $i {
Line 1,360 ⟶ 1,372:
say TDF-II-filter(@signal, @a, @b)».fmt("% 0.8f")
Z~ flat (', ' xx 4, ",\n") xx *;</
{{out}}
<pre>(-0.15297399, -0.43525783, -0.13604340, 0.69750333, 0.65644469,
Line 1,371 ⟶ 1,383:
===version 1===
{{trans|Julia}}
<
@a= '1 -2.77555756e-16 3.33333333e-1 -1.85037171e-17' /*filter coefficients*/
@b= 0.16666667 0.5 0.5 0.16666667 /* " " */
Line 1,386 ⟶ 1,398:
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
tell: numeric digits digits()%2; say right(i, w) " " left('', $.i>=0)$.i /1; return</
{{out|output}}
<pre>
Line 1,413 ⟶ 1,425:
===version 2===
{{trans|Julia}}
<
Numeric Digits 24
acoef = '1.00000000, -2.77555756e-16, 3.33333333e-01, -1.85037171e-17'
Line 1,444 ⟶ 1,456:
ret.i=temp/a.1
Say format(i,2) format(ret.i,2,12)
End</
{{out|output}}
<pre> 1 -0.152973989500
Line 1,467 ⟶ 1,479:
20 0.651770838819
</pre>
=={{header|RPL}}==
We use here useful list handling functions that are available from HP48G or newer models.
{| class="wikitable"
! RPL code
! Comment
|-
|
≪
ROT REVLIST ROT REVLIST → signal a b
≪ { } 1 signal SIZE '''FOR''' j
signal j b SIZE - 1 + j SUB
'''WHILE''' DUP SIZE b SIZE < '''REPEAT''' 0 SWAP + '''END'''
b * ∑LIST
OVER j a SIZE - 1 + j 1 - SUB 0 +
'''WHILE''' DUP SIZE a SIZE < '''REPEAT''' 0 SWAP + '''END'''
a * ∑LIST -
a DUP SIZE GET / +
'''NEXT'''
≫ ≫ '<span style="color:blue">'''FILTR'''</span>' STO
|
<span style="color:blue">'''FILTR'''</span> ''( {a} {b} {signal} → {filtered} ) ''
Reverse a and b
For j = 1 to last signal item
extract what to multiply to b
prepend 0's if necessary
multiply by b and sum
extract what to multiply by a except a[0]
prepend 0's if necessary
multiply by a, sum and substract
divide by a[0] which is the last item once a reversed
|}
Figures have been rounded to 3 digits after the decimal point to ease the 100% manual data transfer.
{ 1 -2.778E-16 0.3333 -1.851E-17 }
{ 0.1667 0.5 0.5 0.1667}
{ -0.9178 0.1420 1.2054 0.1903 -0.6624
-1.007 -0.4047 0.8005 0.7435 1.0109
0.7415 0.2778 0.4008 -0.2086 -0.17281 -
-0.1343 0.02593 0.4901 0.5494 0.90472 }
<span style="color:blue">'''FILTR'''</span> 3 RND
'''Output:'''
<span style="color:grey"> 1:</span> { -.153 -.435 -.136 .697 .656
-.436 -1.089 -.538 .517 1.052
.962 .696 .425 .196 .028
-.212 -.175 .069 .386 .652 }
=={{header|Ruby}}==
{{trans|C#}}
<
result = Array.new(signal.length(), 0.0)
for i in 0..signal.length()-1 do
Line 1,510 ⟶ 1,569:
end
main()</
{{out}}
<pre>-0.15297399, -0.43525783, -0.13604340, 0.69750333, 0.65644469
Line 1,519 ⟶ 1,578:
=={{header|Rust}}==
{{trans|Java}}
<
struct IIRFilter<'f>(&'f [f32], &'f [f32]);
Line 1,620 ⟶ 1,679:
}
println!();
}</
{{out|output}}
<pre>
Line 1,636 ⟶ 1,695:
{{libheader|Scastie qualified}}
{{works with|Scala|2.13}}
<
private def filter(a: Vector[Double],
b: Vector[Double],
Line 1,671 ⟶ 1,730:
.foreach(line => println(line.mkString(" ")))
}</
=={{header|Sidef}}==
{{trans|Raku}}
<
var out = [0]*signal.len
for i in ^signal {
Line 1,700 ⟶ 1,759:
say "["
say f.map { "% 0.8f" % _ }.slices(5).map{.join(', ')}.join(",\n")
say "]"</
{{out}}
<pre>
Line 1,712 ⟶ 1,771:
=={{header|Visual Basic .NET}}==
{{trans|C#}}
<
Function Filter(a As Double(), b As Double(), signal As Double()) As Double()
Line 1,755 ⟶ 1,814:
End Sub
End Module</
{{out}}
<pre>-0.15297399, -0.43525783, -0.13604340, 0.69750333, 0.65644469
Line 1,762 ⟶ 1,821:
-0.21172192, -0.17474556, 0.06925841, 0.38544587, 0.65177084</pre>
=={{header|V (Vlang)}}==
{{trans|Go}}
<syntaxhighlight lang="v (vlang)">struct Filter {
b []f64
a []f64
Line 1,811 ⟶ 1,870:
println("${v:9.6}")
}
}</
{{out}}
Line 1,840 ⟶ 1,899:
{{trans|Kotlin}}
{{libheader|Wren-fmt}}
<
var filter = Fn.new { |a, b, signal|
Line 1,875 ⟶ 1,934:
Fmt.write("$11.8f", result[i])
System.write(((i + 1) % 5 != 0) ? ", " : "\n")
}</
{{out}}
<pre>
-0.15297399, -0.43525783, -0.13604340, 0.69750333, 0.65644469
-0.43548245, -1.08923946, -0.53767655, 0.51704999, 1.05224975
0.96185430, 0.69569009, 0.42435630, 0.19626223, -0.02783512
-0.21172192, -0.17474556, 0.06925841, 0.38544587, 0.65177084
</pre>
=={{header|XPL0}}==
<syntaxhighlight lang "XPL0">real A, B, Signal, Temp, Result(20);
int I, J;
[A:= [1.00000000, -2.77555756e-16, 3.33333333e-01, -1.85037171e-17];
B:= [0.16666667, 0.5, 0.5, 0.16666667];
Signal:= [
-0.917843918645, 0.141984778794, 1.20536903482, 0.190286794412,
-0.662370894973, -1.00700480494, -0.404707073677, 0.800482325044,
0.743500089861, 1.01090520172, 0.741527555207, 0.277841675195,
0.400833448236, -0.2085993586, -0.172842103641, -0.134316096293,
0.0259303398477, 0.490105989562, 0.549391221511, 0.9047198589 ];
Format(2, 8);
for I:= 0 to 20-1 do
[Temp:= 0.;
for J:= 0 to 4-1 do
if I-J >= 0 then
Temp:= Temp + B(J)*Signal(I-J);
for J:= 1 to 4-1 do
if I-J >= 0 then
Temp:= Temp - A(J)*Result(I-J);
Result(I):= Temp / A(0);
RlOut(0, Result(I));
Text(0, if rem(I/5) = 4 then "^m^j" else ", ");
];
]</syntaxhighlight>
{{out}}
<pre>
Line 1,887 ⟶ 1,979:
=={{header|Yabasic}}==
{{trans|D}}
<
local i, j, tmp
Line 1,931 ⟶ 2,023:
print
end if
next</
=={{header|zkl}}==
{{trans|C++}}
<
out:=List.createLong(signal.len(),0.0); // vector of zeros
foreach i in (signal.len()){
Line 1,944 ⟶ 2,036:
}
out
}</
<
-0.662370894973,-1.00700480494, -0.404707073677, 0.800482325044,
0.743500089861, 1.01090520172, 0.741527555207, 0.277841675195,
Line 1,953 ⟶ 2,045:
b:=T(0.16666667, 0.5, 0.5, 0.16666667 );
result:=direct_form_II_transposed_filter(b,a,signal);
println(result);</
{{out}}
<pre>
|