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

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

#include "../sms.h"

/* synthesis of one frame of the deterministic component using the IFFT */

static int SineSynthIFFT (SMS_DATA *pSmsData, float *pFBuffer, 
                          SYNTH_PARAMS *pSynthParams)
{
	long sizeFft = pSynthParams->sizeHop * 2, 
		sizeMag = pSynthParams->sizeHop, nBins = 8,
		iFirstBin, k, i, l, b, nTraj = pSmsData->nTraj;
	float fMag=0, fFreq=0, fPhase=0, fLoc, fSin, fCos, fBinRemainder, 
		fTmp, fNewMag, *pFFftBuffer, fIndex;

	pFFftBuffer = (float *) calloc(sizeFft+1, sizeof(float));

	for (i = 0; i < nTraj; i++)
	{
		if (((fMag = pSmsData->pFMagTraj[i]) > 0) &&
		    ((fFreq = pSmsData->pFFreqTraj[i]) < FHalfSamplingRate))
		{
			if (pSynthParams->previousFrame.pFMagTraj[i] <= 0)
				pSynthParams->previousFrame.pFPhaTraj[i] = 
					TWO_PI * ((random() - HALF_MAX) / HALF_MAX);
			fMag = TO_MAG (fMag);
			fTmp = pSynthParams->previousFrame.pFPhaTraj[i] +
				(TWO_PI * fFreq / pSynthParams->fSamplingRate) * sizeMag;
			fPhase = fTmp - floor(fTmp / TWO_PI) * TWO_PI;
			fLoc = sizeFft * fFreq  / pSynthParams->fSamplingRate;
			iFirstBin = (int) fLoc - 3;
			fBinRemainder = fLoc - floor (fLoc);
			fSin = SinTab (fPhase);
			fCos = SinTab (fPhase + PI_2);
			for (k = 1, l = iFirstBin; k <= nBins; k++, l++)
			{
				fIndex = (k - fBinRemainder);
				if (fIndex > 7.999) fIndex = 0;
				fNewMag = fMag * SincTab (fIndex);
				if (l > 0 && l < sizeMag)
				{
					pFFftBuffer[l*2+1] += fNewMag * fCos;
					pFFftBuffer[l*2] += fNewMag * fSin;
     		  	}
				else if (l == 0)		
				{
					pFFftBuffer[0] += 2 * fNewMag * fSin;
 				}
				else if (l < 0)
				{
					b = abs(l);
					pFFftBuffer[b*2+1] -= fNewMag * fCos;
					pFFftBuffer[b*2] += fNewMag * fSin;
  				}
				else if (l > sizeMag)
				{
					b = sizeMag - (l - sizeMag);
					pFFftBuffer[b*2+1] -= fNewMag * fCos;
					pFFftBuffer[b*2] += fNewMag * fSin;
  				}
				else if (l == sizeMag)		
				{
					pFFftBuffer[1] += 2 * fNewMag * fSin;
 				}
			}
  		}
		pSynthParams->previousFrame.pFMagTraj[i] = fMag;
		pSynthParams->previousFrame.pFPhaTraj[i] = fPhase;
		pSynthParams->previousFrame.pFFreqTraj[i] = fFreq;
	}

	realft (pFFftBuffer-1, sizeMag, -1);
	for(i = 0, k = sizeMag; i < sizeMag; i++, k++) 
		pFBuffer[i] += pFFftBuffer[k] * pSynthParams->pFDetWindow[i];
	for(i= sizeMag, k = 0; i < sizeFft; i++, k++) 
		pFBuffer[i] +=  pFFftBuffer[k] * pSynthParams->pFDetWindow[i];
	free (pFFftBuffer);

	return (1);
}


/* synthesis of one frame of the stochastic component using spectral envelopes */
static int StocSynthIFFT (SMS_DATA *pSmsData, float *pFBuffer, 
                          SYNTH_PARAMS *pSynthParams)
{
	float *pFMagSpectrum, *pFPhaseSpectrum;
	int i, nSegments = pSmsData->nCoeff, nSegmentsUsed;
	int sizeFft = pSynthParams->sizeHop << 1, sizeMag = pSynthParams->sizeHop;

	/* if no gain or no coefficients return */
	if (*(pSmsData->pFStocGain) <= 0)
		return 0;

	if ((pFMagSpectrum = (float *) calloc(sizeMag, sizeof(float))) == NULL)
		return -1;
	if ((pFPhaseSpectrum = (float *) calloc(sizeMag, sizeof(float))) == NULL)
		return -1;
	*(pSmsData->pFStocGain) = TO_MAG(*(pSmsData->pFStocGain));

	/* scale the coefficients to normal amplitude */
	for (i = 0; i < nSegments; i++)
		pSmsData->pFStocCoeff[i] *= 2 * *(pSmsData->pFStocGain);

	nSegmentsUsed = nSegments * pSynthParams->fSamplingRate / 
	       		      pSynthParams->fOriginalSRate;
	SpectralApprox (pSmsData->pFStocCoeff, nSegments, nSegmentsUsed,
	                pFMagSpectrum, sizeMag, nSegmentsUsed);

	/* generate random phases */
	for (i = 0; i < sizeMag; i++)
		pFPhaseSpectrum[i] =  TWO_PI * ((random() - HALF_MAX) / HALF_MAX);

	InverseQuickSpectrumW (pFMagSpectrum, pFPhaseSpectrum, 
	                       	sizeFft, pFBuffer, sizeFft, 
							pSynthParams->pFStocWindow);
	free (pFMagSpectrum);
	free (pFPhaseSpectrum);
	return 1;
}

/* synthesizes one frame of SMS data
 *
 * SMS_DATA *pSmsData;      input SMS data
 * short *pSSynthesis;      output sound buffer
 * SYNTH_PARAMS *pSynthParams;   synthesis parameters
 */
int SmsSynthesis (SMS_DATA *pSmsData, short *pSSynthesis, 
                  SYNTH_PARAMS *pSynthParams)
{
	static float *pFBuffer = NULL;
	int i, sizeHop = pSynthParams->sizeHop;
  
	if (pFBuffer == NULL)
	{
		if((pFBuffer = (float *) calloc(sizeHop*2, sizeof(float))) == NULL)
			return -1;
 	}
  
	memcpy ((char *) pFBuffer, (char *)(pFBuffer+sizeHop), 
	        sizeof(float) * sizeHop);
	memset ((char *)(pFBuffer+sizeHop), 0, sizeof(float) * sizeHop);

	/* synthesize stochastic component */
	if (pSmsData->nCoeff > 0 && pSynthParams->iSynthesisType != 1)
		StocSynthIFFT (pSmsData, pFBuffer, pSynthParams);
 
	/* synthesize deterministic component */
	if (pSynthParams->iSynthesisType != 2)
		SineSynthIFFT (pSmsData, pFBuffer, pSynthParams);
     
	/* de-emphasize the sound */
	for(i = 0; i < sizeHop; i++)
		pSSynthesis[i] = (short) DeEmphasis(pFBuffer[i]);
    
	return (1);
}

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