www.pudn.com > ETSI_ES_202_212_software.rar > ParmInterface.c


/*===============================================================================
 *      ETSI ES 202 212   Distributed Speech Recognition
 *      Extended Advanced Front-End Feature Extraction Algorithm & Compression Algorithm
 *      Speech Reconstruction Algorithm.
 *      C-language software implementation                                      
 *      Version 1.1.1   October, 2003                                            
 *===============================================================================*/
/*-------------------------------------------------------------------------------
 *
 * FILE NAME: ParmInterface.c
 * PURPOSE: Processing one input frame in DoAdvProcess():
 *          DoNoiseSup(), DoWaveProc(), DoCompCeps(), DoPostProc(),
 *          and DoVADProc() are called.
 *
 *-------------------------------------------------------------------------------*/
/*-----------------
 * File Inclusions
 *-----------------*/
#include 
#include 
#include 

#include "ParmInterface.h"

/*--------------------------------------------
 * The followings include the module-specific 
 * and exported methods (or functions).
 *--------------------------------------------*/
#include "NoiseSupExports.h"
#include "WaveProcExports.h"
#include "CompCepsExports.h"
#include "PostProcExports.h"
#include "16kHzProcExports.h"
#include "VADExports.h"

/*----------------------------------------------------------------------------
 * FUNCTION NAME: AdvProcessAlloc
 *
 * PURPOSE:       Memory allocation of front end parameter structure     
 *
 * INPUT:
 *   SamplingFrequency     
 *
 * OUTPUT:
 *   pFEParX      Pointer to front end parameter structure
 *
 * RETURN VALUE:
 *   pFEParX      Pointer to front end parameter structure
 *   
 *---------------------------------------------------------------------------*/
FEParamsX* AdvProcessAlloc (int SamplingFrequency)
{
  FEParamsX *pFEParX = (FEParamsX *) calloc (1, sizeof (FEParamsX));

  pFEParX->DoNoiseSupAlloc = DoNoiseSupAlloc;
  pFEParX->DoNoiseSupInit = DoNoiseSupInit;
  pFEParX->DoNoiseSup = DoNoiseSup;
  pFEParX->DoNoiseSupDelete = DoNoiseSupDelete;

  pFEParX->DoWaveProcAlloc = DoWaveProcAlloc;
  pFEParX->DoWaveProcInit = DoWaveProcInit;
  pFEParX->DoWaveProc = DoWaveProc;
  pFEParX->DoWaveProcDelete = DoWaveProcDelete;

  pFEParX->DoCompCepsAlloc = DoCompCepsAlloc;
  pFEParX->DoCompCepsInit = DoCompCepsInit;
  pFEParX->DoCompCeps = DoCompCeps;
  pFEParX->DoCompCepsDelete = DoCompCepsDelete;

  pFEParX->DoPostProcAlloc = DoPostProcAlloc;
  pFEParX->DoPostProcInit = DoPostProcInit;
  pFEParX->DoPostProc = DoPostProc;
  pFEParX->DoPostProcDelete = DoPostProcDelete;

  pFEParX->DoVADProc = DoVADProc;
  pFEParX->DoVADDelete = DoVADDelete;
  pFEParX->DoVADInit   = DoVADInit;
  pFEParX->DoVADAlloc  = DoVADAlloc;
  pFEParX->DoVADFlush  = DoVADFlush;

  /*----------------------------------------------
   * allocate module-specific expansion structure
   *----------------------------------------------*/
  if (pFEParX->DoNoiseSupAlloc != NULL) pFEParX->NSX = pFEParX->DoNoiseSupAlloc ();
  if (pFEParX->DoWaveProcAlloc != NULL) pFEParX->WPX = pFEParX->DoWaveProcAlloc ();
  if (pFEParX->DoCompCepsAlloc != NULL) pFEParX->CCX = pFEParX->DoCompCepsAlloc ();
  if (pFEParX->DoPostProcAlloc != NULL) pFEParX->PPX = pFEParX->DoPostProcAlloc ();
  if (pFEParX->DoVADAlloc != NULL)  pFEParX->VADX = pFEParX->DoVADAlloc ();

  pFEParX->SamplingFrequency = SamplingFrequency;
  
  if (SamplingFrequency == 16000)
    {
	  pFEParX->SamplingFrequency = 8000;
	  pFEParX->Do16kHzProc = 1;
	  pFEParX->Do16kProcessing = Do16kProcessing;
	  pFEParX->Do16kProcDelete = Do16kProcDelete;
	  pFEParX->Do16kProcInit   = Do16kProcInit;
	  pFEParX->Do16kProcAlloc  = Do16kProcAlloc;
	  if (pFEParX->Do16kProcAlloc != NULL) pFEParX->pData16k = pFEParX->Do16kProcAlloc ();
    }
  else
	{
	  pFEParX->Do16kHzProc = 0;
	  pFEParX->Do16kProcessing = NULL;
	  pFEParX->Do16kProcDelete = NULL;
	  pFEParX->Do16kProcInit   = NULL;
	  pFEParX->Do16kProcAlloc  = NULL;
	}

  return pFEParX;
}

/*----------------------------------------------------------------------------
 * FUNCTION NAME: AdvProcessInit
 *
 * PURPOSE:       Initialization of front end parameter structure
 *
 * INPUT:
 *   pFEParX      Pointer to front end parameter structure
 *
 * OUTPUT:
 *   pFEParX      Pointer to front end parameter structure
 *
 * RETURN VALUE:
 *   
 *---------------------------------------------------------------------------*/
void AdvProcessInit (FEParamsX *pFEParX)
{
  if (pFEParX->SamplingFrequency == SAMPLING_FREQ_1 * 1000)
    {
	  pFEParX->FrameLength = FRAME_LENGTH;
	  pFEParX->FrameShift = FRAME_SHIFT;
	  pFEParX->FFTLength = FFT_LENGTH;
	  pFEParX->StartingFrequency = STARTING_FREQ;
    }
  else if (pFEParX->SamplingFrequency == SAMPLING_FREQ_3 * 1000)
	{
	  pFEParX->FrameLength = FRAME_LENGTH;
	  pFEParX->FrameShift = FRAME_SHIFT;
	  pFEParX->FFTLength = FFT_LENGTH;
	  pFEParX->StartingFrequency = STARTING_FREQ;
	}
  else
    {
	  fprintf (stderr, "ERROR:   Invalid sampling frequency '%d'!\r\n",
			   pFEParX->SamplingFrequency);
	  exit(0);
    }

  {
	int FrameShift = pFEParX->FrameShift;

	if (pFEParX->Do16kHzProc == 1) FrameShift *= 2;
	pFEParX->CurFrame = calloc (1, sizeof (pFEParX->CurFrame[0]) * FrameShift);
	if (pFEParX->CurFrame == NULL)
	  {
		fprintf (stderr, "ERROR:   Memory allocation error occured!\r\n");
		exit(0) ;
	  }
  }
  if (pFEParX->DoNoiseSupInit != NULL) pFEParX->DoNoiseSupInit (pFEParX);
  if (pFEParX->DoWaveProcInit != NULL) pFEParX->DoWaveProcInit (pFEParX);
  if (pFEParX->DoCompCepsInit != NULL) pFEParX->DoCompCepsInit (pFEParX);
  if (pFEParX->DoPostProcInit != NULL) pFEParX->DoPostProcInit (pFEParX);
  if (pFEParX->DoVADInit != NULL) pFEParX->DoVADInit (pFEParX);
  if (pFEParX->Do16kHzProc == 1)
	{
	  if (pFEParX->Do16kProcInit != NULL) pFEParX->Do16kProcInit (pFEParX);
	}

  pFEParX->denoisedBuf = 
	BufInAlloc (pFEParX->FrameLength +                         // at least FrameLength
				(pFEParX->FrameLength % pFEParX->FrameShift) + // integer number times FrameShift
   				1);                                            // for pre-emphasis
  pFEParX->offsetDenoisedFrame = -pFEParX->FrameLength;
  pFEParX->FrameCounter = 0;
  pFEParX->NonZeroFrameOnset = 0;
  pFEParX->ZeroFrameCounter = 0;
  pFEParX->NbSamplesToRead = pFEParX->FrameShift;
  if (pFEParX->Do16kHzProc == 1) 
	pFEParX->NbSamplesToRead  = 2 * pFEParX->FrameShift;
}

/*----------------------------------------------------------------------------
 * FUNCTION NAME: DoAdvProcess
 *
 * PURPOSE:       Processing for a frame 
 *
 * INPUT:
 *   CurrentFrame Current Frame to process     
 *   pFEParX      Pointer to front end parameter structure
 * OUTPUT:
 *   FeatureBuffer Buffer of features
 *
 * RETURN VALUE:
 *   XTRUE        If a feature frame is output
 *   FALSE        If no frame is output (due to delay)
 *
 *---------------------------------------------------------------------------*/
BOOLEAN DoAdvProcess (FILE_TYPE *CurrentFrame, 
					  X_FLOAT32 *FeatureBuffer,
					  FEParamsX *pFEParX) 
{
  int i;
  int FrameShift;
  X_FLOAT32 frameBuf[FRAME_BUF_SIZE + HP16k_MEL_USED];
  X_FLOAT32 *CurFrame;
  X_FLOAT32 *ptDenoised;

  float FrameCheck;

  long NonZeroFrameOnset;
  long ZeroFrameCounter;

  ZeroFrameCounter = pFEParX->ZeroFrameCounter;
  NonZeroFrameOnset = pFEParX->NonZeroFrameOnset;
  FrameShift  = pFEParX->FrameShift;
  if (pFEParX->Do16kHzProc == 1) 
	FrameShift  = 2 * pFEParX->FrameShift;

  /*-----------------------------------------------------------------
   * get the pointeur where to input new Frameshift denoised samples
   * shift left data in denoisedBuf by FrameShift
   * and returns pointer to the new available part of
   * denoisedBuf => (denoisedBuf->size - FrameShift + 1)
   *-----------------------------------------------------------------*/
  ptDenoised = BufInShiftToPut (pFEParX->denoisedBuf, pFEParX->FrameShift);

  CurFrame = pFEParX->CurFrame ;
  
  /*-------------------------------------------------
   * convert input samples from X_INT16 to X_FLOAT32
   *-------------------------------------------------*/
  FrameCheck = 0.0;
  for (i=0 ; iNonZeroFrameOnset = 1;

	  /*------------------------------------------------------------------------
	   * WARNING: 16kHz processing
	   * curFrame [0 to (pFEParX->FrameShift - 1)] contains 0-4kHz data
	   * pData16k->dataHP [0 to (pFEParX->FrameShift - 1)] contains
	   * 4-8kHz data shifted to 0-4kHz freq. range
	   *-------------------------------------------------------------------------*/
	  if (pFEParX->Do16kHzProc)
		pFEParX->Do16kProcessing (CurFrame, pFEParX->pData16k, FrameShift);

	  if (pFEParX->DoNoiseSup (CurFrame, ptDenoised, pFEParX))
		{
		  /*---------------------------------------------------------------------------
		   * the noise suppression module outputs "FrameShift" samples in denoisedBuf.
		   * following modules will be processed only when denoisedBuf will be full.
		   *---------------------------------------------------------------------------*/
		  if (pFEParX->offsetDenoisedFrame < 0) pFEParX->offsetDenoisedFrame += pFEParX->FrameShift;
		  if (pFEParX->offsetDenoisedFrame >= 0)
			{
			  BOOLEAN rVal = FALSE;


			  BufInGetLast (pFEParX->denoisedBuf, frameBuf, pFEParX->FrameLength + pFEParX->offsetDenoisedFrame + 1);

			  /*---------------------
			   * waveform processing
			   *---------------------*/
			  if (pFEParX->DoWaveProc) rVal = pFEParX->DoWaveProc (frameBuf+1, pFEParX);

			  /*----------------------
			   * cepstrum calculation
			   *----------------------*/
			  if (pFEParX->DoCompCeps) rVal = pFEParX->DoCompCeps (frameBuf+1, FeatureBuffer, pFEParX);
		  
			  /*-----------------
			   * post processing
			   *-----------------*/
			  if (pFEParX->DoPostProc) rVal = pFEParX->DoPostProc (FeatureBuffer, pFEParX);

			  /*-----
			   * VAD
			   *-----*/
			  if (pFEParX->DoVADProc)
				return pFEParX->DoVADProc (FeatureBuffer, pFEParX);
			  else
				return rVal;

			}
		  else
			return FALSE;
		}
	  else
		return FALSE;
	}
  else
	{
	  pFEParX->ZeroFrameCounter++;

	  /*-------------------------
	   * Create null MFCC vector
	   *-------------------------*/
	  for (i=0 ; i<=NUM_CEP_COEFF ; i++) FeatureBuffer[i] = 0.0;

	  /*---------------------
	   * Update VAD variable
	   *---------------------*/
	  pFEParX->VAD = NON_SPEECH_FRAME;



      /*--------------------------------------------
       *  Output Unvoiced pitch & non-speech class
       *--------------------------------------------*/
      {
          float fPitchPeriod = 0.f;
          char cVoicingClass = '0';

          if (1!=fwrite(&fPitchPeriod,sizeof(float),1,pFEParX->pitch_fid))
            {
                fprintf (stderr, "ERROR: can't write pitch to file \r\n");
                exit(1);
            }

          if (1 != fprintf(pFEParX->class_fid,"%c",cVoicingClass))
            {
                fprintf (stderr, "ERROR: can't write voicing class to file \r\n");
                exit(1);
            }
      }


	  return TRUE;
	}
}

/*----------------------------------------------------------------------------
 * FUNCTION NAME: FlushAdvProcess
 *
 * PURPOSE:       Flushing of feature frames
 *
 * INPUT:
 *
 * OUTPUT:
 *   FeatureBuffer Buffer of features
 *
 * RETURN VALUE:
 *   XTRUE        If a feature frame is output
 *   FALSE        If no frame is output (due to delay)
 *
 *---------------------------------------------------------------------------*/
BOOLEAN FlushAdvProcess (X_FLOAT32 *FeatureBuffer,
						 FEParamsX *pFEParX) 
{
  if (pFEParX->DoVADFlush)
    return pFEParX->DoVADFlush (FeatureBuffer, pFEParX);
  else
    return FALSE;
}

/*----------------------------------------------------------------------------
 * FUNCTION NAME: AdvProcessDelete
 *
 * PURPOSE:       Memory free of front end parameter structure     
 *
 * INPUT:
 *   ppFEParX     Pointer to pointer to front end parameter structure
 *
 * OUTPUT:
 *
 * RETURN VALUE:
 *   
 *---------------------------------------------------------------------------*/
void AdvProcessDelete (FEParamsX **ppFEParX)
{    
  if ((*ppFEParX)->DoNoiseSupDelete != NULL) (*ppFEParX)->DoNoiseSupDelete ((*ppFEParX)->NSX);
  if ((*ppFEParX)->DoWaveProcDelete != NULL) (*ppFEParX)->DoWaveProcDelete ((*ppFEParX)->WPX);
  if ((*ppFEParX)->DoCompCepsDelete != NULL) (*ppFEParX)->DoCompCepsDelete ((*ppFEParX)->CCX);
  if ((*ppFEParX)->DoPostProcDelete != NULL) (*ppFEParX)->DoPostProcDelete ((*ppFEParX)->PPX);
  if ((*ppFEParX)->Do16kProcDelete != NULL)  (*ppFEParX)->Do16kProcDelete ((*ppFEParX)->pData16k);
  if ((*ppFEParX)->DoVADDelete != NULL)      (*ppFEParX)->DoVADDelete ((*ppFEParX)->VADX);
  
  BufInFree ((*ppFEParX)->denoisedBuf);

  free (*ppFEParX);
  *ppFEParX = NULL;
}