-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathFilterCurve.qml
132 lines (108 loc) · 4.04 KB
/
FilterCurve.qml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import QtQuick 2.0
Item {
id: filter
implicitWidth: 240
implicitHeight: 140
property real cutoffFreq: 20
property real resonance: 0.0
property real zoomIn: 50
property string type: "onePoleLowPassFilter"
onCutoffFreqChanged: canvas.requestPaint()
onResonanceChanged: canvas.requestPaint()
onZoomInChanged: canvas.requestPaint()
onTypeChanged: canvas.requestPaint()
Canvas {
id: canvas
anchors.fill: parent
antialiasing: true
function log10Axes() {
var theFunction;
var args = [];
for(var i = 0; i < arguments.length; ++i) {
if(0 == i) {
theFunction = arguments[i];
}
else {
args.push(Math.pow(10, arguments[i] / filter.zoomIn));
}
}
Math.log10 = Math.log10 || function(x) { // on some systems Math.log10() is not available
return Math.log(x) * Math.LOG10E;
};
return Math.log10(theFunction.apply(this, args)) * filter.zoomIn; // expand array as function argument list
}
function onePoleLowPassFilter(freq, cutoff) {
var A = 1.0;
return A / Math.sqrt(1 + ( (freq * freq) / (cutoff * cutoff) ));
}
function onePoleHighPassFilter(freq, cutoff) {
var A = freq / cutoff;
return A / Math.sqrt(1 + ( (freq * freq) / (cutoff * cutoff) ));
}
function twoPoleLowPassFilter(freq, cutoff) {
var X = freq / cutoff;
var A = 1.0;
var damping = (100.0 - filter.resonance) / 100.0;
return A / Math.sqrt( (1 - X * X) * (1 - X * X) + 4 * X * X * damping * damping);
}
function twoPoleHighPassFilter(freq, cutoff) {
var X = freq / cutoff;
var A = X * X;
var damping = (100.0 - filter.resonance) / 100.0;
return A / Math.sqrt( (1 - X * X) * (1 - X * X) + 4 * X * X * damping * damping);
}
function twoPoleBandPassFilter(freq, cutoff) {
var X = freq / cutoff;
var damping = (100.0 - filter.resonance) / 100.0;
var A = 2 * X * damping;
return A / Math.sqrt( (1 - X * X) * (1 - X * X) + 4 * X * X * damping * damping);
}
onPaint: {
var funct;
switch(type){
case "onePoleLowPassFilter":
funct = onePoleLowPassFilter;
break;
case "onePoleHighPassFilter":
funct = onePoleHighPassFilter;
break;
case "twoPoleLowPassFilter":
funct = twoPoleLowPassFilter;
break;
case "twoPoleHighPassFilter":
funct = twoPoleHighPassFilter;
break;
case "twoPoleBandPassFilter":
funct = twoPoleBandPassFilter;
break;
}
var yOffset = 50;
var ctx = getContext("2d")
ctx.setTransform(1, 0, 0, -1, 0, canvas.height);
// Clear Canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Draw coordinate system
ctx.lineWidth = 1
ctx.strokeStyle = "blue"
ctx.beginPath()
ctx.moveTo(5, 1);
ctx.lineTo(5, canvas.height - 1);
ctx.moveTo(1, yOffset);
ctx.lineTo(canvas.width - 1, yOffset);
ctx.stroke()
// Draw Filter Curve
ctx.lineWidth = 3
ctx.beginPath()
for (var x = 0; x < canvas.width; ++x){
ctx.lineTo(x, log10Axes( funct, x, filter.cutoffFreq) + yOffset );
}
// Draw Cutoff Sign
ctx.lineWidth = 3
ctx.strokeStyle = "red"
ctx.moveTo(filter.cutoffFreq, yOffset - 4);
ctx.lineTo(filter.cutoffFreq, yOffset + 4);
ctx.stroke()
ctx.resetTransform();
}
}
}