User:Lbattich/Sound Prototypes
Circle Scanner
Scans the canvas and produces sounds according to the image data form the canvas element (forefox only)
It has a svg line hovering on top to mark the scan (to keep the canvas image data intact while visualizing the scan)
<!DOCTYPE html>
<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="content-type">
<title>Circle Scanner</title>
</head>
<body>
<button onclick="start()">scan</button>
<button onclick="circle()">draw a circle</button>
<button onclick="white()">clear up</button>
<button onclick="silence()">stop</button>
<br>
<br>
<svg id="line" height="300" style="position: absolute">
<line id= "bar" x1="0" y1="0" x2="0" y2="300" style="stroke:rgba(255,0,0,0.7);stroke-width:1" />
</svg>
<canvas id="myCanvas" height="300"></canvas>
<script>
var context = new AudioContext();
var osc1 = context.createOscillator();
var osc2 = context.createOscillator();
var osc3 = context.createOscillator();
var osc4 = context.createOscillator();
var osc5 = context.createOscillator();
var gain1 = context.createGain(); // Create gain node 1
var gain2 = context.createGain();
var gain3 = context.createGain();
var gain4 = context.createGain();
var gain5 = context.createGain();
var tid;
var x = 0;
// Connect oscillators to gains, and gain to context destination (speakers)
osc1.connect(gain1);
osc2.connect(gain2);
osc3.connect(gain3);
osc4.connect(gain4);
osc5.connect(gain5);
gain1.connect(context.destination);
gain2.connect(context.destination);
gain3.connect(context.destination);
gain4.connect(context.destination);
gain5.connect(context.destination);
osc1.frequency.value = 500;
osc2.frequency.value = 400;
osc3.frequency.value = 300;
osc4.frequency.value = 200;
osc5.frequency.value = 100;
gain1.gain.value = 0;
gain2.gain.value = 0;
gain3.gain.value = 0;
gain4.gain.value = 0;
gain5.gain.value = 0;
osc1.start(0);
osc2.start(0);
osc3.start(0);
osc4.start(0);
osc5.start(0);
var blackloud = true;
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
canvas.width = window.innerWidth-30;
document.getElementById("line").setAttribute("width", canvas.width);
white();
circle();
function start(){
if (tid){
clearTimeout(tid);
}
x = 0;
change();
}
function scan() {
var data = ctx.getImageData(x,0,1,1).data; // (x, y, width, height)
var pixel = data[0] + data[1] + data[2];
var scale = pixel / (255*3); //scale from 0=black=quiet and 1=white=loud
gain1.gain.value = blackloud ? 1-scale : scale;
var data = ctx.getImageData(x,75,1,1).data; // (x, y, width, height)
var pixel = data[0] + data[1] + data[2];
var scale = pixel / (255*3); //0=black and 1=white
gain2.gain.value = blackloud ? 1-scale : scale;
var data = ctx.getImageData(x,150,1,1).data; // (x, y, width, height)
var pixel = data[0] + data[1] + data[2];
var scale = pixel / (255*3); //0=black and 1=white
gain3.gain.value = blackloud ? 1-scale : scale;
var data = ctx.getImageData(x,225,1,1).data; // (x, y, width, height)
var pixel = data[0] + data[1] + data[2];
var scale = pixel / (255*3); //0=black and 1=white
gain4.gain.value = blackloud ? 1-scale : scale;
var data = ctx.getImageData(x,299,1,1).data; // (x, y, width, height)
var pixel = data[0] + data[1] + data[2];
var scale = pixel / (255*3); //0=black and 1=white
gain5.gain.value = blackloud ? 1-scale : scale;
var bar = document.getElementById("bar");
bar.setAttribute("x1", x);
bar.setAttribute("x2", x);
}
function white() {
ctx.fillStyle="white"; //first colour
ctx.fillRect(0,0,canvas.width,canvas.height);
ctx.fill();
}
function change() {
x = x+1;
scan();
if (x < (canvas.width-1)) {
tid = setTimeout(change,7);
}
else {
x=0;
tid = setTimeout(change,7);
}
}
function silence() {
gain1.gain.value = 0;
gain2.gain.value = 0;
gain3.gain.value = 0;
gain4.gain.value = 0;
gain5.gain.value = 0;
clearTimeout(tid);
}
function circle()
{
var xc,yc,radio;
yc=Math.floor((canvas.height+1)*Math.random());
xc=Math.floor((canvas.width+1)*Math.random());
radio=Math.floor((200)*Math.random());
ctx.beginPath();
ctx.arc(xc,yc,radio,0,2*Math.PI);
var grd=ctx.createLinearGradient(xc-radio,yc-radio,xc+radio,yc+radio);
grd.addColorStop(0,colourme());
grd.addColorStop(1,colourme());
ctx.strokeStyle=grd;
ctx.lineWidth=Math.floor((100)*Math.random());
ctx.stroke();
}
function colourme()
{
var a = Math.floor(256*Math.random());
var b = Math.floor(256*Math.random());
var c = Math.floor(256*Math.random());
var colour = "rgb("+a+","+b+","+c+")";
return colour;
}
</script>
</body>
</html>
Audio Test - Play a random composition using the Oscillator wave generator on the Web Audio API
Works only on Firefox so far...
This version jst uses one octave, and it visualizes the notes in the traditional muscial notation (by using the VexFlowlibrary - vexflow-min.js)
<!DOCTYPE html>
<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="content-type">
<script src="vexflow-min.js"></script>
<script src="jquery-1.11.1.min.js"></script>
<title>Audio test - 12-tone</title>
</head>
<body>
<p style="font-size:1.5em;">Audio Test. 12-Tone Composition Generator</p>
<br>
<button onclick="makeRow()">make row</button>
<button onclick="play()">play</button>
<button onclick="silence()">stop</button>
<br>
<p style="font-size:1.2em;">Prime Row:</p><canvas id="primenotation" width="700" height="100"></canvas>
<br>
<p style="font-size:1.2em; color:red;">Now Playing: <span id="current"></span></p>
<canvas id="notation" width="700" height="100"></canvas>
<div style="color:red; font-size:1.5em;" width="700">
<span id="dotspan" style="position: relative; left:55px">●</span>
</div>
<br>
<p>Duration of note now playing <input type="text" size="10" id="tm" value=""> <label for="tm"></label></p>
<p>Frequency: <input type="text" size="7" id="fr" value=""> <label for="fr">Hz</label></p>
<p>Choose gain between 0.3 and 1.2: <input type="text" size="7" id="gn" value=""> <label for="gn">Gain</label></p>
<p>Choose waveform: <input type="text" size="7" id="vw" value=""> <label for="vw">wave</label></p>
<br>
<p><input type="text" size="25" id="tempo" value="120"> <label for="tempo">Tempo - Choose from 50 (largo) to 220 (prestissimo)</label></p>
<p><input type="text" size="25" id="row" value=""> <label for="row">Prime row</label></p>
<p><input type="text" size="25" id="rowr" value=""> <label for="rowr">Retrograde</label></p>
<p><input type="text" size="25" id="rowi" value=""> <label for="rowi">Inversion</label></p>
<p><input type="text" size="25" id="rowri" value=""> <label for="rowri">Retrograde Inversion</label></p>
<p><input type="text" size="25" id="currentR" value=""> <label for="currentR">Row currently being played</label></p>
<p><input type="text" size="25" id="times" value=""> <label for="times">Duration of each note in the row</label></p>
<p><input type="text" size="25" id="note" value=""> <label for="note">Note currently being played (0=C, 1=C#, etc...)</label></p>
<p><textarea rows="10" cols="70" id="log" value="">Log</Textarea></p>
<script>
var context = new AudioContext();
var tone = context.createOscillator();
var gainNode1 = context.createGain(); // Create gain node 1
var on=0;
var tones = [0,1,2,3,4,5,6,7,8,9,10,11];
var freqvalues = [261.63,277.18,293.66,311.13,329.63,349.23,369.99,392,415.30,440,466.16,493.88];
var p = new Array();
var inv = new Array();
var r = new Array();
var ri = new Array()
var currentRow = new Array();
var currentTime = new Array();
var currentTimeName = new Array();
var note = 0;
var tempo = 500;
var durations = [4,2,1,0.5,0.25,0.125,0.0625]; //semibreve to 64th-note
var durationNames = ["Whole-note","Half-note","Quarter-note","Eighth-note","16th-note","32th-note","64th-note"];
var dot = document.getElementById("dotspan");
var primecanvas = document.getElementById("primenotation");
var canvas = document.getElementById("notation");
var currentText = document.getElementById("current");
var str = "";
jQuery.get('source.txt', function(data) {
alert(data);
//$('#log').html(data);
//document.getElementById("log").value = data;
});
tone.type = 0; // sine wave
tone.frequency.value = 0;
tone.connect(gainNode1); // Connect sound source tone to gain node 1
gainNode1.connect(context.destination);
gainNode1.gain.value = 0;
tone.start(0);
setup(canvas);
setup(primecanvas);
function setup(where){
var renderer = new Vex.Flow.Renderer(where,
Vex.Flow.Renderer.Backends.CANVAS);
var ctx = renderer.getContext();
var stave = new Vex.Flow.Stave(10, 0, 500);
stave.addClef("treble").setContext(ctx).draw();
}
function drawNotes(who,where) {
var canvasCTX = where.getContext("2d");
canvasCTX.fillStyle="white";
canvasCTX.fillRect(0,0,where.width,where.height);
canvasCTX.fill();
canvasCTX.fillStyle="black";
var renderer = new Vex.Flow.Renderer(where,
Vex.Flow.Renderer.Backends.CANVAS);
var ctx = renderer.getContext();
var stave = new Vex.Flow.Stave(10, 0, 500);
stave.addClef("treble").setContext(ctx).draw();
// Create the notes
var notes = [
new Vex.Flow.StaveNote({ keys: ["c/4"], duration: "q" }),
new Vex.Flow.StaveNote({ keys: ["c#/4"], duration: "q" }).addAccidental(0, new Vex.Flow.Accidental("#")),
new Vex.Flow.StaveNote({ keys: ["d/4"], duration: "q" }),
new Vex.Flow.StaveNote({ keys: ["d#/4"], duration: "q" }).addAccidental(0, new Vex.Flow.Accidental("#")),
new Vex.Flow.StaveNote({ keys: ["e/4"], duration: "q" }),
new Vex.Flow.StaveNote({ keys: ["f/4"], duration: "q" }),
new Vex.Flow.StaveNote({ keys: ["f#/4"], duration: "q" }).addAccidental(0, new Vex.Flow.Accidental("#")),
new Vex.Flow.StaveNote({ keys: ["g/4"], duration: "q" }),
new Vex.Flow.StaveNote({ keys: ["g#/4"], duration: "q" }).addAccidental(0, new Vex.Flow.Accidental("#")),
new Vex.Flow.StaveNote({ keys: ["a/4"], duration: "q" }),
new Vex.Flow.StaveNote({ keys: ["a#/4"], duration: "q" }).addAccidental(0, new Vex.Flow.Accidental("#")),
new Vex.Flow.StaveNote({ keys: ["b/4"], duration: "q" })
];
var notes2 = [];
// display notes
var all_notes = notes2.concat(notes[who[0]]).concat(notes[who[1]]).concat(notes[who[2]]).concat(notes[who[3]]).concat(notes[who[4]]).concat(notes[who[5]]).concat(notes[who[6]]).concat(notes[who[7]]).concat(notes[who[8]]).concat(notes[who[9]]).concat(notes[who[10]]).concat(notes[who[11]]);
Vex.Flow.Formatter.FormatAndDraw(ctx, stave, all_notes);
}
function makeRow() {
p = shuffle(tones);
r = Array.prototype.slice.call(p);
r.reverse();
inv[0] = p[0];
for (i = 1; i < 12; i++){
inv[i] = inv[i-1] - (p[i] - p[i-1]);
if (inv[i] == -1) {inv[i] = 11;}
else if (inv[i] == -1) {inv[i] = 11;}
else if (inv[i] == -2) {inv[i] = 10;}
else if (inv[i] == -3) {inv[i] = 9;}
else if (inv[i] == -4) {inv[i] = 8;}
else if (inv[i] == -5) {inv[i] = 7;}
else if (inv[i] == -6) {inv[i] = 6;}
else if (inv[i] == -7) {inv[i] = 5;}
else if (inv[i] == -8) {inv[i] = 4;}
else if (inv[i] == -9) {inv[i] = 3;}
else if (inv[i] == -10) {inv[i] = 2;}
else if (inv[i] == -11) {inv[i] = 1;}
else if (inv[i] == 12) {inv[i] = 0;}
else if (inv[i] == 13) {inv[i] = 1;}
else if (inv[i] == 14) {inv[i] = 2;}
else if (inv[i] == 15) {inv[i] = 3;}
else if (inv[i] == 16) {inv[i] = 4;}
else if (inv[i] == 17) {inv[i] = 5;}
else if (inv[i] == 18) {inv[i] = 6;}
else if (inv[i] == 19) {inv[i] = 7;}
else if (inv[i] == 20) {inv[i] = 8;}
else if (inv[i] == 21) {inv[i] = 9;}
else if (inv[i] == 22) {inv[i] = 10;}
else if (inv[i] == 23) {inv[i] = 11;}
}
ri = Array.prototype.slice.call(inv);
ri.reverse();
note = 0;
// choose tempo between 50 and 230 (BPM) - save value in ms
tempo = 60000 / (50 + Math.floor(181*Math.random()));
drawNotes(p,primecanvas);
str="prime:,"+p+",";
chooseRow();
document.getElementById("row").value = p; // display
document.getElementById("rowr").value = r; // display
document.getElementById("rowi").value = inv; // display
document.getElementById("rowri").value = ri; // display
document.getElementById("tempo").value = 60000/tempo;
}
//frequencies:
//http://www.phy.mtu.edu/~suits/notefreqs.html
function chooseRow() {
var numb=Math.floor(Math.random()*4);
if (numb==0){currentRow = Array.prototype.slice.call(p);currentText.innerHTML="Prime Row";} // prime
else if (numb==1){currentRow = Array.prototype.slice.call(r);currentText.innerHTML="Retrograde";} // retro
else if (numb==2){currentRow = Array.prototype.slice.call(inv);currentText.innerHTML="Inversion";} // inv
else if (numb==3){currentRow = Array.prototype.slice.call(ri);currentText.innerHTML="Retrograde Inversion";} // retro in
for (i = 0; i < 12; i++){
var rdmTime = Math.floor(7*Math.random());
currentTime[i] = durations[rdmTime];
currentTimeName[i] = durationNames[rdmTime];
}
document.getElementById("currentR").value = currentRow; // display
document.getElementById("times").value = currentTime; // display
drawNotes(currentRow,canvas);
record();
}
function shuffle(row){
for (var i = row.length-1; i >=0; i--) {
var index = Math.floor(Math.random()*(i+1));
var tempvalue = row[index];
row[index] = row[i];
row[i] = tempvalue;
}
return row;
}
function play(){
if (on==0){
on=1;
makeRow();
changeNote();
}
}
function changeNote() {
if (on==1){
// random gain between 0.5 and 1.5
var gain = 0.5+Math.random();
gainNode1.gain.value = gain;
document.getElementById("gn").value = gain;
// play current note
var n = currentRow[note];
tone.frequency.value = freqvalues[n];
document.getElementById("fr").value = freqvalues[n];
document.getElementById("note").value = n;
dot.style.left = 55+(42*note)+"px";
//random wave shape
var wave = Math.floor(4*Math.random());
tone.type = wave;
if (wave==0){document.getElementById("vw").value="Sine";}
else if (wave==1){document.getElementById("vw").value="Square";}
else if (wave==2){document.getElementById("vw").value="Sawtooth";}
else if (wave==3){document.getElementById("vw").value="Triangle";}
// duration of note
var time = currentTime[note] * tempo;
document.getElementById("tm").value = currentTimeName[note];
note++;
if (note==12){
note=0;
dot.style.left = "55px";
chooseRow();
}
setTimeout(function(){changeNote()},time);
}
}
function record() {
for (var i=0;i<12;i++){
str = str+currentRow[i]+"/"+currentTime[i]+",";
}
document.getElementById("log").value = str;
}
function silence() {
tone.frequency.value = 0;
gainNode1.gain.value = 0;
note=0;
on=0;
}
</script>
</body>
</html>
Code for the Audio Test:
<!DOCTYPE html>
<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="content-type">
<title>Audio test - Play a random composition</title>
</head>
<body>
<p>Choose frequency between 80Hz and 880Hz: <input type="text" size="7" id="fr" value=""> <label for="fr">Hz</label></p>
<p>Choose gain between 0.2 and 1.2: <input type="text" size="7" id="gn" value=""> <label for="gn">Gain</label></p>
<p>Choose duration between 1/50sec and 1sec: <input type="text" size="7" id="tm" value=""> <label for="tm">Seconds</label></p>
<p>Choose waveform: <input type="text" size="7" id="vw" value=""> <label for="tm">wave</label></p>
<br>
<button onclick="play()">play</button>
<button onclick="silence()">stop</button>
<script>
var context = new AudioContext();
var tone = context.createOscillator();
var gainNode1 = context.createGain(); // Create gain node 1
var on=0;
tone.type = 0; // sine wave
tone.frequency.value = 0;
tone.connect(gainNode1); // Connect sound source tone to gain node 1
gainNode1.connect(context.destination);
gainNode1.gain.value = 0;
tone.start(0);
function play(){
if (on==0){
on=1;
change();
}
}
function change() {
if (on==1){
// random gain between 0.2 and 1.2
var gain = 0.2+Math.random();
gainNode1.gain.value = gain;
document.getElementById("gn").value = gain;
// random frequency between 80 and 880
var freq = 80 + Math.floor(801*Math.random());
tone.frequency.value = freq;
document.getElementById("fr").value = freq;
//random wave shape
var wave = Math.floor(4*Math.random());
tone.type = wave;
if (wave==0){document.getElementById("vw").value="Sine";}
else if (wave==1){document.getElementById("vw").value="Square";}
else if (wave==2){document.getElementById("vw").value="Sawtooth";}
else if (wave==3){document.getElementById("vw").value="Triangle";}
// random duration of note - 1/50sec to 1sec
var time = 20 + Math.floor(901*Math.random());
document.getElementById("tm").value = time/1000;
setTimeout(function(){change()},time);
}
}
function silence() {
tone.frequency.value = 0;
gainNode1.gain.value = 0;
on=0;
}
</script>
</body>
</html>