{"__browser":{"country":"US","device":"unknown_device","mobile":false,"name":"unknown browser","platform":"unknown_platform","version":"0"},"__constants":{},"__CPDATA":{"domain_iframe":"https://cdpn.io","environment":"production","host":"codepen.io","iframe_allow":"accelerometer *; ambient-light-sensor *; camera *; display-capture *; encrypted-media *; geolocation *; gyroscope *; microphone *; midi *; payment *; vr *; web-share *; serial *; xr-spatial-tracking *","iframe_sandbox":"allow-downloads allow-forms allow-modals allow-pointer-lock allow-popups-to-escape-sandbox allow-popups allow-presentation allow-same-origin allow-scripts allow-top-navigation-by-user-activation"},"__graphql":{"data":{"data":{"sessionUser":{"id":"VoDkNZ","name":"Captain Anonymous","title":"Captain Anonymous","avatar":"https://assets.codepen.io/t-1/user-default-avatar.jpg?format=auto&version=0","currentContext":{"id":"VoDkNZ","title":"Captain Anonymous","name":"Captain Anonymous","avatar":"https://assets.codepen.io/t-1/user-default-avatar.jpg?format=auto&version=0","username":"anon","__typename":"User"},"currentTeamId":null,"username":"anon","admin":false,"anon":true,"pro":false,"verified":false,"featureFlags":[],"teams":[],"__typename":"User"}}},"url":"https://codepen.io/graphql","api":"cprails"},"__user":{"anon":true,"base_url":"/anon/","cohorts":[],"current_team_hashid":null,"current_team_id":0,"hashid":"VoDkNZ","id":1,"itemType":"user","name":"Captain Anonymous","paid":false,"tier":0,"username":"anon","created_at":null,"email_verified":null,"collections_count":0,"collections_private_count":0,"followers_count":0,"followings_count":0,"pens_count":0,"pens_private_count":0,"projects_count":0,"projects_private_count":0},"__firebase":{"config":{"apiKey":"AIzaSyBgLAe7N_MdFpuVofMkcQLGwwhUu5tuxls","authDomain":"codepen-store-production.firebaseapp.com","databaseURL":"https://codepen-store-production.firebaseio.com","disabled":false,"projectId":"codepen-store-production"},"token":"eyJhbGciOiJSUzI1NiJ9.eyJhdWQiOiJodHRwczovL2lkZW50aXR5dG9vbGtpdC5nb29nbGVhcGlzLmNvbS9nb29nbGUuaWRlbnRpdHkuaWRlbnRpdHl0b29sa2l0LnYxLklkZW50aXR5VG9vbGtpdCIsImNsYWltcyI6eyJvd25lcklkIjoiVm9Ea05aIiwiYWRtaW4iOmZhbHNlfSwiZXhwIjoxNzI4NjgyNzc2LCJpYXQiOjE3Mjg2NzkxNzYsImlzcyI6ImZpcmViYXNlLWFkbWluc2RrLThva3lsQGNvZGVwZW4tc3RvcmUtcHJvZHVjdGlvbi5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsInN1YiI6ImZpcmViYXNlLWFkbWluc2RrLThva3lsQGNvZGVwZW4tc3RvcmUtcHJvZHVjdGlvbi5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsInVpZCI6IlZvRGtOWiJ9.e0EQ-YJfaND3iQK10LTIGKzsB1K1avIn1kkxG4x6Xv8rw69E0v6P-hgAAsDh0zxN76aXuMNHlMO_UOozQxCD6hsmGs5PX2fOLYBbbcXkczLdsFv4BG2aGipeITpGhmIEcbDKTgHENqDleWOAjnX7pwU_19UdBEjnP_YnImoC9dXl34jljp45bnSSqcybkXKY4aH3aigC7M4AEBbi-Wyo7RYTaigBgPQlchZovzv5qp1tEcfKI1IimgCOCyIcSJDuLITVOrK4MvPDlOyT7xSM5NTqg03X6JVw-6wcgt6u51ketNZOc9y1XbzbpfjoBAmKGWE3z3e0q64okCSl9JtYkQ"},"__pay_stripe_public_key":"pk_live_2GndomDfiklqpSNQn8FrGuwZSMIMzha7DkLJqlYe7IR0ihKAlKdiHg68JJc5eVPt68rzAjzAAVXcUwjySHRCsgjQQ00gtRBUFNH","__pay_braintree_env":"production","__item":"{\"id\":7846001,\"user_id\":385326,\"html\":\"<div class=\\\"page-wrap\\\"> \\n <h1>The Repeater Orchestra<\\/h1>\\n <div class=\\\"orchestra\\\">\\n <div class=\\\"label -conductor\\\">The Conductor (You)<\\/div>\\n <div class=\\\"label -repeaters\\\">Repeaters<\\/div>\\n <\\/div>\\n<\\/div>\\n\\n<div class=\\\"controls\\\">\\n <h2>Controls<\\/h2>\\n <button class=\\\"gate-open\\\">Turn Mic On\\/Off<\\/button>\\n <div class=\\\"slider-wrap\\\">\\n <div class=\\\"slider micGain\\\"><\\/div>\\n <div class=\\\"rot -left\\\">Mic<\\/div>\\n <\\/div>\\n <div class=\\\"slider-wrap\\\">\\n <div class=\\\"slider masterGain\\\"><\\/div>\\n <div class=\\\"rot -right\\\">Orch<\\/div>\\n <\\/div>\\n <button class=\\\"clear-delays\\\">Restart Repeaters<\\/button>\\n<\\/div>\\n\\n<a href=\\\"https:\\/\\/codepen.io\\/poopsplat\\/post\\/codepen-chicago-june-2016\\\" target=\\\"_blank\\\" class=\\\"example\\\">Video Example <span class=\\\"fake-link\\\">here<\\/span><\\/a>\\n\\n<div class=\\\"loading\\\"><h1>The Repeater Orchestra (1.0)<\\/h1><\\/div>\",\"css\":\"\\/\\/ Box-sizing\\n*, *::before, *::after {\\n box-sizing: inherit;\\n}\\nhtml {\\n box-sizing: border-box;\\n font-size: 16px; \\/\\/rem\\n}\\n\\n\\/\\/ Fonts\\n@import url(https:\\/\\/fonts.googleapis.com\\/css?family=Share+Tech+Mono);\\n\\n\\/\\/ Colors\\n$blue: rgb(18, 104, 207);\\n$black: rgb(20,20,20);\\n$gray: rgb(150,150,150);\\n$lite-gray: rgb(180,180,180);\\n$white: rgb(255,255,255);\\n\\n\\/\\/ Base\\nbody {\\n background: $blue;\\n text-align: center;\\n text-transform: uppercase;\\n @extend %font;\\n}\\n%font {\\n color: $white;\\n font-family: 'Share Tech Mono';\\n letter-spacing: -0.05em;\\n}\\n%stroke {\\n text-shadow:\\n -2px -2px 0 $black, \\n 2px -2px 0 $black,\\n -2px 2px 0 $black,\\n 2px 2px 0 $black;\\n}\\nh1, h2 {\\n @extend %stroke;\\n margin-top: 0;\\n}\\n.page-wrap {\\n padding-top: 1rem;\\n width: 40rem;\\n margin: auto;\\n}\\n\\n\\/\\/ Orchestra\\n.orchestra {\\n position: relative;\\n margin: auto;\\n width: 100%;\\n height: 20rem;\\n background: rgba($black,.2);\\n margin: 8rem 0 10rem;\\n .label {\\n position: absolute;\\n &.-repeaters{\\n top: 1rem;\\n left: 41rem;\\n }\\n &.-conductor{\\n top: -4rem;\\n left: 26rem;\\n }\\n }\\n}\\ncanvas {\\n background: $blue;\\n transform: translate(-50%,0); \\/\\/ Thus, our bottom\\/left refers to the center\\n position: absolute;\\n border: 2px solid $white;\\n border-radius: 100%;\\n @extend %stroke;\\n}\\n#conductor{\\n top: 0;\\n left: 50%;\\n transform: translate(-50%,-50%);\\n}\\n\\n\\/\\/ UI\\n.controls {\\n position: fixed;\\n padding: 1em;\\n left: 0;\\n bottom: 0;\\n background: $blue;\\n border-top: 2px solid $white;\\n border-right: 2px solid $white;\\n opacity: 0.5;\\n &:hover { opacity: 1; }\\n}\\n\\n\\/\\/ Buttons\\n%button-hover {\\n &:hover{\\n cursor: pointer;\\n background: $lite-gray;\\n }\\n}\\nbutton{\\n position: relative;\\n border: $white 2px solid;\\n background-color: $black;\\n color: $white;\\n font-family: 'Share Tech Mono';\\n letter-spacing: -0.1em;\\n text-align: center;\\n text-transform: uppercase;\\n @extend %button-hover;\\n display: block;\\n margin: auto;\\n padding: .4rem;\\n &.on{\\n background-color: $white;\\n color: black;\\n border-color: $black;\\n }\\n}\\n\\n\\/\\/ Sliders\\n.slider-wrap {\\n display: inline-block;\\n margin: 1rem .5rem;\\n}\\n.slider {\\n border: $black 2px solid;\\n border-radius: 0;\\n background-color: $black;\\n background-image: none;\\n display: inline-block;\\n height: 6rem;\\n &:hover{\\n cursor: pointer;\\n }\\n .ui-slider-range {\\n border-radius: 0;\\n background-color: $white;\\n background-image: none;\\n }\\n .ui-slider-handle {\\n border: $black 2px solid;\\n border-radius: 0;\\n background-color: $white;\\n background-image: none;\\n \\/\\/ transition: transform 0.2s;\\n &:hover{\\n cursor: pointer;\\n }\\n }\\n}\\n\\n\\/\\/ Alert\\n.alert {\\n position: fixed;\\n top: 0;\\n right: 0;\\n left: 0;\\n height: 100%;\\n background: rgba($white, 0.8);\\n .content {\\n position: fixed;\\n top: 50%;\\n left: 50%;\\n transform: translate(-50%,-50%);\\n width: 500px;\\n background: $blue;\\n border: 2px solid $black;\\n padding: 2em;\\n z-index: 100;\\n a {\\n color: $white;\\n }\\n .message {\\n \\/\\/ float: left;\\n text-align: left;\\n display: inline-block;\\n width: 300px;\\n }\\n .icon {\\n float: left;\\n width: 100px;\\n height: auto;\\n margin-right: 2em;\\n }\\n button {\\n clear: both;\\n display: block;\\n margin: 2em auto 0;\\n }\\n }\\n}\\n\\n\\/\\/ Example Performance\\n.example {\\n position: fixed;\\n bottom: 0;\\n left: 100%;\\n padding: 1rem;\\n width: 200px;\\n background: $blue;\\n display: inline-block;\\n color: white;\\n text-decoration: none;\\n .fake-link {\\n text-decoration: underline;\\n }\\n border-top: 2px $white solid;\\n border-right: 2px $white solid;\\n transform: rotate(270deg);\\n transform-origin: 0% 100%;\\n opacity: 0.5;\\n &:hover{ opacity: 1; }\\n}\\n\\n\\/\\/Loading\\n.loading{\\n position: fixed;\\n z-index: 100;\\n position: absolute;\\n top: 0;\\n left: 0;\\n right: 0;\\n height: 100%;\\n background-color: $blue;\\n transition: opacity 0.2s, visibility 0s 0.2s;\\n h1 {\\n position: absolute;\\n top: 40%;\\n left: 50%;\\n transform: translate(-50%,-50%);\\n text-shadow: none;\\n color: $black;\\n }\\n}\",\"js\":\"\\/\\/ TODO ---------------------------------------------------------\\n\\/\\/ [ ] Make all options changeable via UI: n-repeaters, tempo, latency\\n\\/\\/ [ ] Latency reduction should be additive not multiplicative, right?\\n\\/\\/ [ ] Add links for how to record yourself!\\n\\n\\/\\/ GLOBALS ---------------------------------------------------------\\n\\n\\/\\/ Options\\n_nDelays = 50; \\/\\/ Number of Repeaters\\n_tempo = 80; \\/\\/ Global tempo (bpm)\\n_maxEighths = 60; \\/\\/ Max eigth notes a repeater can be delayed.\\n_minGain = 0.2; \\/\\/ Min gain multiple for a repeater.\\n_maxGain = 2; \\/\\/ Max gain multiple for a repeater.\\n_gateOpen = false; \\/\\/ Is the mic \\\"on\\\"?\\n_micGainStart = 0.5; \\/\\/ Starting mic gain\\n_masterGainStart = 0.5; \\/\\/ Starting gain of Orchestra\\n_monitorGainStart = 4; \\/\\/ How much louder should the mic feed be than the repeaters? (Monitor)\\n_latencyTune = 0; \\/\\/ A slight crunching of our delay times to help account for latency\\n\\n\\/\\/ Calculations\\nvar eighthTime = (60 \\/ _tempo \\/ 2)*(1-_latencyTune\\/1000.0); \\/\\/ This _latencyTune thing is HACKY\\nvar gainRange = _maxGain - _minGain;\\n\\n\\/\\/ CUSTOM USER ALERTS --------------------------------------------------------- \\nfunction customAlert(msg, btn, svg) {\\n var btn = btn || 'Word';\\n var svg = svg || 'https:\\/\\/s3-us-west-2.amazonaws.com\\/s.cdpn.io\\/385326\\/achtung.svg';\\n if ($('.alert').length) { \\/\\/ If there is already an alert, we're gonna try again with this message in a short while.\\n setTimeout(function() {\\n customAlert(msg, btn);\\n }, 100);\\n } else {\\n $('<div class=\\\"alert\\\"><div class=\\\"content\\\"><img src=\\\"' + svg + '\\\" class=\\\"icon\\\"><div class=\\\"message\\\">' + msg + '<\\/div><button>' + btn + '<\\/button><\\/div><\\/div>').appendTo('body');\\n $('.alert button').click(function(e) {\\n e.preventDefault();\\n $('.alert').remove();\\n })\\n }\\n}\\n\\n\\/\\/ REQUEST USER AUDIO INPUT STREAM ---------------------------------------------------------\\nnavigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia;\\nnavigator.getUserMedia({\\n audio: {\\n latency: 0, \\/\\/Does this do anything?\\n sampleSize: 128 \\/\\/Does this do anything? Probably not....\\n }\\n}, gotStream, streamErr);\\n\\n\\/\\/ If error getting input...\\nfunction streamErr() {\\n\\n \\/\\/ Clear loading screen\\n $('.loading').remove();\\n\\n \\/\\/ Clear the stage, because nothing will work.\\n $('body *:not(h1)').remove();\\n \\n \\/\\/ Give the user some advice\\n customAlert('Couldn\\\\'t get the mic. Likely, you need to give this site permission to use your mic. You may have been prompted. <a href=\\\"https:\\/\\/support.google.com\\/chrome\\/answer\\/2693767?hl=en-GB\\\">This article<\\/a> might help. Then refresh the page.', 'OK. I\\\\'ll figure it out and refresh!');\\n\\n}\\n\\n\\/\\/ If success...\\nfunction gotStream(stream) {\\n\\n \\/\\/ Clear loading screen\\n $('.loading').remove();\\n\\n \\/\\/ Alert user to wear headphones!!!\\n customAlert('If your mic is near your speakers (like on most computers), this thing is gonna make gnarly feedback. Unless you have a fancy schmancy mic\\/speaker setup, you should put on headphones to enjoy this.', 'Word. I put on headphones!', 'https:\\/\\/s3-us-west-2.amazonaws.com\\/s.cdpn.io\\/385326\\/headphones.svg');\\n\\n \\/\\/ AUDIO CONTEXT --------------------------------------------------------- \\n \\/\\/ Build the audio context. This is from where all the magic of web audio stems.\\n window.AudioContext = window.AudioContext || window.webkitAudioContext;\\n _cxt = new AudioContext();\\n\\n \\/\\/ PRIMARY INPUT\\/OUTPUT CHAIN ---------------------------------------------------------\\n \\/\\/ _mic -> _micGain -> _monitorGain -> _masterGain -> _compressor -> destination\\n\\n \\/\\/ Create + connect _mic\\n _mic = _cxt.createMediaStreamSource(stream);\\n\\n \\/\\/ Create + connect _micGain -- This controls mic volume (it will also be how we \\\"turn the mic off\\\")\\n _micGain = _cxt.createGain(); \\/\\/ Create\\n _micGain.gain.value = _micGainStart * _gateOpen;\\n _mic.connect(_micGain); \\/\\/ Chain _mic to _micGain\\n\\n \\/\\/ Create + connect _monitorGain -- Makes the mic chain louder than the delay chains so you can better monitor.\\n _monitorGain = _cxt.createGain(); \\n _monitorGain.gain.value = _monitorGainStart;\\n _micGain.connect(_monitorGain); \\/\\/ Chain\\n\\n \\/\\/ Create + connect _masterGain -- Volume of entire orchestra\\n _masterGain = _cxt.createGain();\\n _masterGain.gain.value = _masterGainStart;\\n _monitorGain.connect(_masterGain); \\/\\/ Chain\\n\\n \\/\\/ Create + connect _compressor -- Compress me because I hate clipping\\n _compressor = _cxt.createDynamicsCompressor(); \\/\\/ The defaults for this are good.\\n _masterGain.connect(_compressor); \\/\\/ Chain\\n\\n \\/\\/ Finally, connect us to the destination (where the audio is outputted)\\n _compressor.connect(_cxt.destination);\\n\\n \\/\\/ DELAY CHAINS ---------------------------------------------------------\\n \\/\\/ We need to another chain for each of our _delays:\\n \\/\\/ _mic -> _micGain -> _delays[i] -> _gains[i] -> _panners[i] -> _masterGain -> _compressor -> destination\\n\\n \\/\\/ Make some empty arrays to fill\\n _delays = new Array();\\n _delayTimes = new Array();\\n _gains = new Array();\\n _panners = new Array();\\n\\n for (i = 0; i < _nDelays; i++) {\\n\\n \\/\\/ Create delay object\\n _delays[i] = _cxt.createDelay(_maxEighths * eighthTime * 1.1);\\n \\/\\/ Asign a delayTime of some random integer (< _maxEighths) number of eighth notes\\n var nEighths = Math.ceil(Math.random() * _maxEighths); \\/\\/ integer num of eights up to max Eighths\\n _delayTimes[i] = (nEighths) * eighthTime; \\/\\/ Calculate time for this delay and store it\\n _delays[i].delayTime.value = _delayTimes[i]; \\/\\/ Apply delay time.\\n \\/\\/ Chain (_mic is already connected _micGain)\\n _micGain.connect(_delays[i]);\\n\\n \\/\\/ Create gain node\\n _gains[i] = _cxt.createGain();\\n \\/\\/ Set random gain up to within gain r\\n _gains[i].gain.value = Math.random() * gainRange + _minGain;\\n \\/\\/ Chain\\n _delays[i].connect(_gains[i]);\\n\\n \\/\\/ Create pan node\\n _panners[i] = _cxt.createStereoPanner();\\n \\/\\/ Set random pan\\n _panners[i].pan.value = (i % 10) \\/ 5 - 1;\\n \\/\\/ Chain\\n _gains[i].connect(_panners[i]);\\n\\n \\/\\/ Connect _masterGain (and therefore out to _compressor and destination)\\n _panners[i].connect(_masterGain);\\n }\\n\\n \\/\\/ INIT VISUALIZER ---------------------------------------------------------\\n \\/\\/ With more than a little help from: https:\\/\\/developer.mozilla.org\\/en-US\\/docs\\/Web\\/API\\/Web_Audio_API\\/Visualizations_with_Web_Audio_API\\n\\n \\/\\/ Objects \\/ Object Arrays\\n var analysers = new Array();\\n var canvases = new Array();\\n \\n orchW = $('.orchestra').width();\\n orchH = $('.orchestra').height();\\n numInRow = 10;\\n repW = (orchW \\/ numInRow);\\n\\n \\/\\/ Initiate and place canvases for all repeaters\\n for (i = 0; i < _nDelays; i++) {\\n\\n \\/\\/ Use the awesome power of arithmetic to put things in places\\n $('.orchestra').append('<canvas id=\\\"repeater-' + i + '\\\" width=\\\"' + (repW - 10) + '\\\" height=\\\"' + (repW - 10) + '\\\">');\\n var $canvas = $('#repeater-' + i);\\n var x = (((1 \\/ numInRow) \\/ 2) + (i % numInRow) * (1 \\/ numInRow)) * orchW + (Math.floor(Math.random() * 8) - 4);\\n var y = (-Math.sin(x * Math.PI \\/ orchW) + 1) * (orchH \\/ 2) - ((Math.floor(i \\/ numInRow) - 2) * repW); \\/\\/ Who remembers high school trig? This guy remembers high school trig.\\n $canvas.css('left', x);\\n $canvas.css('bottom', y); \\/\\/ Todo -- don't do this with JS, SCSS can probably handle this. And then everyone will be happier.\\n canvases[i] = $canvas[0].getContext('2d');\\n\\n \\/\\/ Create analyzer and connect to _micGain\\n analysers[i] = _cxt.createAnalyser(); \\/\\/ Create\\n _gains[i].connect(analysers[i]); \\/\\/ Chain \\n\\n \\/\\/ Set up an array to house data collected from analyser.\\n analysers[i].fftSize = 1024;\\n }\\n\\n \\/\\/ Do same for conductor (but he's bigger, and we'll just place him in CSS)\\n $('.orchestra').append('<canvas id=\\\"conductor\\\" width=\\\"' + (repW * 3) + '\\\" height=\\\"' + (repW * 3) + '\\\">');\\n conductorCanvas = $('#conductor')[0].getContext('2d');\\n conductorAnalyser = _cxt.createAnalyser();\\n _micGain.connect(conductorAnalyser);\\n\\n \\/\\/ Build array to house analysis data\\n var bufferLength = analysers[0].frequencyBinCount;\\n var dataArray = new Float32Array(bufferLength);\\n\\n \\/\\/ ANIMATE OSCILLOSCOPES\\n function draw() { \\/\\/Our drawing function to be called every frame\\n\\n drawVisual = requestAnimationFrame(draw); \\/\\/ Keep calling this from now on.\\n\\n for (j = 0; j < _nDelays + 1; j++) {\\n\\n if (j < _nDelays) {\\n analysers[j].getFloatTimeDomainData(dataArray); \\/\\/ Get analyser data\\n var canvasToDraw = canvases[j];\\n var canvasWidth = (repW - 10); \\/\\/ Get width and height\\n var canvasHeight = (repW - 10);\\n } else {\\n conductorAnalyser.getFloatTimeDomainData(dataArray); \\/\\/ Get analyser data\\n var canvasToDraw = conductorCanvas;\\n var canvasWidth = (repW * 3); \\/\\/ Get width and height\\n var canvasHeight = (repW * 3);\\n }\\n\\n canvasToDraw.clearRect(0, 0, canvasWidth, canvasHeight); \\/\\/ Clear canvas\\n canvasToDraw.strokeStyle = 'rgb(255,255,255)'; \\/\\/ Style the line\\n canvasToDraw.lineWidth = 2;\\n\\n canvasToDraw.beginPath(); \\/\\/ Draw the line\\n var sliceWidth = canvasWidth * 1.0 \\/ bufferLength;\\n var x = 0;\\n for (var i = 0; i < bufferLength; i++) {\\n var v = dataArray[i] * (canvasHeight \\/ 2) * 40;\\n var y = v + canvasHeight \\/ 2;\\n if (i === 0) { \\/\\/Either start or continue line\\n canvasToDraw.moveTo(x, y);\\n } else {\\n canvasToDraw.lineTo(x, y);\\n }\\n x += sliceWidth;\\n }\\n canvasToDraw.lineTo(canvasWidth, canvasHeight \\/ 2); \\/\\/ Finish in the right spot\\n canvasToDraw.stroke(); \\/\\/ Stroke it (T.W.S.S.)\\n }\\n }\\n draw(); \\/\\/ Start her up! Now we're drawing!\\n\\n \\/\\/ UI ---------------------------------------------------------\\n \\/\\/ Make sliders\\n \\/\\/ For DRY sake, these are the base options:\\n baseOptions = {\\n min: 0,\\n max: 1,\\n range: 'min',\\n step: 0.01,\\n orientation: 'vertical'\\n }\\n \\/\\/ Make slider to control _masterGain's level (for options, duplicate and extend baseOptions object to include slide callback)\\n $('.slider.masterGain').slider($.extend(true, {}, baseOptions, {\\n value: _masterGain.gain.value,\\n change: function(event, ui) {\\n _masterGain.gain.linearRampToValueAtTime(ui.value, _cxt.currentTime + 0.2); \\/\\/We want to set this with a ramp, to make the change gradual and remove potential pops\\n }\\n }));\\n \\/\\/ Ditto for _micGain\\n $('.slider.micGain').slider($.extend(true, {}, baseOptions, {\\n value: _micGainStart,\\n change: function(event, ui) {\\n _micGain.gain.linearRampToValueAtTime(ui.value * _gateOpen, _cxt.currentTime + 0.2);\\n }\\n }));\\n\\n \\/\\/ Gate Open Button\\n _gateOpenToggle = function() {\\n if (_gateOpen) {\\n $('.gate-open').removeClass('on');\\n _gateOpen = false;\\n } else {\\n $('.gate-open').addClass('on');\\n _gateOpen = true;\\n }\\n setTimeout(function() {\\n _micGain.gain.linearRampToValueAtTime($('.slider.micGain').slider('value') * _gateOpen, _cxt.currentTime + 0.2);\\n }, 500);\\n }\\n $('.gate-open').click(function(e) {\\n e.preventDefault();\\n _gateOpenToggle();\\n });\\n $(window).keyup(function(e) {\\n e.preventDefault();\\n if (e.which === 32) _gateOpenToggle();\\n });\\n\\n \\/\\/ Clear Delays\\n $('.clear-delays').click(function(e) {\\n \\/\\/ Force Mute. This will help us avoid pops from delays coming in and out of being\\n _micGain.gain.linearRampToValueAtTime(0, _cxt.currentTime + 0.05);\\n setTimeout(function() { \\/\\/ A bit after we mute\\n for (i = 0; i < _nDelays; i++) {\\n \\/\\/ Close mic gate\\n _gateOpen = false;\\n $('.gate-open').removeClass('on');\\n \\/\\/ Disconnect old gain object\\n _delays[i].disconnect();\\n _delays[i] = null; \\/\\/ I'm doing this in the hopes that it helps JS collect my garbage. I don't know if it's working. I worry these delay objects are just piling up somewhere.\\n \\/\\/ Create new delay object to replace it.\\n _delays[i] = _cxt.createDelay(_maxEighths * eighthTime * 1.1);\\n \\/\\/ Give it its old delay time\\n _delays[i].delayTime.value = _delayTimes[i];\\n \\/\\/ Rechain\\n _micGain.connect(_delays[i]);\\n _delays[i].connect(_gains[i]);\\n }\\n }, 200);\\n \\/\\/ Schedule unmuting (but gate stays closed)\\n setTimeout(function() {\\n _micGain.gain.linearRampToValueAtTime($('.slider.micGain').slider('value') * _gateOpen * 1, _cxt.currentTime + 1);\\n }, 500);\\n });\\n\\n}\",\"html_pre_processor\":\"none\",\"css_pre_processor\":\"scss\",\"js_pre_processor\":\"none\",\"html_classes\":\"\",\"css_starter\":\"normalize\",\"js_library\":null,\"created_at\":\"2016-04-16T16:19:51.000Z\",\"updated_at\":\"2019-05-24T20:19:57.000Z\",\"title\":\"Repeater Orchestra (1.0)\",\"description\":\"Create an orchestra of yourself. An orchestra of Repeaters repeat The Conductor (live mic feed) each with a randomized delay time (N eighth notes), volume and spatial distribution. Used to perform Terry Riley's composition \\\"In C\\\" at Codepen meetups.\\n\\nPerformed live at codepen meetup: http:\\/\\/codepen.io\\/poopsplat\\/post\\/codepen-chicago-june-2016\\n\\nNEEDS FINISHING! HALP ME!\",\"slug_hash\":\"ZWoLmo\",\"head\":\"\",\"private\":false,\"slug_hash_private\":\"37860f75a8eeb3ad3e358b7cc349485e\",\"has_animation\":true,\"team_id\":0,\"css_prefix\":\"neither\",\"template\":false,\"parent_id\":7838636,\"comments_count\":0,\"custom_screenshot_filename\":null,\"loves_count\":0,\"pick\":false,\"popularity_score\":0,\"views_count\":0,\"pick_visible_at\":null,\"cpid\":\"01541fdf-0858-72ba-b676-a3525bab4c7e\",\"is_new_editor_pen\":false,\"protected\":false,\"access\":\"Public\",\"pen_hash\":null,\"hashid\":\"ZWoLmo\"}"}