summaryrefslogtreecommitdiff
path: root/sms/synthesis.c
diff options
context:
space:
mode:
Diffstat (limited to 'sms/synthesis.c')
-rw-r--r--sms/synthesis.c410
1 files changed, 125 insertions, 285 deletions
diff --git a/sms/synthesis.c b/sms/synthesis.c
index bba506c..3a8a3bb 100644
--- a/sms/synthesis.c
+++ b/sms/synthesis.c
@@ -28,171 +28,80 @@
* \param pSmsData pointer to SMS data structure frame
* \param pSynthParams pointer to structure of synthesis parameters
*/
-static void SineSynthIFFT (SMS_Data *pSmsData, SMS_SynthParams *pSynthParams)
+static void SineSynthIFFT(SMS_Data *pSmsData, SMS_SynthParams *pSynthParams)
{
- int sizeFft = pSynthParams->sizeHop << 1;
- int iHalfSamplingRate = pSynthParams->iSamplingRate >> 1;
- int sizeMag = pSynthParams->sizeHop;
- int nBins = 8;
- int nTracks = pSmsData->nTracks;
- int iFirstBin, k, i, l, b;
- sfloat fMag=0.0, fFreq=0.0, fPhase=0.0, fLoc, fSin, fCos, fBinRemainder,
- fTmp, fNewMag, fIndex;
- sfloat fSamplingPeriod = 1.0 / pSynthParams->iSamplingRate;
- memset (pSynthParams->pSpectra, 0, sizeFft * sizeof(sfloat));
- for (i = 0; i < nTracks; i++)
+ int sizeFft = pSynthParams->sizeHop << 1;
+ int iHalfSamplingRate = pSynthParams->iSamplingRate >> 1;
+ int sizeMag = pSynthParams->sizeHop;
+ int nBins = 8;
+ int nTracks = pSmsData->nTracks;
+ int iFirstBin, k, i, l, b;
+ sfloat fMag=0.0, fFreq=0.0, fPhase=0.0, fLoc, fSin, fCos, fBinRemainder,
+ fTmp, fNewMag, fIndex;
+ sfloat fSamplingPeriod = 1.0 / pSynthParams->iSamplingRate;
+ memset (pSynthParams->pSpectra, 0, sizeFft * sizeof(sfloat));
+ for (i = 0; i < nTracks; i++)
+ {
+ if(((fMag = pSmsData->pFSinAmp[i]) > 0) &&
+ ((fFreq = (pSmsData->pFSinFreq[i])) < iHalfSamplingRate))
{
- if (((fMag = pSmsData->pFSinAmp[i]) > 0) &&
- ((fFreq = (pSmsData->pFSinFreq[i])) < iHalfSamplingRate))
+ /* \todo maybe this check can be removed if the SynthParams->prevFrame gets random
+ phases in sms_initSynth? */
+ if(pSynthParams->prevFrame.pFSinAmp[i] <= 0)
+ pSynthParams->prevFrame.pFSinPha[i] = TWO_PI * sms_random();
+
+ // fMag = sms_dBToMag(fMag);
+ fTmp = pSynthParams->prevFrame.pFSinPha[i] +
+ TWO_PI * fFreq * fSamplingPeriod * sizeMag;
+ fPhase = fTmp - floor(fTmp * INV_TWO_PI) * TWO_PI;
+ fLoc = sizeFft * fFreq * fSamplingPeriod;
+ iFirstBin = (int) fLoc - 3;
+ fBinRemainder = fLoc - floor (fLoc);
+ fSin = sms_sine(fPhase);
+ fCos = sms_sine(fPhase + PI_2);
+ for (k = 1, l = iFirstBin; k <= nBins; k++, l++)
+ {
+ fIndex = (k - fBinRemainder);
+ if (fIndex > 7.999) fIndex = 0;
+ fNewMag = fMag * sms_sinc (fIndex);
+ if(l > 0 && l < sizeMag)
{
- /* \todo maybe this check can be removed if the SynthParams->prevFrame gets random
- phases in sms_initSynth? */
- if (pSynthParams->prevFrame.pFSinAmp[i] <= 0)
- pSynthParams->prevFrame.pFSinPha[i] = TWO_PI * sms_random();
-
- // fMag = sms_dBToMag (fMag);
- fTmp = pSynthParams->prevFrame.pFSinPha[i] +
- TWO_PI * fFreq * fSamplingPeriod * sizeMag;
- fPhase = fTmp - floor(fTmp * INV_TWO_PI) * TWO_PI;
- fLoc = sizeFft * fFreq * fSamplingPeriod;
- iFirstBin = (int) fLoc - 3;
- fBinRemainder = fLoc - floor (fLoc);
- fSin = sms_sine (fPhase);
- fCos = sms_sine (fPhase + PI_2);
- for (k = 1, l = iFirstBin; k <= nBins; k++, l++)
- {
- fIndex = (k - fBinRemainder);
- if (fIndex > 7.999) fIndex = 0;
- fNewMag = fMag * sms_sinc (fIndex);
- if (l > 0 && l < sizeMag)
- {
- pSynthParams->pSpectra[l*2+1] += fNewMag * fCos;
- pSynthParams->pSpectra[l*2] += fNewMag * fSin;
- }
- else if (l == 0)
- {
- pSynthParams->pSpectra[0] += 2 * fNewMag * fSin;
- }
- else if (l < 0)
- {
- b = abs(l);
- pSynthParams->pSpectra[b*2+1] -= fNewMag * fCos;
- pSynthParams->pSpectra[b*2] += fNewMag * fSin;
- }
- else if (l > sizeMag)
- {
- b = sizeMag - (l - sizeMag);
- pSynthParams->pSpectra[b*2+1] -= fNewMag * fCos;
- pSynthParams->pSpectra[b*2] += fNewMag * fSin;
- }
- else if (l == sizeMag)
- {
- pSynthParams->pSpectra[1] += 2 * fNewMag * fSin;
- }
- }
+ pSynthParams->pSpectra[l*2+1] += fNewMag * fCos;
+ pSynthParams->pSpectra[l*2] += fNewMag * fSin;
}
- pSynthParams->prevFrame.pFSinAmp[i] = fMag;
- pSynthParams->prevFrame.pFSinPha[i] = fPhase;
- pSynthParams->prevFrame.pFSinFreq[i] = fFreq;
- }
-
- sms_ifft(sizeFft, pSynthParams->pSpectra);
-
- for(i = 0, k = sizeMag; i < sizeMag; i++, k++)
- pSynthParams->pSynthBuff[i] += pSynthParams->pSpectra[k] * pSynthParams->pFDetWindow[i];
- for(i= sizeMag, k = 0; i < sizeFft; i++, k++)
- pSynthParams->pSynthBuff[i] += pSynthParams->pSpectra[k] * pSynthParams->pFDetWindow[i];
-
-}
-
-/*! \brief synthesis of one frame of the deterministic component using the IFFT
- *
- *
- * I made this function trying to pull the ifft out of the SineSynthIFFT
- * that part of the code is in the main sms_synthesize function below
- * Next would be sms_stochastic, so they could be summed and synthesized
- * with only one fft, but the problem is that it needs to be 'pre-inverse-windowed'
- * before the stochastic can be summed.
- *
- * \param pSmsData pointer to SMS data structure frame
- * \param pSynthParams pointer to structure of synthesis parameters
- */
-void sms_deterministic (SMS_Data *pSmsData, SMS_SynthParams *pSynthParams)
-{
- int sizeFft = pSynthParams->sizeHop << 1;
- int iHalfSamplingRate = pSynthParams->iSamplingRate >> 1;
- int sizeSpec = pSynthParams->sizeHop;
- int nBins = 8;
- int nTracks = pSmsData->nTracks;
- int iFirstBin, k, i, l, b;
- sfloat fMag=0.0, fFreq=0.0, fPhase=0.0, fLoc, fSin, fCos, fBinRemainder,
- fTmp, fNewMag, fIndex;
- sfloat fSamplingPeriod = 1.0 / pSynthParams->iSamplingRate;
- printf("| in deterministic | ");
-
- for (i = 0; i < nTracks; i++)
- {
- if (((fMag = pSmsData->pFSinAmp[i]) > 0) &&
- (fFreq = pSmsData->pFSinFreq[i] < iHalfSamplingRate)) /* \todo why does this allow f < 0 */
+ else if(l == 0)
{
- /* \todo maybe this check can be removed if the SynthParams->prevFrame gets random
- phases in sms_initSynth? */
- if (pSynthParams->prevFrame.pFSinAmp[i] <= 0)
- pSynthParams->prevFrame.pFSinPha[i] = TWO_PI * sms_random();
-
- //fMag = sms_dBToMag (fMag);
- fTmp = pSynthParams->prevFrame.pFSinPha[i] +
- TWO_PI * fFreq * fSamplingPeriod * sizeSpec;
- fPhase = fTmp - floor(fTmp * INV_TWO_PI) * TWO_PI;
- fLoc = sizeFft * fFreq * fSamplingPeriod;
- iFirstBin = (int) fLoc - 3;
- fBinRemainder = fLoc - floor (fLoc);
- fSin = sms_sine (fPhase);
- fCos = sms_sine (fPhase + PI_2);
- for (k = 1, l = iFirstBin; k <= nBins; k++, l++)
- {
- fIndex = (k - fBinRemainder);
- if (fIndex > 7.999) fIndex = 0;
- fNewMag = fMag * sms_sinc (fIndex);
- if (l > 0 && l < sizeSpec)
- {
- pSynthParams->pSpectra[l*2+1] += fNewMag * fCos;
- pSynthParams->pSpectra[l*2] += fNewMag * fSin;
- }
- else if (l == 0)
- {
- pSynthParams->pSpectra[0] += 2 * fNewMag * fSin;
- }
- else if (l < 0)
- {
- b = abs(l);
- pSynthParams->pSpectra[b*2+1] -= fNewMag * fCos;
- pSynthParams->pSpectra[b*2] += fNewMag * fSin;
- }
- else if (l > sizeSpec)
- {
- b = sizeSpec - (l - sizeSpec);
- pSynthParams->pSpectra[b*2+1] -= fNewMag * fCos;
- pSynthParams->pSpectra[b*2] += fNewMag * fSin;
- }
- else if (l == sizeSpec)
- {
- pSynthParams->pSpectra[1] += 2 * fNewMag * fSin;
- }
- }
+ pSynthParams->pSpectra[0] += 2 * fNewMag * fSin;
}
- pSynthParams->prevFrame.pFSinAmp[i] = fMag;
- pSynthParams->prevFrame.pFSinPha[i] = fPhase;
- pSynthParams->prevFrame.pFSinFreq[i] = fFreq;
+ else if(l < 0)
+ {
+ b = abs(l);
+ pSynthParams->pSpectra[b*2+1] -= fNewMag * fCos;
+ pSynthParams->pSpectra[b*2] += fNewMag * fSin;
+ }
+ else if(l > sizeMag)
+ {
+ b = sizeMag - (l - sizeMag);
+ pSynthParams->pSpectra[b*2+1] -= fNewMag * fCos;
+ pSynthParams->pSpectra[b*2] += fNewMag * fSin;
+ }
+ else if(l == sizeMag)
+ {
+ pSynthParams->pSpectra[1] += 2 * fNewMag * fSin;
+ }
+ }
}
+ pSynthParams->prevFrame.pFSinAmp[i] = fMag;
+ pSynthParams->prevFrame.pFSinPha[i] = fPhase;
+ pSynthParams->prevFrame.pFSinFreq[i] = fFreq;
+ }
-/* sms_ifft(sizeFft, pSynthParams->pSpectra); */
-
-/* for(i = 0, k = sizeMag; i < sizeMag; i++, k++) */
-/* pSynthParams->pSynthBuff[i] += pSynthParams->pSpectra[k] * pSynthParams->pFDetWindow[i]; */
-/* for(i= sizeMag, k = 0; i < sizeFft; i++, k++) */
-/* pSynthParams->pSynthBuff[i] += pSynthParams->pSpectra[k] * pSynthParams->pFDetWindow[i]; */
+ sms_ifft(sizeFft, pSynthParams->pSpectra);
+ for(i = 0, k = sizeMag; i < sizeMag; i++, k++)
+ pSynthParams->pSynthBuff[i] += pSynthParams->pSpectra[k] * pSynthParams->pFDetWindow[i];
+ for(i= sizeMag, k = 0; i < sizeFft; i++, k++)
+ pSynthParams->pSynthBuff[i] += pSynthParams->pSpectra[k] * pSynthParams->pFDetWindow[i];
}
/*! \brief synthesis of one frame of the stochastic component by apprimating phases
@@ -205,87 +114,38 @@ void sms_deterministic (SMS_Data *pSmsData, SMS_SynthParams *pSynthParams)
* \return
* \todo cleanup returns and various constant multipliers. check that approximation is ok
*/
-static int StocSynthApprox (SMS_Data *pSmsData, SMS_SynthParams *pSynthParams)
+static int StocSynthApprox(SMS_Data *pSmsData, SMS_SynthParams *pSynthParams)
{
- int i, sizeSpec1Used;
- int sizeSpec1 = pSmsData->nCoeff;
- int sizeSpec2 = pSynthParams->sizeHop;
- int sizeFft = pSynthParams->sizeHop << 1; /* 50% overlap, so sizeFft is 2x sizeHop */
- sfloat fStocGain;
- /* if no gain or no coefficients return */
- if (*(pSmsData->pFStocGain) <= 0)
- return 0;
+ int i, sizeSpec1Used;
+ int sizeSpec1 = pSmsData->nCoeff;
+ int sizeSpec2 = pSynthParams->sizeHop;
+ int sizeFft = pSynthParams->sizeHop << 1; /* 50% overlap, so sizeFft is 2x sizeHop */
+ sfloat fStocGain;
- // *(pSmsData->pFStocGain) = sms_dBToMag(*(pSmsData->pFStocGain));
+ /* if no gain or no coefficients return */
+ if (*(pSmsData->pFStocGain) <= 0)
+ return 0;
- /* \todo check why this was here */
- /* for (i = 0; i < sizeSpec1; i++)
- pSmsData->pFStocCoeff[i] *= 2 * *(pSmsData->pFStocGain) ;
- */
- sizeSpec1Used = sizeSpec1 * pSynthParams->iSamplingRate /
- pSynthParams->iOriginalSRate;
- /* sizeSpec1Used cannot be more than what is available \todo check by graph */
- if(sizeSpec1Used > sizeSpec1) sizeSpec1Used = sizeSpec1;
- //printf("iSamplingRate: %d, iOriginalSRate: %d, sizeSpec1: %d, sizeSpec1Used: %d, sizeSpec2: %d \n",
- // pSynthParams->iSamplingRate, pSynthParams->iOriginalSRate, sizeSpec1, sizeSpec1Used, sizeSpec2);
- sms_spectralApprox (pSmsData->pFStocCoeff, sizeSpec1, sizeSpec1Used,
- pSynthParams->pMagBuff, sizeSpec2, sizeSpec1Used);
+ // *(pSmsData->pFStocGain) = sms_dBToMag(*(pSmsData->pFStocGain));
- /* generate random phases */
- for (i = 0; i < sizeSpec2; i++)
- pSynthParams->pPhaseBuff[i] = TWO_PI * sms_random();
+ sizeSpec1Used = sizeSpec1 * pSynthParams->iSamplingRate /
+ pSynthParams->iOriginalSRate;
- sms_invQuickSpectrumW (pSynthParams->pMagBuff, pSynthParams->pPhaseBuff,
- sizeFft, pSynthParams->pSynthBuff, sizeFft,
- pSynthParams->pFStocWindow);
- return 1;
-}
+ /* sizeSpec1Used cannot be more than what is available \todo check by graph */
+ if(sizeSpec1Used > sizeSpec1) sizeSpec1Used = sizeSpec1;
-/*! \brief synthesis of one frame of the residual component, modeled as stochastic,
- * by approximating phases
- *
- * computes a linearly interpolated spectral envelope to fit the correct number of output
- * audio samples. Phases are generated randomly.
- *
- * \todo needs to be pre-windowed to match the windowing effect of the deterministic,
- * so when they are summed then they can be ifft'ed and overlap-added properly
- *
- * \param pSmsData pointer to the current SMS frame
- * \param pSynthParams pointer to a strucure of synthesis parameters
- * \return
- */
-int sms_stochastic (SMS_Data *pSmsData, SMS_SynthParams *pSynthParams)
-{
- int i, sizeOriginalSpecUsed;
- int sizeOriginalSpec = pSmsData->nCoeff;
- int sizeSpec = pSynthParams->sizeHop;
- int sizeFft = pSynthParams->sizeHop << 1; /* 50% overlap, so sizeFft is 2x sizeHop */
-
- /* if no gain or no coefficients return */
- if (*(pSmsData->pFStocGain) <= 0)
- return (0);
-
-/* *(pSmsData->pFStocGain) = sms_dBToMag(*(pSmsData->pFStocGain)); */
-
- /* scale the coefficients to normal amplitude */
- /*! \todo why is it also multiplied by 2? Why aren't the coeffecients just stored with gain already multiplied?*/
-/* for (i = 0; i < sizeOriginalSpec; i++) */
-/* pSmsData->pFStocCoeff[i] *= 2 * *(pSmsData->pFStocGain) ; */
-
- sizeOriginalSpecUsed = sizeOriginalSpec * pSynthParams->iSamplingRate /
- pSynthParams->iOriginalSRate;
- /* sizeOriginalSpecUsed cannot be more than what is available */
- if(sizeOriginalSpecUsed > sizeOriginalSpec) sizeOriginalSpecUsed = sizeOriginalSpec;
- sms_spectralApprox (pSmsData->pFStocCoeff, sizeOriginalSpec, sizeOriginalSpecUsed,
- pSynthParams->pMagBuff, sizeSpec, sizeOriginalSpecUsed);
+ sms_spectralApprox(pSmsData->pFStocCoeff, sizeSpec1, sizeSpec1Used,
+ pSynthParams->pMagBuff, sizeSpec2, sizeSpec1Used,
+ pSynthParams->approxEnvelope);
- /* generate random phases */
- for (i = 0; i < sizeSpec; i++)
- pSynthParams->pPhaseBuff[i] = TWO_PI * sms_random();
+ /* generate random phases */
+ for(i = 0; i < sizeSpec2; i++)
+ pSynthParams->pPhaseBuff[i] = TWO_PI * sms_random();
- /* \todo first multiply the pMagBuff by a window in order to properly un-window below */
- sms_PolarToRect(sizeSpec, pSynthParams->pSpectra, pSynthParams->pMagBuff, pSynthParams->pPhaseBuff);
- return (0);
+ sms_invQuickSpectrumW(pSynthParams->pMagBuff, pSynthParams->pPhaseBuff,
+ sizeFft, pSynthParams->pSynthBuff, sizeFft,
+ pSynthParams->pFStocWindow, pSynthParams->pSpectra);
+ return 1;
}
/*! \brief synthesizes one frame of SMS data
@@ -294,67 +154,47 @@ int sms_stochastic (SMS_Data *pSmsData, SMS_SynthParams *pSynthParams)
* \param pFSynthesis output sound buffer
* \param pSynthParams synthesis parameters
*/
-void sms_synthesize(SMS_Data *pSmsData, sfloat *pFSynthesis,
- SMS_SynthParams *pSynthParams)
+void sms_synthesize(SMS_Data *pSmsData, sfloat *pFSynthesis, SMS_SynthParams *pSynthParams)
{
- int i, k;
- int sizeHop = pSynthParams->sizeHop;
- int sizeFft = sizeHop << 1;
-
- memcpy (pSynthParams->pSynthBuff, (sfloat *)(pSynthParams->pSynthBuff+sizeHop),
- sizeof(sfloat) * sizeHop);
- memset (pSynthParams->pSynthBuff+sizeHop, 0, sizeof(sfloat) * sizeHop);
-
- /* convert mags from linear to db */
- sms_arrayMagToDB(pSmsData->nTracks, pSmsData->pFSinAmp);
-
- /* decide which combo of synthesis methods to use */
- if(pSynthParams->iSynthesisType == SMS_STYPE_ALL)
+ int i, k;
+ int sizeHop = pSynthParams->sizeHop;
+ int sizeFft = sizeHop << 1;
+
+ memcpy(pSynthParams->pSynthBuff, (sfloat *)(pSynthParams->pSynthBuff+sizeHop),
+ sizeof(sfloat) * sizeHop);
+ memset(pSynthParams->pSynthBuff+sizeHop, 0, sizeof(sfloat) * sizeHop);
+
+ /* convert mags from linear to db */
+ /*sms_arrayMagToDB(pSmsData->nTracks, pSmsData->pFSinAmp);*/
+
+ /* decide which combo of synthesis methods to use */
+ if(pSynthParams->iSynthesisType == SMS_STYPE_ALL)
+ {
+ if(pSynthParams->iDetSynthType == SMS_DET_IFFT)
+ SineSynthIFFT(pSmsData, pSynthParams);
+ else /*pSynthParams->iDetSynthType == SMS_DET_SIN*/
{
- if(pSynthParams->iDetSynthType == SMS_DET_IFFT &&
- pSynthParams->iStochasticType == SMS_STOC_IFFT)
- {
- memset (pSynthParams->pSpectra, 0, sizeFft * sizeof(sfloat));
- sms_deterministic(pSmsData, pSynthParams);
- sms_ifft(sizeFft, pSynthParams->pSpectra);
-
- for(i = 0, k = sizeHop; i < sizeHop; i++, k++)
- pSynthParams->pSynthBuff[i] += pSynthParams->pSpectra[k] * pSynthParams->pFDetWindow[i];
- for(i= sizeHop, k = 0; i < sizeFft; i++, k++)
- pSynthParams->pSynthBuff[i] += pSynthParams->pSpectra[k] * pSynthParams->pFDetWindow[i];
-
- //sms_invSpectrum(sizeFft, pSynthParams->pSynthBuff,
-
-
- }
- else /* can't use combo IFFT, synthesize seperately and sum */
- {
- if(pSynthParams->iDetSynthType == SMS_DET_IFFT)
- SineSynthIFFT (pSmsData, pSynthParams);
- else /*pSynthParams->iDetSynthType == SMS_DET_SIN*/
- {
- sms_sineSynthFrame (pSmsData, pSynthParams->pSynthBuff+sizeHop, pSynthParams->sizeHop,
- &(pSynthParams->prevFrame), pSynthParams->iSamplingRate);
- }
- StocSynthApprox (pSmsData, pSynthParams);
- }
-
+ sms_sineSynthFrame(pSmsData, pSynthParams->pSynthBuff, pSynthParams->sizeHop,
+ &(pSynthParams->prevFrame), pSynthParams->iSamplingRate);
}
- else if(pSynthParams->iSynthesisType == SMS_STYPE_DET)
+ StocSynthApprox(pSmsData, pSynthParams);
+ }
+ else if(pSynthParams->iSynthesisType == SMS_STYPE_DET)
+ {
+ if(pSynthParams->iDetSynthType == SMS_DET_IFFT)
+ SineSynthIFFT (pSmsData, pSynthParams);
+ else /*pSynthParams->iDetSynthType == SMS_DET_SIN*/
{
- if(pSynthParams->iDetSynthType == SMS_DET_IFFT)
- SineSynthIFFT (pSmsData, pSynthParams);
- else /*pSynthParams->iDetSynthType == SMS_DET_SIN*/
- {
- sms_sineSynthFrame (pSmsData, pSynthParams->pSynthBuff+sizeHop, pSynthParams->sizeHop,
- &(pSynthParams->prevFrame), pSynthParams->iSamplingRate);
- }
+ sms_sineSynthFrame(pSmsData, pSynthParams->pSynthBuff, pSynthParams->sizeHop,
+ &(pSynthParams->prevFrame), pSynthParams->iSamplingRate);
}
- else /* pSynthParams->iSynthesisType == SMS_STYPE_STOC */
- StocSynthApprox(pSmsData, pSynthParams);
+ }
+ else /* pSynthParams->iSynthesisType == SMS_STYPE_STOC */
+ StocSynthApprox(pSmsData, pSynthParams);
- /* de-emphasize the sound */
- for(i = 0; i < sizeHop; i++)
- pFSynthesis[i] = sms_deEmphasis(pSynthParams->pSynthBuff[i+sizeHop], pSynthParams);
+ /* de-emphasize the sound and normalize*/
+ for(i = 0; i < sizeHop; i++)
+ pFSynthesis[i] = sms_deEmphasis(pSynthParams->pSynthBuff[i], pSynthParams);
}
+