annotate core.js @ 1683:c97a35dc45e5

function loadProjectSpec will parse XML project specification and build interface. Still needs full work. Interface is loaded in ape.js
author Nicholas Jillings <nickjillings@users.noreply.github.com>
date Sun, 08 Mar 2015 18:58:06 +0000
parents e1f00361326d
children 6a6272b06d34
rev   line source
nickjillings@1682 1 /**
nickjillings@1682 2 * core.js
nickjillings@1682 3 *
nickjillings@1682 4 * Main script to run, calls all other core functions and manages loading/store to backend.
nickjillings@1682 5 * Also contains all global variables.
nickjillings@1682 6 */
nickjillings@1682 7
nickjillings@1682 8 /* create the web audio API context and store in audioContext*/
nickjillings@1682 9 var audioContext;
nickjillings@1683 10 var projectXML;
nickjillings@1682 11 var audioEngineContext;
nickjillings@1682 12
nickjillings@1682 13 window.onload = function() {
nickjillings@1682 14 // Function called once the browser has loaded all files.
nickjillings@1682 15 // This should perform any initial commands such as structure / loading documents
nickjillings@1682 16
nickjillings@1682 17 // Create a web audio API context
nickjillings@1682 18 // NORE: Currently this will only work with webkit browsers (Chrome/Safari)!
nickjillings@1682 19 audioContext = new webkitAudioContext;
nickjillings@1682 20
nickjillings@1682 21 // Create the audio engine object
nickjillings@1682 22 audioEngineContext = new AudioEngine();
nickjillings@1682 23 }
nickjillings@1682 24
nickjillings@1682 25 function loadProjectSpec(url) {
nickjillings@1682 26 // Load the project document from the given URL, decode the XML and instruct audioEngine to get audio data
nickjillings@1682 27 // If url is null, request client to upload project XML document
nickjillings@1683 28 var r = new XMLHttpRequest();
nickjillings@1683 29 r.open('GET',url,true);
nickjillings@1683 30 r.onload = function() {
nickjillings@1683 31 loadProjectSpecCallback(r.response);
nickjillings@1683 32 }
nickjillings@1683 33 r.send();
nickjillings@1683 34 }
nickjillings@1683 35
nickjillings@1683 36 function loadProjectSpecCallback(response) {
nickjillings@1683 37 // Function called after asynchronous download of XML project specification
nickjillings@1683 38 var decode = $.parseXML(response);
nickjillings@1683 39 projectXML = $(decode);
nickjillings@1683 40
nickjillings@1683 41 // Now extract the setup tag
nickjillings@1683 42 var xmlSetup = projectXML.find('setup');
nickjillings@1683 43 var interfaceType = xmlSetup[0].attributes['interface'];
nickjillings@1683 44 var interfaceJS = document.createElement('script');
nickjillings@1683 45 interfaceJS.setAttribute("type","text/javascript");
nickjillings@1683 46 if (interfaceType.value == 'APE') {
nickjillings@1683 47 interfaceJS.setAttribute("src","ape.js");
nickjillings@1683 48 }
nickjillings@1683 49 document.getElementsByTagName("head")[0].appendChild(interfaceJS);
nickjillings@1682 50 }
nickjillings@1682 51
nickjillings@1682 52 function createProjectSave(destURL) {
nickjillings@1682 53 // Save the data from interface into XML and send to destURL
nickjillings@1682 54 // If destURL is null then download XML in client
nickjillings@1682 55 }
nickjillings@1682 56
nickjillings@1682 57 function AudioEngine() {
nickjillings@1682 58
nickjillings@1682 59 // Create two output paths, the main outputGain and fooGain.
nickjillings@1682 60 // Output gain is default to 1 and any items for playback route here
nickjillings@1682 61 // Foo gain is used for analysis to ensure paths get processed, but are not heard
nickjillings@1682 62 // because web audio will optimise and any route which does not go to the destination gets ignored.
nickjillings@1682 63 this.outputGain = audioContext.createGain();
nickjillings@1682 64 this.fooGain = audioContext.createGain();
nickjillings@1682 65 this.fooGain.gain = 0;
nickjillings@1682 66
nickjillings@1682 67 // Connect both gains to output
nickjillings@1682 68 this.outputGain.connect(audioContext.destination);
nickjillings@1682 69 this.fooGain.connect(audioContext.destination);
nickjillings@1682 70
nickjillings@1682 71 // Create store for new audioObjects
nickjillings@1682 72 this.audioObjects = [];
nickjillings@1682 73
nickjillings@1682 74 this.play = function() {
nickjillings@1682 75 // Send play command to all playback buffers for synchronised start
nickjillings@1682 76 // Also start timer callbacks to detect if playback has finished
nickjillings@1682 77 }
nickjillings@1682 78
nickjillings@1682 79 this.stop = function() {
nickjillings@1682 80 // Send stop and reset command to all playback buffers
nickjillings@1682 81 }
nickjillings@1682 82
nickjillings@1682 83 this.newTrack = function(url) {
nickjillings@1682 84 // Pull data from given URL into new audio buffer
nickjillings@1682 85 // URLs must either be from the same source OR be setup to 'Access-Control-Allow-Origin'
nickjillings@1682 86 var request = new XMLHttpRequest();
nickjillings@1682 87 request.open('GET',url,true);
nickjillings@1682 88 request.responseType = 'arraybuffer';
nickjillings@1682 89 // Create the audioObject with ID of the new track length;
nickjillings@1682 90 audioObjectId = this.audioObjects.length
nickjillings@1682 91 this.audioObjects[audioObjectId] = new audioObject(audioObjectId);
nickjillings@1682 92
nickjillings@1682 93 // Create callback to decode the data asynchronously
nickjillings@1682 94 request.onload = function() {
nickjillings@1682 95 audioContext.decodeAudioData(request.response, function(decodedData) {
nickjillings@1682 96 audioObj = audioEngineContext.audioObjects[audioObjectId];
nickjillings@1682 97 audioObj.buffer = decodedData;
nickjillings@1682 98 audioObj.bufferNode.buffer = audioObj.buffer;
nickjillings@1682 99 audioObj.state = 1;
nickjillings@1682 100 }, console.log("Err - Buffer not added to " + audioObjectId));
nickjillings@1682 101 }
nickjillings@1682 102 request.send();
nickjillings@1682 103 }
nickjillings@1682 104
nickjillings@1682 105 }
nickjillings@1682 106
nickjillings@1682 107 function audioObject(id) {
nickjillings@1682 108 // The main buffer object with common control nodes to the AudioEngine
nickjillings@1682 109
nickjillings@1682 110 this.id = id;
nickjillings@1682 111 this.state = 0; // 0 - no data, 1 - ready
nickjillings@1682 112
nickjillings@1682 113 // Create a buffer and external gain control to allow internal patching of effects and volume leveling.
nickjillings@1682 114 this.bufferNode = audioContext.createBufferSource();
nickjillings@1682 115 this.outputGain = audioContext.createGain();
nickjillings@1682 116
nickjillings@1682 117 // Connect buffer to the audio graph
nickjillings@1682 118 this.bufferNode.connect(this.outputGain);
nickjillings@1682 119 this.outputGain.connect(audioEngineContext.outputGain);
nickjillings@1682 120
nickjillings@1682 121 // the audiobuffer is not designed for multi-start playback
nickjillings@1682 122 // When stopeed, the buffer node is deleted and recreated with the stored buffer.
nickjillings@1682 123 this.buffer;
nickjillings@1682 124
nickjillings@1682 125 this.play = function(startTime) {
nickjillings@1682 126 this.bufferNode.start(startTime);
nickjillings@1682 127 }
nickjillings@1682 128
nickjillings@1682 129 this.stop = function() {
nickjillings@1682 130 this.bufferNode.stop(0);
nickjillings@1682 131 this.bufferNode = audioContext.createBufferSource();
nickjillings@1682 132 this.bufferNode.connect(this.outputGain);
nickjillings@1682 133 this.bufferNode.buffer = this.buffer;
nickjillings@1682 134 }
nickjillings@1682 135
nickjillings@1682 136 }