ftp.nice.ch/pub/next/unix/audio/sms.N.bs.tar.gz#/sms/hybridMk/hybridize.c

This is hybridize.c in view mode; [Download] [Up]

#include "../sms.h"
#import "hybrid.h"

static float *pFWindow1 = NULL, *pFWindow2 = NULL;
static int sizeFft1, sizeFft2, sizeMag1, sizeMag2, sizeSmooth;
static float *pFMagSpectrum1, *pFMagSpectrum2, *pFPhaseSpectrum1, 
	     *pFPhaseSpectrum2, *pFMagEnv, *pFEnvBuffer, *pFMagEnvFilt;
/* 
 * initialize static arrays 
 */
static int InitializeHybrid (int sizeWave1, int sizeWave2, HYB_PARAMS params)
{
    int i;

    if ((pFWindow1 = (float *) calloc(sizeWave1, sizeof(float))) == NULL)
      return -1;
    if ((pFWindow2 = (float *) calloc(sizeWave2, sizeof(float))) == NULL)
      return -1;
    for (i=0; i<sizeWave1; i++) pFWindow1[i] = 1.0;
    Hamming (sizeWave1, pFWindow1);
    Hamming (sizeWave2, pFWindow2);
    sizeFft1 = (int) pow(2.0,
                 (double)(1+(floor(log((double)sizeWave1) / LOG2))));
    sizeFft2 = (int) pow(2.0, 
                 (double) (1+(floor(log((double)sizeWave2) / LOG2))));
    sizeMag1 = sizeFft1 >> 1;
    sizeMag2 = sizeFft2 >> 1;
    sizeSmooth = 1 + params.iSmoothOrder;
    if ((pFMagSpectrum2 = 
          (float *) calloc(sizeMag2, sizeof(float))) == NULL)
      return -1;
    if ((pFMagSpectrum1 = 
          (float *) calloc(sizeMag1, sizeof(float))) == NULL)
      return -1;
    pFPhaseSpectrum2 = NULL;
    if ((pFPhaseSpectrum1 = 
          (float *) calloc(sizeMag1, sizeof(float))) == NULL)
      return -1;
    if ((pFMagEnv = 
          (float *) calloc(sizeMag1, sizeof(float))) == NULL)
      return -1;
    if ((pFEnvBuffer = 
          (float *) calloc(sizeMag1 * sizeSmooth, sizeof(float))) == NULL)
      return -1;
    if ((pFMagEnvFilt = 
          (float *) calloc(sizeMag1, sizeof(float))) == NULL)
      return -1;

    return 1;
}

int freeBuffers ()
{
	free (pFWindow1);
	pFWindow1 = NULL;
	free (pFWindow2);
	pFWindow2 = NULL;
	if (pFMagSpectrum2)
		free (pFMagSpectrum2);
	if (pFMagSpectrum1)
		free (pFMagSpectrum1);
	if (pFPhaseSpectrum1)
		free (pFPhaseSpectrum1);
	if (pFPhaseSpectrum2)
		free (pFPhaseSpectrum2);
	free (pFMagEnv);
	free (pFEnvBuffer);
	free (pFMagEnvFilt);
	return 1;
}

/* 
 *  Compress-Expand a given spectral envelope 
 */

static int CompExp(float *pFEnv,float *pFSpec,float *pFWeight,int sizeSpec)
{
  float *pFEnd=pFSpec+sizeSpec;		
  do 
  {
      if (*pFWeight == 2.) *pFSpec=1.;
      else if (!*pFWeight) *pFEnv=1.;
      else if (*pFWeight > 1 && *pFSpec)
          *pFSpec=(float)pow(10.,(2.-*pFWeight)*log10((double)*pFSpec)); 
      else if (*pFWeight < 1 && *pFEnv)
          *pFEnv=(float)pow(10.,*pFWeight*log10((double)*pFEnv)); 
      ++pFWeight; 
      ++pFSpec;
      ++pFEnv;
  }
  while (pFSpec<pFEnd);
  return 1;
}


/*
 * filter each magnitude in a spectrum by the surounding magnitudes 
 */ 
static int FilterMagEnv (float *pFMagEnv, float *pFMagEnvFilt, int sizeMag)
{
  int sizeEnvBuffer = sizeSmooth * sizeMag;
   memcpy ((char *) pFEnvBuffer, (char *) (pFEnvBuffer+sizeMag), 
	  sizeof(float) * sizeEnvBuffer);
   memcpy ((char *) (pFEnvBuffer+sizeEnvBuffer-sizeMag), (char *) pFMagEnv, 
	  sizeof(float) * sizeMag);
  FilterArray (pFEnvBuffer, sizeMag, sizeSmooth, pFMagEnvFilt);
  return 1;
}

/* 
 * multiply spectral envelope of one sound with magnitude spectrum of the other 
 *
 * float *pFMagEnv		envelope from hybridizing sound
 * float *pFMagSpectrum		magnitude spectrum of excitation sound
 * int sizeMag			size of magnitude spectrum
 * HYB_PARAMS params		control parameters
 */
static int MultiplySpectra (float *pFMagEnv, float *pFMagSpectrum, int sizeMag, 
                            float *pFMagSpectrum2, int sizeMag2, 
                            HYB_PARAMS params)
{
	float *pFBuffer, fMag = 0, fAverageMag, fMagEnv = 0, fAverageMagEnv, 
		fHybAverage, fMagHyb = 0, fAverageMagHyb;
	int  i;

	/* allocate buffers */    
	if ((pFBuffer = (float *) calloc(sizeMag, sizeof(float))) == NULL)
		return -1;

	/* get energy of excitation spectrum and envelope and normalize them */
	for (i = 0; i < sizeMag; i++)
	{
		fMag += pFMagSpectrum[i];
		fMagEnv += pFMagEnv[i];
	}

	for (i = 0; i < sizeMag2; i++)
		fMagHyb += pFMagSpectrum2[i];

	fAverageMag = MAX (fMag / sizeMag, ENV_THRESHOLD);
	fAverageMagEnv = MAX (fMagEnv / sizeMag, ENV_THRESHOLD);
	fAverageMagHyb = MAX (fMagHyb / sizeMag2, ENV_THRESHOLD);

	for (i = 0; i < sizeMag; i++)
	{
		pFMagSpectrum[i] /= fAverageMag;
		pFMagEnv[i] /= fAverageMagEnv;
	}
  
	/* compress the spectral envelope from one or other sound */
	if (params.pCompressionEnv)
		if (params.sizeCompressionEnv == sizeMag1)
			CompExp (pFMagEnv, pFMagSpectrum, params.pCompressionEnv, sizeMag);
		else return -1;

	/* do the hybridation */
	for (i = 0; i < sizeMag; i++)
		pFMagSpectrum[i] *=  pFMagEnv[i];

	/* get the new average magnitude */
	fHybAverage = params.fMagBalance * fAverageMagHyb + 
		(1 - params.fMagBalance) * fAverageMag;

	if (fHybAverage < .0001 || fHybAverage > 1000) fHybAverage = 1;

	/* scale the new spectrum by the new average magnitude */
	for (i = 0; i < sizeMag; i++)
		pFMagSpectrum[i] *= fHybAverage;

	free (pFBuffer);
	return 1;
}

/*
 * function to hybridize the magnitude of two waveforms
 *
 * short *pIWaveform1		excitation waveform
 * int sizeWave1		    size of excitation waveform
 * short *pIWaveform2		hybridization waveform
 * int sizeWave2		    size of hybridization waveform
 * float *pFWaveform		output waveform (hybridized)
 * HYB_PARAMS params		control parameters
 *
 */
void HybridizeMag (short *pIWaveform1, int sizeWave1, short *pIWaveform2, 
                   int sizeWave2, float *pFWaveform, HYB_PARAMS params)
{
	int i;
	double fMag1 = 0, fMag2 = 0, fScalar;

	for (i = 0; i < sizeWave1; i++)
	{
		pFWaveform[i] = pIWaveform1[i] * pFWindow1[i];
		fMag1 += fabs (pFWaveform[i]);
	}
	fMag1 /= sizeWave1;

	for (i = 0; i < sizeWave2; i++)
		fMag2 += fabs (pIWaveform2[i] * pFWindow2[i]);
	fMag2 /= sizeWave2;

	fScalar = params.fMagBalance * fMag2 + 
				    (1- params.fMagBalance) * fMag1;

	for (i = 0; i < sizeWave1; i++)
		pFWaveform[i] = (pIWaveform1[i] / fMag1) * fScalar;
}

/*
 * function to hybridize two waveforms
 *
 * short *pIWaveform1		excitation waveform
 * int sizeWave1		size of excitation waveform
 * short *pIWaveform2		hybridization waveform
 * int sizeWave2		size of hybridization waveform
 * float *pFWaveform		output waveform (hybridized)
 * HYB_PARAMS params		control parameters
 *
 */
int Hybridize (short *pIWaveform1, int sizeWave1, short *pIWaveform2, 
               int sizeWave2, float *pFWaveform, HYB_PARAMS params)
{
	/* initialize static variables and arrays */
	if (pFWindow1 == NULL)
		InitializeHybrid (sizeWave1, sizeWave2, params);
   
	if (!params.pCompressionEnv)
	{
		HybridizeMag (pIWaveform1, sizeWave1, pIWaveform2, sizeWave2, 
		              pFWaveform, params);
		return (1);
	}
	/* compute the two spectra */
	QuickSpectrum (pIWaveform1, pFWindow1, sizeWave1, pFMagSpectrum1, 
	               pFPhaseSpectrum1, sizeFft1);
	QuickSpectrum (pIWaveform2, pFWindow2, sizeWave2, pFMagSpectrum2, 
	               pFPhaseSpectrum2, sizeFft2);

	/* approximate the second spectrum by line segments and obtain a magnitude 
	 * spectrum of size sizeMag1 */
	SpectralApprox (pFMagSpectrum2, sizeMag2, sizeMag2, pFMagEnv, sizeMag1, 
	                params.nCoefficients);

	/* filter the smoothed spectrum */
	FilterMagEnv (pFMagEnv, pFMagEnvFilt, sizeMag1);

	/* hybridize the two spectra */
	MultiplySpectra (pFMagEnvFilt, pFMagSpectrum1, sizeMag1, pFMagSpectrum2, 
	                 sizeMag2, params);

	/* perform the inverse FFT from the hybridized spectrum */
	InverseQuickSpectrum (pFMagSpectrum1, pFPhaseSpectrum1, sizeFft1, 
	                      pFWaveform, sizeWave1);
  return 1;
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.