2015-08-17 00:32:06 +00:00
|
|
|
<!DOCTYPE html>
|
|
|
|
<html>
|
|
|
|
<head>
|
|
|
|
<meta charset="utf-8">
|
2016-02-18 21:17:45 +00:00
|
|
|
<title>Phasing</title>
|
2015-08-17 00:32:06 +00:00
|
|
|
|
2019-01-09 01:21:29 +00:00
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
|
|
|
<link rel="icon" type="image/png" sizes="174x174" href="./favicon.png">
|
2015-08-17 00:32:06 +00:00
|
|
|
|
2020-07-18 00:58:09 +00:00
|
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/2.4.3/webcomponents-bundle.js"></script>
|
2020-07-18 00:36:42 +00:00
|
|
|
<link href="https://fonts.googleapis.com/css?family=Material+Icons&display=block" rel="stylesheet"/>
|
2019-01-09 01:21:29 +00:00
|
|
|
<script src="../build/Tone.js"></script>
|
2020-07-18 00:58:09 +00:00
|
|
|
<script src="./js/tone-ui.js"></script>
|
|
|
|
<script src="./js/components.js"></script>
|
2015-08-17 00:32:06 +00:00
|
|
|
</head>
|
2019-01-09 01:21:29 +00:00
|
|
|
<body>
|
2015-08-17 00:32:06 +00:00
|
|
|
<style type="text/css">
|
2019-01-09 01:21:29 +00:00
|
|
|
#loop {
|
|
|
|
margin-bottom: 10px;
|
|
|
|
display: flex;
|
2015-08-17 00:32:06 +00:00
|
|
|
}
|
2020-07-18 00:36:42 +00:00
|
|
|
|
|
|
|
#loop .bar {
|
2019-01-09 01:21:29 +00:00
|
|
|
flex-grow: 1;
|
|
|
|
width: 40%;
|
2020-07-18 00:36:42 +00:00
|
|
|
height: 20px;
|
|
|
|
margin: 10px;
|
|
|
|
background-color: #ececec;
|
|
|
|
border-radius: 4px;
|
|
|
|
overflow: hidden;
|
|
|
|
position: relative;
|
|
|
|
}
|
|
|
|
|
|
|
|
#loop .bar .fill {
|
|
|
|
height: 100%;
|
|
|
|
width: 50%;
|
|
|
|
background-color:#7F33ED;
|
|
|
|
position: absolute;
|
|
|
|
left: 50%;
|
|
|
|
transform: translate(-50%, 0);
|
2015-08-17 00:32:06 +00:00
|
|
|
}
|
|
|
|
</style>
|
2020-07-18 00:36:42 +00:00
|
|
|
<tone-example label="Piano Phase">
|
|
|
|
<div slot="explanation">
|
2015-12-05 19:00:44 +00:00
|
|
|
By slightly slowing down the playbackRate of the Tone.Sequence in the right channel,
|
|
|
|
the two identical melodies phase against each other in interesting ways.
|
2019-01-09 01:21:29 +00:00
|
|
|
<br><br>
|
2015-12-05 19:00:44 +00:00
|
|
|
Composition by Steve Reich. Inspiration from Alexander Chen.
|
2020-07-18 00:36:42 +00:00
|
|
|
</div>
|
2019-01-09 01:21:29 +00:00
|
|
|
|
2020-07-18 00:36:42 +00:00
|
|
|
<div id="content">
|
2019-01-09 01:21:29 +00:00
|
|
|
<div id="loop">
|
2020-07-18 00:36:42 +00:00
|
|
|
<div class="bar">
|
|
|
|
<div class="fill" id="left"></div>
|
|
|
|
</div>
|
|
|
|
<div class="bar">
|
|
|
|
<div class="fill" id="right"></div>
|
|
|
|
</div>
|
2019-01-09 01:21:29 +00:00
|
|
|
</div>
|
|
|
|
<tone-play-toggle></tone-play-toggle>
|
2020-07-18 00:36:42 +00:00
|
|
|
</div>
|
2019-01-09 01:21:29 +00:00
|
|
|
</tone-example>
|
|
|
|
|
|
|
|
<script type="text/javascript">
|
2020-07-18 00:36:42 +00:00
|
|
|
// set the bpm and time signature first
|
2015-12-05 19:00:44 +00:00
|
|
|
Tone.Transport.timeSignature = [6, 4];
|
|
|
|
Tone.Transport.bpm.value = 180;
|
2020-07-18 00:36:42 +00:00
|
|
|
|
|
|
|
// L/R channel merging
|
|
|
|
const merge = new Tone.Merge();
|
2015-08-17 00:32:06 +00:00
|
|
|
|
2020-07-18 00:36:42 +00:00
|
|
|
// a little reverb
|
|
|
|
const reverb = new Tone.Reverb({
|
|
|
|
wet: 0.3
|
2015-08-17 00:32:06 +00:00
|
|
|
});
|
|
|
|
|
2020-07-18 00:36:42 +00:00
|
|
|
merge.chain(reverb, Tone.Destination);
|
2015-08-17 00:32:06 +00:00
|
|
|
|
2020-07-19 17:46:11 +00:00
|
|
|
// left and right synthesizers
|
|
|
|
const synthL = new Tone.Synth({
|
2020-07-18 00:36:42 +00:00
|
|
|
oscillator: {
|
|
|
|
type: "custom",
|
|
|
|
partials: [2, 1, 2, 2],
|
2015-08-17 00:32:06 +00:00
|
|
|
},
|
2020-07-18 00:36:42 +00:00
|
|
|
envelope: {
|
|
|
|
attack: 0.005,
|
|
|
|
decay: 0.3,
|
|
|
|
sustain: 0.2,
|
|
|
|
release: 1,
|
2015-08-17 00:32:06 +00:00
|
|
|
},
|
2020-07-18 00:36:42 +00:00
|
|
|
portamento: 0.01,
|
|
|
|
volume: -20
|
2020-07-19 17:46:11 +00:00
|
|
|
}).connect(merge, 0, 0);
|
|
|
|
const synthR = new Tone.Synth({
|
|
|
|
oscillator: {
|
|
|
|
type: "custom",
|
|
|
|
partials: [2, 1, 2, 2],
|
|
|
|
},
|
|
|
|
envelope: {
|
|
|
|
attack: 0.005,
|
|
|
|
decay: 0.3,
|
|
|
|
sustain: 0.2,
|
|
|
|
release: 1,
|
|
|
|
},
|
|
|
|
portamento: 0.01,
|
|
|
|
volume: -20
|
|
|
|
}).connect(merge, 0, 1);
|
2015-08-17 00:32:06 +00:00
|
|
|
|
2020-07-18 00:36:42 +00:00
|
|
|
// the two Tone.Sequences
|
|
|
|
const partL = new Tone.Sequence(((time, note) => {
|
2015-08-17 00:32:06 +00:00
|
|
|
synthL.triggerAttackRelease(note, "8n", time);
|
2020-07-18 00:36:42 +00:00
|
|
|
}), ["E4", "F#4", "B4", "C#5", "D5", "F#4", "E4", "C#5", "B4", "F#4", "D5", "C#5"], "8n").start();
|
2015-08-17 00:32:06 +00:00
|
|
|
|
2020-07-18 00:36:42 +00:00
|
|
|
const partR = new Tone.Sequence(((time, note) => {
|
2015-08-17 00:32:06 +00:00
|
|
|
synthR.triggerAttackRelease(note, "8n", time);
|
2020-07-18 00:36:42 +00:00
|
|
|
}), ["E4", "F#4", "B4", "C#5", "D5", "F#4", "E4", "C#5", "B4", "F#4", "D5", "C#5"], "8n").start("2m");
|
|
|
|
|
|
|
|
// set the playback rate of the right part to be slightly slower
|
2015-12-05 19:00:44 +00:00
|
|
|
partR.playbackRate = 0.985;
|
2015-08-17 00:32:06 +00:00
|
|
|
|
2020-07-19 00:20:19 +00:00
|
|
|
// bind the interface
|
|
|
|
document.querySelector("tone-play-toggle").addEventListener("start", () => Tone.Transport.start());
|
|
|
|
document.querySelector("tone-play-toggle").addEventListener("stop", () => Tone.Transport.stop());
|
2020-07-18 00:36:42 +00:00
|
|
|
|
|
|
|
// update the width of the fill bars to reflect the left and right progress
|
2020-07-19 00:20:19 +00:00
|
|
|
function progressToWidth(progress) {
|
|
|
|
progress = Math.cos(progress * Math.PI * 2 + Math.PI);
|
|
|
|
progress = (progress + 1) / 2;
|
|
|
|
return `${progress * 100}%`;
|
2020-07-18 00:36:42 +00:00
|
|
|
}
|
2020-07-19 00:20:19 +00:00
|
|
|
function loop() {
|
|
|
|
requestAnimationFrame(loop);
|
2020-07-18 00:36:42 +00:00
|
|
|
// make it go out and back for each loop
|
2020-07-19 17:46:11 +00:00
|
|
|
// @ts-ignore
|
2020-07-19 00:20:19 +00:00
|
|
|
document.querySelector("#left").style.width = progressToWidth(partL.progress);
|
2020-07-19 17:46:11 +00:00
|
|
|
// @ts-ignore
|
2020-07-19 00:20:19 +00:00
|
|
|
document.querySelector("#right").style.width = progressToWidth(partR.progress);
|
2020-07-18 00:36:42 +00:00
|
|
|
}
|
2020-07-19 00:20:19 +00:00
|
|
|
loop();
|
2017-03-26 20:39:19 +00:00
|
|
|
|
|
|
|
</script>
|
2015-08-17 00:32:06 +00:00
|
|
|
</body>
|
2017-03-18 16:35:37 +00:00
|
|
|
</html>
|