Commit aca6ed60 authored by Lukas Aspöck's avatar Lukas Aspöck

Merge branch 'master' of https://git.rwth-aachen.de/ita/toolbox

parents 1ce2eec1 9db20186
......@@ -117,10 +117,20 @@ classdef itaHRTF < itaAudio
methods % Special functions that implement operations that are usually performed only on instances of the class
%% Input
function this = itaHRTF(varargin)
this = this@itaAudio();
% initialize itaHRTF with itaAudio properties (only for nargin == 1)
if nargin > 1 || (nargin == 1 && (ischar(varargin{1}) || isa(varargin{1},'itaAudio')))
iniAudio = [];
elseif nargin == 1 && isstruct(varargin{1})
fNames = {'domain','data','signalType','samplingRate'};
for idxFN = 1:numel(fNames)
iniAudio.(fNames{idxFN}) = varargin{1}.(fNames{idxFN});
end
end
this = this@itaAudio(iniAudio);
if nargin >1
% itaAudio input
TF_types = this.propertiesTF_type;
for iTF = 1:numel(TF_types)
......@@ -148,6 +158,7 @@ classdef itaHRTF < itaAudio
end
elseif nargin == 1
if isa(varargin{1},'itaHRTF')
this = varargin{1};
......@@ -176,7 +187,13 @@ classdef itaHRTF < itaAudio
elseif isa(varargin{1},'itaAudio')
this.itaAudio2itaHRTF = varargin{1};
end
elseif ischar(varargin{1}) % openDaff/ sofa/ hdf5 input
if strfind(lower(varargin{1}),'.daff'), this.openDAFF2itaHRTF = varargin{1};
elseif strfind(lower(varargin{1}),'.hdf5'), this.hdf2itaHRTF = varargin{1};
elseif strfind(lower(varargin{1}),'.sofa'), this.sofa2itaHRTF = varargin{1};
end
end
end
end
......@@ -373,7 +390,7 @@ classdef itaHRTF < itaAudio
counter= counter+2;
end
tempMetadata=DAFFv17('getMetadata', handleDaff);
metadata = DAFFv17('getMetadata', handleDaff);
catch
disp( 'Could not read DAFF file right away, falling back to old version and retrying ...' );
......@@ -388,7 +405,27 @@ classdef itaHRTF < itaAudio
counter = 1;
data = zeros(props.filterLength,props.numRecords*2,'double' ) ;
coordDaff = zeros(props.numRecords,2) ;
tempMetadata=DAFFv15('getMetadata', handleDaff);
tempMetadata = DAFFv15('getMetadata', handleDaff);
% Convert old-style metadata format to v17.
names = fieldnames( tempMetadata );
for k = 1:numel( tempMetadata )
switch class(tempMetadata.(names{k}))
case 'logical'
datatype='bool';
case 'char'
datatype='string';
case 'double'
if rem(tempMetadata.(names{k}),1)==0
datatype='int';
else
datatype='float';
end
end
metadata = daffv17_add_metadata( metadata,cell2mat(names(k)),datatype,tempMetadata.(names{k}) );
end
for iDir = 1:props.numRecords
data(:,[counter counter+1]) = DAFFv15( 'getRecordByIndex', handleDaff,iDir )';
coordDaff(iDir,:) = DAFFv15( 'getRecordCoords', handleDaff, 'data', iDir )';
......@@ -396,53 +433,36 @@ classdef itaHRTF < itaAudio
end
end
% Proceed (version independent)
names=fieldnames(tempMetadata);
for k=1:(numel(names))
switch class(tempMetadata.(names{k}))
case 'logical'
datatype='bool';
case 'char'
datatype='string';
case 'double'
if rem(tempMetadata.(names{k}),1)==0
datatype='int';
else
datatype='float';
end
end
metadata=daffv17_add_metadata(metadata,cell2mat(names(k)),datatype,tempMetadata.(names{k}));
end
phiM = coordDaff(:,1)*pi/180;
%phiM = mod(coordDaff(:,1),360)*pi/180;
%if ~isempty(find(0<coordDaff(:,2),1,'first'))
thetaM = coordDaff(:,2)*pi/180;
%thetaM = mod(180-(coordDaff(:,2)+90),180)*pi/180;
%else
% thetaM = coordDaff(:,2)*pi/180;
%end
radius = ones(props.numRecords,1);
chCoord = itaCoordinates;
chCoord.sph = ones(size(data,2),3);
chCoord.phi(1:2:2*props.numRecords) = phiM;
chCoord.phi(2:2:2*props.numRecords) = phiM;
chCoord.theta(1:2:2*props.numRecords) = thetaM;
chCoord.theta(2:2:2*props.numRecords) = thetaM;
this.mMetadata = metadata;
this.data = data;
this.mDirCoord = itaCoordinates([radius thetaM phiM],'sph');
this.channelCoordinates = chCoord;
this.mEarSide = repmat(['L'; 'R'],props.numRecords, 1);
this.signalType = 'energy';
% channelnames coordinates
this.channelNames = ita_sprintf('%s ( %2.0f, \\theta= %2.0f)',...
this.mEarSide , this.channelCoordinates.theta_deg, this.channelCoordinates.phi_deg);
end
phiM = coordDaff(:,1)*pi/180;
%phiM = mod(coordDaff(:,1),360)*pi/180;
%if ~isempty(find(0<coordDaff(:,2),1,'first'))
thetaM = coordDaff(:,2)*pi/180;
%thetaM = mod(180-(coordDaff(:,2)+90),180)*pi/180;
%else
% thetaM = coordDaff(:,2)*pi/180;
%end
radius = ones(props.numRecords,1);
chCoord = itaCoordinates;
chCoord.sph = ones(size(data,2),3);
chCoord.phi(1:2:2*props.numRecords) = phiM;
chCoord.phi(2:2:2*props.numRecords) = phiM;
chCoord.theta(1:2:2*props.numRecords) = thetaM;
chCoord.theta(2:2:2*props.numRecords) = thetaM;
this.mMetadata = metadata;
this.data = data;
this.mDirCoord = itaCoordinates([radius thetaM phiM],'sph');
this.channelCoordinates = chCoord;
this.mEarSide = repmat(['L'; 'R'],props.numRecords, 1);
this.signalType = 'energy';
% channelnames coordinates
this.channelNames = ita_sprintf('%s ( %2.0f, \\theta= %2.0f)',...
this.mEarSide , this.channelCoordinates.theta_deg, this.channelCoordinates.phi_deg);
end
function this = set.init(this,var)
% TO DO !!!!!!!!!!!!!!!!!!!!!!!!!!!
......@@ -512,6 +532,7 @@ classdef itaHRTF < itaAudio
% data
% the data is saved as positions x channel x filterdata
this.samplingRate = handleSofa.Data.SamplingRate;
data = zeros(size(handleSofa.Data.IR,3),numPositions*2);
data(:,1:2:numPositions*2) = squeeze(handleSofa.Data.IR(:,1,:)).';
......@@ -1487,11 +1508,8 @@ classdef itaHRTF < itaAudio
function result = propertiesSphereType
result = {'cap', 'ring','full','undefined'};
end
end
function result = propertiesInit
result = {'channelCoordinates','domain','data'};
end
end
end
......@@ -71,12 +71,29 @@ assert( betarange( 2 ) >= 0.0 )
assert( betarange( 1 ) <= 180.0 )
%% Assemble metadata
%% Assemble metadata (if not already present)
keyname = 'Generation script';
if ~any( strcmpi( { metadata(:).name }, keyname ) )
metadata = daffv17_add_metadata( metadata, keyname, 'String', 'writeDAFFFile.m' );
end
keyname = 'Generation toolkit';
if ~any( strcmpi( { metadata(:).name }, keyname ) )
metadata = daffv17_add_metadata( metadata, keyname, 'String', 'ITA-Toolkit' );
end
keyname = 'Generation date';
if ~any( strcmpi( { metadata(:).name }, keyname ) )
metadata = daffv17_add_metadata( metadata, keyname, 'String', date );
end
keyname = 'Web resource';
if ~any( strcmpi( { metadata(:).name }, keyname ) )
metadata = daffv17_add_metadata( metadata, keyname, 'String', 'http://www.ita-toolkit.org' );
end
metadata = daffv17_add_metadata( metadata, 'Generation script', 'String', 'writeDAFFFile.m' );
metadata = daffv17_add_metadata( metadata, 'Generation toolkit', 'String', 'ITA-Toolkit' );
metadata = daffv17_add_metadata( metadata, 'Generation date', 'String', date );
metadata = daffv17_add_metadata( metadata, 'Web resource', 'String', 'http://www.ita-toolkit.org' );
channels=this.nChannels/this.nDirections;
if(channels<1)
warning('Number of channels per record was not detected correctly, assuming 2 channel records');
......
function varargout = ita_HRTF_postProcessing_smoothLowFreq(varargin)
%ITA_HRTF_POSTPROCESSING_SMOOTHLOWFREQ - Fills low frequency of HRTF measurement
% This function will take a HRTF measurement and fills in low frequency content.
% Data is interpolated to 1 at 0 Hz
% Phase information is preserved.
%
% Syntax:
% audioObjOut = ita_HRTF_postProcessing_smoothLowFreq(audioObjIn, options)
%
% Options (default):
% 'cutOffFrequency' (100) : The lowest point of measured data
% 'upperFrequency' (300) : Frequency information up to this frequency is used during interpolation but not changed
% 'timeShift' (0) : Time shift the data to zero to help
% with unwrap phase
%
% Example:
% audioObjOut = ita_HRTF_postProcessing_smoothLowFreq(audioObjIn,'cutOffFrequency',100)
%
%
% Reference page in Help browser
% <a href="matlab:doc ita_HRTF_postProcessing_smoothLowFreq">doc ita_HRTF_postProcessing_smoothLowFreq</a>
% <ITA-Toolbox>
% This file is part of the ITA-Toolbox. Some rights reserved.
% You can find the license for this m-file in the license.txt file in the ITA-Toolbox folder.
% </ITA-Toolbox>
% Author: Jan-Gerrit Richter -- Email: jri@akustik.rwth-aachen.de
% Created: 21-Aug-2017
%% Initialization and Input Parsing
% all fixed inputs get fieldnames with posX_* and dataTyp
% optonal inputs get a default value ('comment','test', 'opt1', true)
% please see the documentation for more details
sArgs = struct('pos1_data','itaAudio', 'cutOffFrequency', 100,'upperFrequency',300,'timeShift',0);
[input,sArgs] = ita_parse_arguments(sArgs,varargin);
%% body
% for multi instances, do a for loop
for instIndex = 1:length(input)
% first, shift the HRTF to 0. This will allow better phase interpolation
if sArgs.timeShift
shiftSamples = ita_start_IR(input(instIndex));
[tmp] = ita_time_shift(input(instIndex),-shiftSamples,'samples');
else
tmp = input(instIndex);
end
% interpolate to 0
binIdxAtLower = tmp.freq2index(sArgs.cutOffFrequency);
binIdxAtUpper = tmp.freq2index(sArgs.upperFrequency);
dataFromLowerToUpper = tmp.freqData(binIdxAtLower:binIdxAtUpper,:);
interpValues1 = interp1([0 tmp.freqVector(binIdxAtLower:binIdxAtUpper)], [ones(1,tmp.nChannels); abs(dataFromLowerToUpper)], tmp.freqVector(1:binIdxAtUpper));
interpPhase = interp1(tmp.freqVector(binIdxAtLower:binIdxAtUpper),unwrap(angle(dataFromLowerToUpper)),tmp.freqVector(1:binIdxAtUpper),'linear','extrap');
% set the interpolated values into the shifted audio
tmp.freqData(1:binIdxAtUpper,:) = interpValues1.*exp(1i.*interpPhase);
%% Add history line
tmp = ita_metainfo_add_historyline(tmp,mfilename,varargin);
if sArgs.timeShift
% shift the audio back to its original position
data_full(instIndex) = ita_time_shift(tmp,shiftSamples,'samples');
else
data_full(instIndex) = tmp;
end
end
%% Set Output
varargout(1) = {data_full};
%end function
end
......@@ -122,6 +122,7 @@ classdef itaMotorControlNanotec < itaMotorControl
pause(this.waitForSerialPort);
end
end
function moveTo(this,varargin)
% if itaCoordinates are given, the position is passed to all
......@@ -178,6 +179,13 @@ classdef itaMotorControlNanotec < itaMotorControl
end
function freeFromStopButton(this)
for index = 1:length(this.motorList)
this.motorList{index}.freeFromStopButton();
end
end
function reference(this)
this.clear_commandlist;
for index = 1:length(this.motorList)
......@@ -212,12 +220,14 @@ classdef itaMotorControlNanotec < itaMotorControl
% first, do a reference move
ita_verbose_info('Moving to reference',1)
this.reference
ita_verbose_info('Disable reference position',1)
this.motorList{1}.disableReference(1);
ita_verbose_info('Moving to pre angle',1)
this.moveTo(motorName,-sArgs.preAngle,'absolut',false,'speed',1)
this.moveTo(motorName,-sArgs.preAngle,'absolut',false,'speed',2)
% now prepare the big move but don't start it
this.moveTo(motorName,360+sArgs.preAngle+15,'speed',sArgs.speed,'absolut',false,'start',0,'limit',0);
this.moveTo(motorName,360-35,'speed',sArgs.speed,'absolut',true,'start',0,'limit',0);
this.preparedList = motorName;
ita_verbose_info('Finished preparing',2)
end
......@@ -246,6 +256,8 @@ classdef itaMotorControlNanotec < itaMotorControl
end
this.wait4everything
this.preparedList = [];
ita_verbose_info('Enable reference position',1)
% this.sendControlSequenceAndPrintResults(':port_in_a=7');
end
function success = add_to_commandlist(this, string_to_send)
......@@ -456,7 +468,11 @@ classdef itaMotorControlNanotec < itaMotorControl
ita_verbose_info('Position reached',1);
else
ita_verbose_info('Position NOT reached! - Check for errors!', 0);
this.send_commandlist(this.failed_command_repititions); % mpo: bugfix: send_commandlist needs argument
%assuming stop button clicked
%call freefrombutton function
% this.freeFromStopButton
% this.send_commandlist(this.failed_command_repititions); % mpo: bugfix: send_commandlist needs argument
% this.isReferenced = false;
end
this.clear_receivedlist;
......
......@@ -29,7 +29,8 @@ classdef itaMotorNanotec < itaHandle
% basic moves: requires execution to halt while something is moving
this = moveToReferencePosition(this);
this = startMoveToPosition(this);
disableReference(this,value);
% this = freeFromStopButton(this);
ret = prepareMove(this,position,varargin);
end
end
\ No newline at end of file
......@@ -81,6 +81,10 @@ classdef itaMotorNanotec_Arm < itaMotorNanotec
name = this.motorName;
end
function disableReference(this,value)
end
function sendConfiguration(this)
motorControl = this.mMotorControl;
motorControl.add_to_commandlist(sprintf('#%d:port_in_a7\r' , this.motorID));
......
......@@ -23,8 +23,9 @@ classdef itaMotorNanotec_HRTFarc < itaMotorNanotec
'continuous', false, ...
'absolut', true, ...
'closed_loop', false, ...
'acceleration_ramp',1, ...
'gear_ratio', 5, ...
'acceleration_ramp',20, ...
'decceleration_ramp',20, ...
'gear_ratio', 80, ...
'current', 100, ...
'ramp_mode', 2, ...
'P', 400, ...
......@@ -44,14 +45,21 @@ classdef itaMotorNanotec_HRTFarc < itaMotorNanotec
this.motorID = 8;
this.motorName = 'HRTFArc';
this.motorLimits = [-15 375]; % the motor can do a whole rotation + ~15 deg to both sides
this.motorLimits = [-45 330]; % the motor can do a whole rotation + ~15 deg to both sides
end
function this = init(this)
end
function disableReference(this,value)
if value
this.mMotorControl.sendControlSequenceAndPrintResults(':port_in_a=0');
else
this.mMotorControl.sendControlSequenceAndPrintResults(':port_in_a=7');
end
end
function stop(this)
% DO NOT ASK - JUST STOP ALL MOTORS!
for i = 1:5 % repeat several times to ensure that every motor stops!
......@@ -63,6 +71,22 @@ classdef itaMotorNanotec_HRTFarc < itaMotorNanotec
end
end
% function freeFromStopButton(this)
% res = motorControl.sendControlSequenceAndPrintResults('Zd');
% resp = res{end};
% direction = str2double(resp(end));
%
% if direction == 0
% direction = -1;
% else
% direction = 1;
% end
% this.allowMoveOverRefButton(1);
% this.prepareMove(direction*20,'absolut',false,'speed',10);
% this.startMoveToPosition();
% this.allowMoveOverRefButton(0);
% end
function getStatus(this)
motorControl.add_to_commandlist(sprintf('#%d$\r' , this.motorID));
......@@ -88,6 +112,7 @@ classdef itaMotorNanotec_HRTFarc < itaMotorNanotec
function sendConfiguration(this)
% Set Input 1 as external Referenceswitch
motorControl = this.mMotorControl;
motorControl.add_to_commandlist(sprintf('#%d:port_in_a=7\r' , this.motorID));
motorControl.add_to_commandlist(sprintf('#%d:port_in_b=7\r' , this.motorID));
motorControl.add_to_commandlist(sprintf('#%d:port_out_a=1\r' , this.motorID));
motorControl.add_to_commandlist(sprintf('#%d:port_out_a=2\r' , this.motorID));
......@@ -105,10 +130,10 @@ classdef itaMotorNanotec_HRTFarc < itaMotorNanotec
% endschalterverhalten: the ref manual is not very clear. bit 0
% is the most important bit. all not listed bits are 0
% defValue bin2dec('0100010000100010') = 17442
% motorControl.add_to_commandlist(sprintf('#%dl%d\r' , this.motorID, 5154));
this.allowMoveOverRefButton(0);
% set lower speed to 1 Hz/sec (lowest value)
motorControl.add_to_commandlist(sprintf('#%du1\r' , this.motorID));
motorControl.add_to_commandlist(sprintf('#%du3\r' , this.motorID));
end
......@@ -117,25 +142,29 @@ classdef itaMotorNanotec_HRTFarc < itaMotorNanotec
motorControl = this.mMotorControl;
% Turn + some degrees in case we are already at the end of the
% reference switch or already passed it:
this.prepareMove(10,'absolut',false,'speed',1);
this.startMoveToPosition();
if this.mMotorControl.send_commandlist(5);
ita_verbose_info('HRTFarc started move...',2);
end
tmpWait = motorControl.wait;
motorControl.wait = true;
motorControl.wait4everything;
motorControl.wait = tmpWait;
% this.prepareMove(20,'absolut',false,'speed',10);
% this.startMoveToPosition();
% if this.mMotorControl.send_commandlist(5);
% ita_verbose_info('HRTFarc started move...',2);
% end
% tmpWait = motorControl.wait;
% motorControl.wait = true;
% motorControl.wait4everything;
% motorControl.wait = tmpWait;
this.disableReference(0);
% Call Reference-Mode:
motorControl.add_to_commandlist(sprintf('#%dp=4\r' , this.motorID));
% Set direction:
motorControl.add_to_commandlist(sprintf('#%dd=1\r' , this.motorID));
% Calculate and set lower speed:
% stepspersecond = round(this.sArgs_default_motor.speed/0.9*this.sArgs_default_motor.gear_ratio);
motorControl.add_to_commandlist(sprintf('#%du=%d\r' , this.motorID, 1));
stepspersecond = round(this.sArgs_default_motor.speed/0.9*this.sArgs_default_motor.gear_ratio);
motorControl.add_to_commandlist(sprintf('#%du=%d\r' , this.motorID, stepspersecond));
% Calculate and set upper speed:
stepspersecond = round(this.sArgs_default_motor.speed/0.9*this.sArgs_default_motor.gear_ratio);
motorControl.add_to_commandlist(sprintf('#%do=%d\r' , this.motorID, stepspersecond));
% set decel to a high value so the switch is not overrun
motorControl.add_to_commandlist(sprintf('#%d:decel1%.0f\r' , this.motorID,100));
% Start reference move:
motorControl.add_to_commandlist(sprintf('#%dA\r' , this.motorID));
......@@ -192,6 +221,21 @@ classdef itaMotorNanotec_HRTFarc < itaMotorNanotec
methods(Hidden = true)
function this = allowMoveOverRefButton(this,value)
motorControl = this.mMotorControl;
if value
motorControl.sendControlSequenceAndPrintResults('l17442');
else
motorControl.sendControlSequenceAndPrintResults('l5154');
end
% Frei rckwrts
% 5154
% Stop
% 9250
end
function ret = prepare_move(this, angle, varargin)
% This function prepares the moves of the turntable, counterclockwise for a negative
% angle and clockwise for a positive angle.
......@@ -297,7 +341,7 @@ classdef itaMotorNanotec_HRTFarc < itaMotorNanotec
% Choose ramp mode: (0=trapez, 1=sinus-ramp, 2=jerkfree-ramp):
motorControl.add_to_commandlist(sprintf('#%d:ramp_mode=%d\r', this.motorID, this.sArgs_motor.ramp_mode));
% % Set maximum acceleration jerk:
motorControl.add_to_commandlist(sprintf('#%d:b=1\r' , this.motorID));
motorControl.add_to_commandlist(sprintf('#%d:b=4\r' , this.motorID));
% % Use acceleration jerk as braking jerk:
motorControl.add_to_commandlist(sprintf('#%d:B=0\r' , this.motorID));
% Closed_loop?
......@@ -414,7 +458,7 @@ classdef itaMotorNanotec_HRTFarc < itaMotorNanotec
% Set acceleration ramp directly
motorControl.add_to_commandlist(sprintf('#%d:accel%.0f\r' , this.motorID, this.sArgs_motor.acceleration_ramp));
% Brake ramp:
motorControl.add_to_commandlist(sprintf('#%dB0\r' , this.motorID));
motorControl.add_to_commandlist(sprintf('#%d:decel1%.0f\r' , this.motorID,this.sArgs_motor.decceleration_ramp));
% Zero menas equal to acceleration ramp!
ret = true;
......
......@@ -99,6 +99,10 @@ classdef itaMotorNanotec_Slayer < itaMotorNanotec
end
function disableReference(this,value)
end
function this = moveToReferencePosition(this)
% Prepare reference move (arm)
......
......@@ -136,6 +136,9 @@ classdef itaMotorNanotec_Turntable < itaMotorNanotec
this.mMotorControl.add_to_commandlist(sprintf('#%dA\r' , this.motorID));
end
function disableReference(this,value)
end
function started = prepareMove(this,position,varargin)
......
......@@ -209,12 +209,14 @@ classdef test_itaEimarMotorControl < itaMeasurementTasksScan
speed = 360/(numRepetitions*timePerRepetition);
% preangletime
preAngleTime = 2/64*numRepetitions; % it takes 2 seconds to start recording
preAngle = preAngleTime*speed;
preAngle = 45;
preAngleTime = preAngle/speed; % it takes 2 seconds to start recording
preAngle = min(preAngle,15);
preAngle = max(preAngle,8);
numTotalRepetitions = numRepetitions+ceil(preAngleTime/(timePerRepetition))+9;
postAngle = 10;
postAngleTime = postAngle/speed;
additionalReps = ceil((postAngleTime+preAngleTime + 1)/timePerRepetition);
numTotalRepetitions = numRepetitions+additionalReps;
this.measurementSetup.repetitions = numTotalRepetitions;
%prepare motors for continuous measurement
......@@ -236,7 +238,7 @@ classdef test_itaEimarMotorControl < itaMeasurementTasksScan
function [result, result_raw] = runContinuousMeasurement(this)
this.mMotorControl.setWait(false);
this.mMotorControl.startContinuousMoveNow;
pause(1);
pause(0.1);
result_raw = this.measurementSetup.run_raw_imc;
result = this.measurementSetup.deconvolve(result_raw);
% this.stop;
......
......@@ -151,7 +151,7 @@ classdef itaEimar < itaMeasurementTasksScan
sArgs_default_turntable = struct( ...
'wait', true, ...
'speed', 5, ...
'speed', 2, ...
'VST', 'adaptiv', ...
'limit', false, ...
'continuous', false, ...
......
......@@ -455,7 +455,7 @@ classdef itaMSTFinterleaved < itaMSTF
inputvec = this.inputChannels;
% Use first inputchannel!
this.inputChannels = inputvec(1);
% Measure nonlins fr alle LS einzeln:
% Measure nonlins f???r alle LS einzeln:
for idx = 1:numel(outputvec)
this.outputChannels = outputvec(idx);
nonlinearities = this.run_HD(varargin{:});
......@@ -643,8 +643,8 @@ classdef itaMSTFinterleaved < itaMSTF
resultsMI(index) = result;
resultsMI(index).timeData = timeData(:,index:nOutputChannels:end);
repmatFactor = resultsMI(index).nChannels/result.nChannels;
resultsMI(index).channelNames = repmat(result.channelNames,repmatFactor,1);
resultsMI(index).channelUnits = repmat(result.channelUnits,repmatFactor,1);
resultsMI(index).channelNames = repelem(result.channelNames,repmatFactor,1);
resultsMI(index).channelUnits = repelem(result.channelUnits,repmatFactor,1);
end
result = resultsMI;
else
......