diff options
Diffstat (limited to 'sms/synthesis.c')
-rw-r--r-- | sms/synthesis.c | 410 |
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); } + |