% FUNCTION P = BINSEG2WAV( P, BINSEG )
%
% To separate speech and silence into 2 WAV files.
% 
% Input is :
% - one WAV file ( name specified in P )
% - a frame-level sp/sil classifiction 
%   ( specified in BINSEG, possibly n_speaker classifications ).
%
% Output is 2 * n_speaker WAV files.
%
% P an object containing parameters.
% BINSEG a n_speakers - by - n_frames matrix of 0's and 1's.
% ( 0 for silent frame, 1 for speech frame ).
% Returned P contains output filenames.
% 
% Typical use
% 
%   binseg2wav( p, low_energy( [], e ) );
%
% Questions? lathoud@idiap.ch
% version 1 030728

function binseg2wav( p, binseg )

  % Parameters
  
  if nargin < 2
    error( 'binseg2wav needs 2 parameters' );
  end
  
  required_param = { 'in_name', 'frame_shift_sec' };
  check_param( required_param, fieldnames( p ) );

  n_speakers = size( binseg, 1 );
  n_frames = size( binseg, 2 );
  
  p_default.in_dir = '';
  p_default.out_dir = '';
  p_default.out_name_speech  = {};
  p_default.out_name_silence = {};
  p_default.out_fs = [];
  p_default.frame_length_sec = 2 * p.frame_shift_sec;
  p_default.verbose = 1;
  
  p = fill_default( p, p_default );
  
  if isempty( p.out_name_speech )
    if n_speakers < 2
      p.out_name_speech{ 1 } = [ strtok( p.in_name, '.' ) '_speech.wav' ];
    else
      for a = 1:n_speakers
	p.out_name_speech{ a } = ...
	    [ strtok( p.in_name, '.' ) sprintf( '_%d_speech.wav', a ) ];
      end
    end
  end
  
  if length( p.out_name_speech ) ~= n_speakers
    error( sprintf( 'binseg2wav was expecting %d elements in p.out_name_speech',n_speakers));
  end
  
  if isempty( p.out_name_silence )
    if n_speakers < 2
      p.out_name_silence{ 1 } = [ strtok( p.in_name, '.' ) '_silence.wav' ];
    else
      for a = 1:n_speakers
	p.out_name_silence{ a } = ...
	    [ strtok( p.in_name, '.' ) sprintf( '_%d_silence.wav', a ) ];
      end
    end
  end
  
  if length( p.out_name_silence ) ~= n_speakers
    error( sprintf( 'binseg2wav was expecting %d elements in p.out_name_silence',n_speakers));
  end

  % Check files
  
  for a = 1:n_speakers
    out_filename_speech{ a } = fullfile( p.out_dir, p.out_name_speech{ a } );
    fid = fopen( out_filename_speech{ a }, 'w' );
    if fid < 0
      error( [ 'binseg2wav could not write-open ' ...
	    out_filename_speech{ a } ] );
    end
    fclose(fid);
  end
    
  for a = 1:n_speakers
    out_filename_silence{ a } = fullfile( p.out_dir, p.out_name_silence{ a } );
    fid = fopen( out_filename_silence{ a }, 'w' );
    if fid < 0
      error( [ 'binseg2wav could not write-open ' ...
	    out_filename_silence{ a } ] );
    end
    fclose(fid);
  end
  
  in_filename = fullfile( p.in_dir, p.in_name );
  [ y, fs, n_bits ] = wavread( in_filename );

  if isempty( p.out_fs )
    p.out_fs = fs;
  end
  
  if p.verbose
    disp( 'binseg2wav parameters:' );
    disp( p );
  end
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  % Do it!
  
  frame_shift_samples = round( p.frame_shift_sec * fs );
  frame_length_samples = round( p.frame_length_sec * fs );
  
  for a = 1:n_speakers

    % Build two waveforms: one for speech, one for silence
    
    y_sp = [];
    y_sil = [];
    current_frame = 1;
    while current_frame <= n_frames
      
      % current segment
      is_speech  = binseg( a, current_frame );
      aux = find( binseg( a, current_frame+1:end ) ~= is_speech );
      if isempty( aux )
	next_frame = n_frames + 1;
      else
	next_frame = current_frame + aux( 1 );
      end
      
      start_sample = 1 + ( current_frame - 1 ) * frame_shift_samples;
      end_sample = frame_length_samples + ...
	  (next_frame - 2) * frame_shift_samples;
      
      z = resample( y( start_sample:end_sample, : ), p.out_fs, fs );
      if is_speech
	y_sp = [ y_sp; z ];
      else
	y_sil = [ y_sil; z ];
      end
  
      % Next segment
      current_frame = next_frame;
      
    end
  
    % Make sure we are in [ -1 +1 ];
    the_max = max( max( abs( y_sp ) ), max( abs( y_sil ) ) );
    if the_max > 1
      y_sp = y_sp / the_max;
      y_sil = y_sil / the_max;
    end
    
    % Write out the two waveforms for this speaker

    filename_speech  = fullfile( p.out_dir, p.out_name_speech{ a } );
    wavwrite( y_sp, p.out_fs, n_bits, filename_speech );
    
    filename_silence = fullfile( p.out_dir, p.out_name_silence{ a } );
    wavwrite( y_sil, p.out_fs, n_bits, filename_silence );
    
  end
  