Mercurial > hg > webaudioevaluationtool
changeset 2575:249a1152e525
Merge branch 'master' into Dev_main
# Conflicts:
# interfaces/AB.js
# js/core.js
# js/specification.js
author | Nicholas Jillings <nicholas.jillings@mail.bcu.ac.uk> |
---|---|
date | Tue, 18 Oct 2016 15:49:58 +0100 |
parents | b6bc57a2a681 (current diff) 9b536838a962 (diff) |
children | d002a342cfaf |
files | interfaces/AB.js js/core.js js/specification.js tests/examples/project.xml |
diffstat | 8 files changed, 463 insertions(+), 467 deletions(-) [+] |
line wrap: on
line diff
--- a/interfaces/AB.js Tue Oct 18 15:28:24 2016 +0100 +++ b/interfaces/AB.js Tue Oct 18 15:49:58 2016 +0100 @@ -2,15 +2,15 @@ loadInterface(); function loadInterface() { - // Get the dimensions of the screen available to the page - var width = window.innerWidth; - var height = window.innerHeight; - interfaceContext.insertPoint.innerHTML = ""; // Clear the current schema - - // Custom comparator Object - Interface.prototype.comparator = null; - - Interface.prototype.checkScaleRange = function (min, max) { + // Get the dimensions of the screen available to the page + var width = window.innerWidth; + var height = window.innerHeight; + interfaceContext.insertPoint.innerHTML = ""; // Clear the current schema + + // Custom comparator Object + Interface.prototype.comparator = null; + + Interface.prototype.checkScaleRange = function(min, max) { var page = testState.getCurrentTestPage(); var audioObjects = audioEngineContext.audioObjects; var state = true; @@ -19,170 +19,166 @@ var maxRanking = -Infinity; for (var ao of audioObjects) { var rank = ao.interfaceDOM.getValue(); - if (rank < minRanking) { - minRanking = rank; - } - if (rank > maxRanking) { - maxRanking = rank; - } + if (rank < minRanking) {minRanking = rank;} + if (rank > maxRanking) {maxRanking = rank;} } - if (maxRanking * 100 < max) { + if (maxRanking*100 < max) { str += "At least one fragment must be selected." state = false; } if (!state) { console.log(str); this.storeErrorNode(str); - interfaceContext.lightbox.post("Message", str); + interfaceContext.lightbox.post("Message",str); } return state; } - - // The injection point into the HTML page - interfaceContext.insertPoint = document.getElementById("topLevelBody"); - var testContent = document.createElement('div'); - testContent.id = 'testContent'; - - // Create the top div for the Title element - var titleAttr = specification.title; - var title = document.createElement('div'); - title.className = "title"; - title.align = "center"; - var titleSpan = document.createElement('span'); + + // The injection point into the HTML page + interfaceContext.insertPoint = document.getElementById("topLevelBody"); + var testContent = document.createElement('div'); + testContent.id = 'testContent'; + + // Create the top div for the Title element + var titleAttr = specification.title; + var title = document.createElement('div'); + title.className = "title"; + title.align = "center"; + var titleSpan = document.createElement('span'); titleSpan.id = "test-title"; - - // Set title to that defined in XML, else set to default - if (titleAttr != undefined) { - titleSpan.textContent = titleAttr; - } else { - titleSpan.textContent = 'Listening test'; - } - // Insert the titleSpan element into the title div element. - title.appendChild(titleSpan); - - var pagetitle = document.createElement('div'); - pagetitle.className = "pageTitle"; - pagetitle.align = "center"; - var titleSpan = document.createElement('span'); - titleSpan.id = "pageTitle"; - pagetitle.appendChild(titleSpan); - - // Create Interface buttons! - var interfaceButtons = document.createElement('div'); - interfaceButtons.id = 'interface-buttons'; - interfaceButtons.style.height = '25px'; - - // Create playback start/stop points - var playback = document.createElement("button"); - playback.innerHTML = 'Stop'; - playback.id = 'playback-button'; - playback.style.float = 'left'; - // onclick function. Check if it is playing or not, call the correct function in the - // audioEngine, change the button text to reflect the next state. - playback.onclick = function () { - if (audioEngineContext.status == 1) { - audioEngineContext.stop(); - this.innerHTML = 'Stop'; + + // Set title to that defined in XML, else set to default + if (titleAttr != undefined) { + titleSpan.textContent = titleAttr; + } else { + titleSpan.textContent = 'Listening test'; + } + // Insert the titleSpan element into the title div element. + title.appendChild(titleSpan); + + var pagetitle = document.createElement('div'); + pagetitle.className = "pageTitle"; + pagetitle.align = "center"; + var titleSpan = document.createElement('span'); + titleSpan.id = "pageTitle"; + pagetitle.appendChild(titleSpan); + + // Create Interface buttons! + var interfaceButtons = document.createElement('div'); + interfaceButtons.id = 'interface-buttons'; + interfaceButtons.style.height = '25px'; + + // Create playback start/stop points + var playback = document.createElement("button"); + playback.innerHTML = 'Stop'; + playback.id = 'playback-button'; + playback.style.float = 'left'; + // onclick function. Check if it is playing or not, call the correct function in the + // audioEngine, change the button text to reflect the next state. + playback.onclick = function() { + if (audioEngineContext.status == 1) { + audioEngineContext.stop(); + this.innerHTML = 'Stop'; var time = audioEngineContext.timer.getTestTime(); console.log('Stopped at ' + time); // DEBUG/SAFETY - } - }; - // Append the interface buttons into the interfaceButtons object. - interfaceButtons.appendChild(playback); - - // Global parent for the comment boxes on the page - var feedbackHolder = document.createElement('div'); - feedbackHolder.id = 'feedbackHolder'; - + } + }; + // Append the interface buttons into the interfaceButtons object. + interfaceButtons.appendChild(playback); + + // Global parent for the comment boxes on the page + var feedbackHolder = document.createElement('div'); + feedbackHolder.id = 'feedbackHolder'; + // Create outside reference holder var outsideRef = document.createElement("div"); outsideRef.id = "outside-reference-holder"; - - // Construct the AB Boxes - var boxes = document.createElement('div'); - boxes.align = "center"; - boxes.id = "box-holders"; + + // Construct the AB Boxes + var boxes = document.createElement('div'); + boxes.align = "center"; + boxes.id = "box-holders"; boxes.style.float = "left"; - - var submit = document.createElement('button'); - submit.id = "submit"; - submit.onclick = buttonSubmitClick; - submit.className = "big-button"; - submit.textContent = "submit"; - submit.style.position = "relative"; - submit.style.left = (window.innerWidth - 250) / 2 + 'px'; - - feedbackHolder.appendChild(boxes); - + + var submit = document.createElement('button'); + submit.id = "submit"; + submit.onclick = buttonSubmitClick; + submit.className = "big-button"; + submit.textContent = "submit"; + submit.style.position = "relative"; + submit.style.left = (window.innerWidth-250)/2 + 'px'; + + feedbackHolder.appendChild(boxes); + // Create holder for comment boxes var comments = document.createElement("div"); comments.id = "comment-box-holder"; + + // Inject into HTML + testContent.appendChild(title); // Insert the title + testContent.appendChild(pagetitle); + testContent.appendChild(interfaceButtons); + testContent.appendChild(outsideRef); + testContent.appendChild(feedbackHolder); + testContent.appendChild(submit); + testContent.appendChild(comments); + interfaceContext.insertPoint.appendChild(testContent); - // Inject into HTML - testContent.appendChild(title); // Insert the title - testContent.appendChild(pagetitle); - testContent.appendChild(interfaceButtons); - testContent.appendChild(outsideRef); - testContent.appendChild(feedbackHolder); - testContent.appendChild(submit); - testContent.appendChild(comments); - interfaceContext.insertPoint.appendChild(testContent); - - // Load the full interface - testState.initialise(); - testState.advanceState(); + // Load the full interface + testState.initialise(); + testState.advanceState(); } -function loadTest(audioHolderObject) { - var feedbackHolder = document.getElementById('feedbackHolder'); - var interfaceObj = audioHolderObject.interfaces; - if (interfaceObj.length > 1) { - console.log("WARNING - This interface only supports one <interface> node per page. Using first interface node"); - } - interfaceObj = interfaceObj[0]; - +function loadTest(audioHolderObject) +{ + var feedbackHolder = document.getElementById('feedbackHolder'); + var interfaceObj = audioHolderObject.interfaces; + if (interfaceObj.length > 1) + { + console.log("WARNING - This interface only supports one <interface> node per page. Using first interface node"); + } + interfaceObj = interfaceObj[0]; + var commentHolder = document.getElementById('comment-box-holder'); commentHolder.innerHTML = ""; - + // Delete outside reference - var outsideReferenceHolder = document.getElementById("outside-reference-holder"); + var outsideReferenceHolder = document.getElementById("outside-reference-holder"); outsideReferenceHolder.innerHTML = ""; - + // Set the page title if (typeof audioHolderObject.title == "string" && audioHolderObject.title.length > 0) { document.getElementById("test-title").textContent = audioHolderObject.title } - - if (interfaceObj.title != null) { - document.getElementById("pageTitle").textContent = interfaceObj.title; - } - + + if(interfaceObj.title != null) + { + document.getElementById("pageTitle").textContent = interfaceObj.title; + } + var interfaceOptions = specification.interfaces.options.concat(interfaceObj.options); // Clear the interfaceElements { var node = document.getElementById('playback-holder'); - if (node) { - feedbackHolder.removeChild(node); - } + if (node){feedbackHolder.removeChild(node);} node = document.getElementById('page-count'); - if (node) { - document.getElementById('interface-buttons').removeChild(node); - } + if (node){document.getElementById('interface-buttons').removeChild(node);} node = document.getElementById('master-volume-holder-float'); - if (node) { - feedbackHolder.removeChild(node); - } + if (node){feedbackHolder.removeChild(node);} } - + // Populate the comparator object - interfaceContext.comparator = new comparator(audioHolderObject); - - for (var option of interfaceOptions) { - if (option.type == "show") { - switch (option.name) { + interfaceContext.comparator = new comparator(audioHolderObject); + + for (var option of interfaceOptions) + { + if (option.type == "show") + { + switch(option.name) { case "playhead": var playbackHolder = document.getElementById('playback-holder'); - if (playbackHolder == null) { + if (playbackHolder == null) + { playbackHolder = document.createElement('div'); playbackHolder.id = 'playback-holder'; playbackHolder.style.width = "100%"; @@ -194,329 +190,309 @@ break; case "page-count": var pagecountHolder = document.getElementById('page-count'); - if (pagecountHolder == null) { + if (pagecountHolder == null) + { pagecountHolder = document.createElement('div'); pagecountHolder.id = 'page-count'; document.getElementById('interface-buttons').appendChild(pagecountHolder); } - pagecountHolder.innerHTML = '<span>Page ' + (testState.stateIndex + 1) + ' of ' + testState.stateMap.length + '</span>'; + pagecountHolder.innerHTML = '<span>Page '+(testState.stateIndex+1)+' of '+testState.stateMap.length+'</span>'; break; case "volume": - if (document.getElementById('master-volume-holder-float') == null) { + if (document.getElementById('master-volume-holder-float') == null) + { feedbackHolder.appendChild(interfaceContext.volume.object); } break; case "comments": // Generate one comment box per presented page - for (var element of audioEngineContext.audioObjects) { + for (var element of audioEngineContext.audioObjects) + { interfaceContext.commentBoxes.createCommentBox(element); } - interfaceContext.commentBoxes.showCommentBoxes(commentHolder, true); + interfaceContext.commentBoxes.showCommentBoxes(commentHolder,true); break; } } } - - $(audioHolderObject.commentQuestions).each(function (index, element) { - var node = interfaceContext.createCommentQuestion(element); - commentHolder.appendChild(node.holder); - }); - - resizeWindow(null); + + $(audioHolderObject.commentQuestions).each(function(index,element) { + var node = interfaceContext.createCommentQuestion(element); + commentHolder.appendChild(node.holder); + }); + + resizeWindow(null); } -function comparator(audioHolderObject) { - this.comparatorBox = function (audioElement, id, text) { - this.parent = audioElement; - this.id = id; - this.value = 0; - this.disabled = true; - this.box = document.createElement('div'); - this.box.className = 'comparator-holder'; - this.box.setAttribute('track-id', audioElement.id); - this.box.id = 'comparator-' + text; - this.selector = document.createElement('div'); - this.selector.className = 'comparator-selector disabled'; - var selectorText = document.createElement('span'); - selectorText.textContent = text; - this.selector.appendChild(selectorText); - this.playback = document.createElement('button'); - this.playback.className = 'comparator-button'; - this.playback.disabled = true; - this.playback.textContent = "Listen"; - this.box.appendChild(this.selector); - this.box.appendChild(this.playback); - this.selector.onclick = function (event) { - var time = audioEngineContext.timer.getTestTime(); - if ($(event.currentTarget).hasClass('disabled')) { - console.log("Please wait until sample has loaded"); - return; +function comparator(audioHolderObject) +{ + this.comparatorBox = function(audioElement,id,text) + { + this.parent = audioElement; + this.id = id; + this.value = 0; + this.disabled = true; + this.box = document.createElement('div'); + this.box.className = 'comparator-holder'; + this.box.setAttribute('track-id',audioElement.id); + this.box.id = 'comparator-'+text; + this.selector = document.createElement('div'); + this.selector.className = 'comparator-selector disabled'; + var selectorText = document.createElement('span'); + selectorText.textContent = text; + this.selector.appendChild(selectorText); + this.playback = document.createElement('button'); + this.playback.className = 'comparator-button'; + this.playback.disabled = true; + this.playback.textContent = "Listen"; + this.box.appendChild(this.selector); + this.box.appendChild(this.playback); + this.selector.onclick = function(event) + { + var time = audioEngineContext.timer.getTestTime(); + if ($(event.currentTarget).hasClass('disabled')) + { + console.log("Please wait until sample has loaded"); + return; + } + if (audioEngineContext.status == 0) + { + interfaceContext.lightbox.post("Message","Please listen to the samples before making a selection"); + console.log("Please listen to the samples before making a selection"); + return; } - if (audioEngineContext.status == 0) { - interfaceContext.lightbox.post("Message", "Please listen to the samples before making a selection"); - console.log("Please listen to the samples before making a selection"); - return; - } - var id = event.currentTarget.parentElement.getAttribute('track-id'); - interfaceContext.comparator.selected = id; + var id = event.currentTarget.parentElement.getAttribute('track-id'); + interfaceContext.comparator.selected = id; if ($(event.currentTarget).hasClass("selected")) { $(".comparator-selector").removeClass('selected'); - for (var i = 0; i < interfaceContext.comparator.comparators.length; i++) { + for (var i=0; i<interfaceContext.comparator.comparators.length; i++) + { var obj = interfaceContext.comparator.comparators[i]; - obj.parent.metric.moved(time, 0); + obj.parent.metric.moved(time,0); obj.value = 0; } } else { $(".comparator-selector").removeClass('selected'); $(event.currentTarget).addClass('selected'); - for (var i = 0; i < interfaceContext.comparator.comparators.length; i++) { + for (var i=0; i<interfaceContext.comparator.comparators.length; i++) + { var obj = interfaceContext.comparator.comparators[i]; if (i == id) { obj.value = 1; } else { obj.value = 0; } - obj.parent.metric.moved(time, obj.value); + obj.parent.metric.moved(time,obj.value); } - console.log("Selected " + id + ' (' + time + ')'); + console.log("Selected "+id+' ('+time+')'); } - }; - this.playback.setAttribute("playstate", "ready"); - this.playback.onclick = function (event) { - var id = event.currentTarget.parentElement.getAttribute('track-id'); - if (event.currentTarget.getAttribute("playstate") == "ready") { + }; + this.playback.setAttribute("playstate","ready"); + this.playback.onclick = function(event) + { + var id = event.currentTarget.parentElement.getAttribute('track-id'); + if (event.currentTarget.getAttribute("playstate") == "ready") + { audioEngineContext.play(id); } else if (event.currentTarget.getAttribute("playstate") == "playing") { audioEngineContext.stop(); } - - }; - - this.enable = function () { - if (this.parent.state == 1) { - $(this.selector).removeClass('disabled'); - this.playback.disabled = false; - } - }; - this.updateLoading = function (progress) { - if (progress != 100) { - progress = String(progress); - progress = progress.split('.')[0]; - this.playback.textContent = progress + '%'; - } else { - this.playback.textContent = "Play"; - } - }; - this.error = function () { + + }; + + this.enable = function() + { + if (this.parent.state == 1) + { + $(this.selector).removeClass('disabled'); + this.playback.disabled = false; + } + }; + this.updateLoading = function(progress) + { + if (progress != 100) + { + progress = String(progress); + progress = progress.split('.')[0]; + this.playback.textContent = progress+'%'; + } else { + this.playback.textContent = "Play"; + } + }; + this.error = function() { // audioObject has an error!! this.playback.textContent = "Error"; $(this.playback).addClass("error-colour"); } - this.startPlayback = function () { + this.startPlayback = function() + { if (this.parent.specification.parent.playOne || specification.playOne) { $('.comparator-button').text('Wait'); - $('.comparator-button').attr("disabled", "true"); - $(this.playback).css("disabled", "false"); + $('.comparator-button').attr("disabled","true"); + $(this.playback).removeAttr("disabled"); } else { $('.comparator-button').text('Listen'); } $(this.playback).text('Stop'); - this.playback.setAttribute("playstate", "playing"); + this.playback.setAttribute("playstate","playing"); }; - this.stopPlayback = function () { + this.stopPlayback = function() + { if (this.playback.getAttribute("playstate") == "playing") { $('.comparator-button').text('Listen'); $('.comparator-button').removeAttr("disabled"); - this.playback.setAttribute("playstate", "ready"); + this.playback.setAttribute("playstate","ready"); } }; - this.exportXMLDOM = function (audioObject) { - var node = storage.document.createElement('value'); - node.textContent = this.value; - return node; - }; - this.getValue = function () { - return this.value; - }; - this.getPresentedId = function () { - return this.selector.children[0].textContent; - }; - this.canMove = function () { - return false; - }; - }; - - this.boxHolders = document.getElementById('box-holders'); - this.boxHolders.innerHTML = ""; - this.comparators = []; - this.selected = null; - - // First generate the Audio Objects for the Audio Engine - var label = audioHolderObject.labelStart; - if (label == "") { - switch (audioHolderObject.label) { - case "number": - label = "1"; - break; - case "letter": - label = "a"; - break; - case "none": - label = ""; - break; - case "capital": - default: - label = "A"; - break; - } - } else { - switch (audioHolderObject.label) { - case "number": - if (!isFinite(Number(label))) { - label = "1"; - } - break; - case "letter": - if (label.charCodeAt(0) < 97 || label.charCodeAt(0) > 122) { - label = "a"; - } - break; - case "none": - label = ""; - break; - case "capital": - default: - if (label.charCodeAt(0) < 65 || label.charCodeAt(0) > 90) { - label = "A"; - } - break; - } - } - for (var index = 0; index < audioHolderObject.audioElements.length; index++) { - var element = audioHolderObject.audioElements[index]; + this.exportXMLDOM = function(audioObject) + { + var node = storage.document.createElement('value'); + node.textContent = this.value; + return node; + }; + this.getValue = function() { + return this.value; + }; + this.getPresentedId = function() + { + return this.selector.children[0].textContent; + }; + this.canMove = function() + { + return false; + }; + }; + + this.boxHolders = document.getElementById('box-holders'); + this.boxHolders.innerHTML = ""; + this.comparators = []; + this.selected = null; + + // First generate the Audio Objects for the Audio Engine + for (var index=0; index<audioHolderObject.audioElements.length; index++) + { + var element = audioHolderObject.audioElements[index]; var audioObject = audioEngineContext.newTrack(element); - if (index == audioHolderObject.outsideReference || element.type == 'outside-reference') { - var orNode = new interfaceContext.outsideReferenceDOM(audioObject, index, document.getElementById("outside-reference-holder")); - audioObject.bindInterface(orNode); + if (index == audioHolderObject.outsideReference || element.type == 'outside-reference') + { + var orNode = new interfaceContext.outsideReferenceDOM(audioObject,index,document.getElementById("outside-reference-holder")); + audioObject.bindInterface(orNode); } else { - var node = new this.comparatorBox(audioObject, index, label); - switch (audioHolderObject.label) { + var label; + switch(audioObject.specification.parent.label) { case "none": label = ""; break; case "number": - label = (Number(label) + 1).toString(10); + label = ""+index; break; case "letter": - label = String.fromCharCode((label.charCodeAt(0) - 96) % 26 + 97); + label = String.fromCharCode(97 + index); break; - case "capital": default: - label = String.fromCharCode((label.charCodeAt(0) - 64) % 26 + 65); + label = String.fromCharCode(65 + index); break; } + var node = new this.comparatorBox(audioObject,index,label); audioObject.bindInterface(node); this.comparators.push(node); this.boxHolders.appendChild(node.box); } - } - return this; + } + return this; } -function resizeWindow(event) { - document.getElementById('submit').style.left = (window.innerWidth - 250) / 2 + 'px'; - var numObj = interfaceContext.comparator.comparators.length; - var boxW = numObj * 312; +function resizeWindow(event) +{ + document.getElementById('submit').style.left = (window.innerWidth-250)/2 + 'px'; + var numObj = interfaceContext.comparator.comparators.length; + var boxW = numObj*312; var diff = window.innerWidth - boxW; - while (diff < 0) { - numObj = Math.ceil(numObj / 2); - boxW = numObj * 312; + while (diff < 0) + { + numObj = Math.ceil(numObj/2); + boxW = numObj*312; diff = window.innerWidth - boxW; } - document.getElementById('box-holders').style.marginLeft = diff / 2 + 'px'; - document.getElementById('box-holders').style.marginRight = diff / 2 + 'px'; + document.getElementById('box-holders').style.marginLeft = diff/2 + 'px'; + document.getElementById('box-holders').style.marginRight = diff/2 + 'px'; document.getElementById('box-holders').style.width = boxW + 'px'; - + var outsideRef = document.getElementById('outside-reference'); - if (outsideRef != null) { - outsideRef.style.left = (window.innerWidth - 120) / 2 + 'px'; - } + if(outsideRef != null) + { + outsideRef.style.left = (window.innerWidth-120)/2 + 'px'; + } } -function buttonSubmitClick() { - var checks = []; - checks = checks.concat(testState.currentStateMap.interfaces[0].options); - checks = checks.concat(specification.interfaces.options); - var canContinue = true; +function buttonSubmitClick() +{ + var checks = []; + checks = checks.concat(testState.currentStateMap.interfaces[0].options); + checks = checks.concat(specification.interfaces.options); + var canContinue = true; + + for (var i=0; i<checks.length; i++) { + if (checks[i].type == 'check') + { + switch(checks[i].name) { + 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.checkFragmentsFullyPlayed(); + if (checkState == false) {canContinue = false;} + 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; + case 'scalerange': + // Check the scale has been used effectively + var checkState = interfaceContext.checkScaleRange(checks[i].min,checks[i].max); + if (checkState == false) {canContinue = false;} + break; + default: + console.log("WARNING - Check option "+checks[i].check+" is not supported on this interface"); + break; + } - for (var i = 0; i < checks.length; i++) { - if (checks[i].type == 'check') { - switch (checks[i].name) { - 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.checkFragmentsFullyPlayed(); - if (checkState == false) { - canContinue = false; - } - 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; - case 'scalerange': - // Check the scale has been used effectively - var checkState = interfaceContext.checkScaleRange(checks[i].min, checks[i].max); - if (checkState == false) { - canContinue = false; - } - break; - default: - console.log("WARNING - Check option " + checks[i].check + " is not supported on this interface"); - break; - } - - } - if (!canContinue) { - break; - } - } - if (canContinue) { - if (audioEngineContext.status == 1) { - var playback = document.getElementById('playback-button'); - playback.click(); - // This function is called when the submit button is clicked. Will check for any further tests to perform, or any post-test options - } else { - if (audioEngineContext.timer.testStarted == false) { - interfaceContext.lightbox.post("Warning", 'You have not started the test! Please click play on a sample to begin the test!'); - return; - } - } - testState.advanceState(); - } + } + if (!canContinue) {break;} + } + if (canContinue) + { + if (audioEngineContext.status == 1) { + var playback = document.getElementById('playback-button'); + playback.click(); + // This function is called when the submit button is clicked. Will check for any further tests to perform, or any post-test options + } else + { + if (audioEngineContext.timer.testStarted == false) + { + interfaceContext.lightbox.post("Warning",'You have not started the test! Please click play on a sample to begin the test!'); + return; + } + } + testState.advanceState(); + } } -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(); -} +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/ABX.js Tue Oct 18 15:28:24 2016 +0100 +++ b/interfaces/ABX.js Tue Oct 18 15:49:58 2016 +0100 @@ -323,7 +323,7 @@ if (this.parent.specification.parent.playOne || specification.playOne) { $('.comparator-button').text('Wait'); $('.comparator-button').attr("disabled","true"); - $(this.playback).css("disabled","false"); + $(this.playback).removeAttr("disabled"); } else { $('.comparator-button').text('Listen'); }
--- a/js/core.js Tue Oct 18 15:28:24 2016 +0100 +++ b/js/core.js Tue Oct 18 15:49:58 2016 +0100 @@ -1113,7 +1113,8 @@ this.postNode(); } else { // Reached the end of the popupOptions - this.popupContent.innerHTML = ""; + this.popupTitle.textContent = ""; + this.popupResponse.innerHTML = ""; this.hidePopup(); for (var node of this.popupOptions) { this.store.postResult(node); @@ -1387,7 +1388,7 @@ // because web audio will optimise and any route which does not go to the destination gets ignored. this.outputGain = audioContext.createGain(); this.fooGain = audioContext.createGain(); - this.fooGain.gain = 0; + this.fooGain.gain.value = 0; // Use this to detect playback state: 0 - stopped, 1 - playing this.status = 0; @@ -1407,6 +1408,14 @@ this.pageStore = null; + // Chrome 53+ Error solution + // Empty buffer for keep-alive + var nullBuffer = audioContext.createBuffer(1, audioContext.sampleRate, audioContext.sampleRate); + this.nullBufferSource = audioContext.createBufferSource(); + this.nullBufferSource.buffer = nullBuffer; + this.nullBufferSource.loop = true; + this.nullBufferSource.start(0); + // Create store for new audioObjects this.audioObjects = []; @@ -1559,7 +1568,7 @@ } else { var dst = copybuffer.getChannelData(c); for (var n = 0; n < newLength; n++) - dst[n] = src[n + start_sample]; + dst[n] = buffer[n + start_sample]; } } return copybuffer; @@ -1770,6 +1779,7 @@ // Connect buffer to the audio graph this.outputGain.connect(audioEngineContext.outputGain); + audioEngineContext.nullBufferSource.connect(this.outputGain); // the audiobuffer is not designed for multi-start playback // When stopeed, the buffer node is deleted and recreated with the stored buffer. @@ -1793,16 +1803,14 @@ var startTime = this.specification.startTime; var stopTime = this.specification.stopTime; var copybuffer = new callee.constructor(); - if (isFinite(startTime) || isFinite(stopTime)) { - copybuffer.buffer = callee.cropBuffer(startTime, stopTime); + + copybuffer.buffer = callee.cropBuffer(startTime || 0, stopTime || callee.buffer.duration); + if (preSilenceTime != 0 || postSilenceTime != 0) { + copybuffer.buffer = copybuffer.copyBuffer(preSilenceTime, postSilenceTime); } - if (preSilenceTime != 0 || postSilenceTime != 0) { - if (copybuffer.buffer == undefined) { - copybuffer.buffer = callee.copyBuffer(preSilenceTime, postSilenceTime); - } else { - copybuffer.buffer = copybuffer.copyBuffer(preSilenceTime, postSilenceTime); - } - } + + copybuffer.lufs = callee.buffer.lufs; + this.buffer = copybuffer; var targetLUFS = this.specification.parent.loudness || specification.loudness; if (typeof targetLUFS === "number" && isFinite(targetLUFS)) { @@ -1860,14 +1868,21 @@ event.currentTarget.owner.stop(audioContext.currentTime + 1); } }; + this.outputGain.gain.cancelScheduledValues(audioContext.currentTime); if (!audioEngineContext.loopPlayback || !audioEngineContext.synchPlayback) { this.metric.startListening(audioEngineContext.timer.getTestTime()); - this.outputGain.gain.setValueAtTime(this.onplayGain, 0.0); + this.outputGain.gain.setValueAtTime(this.onplayGain, startTime); this.interfaceDOM.startPlayback(); } else { this.outputGain.gain.setValueAtTime(0.0, startTime); } - this.bufferNode.start(startTime, this.specification.startTime || 0, this.specification.stopTime - this.specification.startTime || this.buffer.buffer.duration); + if (audioEngineContext.loopPlayback) { + this.bufferNode.loopStart = this.specification.startTime || 0; + this.bufferNode.loopEnd = this.specification.stopTime - this.specification.startTime || this.buffer.buffer.duration; + this.bufferNode.start(startTime); + } else { + this.bufferNode.start(startTime, this.specification.startTime || 0, this.specification.stopTime - this.specification.startTime || this.buffer.buffer.duration); + } this.bufferNode.playbackStartTime = audioEngineContext.timer.getTestTime(); } }; @@ -1879,7 +1894,7 @@ this.bufferNode.stop(stopTime); this.bufferNode = undefined; } - this.outputGain.gain.value = 0.0; + this.outputGain.gain.setValueAtTime(0.0, stopTime); this.interfaceDOM.stopPlayback(); };
--- a/js/specification.js Tue Oct 18 15:28:24 2016 +0100 +++ b/js/specification.js Tue Oct 18 15:49:58 2016 +0100 @@ -495,83 +495,88 @@ this.decode = function (parent, xml) { this.parent = parent; - var attributeMap = this.schema.getAllElementsByTagName('xs:attribute'); - for (var i = 0; i < attributeMap.length; i++) { - var attributeName = attributeMap[i].getAttribute('name') || attributeMap[i].getAttribute('ref'); - var projectAttr = xml.getAttribute(attributeName); - projectAttr = parent.processAttribute(projectAttr, attributeMap[i], parent.schema); - switch (typeof projectAttr) { - case "number": - case "boolean": - eval('this.' + attributeName + ' = ' + projectAttr); - break; - case "string": - eval('this.' + attributeName + ' = "' + projectAttr + '"'); - break; - } - } - + var attributeMap = this.schema.getAllElementsByTagName('xs:attribute'); + for (var i=0; i<attributeMap.length; i++) + { + var attributeName = attributeMap[i].getAttribute('name') || attributeMap[i].getAttribute('ref'); + var projectAttr = xml.getAttribute(attributeName); + projectAttr = parent.processAttribute(projectAttr,attributeMap[i],parent.schema); + switch(typeof projectAttr) + { + case "number": + case "boolean": + eval('this.'+attributeName+' = '+projectAttr); + break; + case "string": + eval('this.'+attributeName+' = "'+projectAttr+'"'); + break; + } + } + // Get the title var title = xml.getElementsByTagName('title'); - if (title.length != 0) { + if (title.length != 0 && title[0].parentElement == xml) { this.title = title[0].textContent; } - - // Get the Comment Box Prefix - var CBP = xml.getElementsByTagName('commentboxprefix'); - if (CBP.length != 0) { - this.commentBoxPrefix = CBP[0].textContent; - } - - // Now decode the interfaces - var interfaceNode = xml.getElementsByTagName('interface'); - for (var i = 0; i < interfaceNode.length; i++) { - var node = new parent.interfaceNode(this.specification); - node.decode(this, interfaceNode[i], parent.schema.getAllElementsByName('interface')[1]); - this.interfaces.push(node); - } - - // Now process the survey node options - var survey = xml.getElementsByTagName('survey'); - var surveySchema = parent.schema.getAllElementsByName('survey')[0]; - for (var i = 0; i < survey.length; i++) { - var location = survey[i].getAttribute('location'); - if (location == 'pre' || location == 'before') { - if (this.preTest != null) { - this.errors.push("Already a pre/before test survey defined! Ignoring second!!"); - } else { - this.preTest = new parent.surveyNode(this.specification); - this.preTest.decode(parent, survey[i], surveySchema); - } - } else if (location == 'post' || location == 'after') { - if (this.postTest != null) { - this.errors.push("Already a post/after test survey defined! Ignoring second!!"); - } else { - this.postTest = new parent.surveyNode(this.specification); - this.postTest.decode(parent, survey[i], surveySchema); - } - } - } - - // Now process the audioelement tags - var audioElements = xml.getElementsByTagName('audioelement'); - for (var i = 0; i < audioElements.length; i++) { - var node = new this.audioElementNode(this.specification); - node.decode(this, audioElements[i]); - this.audioElements.push(node); - } - - // Now decode the commentquestions - var commentQuestions = xml.getElementsByTagName('commentquestion'); - for (var i = 0; i < commentQuestions.length; i++) { - var node = new this.commentQuestionNode(this.specification); - node.decode(parent, commentQuestions[i]); - this.commentQuestions.push(node); - } - }; - - this.encode = function (root) { - var AHNode = root.createElement("page"); + + // Get the Comment Box Prefix + var CBP = xml.getElementsByTagName('commentboxprefix'); + if (CBP.length != 0 && CBP[0].parentElement == xml) { + this.commentBoxPrefix = CBP[0].textContent; + } + + // Now decode the interfaces + var interfaceNode = xml.getElementsByTagName('interface'); + for (var i=0; i<interfaceNode.length; i++) + { + var node = new parent.interfaceNode(this.specification); + node.decode(this,interfaceNode[i],parent.schema.getAllElementsByName('interface')[1]); + this.interfaces.push(node); + } + + // Now process the survey node options + var survey = xml.getElementsByTagName('survey'); + var surveySchema = parent.schema.getAllElementsByName('survey')[0]; + for (var i=0; i<survey.length; i++){ + var location = survey[i].getAttribute('location'); + if (location == 'pre' || location == 'before') + { + if (this.preTest != null){this.errors.push("Already a pre/before test survey defined! Ignoring second!!");} + else { + this.preTest = new parent.surveyNode(this.specification); + this.preTest.decode(parent,survey[i],surveySchema); + } + } else if (location == 'post' || location == 'after') { + if (this.postTest != null){this.errors.push("Already a post/after test survey defined! Ignoring second!!");} + else { + this.postTest = new parent.surveyNode(this.specification); + this.postTest.decode(parent,survey[i],surveySchema); + } + } + } + + // Now process the audioelement tags + var audioElements = xml.getElementsByTagName('audioelement'); + for (var i=0; i<audioElements.length; i++) + { + var node = new this.audioElementNode(this.specification); + node.decode(this,audioElements[i]); + this.audioElements.push(node); + } + + // Now decode the commentquestions + var commentQuestions = xml.getElementsByTagName('commentquestion'); + for (var i=0; i<commentQuestions.length; i++) + { + var node = new this.commentQuestionNode(this.specification); + node.decode(parent,commentQuestions[i]); + this.commentQuestions.push(node); + } + }; + + this.encode = function(root) + { + var AHNode = root.createElement("page"); // First decode the attributes var attributes = this.schema.getAllElementsByTagName('xs:attribute'); for (var i = 0; i < attributes.length; i++) {
--- a/tests/examples/ABX_example.xml Tue Oct 18 15:28:24 2016 +0100 +++ b/tests/examples/ABX_example.xml Tue Oct 18 15:49:58 2016 +0100 @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <waet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="test-schema.xsd"> - <setup interface="ABX" projectReturn="save.php" randomiseOrder='true' poolSize="2" loudness="-23" sampleRate="44100"> + <setup interface="ABX" projectReturn="save.php" randomiseOrder='true' poolSize="2" loudness="-23"> <survey location="before"> <surveyentry type="question" id="sessionId" mandatory="true"> <statement>Please enter your name.</statement>
--- a/tests/examples/AB_example.xml Tue Oct 18 15:28:24 2016 +0100 +++ b/tests/examples/AB_example.xml Tue Oct 18 15:49:58 2016 +0100 @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <waet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="test-schema.xsd"> - <setup interface="AB" projectReturn="save.php" randomiseOrder='true' poolSize="2" loudness="-23" sampleRate="44100" playOne="true"> + <setup interface="AB" projectReturn="save.php" randomiseOrder='true' poolSize="2" loudness="-23" playOne="true"> <survey location="before"> <surveyentry type="question" id="sessionId" mandatory="true"> <statement>Please enter your name.</statement>
--- a/tests/examples/mushra_example.xml Tue Oct 18 15:28:24 2016 +0100 +++ b/tests/examples/mushra_example.xml Tue Oct 18 15:49:58 2016 +0100 @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <waet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="test-schema.xsd"> - <setup interface="MUSHRA" projectReturn="save.php" randomiseOrder='true' poolSize="2" loudness="-23" sampleRate="44100"> + <setup interface="MUSHRA" projectReturn="save.php" randomiseOrder='true' poolSize="2" loudness="-23"> <exitText>Thank you for looking at WAET. You can modify the successful completion text as well!</exitText> <survey location="before"> <surveyentry type="question" id="sessionId" mandatory="true">
--- a/tests/examples/project.xml Tue Oct 18 15:28:24 2016 +0100 +++ b/tests/examples/project.xml Tue Oct 18 15:49:58 2016 +0100 @@ -94,7 +94,7 @@ </survey> </page> <page id='test-1' hostURL="media/example/" randomiseOrder='true' repeatCount='0' loop='false' label="letter"> - <commentboxprefix>Comment on fragment</commentboxprefix> + <commentboxprefix>Comment on fragment</commentboxprefix> <interface name="preference"> <title>Example Test Question</title> <scales>