mirror of
https://github.com/thedjinn/js303.git
synced 2025-08-17 07:48:13 +02:00
275 lines
7.0 KiB
JavaScript
275 lines
7.0 KiB
JavaScript
(function(){ // TODO: Fix sluggishness in wrapper
|
|
|
|
var audiotimer;
|
|
var synth;
|
|
|
|
var pitchmode=false;
|
|
var currentstep=0;
|
|
|
|
function changestep(pos) {
|
|
currentstep=pos;
|
|
|
|
$("#stepnumber").css("background-position","-"+(pos*50)+"px 0px");
|
|
|
|
var pitch = synth.pattern[pos][0]-40;
|
|
$("#cled").toggleClass("on",pitch==0);
|
|
$("#dbled").toggleClass("on",pitch==1);
|
|
$("#dled").toggleClass("on",pitch==2);
|
|
$("#ebled").toggleClass("on",pitch==3);
|
|
$("#eled").toggleClass("on",pitch==4);
|
|
$("#fled").toggleClass("on",pitch==5);
|
|
$("#gbled").toggleClass("on",pitch==6);
|
|
$("#gled").toggleClass("on",pitch==7);
|
|
$("#abled").toggleClass("on",pitch==8);
|
|
$("#aled").toggleClass("on",pitch==9);
|
|
$("#bbled").toggleClass("on",pitch==10);
|
|
$("#bled").toggleClass("on",pitch==11);
|
|
$("#ccled").toggleClass("on",pitch==12);
|
|
|
|
$("#accentled").toggleClass("on",synth.pattern[pos][1]);
|
|
$("#slideled").toggleClass("on",synth.pattern[pos][2]);
|
|
$("#noteled").toggleClass("on",synth.pattern[pos][3]);
|
|
$("#restled").toggleClass("on",!synth.pattern[pos][3]);
|
|
$("#downled").toggleClass("on",synth.pattern[pos][4]);
|
|
$("#upled").toggleClass("on",synth.pattern[pos][5]);
|
|
}
|
|
|
|
$(function(){
|
|
// init synth
|
|
synth = new TB303;
|
|
if (typeof song !== "undefined") {
|
|
synth.unserialize(song);
|
|
}
|
|
|
|
// set up interface
|
|
$("#tempo").dial({
|
|
numImages: 41,
|
|
imageWidth: 36,
|
|
min: 20.0,
|
|
max: 200.0,
|
|
value: synth.tempo,
|
|
unitsPerPixel: 1,
|
|
change: function(e,u){
|
|
synth.settempo(u.value);
|
|
}
|
|
});
|
|
$("#threshold").dial({
|
|
numImages: 41,
|
|
imageWidth: 36,
|
|
min: 0.0,
|
|
max: 1.0,
|
|
value: synth.dist_threshold,
|
|
unitsPerPixel: 0.01,
|
|
change: function(e,u){
|
|
synth.setdistthreshold(u.value);
|
|
}
|
|
});
|
|
$("#shape").dial({
|
|
numImages: 41,
|
|
imageWidth: 36,
|
|
min: 0.0,
|
|
max: 1.0,
|
|
value: synth.dist_shape,
|
|
unitsPerPixel: 0.01,
|
|
change: function(e,u){
|
|
synth.dist_shape = u.value;
|
|
}
|
|
});
|
|
$("#tuning").dial({
|
|
numImages: 41,
|
|
imageWidth: 36,
|
|
min: -12.0,
|
|
max: 12.0,
|
|
value: synth.tuning,
|
|
unitsPerPixel: 0.1,
|
|
change: function(e,u){
|
|
synth.tuning = u.value;
|
|
}
|
|
});
|
|
$("#cutoff").dial({
|
|
numImages: 41,
|
|
imageWidth: 36,
|
|
min: 200.0,
|
|
max: 20000.0,
|
|
value: synth.cutoff,
|
|
unitsPerPixel: 100,
|
|
change: function(e,u){
|
|
synth.setcutoff(u.value);
|
|
}
|
|
});
|
|
$("#resonance").dial({
|
|
numImages: 41,
|
|
imageWidth: 36,
|
|
min: 0.0,
|
|
max: 1.0,
|
|
value: synth.resonance,
|
|
unitsPerPixel: 0.01,
|
|
change: function(e,u) {
|
|
synth.setresonance(u.value);
|
|
}
|
|
});
|
|
$("#envmod").dial({
|
|
numImages: 41,
|
|
imageWidth: 36,
|
|
min: 0.0,
|
|
max: 1.0,
|
|
value: synth.envmod,
|
|
unitsPerPixel: 0.01,
|
|
change: function(e,u) {
|
|
synth.setenvmod(u.value);
|
|
}
|
|
});
|
|
$("#decay").dial({
|
|
numImages: 41,
|
|
imageWidth: 36,
|
|
min: 100.0,
|
|
max: 2000.0,
|
|
value: synth.decay,
|
|
unitsPerPixel: 2,
|
|
change: function(e,u) {
|
|
synth.decay = u.value;
|
|
}
|
|
});
|
|
$("#accent").dial({
|
|
numImages: 41,
|
|
imageWidth: 36,
|
|
min: 0.0,
|
|
max: 1.0,
|
|
value: synth.accent,
|
|
unitsPerPixel: 0.01,
|
|
change: function(e,u) {
|
|
synth.accent = u.value;
|
|
}
|
|
});
|
|
|
|
$("#waveform").change(function(e) {
|
|
synth.waveform = $(this).attr("checked")?1:0;
|
|
}).attr("checked",synth.waveform==1?true:false);
|
|
|
|
$("#stepbutton").click(function(e) {
|
|
changestep((currentstep+1)%synth.pattern.length);
|
|
});
|
|
|
|
$("#backbutton").click(function(e) {
|
|
changestep((currentstep+synth.pattern.length-1)%synth.pattern.length);
|
|
});
|
|
|
|
$("#gatebutton").click(function(e) {
|
|
synth.pattern[currentstep][3]=!synth.pattern[currentstep][3];
|
|
$("#noteled").toggleClass("on",synth.pattern[currentstep][3]);
|
|
$("#restled").toggleClass("on",!synth.pattern[currentstep][3]);
|
|
});
|
|
|
|
$("#downbutton").click(function(e) {
|
|
synth.pattern[currentstep][4]=!synth.pattern[currentstep][4];
|
|
$("#downled").toggleClass("on",synth.pattern[currentstep][4]);
|
|
});
|
|
|
|
$("#upbutton").click(function(e) {
|
|
synth.pattern[currentstep][5]=!synth.pattern[currentstep][5];
|
|
$("#upled").toggleClass("on",synth.pattern[currentstep][5]);
|
|
});
|
|
|
|
$("#accentbutton").click(function(e) {
|
|
synth.pattern[currentstep][1]=!synth.pattern[currentstep][1];
|
|
$("#accentled").toggleClass("on",synth.pattern[currentstep][1]);
|
|
});
|
|
|
|
$("#slidebutton").click(function(e) {
|
|
synth.pattern[currentstep][2]=!synth.pattern[currentstep][2];
|
|
$("#slideled").toggleClass("on",synth.pattern[currentstep][2]);
|
|
});
|
|
|
|
$("#pitchmodebutton").click(function(e) {
|
|
pitchmode=!pitchmode;
|
|
$("#pitchmodeled").toggleClass("on",pitchmode);
|
|
});
|
|
|
|
$("#clearbutton").click(function(e) {
|
|
synth.pattern[currentstep][0]=40;
|
|
synth.pattern[currentstep][1]=false;
|
|
synth.pattern[currentstep][2]=false;
|
|
synth.pattern[currentstep][3]=false;
|
|
synth.pattern[currentstep][4]=false;
|
|
synth.pattern[currentstep][5]=false;
|
|
changestep(currentstep);
|
|
});
|
|
|
|
var changenote = function(e) {
|
|
var notes=["c","db","d","eb","e","f","gb","g","ab","a","bb","b","cc"];
|
|
if (pitchmode) {
|
|
synth.pattern[currentstep][0]=e.data.number+40;
|
|
changestep((currentstep+1)%synth.pattern.length);
|
|
} else {
|
|
$("#"+notes[synth.pattern[currentstep][0]-40]+"led").removeClass("on");
|
|
synth.pattern[currentstep][0]=e.data.number+40;
|
|
$("#"+notes[synth.pattern[currentstep][0]-40]+"led").addClass("on");
|
|
}
|
|
};
|
|
$("#cbutton").click({number:0},changenote);
|
|
$("#dbbutton").click({number:1},changenote);
|
|
$("#dbutton").click({number:2},changenote);
|
|
$("#ebbutton").click({number:3},changenote);
|
|
$("#ebutton").click({number:4},changenote);
|
|
$("#fbutton").click({number:5},changenote);
|
|
$("#gbbutton").click({number:6},changenote);
|
|
$("#gbutton").click({number:7},changenote);
|
|
$("#abbutton").click({number:8},changenote);
|
|
$("#abutton").click({number:9},changenote);
|
|
$("#bbbutton").click({number:10},changenote);
|
|
$("#bbutton").click({number:11},changenote);
|
|
$("#ccbutton").click({number:12},changenote);
|
|
|
|
$("#run").click(function(e){
|
|
// clearInterval(audiotimer);
|
|
synth.running=!synth.running;
|
|
});
|
|
|
|
$("#createpermalink a").click(function(e) {
|
|
$("#createpermalink").slideUp(200);
|
|
$.ajax({
|
|
data: {
|
|
data:JSON.stringify(synth.serialize())
|
|
},
|
|
dataType: "text",
|
|
error: function(xhr,stat,err) { alert("Oops! Something went horribly wrong: stat="+stat+" err="+err); },
|
|
success: function(data, status, xhr) {
|
|
$("#permalink .url").html("http://js303.com/s/"+data);
|
|
$("#permalink").slideDown(200);
|
|
},
|
|
type: "POST",
|
|
url: "/store"
|
|
});
|
|
});
|
|
|
|
changestep(currentstep);
|
|
|
|
// initialize wavetable
|
|
loadwavetable("/data/wavetable.png", function() {
|
|
|
|
// set up synth
|
|
var audio = new Audio();
|
|
if (typeof audio.mozSetup == 'function') {
|
|
audio.mozSetup(1,44100);
|
|
|
|
var apos=0;
|
|
var buf = new Float32Array(4410);
|
|
audiotimer = setInterval(function() {
|
|
var before = +new Date();
|
|
var b = buf, r = synth;
|
|
for (var i=0;i<4410;i++) {
|
|
b[i]=r.render();
|
|
}
|
|
apos+=audio.mozWriteAudio(b);
|
|
var after = +new Date();
|
|
$("#load").html((after-before)+"%");
|
|
},100);
|
|
} else {
|
|
// no audio data api available
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
})();
|