Mercurial > hg > webaudioevaluationtool
changeset 2619:74e5d7a978ee
Merge branch 'vnext' into Dev_main
author | Nicholas Jillings <nicholas.jillings@mail.bcu.ac.uk> |
---|---|
date | Thu, 17 Nov 2016 13:08:26 +0000 |
parents | cce1fb4009f2 (diff) fff464febd56 (current diff) |
children | 13a0b65143a6 |
files | js/core.js |
diffstat | 4 files changed, 179 insertions(+), 63 deletions(-) [+] |
line wrap: on
line diff
--- a/js/core.js Thu Nov 17 13:08:00 2016 +0000 +++ b/js/core.js Thu Nov 17 13:08:26 2016 +0000 @@ -1488,10 +1488,8 @@ this.buffers = []; this.bufferObj = function () { - this.url = null; + var urls = []; this.buffer = null; - this.xmlRequest = new XMLHttpRequest(); - this.xmlRequest.parent = this; this.users = []; this.progress = 0; this.status = 0; @@ -1506,30 +1504,77 @@ } } }; - this.getMedia = function (url) { - this.url = url; - this.xmlRequest.open('GET', this.url, true); - this.xmlRequest.responseType = 'arraybuffer'; + this.setUrls = function (obj) { + // Obj must be an array of pairs: + // [{sampleRate, url}] + var localFs = audioContext.sampleRate, + list = [], + i; + for (i = 0; i < obj.length; i++) { + if (obj[i].sampleRate == localFs) { + list.push(obj.splice(i, 1)[0]); + } + } + list = list.concat(obj); + urls = list; + }; + this.hasUrl = function (checkUrl) { + var l = urls.length, + i; + for (i = 0; i < l; i++) { + if (urls[i].url == checkUrl) { + return true; + } + } + return false; + } + this.getMedia = function () { + var self = this; + var currentUrlIndex = 0; - var bufferObj = this; + function get(fqurl) { + return new Promise(function (resolve, reject) { + var req = new XMLHttpRequest(); + req.open('GET', fqurl, true); + req.responseType = 'arraybuffer'; + req.onload = function () { + if (req.status == 200) { + resolve(req.response); + } + }; + req.onerror = function () { + reject(new Error(req.statusText)); + }; + + req.addEventListener("progress", progressCallback.bind(self)); + req.send(); + }); + } + + function getNextURL() { + currentUrlIndex++; + var self = this; + if (currentUrlIndex >= urls.length) { + processError(); + } else { + return get(urls[currentUrlIndex].url).then(processAudio.bind(self)).catch(getNextURL.bind(self)); + } + } // Create callback to decode the data asynchronously - this.xmlRequest.onloadend = function () { - // Use inbuilt WAVE decoder first - if (this.status == -1) { - return; - } - var waveObj = new WAVE(); - audioContext.decodeAudioData(bufferObj.xmlRequest.response, function (decodedData) { - bufferObj.buffer = decodedData; - bufferObj.status = 2; - calculateLoudness(bufferObj, "I"); + function processAudio(response) { + var self = this; + return audioContext.decodeAudioData(response, function (decodedData) { + self.buffer = decodedData; + self.status = 2; + calculateLoudness(self, "I"); + return true; }, function (e) { var waveObj = new WAVE(); - if (waveObj.open(bufferObj.xmlRequest.response) == 0) { - bufferObj.buffer = audioContext.createBuffer(waveObj.num_channels, waveObj.num_samples, waveObj.sample_rate); + if (waveObj.open(response) == 0) { + self.buffer = audioContext.createBuffer(waveObj.num_channels, waveObj.num_samples, waveObj.sample_rate); for (var c = 0; c < waveObj.num_channels; c++) { - var buffer_ptr = bufferObj.buffer.getChannelData(c); + var buffer_ptr = self.buffer.getChannelData(c); for (var n = 0; n < waveObj.num_samples; n++) { buffer_ptr[n] = waveObj.decoded_data[c][n]; } @@ -1537,41 +1582,44 @@ delete waveObj; } - if (bufferObj.buffer != undefined) { - bufferObj.status = 2; - calculateLoudness(bufferObj, "I"); + if (self.buffer != undefined) { + self.status = 2; + calculateLoudness(self, "I"); + return true; } + return false; }); - }; + } // Create callback for any error in loading - this.xmlRequest.onerror = function () { - this.parent.status = -1; - for (var i = 0; i < this.parent.users.length; i++) { - this.parent.users[i].state = -1; - if (this.parent.users[i].interfaceDOM != null) { - this.parent.users[i].bufferLoaded(this); + function processError() { + this.status = -1; + for (var i = 0; i < this.users.length; i++) { + this.users[i].state = -1; + if (this.users[i].interfaceDOM != null) { + this.users[i].bufferLoaded(this); } } - interfaceContext.lightbox.post("Error", "Could not load resource " + this.parent.url); + interfaceContext.lightbox.post("Error", "Could not load resource " + urls[currentUrlIndex].url); } - this.progress = 0; - this.progressCallback = function (event) { + function progressCallback(event) { if (event.lengthComputable) { - this.parent.progress = event.loaded / event.total; - for (var i = 0; i < this.parent.users.length; i++) { - if (this.parent.users[i].interfaceDOM != null) { - if (typeof this.parent.users[i].interfaceDOM.updateLoading === "function") { - this.parent.users[i].interfaceDOM.updateLoading(this.parent.progress * 100); + this.progress = event.loaded / event.total; + for (var i = 0; i < this.users.length; i++) { + if (this.users[i].interfaceDOM != null) { + if (typeof this.users[i].interfaceDOM.updateLoading === "function") { + this.users[i].interfaceDOM.updateLoading(this.progress * 100); } } } } }; - this.xmlRequest.addEventListener("progress", this.progressCallback); + + this.progress = 0; this.status = 1; - this.xmlRequest.send(); + currentUrlIndex = 0; + get(urls[0].url).then(processAudio.bind(self)).catch(getNextURL.bind(self)); }; this.registerAudioObject = function (audioObject) { @@ -1648,14 +1696,25 @@ var URL = page.hostURL + element.url; var buffer = null; for (var buffObj of this.buffers) { - if (URL == buffObj.url) { + if (buffObj.hasUrl(URL)) { buffer = buffObj; break; } } if (buffer == null) { buffer = new this.bufferObj(); - buffer.getMedia(URL); + var urls = [{ + url: URL, + sampleRate: element.sampleRate + }]; + element.alternatives.forEach(function (e) { + urls.push({ + url: e.url, + sampleRate: e.sampleRate + }); + }); + buffer.setUrls(urls); + buffer.getMedia(); this.buffers.push(buffer); } } @@ -1725,7 +1784,7 @@ var URL = testState.currentStateMap.hostURL + element.url; var buffer = null; for (var i = 0; i < this.buffers.length; i++) { - if (URL == this.buffers[i].url) { + if (this.buffers[i].hasUrl(URL)) { buffer = this.buffers[i]; break; }
--- a/js/specification.js Thu Nov 17 13:08:00 2016 +0000 +++ b/js/specification.js Thu Nov 17 13:08:26 2016 +0000 @@ -781,6 +781,8 @@ this.label = null; this.startTime = undefined; this.stopTime = undefined; + this.sampleRate = undefined; + this.alternatives = []; this.schema = specification.schema.getAllElementsByName('audioelement')[0];; this.parent = null; this.decode = function (parent, xml) { @@ -800,6 +802,17 @@ break; } } + // Get the alternative nodes + var child = xml.firstElementChild; + while (child) { + if (child.nodeName == "alternative") { + this.alternatives.push({ + 'url': child.getAttribute("url"), + 'sampleRate': child.getAttribute("sampleRate") + }); + } + child = child.nextElementSibling; + } }; this.encode = function (root) { @@ -814,6 +827,12 @@ eval("AENode.setAttribute('" + name + "',this." + name + ")"); } } + this.alternatives.forEach(function (alt) { + var node = root.createElement("alternative"); + node.setAttribute("url", alt.url); + node.setAttribute("sampleRate", alt.sampleRate); + AENode.appendChild(node); + }); return AENode; }; };
--- a/test_create/test_core.js Thu Nov 17 13:08:00 2016 +0000 +++ b/test_create/test_core.js Thu Nov 17 13:08:26 2016 +0000 @@ -975,7 +975,7 @@ handleEvent: function (event) { this.parent.scaleRoot.scales = []; var protoScale = interfaceSpecs.getAllElementsByTagName('scaledefinitions')[0].getAllElementsByName(event.currentTarget.value)[0]; - var protoMarkers = protoScale.getElementsByTagName("scale"); + var protoMarkers = protoScale.getElementsByTagName("scalelabel"); for (var i = 0; i < protoMarkers.length; i++) { var marker = { position: protoMarkers[i].getAttribute("position"), @@ -992,6 +992,22 @@ optionHolder.className = 'node'; optionHolder.id = 'popup-option-holder'; this.content.appendChild(optionHolder); + this.addMarker = { + root: document.createElement("button"), + parent: this, + handleEvent: function () { + var marker = { + position: 0, + text: "text" + }; + this.parent.scaleRoot.scales.push(marker); + var markerNode = new this.parent.buildMarkerNode(this.parent, marker); + document.getElementById("popup-option-holder").appendChild(markerNode.root); + this.parent.markerNodes.push(markerNode); + } + }; + this.addMarker.root.textContent = "Add Marker"; + this.addMarker.root.addEventListener("click", this.addMarker); this.generate = function (scaleRoot, parent) { this.scaleRoot = scaleRoot; this.parent = parent; @@ -1007,23 +1023,6 @@ selectOption.textContent = scaleName; this.preset.input.appendChild(selectOption); } - - this.addMarker = { - root: document.createElement("button"), - parent: this, - handleEvent: function () { - var marker = { - position: 0, - text: "text" - }; - this.parent.scaleRoot.scales.push(marker); - var markerNode = new this.parent.buildMarkerNode(this.parent, marker); - document.getElementById("popup-option-holder").appendChild(markerNode.root); - this.parent.markerNodes.push(markerNode); - } - }; - this.addMarker.root.textContent = "Add Marker"; - this.addMarker.root.addEventListener("click", this.addMarker); this.content.appendChild(this.addMarker.root); // Create Marker List @@ -1595,7 +1594,7 @@ this.parent.specification.title = event.currentTarget.value; } } - this.titleNode.label.textContent = "Axis Title:"; + this.titleNode.label.textContent = "Presented Axis Title:"; this.titleNode.root.className = "node-children"; this.titleNode.root.appendChild(this.titleNode.label); this.titleNode.root.appendChild(this.titleNode.input); @@ -1603,6 +1602,24 @@ this.titleNode.input.value = this.specification.title; this.children.push(this.titleNode); this.childrenDOM.appendChild(this.titleNode.root); + // Set the interface-name attribute + this.axisName = { + root: document.createElement("div"), + label: document.createElement("span"), + input: document.createElement("input"), + parent: this, + handleEvent: function (event) { + this.parent.specification.name = event.currentTarget.value; + } + } + this.axisName.label.textContent = "Saved Axis Name (no spaces):"; + this.axisName.root.className = "node-children"; + this.axisName.root.appendChild(this.axisName.label); + this.axisName.root.appendChild(this.axisName.input); + this.axisName.input.addEventListener("change", this.axisName, false); + this.axisName.input.value = this.specification.name; + this.children.push(this.axisName); + this.childrenDOM.appendChild(this.axisName.root); } // Put in the check / show options as individual children
--- a/xml/test-schema.xsd Thu Nov 17 13:08:00 2016 +0000 +++ b/xml/test-schema.xsd Thu Nov 17 13:08:26 2016 +0000 @@ -162,6 +162,20 @@ <xs:element name="audioelement"> <xs:complexType> + <xs:sequence> + <xs:element name="alternative" minOccurs="0" maxOccurs="unbounded"> + <xs:complexType> + <xs:attribute name="url" type="xs:anyURI" use="required" /> + <xs:attribute name="sampleRate" use="optional"> + <xs:simpleType> + <xs:restriction base="xs:decimal"> + <xs:minInclusive value="1" /> + </xs:restriction> + </xs:simpleType> + </xs:attribute> + </xs:complexType> + </xs:element> + </xs:sequence> <xs:attribute ref="id" use="required" /> <xs:attribute name="url" type="xs:anyURI" use="required" /> <xs:attribute name="gain" type="xs:decimal" default="0" /> @@ -203,6 +217,13 @@ </xs:restriction> </xs:simpleType> </xs:attribute> + <xs:attribute name="sampleRate" use="optional"> + <xs:simpleType> + <xs:restriction base="xs:decimal"> + <xs:minInclusive value="1" /> + </xs:restriction> + </xs:simpleType> + </xs:attribute> </xs:complexType> </xs:element>