Created a Synth class, updated page layouts and interactivity. todo: improve audio feedback, flesh out teach section, and find a system to theme site on.

This commit is contained in:
suroh 2019-03-16 17:16:24 +01:00
parent ab4f7128c9
commit 16899b823a
11 changed files with 241 additions and 70 deletions

View File

@ -23,7 +23,7 @@ nav {
nav>span { nav>span {
font-size: 1.5em; font-size: 1.5em;
color: #1e1e3c33; color: #1e1e3c33;
transition: color ease 0.1s; transition: color ease 0.5s;
} }
nav>span:hover { nav>span:hover {
@ -32,17 +32,27 @@ nav>span:hover {
cursor: pointer; cursor: pointer;
} }
nav>span.active {
color: #1e1e3cff;
transition: color 1s ease;
}
nav>span.active::after {
color: #1e1e3cff;
margin-left: 14px;
content: attr(data-link);
}
h1#menuItem { h1#menuItem {
position: absolute; position: absolute;
left: 20px; left: 20px;
bottom: 20px; bottom: 20px;
margin: 0; margin: 0;
padding: 0; padding: 0;
font-size: 31vw; font-size: 32vw;
opacity: 0; opacity: 0;
transform: translateY(300px); transform: translateY(300px);
transition: opacity ease-in-out 0.1s, transform ease-in-out 0.1s; transition: opacity ease-in-out 0.1s, transform ease-in-out 0.1s;
} }
h1#menuItem.active { h1#menuItem.active {
@ -52,6 +62,36 @@ h1#menuItem.active {
/* --> MAINPAGE CONSTRUCTION <-- */ /* --> MAINPAGE CONSTRUCTION <-- */
section#content { section.content {
margin: 40px 20px; display: grid;
margin: 0;
padding: 0;
opacity: 0;
max-height: 0px;
overflow: hidden;
transition: opacity 0.3s ease;
}
section.content.visible {
margin: 20px 67px;
opacity: 1;
height: inherit;
overflow: inherit;
}
section.content ul.subMenu {
margin: 0;
padding: 0;
list-style: none;
font-size: 1.5em;
}
section.content ul.subMenu li {
border-left: thin solid #d2d2d8;
padding: 5px 10px;
}
section.content ul.subMenu li:hover {
background: #d2d2d8;
cursor: pointer;
} }

View File

@ -8,18 +8,20 @@
<link rel="stylesheet" type="text/css" href="css/resets.css"> <link rel="stylesheet" type="text/css" href="css/resets.css">
<link rel="stylesheet" type="text/css" href="css/master.css"> <link rel="stylesheet" type="text/css" href="css/master.css">
<script src="js/interaction.js" charset="utf-8" defer></script> <script src="js/synth.js" charset="utf-8" defer></script>
<script src="js/audio.js" charset="utf-8" defer></script> <script src="js/audio.js" charset="utf-8" defer></script>
<script src="js/interaction.js" charset="utf-8" defer></script>
</head> </head>
<body> <body>
<nav> <nav>
<span data-link="works"></span> <span data-link="~"><~</span>
<span data-link="audio"></span> <span data-link="works" class=""></span>
<span data-link="teach"></span> <span data-link="audio" class=""></span>
<span data-link="teach" class=""></span>
</nav> </nav>
<section style="position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; z-index: -100;"> <section style="position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; z-index: -100;">
@ -28,7 +30,63 @@
</div> </div>
</section> </section>
<section id="content">
<section id="works" class="content">
<ul class="subMenu">
<li data-link="fragile">Fragile Mastery</li>
<li data-link="euclid">EUCLID</li>
<li data-link="autoArchive">Autonomous Archive</li>
<li data-link="adelaide">Adelaïde</li>
</ul>
</section>
<section id="audio" class="content">
<ul class="subMenu">
<li data-link="solo">solo</li>
<li data-link="postoast">postoast</li>
</ul>
<section class="content">
<div class="imgFeat">
<img src="../assets/audio/solo/thumb-_DSC5695.png">
</div>
<a href="https://work.suroh.tk/" id="home"><< home</a>
<section class="work text">
<h1>Solo</h1>
<p>My solo practice embraces the unstable nature of improvisation in software and in music. I aim to examine the agency that improvisation can provide in the context of creative software and performance. I build custom software that acts both as an instrument and collaborator which I perform alongside with a combination of digital hardware and traditional musical instruments. Through the employment of these tools I challenge my ingrained jazz improvisational training, and examine creative relationships we can have with machines.</p>
<iframe width="100%" height="166" scrolling="no" frameborder="no" allow="autoplay" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/471930894&color=%23333333&auto_play=false&hide_related=false&show_comments=true&show_user=true&show_reposts=false&show_teaser=true"></iframe>
<p>My improvisations to date have included hacking MIDI controllers and playing with audio analysis. Such approaches deconstruct my traditional musical training on the saxophone as I find myself attempting to embody routines as defined by software. It is either the programming of my years of formal music training, or a conceived imposition by the "perfection" of technology that makes me question my agency, and even my role as an interactor.</p>
<p>My performance practice is coupled with research that takes many other forms, where I engage in discussion around agencies a wider adoption of improvisation could provide. Building these instruments is an extension of my improvisational method, which acts as a form of liberation against the standardisation of both musical practices and software development. By employing improvisation towards the development of my tools, I expose the agencies that it might afford us in realms outside of creative practices, and how they might be used to combat outdated structures of hierarchy and value.</p>
<p>All of the code is freely accessible on my git repository here : <a href="https://git.suroh.tk">git.suroh.tk</a>.</p>
<iframe width="100%" height="166" scrolling="no" frameborder="no" allow="autoplay" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/476223060&color=%23333333&auto_play=false&hide_related=true&show_comments=false&show_user=true&show_reposts=false&show_teaser=true"></iframe>
</section>
<section class="work imgs">
<img src="../assets/audio/solo/patch.png">
<img src="../assets/audio/solo/thumb-_DSC5654.png">
</section>
</section>
</section>
<section id="teach" class="content">
<p>teach content</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute
irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</section> </section>

View File

@ -1,52 +1,11 @@
// audio for events // audio for events
// AUDIO SETUP // AUDIO SETUP
let audioEngine = new(window.AudioContext || window.webkitAudioContext)() const audioEngine = new(window.AudioContext || window.webkitAudioContext)()
let masterGain = audioEngine.createGain() const masterGain = audioEngine.createGain()
let voice = {
gain: audioEngine.createGain(),
osc: audioEngine.createOscillator(),
adsr: {
a: typeof amount === 'number' ? amount * 1000 : 0.025,
d: typeof amount === 'number' ? amount * 1000 : 0.5,
sv: typeof amount === 'number' ? amount : 0.8,
r: typeof amount === 'number' ? amount * 1000 : 0.5,
t: audioEngine.currentTime
},
play: function(note) {
freq = typeof note === 'number' ? note : (Math.random() * 350) + 50
this.osc.frequency.setValueAtTime(freq, audioEngine.currentTime)
this.engage()
},
engage: function() {
// clear preScheduled events
this.gain.gain.cancelScheduledValues(this.adsr.t)
// initial value
this.gain.gain.setValueAtTime(0.0, this.adsr.t)
// attack
this.gain.gain.setTargetAtTime(0.9, this.adsr.t, this.adsr.a)
// decay
this.gain.gain.setTargetAtTime(this.adsr.sv, this.adsr.t + this.adsr.a, this.adsr.d)
},
release: function() {
this.adsr.t = audioEngine.currentTime
// release
this.gain.gain.setTargetAtTime(0.0, this.adsr.t, this.adsr.r)
}
}
window.onload = function() { window.onload = function() {
// create gain // create gain
voice.gain.gain.setValueAtTime(0.0001, audioEngine.currentTime)
masterGain.gain.value = 0.9 masterGain.gain.value = 0.9
voice.gain.connect(masterGain)
// create oscilator
voice.osc.type = 'sine'
voice.osc.connect(voice.gain)
voice.osc.start()
masterGain.connect(audioEngine.destination) masterGain.connect(audioEngine.destination)
} }

View File

@ -2,27 +2,76 @@
const primaryNav = document.querySelector('nav') const primaryNav = document.querySelector('nav')
const menuItem = document.querySelector('#menuItem') const menuItem = document.querySelector('#menuItem')
const content = document.querySelectorAll('.content')
// TODO: (create voice class per button) // TODO: (create voice class per button)
// let menuVoices = [] let menuVoices = []
const subMenu = (activePage) => {
let menu = document.querySelector(`\#${activePage} \.subMenu`)
if (menu) {
return menu
} else {
return null
}
}
const showContent = (section) => {
for (let sect of content) {
if (c.dataset.link == sect.id) {
sect.className = 'content visible'
} else if (!c.dataset.link) {
sect.className = 'content'
} else {
sect.className = 'content'
}
}
}
for (let c of primaryNav.children) { for (let c of primaryNav.children) {
// TODO: (create voice class per button) // TODO: (create voice class per button)
// menuVoices[c.dataset.link] = new voice() menuVoices[c.dataset.link] = new Synth(audioEngine)
menuVoices[c.dataset.link].gain.connect(masterGain)
c.addEventListener('click', () => { c.addEventListener('click', () => {
console.log(`clicked : ${c.dataset.link}`) menuVoices[c.dataset.link].mod()
for (let _c of primaryNav.children) {
if (c === _c && c.dataset.link != '~') {
c.className = 'active'
if (subMenu(c.dataset.link)) {
for (let s of subMenu(c.dataset.link).children) {
s.addEventListener('click', () => {
console.log(`clicked : ${s.dataset.link}`)
})
}
}
} else {
_c.className = ''
}
}
for (let sect of content) {
if (c.dataset.link == sect.id) {
sect.className = 'content visible'
} else if (!c.dataset.link) {
sect.className = 'content'
} else {
sect.className = 'content'
}
}
}) })
c.addEventListener('mouseenter', () => { c.addEventListener('mouseenter', () => {
menuItem.innerHTML = c.dataset.link menuItem.innerHTML = c.dataset.link
menuItem.className = 'active' menuItem.className = 'active'
voice.play() menuVoices[c.dataset.link].noteOn()
}) })
c.addEventListener('mouseout', () => { c.addEventListener('mouseout', () => {
menuItem.className = 'inactive' menuItem.className = 'inactive'
voice.release() menuVoices[c.dataset.link].noteOff()
}) })
menuItem.addEventListener('transitionend', () => { menuItem.addEventListener('transitionend', () => {

65
js/synth.js Normal file
View File

@ -0,0 +1,65 @@
class Synth {
// SYNTH VOICE CONSTRUCTOR
// Variables?
constructor(audio, type, env = {
a: 0.2,
r: 0.5,
}) {
this.audio = audio
this.t = this.audio.currentTime
this.env = {
a: env.a,
r: env.r,
}
// PRIMARY GAIN
this.gain = this.audio.createGain()
this.gain.gain.value = 0
// PRIMARY VOICE
this.primVoice = this.audio.createOscillator()
this.primVoice.type = typeof type === 'string' ? type : 'sine'
this.primVoice.connect(this.gain)
this.primVoice.start()
// MOD GAIN
this.modGain = this.audio.createGain()
this.modGain.gain.value = 0
this.modGain.connect(this.gain)
// MOD VOICE
this.modVoice = this.audio.createOscillator()
this.modVoice.type = 'triangle'
this.modVoice.connect(this.modGain)
this.modVoice.start()
}
// OSC -> ADSR -> GAIN
noteOn(freq) {
// note frequency
this.freq = freq ? freq : (Math.random() * 350) + 50
this.primVoice.frequency.setValueAtTime(this.freq, this.t)
this.modVoice.frequency.setValueAtTime(this.freq - 20, this.t)
// clear preScheduled events
this.gain.gain.cancelScheduledValues(this.audio.currentTime)
// attack
this.gain.gain.setTargetAtTime(0.9, this.t + this.env.a, 0.2)
}
noteOff() {
// release
this.gain.gain.setTargetAtTime(0.0, this.t + this.env.r, 1)
}
mod() {
this.modGain.gain.cancelScheduledValues(this.audio.currentTime)
// attack
this.modGain.gain.setTargetAtTime(0.9, this.audio.currentTime, 0.5)
// release
this.modGain.gain.setTargetAtTime(0.0, this.audio.currentTime + 0.4, 0.5)
}
}

View File

@ -5,7 +5,7 @@
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" type="text/css" href="../css/styles.css"> <link rel="stylesheet" type="text/css" href="../css/master.css">
</head> </head>
<body> <body>

View File

@ -5,7 +5,7 @@
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" type="text/css" href="../css/styles.css"> <link rel="stylesheet" type="text/css" href="../css/master.css">
</head> </head>
<body> <body>

View File

@ -5,7 +5,7 @@
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" type="text/css" href="../css/styles.css"> <link rel="stylesheet" type="text/css" href="../css/master.css">
</head> </head>
<body> <body>

View File

@ -5,7 +5,7 @@
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" type="text/css" href="../css/styles.css"> <link rel="stylesheet" type="text/css" href="../css/master.css">
</head> </head>
<body> <body>

View File

@ -5,7 +5,7 @@
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" type="text/css" href="../css/styles.css"> <link rel="stylesheet" type="text/css" href="../css/master.css">
</head> </head>
<body> <body>

View File

@ -5,7 +5,7 @@
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" type="text/css" href="../css/styles.css"> <link rel="stylesheet" type="text/css" href="../css/master.css">
</head> </head>
<body> <body>