function compute_ssm_parameters( pointset_file )
  
  if nargin < 1
    error( [ mfilename ' needs 1 input parameter: pointset_file.' ] );
  end
  
  dbstop error
  VERBOSE = 1;  % Show the expected time of completion
  
  % Load synthetic train data
  load( pointset_file, 'pointset' );
    
  if VERBOSE
    disp( [ mfilename ': loaded "' pointset_file '".' ] );
  end
  
  ssm.framelength = 512;   % Samples
  ssm.fs          = 16000; % Hz
  ssm.c           = 342;   % m/s
  
  % File where centroids ( ssm ) will be stored
  [ tmp, a_name, an_ext ] = fileparts( pointset_file );
  SSM_FILE = sprintf( 'DATA/ssm_parameters_%d_%d_%d-%s.mat', ssm.framelength, ssm.fs, ssm.c, a_name );
  
  % Done already?
  if exist( SSM_FILE, 'file' )
    % Yes
    disp( sprintf( [ '\n' mfilename ': file "' SSM_FILE '" already exists. Skipped.\n' ] ) );
    return;
    
  else
    % No
    system( [ 'echo > ' SSM_FILE ] );
    if VERBOSE
      disp( [ mfilename ': direct computation of "A", "B" and "Z = A * exp( j B )" parameters.' ] );
    end

  end
  
  nchannels = size( pointset.geometry, 2 );
  ssm.pairs = nchoosek( 1:nchannels, 2 );
  npairs = size( ssm.pairs, 1 );

  % Define digital frequencies
  
  w = 2 * pi * (1:ssm.framelength) / ( 2 * ssm.framelength );
  
  % Where the "A" and "B" parameters will be stored
  
  ssm.A = repmat( NaN, [ ssm.framelength, npairs, pointset.nsectors ] );
  ssm.B = repmat( NaN, [ ssm.framelength, npairs, pointset.nsectors ] );
  ssm.Z = repmat( NaN, [ ssm.framelength, npairs, pointset.nsectors ] );
  
  if VERBOSE
    chrono = chrono_start( pointset.nsectors * npairs, 60 );
  end
  
  
  % Also store other stuff
  ssm.w = w;
  ssm.geometry = pointset.geometry;
  
  
  % For each sector k,
  % for each microphone pair p,
  % for each frequency bin f,
  % compute the parameters A(f,p,k), B(f,p,k), Z(f,p,k)
  
  for a = 1:pointset.nsectors
    
    for b = 1:npairs
      
      % Time-delays
      td = location_to_timedelay( pointset.geometry, ssm.pairs( b, : ), pointset.x( :,:,a ), ssm.fs, ssm.c );
      
      for c = 1:ssm.framelength
	
	% Training data: phases between pairs of microphones
	ph = w( c ) * td;
	
	% Average in complex plane
	z = mean( exp( j*ph ) );
	
	% Store module, argument and z
	ssm.A( c,b,a ) = abs( z );
	ssm.B( c,b,a ) = angle( z );
	ssm.Z( c,b,a ) = z;
	
      end  % Loop through frequency bins
      
      if VERBOSE
	chrono = chrono_check( chrono, (a-1) * npairs + b );
      end

    end  % Loop through microphone pairs
    
  end  % Loop through sectors
     
  chrono_stop( chrono );
  
  % Also store the definition of the sectors
  
  for a = 1:pointset.nsectors

    ssm.sector( a ).az_min = pointset.sector_az_min( a );
    ssm.sector( a ).az_max = pointset.sector_az_max( a );
    
    ssm.sector( a ).el_min = pointset.sector_el_min( a );
    ssm.sector( a ).el_max = pointset.sector_el_max( a );
    
    ssm.sector( a ).r_min  = pointset.sector_r_min( a );
    ssm.sector( a ).r_max  = pointset.sector_r_max( a );

  end
  
  % Save result
  
  save( SSM_FILE, 'ssm' );
  if VERBOSE
    disp( [ mfilename ' wrote out "' SSM_FILE '".' ] );
  end
  