function PsychLSLAudioTimingTest(deviceid, latbias)
% PsychAudioLSLTimingTest([, deviceid=-1][, latbias=0]
% Written by Matthew Grivich, SCCN/UCSD

% Derived from PsychPortAudioTimingTest
% (http://docs.psychtoolbox.org/PsychPortAudioTimingTest)
%
% Test script for sound onset timing reliability and sound onset
% latency of the PsychPortAudio sound driver. LSL events have been added
% to measure synchronization.
%
% This script configures the driver for low latency and high timing
% precision, then executes ten trials where it tries to emit a beep sound,


%
% Optional parameters:
%

% 'deviceid'   = -1 -- Auto-select optimal device (Default).
%             >=0   -- Select specified output device. See
%                      PsychPortAudio('GetDevices') for a list of devices.
%
% 'latbias'    = Hardware inherent latency bias. To be determined by
%                measurement - allows to PA to correct for it if provided.
%                Unit is seconds. Defaults to zero.
%


% Initialize driver, request low-latency preinit:
InitializePsychSound(1);

if ~IsLinux
  PsychPortAudio('Verbosity', 10);
end

% Force GetSecs and WaitSecs into memory to avoid latency later on:
GetSecs;
WaitSecs(0.1);




% Default to auto-selected default output device if none specified:
if nargin < 1 
   deviceid = [];
end

if isempty(deviceid)
    deviceid = -1;
end

if deviceid == -1
    fprintf('Will use auto-selected default output device. This is the system default output\n');
    fprintf('device in "normal" (=reliable but high latency) mode. In low-latency mode its the\n');
    fprintf('device with the lowest inherent latency on your system (as determined by some internal\n');
    fprintf('heuristic). If you are not satisfied with the results you may query the available devices\n');
    fprintf('yourself via a call to devs = PsychPortAudio(''GetDevices''); and provide the device index\n');
    fprintf('of a suitable device\n\n');
else
    fprintf('Selected the following output device (deviceid=%i) according to your spec:\n', deviceid);
    devs = PsychPortAudio('GetDevices');
    for idx = 1:length(devs)
        if devs(idx).DeviceIndex == deviceid
            break;
        end
    end
    disp(devs(idx));
end

% Request latency mode 2, which used to be the best one in our measurement:
% classes 3 and 4 didn't yield any improvements, sometimes they even caused
% problems.
reqlatencyclass = 2;

% Requested output frequency, may need adaptation on some audio-hw:
freq = 44100;       % Must set this. 96khz, 48khz, 44.1khz.
buffersize = 0;     % Pointless to set this. Auto-selected to be optimal.
suggestedLatencySecs = .015;


% Needs to determined via measurement once for each piece of audio
% hardware:
if nargin < 2 
   latbias = [];
end


%open lsl event outlet
lib = lsl_loadlib();
info = lsl_streaminfo(lib,'Psychophysics-Markers','Markers',1,0,'cf_string','uniquesourceid752186');
synchInfo = info.desc().append_child('synchronization');
synchInfo.append_child_value('offset_mean', '-.04902');
%TEST
disp('Opening an outlet...');
outlet = lsl_outlet(info); 


% Open audio device for low-latency output:
pahandle = PsychPortAudio('Open', deviceid, [], reqlatencyclass, freq, 2, buffersize, suggestedLatencySecs);

% Tell driver about hardwares inherent latency, determined via calibration
% once:
prelat = PsychPortAudio('LatencyBias', pahandle, latbias) 
postlat = PsychPortAudio('LatencyBias', pahandle) 

% Generate some beep sound 500 Hz, 0.5 secs, 50% amplitude:
mynoise(1,:) = 0.5 * MakeBeep(500, 0.5, freq);
mynoise(2,:) = mynoise(1,:);

% Fill buffer with data:
PsychPortAudio('FillBuffer', pahandle, mynoise);

% Setup display:
% screenid = max(Screen('Screens'));
% 
% win = Screen('OpenWindow', screenid, 0);


% Perform one warmup trial, to get the sound hardware fully up and running,
% performing whatever lazy initialization only happens at real first use.
% This "useless" warmup will allow for lower latency for start of playback
% during actual use of the audio driver in the real trials:
PsychPortAudio('Start', pahandle, 1, 0, 1);
PsychPortAudio('Stop', pahandle, 1);

% Ok, now the audio hardware is fully initialized and our driver is on
% hot-standby, ready to start playback of any sound with minimal latency.

% Wait for keypress.
KbStrokeWait;

% Realtime scheduling: Can be used if otherwise timing is not good enough.
% Priority(MaxPriority(win));

for i=1:10

   t1 = GetSecs(); 
   PsychPortAudio('Start', pahandle, 1, t1 + 0.050, 0); 
   outlet.push_sample({'tone'});
   

    % Spin-Wait until hw reports the first sample is played...
    offset = 0;
    while offset == 0
        status = PsychPortAudio('GetStatus', pahandle);
        offset = status.PositionSecs;
        plat = status.PredictedLatency;
       % fprintf('Predicted Latency: %6.6f msecs.\n', plat*1000);
        if offset>0
            break;
        end
        WaitSecs('YieldSecs', 0.001);
    end
    audio_onset = status.StartTime;

    fprintf('PortAudio expects audio offset  of %6.6f secs.\n', audio_onset-t1);

    % Stop playback:
    PsychPortAudio('Stop', pahandle, 1);

    % Wait a bit...
    WaitSecs(1+rand(1));
    
%     Screen('FillRect', win, 0);
%     Screen('Flip', win); 
    

end

Priority(0);
PsychPortAudio('Close');
Screen('CloseAll');
java.lang.System.gc();

return;
