./code/js_audio/readme.txt
Here is a program that demonstrates how to create audio in javascript. You can try it  here  (you will need a keyboard).

All the html file does is bring in the javascript file. There can be more content there of course, but this is the minimum that is required. 

The javascript program takes the bottom two rows of the keyboard and uses "keydown" event-listeners turns them into the 12 standard notes arranged like on a piano. Like this:

	  [s][d]   [g][h][j]
	[z][x][c][v][b][n][m][,]

(take a look at a piano if you're confused!)

What's happening in this program:

First we retrieve the "audio context" from the html document, (This is similar to how you get the context in a html canvas program), and name it something creative like "audio_context"

To play, every note needs an OSCILLATOR which determines frequency and wavetype. Frequency is the note (i.e. 261.626 hz is middle C). Wavetype determines how smooth or rough the sound is. The default sine wave is smooth, while the triangle wave is well.. triangluar and the square wave is... just listen to them and see. You can also create your own custom waveform if you really want a unique sound (be prepared to do some math!).

Each note also needs a VOLUME CONTROL which lets you gradually ramp up to full volume and fade out, or whatever you like. The volume control is not stricly required, but it sounds much better than just playing the note at full volume the whole time. (try it without volume control, you'll see).

Then, connections are made oscillator -> volume control -> speakers, and the note is ready to play.

	oscillator.start();  starts the note
	oscillator.stop();   stops it.

these functions take a time value as a parameter. The audio context conveniently keeps track of the current time in the variable "audio_context.currentTime", therefore: 

	start_time = audio_context.currentTime;
	stop_time = audio_context.currentTime + 1.5;
	oscillator.start(start_time);
	oscillator.stop(stop_time);

for example, will play the note for 1.5 seconds.

Study this program, and see how adjusting certain parameters will change the sound.  Go here to read the documentation on javascript Audio. 
./code/js_audio/main.html
<!doctype html>

<html lang="en">

	<head>
	  <meta charset="utf-8">
	  <title>Ѭ</title>
	</head>

	<body>
		<script src="audio_demo.js"></script>
	</body>
</html>
./code/js_audio/audio_demo.js
let audio_context = new (this.AudioContext || this.webkitAudioContext)();

// each note has a duration, frequency, and volume control
function play_note(freq) {
	let start_time = audio_context.currentTime;
	let stop_time = start_time + 1; // play for one second

	let o = audio_context.createOscillator();
	o.frequency.value = freq;
	o.type = "triangle"; // other options : sine, square, sawtooth, custom

	let volume_control = audio_context.createGain();
	volume_control.gain.setTargetAtTime(0.5, start_time, 0.02);
	volume_control.gain.setTargetAtTime(0, start_time + 0.1, 0.1);
						// parameters: volume (0-1), start time, speed(sort of) ->
						// -> smaller number means faster exponential ramp 

	o.connect(volume_control)  // connect oscillator to volume control
	volume_control.connect(audio_context.destination) // connect vol. control to speakers
	
	o.start(start_time); // this actually plays the note
	o.stop(stop_time);   // and you need to stop it or else it plays forever
}

// this next part is the DATA portion of the program
// to the computer, notes are just numbers, so we need to translate.

let key = 261.626/2; // one octave below middle C, change this to change key

// Just Temperament... music theory!!
// note: regular pianos use Well Temperament
// you would have to change these numbers if you want that
let tonic = 1;
let semitone = (16/15);
let whole_tone = (9/8);
let minor_third = (6/5);
let major_third = (5/4);
let fourth = (4/3);
let tritone = (7/5);
let fifth = (3/2);
let minor_sixth = (8/5);
let major_sixth = (5/3);
let minor_seventh = (9/5);
let major_seventh = (15/8);
let octave = 2;

// keep track of keys down since we don't want the note
// to spam when the key is held down
let keys_down = new Set();

document.addEventListener("keydown", (e) => {
	if (keys_down.has(e.key))
		return -1; // skip, if the key is already down
	keys_down.add(e.key);
	if (e.key === 'z') play_note(key * tonic);
	if (e.key === 's') play_note(key * semitone);
	if (e.key === 'x') play_note(key * whole_tone);
	if (e.key === 'd') play_note(key * minor_third);
	if (e.key === 'c') play_note(key * major_third);
	if (e.key === 'v') play_note(key * fourth);
	if (e.key === 'g') play_note(key * tritone);
	if (e.key === 'b') play_note(key * fifth);
	if (e.key === 'h') play_note(key * minor_sixth);
	if (e.key === 'n') play_note(key * major_sixth);
	if (e.key === 'j') play_note(key * minor_seventh);
	if (e.key === 'm') play_note(key * major_seventh);
	if (e.key === ',') play_note(key * octave);
});

document.addEventListener("keyup", (e) => {
	if (keys_down.has(e.key))
		keys_down.delete(e.key);
});