# v_enframe

## PURPOSE

V_ENFRAME split signal up into (overlapping) frames: one per row. [F,T]=(X,WIN,HOP)

## SYNOPSIS

function [f,t,w]=v_enframe(x,win,hop,m,fs)

## DESCRIPTION

    V_ENFRAME split signal up into (overlapping) frames: one per row. [F,T]=(X,WIN,HOP)

     Usage:  (1) f=v_enframe(x,n)                          % split into frames of length n
             (2) f=v_enframe(x,hamming(n,'periodic'),n/4)  % use a 75% overlapped Hamming window of length n
             (3) calculate spectrogram in units of power per Hz

                   W=hamming(NW);                      % analysis window (NW = fft length)
                   P=v_enframe(S,W,HOP,'sdp',FS);        % computer first half of PSD (HOP = frame increment in samples)

             (3) frequency domain frame-based processing:

                   S=...;                              % input signal
                   OV=2;                               % overlap factor of 2 (4 is also often used)
                   NW=160;                             % DFT window length
                   W=sqrt(hamming(NW,'periodic'));     % omit sqrt if OV=4
                   [F,T,WS]=v_enframe(S,W,1/OV,'fa');    % do STFT: one row per time frame, +ve frequencies only
                   ... process frames ...
                   X=v_overlapadd(v_irfft(F,NW,2),WS,HOP); % reconstitute the time waveform with scaled window (omit "X=" to plot waveform)

      Inputs:   x    input signal
              win    window or window length in samples
              hop    frame increment or hop in samples or fraction of window [window length]
                m    mode input:
                      'z'  zero pad to fill up final frame
                      'r'  reflect last few samples for final frame
                      'A'  calculate the t output as the centre of mass
                      'E'  calculate the t output as the centre of energy
                      'f'  perform a 1-sided dft on each frame (like v_rfft)
                      'F'  perform a 2-sided dft on each frame using fft
                      'p'  calculate the 1-sided power/energy spectrum of each frame
                      'P'  calculate the 2-sided power/energy spectrum of each frame
                      'a'  scale window to give unity gain with overlap-add
                      's'  scale window so that power is preserved: sum(mean(v_enframe(x,win,hop,'sp'),1))=mean(x.^2)
                      'S'  scale window so that total energy is preserved: sum(sum(v_enframe(x,win,hop,'Sp'),2),1)=sum(x.^2)
                      'd'  make options 's' and 'S' give power/energy per Hz: sum(mean(v_enframe(x,win,hop,'spd',fs),1))*fs/length(win)=mean(x.^2)
               fs    sample frequency (only needed for 'd' option) [1]

     Outputs:   f    enframed data - one frame per row
                t    fractional time in samples at the centre of each frame
                     with the first sample being 1.
                w    window function used including scaling

     By default, the number of frames will be rounded down to the nearest
     integer and the last few samples of x() will be ignored unless its length
     is lw more than a multiple of hop. If the 'z' or 'r' options are given,
     the number of frame will instead be rounded up and no samples will be ignored.

     The scaling options available in the 'm' input imply the follwoing approximate
     constraints which are only exact if the window is rectangular with no overlap
     and the input length is an exact number of frames.
     In the expressions below, ff=sum(f,2), lw=frame length, win is the unscaled window
           'P','P'         mean(ff)            = mean(x.^2) * lw*sum(win.^2)
           'ps','Ps'       mean(ff)            = mean(x.^2)
           'pS','PS'       sum(ff)             = sum(x.^2)
           'psd','Psd'     mean(ff) * fs/lw    = mean(x.^2)
           'pSd','PSd'     sum(ff) * fs/lw     = sum(x.^2) / fs

## CROSS-REFERENCE INFORMATION

This function calls:

This function is called by:

- v_earnoise V_EARNOISE Add noise to simulate the hearing threshold of a listener [Y,X,V]=(S,FS,M,SPL)
- v_melcepst V_MELCEPST Calculate the mel cepstrum of a signal C=(S,FS,W,NC,P,N,INC,FL,FH)
- v_modspect V_MODSPECT Calculate the modulation spectrum of a signal C=(S,FS,W,NC,P,N,INC,FL,FH)
- v_specsub V_SPECSUB performs speech enhancement using spectral subtraction [SS,ZO]=(S,FSZ,P)
- v_spendred V_SPENDRED Speech Enhancement and Dereverberation by Doire
- v_spgrambw V_SPGRAMBW Draw spectrogram [T,F,B]=(s,fs,mode,bw,fmax,db,tinc,ann)
- v_ssubmmse V_SSUBMMSE performs speech enhancement using mmse estimate of spectral amplitude or log amplitude [SS,ZO]=(S,FSZ,PP)
- v_ssubmmsev V_SSUBMMSE performs speech enhancement using mmse estimate of spectral amplitude or log amplitude [SS,ZO]=(S,FSZ,P)
- v_vadsohn V_VADSOHN implements a voice activity detector [VS,ZO]=(S,FSZ,M,P)

## SOURCE CODE

    0001 function [f,t,w]=v_enframe(x,win,hop,m,fs)
    0002 %V_ENFRAME split signal up into (overlapping) frames: one per row. [F,T]=(X,WIN,HOP)
    0003 %
    0004 % Usage:  (1) f=v_enframe(x,n)                          % split into frames of length n
    0005 %         (2) f=v_enframe(x,hamming(n,'periodic'),n/4)  % use a 75% overlapped Hamming window of length n
    0006 %         (3) calculate spectrogram in units of power per Hz
    0007 %
    0008 %               W=hamming(NW);                      % analysis window (NW = fft length)
    0009 %               P=v_enframe(S,W,HOP,'sdp',FS);        % computer first half of PSD (HOP = frame increment in samples)
    0010 %
    0011 %         (3) frequency domain frame-based processing:
    0012 %
    0013 %               S=...;                              % input signal
    0014 %               OV=2;                               % overlap factor of 2 (4 is also often used)
    0015 %               NW=160;                             % DFT window length
    0016 %               W=sqrt(hamming(NW,'periodic'));     % omit sqrt if OV=4
    0017 %               [F,T,WS]=v_enframe(S,W,1/OV,'fa');    % do STFT: one row per time frame, +ve frequencies only
    0018 %               ... process frames ...
    0019 %               X=v_overlapadd(v_irfft(F,NW,2),WS,HOP); % reconstitute the time waveform with scaled window (omit "X=" to plot waveform)
    0020 %
    0021 %  Inputs:   x    input signal
    0022 %          win    window or window length in samples
    0023 %          hop    frame increment or hop in samples or fraction of window [window length]
    0024 %            m    mode input:
    0025 %                  'z'  zero pad to fill up final frame
    0026 %                  'r'  reflect last few samples for final frame
    0027 %                  'A'  calculate the t output as the centre of mass
    0028 %                  'E'  calculate the t output as the centre of energy
    0029 %                  'f'  perform a 1-sided dft on each frame (like v_rfft)
    0030 %                  'F'  perform a 2-sided dft on each frame using fft
    0031 %                  'p'  calculate the 1-sided power/energy spectrum of each frame
    0032 %                  'P'  calculate the 2-sided power/energy spectrum of each frame
    0033 %                  'a'  scale window to give unity gain with overlap-add
    0034 %                  's'  scale window so that power is preserved: sum(mean(v_enframe(x,win,hop,'sp'),1))=mean(x.^2)
    0035 %                  'S'  scale window so that total energy is preserved: sum(sum(v_enframe(x,win,hop,'Sp'),2),1)=sum(x.^2)
    0036 %                  'd'  make options 's' and 'S' give power/energy per Hz: sum(mean(v_enframe(x,win,hop,'spd',fs),1))*fs/length(win)=mean(x.^2)
    0037 %           fs    sample frequency (only needed for 'd' option) [1]
    0038 %
    0039 % Outputs:   f    enframed data - one frame per row
    0040 %            t    fractional time in samples at the centre of each frame
    0041 %                 with the first sample being 1.
    0042 %            w    window function used including scaling
    0043 %
    0044 % By default, the number of frames will be rounded down to the nearest
    0045 % integer and the last few samples of x() will be ignored unless its length
    0046 % is lw more than a multiple of hop. If the 'z' or 'r' options are given,
    0047 % the number of frame will instead be rounded up and no samples will be ignored.
    0048 %
    0049 % The scaling options available in the 'm' input imply the follwoing approximate
    0050 % constraints which are only exact if the window is rectangular with no overlap
    0051 % and the input length is an exact number of frames.
    0052 % In the expressions below, ff=sum(f,2), lw=frame length, win is the unscaled window
    0053 %       'P','P'         mean(ff)            = mean(x.^2) * lw*sum(win.^2)
    0054 %       'ps','Ps'       mean(ff)            = mean(x.^2)
    0055 %       'pS','PS'       sum(ff)             = sum(x.^2)
    0056 %       'psd','Psd'     mean(ff) * fs/lw    = mean(x.^2)
    0057 %       'pSd','PSd'     sum(ff) * fs/lw     = sum(x.^2) / fs
    0058
    0059 % Bugs/Suggestions:
    0060 %  (1) Possible additional mode options:
    0061 %        'u'  modify window for first and last few frames to ensure WOLA
    0062 %        'a'  normalize window to give a mean of unity after overlaps
    0063 %        'e'  normalize window to give an energy of unity after overlaps
    0064 %        'wm' use Hamming window
    0065 %        'wn' use Hanning window
    0066 %        'x'  hoplude all frames that hoplude any of the x samples
    0067
    0068 %       Copyright (C) Mike Brookes 1997-2014
    0069 %      Version: $Id: v_enframe.m 10865 2018-09-21 17:22:45Z dmb $
    0070 %
    0071 %   VOICEBOX is a MATLAB toolbox for speech processing.
    0072 %   Home page: http://www.ee.ic.ac.uk/hp/staff/dmb/voicebox/voicebox.html
    0073 %
    0074 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    0075 %   This program is free software; you can redistribute it and/or modify
    0076 %   it under the terms of the GNU Lesser General Public License as published by
    0077 %   the Free Software Foundation; either version 3 of the License, or
    0078 %   (at your option) any later version.
    0079 %
    0080 %   This program is distributed in the hope that it will be useful,
    0081 %   but WITHOUT ANY WARRANTY; without even the implied warranty of
    0082 %   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    0083 %   GNU Lesser General Public License for more details.
    0084 %
    0085 %   You can obtain a copy of the GNU Lesser General Public License from
    0086 %   https://www.gnu.org/licenses/ .
    0087 %
    0088 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    0089
    0090 nx=length(x(:));
    0091 if nargin<2 || isempty(win)
    0092     win=nx;
    0093 end
    0094 if nargin<4 || isempty(m)
    0095     m='';
    0096 end
    0097 nwin=length(win);
    0098 if nwin == 1
    0099     lw = win;
    0100     w = ones(1,lw);
    0101 else
    0102     lw = nwin;
    0103     w = win(:).'; % force w to be a row vector
    0104 end
    0105 if (nargin < 3) || isempty(hop)
    0106     hop = lw;                   % if no hop given, make non-overlapping
    0107 elseif hop<1
    0108     hop=round(lw*hop);          % if hop<1 then it is a fraction of lw
    0109 end
    0110 wsc=1;                          % window scale factor
    0111 if any(m=='a')
    0112     wsc=sqrt(hop/(w*w'));       % scale to give unity gain for overlap-add
    0113 elseif any(m=='d')
    0114     if nargin<5 || isempty(fs)
    0115         fs=1;                   % default is fs=1
    0116     end
    0117     if any(m=='s')
    0118         wsc=sqrt(1/(w*w'*fs));
    0119     elseif any(m=='S')
    0120         wsc=sqrt(hop/(w*w'))/fs;
    0121     end
    0122 else
    0123     if any(m=='s')
    0124         wsc=sqrt(1/(w*w'*lw));
    0125     elseif any(m=='S')
    0126         wsc=sqrt(hop/(w*w'*lw));
    0127     end
    0128 end
    0129 nli=nx-lw+hop;
    0130 nf = max(fix(nli/hop),0);   % number of full frames
    0131 na=nli-hop*nf+(nf==0)*(lw-hop);       % number of samples left over
    0132 fx=nargin>3 && (any(m=='z') || any(m=='r')) && na>0; % need an extra row
    0133 f=zeros(nf+fx,lw);
    0134 indf= hop*(0:(nf-1)).';
    0135 inds = (1:lw);
    0136 if fx
    0137     f(1:nf,:) = x(indf(:,ones(1,lw))+inds(ones(nf,1),:));
    0138     if any(m=='r')
    0139         ix=1+mod(nf*hop:nf*hop+lw-1,2*nx);
    0140         f(nf+1,:)=x(ix+(ix>nx).*(2*nx+1-2*ix));
    0141     else
    0142         f(nf+1,1:nx-nf*hop)=x(1+nf*hop:nx);
    0143     end
    0144     nf=size(f,1);
    0145 else
    0146     f(:) = x(indf(:,ones(1,lw))+inds(ones(nf,1),:));
    0147 end
    0148 w=wsc*w;                           % scale the window
    0149 if (nwin > 1)                       % if we have a non-unity window
    0150     f = f .* repmat(w,nf,1);        % ... multiply by the scaled window
    0151 else                                % else if the unscaled window is unit-rectangular
    0152     f = wsc*f;                      % ... just multiply by the scale factor
    0153 end
    0154 if any(lower(m)=='p')               % 'pP' = calculate the power spectrum
    0155     f=fft(f,[],2);                  % complex spectrum
    0156     f=real(f.*conj(f));             % power spectrum
    0157     if any(m=='p')                  % if need a 1-sided spectrum
    0158         imx=fix((lw+1)/2);          % highest replicated frequency
    0159         f(:,2:imx)=f(:,2:imx)+f(:,lw:-1:lw-imx+2); % double all except DC and Nyquist
    0160         f=f(:,1:fix(lw/2)+1);       % keep only the positive frequencies
    0161     end
    0162 elseif any(lower(m)=='f')           % 'fF' = take the DFT
    0163     f=fft(f,[],2);
    0164     if any(m=='f')
    0165         f=f(:,1:fix(lw/2)+1);
    0166     end
    0167 end
    0168 if nargout>1
    0169     if any(m=='E')
    0170         t0=sum((1:lw).*w.^2)/sum(w.^2);
    0171     elseif any(m=='A')
    0172         t0=sum((1:lw).*w)/sum(w);
    0173     else
    0174         t0=(1+lw)/2;
    0175     end
    0176     t=t0+hop*(0:(nf-1)).';
    0177 end
    0178
    0179