Ajax Loader
HTML
 
1
 
2
 
3
<script class="cssdeck" src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
4
  <div class="menu">
5
            <span class="title">Synth From Hell</span>
6
            <div class="options left">
7
                <label for="instrument">Instruments</label>
8
                <div class="dropdown">
9
                    <select id='instrument' class="dropdown-select">
10
                        <option value="1">Church Organ</option>
11
                        <option value="2">Cloud Song</option>
12
                        <option value="3">Tom Crazy</option>
13
                        <option value="4">Phone</option>
14
                    </select>
15
                </div>
16
                <span>
17
                    <input type="checkbox" value='vibrato' id="vibrato">
18
                    <label for="vibrato">Vibrato</label>
19
                </span>
20
            </div>
21
            <div class="options right">
22
                <input type="checkbox" checked value='animate' id="animate">
23
                <label for="animate">Animate</label>
24
                <input type="checkbox" value='notes' id="notes">
25
                <label for="notes">Notes</label>
26
                <input type="checkbox" value='keymap' id="keymap">
27
                <label for="keymap">Key Map</label>
28
            </div>
29
        </div>
30
        <div class="volume">
31
            <input id="volume" type="range" min="0" max="1" step="0.1" value="0.1"/>
32
            <label for="volume">Gain</label>
33
        </div>
34
        <div class="octave">
35
            <p>Octave</p>
36
            <div id="oct1" class="box b-active">1</div>
37
            <div id="oct2" class="box">2</div>
38
        </div>
39
        <div class="scene">
40
            <div class="piano animate" id="piano">   
41
            </div>
42
        </div>
43
        <div class="info">
44
            <p>
45
                Use the keyboard to play the notes. <br> Press key <strong>1</strong> or <strong>2</strong> to change the octaves.
46
            </p>
47
        </div>
48
        <div class="credits">
49
            <p>
50
                Allan Esquina
51
            </p>
52
        </div>
 
CSS
* {
1
* {
2
    padding: 0;
3
    margin: 0; 
4
}
5
$colorMenu: #191426;
6
body {
7
    background-image: radial-gradient(#473962 15%, #2E2344 60%);
8
    font: 20px/20px "Lucida Grande", Tahoma, Verdana, sans-serif;
9
    color:#C1B8B7;
10
    overflow: hidden;
11
}
12
html, body {
13
    height: 100%;
14
}
15
@mixin createKey( $colorLeft, $colorRight, $colorTop, $colorFront, $borderColor, $keyWidth, $keyHeight, $keyDeep ) {
16
    transform-style:preserve-3d; 
17
    width: $keyWidth;
18
    height: $keyHeight;
19
    position: absolute;
20
    transform-origin: 0% 0% (-$keyDeep);
21
    backface-visibility: hidden;
22
    transition:.2s;
23
 
24
    .size-lr {
25
        width: $keyDeep;
26
        height: $keyHeight;
27
    }
28
    .size-t {
29
        width: $keyWidth;
30
        height: $keyDeep;
31
    }
32
   .tec {
33
        position: absolute;
34
        top: 0;
35
        left: 0;
36
        transform-origin:0% 0%;
37
        border:1px solid $borderColor;
38
   }
39
   .y90-left {
40
        transform: rotateY(90deg);
41
        background: $colorLeft;
42
        background-image: linear-gradient(to bottom right, $colorTop, $colorLeft);
43
    }
44
   .y90-right {
45
        transform: rotateY(90deg);
46
        left: $keyWidth;
47
        background: $colorRight;
48
        background-image: linear-gradient(to bottom right, $colorTop, $colorRight);
49
    }
50
   .x90-top {
51
        transform: rotateX(-90deg);
52
        background: $colorTop;
53
        background-image: linear-gradient(to bottom right, $colorFront, $colorTop);
54
    }
55
   .x90-front {
56
        transform: rotateX(0deg);
57
        width: $keyWidth;
58
        height: $keyHeight;
59
        background: $colorFront;
60
        background-image: linear-gradient(to top bottom, $colorTop, $colorFront);
61
        position: relative;
62
    }
63
    .x90-front2 {
64
        transform: rotateY(0deg);
65
        margin-left: $keyWidth;
66
        width: $keyWidth;
67
        height: $keyHeight;
68
        background: $colorFront;
69
        background-image: linear-gradient(to bottom right, $colorRight, $colorFront);
70
 
71
    }
72
}
73
.pressed {
74
    transform: rotateX(-10deg);
75
}
76
.pressed-black {
77
    transform: rotateX(-10deg) translateZ(-150px) !important;
78
    margin-top: -20px !important;
79
}
80
.piano {
81
    transform-style:preserve-3d; 
82
    perspective:1500; 
83
    position: absolute;
84
    width: 1260px;
85
    height: 70px;
86
    top:0;
87
    left:0;
88
    right: 0;
89
    bottom: 0;
90
    margin:auto;
91
    margin-top: 300px;
92
    transform:translateZ(10px) rotateY(0deg) rotateX(-50deg);            
93
}
94
 
95
.white-key-group {
96
    z-index: 1;
97
    @include createKey( #999, #999, #fff, #eee, #ccc, 60px, 70px, 400px );    
98
}
99
.black-key-group {
100
    margin-top: -42px;
101
    transform: translateZ(-150px);
102
    z-index: 100;
103
    @include createKey( #222, #222, #111, #333, #222, 30px, 40px, 250px );
104
 
105
    .f-notes {
106
        color:#eee;
107
        top:5%;
108
    }
109
    .f-keymap {
110
        color:#eee;
111
        bottom:5%;
112
    }
113
}
114
 
115
.active {
116
    box-shadow: 0px 0px 150px 10px #72ECFC
117
}
118
.scene {
119
    position: absolute;
120
    width: 1200px;
121
    height: 200px;
122
    top:-20%;
123
    left:-5%;
124
    right: 0;
125
    bottom:0;
126
    margin: auto;
127
}
128
.menu {
129
    position: fixed;
130
    top: 0;
131
    width: 100%;
132
    height: 70px;
133
    background: $colorMenu; 
134
    text-align: center;
135
    color:#C1B8B7;
136
    font-size: 14px;
137
    line-height: 70px;
138
    .options {
139
        border-left: 1px solid lighten( $colorMenu, 10 );
140
        float: right;
141
        height: 70px;
142
        line-height: 70px;
143
        &.left {
144
           width: 400px;
145
        }
146
        &.right {
147
            width: 350px;
148
        }
149
    }
150
    .title {
151
        float: left;
152
        font-size: 20px;
153
        margin-left: 7%;
154
    }
155
    label {
156
        margin: 0 15px;
157
        vertical-align: middle;
158
        padding-top: 3px;
159
        line-height: 20px;
160
    }
161
}
162
 
163
.f-notes {
164
    text-align: center;
165
    font-weight: bold;
166
    font-size: 16px;
167
    color:#222;
168
    position: absolute;
169
    top: 10%;
170
    width: 100%;
171
    text-align: center;
172
    visibility: hidden;
173
}
174
.f-keymap {
175
    text-align: center;
176
    font-weight: bold;
177
    font-size: 12px;
178
    color:#222;
179
    position: absolute;
180
    bottom: 10%;
181
    width: 100%;
182
    text-align: center;
183
    visibility: hidden;
184
}
185
.info-active {
186
    visibility: visible;
187
}
188
.info {
189
   position: absolute;
190
   left: 50px;
191
   bottom:30px;
192
   font-size: 14px;
193
}
194
.credits {
195
    position: absolute;
196
    right: 50px;
197
    bottom: 30px;
198
    font-size: 14px;
199
}
200
.octave {
201
    position: absolute;
202
    top: 100px;
203
    left:25px; 
204
    z-index:300;
205
    p {
206
        font-size: 14px;
207
        margin-bottom: 5px;
208
    }
209
    .box {
210
        float: left;
211
        line-height: 50px;
212
        text-align: center;
213
        width: 50px;
214
        height: 50px;
215
        border:1px solid #ccc;
216
        border-radius: 7px;
217
        margin-right: 10px;
218
        transition:.4s;
219
        cursor:pointer;
220
 
221
        &.b-active {
222
            background: #ccc;
223
            color:#191426;
224
            &:hover {
225
                background: #ccc;
226
            }
227
        }
228
        &:hover {
229
            background: lighten( $colorMenu, 20 );
230
 
231
        }
232
    }
233
}
234
.volume {
235
    position: absolute;
236
    top: 130px;
237
    right: -30px;
238
    height: 50px;
239
    font-size: 14px;
240
    transform: rotate(-90deg);
241
    opacity: 0.2;
242
    z-index: 1000;
243
    transition:.2s;
244
 
245
    &:hover {
246
        opacity: 0.9;
247
    }
248
    label {
249
        display: block;
250
        text-align: center; 
251
    }
252
}
253
 
254
//Animate
255
.animate {
256
    animation-name: expand;
257
    animation-duration: 10s;
258
    animation-iteration-count: infinite;
259
    animation-direction: alternate;
260
}
261
 
262
@keyframes expand {
263
  0% {    
264
    // transform:translateZ(-100px) rotateY(-10deg) rotateX(-10deg);    
265
    transform: rotateY(-30deg) rotateX(-40deg);            
266
  } 
267
  100% {
268
    transform: rotateY(20deg) rotateX(-35deg);            
269
  }
270
}
271
 
272
/* 
273
 * CUSTOM DROP 
274
 * http://codepen.io/Thibaut/pen/Jasci
275
 */
276
 
277
.dropdown {
278
  display: inline-block;
279
  position: relative;
280
  overflow: hidden;
281
  vertical-align: middle;
282
  height: 28px;
283
  width: 150px;
284
  background: #f2f2f2;
285
  line-height: 20px;
286
  border: 1px solid;
287
  border-color: white #f7f7f7 whitesmoke;
288
  border-radius: 3px;
289
  background-image: -webkit-linear-gradient(top, transparent, rgba(0, 0, 0, 0.06));
290
  background-image: -moz-linear-gradient(top, transparent, rgba(0, 0, 0, 0.06));
291
  background-image: -o-linear-gradient(top, transparent, rgba(0, 0, 0, 0.06));
292
  background-image: linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.06));
293
  -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.08);
294
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.08);
295
}
296
 
297
.dropdown:before, .dropdown:after {
298
  content: '';
299
  position: absolute;
300
  z-index: 2;
301
  top: 9px;
302
  right: 10px;
303
  width: 0;
304
  height: 0;
305
  border: 4px dashed;
306
  border-color: #888888 transparent;
307
  pointer-events: none;
308
}
309
 
310
.dropdown:before {
311
  border-bottom-style: solid;
312
  border-top: none;
313
}
314
 
315
.dropdown:after {
316
  margin-top: 7px;
317
  border-top-style: solid;
318
  border-bottom: none;
319
}
320
 
321
.dropdown-select {
322
  position: relative;
323
  width: 130%;
324
  margin: 0;
325
  padding: 6px 8px 6px 10px;
326
  height: 28px;
327
  line-height: 14px;
328
  font-size: 16px;
329
  color: #62717a;
330
  text-shadow: 0 1px white;
331
  background: #f2f2f2; /* Fallback for IE 8 */
332
  background: rgba(0, 0, 0, 0) !important; /* "transparent" doesn't work with Opera */
333
  border: 0;
334
  border-radius: 0;
335
  -webkit-appearance: none;
336
}
337
 
338
.dropdown-select:focus {
339
  z-index: 3;
340
  width: 100%;
341
  color: #394349;
342
  outline: 2px solid #49aff2;
343
  outline: 2px solid -webkit-focus-ring-color;
344
  outline-offset: -2px;
345
}
346
 
347
.dropdown-select > option {
348
  margin: 3px;
349
  padding: 6px 8px;
350
  text-shadow: none;
351
  background: #f2f2f2;
352
  border-radius: 3px;
353
  cursor: pointer;
354
}
355
 
356
/* Fix for IE 8 putting the arrows behind the select element. */
357
 
358
.lt-ie9 .dropdown {
359
  z-index: 1;
360
}
361
 
362
.lt-ie9 .dropdown-select {
363
  z-index: -1;
364
}
365
 
366
.lt-ie9 .dropdown-select:focus {
367
  z-index: 3;
368
}
369
 
370
/* Dirty fix for Firefox adding padding where it shouldn't. */
371
 
372
@-moz-document url-prefix() {
373
  .dropdown-select {
374
    padding-left: 6px;
375
  }
376
}
377
 
378
/* 
379
 * CUSTOM CHECKBOX  
380
 * http://codepen.io/CreativeJuiz/pen/BiHzp 
381
 */
382
 
383
/* Base for label styling */
384
[type="checkbox"]:not(:checked),
385
[type="checkbox"]:checked {
386
    position: absolute;
387
    left: -9999px;
388
}
389
[type="checkbox"]:not(:checked) + label,
390
[type="checkbox"]:checked + label {
391
    position: relative;
392
    padding-left: 25px;
393
    cursor: pointer;
394
}
395
/* checkbox aspect */
396
[type="checkbox"]:not(:checked) + label:before,
397
[type="checkbox"]:checked + label:before {
398
    content: '';
399
    position: absolute;
400
    left:0; top: 2px;
401
    width: 17px; height: 17px;
402
    border: 1px solid #aaa;
403
    background: #f8f8f8;
404
    border-radius: 3px;
405
    box-shadow: inset 0 1px 3px rgba(0,0,0,.3)
406
}
407
/* checked mark aspect */
408
[type="checkbox"]:not(:checked) + label:after,
409
[type="checkbox"]:checked + label:after {
410
    content: 'X';
411
    position: absolute;
412
    top: 0; 
413
    left: -2px;
414
    font-size: 35px;
415
    color: #47AFC4;
416
    transition: all .2s;
417
}
418
/* checked mark aspect changes */
419
[type="checkbox"]:not(:checked) + label:after {
420
    opacity: 0;
421
    transform: scale(0);
422
}
423
[type="checkbox"]:checked + label:after {
424
    opacity: 1;
425
    transform: scale(1);
426
}
427
/* disabled checkbox */
428
[type="checkbox"]:disabled:not(:checked) + label:before,
429
[type="checkbox"]:disabled:checked + label:before {
430
    box-shadow: none;
431
    border-color: #bbb;
432
    background-color: #ddd;
433
}
434
[type="checkbox"]:disabled:checked + label:after {
435
    color: #999;
436
}
437
[type="checkbox"]:disabled + label {
438
    color: #aaa;
439
}
440
/* accessibility */
441
[type="checkbox"]:checked:focus + label:before,
442
[type="checkbox"]:not(:checked):focus + label:before {
443
    border: 1px dotted blue;
444
}
 
JavaScript
;(function( win, doc, $ ){
1
;(function( win, doc, $ ){
2
 
3
  'use strict';
4
 
5
  var __KEYSPRESSED = [], 
6
    __PLAYINGNOTES = [], 
7
    __STOPPEDNOTES = [],
8
    __INSTRUMENT = 1, 
9
    __VOLUME = 0.1, 
10
    __VIBRATO = false, 
11
    __OCTAVE = 3,
12
    audio_context, 
13
    oscillator;
14
 
15
  function Piano( octave, target ) {
16
    this.octave = octave;
17
    this.notes = ['c', 'd', 'e', 'f', 'g', 'a', 'b'];
18
    this.susNotes = ['c', 'd', 'f', 'g', 'a'];
19
    this.mapNotes = ['c', 'd', 'e', 'f', 'g', 'a', 'b','c#', 'd#', 'f#', 'g#', 'a#', 'c', 'd', 'e', 'c#', 'd#', 'f#', 'g#'];
20
    this.keymap = ['a', 's', 'd', 'f', 'g','h', 'j','w',  'e',  'r',   't', 'y',  'k', 'l', 'ç',  'u', 'i',   'o',  'p'];
21
    this.target = target;
22
    this.init();
23
  }
24
 
25
  Piano.prototype = {
26
    init: function() {
27
      this.$target = $( this.target );
28
      this.createKeys();
29
      this.bindEvents();
30
      this.changeOctave();
31
    },
32
    createKeys: function() {
33
      var key,whiteW=60, blackW = ( whiteW / 2 ), o = this.octave, wWidth=0, bWidth=blackW + (blackW/2);
34
      for( var k=0; k<o; k+=1 ) {
35
 
36
        for( var i=0, l=this.notes.length; i<l; i+=1 ) {
37
          key = this.createKey();
38
          key.find( '.f-notes' ).html( this.notes[ i ].toUpperCase() );
39
          key.addClass( 'white-key-group' );
40
          key.addClass( 'key' );
41
          key.addClass( 'tom-' + this.notes[ i ] );
42
          key.attr('data-note', this.notes[ i ].toUpperCase() + ( k + 3 ) );
43
          key.css('left', wWidth + 'px' );
44
          this.$target.append( key );
45
          wWidth += whiteW;
46
 
47
          if( i !== 2 && i !== 6 ) {
48
            key = this.createKey();
49
            key.find( '.f-notes' ).html( this.notes[ i ].toUpperCase() + '#' );
50
            key.addClass( 'black-key-group' );
51
            key.addClass( 'key' );
52
            key.addClass( 'tom-s' + this.notes[ i ] );
53
            key.attr('data-note', this.notes[ i ].toUpperCase()  + '#' + ( k + 3 ) );
54
            key.css('left', bWidth + 'px' );
55
            this.$target.append( key );
56
          }
57
          bWidth += whiteW;
58
        }
59
      }
60
    },
61
    changeOctave: function( octave ) {
62
      var self = this;
63
 
64
      self.$target.find( '.f-keymap' ).html( '' );
65
      var i=0, j=0, oc = octave || __OCTAVE; 
66
      this.mapNotes.forEach( function( e ) { 
67
        if( i===12 ) {
68
          oc++ ; i=0; 
69
        } 
70
        self.$target.find( 'div[data-note='+ e.toUpperCase() + oc + ']').find('.f-keymap').html( self.keymap[ j ].toUpperCase() ); 
71
        i++; 
72
        j++; 
73
      });
74
    },
75
    createKey: function() {
76
      return  $('<div><div class="tec y90-left size-lr"></div><div class="tec y90-right size-lr"></div><div class="tec x90-top keyTop size-t"></div><div class="tec x90-front"><span class="f-keymap"></span><span class="f-notes"></span></div> </div> ');
77
    },
78
    bindEvents: function() {
79
      var $keys = $( '.key' );
80
      $keys.on( 'mouseenter', function( e ) {
81
        var $el = $( e.currentTarget ), freqs, freq;
82
        if( $el.hasClass('white-key-group') ) {
83
          $el.addClass( 'pressed' );
84
        } else {
85
          $el.addClass( 'pressed-black ' );
86
        }
87
        $el.addClass( 'active' );
88
        freq = mplay.getFrequency( $el.attr( 'data-note' ) );
89
        freqs = mplay.getInstrument( freq, __INSTRUMENT, __VIBRATO );
90
        mplay.play( freqs );
91
      });
92
      $keys.on( 'mouseout', function( e ) {
93
        var $el = $( e.currentTarget );
94
        if( $el.hasClass('white-key-group') ) {
95
          $el.removeClass( 'pressed' );
96
        } else {
97
          $el.removeClass( 'pressed-black ' );
98
        }
99
        $el.removeClass( 'active' );
100
        mplay.stop();
101
      });
102
    }
103
  };
104
 
105
  $( doc ).ready(function() {
106
    var $oct1 = $( '#oct1' ),$oct2 = $( '#oct2' );
107
    var _changeOctave = function( oct ) {
108
      if( oct ) {       
109
        $oct1.addClass( 'b-active' );
110
        $oct2.removeClass( 'b-active' );
111
      } else {        
112
        $oct1.removeClass( 'b-active' );
113
        $oct2.addClass( 'b-active' );
114
      }
115
    };
116
    
117
    try {
118
      var Tmp = win.AudioContext || win.webkitAudioContext;
119
      audio_context = new Tmp();
120
    } catch (e) {
121
      alert('No web audio oscillator support in this browser');
122
    }
123
 
124
    $( doc ).keydown(function( e ) {
125
      e.preventDefault();
126
      
127
      if( __KEYSPRESSED.indexOf( e.which ) === -1 ) {
128
        __KEYSPRESSED.push( e.which );
129
      }
130
      if( e.which === 49 ) {
131
        __OCTAVE = 3;
132
        piano.changeOctave();
133
        _changeOctave( true );
134
        
135
      }
136
      if( e.which === 50 ) {
137
        __OCTAVE = 4;
138
        piano.changeOctave();
139
        _changeOctave( false );
140
      }
141
    });
142
    $( doc ).keyup(function( e ) {
143
      e.preventDefault();
144
      var io = __KEYSPRESSED.indexOf( e.which );
145
      if( io !== -1 ) {
146
        __KEYSPRESSED.splice( io, 1 );
147
        __STOPPEDNOTES.push( e.which );
148
      }
149
    });
150
    $( '#vibrato').on( 'change', function( e ) {
151
      __VIBRATO = $( e.currentTarget ).is(':checked') ? true : false;
152
    });
153
    $( '#animate').on( 'change', function( e ) {
154
      if( $( e.currentTarget ).is(':checked') ) {
155
        win.piano.$target.addClass( 'animate' );
156
      } else {
157
        win.piano.$target.removeClass( 'animate' );
158
      }
159
    });
160
    $( '#instrument').on( 'change', function( e ) {
161
      __INSTRUMENT = +e.currentTarget.selectedIndex + 1;
162
    });
163
    $( '#volume').on( 'change', function( e ) {
164
      __VOLUME = +e.currentTarget.value;
165
    });
166
 
167
    $( '#notes' ).on( 'change', function( e ) {
168
      if( $( e.currentTarget ).is(':checked') ) {
169
        win.piano.$target.find( '.f-notes' ).addClass( 'info-active' );
170
      } else {
171
        win.piano.$target.find( '.f-notes' ).removeClass( 'info-active' );
172
      }
173
    });
174
    $( '#keymap' ).on( 'change', function( e ) {
175
      if( $( e.currentTarget ).is(':checked') ) {
176
        win.piano.$target.find( '.f-keymap' ).addClass( 'info-active' );
177
      } else {
178
        win.piano.$target.find( '.f-keymap' ).removeClass( 'info-active' );
179
      }
180
    });
181
    $( '.box' ).on( 'click', function( e ) {
182
      if( $( e.currentTarget ).attr( 'id' ) === 'oct1' ) {
183
        __OCTAVE = 3;
184
        piano.changeOctave();
185
        _changeOctave( true );
186
      } else {
187
        __OCTAVE = 4;
188
        piano.changeOctave();
189
        _changeOctave( false );
190
      }
191
    });
192
 
193
    win.piano = new Piano(3, '#piano');
194
    setInterval( mplay.render, 0 );
195
  });
196
 
197
 
198
  var mplay = {};
199
  var fq = [];
200
  mplay.play = function ( freqs, key ) {
201
    var oscs = [], o, i, g;
202
    freqs.forEach( function( freq ) {
203
      g = createGain();
204
      g.gain.value = __VOLUME;
205
      o = audio_context.createOscillator();
206
      o.frequency.value = freq;
207
      o.connect( g );
208
      g.connect( audio_context.destination );
209
      _play( 0 );
210
      oscs.push( o );
211
    });
212
    fq[ key ] = oscs;
213
 
214
    function createGain() {
215
      var out;
216
      if( audio_context.createGain ) {
217
        out = audio_context.createGain();
218
      } else if ( audio_context.createGainNode ) {
219
        out = audio_context.createGainNode();
220
      }
221
      return out;
222
    }
223
    function _play( arg ) {
224
      if( o.noteOn ) {
225
        o.noteOn( arg );
226
      } else if ( o.start ) {
227
        o.start( arg );
228
      }
229
    }
230
  };
231
 
232
  mplay.stop = function ( key ) {
233
    fq[ key ].forEach( function( o ) {
234
      _stop( 0, o );
235
    });
236
    function _stop( arg, o ) {
237
      if( o.noteOff ) {
238
        o.noteOff( arg );
239
      } else if ( o.stop ) {
240
        o.stop( arg );
241
      }
242
    }
243
 
244
  };
245
 
246
  mplay.getKeyMap = function( map ) {
247
    switch( map ) {
248
      case 65:
249
        return 'C' + __OCTAVE;
250
      case 83:
251
        return 'D' + __OCTAVE;
252
      case 68:
253
        return 'E' + __OCTAVE;
254
      case 70:
255
        return 'F' + __OCTAVE;
256
      case 71:
257
        return 'G' + __OCTAVE;
258
      case 72:
259
        return 'A' + __OCTAVE;
260
      case 74:
261
        return 'B' + __OCTAVE;
262
      case 87:
263
        return 'C#' + __OCTAVE;
264
      case 69:
265
        return 'D#' + __OCTAVE;
266
      case 82:
267
        return 'F#' + __OCTAVE;
268
      case 84:
269
        return 'G#' + __OCTAVE;
270
      case 89:
271
        return 'A#' + __OCTAVE;
272
      case 75:
273
        return 'C' + ( __OCTAVE + 1 );
274
      case 76:
275
        return 'D' + ( __OCTAVE + 1 );
276
      case 186:
277
        return 'E' + ( __OCTAVE + 1 );
278
      case 220:
279
        return 'F' + ( __OCTAVE + 1 );
280
      case 85:
281
        return 'C#' + ( __OCTAVE + 1 );
282
      case 73:
283
        return 'D#' + ( __OCTAVE + 1 );
284
      case 79:
285
        return 'F#' + ( __OCTAVE + 1 );
286
      case 80:
287
        return 'G#' + ( __OCTAVE + 1 );
288
      case 65:
289
        return 'A#' + ( __OCTAVE + 1 );
290
      default:
291
        return false;
292
    }
293
  };
294
 
295
  mplay.render = function() {
296
    var freq, keyMap, $el;
297
    __KEYSPRESSED.forEach( function( key ) {
298
      if( __PLAYINGNOTES.indexOf( key ) === -1 ) {
299
        keyMap = mplay.getKeyMap( key );
300
        if( keyMap ) {
301
          freq = mplay.getFrequency( keyMap );
302
          mplay.play( mplay.getInstrument( freq, __INSTRUMENT, __VIBRATO ), key );
303
          __PLAYINGNOTES.push( key );
304
          $el = $('div[data-note=' + keyMap + ']');
305
 
306
          if( $el.hasClass('white-key-group') ) {
307
            $el.addClass( 'pressed' );
308
          } else {
309
            $el.addClass( 'pressed-black ' );
310
          }
311
          $el.addClass( 'active' );
312
        }
313
      }
314
    });
315
    __STOPPEDNOTES.forEach( function( key ) {
316
      keyMap = mplay.getKeyMap( key );
317
      if( keyMap ) {
318
        mplay.stop( key );
319
        __STOPPEDNOTES.splice( __STOPPEDNOTES.indexOf( key ), 1 );
320
        __PLAYINGNOTES.splice( __PLAYINGNOTES.indexOf( key ), 1 );
321
        $el = $('div[data-note=' + keyMap + ']');
322
        if( $el.hasClass('white-key-group') ) {
323
          $el.removeClass( 'pressed' );
324
        } else {
325
          $el.removeClass( 'pressed-black ' );
326
        }
327
        $el.removeClass( 'active' );
328
      }
329
    });
330
  };
331
 
332
  // From Retrojs
333
  // https://github.com/eshiota/retro-audio-js
334
  mplay.getFrequency= function (note) {
335
    var notes = ["A", "A#", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#"], octave, keyNumber;
336
 
337
    if (note.length === 3) {
338
      octave = note.charAt(2);
339
    } else {
340
      octave = note.charAt(1);
341
    }
342
    octave = +octave + 1;
343
 
344
    keyNumber = notes.indexOf(note.slice(0, -1));
345
 
346
    if (keyNumber < 3) {
347
      keyNumber = keyNumber + 12 + ((octave - 1) * 12) + 1;
348
    } else {
349
      keyNumber = keyNumber + ((octave - 1) * 12) + 1;
350
    }
351
 
352
    // Return frequency of note
353
    return Math.floor(440 * Math.pow(2, (keyNumber - 49) / 12));
354
  };
355
  mplay.getInstrument = function( freq, instrument, vibrato ) {
356
    var freqs = [];
357
 
358
    switch( instrument ) {
359
      case 1:
360
        freqs.push( freq );
361
        freqs.push( freq * 2 );
362
        freqs.push( freq * 4 );
363
        freqs.push( freq * 8.5);
364
        freqs.push( freq * 19 );
365
        freqs.push( freq / 2 );
366
        break;
367
      case 2:
368
        freqs.push( freq );
369
        freqs.push( freq * (freq / ( freq -1 ) ) );
370
        freqs.push( freq * (freq / ( freq -5 ) ) );
371
        freqs.push( freq * (freq * ( freq -22 ) ) );
372
        freqs.push( freq * 4 );       
373
        freqs.push( freq / 2 );
374
        freqs.push( freq / 3 );
375
        break;
376
      case 3:
377
        freqs.push( freq );
378
        freqs.push( freq * (freq * ( freq -122 ) ) );
379
        freqs.push( freq * (freq * ( freq -22 ) ) );
380
        freqs.push( freq * (freq * ( freq -2 ) ) );
381
        freqs.push( freq * 23 );
382
        freqs.push( freq * 1.221 );
383
        freqs.push( freq / 2 );
384
        freqs.push( freq / 2.2 );
385
        freqs.push( freq / 3 );
386
        break;
387
      case 4:
388
        freqs.push( freq * 2 );
389
        freqs.push( freq / 2 );
390
        break;
391
 
392
    }
393
    if( vibrato ) {
394
      freqs.push( freq * (freq / ( freq -5 ) ) );
395
    }
396
    return freqs;
397
  };
398
}( window, document, $ )); 
 

Synth From Hell

CSSDeck G+