aboutsummaryrefslogtreecommitdiff
path: root/site/app/ocsillator/index.html
diff options
context:
space:
mode:
Diffstat (limited to 'site/app/ocsillator/index.html')
-rw-r--r--site/app/ocsillator/index.html319
1 files changed, 319 insertions, 0 deletions
diff --git a/site/app/ocsillator/index.html b/site/app/ocsillator/index.html
new file mode 100644
index 0000000..f115bcc
--- /dev/null
+++ b/site/app/ocsillator/index.html
@@ -0,0 +1,319 @@
+<html>
+<head>
+<script type="text/javascript" src="/code/jquery.js"></script>
+<script type="text/javascript" src="../base/base.js"></script>
+<script type="text/javascript">
+var appdata = {
+"instruments": [
+ {name: "Effemm bass", instr: "ocsinst_blockbass"},
+ {name: "Three Oh", instr: "ocsinst_303"},
+ {name: "Strung", instr: "ocsinst_strings"},
+ {name: "Harm", instr: "ocsinst_guitarharmonics"},
+ {name: "Cold nights", instr: "ocsinst_guitarharmonicsfx"},
+ {name: "Rhedos", instr: "ocsinst_rhodes1"},
+ {name: "Evolo", instr: "oscinst_pad1"},
+ {name: "Kaleb", instr: "oscinst_kalimba1"},
+ {name: "Freakperk", instr: "ocsinst_perc_freak", nvalue: true},
+ {name: "Canne", instr: "ocsinst_perc_case", nvalue: true},
+]};
+
+var Ocsillator = function(appdata) {
+ var elContainer = $("#main");
+ var elControls = $("#controls");
+ var elXy = $("#xy").css("background-color", "#121212");
+ var elNoteSelect = $("<select />").change(changeScale);
+ var elChordSelect = $("<select />").change(changeScale);
+ var elNoteRange = $("<input />").attr("type", "range").attr("min", 2).attr("max", 24).change(changeScale);
+ var elInstrumentSelect = $("<select />").change(changeInstrument);
+ var elDownload = $("<button />").text("Download").click(downloadFile);
+ var elRecord = $("<button />").text("Record").click(downloadFile);
+ var elPosition = $("<div />").css({width: "30px", height: "30px", "border-radius": "15px", "background-color": "#f5dd42", position: "absolute"}).hide();
+ var normaliseValue = false;
+ var notedata;
+ var uiNotes = [];
+ var mouseisdown;
+
+ function mousedown(e) {
+ mouseisdown = true;
+ elPosition.show();
+ handlePosition(e);
+ playInstrument();
+ }
+
+ function mousemove(e) {
+ if (!mouseisdown) return;
+ handlePosition(e);
+ }
+
+ function mouseup() {
+ mouseisdown = false;
+ elPosition.hide();
+ stopInstrument();
+ }
+
+ elXy.on("mousedown", mousedown).on("mousemove", mousemove).on("mouseup", mouseup).on("touchstart", function(e) {
+ mousedown(e.changedTouches[0]);
+ }).on("touchmove", function(e) {
+ mousemove(e.changedTouches[0]);
+ }).on("touchend", mouseup);
+
+ function handlePosition(e) {
+ var offs = elXy.offset();
+ var h = elXy.height();
+ var w = elXy.width();
+ var posX = e.clientX - offs.left;
+ var posY = e.clientY - offs.top;
+ if (posX < 0 || posX > w || posY < 0 || posY > h) return;
+ elPosition.css({left: (posX - 15) + "px", top: (posY - 15) + "px"});
+
+ var valX = posX / w;
+ var valY = 1 - (posY / h);
+
+ if (!normaliseValue) {
+ var note = uiNotes[Math.floor(valX * uiNotes.length)];
+ app.setControlChannel("note", note);
+ } else {
+ app.setControlChannel("valX", valX);
+ }
+ app.setControlChannel("valY", valY);
+ }
+
+ fetch("../base/notedata.json").then(function(r) {
+ r.json().then(function(j) {
+ notedata = j;
+ buildInputs();
+ });
+ });
+
+ function buildInputs() {
+ for (let n of notedata.notes) {
+ if (n[0] >= 24 && n[0] <= 84) {
+ $("<option />").val(n[0]).text(n[1]).appendTo(elNoteSelect);
+ }
+ }
+
+ for (let c in notedata.chords) {
+ $("<option />").val(c).text(notedata.chords[c].name).appendTo(elChordSelect);
+ }
+
+ for (let i in appdata.instruments) {
+ $("<option />").val(i).text(appdata.instruments[i].name).appendTo(elInstrumentSelect);
+ }
+
+ var tb = $("<tbody />").appendTo($("<table />").appendTo(elControls));
+ var tr = $("<tr />").appendTo(tb);
+ $("<td />").text("Base note").appendTo(tr);
+ $("<td />").text("Chord").appendTo(tr);
+ $("<td />").text("Note range").appendTo(tr);
+ $("<td />").text("Instrument").appendTo(tr);
+ $("<td />").appendTo(tr);
+
+ tr = $("<tr />").appendTo(tb);
+ $("<td />").append(elNoteSelect).appendTo(tr);
+ $("<td />").append(elChordSelect).appendTo(tr);
+ $("<td />").append(elNoteRange).appendTo(tr);
+ $("<td />").append(elInstrumentSelect).appendTo(tr);
+ $("<td />").append(elDownload).appendTo(tr);
+
+ elInstrumentSelect.trigger("change");
+ elNoteSelect.val(48);
+ elChordSelect.val(0);
+ elNoteRange.val(12);
+ changeScale();
+ }
+
+
+ function downloadFile() {
+
+ }
+
+ function recordStart() {
+ app.insertScore("ocsi_recordstart");
+ }
+
+ function recordStop() {
+ app.insertScore("ocsi_recordstop");
+ }
+
+ function recordClear() {
+ app.insertScore("ocsi_recordclear");
+ }
+
+ function changeInstrument() {
+ var instrument = appdata.instruments[elInstrumentSelect.val()];
+ if (instrument.nvalue) {
+ normaliseValue = instrument.nvalue;
+ } else {
+ normaliseValue = false;
+ }
+ app.insertScore("ocsi_setinstrument", [0, 1, instrument.instr]);
+ }
+
+
+ function playInstrument() {
+ app.insertScore("ocsi_play");
+ }
+
+ function stopInstrument() {
+ app.insertScore("ocsi_stop");
+ }
+
+ function changeScale() {
+ var noterange = elNoteRange.val();
+ var notenum = elNoteSelect.val();
+ var intervals = notedata.chords[elChordSelect.val()].intervals;
+ var intervalindex = 0;
+ var octave = 0;
+ var notes = [];
+ var note;
+ for (var i = 0; i < noterange; i++) {
+ note = parseInt(notenum) + (octave * 12) + parseInt(intervals[intervalindex]);
+ if (intervalindex < intervals.length - 1) {
+ intervalindex += 1;
+ } else {
+ intervalindex = 0;
+ octave += 1;
+ }
+ notes.push(note);
+ }
+ uiNotes = notes;
+ redraw();
+ }
+
+
+ function redraw() {
+ var w = window.innerWidth;
+ var h = window.innerHeight;
+ var size = Math.min(w, h);
+ elContainer.css({width: w, height: h});
+ var ch = Math.round(size * 0.1);
+ var xys = Math.round(size * 0.9);
+ elControls.css({width: w + "px", height: ch + "px"});
+ elXy.empty().css({width: xys + "px", height: xys + "px", top: ch + "px"}).append(elPosition);
+
+ var step = Math.round(xys / uiNotes.length);
+ for (var x = 0; x < xys; x += step) {
+ $("<div />").addClass("gridline").css({left: x + "px", height: xys + "px"}).appendTo(elXy);
+ }
+ }
+
+
+ window.onresize = redraw;
+};
+
+$(function() {
+ window.app = new CSApplication({
+ csdUrl: "ocsillator.csd",
+ onPlay: function () {
+ $("#loading").hide();
+ window.osc = new Ocsillator(appdata);
+ }
+ });
+ $("#begin").click(function() {
+ $("#begin").hide();
+ app.play();
+ });
+
+});
+
+</script>
+<style type="text/css">
+ body {
+ font-family: Arial, sans-serif;
+ user-select: none;
+ background-color: #a1a1a1;
+ }
+
+ .gridline {
+ width: 1px;
+ height: 1px;
+ position: absolute;
+ background-color: #33aa33;
+ z-index: 10;
+ }
+
+ #loading {
+ width: 100%;
+ height: 100%;
+ top: 0px;
+ left: 0px;
+ position: absolute;
+ z-index: 20;
+ background-color: #344534;
+ }
+
+ #loading_inner {
+ left: 30%;
+ top: 30%;
+ width: 40%;
+ height: 40%;
+ text-align: center;
+ font-size: 48pt;
+ position: absolute
+
+ }
+
+ #begin {
+ width: 100%;
+ height: 100%;
+ top: 0px;
+ left: 0px;
+ position: absolute;
+ z-index: 25;
+ text-align: center;
+ background-color: #344534;
+ cursor: pointer;
+ }
+
+ #begin_inner {
+ left: 30%;
+ top: 30%;
+ width: 40%;
+ height: 40%;
+ text-align: center;
+ font-size: 48pt;
+ position: absolute
+
+ }
+
+ #main {
+ width: 100%;
+ height: 100%;
+ top: 0px;
+ left: 0px;
+ position: absolute;
+ }
+
+ #controls {
+ width: 100%;
+ height: 20%;
+ top: 0px;
+ left: 0px;
+ position: absolute;
+ }
+
+ #xy {
+ position: absolute;
+ width: 80%;
+ height: 80%;
+ top: 20%;
+ left: 0px;
+ z-index: 1;
+ }
+
+</style>
+</head>
+<body>
+ <div id="loading">
+ <div id="loading_inner">Loading</div>
+ </div>
+ <div id="begin">
+ Ocsillator is inspired by the Korg Kaossilator.
+ <div id="begin_inner">Press to begin</div>
+ </div>
+ <div id="main">
+ <div id="controls"></div>
+ <div id="xy"></div>
+ </div>
+</body>
+</html>