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

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

#include "../sms.h"

/* function to generate a sinusoid given two peaks, current and last
 * it interpolation between phase values and magnitudes   
 * float fFreq;              current frequency
 * float fMag;               current magnitude
 * float fPhase;             current phase
 * SMS_DATA                  values from last frame
 * float *pFWaveform;	     pointer to output waveform
 * int sizeBuffer;	     size of the synthesis buffer 
 */
static void SinePhaSynth (float fFreq, float fMag, float fPhase, 
                          SMS_DATA *pLastFrame, float *pFWaveform, 
                          int sizeBuffer, int iTraj)
{
  float  fMagIncr, fInstMag, fInstPhase, fTmp;
  int iM, i;
  float fAlpha, fBeta, fTmp1, fTmp2;
   
  /* if no mag in last frame copy freq from current and make phase */
  if (pLastFrame->pFMagTraj[iTraj] <= 0)
  {
    pLastFrame->pFFreqTraj[iTraj] = fFreq;
    fTmp = fPhase - (fFreq * sizeBuffer);
    pLastFrame->pFPhaTraj[iTraj] = fTmp - floor(fTmp / TWO_PI) * TWO_PI;
  }
  /* and the other way */
  else if (fMag <= 0)
  {
    fFreq = pLastFrame->pFFreqTraj[iTraj];
    fTmp = pLastFrame->pFPhaTraj[iTraj] + 
            (pLastFrame->pFFreqTraj[iTraj] * sizeBuffer);
    fPhase = fTmp - floor(fTmp / TWO_PI) * TWO_PI;
  }
  
  /* caculate the instantaneous amplitude */
  fMagIncr = (fMag - pLastFrame->pFMagTraj[iTraj]) / sizeBuffer;
  fInstMag = pLastFrame->pFMagTraj[iTraj];
  
  /* create instantaneous phase from freq. and phase values */
  fTmp1 = fFreq - pLastFrame->pFFreqTraj[iTraj];
  fTmp2 = ((pLastFrame->pFPhaTraj[iTraj] + 
		pLastFrame->pFFreqTraj[iTraj] * sizeBuffer - fPhase) +
		fTmp1 * sizeBuffer / 2.0) / TWO_PI;
  iM = (int) (fTmp2 + .5);
  fTmp2 = fPhase - pLastFrame->pFPhaTraj[iTraj] - 
		pLastFrame->pFFreqTraj[iTraj] * sizeBuffer +
		TWO_PI * iM;
  fAlpha = (3.0 / (float)(sizeBuffer * sizeBuffer)) * 
    fTmp2 - fTmp1 / sizeBuffer;
  fBeta = (-2.0 / ((float) (sizeBuffer * sizeBuffer * sizeBuffer))) * 
    fTmp2 + fTmp1 / ((float) (sizeBuffer * sizeBuffer));
  
  for(i=0; i<sizeBuffer; i++)
  {
    fInstMag += fMagIncr;
    fInstPhase = pLastFrame->pFPhaTraj[iTraj] + 
			pLastFrame->pFFreqTraj[iTraj] * i + 
			fAlpha * i * i + fBeta * i * i * i;
    pFWaveform[i] += TO_MAG(fInstMag) * SinTab(fInstPhase + PI_2);
  }
  /* save current values into buffer */
  pLastFrame->pFFreqTraj[iTraj] = fFreq;
  pLastFrame->pFMagTraj[iTraj] = fMag;
  pLastFrame->pFPhaTraj[iTraj] = fPhase;
}

/*
 * function to generate a sinusoid given two frames, current and last
 * 
 * float fFreq;	         current frequency 
 * float fMag;              current magnitude  
 * SMS_DATA *pLastFrame;   values from last frame 
 * float *pFBuffer;	 pointer to output waveform 
 * int sizeBuffer;		 size of the synthesis buffer 
 * int iTraj;               current trajectory 
 */
static void SineSynth (float fFreq, float fMag, SMS_DATA *pLastFrame,
                       float *pFBuffer, int sizeBuffer, int iTraj)
{
  float  fMagIncr, fInstMag, fFreqIncr, fInstPhase, fInstFreq;
  int i;
  
  /* if no mag in last frame copy freq from current */
  if (pLastFrame->pFMagTraj[iTraj] <= 0)
  {
    pLastFrame->pFFreqTraj[iTraj] = fFreq;
    pLastFrame->pFPhaTraj[iTraj] = 
			TWO_PI * ((random() - HALF_MAX) / HALF_MAX);
  }
  /* and the other way */
  else if (fMag <= 0)
    fFreq = pLastFrame->pFFreqTraj[iTraj];
  
  /* calculate the instantaneous amplitude */
  fMagIncr = (fMag - pLastFrame->pFMagTraj[iTraj]) / sizeBuffer;
  fInstMag = pLastFrame->pFMagTraj[iTraj];
  /* calculate instantaneous frequency */
  fFreqIncr = (fFreq - pLastFrame->pFFreqTraj[iTraj]) / sizeBuffer;
  fInstFreq = pLastFrame->pFFreqTraj[iTraj];
  fInstPhase = pLastFrame->pFPhaTraj[iTraj];
  
  /* generate all the samples */    
  for (i = 0; i < sizeBuffer; i++)
  {
    fInstMag += fMagIncr;
    fInstFreq += fFreqIncr;
    fInstPhase += fInstFreq;
      
    pFBuffer[i] += TO_MAG (fInstMag) * SinTab (fInstPhase);
  }
  
  /* save current values into last values */
  pLastFrame->pFFreqTraj[iTraj] = fFreq;
  pLastFrame->pFMagTraj[iTraj] = fMag;
  pLastFrame->pFPhaTraj[iTraj] = fInstPhase - 
		floor(fInstPhase / TWO_PI) * TWO_PI;
}

/*
 * function to generate all the sinusoids for a given frame
 * 
 * SMS_DATA *pSmsData;     SMS data for current frame 
 * int nTraj;     	   number of partial trajectories 
 * float *pFBuffer;	   pointer to output waveform 
 * int sizeBuffer;	   size of the synthesis buffer
 * SMS_DATA *pLastFrame;  SMS data from last frame 
 */
int FrameSineSynth (SMS_DATA *pSmsData, float *pFBuffer, 
                    int sizeBuffer, SMS_DATA *pLastFrame)
{
  float fMag, fFreq;
  int i, nTraj = pSmsData->nTraj;
            
  /* go through all the trajectories */    
  for (i = 0; i < nTraj; i++)
  {
    /* get magnitude */
    fMag = pSmsData->pFMagTraj[i];
      
    fFreq = pSmsData->pFFreqTraj[i];
    if (fFreq > FHalfSamplingRate)
      fMag = 0;
      
    /* generate sines if there are magnitude values */
    if ((fMag > 0) || (pLastFrame->pFMagTraj[i] > 0))
    {
      /* frequency from Hz to radians */
      fFreq = (fFreq == 0) ? 0 : TWO_PI * fFreq / FSamplingRate;
	  
      if (pSmsData->pFPhaTraj == NULL)
        SineSynth(fFreq, fMag, pLastFrame, pFBuffer, sizeBuffer, i);
      else
        SinePhaSynth(fFreq, fMag, pSmsData->pFPhaTraj[i], pLastFrame, 
	      	     pFBuffer, sizeBuffer, i);
    }
  }
  return 1;
}     

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