Skip to content

Instantly share code, notes, and snippets.

@skairunner
Created September 13, 2016 07:17
Show Gist options
  • Save skairunner/c5665e58e8e8c2755e28b4b530ba7afc to your computer and use it in GitHub Desktop.
Save skairunner/c5665e58e8e8c2755e28b4b530ba7afc to your computer and use it in GitHub Desktop.
Code of Music: Simple composition
"use strict";
document.addEventListener("DOMContentLoaded", init);
var melody = [
["C5","2n"],
["E5","2n"],
["G5","2n"],
["E5","2n"],
["C5","1n"]
]
var melody_nested = [
["C5", "E5"], ["G5", "E5"], "C5"
]
var harmony = [
"C4", "B3", "C4", "D4", "E4", "D4", "E4", "F4",
"G4", "A4", "G4", "F4", "E4", "F4", "E4", "D4",
"C4", "D4", "C4", "B3", "C4", "G3", "A3", "B3"
] // all 8ths
var drumnotes = [
[ // bar 1 of percussion
{instrument:"drum", duration:"2n+8n", note:"C0", time:"+0"},
{instrument:"snare", duration:"8n", time:"+2n"}
],
[ // bar 2
{instrument:"drum" , duration:"2n+8n", time:"+4n"},
{instrument:"snare", duration:"8n", time:"+2n"}
]
]
function update() {
}
function initsvg() {
let svg = d3.select("svg");
svg
.append("line")
.attr("x1", "100")
.attr("x2", "100")
.attr("y1", "0")
.attr("y2", svg.attr("height"))
.attr("stroke", "rgba(0, 0, 0, 0.5)")
.attr("stroke-width", "2");
}
function secondsFromNotation(notation) {
}
let notetable = {
A: 0,
B: 2,
C: 3,
D: 5,
E: 7,
F: 8,
G: 10
}
let semitoneRatio = Math.pow(2, 1.0/12.0);
function numFromNote(note) {
let letter = notetable[note[0]];
let octave = note[1] - 4; // starting with middle A.
let halftonesFromA = octave * 12 + letter;
return 440 * Math.pow(semitoneRatio, halftonesFromA);
}
function init() {
initsvg();
let visualscore = d3.select("#score");
//create a synth and connect it to the master output (your speakers)
var melodysynth = new Tone.Synth().toMaster();
var harmonysynth = new Tone.Synth().toMaster();
var melodyseq = new Tone.Sequence(function(time, note){
melodysynth.triggerRelease();
melodysynth.triggerAttack(note);
}, melody_nested, "1n");
melodyseq.start("0m").stop("6m");
// need to clean up "hanging" note
melodysynth.triggerAttackRelease(0, 0, "6:0:0");
let harmonycounter = 0;
var harmonyloop = new Tone.Loop(function(time){
let note = harmony[harmonycounter % harmony.length];
harmonycounter += 1;
harmonysynth.triggerAttackRelease(note, "8n", time);
let width = 10/8 * 20; // here be magic numbers
visualscore.select("#harmony")
.append("rect")
.classed("harmony", true)
.attr("x", time * width * 6) // magicer number pls fix
.attr("y", numFromNote(note)/300*20) // magic number pls fix
.attr("width", width)
.attr("height", 10);
}, "8n");
harmonyloop.start("0m").stop("6m");
var drumsyn = new Tone.MembraneSynth({
"envelope": {
attack: 0.001,
decay: 0.8,
sustain: 0.01,
release: 1.4,
attackCurve: "exponential"
},
"volume": -10
});
var reverb = new Tone.Freeverb(0.6, 6000).toMaster();
var snare = new Tone.NoiseSynth().toMaster();
drumsyn.connect(reverb);
var drumcounter = 0;
var drumloop = new Tone.Loop(function(time) {
let notes = drumnotes[drumcounter % drumnotes.length];
let width = 10/8 * 20; // here be magic numbers
for (let i = 0; i < notes.length; i++) {
let note = notes[i];
if (note.instrument == "drum") {
// this whole block is terrible fix later
if (note.time == null) {
drumsyn.triggerAttackRelease(note.note, note.duration);
visualscore.select("#drum")
.append("circle")
.classed("drum", true)
.attr("cx", time * width * 12) // magic numbers, etc
.attr("cy", 75)
.attr("r", 10);
}
else {
drumsyn.triggerAttackRelease(note.note, note.duration, note.time);
visualscore.select("#drum")
.append("circle")
.classed("drum", true)
.attr("cx", time * width * 12) // magic numbers, etc
.attr("cy", 75)
.attr("r", 10);
}
} else if (note.instrument == "snare") {
snare.triggerAttackRelease(note.duration, note.time);
visualscore.select("#drum")
.append("circle")
.classed("snare", true)
.attr("cx", time * width * 12) // magic numbers, etc
.attr("cy", 75)
.attr("r", 10);
}
}
drumcounter += 1;
}, "1n");
drumloop.start("0m").stop("6m");
let timecounter = 1;
function slide() {
d3.select("#score").transition()
.duration(1000)
.delay(0)
.ease(d3.easeLinear)
.attr("transform", "translate(" + (-100 * timecounter) + ")");
timecounter += 1;
}
slide();
setInterval(slide, 1000);
Tone.Transport.start();
}
<html>
<head>
<meta charset="UTF-8">
<script language="javascript" type="text/javascript" src="tone.js"></script>
<script language="javascript" type="text/javascript" src="composition.js"></script>
<script language="javascript" type="text/javascript" src="d3.js"></script>
<!-- this line removes any default padding and style. you might only need one of these values set. -->
<style>.harmony {
fill:rgb(255, 165, 92);
}
.drum{
fill:rgb(0,0,0);
}
.snare {
fill:rgb(255, 61, 61);
}</style>
</head>
<body>
<svg width="800" height="400">
<g id="score" transform="translate(100,0)">
<g id="main" transform="translate(0,0)"></g>
<g id="harmony" transform="translate(0,130)"></g>
<g id="drum" transform="translate(0,260)"></g>
</g>
</svg>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment