Mercurial > hg > webaudioevaluationtool
changeset 1342:397e96ee781a
Better loudness calculation. Buffer ready not called until after loudness calculation to avoid NaNs on gain. <survey> nodes do not need to be present, no survey then no node. Added example boilerplate interface with all required functions and brief descriptions.
author | Nicholas Jillings <nickjillings@users.noreply.github.com> |
---|---|
date | Wed, 13 Jan 2016 10:31:31 +0000 |
parents | bbb6462cf446 |
children | 9af89ccadb59 |
files | core.js interfaces/blank.js interfaces/mushra.js loudness.js test-schema.xsd |
diffstat | 5 files changed, 98 insertions(+), 24 deletions(-) [+] |
line wrap: on
line diff
--- a/core.js Wed Jan 13 09:34:46 2016 +0000 +++ b/core.js Wed Jan 13 10:31:31 2016 +0000 @@ -730,12 +730,14 @@ this.initialise(); } if (this.stateIndex == -1) { + this.stateIndex++; console.log('Starting test...'); if (this.preTestSurvey != null) { popup.initState(this.preTestSurvey,storage.globalPreTest); + } else { + this.advanceState(); } - this.stateIndex++; } else if (this.stateIndex == this.stateMap.length) { // All test pages complete, post test @@ -860,6 +862,17 @@ this.xmlRequest = new XMLHttpRequest(); this.xmlRequest.parent = this; this.users = []; + this.ready = function() + { + 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); + } + } + }; this.getMedia = function(url) { this.url = url; this.xmlRequest.open('GET',this.url,true); @@ -871,15 +884,8 @@ this.xmlRequest.onloadend = function() { audioContext.decodeAudioData(bufferObj.xmlRequest.response, function(decodedData) { bufferObj.buffer = decodedData; - for (var i=0; i<bufferObj.users.length; i++) - { - bufferObj.users[i].state = 1; - if (bufferObj.users[i].interfaceDOM != null) - { - bufferObj.users[i].bufferLoaded(bufferObj); - } - } - calculateLoudness(bufferObj.buffer,"I"); + calculateLoudness(bufferObj,"I"); + }, function(){ // Should only be called if there was an error, but sometimes gets called continuously // Check here if the error is genuine @@ -2827,8 +2833,8 @@ this.initialise = function() { - this.globalPreTest = new this.surveyNode(this,this.root,specification.preTest); - this.globalPostTest = new this.surveyNode(this,this.root,specification.postTest); + if (specification.preTest != undefined){this.globalPreTest = new this.surveyNode(this,this.root,specification.preTest);} + if (specification.postTest != undefined){this.globalPostTest = new this.surveyNode(this,this.root,specification.postTest);} }; this.createTestPageStore = function(specification) @@ -2897,8 +2903,8 @@ this.XMLDOM = this.parent.document.createElement('page'); this.XMLDOM.setAttribute('id',specification.id); this.XMLDOM.setAttribute('presentedId',specification.presentedId); - this.preTest = new this.parent.surveyNode(parent,this.XMLDOM,specification.preTest); - this.postTest = new this.parent.surveyNode(parent,this.XMLDOM,specification.postTest); + if (specification.preTest != undefined){this.preTest = new this.surveyNode(this,this.root,this.specification.preTest);} + if (specification.postTest != undefined){this.postTest = new this.surveyNode(this,this.root,this.specification.postTest);} // Add any page metrics var page_metric = this.parent.document.createElement('metric');
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/interfaces/blank.js Wed Jan 13 10:31:31 2016 +0000 @@ -0,0 +1,67 @@ +/** + * WAET Blank Template + * Use this to start building your custom interface + */ + +// Once this is loaded and parsed, begin execution +loadInterface(); + +function loadInterface() { + // Use this to do any one-time page / element construction. For instance, placing any stationary text objects, + // holding div's, or setting up any nodes which are present for the entire test sequence +}; + +function loadTest(page) +{ + // Called each time a new test page is to be build. The page specification node is the only item passed in +} + +function interfaceObject() +{ + // An example node, you can make this however you want for each audioElement. + // However, every audioObject (audioEngineContext.audioObject) MUST have an interface object with the following + // You attach them by calling audioObject.bindInterface( ) + this.enable = function() + { + // This is used to tell the interface object that playback of this node is ready + }; + this.updateLoading = function(progress) + { + // progress is a value from 0 to 100 indicating the current download state of media files + }; + this.getValue = function() + { + // Return the current value of the object. If there is no value, return 0 + }; + this.getPresentedId = function() + { + // Return the presented ID of the object. For instance, the APE has sliders starting from 0. Whilst AB has alphabetical scale + }; + this.canMove = function() + { + // Return either true or false if the interface object can be moved. AB / Reference cannot, whilst sliders can and therefore have a continuous scale. + // These are checked primarily if the interface check option 'fragmentMoved' is enabled. + }; + this.exportXMLDOM = function(audioObject) { + // Called by the audioObject holding this element to export the interface <value> node. + // If there is no value node (such as outside reference), return null + // If there are multiple value nodes (such as multiple scale / 2D scales), return an array of nodes with each value node having an 'interfaceName' attribute + // Use storage.document.createElement('value'); to generate the XML node. + + }; +}; + +function resizeWindow(event) +{ + // Called on every window resize event, use this to scale your page properly +} + +function pageXMLSave(store, pageSpecification) +{ + // MANDATORY + // Saves a specific test page + // You can use this space to add any extra nodes to your XML <audioHolder> saves + // Get the current <page> information in store (remember to appendChild your data to it) + // pageSpecification is the current page node configuration + // To create new XML nodes, use storage.document.createElement(); +} \ No newline at end of file
--- a/interfaces/mushra.js Wed Jan 13 09:34:46 2016 +0000 +++ b/interfaces/mushra.js Wed Jan 13 10:31:31 2016 +0000 @@ -166,18 +166,18 @@ var node = interfaceContext.createCommentBox(audioObject); // Create a slider per track - audioObject.bindInterface(new sliderObject(audioObject,label)); + var sliderObj = new sliderObject(audioObject,label); if (typeof audioHolderObject.initialPosition === "number") { // Set the values - audioObject.interfaceDOM.slider.value = audioHolderObject.initalPosition; + sliderObj.slider.value = audioHolderObject.initalPosition; } else { // Distribute it randomnly - audioObject.interfaceDOM.slider.value = Math.random(); + sliderObj.slider.value = Math.random(); } - sliderBox.appendChild(audioObject.interfaceDOM.holder); - audioObject.metric.initialise(audioObject.interfaceDOM.slider.value); + sliderBox.appendChild(sliderObj.holder); + audioObject.bindInterface(sliderObj); label += 1; }
--- a/loudness.js Wed Jan 13 09:34:46 2016 +0000 +++ b/loudness.js Wed Jan 13 10:31:31 2016 +0000 @@ -34,7 +34,7 @@ } if (offlineContext == undefined) { - offlineContext = new OfflineAudioContext(buffer.numberOfChannels, buffer.length, buffer.sampleRate); + offlineContext = new OfflineAudioContext(buffer.buffer.numberOfChannels, buffer.buffer.length, buffer.buffer.sampleRate); } // Create the required filters var KFilter = offlineContext.createBiquadFilter(); @@ -48,7 +48,7 @@ HPFilter.frequency.value = 60; // copy Data into the process buffer var processSource = offlineContext.createBufferSource(); - processSource.buffer = buffer; + processSource.buffer = buffer.buffer; processSource.connect(KFilter); KFilter.connect(HPFilter); @@ -100,7 +100,8 @@ } } var overallRelLoudness = calculateOverallLoudnessFromChannelBlocks(relgateEnergy); - buffer.lufs = overallRelLoudness; + buffer.buffer.lufs = overallRelLoudness; + buffer.ready(); } }; offlineContext.startRendering();
--- a/test-schema.xsd Wed Jan 13 09:34:46 2016 +0000 +++ b/test-schema.xsd Wed Jan 13 10:31:31 2016 +0000 @@ -23,7 +23,7 @@ <xs:element name="setup"> <xs:complexType> <xs:sequence> - <xs:element ref="survey" maxOccurs="2"/> + <xs:element ref="survey" minOccurs="0" maxOccurs="2"/> <xs:element ref="metric" maxOccurs="1"/> <xs:element ref="interface" maxOccurs="1"/> </xs:sequence> @@ -44,7 +44,7 @@ <xs:element ref="interface" minOccurs="1" maxOccurs="unbounded"/> <xs:element ref="audioelement" minOccurs="1" maxOccurs="unbounded"/> <xs:element ref="commentquestion" minOccurs="0" maxOccurs="unbounded"/> - <xs:element ref="survey" maxOccurs="2"/> + <xs:element ref="survey" minOccurs="0" maxOccurs="2"/> </xs:sequence> <xs:attribute ref="id" use="required"/> <xs:attribute name="hostURL" type="xs:anyURI" use="required"/>