function y = desamplify(x, opt)
%samplify Decompress signal.
% y = desamplify(x,opt) decompresses a vector of samples using the
% settings given in the Samplify configuration structure opt. The vector
% vector x is samplified (compressed) data. The configuration
% structure *must* contain data for two fields:
%
% 1) opt.orig_nsamps: # samples in original (uncompressed) signal
% 2) opt.InputDataType: one of 'int8','uint8','int16','uint16',
% the data type of the original signal
%
% Typically one does not use samplifyOptions to create opt, and instead
% uses what the samplify compression function returns. The output y will
% be a one-dimensional row vector, whose MATLAB type will match the
% dynamic range of the original uncompressed signal. For example, if the
% dynamic range of the original signal was [0,255] then y will be of type
% UINT8. Likewise, if the original dynamic range was [-32767,32768] then
% then class(y) will be 'int16'.
%
% For example,
%
% [c,opt] = samplify(sig, samplifyOptions('Mode','lossless'));
% sig_prime = desamplify(sig, opt);
%
% 1st losslessy compresses the signal referenced by sig, and then turns
% around and decompresses this signal. There should be no difference
% between sig and sign_prime.
%
% See also SAMPLIFYOPTIONS, SAMPLIFY
% Copyright 2005 Samplify Systems LLC
% Revision: 1.0 (2005/11/23)
x = sanity_check_x(x); % will convert to INT16 if it isn't already
sanity_check_options(opt);
y = samplify_mex(2, x, opt.orig_nsamps, opt.InputDataType);
if isfield(opt, 'FloatingPointNormalization')
% the original input was a floating-point vector, so here we simply
% march through each of the blocks and apply the normalization and cast
% back to floating-point.
[nwin, nblocks, istart, iend] = block_info(length(y));
if nblocks ~= length(opt.FloatingPointNormalization)
error(sprintf('Only %d scale factors? There should be %d.', ...
length(opt.FloatingPointNormalization), nblocks));
end
y = double(y);
for iblock = 1:nblocks
idx = [istart(iblock):iend(iblock)];
y(idx) = y(idx) .* (opt.FloatingPointNormalization(iblock)/32767);
end
end
function x = sanity_check_x(x)
%
% SANITY_CHECK_X
%
if ~isnumeric(x)
error('Input samples have to be a numeric array.');
end
if ndims(x) > 2
error('Input samples must be a 1xN or Nx1 vector.');
else
[M N] = size(x);
if 1~=M & 1~=N
error('Input samples must be a 1xN or Nx1 vector.');
end
end
if ~isa(x,'int16') & ~isa(x,'double')
error('Invalid data type for the input compressed array.');
else
if isa(x,'double')
minimum = min(x);
maximum = max(x);
if minimum<-32768 | maximum>32767
error('Detected out-of-range values in samplified array');
end
x = int16(x);
end
end
function sanity_check_options(options)
%
% SANITY_CHECK_OPTIONS
%
if ~isstruct(options)
error('Malformed samplify options structure.');
end
% all we need are two fields
if ~isfield(options, 'orig_nsamps')
error('Samplify options missing required field orig_nsamples');
end
if ~isfield(options, 'InputDataType')
error('Samplify options missing required field InputDataType');
else
% validate the actual contents of InputDataType
if ~ischar(options.InputDataType)
error('Input data type must be a string.');
end
if ~strcmpi(options.InputDataType, 'uint8') & ...
~strcmpi(options.InputDataType, 'int8') & ...
~strcmpi(options.InputDataType, 'uint16') & ...
~strcmpi(options.InputDataType, 'int16')
error(['Unknown data type specification ' options.InputDataType]);
end
end