Mercurial > hg > webaudioevaluationtool
changeset 221:9e27ca811051
Merge into default
author | Nicholas Jillings <nicholas.jillings@eecs.qmul.ac.uk> |
---|---|
date | Wed, 17 Jun 2015 16:43:13 +0100 |
parents | 0560fe84fde6 (current diff) d8bad6edaa95 (diff) |
children | 49f35ece394c |
files | |
diffstat | 3 files changed, 319 insertions(+), 31 deletions(-) [+] |
line wrap: on
line diff
--- a/ape.js Wed Jun 17 15:27:11 2015 +0100 +++ b/ape.js Wed Jun 17 16:43:13 2015 +0100 @@ -59,6 +59,94 @@ console.log('slider ' + id + ' played (' + time + ')'); // DEBUG/SAFETY: show played slider id }; + // Bindings for interfaceContext + Interface.prototype.checkAllPlayed = function() + { + hasBeenPlayed = audioEngineContext.checkAllPlayed(); + if (hasBeenPlayed.length > 0) // if a fragment has not been played yet + { + str = ""; + if (hasBeenPlayed.length > 1) { + for (var i=0; i<hasBeenPlayed.length; i++) { + str = str + hasBeenPlayed[i]; + if (i < hasBeenPlayed.length-2){ + str += ", "; + } else if (i == hasBeenPlayed.length-2) { + str += " or "; + } + } + alert('You have not played fragments ' + str + ' yet. Please listen, rate and comment all samples before submitting.'); + } else { + alert('You have not played fragment ' + hasBeenPlayed[0] + ' yet. Please listen, rate and comment all samples before submitting.'); + } + return false; + } + return true; + }; + + Interface.prototype.checkAllMoved = function() { + var audioObjs = audioEngineContext.audioObjects; + var state = true; + var strNums = []; + for (var i=0; i<audioObjs.length; i++) + { + if (audioObjs[i].metric.wasMoved == false) { + state = false; + strNums.push(i); + } + } + if (state == false) { + if (strNums.length > 1) { + var str = ""; + for (var i=0; i<strNums.length; i++) { + str = str + strNums[i]; + if (i < strNums.length-2){ + str += ", "; + } else if (i == strNums.length-2) { + str += " or "; + } + } + alert('You have not moved fragments ' + str + ' yet. Please listen, rate and comment all samples before submitting.'); + } else { + alert('You have not moved fragment ' + strNums[0] + ' yet. Please listen, rate and comment all samples before submitting.'); + } + } + return state; + }; + + Interface.prototype.checkAllCommented = function() { + var audioObjs = audioEngineContext.audioObjects; + var audioHolder = testState.stateMap[testState.stateIndex]; + var state = true; + if (audioHolder.elementComments) { + var strNums = []; + for (var i=0; i<audioObjs.length; i++) + { + if (audioObjs[i].commentDOM.trackCommentBox.value.length == 0) { + state = false; + strNums.push(i); + } + } + if (state == false) { + if (strNums.length > 1) { + var str = ""; + for (var i=0; i<strNums.length; i++) { + str = str + strNums[i]; + if (i < strNums.length-2){ + str += ", "; + } else if (i == strNums.length-2) { + str += " or "; + } + } + alert('You have not commented on fragments ' + str + ' yet. Please listen, rate and comment all samples before submitting.'); + } else { + alert('You have not commented on fragment ' + strNums[0] + ' yet. Please listen, rate and comment all samples before submitting.'); + } + } + } + return state; + }; + // Bindings for audioObjects // Create the top div for the Title element @@ -176,11 +264,11 @@ feedbackHolder.innerHTML = null; canvas.innerHTML = null; - var playbackHolder = document.createElement('div'); - playbackHolder.style.width = "100%"; - playbackHolder.align = 'center'; - playbackHolder.appendChild(interfaceContext.playhead.object); - feedbackHolder.appendChild(playbackHolder); + //var playbackHolder = document.createElement('div'); + //playbackHolder.style.width = "100%"; + //playbackHolder.align = 'center'; + //playbackHolder.appendChild(interfaceContext.playhead.object); + //feedbackHolder.appendChild(playbackHolder); // Setup question title var interfaceObj = audioHolderObject.interfaces; var commentBoxPrefix = "Comment on track"; @@ -322,12 +410,15 @@ } }; - this.exportXMLDOM = function() { + this.exportXMLDOM = function(audioObject) { // Called by the audioObject holding this element. Must be present var node = document.createElement('value'); node.textContent = convSliderPosToRate(this.trackSliderObj); return node; }; + this.getValue = function() { + return convSliderPosToRate(this.trackSliderObj); + }; } function dragEnd(ev) { @@ -353,8 +444,98 @@ function buttonSubmitClick() // TODO: Only when all songs have been played! { - hasBeenPlayed = audioEngineContext.checkAllPlayed(); - if (hasBeenPlayed.length == 0) { + var checks = specification.commonInterface.options; + var canContinue = true; + + // Check that the anchor and reference objects are correctly placed + var audioObjs = audioEngineContext.audioObjects; + var audioHolder = testState.stateMap[testState.stateIndex]; + var anchorId = null; + var referenceId = null; + for (var i=0; i<audioObjs.length; i++) { + if (audioObjs[i].specification.anchor == true && anchorId == null) {anchorId = i;} + if (audioObjs[i].specification.reference == true && referenceId == null) {referenceId = i;} + } + if (anchorId != null) { + if (audioObjs[anchorId].specification.marker != null) { + if (audioObjs[anchorId].interfaceDOM.getValue() > audioObjs[anchorId].specification.marker) + { + // Anchor is not set below + console.log('Anchor node not below marker value'); + alert('Please keep listening'); + return; + } + } else { + // No marker value given, ensure it is the minimum value + var anchorVal = audioObjs[anchorId].interfaceDOM.getValue(); + for (var i=0; i<audioObjs.length; i++) { + if (i != anchorId) { + if (anchorVal > audioObjs[i].interfaceDOM.getValue()) { + // Anchor not the minimum + console.log('No marker set, anchor node not the minimum'); + alert('Please keep listening'); + return; + } + } + } + } + } + if (referenceId != null) { + if (audioObjs[referenceId].specification.marker != null) { + if (audioObjs[referenceId].interfaceDOM.getValue() < audioObjs[referenceId].specification.marker) + { + // Anchor is not set below + console.log('Reference node not above marker value'); + alert('Please keep listening'); + return; + } + } else { + // No marker value given, ensure it is the minimum value + var referenceVal = audioObjs[referenceId].interfaceDOM.getValue(); + for (var i=0; i<audioObjs.length; i++) { + if (i != referenceId) { + if (referenceVal > audioObjs[i].interfaceDOM.getValue()) { + // Anchor not the minimum + console.log('No marker set, reference node not the maximum'); + alert('Please keep listening'); + return; + } + } + } + } + } + + for (var i=0; i<checks.length; i++) { + if (checks[i].type == 'check') + { + switch(checks[i].check) { + case 'fragmentPlayed': + // Check if all fragments have been played + var checkState = interfaceContext.checkAllPlayed(); + if (checkState == false) {canContinue = false;} + break; + case 'fragmentFullPlayback': + // Check all fragments have been played to their full length + var checkState = interfaceContext.checkAllPlayed(); + if (checkState == false) {canContinue = false;} + console.log('NOTE: fragmentFullPlayback not currently implemented, performing check fragmentPlayed instead'); + break; + case 'fragmentMoved': + // Check all fragment sliders have been moved. + var checkState = interfaceContext.checkAllMoved(); + if (checkState == false) {canContinue = false;} + break; + case 'fragmentComments': + // Check all fragment sliders have been moved. + var checkState = interfaceContext.checkAllCommented(); + if (checkState == false) {canContinue = false;} + break; + } + + } + } + + if (canContinue) { if (audioEngineContext.status == 1) { var playback = document.getElementById('playback-button'); playback.click(); @@ -368,24 +549,7 @@ } } testState.advanceState(); - } else // if a fragment has not been played yet - { - str = ""; - if (hasBeenPlayed.length > 1) { - for (var i=0; i<hasBeenPlayed.length; i++) { - str = str + hasBeenPlayed[i]; - if (i < hasBeenPlayed.length-2){ - str += ", "; - } else if (i == hasBeenPlayed.length-2) { - str += " or "; - } - } - alert('You have not played fragments ' + str + ' yet. Please listen, rate and comment all samples before submitting.'); - } else { - alert('You have not played fragment ' + hasBeenPlayed[0] + ' yet. Please listen, rate and comment all samples before submitting.'); - } - return; - } + } } function convSliderPosToRate(slider)
--- a/core.js Wed Jun 17 15:27:11 2015 +0100 +++ b/core.js Wed Jun 17 16:43:13 2015 +0100 @@ -892,8 +892,8 @@ var root = document.createElement('audioElement'); root.id = this.specification.id; root.setAttribute('url',this.url); - root.appendChild(this.interfaceDOM.exportXMLDOM()); - root.appendChild(this.commentDOM.exportXMLDOM()); + root.appendChild(this.interfaceDOM.exportXMLDOM(this)); + root.appendChild(this.commentDOM.exportXMLDOM(this)); root.appendChild(this.metric.exportXMLDOM()); return root; }; @@ -1201,6 +1201,7 @@ // Handles the decoding of the project specification XML into a simple JavaScript Object. this.interfaceType; + this.commonInterface; this.projectReturn; this.randomiseOrder; this.collectMetrics; @@ -1233,6 +1234,32 @@ } } + var commonInterfaceNode = setupNode.getElementsByTagName('interface'); + if (commonInterfaceNode.length > 0) { + commonInterfaceNode = commonInterfaceNode[0]; + } else { + commonInterfaceNode = undefined; + } + + this.commonInterface = new function() { + this.OptionNode = function(child) { + this.type = child.nodeName; + if (this.type == 'check') { + this.check = child.getAttribute('name'); + } else if (this.type == 'anchor' || this.type == 'reference') { + this.value = Number(child.textContent); + } + }; + this.options = []; + if (commonInterfaceNode != undefined) { + var child = commonInterfaceNode.firstElementChild; + while (child != undefined) { + this.options.push(new this.OptionNode(child)); + child = child.nextElementSibling; + } + } + }; + var audioHolders = projectXML.getElementsByTagName('audioHolder'); for (var i=0; i<audioHolders.length; i++) { this.audioHolders.push(new this.audioHolderNode(this,audioHolders[i])); @@ -1333,6 +1360,27 @@ this.url = xml.getAttribute('url'); this.id = xml.id; this.parent = parent; + this.anchor = xml.getAttribute('anchor'); + if (this.anchor == 'true') {this.anchor = true;} + else {this.anchor = false;} + + this.reference = xml.getAttribute('reference'); + if (this.reference == 'true') {this.reference = true;} + else {this.reference = false;} + + if (this.anchor == true && this.reference == true) { + console.log('ERROR - Cannot have one audioElement be both the reference and anchor!'); + console.log(this); + console.log('Neither reference nor anchor will be enabled on this fragment'); + this.anchor = false; + this.reference = false; + } + if (this.anchor == true) { + this.marker = anchor; + } + if (this.reference == true) { + this.marker = reference; + } }; this.commentQuestionNode = function(xml) { @@ -1388,6 +1436,46 @@ if (xml.getAttribute('elementComments') == "true") {this.elementComments = true;} else {this.elementComments = false;} + var anchor = xml.getElementsByTagName('anchor'); + if (anchor.length == 0) { + // Find anchor in commonInterface; + for (var i=0; i<parent.commonInterface.options.length; i++) { + if(parent.commonInterface.options[i].type == 'anchor') { + anchor = parent.commonInterface.options[i].value; + break; + } + } + if (typeof(anchor) == "object") { + anchor = null; + } + } else { + anchor = anchor[0].textContent; + } + + var reference = xml.getElementsByTagName('anchor'); + if (reference.length == 0) { + // Find anchor in commonInterface; + for (var i=0; i<parent.commonInterface.options.length; i++) { + if(parent.commonInterface.options[i].type == 'reference') { + reference = parent.commonInterface.options[i].value; + break; + } + } + if (typeof(reference) == "object") { + reference = null; + } + } else { + reference = reference[0].textContent; + } + + if (typeof(anchor) == 'number') { + if (anchor > 1 && anchor < 100) {anchor /= 100.0;} + } + + if (typeof(reference) == 'number') { + if (reference > 1 && reference < 100) {reference /= 100.0;} + } + this.preTest = new parent.prepostNode('pretest',xml.getElementsByTagName('PreTest')); this.postTest = new parent.prepostNode('posttest',xml.getElementsByTagName('PostTest')); @@ -1410,6 +1498,34 @@ this.audioElements.push(new this.audioElementNode(this,audioElementsDOM[i])); } + // Check only one anchor and one reference per audioNode + var anchor = []; + var reference = []; + for (var i=0; i<this.audioElements.length; i++) + { + if (this.audioElements[i].anchor == true) {anchor.push(i);} + if (this.audioElements[i].reference == true) {reference.push(i);} + } + + if (anchor.length > 1) { + console.log('Error - cannot have more than one anchor!'); + console.log('Each anchor node will be a normal mode to continue the test'); + for (var i=0; i<anchor.length; i++) + { + this.audioElements[anchor[i]].anchor = false; + this.audioElements[anchor[i]].value = undefined; + } + } + if (reference.length > 1) { + console.log('Error - cannot have more than one anchor!'); + console.log('Each anchor node will be a normal mode to continue the test'); + for (var i=0; i<reference.length; i++) + { + this.audioElements[reference[i]].reference = false; + this.audioElements[reference[i]].value = undefined; + } + } + this.commentQuestions = []; var commentQuestionsDOM = xml.getElementsByTagName('CommentQuestion'); for (var i=0; i<commentQuestionsDOM.length; i++) {
--- a/example_eval/project.xml Wed Jun 17 15:27:11 2015 +0100 +++ b/example_eval/project.xml Wed Jun 17 16:43:13 2015 +0100 @@ -34,6 +34,14 @@ <metricEnable>elementFlagMoved</metricEnable> <metricEnable>elementListenTracker</metricEnable> </Metric> + <interface> + <!--<check name="fragmentPlayed"/> + <check name="fragmentFullPlayback"/> + <check name="fragmentMoved"/> + <check name="fragmentComments"/>--> + <anchor>20</anchor> + <reference>80</reference> + </interface> </setup> <audioHolder id='test-0' hostURL="example_eval/" sampleRate="44100" randomiseOrder='true' repeatCount='0' loop='true' elementComments='true'> <interface> @@ -44,7 +52,7 @@ <scale position="20">20</scale> <commentBoxPrefix>Comment on fragment</commentBoxPrefix> </interface> - <audioElements url="0.wav" id="0"/> + <audioElements url="0.wav" id="0" anchor='true'/> <audioElements url="1.wav" id="1"/> <audioElements url="2.wav" id="2"/> <audioElements url="3.wav" id="3"/> @@ -86,8 +94,8 @@ <scale position="75">75</scale> <commentBoxPrefix>Comment on fragment</commentBoxPrefix> </interface> - <audioElements url="0.wav" id="0"/> - <audioElements url="1.wav" id="1"/> + <audioElements url="0.wav" id="0" reference="true"/> + <audioElements url="1.wav" id="1" anchor="true"/> <audioElements url="2.wav" id="2"/> <audioElements url="3.wav" id="3"/> <audioElements url="4.wav" id="4"/>