Created
September 13, 2016 07:17
-
-
Save skairunner/c5665e58e8e8c2755e28b4b530ba7afc to your computer and use it in GitHub Desktop.
Code of Music: Simple composition
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"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(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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