2021-06-21 03:47:17 +00:00
|
|
|
<link rel="stylesheet" href="https://cdn.lineicons.com/2.0/LineIcons.css">
|
|
|
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
|
|
|
|
<script type="text/javascript" src="flotr2.min.js"></script>
|
|
|
|
<script src="math.js" type="text/javascript"></script>
|
|
|
|
<link rel="preconnect" href="https://fonts.gstatic.com">
|
|
|
|
<link href="https://fonts.googleapis.com/css2?family=Hind+Vadodara:wght@300;500&display=swap" rel="stylesheet">
|
|
|
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
|
|
|
|
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
|
|
|
|
|
|
|
|
<link rel="stylesheet" href="style.css">
|
|
|
|
<div class="container">
|
|
|
|
<div class="header">
|
|
|
|
<div class="header-logo">
|
|
|
|
<span class="site-title">All Pass Library</span>
|
2021-06-18 00:46:31 +00:00
|
|
|
</div>
|
2021-06-21 03:47:17 +00:00
|
|
|
<div class="header-search">
|
|
|
|
<button class="button-menu"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 385 385">
|
|
|
|
<path d="M12 120.3h361a12 12 0 000-24H12a12 12 0 000 24zM373 180.5H12a12 12 0 000 24h361a12 12 0 000-24zM373 264.7H132.2a12 12 0 000 24H373a12 12 0 000-24z" />
|
|
|
|
</svg></button>
|
2021-06-21 05:12:13 +00:00
|
|
|
<!-- <input type="search" placeholder="Search Documentation..." /> -->
|
2021-06-21 03:47:17 +00:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="main">
|
|
|
|
<div class="sidebar">
|
2021-06-21 07:11:50 +00:00
|
|
|
<ul id="allpass_lib">
|
2021-06-21 07:40:38 +00:00
|
|
|
<li><label>a = </label><input type="text" id="NewAllPassValue"></li><button class="form-control" onclick="addNew()" class="btn btn-primary">Add</button>
|
2021-06-21 07:11:50 +00:00
|
|
|
<li><a href="#" onclick="showZplaneForAllPass('2 + 2i')" ondblclick="addNewAllPass('2 + 2i')"><i class="lni lni-text-format"></i><span>a = 2 + 2j</span></a>
|
|
|
|
<input type="checkbox" onclick="addOrRemove(this, '2 + 2i')"></li>
|
|
|
|
<li><a href="#" onclick="showZplaneForAllPass('2 - 2i')" ondblclick="addNewAllPass('2 - 2i')"><i class="lni lni-text-format" ></i><span>a = 2 - 2j</span></a>
|
|
|
|
<input type="checkbox" onclick="addOrRemove(this, '2 - 2i')"></li>
|
|
|
|
<li><a href="#" onclick="showZplaneForAllPass('1 + 2i')" ondblclick="addNewAllPass('1 + 2i')"><i class="lni lni-text-format" ></i><span>a = 1 + 2j</span></a>
|
|
|
|
<input type="checkbox" onclick="addOrRemove(this, '1 + 2i')"></li>
|
|
|
|
<li><a href="#" onclick="showZplaneForAllPass('2 + 1i')" ondblclick="addNewAllPass('2 + 1i')"><i class="lni lni-text-format" ></i><span>a = 2 + 1j</span></a>
|
|
|
|
<input type="checkbox" onclick="addOrRemove(this, '2 + 1i')"></li>
|
2021-06-21 03:47:17 +00:00
|
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
<div class="page-content">
|
|
|
|
<canvas id="zplane_polezero2" width=300 height=300></canvas>
|
|
|
|
<div id="zeros"></div>
|
|
|
|
<div id="poles"></div>
|
|
|
|
<button onclick="addNewPole()" class="btn btn-primary">New Pole</button>
|
|
|
|
<button onclick="addNewZero()" class="btn btn-primary">New Zero</button>
|
|
|
|
<button onclick="clearZeros()" class="btn btn-primary">clear zeros</button>
|
|
|
|
<button onclick="clearPoles()" class="btn btn-primary">clear poles</button>
|
|
|
|
<button onclick="clearAllPoints()" class="btn btn-primary">clear All</button><br>
|
|
|
|
<input type="checkbox" id="conjugate" onclick="setZplane(poles, zeros)">
|
|
|
|
<label> add Conjugates</label>
|
|
|
|
<input type="checkbox" id="allPassEffect" onclick="setZplane(poles, zeros)">
|
|
|
|
<label> with all Pass filters</label>
|
|
|
|
</div>
|
2021-06-21 05:12:13 +00:00
|
|
|
<div id="design_responses">
|
|
|
|
<div id="mag_response" style="width:500px;height:200px;"></div>
|
|
|
|
<div id="phase_response" style="width:500px;height:200px;"></div>
|
|
|
|
</div>
|
|
|
|
</div>
|
2021-06-21 03:47:17 +00:00
|
|
|
</div>
|
2021-06-21 05:12:13 +00:00
|
|
|
<div id="allpass">
|
|
|
|
<div>
|
|
|
|
<canvas id="allpass_zplane_polezero2" width=300 height=300></canvas>
|
|
|
|
</div>
|
|
|
|
<div>
|
|
|
|
<div id="allpass_phase_response" style="width:600px;height:300px;"></div>
|
|
|
|
</div>
|
2021-06-21 07:11:50 +00:00
|
|
|
<!-- <div>
|
2021-06-21 05:12:13 +00:00
|
|
|
<label>a = </label><input type="text" id="NewAllPassValue">
|
2021-06-21 07:11:50 +00:00
|
|
|
</div> -->
|
2021-06-21 05:12:13 +00:00
|
|
|
</div>
|
2021-06-17 21:07:42 +00:00
|
|
|
|
2021-06-21 03:47:17 +00:00
|
|
|
<script src="layout.js" type="text/javascript"></script>
|
2021-06-07 16:21:05 +00:00
|
|
|
<script>
|
|
|
|
|
2021-06-17 21:07:42 +00:00
|
|
|
// variables used to get mouse position on the canvas
|
|
|
|
var $canvas = $("#zplane_polezero2");
|
|
|
|
var canvasOffset = $canvas.offset();
|
|
|
|
var offsetX = canvasOffset.left;
|
|
|
|
var offsetY = canvasOffset.top;
|
|
|
|
var scrollX = $canvas.scrollLeft();
|
|
|
|
var scrollY = $canvas.scrollTop();
|
2021-06-07 16:21:05 +00:00
|
|
|
|
2021-06-17 22:18:40 +00:00
|
|
|
const conjugateTag = document.getElementById('conjugate');
|
2021-06-21 07:11:50 +00:00
|
|
|
const allPassEffect = document.getElementById('allPassEffect');
|
2021-06-17 21:07:42 +00:00
|
|
|
|
|
|
|
// variables to save last mouse position
|
|
|
|
// used to see how far the user dragged the mouse
|
|
|
|
// and then move the text by that distance
|
|
|
|
var startX;
|
|
|
|
var startY;
|
|
|
|
|
|
|
|
var zeros = new Array;
|
|
|
|
var poles = new Array;
|
2021-06-21 03:47:17 +00:00
|
|
|
var allPass = new Array;
|
2021-06-17 21:07:42 +00:00
|
|
|
var zerosNum = 0;
|
|
|
|
var polesNum = 0;
|
2021-06-21 03:47:17 +00:00
|
|
|
var allPassNum = 0;
|
2021-06-17 21:07:42 +00:00
|
|
|
|
|
|
|
function addNewPole() {
|
|
|
|
// console.log("I'm here!");
|
|
|
|
points = document.getElementById("poles");
|
|
|
|
var div = document.createElement("div");
|
|
|
|
div.id = 'pole' + polesNum + '_polezero2';
|
|
|
|
points.appendChild(div);
|
|
|
|
poles.push([0, 0]);
|
|
|
|
polesNum = polesNum + 1;
|
|
|
|
setZplane(poles, zeros);
|
2021-06-07 16:21:05 +00:00
|
|
|
}
|
|
|
|
|
2021-06-17 21:07:42 +00:00
|
|
|
function addNewZero() {
|
|
|
|
points = document.getElementById("zeros");
|
|
|
|
var div = document.createElement('div');
|
|
|
|
div.id = 'zero' + zerosNum + '_polezero2';
|
|
|
|
points.appendChild(div);
|
|
|
|
zeros.push([0, 0]);
|
|
|
|
zerosNum = zerosNum + 1;
|
|
|
|
setZplane(poles, zeros);
|
2021-06-07 16:21:05 +00:00
|
|
|
}
|
|
|
|
|
2021-06-21 07:40:38 +00:00
|
|
|
// // Get the input field
|
|
|
|
// var allPassValue = document.getElementById("");
|
2021-06-21 07:11:50 +00:00
|
|
|
|
2021-06-21 07:40:38 +00:00
|
|
|
$("#NewAllPassValue").keydown(function(event) {
|
2021-06-21 07:11:50 +00:00
|
|
|
// Number 13 is the "Enter" key on the keyboard
|
|
|
|
if (event.keyCode === 13) {
|
|
|
|
// Cancel the default action, if needed
|
|
|
|
event.preventDefault();
|
|
|
|
// Trigger the button element with a click
|
|
|
|
let target = document.getElementById("allpass_lib");
|
|
|
|
let input = document.getElementById("NewAllPassValue").value;
|
|
|
|
target.innerHTML += "<li><a href=\"#\" onclick=\"showZplaneForAllPass('" + input + "')\" ondblclick=\"addNewAllPass('" + input + "')\"><i class=\"lni lni-text-format\" ></i><span>a = "+ input + "</span></a>\
|
|
|
|
<input type=\"checkbox\" onclick=\"addOrRemove(this, '" + input + "')\"></li>";
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2021-06-21 07:40:38 +00:00
|
|
|
function addNew() {
|
|
|
|
let target = document.getElementById("allpass_lib");
|
|
|
|
let input = document.getElementById("NewAllPassValue").value;
|
|
|
|
target.innerHTML += "<li><a href=\"#\" onclick=\"showZplaneForAllPass('" + input + "')\" ondblclick=\"addNewAllPass('" + input + "')\"><i class=\"lni lni-text-format\" ></i><span>a = "+ input + "</span></a>\
|
|
|
|
<input type=\"checkbox\" onclick=\"addOrRemove(this, '" + input + "')\"></li>";
|
|
|
|
}
|
|
|
|
// // Execute a function when the user releases a key on the keyboard
|
|
|
|
// allPassValue.addEventListener("keyup", function(event) {
|
|
|
|
// // Number 13 is the "Enter" key on the keyboard
|
|
|
|
// if (event.keyCode === 13) {
|
|
|
|
// // Cancel the default action, if needed
|
|
|
|
// event.preventDefault();
|
|
|
|
// // Trigger the button element with a click
|
|
|
|
// let target = document.getElementById("allpass_lib");
|
|
|
|
// let input = document.getElementById("NewAllPassValue").value;
|
|
|
|
// target.innerHTML += "<li><a href=\"#\" onclick=\"showZplaneForAllPass('" + input + "')\" ondblclick=\"addNewAllPass('" + input + "')\"><i class=\"lni lni-text-format\" ></i><span>a = "+ input + "</span></a>\
|
|
|
|
// <input type=\"checkbox\" onclick=\"addOrRemove(this, '" + input + "')\"></li>";
|
|
|
|
// }
|
|
|
|
// });
|
|
|
|
|
2021-06-21 03:47:17 +00:00
|
|
|
function addNewAllPass(a) {
|
|
|
|
allPass.push(math.complex(a));
|
2021-06-21 07:11:50 +00:00
|
|
|
allPassNum = allPassNum + 1;
|
|
|
|
setZplane(poles, zeros);
|
2021-06-21 03:47:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function removeAllPassFilter(a) {
|
|
|
|
allPass = allPass.filter(function(value, index, arr) {
|
|
|
|
return !math.equal(value, math.complex(a));
|
|
|
|
});
|
2021-06-21 07:11:50 +00:00
|
|
|
allPassNum = allPassNum - 1;
|
|
|
|
setZplane(poles, zeros);
|
|
|
|
}
|
|
|
|
|
|
|
|
function addOrRemove(cb, a) {
|
|
|
|
if(cb.checked) {
|
|
|
|
addNewAllPass(a);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
removeAllPassFilter(a);
|
|
|
|
}
|
2021-06-21 03:47:17 +00:00
|
|
|
}
|
|
|
|
|
2021-06-17 22:18:40 +00:00
|
|
|
function clearAllPoints() {
|
|
|
|
poles = [];
|
|
|
|
zeros = [];
|
|
|
|
polesNum = 0;
|
|
|
|
zerosNum = 0;
|
|
|
|
setZplane(poles, zeros);
|
|
|
|
}
|
|
|
|
function clearZeros() {
|
|
|
|
zeros = [];
|
|
|
|
zerosNum = 0;
|
|
|
|
setZplane(poles, zeros);
|
|
|
|
}
|
|
|
|
function clearPoles() {
|
|
|
|
poles = [];
|
|
|
|
polesNum = 0;
|
|
|
|
setZplane(poles, zeros);
|
|
|
|
}
|
2021-06-17 21:07:42 +00:00
|
|
|
|
2021-06-18 00:46:31 +00:00
|
|
|
// variables for mag and phase responses
|
|
|
|
var Z = new Array(100);
|
|
|
|
var freqAxis = new Array(100);
|
|
|
|
|
|
|
|
for(let i = 0; i < 100; i++){
|
2021-06-21 03:47:17 +00:00
|
|
|
Z[i] = math.complex(math.cos(math.PI * (i/100)), math.sin(math.PI * (i/100)));
|
2021-06-18 00:46:31 +00:00
|
|
|
freqAxis[i] = Math.PI * (i/100);
|
|
|
|
}
|
|
|
|
|
|
|
|
// this var will hold the index of the selected point in zplane
|
2021-06-17 21:07:42 +00:00
|
|
|
var selectedPoint = -1;
|
|
|
|
|
|
|
|
// test if x,y is inside the bounding box of texts[textIndex]
|
|
|
|
function pointHittest(x, y, textIndex) {
|
2021-06-17 22:18:40 +00:00
|
|
|
// console.log([x, y]);
|
|
|
|
// console.log("poles.length is " + poles.length);
|
2021-06-17 21:07:42 +00:00
|
|
|
if(textIndex >= polesNum){
|
2021-06-17 22:18:40 +00:00
|
|
|
// console.log("check some zero!");
|
2021-06-21 08:55:58 +00:00
|
|
|
return (x >= zeros[textIndex - polesNum][0] - 0.2 && x <= zeros[textIndex - polesNum][0] + 0.2 && y >= zeros[textIndex - polesNum][1] - 0.2 && y <= zeros[textIndex - polesNum][1] + 0.2);
|
2021-06-17 21:07:42 +00:00
|
|
|
}
|
|
|
|
if(textIndex < polesNum){
|
2021-06-17 22:18:40 +00:00
|
|
|
// console.log("check some pole!");
|
2021-06-17 21:07:42 +00:00
|
|
|
return (x >= poles[textIndex][0] - 0.05 && x <= poles[textIndex][0] + 0.05 && y >= poles[textIndex][1] - 0.05 && y <= poles[textIndex][1] + 0.05);
|
|
|
|
}
|
2021-06-07 16:21:05 +00:00
|
|
|
}
|
|
|
|
|
2021-06-17 21:07:42 +00:00
|
|
|
// handle mousedown events
|
|
|
|
// iterate through texts[] and see if the user
|
|
|
|
// mousedown'ed on one of them
|
|
|
|
// If yes, set the selectedText to the index of that text
|
|
|
|
function handleMouseDown(e) {
|
|
|
|
e.preventDefault();
|
|
|
|
startX = parseInt(e.clientX - offsetX);
|
|
|
|
startY = parseInt(e.clientY - offsetY);
|
2021-06-21 07:11:50 +00:00
|
|
|
// console.log("you selected point [" + startX + ", " + startY + "]");
|
|
|
|
// console.log("which is point [" + (startX+70)/100 + ", " + -(startY-150)/100 + "]");
|
2021-06-17 21:07:42 +00:00
|
|
|
|
2021-06-17 22:18:40 +00:00
|
|
|
// console.log("poles number is " + poles.length);
|
|
|
|
// console.log("zeros number is " + zeros.length);
|
2021-06-17 21:07:42 +00:00
|
|
|
totalLength = polesNum + zerosNum;
|
|
|
|
// Put your mousedown stuff here
|
|
|
|
for (var i = 0; i < totalLength; i++) {
|
2021-06-21 03:47:17 +00:00
|
|
|
if (pointHittest((startX+70)/100, -(startY-150)/100, i)) {
|
2021-06-17 21:07:42 +00:00
|
|
|
selectedPoint = i;
|
|
|
|
if(i >= polesNum){
|
2021-06-17 22:18:40 +00:00
|
|
|
// console.log("selected zero" + (i - polesNum));
|
2021-06-17 21:07:42 +00:00
|
|
|
}else if(i < polesNum){
|
2021-06-17 22:18:40 +00:00
|
|
|
// console.log("selected pole" + (i));
|
2021-06-17 21:07:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// handle mousemove events
|
|
|
|
// calc how far the mouse has been dragged since
|
|
|
|
// the last mousemove event and move the selected text
|
|
|
|
// by that distance
|
|
|
|
function handleMouseMove(e) {
|
|
|
|
if (selectedPoint < 0) {
|
|
|
|
return;
|
|
|
|
}
|
2021-06-17 22:18:40 +00:00
|
|
|
// console.log("Mouse is Moving!...");
|
2021-06-17 21:07:42 +00:00
|
|
|
e.preventDefault();
|
|
|
|
mouseX = parseInt(e.clientX - offsetX);
|
|
|
|
mouseY = parseInt(e.clientY - offsetY);
|
|
|
|
|
|
|
|
// Put your mousemove stuff here
|
|
|
|
var dx = (mouseX - startX)/100;
|
|
|
|
var dy = -(mouseY - startY)/100;
|
2021-06-17 22:18:40 +00:00
|
|
|
// console.log("MouseXY -> [" + mouseX + ", " + mouseY + "]");
|
|
|
|
// console.log("MouseXY -> [" + startX + ", " + startY + "]");
|
2021-06-17 21:07:42 +00:00
|
|
|
startX = mouseX;
|
|
|
|
startY = mouseY;
|
2021-06-17 22:18:40 +00:00
|
|
|
// console.log("moved to point [" + startX + ", " + startY + "]");
|
2021-06-21 03:47:17 +00:00
|
|
|
// console.log("which is point [" + (startX+70)/100 + ", " + -(startY-150)/100 + "]");
|
2021-06-17 22:18:40 +00:00
|
|
|
// console.log("moved by [" + dx + ", " + dy + "]");
|
2021-06-17 21:07:42 +00:00
|
|
|
|
|
|
|
if(selectedPoint >= poles.length){
|
|
|
|
zeros[selectedPoint - poles.length][0] += dx;
|
|
|
|
zeros[selectedPoint - poles.length][1] += dy;
|
|
|
|
}else if(selectedPoint < poles.length){
|
|
|
|
poles[selectedPoint][0] += dx;
|
|
|
|
poles[selectedPoint][1] += dy;
|
|
|
|
}
|
|
|
|
// addNewPole([dx, dy]);
|
|
|
|
setZplane(poles, zeros);
|
|
|
|
}
|
|
|
|
|
|
|
|
// done dragging
|
|
|
|
function handleMouseUp(e) {
|
|
|
|
e.preventDefault();
|
|
|
|
selectedPoint = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// also done dragging
|
|
|
|
function handleMouseOut(e) {
|
|
|
|
e.preventDefault();
|
|
|
|
selectedPoint = -1;
|
|
|
|
}
|
|
|
|
|
2021-06-17 22:18:40 +00:00
|
|
|
// clicked pole or zero -> delete it
|
|
|
|
function handleMouseClick(e) {
|
|
|
|
// e.preventDefault();
|
|
|
|
startX = parseInt(e.clientX - offsetX);
|
|
|
|
startY = parseInt(e.clientY - offsetY);
|
2021-06-21 03:47:17 +00:00
|
|
|
// console.log("you selected point [" + startX + ", " + startY + "]");
|
|
|
|
// console.log("which is point [" + (startX+70)/100 + ", " + -(startY-150)/100 + "]");
|
2021-06-17 22:18:40 +00:00
|
|
|
|
|
|
|
// console.log("poles number is " + poles.length);
|
|
|
|
// console.log("zeros number is " + zeros.length);
|
|
|
|
totalLength = polesNum + zerosNum;
|
|
|
|
// Put your mousedown stuff here
|
|
|
|
for (var i = 0; i < totalLength; i++) {
|
2021-06-21 03:47:17 +00:00
|
|
|
if (pointHittest((startX+70)/100, -(startY-150)/100, i)) {
|
2021-06-17 22:18:40 +00:00
|
|
|
if(i >= polesNum){
|
|
|
|
zeros.splice(i - polesNum, 1);
|
|
|
|
zerosNum = zerosNum -1;
|
|
|
|
// console.log("selected zero" + (i - polesNum));
|
|
|
|
}else if(i < polesNum){
|
|
|
|
poles.splice(i, 1);
|
|
|
|
polesNum = polesNum -1;
|
|
|
|
// console.log("selected pole" + (i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
setZplane(poles, zeros);
|
|
|
|
}
|
|
|
|
|
2021-06-17 21:07:42 +00:00
|
|
|
// listen for mouse events
|
|
|
|
$("#zplane_polezero2").mousedown(function (e) {
|
|
|
|
handleMouseDown(e);
|
|
|
|
});
|
|
|
|
$("#zplane_polezero2").mousemove(function (e) {
|
|
|
|
handleMouseMove(e);
|
|
|
|
});
|
|
|
|
$("#zplane_polezero2").mouseup(function (e) {
|
|
|
|
handleMouseUp(e);
|
|
|
|
});
|
|
|
|
$("#zplane_polezero2").mouseout(function (e) {
|
|
|
|
handleMouseOut(e);
|
|
|
|
});
|
2021-06-17 22:18:40 +00:00
|
|
|
$("#zplane_polezero2").dblclick(function (e) {
|
|
|
|
handleMouseClick(e);
|
|
|
|
});
|
2021-06-17 21:07:42 +00:00
|
|
|
|
|
|
|
function setZplane(poles, zeros) {
|
|
|
|
|
|
|
|
// console.log("drawing..");
|
|
|
|
// console.log("poles number is " + poles.length);
|
|
|
|
// console.log("zeros number is " + zeros.length);
|
|
|
|
|
|
|
|
var radius = 100; // radius of unit circle
|
|
|
|
var pSize = 4; // size of pole and zero graphic
|
|
|
|
var zSize = 4;
|
|
|
|
|
|
|
|
var c=document.getElementById("zplane_polezero2");
|
|
|
|
var ctx=c.getContext("2d");
|
|
|
|
|
|
|
|
ctx.clearRect(0, 0, c.width, c.height);
|
|
|
|
|
|
|
|
var pad = (c.width - 2 * radius) / 2; // padding on each side
|
|
|
|
|
|
|
|
// unit circle
|
|
|
|
ctx.beginPath();
|
|
|
|
ctx.strokeStyle="red";
|
|
|
|
ctx.arc(radius+pad,radius+pad,radius,0,2*Math.PI);
|
|
|
|
ctx.stroke();
|
|
|
|
|
|
|
|
// y axis
|
|
|
|
ctx.beginPath();
|
|
|
|
//ctx.lineWidth="1";
|
|
|
|
ctx.strokeStyle="lightgray";
|
|
|
|
ctx.moveTo(radius+pad,0);
|
|
|
|
ctx.lineTo(radius+pad,c.height);
|
|
|
|
ctx.font = "italic 8px sans-serif";
|
|
|
|
ctx.fillText("Im", radius+pad+2, pad-2);
|
|
|
|
|
|
|
|
// x axis
|
|
|
|
ctx.moveTo(0,radius+pad);
|
|
|
|
ctx.lineTo(c.width,radius+pad);
|
|
|
|
ctx.fillText("Re", radius+radius+pad+2, radius+pad-2);
|
|
|
|
ctx.stroke(); // Draw it
|
|
|
|
|
|
|
|
// poles
|
|
|
|
ctx.strokeStyle="blue";
|
|
|
|
var idx;
|
|
|
|
for (idx = 0; idx < poles.length; idx++) {
|
2021-06-17 22:18:40 +00:00
|
|
|
let x = radius + Math.round(radius * poles[idx][0]);
|
|
|
|
let y = radius - Math.round(radius * poles[idx][1]);
|
2021-06-17 21:07:42 +00:00
|
|
|
ctx.beginPath();
|
|
|
|
ctx.moveTo(x - pSize + pad, y - pSize + pad);
|
|
|
|
ctx.lineTo(x + pSize + pad, y + pSize + pad);
|
|
|
|
ctx.moveTo(x - pSize + pad, y + pSize + pad);
|
|
|
|
ctx.lineTo(x + pSize + pad, y - pSize + pad);
|
|
|
|
ctx.stroke();
|
2021-06-17 22:18:40 +00:00
|
|
|
if(conjugateTag.checked){
|
|
|
|
let x = radius + Math.round(radius * poles[idx][0]);
|
|
|
|
let y = radius + Math.round(radius * poles[idx][1]);
|
|
|
|
ctx.beginPath();
|
|
|
|
ctx.moveTo(x - pSize + pad, y - pSize + pad);
|
|
|
|
ctx.lineTo(x + pSize + pad, y + pSize + pad);
|
|
|
|
ctx.moveTo(x - pSize + pad, y + pSize + pad);
|
|
|
|
ctx.lineTo(x + pSize + pad, y - pSize + pad);
|
|
|
|
ctx.stroke();
|
|
|
|
}
|
2021-06-17 21:07:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// zeros
|
|
|
|
for (idx = 0; idx < zeros.length; idx++) {
|
2021-06-17 22:18:40 +00:00
|
|
|
let x = radius + Math.round(radius * zeros[idx][0]);
|
|
|
|
let y = radius - Math.round(radius * zeros[idx][1]);
|
2021-06-17 21:07:42 +00:00
|
|
|
ctx.beginPath();
|
|
|
|
ctx.arc(x + pad, y + pad, zSize, 0, 2*Math.PI);
|
|
|
|
ctx.stroke();
|
2021-06-17 22:18:40 +00:00
|
|
|
if(conjugateTag.checked){
|
|
|
|
let x = radius + Math.round(radius * zeros[idx][0]);
|
|
|
|
let y = radius + Math.round(radius * zeros[idx][1]);
|
|
|
|
ctx.beginPath();
|
|
|
|
ctx.arc(x + pad, y + pad, zSize, 0, 2*Math.PI);
|
|
|
|
ctx.stroke();
|
|
|
|
}
|
2021-06-17 21:07:42 +00:00
|
|
|
}
|
2021-06-21 03:47:17 +00:00
|
|
|
|
|
|
|
if(allPassEffect.checked){
|
|
|
|
// allpass poles
|
|
|
|
for (idx = 0; idx < allPass.length; idx++) {
|
|
|
|
let x = radius + Math.round(radius * allPass[idx].re);
|
|
|
|
let y = radius - Math.round(radius * allPass[idx].im);
|
|
|
|
ctx.beginPath();
|
|
|
|
ctx.moveTo(x - pSize + pad, y - pSize + pad);
|
|
|
|
ctx.lineTo(x + pSize + pad, y + pSize + pad);
|
|
|
|
ctx.moveTo(x - pSize + pad, y + pSize + pad);
|
|
|
|
ctx.lineTo(x + pSize + pad, y - pSize + pad);
|
|
|
|
ctx.stroke();
|
|
|
|
}
|
|
|
|
|
|
|
|
// allpass zeros
|
|
|
|
for (idx = 0; idx < allPass.length; idx++) {
|
|
|
|
let tempVar = math.divide(1, math.conj(allPass[idx]));
|
|
|
|
let x = radius + Math.round(radius * tempVar.re);
|
|
|
|
let y = radius - Math.round(radius * tempVar.im);
|
|
|
|
ctx.beginPath();
|
|
|
|
ctx.arc(x + pad, y + pad, zSize, 0, 2*Math.PI);
|
|
|
|
ctx.stroke();
|
|
|
|
}
|
|
|
|
}
|
2021-06-18 00:46:31 +00:00
|
|
|
drawResponses();
|
2021-06-17 21:07:42 +00:00
|
|
|
}
|
|
|
|
|
2021-06-21 03:47:17 +00:00
|
|
|
function showZplaneForAllPass(a) {
|
2021-06-21 07:11:50 +00:00
|
|
|
if(a != '') {
|
|
|
|
let zero = math.divide(math.complex(1,0), math.conj(math.complex(a)));
|
|
|
|
let pole = math.complex(a);
|
|
|
|
var radius = 50; // radius of unit circle
|
|
|
|
var pSize = 4; // size of pole and zero graphic
|
|
|
|
var zSize = 4;
|
|
|
|
|
|
|
|
var c=document.getElementById("allpass_zplane_polezero2");
|
|
|
|
var ctx=c.getContext("2d");
|
|
|
|
|
|
|
|
ctx.clearRect(0, 0, c.width, c.height);
|
|
|
|
|
|
|
|
var pad = (c.width - 2 * radius) / 2; // padding on each side
|
|
|
|
|
|
|
|
// unit circle
|
|
|
|
ctx.beginPath();
|
|
|
|
ctx.strokeStyle="red";
|
|
|
|
ctx.arc(radius+pad,radius+pad,radius,0,2*Math.PI);
|
|
|
|
ctx.stroke();
|
|
|
|
|
|
|
|
// y axis
|
|
|
|
ctx.beginPath();
|
|
|
|
//ctx.lineWidth="1";
|
|
|
|
ctx.strokeStyle="lightgray";
|
|
|
|
ctx.moveTo(radius+pad,0);
|
|
|
|
ctx.lineTo(radius+pad,c.height);
|
|
|
|
ctx.font = "italic 8px sans-serif";
|
|
|
|
ctx.fillText("Im", radius+pad+2, pad-2);
|
|
|
|
|
|
|
|
// x axis
|
|
|
|
ctx.moveTo(0,radius+pad);
|
|
|
|
ctx.lineTo(c.width,radius+pad);
|
|
|
|
ctx.fillText("Re", radius+radius+pad+2, radius+pad-2);
|
|
|
|
ctx.stroke(); // Draw it
|
|
|
|
|
|
|
|
// pole
|
|
|
|
ctx.strokeStyle="blue";
|
|
|
|
let x = radius + Math.round(radius * pole.re);
|
|
|
|
let y = radius - Math.round(radius * pole.im);
|
|
|
|
ctx.beginPath();
|
|
|
|
ctx.moveTo(x - pSize + pad, y - pSize + pad);
|
|
|
|
ctx.lineTo(x + pSize + pad, y + pSize + pad);
|
|
|
|
ctx.moveTo(x - pSize + pad, y + pSize + pad);
|
|
|
|
ctx.lineTo(x + pSize + pad, y - pSize + pad);
|
|
|
|
ctx.stroke();
|
|
|
|
|
|
|
|
// zero
|
|
|
|
x = radius + Math.round(radius * zero.re);
|
|
|
|
y = radius - Math.round(radius * zero.im);
|
|
|
|
ctx.beginPath();
|
|
|
|
ctx.arc(x + pad, y + pad, zSize, 0, 2*Math.PI);
|
|
|
|
ctx.stroke();
|
|
|
|
|
|
|
|
drawResponseOfAllPass(a);
|
|
|
|
}
|
|
|
|
|
2021-06-21 03:47:17 +00:00
|
|
|
}
|
|
|
|
|
2021-06-21 05:12:13 +00:00
|
|
|
function drawResponseOfAllPass(a) {
|
|
|
|
let zero = math.divide(1, math.conj(math.complex(a)));
|
|
|
|
let pole = math.complex(a);
|
2021-06-21 03:47:17 +00:00
|
|
|
let magResponse = [];
|
|
|
|
let phaseResponse = [];
|
|
|
|
for(let i = 0; i < 100; i++){
|
|
|
|
let magPoint = math.complex(1,0);
|
|
|
|
let phasePoint = math.complex(1,0);
|
|
|
|
let temp = math.subtract(Z[i], math.complex(zero.re, zero.im));
|
|
|
|
magPoint *= temp.abs();
|
|
|
|
phasePoint *= temp.arg();
|
|
|
|
temp = math.subtract(Z[i], math.complex(pole.re, pole.im));
|
|
|
|
magPoint /= temp.abs();
|
|
|
|
phasePoint /= temp.arg();
|
|
|
|
|
|
|
|
magResponse.push(magPoint);
|
|
|
|
phaseResponse.push(phasePoint);
|
|
|
|
}
|
|
|
|
|
|
|
|
// normalize
|
|
|
|
var maxMag = Math.max(...magResponse);
|
|
|
|
var maxPhase = Math.max(...phaseResponse);
|
|
|
|
for(let i = 0; i < magResponse; i++) {
|
|
|
|
magResponse[i] /= maxMag;
|
|
|
|
phaseResponse[i] /= maxPhase;
|
2021-06-17 21:07:42 +00:00
|
|
|
}
|
|
|
|
|
2021-06-21 03:47:17 +00:00
|
|
|
let magData = [];
|
|
|
|
let phaseData = [];
|
|
|
|
|
|
|
|
for(let i = 0; i < 100; i++){
|
|
|
|
magData.push([freqAxis[i], magResponse[i]]);
|
|
|
|
// console.log(magResponse[i]);
|
|
|
|
phaseData.push([freqAxis[i], phaseResponse[i]]);
|
|
|
|
// console.log(phaseResponse[i]);
|
2021-06-17 21:07:42 +00:00
|
|
|
}
|
2021-06-21 03:47:17 +00:00
|
|
|
|
|
|
|
// plot phase_response
|
|
|
|
var container = document.getElementById('allpass_phase_response');
|
2021-06-21 07:11:50 +00:00
|
|
|
graph = Flotr.draw(container, [ phaseData ], { yaxis: { max : 5, min : -5 } });
|
2021-06-17 21:07:42 +00:00
|
|
|
}
|
|
|
|
|
2021-06-18 00:46:31 +00:00
|
|
|
function drawResponses() {
|
2021-06-21 03:47:17 +00:00
|
|
|
let magResponse = [];
|
|
|
|
let phaseResponse = [];
|
2021-06-18 00:46:31 +00:00
|
|
|
for(let i = 0; i < 100; i++){
|
2021-06-21 03:47:17 +00:00
|
|
|
let magPoint = math.complex(1,0);
|
|
|
|
let phasePoint = math.complex(1,0);
|
2021-06-18 00:46:31 +00:00
|
|
|
for(let j = 0; j < zeros.length; j++){
|
2021-06-21 03:47:17 +00:00
|
|
|
let temp = math.subtract(Z[i], math.complex(zeros[j][0], zeros[j][1]));
|
|
|
|
magPoint *= temp.abs();
|
|
|
|
phasePoint *= temp.arg();
|
2021-06-18 00:46:31 +00:00
|
|
|
}
|
|
|
|
for(let j = 0; j < poles.length; j++){
|
2021-06-21 03:47:17 +00:00
|
|
|
let temp = math.subtract(Z[i], math.complex(poles[j][0], poles[j][1]));
|
|
|
|
magPoint /= temp.abs();
|
|
|
|
phasePoint /= temp.arg();
|
|
|
|
}
|
|
|
|
if(allPassEffect.checked){
|
|
|
|
for(let j = 0; j < allPass.length; j++)
|
|
|
|
{
|
|
|
|
let temp = math.subtract(Z[i], math.divide(1, math.conj(allPass[j])));
|
|
|
|
magPoint *= temp.abs();
|
|
|
|
phasePoint *= temp.arg();
|
|
|
|
temp = math.subtract(Z[i], allPass[j]);
|
|
|
|
magPoint /= temp.abs();
|
|
|
|
phasePoint /= temp.arg();
|
|
|
|
}
|
2021-06-18 00:46:31 +00:00
|
|
|
}
|
|
|
|
magResponse.push(magPoint);
|
|
|
|
phaseResponse.push(phasePoint);
|
|
|
|
}
|
|
|
|
|
|
|
|
// normalize
|
|
|
|
var maxMag = Math.max(...magResponse);
|
|
|
|
var maxPhase = Math.max(...phaseResponse);
|
|
|
|
for(let i = 0; i < magResponse; i++) {
|
|
|
|
magResponse[i] /= maxMag;
|
|
|
|
phaseResponse[i] /= maxPhase;
|
|
|
|
}
|
|
|
|
|
|
|
|
let magData = [];
|
|
|
|
let phaseData = [];
|
|
|
|
|
|
|
|
for(let i = 0; i < 100; i++){
|
|
|
|
magData.push([freqAxis[i], magResponse[i]]);
|
2021-06-21 03:47:17 +00:00
|
|
|
// console.log(magResponse[i]);
|
2021-06-18 00:46:31 +00:00
|
|
|
phaseData.push([freqAxis[i], phaseResponse[i]]);
|
2021-06-21 03:47:17 +00:00
|
|
|
// console.log(phaseResponse[i]);
|
2021-06-18 00:46:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// plot mag_response
|
|
|
|
var container = document.getElementById('mag_response');
|
2021-06-21 03:47:17 +00:00
|
|
|
graph = Flotr.draw(container, [ magData ], { yaxis: { max : 10, min : 0 } });
|
2021-06-18 00:46:31 +00:00
|
|
|
|
|
|
|
// plot phase_response
|
|
|
|
var container = document.getElementById('phase_response');
|
2021-06-21 07:11:50 +00:00
|
|
|
graph = Flotr.draw(container, [ phaseData ], { yaxis: { max : 4, min : -4 } });
|
2021-06-18 00:46:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-06-17 21:07:42 +00:00
|
|
|
setZplane(poles, zeros);
|
|
|
|
|
|
|
|
|
2021-06-07 16:21:05 +00:00
|
|
|
</script>
|