diff --git a/VERSION b/VERSION
index 2989c6c763b6767154c80b6e3a0fa44d73a471f9..fefb598af8c98e1a2953068d56df3a81f968074b 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-283
\ No newline at end of file
+284
\ No newline at end of file
diff --git a/lib/+artoa/+controller/+edit/+offsets/buttonAppliedToNan.m b/lib/+artoa/+controller/+edit/+offsets/buttonAppliedToNan.m
index b1b4b7610be7416557187aeb5ecb2f1d768fdf44..63926fa53a5fc6a5a3a7b80339759aff6dfdafc7 100644
--- a/lib/+artoa/+controller/+edit/+offsets/buttonAppliedToNan.m
+++ b/lib/+artoa/+controller/+edit/+offsets/buttonAppliedToNan.m
@@ -11,8 +11,7 @@ artoa.controller.edit.offsets.saveAppliedState();
 
 artoaWorkspace.editOffsets.offsets{:, 'AppliedOffset'} = NaN;
 artoaWorkspace.editOffsets.offsets{:, 'AppliedDrift'} = NaN;
-
-artoaWorkspace.editOffsets.soundspeed.Applied(1) = NaN;
+artoaWorkspace.editOffsets.offsets{:, 'AppliedSoundspeed'} = NaN;
 
 %% Update GUI
 artoa.controller.edit.offsets.updateGui();
diff --git a/lib/+artoa/+controller/+edit/+offsets/buttonCalculateOffsets.m b/lib/+artoa/+controller/+edit/+offsets/buttonCalculateOffsets.m
index 5be402bf1fdb422a0f95c1e08724422198a996f0..0bfea9afae00ce84bafd9db9204f47cb32377b28 100644
--- a/lib/+artoa/+controller/+edit/+offsets/buttonCalculateOffsets.m
+++ b/lib/+artoa/+controller/+edit/+offsets/buttonCalculateOffsets.m
@@ -29,8 +29,7 @@ toaData.toa = artoaDataInput.toaData.toa;
     toaData, ...
     satData, ...
     artoa.data.getMember(artoaConfig, {'leapseconds'}), ...
-    artoaWorkspace.editOffsets, ...
-    artoa.controller.selectSoundspeed() ...
+    artoaWorkspace.editOffsets ...
 );
 
 %% Store offsets in table
diff --git a/lib/+artoa/+controller/+edit/+offsets/buttonCopySoundspeed.m b/lib/+artoa/+controller/+edit/+offsets/buttonCopySoundspeed.m
index 1b208500667134252f10ad6b34fca467ab8817ff..beb934fbce11c4711b20083ecd6bd0833e624535 100644
--- a/lib/+artoa/+controller/+edit/+offsets/buttonCopySoundspeed.m
+++ b/lib/+artoa/+controller/+edit/+offsets/buttonCopySoundspeed.m
@@ -8,12 +8,12 @@ global artoaGui artoaWorkspace;
 index = artoaGui.editOffsets.comboboxSoundvelocityToApplied.Value;
 
 %% Soundspeed 
-if strcmp(artoaGui.editOffsets.comboboxSoundvelocityToApplied.String{index}, 'Measured')
-    artoaWorkspace.editOffsets.soundspeed.Applied(1) = artoaWorkspace.editOffsets.soundspeed.Measured(1);
-end
-if strcmp(artoaGui.editOffsets.comboboxSoundvelocityToApplied.String{index}, 'Optimum')
-    artoaWorkspace.editOffsets.soundspeed.Applied(1) = artoaWorkspace.editOffsets.soundspeed.Optimum(1);
-end    
+
+artoaWorkspace.editOffsets.offsets{:, 'AppliedSoundspeed'} = ...
+    artoaWorkspace.editOffsets.offsets{ ...
+        :, ...
+        [artoaGui.editOffsets.comboboxSoundvelocityToApplied.String{index} 'Soundspeed'] ...
+        };
     
 %% Update GUI
 artoa.controller.edit.offsets.updateGui();
diff --git a/lib/+artoa/+controller/+edit/+offsets/buttonUndoLastCopy.m b/lib/+artoa/+controller/+edit/+offsets/buttonUndoLastCopy.m
index f1359c2a5fd817a7957a76c671cd755ecd5ad22a..c29a709c0886ae8eeb5a95e6e49a072ff9dd15d3 100644
--- a/lib/+artoa/+controller/+edit/+offsets/buttonUndoLastCopy.m
+++ b/lib/+artoa/+controller/+edit/+offsets/buttonUndoLastCopy.m
@@ -14,15 +14,7 @@ end
 
 artoaWorkspace.editOffsets.offsets.AppliedOffset = lastValues.AppliedOffset;
 artoaWorkspace.editOffsets.offsets.AppliedDrift = lastValues.AppliedDrift;
-
-%% Restore soundspeed
-lastSoundspeed = artoa.data.getMember(artoaWorkspace, {'editOffsets', 'undoCopySoundspeed'}, false);
-
-if islogical(lastSoundspeed)
-    return;
-end
-
-artoaWorkspace.editOffsets.soundspeed.Applied(1) = lastSoundspeed(1);
+artoaWorkspace.editOffsets.offsets.AppliedSoundspeed = lastValues.AppliedSoundspeed;
 
 artoa.controller.edit.offsets.updateGui();
 
diff --git a/lib/+artoa/+controller/+edit/+offsets/initialize.m b/lib/+artoa/+controller/+edit/+offsets/initialize.m
index 79d4986402915a97cb408e7348db742ce80e50b4..7bd49322bfe4e46114ec0cfc4e939af25d576ce3 100644
--- a/lib/+artoa/+controller/+edit/+offsets/initialize.m
+++ b/lib/+artoa/+controller/+edit/+offsets/initialize.m
@@ -2,35 +2,12 @@ function [] = initialize(pForceOverwrite)
 %INITIALIZE Summary of this function goes here
 %   Detailed explanation goes here
 
-global artoaGui;
-
 %% Initialize default variables
 if ~exist('pForceOverwrite', 'var')
     pForceOverwrite = false;
 end
 
 %% Initialize
-callbacks = artoaGui.callbacks.main;
-
-availableCallbacks = { ...
-    'tableSoundsourceOffsetsSelect', ...
-    'tableSoundsourceOffsetsEdit', ...
-    'tableSoundspeedEdit', ...
-    'buttonCalculateOffsets', ...
-    'checkboxUseOffsets', ...
-    'buttonCopyFromOptimum', ...
-    'buttonCopyFromMeasured', ...
-    'buttonAppliedToNan', ...
-    'buttonUndoLastCopy' ...
-};
-
-for i = 1:length(availableCallbacks) % check if a callback is undefined
-    if ~isfield(callbacks, availableCallbacks{i})
-        callbacks.(availableCallbacks{i}) = @(~, ~) false;
-    end
-end
-
-artoa.controller.edit.offsets.initializeSoundspeedTable();
 artoa.controller.edit.offsets.updateWorkspaceOffsetsTable(pForceOverwrite);
 
 end
diff --git a/lib/+artoa/+controller/+edit/+offsets/initializeSoundspeedTable.m b/lib/+artoa/+controller/+edit/+offsets/initializeSoundspeedTable.m
deleted file mode 100644
index 5e6add0f333c695abd0310a82de161a20c91160b..0000000000000000000000000000000000000000
--- a/lib/+artoa/+controller/+edit/+offsets/initializeSoundspeedTable.m
+++ /dev/null
@@ -1,37 +0,0 @@
-function [] = initializeSoundspeedTable()
-%INITIALIZESOUNDSPEEDTABLE Summary of this function goes here
-%   Detailed explanation goes here
-
-global artoaWorkspace;
-
-
-%% Check if edit offsets is ready
-if ~artoa.data.hasMember(artoaWorkspace, {'editOffsets'})
-    return;
-end
-
-%% Initialize soundspeed table for calculations
-artoaWorkspace.editOffsets.soundspeed = table();
-
-if artoa.data.hasMember(artoaWorkspace, {'trackParameter', 'soundspeedMethodString'})
-    method = artoaWorkspace.trackParameter.soundspeedMethodString;
-else
-    method = 'del grosso';
-end
-
-artoaWorkspace.editOffsets.soundspeed{1, :} = [ ...
-    artoa.data.calculateSoundVelocity( ...
-        artoaWorkspace.temperature(artoaWorkspace.statusTemperature == 1), ...
-        artoaWorkspace.pressure(artoaWorkspace.statusPressure == 1), ...
-        method ...
-    ) ...
-    NaN ...
-    NaN ...
-];
-
-artoaWorkspace.editOffsets.soundspeed.Properties.RowNames = {'Soundspeed'};
-artoaWorkspace.editOffsets.soundspeed.Properties.VariableNames = ...
-    {'Measured', 'Optimum', 'Applied'};
-
-end
-
diff --git a/lib/+artoa/+controller/+edit/+offsets/saveAppliedState.m b/lib/+artoa/+controller/+edit/+offsets/saveAppliedState.m
index 60e7906d6ce71f4830a09bffaac0e5cbf617d25f..7ac6501a13b2aab84b1ab13764e989e22080721b 100644
--- a/lib/+artoa/+controller/+edit/+offsets/saveAppliedState.m
+++ b/lib/+artoa/+controller/+edit/+offsets/saveAppliedState.m
@@ -5,10 +5,7 @@ function [] = saveAppliedState()
 global artoaWorkspace;
 
 artoaWorkspace.editOffsets.undoCopyValues = ...
-    artoaWorkspace.editOffsets.offsets(:, {'AppliedOffset', 'AppliedDrift'});
-
-artoaWorkspace.editOffsets.undoCopySoundspeed = ...
-    artoaWorkspace.editOffsets.soundspeed.Applied(1);
+    artoaWorkspace.editOffsets.offsets(:, {'AppliedOffset', 'AppliedDrift', 'AppliedSoundspeed'});
 
 end
 
diff --git a/lib/+artoa/+controller/+edit/+offsets/saveOptimumToWorkspace.m b/lib/+artoa/+controller/+edit/+offsets/saveOptimumToWorkspace.m
index f041ee88d9f6f2e52607b9be7dc10d03a74193f6..14258c3938718feef7571de2aa13372f7a84b94f 100644
--- a/lib/+artoa/+controller/+edit/+offsets/saveOptimumToWorkspace.m
+++ b/lib/+artoa/+controller/+edit/+offsets/saveOptimumToWorkspace.m
@@ -18,11 +18,12 @@ end
 %% Initialize constants
 optimumColumnOffsetName = 'OptimumTotalOffset';
 optimumColumnDriftName = 'OptimumTotalDrift';
+optimumColumnSoundspeedName = 'OptimumSoundspeed';
 
 %% Reset all to NaN
 offsets{:, optimumColumnOffsetName} = NaN;
 offsets{:, optimumColumnDriftName} = NaN;
-artoaWorkspace.editOffsets.soundspeed{'Soundspeed', 'Optimum'} = NaN;
+offsets{:, optimumColumnSoundspeedName} = NaN;
 
 %% Store values
 varNames = X.Properties.RowNames;
@@ -30,7 +31,7 @@ for i = 1:length(varNames)
     % check if it is soundspeed
     if strcmp(varNames{i}, 'Soundspeed')
         % [km/s] * 1000
-        artoaWorkspace.editOffsets.soundspeed{'Soundspeed', 'Optimum'} = X{varNames{i}, 'Value'} * 1000;
+        artoaWorkspace.editOffsets.offsets{:, optimumColumnSoundspeedName} = X{varNames{i}, 'Value'} * 1000;
         continue;
     end
     % check if it is offset
diff --git a/lib/+artoa/+controller/+edit/+offsets/tableSoundsourceOffsetsEdit.m b/lib/+artoa/+controller/+edit/+offsets/tableSoundsourceOffsetsEdit.m
index e6a56e7e02aa3d4c2b82c26e0839e16373ebd09e..9a912d5eb5e528bb2448376b159cb4dfddca972a 100644
--- a/lib/+artoa/+controller/+edit/+offsets/tableSoundsourceOffsetsEdit.m
+++ b/lib/+artoa/+controller/+edit/+offsets/tableSoundsourceOffsetsEdit.m
@@ -15,7 +15,7 @@ catch
 end
 
 %% Check if the column that has been edited is locked
-if 1 <= selectedColumn & selectedColumn <= 9
+if (1 <= selectedColumn & selectedColumn < 9) | (10 <= selectedColumn & selectedColumn <= 13)
     artoa.controller.edit.offsets.updateGui();
     return;
 end
diff --git a/lib/+artoa/+controller/+edit/+offsets/tableSoundspeedEdit.m b/lib/+artoa/+controller/+edit/+offsets/tableSoundspeedEdit.m
deleted file mode 100644
index 79f44521ab0f3877e2e3da41377059d748965859..0000000000000000000000000000000000000000
--- a/lib/+artoa/+controller/+edit/+offsets/tableSoundspeedEdit.m
+++ /dev/null
@@ -1,31 +0,0 @@
-function [] = tableSoundspeedEdit(~, event)
-%TABLESOUNDSOURCEOFFSETSEDIT Summary of this function goes here
-%   Detailed explanation goes here
-
-
-global artoaGui artoaWorkspace;
-
-%% Get data
-try
-    selectedColumn = event.Indices(2);
-catch
-    selectedColumn = NaN;
-end
-
-%% Check if the column that has been edited is locked
-if 1 <= selectedColumn & selectedColumn <= 2
-    artoa.controller.edit.offsets.updateGui();
-    return;
-end
-
-if ~artoa.data.hasMember(artoaWorkspace, {'editOffsets', 'soundspeed'})
-    return;
-end
-
-%% Save to workspace
-artoaWorkspace.editOffsets.soundspeed(:, :) = artoaGui.editOffsets.tableSoundspeed.Data;
-
-%% Recalculate
-artoa.controller.edit.recalculateToaGpsAndPlot();
-
-end
diff --git a/lib/+artoa/+controller/+edit/+offsets/updateGui.m b/lib/+artoa/+controller/+edit/+offsets/updateGui.m
index 158b2c583d8bc1001d31fd8f8f00ec04cb4f2745..28def9e89ee6410ac79e5e0c134e3a75826b054d 100644
--- a/lib/+artoa/+controller/+edit/+offsets/updateGui.m
+++ b/lib/+artoa/+controller/+edit/+offsets/updateGui.m
@@ -16,16 +16,28 @@ for i = 1:length(fieldNames)
     switch fieldNames{i}
         case 'useOffsets'
             artoaGui.editOffsets.checkboxUseOffsets.Value = currentValue;
-        case 'soundspeed'
-            artoaGui.editOffsets.tableSoundspeed.Data = table2cell(currentValue);
-            artoaGui.editOffsets.tableSoundspeed.RowName = currentValue.Properties.RowNames;
-            artoaGui.editOffsets.tableSoundspeed.ColumnName = currentValue.Properties.VariableNames;
         case 'offsets'
             artoaGui.editOffsets.tableSoundsourceOffsets.Data = table2cell( ...
                 currentValue ...
             );
             artoaGui.editOffsets.tableSoundsourceOffsets.RowName = currentValue.Properties.RowNames;
-            artoaGui.editOffsets.tableSoundsourceOffsets.ColumnName = currentValue.Properties.VariableNames;
+            artoaGui.editOffsets.tableSoundsourceOffsets.ColumnName = { ...
+                '<html>Date<br>Start', ...
+                '<html>Offset<br>Start', ...
+                '<html>Date<br>End', ...
+                '<html>Offset<br>End', ...
+                'Drift', ...
+                '<html>Measured<br>Soundspeed', ...
+                '<html>Empirical<br>Soundspeed', ...
+                '<html>Optimum<br>Soundspeed', ...
+                '<html><b>Applied<br>Soundspeed', ...
+                '<html>Empirical<br>Offset', ...
+                '<html>Empirical<br>Drift', ...
+                '<html>Optimum<br>TotalOffset', ...
+                '<html>Optimum<br>TotalDrift', ...
+                '<html><b>Applied<br>Offset', ...
+                '<html><b>Applied<br>Drift' ...
+            };
     end
 end
 
diff --git a/lib/+artoa/+controller/+edit/+offsets/updateMeasuredSoundspeed.m b/lib/+artoa/+controller/+edit/+offsets/updateMeasuredSoundspeed.m
index 81975d7cdc7e135ea93a2f8926729676494bf9cf..9e2ab61a5bcdc032aba2e45ca0c003a03eaa8f31 100644
--- a/lib/+artoa/+controller/+edit/+offsets/updateMeasuredSoundspeed.m
+++ b/lib/+artoa/+controller/+edit/+offsets/updateMeasuredSoundspeed.m
@@ -10,7 +10,7 @@ else
     method = 'del grosso';
 end
 
-artoaWorkspace.editOffsets.soundspeed{1, 1} = ...
+artoaWorkspace.editOffsets.offsets{:, 'MeasuredSoundspeed'} = ...
     artoa.data.calculateSoundVelocity( ...
         artoaWorkspace.temperature(artoaWorkspace.statusTemperature == 1), ...
         artoaWorkspace.pressure(artoaWorkspace.statusPressure == 1), ...
diff --git a/lib/+artoa/+controller/+edit/+offsets/updateWorkspaceOffsetsTable.m b/lib/+artoa/+controller/+edit/+offsets/updateWorkspaceOffsetsTable.m
index 2271cadfea5afff651408743a42c74e1343dcc5e..131c5ca5fb61bc4692e0b93d844b308e9c17fecf 100644
--- a/lib/+artoa/+controller/+edit/+offsets/updateWorkspaceOffsetsTable.m
+++ b/lib/+artoa/+controller/+edit/+offsets/updateWorkspaceOffsetsTable.m
@@ -17,11 +17,28 @@ end
 %% Prepare required variables
 soundsources = artoa.controller.getSoundsourcesWithAppliedToa();
 
+%% Calculate measured soundspeed
+if artoa.data.hasMember(artoaWorkspace, {'trackParameter', 'soundspeedMethodString'})
+    method = artoaWorkspace.trackParameter.soundspeedMethodString;
+else
+    method = 'del grosso';
+end
+measuredSoundspeed = artoa.data.calculateSoundVelocity( ...
+        artoaWorkspace.temperature(artoaWorkspace.statusTemperature == 1), ...
+        artoaWorkspace.pressure(artoaWorkspace.statusPressure == 1), ...
+        method ...
+    );
+clear method;
+
 %% Initialize if not available
 if pForceOverwrite || ~artoa.data.hasMember(artoaWorkspace, {'editOffsets', 'offsets'})
     % initialize sound source offsets
     artoaWorkspace.editOffsets.offsets = ...
-        artoa.offsets.generateOffsetTable(artoaWorkspace.float, soundsources);
+        artoa.offsets.generateOffsetTable( ...
+            artoaWorkspace.float, ...
+            soundsources, ...
+            measuredSoundspeed ...
+            );
 end
 
 workspaceOffsets = artoaWorkspace.editOffsets.offsets;
diff --git a/lib/+artoa/+controller/+edit/+timeOfArrival/calculateGpsToas.m b/lib/+artoa/+controller/+edit/+timeOfArrival/calculateGpsToas.m
index 689a43b71c599bdba97d74cca252d78a630bbb4f..3f62648d7b95b6fa865468810ec6796688952a55 100644
--- a/lib/+artoa/+controller/+edit/+timeOfArrival/calculateGpsToas.m
+++ b/lib/+artoa/+controller/+edit/+timeOfArrival/calculateGpsToas.m
@@ -22,14 +22,17 @@ for o = 1:length(fnames)
     soundSourceEnd = artoa.convert.dmy2rd(artoaDataInput.soundsources.(fnames{o}).endemis(3), ...
         artoaDataInput.soundsources.(fnames{o}).endemis(2), ...
         artoaDataInput.soundsources.(fnames{o}).endemis(1));
-
-
-    % get soundspeed
-    soundvelocity = artoa.controller.selectSoundspeed();
+    
+    if any(strcmp(artoaWorkspace.editOffsets.offsets.Properties.RowNames, fnames(o)))
+        soundvelocity = artoaWorkspace.editOffsets.offsets{fnames{o}, 'AppliedSoundspeed'};
+    else
+        soundvelocity = NaN;
+    end
+    
 
     [gpsDates, predictedToas, launchDateToa] = artoa.toa.predictFromGps( ...
         artoaDataInput.rfb, artoaWorkspace.filteredSoundsources.(fnames{o}), ...
-        soundvelocity{fnames{o}, 1}, ...
+        soundvelocity, ...
         artoa.data.getMember(artoaConfig, {'leapseconds'}) ...
     );
 
diff --git a/lib/+artoa/+controller/+track/+parameter/validateCombinationsInput.m b/lib/+artoa/+controller/+track/+parameter/validateCombinationsInput.m
index a1fab16a25804a6c23bb7af5c900b2d98cedfd91..b93423c4fb94a738deb697956a410b447f84bb77 100644
--- a/lib/+artoa/+controller/+track/+parameter/validateCombinationsInput.m
+++ b/lib/+artoa/+controller/+track/+parameter/validateCombinationsInput.m
@@ -21,13 +21,6 @@ if any(strcmp(pCombinationsTable.soundsources, ''))
     return;
 end
 
-if any(isnan(pCombinationsTable.soundspeed1)) ...
-        || any(isnan(pCombinationsTable.soundspeed2)) ...
-        || any(isnan(pCombinationsTable.soundspeed3))
-    message = 'One of the soundspeeds contains an invalid value!';
-    return;
-end
-
 if any(isempty(pCombinationsTable.trackingMethod)) ...
         || any(strcmp(pCombinationsTable.trackingMethod, ''))
     message = 'You must select a tracking method for all combinations!';
diff --git a/lib/+artoa/+controller/+track/calculateTrajectoryObject.m b/lib/+artoa/+controller/+track/calculateTrajectoryObject.m
index d1a68ac191e5484e3318cd4f6ef62109a9f827b5..d5cf5bd0a2ead99911d4bbe23166644e9616ff01 100644
--- a/lib/+artoa/+controller/+track/calculateTrajectoryObject.m
+++ b/lib/+artoa/+controller/+track/calculateTrajectoryObject.m
@@ -4,32 +4,6 @@ function [trajectoryObject] = calculateTrajectoryObject()
 
 global artoaWorkspace artoaConfig artoaDataInput;
 
-%% Prepare sound velocity
-soundVelocity = NaN( ...
-    size(artoaWorkspace.trackParameter.soundsourceCombinations, 1), ...
-    3 ...
-);
-
-%% Get sound velocity
-% select a sound velocity for every soundsource available
-selectedVelocity = artoa.controller.selectSoundspeed();
-% filter the sound velocities that are required for calcucations
-for i = 1:size(soundVelocity, 1)
-    if strcmpi( ...
-        artoaWorkspace.trackParameter.soundspeedMethodString, ...
-        'soundsource file' ...
-        )
-        % get soundsource names
-        soundsourceNames = strsplit(artoaWorkspace.trackParameter.soundsourceCombinations.soundsources{i});
-        % get soundspeed for every soundsource
-        for oName = 1:length(soundsourceNames)
-            soundVelocity(i, oName) = selectedVelocity{soundsourceNames{oName}, 1};
-        end
-    else
-        soundVelocity(i, :) = selectedVelocity{1, 1};
-    end
-end
-
 %% Calculate trajectory
 [ ...
     trajectory, ...
@@ -104,7 +78,6 @@ trajectoryObject.temperature(dateIndices) = artoaWorkspace.temperature(indices);
             artoaWorkspace.filteredSoundsources, ...
             pTrackingParameter, ...
             artoaWorkspace.editOffsets, ...
-            soundVelocity, ...
             artoaConfig.leapseconds, ...
             artoaConfig.offsetvariations, ...
             pStartEndPosition ...
diff --git a/lib/+artoa/+controller/addDefaults.m b/lib/+artoa/+controller/addDefaults.m
index 9f30456e1a1b8a347a5431ca3160c752d4d209c8..63f6cf6e5aa0badf856cd4d37f5852f1685276a9 100644
--- a/lib/+artoa/+controller/addDefaults.m
+++ b/lib/+artoa/+controller/addDefaults.m
@@ -15,9 +15,7 @@ artoaConfig.defaults.interpolationMethods = { ...
 };
 artoaConfig.defaults.soundspeedMethods = { ...
     'Del Grosso', ...
-    'Linear', ...
-    'Soundsource file', ...
-    'Manual' ...
+    'Linear' ...
 };
 artoaConfig.defaults.offsetsToCopy = { ...
     'Measured', ...
@@ -26,6 +24,7 @@ artoaConfig.defaults.offsetsToCopy = { ...
 };
 artoaConfig.defaults.soundvelocityToCopy = { ...
     'Measured', ...
+    'Empirical', ...
     'Optimum' ...
 };
 artoaConfig.defaults.pickPointMarkerSize = 80;
diff --git a/lib/+artoa/+controller/selectSoundspeed.m b/lib/+artoa/+controller/selectSoundspeed.m
deleted file mode 100644
index 054d90831d7b5e6259f8443541992665ee5bb5af..0000000000000000000000000000000000000000
--- a/lib/+artoa/+controller/selectSoundspeed.m
+++ /dev/null
@@ -1,51 +0,0 @@
-function [soundvelocity] = selectSoundspeed()
-%SELECTSOUNDSPEED Summary of this function goes here
-%   Detailed explanation goes here
-
-global artoaWorkspace;
-
-%% Get required variables
-soundsourceNames = fieldnames(artoaWorkspace.filteredSoundsources);
-trackParameter = artoa.data.getMember(artoaWorkspace, {'trackParameter'}, false);
-soundspeedTable = artoa.data.getMember(artoaWorkspace, {'editOffsets', 'soundspeed'}, false);
-
-%% Get used method
-if ~islogical(trackParameter)
-    method = trackParameter.soundspeedMethodString;
-else
-    method = 'del grosso';
-end
-
-%% Fill with manual values or NaN
-if ~islogical(soundspeedTable)
-    initMatrix = repmat(soundspeedTable{'Soundspeed', 'Applied'}, length(soundsourceNames), 1);
-else
-    initMatrix = NaN(length(soundsourceNames), 1);
-end
-
-%% Initialize table
-soundvelocity = table(initMatrix, 'RowNames', soundsourceNames);
-
-%% If manual has been chosen, we are ready
-if strcmpi(method, 'manual')
-    return;
-end
-
-%% Get every velocity for each soundsource
-if strcmpi(method, 'soundsource file')
-    for i = 1:length(soundsourceNames)
-        soundvelocity{soundsourceNames{i}, 1} = ...
-            artoaWorkspace.filteredSoundsources.(soundsourceNames{i}).sound_speed;
-    end
-    return;
-end
-
-soundvelocity{:, :} = artoa.data.calculateSoundVelocity( ...
-    artoaWorkspace.temperature(artoaWorkspace.statusTemperature == 1), ...
-    artoaWorkspace.pressure(artoaWorkspace.statusPressure == 1), ...
-    method ...
-);
-
-
-end
-
diff --git a/lib/+artoa/+data/calculateResiduals.m b/lib/+artoa/+data/calculateResiduals.m
index 98675c000a8e39747ec53c4976958daade702c47..76d1a560fb47ad2796b0dcda323b436859815093 100644
--- a/lib/+artoa/+data/calculateResiduals.m
+++ b/lib/+artoa/+data/calculateResiduals.m
@@ -15,7 +15,7 @@ end
 %% Calculate misfits
 for i = 1:length(soundsourcePositions)
     geoDistance(i) = artoa.data.calculateGeodist(soundsourcePositions, calculatedPosition);
-    residuals(i) = (calculatedDistances(i) - geoDistance(i)) / soundVelocities(i);
+    residuals(i) = (calculatedDistances(i) - geoDistance(i)) / soundVelocities{i + 1, 'AppliedSoundspeed'};
 end
 
 end
diff --git a/lib/+artoa/+gui/main.m b/lib/+artoa/+gui/main.m
index 8e4a363c1e400123111c1c3092a8c7d19c4ce69f..065f12432df1fa7b2b11d21682d7b6fe6bea25ce 100644
--- a/lib/+artoa/+gui/main.m
+++ b/lib/+artoa/+gui/main.m
@@ -45,7 +45,6 @@ availableCallbacks = { ...
     'buttonResetAllCombinations', ...
     'tableSoundsourceOffsetsSelect', ... % FIRST ITEM OF OFFSETS
     'tableSoundsourceOffsetsEdit', ...
-    'tableSoundspeedEdit', ...
     'buttonCalculateOffsets', ...
     'checkboxUseOffsets', ...
     'buttonCopyOffsets', ...
@@ -435,10 +434,9 @@ artoaGui.trackParameter.inputOutputInterpolationInterval = uicontrol( ...
 columns = { ...
     'Begin', ...
     'End', ...
-    '<html>Sound<br>Sources', ...
-    '<html>(Reference)<br>Position Start', ...
-    '<html>(Reference)<br>Position End', ...
-    '<html>Sound<br>Speed', '<html>Sound<br>Speed', '<html>Sound<br>Speed', ...
+    'Sound Sources', ...
+    '(Reference) Position Start', ...
+    '(Reference) Position End', ...
     '<html>Tracking<br>Method', ...
     '<html>Backward<br>Tracking' ...
 };
@@ -576,21 +574,12 @@ fullwidth = 1 - (2 * left);
 artoaGui.editOffsets.tableSoundsourceOffsets = uitable( ...
     artoaGui.editOffsets.frameOffsets, ...
     'Units', 'normalized', ...
-    'Position', [left, 0.5, fullwidth, 0.5], ...
+    'Position', [left, 0.35, fullwidth, 0.65], ...
     'ColumnEditable', true, ...
     'CellSelectionCallback', pCallbacks.tableSoundsourceOffsetsSelect, ...
     'CellEditCallback', pCallbacks.tableSoundsourceOffsetsEdit ...
 );
 
-% Initialize soundspeed table
-artoaGui.editOffsets.tableSoundspeed = uitable( ...
-    artoaGui.editOffsets.frameOffsets, ...
-    'Units', 'normalized', ...
-    'Position', [left, 0.375, fullwidth, 0.125], ...
-    'ColumnEditable', true, ...'CellSelectionCallback', pCallbacks.tableSoundsourceOffsetsSelect, ...
-    'CellEditCallback', pCallbacks.tableSoundspeedEdit ...
-);
-
 % Optimum offsets frame
 artoaGui.editOffsets.frameOptimumOffsets = uipanel( ...
     'Parent', artoaGui.editOffsets.frameOffsets, ...
diff --git a/lib/+artoa/+offsets/createCalculationTables.m b/lib/+artoa/+offsets/createCalculationTables.m
index f0066a5c57a73a1f0300b0fa59438100b0ba02c2..6e765642af780a4f0ab2b42c4e3b62198200d4e2 100644
--- a/lib/+artoa/+offsets/createCalculationTables.m
+++ b/lib/+artoa/+offsets/createCalculationTables.m
@@ -29,7 +29,7 @@ for i = 1:length(fnames)
     try
         soundvelocity = pSoundvelocity{fnames{i}, 1};
     catch
-        soundvelocity = pSoundvelocity{1, 1};
+        soundvelocity = NaN;
     end
     
     [date, toa, ~] = artoa.toa.predictFromGps( ...
diff --git a/lib/+artoa/+offsets/generateOffsetTable.m b/lib/+artoa/+offsets/generateOffsetTable.m
index 8dba58bfd0ef725640166037eb6a51dde6a0fb84..adebe475951938856432acb233d2c2b7bffdf05a 100644
--- a/lib/+artoa/+offsets/generateOffsetTable.m
+++ b/lib/+artoa/+offsets/generateOffsetTable.m
@@ -1,14 +1,11 @@
-function [offsetTable] = generateOffsetTable(pFloatDetails, pSoundsources)
+function [offsetTable] = generateOffsetTable(pFloatDetails, pSoundsources, pMeasuredSoundspeed)
 %GETDEFAULTOFFSETTABLE Summary of this function goes here
 %   Detailed explanation goes here
 
-%% Get required variables
-variableNames = artoa.offsets.getDefaultVariableNames();
-
 %% Initialize return variable
 offsetTable = cell2table( ...
     artoa.offsets.getDefaultRowValues(), ...
-    'VariableNames', variableNames ...
+    'VariableNames', artoa.offsets.getDefaultVariableNames() ...
 );
 
 %% Setup rows
@@ -50,13 +47,14 @@ if ~islogical(floatOffsets)
     end
 end
 
-offsetTable{1, variableNames{1}} = startDate;
-offsetTable{1, variableNames{2}} = startOffset;
-offsetTable{1, variableNames{3}} = endDate;
-offsetTable{1, variableNames{4}} = endOffset;
-offsetTable{1, variableNames{5}} = drift;
-offsetTable{1, variableNames{6}} = floatEmpiricOffset;
-offsetTable{1, variableNames{7}} = floatEmpiricDrift;
+offsetTable{1, 'DateStart'} = startDate;
+offsetTable{1, 'OffsetStart'} = startOffset;
+offsetTable{1, 'DateEnd'} = endDate;
+offsetTable{1, 'OffsetEnd'} = endOffset;
+offsetTable{1, 'Drift'} = drift;
+offsetTable{1, 'EmpiricalOffset'} = floatEmpiricOffset;
+offsetTable{1, 'EmpiricalDrift'} = floatEmpiricDrift;
+offsetTable{1, 'MeasuredSoundspeed'} = pMeasuredSoundspeed;
 clear startDate startOffset endDate endOffset drift floatEmpiricOffset floatEmpiricDrift;
 
 if nargin == 1
@@ -68,14 +66,16 @@ if iscell(pSoundsources)
         offsetTable(i + 1, :) = artoa.offsets.getDefaultRowValues();
         offsetTable.Properties.RowNames(i + 1) = {pSoundsources{i}.sourcename};
         [ ...
-            offsetTable{i + 1, variableNames{1}}, ...
-            offsetTable{i + 1, variableNames{2}}, ...
-            offsetTable{i + 1, variableNames{3}}, ...
-            offsetTable{i + 1, variableNames{4}}, ...
-            offsetTable{i + 1, variableNames{5}}, ...
-            offsetTable{i + 1, variableNames{6}}, ...
-            offsetTable{i + 1, variableNames{7}} ...
+            offsetTable{i + 1, 'DateStart'}, ...
+            offsetTable{i + 1, 'OffsetStart'}, ...
+            offsetTable{i + 1, 'DateEnd'}, ...
+            offsetTable{i + 1, 'OffsetEnd'}, ...
+            offsetTable{i + 1, 'Drift'}, ...
+            offsetTable{i + 1, 'EmpiricalOffset'}, ...
+            offsetTable{i + 1, 'EmpiricalDrift'}, ...
+            offsetTable{i + 1, 'EmpiricalSoundspeed'} ...
             ] = extract(pSoundsources{i});
+        offsetTable{i + 1, 'MeasuredSoundspeed'} = pMeasuredSoundspeed;
     end
 end
 
@@ -85,18 +85,29 @@ if isstruct(pSoundsources)
         offsetTable(i + 1, :) = artoa.offsets.getDefaultRowValues();
         offsetTable.Properties.RowNames(i + 1) = {pSoundsources.(fnames{i}).sourcename};
         [ ...
-            offsetTable{i + 1, variableNames{1}}, ...
-            offsetTable{i + 1, variableNames{2}}, ...
-            offsetTable{i + 1, variableNames{3}}, ...
-            offsetTable{i + 1, variableNames{4}}, ...
-            offsetTable{i + 1, variableNames{5}}, ...
-            offsetTable{i + 1, variableNames{6}}, ...
-            offsetTable{i + 1, variableNames{7}} ...
+            offsetTable{i + 1, 'DateStart'}, ...
+            offsetTable{i + 1, 'OffsetStart'}, ...
+            offsetTable{i + 1, 'DateEnd'}, ...
+            offsetTable{i + 1, 'OffsetEnd'}, ...
+            offsetTable{i + 1, 'Drift'}, ...
+            offsetTable{i + 1, 'EmpiricalOffset'}, ...
+            offsetTable{i + 1, 'EmpiricalDrift'}, ...
+            offsetTable{i + 1, 'EmpiricalSoundspeed'} ...
             ] = extract(pSoundsources.(fnames{i}));
+        offsetTable{i + 1, 'MeasuredSoundspeed'} = pMeasuredSoundspeed;
     end
 end
 
-    function [startDate, startOffset, endDate, endOffset, drift, empiric_offset, empiric_drift] = extract(pSoundsource)
+    function [ ...
+            startDate, ...
+            startOffset, ...
+            endDate, ...
+            endOffset, ...
+            drift, ...
+            empiric_offset, ...
+            empiric_drift, ...
+            empiric_soundspeed ...
+            ] = extract(pSoundsource)
         startDate = NaN;
         startOffset = NaN;
         endDate = NaN;
@@ -143,6 +154,7 @@ end
             empiric_offset = pSoundsource.empiric_offset(4);
         end
         empiric_drift = artoa.data.getMember(pSoundsource, {'empiric_drift'}, NaN);
+        empiric_soundspeed = artoa.data.getMember(pSoundsource, {'sound_speed'}, NaN);
     end
 
 end
diff --git a/lib/+artoa/+offsets/getDefaultRowValues.m b/lib/+artoa/+offsets/getDefaultRowValues.m
index b4d197781af5a27b823a637ac9268d01f24ead0b..d200c3efd648d7af43051c77de1a48d196a353c6 100644
--- a/lib/+artoa/+offsets/getDefaultRowValues.m
+++ b/lib/+artoa/+offsets/getDefaultRowValues.m
@@ -2,7 +2,7 @@ function [defaultRow] = getDefaultRowValues()
 %GETDEFAULTROW Summary of this function goes here
 %   Detailed explanation goes here
 
-defaultRow = {NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN};
+defaultRow = {NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN};
 
 end
 
diff --git a/lib/+artoa/+offsets/getDefaultVariableNames.m b/lib/+artoa/+offsets/getDefaultVariableNames.m
index 468e745902e96e856e0a31175be88ac453f03b2a..9b967071d09ada3b8dd4b0edef09be05b0621f73 100644
--- a/lib/+artoa/+offsets/getDefaultVariableNames.m
+++ b/lib/+artoa/+offsets/getDefaultVariableNames.m
@@ -8,6 +8,10 @@ defaultVariableNames = { ...
     'DateEnd', ...
     'OffsetEnd', ...
     'Drift', ...
+    'MeasuredSoundspeed', ...
+    'EmpiricalSoundspeed', ...
+    'OptimumSoundspeed', ...
+    'AppliedSoundspeed', ...
     'EmpiricalOffset', ...
     'EmpiricalDrift', ...
     'OptimumTotalOffset', ...
diff --git a/lib/+artoa/+offsets/solve.m b/lib/+artoa/+offsets/solve.m
index 94fbfe2b0fd7f194e65cb41eb10f95c0d2527317..d2bbc268abfaa7855e1980b4d96f6c8576d1d927 100644
--- a/lib/+artoa/+offsets/solve.m
+++ b/lib/+artoa/+offsets/solve.m
@@ -1,4 +1,4 @@
-function [A, B, X, unfilteredA, unfilteredB, D] = solve(pRfb, pSoundsources, pTrackingParameter, pToaData, pSatData, pLeapsecondsMatrix, pOffsetsParameter, pSoundvelocity)
+function [A, B, X, unfilteredA, unfilteredB, D] = solve(pRfb, pSoundsources, pTrackingParameter, pToaData, pSatData, pLeapsecondsMatrix, pOffsetsParameter)
 %UNTITLED Summary of this function goes here
 %   Detailed explanation goes here
 
@@ -10,7 +10,7 @@ function [A, B, X, unfilteredA, unfilteredB, D] = solve(pRfb, pSoundsources, pTr
     pOffsetsParameter, ...
     pToaData, ...
     pSatData, ...
-    pSoundvelocity, ...
+    pOffsetsParameter.offsets(:, 'AppliedSoundspeed'), ...
     pLeapsecondsMatrix ...
 );
 
@@ -38,13 +38,13 @@ function [A, B, X, unfilteredA, unfilteredB, D] = solve(pRfb, pSoundsources, pTr
 B.toa = B.toa - unfilteredC.ReferenceTime;
 
 %% Use soundspeed
-if ~isnan(pOffsetsParameter.soundspeed{'Soundspeed', 'Applied'})
+if ~isnan(pOffsetsParameter.offsets{'Float', 'AppliedSoundspeed'})
     if isempty(A)
         return; % nothing to be done, everything is given and soundspeed is fixed
     end
     
     % Distances are in km, soundspeed m/s
-    B.toa = B.toa - A{:, 'Distances'} / (pOffsetsParameter.soundspeed{'Soundspeed', 'Applied'} / 1000);
+    B.toa = B.toa - A{:, 'Distances'} / (pOffsetsParameter.offsets{'Float', 'AppliedSoundspeed'} / 1000);
     A.Distances = [];
 end
 
diff --git a/lib/+artoa/+trajectory/calculate.m b/lib/+artoa/+trajectory/calculate.m
index e787ceeb7a93abe0421686cb4e7b72ceb4842d66..8987d8a2d40aedca626c29da39aff22833737259 100644
--- a/lib/+artoa/+trajectory/calculate.m
+++ b/lib/+artoa/+trajectory/calculate.m
@@ -1,4 +1,4 @@
-function [trajectory, trajectoryDates, trajectoryClockError, trajectoryResiduals, trajectoryVelocities, trajectoryTimeDivergenceToGps, trajectorySegmentSize, trajectoryVariationResults] = calculate(pFloatDetails, pPressureAndDate, pSatData, pToaData, pSoundsources, pTrackingParameter, pOffsetsParameter, pSoundVelocity, pLeapsecondsMatrix, pOffsetVariations, pStartEndPosition)
+function [trajectory, trajectoryDates, trajectoryClockError, trajectoryResiduals, trajectoryVelocities, trajectoryTimeDivergenceToGps, trajectorySegmentSize, trajectoryVariationResults] = calculate(pFloatDetails, pPressureAndDate, pSatData, pToaData, pSoundsources, pTrackingParameter, pOffsetsParameter, pLeapsecondsMatrix, pOffsetVariations, pStartEndPosition)
 %CALCULATETRAJECTORY Calculates the trajectory using the given details.
 %   Applies all required corrections to the data and calculates the trajectory
 %   segment by segment afterwards.
@@ -21,10 +21,6 @@ function [trajectory, trajectoryDates, trajectoryClockError, trajectoryResiduals
 %           float.
 %       pTrackingParameter (struct):
 %           Tracking parameter according to artoa data specification.
-%       pSoundVelocity (double):
-%           x by 3 vector, containing the soundspeed values corresponding
-%           to the specified soundsources in the tracking parameter ->
-%           soundsource combination table.
 %       pLeapsecondsMatrix (double):
 %           The leapseconds matrix that is specified in the artoa.ini file.
 %       pOffsetVariations (double):
@@ -251,7 +247,7 @@ for oCombination = 1:size(soundsourceCombinations, 1)
         preparedData, ...
         currentCombination, ...
         floatReferenceTime, ...
-        pSoundVelocity(oCombination, :), ...
+        pOffsetsParameter.offsets(:, 'AppliedSoundspeed'), ...
         currentCombination.backwardTracking(1), ...
         pStartEndPosition ...
     );
@@ -304,7 +300,7 @@ for oCombination = 1:size(soundsourceCombinations, 1)
             preparedData, ...
             currentCombination, ...
             floatReferenceTime, ...
-            pSoundVelocity(oCombination, :), ...
+            pOffsetsParameter.offsets(:, 'AppliedSoundspeed'), ...
             pTrackingParameter, ...
             pOffsetVariations ...
             );
@@ -390,12 +386,12 @@ for oCombination = 1:size(soundsourceCombinations, 1)
         [soundsourceDivergence, ~] = artoa.data.calculateTimeDivergence( ...
             repmat(currentSoundsource.position, size(intersectedSegmentPositions, 1), 1), ...
             intersectedSegmentPositions, ...
-            pSoundVelocity(oCombination, oSoundsource) ...
+            pOffsetsParameter.offsets{currentSoundsource.sourcename, 'AppliedSoundspeed'} ...
         );
         [gpsDivergence, usedIndices] = artoa.data.calculateTimeDivergence( ...
             repmat(currentSoundsource.position, size(segmentSatPositions, 1), 1), ...
             segmentSatPositions, ...
-            pSoundVelocity(oCombination, oSoundsource) ...
+            pOffsetsParameter.offsets{currentSoundsource.sourcename, 'AppliedSoundspeed'} ...
         );
         if isempty(usedIndices) || isempty(soundsourceDivergence) || isempty(gpsDivergence)
             continue;
diff --git a/lib/+artoa/+trajectory/calculateCombinationSegment.m b/lib/+artoa/+trajectory/calculateCombinationSegment.m
index eed90eba163362ba4cbac92889683bb68e76543d..8d21a4e9e09edb4bbd652b183aa6d84e99044c51 100644
--- a/lib/+artoa/+trajectory/calculateCombinationSegment.m
+++ b/lib/+artoa/+trajectory/calculateCombinationSegment.m
@@ -8,7 +8,7 @@ function [ ...
         pCorrectedData, ...
         pCombinationDetails, ...
         pFloatReferenceTime, ...
-        pSoundVelocity, ...
+        pSoundVelocities, ...
         pBackwardTracking, ...
         pStartEndPosition ...
     )
@@ -26,12 +26,9 @@ function [ ...
 %       pFloatReferenceTime (double):
 %           Vector containing the float reference time, in the
 %           format [hour, minute]
-%       pSoundVelocity (double):
-%           Sound velocity next to the sound sources that are used.
-%           If hyperbolic is being used, it needs to be a vector containing
-%           at least as many entries as the count of sound sources being
-%           used.
-%           For all other methods, only one value needs to be set.
+%       pSoundVelocity (table):
+%           A table containing one variable, 'AppliedSoundspeed'. For every
+%           soundsource, there needs to be a soundspeed available.
 %           Unit: [m/s]
 %       pBackwardTracking (bool):
 %           If true, the data will be prepared for backward tracking
@@ -80,6 +77,7 @@ intersectedToaDates = intersectedToaDates( ...
 
 %% Create a table for every soundsource (required by tracking plugin system)
 pluginTables = struct();
+pluginTables.float = struct('soundspeed', pSoundVelocities{'Float', 'AppliedSoundspeed'});
 for i = 1:length(soundsourceNames)
     pluginTables.(soundsourceNames{i}) = table();
 end
@@ -116,13 +114,14 @@ for oDates = 1:lenIntersectedToaDates
         % calculate distance to the source
         distanceToSoundsources{oDates} = [ ...
             distanceToSoundsources{oDates}; ...
-            relativeToa * (pSoundVelocity(i)/1000)
+            relativeToa * (pSoundVelocities{soundsourceNames{i}, 'AppliedSoundspeed'}/1000)
         ];
     
         % store in pluginTables
         pluginTables.(currentName).date{oDates} = currentDateValue;
         pluginTables.(currentName).toa{oDates} = relativeToa;
         pluginTables.(currentName).distance{oDates} = distanceToSoundsources{oDates}(i);
+        pluginTables.(currentName).soundspeed{oDates} = pSoundVelocities{soundsourceNames{i}, 'AppliedSoundspeed'};
 
     end
 
@@ -195,7 +194,7 @@ for oDates = 1:length(intersectedToaDates)
         segmentPositions(1, :), ...
         distanceToSoundsources{oDates}, ...
         soundsourcePositions, ...
-        pSoundVelocity ...
+        pSoundVelocities ...
     );
     % split up for storing it as table
     for i = 1:length(soundsourceNames)
diff --git a/lib/+artoa/+versioning/+migrations/versions/v4284.m b/lib/+artoa/+versioning/+migrations/versions/v4284.m
new file mode 100644
index 0000000000000000000000000000000000000000..c7613535bb1cb0950b4cdee833031268fa474ba4
--- /dev/null
+++ b/lib/+artoa/+versioning/+migrations/versions/v4284.m
@@ -0,0 +1,71 @@
+%% Update the soundspeed method defaults
+artoaConfig.defaults.soundspeedMethods = { ...
+    'Del Grosso', ...
+    'Linear' ...
+};
+if artoa.data.hasMember(artoaWorkspace, 'trackParameter', 'soundspeedMethodValue')
+    artoaWorkspace.trackParameter.soundspeedMethodValue = 1;
+end
+if artoa.data.hasMember(artoaWorkspace, 'trackParameter', 'soundspeedMethodString')
+    artoaWorkspace.trackParameter.soundspeedMethodString = artoaConfig.defaults.soundspeedMethods{artoaWorkspace.trackParameter.soundspeedMethodValue};
+end
+
+%% Add soundvelocity options
+artoaConfig.defaults.soundvelocityToCopy = { ...
+    'Measured', ...
+    'Empirical', ...
+    'Optimum' ...
+};
+
+%% Remove soundspeed table and undo copy value
+artoaWorkspace.editOffsets = rmfield(artoaWorkspace.editOffsets, 'undoCopySoundspeed');
+artoaWorkspace.editOffsets = rmfield(artoaWorkspace.editOffsets, 'soundspeed');
+
+%% Add variables for soundspeeds to the offsets panel
+if artoa.data.hasMember(artoaWorkspace, 'editOffsets', 'offsets')
+    % applied
+    artoaWorkspace.editOffsets.offsets = ...
+        addvars( ...
+            artoaWorkspace.editOffsets.offsets, ...
+            addNaNCell4284(length(artoaWorkspace.editOffsets.offsets.DateStart)), ...
+            'After', 'Drift' ...
+            );
+	artoaWorkspace.editOffsets.offsets.Properties.VariableNames{6} = 'AppliedSoundspeed';
+    % optimum
+    artoaWorkspace.editOffsets.offsets = ...
+        addvars( ...
+            artoaWorkspace.editOffsets.offsets, ...
+            addNaNCell4284(length(artoaWorkspace.editOffsets.offsets.DateStart)), ...
+            'After', 'Drift' ...
+            );
+	artoaWorkspace.editOffsets.offsets.Properties.VariableNames{6} = 'OptimumSoundspeed';
+    % empirical
+    artoaWorkspace.editOffsets.offsets = ...
+        addvars( ...
+            artoaWorkspace.editOffsets.offsets, ...
+            addNaNCell4284(length(artoaWorkspace.editOffsets.offsets.DateStart)), ...
+            'After', 'Drift' ...
+            );
+	artoaWorkspace.editOffsets.offsets.Properties.VariableNames{6} = 'EmpiricalSoundspeed';
+    % measured
+    artoaWorkspace.editOffsets.offsets = ...
+        addvars( ...
+            artoaWorkspace.editOffsets.offsets, ...
+            addNaNCell4284(length(artoaWorkspace.editOffsets.offsets.DateStart)), ...
+            'After', 'Drift' ...
+            );
+	artoaWorkspace.editOffsets.offsets.Properties.VariableNames{6} = 'MeasuredSoundspeed';
+end
+
+%% Remove soundspeed from tracking parameter panel
+if artoa.data.hasMember(artoaWorkspace, 'trackParameter', 'soundsourceCombinations')
+    artoaWorkspace.trackParameter.soundsourceCombinations(:, 'soundspeed1') = [];
+    artoaWorkspace.trackParameter.soundsourceCombinations(:, 'soundspeed2') = [];
+    artoaWorkspace.trackParameter.soundsourceCombinations(:, 'soundspeed3') = [];
+end
+
+%% Helper functions
+
+function emptyCell = addNaNCell4284(pLength)
+    emptyCell = NaN(pLength, 1);
+end
\ No newline at end of file
diff --git a/plugins/tracking/Circular.m b/plugins/tracking/Circular.m
index 0db6b9e28733f89545f56f704b8aac8bf2b813a5..7cd606c9d7f08bfa5b7ff04d1a054def820ba3b6 100644
--- a/plugins/tracking/Circular.m
+++ b/plugins/tracking/Circular.m
@@ -43,7 +43,7 @@ for oSoundsource = 1:length(soundsourceNames)
         cell2mat(pData.(soundsourceNames{oSoundsource}).distance);
     soundsourcePositions(oSoundsource, :) = ...
         pSoundsourcePositions.(soundsourceNames{oSoundsource});
-    soundVelocity(oSoundsource) = pCombinationDetails.(['soundspeed' num2str(oSoundsource)]);
+    soundVelocity(oSoundsource) = pData.(soundsourceNames{oSoundsource}).soundspeed;
 end
 
 % initialize return variables
diff --git a/plugins/tracking/Hyperbolic.m b/plugins/tracking/Hyperbolic.m
index e351d3a1739651a8bef07984b0c4e8f627f6a6fb..cfd21af38d03ed1b46eb9b8c879483c8de018a2f 100644
--- a/plugins/tracking/Hyperbolic.m
+++ b/plugins/tracking/Hyperbolic.m
@@ -43,7 +43,7 @@ for oSoundsource = 1:length(soundsourceNames)
         cell2mat(pData.(soundsourceNames{oSoundsource}).distance);
     soundsourcePositions(oSoundsource, :) = ...
         pSoundsourcePositions.(soundsourceNames{oSoundsource});
-    soundVelocity(oSoundsource) = pCombinationDetails.(['soundspeed' num2str(oSoundsource)]);
+    soundVelocity(oSoundsource) = pData.(soundsourceNames{oSoundsource}).soundspeed;
 end
 
 % initialize return variables
diff --git a/plugins/tracking/LeastSquares.m b/plugins/tracking/LeastSquares.m
index 508ff2d41f474a6f4ca2741fc025ee797e187488..4b603bc5a556e5af1b9bfc093e7fdc9b1a76f7c3 100644
--- a/plugins/tracking/LeastSquares.m
+++ b/plugins/tracking/LeastSquares.m
@@ -55,7 +55,7 @@ for oDates = 1:length(dates)
                 length(soundsourceNames), ...
                 soundsourcePositions, ...
                 distances(oDates, :), ...
-                pCombinationDetails.soundspeed1/1000 ...
+                pData.float.soundspeed/1000 ...
             ) ...
         ) ...
     ];