From 4777c058469847cbe02eb2a24634b21ee37384fc Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 7 Jan 2019 23:01:11 +0100 Subject: move docs --- docs/assets/css/css.css | 342 +++++++++++++++++++++++++ docs/assets/fonts/NHaasGroteskTXPro-55Rg.ttf | Bin 0 -> 275008 bytes docs/assets/fonts/NHaasGroteskTXPro-56It.ttf | Bin 0 -> 306228 bytes docs/assets/fonts/NHaasGroteskTXPro-75Bd.ttf | Bin 0 -> 300820 bytes docs/assets/fonts/NHaasGroteskTXPro-76BdIt.ttf | Bin 0 -> 297312 bytes docs/assets/fonts/alarmclock.ttf | Bin 0 -> 21664 bytes docs/assets/fonts/roadrage.ttf | Bin 0 -> 341760 bytes docs/assets/img/dreaming-city.jpg | Bin 0 -> 125438 bytes docs/assets/img/escape-from-neukoelln.jpg | Bin 0 -> 167756 bytes docs/assets/img/pause-button.png | Bin 0 -> 1174 bytes docs/assets/img/pause-inv.png | Bin 0 -> 3208 bytes docs/assets/img/pause.png | Bin 0 -> 1336 bytes docs/assets/img/play-button.png | Bin 0 -> 1336 bytes docs/assets/img/play-fill.png | Bin 0 -> 1801 bytes docs/assets/img/play-inv.png | Bin 0 -> 1993 bytes docs/assets/img/play.png | Bin 0 -> 1978 bytes docs/assets/img/playbutton.psd | Bin 0 -> 50227 bytes docs/assets/img/xena-vectra-logo-sm.png | Bin 0 -> 9139 bytes docs/assets/img/xena-vectra-logo.png | Bin 0 -> 30091 bytes docs/assets/img/xenavectra.gif | Bin 0 -> 41515 bytes docs/assets/js/cielab.js | 70 +++++ docs/assets/js/player.js | 79 ++++++ docs/assets/js/shards.js | 107 ++++++++ docs/assets/js/site.js | 72 ++++++ docs/assets/js/sounds.js | 17 ++ docs/assets/js/stars.js | 63 +++++ docs/assets/js/util.js | 139 ++++++++++ docs/assets/sounds/click.mp3 | Bin 0 -> 2337 bytes docs/assets/sounds/click.wav | Bin 0 -> 142582 bytes docs/css/css.css | 342 ------------------------- docs/fonts/NHaasGroteskTXPro-55Rg.ttf | Bin 275008 -> 0 bytes docs/fonts/NHaasGroteskTXPro-56It.ttf | Bin 306228 -> 0 bytes docs/fonts/NHaasGroteskTXPro-75Bd.ttf | Bin 300820 -> 0 bytes docs/fonts/NHaasGroteskTXPro-76BdIt.ttf | Bin 297312 -> 0 bytes docs/img/dreaming-city.jpg | Bin 125438 -> 0 bytes docs/img/escape-from-neukoelln.jpg | Bin 167756 -> 0 bytes docs/img/pause-button.png | Bin 1174 -> 0 bytes docs/img/pause-inv.png | Bin 3208 -> 0 bytes docs/img/pause.png | Bin 1336 -> 0 bytes docs/img/play-button.png | Bin 1336 -> 0 bytes docs/img/play-fill.png | Bin 1801 -> 0 bytes docs/img/play-inv.png | Bin 1993 -> 0 bytes docs/img/play.png | Bin 1978 -> 0 bytes docs/img/playbutton.psd | Bin 50227 -> 0 bytes docs/img/xena-vectra-logo-sm.png | Bin 9139 -> 0 bytes docs/img/xena-vectra-logo.png | Bin 30091 -> 0 bytes docs/img/xenavectra.gif | Bin 41515 -> 0 bytes docs/index.html | 14 +- docs/js/cielab.js | 70 ----- docs/js/player.js | 79 ------ docs/js/shards.js | 107 -------- docs/js/site.js | 59 ----- docs/js/sounds.js | 17 -- docs/js/stars.js | 63 ----- docs/js/util.js | 139 ---------- docs/sounds/click.mp3 | Bin 2337 -> 0 bytes docs/sounds/click.wav | Bin 142582 -> 0 bytes 57 files changed, 896 insertions(+), 883 deletions(-) create mode 100644 docs/assets/css/css.css create mode 100755 docs/assets/fonts/NHaasGroteskTXPro-55Rg.ttf create mode 100755 docs/assets/fonts/NHaasGroteskTXPro-56It.ttf create mode 100755 docs/assets/fonts/NHaasGroteskTXPro-75Bd.ttf create mode 100755 docs/assets/fonts/NHaasGroteskTXPro-76BdIt.ttf create mode 100755 docs/assets/fonts/alarmclock.ttf create mode 100755 docs/assets/fonts/roadrage.ttf create mode 100644 docs/assets/img/dreaming-city.jpg create mode 100644 docs/assets/img/escape-from-neukoelln.jpg create mode 100644 docs/assets/img/pause-button.png create mode 100644 docs/assets/img/pause-inv.png create mode 100644 docs/assets/img/pause.png create mode 100644 docs/assets/img/play-button.png create mode 100644 docs/assets/img/play-fill.png create mode 100644 docs/assets/img/play-inv.png create mode 100644 docs/assets/img/play.png create mode 100644 docs/assets/img/playbutton.psd create mode 100644 docs/assets/img/xena-vectra-logo-sm.png create mode 100644 docs/assets/img/xena-vectra-logo.png create mode 100644 docs/assets/img/xenavectra.gif create mode 100644 docs/assets/js/cielab.js create mode 100644 docs/assets/js/player.js create mode 100644 docs/assets/js/shards.js create mode 100644 docs/assets/js/site.js create mode 100644 docs/assets/js/sounds.js create mode 100644 docs/assets/js/stars.js create mode 100644 docs/assets/js/util.js create mode 100644 docs/assets/sounds/click.mp3 create mode 100644 docs/assets/sounds/click.wav delete mode 100644 docs/css/css.css delete mode 100755 docs/fonts/NHaasGroteskTXPro-55Rg.ttf delete mode 100755 docs/fonts/NHaasGroteskTXPro-56It.ttf delete mode 100755 docs/fonts/NHaasGroteskTXPro-75Bd.ttf delete mode 100755 docs/fonts/NHaasGroteskTXPro-76BdIt.ttf delete mode 100644 docs/img/dreaming-city.jpg delete mode 100644 docs/img/escape-from-neukoelln.jpg delete mode 100644 docs/img/pause-button.png delete mode 100644 docs/img/pause-inv.png delete mode 100644 docs/img/pause.png delete mode 100644 docs/img/play-button.png delete mode 100644 docs/img/play-fill.png delete mode 100644 docs/img/play-inv.png delete mode 100644 docs/img/play.png delete mode 100644 docs/img/playbutton.psd delete mode 100644 docs/img/xena-vectra-logo-sm.png delete mode 100644 docs/img/xena-vectra-logo.png delete mode 100644 docs/img/xenavectra.gif delete mode 100644 docs/js/cielab.js delete mode 100644 docs/js/player.js delete mode 100644 docs/js/shards.js delete mode 100644 docs/js/site.js delete mode 100644 docs/js/sounds.js delete mode 100644 docs/js/stars.js delete mode 100644 docs/js/util.js delete mode 100644 docs/sounds/click.mp3 delete mode 100644 docs/sounds/click.wav diff --git a/docs/assets/css/css.css b/docs/assets/css/css.css new file mode 100644 index 0000000..6271eb3 --- /dev/null +++ b/docs/assets/css/css.css @@ -0,0 +1,342 @@ +@font-face { + font-family: nhg; + src: url(../fonts/NHaasGroteskTXPro-55Rg.ttf); + font-weight: normal; + font-style: normal; +} +@font-face { + font-family: nhg; + src: url(../fonts/NHaasGroteskTXPro-56It.ttf); + font-weight: normal; + font-style: italic; +} +@font-face { + font-family: nhg; + src: url(../fonts/NHaasGroteskTXPro-75Bd.ttf); + font-weight: bold; + font-style: normal; +} +@font-face { + font-family: nhg; + src: url(../fonts/NHaasGroteskTXPro-76BdIt.ttf); + font-weight: bold; + font-style: italic; +} +.desktop .m, +.mobile .d { display: none; } +html, body { + margin: 0; padding: 0; width: 100%; height: 100%; + font-family: nhg, sans-serif; + color: rgba(255,255,255,0.9); +} +html { + background-color: rgb(0,0,0); + background-image: linear-gradient(rgba(20, 10, 0, 0.0), rgba(20, 10, 0, 1.0)); + background-attachment: fixed; + transition: background-color 1s; +} +html.day { + background-color: rgb(80,10,60); +} +html.night { + background-color: rgb(8,10,30); +} +body { + background-color: rgba(0,0,0,0); + transition: background-color 1000ms, opacity 500ms; + opacity: 1; +} +body.loading { + background-color: rgba(255,128,192,1); + background-color: black; + opacity: 0; +} +body.fade { + opacity: 1; + background-color: black; + background-color: rgba(255,128,192,1); +} +.shards { + position: absolute; + top: 0; left: 0; + width: 100%; height: 100%; + overflow: hidden; + pointer-events: none; +} +.bgs { + position: absolute; + top: 50%; left: 50%; + opacity: 0.7; + transition: opacity 500ms; + perspective: 10000px; +} +.stars { + transition: all 500ms cubic-bezier(0,0,0,1); + transform: translateZ(0) scaleX(1) scaleY(1); +} +.stars.fade { + transform: translateZ(0) scaleX(1.03) scaleY(1.03); +} +.fade { + opacity: 0; +} +.bg { + position: absolute; + top: 0; left: 0; + transition: all 120s; +} +header { + background-color: rgba(40,20,30,0.9); + position: absolute; + width: 100%; + bottom: 100px; + left: 0; +} +p { + margin: 0; padding: 0; + line-height: 1.4; +} +p + p { + margin-top: 14px;ß +} +a { + text-decoration: none; + color: rgba(255,255,255,0.8); + transition: color 200ms; + border-bottom: 1px dotted; +} +.desktop a:hover { + color: rgba(255,255,255,1.0); +} +img { + max-width: 100%; +} +img.cover { + max-width: 300px; +} +.menu a { + margin-right: 10px; + border-bottom: 0; +} +.menu a.active { + border-bottom: 1px dotted; + color: rgba(255,255,255,1.0); +} +.logo { + width: 400px; + opacity: 0.8; + animation: fade 10s infinite; +} +.row { + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; +} +h1 { + font-size: 32px; + margin: 0; + padding: 10px 20px; + letter-spacing: -2px; + text-transform: uppercase; + cursor: pointer; + opacity: 0.9; + transition: opacity 500ms; + color: white; +} +.desktop h1:hover { + opacity: 1; +} +h2 { + margin: 0; + padding: 0 0 15px 0; + letter-spacing: -1px; +} +h3 { + margin: 0; + padding: 0 0 6px 0; + letter-spacing: 1px; + font-weight: normal; + font-style: italic; + font-size: 14px; + text-transform: uppercase; + opacity: 0.7; +} +ul { + margin: 0 0 20px 0; + padding: 0; + list-style-type: none; +} +ul li { + list-style-type: none; + line-height: 1.4; +} +ol { + margin: 0 0 20px 0; + padding: 0; +} +ol li { + line-height: 1.4; +} +.player { + padding: 12px 20px; + width: 300px; + display: flex; + flex-direction: row; + justify-content: flex-start; + align-items: center; + cursor: pointer; + border-left: 1px solid #000; +} +.player .icon { + width: 1.2em; + height: 1.2em; + background-image: url(../img/pause-inv.png); + background-size: 100%; + background-position: center; + border: 2px solid rgba(255,255,255,0.3); + border-radius: 100%; + margin: 0 10px 0 10px; +} +.player.playing .icon { + background-image: url(../img/pause-inv.png); +} +.player.paused .icon { + background-image: url(../img/play-inv.png); +} +.player .track { + transition: all 100ms; + flex: auto; +} +.desktop .player:hover .track { + color: rgba(255,255,255,1.0); +} +.playlist { + -webkit-overflow-scrolling: touch; + overflow-y: auto; + max-height: calc(100vh - 140px); + width: 331px; + max-width: calc(100vw - 30px); + background: black; + position: absolute; + bottom: 160px; right: 0; + margin: 0px 10px; + padding: 0px; + height: 0; overflow: hidden; + transition: all 0.5s cubic-bezier(0,1,1,1); +} +.playlist.visible { + height: 180px; +} +.playlist ul { + margin: 0; padding: 0; +} +.playlist li { + margin: 0; padding: 10px; + cursor: pointer; + transition: all 0.2s; + background: rgba(20,5,10,0.5); +} +.playlist li.active { + color: #000; + background: rgba(255,255,255,0.9); +} +.playlistToggle { + align-self: flex-end; + width: 15px; + height: 15px; + padding: 10px; + display: flex; + flex-direction: column; + justify-content:space-between; +} +.playlistToggle div { + width: 100%; + height: 2px; + border-bottom: 1px solid #999; + background: white; +} +section { + -webkit-overflow-scrolling: touch; + overflow-y: auto; + max-height: calc(100vh - 140px); + max-width: 500px; + background: black; + position: absolute; + bottom: 160px; left: 0; + margin: 10px 10px; + padding: 10px; + background: rgba(20,5,10,0.5); + pointer-events: none; + opacity: 0; + transition: opacity 200ms; +} +.bio #bio, +.discography #discography, +.hardware #hardware, +.contact #contact { + opacity: 1; + pointer-events: auto; +} +@keyframes fade { + 0% { opacity: 0.6; } + 50% { opacity: 1.0; } + 90% { opacity: 0.7; } +100% { opacity: 0.6; } +} + +@media (max-width: 700px) { + * { box-sizing: border-box; } + header { + bottom: auto; + top: 0px; + } + header .row { + flex-direction: column; + } + header .row .menu { + flex-direction: row; + flex-wrap: wrap; + } + h1 { + flex: 1 1 100%; + text-align: center; + } + .menu a { + display: block; + text-align: center; + margin-left: 6px; + margin-right: 6px; + padding-bottom: 10px; + } + .menu a.active { + border: 0; + } + .playlist { + width: 100vw; + margin: 0; + bottom: 59px; + } + section { + height: calc(100vh - 150px); + width: 100%; + max-width: auto; + min-width: auto; + max-height: auto; + padding-bottom: 20px; + bottom: auto; + top: 90px; + margin: 0; + } + .player { + position: fixed; + bottom: 0; + background: rgba(80,10,60,0.6); + width: 100vw; + padding: 12px 20px; + } + .playlistToggle { + width: 36px; + height: 36px; + } +} \ No newline at end of file diff --git a/docs/assets/fonts/NHaasGroteskTXPro-55Rg.ttf b/docs/assets/fonts/NHaasGroteskTXPro-55Rg.ttf new file mode 100755 index 0000000..e5ad72b Binary files /dev/null and b/docs/assets/fonts/NHaasGroteskTXPro-55Rg.ttf differ diff --git a/docs/assets/fonts/NHaasGroteskTXPro-56It.ttf b/docs/assets/fonts/NHaasGroteskTXPro-56It.ttf new file mode 100755 index 0000000..8aa3443 Binary files /dev/null and b/docs/assets/fonts/NHaasGroteskTXPro-56It.ttf differ diff --git a/docs/assets/fonts/NHaasGroteskTXPro-75Bd.ttf b/docs/assets/fonts/NHaasGroteskTXPro-75Bd.ttf new file mode 100755 index 0000000..d80c0ee Binary files /dev/null and b/docs/assets/fonts/NHaasGroteskTXPro-75Bd.ttf differ diff --git a/docs/assets/fonts/NHaasGroteskTXPro-76BdIt.ttf b/docs/assets/fonts/NHaasGroteskTXPro-76BdIt.ttf new file mode 100755 index 0000000..81dfad5 Binary files /dev/null and b/docs/assets/fonts/NHaasGroteskTXPro-76BdIt.ttf differ diff --git a/docs/assets/fonts/alarmclock.ttf b/docs/assets/fonts/alarmclock.ttf new file mode 100755 index 0000000..9e9b593 Binary files /dev/null and b/docs/assets/fonts/alarmclock.ttf differ diff --git a/docs/assets/fonts/roadrage.ttf b/docs/assets/fonts/roadrage.ttf new file mode 100755 index 0000000..a7699af Binary files /dev/null and b/docs/assets/fonts/roadrage.ttf differ diff --git a/docs/assets/img/dreaming-city.jpg b/docs/assets/img/dreaming-city.jpg new file mode 100644 index 0000000..211a0a9 Binary files /dev/null and b/docs/assets/img/dreaming-city.jpg differ diff --git a/docs/assets/img/escape-from-neukoelln.jpg b/docs/assets/img/escape-from-neukoelln.jpg new file mode 100644 index 0000000..dcd1180 Binary files /dev/null and b/docs/assets/img/escape-from-neukoelln.jpg differ diff --git a/docs/assets/img/pause-button.png b/docs/assets/img/pause-button.png new file mode 100644 index 0000000..6ab7818 Binary files /dev/null and b/docs/assets/img/pause-button.png differ diff --git a/docs/assets/img/pause-inv.png b/docs/assets/img/pause-inv.png new file mode 100644 index 0000000..9780255 Binary files /dev/null and b/docs/assets/img/pause-inv.png differ diff --git a/docs/assets/img/pause.png b/docs/assets/img/pause.png new file mode 100644 index 0000000..c2d30ae Binary files /dev/null and b/docs/assets/img/pause.png differ diff --git a/docs/assets/img/play-button.png b/docs/assets/img/play-button.png new file mode 100644 index 0000000..c0fd3fc Binary files /dev/null and b/docs/assets/img/play-button.png differ diff --git a/docs/assets/img/play-fill.png b/docs/assets/img/play-fill.png new file mode 100644 index 0000000..2205696 Binary files /dev/null and b/docs/assets/img/play-fill.png differ diff --git a/docs/assets/img/play-inv.png b/docs/assets/img/play-inv.png new file mode 100644 index 0000000..4baaa5f Binary files /dev/null and b/docs/assets/img/play-inv.png differ diff --git a/docs/assets/img/play.png b/docs/assets/img/play.png new file mode 100644 index 0000000..b5b4a08 Binary files /dev/null and b/docs/assets/img/play.png differ diff --git a/docs/assets/img/playbutton.psd b/docs/assets/img/playbutton.psd new file mode 100644 index 0000000..e2dbed4 Binary files /dev/null and b/docs/assets/img/playbutton.psd differ diff --git a/docs/assets/img/xena-vectra-logo-sm.png b/docs/assets/img/xena-vectra-logo-sm.png new file mode 100644 index 0000000..b42111b Binary files /dev/null and b/docs/assets/img/xena-vectra-logo-sm.png differ diff --git a/docs/assets/img/xena-vectra-logo.png b/docs/assets/img/xena-vectra-logo.png new file mode 100644 index 0000000..4b3f810 Binary files /dev/null and b/docs/assets/img/xena-vectra-logo.png differ diff --git a/docs/assets/img/xenavectra.gif b/docs/assets/img/xenavectra.gif new file mode 100644 index 0000000..fb81d57 Binary files /dev/null and b/docs/assets/img/xenavectra.gif differ diff --git a/docs/assets/js/cielab.js b/docs/assets/js/cielab.js new file mode 100644 index 0000000..14c096f --- /dev/null +++ b/docs/assets/js/cielab.js @@ -0,0 +1,70 @@ +var cielab = (function(){ + var cielab = {} + + var xyz = [0,0,0] + var rgb = [0,0,0] + + L_range = [0, 100] + a_range = [-86.185, 98.254] + b_range = [-107.863, 94.482] + + cielab.gradient = function (n) { + n = n || 100 + var k = 0 + + var L, a, b + + var L0 = randrange(L_range[0] + 50, L_range[1]) + var L1 = randrange(L_range[0]+ 50, L_range[1]) + var a0 = randrange(a_range[0], a_range[1]) + var a1 = randrange(a_range[0], a_range[1]) + var b0 = randrange(b_range[0], b_range[1]) + var b1 = randrange(b_range[0], b_range[1]) + return function next (aa){ + L = mix(k/n, L0, L1) + a = mix(k/n, a0, a1) + b = mix(k/n, b0, b1) + rgb = xyz2rgb(hunterlab2xyz(L, a, b)) + k += 1 + return rgba_string(rgb, aa) + } + } + function rgba_string (rgb, a) { return "rgba(" + rgb.map(Math.round).join(",") + "," + a + ")" } + function hex_string (rgb) { return "#" + rgb.map(Math.round).map(function(n){ var s = n.toString(16); return s.length == 1 ? "0"+s : s }).join("") } + + function mix(n,a,b){ return n*a + (1-n)*b } + function clamp(n,a,b){ return n 0.0031308 ) var_R = 1.055 * Math.pow( var_R, 1 / 2.4 ) - 0.055 + else var_R = 12.92 * var_R + if ( var_G > 0.0031308 ) var_G = 1.055 * Math.pow( var_G, 1 / 2.4 ) - 0.055 + else var_G = 12.92 * var_G + if ( var_B > 0.0031308 ) var_B = 1.055 * Math.pow( var_B, 1 / 2.4 ) - 0.055 + else var_B = 12.92 * var_B + + rgb[0] = clamp(var_R * 255, 0, 255) + rgb[1] = clamp(var_G * 255, 0, 255) + rgb[2] = clamp(var_B * 255, 0, 255) + return rgb + } + + return cielab +})() \ No newline at end of file diff --git a/docs/assets/js/player.js b/docs/assets/js/player.js new file mode 100644 index 0000000..25fdfd6 --- /dev/null +++ b/docs/assets/js/player.js @@ -0,0 +1,79 @@ +const player = (function(){ + let player = {} + let current_index = -1 + let audio = document.createElement('audio') + let tracks = [ + { file: "mp3/xena_vectra-cruise.mp3", title: "Cruise" }, + { file: "mp3/xena_vectra-dreaming_city_2.mp3", title: "Dreaming City 2" }, + { file: "mp3/xena_vectra-escape_from_nk.mp3", title: "Escape from Neukölln" }, + ] + function init(){ + bind() + build() + // play(0) + } + function bind(){ + audio.addEventListener('play', handlePlay) + audio.addEventListener('pause', handlePause) + audio.addEventListener('ended', handleEnded) + document.querySelector('.player .icon').addEventListener('click', togglePlaying) + document.querySelector('.player .track').addEventListener('click', play) + document.querySelector('.player .playlistToggle').addEventListener('click', togglePlaylist) + } + function build() { + tracks.forEach((track, i) => { + let el = document.createElement('li') + el.innerHTML = track.title + el.addEventListener('click', () => { + if (is_mobile) { + hidePlaylist() + } + shards.rebuild() + play(i) + }) + document.querySelector('.playlist ul').appendChild(el) + }) + document.querySelector('.player .track').innerHTML = tracks[0].title + } + function play(n){ + const active = document.querySelector('.playlist ul .active') + if (active) active.classList.remove('active') + document.querySelector('.playlist ul').children[n].classList.add('active') + + current_index = (n + tracks.length) % tracks.length + audio.src = tracks[n].file + audio.play() + document.querySelector('.player .track').innerHTML = tracks[n].title + } + function handlePlay(){ + document.querySelector('.player').classList.add('playing') + document.querySelector('.player').classList.remove('paused') + shards.step() + } + function handlePause(){ + document.querySelector('.player').classList.remove('playing') + document.querySelector('.player').classList.add('paused') + } + function handleEnded(){ + shards.rebuild() + play(current_index+1) + } + function togglePlaying() { + // sounds.play('click') + if (current_index == -1) { + play(0) + } else { + if (audio.paused) audio.play() + else audio.pause() + } + } + function togglePlaylist() { + site.navigateHash('') + document.querySelector('.playlist').classList.toggle('visible') + } + function hidePlaylist() { + document.querySelector('.playlist').classList.remove('visible') + } + init() + return { hidePlaylist } +})() \ No newline at end of file diff --git a/docs/assets/js/shards.js b/docs/assets/js/shards.js new file mode 100644 index 0000000..1b374ee --- /dev/null +++ b/docs/assets/js/shards.js @@ -0,0 +1,107 @@ +const shards = (function(){ + let count + let delay = 120 * 1000 + let els = [] + let t = 0 + let rebuilding = false + let nextTimeout + let dark, light + const bg_el = document.querySelector('.bgs') + + function init(){ + bind() + build() + step() + setTimeout(next, 20) + bg_el.classList.remove('fade') + } + function bind(){ + document.querySelector('h1').addEventListener('click', () => { + sounds.play('click') + rebuild() + site.navigateHash('') + player.hidePlaylist() + }) + } + function build(){ + count = choice(is_mobile ? [5,7] : [5,7,7,11,11]) + light = cielab.gradient(count) + dark = cielab.gradient(count) + let el + for (var i = 0; i < count; i++) { + el = append(i) + } + } + function destroy(){ + for (var i = 0; i < count; i++) { + els[i] && bg_el.removeChild(els[i]) + } + els.length = 0 + } + function rebuild(){ + if (rebuilding) return + rebuilding = true + // sounds.play('click') + stars.rebuild() + next() + t = 0 + bg_el.classList.add('fade') + setTimeout(() => { + destroy() + build() + step() + setTimeout(next, 20) + bg_el.classList.remove('fade') + rebuilding = false + // sounds.play('click') + }, 500) + } + function append(i){ + const el = document.createElement('div') + el.classList.add('bg') + els.push(el) + bg_el.appendChild(el) + return el + } + function next(){ + clearTimeout(nextTimeout) + nextTimeout = setTimeout(next, delay) + step() + } + function step() { + t += 1 + light = cielab.gradient(count) + let w = { min: is_mobile ? randrange(40, 90) : randrange(20, 40), max: randrange(10, 90) } + if (w.min > w.max) { + w.min += 10 + } + let rot = { min: randint(360), max: randrange(720, 1080) } + for (var i = 0; i < count; i++) { + update(i, t, w, rot, dark, light) + } + document.body.style.backgroundColor = cielab.gradient(2)(0.05) + } + function update(i, t, w, rot){ + const el = els[i] + const n = i / count + const side = lerp(n, w.min, w.max) + const spin = lerp(i % 2 ? (1-n) : (n), rot.min, rot.max) + const rotation = "rotate3d(" + [randrange(-1,1), randrange(-1,1), randrange(-1,1)].join(',') + ',' + randint(360) + "deg)" + el.style.width = side + 'vmin' + el.style.height = side + 'vmin' + el.style.transform = "translate3d(-50%, -50%, 0) rotate(" + spin + "deg) translate3d(50%, 50%, 0) " + rotation + // el.style.transform = "translate3d(-50%, -50%, 0)" + if (t === 1) { + light = cielab.gradient(count) + if (is_mobile) { + el.style.backgroundImage = 'linear-gradient(0deg, ' + dark(1) + ', ' + light(1) + ')' + } else { + el.style.backgroundImage = 'linear-gradient(0deg, ' + dark(1) + ', ' + light(0) + ')' + } + } + el.style.backgroundColor = light(1) + el.style.opacity = lerp(n, randrange(0.1, 0.4), randrange(0.2, 0.5)) + } + init() + return { rebuild: rebuild, step: step, } +})() \ No newline at end of file diff --git a/docs/assets/js/site.js b/docs/assets/js/site.js new file mode 100644 index 0000000..bff06bb --- /dev/null +++ b/docs/assets/js/site.js @@ -0,0 +1,72 @@ +const site = (function(){ + let section + let links = toArray(document.querySelectorAll('.menu a')) + let time = new Date() + let hour = time.getHours() + let quotes = [ + "So, are softsynths as nasty as they say?", + "Ah, a hardware person, I get it.", + "You have to make space to leave space.", + "Those waveforms are more powerful than we realize.", + "And that sub-oscillator? W-O-W!", + "Get in there, sweep the filter and give yourself a pat on the back. In that order.", + "Not a museum. Move along.", + "I've got to get out of this studio and back out there.", + ] + if (hour < 8 || hour > 16) { + document.body.parentNode.classList.add('night') + } else { + document.body.parentNode.classList.add('day') + } + preload('img/pause-inv.png') + setTimeout(() => { + document.body.classList.remove('loading') + navigateHash(window.location.hash) + const email = atob("eGVuYXZlY3RyYTkwOUBnbWFpbC5jb20=") + const twitter = atob("dmVjdHJheGVuYQ==") + document.querySelector("#email_addr").href = 'mailto:' + email + document.querySelector("#email_addr").innerHTML = email + document.querySelector("#twitter_addr").innerHTML = twitter + document.querySelector("#twitter_addr").href = 'https://twitter.com/' + twitter + }, 0) + toArray(document.querySelectorAll('.menu a')).forEach(a => { + a.addEventListener("click", e => { + e.preventDefault() + sounds.play('click') + console.log(e.target) + if (e.target.nodeName.toLowerCase() !== 'a') { + navigateHash(e.target.parentNode.href) + } else { + navigateHash(e.target.href) + } + }) + }) + function navigateHash(url){ + if (is_mobile) { + player.hidePlaylist() + } + let new_section = (url || "").split('#')[1] + if (section) { + document.body.classList.remove(section) + links.forEach(link => link.classList.remove('active')) + } + if (new_section && new_section !== section) { + if (new_section.match('hardware')) { + document.querySelector('#quote').innerHTML = choice(quotes) + } + document.body.classList.add(new_section) + links.forEach(link => link.getAttribute('href').match(new_section) && link.classList.add('active')) + section = new_section + } else { + section = null + } + // window.location.hash = section || "" + } + function preload(src) { + const img = new Image + img.src = src + } + return { + navigateHash: navigateHash + } +})() diff --git a/docs/assets/js/sounds.js b/docs/assets/js/sounds.js new file mode 100644 index 0000000..39f725d --- /dev/null +++ b/docs/assets/js/sounds.js @@ -0,0 +1,17 @@ +const sounds = (function(){ + let sounds = {} + let els = {} + sounds.add = (fn) => { + const el = document.createElement('audio') + el.src = 'sounds/' + fn + '.mp3' + els[fn] = el + } + sounds.play = (fn) => { + const el = els[fn] + el.currentTime = 0 + el.volume = 0.8 + el.play() + } + sounds.add('click') + return sounds +})() diff --git a/docs/assets/js/stars.js b/docs/assets/js/stars.js new file mode 100644 index 0000000..0637473 --- /dev/null +++ b/docs/assets/js/stars.js @@ -0,0 +1,63 @@ +const stars = (function(){ + var canvas = document.createElement("canvas"), ctx = canvas.getContext('2d') + var s = Math.sin, c = Math.cos + document.addEventListener("DOMContentLoaded", function(){ + document.body.appendChild(canvas) + canvas.classList.add('stars') + canvas.style.width="100%" + canvas.style.height="100%" + canvas.style.position="fixed" + canvas.style.top="0px" + canvas.style.left="0px" + canvas.style.zIndex=-1 + document.body.addEventListener("resize", build) + // document.body.parentNode.style.backgroundColor="black" + ctx.strokeStyle="white" + build() + }) + function ri(n){ return Math.random() * n } + function rr(a,b){ return (b-a) * Math.random() + a } + function build(){ + var w = canvas.width = window.innerWidth * window.devicePixelRatio + var h = canvas.height = window.innerHeight * window.devicePixelRatio + ctx.clearRect(0,0,w,h) + var n = Math.sqrt(w*h)|0 + while (n--) { + var x = ri(w) + var y = ri(h) + var r0 = rr(0, 1) + var r1 = rr(0, 1) + var r2 = rr(0, 1) + var t0 = ri(2*Math.PI) + var t1 = ri(2*Math.PI) + var t2 = ri(2*Math.PI) + var x0 = x+c(t0)*r0 + var y0 = y+s(t0)*r0 + var x1 = x+c(t1)*r1 + var y1 = y+s(t1)*r1 + var x2 = x+c(t2)*r2 + var y2 = y+s(t2)*r2 + ctx.beginPath() + ctx.moveTo(x,y) + ctx.bezierCurveTo(x0,y0,x1,y1,x2,y2) + var color = rr(0, 255)|0 + ctx.strokeStyle="rgb("+color+","+color+","+color+")" + ctx.stroke() + } + } + let rebuilding = false + function rebuild(){ + if (rebuilding) return + rebuilding = true + canvas.classList.add('fade') + document.body.classList.add('fade') + setTimeout(() => { + // destroy() + build() + canvas.classList.remove('fade') + document.body.classList.remove('fade') + rebuilding = false + }, 500) + } + return { rebuild: rebuild } +})() \ No newline at end of file diff --git a/docs/assets/js/util.js b/docs/assets/js/util.js new file mode 100644 index 0000000..e40db4a --- /dev/null +++ b/docs/assets/js/util.js @@ -0,0 +1,139 @@ +const is_iphone = (navigator.userAgent.match(/iPhone/i)) || (navigator.userAgent.match(/iPod/i)) +const is_ipad = (navigator.userAgent.match(/iPad/i)) +const is_android = (navigator.userAgent.match(/Android/i)) +const is_mobile = is_iphone || is_ipad || is_android +const is_desktop = !is_mobile; +document.body.parentNode.classList.add(is_desktop ? 'desktop' : 'mobile') + +function avg(a,b,n){ return (a*(n-1) + b)/n } +function rand(n){ return Math.random()*n } +function randint(n) { return ~~(Math.random()*n) } +function randrange(a,b){ return a+rand(b-a) } +function choice(a) { return a[randint(a.length)] } +function clamp(n,a,b) { return a > n ? a : n > b ? b : n } +function sign(n){ return n < 0 ? -1 : 1 } +function mod(n,m){ return n-(m * Math.floor(n/m)) } +function lerp(n,a,b){ return (b-a)*n+a } +function quantize(m,n){ return n * ((m/n)|0) } + +function randgauss (obj, jog) { + var radius = Math.random() * jog + var angle = Math.random() * Math.PI * 2 + obj.left += Math.sin(angle) * radius + obj.top += Math.cos(angle) * radius +} + +function shuffle(a){ + for (var i = a.length; i > 0; i--){ + var r = randint(i) + var swap = a[i-1] + a[i-1] = a[r] + a[r] = swap + } + return a +} + +function toArray (els){ + return Array.prototype.slice.apply(els) +} + +// easing functions +function circular (t) { return Math.sqrt( 1 - ( --t * t ) ) } +function quadratic (t) { return t * ( 2 - t ) } +function back (t) { + var b = 4; + return ( t = t - 1 ) * t * ( ( b + 1 ) * t + b ) + 1; +} +function bounce (t) { + if (t >= 1) return 1; + if ( ( t /= 1 ) < ( 1 / 2.75 ) ) { + return 7.5625 * t * t; + } else if ( t < ( 2 / 2.75 ) ) { + return 7.5625 * ( t -= ( 1.5 / 2.75 ) ) * t + 0.75; + } else if ( t < ( 2.5 / 2.75 ) ) { + return 7.5625 * ( t -= ( 2.25 / 2.75 ) ) * t + 0.9375; + } else { + return 7.5625 * ( t -= ( 2.625 / 2.75 ) ) * t + 0.984375; + } +} +function elastic (t) { + var f = 0.22, + e = 0.4; + + if ( t === 0 ) { return 0; } + if ( t == 1 ) { return 1; } + + return ( e * Math.pow( 2, - 10 * t ) * Math.sin( ( t - f / 4 ) * ( 2 * Math.PI ) / f ) + 1 ); +} + +function preload (url) { + var img = new Image () + var loaded = false, _cb + img.onload = function(){ + if (loaded) return + loaded = true + if (_cb) { _cb(img) } + } + img.src = url + if (img.complete) { img.onload() } + return { + then: function(cb){ + if (loaded) { cb(img) } + else { _cb = cb } + } + } +} + +function preloadImages () { + var images = toArray(document.getElementById("images").children) + var count = 0, ready = false, _cb + images.forEach(function(img){ + var loaded = false + img.onload = function(){ + if (loaded) return + loaded = true + done(img) + } + if (img.complete) { img.onload() } + }) + function done () { + if (++count == images.length && ! ready) { + ready = true + _cb && _cb() + } + } + return { + then: function(cb){ + if (ready) { cb() } + else { _cb = cb } + } + } +} + +function smoothstep(min,max,n){ + var t = clamp((n - min) / (max - min), 0.0, 1.0); + return t * t * (3.0 - 2.0 * t) +} + +function detrand (x,y) { + return (Math.sin( x * 12.9898 + y * 78.233 ) * 43758.5453) % 1 +} + +function gray_to_transparency(img) { + var canvas = document.createElement("canvas") + var ctx = canvas.getContext('2d') + var nw = img.naturalWidth, nh = img.naturalHeight + canvas.width = nw + canvas.height = nh + ctx.drawImage(img,0,0) + var pixels = ctx.getImageData(0,0,nw,nh) + var data = pixels.data + for (var i = 0, len = nw*nh*4; i < len; i += 4) { + data[i+3] = data[i] + data[i] = data[i+1] = data[i+2] = 255 + } + ctx.putImageData(pixels,0,0) + return canvas +} + +var TWO_PI = 2*Math.PI \ No newline at end of file diff --git a/docs/assets/sounds/click.mp3 b/docs/assets/sounds/click.mp3 new file mode 100644 index 0000000..37e7df0 Binary files /dev/null and b/docs/assets/sounds/click.mp3 differ diff --git a/docs/assets/sounds/click.wav b/docs/assets/sounds/click.wav new file mode 100644 index 0000000..7c45aed Binary files /dev/null and b/docs/assets/sounds/click.wav differ diff --git a/docs/css/css.css b/docs/css/css.css deleted file mode 100644 index 6271eb3..0000000 --- a/docs/css/css.css +++ /dev/null @@ -1,342 +0,0 @@ -@font-face { - font-family: nhg; - src: url(../fonts/NHaasGroteskTXPro-55Rg.ttf); - font-weight: normal; - font-style: normal; -} -@font-face { - font-family: nhg; - src: url(../fonts/NHaasGroteskTXPro-56It.ttf); - font-weight: normal; - font-style: italic; -} -@font-face { - font-family: nhg; - src: url(../fonts/NHaasGroteskTXPro-75Bd.ttf); - font-weight: bold; - font-style: normal; -} -@font-face { - font-family: nhg; - src: url(../fonts/NHaasGroteskTXPro-76BdIt.ttf); - font-weight: bold; - font-style: italic; -} -.desktop .m, -.mobile .d { display: none; } -html, body { - margin: 0; padding: 0; width: 100%; height: 100%; - font-family: nhg, sans-serif; - color: rgba(255,255,255,0.9); -} -html { - background-color: rgb(0,0,0); - background-image: linear-gradient(rgba(20, 10, 0, 0.0), rgba(20, 10, 0, 1.0)); - background-attachment: fixed; - transition: background-color 1s; -} -html.day { - background-color: rgb(80,10,60); -} -html.night { - background-color: rgb(8,10,30); -} -body { - background-color: rgba(0,0,0,0); - transition: background-color 1000ms, opacity 500ms; - opacity: 1; -} -body.loading { - background-color: rgba(255,128,192,1); - background-color: black; - opacity: 0; -} -body.fade { - opacity: 1; - background-color: black; - background-color: rgba(255,128,192,1); -} -.shards { - position: absolute; - top: 0; left: 0; - width: 100%; height: 100%; - overflow: hidden; - pointer-events: none; -} -.bgs { - position: absolute; - top: 50%; left: 50%; - opacity: 0.7; - transition: opacity 500ms; - perspective: 10000px; -} -.stars { - transition: all 500ms cubic-bezier(0,0,0,1); - transform: translateZ(0) scaleX(1) scaleY(1); -} -.stars.fade { - transform: translateZ(0) scaleX(1.03) scaleY(1.03); -} -.fade { - opacity: 0; -} -.bg { - position: absolute; - top: 0; left: 0; - transition: all 120s; -} -header { - background-color: rgba(40,20,30,0.9); - position: absolute; - width: 100%; - bottom: 100px; - left: 0; -} -p { - margin: 0; padding: 0; - line-height: 1.4; -} -p + p { - margin-top: 14px;ß -} -a { - text-decoration: none; - color: rgba(255,255,255,0.8); - transition: color 200ms; - border-bottom: 1px dotted; -} -.desktop a:hover { - color: rgba(255,255,255,1.0); -} -img { - max-width: 100%; -} -img.cover { - max-width: 300px; -} -.menu a { - margin-right: 10px; - border-bottom: 0; -} -.menu a.active { - border-bottom: 1px dotted; - color: rgba(255,255,255,1.0); -} -.logo { - width: 400px; - opacity: 0.8; - animation: fade 10s infinite; -} -.row { - display: flex; - flex-direction: row; - align-items: center; - justify-content: space-between; -} -h1 { - font-size: 32px; - margin: 0; - padding: 10px 20px; - letter-spacing: -2px; - text-transform: uppercase; - cursor: pointer; - opacity: 0.9; - transition: opacity 500ms; - color: white; -} -.desktop h1:hover { - opacity: 1; -} -h2 { - margin: 0; - padding: 0 0 15px 0; - letter-spacing: -1px; -} -h3 { - margin: 0; - padding: 0 0 6px 0; - letter-spacing: 1px; - font-weight: normal; - font-style: italic; - font-size: 14px; - text-transform: uppercase; - opacity: 0.7; -} -ul { - margin: 0 0 20px 0; - padding: 0; - list-style-type: none; -} -ul li { - list-style-type: none; - line-height: 1.4; -} -ol { - margin: 0 0 20px 0; - padding: 0; -} -ol li { - line-height: 1.4; -} -.player { - padding: 12px 20px; - width: 300px; - display: flex; - flex-direction: row; - justify-content: flex-start; - align-items: center; - cursor: pointer; - border-left: 1px solid #000; -} -.player .icon { - width: 1.2em; - height: 1.2em; - background-image: url(../img/pause-inv.png); - background-size: 100%; - background-position: center; - border: 2px solid rgba(255,255,255,0.3); - border-radius: 100%; - margin: 0 10px 0 10px; -} -.player.playing .icon { - background-image: url(../img/pause-inv.png); -} -.player.paused .icon { - background-image: url(../img/play-inv.png); -} -.player .track { - transition: all 100ms; - flex: auto; -} -.desktop .player:hover .track { - color: rgba(255,255,255,1.0); -} -.playlist { - -webkit-overflow-scrolling: touch; - overflow-y: auto; - max-height: calc(100vh - 140px); - width: 331px; - max-width: calc(100vw - 30px); - background: black; - position: absolute; - bottom: 160px; right: 0; - margin: 0px 10px; - padding: 0px; - height: 0; overflow: hidden; - transition: all 0.5s cubic-bezier(0,1,1,1); -} -.playlist.visible { - height: 180px; -} -.playlist ul { - margin: 0; padding: 0; -} -.playlist li { - margin: 0; padding: 10px; - cursor: pointer; - transition: all 0.2s; - background: rgba(20,5,10,0.5); -} -.playlist li.active { - color: #000; - background: rgba(255,255,255,0.9); -} -.playlistToggle { - align-self: flex-end; - width: 15px; - height: 15px; - padding: 10px; - display: flex; - flex-direction: column; - justify-content:space-between; -} -.playlistToggle div { - width: 100%; - height: 2px; - border-bottom: 1px solid #999; - background: white; -} -section { - -webkit-overflow-scrolling: touch; - overflow-y: auto; - max-height: calc(100vh - 140px); - max-width: 500px; - background: black; - position: absolute; - bottom: 160px; left: 0; - margin: 10px 10px; - padding: 10px; - background: rgba(20,5,10,0.5); - pointer-events: none; - opacity: 0; - transition: opacity 200ms; -} -.bio #bio, -.discography #discography, -.hardware #hardware, -.contact #contact { - opacity: 1; - pointer-events: auto; -} -@keyframes fade { - 0% { opacity: 0.6; } - 50% { opacity: 1.0; } - 90% { opacity: 0.7; } -100% { opacity: 0.6; } -} - -@media (max-width: 700px) { - * { box-sizing: border-box; } - header { - bottom: auto; - top: 0px; - } - header .row { - flex-direction: column; - } - header .row .menu { - flex-direction: row; - flex-wrap: wrap; - } - h1 { - flex: 1 1 100%; - text-align: center; - } - .menu a { - display: block; - text-align: center; - margin-left: 6px; - margin-right: 6px; - padding-bottom: 10px; - } - .menu a.active { - border: 0; - } - .playlist { - width: 100vw; - margin: 0; - bottom: 59px; - } - section { - height: calc(100vh - 150px); - width: 100%; - max-width: auto; - min-width: auto; - max-height: auto; - padding-bottom: 20px; - bottom: auto; - top: 90px; - margin: 0; - } - .player { - position: fixed; - bottom: 0; - background: rgba(80,10,60,0.6); - width: 100vw; - padding: 12px 20px; - } - .playlistToggle { - width: 36px; - height: 36px; - } -} \ No newline at end of file diff --git a/docs/fonts/NHaasGroteskTXPro-55Rg.ttf b/docs/fonts/NHaasGroteskTXPro-55Rg.ttf deleted file mode 100755 index e5ad72b..0000000 Binary files a/docs/fonts/NHaasGroteskTXPro-55Rg.ttf and /dev/null differ diff --git a/docs/fonts/NHaasGroteskTXPro-56It.ttf b/docs/fonts/NHaasGroteskTXPro-56It.ttf deleted file mode 100755 index 8aa3443..0000000 Binary files a/docs/fonts/NHaasGroteskTXPro-56It.ttf and /dev/null differ diff --git a/docs/fonts/NHaasGroteskTXPro-75Bd.ttf b/docs/fonts/NHaasGroteskTXPro-75Bd.ttf deleted file mode 100755 index d80c0ee..0000000 Binary files a/docs/fonts/NHaasGroteskTXPro-75Bd.ttf and /dev/null differ diff --git a/docs/fonts/NHaasGroteskTXPro-76BdIt.ttf b/docs/fonts/NHaasGroteskTXPro-76BdIt.ttf deleted file mode 100755 index 81dfad5..0000000 Binary files a/docs/fonts/NHaasGroteskTXPro-76BdIt.ttf and /dev/null differ diff --git a/docs/img/dreaming-city.jpg b/docs/img/dreaming-city.jpg deleted file mode 100644 index 211a0a9..0000000 Binary files a/docs/img/dreaming-city.jpg and /dev/null differ diff --git a/docs/img/escape-from-neukoelln.jpg b/docs/img/escape-from-neukoelln.jpg deleted file mode 100644 index dcd1180..0000000 Binary files a/docs/img/escape-from-neukoelln.jpg and /dev/null differ diff --git a/docs/img/pause-button.png b/docs/img/pause-button.png deleted file mode 100644 index 6ab7818..0000000 Binary files a/docs/img/pause-button.png and /dev/null differ diff --git a/docs/img/pause-inv.png b/docs/img/pause-inv.png deleted file mode 100644 index 9780255..0000000 Binary files a/docs/img/pause-inv.png and /dev/null differ diff --git a/docs/img/pause.png b/docs/img/pause.png deleted file mode 100644 index c2d30ae..0000000 Binary files a/docs/img/pause.png and /dev/null differ diff --git a/docs/img/play-button.png b/docs/img/play-button.png deleted file mode 100644 index c0fd3fc..0000000 Binary files a/docs/img/play-button.png and /dev/null differ diff --git a/docs/img/play-fill.png b/docs/img/play-fill.png deleted file mode 100644 index 2205696..0000000 Binary files a/docs/img/play-fill.png and /dev/null differ diff --git a/docs/img/play-inv.png b/docs/img/play-inv.png deleted file mode 100644 index 4baaa5f..0000000 Binary files a/docs/img/play-inv.png and /dev/null differ diff --git a/docs/img/play.png b/docs/img/play.png deleted file mode 100644 index b5b4a08..0000000 Binary files a/docs/img/play.png and /dev/null differ diff --git a/docs/img/playbutton.psd b/docs/img/playbutton.psd deleted file mode 100644 index e2dbed4..0000000 Binary files a/docs/img/playbutton.psd and /dev/null differ diff --git a/docs/img/xena-vectra-logo-sm.png b/docs/img/xena-vectra-logo-sm.png deleted file mode 100644 index b42111b..0000000 Binary files a/docs/img/xena-vectra-logo-sm.png and /dev/null differ diff --git a/docs/img/xena-vectra-logo.png b/docs/img/xena-vectra-logo.png deleted file mode 100644 index 4b3f810..0000000 Binary files a/docs/img/xena-vectra-logo.png and /dev/null differ diff --git a/docs/img/xenavectra.gif b/docs/img/xenavectra.gif deleted file mode 100644 index fb81d57..0000000 Binary files a/docs/img/xenavectra.gif and /dev/null differ diff --git a/docs/index.html b/docs/index.html index d141040..ddee963 100644 --- a/docs/index.html +++ b/docs/index.html @@ -3,7 +3,7 @@ Xena Vectra - + @@ -36,7 +36,7 @@ Xena Vectra is the alter ego of synth goddess Bethany Barrett. Born in the mountains of the Black Forest and raised in sunny California, Beth has a long history in Berlin's underground music scene. Over the years she has produced everything from shoegaze to noise, avant garde disco and synthwave alike. Her unique style as Xena Vectra is inspired by vintage horror soundtracks, driven by her love of analog electronics.

- Beth performs live using an all hardware setup without a laptop in sight. She is available for bookings throughout Europe. Her soundtrack work includes scoring indie film Figaros Wölfe (2017) and she is currently working on several upcoming projects with the German artist Hito Steyerl. + As Xena Vectra, she performs live using an all hardware setup without a laptop in sight. She is available for bookings throughout Europe. Her soundtrack work includes scoring indie film Figaros Wölfe (2017).

@@ -61,6 +61,7 @@
  • Moog Subphatty
  • Korg Monologue
  • +
  • Korg Minilogue
  • Arturia Microbrute
  • Pittsburgh Modular Lifeforms SV-1
@@ -68,6 +69,8 @@
  • Behringer DeepMind 12
  • Roland JX-8P
  • +
  • Roland D-05
  • +
  • Korg Volca FM

Drum machines

    @@ -79,11 +82,8 @@
  • Strymon Timeline
  • Strymon Big Sky
- "So, are softsynths as nasty as they say?" —Cayde-6 -
-
-

Contact

-

+ "" —Cayde-6 +

Contact

Booking:
Twitter: diff --git a/docs/js/cielab.js b/docs/js/cielab.js deleted file mode 100644 index 14c096f..0000000 --- a/docs/js/cielab.js +++ /dev/null @@ -1,70 +0,0 @@ -var cielab = (function(){ - var cielab = {} - - var xyz = [0,0,0] - var rgb = [0,0,0] - - L_range = [0, 100] - a_range = [-86.185, 98.254] - b_range = [-107.863, 94.482] - - cielab.gradient = function (n) { - n = n || 100 - var k = 0 - - var L, a, b - - var L0 = randrange(L_range[0] + 50, L_range[1]) - var L1 = randrange(L_range[0]+ 50, L_range[1]) - var a0 = randrange(a_range[0], a_range[1]) - var a1 = randrange(a_range[0], a_range[1]) - var b0 = randrange(b_range[0], b_range[1]) - var b1 = randrange(b_range[0], b_range[1]) - return function next (aa){ - L = mix(k/n, L0, L1) - a = mix(k/n, a0, a1) - b = mix(k/n, b0, b1) - rgb = xyz2rgb(hunterlab2xyz(L, a, b)) - k += 1 - return rgba_string(rgb, aa) - } - } - function rgba_string (rgb, a) { return "rgba(" + rgb.map(Math.round).join(",") + "," + a + ")" } - function hex_string (rgb) { return "#" + rgb.map(Math.round).map(function(n){ var s = n.toString(16); return s.length == 1 ? "0"+s : s }).join("") } - - function mix(n,a,b){ return n*a + (1-n)*b } - function clamp(n,a,b){ return n 0.0031308 ) var_R = 1.055 * Math.pow( var_R, 1 / 2.4 ) - 0.055 - else var_R = 12.92 * var_R - if ( var_G > 0.0031308 ) var_G = 1.055 * Math.pow( var_G, 1 / 2.4 ) - 0.055 - else var_G = 12.92 * var_G - if ( var_B > 0.0031308 ) var_B = 1.055 * Math.pow( var_B, 1 / 2.4 ) - 0.055 - else var_B = 12.92 * var_B - - rgb[0] = clamp(var_R * 255, 0, 255) - rgb[1] = clamp(var_G * 255, 0, 255) - rgb[2] = clamp(var_B * 255, 0, 255) - return rgb - } - - return cielab -})() \ No newline at end of file diff --git a/docs/js/player.js b/docs/js/player.js deleted file mode 100644 index 25fdfd6..0000000 --- a/docs/js/player.js +++ /dev/null @@ -1,79 +0,0 @@ -const player = (function(){ - let player = {} - let current_index = -1 - let audio = document.createElement('audio') - let tracks = [ - { file: "mp3/xena_vectra-cruise.mp3", title: "Cruise" }, - { file: "mp3/xena_vectra-dreaming_city_2.mp3", title: "Dreaming City 2" }, - { file: "mp3/xena_vectra-escape_from_nk.mp3", title: "Escape from Neukölln" }, - ] - function init(){ - bind() - build() - // play(0) - } - function bind(){ - audio.addEventListener('play', handlePlay) - audio.addEventListener('pause', handlePause) - audio.addEventListener('ended', handleEnded) - document.querySelector('.player .icon').addEventListener('click', togglePlaying) - document.querySelector('.player .track').addEventListener('click', play) - document.querySelector('.player .playlistToggle').addEventListener('click', togglePlaylist) - } - function build() { - tracks.forEach((track, i) => { - let el = document.createElement('li') - el.innerHTML = track.title - el.addEventListener('click', () => { - if (is_mobile) { - hidePlaylist() - } - shards.rebuild() - play(i) - }) - document.querySelector('.playlist ul').appendChild(el) - }) - document.querySelector('.player .track').innerHTML = tracks[0].title - } - function play(n){ - const active = document.querySelector('.playlist ul .active') - if (active) active.classList.remove('active') - document.querySelector('.playlist ul').children[n].classList.add('active') - - current_index = (n + tracks.length) % tracks.length - audio.src = tracks[n].file - audio.play() - document.querySelector('.player .track').innerHTML = tracks[n].title - } - function handlePlay(){ - document.querySelector('.player').classList.add('playing') - document.querySelector('.player').classList.remove('paused') - shards.step() - } - function handlePause(){ - document.querySelector('.player').classList.remove('playing') - document.querySelector('.player').classList.add('paused') - } - function handleEnded(){ - shards.rebuild() - play(current_index+1) - } - function togglePlaying() { - // sounds.play('click') - if (current_index == -1) { - play(0) - } else { - if (audio.paused) audio.play() - else audio.pause() - } - } - function togglePlaylist() { - site.navigateHash('') - document.querySelector('.playlist').classList.toggle('visible') - } - function hidePlaylist() { - document.querySelector('.playlist').classList.remove('visible') - } - init() - return { hidePlaylist } -})() \ No newline at end of file diff --git a/docs/js/shards.js b/docs/js/shards.js deleted file mode 100644 index 1b374ee..0000000 --- a/docs/js/shards.js +++ /dev/null @@ -1,107 +0,0 @@ -const shards = (function(){ - let count - let delay = 120 * 1000 - let els = [] - let t = 0 - let rebuilding = false - let nextTimeout - let dark, light - const bg_el = document.querySelector('.bgs') - - function init(){ - bind() - build() - step() - setTimeout(next, 20) - bg_el.classList.remove('fade') - } - function bind(){ - document.querySelector('h1').addEventListener('click', () => { - sounds.play('click') - rebuild() - site.navigateHash('') - player.hidePlaylist() - }) - } - function build(){ - count = choice(is_mobile ? [5,7] : [5,7,7,11,11]) - light = cielab.gradient(count) - dark = cielab.gradient(count) - let el - for (var i = 0; i < count; i++) { - el = append(i) - } - } - function destroy(){ - for (var i = 0; i < count; i++) { - els[i] && bg_el.removeChild(els[i]) - } - els.length = 0 - } - function rebuild(){ - if (rebuilding) return - rebuilding = true - // sounds.play('click') - stars.rebuild() - next() - t = 0 - bg_el.classList.add('fade') - setTimeout(() => { - destroy() - build() - step() - setTimeout(next, 20) - bg_el.classList.remove('fade') - rebuilding = false - // sounds.play('click') - }, 500) - } - function append(i){ - const el = document.createElement('div') - el.classList.add('bg') - els.push(el) - bg_el.appendChild(el) - return el - } - function next(){ - clearTimeout(nextTimeout) - nextTimeout = setTimeout(next, delay) - step() - } - function step() { - t += 1 - light = cielab.gradient(count) - let w = { min: is_mobile ? randrange(40, 90) : randrange(20, 40), max: randrange(10, 90) } - if (w.min > w.max) { - w.min += 10 - } - let rot = { min: randint(360), max: randrange(720, 1080) } - for (var i = 0; i < count; i++) { - update(i, t, w, rot, dark, light) - } - document.body.style.backgroundColor = cielab.gradient(2)(0.05) - } - function update(i, t, w, rot){ - const el = els[i] - const n = i / count - const side = lerp(n, w.min, w.max) - const spin = lerp(i % 2 ? (1-n) : (n), rot.min, rot.max) - const rotation = "rotate3d(" + [randrange(-1,1), randrange(-1,1), randrange(-1,1)].join(',') + ',' + randint(360) + "deg)" - el.style.width = side + 'vmin' - el.style.height = side + 'vmin' - el.style.transform = "translate3d(-50%, -50%, 0) rotate(" + spin + "deg) translate3d(50%, 50%, 0) " + rotation - // el.style.transform = "translate3d(-50%, -50%, 0)" - if (t === 1) { - light = cielab.gradient(count) - if (is_mobile) { - el.style.backgroundImage = 'linear-gradient(0deg, ' + dark(1) + ', ' + light(1) + ')' - } else { - el.style.backgroundImage = 'linear-gradient(0deg, ' + dark(1) + ', ' + light(0) + ')' - } - } - el.style.backgroundColor = light(1) - el.style.opacity = lerp(n, randrange(0.1, 0.4), randrange(0.2, 0.5)) - } - init() - return { rebuild: rebuild, step: step, } -})() \ No newline at end of file diff --git a/docs/js/site.js b/docs/js/site.js deleted file mode 100644 index 37b9d77..0000000 --- a/docs/js/site.js +++ /dev/null @@ -1,59 +0,0 @@ -const site = (function(){ - let section - let links = toArray(document.querySelectorAll('.menu a')) - let time = new Date() - let hour = time.getHours() - if (hour < 8 || hour > 16) { - document.body.parentNode.classList.add('night') - } else { - document.body.parentNode.classList.add('day') - } - preload('img/pause-inv.png') - setTimeout(() => { - document.body.classList.remove('loading') - navigateHash(window.location.hash) - const email = atob("eGVuYXZlY3RyYTkwOUBnbWFpbC5jb20=") - const twitter = atob("dmVjdHJheGVuYQ==") - document.querySelector("#email_addr").href = 'mailto:' + email - document.querySelector("#email_addr").innerHTML = email - document.querySelector("#twitter_addr").innerHTML = twitter - document.querySelector("#twitter_addr").href = 'https://twitter.com/' + twitter - }, 0) - toArray(document.querySelectorAll('.menu a')).forEach(a => { - a.addEventListener("click", e => { - e.preventDefault() - sounds.play('click') - console.log(e.target) - if (e.target.nodeName.toLowerCase() !== 'a') { - navigateHash(e.target.parentNode.href) - } else { - navigateHash(e.target.href) - } - }) - }) - function navigateHash(url){ - if (is_mobile) { - player.hidePlaylist() - } - let new_section = (url || "").split('#')[1] - if (section) { - document.body.classList.remove(section) - links.forEach(link => link.classList.remove('active')) - } - if (new_section && new_section !== section) { - document.body.classList.add(new_section) - links.forEach(link => link.getAttribute('href').match(new_section) && link.classList.add('active')) - section = new_section - } else { - section = null - } - // window.location.hash = section || "" - } - function preload(src) { - const img = new Image - img.src = src - } - return { - navigateHash: navigateHash - } -})() diff --git a/docs/js/sounds.js b/docs/js/sounds.js deleted file mode 100644 index 39f725d..0000000 --- a/docs/js/sounds.js +++ /dev/null @@ -1,17 +0,0 @@ -const sounds = (function(){ - let sounds = {} - let els = {} - sounds.add = (fn) => { - const el = document.createElement('audio') - el.src = 'sounds/' + fn + '.mp3' - els[fn] = el - } - sounds.play = (fn) => { - const el = els[fn] - el.currentTime = 0 - el.volume = 0.8 - el.play() - } - sounds.add('click') - return sounds -})() diff --git a/docs/js/stars.js b/docs/js/stars.js deleted file mode 100644 index 0637473..0000000 --- a/docs/js/stars.js +++ /dev/null @@ -1,63 +0,0 @@ -const stars = (function(){ - var canvas = document.createElement("canvas"), ctx = canvas.getContext('2d') - var s = Math.sin, c = Math.cos - document.addEventListener("DOMContentLoaded", function(){ - document.body.appendChild(canvas) - canvas.classList.add('stars') - canvas.style.width="100%" - canvas.style.height="100%" - canvas.style.position="fixed" - canvas.style.top="0px" - canvas.style.left="0px" - canvas.style.zIndex=-1 - document.body.addEventListener("resize", build) - // document.body.parentNode.style.backgroundColor="black" - ctx.strokeStyle="white" - build() - }) - function ri(n){ return Math.random() * n } - function rr(a,b){ return (b-a) * Math.random() + a } - function build(){ - var w = canvas.width = window.innerWidth * window.devicePixelRatio - var h = canvas.height = window.innerHeight * window.devicePixelRatio - ctx.clearRect(0,0,w,h) - var n = Math.sqrt(w*h)|0 - while (n--) { - var x = ri(w) - var y = ri(h) - var r0 = rr(0, 1) - var r1 = rr(0, 1) - var r2 = rr(0, 1) - var t0 = ri(2*Math.PI) - var t1 = ri(2*Math.PI) - var t2 = ri(2*Math.PI) - var x0 = x+c(t0)*r0 - var y0 = y+s(t0)*r0 - var x1 = x+c(t1)*r1 - var y1 = y+s(t1)*r1 - var x2 = x+c(t2)*r2 - var y2 = y+s(t2)*r2 - ctx.beginPath() - ctx.moveTo(x,y) - ctx.bezierCurveTo(x0,y0,x1,y1,x2,y2) - var color = rr(0, 255)|0 - ctx.strokeStyle="rgb("+color+","+color+","+color+")" - ctx.stroke() - } - } - let rebuilding = false - function rebuild(){ - if (rebuilding) return - rebuilding = true - canvas.classList.add('fade') - document.body.classList.add('fade') - setTimeout(() => { - // destroy() - build() - canvas.classList.remove('fade') - document.body.classList.remove('fade') - rebuilding = false - }, 500) - } - return { rebuild: rebuild } -})() \ No newline at end of file diff --git a/docs/js/util.js b/docs/js/util.js deleted file mode 100644 index e40db4a..0000000 --- a/docs/js/util.js +++ /dev/null @@ -1,139 +0,0 @@ -const is_iphone = (navigator.userAgent.match(/iPhone/i)) || (navigator.userAgent.match(/iPod/i)) -const is_ipad = (navigator.userAgent.match(/iPad/i)) -const is_android = (navigator.userAgent.match(/Android/i)) -const is_mobile = is_iphone || is_ipad || is_android -const is_desktop = !is_mobile; -document.body.parentNode.classList.add(is_desktop ? 'desktop' : 'mobile') - -function avg(a,b,n){ return (a*(n-1) + b)/n } -function rand(n){ return Math.random()*n } -function randint(n) { return ~~(Math.random()*n) } -function randrange(a,b){ return a+rand(b-a) } -function choice(a) { return a[randint(a.length)] } -function clamp(n,a,b) { return a > n ? a : n > b ? b : n } -function sign(n){ return n < 0 ? -1 : 1 } -function mod(n,m){ return n-(m * Math.floor(n/m)) } -function lerp(n,a,b){ return (b-a)*n+a } -function quantize(m,n){ return n * ((m/n)|0) } - -function randgauss (obj, jog) { - var radius = Math.random() * jog - var angle = Math.random() * Math.PI * 2 - obj.left += Math.sin(angle) * radius - obj.top += Math.cos(angle) * radius -} - -function shuffle(a){ - for (var i = a.length; i > 0; i--){ - var r = randint(i) - var swap = a[i-1] - a[i-1] = a[r] - a[r] = swap - } - return a -} - -function toArray (els){ - return Array.prototype.slice.apply(els) -} - -// easing functions -function circular (t) { return Math.sqrt( 1 - ( --t * t ) ) } -function quadratic (t) { return t * ( 2 - t ) } -function back (t) { - var b = 4; - return ( t = t - 1 ) * t * ( ( b + 1 ) * t + b ) + 1; -} -function bounce (t) { - if (t >= 1) return 1; - if ( ( t /= 1 ) < ( 1 / 2.75 ) ) { - return 7.5625 * t * t; - } else if ( t < ( 2 / 2.75 ) ) { - return 7.5625 * ( t -= ( 1.5 / 2.75 ) ) * t + 0.75; - } else if ( t < ( 2.5 / 2.75 ) ) { - return 7.5625 * ( t -= ( 2.25 / 2.75 ) ) * t + 0.9375; - } else { - return 7.5625 * ( t -= ( 2.625 / 2.75 ) ) * t + 0.984375; - } -} -function elastic (t) { - var f = 0.22, - e = 0.4; - - if ( t === 0 ) { return 0; } - if ( t == 1 ) { return 1; } - - return ( e * Math.pow( 2, - 10 * t ) * Math.sin( ( t - f / 4 ) * ( 2 * Math.PI ) / f ) + 1 ); -} - -function preload (url) { - var img = new Image () - var loaded = false, _cb - img.onload = function(){ - if (loaded) return - loaded = true - if (_cb) { _cb(img) } - } - img.src = url - if (img.complete) { img.onload() } - return { - then: function(cb){ - if (loaded) { cb(img) } - else { _cb = cb } - } - } -} - -function preloadImages () { - var images = toArray(document.getElementById("images").children) - var count = 0, ready = false, _cb - images.forEach(function(img){ - var loaded = false - img.onload = function(){ - if (loaded) return - loaded = true - done(img) - } - if (img.complete) { img.onload() } - }) - function done () { - if (++count == images.length && ! ready) { - ready = true - _cb && _cb() - } - } - return { - then: function(cb){ - if (ready) { cb() } - else { _cb = cb } - } - } -} - -function smoothstep(min,max,n){ - var t = clamp((n - min) / (max - min), 0.0, 1.0); - return t * t * (3.0 - 2.0 * t) -} - -function detrand (x,y) { - return (Math.sin( x * 12.9898 + y * 78.233 ) * 43758.5453) % 1 -} - -function gray_to_transparency(img) { - var canvas = document.createElement("canvas") - var ctx = canvas.getContext('2d') - var nw = img.naturalWidth, nh = img.naturalHeight - canvas.width = nw - canvas.height = nh - ctx.drawImage(img,0,0) - var pixels = ctx.getImageData(0,0,nw,nh) - var data = pixels.data - for (var i = 0, len = nw*nh*4; i < len; i += 4) { - data[i+3] = data[i] - data[i] = data[i+1] = data[i+2] = 255 - } - ctx.putImageData(pixels,0,0) - return canvas -} - -var TWO_PI = 2*Math.PI \ No newline at end of file diff --git a/docs/sounds/click.mp3 b/docs/sounds/click.mp3 deleted file mode 100644 index 37e7df0..0000000 Binary files a/docs/sounds/click.mp3 and /dev/null differ diff --git a/docs/sounds/click.wav b/docs/sounds/click.wav deleted file mode 100644 index 7c45aed..0000000 Binary files a/docs/sounds/click.wav and /dev/null differ -- cgit v1.2.3-70-g09d2