diff --git a/lib/+artoa/+controller/+track/+parameter/inputFloatOffsetBegin.m b/lib/+artoa/+controller/+track/+parameter/inputFloatOffsetBegin.m
deleted file mode 100644
index a17d6914a637032f4d87d96fc6363e687b96c85f..0000000000000000000000000000000000000000
--- a/lib/+artoa/+controller/+track/+parameter/inputFloatOffsetBegin.m
+++ /dev/null
@@ -1,13 +0,0 @@
-function [newValue] = inputFloatOffsetBegin(~, ~)
-%INPUTFLOATOFFSETBEGIN Summary of this function goes here
-%   Detailed explanation goes here
-
-global artoaGui artoaWorkspace;
-
-newValue = artoaGui.trackParameter.inputFloatOffsetBegin.String;
-
-artoaWorkspace.trackParameter.floatOffsetBegin = str2double(newValue);
-
-
-end
-
diff --git a/lib/+artoa/+controller/+track/+parameter/inputFloatOffsetEnd.m b/lib/+artoa/+controller/+track/+parameter/inputFloatOffsetEnd.m
deleted file mode 100644
index 029cfa0f7679dab212ff6cc92526eb9f7a1093d7..0000000000000000000000000000000000000000
--- a/lib/+artoa/+controller/+track/+parameter/inputFloatOffsetEnd.m
+++ /dev/null
@@ -1,13 +0,0 @@
-function [newValue] = inputFloatOffsetEnd(~, ~)
-%INPUTFLOATOFFSETBEGIN Summary of this function goes here
-%   Detailed explanation goes here
-
-global artoaGui artoaWorkspace;
-
-newValue = artoaGui.trackParameter.inputFloatOffsetEnd.String;
-
-artoaWorkspace.trackParameter.floatOffsetEnd = str2double(newValue);
-
-
-end
-
diff --git a/lib/+artoa/+controller/+track/+parameter/open.m b/lib/+artoa/+controller/+track/+parameter/open.m
index aab05a93a2620a82ca161b0b46d10ef470aeb2f0..2be37ac6f05ae92601649beba8dd75c9b74cf830 100644
--- a/lib/+artoa/+controller/+track/+parameter/open.m
+++ b/lib/+artoa/+controller/+track/+parameter/open.m
@@ -25,14 +25,11 @@ callbacks.tableSoundSourceCombinationsSelection = @artoa.controller.track.parame
 callbacks.tableSoundSourceCombinationsEdit = @artoa.controller.track.parameter.tableSoundsourceCombinationsEdit;
 callbacks.tableSoundSourceOffsetsEdit = @artoa.controller.track.parameter.tableSoundsourceOffsetsEdit;
 callbacks.buttonTrack = @artoa.controller.track.run;
-callbacks.buttonQuickTrack = '';
 callbacks.buttonAddCombination = @artoa.controller.track.parameter.addSoundsourceCombination;
 callbacks.buttonAddCombinationAbove = @artoa.controller.track.parameter.addSoundsourceCombinationAbove;
 callbacks.buttonDuplicateCombination = @artoa.controller.track.parameter.duplicateSoundsourceCombination;
 callbacks.buttonRemoveCombination = @artoa.controller.track.parameter.removeSoundsourceCombination;
 callbacks.buttonResetAllCombinations = @artoa.controller.track.parameter.resetSoundsourceCombinations;
-callbacks.inputFloatOffsetBegin = @artoa.controller.track.parameter.inputFloatOffsetBegin;
-callbacks.inputFloatOffsetEnd = @artoa.controller.track.parameter.inputFloatOffsetEnd;
 
 %% Open the gui
 artoa.gui.track.parameter( ...
@@ -42,16 +39,6 @@ artoa.gui.track.parameter( ...
     artoaWorkspace.defaults.soundspeedMethods ...
 );
 
-%% Get sources with applied toa
-soundsourcesWithAppliedToa = artoa.controller.getSoundsourcesWithAppliedToa();
-
-%% Setup sound source offsets table
-% initialize sound source offsets
-artoaGui.trackParameter.tableSoundSourceOffsets.RowName = fieldnames( ...
-    soundsourcesWithAppliedToa ...
-);
-
-
 %% Create workspace variables
 if ~isfield(artoaWorkspace, 'trackParameter')
     artoaWorkspace.trackParameter = struct();
@@ -64,11 +51,8 @@ if ~isfield(artoaWorkspace, 'trackParameter')
     artoaGui.trackParameter.tableSoundSourceCombinations.Data = artoa.controller.track.parameter.getDefaultCombinationCell();
     
     % initialize sound source offsets
-    artoaGui.trackParameter.tableSoundSourceOffsets.Data(1:length(artoaGui.trackParameter.tableSoundSourceOffsets.RowName), 1) = {0};
-    artoaWorkspace.trackParameter.soundsourceOffsets = artoa.soundsources.createOffsetsStruct( ...
-        artoaGui.trackParameter.tableSoundSourceOffsets.RowName, ...
-        artoaGui.trackParameter.tableSoundSourceOffsets.Data ...
-    );
+    artoaWorkspace.trackParameter.soundsourceOffsets = ...
+        artoa.offsets.generateOffsetTable(artoa.controller.getSoundsourcesWithAppliedToa());
     
     % initialize settings
     availableCallbacks = { ...
@@ -78,11 +62,8 @@ if ~isfield(artoaWorkspace, 'trackParameter')
         'comboboxSoundspeedMethod', ...
         'checkboxPlotResiduals', ...
         'inputOutputInterpolationInterval', ...
-        'inputGapSize', ...
-        'tableSoundSourceOffsetsEdit', ...
-        'tableSoundSourceCombinationsEdit', ...
-        'inputFloatOffsetBegin', ...
-        'inputFloatOffsetEnd' ...
+        'inputGapSize', ...'tableSoundSourceOffsetsEdit', ...
+        'tableSoundSourceCombinationsEdit' ...
     };
 
     for i = 1:length(availableCallbacks)
diff --git a/lib/+artoa/+controller/+track/+parameter/tableSoundsourceOffsetsEdit.m b/lib/+artoa/+controller/+track/+parameter/tableSoundsourceOffsetsEdit.m
index 86d229a5df8bc2e5d586104e4b15277e4c126551..1a747cf12892180555bf2381f65af51de1734c38 100644
--- a/lib/+artoa/+controller/+track/+parameter/tableSoundsourceOffsetsEdit.m
+++ b/lib/+artoa/+controller/+track/+parameter/tableSoundsourceOffsetsEdit.m
@@ -6,10 +6,7 @@ function [] = tableSoundsourceOffsetsEdit(~, ~)
 global artoaGui artoaWorkspace;
 
 %% Save to workspace
-artoaWorkspace.trackParameter.soundsourceOffsets = artoa.soundsources.createOffsetsStruct( ...
-    artoaGui.trackParameter.tableSoundSourceOffsets.RowName, ...
-    artoaGui.trackParameter.tableSoundSourceOffsets.Data ...
-);
+artoaWorkspace.trackParameter.soundsourceOffsets(:, :) = artoaGui.trackParameter.tableSoundSourceOffsets.Data;
 
 end
 
diff --git a/lib/+artoa/+controller/+track/+parameter/updateGui.m b/lib/+artoa/+controller/+track/+parameter/updateGui.m
index cf03a6b6c10c5ba661710431ccc6b16f1fc03681..b41d006b5e35677bfabbb16c5447cfed4dd7e9c6 100644
--- a/lib/+artoa/+controller/+track/+parameter/updateGui.m
+++ b/lib/+artoa/+controller/+track/+parameter/updateGui.m
@@ -36,17 +36,13 @@ for i = 1:length(fieldNames)
         case 'gapSize'
             artoaGui.trackParameter.inputGapSize.String = currentValue;
         case 'soundsourceOffsets'
-            artoaGui.trackParameter.tableSoundSourceOffsets.Data = ...
-                artoa.soundsources.createOffsetsCell( ...
-                    currentValue, ...
-                    artoaGui.trackParameter.tableSoundSourceOffsets.RowName ...
-                );
+            artoaGui.trackParameter.tableSoundSourceOffsets.Data = table2cell( ...
+                currentValue ...
+            );
+            artoaGui.trackParameter.tableSoundSourceOffsets.RowName = currentValue.Properties.RowNames;
+            artoaGui.trackParameter.tableSoundSourceOffsets.ColumnName = currentValue.Properties.VariableNames;
         case 'soundsourceCombinations'
             artoaGui.trackParameter.tableSoundSourceCombinations.Data = artoa.soundsources.createCombinationsCell(currentValue);
-        case 'floatOffsetBegin'
-            artoaGui.trackParameter.inputFloatOffsetBegin.String = currentValue;
-        case 'floatOffsetEnd'
-            artoaGui.trackParameter.inputFloatOffsetEnd.String = currentValue;
     end
 end
 
diff --git a/lib/+artoa/+float/calculateTrajectory.m b/lib/+artoa/+float/calculateTrajectory.m
index 328228bc2057785be7ca10f4ce8e38b8317aee2c..9db1b260654b4520e3fc505ff7c36cc64f6e5ba4 100644
--- a/lib/+artoa/+float/calculateTrajectory.m
+++ b/lib/+artoa/+float/calculateTrajectory.m
@@ -40,8 +40,8 @@ uniqueToaDates = unique(pToaData.toaDate);
 %% Add float drift to TOA
 pToaData = artoa.data.addFloatDrift( ...
         pToaData, ...
-        pTrackingParameter.floatOffsetBegin, ...
-        pTrackingParameter.floatOffsetEnd ...
+        pTrackingParameter.soundsourceOffsets{'Float', 'Begin'}, ...
+        pTrackingParameter.soundsourceOffsets{'Float', 'End'} ...
 );
 
 %% Initialize return variables
@@ -113,8 +113,8 @@ for i = 1:length(involvedSoundsources)
     
     % subtract offset (corrective value) of sound source
     soundsourceOffsetCorrectiveValue = ...
-        pTrackingParameter.soundsourceOffsets.(currentSoundsource.sourcename);
-    currentToa = currentToa - soundsourceOffsetCorrectiveValue(1);
+        pTrackingParameter.soundsourceOffsets{currentSoundsource.sourcename, 'Begin'};
+    currentToa = currentToa - soundsourceOffsetCorrectiveValue;
         
     % interpolate toa data
     [ ...
diff --git a/lib/+artoa/+gui/+track/parameter.m b/lib/+artoa/+gui/+track/parameter.m
index ffba8177b96320c2fdfd5933c0f14432e2bc03f7..4f6638043cc329b4daae93ea38419e44a1218a1b 100644
--- a/lib/+artoa/+gui/+track/parameter.m
+++ b/lib/+artoa/+gui/+track/parameter.m
@@ -25,9 +25,7 @@ availableCallbacks = { ...
     'buttonAddCombinationAbove', ...
     'buttonDuplicateCombination', ...
     'buttonRemoveCombination', ...
-    'buttonResetAllCombinations', ...
-    'inputFloatOffsetBegin', ...
-    'inputFloatOffsetEnd' ...
+    'buttonResetAllCombinations' ...
 };
 
 for i = 1:length(availableCallbacks) % check if a callback is undefined
@@ -203,20 +201,14 @@ clear columns;
 
 %% Sound source offset table
 
-columns = { ...
-    'Offset'
-};
 artoaGui.trackParameter.tableSoundSourceOffsets = uitable( ...
     artoaGui.figures.trackParameter, ...
     'Units', 'normalized', ...
-    'Position', [left, 0.1, width, 0.27], ...
-    'Data', cell(1, length(columns)), ...
-    'ColumnName', columns, ...
+    'Position', [left, 0.1, width * 2, 0.27], ...
     'ColumnEditable', true, ...
     'CellSelectionCallback', pCallbacks.tableSoundSourceOffsetsSelection,... %@(app,event) disp(num2str(event.Indices)) ...
     'CellEditCallback', pCallbacks.tableSoundSourceOffsetsEdit ...
 );
-clear columns;
 
 %% Track buttons frame
 
@@ -237,7 +229,6 @@ artoaGui.trackParameter.buttonTrack = uicontrol( ...
     'CallBack', pCallbacks.buttonTrack ...
 );
 
-
 %% Combination buttons frame
 
 artoaGui.trackParameter.frameCombinationButtons = uipanel( ...
@@ -298,54 +289,5 @@ artoaGui.trackParameter.buttonResetAllCombinations = uicontrol( ...
     'CallBack', pCallbacks.buttonResetAllCombinations ...
 );
 
-%% Float offset frame
-
-artoaGui.trackParameter.frameFloatOffsets = uipanel( ...
-    'Title', 'Float offsets', ...
-    'Units', 'normalized', ...
-    'BackgroundColor', 'white', ...
-    'Position', [(2*left + width) .1 width .27] ...
-);
-
-artoaGui.trackParameter.textFloatOffsetBegin = uicontrol( ...
-    'Parent', artoaGui.trackParameter.frameFloatOffsets, ...
-    'String', 'Begin [s]', ...
-    'Style', 'text', ...
-    'FontSize', 8, ...
-    'Units', 'normalized', ...
-    'Position', [left .6 .3 .2], ...
-    'CallBack', '' ...
-);
-
-artoaGui.trackParameter.inputFloatOffsetBegin = uicontrol( ...
-    'Parent', artoaGui.trackParameter.frameFloatOffsets, ...
-    'String', '0', ...
-    'Style', 'edit', ...
-    'FontSize', 8, ...
-    'Units', 'normalized', ...
-    'Position', [(.5-left) .6 .3 .2], ...
-    'CallBack', pCallbacks.inputFloatOffsetBegin ...
-);
-
-artoaGui.trackParameter.textFloatOffsetEnd = uicontrol( ...
-    'Parent', artoaGui.trackParameter.frameFloatOffsets, ...
-    'String', 'End [s]', ...
-    'Style', 'text', ...
-    'FontSize', 8, ...
-    'Units', 'normalized', ...
-    'Position', [left .2 .3 .2], ...
-    'CallBack', '' ...
-);
-
-artoaGui.trackParameter.inputFloatOffsetEnd = uicontrol( ...
-    'Parent', artoaGui.trackParameter.frameFloatOffsets, ...
-    'String', '0', ...
-    'Style', 'edit', ...
-    'FontSize', 8, ...
-    'Units', 'normalized', ...
-    'Position', [(.5-left) .2 .3 .2], ...
-    'CallBack', pCallbacks.inputFloatOffsetEnd ...
-);
-
 end
 
diff --git a/lib/+artoa/+offsets/addSoundsource.m b/lib/+artoa/+offsets/addSoundsource.m
new file mode 100644
index 0000000000000000000000000000000000000000..0c07fcdf08ad352ea02d5906c7145a3b4bb23f42
--- /dev/null
+++ b/lib/+artoa/+offsets/addSoundsource.m
@@ -0,0 +1,21 @@
+function [offsetsTable] = addSoundsource(pOffsetsTable, pSoundsource)
+%ADDROW Summary of this function goes here
+%   Detailed explanation goes here
+
+%% Initialize return variable
+offsetsTable = pOffsetsTable;
+
+%% Check if soundsource already exists
+if any(strcmp(pSoundsource.sourcename, pOffsetsTable.Properties.RowNames))
+    return;
+end
+
+%% Add variable
+offsetsTable(end + 1, :) = artoa.offsets.getDefaultRowValues();
+offsetsTable.Properties.RowNames{end} = pSoundsource.sourcename;
+
+%% Sort rows
+offsetsTable = sortrows(offsetsTable, 'RowNames');
+
+end
+
diff --git a/lib/+artoa/+offsets/generateOffsetTable.m b/lib/+artoa/+offsets/generateOffsetTable.m
new file mode 100644
index 0000000000000000000000000000000000000000..387c45b1d72c347b4b24e8dbcb59c6c605c4ea99
--- /dev/null
+++ b/lib/+artoa/+offsets/generateOffsetTable.m
@@ -0,0 +1,34 @@
+function [offsetTable] = generateOffsetTable(pSoundsources)
+%GETDEFAULTOFFSETTABLE Summary of this function goes here
+%   Detailed explanation goes here
+
+%% Initialize return variable
+offsetTable = cell2table( ...
+    artoa.offsets.getDefaultRowValues(), ...
+    'VariableNames', artoa.offsets.getDefaultVariableNames() ...
+);
+
+%% Setup rows
+offsetTable.Properties.RowNames(1) = {'Float'};
+
+if nargin ~= 1
+    return;
+end
+
+if iscell(pSoundsources)
+    for i = 1:length(pSoundsources)
+        offsetTable(i + 1, :) = artoa.offsets.getDefaultRowValues();
+        offsetTable.Properties.RowNames(i + 1) = {pSoundsources{i}.sourcename};
+    end
+end
+
+if isstruct(pSoundsources)
+    fnames = fieldnames(pSoundsources);
+    for i = 1:length(fnames)
+        offsetTable(i + 1, :) = artoa.offsets.getDefaultRowValues();
+        offsetTable.Properties.RowNames(i + 1) = {pSoundsources.(fnames{i}).sourcename};
+    end
+end
+
+end
+
diff --git a/lib/+artoa/+offsets/getDefaultRowValues.m b/lib/+artoa/+offsets/getDefaultRowValues.m
new file mode 100644
index 0000000000000000000000000000000000000000..d30dde7a4717b71d9a06537a82e5c17f59eda18c
--- /dev/null
+++ b/lib/+artoa/+offsets/getDefaultRowValues.m
@@ -0,0 +1,10 @@
+function [defaultRow] = getDefaultRowValues()
+%GETDEFAULTROW Summary of this function goes here
+%   Detailed explanation goes here
+
+defaultOffset = 0;
+defaultUseOffset = false;
+defaultRow = {defaultOffset, defaultUseOffset, defaultOffset, defaultUseOffset};
+
+end
+
diff --git a/lib/+artoa/+offsets/getDefaultVariableNames.m b/lib/+artoa/+offsets/getDefaultVariableNames.m
new file mode 100644
index 0000000000000000000000000000000000000000..d68a7679e8f287789e07f1731f1ae9109b855fa0
--- /dev/null
+++ b/lib/+artoa/+offsets/getDefaultVariableNames.m
@@ -0,0 +1,14 @@
+function [defaultVariableNames] = getDefaultVariableNames()
+%GETDEFAULTVARIABLENAMES Summary of this function goes here
+%   Detailed explanation goes here
+
+defaultVariableNames = { ...
+    'Begin', ...
+    'UseBegin', ...
+    'End', ...
+    'UseEnd' ...
+};
+
+
+end
+
diff --git a/lib/+artoa/+offsets/removeSoundsource.m b/lib/+artoa/+offsets/removeSoundsource.m
new file mode 100644
index 0000000000000000000000000000000000000000..0f74f9cdec11635b76ef39adb49994163d5fd685
--- /dev/null
+++ b/lib/+artoa/+offsets/removeSoundsource.m
@@ -0,0 +1,20 @@
+function [offsetsTable] = removeSoundsource(pOffsetsTable, pSoundsourceName)
+%ADDROW Summary of this function goes here
+%   Detailed explanation goes here
+
+%% Initialize return variable
+offsetsTable = pOffsetsTable;
+
+%% Check if soundsource exists
+if ~any(strcmp(pSoundsourceName, pOffsetsTable.Properties.RowNames))
+    return;
+end
+
+%% Remove from table
+offsetsTable(pSoundsourceName, :) = [];
+
+%% Sort rows
+offsetsTable = sortrows(offsetsTable, 'RowNames');
+
+end
+
diff --git a/lib/+artoa/+soundsources/createOffsetsCell.m b/lib/+artoa/+soundsources/createOffsetsCell.m
deleted file mode 100644
index 85ee06c6a8a81474c7b54c5354f1836e6235e9db..0000000000000000000000000000000000000000
--- a/lib/+artoa/+soundsources/createOffsetsCell.m
+++ /dev/null
@@ -1,21 +0,0 @@
-function [offsetsCell] = createOffsetsCell(pOffsetsStruct, pTableRowNames)
-%CREATEOFFSETSCELL Summary of this function goes here
-%   Detailed explanation goes here
-
-%% Initialize return variable
-offsetsCell = cell(length(pTableRowNames), 1);
-
-%% Create cell
-
-for i = 1:length(pTableRowNames)
-    currentRowName = pTableRowNames{i};
-    if artoa.data.hasMember(pOffsetsStruct, {currentRowName})
-        value = pOffsetsStruct.(currentRowName);
-    else
-        value = 0;
-    end
-    offsetsCell{i} = value;
-end
-
-end
-
diff --git a/lib/+artoa/+soundsources/createOffsetsStruct.m b/lib/+artoa/+soundsources/createOffsetsStruct.m
deleted file mode 100644
index 905254a3c7393c6776ceef67c850e9daf2324732..0000000000000000000000000000000000000000
--- a/lib/+artoa/+soundsources/createOffsetsStruct.m
+++ /dev/null
@@ -1,16 +0,0 @@
-function [offsetStruct] = createOffsetsStruct(pOffsetTableRowNames, pOffsetTableData)
-%CREATEOFFSETSSTRUCT Summary of this function goes here
-%   Detailed explanation goes here
-
-%% Initialize return variable
-offsetStruct = struct();
-
-%% Convert to struct
-rowNames = pOffsetTableRowNames;
-
-for i = 1:length(rowNames)
-    offsetStruct.(rowNames{i}) = pOffsetTableData{i, 1};
-end
-
-end
-