diff --git a/public/about/index.php b/public/about/index.php
index 06791f9..390c33d 100644
--- a/public/about/index.php
+++ b/public/about/index.php
@@ -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();
?>
diff --git a/public/database/TAXREF14.0_CHIRO.csv b/public/database/TAXREF14.0_CHIRO.csv
old mode 100755
new mode 100644
diff --git a/public/explore/spectrograms/index.php b/public/explore/spectrograms/index.php
index 96b5855..7ead7c7 100644
--- a/public/explore/spectrograms/index.php
+++ b/public/explore/spectrograms/index.php
@@ -58,8 +58,10 @@ include("$root/analytics/matomo.php");
-
-
+
+
+
diff --git a/public/larynx/index.php b/public/larynx/index.php
new file mode 100644
index 0000000..a969589
--- /dev/null
+++ b/public/larynx/index.php
@@ -0,0 +1,85 @@
+ 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();
+?>
+
+
+
+
+
+
+ Larynx | Chiro - Canto
+
+
+
+
+
+
+
+
+ Larynx
+ A web tool for bat sound analysis
+
+
+
Larynx v=$version?>
+
+
+
+
+
+
+
+
+
=$data['license']?> =$data['recordist_name']?>
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/public/larynx/scripts/create_colormap.js b/public/larynx/scripts/create_colormap.js
new file mode 100644
index 0000000..29aae2f
--- /dev/null
+++ b/public/larynx/scripts/create_colormap.js
@@ -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));
\ No newline at end of file
diff --git a/public/larynx/scripts/hot-colormap.js b/public/larynx/scripts/hot-colormap.js
new file mode 100644
index 0000000..152b903
--- /dev/null
+++ b/public/larynx/scripts/hot-colormap.js
@@ -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]
+]
\ No newline at end of file
diff --git a/public/larynx/scripts/p5.fft.js b/public/larynx/scripts/p5.fft.js
new file mode 100644
index 0000000..d09250c
--- /dev/null
+++ b/public/larynx/scripts/p5.fft.js
@@ -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();
+ }
+}
\ No newline at end of file
diff --git a/public/larynx/scripts/script.js b/public/larynx/scripts/script.js
new file mode 100644
index 0000000..db8992f
--- /dev/null
+++ b/public/larynx/scripts/script.js
@@ -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);
\ No newline at end of file
diff --git a/public/larynx/scripts/sketch.js b/public/larynx/scripts/sketch.js
new file mode 100644
index 0000000..4195c0d
--- /dev/null
+++ b/public/larynx/scripts/sketch.js
@@ -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);
+ }
+}
diff --git a/public/larynx/scripts/spectro.borismus.js b/public/larynx/scripts/spectro.borismus.js
new file mode 100644
index 0000000..4fbab88
--- /dev/null
+++ b/public/larynx/scripts/spectro.borismus.js
@@ -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();
+ }
+ }
+ });
+
\ No newline at end of file
diff --git a/public/larynx/scripts/spectro.js b/public/larynx/scripts/spectro.js
new file mode 100644
index 0000000..c4e14cc
--- /dev/null
+++ b/public/larynx/scripts/spectro.js
@@ -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));
+});
\ No newline at end of file
diff --git a/public/larynx/scripts/spectro.larynx.js b/public/larynx/scripts/spectro.larynx.js
new file mode 100644
index 0000000..b280a49
--- /dev/null
+++ b/public/larynx/scripts/spectro.larynx.js
@@ -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() {
+
+}
\ No newline at end of file
diff --git a/public/larynx/scripts/webaudio.spectro.js b/public/larynx/scripts/webaudio.spectro.js
new file mode 100644
index 0000000..5d66785
--- /dev/null
+++ b/public/larynx/scripts/webaudio.spectro.js
@@ -0,0 +1,6 @@
+let audio = document.getElementById('audio');
+let file_path = audio.src;
+
+function specgram() {
+ const analyser =
+}
\ No newline at end of file
diff --git a/public/styles/style.css b/public/styles/style.css
index f89c75e..60df212 100644
--- a/public/styles/style.css
+++ b/public/styles/style.css
@@ -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 {
+ background-color: rgba(0, 0, 0, 0.8);
+ width: auto;
+ min-height: 100vh;
+ margin: 0;
+
+ color: white;
+ padding: 1em;
+}
+
+#larynx h2 {
+ text-align: center;
+}
+
+#larynx {
+ text-align: center;
+}
+
+#larynx .license {
+ text-align: left;
+}
+
+#larynx canvas {
+ width: 100vw;
+ position: relative;
+ left: 0;
+}
+
+#larynx .container {
+ background: transparent;
+ display: flex;
+ justify-content: space-between;
+}
\ No newline at end of file