function [fid, err, total_samples] = append_wavedat(wavefile, fmt, data)

% APPEND_WAVEDAT: APPEND WAVE data chunk
% Assumes that the header of the wave file is already written.
% wavefile is the name of the output file.
% Requires <wave-format> structure to be passed.
% In the case that data is a vector and two channels, the correct
% alignement of left and right channel in data is assumed! For each
% sample (left channel sample, right channel sample).  
%
% See also WAVWRITE_HEADER.
%
% Copyright (c) 2001 by Fraunhofer-IGD
% $Revision: 1.0 $  $Date: 2001/07/12 $
%
% M.Arnold, 07/01

err = '';

% Open file for output:
[fid, err] = OpenWaveAppend(wavefile);
error(err);

if fmt.wFormatTag == 1,

  % PCM Format
  data = PCM_Quantize(data, fmt);
   
  switch fmt.nBitsPerSample
   case 8,
	dtype='uchar'; % unsigned 8-bit
   case 16,
	dtype='short'; % signed 16-bit
   otherwise,
	err = 'Invalid number of bits specified.'; return;
  end
   
  % If input is a vector, force it to be a column:
  if ndims(data) > 2,
	error('Data array cannot be an N-D array in function append_wavedat');
  end

  % Check if data is a row vector.
  if size(data, 1) == 1, % data is a row vector
	data = data(:); % data(:) is all elements of data, regarded as a single
                    % column.
	total_samples = length(data);
  else % data is column vector or 2-dim matrix 
	total_samples = size(data, 1)*size(data, 2);
  end
	
  % Transpose data and reshape to vector to get the right alignement of
  % the samples for left and right channel if data is a matrix.  
  if (fwrite(fid, reshape(data',total_samples,1), dtype) ~= total_samples),
	err = 'Failed to write PCM data samples.'; return;
  end
  
  % Determine # bytes/sample - format requires rounding
  %  to next integer number of bytes. ceil rounds to the nearest int
  %  towards infinity.
  BytesPerSample = ceil(fmt.nBitsPerSample/8);
  
  % Determine if a pad-byte must be appended to data chunk. Necessary if
  % data does not end on an even byte boundary. Don't know exactly why!
  if rem(total_samples*BytesPerSample, 2) ~= 0,
	fwrite(fid,0,'uchar');
  end
  
else
  % Unknown wave-format for data.
  err = 'Unsupported data format.';
end

return

% end of append_wavedat()

% ------------------------------------------------------------------------
% Private functions:
% ------------------------------------------------------------------------

% ------------------------------------------------------------------------
function [fid, err] = OpenWaveAppend(wavefile)
% OpenWaveAppend
%   Open WAV file for appending.
%   If filename does not contain an extension, add ".wav"

fid = [];
err = '';
if ~isstr(wavefile),
   err='Wave file name must be a string.'; return;
end
if isempty(findstr(wavefile,'.')),
  wavefile=[wavefile '.wav'];
end
% Open file, little-endian:
[fid,err] = fopen(wavefile,'ab','l');

return


% -----------------------------------------------------------------------
function y = PCM_Quantize(x, fmt)
% PCM_Quantize:
%   Scale and quantize input data, from [-1, +1] range to
%   either an 8- or 16-bit data range. 

% Clip data to normalized range [-1,+1]:
ClipMsg  = ['Data clipped during write to file:' fmt.filename];
ClipWarn = 0;

% Determine slope (m) and bias (b) for data scaling:
nbits = fmt.nBitsPerSample;
m = 2.^(nbits-1);

switch nbits
case 8,
   b=128; % Storing 8-bit samples as unsigned bytes [0, 255]
case 16,
   b=0; % Storing 16-bit samples: 2's complement signed int [-32768, 32767]
otherwise,
   error('Invalid number of bits specified - must be 8 or 16.');
end

% Round to nearest integer.
y = round(m .* x + b);

% Determine quantized data limits, based on the
% presumed input data limits of [-1, +1]:
ylim = [-1 +1];
qlim = m * ylim + b;

%ALTERAMOS ALTERAMOS ALTERAMSO!!!!!!
%qlim(2) = qlim(2)-1; % upper limit

qlim(2) = qlim(2); % upper limit



% Clip data to quantizer limits:
i = find(y < qlim(1)); 
if ~isempty(i), % y < lower limit 
   warning(ClipMsg); ClipWarn=1;
   y(i) = qlim(1);
end

i = find(y > qlim(2)); 
if ~isempty(i),% y > upper limit
   if ~ClipWarn, warning(ClipMsg); end
   y(i) = qlim(2);
end

return

% end of PCM_Quantize()

% end of append_wavedat.m






