Added Larynx v1.0

This commit is contained in:
Samuel Ortion 2021-04-07 12:35:25 +02:00
parent 6dbee3d585
commit ec4e1b20cb
14 changed files with 1090 additions and 160 deletions

View File

@ -4,7 +4,27 @@ ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
session_start();
$root = realpath($_SERVER["DOCUMENT_ROOT"]);
require "$root/database/credentials.php";
// Connect the database
try {
$db = new PDO("mysql:host=$host;dbname=$database;charset=utf8",
$user,
$password,
array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
));
} catch (Exception $e) {
die("Error : ".$e->getMessage());
}
if (isset($_GET['record'])) {
$req = $db->prepare('SELECT id, recordist_name, file_name, license, species, sound_type, date, time FROM `records` WHERE id=:id');
$req->execute(array(
"id"=>$_GET['record']
));
} else {
$req = $db->prepare('SELECT id, recordist_name, file_name, license, species, sound_type, date, time FROM `records` ORDER BY date DESC, time DESC LIMIT 1');
$req->execute();
}
$data = $req->fetch();
?>
<!DOCTYPE html>

0
public/database/TAXREF14.0_CHIRO.csv Executable file → Normal file
View File

View File

@ -58,8 +58,10 @@ include("$root/analytics/matomo.php");
<?php
}
?>
<div id="waveform"></div>
<div id="wave-spectrogram"></div>
<!-- <div id="waveform"></div>
<div id="wave-spectrogram"></div> -->
<canvas class="spectrogram"></canvas>
<canvas class="waveform"></canvas>
<br>
<audio src="<?="/storage/records/".$data['file_name']?>" id="audio"></audio>

85
public/larynx/index.php Normal file
View File

@ -0,0 +1,85 @@
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
session_start();
$root = realpath($_SERVER["DOCUMENT_ROOT"]);
$version = "1.0";
require "$root/database/credentials.php";
// Connect the database
try {
$db = new PDO("mysql:host=$host;dbname=$database;charset=utf8",
$user,
$password,
array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
));
} catch (Exception $e) {
die("Error : ".$e->getMessage());
}
if (isset($_GET['record'])) {
$req = $db->prepare('SELECT id, recordist_name, file_name, license, species, sound_type, date, time FROM `records` WHERE id=:id');
$req->execute(array(
"id"=>$_GET['record']
));
} else {
$req = $db->prepare('SELECT id, recordist_name, file_name, license, species, sound_type, date, time FROM `records` ORDER BY date DESC, time DESC LIMIT 1');
$req->execute();
}
$data = $req->fetch();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Larynx | Chiro - Canto</title>
<link rel="stylesheet" type="text/css" href="/styles/style.css">
</head>
<?php include("$root/analytics/matomo.php");?>
<?php
include("$root/analytics/matomo.php");
?>
<body>
<?php include("$root/menu.php");?>
<?php include("$root/header.php");?>
<section>
<h2>Larynx</h2>
<p>A web tool for bat sound analysis</p>
</section>
<div id="larynx">
<h2>Larynx v<?=$version?></h2>
<audio src="<?="/storage/records/".$data['file_name']?>" id="audio"></audio>
<div class="spectrogram">
<div id="waveform"></div>
<div id="wave-spectrogram">
<!-- <canvas id="spectrogram"></canvas> -->
</div>
<div class="container row">
<div class="measures">
T:
<span id="cursor-time"></span>
ms F:
<span id="cursor-frequency"></span>
kHz
</div>
<div class="controls">
<input type="button" name="play" value="play" id="play">
<input type="button" value="pause" id="pause">
<input type="button" value="restart" id="restart">
</div>
</div>
<p class="license"><?=$data['license']?> <?=$data['recordist_name']?></p>
</div>
</div>
<?php include("$root/footer.php");?>
</body>
<script src="/scripts/script.js"></script>
<script src="https://unpkg.com/wavesurfer.js"></script>
<script src="https://unpkg.com/wavesurfer.js/dist/plugin/wavesurfer.spectrogram.min.js" type="text/javascript"></script>
<!-- <script src="scripts/spectro.js"></script> -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.16/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.16/addons/p5.sound.js"></script>
<script src="scripts/spectro.js"></script>
</html>

View File

@ -0,0 +1,9 @@
const colormap = require('colormap');
const colors = colormap({
colormap: 'hot',
nshades: 256,
format: 'float'
});
// const fs = require('fs');
// fs.writeFile('hot-colormap.json', JSON.stringify(colors));
console.log(JSON.stringify(colors));

View File

@ -0,0 +1,258 @@
[
[0, 0, 0, 1],
[0.011764705882352941, 0, 0, 1],
[0.023529411764705882, 0, 0, 1],
[0.03529411764705882, 0, 0, 1],
[0.047058823529411764, 0, 0, 1],
[0.058823529411764705, 0, 0, 1],
[0.07058823529411765, 0, 0, 1],
[0.08235294117647059, 0, 0, 1],
[0.09411764705882353, 0, 0, 1],
[0.10588235294117647, 0, 0, 1],
[0.11764705882352941, 0, 0, 1],
[0.12941176470588237, 0, 0, 1],
[0.1411764705882353, 0, 0, 1],
[0.15294117647058825, 0, 0, 1],
[0.16470588235294117, 0, 0, 1],
[0.17647058823529413, 0, 0, 1],
[0.18823529411764706, 0, 0, 1],
[0.2, 0, 0, 1],
[0.21176470588235294, 0, 0, 1],
[0.2235294117647059, 0, 0, 1],
[0.23529411764705882, 0, 0, 1],
[0.24705882352941178, 0, 0, 1],
[0.25882352941176473, 0, 0, 1],
[0.27058823529411763, 0, 0, 1],
[0.2823529411764706, 0, 0, 1],
[0.29411764705882354, 0, 0, 1],
[0.3058823529411765, 0, 0, 1],
[0.3176470588235294, 0, 0, 1],
[0.32941176470588235, 0, 0, 1],
[0.3411764705882353, 0, 0, 1],
[0.35294117647058826, 0, 0, 1],
[0.36470588235294116, 0, 0, 1],
[0.3764705882352941, 0, 0, 1],
[0.38823529411764707, 0, 0, 1],
[0.4, 0, 0, 1],
[0.4117647058823529, 0, 0, 1],
[0.4235294117647059, 0, 0, 1],
[0.43529411764705883, 0, 0, 1],
[0.4470588235294118, 0, 0, 1],
[0.4549019607843137, 0, 0, 1],
[0.4666666666666667, 0, 0, 1],
[0.47843137254901963, 0, 0, 1],
[0.49019607843137253, 0, 0, 1],
[0.5019607843137255, 0, 0, 1],
[0.5137254901960784, 0, 0, 1],
[0.5254901960784314, 0, 0, 1],
[0.5372549019607843, 0, 0, 1],
[0.5490196078431373, 0, 0, 1],
[0.5607843137254902, 0, 0, 1],
[0.5725490196078431, 0, 0, 1],
[0.5843137254901961, 0, 0, 1],
[0.596078431372549, 0, 0, 1],
[0.6078431372549019, 0, 0, 1],
[0.6196078431372549, 0, 0, 1],
[0.6313725490196078, 0, 0, 1],
[0.6431372549019608, 0, 0, 1],
[0.6549019607843137, 0, 0, 1],
[0.6666666666666666, 0, 0, 1],
[0.6784313725490196, 0, 0, 1],
[0.6901960784313725, 0, 0, 1],
[0.7019607843137254, 0, 0, 1],
[0.7137254901960784, 0, 0, 1],
[0.7254901960784313, 0, 0, 1],
[0.7372549019607844, 0, 0, 1],
[0.7490196078431373, 0, 0, 1],
[0.7607843137254902, 0, 0, 1],
[0.7725490196078432, 0, 0, 1],
[0.7843137254901961, 0, 0, 1],
[0.796078431372549, 0, 0, 1],
[0.807843137254902, 0, 0, 1],
[0.8196078431372549, 0, 0, 1],
[0.8313725490196079, 0, 0, 1],
[0.8431372549019608, 0, 0, 1],
[0.8549019607843137, 0, 0, 1],
[0.8666666666666667, 0, 0, 1],
[0.8784313725490196, 0, 0, 1],
[0.8901960784313725, 0, 0, 1],
[0.9019607843137255, 0, 0, 1],
[0.9019607843137255, 0.011764705882352941, 0, 1],
[0.9058823529411765, 0.023529411764705882, 0, 1],
[0.9058823529411765, 0.03137254901960784, 0, 1],
[0.9058823529411765, 0.043137254901960784, 0, 1],
[0.9098039215686274, 0.054901960784313725, 0, 1],
[0.9098039215686274, 0.06666666666666667, 0, 1],
[0.9098039215686274, 0.07450980392156863, 0, 1],
[0.9137254901960784, 0.08627450980392157, 0, 1],
[0.9137254901960784, 0.09803921568627451, 0, 1],
[0.9137254901960784, 0.10980392156862745, 0, 1],
[0.9176470588235294, 0.11764705882352941, 0, 1],
[0.9176470588235294, 0.12941176470588237, 0, 1],
[0.9176470588235294, 0.1411764705882353, 0, 1],
[0.9215686274509803, 0.15294117647058825, 0, 1],
[0.9215686274509803, 0.1607843137254902, 0, 1],
[0.9215686274509803, 0.17254901960784313, 0, 1],
[0.9254901960784314, 0.1843137254901961, 0, 1],
[0.9254901960784314, 0.19607843137254902, 0, 1],
[0.9254901960784314, 0.20784313725490197, 0, 1],
[0.9294117647058824, 0.21568627450980393, 0, 1],
[0.9294117647058824, 0.22745098039215686, 0, 1],
[0.9294117647058824, 0.23921568627450981, 0, 1],
[0.9333333333333333, 0.25098039215686274, 0, 1],
[0.9333333333333333, 0.25882352941176473, 0, 1],
[0.9333333333333333, 0.27058823529411763, 0, 1],
[0.9372549019607843, 0.2823529411764706, 0, 1],
[0.9372549019607843, 0.29411764705882354, 0, 1],
[0.9372549019607843, 0.30196078431372547, 0, 1],
[0.9411764705882353, 0.3137254901960784, 0, 1],
[0.9411764705882353, 0.3254901960784314, 0, 1],
[0.9411764705882353, 0.33725490196078434, 0, 1],
[0.9450980392156862, 0.34509803921568627, 0, 1],
[0.9450980392156862, 0.3568627450980392, 0, 1],
[0.9450980392156862, 0.3686274509803922, 0, 1],
[0.9490196078431372, 0.3803921568627451, 0, 1],
[0.9490196078431372, 0.38823529411764707, 0, 1],
[0.9490196078431372, 0.4, 0, 1],
[0.9529411764705882, 0.4117647058823529, 0, 1],
[0.9529411764705882, 0.4235294117647059, 0, 1],
[0.9529411764705882, 0.43529411764705883, 0, 1],
[0.9529411764705882, 0.44313725490196076, 0, 1],
[0.9568627450980393, 0.4549019607843137, 0, 1],
[0.9568627450980393, 0.4666666666666667, 0, 1],
[0.9568627450980393, 0.47843137254901963, 0, 1],
[0.9607843137254902, 0.48627450980392156, 0, 1],
[0.9607843137254902, 0.4980392156862745, 0, 1],
[0.9607843137254902, 0.5098039215686274, 0, 1],
[0.9647058823529412, 0.5215686274509804, 0, 1],
[0.9647058823529412, 0.5294117647058824, 0, 1],
[0.9647058823529412, 0.5411764705882353, 0, 1],
[0.9686274509803922, 0.5529411764705883, 0, 1],
[0.9686274509803922, 0.5647058823529412, 0, 1],
[0.9686274509803922, 0.5725490196078431, 0, 1],
[0.9725490196078431, 0.5843137254901961, 0, 1],
[0.9725490196078431, 0.596078431372549, 0, 1],
[0.9725490196078431, 0.6078431372549019, 0, 1],
[0.9764705882352941, 0.6196078431372549, 0, 1],
[0.9764705882352941, 0.6274509803921569, 0, 1],
[0.9764705882352941, 0.6392156862745098, 0, 1],
[0.9803921568627451, 0.6509803921568628, 0, 1],
[0.9803921568627451, 0.6627450980392157, 0, 1],
[0.9803921568627451, 0.6705882352941176, 0, 1],
[0.984313725490196, 0.6823529411764706, 0, 1],
[0.984313725490196, 0.6941176470588235, 0, 1],
[0.984313725490196, 0.7058823529411765, 0, 1],
[0.9882352941176471, 0.7137254901960784, 0, 1],
[0.9882352941176471, 0.7254901960784313, 0, 1],
[0.9882352941176471, 0.7372549019607844, 0, 1],
[0.9921568627450981, 0.7490196078431373, 0, 1],
[0.9921568627450981, 0.7568627450980392, 0, 1],
[0.9921568627450981, 0.7686274509803922, 0, 1],
[0.996078431372549, 0.7803921568627451, 0, 1],
[0.996078431372549, 0.792156862745098, 0, 1],
[0.996078431372549, 0.8, 0, 1],
[1, 0.8117647058823529, 0, 1],
[1, 0.8235294117647058, 0, 1],
[1, 0.8235294117647058, 0.011764705882352941, 1],
[1, 0.8274509803921568, 0.0196078431372549, 1],
[1, 0.8274509803921568, 0.03137254901960784, 1],
[1, 0.8313725490196079, 0.0392156862745098, 1],
[1, 0.8313725490196079, 0.050980392156862744, 1],
[1, 0.8352941176470589, 0.058823529411764705, 1],
[1, 0.8352941176470589, 0.07058823529411765, 1],
[1, 0.8392156862745098, 0.0784313725490196, 1],
[1, 0.8392156862745098, 0.09019607843137255, 1],
[1, 0.8392156862745098, 0.09803921568627451, 1],
[1, 0.8431372549019608, 0.10980392156862745, 1],
[1, 0.8431372549019608, 0.11764705882352941, 1],
[1, 0.8470588235294118, 0.12941176470588237, 1],
[1, 0.8470588235294118, 0.13725490196078433, 1],
[1, 0.8509803921568627, 0.14901960784313725, 1],
[1, 0.8509803921568627, 0.1568627450980392, 1],
[1, 0.8549019607843137, 0.16862745098039217, 1],
[1, 0.8549019607843137, 0.17647058823529413, 1],
[1, 0.8549019607843137, 0.18823529411764706, 1],
[1, 0.8588235294117647, 0.19607843137254902, 1],
[1, 0.8588235294117647, 0.20784313725490197, 1],
[1, 0.8627450980392157, 0.21568627450980393, 1],
[1, 0.8627450980392157, 0.22745098039215686, 1],
[1, 0.8666666666666667, 0.23529411764705882, 1],
[1, 0.8666666666666667, 0.24705882352941178, 1],
[1, 0.8666666666666667, 0.2549019607843137, 1],
[1, 0.8705882352941177, 0.26666666666666666, 1],
[1, 0.8705882352941177, 0.27450980392156865, 1],
[1, 0.8745098039215686, 0.28627450980392155, 1],
[1, 0.8745098039215686, 0.29411764705882354, 1],
[1, 0.8784313725490196, 0.3058823529411765, 1],
[1, 0.8784313725490196, 0.3137254901960784, 1],
[1, 0.8823529411764706, 0.3254901960784314, 1],
[1, 0.8823529411764706, 0.3333333333333333, 1],
[1, 0.8823529411764706, 0.34509803921568627, 1],
[1, 0.8862745098039215, 0.35294117647058826, 1],
[1, 0.8862745098039215, 0.36470588235294116, 1],
[1, 0.8901960784313725, 0.37254901960784315, 1],
[1, 0.8901960784313725, 0.3843137254901961, 1],
[1, 0.8941176470588236, 0.39215686274509803, 1],
[1, 0.8941176470588236, 0.403921568627451, 1],
[1, 0.8980392156862745, 0.4117647058823529, 1],
[1, 0.8980392156862745, 0.4235294117647059, 1],
[1, 0.8980392156862745, 0.43137254901960786, 1],
[1, 0.9019607843137255, 0.44313725490196076, 1],
[1, 0.9019607843137255, 0.45098039215686275, 1],
[1, 0.9058823529411765, 0.4627450980392157, 1],
[1, 0.9058823529411765, 0.47058823529411764, 1],
[1, 0.9098039215686274, 0.4823529411764706, 1],
[1, 0.9098039215686274, 0.49019607843137253, 1],
[1, 0.9137254901960784, 0.5019607843137255, 1],
[1, 0.9137254901960784, 0.5098039215686274, 1],
[1, 0.9137254901960784, 0.5215686274509804, 1],
[1, 0.9176470588235294, 0.5294117647058824, 1],
[1, 0.9176470588235294, 0.5411764705882353, 1],
[1, 0.9215686274509803, 0.5490196078431373, 1],
[1, 0.9215686274509803, 0.5607843137254902, 1],
[1, 0.9254901960784314, 0.5686274509803921, 1],
[1, 0.9254901960784314, 0.5803921568627451, 1],
[1, 0.9254901960784314, 0.5882352941176471, 1],
[1, 0.9294117647058824, 0.6, 1],
[1, 0.9294117647058824, 0.6078431372549019, 1],
[1, 0.9333333333333333, 0.6196078431372549, 1],
[1, 0.9333333333333333, 0.6274509803921569, 1],
[1, 0.9372549019607843, 0.6392156862745098, 1],
[1, 0.9372549019607843, 0.6470588235294118, 1],
[1, 0.9411764705882353, 0.6588235294117647, 1],
[1, 0.9411764705882353, 0.6666666666666666, 1],
[1, 0.9411764705882353, 0.6784313725490196, 1],
[1, 0.9450980392156862, 0.6862745098039216, 1],
[1, 0.9450980392156862, 0.6980392156862745, 1],
[1, 0.9490196078431372, 0.7058823529411765, 1],
[1, 0.9490196078431372, 0.7176470588235294, 1],
[1, 0.9529411764705882, 0.7254901960784313, 1],
[1, 0.9529411764705882, 0.7372549019607844, 1],
[1, 0.9568627450980393, 0.7450980392156863, 1],
[1, 0.9568627450980393, 0.7568627450980392, 1],
[1, 0.9568627450980393, 0.7647058823529411, 1],
[1, 0.9607843137254902, 0.7764705882352941, 1],
[1, 0.9607843137254902, 0.7843137254901961, 1],
[1, 0.9647058823529412, 0.796078431372549, 1],
[1, 0.9647058823529412, 0.803921568627451, 1],
[1, 0.9686274509803922, 0.8156862745098039, 1],
[1, 0.9686274509803922, 0.8235294117647058, 1],
[1, 0.9725490196078431, 0.8352941176470589, 1],
[1, 0.9725490196078431, 0.8431372549019608, 1],
[1, 0.9725490196078431, 0.8549019607843137, 1],
[1, 0.9764705882352941, 0.8627450980392157, 1],
[1, 0.9764705882352941, 0.8745098039215686, 1],
[1, 0.9803921568627451, 0.8823529411764706, 1],
[1, 0.9803921568627451, 0.8941176470588236, 1],
[1, 0.984313725490196, 0.9019607843137255, 1],
[1, 0.984313725490196, 0.9137254901960784, 1],
[1, 0.984313725490196, 0.9215686274509803, 1],
[1, 0.9882352941176471, 0.9333333333333333, 1],
[1, 0.9882352941176471, 0.9411764705882353, 1],
[1, 0.9921568627450981, 0.9529411764705882, 1],
[1, 0.9921568627450981, 0.9607843137254902, 1],
[1, 0.996078431372549, 0.9725490196078431, 1],
[1, 0.996078431372549, 0.9803921568627451, 1],
[1, 1, 0.9921568627450981, 1],
[1, 1, 1, 1]
]

View File

@ -0,0 +1,47 @@
let audio = document.getElementById('audio');
let file_path = audio.src;
function preload(){
sound = loadSound(audio.src);
}
function setup(){
let cnv = createCanvas(100,100);
cnv.mouseClicked(togglePlay);
fft = new p5.FFT();
sound.amp(0.2);
}
function draw(){
background(220);
let spectrum = fft.analyze();
noStroke();
fill(255, 0, 255);
for (let i = 0; i< spectrum.length; i++){
let x = map(i, 0, spectrum.length, 0, width);
let h = -height + map(spectrum[i], 0, 255, height, 0);
rect(x, height, width / spectrum.length, h )
}
let waveform = fft.waveform();
noFill();
beginShape();
stroke(20);
for (let i = 0; i < waveform.length; i++){
let x = map(i, 0, waveform.length, 0, width);
let y = map( waveform[i], -1, 1, 0, height);
vertex(x,y);
}
endShape();
text('tap to play', 20, 20);
}
function togglePlay() {
if (sound.isPlaying()) {
sound.pause();
} else {
sound.loop();
}
}

View File

@ -0,0 +1,11 @@
var wavesurfer = WaveSurfer.create({
container: '#waveform',
waveColor: 'violet',
progressColor: 'purple'
});
wavesurfer.on('ready', function () {
wavesurfer.play();
});
let audio = document.getElementById('audio');
let file_path = audio.src;
wavesurfer.load(file_path);

View File

@ -0,0 +1,34 @@
let audio = document.getElementById('audio');
let file_path = audio.src;
var sound;
var fft;
function preload() {
sound = loadSound(audio.src);
}
function setup() {
createCanvas(500, 500);
colorMode(HSB);
angleMode(DEGREES);
sound.play();
fft = new p5.FFT(0.9, 128);
}
function draw() {
background(0);
var spectrum = fft.analyze();
noStroke();
translate(width / 2, height / 2);
for (var i = 0; i < spectrum.length; i++) {
var angle = map(i, 0, spectrum.length, 0, 360);
var amp = spectrum[i];
var r = map(amp, 0, 256, 20, 100);
var x = r * cos(angle);
var y = r * sin(angle);
stroke(i, 255, 255);
line(0, 0, x, y);
}
}

View File

@ -0,0 +1,259 @@
// Assumes context is an AudioContext defined outside of this class.
Polymer('g-spectrogram', {
// Show the controls UI.
controls: false,
// Log mode.
log: false,
// Show axis labels, and how many ticks.
labels: false,
ticks: 5,
speed: 2,
// FFT bin size,
fftsize: 2048,
oscillator: false,
color: false,
attachedCallback: function() {
this.tempCanvas = document.createElement('canvas'),
console.log('Created spectrogram');
// Get input from the microphone.
if (navigator.mozGetUserMedia) {
navigator.mozGetUserMedia({audio: true},
this.onStream.bind(this),
this.onStreamError.bind(this));
} else if (navigator.webkitGetUserMedia) {
navigator.webkitGetUserMedia({audio: true},
this.onStream.bind(this),
this.onStreamError.bind(this));
}
this.ctx = this.$.canvas.getContext('2d');
},
render: function() {
//console.log('Render');
this.width = window.innerWidth;
this.height = window.innerHeight;
var didResize = false;
// Ensure dimensions are accurate.
if (this.$.canvas.width != this.width) {
this.$.canvas.width = this.width;
this.$.labels.width = this.width;
didResize = true;
}
if (this.$.canvas.height != this.height) {
this.$.canvas.height = this.height;
this.$.labels.height = this.height;
didResize = true;
}
//this.renderTimeDomain();
this.renderFreqDomain();
if (this.labels && didResize) {
this.renderAxesLabels();
}
requestAnimationFrame(this.render.bind(this));
var now = new Date();
if (this.lastRenderTime_) {
this.instantaneousFPS = now - this.lastRenderTime_;
}
this.lastRenderTime_ = now;
},
renderTimeDomain: function() {
var times = new Uint8Array(this.analyser.frequencyBinCount);
this.analyser.getByteTimeDomainData(times);
for (var i = 0; i < times.length; i++) {
var value = times[i];
var percent = value / 256;
var barHeight = this.height * percent;
var offset = this.height - barHeight - 1;
var barWidth = this.width/times.length;
this.ctx.fillStyle = 'black';
this.ctx.fillRect(i * barWidth, offset, 1, 1);
}
},
renderFreqDomain: function() {
var freq = new Uint8Array(this.analyser.frequencyBinCount);
this.analyser.getByteFrequencyData(freq);
var ctx = this.ctx;
// Copy the current canvas onto the temp canvas.
this.tempCanvas.width = this.width;
this.tempCanvas.height = this.height;
//console.log(this.$.canvas.height, this.tempCanvas.height);
var tempCtx = this.tempCanvas.getContext('2d');
tempCtx.drawImage(this.$.canvas, 0, 0, this.width, this.height);
// Iterate over the frequencies.
for (var i = 0; i < freq.length; i++) {
var value;
// Draw each pixel with the specific color.
if (this.log) {
logIndex = this.logScale(i, freq.length);
value = freq[logIndex];
} else {
value = freq[i];
}
ctx.fillStyle = (this.color ? this.getFullColor(value) : this.getGrayColor(value));
var percent = i / freq.length;
var y = Math.round(percent * this.height);
// draw the line at the right side of the canvas
ctx.fillRect(this.width - this.speed, this.height - y,
this.speed, this.speed);
}
// Translate the canvas.
ctx.translate(-this.speed, 0);
// Draw the copied image.
ctx.drawImage(this.tempCanvas, 0, 0, this.width, this.height,
0, 0, this.width, this.height);
// Reset the transformation matrix.
ctx.setTransform(1, 0, 0, 1, 0, 0);
},
/**
* Given an index and the total number of entries, return the
* log-scaled value.
*/
logScale: function(index, total, opt_base) {
var base = opt_base || 2;
var logmax = this.logBase(total + 1, base);
var exp = logmax * index / total;
return Math.round(Math.pow(base, exp) - 1);
},
logBase: function(val, base) {
return Math.log(val) / Math.log(base);
},
renderAxesLabels: function() {
var canvas = this.$.labels;
canvas.width = this.width;
canvas.height = this.height;
var ctx = canvas.getContext('2d');
var startFreq = 440;
var nyquist = context.sampleRate/2;
var endFreq = nyquist - startFreq;
var step = (endFreq - startFreq) / this.ticks;
var yLabelOffset = 5;
// Render the vertical frequency axis.
for (var i = 0; i <= this.ticks; i++) {
var freq = startFreq + (step * i);
// Get the y coordinate from the current label.
var index = this.freqToIndex(freq);
var percent = index / this.getFFTBinCount();
var y = (1-percent) * this.height;
var x = this.width - 60;
// Get the value for the current y coordinate.
var label;
if (this.log) {
// Handle a logarithmic scale.
var logIndex = this.logScale(index, this.getFFTBinCount());
// Never show 0 Hz.
freq = Math.max(1, this.indexToFreq(logIndex));
}
var label = this.formatFreq(freq);
var units = this.formatUnits(freq);
ctx.font = '16px Inconsolata';
// Draw the value.
ctx.textAlign = 'right';
ctx.fillText(label, x, y + yLabelOffset);
// Draw the units.
ctx.textAlign = 'left';
ctx.fillText(units, x + 10, y + yLabelOffset);
// Draw a tick mark.
ctx.fillRect(x + 40, y, 30, 2);
}
},
clearAxesLabels: function() {
var canvas = this.$.labels;
var ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, this.width, this.height);
},
formatFreq: function(freq) {
return (freq >= 1000 ? (freq/1000).toFixed(1) : Math.round(freq));
},
formatUnits: function(freq) {
return (freq >= 1000 ? 'KHz' : 'Hz');
},
indexToFreq: function(index) {
var nyquist = context.sampleRate/2;
return nyquist/this.getFFTBinCount() * index;
},
freqToIndex: function(frequency) {
var nyquist = context.sampleRate/2;
return Math.round(frequency/nyquist * this.getFFTBinCount());
},
getFFTBinCount: function() {
return this.fftsize / 2;
},
onStream: function(stream) {
var input = context.createMediaStreamSource(stream);
var analyser = context.createAnalyser();
analyser.smoothingTimeConstant = 0;
analyser.fftSize = this.fftsize;
// Connect graph.
input.connect(analyser);
this.analyser = analyser;
// Setup a timer to visualize some stuff.
this.render();
},
onStreamError: function(e) {
console.error(e);
},
getGrayColor: function(value) {
return 'rgb(V, V, V)'.replace(/V/g, 255 - value);
},
getFullColor: function(value) {
var fromH = 62;
var toH = 0;
var percent = value / 255;
var delta = percent * (toH - fromH);
var hue = fromH + delta;
return 'hsl(H, 100%, 50%)'.replace(/H/g, hue);
},
logChanged: function() {
if (this.labels) {
this.renderAxesLabels();
}
},
ticksChanged: function() {
if (this.labels) {
this.renderAxesLabels();
}
},
labelsChanged: function() {
if (this.labels) {
this.renderAxesLabels();
} else {
this.clearAxesLabels();
}
}
});

View File

@ -0,0 +1,63 @@
'use strict';
let audio = document.getElementById('audio');
let file_path = audio.src;
var wavesurfer;
// Init & load
document.addEventListener('DOMContentLoaded', function() {
// Create an instance
var options = {
container: '#waveform',
waveColor: 'white',
progressColor: 'purple',
loaderColor: 'purple',
cursorColor: 'navy',
plugins: [
WaveSurfer.spectrogram.create({
wavesurfer: wavesurfer,
container: "#wave-spectrogram",
labels: true
})
]
};
wavesurfer = WaveSurfer.create(options);
wavesurfer.load(file_path);
});
let play = document.getElementById('play').addEventListener('click', function() {
wavesurfer.play();
});
let pause = document.getElementById('pause').addEventListener('click', function() {
wavesurfer.pause();
});
let restart = document.getElementById('restart').addEventListener('click', function() {
wavesurfer.play(0);
});
function getCursorXY(e) {
return [e.pageX, e.pageY];
}
function measure(x, y) {
let spectro = document.getElementById('wave-spectrogram');
let spectro_x = spectro.offsetLeft;
let spectro_y = spectro.offsetTop;
let spectro_height = spectro.clientHeight;
let spectro_width = spectro.clientWidth;
x = (x - spectro_x);
y = -(-(-y + spectro_y) - spectro_height);
let t = (x / spectro_width) * audio.duration;
let f = (y / spectro_height) * 24;
document.getElementById('cursor-time').innerHTML = Math.round(t);
document.getElementById('cursor-frequency').innerHTML = Math.round(f);
}
let spectro = document.getElementById("wave-spectrogram");
console.log(spectro);
spectro.addEventListener('mousemove', function() {
let coords = getCursorXY(window.event);
measure(coords[0], coords[1]);
// console.log(getCursorXY(window.event));
});

View File

@ -0,0 +1,78 @@
let audio = document.getElementById('audio');
let file_path = audio.src;
fftsize = 2048;
color = true;
cnv = document.getElementById("spectrogram");
width = window.innerWidth;
height = window.innerHeight;
if (cnv.width != width) {
cnv.width = width;
}
if (cnv.height != height) {
cnv.height = height;
}
let now = new Date();
if (lastRenderTime) {
instantaneousFPS = now - lastRenderTime;
}
function renderTimeDomain() {
let times = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteTimeDomainData(times);
for (var i = 0; i < times.length; i++) {
var value = times[i];
var percent = value / 256;
var barHeight = height * percent;
var offset = height - barHeight - 1;
var barWidth = width / times.length;
ctx.fillStyle = 'black';
ctx.fillRect(i * barWidth, offset, 1, 1);
}
}
function renderFreqDomain() {
var freq = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(freq);
cnv.width = width;
cnv.height = height;
var tempCtx = cnv.getContext('2d');
tempCtx.drawImage(cnv, 0, 0, width, height);
for (var i = 0; i < freq.length; i++) {
var value;
if (log) {
logIndex = logScale(i, freq.length);
value = freq[logIndex];
} else {
value = freq[i];
}
ctx.fillStyle = (color ? getFullColor(value): getGrayColor(value));
var percent = i / freq.length;
var y = Math.round(percent * height);
ctx.fillRect(width - speed, height - y, speed, speed);
}
ctx.translate(-speed, 0);
ctx.drawImage(cnv, 0, 0, width, height, 0, 0, width, height);
ctx.setTransform(1, 0, 0, 1, 0, 0);
}
function logScale(index, total, opt_base) {
var base = opt_base || 2;
var logmax = logBase(total + 1, base);
var exp = logmax * index / total;
return Math.round(Math.pow(base, exp) - 1);
}
function renderAxesLabels() {
}

View File

@ -0,0 +1,6 @@
let audio = document.getElementById('audio');
let file_path = audio.src;
function specgram() {
const analyser =
}

View File

@ -1,325 +1,383 @@
* {
align-self: baseline;
align-self: baseline;
}
body{
margin: 0;
background-color: white;
body {
margin: 0;
background-color: white;
}
header {
text-align: right;
padding: 0;
margin-top: 1em;
text-align: right;
padding: 0;
margin-top: 1em;
}
header a {
text-decoration: none;
color: black;
text-decoration: none;
color: black;
}
nav, nav .container{
padding: 0;
margin: 0;
nav,
nav .container {
padding: 0;
margin: 0;
}
header .container, nav .container {
display: flex;
justify-content: space-between;
header .container,
nav .container {
display: flex;
justify-content: space-between;
}
header h1 {
font-size: 4em;
padding: 0;
margin: 0;
font-size: 4em;
padding: 0;
margin: 0;
}
img.banner {
width: 100%;
height: auto;
width: 100%;
height: auto;
}
section{
padding: 1em;
min-height: 100vh;
width: 50vw;
text-align: left;
margin: auto;
section {
padding: 1em;
min-height: 100vh;
width: 50vw;
text-align: left;
margin: auto;
}
article {
width: 50vw;
text-align: left;
margin: auto;
width: 50vw;
text-align: left;
margin: auto;
}
article h1 {
font-size: 5em;
article h1 {
font-size: 5em;
}
footer {
color: white;
text-align: center;
background-color: rgba(0,0,0, 0.8);
padding: 1em;
color: white;
text-align: center;
background-color: rgba(0, 0, 0, 0.9);
padding: 1em;
}
footer a {
text-decoration: none;
text-decoration: none;
}
footer img {
height: 1em;
height: 1em;
}
label {
width: 40em;
display: inline;
width: 40em;
display: inline;
}
label span.info {
display: none;
display: none;
}
label:hover span.info {
display: inline-block;
position: relative;
background: yellow;
padding: 0.5em;
border-radius: 5px;
display: inline-block;
position: relative;
background: yellow;
padding: 0.5em;
border-radius: 5px;
}
input {
margin: 0.1em;
margin: 0.1em;
}
/* Style inputs with type="text", select elements and textareas */
input[type=text], input[type=email], input[type=url], input[type=password], input[type=number], input[type=date], input[type=time], select, textarea {
width: 100%; /* Full width */
padding: 12px; /* Some padding */
border: 1px solid #ccc; /* Gray border */
border-radius: 4px; /* Rounded borders */
box-sizing: border-box; /* Make sure that padding and width stays in place */
margin-top: 6px; /* Add a top margin */
margin-bottom: 16px; /* Bottom margin */
resize: vertical /* Allow the user to vertically resize the textarea (not horizontally) */
input[type=text],
input[type=email],
input[type=url],
input[type=password],
input[type=number],
input[type=date],
input[type=time],
select,
textarea {
width: 100%;
/* Full width */
padding: 12px;
/* Some padding */
border: 1px solid #ccc;
/* Gray border */
border-radius: 4px;
/* Rounded borders */
box-sizing: border-box;
/* Make sure that padding and width stays in place */
margin-top: 6px;
/* Add a top margin */
margin-bottom: 16px;
/* Bottom margin */
resize: vertical
/* Allow the user to vertically resize the textarea (not horizontally) */
}
/* Style the submit button with a specific background color etc */
input[type=submit] {
background-color: #4CAF50;
color: white;
padding: 12px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
background-color: #4CAF50;
color: white;
padding: 12px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
}
input[type=reset] {
background-color: #af4c4c;
color: white;
padding: 12px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
background-color: #af4c4c;
color: white;
padding: 12px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
}
/* When moving the mouse over the submit button, add a darker green color */
input[type=submit]:hover {
background-color: #45a049;
background-color: #45a049;
}
/* When moving the mouse over the reset button, add a darker red color */
input[type=reset]:hover {
background-color: #923737;
background-color: #923737;
}
/* Add a background color and some padding around the form */
.container {
border-radius: 5px;
background-color: #f2f2f2;
padding: 1em;
border-radius: 5px;
background-color: #f2f2f2;
padding: 1em;
}
nav {
border-bottom: 1px solid black;
position: flex;
display: block;
width: 100%;
background-color: white;
z-index: 10;
border-bottom: 1px solid black;
position: flex;
display: block;
width: 100%;
background-color: white;
z-index: 10;
}
nav div {
padding: 1em;
padding: 1em;
}
nav.dark-theme {
background: black;
background: black;
}
nav.dark-theme ul li {
color: white;
color: white;
}
nav ul {
display: flex;
flex-direction: row;
display: flex;
flex-direction: row;
}
nav ul a {
text-decoration: none;
text-decoration: none;
}
nav ul li {
list-style: none;
color: black;
margin: 0.5em;
list-style: none;
color: black;
margin: 0.5em;
}
iframe::parent {
padding: 0;
margin: 0;
padding: 0;
margin: 0;
}
iframe {
width: 100%;
height: 750px;
width: 100%;
height: 750px;
}
#previewFrame {
width: 300px;
height: 200px;
resize: both;
zoom: 0.2;
-moz-transform: scale(0.5);
-moz-transform-origin: 0 0;
-o-transform: scale(0.5);
-o-transform-origin: 0 0;
-webkit-transform: scale(0.5);
-webkit-transform-origin: 0 0;
width: 300px;
height: 200px;
resize: both;
zoom: 0.2;
-moz-transform: scale(0.5);
-moz-transform-origin: 0 0;
-o-transform: scale(0.5);
-o-transform-origin: 0 0;
-webkit-transform: scale(0.5);
-webkit-transform-origin: 0 0;
}
iframe html body {
font-size: 0.1em;
iframe html body {
font-size: 0.1em;
}
.container {
display: flex;
padding-top: 0;
padding-bottom: 0;
display: flex;
padding-top: 0;
padding-bottom: 0;
}
.container.row {
flex-direction: row;
flex-direction: row;
}
.container.column {
flex-direction: column;
flex-direction: column;
}
h3, p{
padding: 1em;
width: auto;
h3,
p {
padding: 1em;
width: auto;
}
p.large {
width: auto;
width: auto;
}
table {
border-radius: 5px;
width: 100%;
border-collapse: collapse;
border-radius: 5px;
width: 100%;
border-collapse: collapse;
}
td, th {
border: 1px solid #dddddd;
text-align: left;
padding: 0.5em;
td,
th {
border: 1px solid #dddddd;
text-align: left;
padding: 0.5em;
}
tr:nth-child(even) {
background-color: #dddddd;
background-color: #dddddd;
}
table a {
text-decoration: none;
color: black;
text-decoration: none;
color: black;
}
table a:hover {
font-style: italic;
font-style: italic;
}
#searchbar {
display: flex;
flex-direction: row;
align-self: right;
display: flex;
flex-direction: row;
align-self: right;
}
ul.breadcrumb {
display: flex;
flex-basis: row;
display: flex;
flex-basis: row;
}
ul.breadcrumb li {
list-style: url("/media/icons/arrow.svg");
margin-left: 2em;
list-style: url("/media/icons/arrow.svg");
margin-left: 2em;
}
ul.breadcrumb li.active {
font-weight: bold;
font-weight: bold;
}
div.coordinates {
display: flex;
flex-direction: row;
display: flex;
flex-direction: row;
}
div.coordinates input[type="text"] {
width: 25em;
width: 25em;
}
.sci-name {
font-style: italic;
font-style: italic;
}
.error {
border: solid red;
border-radius: 5px;
padding: 0.5em;
background-color: rgba(255, 0, 0, 0.4)
border: solid red;
border-radius: 5px;
padding: 0.5em;
background-color: rgba(255, 0, 0, 0.4)
}
.sound {
background-color: rgba(0, 255, 0, 0.5);
padding: 1em;
border-radius: 5px;
overflow: auto;
background-color: rgba(0, 255, 0, 0.5);
padding: 1em;
border-radius: 5px;
overflow: auto;
}
#spectrogram {
width: 100%;
max-width: 75vh;
width: 100%;
max-width: 75vh;
}
button img {
max-height: 1em;
max-height: 1em;
}
form#url-form {
display: none;
position: fixed;
top: 50%;
left: 35%;
width: 15em;
z-index: 1;
background-color: white;
padding: 1em;
border-radius: 5px;
border: 1px solid #ccc;
display: none;
position: fixed;
top: 50%;
left: 35%;
width: 15em;
z-index: 1;
background-color: white;
padding: 1em;
border-radius: 5px;
border: 1px solid #ccc;
}
table#replies td {
background-color: white;
background-color: white;
}
#larynx {