From e842b1636b761929ca2445cce810a9ca85a9ca0f Mon Sep 17 00:00:00 2001 From: nullpunktTUD Date: Fri, 29 Jan 2021 00:01:38 +0100 Subject: [PATCH 01/16] Added a version check so get_magic_quotes_gpc() is only used for PHP version less than 8 because it was removed. --- service/write.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/service/write.php b/service/write.php index 3cd901d7..fbd97c76 100644 --- a/service/write.php +++ b/service/write.php @@ -18,11 +18,15 @@ function sanitize($string = '', $is_filename = FALSE) $sessionParam = null; -if(get_magic_quotes_gpc()){ - $sessionParam = stripslashes($_POST['sessionJSON']); + +//get_magic_quotes_gpc() was removed in PHP 8 +if(version_compare(PHP_VERSION, '8.0.0', '<') and get_magic_quotes_gpc()){ + $sessionParam = stripslashes($_POST['sessionJSON']); }else{ - $sessionParam = $_POST['sessionJSON']; + $sessionParam = $_POST['sessionJSON']; } + + $session = json_decode($sessionParam); From 34116f741478cbd0aca0ad651d817df050bbcb06 Mon Sep 17 00:00:00 2001 From: Simon Stone Date: Fri, 27 May 2022 12:31:35 +0200 Subject: [PATCH 02/16] started working on the preference test. Nothing is working so far. --- configs/pref_noloop.yaml | 29 +++ index.html | 2 + lib/webmushra/nls/nls.js | 5 +- lib/webmushra/pages/PreferenceTestPage.js | 230 ++++++++++++++++++ .../pages/PreferenceTestPageManager.js | 51 ++++ startup.js | 6 +- 6 files changed, 321 insertions(+), 2 deletions(-) create mode 100644 configs/pref_noloop.yaml create mode 100644 lib/webmushra/pages/PreferenceTestPage.js create mode 100644 lib/webmushra/pages/PreferenceTestPageManager.js diff --git a/configs/pref_noloop.yaml b/configs/pref_noloop.yaml new file mode 100644 index 00000000..f2957ce6 --- /dev/null +++ b/configs/pref_noloop.yaml @@ -0,0 +1,29 @@ +# test config AB test, waveform, 11 conditions, no looping + + +testname: Preference test with no looping +testId: pref_noloop +bufferSize: 2048 +stopOnErrors: true +showButtonPreviousPage: true +remoteService: service/write.php + + +pages: + + - type: preference_test + id: trialpref2 + name: Mono Trial AB + content: Welche Äußerung finden Sie natürlicher? + numPerTrial: 2 + stimuli: + C1: configs/resources/audio/mono_c1.wav + C2: configs/resources/audio/mono_c2.wav + C3: configs/resources/audio/mono_c3.wav + + + - type: finish + name: Danke + content: Vielen Dank für Ihre Teilnahme! + showResults: true + writeResults: true diff --git a/index.html b/index.html index e6d735e7..d089ce72 100644 --- a/index.html +++ b/index.html @@ -111,6 +111,8 @@ + + diff --git a/lib/webmushra/nls/nls.js b/lib/webmushra/nls/nls.js index dd4436bf..6efe22e3 100644 --- a/lib/webmushra/nls/nls.js +++ b/lib/webmushra/nls/nls.js @@ -76,7 +76,10 @@ nls['fr']['slightly'] = "Légèrement gênante"; nls['fr']['annoying'] = "Dégradation gênante"; nls['fr']['very'] = "Dégradation très gênante"; - +// captions Preference Test +nls['en']['pref'] = "Which item do you prefer?"; +nls['de']['pref'] = "Welche Version bevorzugen Sie?"; +nls['fr']['pref'] = "Quel item préférez-vous?"; // captions Paired Comparison AB/ABN nls['en']['quest'] = "Which item is the reference?"; diff --git a/lib/webmushra/pages/PreferenceTestPage.js b/lib/webmushra/pages/PreferenceTestPage.js new file mode 100644 index 00000000..b4e70af7 --- /dev/null +++ b/lib/webmushra/pages/PreferenceTestPage.js @@ -0,0 +1,230 @@ +/************************************************************************* + (C) Copyright AudioLabs 2017 + +This source code is protected by copyright law and international treaties. This source code is made available to You subject to the terms and conditions of the Software License for the webMUSHRA.js Software. Said terms and conditions have been made available to You prior to Your download of this source code. By downloading this source code You agree to be bound by the above mentionend terms and conditions, which can also be found here: https://www.audiolabs-erlangen.de/resources/webMUSHRA. Any unauthorised use of this source code may result in severe civil and criminal penalties, and will be prosecuted to the maximum extent possible under law. + +**************************************************************************/ + +function PreferenceTestPage(_pageManager, _pageTemplateRenderer, _audioContext, _bufferSize, _audioFileLoader, _stimuli, _session, _pageConfig, _errorHandler, _language) { + this.pageManager = _pageManager; + this.pageTemplateRenderer = _pageTemplateRenderer; + this.audioContext = _audioContext; + this.bufferSize = _bufferSize; + this.audioFileLoader = _audioFileLoader; + this.session = _session; + this.pageConfig = _pageConfig; + this.errorHandler = _errorHandler; + this.language = _language; + this.div = null; + this.fpc = null; + + this.currentItem = null; + + this.stimuli = _stimuli + + for (var i = 0; i < this.stimuli.length; ++i) { + this.audioFileLoader.addFile(this.stimuli[i].getFilepath(), (function (_buffer, _stimulus) { _stimulus.setAudioBuffer(_buffer); }), this.stimuli[i]); + } + this.filePlayer = null; + this.choice = null; +} + + + +PreferenceTestPage.prototype.getName = function () { + return this.pageConfig.name; +}; + +PreferenceTestPage.prototype.init = function () { + this.choice = null + + this.filePlayer = new FilePlayer(this.audioContext, this.bufferSize, this.stimuli, this.errorHandler, this.language, this.pageManager.getLocalizer()); +}; + +PreferenceTestPage.prototype.render = function (_parent) { + var div = $("
"); + _parent.append(div); + + var content; + if(this.pageConfig.content === null){ + content =""; + } else { + content = this.pageConfig.content; + } + + var p = $("

" + content + "

"); + div.append(p); + + var table = $("
"); + div.append(table); + + this.filePlayer.render(_parent); + + var trAB = $(""); + table.append(trAB); + var tdAB = $(""); + trAB.append(tdAB); + + var tableAB = $("
"); + tdAB.append(tableAB); + + // names + var trNames = $("AB"); + tableAB.append(trNames); + + var trPlays = $(""); + tableAB.append(trPlays); + + var buttonPlayA = $(""); + trPlays.append(buttonPlayA); + var buttonPlayB = $(""); + trPlays.append(buttonPlayB); + + + var trResponse = $(""); + tableAB.append(trResponse); + var tdResponse = $(""); + trResponse.append(tdResponse); + + var radioChoice = $("
\ + \ + \ + \ + \ +
"); + + radioChoice.find("input[type='radio']").bind("change", (function(){ + this.pageTemplateRenderer.unlockNextButton(); + } + ).bind(this)); + + tdResponse.append(radioChoice); + + this.fpc = new FilePlayerController(this.filePlayer); + this.fpc.bind(); + +}; + +PreferenceTestPage.prototype.cleanButtons = function() { + if($('#buttonStop').attr("active") == "true") { + $.mobile.activePage.find('#buttonStop') //remove color from Stop + .removeClass('ui-btn-b') + .addClass('ui-btn-a').attr('data-theme', 'a'); + $('#buttonStop').attr("active", "false"); + } + + + if($('#buttonConditions0').attr("active") == "true") { + $.mobile.activePage.find('#buttonConditions0') //remove color from Reference + .removeClass('ui-btn-b') + .addClass('ui-btn-a').attr('data-theme', 'a'); + $('#buttonConditions0').attr("active", "false"); + } + + if($('#buttonConditions1').attr("active") == "true") { + $.mobile.activePage.find('#buttonConditions1') //remove color from Reference + .removeClass('ui-btn-b') + .addClass('ui-btn-a').attr('data-theme', 'a'); + $('#buttonConditions1').attr("active", "false"); + } +}; + + +PreferenceTestPage.prototype.btnCallbackA = function() { + this.currentItem = "A"; + var label = $("#buttonConditions0").text(); + if (label == this.pageManager.getLocalizer().getFragment(this.language, 'pauseButton')) { + this.mushraAudioControl.pause(); + $("#buttonConditions0").text(this.pageManager.getLocalizer().getFragment(this.language, 'playButton')); + } else if (label == this.pageManager.getLocalizer().getFragment(this.language, 'playButton')) { + $(".audioControlElement").text(this.pageManager.getLocalizer().getFragment(this.language, 'playButton')); + this.mushraAudioControl.playCondition(0); + $("#buttonConditions0").text(this.pageManager.getLocalizer().getFragment(this.language, 'pauseButton')); + + this.cleanButtons(); + $.mobile.activePage.find('#buttonConditions0') //add color to reference + .removeClass('ui-btn-a') + .addClass('ui-btn-b').attr('data-theme', 'b'); + $('#buttonConditions0').focus(); + $('#buttonConditions0').attr("active", "true"); + } +}; + +PreferenceTestPage.prototype.btnCallbackB = function() { + this.currentItem = "B"; + var label = $("#buttonConditions1").text(); + if (label == this.pageManager.getLocalizer().getFragment(this.language, 'pauseButton')) { + this.mushraAudioControl.pause(); + $("#buttonConditions1").text(this.pageManager.getLocalizer().getFragment(this.language, 'playButton')); + } else if (label == this.pageManager.getLocalizer().getFragment(this.language, 'playButton')) { + $(".audioControlElement").text(this.pageManager.getLocalizer().getFragment(this.language, 'playButton')); + this.mushraAudioControl.playCondition(1); + $("#buttonConditions1").text(this.pageManager.getLocalizer().getFragment(this.language, 'pauseButton')); + + this.cleanButtons(); + $.mobile.activePage.find('#buttonConditions1') //add color to reference + .removeClass('ui-btn-a') + .addClass('ui-btn-b').attr('data-theme', 'b'); + $('#buttonConditions1').focus(); + $('#buttonConditions1').attr("active", "true"); + + } +}; + + + +PreferenceTestPage.prototype.load = function () { + this.startTimeOnPage = new Date(); + + if (this.choice === null) { + this.pageTemplateRenderer.lockNextButton(); + } + // audio + this.filePlayer.init(); + + //choice + if(this.choice === 'a') { + $('#radio-choice-a').prop('checked', true).checkboxradio('refresh'); + $('#radio-choice-b').prop('checked', false).checkboxradio('refresh'); + } else if (this.choice === 'b') { + $('#radio-choice-b').prop('checked', true).checkboxradio('refresh'); + $('#radio-choice-a').prop('checked', false).checkboxradio('refresh'); + } +}; + +PreferenceTestPage.prototype.save = function () { + this.macic.unbind(); + this.time += (new Date() - this.startTimeOnPage); + this.mushraAudioControl.removeEventListener(this.waveformVisualizer.numberEventListener); + // audio + this.mushraAudioControl.freeAudio(); + // choice + var radio = $('#radio-choice :radio:checked'); + this.choice = (radio.length > 0) ? radio[0].value : null; + //loop + this.loop.start = parseInt(this.waveformVisualizer.mushraAudioControl.audioLoopStart); + this.loop.end = parseInt(this.waveformVisualizer.mushraAudioControl.audioLoopEnd); +}; + + +PreferenceTestPage.prototype.store = function () { + var trial = this.session.getTrial(this.pageConfig.type, this.pageConfig.id); + if (trial === null) { + trial = new Trial(); + trial.type = this.pageConfig.type; + trial.id = this.pageConfig.id; + this.session.trials[this.session.trials.length] = trial; + } + var choice = new PairedComparisonChoice(); + choice.nonReference = this.condition.getId(); + choice.answer = this.choice + + if (this.choice === null) { + choice.answer = "unknown"; + } else if (this.choice === "n") { + choice.answer = "undecided"; + } + choice.time = this.time; + trial.responses[trial.responses.length] = choice; + +}; diff --git a/lib/webmushra/pages/PreferenceTestPageManager.js b/lib/webmushra/pages/PreferenceTestPageManager.js new file mode 100644 index 00000000..46789e04 --- /dev/null +++ b/lib/webmushra/pages/PreferenceTestPageManager.js @@ -0,0 +1,51 @@ +/************************************************************************* + (C) Copyright AudioLabs 2017 + +This source code is protected by copyright law and international treaties. This source code is made available to You subject to the terms and conditions of the Software License for the webMUSHRA.js Software. Said terms and conditions have been made available to You prior to Your download of this source code. By downloading this source code You agree to be bound by the above mentionend terms and conditions, which can also be found here: https://www.audiolabs-erlangen.de/resources/webMUSHRA. Any unauthorised use of this source code may result in severe civil and criminal penalties, and will be prosecuted to the maximum extent possible under law. + +**************************************************************************/ + +function PreferenceTestPageManager() { + +} + +PreferenceTestPageManager.prototype.createPages = function (_pageManager, _pageTemplateRenderer, _pageConfig, _audioContext, _bufferSize, _audioFileLoader, _session, _errorHandler, _language) { + + /* Create a set of trials */ + this.stimuli = []; + for (var key in _pageConfig.stimuli) { + this.stimuli[this.stimuli.length] = new Stimulus(key, _pageConfig.stimuli[key]); + } + + this.trials = []; + + + for (subset of subsets(this.stimuli, _pageConfig.numPerTrial)){ + this.trials.push(subset); + } + + shuffle(this.trials); + + + for (var i = 0; i < this.trials.length; ++i) { + var page = new PreferenceTestPage(_pageManager, _pageTemplateRenderer, _audioContext, _bufferSize, _audioFileLoader, this.trials[i], + _session, _pageConfig, _errorHandler, _language); + _pageManager.addPage(page); + } +}; + +function* subsets(array, length, start = 0) { + if (start >= array.length || length < 1) { + yield new Set(); + } else { + while (start <= array.length - length) { + let first = array[start]; + for (subset of subsets(array, length - 1, start + 1)) { + subset.add(first); + yield subset; + } + ++start; + } + } +} + \ No newline at end of file diff --git a/startup.js b/startup.js index 4e2d6fcf..7a509a76 100644 --- a/startup.js +++ b/startup.js @@ -89,7 +89,11 @@ function addPagesToPageManager(_pageManager, _pages) { var pcPageManager = new PairedComparisonPageManager(); pcPageManager.createPages(_pageManager, pageTemplateRenderer, pageConfig, audioContext, config.bufferSize, audioFileLoader, session, errorHandler, config.language); pcPageManager = null; - } else if (pageConfig.type == "bs1116") { + } else if (pageConfig.type == "preference_test") { + var prefPageManager = new PreferenceTestPageManager(); + prefPageManager.createPages(_pageManager, pageTemplateRenderer, pageConfig, audioContext, config.bufferSize, audioFileLoader, session, errorHandler, config.language); + prefPageManager = null; + }else if (pageConfig.type == "bs1116") { var bs1116PageManager = new BS1116PageManager(); bs1116PageManager.createPages(_pageManager, pageTemplateRenderer, pageConfig, audioContext, config.bufferSize, audioFileLoader, session, errorHandler, config.language); bs1116PageManager = null; From 54ad3ff569790ae10f99edd85fa2b7df41a1036a Mon Sep 17 00:00:00 2001 From: Simon Stone Date: Tue, 31 May 2022 13:09:47 +0200 Subject: [PATCH 03/16] adds a working prototype of the preference test. Also adds ability to show a confirmation code on the final page and to generate a random subject ID for each session --- configs/default.yaml | 192 ++++++++++++------ configs/default.yaml_ | 77 +++++++ configs/pref.yaml | 55 +++++ configs/pref_noloop.yaml | 29 --- index.html | 1 + .../datamodel/PreferenceTestChoice.js | 14 ++ lib/webmushra/nls/nls.js | 7 + lib/webmushra/pages/FinishPage.js | 53 +++++ lib/webmushra/pages/PreferenceTestPage.js | 51 ++--- .../pages/PreferenceTestPageManager.js | 31 +-- service/write.php | 45 ++++ 11 files changed, 421 insertions(+), 134 deletions(-) create mode 100644 configs/default.yaml_ create mode 100644 configs/pref.yaml delete mode 100644 configs/pref_noloop.yaml create mode 100644 lib/webmushra/datamodel/PreferenceTestChoice.js diff --git a/configs/default.yaml b/configs/default.yaml index 8b503287..ca6a54f4 100644 --- a/configs/default.yaml +++ b/configs/default.yaml @@ -1,77 +1,135 @@ -testname: webMUSHRA Example -testId: default_example +# Likert multi stimulus page 1 stimuli, 4 responses + + +testname: Hörexperiment +testId: lms_4scale bufferSize: 2048 stopOnErrors: true showButtonPreviousPage: true +language: de remoteService: service/write.php pages: - - type: generic - id: first_page - name: Welcome - content: Welcome to webMUSHRA! - - type: mushra - id: trial1 - name: MUSHRA - content: This training shows how to use our user interface. Please perform the underlined instructions to proceed with the training session. Reminder: In a MUSHRA listening test you are asked to rate the Basic Audio Quality (BAQ) of each condition.
Basic Audio Quality is a single and global attribute that is used to judge any and all detected differences between the reference and the condition. - showWaveform: true - enableLooping: true - reference: configs/resources/audio/mono_ref.wav - createAnchor35: true - createAnchor70: true - stimuli: - C1: configs/resources/audio/mono_c1.wav - C2: configs/resources/audio/mono_c2.wav - C3: configs/resources/audio/mono_c3.wav + - type: volume + id: vol + name: Lautstärke + content: Bitte regeln Sie die Lautstärke auf ein für Sie angenehmes Niveau. + stimulus: configs/resources/audio/bsp-Beispielsatz.wav + defaultVolume: 0.5 + - - - random - - type: mushra - id: trial_random_1 - name: MUSHRA - Random 2 - content: Due to randomization, this page will be either the second MUSHRA page or the third MUSHRA page. - enableLooping: true - reference: configs/resources/audio/mono_ref.wav - createAnchor35: false - createAnchor70: false - stimuli: - C1: configs/resources/audio/mono_c1.wav - C2: configs/resources/audio/mono_c2.wav - C3: configs/resources/audio/mono_c3.wav - - type: mushra - id: trial_random_2 - name: MUSHRA - Random 1 - content: Due to randomization, this page will be either the second MUSHRA page or the third MUSHRA page. - enableLooping: true - reference: configs/resources/audio/mono_ref.wav - createAnchor35: false - createAnchor70: false - stimuli: - C1: configs/resources/audio/mono_c1.wav - C2: configs/resources/audio/mono_c2.wav - C3: configs/resources/audio/mono_c3.wav + - random + - + - type: likert_multi_stimulus + id: aI01 + name: Sie leiht sich eine + mustRate: true + mustPlayback: ended + content: Wie natürlich klingen diese Äußerungen für Sie? + stimuli: + C1: configs/resources/audio/aI-Sie_leiht_sich_eine.wav + C2: configs/resources/audio/aI-Sie_leiht_sich_eine-a-aI_end.wav + C3: configs/resources/audio/aI-Sie_leiht_sich_eine-a-e.wav + C4: configs/resources/audio/aI-Sie_leiht_sich_eine-a-I.wav + C5: configs/resources/audio/aI-Sie_leiht_sich_eine-aI_begin-aI_end.wav + C6: configs/resources/audio/aI-Sie_leiht_sich_eine-aI_begin-e.wav + C7: configs/resources/audio/aI-Sie_leiht_sich_eine-aI_begin-I.wav + response: + - value: 0 + label: Völlig unnatürlich + img: configs/resources/images/star_off.png + imgSelected: configs/resources/images/star_on.png + imgHigherResponseSelected: configs/resources/images/star_on.png + - value: 1 + label: Etwas unnatürlich + img: configs/resources/images/star_off.png + imgSelected: configs/resources/images/star_on.png + imgHigherResponseSelected: configs/resources/images/star_on.png + - value: 2 + label: Eher natürlich + img: configs/resources/images/star_off.png + imgSelected: configs/resources/images/star_on.png + imgHigherResponseSelected: configs/resources/images/star_on.png + - value: 3 + label: Sehr natürlich + img: configs/resources/images/star_off.png + imgSelected: configs/resources/images/star_on.png + imgHigherResponseSelected: configs/resources/images/star_on.png + - + - type: likert_multi_stimulus + id: aI02 + name: Weißer Hai + mustRate: true + mustPlayback: ended + content: Wie natürlich klingen diese Äußerungen für Sie? + stimuli: + C1: configs/resources/audio/aI-weisser_Hai.wav + C2: configs/resources/audio/aI-weisser_Hai-a-aI_end.wav + C3: configs/resources/audio/aI-weisser_Hai-a-e.wav + C4: configs/resources/audio/aI-weisser_Hai-a-I.wav + C5: configs/resources/audio/aI-weisser_Hai-aI_begin-aI_end.wav + C6: configs/resources/audio/aI-weisser_Hai-aI_begin-e.wav + C7: configs/resources/audio/aI-weisser_Hai-aI_begin-I.wav + response: + - value: 0 + label: Völlig unnatürlich + img: configs/resources/images/star_off.png + imgSelected: configs/resources/images/star_on.png + imgHigherResponseSelected: configs/resources/images/star_on.png + - value: 1 + label: Etwas unnatürlich + img: configs/resources/images/star_off.png + imgSelected: configs/resources/images/star_on.png + imgHigherResponseSelected: configs/resources/images/star_on.png + - value: 2 + label: Eher natürlich + img: configs/resources/images/star_off.png + imgSelected: configs/resources/images/star_on.png + imgHigherResponseSelected: configs/resources/images/star_on.png + - value: 3 + label: Sehr natürlich + img: configs/resources/images/star_off.png + imgSelected: configs/resources/images/star_on.png + imgHigherResponseSelected: configs/resources/images/star_on.png + - + - type: likert_multi_stimulus + id: OY01 + name: neues Europa + mustRate: true + mustPlayback: ended + content: Wie natürlich klingen diese Äußerungen für Sie? + stimuli: + C1: configs/resources/audio/OY-neues_Europa.wav + C2: configs/resources/audio/OY-neues_Europa-O-e.wav + C3: configs/resources/audio/OY-neues_Europa-O-I.wav + C4: configs/resources/audio/OY-neues_Europa-O-OY_end.wav + C5: configs/resources/audio/OY-neues_Europa-OY_begin-e.wav + C6: configs/resources/audio/OY-neues_Europa-OY_begin-I.wav + C7: configs/resources/audio/OY-neues_Europa-OY_begin-OY_end.wav + response: + - value: 0 + label: Völlig unnatürlich + img: configs/resources/images/star_off.png + imgSelected: configs/resources/images/star_on.png + imgHigherResponseSelected: configs/resources/images/star_on.png + - value: 1 + label: Etwas unnatürlich + img: configs/resources/images/star_off.png + imgSelected: configs/resources/images/star_on.png + imgHigherResponseSelected: configs/resources/images/star_on.png + - value: 2 + label: Eher natürlich + img: configs/resources/images/star_off.png + imgSelected: configs/resources/images/star_on.png + imgHigherResponseSelected: configs/resources/images/star_on.png + - value: 3 + label: Sehr natürlich + img: configs/resources/images/star_off.png + imgSelected: configs/resources/images/star_on.png + imgHigherResponseSelected: configs/resources/images/star_on.png + - type: finish - name: Thank you - content: Thank you for attending! - showResults: true + name: Danke + content: Vielen Dank für Ihre Teilnahme. writeResults: true - questionnaire: - - type: text - label: eMail - name: email - - type: number - label: Age - name: age - min: 0 - max: 100 - default: 30 - - type: likert - name: gender - label: Gender - response: - - value: female - label: Female - - value: male - label: Male - - value: other - label: Other diff --git a/configs/default.yaml_ b/configs/default.yaml_ new file mode 100644 index 00000000..8b503287 --- /dev/null +++ b/configs/default.yaml_ @@ -0,0 +1,77 @@ +testname: webMUSHRA Example +testId: default_example +bufferSize: 2048 +stopOnErrors: true +showButtonPreviousPage: true +remoteService: service/write.php + + +pages: + - type: generic + id: first_page + name: Welcome + content: Welcome to webMUSHRA! + - type: mushra + id: trial1 + name: MUSHRA + content: This training shows how to use our user interface. Please perform the underlined instructions to proceed with the training session. Reminder: In a MUSHRA listening test you are asked to rate the Basic Audio Quality (BAQ) of each condition.
Basic Audio Quality is a single and global attribute that is used to judge any and all detected differences between the reference and the condition. + showWaveform: true + enableLooping: true + reference: configs/resources/audio/mono_ref.wav + createAnchor35: true + createAnchor70: true + stimuli: + C1: configs/resources/audio/mono_c1.wav + C2: configs/resources/audio/mono_c2.wav + C3: configs/resources/audio/mono_c3.wav + - + - random + - type: mushra + id: trial_random_1 + name: MUSHRA - Random 2 + content: Due to randomization, this page will be either the second MUSHRA page or the third MUSHRA page. + enableLooping: true + reference: configs/resources/audio/mono_ref.wav + createAnchor35: false + createAnchor70: false + stimuli: + C1: configs/resources/audio/mono_c1.wav + C2: configs/resources/audio/mono_c2.wav + C3: configs/resources/audio/mono_c3.wav + - type: mushra + id: trial_random_2 + name: MUSHRA - Random 1 + content: Due to randomization, this page will be either the second MUSHRA page or the third MUSHRA page. + enableLooping: true + reference: configs/resources/audio/mono_ref.wav + createAnchor35: false + createAnchor70: false + stimuli: + C1: configs/resources/audio/mono_c1.wav + C2: configs/resources/audio/mono_c2.wav + C3: configs/resources/audio/mono_c3.wav + - type: finish + name: Thank you + content: Thank you for attending! + showResults: true + writeResults: true + questionnaire: + - type: text + label: eMail + name: email + - type: number + label: Age + name: age + min: 0 + max: 100 + default: 30 + - type: likert + name: gender + label: Gender + response: + - value: female + label: Female + - value: male + label: Male + - value: other + label: Other diff --git a/configs/pref.yaml b/configs/pref.yaml new file mode 100644 index 00000000..fe57ce86 --- /dev/null +++ b/configs/pref.yaml @@ -0,0 +1,55 @@ +# test config preference test + + +testname: Preference test +testId: pref +bufferSize: 2048 +stopOnErrors: true +showButtonPreviousPage: true +remoteService: service/write.php +language: de + +pages: + + - type: preference_test + id: trialpref2 + name: Hörexperiment + content: Welche Äußerung finden Sie natürlicher? + considerOrder: false + stimuli: + aI-ori: configs/resources/audio/aI-Sie_leiht_sich_eine.wav + aI-a-e: configs/resources/audio/aI-Sie_leiht_sich_eine-a-e.wav + aI-a-I: configs/resources/audio/aI-Sie_leiht_sich_eine-a-I.wav + aI-aI_begin-aI_end: configs/resources/audio/aI-Sie_leiht_sich_eine-aI_begin-aI_end.wav + aI-aI_begin-e: configs/resources/audio/aI-Sie_leiht_sich_eine-aI_begin-e.wav + aI-aI_begin-I: configs/resources/audio/aI-Sie_leiht_sich_eine-aI_begin-I.wav + aI-a-aI_end: configs/resources/audio/aI-Sie_leiht_sich_eine-a-aI_end.wav + + - type: finish + name: Vielen Dank für Ihre Teilnahme! + content:

Lassen Sie uns gerne Feedback zum Experiment hier.

Nachdem Sie auf "Ergebnisse senden" geklickt haben, erhalten Sie den Code zur Einlösung auf Clickworkers.de

. + questionnaire: + - type: long_text + label: Kommentar + name: feedback + optional: true + - type: number + label: Alter + name: age + min: 0 + max: 100 + default: 30 + - type: likert + name: Geschlecht + label: Gender + response: + - value: weiblich + label: weiblich + - value: männlich + label: männlich + - value: divers + label: divers + showResults: true + writeResults: true + generateSubjectId: true + confirmationCode: prefTest diff --git a/configs/pref_noloop.yaml b/configs/pref_noloop.yaml deleted file mode 100644 index f2957ce6..00000000 --- a/configs/pref_noloop.yaml +++ /dev/null @@ -1,29 +0,0 @@ -# test config AB test, waveform, 11 conditions, no looping - - -testname: Preference test with no looping -testId: pref_noloop -bufferSize: 2048 -stopOnErrors: true -showButtonPreviousPage: true -remoteService: service/write.php - - -pages: - - - type: preference_test - id: trialpref2 - name: Mono Trial AB - content: Welche Äußerung finden Sie natürlicher? - numPerTrial: 2 - stimuli: - C1: configs/resources/audio/mono_c1.wav - C2: configs/resources/audio/mono_c2.wav - C3: configs/resources/audio/mono_c3.wav - - - - type: finish - name: Danke - content: Vielen Dank für Ihre Teilnahme! - showResults: true - writeResults: true diff --git a/index.html b/index.html index d089ce72..6a1cde34 100644 --- a/index.html +++ b/index.html @@ -80,6 +80,7 @@ + diff --git a/lib/webmushra/datamodel/PreferenceTestChoice.js b/lib/webmushra/datamodel/PreferenceTestChoice.js new file mode 100644 index 00000000..8b82b928 --- /dev/null +++ b/lib/webmushra/datamodel/PreferenceTestChoice.js @@ -0,0 +1,14 @@ +/************************************************************************* + (C) Copyright AudioLabs 2017 + +This source code is protected by copyright law and international treaties. This source code is made available to You subject to the terms and conditions of the Software License for the webMUSHRA.js Software. Said terms and conditions have been made available to You prior to Your download of this source code. By downloading this source code You agree to be bound by the above mentionend terms and conditions, which can also be found here: https://www.audiolabs-erlangen.de/resources/webMUSHRA. Any unauthorised use of this source code may result in severe civil and criminal penalties, and will be prosecuted to the maximum extent possible under law. + +**************************************************************************/ + +function PreferenceTestChoice() { + this.optionA = null; + this.optionB = null; + this.answer = null; + this.comment = null; + this.time = null; +} diff --git a/lib/webmushra/nls/nls.js b/lib/webmushra/nls/nls.js index 6efe22e3..17e76dcb 100644 --- a/lib/webmushra/nls/nls.js +++ b/lib/webmushra/nls/nls.js @@ -81,6 +81,7 @@ nls['en']['pref'] = "Which item do you prefer?"; nls['de']['pref'] = "Welche Version bevorzugen Sie?"; nls['fr']['pref'] = "Quel item préférez-vous?"; + // captions Paired Comparison AB/ABN nls['en']['quest'] = "Which item is the reference?"; nls['de']['quest'] = "Welches Stück ist die Referenz?"; @@ -93,3 +94,9 @@ nls['fr']['results'] = "Vos résultats:"; nls['en']['attending'] = "Thank you for your participation!"; nls['de']['attending'] = "Vielen Dank für die Teilnahme!"; nls['fr']['attending'] = "Merci pour votre participation!"; +nls['en']['response'] = "Response"; +nls['de']['response'] = "Antwort"; +nls['fr']['response'] = "Réponse"; +nls['en']['code'] = "Your confirmation code:"; +nls['de']['code'] = "Ihr Bestätigungscode:"; +nls['fr']['code'] = "Votre code de confirmation:"; \ No newline at end of file diff --git a/lib/webmushra/pages/FinishPage.js b/lib/webmushra/pages/FinishPage.js index fd1e3ce1..d3ead586 100644 --- a/lib/webmushra/pages/FinishPage.js +++ b/lib/webmushra/pages/FinishPage.js @@ -32,8 +32,21 @@ FinishPage.prototype.getName = function () { return this.pageConfig.name; }; +function getId(){ + /* Returns an ID based on random number and the current timestampe */ + return Math.floor(Math.random() * Date.now()); +} + + FinishPage.prototype.storeParticipantData = function() { var i; + if (this.pageConfig.generateSubjectId){ + this.session.participant.name[this.session.participant.name.length] = "subjectId"; + this.session.participant.response[this.session.participant.response.length] = getId(); + } else { + this.session.participant.name[this.session.participant.name.length] = "subjectId"; + this.session.participant.response[this.session.participant.response.length] = null; + } for (i = 0; i < this.pageConfig.questionnaire.length; ++i) { var element = this.pageConfig.questionnaire[i]; @@ -91,6 +104,14 @@ FinishPage.prototype.render = function (_parent) { $("#popHeader").text(this.pageManager.getLocalizer().getFragment(this.language, 'attending')); + if (this.pageConfig.confirmationCode != ""){ + divCode = $("

" + this.pageManager.getLocalizer().getFragment(this.language, 'code') + "

"); + code = $("

" + this.pageConfig.confirmationCode + "

"); + code.css("font-size", "28px"); + divCode.append(code); + $("#popupResultsContent").append(divCode); + } + var table = $("
"); var trHeader = document.createElement("tr"); var trT; @@ -166,6 +187,38 @@ FinishPage.prototype.render = function (_parent) { trEmpty = $(""); $(table).append(trEmpty); + } else if (trial.type === "preference_test") { + + trPref = document.createElement("tr"); + thT = $(""); + $(thT).append(trial.id + " (Preference Test)" ); + $(trPref).append(thT); + $(table).append(trPref); + trLabel = document.createElement("tr"); + thT = $("AB" + this.pageManager.getLocalizer().getFragment(this.language, 'response') + ""); + $(trLabel).append(thT); + $(table).append(trLabel); + + var j; + for(j = 0; j < trial.responses.length; ++j){ + trPT = document.createElement("tr"); + tdPTOptionA = document.createElement("td"); + tdPTOptionB = document.createElement("td"); + tdPTAnswer = document.createElement("td"); + var response = trial.responses[j]; + + + $(tdPTOptionA).append(response.optionA); + $(tdPTOptionB).append(response.optionB); + $(tdPTAnswer).append(response.answer); + $(trPT).append(tdPTOptionA); + $(trPT).append(tdPTOptionB); + $(trPT).append(tdPTAnswer); + $(table).append(trPT); + } + trEmpty = $(""); + $(table).append(trEmpty); + } else if(trial.type ==="bs1116") { trPaired = document.createElement("tr"); thT = $(""); diff --git a/lib/webmushra/pages/PreferenceTestPage.js b/lib/webmushra/pages/PreferenceTestPage.js index b4e70af7..46986904 100644 --- a/lib/webmushra/pages/PreferenceTestPage.js +++ b/lib/webmushra/pages/PreferenceTestPage.js @@ -42,7 +42,7 @@ PreferenceTestPage.prototype.init = function () { }; PreferenceTestPage.prototype.render = function (_parent) { - var div = $("
"); + var div = $("
"); _parent.append(div); var content; @@ -55,32 +55,40 @@ PreferenceTestPage.prototype.render = function (_parent) { var p = $("

" + content + "

"); div.append(p); + var outerTable = $("
"); + div.append(outerTable); + var trOuter = $(""); + outerTable.append(trOuter); + var tdLabels = $(""); + trOuter.append(tdLabels); + var innerTable = $("
"); + tdLabels.append(innerTable); + var trA = $(""); + innerTable.append(trA); + trA.append($("A:")); + var trB = $(""); + innerTable.append(trB); + trB.append($("B:")); + trA.height(tdLabels.height()); + trB.height(tdLabels.height()); + var tdPlayer = $(""); + trOuter.append(tdPlayer); + this.filePlayer.render(tdPlayer); + var table = $("
"); div.append(table); - - this.filePlayer.render(_parent); var trAB = $(""); table.append(trAB); var tdAB = $(""); trAB.append(tdAB); - + var tableAB = $("
"); tdAB.append(tableAB); - // names - var trNames = $("AB"); - tableAB.append(trNames); - var trPlays = $(""); tableAB.append(trPlays); - var buttonPlayA = $(""); - trPlays.append(buttonPlayA); - var buttonPlayB = $(""); - trPlays.append(buttonPlayB); - - var trResponse = $(""); tableAB.append(trResponse); var tdResponse = $(""); @@ -193,17 +201,13 @@ PreferenceTestPage.prototype.load = function () { }; PreferenceTestPage.prototype.save = function () { - this.macic.unbind(); + this.fpc.unbind(); this.time += (new Date() - this.startTimeOnPage); - this.mushraAudioControl.removeEventListener(this.waveformVisualizer.numberEventListener); // audio - this.mushraAudioControl.freeAudio(); + this.filePlayer.free(); // choice var radio = $('#radio-choice :radio:checked'); this.choice = (radio.length > 0) ? radio[0].value : null; - //loop - this.loop.start = parseInt(this.waveformVisualizer.mushraAudioControl.audioLoopStart); - this.loop.end = parseInt(this.waveformVisualizer.mushraAudioControl.audioLoopEnd); }; @@ -215,9 +219,10 @@ PreferenceTestPage.prototype.store = function () { trial.id = this.pageConfig.id; this.session.trials[this.session.trials.length] = trial; } - var choice = new PairedComparisonChoice(); - choice.nonReference = this.condition.getId(); - choice.answer = this.choice + var choice = new PreferenceTestChoice(); + choice.optionA = this.stimuli[0].getId(); + choice.optionB = this.stimuli[1].getId(); + choice.answer = (this.choice == 'a') ? choice.optionA : choice.optionB; if (this.choice === null) { choice.answer = "unknown"; diff --git a/lib/webmushra/pages/PreferenceTestPageManager.js b/lib/webmushra/pages/PreferenceTestPageManager.js index 46789e04..3842dad1 100644 --- a/lib/webmushra/pages/PreferenceTestPageManager.js +++ b/lib/webmushra/pages/PreferenceTestPageManager.js @@ -16,12 +16,9 @@ PreferenceTestPageManager.prototype.createPages = function (_pageManager, _pageT for (var key in _pageConfig.stimuli) { this.stimuli[this.stimuli.length] = new Stimulus(key, _pageConfig.stimuli[key]); } - this.trials = []; - - - for (subset of subsets(this.stimuli, _pageConfig.numPerTrial)){ - this.trials.push(subset); + for (pair of pairs(this.stimuli, _pageConfig.considerOrder)){ + this.trials.push(pair); } shuffle(this.trials); @@ -34,18 +31,22 @@ PreferenceTestPageManager.prototype.createPages = function (_pageManager, _pageT } }; -function* subsets(array, length, start = 0) { - if (start >= array.length || length < 1) { +function* pairs(array, fullSet = true) { +/* + * This generator returns the items from arrays in pairs. + * If fullSet is true, all pairs are returned (i.e. {A, B} and {B, A}). + * If it is false, only the first half of pairs is returned (i.e. only {A, B} and not {B, A}) + */ + if (array.length < 2) { yield new Set(); } else { - while (start <= array.length - length) { - let first = array[start]; - for (subset of subsets(array, length - 1, start + 1)) { - subset.add(first); - yield subset; - } - ++start; - } + for (let i = 0; i < array.length; ++i){ + for (let j = fullSet ? 0 : i; j < array.length; ++j){ + if (i == j){continue;} + var pair = [array[i], array[j]]; + yield pair; + } + } } } \ No newline at end of file diff --git a/service/write.php b/service/write.php index fbd97c76..46485955 100644 --- a/service/write.php +++ b/service/write.php @@ -137,6 +137,51 @@ function sanitize($string = '', $is_filename = FALSE) fclose($fp); } +// preference test + +$write_pt = false; +$ptCsvData = array(); + +$input = array("session_test_id"); +for($i =0; $i < $length; $i++){ + array_push($input, $session->participant->name[$i]); +} +array_push($input, "trial_id", "choice_option_A", "choice_option_B", "choice_answer", "choice_time", "choice_comment"); +array_push($ptCsvData, $input); + + + +foreach ($session->trials as $trial) { + if ($trial->type == "preference_test") { + foreach ($trial->responses as $response) { + $write_pc = true; + + + $results = array($session->testId); + for($i =0; $i < $length; $i++){ + array_push($results, $session->participant->response[$i]); + } + array_push($results, $trial->id, $response->optionA, $response->optionB, $response->answer, $response->time, $response->comment); + + array_push($ptCsvData, $results); + } + } +} + +if ($write_pc) { + $filename = $filepathPrefix."preference_test".$filepathPostfix; + $isFile = is_file($filename); + $fp = fopen($filename, 'a'); + foreach ($ptCsvData as $row) { + if ($isFile) { + $isFile = false; + } else { + fputcsv($fp, $row); + } + } + fclose($fp); +} + // bs1116 $write_bs1116 = false; From c90510c209fb1624b4e10fa5f480fc4e8608ba8c Mon Sep 17 00:00:00 2001 From: Simon Stone Date: Tue, 31 May 2022 14:55:40 +0200 Subject: [PATCH 04/16] adds support for grouped stimuli so that only pairs from each group are compared --- configs/pref.yaml | 58 ++++++++++++++++--- .../pages/PreferenceTestPageManager.js | 28 ++++++--- 2 files changed, 70 insertions(+), 16 deletions(-) diff --git a/configs/pref.yaml b/configs/pref.yaml index fe57ce86..c26784b3 100644 --- a/configs/pref.yaml +++ b/configs/pref.yaml @@ -10,20 +10,62 @@ remoteService: service/write.php language: de pages: + - type: generic + id: welcome + name: Wilkommen + content: | +

Willkommen beim Hörexperiment

Ihnen werden auf den folgenden Seiten paarweise einige Äußerungen präsentiert.

Bitte spielen Sie jeweils beide Varianten ab und wählen Sie dann die Variante aus, die Ihnen natürlicher erscheint.

+ + - type: volume + id: vol + name: Lautstärke + content:

Bitte regeln Sie die Lautstärke auf ein für Sie angenehmes Niveau.

+ stimulus: configs/resources/audio/bsp-Beispielsatz.wav + defaultVolume: 0.5 - type: preference_test id: trialpref2 name: Hörexperiment - content: Welche Äußerung finden Sie natürlicher? + content:

Welche Äußerung finden Sie natürlicher?

considerOrder: false stimuli: - aI-ori: configs/resources/audio/aI-Sie_leiht_sich_eine.wav - aI-a-e: configs/resources/audio/aI-Sie_leiht_sich_eine-a-e.wav - aI-a-I: configs/resources/audio/aI-Sie_leiht_sich_eine-a-I.wav - aI-aI_begin-aI_end: configs/resources/audio/aI-Sie_leiht_sich_eine-aI_begin-aI_end.wav - aI-aI_begin-e: configs/resources/audio/aI-Sie_leiht_sich_eine-aI_begin-e.wav - aI-aI_begin-I: configs/resources/audio/aI-Sie_leiht_sich_eine-aI_begin-I.wav - aI-a-aI_end: configs/resources/audio/aI-Sie_leiht_sich_eine-a-aI_end.wav + - aI-a-e-01: configs/resources/audio/aI-Sie_leiht_sich_eine-a-e.wav + aI-a-I-01: configs/resources/audio/aI-Sie_leiht_sich_eine-a-I.wav + aI-aI_begin-aI_end-01: configs/resources/audio/aI-Sie_leiht_sich_eine-aI_begin-aI_end.wav + aI-aI_begin-e-01: configs/resources/audio/aI-Sie_leiht_sich_eine-aI_begin-e.wav + aI-aI_begin-I-01: configs/resources/audio/aI-Sie_leiht_sich_eine-aI_begin-I.wav + aI-a-aI_end-01: configs/resources/audio/aI-Sie_leiht_sich_eine-a-aI_end.wav + - aI-a-e-02: configs/resources/audio/aI-weisser_Hai-a-e.wav + aI-a-I-02: configs/resources/audio/aI-weisser_Hai-a-I.wav + aI-aI_begin-aI_end-02: configs/resources/audio/aI-weisser_Hai-aI_begin-aI_end.wav + aI-aI_begin-e-02: configs/resources/audio/aI-weisser_Hai-aI_begin-e.wav + aI-aI_begin-I-02: configs/resources/audio/aI-weisser_Hai-aI_begin-I.wav + aI-a-aI_end-02: configs/resources/audio/aI-weisser_Hai-a-aI_end.wav + - aU-a-o-01: configs/resources/audio/aU-blaue_Maus-a-o.wav + aU-a-u-01: configs/resources/audio/aU-blaue_Maus-a-u.wav + aU-aU_begin-aU_end-01: configs/resources/audio/aU-blaue_Maus-aU_begin-aU_end.wav + aU-aU_begin-o-01: configs/resources/audio/aU-blaue_Maus-aU_begin-o.wav + aU-aU_begin-u-01: configs/resources/audio/aU-blaue_Maus-aU_begin-u.wav + aU-a-aU_end-01: configs/resources/audio/aU-blaue_Maus-a-aU_end.wav + - aU-a-o-02: configs/resources/audio/aU-Sie_haut_die_Pauke-a-o.wav + aU-a-u-02: configs/resources/audio/aU-Sie_haut_die_Pauke-a-u.wav + aU-aU_begin-aU_end-02: configs/resources/audio/aU-Sie_haut_die_Pauke-aU_begin-aU_end.wav + aU-aU_begin-o-02: configs/resources/audio/aU-Sie_haut_die_Pauke-aU_begin-o.wav + aU-aU_begin-u-02: configs/resources/audio/aU-Sie_haut_die_Pauke-aU_begin-u.wav + aU-a-aU_end-02: configs/resources/audio/aU-Sie_haut_die_Pauke-a-aU_end.wav + - OY-O-e-01: configs/resources/audio/OY-neues_Europa-O-e.wav + OY-O-I-01: configs/resources/audio/OY-neues_Europa-O-I.wav + OY-OY_begin-OY_end-01: configs/resources/audio/OY-neues_Europa-OY_begin-OY_end.wav + OY-OY_begin-e-01: configs/resources/audio/OY-neues_Europa-OY_begin-e.wav + OY-OY_begin-I-01: configs/resources/audio/OY-neues_Europa-OY_begin-I.wav + OY-O-OY_end-01: configs/resources/audio/OY-neues_Europa-O-OY_end.wav + - OY-O-e-02: configs/resources/audio/OY-neues_Europa-O-e.wav + OY-O-I-02: configs/resources/audio/OY-neues_Europa-O-I.wav + OY-OY_begin-OY_end-02: configs/resources/audio/OY-neues_Europa-OY_begin-OY_end.wav + OY-OY_begin-e-02: configs/resources/audio/OY-neues_Europa-OY_begin-e.wav + OY-OY_begin-I-02: configs/resources/audio/OY-neues_Europa-OY_begin-I.wav + OY-O-OY_end-02: configs/resources/audio/OY-neues_Europa-O-OY_end.wav + - type: finish name: Vielen Dank für Ihre Teilnahme! diff --git a/lib/webmushra/pages/PreferenceTestPageManager.js b/lib/webmushra/pages/PreferenceTestPageManager.js index 3842dad1..d7866c68 100644 --- a/lib/webmushra/pages/PreferenceTestPageManager.js +++ b/lib/webmushra/pages/PreferenceTestPageManager.js @@ -13,17 +13,29 @@ PreferenceTestPageManager.prototype.createPages = function (_pageManager, _pageT /* Create a set of trials */ this.stimuli = []; - for (var key in _pageConfig.stimuli) { - this.stimuli[this.stimuli.length] = new Stimulus(key, _pageConfig.stimuli[key]); - } this.trials = []; - for (pair of pairs(this.stimuli, _pageConfig.considerOrder)){ - this.trials.push(pair); + /* If the stimuli are passed in groups, only create pairs from the items within each group */ + if (Array.isArray(_pageConfig.stimuli)){ + for (group of _pageConfig.stimuli){ + this.stimuli = []; + for (var key in group) { + this.stimuli[this.stimuli.length] = new Stimulus(key, group[key]); + } + for (pair of pairs(this.stimuli, _pageConfig.considerOrder)){ + this.trials.push(pair); + } + } + } else { /* Otherwise make pairs of all stimuli */ + for (var key in _pageConfig.stimuli) { + this.stimuli[this.stimuli.length] = new Stimulus(key, _pageConfig.stimuli[key]); + } + for (pair of pairs(this.stimuli, _pageConfig.considerOrder)){ + this.trials.push(pair); + } } - - shuffle(this.trials); - + shuffle(this.trials); + for (var i = 0; i < this.trials.length; ++i) { var page = new PreferenceTestPage(_pageManager, _pageTemplateRenderer, _audioContext, _bufferSize, _audioFileLoader, this.trials[i], _session, _pageConfig, _errorHandler, _language); From bb3fed8e965865e91cfe9eab7a90f3069eb7909e Mon Sep 17 00:00:00 2001 From: Simon Stone Date: Tue, 31 May 2022 15:21:57 +0200 Subject: [PATCH 05/16] adds support for 'mustPlay' flag --- configs/pref.yaml | 11 +++++---- lib/webmushra/pages/PreferenceTestPage.js | 29 ++++++++++++++++------- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/configs/pref.yaml b/configs/pref.yaml index c26784b3..3ff5b1e0 100644 --- a/configs/pref.yaml +++ b/configs/pref.yaml @@ -28,6 +28,7 @@ pages: name: Hörexperiment content:

Welche Äußerung finden Sie natürlicher?

considerOrder: false + mustPlayback: ended stimuli: - aI-a-e-01: configs/resources/audio/aI-Sie_leiht_sich_eine-a-e.wav aI-a-I-01: configs/resources/audio/aI-Sie_leiht_sich_eine-a-I.wav @@ -69,7 +70,7 @@ pages: - type: finish name: Vielen Dank für Ihre Teilnahme! - content:

Lassen Sie uns gerne Feedback zum Experiment hier.

Nachdem Sie auf "Ergebnisse senden" geklickt haben, erhalten Sie den Code zur Einlösung auf Clickworkers.de

. + content:

Lassen Sie uns gerne Feedback zum Experiment hier.

Nachdem Sie auf "Ergebnisse senden" geklickt haben, erhalten Sie den Code zur Einlösung auf clickworkers.de

. questionnaire: - type: long_text label: Kommentar @@ -85,13 +86,13 @@ pages: name: Geschlecht label: Gender response: - - value: weiblich + - value: female label: weiblich - - value: männlich + - value: male label: männlich - - value: divers + - value: diverse label: divers showResults: true writeResults: true generateSubjectId: true - confirmationCode: prefTest + confirmationCode: this_is_a_placeholder_code diff --git a/lib/webmushra/pages/PreferenceTestPage.js b/lib/webmushra/pages/PreferenceTestPage.js index 46986904..0f5e17c4 100644 --- a/lib/webmushra/pages/PreferenceTestPage.js +++ b/lib/webmushra/pages/PreferenceTestPage.js @@ -20,10 +20,11 @@ function PreferenceTestPage(_pageManager, _pageTemplateRenderer, _audioContext, this.currentItem = null; - this.stimuli = _stimuli - + this.stimuli = _stimuli; + this.played = []; for (var i = 0; i < this.stimuli.length; ++i) { this.audioFileLoader.addFile(this.stimuli[i].getFilepath(), (function (_buffer, _stimulus) { _stimulus.setAudioBuffer(_buffer); }), this.stimuli[i]); + this.played.push(false); } this.filePlayer = null; this.choice = null; @@ -35,10 +36,20 @@ PreferenceTestPage.prototype.getName = function () { return this.pageConfig.name; }; -PreferenceTestPage.prototype.init = function () { - this.choice = null - +PreferenceTestPage.prototype.init = function () { this.filePlayer = new FilePlayer(this.audioContext, this.bufferSize, this.stimuli, this.errorHandler, this.language, this.pageManager.getLocalizer()); + + if (this.pageConfig.mustPlayback) { + this.filePlayer.genericAudioControl.addEventListener((function (_event) { + if (_event.name == this.pageConfig.mustPlayback) { + this.played[_event.index] = true; + if (this.played.every(element => element === true)){ + $('#radio-choice-a').checkboxradio('enable'); + $('#radio-choice-b').checkboxradio('enable'); + } + } + }).bind(this)); + } }; PreferenceTestPage.prototype.render = function (_parent) { @@ -95,10 +106,10 @@ PreferenceTestPage.prototype.render = function (_parent) { trResponse.append(tdResponse); var radioChoice = $("
\ - \ - \ - \ - \ + \ + \ + \ + \
"); radioChoice.find("input[type='radio']").bind("change", (function(){ From 6d47a8c4f1bef9f3e7760fba0ad38a64bc2f0c49 Mon Sep 17 00:00:00 2001 From: Simon Stone Date: Tue, 31 May 2022 15:24:56 +0200 Subject: [PATCH 06/16] adds hotkey notice --- configs/pref.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/configs/pref.yaml b/configs/pref.yaml index 3ff5b1e0..bd3d0fa8 100644 --- a/configs/pref.yaml +++ b/configs/pref.yaml @@ -26,7 +26,9 @@ pages: - type: preference_test id: trialpref2 name: Hörexperiment - content:

Welche Äußerung finden Sie natürlicher?

+ content: | +

Welche Äußerung finden Sie natürlicher?

+

(Zifferntaste 1: A abspielen, Zifferntaste 2: B abspielen)

considerOrder: false mustPlayback: ended stimuli: From 98a560f6bbd7e5489a8279e7bfc0c062ff808c5d Mon Sep 17 00:00:00 2001 From: Simon Stone Date: Tue, 31 May 2022 16:30:30 +0200 Subject: [PATCH 07/16] added some more explanations --- configs/pref.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configs/pref.yaml b/configs/pref.yaml index bd3d0fa8..19eac307 100644 --- a/configs/pref.yaml +++ b/configs/pref.yaml @@ -1,7 +1,7 @@ # test config preference test -testname: Preference test +testname: Hörexperiment testId: pref bufferSize: 2048 stopOnErrors: true @@ -15,6 +15,7 @@ pages: name: Wilkommen content: |

Willkommen beim Hörexperiment

Ihnen werden auf den folgenden Seiten paarweise einige Äußerungen präsentiert.

Bitte spielen Sie jeweils beide Varianten ab und wählen Sie dann die Variante aus, die Ihnen natürlicher erscheint.

+

Bitte beachten Sie: Sie müssen immer erst alle Äußerungen bis zum Ende hören, bevor Sie eine Entscheidung treffen können.

- type: volume id: vol From f2a4566453ae0916259f3dc3553e6a5e167f6df9 Mon Sep 17 00:00:00 2001 From: Simon Stone Date: Tue, 31 May 2022 16:49:34 +0200 Subject: [PATCH 08/16] removing personal config yaml and adding demo yamls for the Preference Test --- configs/default.yaml | 192 +++++++++++++------------------------- configs/default.yaml_ | 77 --------------- configs/pref.yaml | 93 +++--------------- configs/pref_grouped.yaml | 31 ++++++ 4 files changed, 109 insertions(+), 284 deletions(-) delete mode 100644 configs/default.yaml_ create mode 100644 configs/pref_grouped.yaml diff --git a/configs/default.yaml b/configs/default.yaml index ca6a54f4..8b503287 100644 --- a/configs/default.yaml +++ b/configs/default.yaml @@ -1,135 +1,77 @@ -# Likert multi stimulus page 1 stimuli, 4 responses - - -testname: Hörexperiment -testId: lms_4scale +testname: webMUSHRA Example +testId: default_example bufferSize: 2048 stopOnErrors: true showButtonPreviousPage: true -language: de remoteService: service/write.php pages: - - type: volume - id: vol - name: Lautstärke - content: Bitte regeln Sie die Lautstärke auf ein für Sie angenehmes Niveau. - stimulus: configs/resources/audio/bsp-Beispielsatz.wav - defaultVolume: 0.5 - + - type: generic + id: first_page + name: Welcome + content: Welcome to webMUSHRA! + - type: mushra + id: trial1 + name: MUSHRA + content: This training shows how to use our user interface. Please perform the underlined instructions to proceed with the training session. Reminder: In a MUSHRA listening test you are asked to rate the Basic Audio Quality (BAQ) of each condition.
Basic Audio Quality is a single and global attribute that is used to judge any and all detected differences between the reference and the condition. + showWaveform: true + enableLooping: true + reference: configs/resources/audio/mono_ref.wav + createAnchor35: true + createAnchor70: true + stimuli: + C1: configs/resources/audio/mono_c1.wav + C2: configs/resources/audio/mono_c2.wav + C3: configs/resources/audio/mono_c3.wav - - - random - - - - type: likert_multi_stimulus - id: aI01 - name: Sie leiht sich eine - mustRate: true - mustPlayback: ended - content: Wie natürlich klingen diese Äußerungen für Sie? - stimuli: - C1: configs/resources/audio/aI-Sie_leiht_sich_eine.wav - C2: configs/resources/audio/aI-Sie_leiht_sich_eine-a-aI_end.wav - C3: configs/resources/audio/aI-Sie_leiht_sich_eine-a-e.wav - C4: configs/resources/audio/aI-Sie_leiht_sich_eine-a-I.wav - C5: configs/resources/audio/aI-Sie_leiht_sich_eine-aI_begin-aI_end.wav - C6: configs/resources/audio/aI-Sie_leiht_sich_eine-aI_begin-e.wav - C7: configs/resources/audio/aI-Sie_leiht_sich_eine-aI_begin-I.wav - response: - - value: 0 - label: Völlig unnatürlich - img: configs/resources/images/star_off.png - imgSelected: configs/resources/images/star_on.png - imgHigherResponseSelected: configs/resources/images/star_on.png - - value: 1 - label: Etwas unnatürlich - img: configs/resources/images/star_off.png - imgSelected: configs/resources/images/star_on.png - imgHigherResponseSelected: configs/resources/images/star_on.png - - value: 2 - label: Eher natürlich - img: configs/resources/images/star_off.png - imgSelected: configs/resources/images/star_on.png - imgHigherResponseSelected: configs/resources/images/star_on.png - - value: 3 - label: Sehr natürlich - img: configs/resources/images/star_off.png - imgSelected: configs/resources/images/star_on.png - imgHigherResponseSelected: configs/resources/images/star_on.png - - - - type: likert_multi_stimulus - id: aI02 - name: Weißer Hai - mustRate: true - mustPlayback: ended - content: Wie natürlich klingen diese Äußerungen für Sie? - stimuli: - C1: configs/resources/audio/aI-weisser_Hai.wav - C2: configs/resources/audio/aI-weisser_Hai-a-aI_end.wav - C3: configs/resources/audio/aI-weisser_Hai-a-e.wav - C4: configs/resources/audio/aI-weisser_Hai-a-I.wav - C5: configs/resources/audio/aI-weisser_Hai-aI_begin-aI_end.wav - C6: configs/resources/audio/aI-weisser_Hai-aI_begin-e.wav - C7: configs/resources/audio/aI-weisser_Hai-aI_begin-I.wav - response: - - value: 0 - label: Völlig unnatürlich - img: configs/resources/images/star_off.png - imgSelected: configs/resources/images/star_on.png - imgHigherResponseSelected: configs/resources/images/star_on.png - - value: 1 - label: Etwas unnatürlich - img: configs/resources/images/star_off.png - imgSelected: configs/resources/images/star_on.png - imgHigherResponseSelected: configs/resources/images/star_on.png - - value: 2 - label: Eher natürlich - img: configs/resources/images/star_off.png - imgSelected: configs/resources/images/star_on.png - imgHigherResponseSelected: configs/resources/images/star_on.png - - value: 3 - label: Sehr natürlich - img: configs/resources/images/star_off.png - imgSelected: configs/resources/images/star_on.png - imgHigherResponseSelected: configs/resources/images/star_on.png - - - - type: likert_multi_stimulus - id: OY01 - name: neues Europa - mustRate: true - mustPlayback: ended - content: Wie natürlich klingen diese Äußerungen für Sie? - stimuli: - C1: configs/resources/audio/OY-neues_Europa.wav - C2: configs/resources/audio/OY-neues_Europa-O-e.wav - C3: configs/resources/audio/OY-neues_Europa-O-I.wav - C4: configs/resources/audio/OY-neues_Europa-O-OY_end.wav - C5: configs/resources/audio/OY-neues_Europa-OY_begin-e.wav - C6: configs/resources/audio/OY-neues_Europa-OY_begin-I.wav - C7: configs/resources/audio/OY-neues_Europa-OY_begin-OY_end.wav - response: - - value: 0 - label: Völlig unnatürlich - img: configs/resources/images/star_off.png - imgSelected: configs/resources/images/star_on.png - imgHigherResponseSelected: configs/resources/images/star_on.png - - value: 1 - label: Etwas unnatürlich - img: configs/resources/images/star_off.png - imgSelected: configs/resources/images/star_on.png - imgHigherResponseSelected: configs/resources/images/star_on.png - - value: 2 - label: Eher natürlich - img: configs/resources/images/star_off.png - imgSelected: configs/resources/images/star_on.png - imgHigherResponseSelected: configs/resources/images/star_on.png - - value: 3 - label: Sehr natürlich - img: configs/resources/images/star_off.png - imgSelected: configs/resources/images/star_on.png - imgHigherResponseSelected: configs/resources/images/star_on.png - + - random + - type: mushra + id: trial_random_1 + name: MUSHRA - Random 2 + content: Due to randomization, this page will be either the second MUSHRA page or the third MUSHRA page. + enableLooping: true + reference: configs/resources/audio/mono_ref.wav + createAnchor35: false + createAnchor70: false + stimuli: + C1: configs/resources/audio/mono_c1.wav + C2: configs/resources/audio/mono_c2.wav + C3: configs/resources/audio/mono_c3.wav + - type: mushra + id: trial_random_2 + name: MUSHRA - Random 1 + content: Due to randomization, this page will be either the second MUSHRA page or the third MUSHRA page. + enableLooping: true + reference: configs/resources/audio/mono_ref.wav + createAnchor35: false + createAnchor70: false + stimuli: + C1: configs/resources/audio/mono_c1.wav + C2: configs/resources/audio/mono_c2.wav + C3: configs/resources/audio/mono_c3.wav - type: finish - name: Danke - content: Vielen Dank für Ihre Teilnahme. + name: Thank you + content: Thank you for attending! + showResults: true writeResults: true + questionnaire: + - type: text + label: eMail + name: email + - type: number + label: Age + name: age + min: 0 + max: 100 + default: 30 + - type: likert + name: gender + label: Gender + response: + - value: female + label: Female + - value: male + label: Male + - value: other + label: Other diff --git a/configs/default.yaml_ b/configs/default.yaml_ deleted file mode 100644 index 8b503287..00000000 --- a/configs/default.yaml_ +++ /dev/null @@ -1,77 +0,0 @@ -testname: webMUSHRA Example -testId: default_example -bufferSize: 2048 -stopOnErrors: true -showButtonPreviousPage: true -remoteService: service/write.php - - -pages: - - type: generic - id: first_page - name: Welcome - content: Welcome to webMUSHRA! - - type: mushra - id: trial1 - name: MUSHRA - content: This training shows how to use our user interface. Please perform the underlined instructions to proceed with the training session. Reminder: In a MUSHRA listening test you are asked to rate the Basic Audio Quality (BAQ) of each condition.
Basic Audio Quality is a single and global attribute that is used to judge any and all detected differences between the reference and the condition. - showWaveform: true - enableLooping: true - reference: configs/resources/audio/mono_ref.wav - createAnchor35: true - createAnchor70: true - stimuli: - C1: configs/resources/audio/mono_c1.wav - C2: configs/resources/audio/mono_c2.wav - C3: configs/resources/audio/mono_c3.wav - - - - random - - type: mushra - id: trial_random_1 - name: MUSHRA - Random 2 - content: Due to randomization, this page will be either the second MUSHRA page or the third MUSHRA page. - enableLooping: true - reference: configs/resources/audio/mono_ref.wav - createAnchor35: false - createAnchor70: false - stimuli: - C1: configs/resources/audio/mono_c1.wav - C2: configs/resources/audio/mono_c2.wav - C3: configs/resources/audio/mono_c3.wav - - type: mushra - id: trial_random_2 - name: MUSHRA - Random 1 - content: Due to randomization, this page will be either the second MUSHRA page or the third MUSHRA page. - enableLooping: true - reference: configs/resources/audio/mono_ref.wav - createAnchor35: false - createAnchor70: false - stimuli: - C1: configs/resources/audio/mono_c1.wav - C2: configs/resources/audio/mono_c2.wav - C3: configs/resources/audio/mono_c3.wav - - type: finish - name: Thank you - content: Thank you for attending! - showResults: true - writeResults: true - questionnaire: - - type: text - label: eMail - name: email - - type: number - label: Age - name: age - min: 0 - max: 100 - default: 30 - - type: likert - name: gender - label: Gender - response: - - value: female - label: Female - - value: male - label: Male - - value: other - label: Other diff --git a/configs/pref.yaml b/configs/pref.yaml index 19eac307..fa018a4b 100644 --- a/configs/pref.yaml +++ b/configs/pref.yaml @@ -1,101 +1,30 @@ # test config preference test -testname: Hörexperiment +testname: Preference test testId: pref bufferSize: 2048 stopOnErrors: true showButtonPreviousPage: true remoteService: service/write.php -language: de pages: - - type: generic - id: welcome - name: Wilkommen - content: | -

Willkommen beim Hörexperiment

Ihnen werden auf den folgenden Seiten paarweise einige Äußerungen präsentiert.

Bitte spielen Sie jeweils beide Varianten ab und wählen Sie dann die Variante aus, die Ihnen natürlicher erscheint.

-

Bitte beachten Sie: Sie müssen immer erst alle Äußerungen bis zum Ende hören, bevor Sie eine Entscheidung treffen können.

- - - type: volume - id: vol - name: Lautstärke - content:

Bitte regeln Sie die Lautstärke auf ein für Sie angenehmes Niveau.

- stimulus: configs/resources/audio/bsp-Beispielsatz.wav - defaultVolume: 0.5 - - type: preference_test - id: trialpref2 - name: Hörexperiment + id: trialpref + name: Preference test content: | -

Welche Äußerung finden Sie natürlicher?

-

(Zifferntaste 1: A abspielen, Zifferntaste 2: B abspielen)

- considerOrder: false +

Which sound do you prefer?

+ considerOrder: true mustPlayback: ended stimuli: - - aI-a-e-01: configs/resources/audio/aI-Sie_leiht_sich_eine-a-e.wav - aI-a-I-01: configs/resources/audio/aI-Sie_leiht_sich_eine-a-I.wav - aI-aI_begin-aI_end-01: configs/resources/audio/aI-Sie_leiht_sich_eine-aI_begin-aI_end.wav - aI-aI_begin-e-01: configs/resources/audio/aI-Sie_leiht_sich_eine-aI_begin-e.wav - aI-aI_begin-I-01: configs/resources/audio/aI-Sie_leiht_sich_eine-aI_begin-I.wav - aI-a-aI_end-01: configs/resources/audio/aI-Sie_leiht_sich_eine-a-aI_end.wav - - aI-a-e-02: configs/resources/audio/aI-weisser_Hai-a-e.wav - aI-a-I-02: configs/resources/audio/aI-weisser_Hai-a-I.wav - aI-aI_begin-aI_end-02: configs/resources/audio/aI-weisser_Hai-aI_begin-aI_end.wav - aI-aI_begin-e-02: configs/resources/audio/aI-weisser_Hai-aI_begin-e.wav - aI-aI_begin-I-02: configs/resources/audio/aI-weisser_Hai-aI_begin-I.wav - aI-a-aI_end-02: configs/resources/audio/aI-weisser_Hai-a-aI_end.wav - - aU-a-o-01: configs/resources/audio/aU-blaue_Maus-a-o.wav - aU-a-u-01: configs/resources/audio/aU-blaue_Maus-a-u.wav - aU-aU_begin-aU_end-01: configs/resources/audio/aU-blaue_Maus-aU_begin-aU_end.wav - aU-aU_begin-o-01: configs/resources/audio/aU-blaue_Maus-aU_begin-o.wav - aU-aU_begin-u-01: configs/resources/audio/aU-blaue_Maus-aU_begin-u.wav - aU-a-aU_end-01: configs/resources/audio/aU-blaue_Maus-a-aU_end.wav - - aU-a-o-02: configs/resources/audio/aU-Sie_haut_die_Pauke-a-o.wav - aU-a-u-02: configs/resources/audio/aU-Sie_haut_die_Pauke-a-u.wav - aU-aU_begin-aU_end-02: configs/resources/audio/aU-Sie_haut_die_Pauke-aU_begin-aU_end.wav - aU-aU_begin-o-02: configs/resources/audio/aU-Sie_haut_die_Pauke-aU_begin-o.wav - aU-aU_begin-u-02: configs/resources/audio/aU-Sie_haut_die_Pauke-aU_begin-u.wav - aU-a-aU_end-02: configs/resources/audio/aU-Sie_haut_die_Pauke-a-aU_end.wav - - OY-O-e-01: configs/resources/audio/OY-neues_Europa-O-e.wav - OY-O-I-01: configs/resources/audio/OY-neues_Europa-O-I.wav - OY-OY_begin-OY_end-01: configs/resources/audio/OY-neues_Europa-OY_begin-OY_end.wav - OY-OY_begin-e-01: configs/resources/audio/OY-neues_Europa-OY_begin-e.wav - OY-OY_begin-I-01: configs/resources/audio/OY-neues_Europa-OY_begin-I.wav - OY-O-OY_end-01: configs/resources/audio/OY-neues_Europa-O-OY_end.wav - - OY-O-e-02: configs/resources/audio/OY-neues_Europa-O-e.wav - OY-O-I-02: configs/resources/audio/OY-neues_Europa-O-I.wav - OY-OY_begin-OY_end-02: configs/resources/audio/OY-neues_Europa-OY_begin-OY_end.wav - OY-OY_begin-e-02: configs/resources/audio/OY-neues_Europa-OY_begin-e.wav - OY-OY_begin-I-02: configs/resources/audio/OY-neues_Europa-OY_begin-I.wav - OY-O-OY_end-02: configs/resources/audio/OY-neues_Europa-O-OY_end.wav + C1: configs/resources/audio/mono_c1.wav + C2: configs/resources/audio/mono_c2.wav + C3: configs/resources/audio/mono_c3.wav - - type: finish - name: Vielen Dank für Ihre Teilnahme! - content:

Lassen Sie uns gerne Feedback zum Experiment hier.

Nachdem Sie auf "Ergebnisse senden" geklickt haben, erhalten Sie den Code zur Einlösung auf clickworkers.de

. - questionnaire: - - type: long_text - label: Kommentar - name: feedback - optional: true - - type: number - label: Alter - name: age - min: 0 - max: 100 - default: 30 - - type: likert - name: Geschlecht - label: Gender - response: - - value: female - label: weiblich - - value: male - label: männlich - - value: diverse - label: divers + name: Thank you + content: Thank you for attending showResults: true writeResults: true generateSubjectId: true - confirmationCode: this_is_a_placeholder_code + confirmationCode: your_code_here diff --git a/configs/pref_grouped.yaml b/configs/pref_grouped.yaml new file mode 100644 index 00000000..1481a10a --- /dev/null +++ b/configs/pref_grouped.yaml @@ -0,0 +1,31 @@ +# test config preference test + + +testname: Preference test +testId: pref_grouped +bufferSize: 2048 +stopOnErrors: true +showButtonPreviousPage: true +remoteService: service/write.php + +pages: + - type: preference_test + id: trialpref + name: Preference test + content: | +

Which sound do you prefer?

+ considerOrder: true + mustPlayback: ended + stimuli: + - C1: configs/resources/audio/mono_c1.wav + C2: configs/resources/audio/mono_c2.wav + - C3: configs/resources/audio/mono_c3.wav + C2: configs/resources/audio/mono_c2.wav + + - type: finish + name: Thank you + content: Thank you for attending + showResults: true + writeResults: true + generateSubjectId: true + confirmationCode: your_code_here From 721fe843d2139232428c186f7b63b2196e70e084 Mon Sep 17 00:00:00 2001 From: Simon Stone Date: Tue, 31 May 2022 17:24:51 +0200 Subject: [PATCH 09/16] fixes a bug when certain config paramters are undefined --- lib/webmushra/pages/FinishPage.js | 2 +- lib/webmushra/pages/PreferenceTestPage.js | 13 ++++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/lib/webmushra/pages/FinishPage.js b/lib/webmushra/pages/FinishPage.js index d3ead586..c20e700e 100644 --- a/lib/webmushra/pages/FinishPage.js +++ b/lib/webmushra/pages/FinishPage.js @@ -104,7 +104,7 @@ FinishPage.prototype.render = function (_parent) { $("#popHeader").text(this.pageManager.getLocalizer().getFragment(this.language, 'attending')); - if (this.pageConfig.confirmationCode != ""){ + if (typeof this.pageConfig.confirmationCode !== "undefined"){ divCode = $("

" + this.pageManager.getLocalizer().getFragment(this.language, 'code') + "

"); code = $("

" + this.pageConfig.confirmationCode + "

"); code.css("font-size", "28px"); diff --git a/lib/webmushra/pages/PreferenceTestPage.js b/lib/webmushra/pages/PreferenceTestPage.js index 0f5e17c4..efbcde01 100644 --- a/lib/webmushra/pages/PreferenceTestPage.js +++ b/lib/webmushra/pages/PreferenceTestPage.js @@ -39,7 +39,7 @@ PreferenceTestPage.prototype.getName = function () { PreferenceTestPage.prototype.init = function () { this.filePlayer = new FilePlayer(this.audioContext, this.bufferSize, this.stimuli, this.errorHandler, this.language, this.pageManager.getLocalizer()); - if (this.pageConfig.mustPlayback) { + if (typeof this.pageConfig.mustPlayback !== "undefined") { this.filePlayer.genericAudioControl.addEventListener((function (_event) { if (_event.name == this.pageConfig.mustPlayback) { this.played[_event.index] = true; @@ -106,11 +106,14 @@ PreferenceTestPage.prototype.render = function (_parent) { trResponse.append(tdResponse); var radioChoice = $("
\ - \ - \ - \ - \ + \ + \ + \ + \
"); + if (typeof this.pageConfig.mustPlayback !== "undefined"){ + radioChoice.find("input[type='radio']").attr("disabled", true);; + } radioChoice.find("input[type='radio']").bind("change", (function(){ this.pageTemplateRenderer.unlockNextButton(); From 14c42761fc7e44bb46447738fc23750392a9e618 Mon Sep 17 00:00:00 2001 From: Simon Stone Date: Tue, 31 May 2022 17:26:59 +0200 Subject: [PATCH 10/16] adds documentation for the preference_test page and makes the pref_grouped.yaml more different than the pref.yaml --- configs/pref_grouped.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/configs/pref_grouped.yaml b/configs/pref_grouped.yaml index 1481a10a..a715f6c0 100644 --- a/configs/pref_grouped.yaml +++ b/configs/pref_grouped.yaml @@ -15,7 +15,6 @@ pages: content: |

Which sound do you prefer?

considerOrder: true - mustPlayback: ended stimuli: - C1: configs/resources/audio/mono_c1.wav C2: configs/resources/audio/mono_c2.wav @@ -27,5 +26,3 @@ pages: content: Thank you for attending showResults: true writeResults: true - generateSubjectId: true - confirmationCode: your_code_here From 8e7eb41dd31760ce1fbf88cd8c00dd75ca4d74c3 Mon Sep 17 00:00:00 2001 From: Simon Stone Date: Wed, 1 Jun 2022 14:31:54 +0200 Subject: [PATCH 11/16] adds documentation in the doc files --- doc/experimenter.md | 14 ++++++++++++++ doc/participant.md | 5 +++++ 2 files changed, 19 insertions(+) diff --git a/doc/experimenter.md b/doc/experimenter.md index befc184a..7557c724 100644 --- a/doc/experimenter.md +++ b/doc/experimenter.md @@ -96,6 +96,18 @@ A paired comparison page creates a forced or unforced paired comparison (AB/ABX/ * **reference** Filepath to the reference stimulus (WAV file). * **stimuli** A map of stimuli representing three conditions. The key is the name of the condition. The value is the filepath to the stimulus (WAV file). +#### `preference_test` page + +A preference test page creates a forced paired comparison between two stimuli. The main difference to `paired_comparison` is that there is no reference or ground truth. + +* **type** must be preference_test. +* **id** Identifier of the page. +* **name** Name of the page (is shown as title) +* **content** Content (HTML) of the page. The content is shown on the upper part of the page. +* **considerOrder** If set to true, a complete set of pairs is generated from the list of stimuli: A set of `{A, B}` would result in two pairs `(A, B)` and `(B, A)`. Otherwise only the pair `(A, B)` would be generated. +* **mustPlayback** If set to `ended`, the participant must fully play back all stimuli to the end. If set to `processUpdate`, the participant must start playing back all stimuli before responding becomes possible. +* **stimuli** Either a map of stimuli or an array of maps of stimuli. If it is a map, pairs will be generated from the list and then shuffled. If it is an array of maps, pairs will be generated for each map individually and then all the pairs from all maps are shuffled. + #### `likert_multi_stimulus` page A likert multi stimulus page creates a multi-stimulus likert rating. @@ -133,6 +145,8 @@ The finish page must be the last page of the experiment. * **content** Content (HTML) of the page. The content is shown on the upper part of the page. * **showResults** The results are shown to the participant. * **writeResults** The results are sent to the remote service (which writes the results into a file). +* **generateSubjectId** If set to true, a random subject ID is generated and appended to the results. +* **confirmationCode:** If set, this code is displayed after the results were sent. This can be used to confirm that subjects have completed the experiment and facilitates ## Results diff --git a/doc/participant.md b/doc/participant.md index 4ac44120..b50fd82c 100644 --- a/doc/participant.md +++ b/doc/participant.md @@ -41,3 +41,8 @@ * SPACE Play/pause the current selection * a Set begin of loop to current position * b Set end of loop to current position + +### Preference test + +* 1 Play item A +* 2 Play item B \ No newline at end of file From 2c2cee1243aa739f88072029e4f73b250e931d43 Mon Sep 17 00:00:00 2001 From: Simon Stone Date: Thu, 2 Jun 2022 15:10:38 +0200 Subject: [PATCH 12/16] removes some dead code --- lib/webmushra/pages/PreferenceTestPage.js | 68 ----------------------- 1 file changed, 68 deletions(-) diff --git a/lib/webmushra/pages/PreferenceTestPage.js b/lib/webmushra/pages/PreferenceTestPage.js index efbcde01..2340a5c9 100644 --- a/lib/webmushra/pages/PreferenceTestPage.js +++ b/lib/webmushra/pages/PreferenceTestPage.js @@ -127,74 +127,6 @@ PreferenceTestPage.prototype.render = function (_parent) { }; -PreferenceTestPage.prototype.cleanButtons = function() { - if($('#buttonStop').attr("active") == "true") { - $.mobile.activePage.find('#buttonStop') //remove color from Stop - .removeClass('ui-btn-b') - .addClass('ui-btn-a').attr('data-theme', 'a'); - $('#buttonStop').attr("active", "false"); - } - - - if($('#buttonConditions0').attr("active") == "true") { - $.mobile.activePage.find('#buttonConditions0') //remove color from Reference - .removeClass('ui-btn-b') - .addClass('ui-btn-a').attr('data-theme', 'a'); - $('#buttonConditions0').attr("active", "false"); - } - - if($('#buttonConditions1').attr("active") == "true") { - $.mobile.activePage.find('#buttonConditions1') //remove color from Reference - .removeClass('ui-btn-b') - .addClass('ui-btn-a').attr('data-theme', 'a'); - $('#buttonConditions1').attr("active", "false"); - } -}; - - -PreferenceTestPage.prototype.btnCallbackA = function() { - this.currentItem = "A"; - var label = $("#buttonConditions0").text(); - if (label == this.pageManager.getLocalizer().getFragment(this.language, 'pauseButton')) { - this.mushraAudioControl.pause(); - $("#buttonConditions0").text(this.pageManager.getLocalizer().getFragment(this.language, 'playButton')); - } else if (label == this.pageManager.getLocalizer().getFragment(this.language, 'playButton')) { - $(".audioControlElement").text(this.pageManager.getLocalizer().getFragment(this.language, 'playButton')); - this.mushraAudioControl.playCondition(0); - $("#buttonConditions0").text(this.pageManager.getLocalizer().getFragment(this.language, 'pauseButton')); - - this.cleanButtons(); - $.mobile.activePage.find('#buttonConditions0') //add color to reference - .removeClass('ui-btn-a') - .addClass('ui-btn-b').attr('data-theme', 'b'); - $('#buttonConditions0').focus(); - $('#buttonConditions0').attr("active", "true"); - } -}; - -PreferenceTestPage.prototype.btnCallbackB = function() { - this.currentItem = "B"; - var label = $("#buttonConditions1").text(); - if (label == this.pageManager.getLocalizer().getFragment(this.language, 'pauseButton')) { - this.mushraAudioControl.pause(); - $("#buttonConditions1").text(this.pageManager.getLocalizer().getFragment(this.language, 'playButton')); - } else if (label == this.pageManager.getLocalizer().getFragment(this.language, 'playButton')) { - $(".audioControlElement").text(this.pageManager.getLocalizer().getFragment(this.language, 'playButton')); - this.mushraAudioControl.playCondition(1); - $("#buttonConditions1").text(this.pageManager.getLocalizer().getFragment(this.language, 'pauseButton')); - - this.cleanButtons(); - $.mobile.activePage.find('#buttonConditions1') //add color to reference - .removeClass('ui-btn-a') - .addClass('ui-btn-b').attr('data-theme', 'b'); - $('#buttonConditions1').focus(); - $('#buttonConditions1').attr("active", "true"); - - } -}; - - - PreferenceTestPage.prototype.load = function () { this.startTimeOnPage = new Date(); From b062a7a9a34d1eddf01460e832d47a3060f9059b Mon Sep 17 00:00:00 2001 From: Simon Stone Date: Fri, 3 Jun 2022 08:53:41 +0200 Subject: [PATCH 13/16] adds a dropdown to the widget options for the questionnaire --- configs/complete.yaml | 14 ++++++ configs/pref.yaml | 76 +++++++++++++++++++++++++------ lib/webmushra/pages/FinishPage.js | 27 +++++++++-- 3 files changed, 98 insertions(+), 19 deletions(-) diff --git a/configs/complete.yaml b/configs/complete.yaml index 433682c9..85adf409 100644 --- a/configs/complete.yaml +++ b/configs/complete.yaml @@ -284,6 +284,20 @@ pages: label: Male - value: other label: Other + - type: dropdown + name: referral + label: How have you heard of us? + response: + - value: searchEngine + label: Google/internet search + - value: friends + label: Friends or colleagues + - value: participant + label: Previous experiment + - value: paper + label: Seen in published paper + - value: other + label: Other - type: long_text label: Feedback name: feedback diff --git a/configs/pref.yaml b/configs/pref.yaml index fa018a4b..251e7859 100644 --- a/configs/pref.yaml +++ b/configs/pref.yaml @@ -1,30 +1,78 @@ # test config preference test -testname: Preference test +testname: Hörexperiment testId: pref -bufferSize: 2048 +bufferSize: 4096 stopOnErrors: true showButtonPreviousPage: true remoteService: service/write.php +language: de pages: + - type: generic + id: welcome + name: Willkommen beim Hörexperiment + content: | +

Ihnen werden auf den folgenden Seiten paarweise einige Äußerungen präsentiert.

Bitte spielen Sie jeweils beide Varianten ab und wählen Sie dann die Variante aus, die Ihnen natürlicher (realistischer, menschenähnlicher, normaler, ...) erscheint.

+

Hören Sie sich ruhig beide Äußerungen mehrfach an, aber entscheiden Sie letzlich ganz spontan. Wenn Sie bei einem Paar keine klare Entscheidung treffen können, dann folgen Sie einfach Ihrem Bauchgefühl oder wählen Sie eine der Äußerungen zufällig aus.

+

Bitte beachten Sie: Sie müssen immer erst alle Äußerungen bis zum Ende hören, bevor Sie eine Entscheidung treffen können.

+

Steuerung

+

Sie können das gesamte Experiment mit der Maus bedienen. Wir empfehlen Ihnen jedoch, die Zifferntasten "1" und "2" zum Abspielen der 1. bzw. 2. Äußerung zu verwenden. So können Sie sich mit der Maus auf die Auswahl der bevorzugten Äußerung und das Vor- und Zurückschalten konzentrieren.

+

Ablauf

+

Wenn Sie unten auf "Nächste Seite" klicken, folgt zunächst eine Seite, auf der Sie die Lautstärke auf ein für Sie angenehmes Niveau einpegeln können.

+

Auf der Seite danach geht es dann direkt los. Spielen Sie bitte zunächst beide Äußerungen vollständig ab, wählen Sie dann die von Ihnen bevorzugte Äußerung aus und klicken Sie anschließend auf "Nächste Seite".

+

Anhand des Fortschrittbalkens auf jeder Seite können Sie sehen, wie weit Sie schon sind. Sie können ruhig nach eigenem Ermessen jederzeit Pausen einlegen.

+

Am Ende des Experiments bitten wir Sie noch um ein paar statistische Angaben. Danach wird Ihnen der Bestätigungscode angezeigt, den Sie für die Auszahlung der Aufwandsentschädigung benötigen.

+

Viel Spaß beim Experiment!

+ + - type: volume + id: vol + name: Lautstärke + content: | +

Bitte regeln Sie die Lautstärke auf ein für Sie angenehmes Niveau.

+

Wenn der Beispielsatz auch bei voller Aussteuerung des Laustärkereglers noch zu leise ist, erhöhen Sie bitte zusätzlich Ihre Systemlautstärke.

+ stimulus: configs/resources/audio/bsp-Beispielsatz.wav + defaultVolume: 0.5 + - type: preference_test - id: trialpref - name: Preference test + id: trialpref2 + name: Hörexperiment content: | -

Which sound do you prefer?

+

Welche Äußerung finden Sie natürlicher?

+

(Zifferntaste 1: A abspielen, Zifferntaste 2: B abspielen)

considerOrder: true - mustPlayback: ended stimuli: - C1: configs/resources/audio/mono_c1.wav - C2: configs/resources/audio/mono_c2.wav - C3: configs/resources/audio/mono_c3.wav - + - aI-a-e-01: configs/resources/audio/aI-Sie_leiht_sich_eine-a-e.wav + OY-O-e-01: configs/resources/audio/OY-neues_Europa-O-e.wav + aI-a-e-02: configs/resources/audio/aI-weisser_Hai-a-e.wav + - type: finish - name: Thank you - content: Thank you for attending - showResults: true + name: Vielen Dank für Ihre Teilnahme! + content:

Lassen Sie uns gerne Feedback zum Experiment hier.

Nachdem Sie auf "Ergebnisse senden" geklickt haben, erhalten Sie den Code zur Einlösung auf clickworkers.de

. + questionnaire: + - type: long_text + label: Kommentar + name: feedback + optional: true + - type: number + label: Alter + name: age + min: 0 + max: 100 + default: 30 + - type: likert + label: Geschlecht + name: gender + response: + - value: female + label: weiblich + - value: male + label: männlich + - value: diverse + label: divers + + showResults: false writeResults: true generateSubjectId: true - confirmationCode: your_code_here + confirmationCode: this_is_a_placeholder_code diff --git a/lib/webmushra/pages/FinishPage.js b/lib/webmushra/pages/FinishPage.js index c20e700e..d41412c3 100644 --- a/lib/webmushra/pages/FinishPage.js +++ b/lib/webmushra/pages/FinishPage.js @@ -77,20 +77,33 @@ FinishPage.prototype.render = function (_parent) { for (i = 0; i < this.pageConfig.questionnaire.length; ++i) { var element = this.pageConfig.questionnaire[i]; if (element.type === "text") { - table.append($(""+ element.label +"")); + table.append($(""+ element.label +"")); } else if (element.type === "number") { - table.append($(""+ element.label +"")); + table.append($(""+ element.label +"")); } else if(element.type === "likert") { this.likert = new LikertScale(element.response, element.name + "_"); var td = $(""); table.append($("").append( - $(""+ element.label +""), + $(""+ element.label +""), td )); this.likert.render(td); }else if (element.type === "long_text"){ - table.append($(""+ element.label +"")); - } + table.append($(""+ element.label +"")); + }else if (element.type === "dropdown"){ + var td = $(""); + table.append($("").append( + $(""+ element.label +""), + td)); + dropdown = $(""); + var opt = $(""); + dropdown.append(opt); + for (i = 0; i < element.response.length; ++i) { + opt = $("") + dropdown.append(opt); + } + td.append(dropdown); + } console.log(element); } var button = $(""); @@ -340,6 +353,10 @@ FinishPage.prototype.load = function() { if ($("#" + element.name).val() || element.optional == true) { ++counter; } + } else if(element.type === "dropdown") { + if ($("#" + element.name).val() || element.optional == true) { + ++counter; + } } if (counter == this.pageConfig.questionnaire.length) { $('#send_results').removeAttr('disabled'); From 137aee147c78aec0c679ca398e7b353dbd4c50b5 Mon Sep 17 00:00:00 2001 From: Simon Stone Date: Fri, 3 Jun 2022 09:00:58 +0200 Subject: [PATCH 14/16] restores to a generic version --- configs/pref.yaml | 76 +++++++++-------------------------------------- 1 file changed, 14 insertions(+), 62 deletions(-) diff --git a/configs/pref.yaml b/configs/pref.yaml index 251e7859..fa018a4b 100644 --- a/configs/pref.yaml +++ b/configs/pref.yaml @@ -1,78 +1,30 @@ # test config preference test -testname: Hörexperiment +testname: Preference test testId: pref -bufferSize: 4096 +bufferSize: 2048 stopOnErrors: true showButtonPreviousPage: true remoteService: service/write.php -language: de pages: - - type: generic - id: welcome - name: Willkommen beim Hörexperiment - content: | -

Ihnen werden auf den folgenden Seiten paarweise einige Äußerungen präsentiert.

Bitte spielen Sie jeweils beide Varianten ab und wählen Sie dann die Variante aus, die Ihnen natürlicher (realistischer, menschenähnlicher, normaler, ...) erscheint.

-

Hören Sie sich ruhig beide Äußerungen mehrfach an, aber entscheiden Sie letzlich ganz spontan. Wenn Sie bei einem Paar keine klare Entscheidung treffen können, dann folgen Sie einfach Ihrem Bauchgefühl oder wählen Sie eine der Äußerungen zufällig aus.

-

Bitte beachten Sie: Sie müssen immer erst alle Äußerungen bis zum Ende hören, bevor Sie eine Entscheidung treffen können.

-

Steuerung

-

Sie können das gesamte Experiment mit der Maus bedienen. Wir empfehlen Ihnen jedoch, die Zifferntasten "1" und "2" zum Abspielen der 1. bzw. 2. Äußerung zu verwenden. So können Sie sich mit der Maus auf die Auswahl der bevorzugten Äußerung und das Vor- und Zurückschalten konzentrieren.

-

Ablauf

-

Wenn Sie unten auf "Nächste Seite" klicken, folgt zunächst eine Seite, auf der Sie die Lautstärke auf ein für Sie angenehmes Niveau einpegeln können.

-

Auf der Seite danach geht es dann direkt los. Spielen Sie bitte zunächst beide Äußerungen vollständig ab, wählen Sie dann die von Ihnen bevorzugte Äußerung aus und klicken Sie anschließend auf "Nächste Seite".

-

Anhand des Fortschrittbalkens auf jeder Seite können Sie sehen, wie weit Sie schon sind. Sie können ruhig nach eigenem Ermessen jederzeit Pausen einlegen.

-

Am Ende des Experiments bitten wir Sie noch um ein paar statistische Angaben. Danach wird Ihnen der Bestätigungscode angezeigt, den Sie für die Auszahlung der Aufwandsentschädigung benötigen.

-

Viel Spaß beim Experiment!

- - - type: volume - id: vol - name: Lautstärke - content: | -

Bitte regeln Sie die Lautstärke auf ein für Sie angenehmes Niveau.

-

Wenn der Beispielsatz auch bei voller Aussteuerung des Laustärkereglers noch zu leise ist, erhöhen Sie bitte zusätzlich Ihre Systemlautstärke.

- stimulus: configs/resources/audio/bsp-Beispielsatz.wav - defaultVolume: 0.5 - - type: preference_test - id: trialpref2 - name: Hörexperiment + id: trialpref + name: Preference test content: | -

Welche Äußerung finden Sie natürlicher?

-

(Zifferntaste 1: A abspielen, Zifferntaste 2: B abspielen)

+

Which sound do you prefer?

considerOrder: true + mustPlayback: ended stimuli: - - aI-a-e-01: configs/resources/audio/aI-Sie_leiht_sich_eine-a-e.wav - OY-O-e-01: configs/resources/audio/OY-neues_Europa-O-e.wav - aI-a-e-02: configs/resources/audio/aI-weisser_Hai-a-e.wav - - - type: finish - name: Vielen Dank für Ihre Teilnahme! - content:

Lassen Sie uns gerne Feedback zum Experiment hier.

Nachdem Sie auf "Ergebnisse senden" geklickt haben, erhalten Sie den Code zur Einlösung auf clickworkers.de

. - questionnaire: - - type: long_text - label: Kommentar - name: feedback - optional: true - - type: number - label: Alter - name: age - min: 0 - max: 100 - default: 30 - - type: likert - label: Geschlecht - name: gender - response: - - value: female - label: weiblich - - value: male - label: männlich - - value: diverse - label: divers + C1: configs/resources/audio/mono_c1.wav + C2: configs/resources/audio/mono_c2.wav + C3: configs/resources/audio/mono_c3.wav - showResults: false + - type: finish + name: Thank you + content: Thank you for attending + showResults: true writeResults: true generateSubjectId: true - confirmationCode: this_is_a_placeholder_code + confirmationCode: your_code_here From a370979b1d4df2aeef405f1dac8ba9202bb665e3 Mon Sep 17 00:00:00 2001 From: Simon Stone Date: Fri, 3 Jun 2022 12:46:23 +0200 Subject: [PATCH 15/16] fixes missing time calculation --- lib/webmushra/pages/PreferenceTestPage.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/webmushra/pages/PreferenceTestPage.js b/lib/webmushra/pages/PreferenceTestPage.js index 2340a5c9..c2cf6057 100644 --- a/lib/webmushra/pages/PreferenceTestPage.js +++ b/lib/webmushra/pages/PreferenceTestPage.js @@ -26,8 +26,11 @@ function PreferenceTestPage(_pageManager, _pageTemplateRenderer, _audioContext, this.audioFileLoader.addFile(this.stimuli[i].getFilepath(), (function (_buffer, _stimulus) { _stimulus.setAudioBuffer(_buffer); }), this.stimuli[i]); this.played.push(false); } + this.filePlayer = null; this.choice = null; + this.time = 0; + this.startTimeOnPage = null; } From 8117a0f7ba907a4d222ed03b370abdae7dcb7987 Mon Sep 17 00:00:00 2001 From: Simon Stone Date: Wed, 6 Jul 2022 08:41:42 +0200 Subject: [PATCH 16/16] Update lib/webmushra/pages/PreferenceTestPage.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fabian-Robert Stöter --- lib/webmushra/pages/PreferenceTestPage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/webmushra/pages/PreferenceTestPage.js b/lib/webmushra/pages/PreferenceTestPage.js index c2cf6057..6af7599b 100644 --- a/lib/webmushra/pages/PreferenceTestPage.js +++ b/lib/webmushra/pages/PreferenceTestPage.js @@ -46,7 +46,7 @@ PreferenceTestPage.prototype.init = function () { this.filePlayer.genericAudioControl.addEventListener((function (_event) { if (_event.name == this.pageConfig.mustPlayback) { this.played[_event.index] = true; - if (this.played.every(element => element === true)){ + if (this.played.every((element) => element === true)){ $('#radio-choice-a').checkboxradio('enable'); $('#radio-choice-b').checkboxradio('enable'); }