R.Muralikrishnan, MPI for Empirical Aesthetics. This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Licence. ############################################################################## ## ## ## Categories Discrimination : Auditory Study with Discrimination Task ## ## Experiment Script for use with Presentation ## ## Experimenter : Pauline Larrouy-Maestri ## ## Author: R. Muralikrishnan ## ## ## ############################################################################## ############################################################################## # Scenario Description Language (SDL) Header Part ############################################################################## # These button codes have to correspond to those set in 'Settings -> Response' active_buttons = 3; # There are 3 active buttons defined in 'Settings -> Response' button_codes = 1,2,3; # These are the codes of those buttons response_matching = simple_matching; # Enables features not in legacy_matching # Only those button presses that one expects are logged; not all response_logging = log_active; # Needed for EEG Trigger files # write_codes = true; # pulse_width = 5; # default_output_port = 1; # This is most probably going to be the same for everyone. # This is the LPT Parallel port that you will define in the Port settings tab of # Presentation. This will be used as the output port for sending codes to EEG. # Defining this here saves getting a port number in the PCL part from the output_manager # and calling send_code etc. Stimulus events themselves will send these for us, provided we # define the correct port_codes in each Stimulus event. # Default Settings for Font, FG and BG Colours etc. default_background_color = "0, 0, 0"; # RGB codes in decimal; 000 => Black default_font = "Verdana"; default_font_size = 28; default_text_color = "000, 102, 153"; # #006699 A bluish colour default_text_align = align_center; default_deltat = 0; default_picture_duration = next_picture; /* This implies that all pictures ... /...are shown until the next picture is shown, unless otherwise specified */ #default_all_responses = false; ############################################################################## # Scenario Description Language (SDL) Part ############################################################################## begin; # ============================ # SDL Variable Declarations: - # ============================ # # We don't use any variables. All the timer parameters appear as numbers. # ============================== # Picture Stimuli Definitions: - Everything that is shown, including text! # ============================== # Screen definition for the trial that starts an Experimental Session. # Used as the first screen that the participant sees. Operator Controlled. picture { text { caption = "Welcome! The Experiment will begin in a moment."; }; x = 0; y = 0; } P_Start_Exp; # Screen definition for the Pause trial # Operator Controlled! picture { text { caption = "Let us continue after a break."; }; x = 0; y = 0; } P_Pause; # Screen definition for the Continue trial # Participant Controlled! picture { text { caption = "Press a button to continue."; }; x = 0; y = 0; } P_Continue; # Screen definition for the Interruption trial # Operator Controlled! picture { text { caption = "Sorry for the interruption. Please wait."; }; x = 0; y = 0; } P_Interruption; # Screen definition for showing the focus star picture { text { caption = "*"; } Txt_Focus_Star; x = 0; y = 0; } P_Focus_Star; # Screen definition for the Discrimination Task picture { text { caption = "Same or Different?"; }; x = 0; y = 0; } P_Discrimination_Task; # Screen definition for the End_Thanks trial picture { text {caption = "Thank you! We're done!";}; x = 0; y = 0; } P_End_Thanks; ##### #### Specific for presenting Auditory Stimuli ------------------------------- # ============================ # Sound Stimuli Definitions: - # ============================ sound { wavefile { filename = ""; # PCL Program below fills the file name preload = false; } Wav_Auditory_Reference; } S_Auditory_Reference; #### sound { wavefile { filename = ""; # PCL Program below fills the file name preload = false; } Wav_Auditory_Stimulus; } S_Auditory_Stimulus; #### #===================== # Trial Definitions: - #===================== /**** / Note that the name 'Trial' could be misleading. Unless otherwise specified, / what we mean by a 'Trial' here is actually a sub-trial or sub-task that is / part - and thereby defines the structure - of an actual experimental trial. ****/ /**** / Template for defining an SDL Trial. / trial / { / Trial-related parameters such as trial_duration, trial_type etc. / Trial-related parameters / / Stimulus event 1 such as picture, sound, video, nothing or force-FB; / Stimulus event parameters such as time, event code etc. / If the parameters aren't specified, the default values are used!!! / / Stimulus event 2; / its parameters...and so on / } ****/ trial { trial_duration = 1500; all_responses = false; stimulus_event { picture {}; # This is the default picture, which is nothing! #code = "CLS"; # Comment this out to avoid seeing this in the logfile. }; } T_Blank_Screen; # Definition of the Trial to start an Experimental Session. # Operator Controlled! trial { trial_duration = forever; # Keep running the trial... trial_type = specific_response; # ...until the following specific response. terminator_button = 3; # Operator PC - ENTER key. stimulus_event { picture P_Start_Exp; # Show P_Start_Exp. code = "The Experiment starts now!"; }; } T_Start_Exp; # Definition of the Trial to continue further. # Participant Controlled! trial { trial_duration = forever; # Keep running the trial... trial_type = specific_response; # ...until the following specific response. terminator_button = 1,2; # Participant Joystick - L or R button. stimulus_event { picture P_Continue; # Show P_Continue. code = "Trials follow!"; }; } T_Continue; # Definition of the Trial to Launch an Experimental Trial trial { trial_duration = 500; # Run the trial for 500 ms... all_responses = false; # ..without recognising any key presses. stimulus_event { picture P_Focus_Star; # Show the focus star for fixation. code = ""; # Code set below in the PCL program. # port_code = ; # Port code set by the PCL program. } E_Launch_New_Trial; } T_Launch_New_Trial; # Definition of the Trial to keep showing the Focus Star for fixation. trial { trial_duration = 1000; # Show star until the next clear-screen... all_responses = false; # ..without recognising any key presses. stimulus_event { picture P_Focus_Star; # Show the focus star for fixation. #code = "*"; # Comment this out later to avoid seeing this in the log file. }; } T_Keep_Showing_Star; # Definition of the Trial to show a question for the Discrimination Task trial { trial_duration = forever; trial_type = specific_response; terminator_button = 1,2; # The exact response can be either of these; stimulus_event { picture P_Discrimination_Task; code = "Discrimination-Task"; # PCL Program sets this. #port_code = 191; # Send '191' to EEG target_button = 2; # 2 is good (=> Different), 1 is bad (=> Reference = Stimulus). } E_Discrimination_Task; # This is necessary to test for stimulus_miss later! } T_Discrimination_Task; #### Specific for presenting Auditory Stimuli ------------------------------- # Definition of the Trial to play the Reference Tone sequence trial { trial_duration = stimuli_length; all_responses = false; stimulus_event { sound S_Auditory_Reference; code = ""; # PCL Program sets Event code # port_code = ; # PCL Program sets port code } E_Auditory_Reference; } T_Auditory_Reference; #### # Definition of the Trial to play the Stimulus Tone sequence trial { trial_duration = stimuli_length; all_responses = false; stimulus_event { sound S_Auditory_Stimulus; code = ""; # PCL Program sets Event code # port_code = ; # PCL Program sets port code } E_Auditory_Stimulus; } T_Auditory_Stimulus; #### # Definition of the Trial to send a code indicating that a Timeout has occurred. /* When a button-pressed response occurs, 1 or 2 or 3 or 4 is sent to EEG depending upon the button pressed. When a timeout occurs, nothing gets sent. Just in order to have equal number of lines in the trigger files later, it's better to send a code indicating timeout. (Yes, IN ADDITION to the usual code 199 that will follow.) */ /* trial { trial_duration = 10; all_responses = false; stimulus_event { nothing {}; # This is the default picture, which is nothing! code = "Timeout"; port_code = 5; } E_Report_Timeout_to_EEG; } T_Report_Timeout_to_EEG; */ # Definition of the Trial to log the response trial { trial_duration = 10; all_responses = false; stimulus_event { nothing {}; time = 5; # Start this event after 5 ms from the start the trial. # This is just to make sure the order in the log-file is correct (due to the nothing task jumping the queue). # Basically, nothing is done! # code = "Send Code"; # Comment this out to avoid seeing this in the logfile. # port_code = 196, 197 or 199, PCL Program fills this!!! } E_Log_Response; } T_Log_Response; # Definition of the Trial to show a Pause # Operator Controlled trial { trial_duration = forever; trial_type = specific_response; terminator_button = 3; stimulus_event { picture P_Pause; code = "Pause"; }; } T_Pause; # Definition of the Trial to Interrupt in the middle of a session # Operator Controlled trial { trial_duration = forever; trial_type = specific_response; terminator_button = 3; stimulus_event { picture P_Interruption; code = "Interrupted!!!"; }; } T_Interruption; # Definition of the Trial to end the session # Operator Controlled trial { trial_duration = forever; all_responses = false; trial_type = first_response; stimulus_event { picture P_End_Thanks; code = "End of Session!"; }; picture P_End_Thanks; } T_End_Thanks; ############################################################################## # Presentation Control Language (PCL) Program Part ############################################################################## begin_pcl; #int N_of_Trials = 20; # Number of Experimental Trials per Session. int N_of_Blocks = 5; # Number of Blocks per Session. #int N_of_Trials_per_Block = N_of_Trials/N_of_Blocks; # Number of Experimental Trials per Block. bool V_Finish_Block = false; preset string V_Version; # Prompt the version at the beginning!!! input_file F_Session_List = new input_file; F_Session_List.open("Session_List_" + V_Version + ".txt"); # This is the file containing the list of stimuli for one session. # Each line in this file must correspond to one experimental trial. #### # Columns of strings in the order found in the input Session List file. string V_Melody; int V_Reference_Level; int V_Stimulus_Level; int V_Max_Level = 20; # This is the maximum that the stimulus level can go. Once this is reached, we stop. int V_Min_Level; # Since we want the stimulus level to be always higher or equal to the reference level, # we want the minimum level the stimulus can reach to be equal to the reference level in a given block. # Say if the Ref_Level is 10, we don't want combinations such as 10+9 10+8 etc. # Assigned after reading the Ref_Level from the session list below. int V_Decrement_Value_Before_First_Increment = 2; # Until the participant chooses 'Same' for the first ever time (and therefore leads to an increment), # we need to DECREMENT the tones...we do this by this step value. # But after the first ever increment, this value is always 1. int V_Changes_Needed_To_End_Staircase = 3; # This is the number of change of directions after which the trial will end! string V_Auditory_Reference; string V_Auditory_Stimulus; string V_Previous_Response; string V_Current_Response; string V_Previous_Change_of_Direction_Trigger; int V_Change_of_Direction_Counter = 0; # output_port O_Port_to_EEG = output_port_manager.get_port(1); stimulus_data D_Stimulus_Data = stimulus_manager.last_stimulus_data(); int D_Last_Response = response_manager.last_response(); #======================== # Main Experiment Loop: - #======================== loop /*** Begin Main Loop 1 for Blocks ***/ int V_Current_Block = 1 until V_Current_Block > N_of_Blocks begin if V_Current_Block == 1 then T_Start_Exp.present(); else T_Pause.present(); end; T_Continue.present(); T_Blank_Screen.present(); V_Finish_Block = false; V_Previous_Response = " "; V_Current_Response = " "; # In the Discrimination experiment, each line in the session list corresponds to one full block! # Because, starting with the reference and stimulus sequences, we will try many combinations # entirely based on participants'responses. These will then be equivalent to the usual trials. V_Melody = F_Session_List.get_string(); # Eg: Mel1-2nd-end_P V_Reference_Level = F_Session_List.get_int(); # Eg: 0 V_Stimulus_Level = F_Session_List.get_int(); # Eg: 17 V_Min_Level = V_Reference_Level; V_Auditory_Reference = V_Melody + string(V_Reference_Level); V_Auditory_Stimulus = V_Melody + string(V_Stimulus_Level); # Do filename and event-code assignments valid during this exp-trial; # Load wavefile and bitmap stimuli that are needed for this trial; /* We do this before launching the experimental trial so as to keep as minimal intereference as possible in trial timings. You see, these things consume processor time, however small they are! */ #### Specific for presenting Auditory Stimuli ------------------------------- Wav_Auditory_Reference.set_filename(V_Auditory_Reference + ".wav"); Wav_Auditory_Reference.load(); Wav_Auditory_Stimulus.set_filename(V_Auditory_Stimulus + ".wav"); # This will change based on participant response...see below. Wav_Auditory_Stimulus.load(); E_Auditory_Reference.set_event_code(V_Auditory_Reference + ".wav"); E_Auditory_Stimulus.set_event_code(V_Auditory_Stimulus + ".wav"); # This will change based on participant response...see below. #### #========== # Loop 2: - #========== loop /*** Begin Loop 2 for Trials ***/ int V_Current_Trial = 1 until V_Finish_Block == true begin E_Launch_New_Trial.set_event_code("B" + string(V_Current_Block) + " T" + string(V_Current_Trial)); # Execute the Experimental Trial!!! T_Launch_New_Trial.present(); # Show Star for 500 ms /************ Auditory Stimulus Presentation Begins *****************/ T_Auditory_Reference.present(); #Txt_Focus_Star.set_caption(string(V_Stimulus_Level)); #Txt_Focus_Star.redraw(); T_Keep_Showing_Star.present(); T_Auditory_Stimulus.present(); T_Keep_Showing_Star.present(); #T_Blank_Screen.set_duration(500); #T_Blank_Screen.present(); #T_Blank_Screen.set_duration(1500); /************ Auditory Stimulus Presentation Ends *******************/ /***************** Task Begins **********************/ T_Discrimination_Task.present(); # Monitor the Response and send appropriate port codes to EEG!!! D_Stimulus_Data = stimulus_manager.last_stimulus_data(); if (D_Stimulus_Data.type() == stimulus_hit) then E_Log_Response.set_event_code("Different"); T_Log_Response.present(); V_Previous_Response = V_Current_Response; V_Current_Response = "Different"; elseif (D_Stimulus_Data.type() == stimulus_incorrect) then E_Log_Response.set_event_code("Similar"); T_Log_Response.present(); V_Previous_Response = V_Current_Response; V_Current_Response = "Same"; elseif (D_Stimulus_Data.type() == stimulus_miss) then E_Log_Response.set_event_code("Timeout"); T_Log_Response.present(); end; /***************** Task Ends **********************/ T_Blank_Screen.present(); if (V_Current_Response == "Different" && V_Previous_Response != "Different") then # Do the same trial again # No change of Direction # Do nothing...That is, present the same combination again without changes; elseif (V_Current_Response == "Different" && V_Previous_Response == "Different") then # We've played the same set of reference+stimulus two times, and the participant answered that they are different both times. # Now we need to DECREMENT the stimulus sequence once and play the new combination. # That is, change of direction ... down. # Increment the change of direction counter only if the previous change of direction was caused by a different response. # The idea is, we only increment the counter for changes of directions (i.e., caused by different responses). # Changes in the same direction don't count...in that case, don't do anything with the counter; (but not also reset it....untlike the longstaircase version). if (V_Previous_Change_of_Direction_Trigger != V_Current_Response) then V_Change_of_Direction_Counter = V_Change_of_Direction_Counter + 1; # Long-Staircase version #else # V_Change_of_Direction_Counter = 1; end; V_Previous_Change_of_Direction_Trigger = "Different"; if (V_Stimulus_Level <= V_Min_Level) then # We have reached the lowest extreme...we cannot go down any further! # So we set the flag to end the block. V_Finish_Block = true; else V_Stimulus_Level = V_Stimulus_Level - V_Decrement_Value_Before_First_Increment; # Will be reset to 1 the first time participant presses 'Same'. V_Auditory_Stimulus = V_Melody + string(V_Stimulus_Level); Wav_Auditory_Stimulus.set_filename(V_Auditory_Stimulus + ".wav"); Wav_Auditory_Stimulus.load(); E_Auditory_Stimulus.set_event_code(V_Auditory_Stimulus + ".wav"); end; V_Current_Response = " "; # Reset this, because, when Different is also pressed the next time, V_Previous_Response = " "; # we should not land here, for every time different is pressed, the same tone has to be played twice! elseif (V_Current_Response == "Same") then # We don't need to play the same combination again. # Instead, we need to INCREMENT the stimulus sequence once and play the new combination. # That is, change of direction ... up. # If 'Same' is pressed, then we are going to increment the tone. # And as soon as the first increment happens, from the next time, # the decrement should always be 1. So reset V_Decrement_Value_Before_First_Increment = 1; if (V_Decrement_Value_Before_First_Increment > 1) then V_Decrement_Value_Before_First_Increment = 1; end; # Increment the change of direction counter only if the previous change of direction was caused by a different response. # The idea is, we only increment the counter for Consecutive changes of directions (i.e., caused by different responses). # Changes in the same direction don't count..., don't do anything with the counter; (but not also reset it....untlike the longstaircase version). if (V_Previous_Change_of_Direction_Trigger != V_Current_Response) then V_Change_of_Direction_Counter = V_Change_of_Direction_Counter + 1; # Long-Staircase version #else # V_Change_of_Direction_Counter = 1; end; V_Previous_Change_of_Direction_Trigger = "Same"; if (V_Stimulus_Level == V_Max_Level) then # We have reached the highest extreme...we cannot go up any further! # So we set the flag to end the block. V_Finish_Block = true; else V_Stimulus_Level = V_Stimulus_Level + 1; V_Auditory_Stimulus = V_Melody + string(V_Stimulus_Level); Wav_Auditory_Stimulus.set_filename(V_Auditory_Stimulus + ".wav"); Wav_Auditory_Stimulus.load(); E_Auditory_Stimulus.set_event_code(V_Auditory_Stimulus + ".wav"); end; end; if V_Change_of_Direction_Counter > V_Changes_Needed_To_End_Staircase then V_Finish_Block = true; end; # Go to the Next Trial V_Current_Trial = V_Current_Trial + 1; #=========== # End Loop 2 #=========== end; /*** End Loop 2 for Trials ***/ #### Specific for presenting Auditory Stimuli ------------------------------- # Unload all memory occupiers such as wavefile stimuli. Wav_Auditory_Reference.unload(); Wav_Auditory_Stimulus.unload(); #### # Go to the Next Block V_Current_Block = V_Current_Block + 1; #================ # End Main Loop 1 #================ end; /*** End Main Loop 1 for Blocks ***/ # Close all the open files F_Session_List.close(); # Finish off the session!!! T_End_Thanks.present();