Skip to content

Commit

Permalink
Add sound
Browse files Browse the repository at this point in the history
  • Loading branch information
cifkao committed Feb 16, 2016
1 parent 683f043 commit 1aeeb2a
Show file tree
Hide file tree
Showing 5 changed files with 160 additions and 4 deletions.
41 changes: 41 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@
Appearance<span class="caret"></span>
</a>
</li>
<li>
<a href="#sound" data-toggle="tab" role="tab" aria-controls="sound">
<i class="fa fa-fw fa-volume-up" aria-hidden="true"></i>
Sound<span class="caret"></span>
</a>
</li>
<li>
<a href="#about" data-toggle="tab" role="tab" aria-controls="about">
<i class="fa fa-fw fa-question-circle" aria-hidden="true"></i>
Expand Down Expand Up @@ -193,6 +199,40 @@
</div>
<div class="alert alert-info" role="alert"><strong>Tip:</strong> Use your mouse wheel to zoom in or out.</div>
</div>
<div role="tabpanel" class="tab-pane" id="sound">
<div class="panel panel-default">
<div class="panel-heading">Sound</label></div>
<div class="panel-body">
<div class="form-horizontal">
<div class="form-group">
<label class="control-label col-xs-5 col-sm-4 col-md-3">Enable sound</label>
<div class="col-xs-6 col-sm-7 col-md-8">
<div class="checkbox">
<label><input name="sound-on" id="sound-on" type="checkbox"> <i class="fa fa-lg fa-volume-off"></i></label>
</div>
</div>
</div>
<div class="form-group">
<label for="gain" class="control-label col-xs-5 col-sm-4 col-md-3">Gain</label>
<div class="col-xs-6 col-sm-4 col-md-3">
<input type="number" class="form-control" id="gain" min="0" max="1" step="0.1" value="0.3">
</div>
</div>
<div class="form-group">
<label for="synth-type" class="control-label col-xs-5 col-sm-4 col-md-3">Synth type</label>
<div class="col-xs-6 col-sm-4 col-md-3">
<select class="form-control" name="synth-type" id="synth-type">
<option value="sine">Sine</option>
<option value="square">Square</option>
<option value="sawtooth">Sawtooth</option>
<option value="triangle">Triangle</option>
</select>
</div>
</div>
</div>
</div>
</div>
</div>
<div role="tabpanel" class="tab-pane" id="about">
<div class="panel panel-default">
<div class="panel-heading">What is TonnetzViz?</div>
Expand Down Expand Up @@ -280,6 +320,7 @@ <h4 class="modal-title" id="scheme-editor-label">Edit colour scheme</h4>
<script type="text/javascript" src="js/jsoneditor.min.js"></script>

<script type="text/javascript" src="js/storage.js"></script>
<script type="text/javascript" src="js/audio.js"></script>
<script type="text/javascript" src="js/tonnetz.js"></script>
<script type="text/javascript" src="js/midi.js"></script>
<script type="text/javascript" src="js/keyboard.js"></script>
Expand Down
107 changes: 107 additions & 0 deletions js/audio.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
var audio = (function() {
"use strict";

var Note = function(ctx, type, frequency, attack, release, output) {
this.oscillator = ctx.createOscillator();
this.oscillator.type = type;
this.oscillator.frequency.value = frequency;
this.gain = ctx.createGain();
this.gain.gain.value = 0;

this.oscillator.connect(this.gain);
this.gain.connect(output);

this.ctx = ctx;
this.attack = attack;
this.release = release;
};

Note.prototype.start = function() {
this.oscillator.start();
this.gain.gain.setValueAtTime(0, this.ctx.currentTime);
this.gain.gain.linearRampToValueAtTime(1, this.ctx.currentTime + this.attack);
};

Note.prototype.stop = function() {
this.gain.gain.setValueAtTime(this.gain.gain.value, this.ctx.currentTime);
this.gain.gain.linearRampToValueAtTime(0, this.ctx.currentTime + this.release);
var self = this;
setTimeout(function() {
self.gain.disconnect();
self.oscillator.stop();
self.oscillator.disconnect();
}, Math.floor(this.release * 1000));
};


var module = {};

var audioCtx, notes, gain;
var enabled = false;
var synthType;

var CHANNELS = 17;
var ATTACK = 0.05;
var RELEASE = 0.1;


module.init = function() {
var AudioContext = window.AudioContext || window.webkitAudioContext;
if (AudioContext) {
audioCtx = new AudioContext();
gain = audioCtx.createGain();
gain.connect(audioCtx.destination);
} else {
// display an alert
}

notes = $.map(Array(CHANNELS), function() { return {}; });

$('#sound-on').click(function() {
enabled = !enabled;
$(this).next('i').toggleClass('fa-volume-off fa-volume-up');
});

$('#synth-type').change(function() {
synthType = $(this).val();
}).change();

$('#gain').on('input change propertychange paste', function() {
gain.gain.value = Math.min(1, Math.max(Number($(this).val()), 0));
}).change();
};

module.noteOn = function(channel, pitch) {
if (!audioCtx || !enabled) return;

if (!(pitch in notes[channel])) {
notes[channel][pitch] =
new Note(audioCtx, synthType, pitchToFrequency(pitch),
ATTACK, RELEASE, gain);
notes[channel][pitch].start();
}
};

module.noteOff = function(channel, pitch) {
if (!audioCtx) return;

if (pitch in notes[channel]) {
notes[channel][pitch].stop();
delete notes[channel][pitch];
}
};

module.allNotesOff = function(channel) {
for (var i=0; i<CHANNELS; i++) {
for (var pitch in notes[channel]) {
module.noteOff(channel, pitch);
}
}
};

var pitchToFrequency = function(pitch) {
return Math.pow(2, (pitch - 69)/12) * 440;
};

return module;
})();
4 changes: 2 additions & 2 deletions js/keyboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ var keyboard = (function() {

var note = getPitchFromKeyboardEvent(event);
if (note != null) {
tonnetz.noteOn(getChannel(), note);
tonnetz.noteOn(16, note);
}
};

Expand All @@ -60,7 +60,7 @@ var keyboard = (function() {

var note = getPitchFromKeyboardEvent(event);
if (note != null) {
tonnetz.noteOff(getChannel(), note);
tonnetz.noteOff(16, note);
}
};

Expand Down
1 change: 1 addition & 0 deletions js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ $(function(){

storage.init();
colorscheme.init('default');
audio.init();
tonnetz.init();
midi.init();
keyboard.init();
Expand Down
11 changes: 9 additions & 2 deletions js/tonnetz.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ var tonnetz = (function() {
sustain = false;

var SQRT_3 = Math.sqrt(3);
var CHANNELS = 17; // the 17th channel is for the computer keyboard


module.init = function() {
Expand All @@ -43,7 +44,7 @@ var tonnetz = (function() {
};
});

channels = $.map(Array(16), function(_, i) {
channels = $.map(Array(CHANNELS), function(_, i) {
return {
'number': i,
'pitches': {},
Expand All @@ -58,6 +59,8 @@ var tonnetz = (function() {


module.noteOn = function(c, pitch) {
audio.noteOn(c, pitch);

if (!(pitch in channels[c].pitches)) {
var i = pitch%12;
tones[i].state = STATE_ON;
Expand All @@ -77,6 +80,8 @@ var tonnetz = (function() {
};

module.noteOff = function(c, pitch) {
audio.noteOff(c, pitch);

if (pitch in channels[c].pitches) {
var i = pitch%12;
delete channels[c].pitches[pitch];
Expand Down Expand Up @@ -104,6 +109,8 @@ var tonnetz = (function() {
};

module.allNotesOff = function(c) {
audio.allNotesOff(c);

for (var i=0; i<12; i++) {
delete tones[i].byChannel[c];
delete tones[i].channelsSust[c];
Expand Down Expand Up @@ -141,7 +148,7 @@ var tonnetz = (function() {
};

module.panic = function() {
for (var i=0; i<16; i++) {
for (var i=0; i<CHANNELS; i++) {
this.sustainOff(i);
this.allNotesOff(i);
}
Expand Down

0 comments on commit 1aeeb2a

Please sign in to comment.