From 5e25edb1b78f28bee09bd7513a80fb500bbd59c4 Mon Sep 17 00:00:00 2001 From: John Glover Date: Wed, 24 Nov 2010 23:26:43 +0000 Subject: Updated libsms to the latest version (1.15), includes some memory management improvements/simplifications but the basic API is the same. Also started updating the unit tests, which will now use the nose framework --- sms/analysis.c | 1081 ++++++++++++++++++++++++------------------------ sms/fileIO.c | 418 ++++++++----------- sms/filters.c | 73 ++-- sms/fixTracks.c | 149 ++++--- sms/peakContinuation.c | 250 ++++++----- sms/peakDetection.c | 27 +- sms/residual.c | 126 ++---- sms/sineSynth.c | 268 ++++++------ sms/sms.c | 464 ++++++++++++++------- sms/sms.h | 654 ++++++++++++++--------------- sms/sms.i | 702 +++++++++++++++---------------- sms/soundIO.c | 3 - sms/spectralApprox.c | 213 +++++----- sms/spectrum.c | 403 +++++++----------- sms/stocAnalysis.c | 66 ++- sms/synthesis.c | 410 ++++++------------ sms/tables.c | 135 +++--- 17 files changed, 2539 insertions(+), 2903 deletions(-) (limited to 'sms') diff --git a/sms/analysis.c b/sms/analysis.c index 84eb28c..55c955f 100644 --- a/sms/analysis.c +++ b/sms/analysis.c @@ -33,19 +33,19 @@ void printAnalysisParams(SMS_AnalParams* params) { - printf("fLowestFreq: %f\n" - "fHighestFreq: %f\n" - "fMinPeakMag: %f\n" - "iSamplingRate: %d\n" - "iMaxPeaks: %d\n" - "fHighestFundamental: %f\n" - "iRefHarmonic: %d\n" - "fMinRefHarmMag: %f\n" - "fRefHarmMagDiffFromMax: %f\n" - "iSoundType: %d\n", - params->fLowestFreq, params->fHighestFreq, params->fMinPeakMag, params->iSamplingRate, - params->maxPeaks, params->fHighestFundamental, params->iRefHarmonic, - params->fMinRefHarmMag, params->fRefHarmMagDiffFromMax, params->iSoundType); + printf("fLowestFreq: %f\n" + "fHighestFreq: %f\n" + "fMinPeakMag: %f\n" + "iSamplingRate: %d\n" + "iMaxPeaks: %d\n" + "fHighestFundamental: %f\n" + "iRefHarmonic: %d\n" + "fMinRefHarmMag: %f\n" + "fRefHarmMagDiffFromMax: %f\n" + "iSoundType: %d\n", + params->fLowestFreq, params->fHighestFreq, params->fMinPeakMag, params->iSamplingRate, + params->maxPeaks, params->fHighestFundamental, params->iRefHarmonic, + params->fMinRefHarmMag, params->fRefHarmMagDiffFromMax, params->iSoundType); } /*! \brief compute spectrum, find peaks, and fundamental of one frame @@ -58,49 +58,40 @@ void printAnalysisParams(SMS_AnalParams* params) */ void sms_analyzeFrame(int iCurrentFrame, SMS_AnalParams *pAnalParams, sfloat fRefFundamental) { - int i, iFrame; - static int sizeWindowStatic = 0; - static int sizeMag = 0; - static sfloat pFMagSpectrum[SMS_MAX_SPEC]; - static sfloat pFPhaSpectrum[SMS_MAX_SPEC]; - static sfloat pFSpectrumWindow[SMS_MAX_SPEC]; + int i, iFrame; SMS_AnalFrame *pCurrentFrame = pAnalParams->ppFrames[iCurrentFrame]; - int sizeWindow = pCurrentFrame->iFrameSize; int iSoundLoc = pCurrentFrame->iFrameSample -((pCurrentFrame->iFrameSize + 1) >> 1) + 1; - sfloat *pFData = &(pAnalParams->soundBuffer.pFBuffer[iSoundLoc - pAnalParams->soundBuffer.iMarker]); - - /*if window size has changed, update the window and sizemag*/ - if (sizeWindowStatic != sizeWindow) - { - sizeMag = sms_power2(sizeWindow); - sms_getWindow(sizeWindow, pFSpectrumWindow, pAnalParams->iWindowType); - sms_scaleWindow(sizeWindow, pFSpectrumWindow); - sizeWindowStatic = sizeWindow; - } - - /* compute the magnitude and (zero-windowed) phase spectra */ - sms_spectrum(sizeWindow, pFData, pFSpectrumWindow, sizeMag, - pFMagSpectrum, pFPhaSpectrum); - - /* convert magnitude spectra to dB */ - sms_arrayMagToDB(sizeMag, pFMagSpectrum); - - /* find the prominent peaks */ - pCurrentFrame->nPeaks = sms_detectPeaks(sizeMag, - pFMagSpectrum, - pFPhaSpectrum, + sfloat *pFData = &(pAnalParams->soundBuffer.pFBuffer[iSoundLoc - pAnalParams->soundBuffer.iMarker]); + + /* TODO: this doesn't have to be done every time */ + int sizeWindow = pCurrentFrame->iFrameSize; + int sizeMag = sms_power2(sizeWindow); + sms_getWindow(sizeWindow, pAnalParams->spectrumWindow, pAnalParams->iWindowType); + sms_scaleWindow(sizeWindow, pAnalParams->spectrumWindow); + + /* compute the magnitude and (zero-windowed) phase spectra */ + sms_spectrum(sizeWindow, pFData, pAnalParams->spectrumWindow, sizeMag, + pAnalParams->magSpectrum, pAnalParams->phaseSpectrum, + pAnalParams->fftBuffer); + + /* convert magnitude spectra to dB */ + sms_arrayMagToDB(sizeMag, pAnalParams->magSpectrum); + + /* find the prominent peaks */ + pCurrentFrame->nPeaks = sms_detectPeaks(sizeMag, + pAnalParams->magSpectrum, + pAnalParams->phaseSpectrum, pCurrentFrame->pSpectralPeaks, pAnalParams); - /* find a reference harmonic */ - if (pCurrentFrame->nPeaks > 0 && - (pAnalParams->iFormat == SMS_FORMAT_H || - pAnalParams->iFormat == SMS_FORMAT_HP)) - pCurrentFrame->fFundamental = sms_harmDetection(pAnalParams->nTracks, pCurrentFrame->pSpectralPeaks, - fRefFundamental, pAnalParams->iRefHarmonic, - pAnalParams->fLowestFundamental, pAnalParams->fHighestFundamental, - pAnalParams->iSoundType, pAnalParams->fMinRefHarmMag, - pAnalParams->fRefHarmMagDiffFromMax); + /* find a reference harmonic */ + if (pCurrentFrame->nPeaks > 0 && + (pAnalParams->iFormat == SMS_FORMAT_H || pAnalParams->iFormat == SMS_FORMAT_HP)) + pCurrentFrame->fFundamental = sms_harmDetection(pAnalParams->nTracks, pCurrentFrame->pSpectralPeaks, + fRefFundamental, pAnalParams->iRefHarmonic, + pAnalParams->fLowestFundamental, pAnalParams->fHighestFundamental, + pAnalParams->iSoundType, pAnalParams->fMinRefHarmMag, + pAnalParams->fRefHarmMagDiffFromMax); } /*! \brief re-analyze the previous frames if necessary @@ -115,545 +106,545 @@ void sms_analyzeFrame(int iCurrentFrame, SMS_AnalParams *pAnalParams, sfloat fRe static int ReAnalyzeFrame(int iCurrentFrame, SMS_AnalParams *pAnalParams) { sfloat fFund, fLastFund, fDev; - int iNewFrameSize, i; - sfloat fAvgDeviation = sms_fundDeviation(pAnalParams, iCurrentFrame); + int iNewFrameSize, i; + sfloat fAvgDeviation = sms_fundDeviation(pAnalParams, iCurrentFrame); int iFirstFrame = iCurrentFrame - pAnalParams->minGoodFrames; - /*! \todo mae this a < 0 check, but first make sure sms_fundDeviation does not - return values below zero */ - if (fAvgDeviation == -1) - return (-1); - - /* if the last pAnalParams->minGoodFrames are stable look before them */ - /* and recompute the frames that are not stable */ - if (fAvgDeviation <= pAnalParams->maxDeviation) - for (i = 0; i < pAnalParams->analDelay; i++) - { - if (pAnalParams->ppFrames[iFirstFrame - i]->iFrameNum <= 0 || - pAnalParams->ppFrames[iFirstFrame - i]->iStatus == SMS_FRAME_RECOMPUTED) - return(-1); - fFund = pAnalParams->ppFrames[iFirstFrame - i]->fFundamental; - fLastFund = pAnalParams->ppFrames[iFirstFrame - i + 1]->fFundamental; - fDev = fabs (fFund - fLastFund) / fLastFund; - iNewFrameSize = ((pAnalParams->iSamplingRate / fLastFund) * - pAnalParams->fSizeWindow/2) * 2 + 1; - - if (fFund <= 0 || fDev > .2 || - fabs ((double)(pAnalParams->ppFrames[iFirstFrame - i]->iFrameSize - - iNewFrameSize)) / - iNewFrameSize >= .2) - { - pAnalParams->ppFrames[iFirstFrame - i]->iFrameSize = iNewFrameSize; - pAnalParams->ppFrames[iFirstFrame - i]->iStatus = SMS_FRAME_READY; - - /* recompute frame */ - sms_analyzeFrame(iFirstFrame - i, pAnalParams, fLastFund); - pAnalParams->ppFrames[iFirstFrame - i]->iStatus = SMS_FRAME_RECOMPUTED; - - if (fabs(pAnalParams->ppFrames[iFirstFrame - i]->fFundamental - fLastFund) / - fLastFund >= .2) - return(-1); - } - } - return (1); + /*! \todo make this a < 0 check, but first make sure sms_fundDeviation does not + return values below zero */ + if(fAvgDeviation == -1) + return -1; + + /* if the last SMS_MIN_GOOD_FRAMES are stable look before them */ + /* and recompute the frames that are not stable */ + if (fAvgDeviation <= pAnalParams->maxDeviation) + { + for(i = 0; i < pAnalParams->analDelay; i++) + { + if(pAnalParams->ppFrames[iFirstFrame - i]->iFrameNum <= 0 || + pAnalParams->ppFrames[iFirstFrame - i]->iStatus == SMS_FRAME_RECOMPUTED) + return -1; + fFund = pAnalParams->ppFrames[iFirstFrame - i]->fFundamental; + fLastFund = pAnalParams->ppFrames[iFirstFrame - i + 1]->fFundamental; + fDev = fabs (fFund - fLastFund) / fLastFund; + iNewFrameSize = ((pAnalParams->iSamplingRate / fLastFund) * + pAnalParams->fSizeWindow/2) * 2 + 1; + + if(fFund <= 0 || fDev > .2 || + fabs((double)(pAnalParams->ppFrames[iFirstFrame - i]->iFrameSize - + iNewFrameSize)) / iNewFrameSize >= .2) + { + pAnalParams->ppFrames[iFirstFrame - i]->iFrameSize = iNewFrameSize; + pAnalParams->ppFrames[iFirstFrame - i]->iStatus = SMS_FRAME_READY; + + /* recompute frame */ + sms_analyzeFrame(iFirstFrame - i, pAnalParams, fLastFund); + pAnalParams->ppFrames[iFirstFrame - i]->iStatus = SMS_FRAME_RECOMPUTED; + + if(fabs(pAnalParams->ppFrames[iFirstFrame - i]->fFundamental - fLastFund) / + fLastFund >= .2) + return -1; + } + } + } + return 1; } int sms_findPeaks(int sizeWaveform, sfloat *pWaveform, SMS_AnalParams *pAnalParams, SMS_SpectralPeaks *pSpectralPeaks) { - int iCurrentFrame = pAnalParams->iMaxDelayFrames - 1; /* frame # of current frame */ - sfloat fRefFundamental = 0; /* reference fundamental for current frame */ - int i, iError, iExtraSamples; /* samples used for next analysis frame */ + int iCurrentFrame = pAnalParams->iMaxDelayFrames - 1; /* frame # of current frame */ + sfloat fRefFundamental = 0; /* reference fundamental for current frame */ + int i, iError, iExtraSamples; /* samples used for next analysis frame */ SMS_AnalFrame *pTmpAnalFrame; /* set initial analysis-window size */ - if(pAnalParams->windowSize == 0) - pAnalParams->windowSize = pAnalParams->iDefaultSizeWindow; - - /* fill sound buffer and perform pre-emphasis */ - if (sizeWaveform > 0) - sms_fillSoundBuffer(sizeWaveform, pWaveform, pAnalParams); - - /* move analysis data one frame back */ - pTmpAnalFrame = pAnalParams->ppFrames[0]; - for(i = 1; i < pAnalParams->iMaxDelayFrames; i++) - pAnalParams->ppFrames[i-1] = pAnalParams->ppFrames[i]; - pAnalParams->ppFrames[pAnalParams->iMaxDelayFrames-1] = pTmpAnalFrame; - - /* initialize the current frame */ - sms_initFrame(iCurrentFrame, pAnalParams, pAnalParams->windowSize); - if(sms_errorCheck()) - { - printf("Error in init frame: %s \n", sms_errorString()); - return(0); - } - - if(pAnalParams->ppFrames[iCurrentFrame]->iStatus == SMS_FRAME_READY) - { - sfloat fAvgDev = sms_fundDeviation(pAnalParams, iCurrentFrame - 1); - - /* if single note use the default fundamental as reference */ - if(pAnalParams->iSoundType == SMS_SOUND_TYPE_NOTE) - fRefFundamental = pAnalParams->fDefaultFundamental; - /* if sound is stable use the last fundamental as a reference */ - else if(fAvgDev != -1 && fAvgDev <= pAnalParams->maxDeviation) - fRefFundamental = pAnalParams->ppFrames[iCurrentFrame - 1]->fFundamental; - else - fRefFundamental = 0; - - /* compute spectrum, find peaks, and find fundamental of frame */ - sms_analyzeFrame(iCurrentFrame, pAnalParams, fRefFundamental); - - /* set the size of the next analysis window */ - if(pAnalParams->ppFrames[iCurrentFrame]->fFundamental > 0 && - pAnalParams->iSoundType != SMS_SOUND_TYPE_NOTE) - pAnalParams->windowSize = sms_sizeNextWindow(iCurrentFrame, pAnalParams); - - /* figure out how much needs to be read next time */ - // how many processed - sample no. of end of next frame - // = no. samples that we haven't processed yet from whenever, if sizeNextRead was 0 - iExtraSamples = (pAnalParams->soundBuffer.iMarker + pAnalParams->soundBuffer.sizeBuffer) - - (pAnalParams->ppFrames[iCurrentFrame]->iFrameSample + pAnalParams->sizeHop); - - pAnalParams->sizeNextRead = MAX(0, (pAnalParams->windowSize+1)/2 - iExtraSamples); - ReAnalyzeFrame(iCurrentFrame, pAnalParams); - - /* save peaks */ - pSpectralPeaks->nPeaksFound = pAnalParams->ppFrames[iCurrentFrame]->nPeaks; - pSpectralPeaks->nPeaks = pAnalParams->maxPeaks; - pSpectralPeaks->pSpectralPeaks = pAnalParams->ppFrames[iCurrentFrame]->pSpectralPeaks; + if(pAnalParams->windowSize == 0) + pAnalParams->windowSize = pAnalParams->iDefaultSizeWindow; + + /* fill sound buffer and perform pre-emphasis */ + if (sizeWaveform > 0) + sms_fillSoundBuffer(sizeWaveform, pWaveform, pAnalParams); + + /* move analysis data one frame back */ + pTmpAnalFrame = pAnalParams->ppFrames[0]; + for(i = 1; i < pAnalParams->iMaxDelayFrames; i++) + pAnalParams->ppFrames[i-1] = pAnalParams->ppFrames[i]; + pAnalParams->ppFrames[pAnalParams->iMaxDelayFrames-1] = pTmpAnalFrame; + + /* initialize the current frame */ + sms_initFrame(iCurrentFrame, pAnalParams, pAnalParams->windowSize); + if(sms_errorCheck()) + { + printf("Error in init frame: %s \n", sms_errorString()); + return(0); + } + + if(pAnalParams->ppFrames[iCurrentFrame]->iStatus == SMS_FRAME_READY) + { + sfloat fAvgDev = sms_fundDeviation(pAnalParams, iCurrentFrame - 1); + + /* if single note use the default fundamental as reference */ + if(pAnalParams->iSoundType == SMS_SOUND_TYPE_NOTE) + fRefFundamental = pAnalParams->fDefaultFundamental; + /* if sound is stable use the last fundamental as a reference */ + else if(fAvgDev != -1 && fAvgDev <= pAnalParams->maxDeviation) + fRefFundamental = pAnalParams->ppFrames[iCurrentFrame - 1]->fFundamental; + else + fRefFundamental = 0; + + /* compute spectrum, find peaks, and find fundamental of frame */ + sms_analyzeFrame(iCurrentFrame, pAnalParams, fRefFundamental); + + /* set the size of the next analysis window */ + if(pAnalParams->ppFrames[iCurrentFrame]->fFundamental > 0 && + pAnalParams->iSoundType != SMS_SOUND_TYPE_NOTE) + pAnalParams->windowSize = sms_sizeNextWindow(iCurrentFrame, pAnalParams); + + /* figure out how much needs to be read next time */ + // how many processed - sample no. of end of next frame + // = no. samples that we haven't processed yet from whenever, if sizeNextRead was 0 + iExtraSamples = (pAnalParams->soundBuffer.iMarker + pAnalParams->soundBuffer.sizeBuffer) - + (pAnalParams->ppFrames[iCurrentFrame]->iFrameSample + pAnalParams->sizeHop); + + pAnalParams->sizeNextRead = MAX(0, (pAnalParams->windowSize+1)/2 - iExtraSamples); + ReAnalyzeFrame(iCurrentFrame, pAnalParams); + + /* save peaks */ + pSpectralPeaks->nPeaksFound = pAnalParams->ppFrames[iCurrentFrame]->nPeaks; + pSpectralPeaks->nPeaks = pAnalParams->maxPeaks; + pSpectralPeaks->pSpectralPeaks = pAnalParams->ppFrames[iCurrentFrame]->pSpectralPeaks; /* convert peak amps to linear */ for(i = 0; i < pSpectralPeaks->nPeaksFound; i++) { pSpectralPeaks->pSpectralPeaks[i].fMag = pow(10.0, 0.05*(pSpectralPeaks->pSpectralPeaks[i].fMag)); } - return pSpectralPeaks->nPeaks; - } - else - { - return 0; - } + return pSpectralPeaks->nPeaks; + } + else + { + return 0; + } } void sms_setPeaks(SMS_AnalParams *pAnalParams, int numamps, sfloat* amps, - int numfreqs, sfloat* freqs, int numphases, sfloat* phases) + int numfreqs, sfloat* freqs, int numphases, sfloat* phases) { - int i; - SMS_AnalFrame *tempFrame; - - /* move analysis data one frame back */ - tempFrame = pAnalParams->ppFrames[0]; - for(i = 1; i < pAnalParams->iMaxDelayFrames; i++) - pAnalParams->ppFrames[i-1] = pAnalParams->ppFrames[i]; - pAnalParams->ppFrames[pAnalParams->iMaxDelayFrames-1] = tempFrame; - - /* initialize the current frame */ - SMS_AnalFrame *currentFrame = pAnalParams->ppFrames[2]; - sms_initFrame(2, pAnalParams, 0); - if(sms_errorCheck()) - { - printf("Error in init frame: %s \n", sms_errorString()); - return; - } - - for(i = 0; i < numamps; i++) - { - /* copy current peaks data */ - currentFrame->pSpectralPeaks[i].fMag = sms_magToDB(amps[i]); - currentFrame->pSpectralPeaks[i].fFreq = freqs[i]; - currentFrame->pSpectralPeaks[i].fPhase = phases[i]; - } - currentFrame->nPeaks = numamps; - currentFrame->iStatus = SMS_FRAME_READY; - - /* harmonic detection */ - if (currentFrame->nPeaks > 0 && - (pAnalParams->iFormat == SMS_FORMAT_H || pAnalParams->iFormat == SMS_FORMAT_HP)) - { - /* get a reference fundamental */ - sfloat refFundamental = 0; - sfloat avgDeviation = sms_fundDeviation(pAnalParams, 1); - if(pAnalParams->iSoundType == SMS_SOUND_TYPE_NOTE) - refFundamental = pAnalParams->fDefaultFundamental; - /* if sound is stable use the last fundamental as a reference */ - else if(avgDeviation != -1 && avgDeviation <= pAnalParams->maxDeviation) - refFundamental = pAnalParams->ppFrames[1]->fFundamental; - else - refFundamental = 0; - - currentFrame->fFundamental = sms_harmDetection(pAnalParams->nTracks, currentFrame->pSpectralPeaks, - refFundamental, pAnalParams->iRefHarmonic, - pAnalParams->fLowestFundamental, pAnalParams->fHighestFundamental, - pAnalParams->iSoundType, pAnalParams->fMinRefHarmMag, - pAnalParams->fRefHarmMagDiffFromMax); - } + int i; + SMS_AnalFrame *tempFrame; + + /* move analysis data one frame back */ + tempFrame = pAnalParams->ppFrames[0]; + for(i = 1; i < pAnalParams->iMaxDelayFrames; i++) + pAnalParams->ppFrames[i-1] = pAnalParams->ppFrames[i]; + pAnalParams->ppFrames[pAnalParams->iMaxDelayFrames-1] = tempFrame; + + /* initialize the current frame */ + SMS_AnalFrame *currentFrame = pAnalParams->ppFrames[2]; + sms_initFrame(2, pAnalParams, 0); + if(sms_errorCheck()) + { + printf("Error in init frame: %s \n", sms_errorString()); + return; + } + + for(i = 0; i < numamps; i++) + { + /* copy current peaks data */ + currentFrame->pSpectralPeaks[i].fMag = sms_magToDB(amps[i]); + currentFrame->pSpectralPeaks[i].fFreq = freqs[i]; + currentFrame->pSpectralPeaks[i].fPhase = phases[i]; + } + currentFrame->nPeaks = numamps; + currentFrame->iStatus = SMS_FRAME_READY; + + /* harmonic detection */ + if (currentFrame->nPeaks > 0 && + (pAnalParams->iFormat == SMS_FORMAT_H || pAnalParams->iFormat == SMS_FORMAT_HP)) + { + /* get a reference fundamental */ + sfloat refFundamental = 0; + sfloat avgDeviation = sms_fundDeviation(pAnalParams, 1); + if(pAnalParams->iSoundType == SMS_SOUND_TYPE_NOTE) + refFundamental = pAnalParams->fDefaultFundamental; + /* if sound is stable use the last fundamental as a reference */ + else if(avgDeviation != -1 && avgDeviation <= pAnalParams->maxDeviation) + refFundamental = pAnalParams->ppFrames[1]->fFundamental; + else + refFundamental = 0; + + currentFrame->fFundamental = sms_harmDetection(pAnalParams->nTracks, currentFrame->pSpectralPeaks, + refFundamental, pAnalParams->iRefHarmonic, + pAnalParams->fLowestFundamental, pAnalParams->fHighestFundamental, + pAnalParams->iSoundType, pAnalParams->fMinRefHarmMag, + pAnalParams->fRefHarmMagDiffFromMax); + } } int sms_findPartials(SMS_Data *pSmsData, SMS_AnalParams *pAnalParams) { - /* clear SMS output */ - sms_clearFrame(pSmsData); - - /* incorporate the peaks into the corresponding tracks */ - /* todo: allow for longer analysis delays */ - if(pAnalParams->ppFrames[1]->fFundamental > 0 || - ((pAnalParams->iFormat == SMS_FORMAT_IH || pAnalParams->iFormat == SMS_FORMAT_IHP) && - pAnalParams->ppFrames[1]->nPeaks > 0)) - { - sms_peakContinuation(1, pAnalParams); - } - - /* fill gaps and delete short tracks */ - /* todo: allow for longer analysis delays */ - if(pAnalParams->iCleanTracks > 0) - { - sms_cleanTracks(1, pAnalParams); - } - - /* output data */ - sms_allocFrame(pSmsData, pAnalParams->nTracks, pAnalParams->nStochasticCoeff, - 1, pAnalParams->iStochasticType, pAnalParams->specEnvParams.nCoeff); - - int length = sizeof(sfloat) * pSmsData->nTracks; - memcpy((char *) pSmsData->pFSinFreq, (char *) - pAnalParams->ppFrames[0]->deterministic.pFSinFreq, length); - memcpy((char *) pSmsData->pFSinAmp, (char *) - pAnalParams->ppFrames[0]->deterministic.pFSinAmp, length); - - /* convert mags back to linear */ - sms_arrayDBToMag(pSmsData->nTracks, pSmsData->pFSinAmp); - - if(pAnalParams->iFormat == SMS_FORMAT_HP || - pAnalParams->iFormat == SMS_FORMAT_IHP) - memcpy((char *) pSmsData->pFSinPha, (char *) - pAnalParams->ppFrames[0]->deterministic.pFSinPha, length); - - /* do post-processing (for now, spectral envelope calculation and storage) */ - if(pAnalParams->specEnvParams.iType != SMS_ENV_NONE) - { - sms_spectralEnvelope(pSmsData, &pAnalParams->specEnvParams); - } - - return 1; + /* clear SMS output */ + sms_clearFrame(pSmsData); + + /* incorporate the peaks into the corresponding tracks */ + /* todo: allow for longer analysis delays */ + if(pAnalParams->ppFrames[1]->fFundamental > 0 || + ((pAnalParams->iFormat == SMS_FORMAT_IH || pAnalParams->iFormat == SMS_FORMAT_IHP) && + pAnalParams->ppFrames[1]->nPeaks > 0)) + { + sms_peakContinuation(1, pAnalParams); + } + + /* fill gaps and delete short tracks */ + /* todo: allow for longer analysis delays */ + if(pAnalParams->iCleanTracks > 0) + { + sms_cleanTracks(1, pAnalParams); + } + + /* output data */ + sms_allocFrame(pSmsData, pAnalParams->nTracks, pAnalParams->nStochasticCoeff, + 1, pAnalParams->iStochasticType, pAnalParams->specEnvParams.nCoeff); + + int length = sizeof(sfloat) * pSmsData->nTracks; + memcpy((char *) pSmsData->pFSinFreq, (char *) + pAnalParams->ppFrames[0]->deterministic.pFSinFreq, length); + memcpy((char *) pSmsData->pFSinAmp, (char *) + pAnalParams->ppFrames[0]->deterministic.pFSinAmp, length); + + /* convert mags back to linear */ + sms_arrayDBToMag(pSmsData->nTracks, pSmsData->pFSinAmp); + + if(pAnalParams->iFormat == SMS_FORMAT_HP || + pAnalParams->iFormat == SMS_FORMAT_IHP) + memcpy((char *) pSmsData->pFSinPha, (char *) + pAnalParams->ppFrames[0]->deterministic.pFSinPha, length); + + /* do post-processing (for now, spectral envelope calculation and storage) */ + if(pAnalParams->specEnvParams.iType != SMS_ENV_NONE) + { + sms_spectralEnvelope(pSmsData, &pAnalParams->specEnvParams); + } + + return 1; } int sms_findResidual(int sizeSynthesis, sfloat* pSynthesis, - int sizeOriginal, sfloat* pOriginal, - int sizeResidual, sfloat* pResidual, - SMS_AnalParams *analParams) + int sizeOriginal, sfloat* pOriginal, + int sizeResidual, sfloat* pResidual, + SMS_AnalParams *analParams) { - if(sizeSynthesis != sizeOriginal || sizeOriginal != sizeResidual) - { - return -1; - } - - /* perform preemphasis */ - int i; - for(i = 0; i < sizeSynthesis; i++) - { - pOriginal[i] = sms_preEmphasis(pOriginal[i], analParams); - } - - sms_residual(sizeResidual, pSynthesis, pOriginal, pResidual); - return 0; + if(sizeSynthesis != sizeOriginal || sizeOriginal != sizeResidual) + { + return -1; + } + + /* perform preemphasis */ + int i; + for(i = 0; i < sizeSynthesis; i++) + { + pOriginal[i] = sms_preEmphasis(pOriginal[i], analParams); + } + + /*sms_residual(sizeResidual, pSynthesis, pOriginal, pResidual);*/ + return 0; } void sms_approxResidual(int sizeResidual, sfloat* pResidual, - SMS_Data* pSmsData, SMS_SynthParams* pSynthParams) + SMS_Data* pSmsData, SMS_SynthParams* pSynthParams) { - /* perform stochastic analysis after 1 frame of the */ - /* deterministic synthesis because it needs two frames */ -// if (pAnalParams->ppFrames[0]->iStatus != SMS_FRAME_EMPTY && -// pAnalParams->ppFrames[0]->iStatus != SMS_FRAME_END) -// { -// int sizeResidual = pAnalParams->sizeHop * 2; -// int iSoundLoc = pAnalParams->ppFrames[0]->iFrameSample - pAnalParams->sizeHop; -// // sfloat *pOriginal = &(pAnalParams->soundBuffer.pFBuffer[iSoundLoc - pAnalParams->soundBuffer.iMarker]); -// sfloat *pOriginal; -// sfloat *pFResidual; + /* perform stochastic analysis after 1 frame of the */ + /* deterministic synthesis because it needs two frames */ +// if (pAnalParams->ppFrames[0]->iStatus != SMS_FRAME_EMPTY && +// pAnalParams->ppFrames[0]->iStatus != SMS_FRAME_END) +// { +// int sizeResidual = pAnalParams->sizeHop * 2; +// int iSoundLoc = pAnalParams->ppFrames[0]->iFrameSample - pAnalParams->sizeHop; +// // sfloat *pOriginal = &(pAnalParams->soundBuffer.pFBuffer[iSoundLoc - pAnalParams->soundBuffer.iMarker]); +// sfloat *pOriginal; +// sfloat *pFResidual; // -// static sfloat *pWindow; -// static int sizeWindowArray = 0; +// static sfloat *pWindow; +// static int sizeWindowArray = 0; // -// // int sizeData = MIN(pAnalParams->soundBuffer.sizeBuffer - -// // (iSoundLoc - pAnalParams->soundBuffer.iMarker), -// // sizeResidual); -// int sizeData = sizeResidual; -// if ((pFResidual = (sfloat *) calloc (sizeResidual, sizeof(sfloat))) == NULL) -// { -// sms_error("sms_analyze: error allocating memory for pFResidual"); -// return -1; -// } -// if (sizeWindowArray != sizeData) -// { -// if(sizeWindowArray != 0) free(pWindow); -// if((pWindow = (sfloat *) calloc(sizeData, sizeof(sfloat))) == NULL) -// { -// sms_error("sms_analyze: error allocating memory for pWindow"); -// return -1; -// } -// sms_getWindow( sizeData, pWindow, SMS_WIN_HAMMING); -// sms_scaleWindow( sizeData, pWindow); -// sizeWindowArray = sizeData; -// } +// // int sizeData = MIN(pAnalParams->soundBuffer.sizeBuffer - +// // (iSoundLoc - pAnalParams->soundBuffer.iMarker), +// // sizeResidual); +// int sizeData = sizeResidual; +// if ((pFResidual = (sfloat *) calloc (sizeResidual, sizeof(sfloat))) == NULL) +// { +// sms_error("sms_analyze: error allocating memory for pFResidual"); +// return -1; +// } +// if (sizeWindowArray != sizeData) +// { +// if(sizeWindowArray != 0) free(pWindow); +// if((pWindow = (sfloat *) calloc(sizeData, sizeof(sfloat))) == NULL) +// { +// sms_error("sms_analyze: error allocating memory for pWindow"); +// return -1; +// } +// sms_getWindow( sizeData, pWindow, SMS_WIN_HAMMING); +// sms_scaleWindow( sizeData, pWindow); +// sizeWindowArray = sizeData; +// } // -// /* obtain residual sound from original and synthesized sounds. accumulate the residual percentage.*/ -// pAnalParams->fResidualAccumPerc += sms_residual(sizeData, -// pAnalParams->synthBuffer.pFBuffer, -// pOriginal, -// pFResidual, -// pWindow); +// /* obtain residual sound from original and synthesized sounds. accumulate the residual percentage.*/ +// pAnalParams->fResidualAccumPerc += sms_residual(sizeData, +// pAnalParams->synthBuffer.pFBuffer, +// pOriginal, +// pFResidual, +// pWindow); // -// if (pAnalParams->iStochasticType == SMS_STOC_APPROX) -// { -// /* filter residual with a high pass filter (it solves some problems) */ -// sms_filterHighPass (sizeData, pFResidual, pAnalParams->iSamplingRate); +// if (pAnalParams->iStochasticType == SMS_STOC_APPROX) +// { +// /* filter residual with a high pass filter (it solves some problems) */ +// sms_filterHighPass (sizeData, pFResidual, pAnalParams->iSamplingRate); // -// /* approximate residual */ -// sms_stocAnalysis (sizeData, pFResidual, pWindow, pSmsData); -// } -// else if (pAnalParams->iStochasticType == SMS_STOC_IFFT) -// { -// int sizeMag = sms_power2(sizeData >> 1); -// sms_spectrum (sizeData, pFResidual, pWindow, sizeMag, pSmsData->pFStocCoeff, -// pSmsData->pResPhase); -// } +// /* approximate residual */ +// sms_stocAnalysis (sizeData, pFResidual, pWindow, pSmsData); +// } +// else if (pAnalParams->iStochasticType == SMS_STOC_IFFT) +// { +// int sizeMag = sms_power2(sizeData >> 1); +// sms_spectrum (sizeData, pFResidual, pWindow, sizeMag, pSmsData->pFStocCoeff, +// pSmsData->pResPhase); +// } // -// /* get sharper transitions in deterministic representation */ -// // sms_scaleDet (pAnalParams->synthBuffer.pFBuffer, pOriginal, -// // pAnalParams->ppFrames[0]->deterministic.pFSinAmp, -// // pAnalParams, pSmsData->nTracks); +// /* get sharper transitions in deterministic representation */ +// // sms_scaleDet (pAnalParams->synthBuffer.pFBuffer, pOriginal, +// // pAnalParams->ppFrames[0]->deterministic.pFSinAmp, +// // pAnalParams, pSmsData->nTracks); // -// pAnalParams->ppFrames[0]->iStatus = SMS_FRAME_DONE; +// pAnalParams->ppFrames[0]->iStatus = SMS_FRAME_DONE; // -// free ((char *) pFResidual); /* \todo get rid of this free, manage memory the same as spectrum functions */ -// } +// free ((char *) pFResidual); /* \todo get rid of this free, manage memory the same as spectrum functions */ +// } } -int sms_analyze (int sizeWaveform, sfloat *pWaveform, SMS_Data *pSmsData, SMS_AnalParams *pAnalParams) +int sms_analyze(int sizeWaveform, sfloat *pWaveform, SMS_Data *pSmsData, SMS_AnalParams *pAnalParams) { - static int sizeWindow = 0; /* size of current analysis window */ //RTE ?: shouldn't this just be initilalized outside? - - int iCurrentFrame = pAnalParams->iMaxDelayFrames - 1; /* frame # of current frame */ - int delayFrames = pAnalParams->minGoodFrames + pAnalParams->analDelay; - int i, iError, iExtraSamples; /* samples used for next analysis frame */ - sfloat fRefFundamental = 0; /* reference fundamental for current frame */ + int iCurrentFrame = pAnalParams->iMaxDelayFrames - 1; /* frame # of current frame */ + int delayFrames; + int i, iError, iExtraSamples; /* samples used for next analysis frame */ + sfloat fRefFundamental = 0; /* reference fundamental for current frame */ SMS_AnalFrame *pTmpAnalFrame; - /* clear SMS output */ - sms_clearFrame (pSmsData); - - /* set initial analysis-window size */ - if (sizeWindow == 0) - sizeWindow = pAnalParams->iDefaultSizeWindow; - - /* fill the input sound buffer and perform pre-emphasis */ - if (sizeWaveform > 0) - sms_fillSoundBuffer (sizeWaveform, pWaveform, pAnalParams); - - /* move analysis data one frame back */ - pTmpAnalFrame = pAnalParams->ppFrames[0]; - for(i = 1; i < pAnalParams->iMaxDelayFrames; i++) - pAnalParams->ppFrames[i-1] = pAnalParams->ppFrames[i]; - pAnalParams->ppFrames[pAnalParams->iMaxDelayFrames-1] = pTmpAnalFrame; - - /* initialize the current frame */ - sms_initFrame (iCurrentFrame, pAnalParams, sizeWindow); - if(sms_errorCheck()) - { - printf("error in init frame: %s \n", sms_errorString()); - return(-1); - } - - /* if right data in the sound buffer do analysis */ - if (pAnalParams->ppFrames[iCurrentFrame]->iStatus == SMS_FRAME_READY) - { - sfloat fAvgDev = sms_fundDeviation( pAnalParams, iCurrentFrame - 1); - - /* if single note use the default fundamental as reference */ - if (pAnalParams->iSoundType == SMS_SOUND_TYPE_NOTE) - fRefFundamental = pAnalParams->fDefaultFundamental; - /* if sound is stable use the last fundamental as a reference */ - else if (fAvgDev != -1 && fAvgDev <= pAnalParams->maxDeviation) - fRefFundamental = pAnalParams->ppFrames[iCurrentFrame - 1]->fFundamental; - else - fRefFundamental = 0; - - /* compute spectrum, find peaks, and find fundamental of frame */ - sms_analyzeFrame (iCurrentFrame, pAnalParams, fRefFundamental); - - /* set the size of the next analysis window */ - if (pAnalParams->ppFrames[iCurrentFrame]->fFundamental > 0 && - pAnalParams->iSoundType != SMS_SOUND_TYPE_NOTE) - sizeWindow = sms_sizeNextWindow (iCurrentFrame, pAnalParams); - - /* figure out how much needs to be read next time */ - iExtraSamples = - (pAnalParams->soundBuffer.iMarker + pAnalParams->soundBuffer.sizeBuffer) - - (pAnalParams->ppFrames[iCurrentFrame]->iFrameSample + pAnalParams->sizeHop); - - pAnalParams->sizeNextRead = MAX (0, (sizeWindow+1)/2 - iExtraSamples); - - /* check again the previous frames and recompute if necessary */ - ReAnalyzeFrame (iCurrentFrame, pAnalParams); - } - - /* incorporate the peaks into the corresponding tracks */ - /* This is done after a pAnalParams->iMaxDelayFrames delay */ - if (pAnalParams->ppFrames[iCurrentFrame - delayFrames]->fFundamental > 0 || - ((pAnalParams->iFormat == SMS_FORMAT_IH || - pAnalParams->iFormat == SMS_FORMAT_IHP) && - pAnalParams->ppFrames[iCurrentFrame - delayFrames]->nPeaks > 0)) - sms_peakContinuation (iCurrentFrame - delayFrames, pAnalParams); - - /* fill gaps and delete short tracks */ - if (pAnalParams->iCleanTracks > 0 && - pAnalParams->ppFrames[iCurrentFrame - delayFrames]->iStatus != SMS_FRAME_EMPTY) - sms_cleanTracks (iCurrentFrame - delayFrames, pAnalParams); - - /* do stochastic analysis */ - if (pAnalParams->iStochasticType != SMS_STOC_NONE) - { - /* synthesize deterministic signal */ - if (pAnalParams->ppFrames[1]->iStatus != SMS_FRAME_EMPTY && - pAnalParams->ppFrames[1]->iStatus != SMS_FRAME_END) - { - /* shift synthesis buffer */ - memcpy(pAnalParams->synthBuffer.pFBuffer, + /* set the frame delay, checking that it does not exceed the given maximum + * + * TODO: check for good values of pAnalParams->minGoodFrames and + * pAnalParams->analDelay here too? Or figure out why sms_crashes if + * pAnalParamx->iMaxDelayFrames is changed without changing the other + * two variables. + */ + delayFrames = pAnalParams->minGoodFrames + pAnalParams->analDelay; + if(delayFrames > (pAnalParams->iMaxDelayFrames - 1)) + delayFrames = pAnalParams->iMaxDelayFrames - 1; + + /* clear SMS output */ + sms_clearFrame(pSmsData); + + /* set initial analysis-window size */ + if(pAnalParams->windowSize == 0) + pAnalParams->windowSize = pAnalParams->iDefaultSizeWindow; + + /* fill the input sound buffer and perform pre-emphasis */ + if(sizeWaveform > 0) + sms_fillSoundBuffer(sizeWaveform, pWaveform, pAnalParams); + + /* move analysis data one frame back */ + pTmpAnalFrame = pAnalParams->ppFrames[0]; + for(i = 1; i < pAnalParams->iMaxDelayFrames; i++) + pAnalParams->ppFrames[i-1] = pAnalParams->ppFrames[i]; + pAnalParams->ppFrames[pAnalParams->iMaxDelayFrames-1] = pTmpAnalFrame; + + /* initialize the current frame */ + sms_initFrame(iCurrentFrame, pAnalParams, pAnalParams->windowSize); + if(sms_errorCheck()) + { + printf("error in init frame: %s \n", sms_errorString()); + return -1; + } + + /* if right data in the sound buffer do analysis */ + if(pAnalParams->ppFrames[iCurrentFrame]->iStatus == SMS_FRAME_READY) + { + sfloat fAvgDev = sms_fundDeviation(pAnalParams, iCurrentFrame - 1); + + /* if single note use the default fundamental as reference */ + if(pAnalParams->iSoundType == SMS_SOUND_TYPE_NOTE) + fRefFundamental = pAnalParams->fDefaultFundamental; + /* if sound is stable use the last fundamental as a reference */ + else if(fAvgDev != -1 && fAvgDev <= pAnalParams->maxDeviation) + fRefFundamental = pAnalParams->ppFrames[iCurrentFrame - 1]->fFundamental; + else + fRefFundamental = 0; + + /* compute spectrum, find peaks, and find fundamental of frame */ + sms_analyzeFrame(iCurrentFrame, pAnalParams, fRefFundamental); + + /* set the size of the next analysis window */ + if(pAnalParams->ppFrames[iCurrentFrame]->fFundamental > 0 && + pAnalParams->iSoundType != SMS_SOUND_TYPE_NOTE) + pAnalParams->windowSize = sms_sizeNextWindow (iCurrentFrame, pAnalParams); + + /* figure out how much needs to be read next time */ + iExtraSamples = + (pAnalParams->soundBuffer.iMarker + pAnalParams->soundBuffer.sizeBuffer) - + (pAnalParams->ppFrames[iCurrentFrame]->iFrameSample + pAnalParams->sizeHop); + + pAnalParams->sizeNextRead = MAX(0, (pAnalParams->windowSize+1)/2 - iExtraSamples); + + /* check again the previous frames and recompute if necessary */ + ReAnalyzeFrame(iCurrentFrame, pAnalParams); + } + + /* incorporate the peaks into the corresponding tracks */ + /* This is done after a pAnalParams->iMaxDelayFrames delay */ + if(pAnalParams->ppFrames[iCurrentFrame - delayFrames]->fFundamental > 0 || + ((pAnalParams->iFormat == SMS_FORMAT_IH || pAnalParams->iFormat == SMS_FORMAT_IHP) && + pAnalParams->ppFrames[iCurrentFrame - delayFrames]->nPeaks > 0)) + sms_peakContinuation(iCurrentFrame - delayFrames, pAnalParams); + + /* fill gaps and delete short tracks */ + if(pAnalParams->iCleanTracks > 0 && + pAnalParams->ppFrames[iCurrentFrame - delayFrames]->iStatus != SMS_FRAME_EMPTY) + sms_cleanTracks(iCurrentFrame - delayFrames, pAnalParams); + + /* do stochastic analysis */ + if(pAnalParams->iStochasticType != SMS_STOC_NONE) + { + /* synthesize deterministic signal */ + if(pAnalParams->ppFrames[1]->iStatus != SMS_FRAME_EMPTY && + pAnalParams->ppFrames[1]->iStatus != SMS_FRAME_END) + { + /* shift synthesis buffer */ + memcpy(pAnalParams->synthBuffer.pFBuffer, pAnalParams->synthBuffer.pFBuffer+pAnalParams->sizeHop, - sizeof(sfloat) * pAnalParams->sizeHop); - memset(pAnalParams->synthBuffer.pFBuffer+pAnalParams->sizeHop, + sizeof(sfloat) * pAnalParams->sizeHop); + memset(pAnalParams->synthBuffer.pFBuffer+pAnalParams->sizeHop, 0, sizeof(sfloat) * pAnalParams->sizeHop); - /* get deterministic signal with phase */ - sms_sineSynthFrame(&pAnalParams->ppFrames[1]->deterministic, - pAnalParams->synthBuffer.pFBuffer+pAnalParams->sizeHop, - pAnalParams->sizeHop, &pAnalParams->prevFrame, - pAnalParams->iSamplingRate); - } - - /* perform stochastic analysis after 1 frame of the */ - /* deterministic synthesis because it needs two frames */ - if (pAnalParams->ppFrames[0]->iStatus != SMS_FRAME_EMPTY && - pAnalParams->ppFrames[0]->iStatus != SMS_FRAME_END) - - { - int sizeResidual = pAnalParams->sizeHop * 2; - int iSoundLoc = pAnalParams->ppFrames[0]->iFrameSample - pAnalParams->sizeHop; - sfloat *pOriginal = &(pAnalParams->soundBuffer.pFBuffer[iSoundLoc - - pAnalParams->soundBuffer.iMarker]); - sfloat *pFResidual; - - static sfloat *pWindow; - static int sizeWindowArray = 0; - - int sizeData = MIN(pAnalParams->soundBuffer.sizeBuffer - - (iSoundLoc - pAnalParams->soundBuffer.iMarker), - sizeResidual); - if ((pFResidual = (sfloat *) calloc (sizeResidual, sizeof(sfloat))) == NULL) - { - sms_error("sms_analyze: error allocating memory for pFResidual"); - return -1; - } - if (sizeWindowArray != sizeData) - { - if(sizeWindowArray != 0) free(pWindow); - if((pWindow = (sfloat *) calloc(sizeData, sizeof(sfloat))) == NULL) - { - sms_error("sms_analyze: error allocating memory for pWindow"); - return -1; - } - sms_getWindow( sizeData, pWindow, SMS_WIN_HAMMING); - sms_scaleWindow( sizeData, pWindow); - sizeWindowArray = sizeData; - } - - /* obtain residual sound from original and synthesized sounds. accumulate the residual percentage.*/ - pAnalParams->fResidualAccumPerc += sms_residual(sizeData, - pAnalParams->synthBuffer.pFBuffer, - pOriginal, - pFResidual); - - if(pAnalParams->iStochasticType == SMS_STOC_APPROX) - { - /* filter residual with a high pass filter (it solves some problems) */ - sms_filterHighPass (sizeData, pFResidual, pAnalParams->iSamplingRate); - - /* approximate residual */ - sms_stocAnalysis (sizeData, pFResidual, pWindow, pSmsData); - } - else if(pAnalParams->iStochasticType == SMS_STOC_IFFT) - { - int sizeMag = sms_power2(sizeData >> 1); - sms_spectrum (sizeData, pFResidual, pWindow, sizeMag, pSmsData->pFStocCoeff, - pSmsData->pResPhase); - } - - /* get sharper transitions in deterministic representation */ - sms_scaleDet(pAnalParams->synthBuffer.pFBuffer, pOriginal, - pAnalParams->ppFrames[0]->deterministic.pFSinAmp, - pAnalParams, pSmsData->nTracks); - - pAnalParams->ppFrames[0]->iStatus = SMS_FRAME_DONE; - - free ((char *) pFResidual); /* \todo get rid of this free, manage memory the same as spectrum functions */ - } - } - else if (pAnalParams->ppFrames[0]->iStatus != SMS_FRAME_EMPTY && - pAnalParams->ppFrames[0]->iStatus != SMS_FRAME_END) - pAnalParams->ppFrames[0]->iStatus = SMS_FRAME_DONE; - - /* get the result */ - if (pAnalParams->ppFrames[0]->iStatus == SMS_FRAME_EMPTY) - { - /* no partials yet, so output the current peaks for testing */ - int numPeaks = pAnalParams->ppFrames[iCurrentFrame]->nPeaks; - int numTracks = pSmsData->nTracks; - numTracks = MIN(numPeaks, numTracks); - for(i = 0; i < numTracks; i++) - { - pSmsData->pFSinFreq[i] = pAnalParams->ppFrames[iCurrentFrame]->pSpectralPeaks[i].fFreq; - pSmsData->pFSinAmp[i] = pAnalParams->ppFrames[iCurrentFrame]->pSpectralPeaks[i].fMag; - if(pAnalParams->iFormat == SMS_FORMAT_HP || - pAnalParams->iFormat == SMS_FORMAT_IHP) - { - pSmsData->pFSinPha[i] = pAnalParams->ppFrames[iCurrentFrame]->pSpectralPeaks[i].fPhase; - } - } - pSmsData->nTracks = numTracks; - return 0; - } - /* return analysis data */ - else if (pAnalParams->ppFrames[0]->iStatus == SMS_FRAME_DONE) - { - /* put data into output */ - int length = sizeof(sfloat) * pSmsData->nTracks; - memcpy ((char *) pSmsData->pFSinFreq, (char *) - pAnalParams->ppFrames[0]->deterministic.pFSinFreq, length); - memcpy ((char *) pSmsData->pFSinAmp, (char *) - pAnalParams->ppFrames[0]->deterministic.pFSinAmp, length); - - /* convert mags back to linear */ - sms_arrayDBToMag(pSmsData->nTracks, pSmsData->pFSinAmp); - if (pAnalParams->iFormat == SMS_FORMAT_HP || - pAnalParams->iFormat == SMS_FORMAT_IHP) - memcpy ((char *) pSmsData->pFSinPha, (char *) - pAnalParams->ppFrames[0]->deterministic.pFSinPha, length); - - /* do post-processing (for now, spectral envelope calculation and storage) */ - if(pAnalParams->specEnvParams.iType != SMS_ENV_NONE) - { - sms_spectralEnvelope( pSmsData, &pAnalParams->specEnvParams); - } - return (1); - } - /* done, end of sound */ - else if (pAnalParams->ppFrames[0]->iStatus == SMS_FRAME_END) - return (-1); - else - { - sms_error ("sms_analyze error: wrong status of frame."); - return(-1); - } - return (1); + /* get deterministic signal with phase */ + sms_sineSynthFrame(&pAnalParams->ppFrames[1]->deterministic, + pAnalParams->synthBuffer.pFBuffer+pAnalParams->sizeHop, + pAnalParams->sizeHop, &pAnalParams->prevFrame, + pAnalParams->iSamplingRate); + } + + /* perform stochastic analysis after 1 frame of the */ + /* deterministic synthesis because it needs two frames */ + if(pAnalParams->ppFrames[0]->iStatus != SMS_FRAME_EMPTY && + pAnalParams->ppFrames[0]->iStatus != SMS_FRAME_END) + { + int sizeResidual = pAnalParams->sizeHop * 2; + int iSoundLoc = pAnalParams->ppFrames[0]->iFrameSample - pAnalParams->sizeHop; + sfloat *pOriginal = &(pAnalParams->soundBuffer.pFBuffer[iSoundLoc - + pAnalParams->soundBuffer.iMarker]); + + int sizeData = MIN(pAnalParams->soundBuffer.sizeBuffer - + (iSoundLoc - pAnalParams->soundBuffer.iMarker), + pAnalParams->sizeResidual); + + if(sizeData > pAnalParams->sizeResidual) + { + sms_error("Residual size larger than expected."); + return -1; + } + else if(sizeData < pAnalParams->sizeResidual) + { + /* should only happen if we're at the end of a sound, unless hop size changes */ + sms_getWindow(sizeData, pAnalParams->residualWindow, SMS_WIN_HAMMING); + sms_scaleWindow(sizeData, pAnalParams->residualWindow); + } + + /* obtain residual sound from original and synthesized sounds. accumulate the residual percentage.*/ + pAnalParams->fResidualAccumPerc += sms_residual(sizeData, + pAnalParams->synthBuffer.pFBuffer, + pOriginal, + pAnalParams->residual, + pAnalParams->residualWindow); + + if(pAnalParams->iStochasticType == SMS_STOC_APPROX) + { + /* filter residual with a high pass filter (it solves some problems) */ + sms_filterHighPass(sizeData, pAnalParams->residual, pAnalParams->iSamplingRate); + + /* approximate residual */ + sms_stocAnalysis(sizeData, pAnalParams->residual, pAnalParams->residualWindow, + pSmsData, pAnalParams); + } + else if(pAnalParams->iStochasticType == SMS_STOC_IFFT) + { + int sizeMag = sms_power2(sizeData >> 1); + sms_spectrum(sizeData, pAnalParams->residual, pAnalParams->residualWindow, + sizeMag, pSmsData->pFStocCoeff, pSmsData->pResPhase, + pAnalParams->fftBuffer); + } + + /* get sharper transitions in deterministic representation */ + sms_scaleDet(pAnalParams->synthBuffer.pFBuffer, pOriginal, + pAnalParams->ppFrames[0]->deterministic.pFSinAmp, + pAnalParams, pSmsData->nTracks); + + pAnalParams->ppFrames[0]->iStatus = SMS_FRAME_DONE; + } + } + else if(pAnalParams->ppFrames[0]->iStatus != SMS_FRAME_EMPTY && + pAnalParams->ppFrames[0]->iStatus != SMS_FRAME_END) + pAnalParams->ppFrames[0]->iStatus = SMS_FRAME_DONE; + + /* get the result */ + if(pAnalParams->ppFrames[0]->iStatus == SMS_FRAME_EMPTY) + { + /* no partials yet, so output the current peaks for testing */ + int numPeaks = pAnalParams->ppFrames[iCurrentFrame]->nPeaks; + int numTracks = pSmsData->nTracks; + numTracks = MIN(numPeaks, numTracks); + for(i = 0; i < numTracks; i++) + { + pSmsData->pFSinFreq[i] = pAnalParams->ppFrames[iCurrentFrame]->pSpectralPeaks[i].fFreq; + pSmsData->pFSinAmp[i] = pAnalParams->ppFrames[iCurrentFrame]->pSpectralPeaks[i].fMag; + if(pAnalParams->iFormat == SMS_FORMAT_HP || + pAnalParams->iFormat == SMS_FORMAT_IHP) + { + pSmsData->pFSinPha[i] = pAnalParams->ppFrames[iCurrentFrame]->pSpectralPeaks[i].fPhase; + } + } + pSmsData->nTracks = numTracks; + return 0; + } + /* return analysis data */ + else if(pAnalParams->ppFrames[0]->iStatus == SMS_FRAME_DONE) + { + /* put data into output */ + int length = sizeof(sfloat) * pSmsData->nTracks; + memcpy((char *) pSmsData->pFSinFreq, (char *) + pAnalParams->ppFrames[0]->deterministic.pFSinFreq, length); + memcpy((char *) pSmsData->pFSinAmp, (char *) + pAnalParams->ppFrames[0]->deterministic.pFSinAmp, length); + + /* convert mags back to linear */ + sms_arrayDBToMag(pSmsData->nTracks, pSmsData->pFSinAmp); + if(pAnalParams->iFormat == SMS_FORMAT_HP || + pAnalParams->iFormat == SMS_FORMAT_IHP) + memcpy((char *) pSmsData->pFSinPha, (char *) + pAnalParams->ppFrames[0]->deterministic.pFSinPha, length); + + /* do post-processing (for now, spectral envelope calculation and storage) */ + if(pAnalParams->specEnvParams.iType != SMS_ENV_NONE) + { + sms_spectralEnvelope(pSmsData, &pAnalParams->specEnvParams); + } + return 1; + } + /* done, end of sound */ + else if(pAnalParams->ppFrames[0]->iStatus == SMS_FRAME_END) + return -1; + else + { + sms_error("sms_analyze error: wrong status of frame."); + return -1; + } + return 1; } diff --git a/sms/fileIO.c b/sms/fileIO.c index 8fbfa5b..e870c5a 100644 --- a/sms/fileIO.c +++ b/sms/fileIO.c @@ -37,7 +37,7 @@ static char pChTextString[1000]; /*!< string to store analysis parameters in sms * * \param pSmsHeader header for SMS file */ -void sms_initHeader (SMS_Header *pSmsHeader) +void sms_initHeader(SMS_Header *pSmsHeader) { pSmsHeader->iSmsMagic = SMS_MAGIC; pSmsHeader->iHeadBSize = sizeof(SMS_Header); @@ -51,8 +51,6 @@ void sms_initHeader (SMS_Header *pSmsHeader) pSmsHeader->nEnvCoeff = 0; pSmsHeader->iMaxFreq = 0; pSmsHeader->fResidualPerc = 0; - pSmsHeader->nTextCharacters = 0; - pSmsHeader->pChTextCharacters = NULL; } /*! \brief fill an SMS header with necessary information for storage @@ -67,10 +65,9 @@ void sms_initHeader (SMS_Header *pSmsHeader) * \param pAnalParams structure of analysis parameters * \param pProgramString pointer to a string containing the name of the program that made the analysis data */ -void sms_fillHeader (SMS_Header *pSmsHeader, SMS_AnalParams *pAnalParams, - char *pProgramString) +void sms_fillHeader(SMS_Header *pSmsHeader, SMS_AnalParams *pAnalParams, char *pProgramString) { - sms_initHeader (pSmsHeader); + sms_initHeader(pSmsHeader); pSmsHeader->nFrames = pAnalParams->nFrames; pSmsHeader->iFormat = pAnalParams->iFormat; pSmsHeader->iFrameRate = pAnalParams->iFrameRate; @@ -83,35 +80,8 @@ void sms_fillHeader (SMS_Header *pSmsHeader, SMS_AnalParams *pAnalParams, pSmsHeader->nStochasticCoeff = pAnalParams->nStochasticCoeff; pSmsHeader->iEnvType = pAnalParams->specEnvParams.iType; pSmsHeader->nEnvCoeff = pAnalParams->specEnvParams.nCoeff; - pSmsHeader->iMaxFreq = (int) pAnalParams->fHighestFreq; + pSmsHeader->iMaxFreq = (int)pAnalParams->fHighestFreq; pSmsHeader->iFrameBSize = sms_frameSizeB(pSmsHeader); - sprintf (pChTextString, - "created by %s with parameters: format %d, soundType %d, " - "analysisDirection %d, windowSize %.2f," - " windowType %d, frameRate %d, highestFreq %.2f, minPeakMag %.2f," - " refHarmonic %d, minRefHarmMag %.2f, refHarmMagDiffFromMax %.2f," - " defaultFund %.2f, lowestFund %.2f, highestFund %.2f, nGuides %d," - " nTracks %d, freqDeviation %.2f, peakContToGuide %.2f," - " fundContToGuide %.2f, cleanTracks %d, iMinTrackLength %d," - "iMaxSleepingTime %d, stochasticType %d, nStocCoeff %d\n" - "iEnvType: %d, nEnvCoeff: %d", - pProgramString, - pAnalParams->iFormat, pAnalParams->iSoundType, - pAnalParams->iAnalysisDirection, pAnalParams->fSizeWindow, - pAnalParams->iWindowType, pAnalParams->iFrameRate, - pAnalParams->fHighestFreq, pAnalParams->fMinPeakMag, - pAnalParams->iRefHarmonic, pAnalParams->fMinRefHarmMag, - pAnalParams->fRefHarmMagDiffFromMax, - pAnalParams->fDefaultFundamental, pAnalParams->fLowestFundamental, - pAnalParams->fHighestFundamental, pAnalParams->nGuides, - pAnalParams->nTracks, pAnalParams->fFreqDeviation, - pAnalParams->fPeakContToGuide, pAnalParams->fFundContToGuide, - pAnalParams->iCleanTracks, pAnalParams->iMinTrackLength, - pAnalParams->iMaxSleepingTime, pAnalParams->iStochasticType, - pAnalParams->nStochasticCoeff, pSmsHeader->iEnvType, pSmsHeader->nEnvCoeff); - - pSmsHeader->nTextCharacters = strlen (pChTextString) + 1; - pSmsHeader->pChTextCharacters = (char *) pChTextString; } /*! \brief write SMS header to file @@ -121,50 +91,31 @@ void sms_fillHeader (SMS_Header *pSmsHeader, SMS_AnalParams *pAnalParams, * \param ppSmsFile (double pointer to) file to be created * \return error code \see SMS_WRERR in SMS_ERRORS */ -int sms_writeHeader (char *pChFileName, SMS_Header *pSmsHeader, - FILE **ppSmsFile) +int sms_writeHeader(char *pChFileName, SMS_Header *pSmsHeader, FILE **ppSmsFile) { int iVariableSize = 0; - if (pSmsHeader->iSmsMagic != SMS_MAGIC) + if(pSmsHeader->iSmsMagic != SMS_MAGIC) { sms_error("not an SMS file"); - return(-1); + return -1; } - if ((*ppSmsFile = fopen (pChFileName, "w+")) == NULL) + if((*ppSmsFile = fopen (pChFileName, "w+")) == NULL) { sms_error("cannot open file for writing"); - return(-1); + return -1; } - /* check variable size of header */ - /* iVariableSize = sizeof (int) * pSmsHeader->nLoopRecords + */ - /* sizeof (sfloat) * pSmsHeader->nSpecEnvelopePoints + */ - /* sizeof(char) * pSmsHeader->nTextCharacters; */ - iVariableSize = sizeof(char) * pSmsHeader->nTextCharacters; - pSmsHeader->iHeadBSize = sizeof(SMS_Header) + iVariableSize; + pSmsHeader->iHeadBSize = sizeof(SMS_Header); /* write header */ - if (fwrite((void *)pSmsHeader, (size_t)1, (size_t)sizeof(SMS_Header), - *ppSmsFile) < (size_t)sizeof(SMS_Header)) + if(fwrite((void *)pSmsHeader, (size_t)1, (size_t)sizeof(SMS_Header), + *ppSmsFile) < (size_t)sizeof(SMS_Header)) { sms_error("cannot write output file"); return(-1); } - /* write variable part of header */ - if (pSmsHeader->nTextCharacters > 0) - { - char *pChStart = (char *) pSmsHeader->pChTextCharacters; - int iSize = sizeof(char) * pSmsHeader->nTextCharacters; - - if (fwrite ((void *)pChStart, (size_t)1, (size_t)iSize, *ppSmsFile) < - (size_t)iSize) - { - sms_error("cannot write output file (nTextCharacters)"); - return(-1); - } - } - return (0); + return 0; } /*! \brief rewrite SMS header and close file @@ -173,40 +124,23 @@ int sms_writeHeader (char *pChFileName, SMS_Header *pSmsHeader, * \param pSmsHeader pointer to header for SMS file * \return error code \see SMS_WRERR in SMS_ERRORS */ -int sms_writeFile (FILE *pSmsFile, SMS_Header *pSmsHeader) +int sms_writeFile(FILE *pSmsFile, SMS_Header *pSmsHeader) { int iVariableSize; - rewind(pSmsFile); - /* check variable size of header */ - iVariableSize = sizeof(char) * pSmsHeader->nTextCharacters; - - pSmsHeader->iHeadBSize = sizeof(SMS_Header) + iVariableSize; + pSmsHeader->iHeadBSize = sizeof(SMS_Header); /* write header */ - if (fwrite((void *)pSmsHeader, (size_t)1, (size_t)sizeof(SMS_Header), + if(fwrite((void *)pSmsHeader, (size_t)1, (size_t)sizeof(SMS_Header), pSmsFile) < (size_t)sizeof(SMS_Header)) { sms_error("cannot write output file (header)"); - return(-1); + return -1; } - if (pSmsHeader->nTextCharacters > 0) - { - char *pChStart = (char *) pSmsHeader->pChTextCharacters; - int iSize = sizeof(char) * pSmsHeader->nTextCharacters; - - if (fwrite ((void *)pChStart, (size_t)1, (size_t)iSize, pSmsFile) < - (size_t)iSize) - { - sms_error("cannot write output file (nTextCharacters)"); - return(-1); - } - } - fclose(pSmsFile); - return (0); + return 0; } /*! \brief write SMS frame @@ -216,32 +150,31 @@ int sms_writeFile (FILE *pSmsFile, SMS_Header *pSmsHeader) * \param pSmsFrame pointer to SMS data frame * \return 0 on success, -1 on failure */ -int sms_writeFrame (FILE *pSmsFile, SMS_Header *pSmsHeader, - SMS_Data *pSmsFrame) +int sms_writeFrame(FILE *pSmsFile, SMS_Header *pSmsHeader, SMS_Data *pSmsFrame) { - if (fwrite ((void *)pSmsFrame->pSmsData, 1, pSmsHeader->iFrameBSize, - pSmsFile) < (unsigned int) pSmsHeader->iFrameBSize) + if (fwrite((void *)pSmsFrame->pSmsData, 1, pSmsHeader->iFrameBSize, + pSmsFile) < (unsigned int) pSmsHeader->iFrameBSize) { sms_error("cannot write frame to output file"); - return(-1); + return -1; } - else return (0); + return 0; } - /*! \brief get the size in bytes of the frame in a SMS file * * \param pSmsHeader pointer to SMS header * \return the size in bytes of the frame */ -int sms_frameSizeB (SMS_Header *pSmsHeader) +int sms_frameSizeB(SMS_Header *pSmsHeader) { int iSize, nDet; - if (pSmsHeader->iFormat == SMS_FORMAT_H || - pSmsHeader->iFormat == SMS_FORMAT_IH) + if(pSmsHeader->iFormat == SMS_FORMAT_H || + pSmsHeader->iFormat == SMS_FORMAT_IH) nDet = 2;/* freq, mag */ - else nDet = 3; /* freq, mag, phase */ + else + nDet = 3; /* freq, mag, phase */ iSize = sizeof (sfloat) * (nDet * pSmsHeader->nTracks); @@ -255,10 +188,9 @@ int sms_frameSizeB (SMS_Header *pSmsHeader) iSize += sizeof(sfloat) * (pSmsHeader->nStochasticCoeff * 2 + 1); } iSize += sizeof(sfloat) * pSmsHeader->nEnvCoeff; - return(iSize); + return iSize; } - /*! \brief function to read SMS header * * \param pChFileName file name for SMS file @@ -266,108 +198,89 @@ int sms_frameSizeB (SMS_Header *pSmsHeader) * \param ppSmsFile (double pointer to) inputfile * \return error code \see SMS_ERRORS */ -int sms_getHeader (char *pChFileName, SMS_Header **ppSmsHeader, - FILE **ppSmsFile) +int sms_getHeader(char *pChFileName, SMS_Header **ppSmsHeader, FILE **ppSmsFile) { int iHeadBSize, iFrameBSize, nFrames; int iMagicNumber; /* open file for reading */ - if ((*ppSmsFile = fopen (pChFileName, "r")) == NULL) + if((*ppSmsFile = fopen (pChFileName, "r")) == NULL) { sms_error("could not open SMS header"); - return (-1); + return -1; } /* read magic number */ - if (fread ((void *) &iMagicNumber, (size_t) sizeof(int), (size_t)1, - *ppSmsFile) < (size_t)1) + if(fread((void *) &iMagicNumber, (size_t) sizeof(int), (size_t)1, + *ppSmsFile) < (size_t)1) { sms_error("could not read SMS header"); - return (-1); + return -1; } - if (iMagicNumber != SMS_MAGIC) + if(iMagicNumber != SMS_MAGIC) { sms_error("not an SMS file"); - return (-1); + return -1; } /* read size of of header */ - if (fread ((void *) &iHeadBSize, (size_t) sizeof(int), (size_t)1, - *ppSmsFile) < (size_t)1) + if(fread((void *) &iHeadBSize, (size_t) sizeof(int), (size_t)1, + *ppSmsFile) < (size_t)1) { sms_error("could not read SMS header (iHeadBSize)"); - return (-1); + return -1; } - if (iHeadBSize <= 0) + if(iHeadBSize <= 0) { sms_error("bad SMS header size"); - return (-1); + return -1; } /* read number of data Frames */ - if (fread ((void *) &nFrames, (size_t) sizeof(int), (size_t)1, - *ppSmsFile) < (size_t)1) + if(fread((void *) &nFrames, (size_t) sizeof(int), (size_t)1, + *ppSmsFile) < (size_t)1) { sms_error("could not read SMS number of frames"); - return (-1); + return -1; } - if (nFrames <= 0) + if(nFrames <= 0) { sms_error("number of frames <= 0"); - return (-1); + return -1; } /* read size of data Frames */ - if (fread ((void *) &iFrameBSize, (size_t) sizeof(int), (size_t)1, - *ppSmsFile) < (size_t)1) + if(fread((void *) &iFrameBSize, (size_t) sizeof(int), (size_t)1, + *ppSmsFile) < (size_t)1) { sms_error("could not read size of SMS data"); - return (-1); + return -1; } - if (iFrameBSize <= 0) + if(iFrameBSize <= 0) { sms_error("size bytes of frames <= 0"); - return (-1); + return -1; } /* allocate memory for header */ - if (((*ppSmsHeader) = (SMS_Header *)malloc (iHeadBSize)) == NULL) + if(((*ppSmsHeader) = (SMS_Header *)malloc (iHeadBSize)) == NULL) { sms_error("cannot allocate memory for header"); - return (-1); + return -1; } /* read header */ - rewind (*ppSmsFile); - if (fread ((void *) (*ppSmsHeader), 1, iHeadBSize, *ppSmsFile) < (unsigned int) iHeadBSize) + rewind(*ppSmsFile); + if(fread ((void *) (*ppSmsHeader), 1, iHeadBSize, *ppSmsFile) < (unsigned int) iHeadBSize) { sms_error("cannot read header of SMS file"); - return (-1); + return -1; } - /* set pointers to variable part of header */ - /* if ((*ppSmsHeader)->nLoopRecords > 0) */ - /* (*ppSmsHeader)->pILoopRecords = (int *) ((char *)(*ppSmsHeader) + */ - /* sizeof(SMS_Header)); */ - - /* if ((*ppSmsHeader)->nSpecEnvelopePoints > 0) */ - /* (*ppSmsHeader)->pFSpectralEnvelope = */ - /* (sfloat *) ((char *)(*ppSmsHeader) + sizeof(SMS_Header) + */ - /* sizeof(int) * (*ppSmsHeader)->nLoopRecords); */ - - /* if ((*ppSmsHeader)->nTextCharacters > 0) */ - /* (*ppSmsHeader)->pChTextCharacters = */ - /* (char *) ((char *)(*ppSmsHeader) + sizeof(SMS_Header) + */ - /* sizeof(int) * (*ppSmsHeader)->nLoopRecords + */ - /* sizeof(sfloat) * (*ppSmsHeader)->nSpecEnvelopePoints); */ - if ((*ppSmsHeader)->nTextCharacters > 0) - (*ppSmsHeader)->pChTextCharacters = (char *)(*ppSmsHeader) + sizeof(SMS_Header); - - return (0); + return 0; } /*! \brief read an SMS data frame @@ -378,24 +291,23 @@ int sms_getHeader (char *pChFileName, SMS_Header **ppSmsHeader, * \param pSmsFrame pointer to SMS frame * \return 0 on sucess, -1 on error */ -int sms_getFrame (FILE *pSmsFile, SMS_Header *pSmsHeader, int iFrame, - SMS_Data *pSmsFrame) +int sms_getFrame(FILE *pSmsFile, SMS_Header *pSmsHeader, int iFrame, SMS_Data *pSmsFrame) { - if (fseek (pSmsFile, pSmsHeader->iHeadBSize + iFrame * - pSmsHeader->iFrameBSize, SEEK_SET) < 0) + if(fseek(pSmsFile, pSmsHeader->iHeadBSize + iFrame * + pSmsHeader->iFrameBSize, SEEK_SET) < 0) { - sms_error ("cannot seek to the SMS frame"); - return (-1); + sms_error("cannot seek to the SMS frame"); + return -1; } - if ((pSmsHeader->iFrameBSize = - fread ((void *)pSmsFrame->pSmsData, (size_t)1, - (size_t)pSmsHeader->iFrameBSize, pSmsFile)) - != pSmsHeader->iFrameBSize) + if((pSmsHeader->iFrameBSize = + fread((void *)pSmsFrame->pSmsData, (size_t)1, + (size_t)pSmsHeader->iFrameBSize, pSmsFile)) + != pSmsHeader->iFrameBSize) { - sms_error ("cannot read SMS frame"); - return (-1); + sms_error("cannot read SMS frame"); + return -1; } - return (0); + return 0; } /*! \brief allocate memory for a frame of SMS data @@ -409,25 +321,34 @@ int sms_getFrame (FILE *pSmsFile, SMS_Header *pSmsHeader, int iFrame, * \param nEnvCoeff number of envelope coefficients in frame * \return 0 on success, -1 on error */ -int sms_allocFrame (SMS_Data *pSmsFrame, int nTracks, int nStochCoeff, int iPhase, - int stochType, int nEnvCoeff) +int sms_allocFrame(SMS_Data *pSmsFrame, int nTracks, int nStochCoeff, int iPhase, + int stochType, int nEnvCoeff) { sfloat *dataPos; /* a marker to locate specific data witin smsData */ + /* calculate size of frame */ - int sizeData = 2 * nTracks * sizeof(sfloat); - sizeData += 1 * sizeof(sfloat); //adding one for nSamples - if (iPhase > 0) sizeData += nTracks * sizeof(sfloat); - if (stochType == SMS_STOC_APPROX) + int sizeData = sizeof(sfloat); /* nSamples */ + /* frequencies and magnitudes */ + sizeData += 2 * nTracks * sizeof(sfloat); + /* phases */ + if(iPhase > 0) + sizeData += nTracks * sizeof(sfloat); + /* stochastic coefficients */ + if(stochType == SMS_STOC_APPROX) sizeData += (nStochCoeff + 1) * sizeof(sfloat); - else if (stochType == SMS_STOC_IFFT) - sizeData += (2*nStochCoeff + 1) * sizeof(sfloat); + else if(stochType == SMS_STOC_IFFT) + sizeData += ((2*nStochCoeff) + 1) * sizeof(sfloat); + /* spectral envelope */ sizeData += nEnvCoeff * sizeof(sfloat); /* add in number of envelope coefficients (cep or fbins) if any */ + /* allocate memory for data */ - if ((pSmsFrame->pSmsData = (sfloat *) malloc (sizeData)) == NULL) + pSmsFrame->pSmsData = (sfloat *)malloc(sizeData); + if(pSmsFrame->pSmsData == NULL) { sms_error("cannot allocate memory for SMS frame data"); - return (-1); + return -1; } + memset(pSmsFrame->pSmsData, 0, sizeData); /* set the variables in the structure */ /* \todo why not set these in init functions, then allocate with them?? */ @@ -435,40 +356,38 @@ int sms_allocFrame (SMS_Data *pSmsFrame, int nTracks, int nStochCoeff, int iPhas pSmsFrame->nTracks = nTracks; pSmsFrame->nCoeff = nStochCoeff; pSmsFrame->nEnvCoeff = nEnvCoeff; + /* set pointers to data types within smsData array */ pSmsFrame->pFSinFreq = pSmsFrame->pSmsData; - dataPos = (sfloat *)(pSmsFrame->pFSinFreq + nTracks); - memset(pSmsFrame->pFSinFreq, 0, sizeof(sfloat) * nTracks); + dataPos = (sfloat *)(pSmsFrame->pFSinFreq + nTracks); pSmsFrame->pFSinAmp = dataPos; dataPos = (sfloat *)(pSmsFrame->pFSinAmp + nTracks); - memset(pSmsFrame->pFSinAmp, 0, sizeof(sfloat) * nTracks); - if (iPhase > 0) + if(iPhase > 0) { pSmsFrame->pFSinPha = dataPos; - dataPos = (sfloat *) (pSmsFrame->pFSinPha + nTracks); - memset(pSmsFrame->pFSinPha, 0, sizeof(sfloat) * nTracks); + dataPos = (sfloat *)(pSmsFrame->pFSinPha + nTracks); } - else pSmsFrame->pFSinPha = NULL; + else + pSmsFrame->pFSinPha = NULL; - if (stochType == SMS_STOC_APPROX) + if(stochType == SMS_STOC_APPROX) { pSmsFrame->pFStocCoeff = dataPos; - dataPos = (sfloat *) (pSmsFrame->pFStocCoeff + nStochCoeff); - memset(pSmsFrame->pFStocCoeff, 0, sizeof(sfloat) * nStochCoeff); + dataPos = (sfloat *)(pSmsFrame->pFStocCoeff + nStochCoeff); pSmsFrame->pFStocGain = dataPos; - dataPos = (sfloat *) (pSmsFrame->pFStocGain + 1); + dataPos = (sfloat *)(pSmsFrame->pFStocGain + 1); } - else if (stochType == SMS_STOC_IFFT) + else if(stochType == SMS_STOC_IFFT) { pSmsFrame->pFStocCoeff = dataPos; - dataPos = (sfloat *) (pSmsFrame->pFStocCoeff + nStochCoeff); + dataPos = (sfloat *)(pSmsFrame->pFStocCoeff + nStochCoeff); pSmsFrame->pResPhase = dataPos; - dataPos = (sfloat *) (pSmsFrame->pResPhase + nStochCoeff); + dataPos = (sfloat *)(pSmsFrame->pResPhase + nStochCoeff); pSmsFrame->pFStocGain = dataPos; - dataPos = (sfloat *) (pSmsFrame->pFStocGain + 1); + dataPos = (sfloat *)(pSmsFrame->pFStocGain + 1); } else { @@ -476,11 +395,13 @@ int sms_allocFrame (SMS_Data *pSmsFrame, int nTracks, int nStochCoeff, int iPhas pSmsFrame->pResPhase = NULL; pSmsFrame->pFStocGain = NULL; } - if (nEnvCoeff > 0) + + if(nEnvCoeff > 0) pSmsFrame->pSpecEnv = dataPos; else pSmsFrame->pSpecEnv = NULL; - return (0); + + return 0; } /*! \brief function to allocate an SMS data frame using an SMS_Header @@ -492,40 +413,45 @@ int sms_allocFrame (SMS_Data *pSmsFrame, int nTracks, int nStochCoeff, int iPhas * \param pSmsFrame pointer to SMS frame * \return 0 on success, -1 on error */ -int sms_allocFrameH (SMS_Header *pSmsHeader, SMS_Data *pSmsFrame) +int sms_allocFrameH(SMS_Header *pSmsHeader, SMS_Data *pSmsFrame) { int iPhase = (pSmsHeader->iFormat == SMS_FORMAT_HP || - pSmsHeader->iFormat == SMS_FORMAT_IHP) ? 1 : 0; - return (sms_allocFrame (pSmsFrame, pSmsHeader->nTracks, - pSmsHeader->nStochasticCoeff, iPhase, - pSmsHeader->iStochasticType, pSmsHeader->nEnvCoeff)); + pSmsHeader->iFormat == SMS_FORMAT_IHP) ? 1 : 0; + return sms_allocFrame(pSmsFrame, pSmsHeader->nTracks, + pSmsHeader->nStochasticCoeff, iPhase, + pSmsHeader->iStochasticType, + pSmsHeader->nEnvCoeff); } - /*! \brief free the SMS data structure * * \param pSmsFrame pointer to frame of SMS data */ -void sms_freeFrame (SMS_Data *pSmsFrame) +void sms_freeFrame(SMS_Data *pSmsFrame) { - free(pSmsFrame->pSmsData); - pSmsFrame->nTracks = 0; - pSmsFrame->nCoeff = 0; - pSmsFrame->sizeData = 0; - pSmsFrame->pFSinFreq = NULL; - pSmsFrame->pFSinAmp = NULL; - pSmsFrame->pFStocCoeff = NULL; - pSmsFrame->pResPhase = NULL; - pSmsFrame->pFStocGain = NULL; + if(!pSmsFrame) + return; + + if(pSmsFrame->pSmsData) + free(pSmsFrame->pSmsData); + + pSmsFrame->nTracks = 0; + pSmsFrame->nCoeff = 0; + pSmsFrame->sizeData = 0; + pSmsFrame->pFSinFreq = NULL; + pSmsFrame->pFSinAmp = NULL; + pSmsFrame->pFStocCoeff = NULL; + pSmsFrame->pResPhase = NULL; + pSmsFrame->pFStocGain = NULL; } /*! \brief clear the SMS data structure * * \param pSmsFrame pointer to frame of SMS data */ -void sms_clearFrame (SMS_Data *pSmsFrame) +void sms_clearFrame(SMS_Data *pSmsFrame) { - memset ((char *) pSmsFrame->pSmsData, 0, pSmsFrame->sizeData); + memset(pSmsFrame->pSmsData, 0, pSmsFrame->sizeData); } /*! \brief copy a frame of SMS_Data @@ -534,49 +460,49 @@ void sms_clearFrame (SMS_Data *pSmsFrame) * \param pOriginalSmsData original frame * */ -void sms_copyFrame (SMS_Data *pCopySmsData, SMS_Data *pOriginalSmsData) +void sms_copyFrame(SMS_Data *pCopySmsData, SMS_Data *pOriginalSmsData) { /* if the two frames are the same size just copy data */ - if (pCopySmsData->sizeData == pOriginalSmsData->sizeData && - pCopySmsData->nTracks == pOriginalSmsData->nTracks) + if(pCopySmsData->sizeData == pOriginalSmsData->sizeData && + pCopySmsData->nTracks == pOriginalSmsData->nTracks) { - memcpy ((char *)pCopySmsData->pSmsData, - (char *)pOriginalSmsData->pSmsData, - pCopySmsData->sizeData); + memcpy((char *)pCopySmsData->pSmsData, + (char *)pOriginalSmsData->pSmsData, + pCopySmsData->sizeData); } /* if frames is different size copy the smallest */ else { - int nTracks = MIN (pCopySmsData->nTracks, pOriginalSmsData->nTracks); - int nCoeff = MIN (pCopySmsData->nCoeff, pOriginalSmsData->nCoeff); + int nTracks = MIN(pCopySmsData->nTracks, pOriginalSmsData->nTracks); + int nCoeff = MIN(pCopySmsData->nCoeff, pOriginalSmsData->nCoeff); pCopySmsData->nTracks = nTracks; pCopySmsData->nCoeff = nCoeff; - memcpy ((char *)pCopySmsData->pFSinFreq, - (char *)pOriginalSmsData->pFSinFreq, - sizeof(sfloat) * nTracks); - memcpy ((char *)pCopySmsData->pFSinAmp, - (char *)pOriginalSmsData->pFSinAmp, - sizeof(sfloat) * nTracks); - if (pOriginalSmsData->pFSinPha != NULL && - pCopySmsData->pFSinPha != NULL) - memcpy ((char *)pCopySmsData->pFSinPha, - (char *)pOriginalSmsData->pFSinPha, - sizeof(sfloat) * nTracks); - if (pOriginalSmsData->pFStocCoeff != NULL && - pCopySmsData->pFStocCoeff != NULL) + memcpy((char *)pCopySmsData->pFSinFreq, + (char *)pOriginalSmsData->pFSinFreq, + sizeof(sfloat) * nTracks); + memcpy((char *)pCopySmsData->pFSinAmp, + (char *)pOriginalSmsData->pFSinAmp, + sizeof(sfloat) * nTracks); + if(pOriginalSmsData->pFSinPha != NULL && + pCopySmsData->pFSinPha != NULL) + memcpy((char *)pCopySmsData->pFSinPha, + (char *)pOriginalSmsData->pFSinPha, + sizeof(sfloat) * nTracks); + if(pOriginalSmsData->pFStocCoeff != NULL && + pCopySmsData->pFStocCoeff != NULL) { - if (pOriginalSmsData->pResPhase != NULL && - pCopySmsData->pResPhase != NULL) - memcpy ((char *)pCopySmsData->pResPhase, - (char *)pOriginalSmsData->pResPhase, - sizeof(sfloat) * nCoeff); + if(pOriginalSmsData->pResPhase != NULL && + pCopySmsData->pResPhase != NULL) + memcpy((char *)pCopySmsData->pResPhase, + (char *)pOriginalSmsData->pResPhase, + sizeof(sfloat) * nCoeff); } - if (pOriginalSmsData->pFStocGain != NULL && - pCopySmsData->pFStocGain != NULL) - memcpy ((char *)pCopySmsData->pFStocGain, - (char *)pOriginalSmsData->pFStocGain, - sizeof(sfloat)); + if(pOriginalSmsData->pFStocGain != NULL && + pCopySmsData->pFStocGain != NULL) + memcpy((char *)pCopySmsData->pFStocGain, + (char *)pOriginalSmsData->pFStocGain, + sizeof(sfloat)); } } @@ -589,21 +515,22 @@ void sms_copyFrame (SMS_Data *pCopySmsData, SMS_Data *pOriginalSmsData) * \param pSmsFrameOut sms output frame * \param fInterpFactor interpolation factor */ -void sms_interpolateFrames (SMS_Data *pSmsFrame1, SMS_Data *pSmsFrame2, - SMS_Data *pSmsFrameOut, sfloat fInterpFactor) +void sms_interpolateFrames(SMS_Data *pSmsFrame1, SMS_Data *pSmsFrame2, + SMS_Data *pSmsFrameOut, sfloat fInterpFactor) { int i; sfloat fFreq1, fFreq2; /* interpolate the deterministic part */ - for (i = 0; i < pSmsFrame1->nTracks; i++) + for(i = 0; i < pSmsFrame1->nTracks; i++) { fFreq1 = pSmsFrame1->pFSinFreq[i]; fFreq2 = pSmsFrame2->pFSinFreq[i]; - if (fFreq1 == 0) fFreq1 = fFreq2; - if (fFreq2 == 0) fFreq2 = fFreq1; - pSmsFrameOut->pFSinFreq[i] = - fFreq1 + fInterpFactor * (fFreq2 - fFreq1); + if(fFreq1 == 0) + fFreq1 = fFreq2; + if(fFreq2 == 0) + fFreq2 = fFreq1; + pSmsFrameOut->pFSinFreq[i] = fFreq1 + fInterpFactor * (fFreq2 - fFreq1); pSmsFrameOut->pFSinAmp[i] = pSmsFrame1->pFSinAmp[i] + fInterpFactor * (pSmsFrame2->pFSinAmp[i] - pSmsFrame1->pFSinAmp[i]); @@ -611,23 +538,22 @@ void sms_interpolateFrames (SMS_Data *pSmsFrame1, SMS_Data *pSmsFrame2, /* interpolate the stochastic part. The pointer is non-null when the frame contains stochastic coefficients */ - if (pSmsFrameOut->pFStocGain) + if(pSmsFrameOut->pFStocGain) { *(pSmsFrameOut->pFStocGain) = *(pSmsFrame1->pFStocGain) + fInterpFactor * (*(pSmsFrame2->pFStocGain) - *(pSmsFrame1->pFStocGain)); } /*! \todo how to interpolate residual phase spectrum */ - for (i = 0; i < pSmsFrame1->nCoeff; i++) + for(i = 0; i < pSmsFrame1->nCoeff; i++) pSmsFrameOut->pFStocCoeff[i] = pSmsFrame1->pFStocCoeff[i] + fInterpFactor * (pSmsFrame2->pFStocCoeff[i] - pSmsFrame1->pFStocCoeff[i]); /* DO NEXT: interpolate spec env here if fbins */ - for (i = 0; i < pSmsFrame1->nEnvCoeff; i++) + for(i = 0; i < pSmsFrame1->nEnvCoeff; i++) pSmsFrameOut->pSpecEnv[i] = pSmsFrame1->pSpecEnv[i] + fInterpFactor * (pSmsFrame2->pSpecEnv[i] - pSmsFrame1->pSpecEnv[i]); - - } + diff --git a/sms/filters.c b/sms/filters.c index b1ca9fc..9c13ad5 100644 --- a/sms/filters.c +++ b/sms/filters.c @@ -31,13 +31,11 @@ * * sfloat fInput; sound sample */ -sfloat sms_preEmphasis (sfloat fInput, SMS_AnalParams *pAnalParams) +sfloat sms_preEmphasis(sfloat fInput, SMS_AnalParams *pAnalParams) { - sfloat fOutput = 0; - fOutput = fInput - SMS_EMPH_COEF * pAnalParams->preEmphasisLastValue; - pAnalParams->preEmphasisLastValue = fOutput; - - return (fOutput); + sfloat fOutput = fInput - SMS_EMPH_COEF * pAnalParams->preEmphasisLastValue; + pAnalParams->preEmphasisLastValue = fOutput; + return fOutput; } /* de-emphasis filter function, it returns the filtered value @@ -46,11 +44,9 @@ sfloat sms_preEmphasis (sfloat fInput, SMS_AnalParams *pAnalParams) */ sfloat sms_deEmphasis(sfloat fInput, SMS_SynthParams *pSynthParams) { - sfloat fOutput = 0; - fOutput = fInput + SMS_EMPH_COEF * pSynthParams->deemphasisLastValue; - pSynthParams->deemphasisLastValue = fInput; - - return(fOutput); + sfloat fOutput = fInput + SMS_EMPH_COEF * pSynthParams->deEmphasisLastValue; + pSynthParams->deEmphasisLastValue = fInput; + return fOutput; } /*! \brief function to implement a zero-pole filter @@ -65,15 +61,11 @@ sfloat sms_deEmphasis(sfloat fInput, SMS_SynthParams *pSynthParams) * \param fInput input sample * \return value is the filtered sample */ -static sfloat ZeroPoleFilter (sfloat *pFa, sfloat *pFb, int nCoeff, sfloat fInput ) +static sfloat ZeroPoleFilter(sfloat *pFa, sfloat *pFb, int nCoeff, sfloat fInput ) { double fOut = 0; int iSection; - -/* static sfloat *pD = NULL; */ -/* if (pD == NULL) */ -/* pD = (sfloat *) calloc(5, sizeof(sfloat)); */ - static sfloat pD[5] = {0, 0, 0, 0, 0}; + static sfloat pD[5] = {0, 0, 0, 0, 0}; pD[0] = fInput; for (iSection = nCoeff-1; iSection > 0; iSection--) @@ -83,23 +75,9 @@ static sfloat ZeroPoleFilter (sfloat *pFa, sfloat *pFb, int nCoeff, sfloat fInpu pD[iSection] = pD [iSection-1]; } fOut = fOut + pFa[0] * pD[0]; - return((sfloat) fOut); + return (sfloat) fOut; } - /* cutoff 1500 Hz */ -/* static sfloat pFCoeff32k[10] = {0.679459, -2.71784, 4.07676, -2.71784, - 0.679459, 1, -3.23168, 3.97664, -2.20137, 0.461665}; - static sfloat pFCoeff36k[10] = {0.709489, -2.83796, 4.25694, -2.83796, - 0.709489, 1, -3.31681, 4.17425, -2.3574, 0.503375}; - static sfloat pFCoeff40k[10] = {0.734408, -2.93763, 4.40645, -2.93763, - 0.734408, 1, -3.38497, 4.33706, -2.48914, 0.539355}; - static sfloat pFCoeff441k[10] = {0.755893, -3.02357, 4.53536, -3.02357, - 0.755893, 1, -3.44205, 4.47657, -2.6043, 0.571374}; - static sfloat pFCoeff48k[10] = {0.773347, -3.09339, 4.64008, -3.09339, - 0.773347, 1, -3.48731, 4.58929, -2.69888, 0.598065}; -*/ - - /*! \brief function to filter a waveform with a high-pass filter * * cutoff =1500 Hz @@ -110,10 +88,8 @@ static sfloat ZeroPoleFilter (sfloat *pFa, sfloat *pFb, int nCoeff, sfloat fInpu * \param pResidual pointer to residual signal * \param iSamplingRate sampling rate of signal */ -void sms_filterHighPass ( int sizeResidual, sfloat *pResidual, int iSamplingRate) +void sms_filterHighPass(int sizeResidual, sfloat *pResidual, int iSamplingRate) { - - /* cutoff 800Hz */ static sfloat pFCoeff32k[10] = {0.814255, -3.25702, 4.88553, -3.25702, 0.814255, 1, -3.58973, 4.85128, -2.92405, 0.66301}; @@ -128,13 +104,13 @@ void sms_filterHighPass ( int sizeResidual, sfloat *pResidual, int iSamplingRate sfloat *pFCoeff, fSample = 0; int i; - if (iSamplingRate <= 32000) + if(iSamplingRate <= 32000) pFCoeff = pFCoeff32k; - else if (iSamplingRate <= 36000) + else if(iSamplingRate <= 36000) pFCoeff = pFCoeff36k; - else if (iSamplingRate <= 40000) + else if(iSamplingRate <= 40000) pFCoeff = pFCoeff40k; - else if (iSamplingRate <= 44100) + else if(iSamplingRate <= 44100) pFCoeff = pFCoeff441k; else pFCoeff = pFCoeff48k; @@ -142,12 +118,11 @@ void sms_filterHighPass ( int sizeResidual, sfloat *pResidual, int iSamplingRate for(i = 0; i < sizeResidual; i++) { /* try to avoid underflow when there is nothing to filter */ - if (i > 0 && fSample == 0 && pResidual[i] == 0) + if(i > 0 && fSample == 0 && pResidual[i] == 0) return; fSample = pResidual[i]; - pResidual[i] = - ZeroPoleFilter (&pFCoeff[0], &pFCoeff[5], 5, fSample); + pResidual[i] = ZeroPoleFilter (&pFCoeff[0], &pFCoeff[5], 5, fSample); } } @@ -161,32 +136,32 @@ void sms_filterHighPass ( int sizeResidual, sfloat *pResidual, int iSamplingRate * \param size2 horizontal size of pFArray * \param pFOutArray output array of size size1 */ -void sms_filterArray (sfloat *pFArray, int size1, int size2, sfloat *pFOutArray) +void sms_filterArray(sfloat *pFArray, int size1, int size2, sfloat *pFOutArray) { int i, j, iPoint, iFrame, size2_2 = size2-2, size2_1 = size2-1; sfloat *pFCurrentArray = pFArray + (size2_1) * size1; - sfloat fVal, fWeighting, fTotalWeighting, fTmpVal; + sfloat fVal, fWeighting, fTotalWeighting, fTmpVal; /* find the filtered envelope */ - for (i = 0; i < size1; i++) + for(i = 0; i < size1; i++) { fVal = pFCurrentArray[i]; fTotalWeighting = 1; /* filter by the surrounding points */ - for (j = 1; j < (size2_2); j++) + for(j = 1; j < (size2_2); j++) { fWeighting = (sfloat) size2 / (1+ j); /* filter on the vertical dimension */ /* consider the lower points */ iPoint = i - (size2_1) + j; - if (iPoint >= 0) + if(iPoint >= 0) { fVal += pFCurrentArray[iPoint] * fWeighting; fTotalWeighting += fWeighting; } /* consider the higher points */ iPoint = i + (size2_1) - j; - if (iPoint < size1) + if(iPoint < size1) { fVal += pFCurrentArray[iPoint] * fWeighting; fTotalWeighting += fWeighting; @@ -195,7 +170,7 @@ void sms_filterArray (sfloat *pFArray, int size1, int size2, sfloat *pFOutArray) /* consider the previous points */ iFrame = j; fTmpVal = pFArray[iFrame*size1 + i]; - if (fTmpVal) + if(fTmpVal) { fVal += fTmpVal * fWeighting; fTotalWeighting += fWeighting; diff --git a/sms/fixTracks.c b/sms/fixTracks.c index dc507f8..81e24ee 100644 --- a/sms/fixTracks.c +++ b/sms/fixTracks.c @@ -153,79 +153,70 @@ static void DeleteShortTrack (int iCurrentFrame, int iTrack, int *pIState, */ void sms_cleanTracks(int iCurrentFrame, SMS_AnalParams *pAnalParams) { - int iTrack, iLength, iFrame; - static int *pIState = NULL; - static int nStates = 0; + int iTrack, iLength, iFrame; - if (pIState == NULL || nStates != pAnalParams->nGuides || pAnalParams->resetGuideStates == 1) - { - /* \todo shouldn't this memory allocation be checked? */ - pIState = (int *) calloc (pAnalParams->nGuides, sizeof(int)); - nStates = pAnalParams->nGuides; - pAnalParams->resetGuideStates = 0; - } - - /* if fundamental and first partial are short, delete everything */ - if ((pAnalParams->iFormat == SMS_FORMAT_H || - pAnalParams->iFormat == SMS_FORMAT_HP) && - pAnalParams->ppFrames[iCurrentFrame]->deterministic.pFSinAmp[0] == 0 && - pIState[0] > 0 && - pIState[0] < pAnalParams->iMinTrackLength && - pAnalParams->ppFrames[iCurrentFrame]->deterministic.pFSinAmp[1] == 0 && - pIState[1] > 0 && - pIState[1] < pAnalParams->iMinTrackLength) - { - iLength = pIState[0]; - for (iTrack = 0; iTrack < pAnalParams->nGuides; iTrack++) - { - for (iFrame = 1; iFrame <= iLength; iFrame++) - { - if((iCurrentFrame - iFrame) >= 0) - { - pAnalParams->ppFrames[iCurrentFrame - - iFrame]->deterministic.pFSinAmp[iTrack] = 0; - pAnalParams->ppFrames[iCurrentFrame - - iFrame]->deterministic.pFSinFreq[iTrack] = 0; - pAnalParams->ppFrames[iCurrentFrame - - iFrame]->deterministic.pFSinPha[iTrack] = 0; - } - } - pIState[iTrack] = -pAnalParams->iMaxSleepingTime; - } - if (pAnalParams->iDebugMode == SMS_DBG_CLEAN_TRAJ || - pAnalParams->iDebugMode == SMS_DBG_ALL) + /* if fundamental and first partial are short, delete everything */ + if((pAnalParams->iFormat == SMS_FORMAT_H || pAnalParams->iFormat == SMS_FORMAT_HP) && + pAnalParams->ppFrames[iCurrentFrame]->deterministic.pFSinAmp[0] == 0 && + pAnalParams->guideStates[0] > 0 && + pAnalParams->guideStates[0] < pAnalParams->iMinTrackLength && + pAnalParams->ppFrames[iCurrentFrame]->deterministic.pFSinAmp[1] == 0 && + pAnalParams->guideStates[1] > 0 && + pAnalParams->guideStates[1] < pAnalParams->iMinTrackLength) + { + iLength = pAnalParams->guideStates[0]; + for(iTrack = 0; iTrack < pAnalParams->nGuides; iTrack++) + { + for(iFrame = 1; iFrame <= iLength; iFrame++) + { + if((iCurrentFrame - iFrame) >= 0) { - fprintf(stdout, "cleanTrack: frame %d to frame %d deleted\n", - pAnalParams->ppFrames[iCurrentFrame-iLength]->iFrameNum, - pAnalParams->ppFrames[iCurrentFrame-1]->iFrameNum); + pAnalParams->ppFrames[iCurrentFrame - + iFrame]->deterministic.pFSinAmp[iTrack] = 0; + pAnalParams->ppFrames[iCurrentFrame - + iFrame]->deterministic.pFSinFreq[iTrack] = 0; + pAnalParams->ppFrames[iCurrentFrame - + iFrame]->deterministic.pFSinPha[iTrack] = 0; } + } + pAnalParams->guideStates[iTrack] = -pAnalParams->iMaxSleepingTime; + } + if(pAnalParams->iDebugMode == SMS_DBG_CLEAN_TRAJ || + pAnalParams->iDebugMode == SMS_DBG_ALL) + { + fprintf(stdout, "cleanTrack: frame %d to frame %d deleted\n", + pAnalParams->ppFrames[iCurrentFrame-iLength]->iFrameNum, + pAnalParams->ppFrames[iCurrentFrame-1]->iFrameNum); + } - return; - } - - /* check every partial individually */ - for (iTrack = 0; iTrack < pAnalParams->nGuides; iTrack++) - { - /* track after gap */ - if(pAnalParams->ppFrames[iCurrentFrame]->deterministic.pFSinAmp[iTrack] != 0) - { - if(pIState[iTrack] < 0 && - pIState[iTrack] > -pAnalParams->iMaxSleepingTime) - FillGap (iCurrentFrame, iTrack, pIState, pAnalParams); - else - pIState[iTrack] = (pIState[iTrack]<0) ? 1 : pIState[iTrack]+1; - } - /* gap after track */ - else - { - if(pIState[iTrack] > 0 && - pIState[iTrack] < pAnalParams->iMinTrackLength) - DeleteShortTrack (iCurrentFrame, iTrack, pIState, pAnalParams); - else - pIState[iTrack] = (pIState[iTrack]>0) ? -1 : pIState[iTrack]-1; - } - } - return; + return; + } + + /* check every partial individually */ + for(iTrack = 0; iTrack < pAnalParams->nGuides; iTrack++) + { + /* track after gap */ + if(pAnalParams->ppFrames[iCurrentFrame]->deterministic.pFSinAmp[iTrack] != 0) + { + if(pAnalParams->guideStates[iTrack] < 0 && + pAnalParams->guideStates[iTrack] > -pAnalParams->iMaxSleepingTime) + FillGap (iCurrentFrame, iTrack, pAnalParams->guideStates, pAnalParams); + else + pAnalParams->guideStates[iTrack] = + (pAnalParams->guideStates[iTrack]<0) ? 1 : pAnalParams->guideStates[iTrack]+1; + } + /* gap after track */ + else + { + if(pAnalParams->guideStates[iTrack] > 0 && + pAnalParams->guideStates[iTrack] < pAnalParams->iMinTrackLength) + DeleteShortTrack (iCurrentFrame, iTrack, pAnalParams->guideStates, pAnalParams); + else + pAnalParams->guideStates[iTrack] = + (pAnalParams->guideStates[iTrack]>0) ? -1 : pAnalParams->guideStates[iTrack]-1; + } + } + return; } /*! \brief scale deterministic magnitude if synthesis is larger than original @@ -236,15 +227,15 @@ void sms_cleanTracks(int iCurrentFrame, SMS_AnalParams *pAnalParams) * \param pAnalParams pointer to analysis parameters * \param nTrack number of tracks */ -void sms_scaleDet (sfloat *pFSynthBuffer, sfloat *pFOriginalBuffer, - sfloat *pFSinAmp, SMS_AnalParams *pAnalParams, int nTrack) +void sms_scaleDet(sfloat *pFSynthBuffer, sfloat *pFOriginalBuffer, + sfloat *pFSinAmp, SMS_AnalParams *pAnalParams, int nTrack) { sfloat fOriginalMag = 0, fSynthesisMag = 0; sfloat fCosScaleFactor; int iTrack, i; /* get sound energy */ - for (i = 0; i < pAnalParams->sizeHop; i++) + for(i = 0; i < pAnalParams->sizeHop; i++) { fOriginalMag += fabs((double) pFOriginalBuffer[i]); fSynthesisMag += fabs((double) pFSynthBuffer[i]); @@ -252,18 +243,18 @@ void sms_scaleDet (sfloat *pFSynthBuffer, sfloat *pFOriginalBuffer, /* if total energy of deterministic sound is larger than original, scale deterministic representation */ - if (fSynthesisMag > (1.5 * fOriginalMag)) + if(fSynthesisMag > (1.5 * fOriginalMag)) { fCosScaleFactor = fOriginalMag / fSynthesisMag; if(pAnalParams->iDebugMode == SMS_DBG_CLEAN_TRAJ || pAnalParams->iDebugMode == SMS_DBG_ALL) - fprintf (stdout, "Frame %d: magnitude scaled by %f\n", - pAnalParams->ppFrames[0]->iFrameNum, fCosScaleFactor); + fprintf(stdout, "Frame %d: magnitude scaled by %f\n", + pAnalParams->ppFrames[0]->iFrameNum, fCosScaleFactor); - for (iTrack = 0; iTrack < nTrack; iTrack++) - if (pFSinAmp[iTrack] > 0) - pFSinAmp[iTrack] = - sms_magToDB (sms_dBToMag (pFSinAmp[iTrack]) * fCosScaleFactor); + for(iTrack = 0; iTrack < nTrack; iTrack++) + if(pFSinAmp[iTrack] > 0) + pFSinAmp[iTrack] = sms_magToDB (sms_dBToMag (pFSinAmp[iTrack]) * fCosScaleFactor); } } + diff --git a/sms/peakContinuation.c b/sms/peakContinuation.c index 571772f..b514266 100644 --- a/sms/peakContinuation.c +++ b/sms/peakContinuation.c @@ -362,140 +362,120 @@ static int GetStartingPeak(int iGuide, SMS_Guide *pGuides, int nGuides, */ int sms_peakContinuation(int iFrame, SMS_AnalParams *pAnalParams) { - int iGuide, iCurrentPeak = -1, iGoodPeak = -1; - sfloat fFund = pAnalParams->ppFrames[iFrame]->fFundamental; - sfloat fFreqDev = fFund * pAnalParams->fFreqDeviation, fCurrentMax = 1000; - static SMS_Guide *pGuides = NULL; - static int nGuides = 0; - - if(pGuides == NULL || nGuides != pAnalParams->nGuides || pAnalParams->resetGuides == 1) - { - if((pGuides = (SMS_Guide *) calloc(pAnalParams->nGuides, sizeof(SMS_Guide))) - == NULL) - return SMS_MALLOC; - if (pAnalParams->iFormat == SMS_FORMAT_H || - pAnalParams->iFormat == SMS_FORMAT_HP) - for (iGuide = 0; iGuide < pAnalParams->nGuides; iGuide++) - pGuides[iGuide].fFreq = pAnalParams->fDefaultFundamental * (iGuide + 1); - nGuides = pAnalParams->nGuides; - pAnalParams->resetGuides = 0; - } - - /* update guides with fundamental contribution */ - if(fFund > 0 && - (pAnalParams->iFormat == SMS_FORMAT_H || - pAnalParams->iFormat == SMS_FORMAT_HP)) - for(iGuide = 0; iGuide < pAnalParams->nGuides; iGuide++) - pGuides[iGuide].fFreq = - (1 - pAnalParams->fFundContToGuide) * pGuides[iGuide].fFreq + - pAnalParams->fFundContToGuide * fFund * (iGuide + 1); - - if (pAnalParams->iDebugMode == SMS_DBG_PEAK_CONT || - pAnalParams->iDebugMode == SMS_DBG_ALL) - fprintf(stdout, - "Frame %d Peak Continuation: \n", - pAnalParams->ppFrames[iFrame]->iFrameNum); - - /* continue all guides */ - for(iGuide = 0; iGuide < pAnalParams->nGuides; iGuide++) - { - sfloat fPreviousFreq = - pAnalParams->ppFrames[iFrame-1]->deterministic.pFSinFreq[iGuide]; - - /* get the guide value by upgrading the previous guide */ - if(fPreviousFreq > 0) - pGuides[iGuide].fFreq = - (1 - pAnalParams->fPeakContToGuide) * pGuides[iGuide].fFreq + - pAnalParams->fPeakContToGuide * fPreviousFreq; - - if(pAnalParams->iDebugMode == SMS_DBG_PEAK_CONT || - pAnalParams->iDebugMode == SMS_DBG_ALL) - fprintf(stdout, "Guide %d: freq %f, mag %f\n", - iGuide, pGuides[iGuide].fFreq, pGuides[iGuide].fMag); - - if(pGuides[iGuide].fFreq <= 0.0 || - pGuides[iGuide].fFreq > pAnalParams->fHighestFreq) - { - pGuides[iGuide].iStatus = GUIDE_DEAD; - pGuides[iGuide].fFreq = 0; - continue; - } - - pGuides[iGuide].iPeakChosen = -1; - - if(pAnalParams->iFormat == SMS_FORMAT_IH || - pAnalParams->iFormat == SMS_FORMAT_IHP) - fFreqDev = pGuides[iGuide].fFreq * pAnalParams->fFreqDeviation; - - /* get the best peak for the guide */ - GetBestPeak(pGuides, iGuide, pAnalParams->ppFrames[iFrame]->pSpectralPeaks, - pAnalParams, fFreqDev); - } - - /* try to find good peaks for the GUIDE_DEAD guides */ - if(pAnalParams->iFormat == SMS_FORMAT_IH || - pAnalParams->iFormat == SMS_FORMAT_IHP) - { - for(iGuide = 0; iGuide < pAnalParams->nGuides; iGuide++) - { - if(pGuides[iGuide].iStatus != GUIDE_DEAD) - continue; - - /* TODO: make this function use pAnalParams->maxPeaks instead - * of SMS_MAX_NPEAKS */ - if(GetStartingPeak (iGuide, pGuides, pAnalParams->nGuides, - pAnalParams->ppFrames[iFrame]->pSpectralPeaks, - &fCurrentMax) == -1) - break; - } - } - - /* save all the continuation values, - * assume output tracks are already clear */ - for(iGuide = 0; iGuide < pAnalParams->nGuides; iGuide++) - { - if(pGuides[iGuide].iStatus == GUIDE_DEAD) - continue; - - if(pAnalParams->iFormat == SMS_FORMAT_IH || - pAnalParams->iFormat == SMS_FORMAT_IHP) - { - if(pGuides[iGuide].iStatus > 0 && - pGuides[iGuide].iPeakChosen == -1) - { - if(pGuides[iGuide].iStatus++ > pAnalParams->iMaxSleepingTime) - { - pGuides[iGuide].iStatus = GUIDE_DEAD; - pGuides[iGuide].fFreq = 0; - pGuides[iGuide].fMag = 0; - pGuides[iGuide].iPeakChosen = -1; - } - else - pGuides[iGuide].iStatus++; - continue; - } - - if(pGuides[iGuide].iStatus == GUIDE_ACTIVE && - pGuides[iGuide].iPeakChosen == -1) - { - pGuides[iGuide].iStatus = 1; - continue; - } - } - - /* if good continuation peak found, save it */ - if((iCurrentPeak = pGuides[iGuide].iPeakChosen) >= 0) - { - pAnalParams->ppFrames[iFrame]->deterministic.pFSinFreq[iGuide] = - pAnalParams->ppFrames[iFrame]->pSpectralPeaks[iCurrentPeak].fFreq; - pAnalParams->ppFrames[iFrame]->deterministic.pFSinAmp[iGuide] = - pAnalParams->ppFrames[iFrame]->pSpectralPeaks[iCurrentPeak].fMag; - pAnalParams->ppFrames[iFrame]->deterministic.pFSinPha[iGuide] = - pAnalParams->ppFrames[iFrame]->pSpectralPeaks[iCurrentPeak].fPhase; - - pGuides[iGuide].iStatus = GUIDE_ACTIVE; - pGuides[iGuide].iPeakChosen = -1; - } - } + int iGuide, iCurrentPeak = -1, iGoodPeak = -1; + sfloat fFund = pAnalParams->ppFrames[iFrame]->fFundamental, + fFreqDev = fFund * pAnalParams->fFreqDeviation, fCurrentMax = 1000; + + /* update guides with fundamental contribution */ + if(fFund > 0 && (pAnalParams->iFormat == SMS_FORMAT_H || + pAnalParams->iFormat == SMS_FORMAT_HP)) + for(iGuide = 0; iGuide < pAnalParams->nGuides; iGuide++) + pAnalParams->guides[iGuide].fFreq = + (1 - pAnalParams->fFundContToGuide) * pAnalParams->guides[iGuide].fFreq + + pAnalParams->fFundContToGuide * fFund * (iGuide + 1); + + if(pAnalParams->iDebugMode == SMS_DBG_PEAK_CONT || + pAnalParams->iDebugMode == SMS_DBG_ALL) + fprintf(stdout, "Frame %d Peak Continuation: \n", + pAnalParams->ppFrames[iFrame]->iFrameNum); + + /* continue all guides */ + for(iGuide = 0; iGuide < pAnalParams->nGuides; iGuide++) + { + sfloat fPreviousFreq = pAnalParams->ppFrames[iFrame-1]->deterministic.pFSinFreq[iGuide]; + + /* get the guide value by upgrading the previous guide */ + if(fPreviousFreq > 0) + pAnalParams->guides[iGuide].fFreq = + (1 - pAnalParams->fPeakContToGuide) * pAnalParams->guides[iGuide].fFreq + + pAnalParams->fPeakContToGuide * fPreviousFreq; + + if(pAnalParams->iDebugMode == SMS_DBG_PEAK_CONT || + pAnalParams->iDebugMode == SMS_DBG_ALL) + fprintf(stdout, "Guide %d: freq %f, mag %f\n", + iGuide, pAnalParams->guides[iGuide].fFreq, pAnalParams->guides[iGuide].fMag); + + if(pAnalParams->guides[iGuide].fFreq <= 0.0 || + pAnalParams->guides[iGuide].fFreq > pAnalParams->fHighestFreq) + { + pAnalParams->guides[iGuide].iStatus = GUIDE_DEAD; + pAnalParams->guides[iGuide].fFreq = 0; + continue; + } + + pAnalParams->guides[iGuide].iPeakChosen = -1; + + if(pAnalParams->iFormat == SMS_FORMAT_IH || + pAnalParams->iFormat == SMS_FORMAT_IHP) + fFreqDev = pAnalParams->guides[iGuide].fFreq * pAnalParams->fFreqDeviation; + + /* get the best peak for the guide */ + iGoodPeak = + GetBestPeak(pAnalParams->guides, iGuide, pAnalParams->ppFrames[iFrame]->pSpectralPeaks, + pAnalParams, fFreqDev); + } + + /* try to find good peaks for the GUIDE_DEAD guides */ + if(pAnalParams->iFormat == SMS_FORMAT_IH || + pAnalParams->iFormat == SMS_FORMAT_IHP) + for(iGuide = 0; iGuide < pAnalParams->nGuides; iGuide++) + { + if(pAnalParams->guides[iGuide].iStatus != GUIDE_DEAD) + continue; + + if(GetStartingPeak(iGuide, pAnalParams->guides, pAnalParams->nGuides, + pAnalParams->ppFrames[iFrame]->pSpectralPeaks, + &fCurrentMax) == -1) + break; + } + + /* save all the continuation values, + * assume output tracks are already clear */ + for(iGuide = 0; iGuide < pAnalParams->nGuides; iGuide++) + { + if(pAnalParams->guides[iGuide].iStatus == GUIDE_DEAD) + continue; + + if(pAnalParams->iFormat == SMS_FORMAT_IH || + pAnalParams->iFormat == SMS_FORMAT_IHP) + { + if(pAnalParams->guides[iGuide].iStatus > 0 && + pAnalParams->guides[iGuide].iPeakChosen == -1) + { + if(pAnalParams->guides[iGuide].iStatus++ > pAnalParams->iMaxSleepingTime) + { + pAnalParams->guides[iGuide].iStatus = GUIDE_DEAD; + pAnalParams->guides[iGuide].fFreq = 0; + pAnalParams->guides[iGuide].fMag = 0; + pAnalParams->guides[iGuide].iPeakChosen = -1; + } + else + pAnalParams->guides[iGuide].iStatus++; + continue; + } + + if(pAnalParams->guides[iGuide].iStatus == GUIDE_ACTIVE && + pAnalParams->guides[iGuide].iPeakChosen == -1) + { + pAnalParams->guides[iGuide].iStatus = 1; + continue; + } + } + + /* if good continuation peak found, save it */ + if((iCurrentPeak = pAnalParams->guides[iGuide].iPeakChosen) >= 0) + { + pAnalParams->ppFrames[iFrame]->deterministic.pFSinFreq[iGuide] = + pAnalParams->ppFrames[iFrame]->pSpectralPeaks[iCurrentPeak].fFreq; + pAnalParams->ppFrames[iFrame]->deterministic.pFSinAmp[iGuide] = + pAnalParams->ppFrames[iFrame]->pSpectralPeaks[iCurrentPeak].fMag; + pAnalParams->ppFrames[iFrame]->deterministic.pFSinPha[iGuide] = + pAnalParams->ppFrames[iFrame]->pSpectralPeaks[iCurrentPeak].fPhase; + + pAnalParams->guides[iGuide].iStatus = GUIDE_ACTIVE; + pAnalParams->guides[iGuide].iPeakChosen = -1; + } + } return SMS_OK; } + diff --git a/sms/peakDetection.c b/sms/peakDetection.c index 1bbe713..fc40e69 100644 --- a/sms/peakDetection.c +++ b/sms/peakDetection.c @@ -165,31 +165,20 @@ static sfloat GetPhaseVal (sfloat *pPhaseSpectrum, sfloat fPeakLoc) int sms_detectPeaks(int sizeSpec, sfloat *pMag, sfloat *pPhase, SMS_Peak *pSpectralPeaks, SMS_AnalParams *pAnalParams) { - static int iFirstBin, iHighestBin, sizeFft; - static sfloat fInvSizeFft; - static int sizeSpecStatic = 0; - - /* allocate memory if sizeSpec has changed or this is the first run */ - if(sizeSpecStatic != sizeSpec) - { - sizeSpecStatic = sizeSpec; - sizeFft = sizeSpec << 1; - fInvSizeFft = 1.0 / sizeFft; - /* make sure to start on the 2nd bin so interpolation is possible QUESTION: why not allow a peak in bin 1 or 0? */ - /* rte: changed the first argument of MAX from 2 to 1 */ - iFirstBin = MAX(1, sizeFft * pAnalParams->fLowestFreq / pAnalParams->iSamplingRate); - iHighestBin = MIN(sizeSpec-1, sizeFft * pAnalParams->fHighestFreq / pAnalParams->iSamplingRate); - } + int sizeFft = sizeSpec << 1; + sfloat fInvSizeFft = 1.0 / sizeFft; + int iFirstBin = MAX(1, sizeFft * pAnalParams->fLowestFreq / pAnalParams->iSamplingRate); + int iHighestBin = MIN(sizeSpec-1, sizeFft * pAnalParams->fHighestFreq / pAnalParams->iSamplingRate); /* clear peak structure */ memset(pSpectralPeaks, 0, pAnalParams->maxPeaks * sizeof(SMS_Peak)); /* set starting search values */ int iCurrentLoc = iFirstBin; - int iPeak = 0; /* index for spectral search */ - sfloat fPeakMag = 0.0; /* magnitude of peak */ - sfloat fPeakLoc = 0.0; /* location of peak */ - + int iPeak = 0; /* index for spectral search */ + sfloat fPeakMag = 0.0; /* magnitude of peak */ + sfloat fPeakLoc = 0.0; /* location of peak */ + /* find peaks */ while((iPeak < pAnalParams->maxPeaks) && (FindNextPeak(pMag, iHighestBin, &iCurrentLoc, &fPeakMag, diff --git a/sms/residual.c b/sms/residual.c index a9237dc..b69a28f 100644 --- a/sms/residual.c +++ b/sms/residual.c @@ -32,109 +32,45 @@ * \param pResidual pointer to output residual waveform * \param pWindow pointer to windowing array * \return residual percentage (0 if residual was not large enough) - \todo why is residual energy percentage computed this way? should be optional and in a seperate function + \todo why is residual energy percentage computed this way? should be optional and in a seperate function */ -int sms_residual (int sizeWindow, sfloat *pSynthesis, sfloat *pOriginal, sfloat *pResidual) +int sms_residual(int sizeWindow, sfloat *pSynthesis, sfloat *pOriginal, sfloat *pResidual, sfloat *pWindow) { - static sfloat fResidualMag = 0.; + static sfloat fResidualMag = 0.; static sfloat fOriginalMag = 0.; - sfloat fScale = 1.; - sfloat fCurrentResidualMag = 0.; - sfloat fCurrentOriginalMag = 0.; - int i; - - /* get residual */ - for (i=0; i fOriginalMag) - { - fScale = fOriginalMag / fResidualMag; - for (i=0; i fOriginalMag) + { + fScale = fOriginalMag / fResidualMag; + for (i=0; i .01) - if (fCurrentResidualMag) //always compute - { -/* printf(" fCurrentResidualMag: %f, sizeWindow: %d, ratio: %f\n", */ -/* fCurrentResidualMag, sizeWindow, fCurrentResidualMag/sizeWindow ); */ - - /* get energy of original */ - for (i=0; i fOriginalMag) - { - fScale = fOriginalMag / fResidualMag; - for (i=0; ipFSinAmp[iTrack] <= 0) - { - pLastFrame->pFSinFreq[iTrack] = fFreq; - fTmp = fPhase - (fFreq * sizeBuffer); - pLastFrame->pFSinPha[iTrack] = fTmp - floor(fTmp / TWO_PI) * TWO_PI; - } - /* and the other way */ - else if (fMag <= 0) - { - fFreq = pLastFrame->pFSinFreq[iTrack]; - fTmp = pLastFrame->pFSinPha[iTrack] + + /* if no mag in last frame copy freq from current and make phase */ + if (pLastFrame->pFSinAmp[iTrack] <= 0) + { + pLastFrame->pFSinFreq[iTrack] = fFreq; + fTmp = fPhase - (fFreq * sizeBuffer); + pLastFrame->pFSinPha[iTrack] = fTmp - floor(fTmp / TWO_PI) * TWO_PI; + } + /* and the other way */ + else if (fMag <= 0) + { + fFreq = pLastFrame->pFSinFreq[iTrack]; + fTmp = pLastFrame->pFSinPha[iTrack] + (pLastFrame->pFSinFreq[iTrack] * sizeBuffer); - fPhase = fTmp - floor(fTmp / TWO_PI) * TWO_PI; - } - - /* caculate the instantaneous amplitude */ - fMagIncr = (fMag - pLastFrame->pFSinAmp[iTrack]) / sizeBuffer; - fInstMag = pLastFrame->pFSinAmp[iTrack]; - - /* create instantaneous phase from freq. and phase values */ - fTmp1 = fFreq - pLastFrame->pFSinFreq[iTrack]; - fTmp2 = ((pLastFrame->pFSinPha[iTrack] + - pLastFrame->pFSinFreq[iTrack] * sizeBuffer - fPhase) + - fTmp1 * sizeBuffer / 2.0) / TWO_PI; - iM = (int) (fTmp2 + .5); - fTmp2 = fPhase - pLastFrame->pFSinPha[iTrack] - - pLastFrame->pFSinFreq[iTrack] * sizeBuffer + - TWO_PI * iM; - fAlpha = (3.0 / (sfloat)(sizeBuffer * sizeBuffer)) * - fTmp2 - fTmp1 / sizeBuffer; - fBeta = (-2.0 / ((sfloat) (sizeBuffer * sizeBuffer * sizeBuffer))) * - fTmp2 + fTmp1 / ((sfloat) (sizeBuffer * sizeBuffer)); - - for(i=0; ipFSinPha[iTrack] + - pLastFrame->pFSinFreq[iTrack] * i + - fAlpha * i * i + fBeta * i * i * i; - -/* pFWaveform[i] += sms_dBToMag(fInstMag) * sms_sine(fInstPhase + PI_2); */ - pFWaveform[i] += sms_dBToMag(fInstMag) * sinf(fInstPhase + PI_2); - } - /* save current values into buffer */ - pLastFrame->pFSinFreq[iTrack] = fFreq; - pLastFrame->pFSinAmp[iTrack] = fMag; - pLastFrame->pFSinPha[iTrack] = fPhase; + fPhase = fTmp - floor(fTmp / TWO_PI) * TWO_PI; + } + + /* caculate the instantaneous amplitude */ + fMagIncr = (fMag - pLastFrame->pFSinAmp[iTrack]) / sizeBuffer; + fInstMag = pLastFrame->pFSinAmp[iTrack]; + + /* create instantaneous phase from freq. and phase values */ + fTmp1 = fFreq - pLastFrame->pFSinFreq[iTrack]; + fTmp2 = ((pLastFrame->pFSinPha[iTrack] + + pLastFrame->pFSinFreq[iTrack] * sizeBuffer - fPhase) + + fTmp1 * sizeBuffer / 2.0) / TWO_PI; + iM = (int) (fTmp2 + .5); + fTmp2 = fPhase - pLastFrame->pFSinPha[iTrack] - + pLastFrame->pFSinFreq[iTrack] * sizeBuffer + + TWO_PI * iM; + fAlpha = (3.0 / (sfloat)(sizeBuffer * sizeBuffer)) * + fTmp2 - fTmp1 / sizeBuffer; + fBeta = (-2.0 / ((sfloat) (sizeBuffer * sizeBuffer * sizeBuffer))) * + fTmp2 + fTmp1 / ((sfloat) (sizeBuffer * sizeBuffer)); + + for(i=0; ipFSinPha[iTrack] + + pLastFrame->pFSinFreq[iTrack] * i + + fAlpha * i * i + fBeta * i * i * i; + + /* pFWaveform[i] += sms_dBToMag(fInstMag) * sms_sine(fInstPhase + PI_2); */ + pFWaveform[i] += sms_dBToMag(fInstMag) * sinf(fInstPhase + PI_2); + } + /* save current values into buffer */ + pLastFrame->pFSinFreq[iTrack] = fFreq; + pLastFrame->pFSinAmp[iTrack] = fMag; + pLastFrame->pFSinPha[iTrack] = fPhase; } /*! \brief generate a sinusoid given two frames, current and last * - * \param fFreq current frequency + * \param fFreq current frequency * \param fMag current magnitude * \param pLastFrame stucture with values from last frame - * \param pFBuffer pointer to output waveform - * \param sizeBuffer size of the synthesis buffer + * \param pFBuffer pointer to output waveform + * \param sizeBuffer size of the synthesis buffer * \param iTrack current track */ -static void SineSynth (sfloat fFreq, sfloat fMag, SMS_Data *pLastFrame, - sfloat *pFBuffer, int sizeBuffer, int iTrack) +static void SineSynth(sfloat fFreq, sfloat fMag, SMS_Data *pLastFrame, + sfloat *pFBuffer, int sizeBuffer, int iTrack) { - sfloat fMagIncr, fInstMag, fFreqIncr, fInstPhase, fInstFreq; - int i; - - /* if no mag in last frame copy freq from current */ - if (pLastFrame->pFSinAmp[iTrack] <= 0) - { + sfloat fMagIncr, fInstMag, fFreqIncr, fInstPhase, fInstFreq; + int i; + + /* if no mag in last frame copy freq from current */ + if (pLastFrame->pFSinAmp[iTrack] <= 0) + { + pLastFrame->pFSinFreq[iTrack] = fFreq; + pLastFrame->pFSinPha[iTrack] = + TWO_PI * sms_random(); + } + /* and the other way */ + else if (fMag <= 0) + fFreq = pLastFrame->pFSinFreq[iTrack]; + + /* calculate the instantaneous amplitude */ + fMagIncr = (fMag - pLastFrame->pFSinAmp[iTrack]) / sizeBuffer; + fInstMag = pLastFrame->pFSinAmp[iTrack]; + /* calculate instantaneous frequency */ + fFreqIncr = (fFreq - pLastFrame->pFSinFreq[iTrack]) / sizeBuffer; + fInstFreq = pLastFrame->pFSinFreq[iTrack]; + fInstPhase = pLastFrame->pFSinPha[iTrack]; + + /* generate all the samples */ + for (i = 0; i < sizeBuffer; i++) + { + fInstMag += fMagIncr; + fInstFreq += fFreqIncr; + fInstPhase += fInstFreq; + + pFBuffer[i] += sms_dBToMag(fInstMag) * sms_sine(fInstPhase); + } + + /* save current values into last values */ pLastFrame->pFSinFreq[iTrack] = fFreq; - pLastFrame->pFSinPha[iTrack] = - TWO_PI * sms_random(); - } - /* and the other way */ - else if (fMag <= 0) - fFreq = pLastFrame->pFSinFreq[iTrack]; - - /* calculate the instantaneous amplitude */ - fMagIncr = (fMag - pLastFrame->pFSinAmp[iTrack]) / sizeBuffer; - fInstMag = pLastFrame->pFSinAmp[iTrack]; - /* calculate instantaneous frequency */ - fFreqIncr = (fFreq - pLastFrame->pFSinFreq[iTrack]) / sizeBuffer; - fInstFreq = pLastFrame->pFSinFreq[iTrack]; - fInstPhase = pLastFrame->pFSinPha[iTrack]; - - /* generate all the samples */ - for (i = 0; i < sizeBuffer; i++) - { - fInstMag += fMagIncr; - fInstFreq += fFreqIncr; - fInstPhase += fInstFreq; - - pFBuffer[i] += sms_dBToMag (fInstMag) * sms_sine (fInstPhase); - } - - /* save current values into last values */ - pLastFrame->pFSinFreq[iTrack] = fFreq; - pLastFrame->pFSinAmp[iTrack] = fMag; - pLastFrame->pFSinPha[iTrack] = fInstPhase - - floor(fInstPhase / TWO_PI) * TWO_PI; + pLastFrame->pFSinAmp[iTrack] = fMag; + pLastFrame->pFSinPha[iTrack] = fInstPhase - + floor(fInstPhase / TWO_PI) * TWO_PI; } /*! \brief generate all the sinusoids for a given frame * * \param pSmsData SMS data for current frame - * \param pFBuffer pointer to output waveform + * \param pFBuffer pointer to output waveform * \param sizeBuffer size of the synthesis buffer * \param pLastFrame SMS data from last frame * \param iSamplingRate sampling rate to synthesize for */ -void sms_sineSynthFrame (SMS_Data *pSmsData, sfloat *pFBuffer, - int sizeBuffer, SMS_Data *pLastFrame, int iSamplingRate) +void sms_sineSynthFrame(SMS_Data *pSmsData, sfloat *pFBuffer, + int sizeBuffer, SMS_Data *pLastFrame, + int iSamplingRate) { - sfloat fMag, fFreq; - int i; - int nTracks = pSmsData->nTracks; - int iHalfSamplingRate = iSamplingRate >> 1; - - /* go through all the tracks */ - for (i = 0; i < nTracks; i++) - { - /* get magnitude */ - fMag = pSmsData->pFSinAmp[i]; - - fFreq = pSmsData->pFSinFreq[i]; - - /* gaurd so transposed frequencies don't alias */ - if (fFreq > iHalfSamplingRate || fFreq < 0) - fMag = 0; - - /* generate sines if there are magnitude values */ - if ((fMag > 0) || (pLastFrame->pFSinAmp[i] > 0)) - { - /* frequency from Hz to radians */ - fFreq = (fFreq == 0) ? 0 : TWO_PI * fFreq / iSamplingRate; - - /* \todo make seperate function for SineSynth /wo phase */ - if (pSmsData->pFSinPha == NULL) - { - SineSynth(fFreq, fMag, pLastFrame, pFBuffer, sizeBuffer, i); - } - else - { - SinePhaSynth(fFreq, fMag, pSmsData->pFSinPha[i], pLastFrame, - pFBuffer, sizeBuffer, i); - } - } + sfloat fMag, fFreq; + int i; + int nTracks = pSmsData->nTracks; + int iHalfSamplingRate = iSamplingRate >> 1; + + /* go through all the tracks */ + for (i = 0; i < nTracks; i++) + { + /* get magnitude */ + fMag = pSmsData->pFSinAmp[i]; + + fFreq = pSmsData->pFSinFreq[i]; + + /* gaurd so transposed frequencies don't alias */ + if (fFreq > iHalfSamplingRate || fFreq < 0) + fMag = 0; + + /* generate sines if there are magnitude values */ + if ((fMag > 0) || (pLastFrame->pFSinAmp[i] > 0)) + { + /* frequency from Hz to radians */ + fFreq = (fFreq == 0) ? 0 : TWO_PI * fFreq / iSamplingRate; + + /* \todo make seperate function for SineSynth /wo phase */ + if (pSmsData->pFSinPha == NULL) + { + SineSynth(fFreq, fMag, pLastFrame, pFBuffer, sizeBuffer, i); + } + else + { + SinePhaSynth(fFreq, fMag, pSmsData->pFSinPha[i], pLastFrame, + pFBuffer, sizeBuffer, i); + } } + } } + diff --git a/sms/sms.c b/sms/sms.c index 6d29e53..f9e2e95 100644 --- a/sms/sms.c +++ b/sms/sms.c @@ -35,7 +35,6 @@ static sfloat inv_mag_thresh = 100000.; /*!< inv(.00001) */ static int initIsDone = 0; /* \todo is this variable necessary? */ #define SIZE_TABLES 4096 - #define HALF_MAX 1073741823.5 /*!< half the max of a 32-bit word */ #define INV_HALF_MAX (1.0 / HALF_MAX) #define TWENTY_OVER_LOG10 (20. / LOG10) @@ -50,36 +49,35 @@ static int initIsDone = 0; /* \todo is this variable necessary? */ * * \return error code \see SMS_MALLOC or SMS_OK in SMS_ERRORS */ -int sms_init( void ) +int sms_init(void) { - int iError; if (!initIsDone) { initIsDone = 1; - if(sms_prepSine (SIZE_TABLES)) + if(sms_prepSine(SIZE_TABLES)) { sms_error("cannot allocate memory for sine table"); - return (-1); + return -1; } - if(sms_prepSinc (SIZE_TABLES)) + if(sms_prepSinc(SIZE_TABLES)) { sms_error("cannot allocate memory for sinc table"); - return (-1); + return -1; } - } #ifdef MERSENNE_TWISTER - init_gen_rand(1234); + init_gen_rand(1234); #endif + } - return (0); + return 0; } /*! \brief free global data * * deallocates memory allocated to global arrays (windows and tables) */ -void sms_free( void ) +void sms_free() { initIsDone = 0; sms_clearSine(); @@ -101,6 +99,7 @@ void sms_free( void ) */ void sms_initAnalParams(SMS_AnalParams *pAnalParams) { + int i; pAnalParams->iDebugMode = 0; pAnalParams->iFormat = SMS_FORMAT_H; pAnalParams->iSoundType = SMS_SOUND_TYPE_MELODY; @@ -141,8 +140,6 @@ void sms_initAnalParams(SMS_AnalParams *pAnalParams) (pAnalParams->minGoodFrames + pAnalParams->analDelay); pAnalParams->fResidualAccumPerc = 0.; pAnalParams->preEmphasisLastValue = 0.; - pAnalParams->resetGuides = 1; - pAnalParams->resetGuideStates = 1; /* spectral envelope params */ pAnalParams->specEnvParams.iType = SMS_ENV_NONE; /* turn off enveloping */ pAnalParams->specEnvParams.iOrder = 25; /* ... but set default params anyway */ @@ -150,6 +147,33 @@ void sms_initAnalParams(SMS_AnalParams *pAnalParams) pAnalParams->specEnvParams.iMaxFreq = 0; pAnalParams->specEnvParams.nCoeff = 0; pAnalParams->specEnvParams.iAnchor = 0; /* not yet implemented */ + pAnalParams->pFrames = NULL; + /* fft */ + for(i = 0; i < SMS_MAX_SPEC; i++) + { + pAnalParams->magSpectrum[i] = 0.0; + pAnalParams->phaseSpectrum[i] = 0.0; + pAnalParams->spectrumWindow[i] = 0.0; + pAnalParams->fftBuffer[i] = 0.0; + pAnalParams->fftBuffer[i+SMS_MAX_SPEC] = 0.0; + } + /* analysis frames */ + pAnalParams->pFrames = NULL; + pAnalParams->ppFrames = NULL; + /* residual */ + pAnalParams->sizeResidual = pAnalParams->sizeHop * 2; + pAnalParams->residual = NULL; + pAnalParams->residualWindow = NULL; + /* peak continuation */ + pAnalParams->guideStates = NULL; + pAnalParams->guides = NULL; + /* audio input frame */ + for(i = 0; i < SMS_MAX_FRAME_SIZE; i++) + pAnalParams->inputBuffer[i] = 0.0; + /* stochastic analysis */ + pAnalParams->stocMagSpectrum = NULL; + pAnalParams->approxEnvelope = NULL; + pAnalParams->ppFrames = NULL; } /*! \brief initialize analysis data structure's arrays @@ -170,16 +194,12 @@ int sms_initAnalysis(SMS_AnalParams *pAnalParams) /* define the hopsize for each record */ pAnalParams->sizeHop = (int)(pAnalParams->iSamplingRate / - (sfloat) pAnalParams->iFrameRate); - - /* define the number of frames and number of samples */ - // pAnalParams->nFrames = pSoundHeader->nSamples / (sfloat) pAnalParams->sizeHop; - // pAnalParams->iSizeSound = pSoundHeader->nSamples; + (sfloat) pAnalParams->iFrameRate); /* set the default size window to an odd length */ pAnalParams->iDefaultSizeWindow = (int)((pAnalParams->iSamplingRate / pAnalParams->fDefaultFundamental) * - pAnalParams->fSizeWindow / 2) * 2 + 1; + pAnalParams->fSizeWindow / 2) * 2 + 1; int sizeBuffer = (pAnalParams->iMaxDelayFrames * pAnalParams->sizeHop) + SMS_MAX_WINDOW; @@ -197,16 +217,16 @@ int sms_initAnalysis(SMS_AnalParams *pAnalParams) pAnalParams->specEnvParams.iMaxFreq = pAnalParams->fHighestFreq; /*\todo this probably doesn't need env coefficients - they aren't getting used */ - sms_allocFrame (&pAnalParams->prevFrame, pAnalParams->nGuides, - pAnalParams->nStochasticCoeff, 1, pAnalParams->iStochasticType, 0); + sms_allocFrame(&pAnalParams->prevFrame, pAnalParams->nGuides, + pAnalParams->nStochasticCoeff, 1, pAnalParams->iStochasticType, 0); - pAnalParams->sizeNextRead = (pAnalParams->iDefaultSizeWindow + 1) * 0.5; /* \todo REMOVE THIS from other files first */ + pAnalParams->sizeNextRead = (pAnalParams->iDefaultSizeWindow + 1) * 0.5; /* sound buffer */ if ((pSoundBuf->pFBuffer = (sfloat *) calloc(sizeBuffer, sizeof(sfloat))) == NULL) { sms_error("could not allocate memory"); - return(-1); + return -1; } pSoundBuf->iMarker = -sizeBuffer; pSoundBuf->iFirstGood = sizeBuffer; @@ -222,74 +242,179 @@ int sms_initAnalysis(SMS_AnalParams *pAnalParams) pAnalParams->fDefaultFundamental = pAnalParams->fHighestFundamental; } - /* initialize peak detection/continuation parameters */ - /*pAnalParams->peakParams.fLowestFreq = pAnalParams->fLowestFundamental;*/ - /*pAnalParams->peakParams.fHighestFreq = pAnalParams->fHighestFreq;*/ - /*pAnalParams->peakParams.fMinPeakMag = pAnalParams->fMinPeakMag;*/ - /*pAnalParams->peakParams.iSamplingRate = pAnalParams->iSamplingRate;*/ - /*pAnalParams->peakParams.iMaxPeaks = SMS_MAX_NPEAKS;*/ - /*pAnalParams->peakParams.fHighestFundamental = pAnalParams->fHighestFundamental;*/ - /*pAnalParams->peakParams.iRefHarmonic = pAnalParams->iRefHarmonic;*/ - /*pAnalParams->peakParams.fMinRefHarmMag = pAnalParams->fMinRefHarmMag;*/ - /*pAnalParams->peakParams.fRefHarmMagDiffFromMax = pAnalParams->fRefHarmMagDiffFromMax;*/ - /*pAnalParams->peakParams.iSoundType = pAnalParams->iSoundType;*/ - /* deterministic synthesis buffer */ pSynthBuf->sizeBuffer = pAnalParams->sizeHop << 1; - if((pSynthBuf->pFBuffer = (sfloat *)calloc(pSynthBuf->sizeBuffer, sizeof(sfloat))) == NULL) + pSynthBuf->pFBuffer = calloc(pSynthBuf->sizeBuffer, sizeof(sfloat)); + if(pSynthBuf->pFBuffer == NULL) { sms_error("could not allocate memory"); - return(-1); + return -1; } - pSynthBuf->iMarker = -sizeBuffer; pSynthBuf->iMarker = pSynthBuf->sizeBuffer; - /* buffer of analysis frames */ - if ((pAnalParams->pFrames = (SMS_AnalFrame *) calloc(pAnalParams->iMaxDelayFrames, sizeof(SMS_AnalFrame))) == NULL) + pAnalParams->pFrames = (SMS_AnalFrame *)malloc(pAnalParams->iMaxDelayFrames * sizeof(SMS_AnalFrame)); + if(pAnalParams->pFrames == NULL) { sms_error("could not allocate memory for delay frames"); - return(-1); + return -1; } - if ((pAnalParams->ppFrames = - (SMS_AnalFrame **) calloc(pAnalParams->iMaxDelayFrames, sizeof(SMS_AnalFrame *))) == NULL) + pAnalParams->ppFrames = (SMS_AnalFrame **)malloc(pAnalParams->iMaxDelayFrames * sizeof(SMS_AnalFrame *)); + if(pAnalParams->ppFrames == NULL) { sms_error("could not allocate memory for pointers to delay frames"); - return(-1); + return -1; } /* initialize the frame pointers and allocate memory */ - for (i = 0; i < pAnalParams->iMaxDelayFrames; i++) + for(i = 0; i < pAnalParams->iMaxDelayFrames; i++) { pAnalParams->pFrames[i].iStatus = SMS_FRAME_EMPTY; - if (((pAnalParams->pFrames[i]).pSpectralPeaks = - (SMS_Peak *)calloc (pAnalParams->maxPeaks, sizeof(SMS_Peak))) == NULL) + pAnalParams->pFrames[i].iFrameSample = 0; + pAnalParams->pFrames[i].iFrameSize = 0; + pAnalParams->pFrames[i].iFrameNum = 0; + pAnalParams->pFrames[i].pSpectralPeaks = + (SMS_Peak *)malloc(pAnalParams->maxPeaks * sizeof(SMS_Peak)); + if((pAnalParams->pFrames[i]).pSpectralPeaks == NULL) { sms_error("could not allocate memory for spectral peaks"); - return(-1); + return -1; } (pAnalParams->pFrames[i].deterministic).nTracks = pAnalParams->nGuides; - if (((pAnalParams->pFrames[i].deterministic).pFSinFreq = - (sfloat *)calloc (pAnalParams->nGuides, sizeof(sfloat))) == NULL) + + (pAnalParams->pFrames[i].deterministic).pFSinFreq = + (sfloat *)calloc(pAnalParams->nGuides, sizeof(sfloat)); + if((pAnalParams->pFrames[i].deterministic).pFSinFreq == NULL) { sms_error("could not allocate memory"); - return(-1); + return -1; } - if (((pAnalParams->pFrames[i].deterministic).pFSinAmp = - (sfloat *)calloc (pAnalParams->nGuides, sizeof(sfloat))) == NULL) + + (pAnalParams->pFrames[i].deterministic).pFSinAmp = + (sfloat *)calloc(pAnalParams->nGuides, sizeof(sfloat)); + if((pAnalParams->pFrames[i].deterministic).pFSinAmp == NULL) { sms_error("could not allocate memory"); - return(-1); + return -1; } - if (((pAnalParams->pFrames[i].deterministic).pFSinPha = - (sfloat *) calloc (pAnalParams->nGuides, sizeof(sfloat))) == NULL) + + (pAnalParams->pFrames[i].deterministic).pFSinPha = + (sfloat *)calloc(pAnalParams->nGuides, sizeof(sfloat)); + if((pAnalParams->pFrames[i].deterministic).pFSinPha == NULL) { sms_error("could not allocate memory"); - return(-1); + return -1; } pAnalParams->ppFrames[i] = &pAnalParams->pFrames[i]; } + /* memory for residual */ + pAnalParams->sizeResidual = pAnalParams->sizeHop * 2; + pAnalParams->residual = (sfloat *)calloc(pAnalParams->sizeResidual, sizeof(sfloat)); + if(pAnalParams->residual == NULL) + { + sms_error("Could not allocate memory for residual"); + return -1; + } + pAnalParams->residualWindow = (sfloat *)calloc(pAnalParams->sizeResidual, sizeof(sfloat)); + if(pAnalParams->residualWindow == NULL) + { + sms_error("Could not allocate memory for residualWindow"); + return -1; + } + sms_getWindow(pAnalParams->sizeResidual, pAnalParams->residualWindow, SMS_WIN_HAMMING); + sms_scaleWindow(pAnalParams->sizeResidual, pAnalParams->residualWindow); + + /* memory for guide states */ + pAnalParams->guideStates = (int *)calloc(pAnalParams->nGuides, sizeof(int)); + if(pAnalParams->guideStates == NULL) + { + sms_error("Could not allocate memory for guide states"); + return -1; + } + + /* memory for guides */ + pAnalParams->guides = (SMS_Guide *)malloc(pAnalParams->nGuides * sizeof(SMS_Guide)); + if(pAnalParams->guides == NULL) + { + sms_error("Could not allocate memory for guides"); + return -1; + } + /* initial guide values */ + if(pAnalParams->iFormat == SMS_FORMAT_H || + pAnalParams->iFormat == SMS_FORMAT_HP) + { + for (i = 0; i < pAnalParams->nGuides; i++) + { + pAnalParams->guides[i].fFreq = pAnalParams->fDefaultFundamental * (i + 1); + } + } + + /* stochastic analysis */ + pAnalParams->sizeStocMagSpectrum = sms_power2(pAnalParams->sizeResidual) >> 1; + pAnalParams->stocMagSpectrum = (sfloat *)calloc(pAnalParams->sizeStocMagSpectrum, sizeof(sfloat)); + if(pAnalParams->stocMagSpectrum == NULL) + { + sms_error("Could not allocate memory for stochastic magnitude spectrum"); + return -1; + } + pAnalParams->approxEnvelope = (sfloat *)calloc(pAnalParams->nStochasticCoeff, sizeof(sfloat)); + if(pAnalParams->approxEnvelope == NULL) + { + sms_error("Could not allocate memory for spectral approximation envelope"); + return -1; + } + return 0; + + /*[> buffer of analysis frames <]*/ + /*pAnalParams->pFrames = (SMS_AnalFrame *) malloc(pAnalParams->iMaxDelayFrames * sizeof(SMS_AnalFrame)); */ + /*if(pAnalParams->pFrames == NULL)*/ + /*{*/ + /* sms_error("could not allocate memory for delay frames");*/ + /* return -1;*/ + /*}*/ + + /*pAnalParams->ppFrames = (SMS_AnalFrame **) malloc(pAnalParams->iMaxDelayFrames * sizeof(SMS_AnalFrame *));*/ + /*if(pAnalParams->ppFrames == NULL)*/ + /*{*/ + /* sms_error("could not allocate memory for pointers to delay frames");*/ + /* return -1;*/ + /*}*/ + + /*[> initialize the frame pointers and allocate memory <]*/ + /*for (i = 0; i < pAnalParams->iMaxDelayFrames; i++)*/ + /*{*/ + /* pAnalParams->pFrames[i].iStatus = SMS_FRAME_EMPTY;*/ + /* pAnalParams->pFrames[i].pSpectralPeaks =*/ + /* (SMS_Peak *)malloc(pAnalParams->maxPeaks * sizeof(SMS_Peak));*/ + /* if (pAnalParams->pFrames[i].pSpectralPeaks == NULL)*/ + /* {*/ + /* sms_error("could not allocate memory for spectral peaks");*/ + /* return -1;*/ + /* }*/ + /* (pAnalParams->pFrames[i].deterministic).nTracks = pAnalParams->nGuides;*/ + /* if (((pAnalParams->pFrames[i].deterministic).pFSinFreq =*/ + /* (sfloat *)calloc (pAnalParams->nGuides, sizeof(sfloat))) == NULL)*/ + /* {*/ + /* sms_error("could not allocate memory");*/ + /* return -1;*/ + /* }*/ + /* if (((pAnalParams->pFrames[i].deterministic).pFSinAmp =*/ + /* (sfloat *)calloc (pAnalParams->nGuides, sizeof(sfloat))) == NULL)*/ + /* {*/ + /* sms_error("could not allocate memory");*/ + /* return -1;*/ + /* }*/ + /* if (((pAnalParams->pFrames[i].deterministic).pFSinPha =*/ + /* (sfloat *) calloc (pAnalParams->nGuides, sizeof(sfloat))) == NULL)*/ + /* {*/ + /* sms_error("could not allocate memory");*/ + /* return -1;*/ + /* }*/ + /* pAnalParams->ppFrames[i] = &pAnalParams->pFrames[i];*/ + /*}*/ + + /*return 0;*/ } void sms_changeHopSize(int hopSize, SMS_AnalParams *pAnalParams) @@ -297,15 +422,17 @@ void sms_changeHopSize(int hopSize, SMS_AnalParams *pAnalParams) pAnalParams->sizeHop = hopSize; pAnalParams->iFrameRate = pAnalParams->iSamplingRate / hopSize; int sizeBuffer = (pAnalParams->iMaxDelayFrames * pAnalParams->sizeHop) + SMS_MAX_WINDOW; - SMS_SndBuffer *pSynthBuf = &pAnalParams->synthBuffer; - SMS_SndBuffer *pSoundBuf = &pAnalParams->soundBuffer; /* if storing residual phases, restrict number of stochastic coefficients to the size of the spectrum (sizeHop = 1/2 sizeFft)*/ if(pAnalParams->iStochasticType == SMS_STOC_IFFT) pAnalParams->nStochasticCoeff = sms_power2(pAnalParams->sizeHop); /* sound buffer */ - if ((pSoundBuf->pFBuffer = (sfloat *) calloc(sizeBuffer, sizeof(sfloat))) == NULL) + SMS_SndBuffer *pSoundBuf = &pAnalParams->soundBuffer; + + free(pSoundBuf->pFBuffer); + pSoundBuf->pFBuffer = calloc(sizeBuffer, sizeof(sfloat)); + if(pSoundBuf->pFBuffer == NULL) { sms_error("could not allocate memory"); return; @@ -315,13 +442,16 @@ void sms_changeHopSize(int hopSize, SMS_AnalParams *pAnalParams) pSoundBuf->sizeBuffer = sizeBuffer; /* deterministic synthesis buffer */ + SMS_SndBuffer *pSynthBuf = &pAnalParams->synthBuffer; pSynthBuf->sizeBuffer = pAnalParams->sizeHop << 1; - if((pSynthBuf->pFBuffer = (sfloat *)calloc(pSynthBuf->sizeBuffer, sizeof(sfloat))) == NULL) + + free(pSynthBuf->pFBuffer); + pSynthBuf->pFBuffer = calloc(sizeBuffer, sizeof(sfloat)); + if(pSynthBuf->pFBuffer == NULL) { sms_error("could not allocate memory"); return; } - pSynthBuf->iMarker = -sizeBuffer; pSynthBuf->iMarker = pSynthBuf->sizeBuffer; } @@ -344,7 +474,14 @@ void sms_initSynthParams(SMS_SynthParams *synthParams) synthParams->nTracks = 60; synthParams->iStochasticType = SMS_STOC_APPROX; synthParams->nStochasticCoeff = 128; - synthParams->deemphasisLastValue = 0; + synthParams->pFDetWindow = NULL; + synthParams->pFStocWindow = NULL; + synthParams->pSynthBuff = NULL; + synthParams->pMagBuff = NULL; + synthParams->pPhaseBuff = NULL; + synthParams->pSpectra = NULL; + synthParams->approxEnvelope = NULL; + synthParams->deEmphasisLastValue = 0; } /*! \brief initialize synthesis data structure's arrays @@ -364,12 +501,6 @@ void sms_initSynthParams(SMS_SynthParams *synthParams) int sms_initSynth(SMS_SynthParams *pSynthParams) { int sizeHop, sizeFft, err; - /* set synthesis parameters from arguments and header */ - // pSynthParams->iOriginalSRate = pSmsHeader->iSamplingRate; - // pSynthParams->origSizeHop = pSynthParams->iOriginalSRate / pSmsHeader->iFrameRate; - // pSynthParams->iStochasticType = pSmsHeader->iStochasticType; - // if(pSynthParams->iSamplingRate <= 0) - // pSynthParams->iSamplingRate = pSynthParams->iOriginalSRate; /* make sure sizeHop is something to the power of 2 */ sizeHop = sms_power2(pSynthParams->sizeHop); @@ -382,29 +513,34 @@ int sms_initSynth(SMS_SynthParams *pSynthParams) sizeFft = sizeHop * 2; pSynthParams->pFStocWindow =(sfloat *) calloc(sizeFft, sizeof(sfloat)); - sms_getWindow( sizeFft, pSynthParams->pFStocWindow, SMS_WIN_HANNING ); + sms_getWindow(sizeFft, pSynthParams->pFStocWindow, SMS_WIN_HANNING); pSynthParams->pFDetWindow = (sfloat *) calloc(sizeFft, sizeof(sfloat)); - sms_getWindow( sizeFft, pSynthParams->pFDetWindow, SMS_WIN_IFFT ); + sms_getWindow(sizeFft, pSynthParams->pFDetWindow, SMS_WIN_IFFT); /* allocate memory for analysis data - size of original hopsize */ /* previous frame to interpolate from */ /* \todo why is stoch coeff + 1? */ sms_allocFrame(&pSynthParams->prevFrame, pSynthParams->nTracks, - pSynthParams->nStochasticCoeff + 1, 1, - pSynthParams->iStochasticType, 0); + pSynthParams->nStochasticCoeff + 1, 1, + pSynthParams->iStochasticType, 0); pSynthParams->pSynthBuff = (sfloat *) calloc(sizeFft, sizeof(sfloat)); pSynthParams->pMagBuff = (sfloat *) calloc(sizeHop, sizeof(sfloat)); pSynthParams->pPhaseBuff = (sfloat *) calloc(sizeHop, sizeof(sfloat)); pSynthParams->pSpectra = (sfloat *) calloc(sizeFft, sizeof(sfloat)); - /* set/check modification parameters */ - // pSynthParams->modParams.maxFreq = pSmsHeader->iMaxFreq; + /* approximation envelope */ + pSynthParams->approxEnvelope = (sfloat *)calloc(pSynthParams->nStochasticCoeff, sizeof(sfloat)); + if(pSynthParams->approxEnvelope == NULL) + { + sms_error("Could not allocate memory for spectral approximation envelope"); + return -1; + } return SMS_OK; } -int sms_changeSynthHop( SMS_SynthParams *pSynthParams, int sizeHop) +int sms_changeSynthHop(SMS_SynthParams *pSynthParams, int sizeHop) { int sizeFft = sizeHop * 2; @@ -417,7 +553,7 @@ int sms_changeSynthHop( SMS_SynthParams *pSynthParams, int sizeHop) sms_getWindow( sizeFft, pSynthParams->pFStocWindow, SMS_WIN_HANNING ); pSynthParams->pFDetWindow = (sfloat *) realloc(pSynthParams->pFDetWindow, sizeFft * sizeof(sfloat)); - sms_getWindow( sizeFft, pSynthParams->pFDetWindow, SMS_WIN_IFFT ); + sms_getWindow(sizeFft, pSynthParams->pFDetWindow, SMS_WIN_IFFT); pSynthParams->sizeHop = sizeHop; @@ -431,24 +567,44 @@ int sms_changeSynthHop( SMS_SynthParams *pSynthParams, int sizeHop) * * \param pAnalParams pointer to analysis data structure */ -void sms_freeAnalysis( SMS_AnalParams *pAnalParams ) +void sms_freeAnalysis(SMS_AnalParams *pAnalParams) { - int i; - for (i = 0; i < pAnalParams->iMaxDelayFrames; i++) + if(pAnalParams->pFrames) { - free((pAnalParams->pFrames[i]).pSpectralPeaks); - free((pAnalParams->pFrames[i].deterministic).pFSinFreq); - free((pAnalParams->pFrames[i].deterministic).pFSinAmp); - free((pAnalParams->pFrames[i].deterministic).pFSinPha); + int i; + for(i = 0; i < pAnalParams->iMaxDelayFrames; i++) + { + if((pAnalParams->pFrames[i]).pSpectralPeaks) + free((pAnalParams->pFrames[i]).pSpectralPeaks); + if((pAnalParams->pFrames[i].deterministic).pFSinFreq) + free((pAnalParams->pFrames[i].deterministic).pFSinFreq); + if((pAnalParams->pFrames[i].deterministic).pFSinAmp) + free((pAnalParams->pFrames[i].deterministic).pFSinAmp); + if((pAnalParams->pFrames[i].deterministic).pFSinPha) + free((pAnalParams->pFrames[i].deterministic).pFSinPha); + } + free(pAnalParams->pFrames); } sms_freeFrame(&pAnalParams->prevFrame); - // free(pAnalParams->soundBuffer.pFBuffer); - free(pAnalParams->synthBuffer.pFBuffer); - free(pAnalParams->pFrames); - free(pAnalParams->ppFrames); - // free(pAnalParams->pFSpectrumWindow); - + if(pAnalParams->soundBuffer.pFBuffer) + free(pAnalParams->soundBuffer.pFBuffer); + if((pAnalParams->synthBuffer).pFBuffer) + free((pAnalParams->synthBuffer).pFBuffer); + if(pAnalParams->ppFrames) + free(pAnalParams->ppFrames); + if(pAnalParams->residual) + free(pAnalParams->residual); + if(pAnalParams->residualWindow) + free(pAnalParams->residualWindow); + if(pAnalParams->guideStates) + free(pAnalParams->guideStates); + if(pAnalParams->guides) + free(pAnalParams->guides); + if(pAnalParams->stocMagSpectrum) + free(pAnalParams->stocMagSpectrum); + if(pAnalParams->approxEnvelope) + free(pAnalParams->approxEnvelope); } /*! \brief free analysis data @@ -460,16 +616,24 @@ void sms_freeAnalysis( SMS_AnalParams *pAnalParams ) * already? as it is, it crashes if this is called without one * \param pSynthParams pointer to synthesis data structure */ -void sms_freeSynth( SMS_SynthParams *pSynthParams ) +void sms_freeSynth(SMS_SynthParams *pSynthParams) { - free(pSynthParams->pFStocWindow); - free(pSynthParams->pFDetWindow); - free (pSynthParams->pSynthBuff); - free (pSynthParams->pSpectra); - free (pSynthParams->pMagBuff); - free (pSynthParams->pPhaseBuff); - sms_freeFrame(&pSynthParams->prevFrame); + if(pSynthParams->pFStocWindow) + free(pSynthParams->pFStocWindow); + if(pSynthParams->pFDetWindow) + free(pSynthParams->pFDetWindow); + if(pSynthParams->pSynthBuff) + free(pSynthParams->pSynthBuff); + if(pSynthParams->pSpectra) + free(pSynthParams->pSpectra); + if(pSynthParams->pMagBuff) + free(pSynthParams->pMagBuff); + if(pSynthParams->pPhaseBuff) + free(pSynthParams->pPhaseBuff); + if(pSynthParams->approxEnvelope) + free(pSynthParams->approxEnvelope); + sms_freeFrame(&pSynthParams->prevFrame); } /*! \brief set window size for next frame @@ -481,23 +645,23 @@ void sms_freeSynth( SMS_SynthParams *pSynthParams ) * \param pAnalParams analysis parameters * \return the size of the next window in samples */ -int sms_sizeNextWindow (int iCurrentFrame, SMS_AnalParams *pAnalParams) +int sms_sizeNextWindow(int iCurrentFrame, SMS_AnalParams *pAnalParams) { sfloat fFund = pAnalParams->ppFrames[iCurrentFrame]->fFundamental; sfloat fPrevFund = pAnalParams->ppFrames[iCurrentFrame-1]->fFundamental; int sizeWindow; /* if the previous fundamental was stable use it to set the window size */ - if (fPrevFund > 0 && fabs(fPrevFund - fFund) / fFund <= .2) - sizeWindow = (int) ((pAnalParams->iSamplingRate / fFund) * - pAnalParams->fSizeWindow * .5) * 2 + 1; + if(fPrevFund > 0 && fabs(fPrevFund - fFund) / fFund <= .2) + sizeWindow = (int)((pAnalParams->iSamplingRate / fFund) * + pAnalParams->fSizeWindow * .5) * 2 + 1; /* otherwise use the default size window */ else sizeWindow = pAnalParams->iDefaultSizeWindow; - if (sizeWindow > SMS_MAX_WINDOW) + if(sizeWindow > SMS_MAX_WINDOW) { - fprintf (stderr, "sms_sizeNextWindow error: sizeWindow (%d) too big, set to %d\n", sizeWindow, + fprintf(stderr, "sms_sizeNextWindow error: sizeWindow (%d) too big, set to %d\n", sizeWindow, SMS_MAX_WINDOW); sizeWindow = SMS_MAX_WINDOW; } @@ -519,22 +683,22 @@ int sms_sizeNextWindow (int iCurrentFrame, SMS_AnalParams *pAnalParams) int sms_initFrame(int iCurrentFrame, SMS_AnalParams *pAnalParams, int sizeWindow) { /* clear deterministic data */ - memset ((sfloat *) pAnalParams->ppFrames[iCurrentFrame]->deterministic.pFSinFreq, 0, - sizeof(sfloat) * pAnalParams->nGuides); - memset ((sfloat *) pAnalParams->ppFrames[iCurrentFrame]->deterministic.pFSinAmp, 0, - sizeof(sfloat) * pAnalParams->nGuides); - memset ((sfloat *) pAnalParams->ppFrames[iCurrentFrame]->deterministic.pFSinPha, 0, - sizeof(sfloat) * pAnalParams->nGuides); + memset((sfloat *) pAnalParams->ppFrames[iCurrentFrame]->deterministic.pFSinFreq, 0, + sizeof(sfloat) * pAnalParams->nGuides); + memset((sfloat *) pAnalParams->ppFrames[iCurrentFrame]->deterministic.pFSinAmp, 0, + sizeof(sfloat) * pAnalParams->nGuides); + memset((sfloat *) pAnalParams->ppFrames[iCurrentFrame]->deterministic.pFSinPha, 0, + sizeof(sfloat) * pAnalParams->nGuides); /* clear peaks */ - memset ((void *) pAnalParams->ppFrames[iCurrentFrame]->pSpectralPeaks, 0, - sizeof (SMS_Peak) * pAnalParams->maxPeaks); + memset((void *) pAnalParams->ppFrames[iCurrentFrame]->pSpectralPeaks, 0, + sizeof (SMS_Peak) * pAnalParams->maxPeaks); pAnalParams->ppFrames[iCurrentFrame]->nPeaks = 0; pAnalParams->ppFrames[iCurrentFrame]->fFundamental = 0; pAnalParams->ppFrames[iCurrentFrame]->iFrameNum = - pAnalParams->ppFrames[iCurrentFrame - 1]->iFrameNum + 1; + pAnalParams->ppFrames[iCurrentFrame - 1]->iFrameNum + 1; pAnalParams->ppFrames[iCurrentFrame]->iFrameSize = sizeWindow; /* if first frame set center of data around 0 */ @@ -548,7 +712,7 @@ int sms_initFrame(int iCurrentFrame, SMS_AnalParams *pAnalParams, int sizeWindow /* check for end of sound */ if ((pAnalParams->ppFrames[iCurrentFrame]->iFrameSample + (sizeWindow+1)/2) >= pAnalParams->iSizeSound - && pAnalParams->iSizeSound > 0) + && pAnalParams->iSizeSound > 0) { pAnalParams->ppFrames[iCurrentFrame]->iFrameNum = -1; pAnalParams->ppFrames[iCurrentFrame]->iFrameSize = 0; @@ -574,11 +738,11 @@ sfloat sms_fundDeviation(SMS_AnalParams *pAnalParams, int iCurrentFrame) int i; /* get the sum of the past few fundamentals */ - for (i = 0; i < pAnalParams->minGoodFrames; i++) + for(i = 0; i < pAnalParams->minGoodFrames; i++) { fFund = pAnalParams->ppFrames[iCurrentFrame-i]->fFundamental; if(fFund <= 0) - return(-1); + return -1; else fSum += fFund; } @@ -587,11 +751,11 @@ sfloat sms_fundDeviation(SMS_AnalParams *pAnalParams, int iCurrentFrame) fAverage = fSum / pAnalParams->minGoodFrames; /* get the deviation from the average */ - for (i = 0; i < pAnalParams->minGoodFrames; i++) + for(i = 0; i < pAnalParams->minGoodFrames; i++) fDeviation += fabs(pAnalParams->ppFrames[iCurrentFrame-i]->fFundamental - fAverage); /* return the deviation from the average */ - return (fDeviation / (pAnalParams->minGoodFrames * fAverage)); + return fDeviation / (pAnalParams->minGoodFrames * fAverage); } @@ -600,14 +764,14 @@ sfloat sms_fundDeviation(SMS_AnalParams *pAnalParams, int iCurrentFrame) * \param pAnalParams pointer to analysis params * \return error value \see SMS_ERRORS */ -int sms_createDebugFile (SMS_AnalParams *pAnalParams) +int sms_createDebugFile(SMS_AnalParams *pAnalParams) { - if ((pDebug = fopen(pChDebugFile, "w+")) == NULL) + if((pDebug = fopen(pChDebugFile, "w+")) == NULL) { fprintf(stderr, "Cannot open debugfile: %s\n", pChDebugFile); - return(SMS_WRERR); + return SMS_WRERR; } - else return(SMS_OK); + return SMS_OK; } /*! \brief function to write to the debug file @@ -621,16 +785,15 @@ int sms_createDebugFile (SMS_AnalParams *pAnalParams) * \param pFBuffer3 pointer to array 3 * \param sizeBuffer the size of the buffers */ -void sms_writeDebugData (sfloat *pFBuffer1, sfloat *pFBuffer2, - sfloat *pFBuffer3, int sizeBuffer) +void sms_writeDebugData(sfloat *pFBuffer1, sfloat *pFBuffer2, + sfloat *pFBuffer3, int sizeBuffer) { int i; static int counter = 0; - for (i = 0; i < sizeBuffer; i++) - fprintf (pDebug, "%d %d %d %d\n", counter++, (int)pFBuffer1[i], - (int)pFBuffer2[i], (int)pFBuffer3[i]); - + for(i = 0; i < sizeBuffer; i++) + fprintf(pDebug, "%d %d %d %d\n", counter++, (int)pFBuffer1[i], + (int)pFBuffer2[i], (int)pFBuffer3[i]); } /*! \brief function to write the residual sound file to disk @@ -639,7 +802,7 @@ void sms_writeDebugData (sfloat *pFBuffer1, sfloat *pFBuffer2, */ void sms_writeDebugFile () { - fclose (pDebug); + fclose(pDebug); } /*! \brief convert from magnitude to decibel @@ -647,7 +810,7 @@ void sms_writeDebugFile () * \param x magnitude (0:1) * \return decibel (0: -100) */ -sfloat sms_magToDB( sfloat x) +sfloat sms_magToDB(sfloat x) { if(x < mag_thresh) return 0.0; @@ -662,7 +825,7 @@ sfloat sms_magToDB( sfloat x) * \param x decibel (0-100) * \return magnitude (0-1) */ -sfloat sms_dBToMag( sfloat x) +sfloat sms_dBToMag(sfloat x) { if(x < 0.00001) return 0.0; @@ -680,10 +843,10 @@ sfloat sms_dBToMag( sfloat x) * \param sizeArray size of array * \param pArray pointer to array */ -void sms_arrayMagToDB( int sizeArray, sfloat *pArray) +void sms_arrayMagToDB(int sizeArray, sfloat *pArray) { int i; - for( i = 0; i < sizeArray; i++) + for(i = 0; i < sizeArray; i++) pArray[i] = sms_magToDB(pArray[i]); } @@ -695,10 +858,10 @@ void sms_arrayMagToDB( int sizeArray, sfloat *pArray) * \param sizeArray size of array * \param pArray pointer to array */ -void sms_arrayDBToMag( int sizeArray, sfloat *pArray) +void sms_arrayDBToMag(int sizeArray, sfloat *pArray) { int i; - for( i = 0; i < sizeArray; i++) + for(i = 0; i < sizeArray; i++) pArray[i] = sms_dBToMag(pArray[i]); } /*! \brief set the linear magnitude threshold @@ -708,7 +871,7 @@ void sms_arrayDBToMag( int sizeArray, sfloat *pArray) * * \param x threshold value */ -void sms_setMagThresh( sfloat x) +void sms_setMagThresh(sfloat x) { /* limit threshold to -100db */ if(x < 0.00001) @@ -722,7 +885,8 @@ void sms_setMagThresh( sfloat x) * * \param pErrorMessage pointer to error message string */ -void sms_error(char *pErrorMessage) { +void sms_error(char *pErrorMessage) +{ strncpy(error_message, pErrorMessage, 256); error_status = -1; } @@ -733,7 +897,7 @@ void sms_error(char *pErrorMessage) { */ int sms_errorCheck() { - return(error_status); + return error_status; } /*! \brief get a string containing information about the last error @@ -747,7 +911,7 @@ char* sms_errorString() error_status = 0; return error_message; } - else return NULL; + return NULL; } /*! \brief random number genorator @@ -757,9 +921,9 @@ char* sms_errorString() sfloat sms_random() { #ifdef MERSENNE_TWISTER - return(genrand_real1()); + return genrand_real1(); #else - return((sfloat)(random() * 2 * INV_HALF_MAX)); + return (sfloat)(random() * 2 * INV_HALF_MAX); #endif } @@ -771,17 +935,17 @@ sfloat sms_rms(int sizeArray, sfloat *pArray) { int i; sfloat mean_squared = 0.; - for( i = 0; i < sizeArray; i++) + for(i = 0; i < sizeArray; i++) mean_squared += pArray[i] * pArray[i]; - return(sqrtf(mean_squared / sizeArray)); + return sqrtf(mean_squared / sizeArray); } /*! \brief make sure a number is a power of 2 * * \return a power of two integer >= input value */ -int sms_power2( int n) +int sms_power2(int n) { int p = -1; int N = n; @@ -793,12 +957,12 @@ int sms_power2( int n) if(1<

#include -#define SMS_VERSION 1.1 /*!< \brief version control number */ +#define SMS_VERSION 1.15 /*!< \brief version control number */ -#define SMS_MAX_NPEAKS 400 /*!< \brief maximum number of peaks */ +#define SMS_MAX_NPEAKS 400 /*!< \brief maximum number of peaks */ +#define SMS_MAX_FRAME_SIZE 10000 /* maximum size of input frame in samples */ +#define SMS_MAX_SPEC 8192 /*! \brief maximum size for magnitude spectrum */ #define sfloat double -/*#define sfloat float*/ /*! \struct SMS_Header * \brief structure for the header of an SMS file @@ -61,24 +62,18 @@ typedef struct { int iSmsMagic; /*!< identification constant */ int iHeadBSize; /*!< size in bytes of header */ - int nFrames; /*!< number of data frames */ - int iFrameBSize; /*!< size in bytes of each data frame */ + int nFrames; /*!< number of data frames */ + int iFrameBSize; /*!< size in bytes of each data frame */ int iSamplingRate; /*!< samplerate of analysis signal (necessary to recreate residual spectrum */ int iFormat; /*!< type of data format \see SMS_Format */ - int nTracks; /*!< number of sinusoidal tracks per frame */ + int nTracks; /*!< number of sinusoidal tracks per frame */ int iFrameRate; /*!< rate in Hz of data frames */ int iStochasticType; /*!< type stochastic representation */ int nStochasticCoeff; /*!< number of stochastic coefficients per frame */ - int iEnvType; /*!< type of envelope representation */ - int nEnvCoeff; /*!< number of cepstral coefficents per frame */ - int iMaxFreq; /*!< maximum frequency of peaks (also corresponds to the last bin of the specEnv */ - /* sfloat fAmplitude; /\*!< average amplitude of represented sound. *\/ */ - /* sfloat fFrequency; /\*!< average fundamental frequency *\/ */ - /* int iBegSteadyState; /\*!< record number of begining of steady state. *\/ */ - /* int iEndSteadyState; /\*!< record number of end of steady state. *\/ */ - sfloat fResidualPerc; /*!< percentage of the residual to original */ - int nTextCharacters; /*!< number of text characters */ - char *pChTextCharacters; /*!< Text string relating to the sound */ + int iEnvType; /*!< type of envelope representation */ + int nEnvCoeff; /*!< number of cepstral coefficents per frame */ + int iMaxFreq; /*!< maximum frequency of peaks (also corresponds to the last bin of the specEnv */ + sfloat fResidualPerc; /*!< percentage of the residual to original */ } SMS_Header; /*! \struct SMS_Data @@ -95,17 +90,17 @@ typedef struct */ typedef struct { - sfloat *pSmsData; /*!< pointer to all SMS data */ - int sizeData; /*!< size of all the data */ - sfloat *pFSinFreq; /*!< frequency of sinusoids */ - sfloat *pFSinAmp; /*!< magnitude of sinusoids (stored in dB) */ - sfloat *pFSinPha; /*!< phase of sinusoids */ - int nTracks; /*!< number of sinusoidal tracks in frame */ - sfloat *pFStocGain; /*!< gain of stochastic component */ - int nCoeff; /*!< number of filter coefficients */ - sfloat *pFStocCoeff; /*!< filter coefficients for stochastic component */ - sfloat *pResPhase; /*!< residual phase spectrum */ - int nEnvCoeff; /*!< number of spectral envelope coefficients */ + sfloat *pSmsData; /*!< pointer to all SMS data */ + int sizeData; /*!< size of all the data */ + sfloat *pFSinFreq; /*!< frequency of sinusoids */ + sfloat *pFSinAmp; /*!< magnitude of sinusoids (stored in dB) */ + sfloat *pFSinPha; /*!< phase of sinusoids */ + int nTracks; /*!< number of sinusoidal tracks in frame */ + sfloat *pFStocGain; /*!< gain of stochastic component */ + int nCoeff; /*!< number of filter coefficients */ + sfloat *pFStocCoeff; /*!< filter coefficients for stochastic component */ + sfloat *pResPhase; /*!< residual phase spectrum */ + int nEnvCoeff; /*!< number of spectral envelope coefficients */ sfloat *pSpecEnv; } SMS_Data; @@ -120,22 +115,20 @@ typedef struct */ typedef struct { - sfloat *pFBuffer; /*!< buffer for sound data*/ - int sizeBuffer; /*!< size of buffer */ - int iMarker; /*!< sample marker relating to sound source */ - int iFirstGood; /*!< first sample in buffer that is a good one */ + sfloat *pFBuffer; /*!< buffer for sound data*/ + int sizeBuffer; /*!< size of buffer */ + int iMarker; /*!< sample marker relating to sound source */ + int iFirstGood; /*!< first sample in buffer that is a good one */ } SMS_SndBuffer; /*! \struct SMS_Peak * \brief structure for sinusodial peak */ - -/* information attached to a spectral peak */ typedef struct { - sfloat fFreq; /*!< frequency of peak */ - sfloat fMag; /*!< magnitude of peak */ - sfloat fPhase; /*!< phase of peak */ + sfloat fFreq; /*!< frequency of peak */ + sfloat fMag; /*!< magnitude of peak */ + sfloat fPhase; /*!< phase of peak */ } SMS_Peak; /* a collection of spectral peaks */ @@ -157,48 +150,42 @@ typedef struct int iFrameSample; /*!< sample number of the middle of the frame */ int iFrameSize; /*!< number of samples used in the frame */ int iFrameNum; /*!< frame number */ - SMS_Peak *pSpectralPeaks; /*!< spectral peaks found in frame */ + SMS_Peak *pSpectralPeaks; /*!< spectral peaks found in frame */ int nPeaks; /*!< number of peaks found */ - sfloat fFundamental; /*!< fundamental frequency in frame */ + sfloat fFundamental; /*!< fundamental frequency in frame */ SMS_Data deterministic; /*!< deterministic data */ - int iStatus; /*!< status of frame enumerated by SMS_FRAME_STATUS - \see SMS_FRAME_STATUS */ + int iStatus; /*!< status of frame enumerated by SMS_FRAME_STATUS \see SMS_FRAME_STATUS */ } SMS_AnalFrame; -/*! \struct SMS_PeakParams - * \brief structure with useful information for peak detection and continuation - * - */ -//typedef struct -//{ -// sfloat fLowestFreq; [>!< the first bin to look for a peak <] -// sfloat fHighestFreq; [>!< the last bin to look for a peak <] -// sfloat fMinPeakMag; [>!< mininum magnitude to consider as a peak <] -// int iSamplingRate; [>!< sampling rate of analysis signal <] -// int iMaxPeaks; [>!< maximum number of spectral peaks to look for <] -// int nPeaksFound; [>!< the number of peaks found in each analysis <] -// sfloat fHighestFundamental;[>!< highest fundamental frequency in Hz <] -// int iRefHarmonic; [>!< reference harmonic to use in the fundamental detection <] -// sfloat fMinRefHarmMag; [>!< minimum magnitude in dB for reference peak <] -// sfloat fRefHarmMagDiffFromMax; [>!< maximum magnitude difference from reference peak to highest peak <] -// int iSoundType; [>!< type of sound to be analyzed \see SMS_SOUND_TYPE <] -//} SMS_PeakParams; - /*! \struct SMS_SEnvParams; * \brief structure information and data for spectral enveloping * */ typedef struct { - int iType; /*!< envelope type \see SMS_SpecEnvType */ - int iOrder; /*!< ceptrum order */ - int iMaxFreq; /*!< maximum frequency covered by the envelope */ + int iType; /*!< envelope type \see SMS_SpecEnvType */ + int iOrder; /*!< ceptrum order */ + int iMaxFreq; /*!< maximum frequency covered by the envelope */ sfloat fLambda; /*!< regularization factor */ - int nCoeff; /*!< number of coefficients (bins) in the envelope */ - int iAnchor; /*!< whether to make anchor points at DC / Nyquist or not */ + int nCoeff; /*!< number of coefficients (bins) in the envelope */ + int iAnchor; /*!< whether to make anchor points at DC / Nyquist or not */ } SMS_SEnvParams; - +/*! \struct SMS_Guide + * \brief information attached to a guide + * + * This structure is used to organize the detected peaks into time-varying + * trajectories, or sinusoidal tracks. As the analysis progresses, previous + * guides may be updated according to new information in the peak continuation + * of new frames (two-way mismatch). + */ +typedef struct +{ + sfloat fFreq; /*!< frequency of guide */ + sfloat fMag; /*!< magnitude of guide */ + int iStatus; /*!< status of guide: DEAD, SLEEPING, ACTIVE */ + int iPeakChosen; /*!< peak number chosen by the guide */ +} SMS_Guide; /*! \struct SMS_AnalParams * \brief structure with useful information for analysis functions @@ -216,56 +203,112 @@ typedef struct */ typedef struct { - int iDebugMode; /*!< debug codes enumerated by SMS_DBG \see SMS_DBG */ - int iFormat; /*!< analysis format code defined by SMS_Format \see SMS_Format */ - int iSoundType; /*!< type of sound to be analyzed \see SMS_SOUND_TYPE */ - int iStochasticType; /*!< type of stochastic model defined by SMS_StocSynthType \see SMS_StocSynthType */ - int iFrameRate; /*!< rate in Hz of data frames */ - int nStochasticCoeff; /*!< number of stochastic coefficients per frame */ - sfloat fLowestFundamental; /*!< lowest fundamental frequency in Hz */ - sfloat fHighestFundamental;/*!< highest fundamental frequency in Hz */ - sfloat fDefaultFundamental;/*!< default fundamental in Hz */ - sfloat fPeakContToGuide; /*!< contribution of previous peak to current guide (between 0 and 1) */ - sfloat fFundContToGuide; /*!< contribution of current fundamental to current guide (between 0 and 1) */ - sfloat fFreqDeviation; /*!< maximum deviation from peak to peak */ - int iSamplingRate; /*! sampling rate of sound to be analyzed */ - int iDefaultSizeWindow; /*!< default size of analysis window in samples */ - int windowSize; /*!< the current window size */ - int sizeHop; /*!< hop size of analysis window in samples */ - sfloat fSizeWindow; /*!< size of analysis window in number of periods */ - int nTracks; /*!< number of sinusoidal tracks in frame */ - int maxPeaks; /*!< maximum number of peaks in a frame */ - int nGuides; /*!< number of guides used for peak detection and continuation \see SMS_Guide */ - int iCleanTracks; /*!< whether or not to clean sinusoidal tracks */ - //int iEnvelope; /*!< whether or not to compute spectral envelope */ - sfloat fMinRefHarmMag; /*!< minimum magnitude in dB for reference peak */ - sfloat fRefHarmMagDiffFromMax; /*!< maximum magnitude difference from reference peak to highest peak */ - int iRefHarmonic; /*!< reference harmonic to use in the fundamental detection */ - int iMinTrackLength; /*!< minimum length in samples of a given track */ - int iMaxSleepingTime; /*!< maximum sleeping time for a track */ - sfloat fLowestFreq; /*!< lowest frequency to be searched */ - sfloat fHighestFreq; /*!< highest frequency to be searched */ - sfloat fMinPeakMag; /*!< minimum magnitude in dB for a good peak */ - int iAnalysisDirection; /*!< analysis direction, direct or reverse */ - int iSizeSound; /*!< total size of sound to be analyzed in samples */ - int nFrames; /*!< total number of frames that will be analyzed */ - int iWindowType; /*!< type of FFT analysis window \see SMS_WINDOWS */ - int iMaxDelayFrames; /*!< maximum number of frames to delay before peak continuation */ - int minGoodFrames; /*!< minimum number of stable frames for backward search */ - sfloat maxDeviation; /*!< maximum deviation allowed */ - int analDelay; /*! number of frames in the past to be looked in possible re-analyze */ - sfloat fResidualAccumPerc; /*!< accumalitive residual percentage */ - int sizeNextRead; /*!< size of samples to read from sound file next analysis */ + int iDebugMode; /*!< debug codes enumerated by SMS_DBG \see SMS_DBG */ + int iFormat; /*!< analysis format code defined by SMS_Format \see SMS_Format */ + int iSoundType; /*!< type of sound to be analyzed \see SMS_SOUND_TYPE */ + int iStochasticType; /*!< type of stochastic model defined by SMS_StocSynthType \see SMS_StocSynthType */ + int iFrameRate; /*!< rate in Hz of data frames */ + int nStochasticCoeff; /*!< number of stochastic coefficients per frame */ + sfloat fLowestFundamental; /*!< lowest fundamental frequency in Hz */ + sfloat fHighestFundamental; /*!< highest fundamental frequency in Hz */ + sfloat fDefaultFundamental; /*!< default fundamental in Hz */ + sfloat fPeakContToGuide; /*!< contribution of previous peak to current guide (between 0 and 1) */ + sfloat fFundContToGuide; /*!< contribution of current fundamental to current guide (between 0 and 1) */ + sfloat fFreqDeviation; /*!< maximum deviation from peak to peak */ + int iSamplingRate; /*! sampling rate of sound to be analyzed */ + int iDefaultSizeWindow; /*!< default size of analysis window in samples */ + int windowSize; /*!< the current window size */ + int sizeHop; /*!< hop size of analysis window in samples */ + sfloat fSizeWindow; /*!< size of analysis window in number of periods */ + int nTracks; /*!< number of sinusoidal tracks in frame */ + int maxPeaks; /*!< maximum number of peaks in a frame */ + int nGuides; /*!< number of guides used for peak detection and continuation \see SMS_Guide */ + int iCleanTracks; /*!< whether or not to clean sinusoidal tracks */ + sfloat fMinRefHarmMag; /*!< minimum magnitude in dB for reference peak */ + sfloat fRefHarmMagDiffFromMax; /*!< maximum magnitude difference from reference peak to highest peak */ + int iRefHarmonic; /*!< reference harmonic to use in the fundamental detection */ + int iMinTrackLength; /*!< minimum length in samples of a given track */ + int iMaxSleepingTime; /*!< maximum sleeping time for a track */ + sfloat fLowestFreq; /*!< lowest frequency to be searched */ + sfloat fHighestFreq; /*!< highest frequency to be searched */ + sfloat fMinPeakMag; /*!< minimum magnitude in dB for a good peak */ + int iAnalysisDirection; /*!< analysis direction, direct or reverse */ + int iSizeSound; /*!< total size of sound to be analyzed in samples */ + int nFrames; /*!< total number of frames that will be analyzed */ + int iWindowType; /*!< type of FFT analysis window \see SMS_WINDOWS */ + int iMaxDelayFrames; /*!< maximum number of frames to delay before peak continuation */ + int minGoodFrames; /*!< minimum number of stable frames for backward search */ + sfloat maxDeviation; /*!< maximum deviation allowed */ + int analDelay; /*! number of frames in the past to be looked in possible re-analyze */ + sfloat fResidualAccumPerc; /*!< accumalitive residual percentage */ + int sizeNextRead; /*!< size of samples to read from sound file next analysis */ sfloat preEmphasisLastValue; - int resetGuides; - int resetGuideStates; - //SMS_PeakParams peakParams; [>!< structure with parameters for spectral peaks <] - SMS_Data prevFrame; /*!< the previous analysis frame */ - SMS_SEnvParams specEnvParams; /*!< all data for spectral enveloping */ - SMS_SndBuffer soundBuffer; /*!< signal to be analyzed */ - SMS_SndBuffer synthBuffer; /*!< resynthesized signal used to create the residual */ - SMS_AnalFrame *pFrames; /*!< an array of frames that have already been analyzed */ - SMS_AnalFrame **ppFrames; /*!< pointers to the frames analyzed (it is circular-shifted once the array is full */ + SMS_Data prevFrame; /*!< the previous analysis frame */ + SMS_SEnvParams specEnvParams; /*!< all data for spectral enveloping */ + SMS_SndBuffer soundBuffer; /*!< signal to be analyzed */ + SMS_SndBuffer synthBuffer; /*!< resynthesized signal used to create the residual */ + SMS_AnalFrame *pFrames; /*!< an array of frames that have already been analyzed */ + sfloat magSpectrum[SMS_MAX_SPEC]; + sfloat phaseSpectrum[SMS_MAX_SPEC]; + sfloat spectrumWindow[SMS_MAX_SPEC]; + sfloat fftBuffer[SMS_MAX_SPEC * 2]; + int sizeResidual; + sfloat *residual; + sfloat *residualWindow; + int *guideStates; + SMS_Guide* guides; + sfloat inputBuffer[SMS_MAX_FRAME_SIZE]; + int sizeStocMagSpectrum; + sfloat *stocMagSpectrum; + sfloat *approxEnvelope; /*!< spectral approximation envelope */ + SMS_AnalFrame **ppFrames; /*!< pointers to the frames analyzed (it is circular-shifted once the array is full */ + + //int iDebugMode; [>!< debug codes enumerated by SMS_DBG \see SMS_DBG <] + //int iFormat; [>!< analysis format code defined by SMS_Format \see SMS_Format <] + //int iSoundType; [>!< type of sound to be analyzed \see SMS_SOUND_TYPE <] + //int iStochasticType; [>!< type of stochastic model defined by SMS_StocSynthType \see SMS_StocSynthType <] + //int iFrameRate; [>!< rate in Hz of data frames <] + //int nStochasticCoeff; [>!< number of stochastic coefficients per frame <] + //sfloat fLowestFundamental; [>!< lowest fundamental frequency in Hz <] + //sfloat fHighestFundamental;[>!< highest fundamental frequency in Hz <] + //sfloat fDefaultFundamental;[>!< default fundamental in Hz <] + //sfloat fPeakContToGuide; [>!< contribution of previous peak to current guide (between 0 and 1) <] + //sfloat fFundContToGuide; [>!< contribution of current fundamental to current guide (between 0 and 1) <] + //sfloat fFreqDeviation; [>!< maximum deviation from peak to peak <] + //int iSamplingRate; [>! sampling rate of sound to be analyzed <] + //int iDefaultSizeWindow; [>!< default size of analysis window in samples <] + //int windowSize; [>!< the current window size <] + //int sizeHop; [>!< hop size of analysis window in samples <] + //sfloat fSizeWindow; [>!< size of analysis window in number of periods <] + //int nTracks; [>!< number of sinusoidal tracks in frame <] + //int maxPeaks; [>!< maximum number of peaks in a frame <] + //int nGuides; [>!< number of guides used for peak detection and continuation \see SMS_Guide <] + //int iCleanTracks; [>!< whether or not to clean sinusoidal tracks <] + //sfloat fMinRefHarmMag; [>!< minimum magnitude in dB for reference peak <] + //sfloat fRefHarmMagDiffFromMax; [>!< maximum magnitude difference from reference peak to highest peak <] + //int iRefHarmonic; [>!< reference harmonic to use in the fundamental detection <] + //int iMinTrackLength; [>!< minimum length in samples of a given track <] + //int iMaxSleepingTime; [>!< maximum sleeping time for a track <] + //sfloat fLowestFreq; [>!< lowest frequency to be searched <] + //sfloat fHighestFreq; [>!< highest frequency to be searched <] + //sfloat fMinPeakMag; [>!< minimum magnitude in dB for a good peak <] + //int iAnalysisDirection; [>!< analysis direction, direct or reverse <] + //int iSizeSound; [>!< total size of sound to be analyzed in samples <] + //int nFrames; [>!< total number of frames that will be analyzed <] + //int iWindowType; [>!< type of FFT analysis window \see SMS_WINDOWS <] + //int iMaxDelayFrames; [>!< maximum number of frames to delay before peak continuation <] + //int minGoodFrames; [>!< minimum number of stable frames for backward search <] + //sfloat maxDeviation; [>!< maximum deviation allowed <] + //int analDelay; [>! number of frames in the past to be looked in possible re-analyze <] + //sfloat fResidualAccumPerc; [>!< accumalitive residual percentage <] + //int sizeNextRead; [>!< size of samples to read from sound file next analysis <] + //sfloat preEmphasisLastValue; + //SMS_Data prevFrame; [>!< the previous analysis frame <] + //SMS_SEnvParams specEnvParams; [>!< all data for spectral enveloping <] + //SMS_SndBuffer soundBuffer; [>!< signal to be analyzed <] + //SMS_SndBuffer synthBuffer; [>!< resynthesized signal used to create the residual <] + //SMS_AnalFrame *pFrames; [>!< an array of frames that have already been analyzed <] + //SMS_AnalFrame **ppFrames; [>!< pointers to the frames analyzed (it is circular-shifted once the array is full <] } SMS_AnalParams; /*! \struct SMS_ModifyParams @@ -274,20 +317,20 @@ typedef struct */ typedef struct { - int ready; /*!< a flag to know if the struct has been initialized) */ - int maxFreq; /*!< maximum frequency component */ - int doResGain; /*!< whether or not to scale residual gain */ - sfloat resGain; /*!< residual scale factor */ - int doTranspose; /*!< whether or not to transpose */ - sfloat transpose; /*!< transposition factor */ - int doSinEnv; /*!< whether or not to apply a new spectral envelope to the sin component */ - sfloat sinEnvInterp; /*!< value between 0 (use frame's env) and 1 (use *env). Interpolates inbetween values*/ - int sizeSinEnv; /*!< size of the envelope pointed to by env */ - sfloat *sinEnv; /*!< sinusoidal spectral envelope */ - int doResEnv; /*!< whether or not to apply a new spectral envelope to the residual component */ - sfloat resEnvInterp; /*!< value between 0 (use frame's env) and 1 (use *env). Interpolates inbetween values*/ - int sizeResEnv; /*!< size of the envelope pointed to by resEnv */ - sfloat *resEnv; /*!< residual spectral envelope */ + int ready; /*!< a flag to know if the struct has been initialized) */ + int maxFreq; /*!< maximum frequency component */ + int doResGain; /*!< whether or not to scale residual gain */ + sfloat resGain; /*!< residual scale factor */ + int doTranspose; /*!< whether or not to transpose */ + sfloat transpose; /*!< transposition factor */ + int doSinEnv; /*!< whether or not to apply a new spectral envelope to the sin component */ + sfloat sinEnvInterp; /*!< value between 0 (use frame's env) and 1 (use *env). Interpolates inbetween values*/ + int sizeSinEnv; /*!< size of the envelope pointed to by env */ + sfloat *sinEnv; /*!< sinusoidal spectral envelope */ + int doResEnv; /*!< whether or not to apply a new spectral envelope to the residual component */ + sfloat resEnvInterp; /*!< value between 0 (use frame's env) and 1 (use *env). Interpolates inbetween values*/ + int sizeResEnv; /*!< size of the envelope pointed to by resEnv */ + sfloat *resEnv; /*!< residual spectral envelope */ } SMS_ModifyParams; /*! \struct SMS_SynthParams @@ -300,7 +343,8 @@ typedef struct */ typedef struct { - int iStochasticType; /*!< type of stochastic model defined by SMS_StocSynthType \see SMS_StocSynthType */ + int iStochasticType; /*!< type of stochastic model defined by SMS_StocSynthType + \see SMS_StocSynthType */ int iSynthesisType; /*!< type of synthesis to perform \see SMS_SynthType */ int iDetSynthType; /*!< method for synthesizing deterministic component \see SMS_DetSynthType */ int iOriginalSRate; /*!< samplerate of the sound model source (for stochastic synthesis approximation) */ @@ -309,7 +353,7 @@ typedef struct int origSizeHop; /*!< original number of samples used to create each analysis frame */ int nTracks; int nStochasticCoeff; - sfloat deemphasisLastValue; + sfloat deEmphasisLastValue; sfloat *pFDetWindow; /*!< array to hold the window used for deterministic synthesis \see SMS_WIN_IFFT */ sfloat *pFStocWindow; /*!< array to hold the window used for stochastic synthesis (Hanning) */ sfloat *pSynthBuff; /*!< an array for keeping samples during overlap-add (2x sizeHop) */ @@ -318,7 +362,29 @@ typedef struct sfloat *pSpectra; /*!< array for in-place FFT transform */ SMS_Data prevFrame; /*!< previous data frame, for interpolation between frames */ SMS_ModifyParams modParams; /*!< modification parameters */ + sfloat *approxEnvelope; /*!< spectral approximation envelope */ } SMS_SynthParams; +//typedef struct +//{ +// int iStochasticType; [>!< type of stochastic model defined by SMS_StocSynthType \see SMS_StocSynthType <] +// int iSynthesisType; [>!< type of synthesis to perform \see SMS_SynthType <] +// int iDetSynthType; [>!< method for synthesizing deterministic component \see SMS_DetSynthType <] +// int iOriginalSRate; [>!< samplerate of the sound model source (for stochastic synthesis approximation) <] +// int iSamplingRate; [>!< synthesis samplerate <] +// int sizeHop; [>!< number of samples to synthesis for each frame <] +// int origSizeHop; [>!< original number of samples used to create each analysis frame <] +// int nTracks; +// int nStochasticCoeff; +// sfloat deemphasisLastValue; +// sfloat *pFDetWindow; [>!< array to hold the window used for deterministic synthesis \see SMS_WIN_IFFT <] +// sfloat *pFStocWindow; [>!< array to hold the window used for stochastic synthesis (Hanning) <] +// sfloat *pSynthBuff; [>!< an array for keeping samples during overlap-add (2x sizeHop) <] +// sfloat *pMagBuff; [>!< an array for keeping magnitude spectrum for stochastic synthesis <] +// sfloat *pPhaseBuff; [>!< an array for keeping phase spectrum for stochastic synthesis <] +// sfloat *pSpectra; [>!< array for in-place FFT transform <] +// SMS_Data prevFrame; [>!< previous data frame, for interpolation between frames <] +// SMS_ModifyParams modParams; [>!< modification parameters <] +//} SMS_SynthParams; /*! \struct SMS_HarmCandidate * \brief structure to hold information about a harmonic candidate @@ -329,11 +395,11 @@ typedef struct */ typedef struct { - sfloat fFreq; /*!< frequency of harmonic */ - sfloat fMag; /*!< magnitude of harmonic */ - sfloat fMagPerc; /*!< percentage of magnitude */ - sfloat fFreqDev; /*!< deviation from perfect harmonic */ - sfloat fHarmRatio; /*!< percentage of harmonics found */ + sfloat fFreq; /*!< frequency of harmonic */ + sfloat fMag; /*!< magnitude of harmonic */ + sfloat fMagPerc; /*!< percentage of magnitude */ + sfloat fFreqDev; /*!< deviation from perfect harmonic */ + sfloat fHarmRatio; /*!< percentage of harmonics found */ } SMS_HarmCandidate; /*! \struct SMS_ContCandidate @@ -344,27 +410,11 @@ typedef struct */ typedef struct { - sfloat fFreqDev; /*!< frequency deviation from guide */ - sfloat fMagDev; /*!< magnitude deviation from guide */ - int iPeak; /*!< peak number (organized according to frequency)*/ + sfloat fFreqDev; /*!< frequency deviation from guide */ + sfloat fMagDev; /*!< magnitude deviation from guide */ + int iPeak; /*!< peak number (organized according to frequency)*/ } SMS_ContCandidate; -/*! \struct SMS_Guide - * \brief information attached to a guide - * - * This structure is used to organize the detected peaks into time-varying - * trajectories, or sinusoidal tracks. As the analysis progresses, previous - * guides may be updated according to new information in the peak continuation - * of new frames (two-way mismatch). - */ -typedef struct -{ - sfloat fFreq; /*!< frequency of guide */ - sfloat fMag; /*!< magnitude of guide */ - int iStatus; /*!< status of guide: DEAD, SLEEPING, ACTIVE */ - int iPeakChosen; /*!< peak number chosen by the guide */ -} SMS_Guide; - /*! \brief analysis format * * Is the signal is known to be harmonic, using format harmonic (with out without @@ -375,10 +425,10 @@ typedef struct */ enum SMS_Format { - SMS_FORMAT_H, /*!< 0, format harmonic */ - SMS_FORMAT_IH, /*!< 1, format inharmonic */ - SMS_FORMAT_HP, /*!< 2, format harmonic with phase */ - SMS_FORMAT_IHP /*!< 3, format inharmonic with phase */ + SMS_FORMAT_H, /*!< 0, format harmonic */ + SMS_FORMAT_IH, /*!< 1, format inharmonic */ + SMS_FORMAT_HP, /*!< 2, format harmonic with phase */ + SMS_FORMAT_IHP /*!< 3, format inharmonic with phase */ }; /*! \brief synthesis types @@ -390,9 +440,9 @@ enum SMS_Format */ enum SMS_SynthType { - SMS_STYPE_ALL, /*!< both components combined */ - SMS_STYPE_DET, /*!< deterministic component alone */ - SMS_STYPE_STOC /*!< stochastic component alone */ + SMS_STYPE_ALL, /*!< both components combined */ + SMS_STYPE_DET, /*!< deterministic component alone */ + SMS_STYPE_STOC /*!< stochastic component alone */ }; /*! \brief synthesis method for deterministic component @@ -406,8 +456,8 @@ enum SMS_SynthType */ enum SMS_DetSynthType { - SMS_DET_IFFT, /*!< Inverse Fast Fourier Transform (IFFT) */ - SMS_DET_SIN /*!< Sinusoidal Table Lookup (SIN) */ + SMS_DET_IFFT, /*!< Inverse Fast Fourier Transform (IFFT) */ + SMS_DET_SIN /*!< Sinusoidal Table Lookup (SIN) */ }; /*! \brief synthesis method for stochastic component @@ -433,9 +483,9 @@ enum SMS_DetSynthType */ enum SMS_StocSynthType { - SMS_STOC_NONE, /*!< 0, no stochastistic component */ - SMS_STOC_APPROX, /*!< 1, Inverse FFT, magnitude approximation and generated phases */ - SMS_STOC_IFFT /*!< 2, inverse FFT, interpolated spectrum (not used) */ + SMS_STOC_NONE, /*!< 0, no stochastistic component */ + SMS_STOC_APPROX, /*!< 1, Inverse FFT, magnitude approximation and generated phases */ + SMS_STOC_IFFT /*!< 2, inverse FFT, interpolated spectrum (not used) */ }; /*! \brief synthesis method for deterministic component @@ -449,23 +499,22 @@ enum SMS_StocSynthType */ enum SMS_SpecEnvType { - SMS_ENV_NONE, /*!< none */ - SMS_ENV_CEP, /*!< cepstral coefficients */ - SMS_ENV_FBINS /*!< frequency bins */ + SMS_ENV_NONE, /*!< none */ + SMS_ENV_CEP, /*!< cepstral coefficients */ + SMS_ENV_FBINS /*!< frequency bins */ }; - /*! \brief Error codes returned by SMS file functions */ /* \todo remove me */ enum SMS_ERRORS { - SMS_OK, /*!< 0, no error*/ - SMS_NOPEN, /*!< 1, couldn't open file */ - SMS_NSMS , /*!< 2, not a SMS file */ - SMS_MALLOC, /*!< 3, couldn't allocate memory */ - SMS_RDERR, /*!< 4, read error */ - SMS_WRERR, /*!< 5, write error */ - SMS_SNDERR /*!< 7, sound IO error */ + SMS_OK, /*!< 0, no error*/ + SMS_NOPEN, /*!< 1, couldn't open file */ + SMS_NSMS , /*!< 2, not a SMS file */ + SMS_MALLOC, /*!< 3, couldn't allocate memory */ + SMS_RDERR, /*!< 4, read error */ + SMS_WRERR, /*!< 5, write error */ + SMS_SNDERR /*!< 6, sound IO error */ }; /*! \brief debug modes @@ -474,20 +523,19 @@ enum SMS_ERRORS */ enum SMS_DBG { - SMS_DBG_NONE, /*!< 0, no debugging */ - SMS_DBG_DET, /*!< 1, not yet implemented \todo make this show main information to look at for discovering the correct deterministic parameters*/ - SMS_DBG_PEAK_DET, /*!< 2, peak detection function */ - SMS_DBG_HARM_DET, /*!< 3, harmonic detection function */ - SMS_DBG_PEAK_CONT, /*!< 4, peak continuation function */ - SMS_DBG_CLEAN_TRAJ, /*!< 5, clean tracks function */ - SMS_DBG_SINE_SYNTH, /*!< 6, sine synthesis function */ - SMS_DBG_STOC_ANAL, /*!< 7, stochastic analysis function */ - SMS_DBG_STOC_SYNTH, /*!< 8, stochastic synthesis function */ - SMS_DBG_SMS_ANAL, /*!< 9, top level analysis function */ - SMS_DBG_ALL, /*!< 10, everything */ - SMS_DBG_RESIDUAL, /*!< 11, write residual to file */ - SMS_DBG_SYNC, /*!< 12, write original, synthesis and residual - to a text file */ + SMS_DBG_NONE, /*!< 0, no debugging */ + SMS_DBG_DET, /*!< 1, not yet implemented \todo make this show main information to look at for discovering the correct deterministic parameters*/ + SMS_DBG_PEAK_DET, /*!< 2, peak detection function */ + SMS_DBG_HARM_DET, /*!< 3, harmonic detection function */ + SMS_DBG_PEAK_CONT, /*!< 4, peak continuation function */ + SMS_DBG_CLEAN_TRAJ, /*!< 5, clean tracks function */ + SMS_DBG_SINE_SYNTH, /*!< 6, sine synthesis function */ + SMS_DBG_STOC_ANAL, /*!< 7, stochastic analysis function */ + SMS_DBG_STOC_SYNTH, /*!< 8, stochastic synthesis function */ + SMS_DBG_SMS_ANAL, /*!< 9, top level analysis function */ + SMS_DBG_ALL, /*!< 10, everything */ + SMS_DBG_RESIDUAL, /*!< 11, write residual to file */ + SMS_DBG_SYNC, /*!< 12, write original, synthesis and residual to a text file */ }; #define SMS_MAX_WINDOW 8190 /*!< \brief maximum size for analysis window */ @@ -498,8 +546,8 @@ enum SMS_DBG */ enum SMS_SOUND_TYPE { - SMS_SOUND_TYPE_MELODY, /*!< 0, sound composed of several notes */ - SMS_SOUND_TYPE_NOTE /*!< 1, sound composed of a single note */ + SMS_SOUND_TYPE_MELODY, /*!< 0, sound composed of several notes */ + SMS_SOUND_TYPE_NOTE /*!< 1, sound composed of a single note */ }; /* \brief direction of analysis @@ -510,22 +558,22 @@ enum SMS_SOUND_TYPE */ enum SMS_DIRECTION { - SMS_DIR_FWD, /*!< analysis from left to right */ - SMS_DIR_REV /*!< analysis from right to left */ + SMS_DIR_FWD, /*!< analysis from left to right */ + SMS_DIR_REV /*!< analysis from right to left */ }; /* \brief window selection */ enum SMS_WINDOWS { - SMS_WIN_HAMMING, /*!< 0: hamming */ - SMS_WIN_BH_62, /*!< 1: blackman-harris, 62dB cutoff */ - SMS_WIN_BH_70, /*!< 2: blackman-harris, 70dB cutoff */ - SMS_WIN_BH_74, /*!< 3: blackman-harris, 74dB cutoff */ - SMS_WIN_BH_92, /*!< 4: blackman-harris, 92dB cutoff */ - SMS_WIN_HANNING, /*!< 5: hanning */ - SMS_WIN_IFFT /*!< 6: window for deterministic synthesis based on the Inverse-FFT algorithm. - This is a combination of an inverse Blackman-Harris 92dB and a triangular window. */ + SMS_WIN_HAMMING, /*!< 0: hamming */ + SMS_WIN_BH_62, /*!< 1: blackman-harris, 62dB cutoff */ + SMS_WIN_BH_70, /*!< 2: blackman-harris, 70dB cutoff */ + SMS_WIN_BH_74, /*!< 3: blackman-harris, 74dB cutoff */ + SMS_WIN_BH_92, /*!< 4: blackman-harris, 92dB cutoff */ + SMS_WIN_HANNING, /*!< 5: hanning */ + SMS_WIN_IFFT /*!< 6: window for deterministic synthesis based on the Inverse-FFT algorithm. + This is a combination of an inverse Blackman-Harris 92dB and a triangular window. */ }; /*! @@ -546,7 +594,6 @@ enum SMS_FRAME_STATUS SMS_FRAME_END }; - #define SMS_MIN_SIZE_FRAME 128 /* size of synthesis frame */ /*! \defgroup math_macros Math Macros @@ -554,13 +601,13 @@ enum SMS_FRAME_STATUS * this library * \{ */ -#define PI 3.141592653589793238462643 /*!< pi */ +#define PI 3.141592653589793238462643 /*!< pi */ #define TWO_PI 6.28318530717958647692 /*!< pi * 2 */ -#define INV_TWO_PI (1 / TWO_PI) /*!< 1 / ( pi * 2) */ -#define PI_2 1.57079632679489661923 /*!< pi / 2 */ -#define LOG2 0.69314718055994529 /*!< natural logarithm of 2 */ -#define LOG10 2.3025850929940459 /*!< natural logarithm of 10 */ -#define EXP 2.7182818284590451 /*!< Eurler's number */ +#define INV_TWO_PI (1 / TWO_PI) /*!< 1 / ( pi * 2) */ +#define PI_2 1.57079632679489661923 /*!< pi / 2 */ +#define LOG2 0.69314718055994529 /*!< natural logarithm of 2 */ +#define LOG10 2.3025850929940459 /*!< natural logarithm of 10 */ +#define EXP 2.7182818284590451 /*!< Eurler's number */ sfloat sms_magToDB(sfloat x); sfloat sms_dBToMag(sfloat x); @@ -588,187 +635,120 @@ void sms_arrayScalarTempered( int sizeArray, sfloat *pArray); /* function declarations */ void sms_setPeaks(SMS_AnalParams *pAnalParams, int numamps, sfloat* amps, int numfreqs, sfloat* freqs, int numphases, sfloat* phases); - int sms_findPeaks(int sizeWaveform, sfloat *pWaveform, SMS_AnalParams *pAnalParams, SMS_SpectralPeaks *pSpectralPeaks); - int sms_findPartials(SMS_Data *pSmsFrame, SMS_AnalParams *pAnalParams); - int sms_findResidual(int sizeSynthesis, sfloat* pSynthesis, int sizeOriginal, sfloat* pOriginal, int sizeResidual, sfloat* pResidual, SMS_AnalParams *analParams); - int sms_analyze(int sizeWaveform, sfloat *pWaveform, SMS_Data *pSmsData, SMS_AnalParams *pAnalParams); - void sms_analyzeFrame(int iCurrentFrame, SMS_AnalParams *pAnalParams, sfloat fRefFundamental); -int sms_init(void); - -void sms_free(void); - +int sms_init(); +void sms_free(); int sms_initAnalysis(SMS_AnalParams *pAnalParams); - void sms_initAnalParams(SMS_AnalParams *pAnalParams); - void sms_changeHopSize(int hopSize, SMS_AnalParams *pAnalParams); - void sms_initSynthParams(SMS_SynthParams *synthParams); - int sms_initSynth(SMS_SynthParams *pSynthParams); - int sms_changeSynthHop(SMS_SynthParams *pSynthParams, int sizeHop); - void sms_freeAnalysis(SMS_AnalParams *pAnalParams); - void sms_freeSynth(SMS_SynthParams *pSynthParams ); void sms_fillSoundBuffer(int sizeWaveform, sfloat *pWaveform, SMS_AnalParams *pAnalParams); - void sms_windowCentered(int sizeWindow, sfloat *pWaveform, sfloat *pWindow, int sizeFft, sfloat *pFftBuffer); - void sms_getWindow(int sizeWindow, sfloat *pWindow, int iWindowType); - void sms_scaleWindow(int sizeWindow, sfloat *pWindow); - int sms_spectrum(int sizeWindow, sfloat *pWaveform, sfloat *pWindow, int sizeMag, - sfloat *pMag, sfloat *pPhase); - + sfloat *pMag, sfloat *pPhase, sfloat *pFftBuffer); int sms_invSpectrum(int sizeWaveform, sfloat *pWaveform, sfloat *pWindow , - int sizeMag, sfloat *pMag, sfloat *pPhase); - + int sizeMag, sfloat *pMag, sfloat *pPhase, sfloat *pFftBuffer); /* \todo remove this once invSpectrum is completely implemented */ int sms_invQuickSpectrumW(sfloat *pFMagSpectrum, sfloat *pFPhaseSpectrum, int sizeFft, sfloat *pFWaveform, int sizeWave, - sfloat *pFWindow); - + sfloat *pFWindow, sfloat *pFftBuffer); int sms_spectralApprox(sfloat *pSpec1, int sizeSpec1, int sizeSpec1Used, - sfloat *pSpec2, int sizeSpec2, int nCoefficients); - + sfloat *pSpec2, int sizeSpec2, int nCoefficients, + sfloat *envelope); int sms_spectrumMag(int sizeWindow, sfloat *pWaveform, sfloat *pWindow, - int sizeMag, sfloat *pMag); + int sizeMag, sfloat *pMag, sfloat *pFftBuffer); void sms_dCepstrum(int sizeCepstrum, sfloat *pCepstrum, int sizeFreq, sfloat *pFreq, sfloat *pMag, sfloat fLambda, int iSamplingRate); - void sms_dCepstrumEnvelope(int sizeCepstrum, sfloat *pCepstrum, int sizeEnv, sfloat *pEnv); - void sms_spectralEnvelope(SMS_Data *pSmsData, SMS_SEnvParams *pSpecEnvParams); int sms_sizeNextWindow(int iCurrentFrame, SMS_AnalParams *pAnalParams); - sfloat sms_fundDeviation(SMS_AnalParams *pAnalParams, int iCurrentFrame); - int sms_detectPeaks(int sizeSpec, sfloat *pFMag, sfloat *pPhase, SMS_Peak *pSpectralPeaks, SMS_AnalParams *pAnalParams); - sfloat sms_harmDetection(int numPeaks, SMS_Peak* spectralPeaks, sfloat refFundamental, - sfloat refHarmonic, sfloat lowestFreq, sfloat highestFreq, - int soundType, sfloat minRefHarmMag, sfloat refHarmMagDiffFromMax); - -int sms_peakContinuation (int iFrame, SMS_AnalParams *pAnalParams); - -sfloat sms_preEmphasis (sfloat fInput, SMS_AnalParams *pAnalParams); + sfloat refHarmonic, sfloat lowestFreq, sfloat highestFreq, + int soundType, sfloat minRefHarmMag, sfloat refHarmMagDiffFromMax); +int sms_peakContinuation(int iFrame, SMS_AnalParams *pAnalParams); +sfloat sms_preEmphasis(sfloat fInput, SMS_AnalParams *pAnalParams); sfloat sms_deEmphasis(sfloat fInput, SMS_SynthParams *pSynthParams); -void sms_cleanTracks (int iCurrentFrame, SMS_AnalParams *pAnalParams); - -void sms_scaleDet (sfloat *pSynthBuffer, sfloat *pOriginalBuffer, - sfloat *pSinAmp, SMS_AnalParams *pAnalParams, int nTracks); - -int sms_prepSine (int nTableSize); - -int sms_prepSinc (int nTableSize); - -void sms_clearSine( void ); - -void sms_clearSinc( void ); - -void sms_synthesize (SMS_Data *pSmsFrame, sfloat*pSynthesis, - SMS_SynthParams *pSynthParams); - -void sms_sineSynthFrame (SMS_Data *pSmsFrame, sfloat *pBuffer, - int sizeBuffer, SMS_Data *pLastFrame, - int iSamplingRate); - -void sms_initHeader (SMS_Header *pSmsHeader); - -int sms_getHeader (char *pChFileName, SMS_Header **ppSmsHeader, - FILE **ppInputFile); - -void sms_fillHeader (SMS_Header *pSmsHeader, SMS_AnalParams *pAnalParams, - char *pProgramString); - -int sms_writeHeader (char *pFileName, SMS_Header *pSmsHeader, - FILE **ppOutSmsFile); - -int sms_writeFile (FILE *pSmsFile, SMS_Header *pSmsHeader); - -int sms_initFrame (int iCurrentFrame, SMS_AnalParams *pAnalParams, - int sizeWindow); - -int sms_allocFrame (SMS_Data *pSmsFrame, int nTracks, int nCoeff, - int iPhase, int stochType, int nEnvCoeff); - -int sms_allocFrameH (SMS_Header *pSmsHeader, SMS_Data *pSmsFrame); - -int sms_getFrame (FILE *pInputFile, SMS_Header *pSmsHeader, int iFrame, - SMS_Data *pSmsFrame); - -int sms_writeFrame (FILE *pSmsFile, SMS_Header *pSmsHeader, - SMS_Data *pSmsFrame); - -void sms_freeFrame (SMS_Data *pSmsFrame); - -void sms_clearFrame (SMS_Data *pSmsFrame); - -void sms_copyFrame (SMS_Data *pCopySmsFrame, SMS_Data *pOriginalSmsFrame); - -int sms_frameSizeB (SMS_Header *pSmsHeader); - -int sms_residual (int sizeWindow, sfloat *pSynthesis, sfloat *pOriginal, sfloat *pResidual); - -void sms_filterHighPass ( int sizeResidual, sfloat *pResidual, int iSamplingRate); - -int sms_stocAnalysis ( int sizeWindow, sfloat *pResidual, sfloat *pWindow, - SMS_Data *pSmsFrame); - -void sms_interpolateFrames (SMS_Data *pSmsFrame1, SMS_Data *pSmsFrame2, - SMS_Data *pSmsFrameOut, sfloat fInterpFactor); - +void sms_cleanTracks(int iCurrentFrame, SMS_AnalParams *pAnalParams); +void sms_scaleDet(sfloat *pSynthBuffer, sfloat *pOriginalBuffer, + sfloat *pSinAmp, SMS_AnalParams *pAnalParams, int nTracks); + +int sms_prepSine(int nTableSize); +int sms_prepSinc(int nTableSize); +void sms_clearSine(); +void sms_clearSinc(); + +void sms_synthesize(SMS_Data *pSmsFrame, sfloat*pSynthesis, SMS_SynthParams *pSynthParams); +void sms_sineSynthFrame(SMS_Data *pSmsFrame, sfloat *pBuffer, + int sizeBuffer, SMS_Data *pLastFrame, + int iSamplingRate); + +void sms_initHeader(SMS_Header *pSmsHeader); +int sms_getHeader(char *pChFileName, SMS_Header **ppSmsHeader, FILE **ppInputFile); +void sms_fillHeader(SMS_Header *pSmsHeader, SMS_AnalParams *pAnalParams, char *pProgramString); +int sms_writeHeader(char *pFileName, SMS_Header *pSmsHeader, FILE **ppOutSmsFile); +int sms_writeFile(FILE *pSmsFile, SMS_Header *pSmsHeader); +int sms_initFrame(int iCurrentFrame, SMS_AnalParams *pAnalParams, int sizeWindow); +int sms_allocFrame(SMS_Data *pSmsFrame, int nTracks, int nCoeff, + int iPhase, int stochType, int nEnvCoeff); +int sms_allocFrameH(SMS_Header *pSmsHeader, SMS_Data *pSmsFrame); +int sms_getFrame(FILE *pInputFile, SMS_Header *pSmsHeader, int iFrame, SMS_Data *pSmsFrame); +int sms_writeFrame(FILE *pSmsFile, SMS_Header *pSmsHeader, SMS_Data *pSmsFrame); +void sms_freeFrame(SMS_Data *pSmsFrame); +void sms_clearFrame(SMS_Data *pSmsFrame); +void sms_copyFrame(SMS_Data *pCopySmsFrame, SMS_Data *pOriginalSmsFrame); +int sms_frameSizeB(SMS_Header *pSmsHeader); + +int sms_residual(int sizeWindow, sfloat *pSynthesis, sfloat *pOriginal, + sfloat *pResidual, sfloat *pWindow); +void sms_filterHighPass(int sizeResidual, sfloat *pResidual, int iSamplingRate); +int sms_stocAnalysis(int sizeWindow, sfloat *pResidual, sfloat *pWindow, + SMS_Data *pSmsFrame, SMS_AnalParams *pAnalParams); + +void sms_interpolateFrames(SMS_Data *pSmsFrame1, SMS_Data *pSmsFrame2, + SMS_Data *pSmsFrameOut, sfloat fInterpFactor); void sms_fft(int sizeFft, sfloat *pArray); - void sms_ifft(int sizeFft, sfloat *pArray); - -void sms_RectToPolar( int sizeSpec, sfloat *pReal, sfloat *pMag, sfloat *pPhase); - -void sms_PolarToRect( int sizeSpec, sfloat *pReal, sfloat *pMag, sfloat *pPhase); - -void sms_spectrumRMS( int sizeMag, sfloat *pReal, sfloat *pMag); +void sms_RectToPolar(int sizeSpec, sfloat *pReal, sfloat *pMag, sfloat *pPhase); +void sms_PolarToRect(int sizeSpec, sfloat *pReal, sfloat *pMag, sfloat *pPhase); +void sms_spectrumRMS(int sizeMag, sfloat *pReal, sfloat *pMag); void sms_initModify(SMS_Header *header, SMS_ModifyParams *params); - void sms_initModifyParams(SMS_ModifyParams *params); - void sms_freeModify(SMS_ModifyParams *params); - void sms_modify(SMS_Data *frame, SMS_ModifyParams *params); /***********************************************************************************/ /************* debug functions: ******************************************************/ -int sms_createDebugFile (SMS_AnalParams *pAnalParams); - -void sms_writeDebugData (sfloat *pBuffer1, sfloat *pBuffer2, - sfloat *pBuffer3, int sizeBuffer); - -void sms_writeDebugFile ( void ); - -void sms_error( char *pErrorMessage ); - -int sms_errorCheck( void ); - -char* sms_errorString( void ); +int sms_createDebugFile(SMS_AnalParams *pAnalParams); +void sms_writeDebugData(sfloat *pBuffer1, sfloat *pBuffer2, + sfloat *pBuffer3, int sizeBuffer); +void sms_writeDebugFile(); +void sms_error(char *pErrorMessage ); +int sms_errorCheck(); +char* sms_errorString(); #endif /* _SMS_H */ diff --git a/sms/sms.i b/sms/sms.i index e091312..d33c280 100644 --- a/sms/sms.i +++ b/sms/sms.i @@ -1,4 +1,4 @@ -%module pysms +%module simplsms %{ #include "sms.h" #define SWIG_FILE_WITH_INIT @@ -9,7 +9,6 @@ %init %{ import_array(); - sms_init(); /* initialize the library (makes some tables, seeds the random number generator, etc */ %} %exception @@ -23,24 +22,24 @@ } /* apply all numpy typemaps to various names in sms.h */ -%apply (int DIM1, double* INPLACE_ARRAY1) {(int sizeWindow, double* pWindow)}; -%apply (int DIM1, double* INPLACE_ARRAY1) {(int sizeWaveform, double* pWaveform)}; -%apply (int DIM1, double* INPLACE_ARRAY1) {(long sizeSound, double* pSound)}; -%apply (int DIM1, double* INPLACE_ARRAY1) {(int sizeFft, double* pArray)}; -%apply (int DIM1, double* INPLACE_ARRAY1) {(int sizeFft, double* pFftBuffer)}; -%apply (int DIM1, double* INPLACE_ARRAY1) {(int sizeFreq, double* pFreq)}; -%apply (int DIM1, double* INPLACE_ARRAY1) {(int sizeAmp, double* pAmp)}; -%apply (int DIM1, double* INPLACE_ARRAY1) {(int sizeMag, double* pMag)}; -%apply (int DIM1, double* INPLACE_ARRAY1) {(int sizePhase, double* pPhase)}; -%apply (int DIM1, double* INPLACE_ARRAY1) {(int sizeRes, double* pRes)}; -%apply (int DIM1, double* INPLACE_ARRAY1) {(int sizeCepstrum, double* pCepstrum)}; -%apply (int DIM1, double* INPLACE_ARRAY1) {(int sizeEnv, double* pEnv)}; -%apply (int DIM1, double* INPLACE_ARRAY1) {(int sizeTrack, double* pTrack)}; -%apply (int DIM1, double* INPLACE_ARRAY1) {(int sizeArray, double* pArray)}; -%apply (int DIM1, double* IN_ARRAY1) {(int sizeInArray, double* pInArray)}; -%apply (int DIM1, double* INPLACE_ARRAY1) {(int sizeOutArray, double* pOutArray)}; -%apply (int DIM1, double* INPLACE_ARRAY1) {(int sizeHop, double* pSynthesis)}; -%apply (int DIM1, double* IN_ARRAY1) +%apply(int DIM1, double* INPLACE_ARRAY1) {(int sizeWindow, double* pWindow)}; +%apply(int DIM1, double* INPLACE_ARRAY1) {(int sizeWaveform, double* pWaveform)}; +%apply(int DIM1, double* INPLACE_ARRAY1) {(long sizeSound, double* pSound)}; +%apply(int DIM1, double* INPLACE_ARRAY1) {(int sizeFft, double* pArray)}; +%apply(int DIM1, double* INPLACE_ARRAY1) {(int sizeFft, double* pFftBuffer)}; +%apply(int DIM1, double* INPLACE_ARRAY1) {(int sizeFreq, double* pFreq)}; +%apply(int DIM1, double* INPLACE_ARRAY1) {(int sizeAmp, double* pAmp)}; +%apply(int DIM1, double* INPLACE_ARRAY1) {(int sizeMag, double* pMag)}; +%apply(int DIM1, double* INPLACE_ARRAY1) {(int sizePhase, double* pPhase)}; +%apply(int DIM1, double* INPLACE_ARRAY1) {(int sizeRes, double* pRes)}; +%apply(int DIM1, double* INPLACE_ARRAY1) {(int sizeCepstrum, double* pCepstrum)}; +%apply(int DIM1, double* INPLACE_ARRAY1) {(int sizeEnv, double* pEnv)}; +%apply(int DIM1, double* INPLACE_ARRAY1) {(int sizeTrack, double* pTrack)}; +%apply(int DIM1, double* INPLACE_ARRAY1) {(int sizeArray, double* pArray)}; +%apply(int DIM1, double* IN_ARRAY1) {(int sizeInArray, double* pInArray)}; +%apply(int DIM1, double* INPLACE_ARRAY1) {(int sizeOutArray, double* pOutArray)}; +%apply(int DIM1, double* INPLACE_ARRAY1) {(int sizeHop, double* pSynthesis)}; +%apply(int DIM1, double* IN_ARRAY1) { (int numamps, double* amps), (int numfreqs, double* freqs), @@ -55,17 +54,16 @@ %include "sms.h" - /* overload the functions that will be wrapped to fit numpy typmaps (defined below) * by renaming the wrapped names back to originals */ -%rename (sms_detectPeaks) simplsms_detectPeaks; -%rename (sms_spectrum) simplsms_spectrum; -%rename (sms_spectrumMag) simplsms_spectrumMag; -%rename (sms_windowCentered) simplsms_windowCentered; -%rename (sms_invSpectrum) simplsms_invSpectrum; -%rename (sms_dCepstrum) simplsms_dCepstrum; -%rename (sms_synthesize) simplsms_synthesize_wrapper; +%rename(sms_detectPeaks) simplsms_detectPeaks; +%rename(sms_spectrum) simplsms_spectrum; +%rename(sms_spectrumMag) simplsms_spectrumMag; +%rename(sms_windowCentered) simplsms_windowCentered; +%rename(sms_invSpectrum) simplsms_invSpectrum; +%rename(sms_dCepstrum) simplsms_dCepstrum; +%rename(sms_synthesize) simplsms_synthesize_wrapper; %inline %{ @@ -76,8 +74,8 @@ int allocated; } SMS_File; - void simplsms_dCepstrum( int sizeCepstrum, sfloat *pCepstrum, int sizeFreq, sfloat *pFreq, int sizeMag, sfloat *pMag, - sfloat fLambda, int iSamplingRate) + void simplsms_dCepstrum(int sizeCepstrum, sfloat *pCepstrum, int sizeFreq, sfloat *pFreq, int sizeMag, sfloat *pMag, + sfloat fLambda, int iSamplingRate) { sms_dCepstrum(sizeCepstrum,pCepstrum, sizeFreq, pFreq, pMag, fLambda, iSamplingRate); @@ -98,23 +96,23 @@ pPeakStruct->nPeaksFound = sms_detectPeaks(sizeMag, pMag, pPhase, pPeakStruct->pSpectralPeaks, pAnalParams); return pPeakStruct->nPeaksFound; } - int simplsms_spectrum( int sizeWaveform, sfloat *pWaveform, int sizeWindow, sfloat *pWindow, - int sizeMag, sfloat *pMag, int sizePhase, sfloat *pPhase) + int simplsms_spectrum(int sizeWaveform, sfloat *pWaveform, int sizeWindow, sfloat *pWindow, + int sizeMag, sfloat *pMag, int sizePhase, sfloat *pPhase, sfloat *pFftBuffer) { - return(sms_spectrum(sizeWindow, pWaveform, pWindow, sizeMag, pMag, pPhase)); + return sms_spectrum(sizeWindow, pWaveform, pWindow, sizeMag, pMag, pPhase, pFftBuffer); } - int simplsms_spectrumMag( int sizeWaveform, sfloat *pWaveform, int sizeWindow, sfloat *pWindow, - int sizeMag, sfloat *pMag) + int simplsms_spectrumMag(int sizeWaveform, sfloat *pWaveform, int sizeWindow, sfloat *pWindow, + int sizeMag, sfloat *pMag, sfloat *pFftBuffer) { - return(sms_spectrumMag(sizeWindow, pWaveform, pWindow, sizeMag, pMag)); + return sms_spectrumMag(sizeWindow, pWaveform, pWindow, sizeMag, pMag, pFftBuffer); } - int simplsms_invSpectrum( int sizeWaveform, sfloat *pWaveform, int sizeWindow, sfloat *pWindow, - int sizeMag, sfloat *pMag, int sizePhase, sfloat *pPhase) + int simplsms_invSpectrum(int sizeWaveform, sfloat *pWaveform, int sizeWindow, sfloat *pWindow, + int sizeMag, sfloat *pMag, int sizePhase, sfloat *pPhase, sfloat *pFftBuffer) { - return(sms_invSpectrum(sizeWaveform, pWaveform, pWindow, sizeMag, pMag, pPhase)); + return sms_invSpectrum(sizeWaveform, pWaveform, pWindow, sizeMag, pMag, pPhase, pFftBuffer); } void simplsms_windowCentered(int sizeWaveform, sfloat *pWaveform, int sizeWindow, - sfloat *pWindow, int sizeFft, sfloat *pFftBuffer) + sfloat *pWindow, int sizeFft, sfloat *pFftBuffer) { if (sizeWaveform != sizeWindow) { @@ -132,405 +130,389 @@ } sms_synthesize(pSmsData, pSynthesis, pSynthParams); } - %} %extend SMS_File { /* load an entire file to an internal numpy array */ - void load( char *pFilename ) + void load(char *pFilename) { - int i; - FILE *pSmsFile; - $self->allocated = 0; - sms_getHeader (pFilename, &$self->header, &pSmsFile); - if(sms_errorCheck()) return; - - $self->smsData = calloc($self->header->nFrames, sizeof(SMS_Data)); - for( i = 0; i < $self->header->nFrames; i++ ) - { - sms_allocFrameH ($self->header, &$self->smsData[i]); - if(sms_errorCheck()) return; - sms_getFrame (pSmsFile, $self->header, i, &$self->smsData[i]); - if(sms_errorCheck()) return; - } - $self->allocated = 1; - return; + int i; + FILE *pSmsFile; + $self->allocated = 0; + sms_getHeader (pFilename, &$self->header, &pSmsFile); + if(sms_errorCheck()) return; + + $self->smsData = calloc($self->header->nFrames, sizeof(SMS_Data)); + for(i = 0; i < $self->header->nFrames; i++) + { + sms_allocFrameH ($self->header, &$self->smsData[i]); + if(sms_errorCheck()) + return; + sms_getFrame (pSmsFile, $self->header, i, &$self->smsData[i]); + if(sms_errorCheck()) + return; + } + $self->allocated = 1; } - void close(void) /* todo: this should be in the destructor, no? */ + void close() /* todo: this should be in the destructor, no? */ { - int i; - if(!$self->allocated) - { - sms_error("file not yet alloceted"); - return; - } - $self->allocated = 0; - for( i = 0; i < $self->header->nFrames; i++) - sms_freeFrame(&$self->smsData[i]); - free($self->smsData); + int i; + if(!$self->allocated) + { + sms_error("file not yet alloceted"); return; + } + $self->allocated = 0; + for(i = 0; i < $self->header->nFrames; i++) + sms_freeFrame(&$self->smsData[i]); + free($self->smsData); } /* return a pointer to a frame, which can be passed around to other libsms functions */ void getFrame(int i, SMS_Data *frame) { - if(i < 0 || i >= $self->header->nFrames) - { - sms_error("index is out of file boundaries"); - return; - } - frame = &$self->smsData[i]; + if(i < 0 || i >= $self->header->nFrames) + { + sms_error("index is out of file boundaries"); + return; + } + frame = &$self->smsData[i]; } - void getTrack(int track, int sizeFreq, sfloat *pFreq, int sizeAmp, - sfloat *pAmp) + void getTrack(int track, int sizeFreq, sfloat *pFreq, int sizeAmp, sfloat *pAmp) { - /* fatal error protection first */ - if(!$self->allocated) - { - sms_error("file not yet alloceted"); - return ; - } - if(track >= $self->header->nTracks) - { - sms_error("desired track is greater than number of tracks in file"); - return; - } - if(sizeFreq != sizeAmp) - { - sms_error("freq and amp arrays are different in size"); - return; - } - /* make sure arrays are big enough, or return less data */ - int nFrames = MIN (sizeFreq, $self->header->nFrames); - int i; - for( i=0; i < nFrames; i++) - { - pFreq[i] = $self->smsData[i].pFSinFreq[track]; - pAmp[i] = $self->smsData[i].pFSinAmp[track]; - } + /* fatal error protection first */ + if(!$self->allocated) + { + sms_error("file not yet alloceted"); + return; + } + if(track >= $self->header->nTracks) + { + sms_error("desired track is greater than number of tracks in file"); + return; + } + if(sizeFreq != sizeAmp) + { + sms_error("freq and amp arrays are different in size"); + return; + } + /* make sure arrays are big enough, or return less data */ + int nFrames = MIN(sizeFreq, $self->header->nFrames); + int i; + for(i=0; i < nFrames; i++) + { + pFreq[i] = $self->smsData[i].pFSinFreq[track]; + pAmp[i] = $self->smsData[i].pFSinAmp[track]; + } } // TODO turn into getTrackP - and check if phase exists void getTrack(int track, int sizeFreq, sfloat *pFreq, int sizeAmp, - sfloat *pAmp, int sizePhase, sfloat *pPhase) + sfloat *pAmp, int sizePhase, sfloat *pPhase) { - /* fatal error protection first */ - if(!$self->allocated) - { - sms_error("file not yet alloceted"); - return ; - } - if(track >= $self->header->nTracks) - { - sms_error("desired track is greater than number of tracks in file"); - return; - } - if(sizeFreq != sizeAmp) - { - sms_error("freq and amp arrays are different in size"); - return; - } - /* make sure arrays are big enough, or return less data */ - int nFrames = MIN (sizeFreq, $self->header->nFrames); - int i; - for( i=0; i < nFrames; i++) - { - pFreq[i] = $self->smsData[i].pFSinFreq[track]; - pAmp[i] = $self->smsData[i].pFSinFreq[track]; - } - if($self->header->iFormat < SMS_FORMAT_HP) return; - - if(sizePhase != sizeFreq || sizePhase != sizeAmp) - { - sms_error("phase array and freq/amp arrays are different in size"); - return; - } - for( i=0; i < nFrames; i++) - pPhase[i] = $self->smsData[i].pFSinPha[track]; - + /* fatal error protection first */ + if(!$self->allocated) + { + sms_error("file not yet alloceted"); return; + } + if(track >= $self->header->nTracks) + { + sms_error("desired track is greater than number of tracks in file"); + return; + } + if(sizeFreq != sizeAmp) + { + sms_error("freq and amp arrays are different in size"); + return; + } + /* make sure arrays are big enough, or return less data */ + int nFrames = MIN (sizeFreq, $self->header->nFrames); + int i; + for(i=0; i < nFrames; i++) + { + pFreq[i] = $self->smsData[i].pFSinFreq[track]; + pAmp[i] = $self->smsData[i].pFSinFreq[track]; + } + if($self->header->iFormat < SMS_FORMAT_HP) + return; + + if(sizePhase != sizeFreq || sizePhase != sizeAmp) + { + sms_error("phase array and freq/amp arrays are different in size"); + return; + } + for(i=0; i < nFrames; i++) + pPhase[i] = $self->smsData[i].pFSinPha[track]; } void getFrameDet(int i, int sizeFreq, sfloat *pFreq, int sizeAmp, sfloat *pAmp) { - if(!$self->allocated) - { - sms_error("file not yet alloceted"); - return ; - } - if(i >= $self->header->nFrames) - { - sms_error("index is greater than number of frames in file"); - return; - } - int nTracks = $self->smsData[i].nTracks; - if(sizeFreq > nTracks) - { - sms_error("index is greater than number of frames in file"); - return; - } - if(sizeFreq != sizeAmp) - { - sms_error("freq and amp arrays are different in size"); - return; - } - memcpy(pFreq, $self->smsData[i].pFSinFreq, sizeof(sfloat) * nTracks); - memcpy(pAmp, $self->smsData[i].pFSinAmp, sizeof(sfloat) * nTracks); - - if($self->header->iFormat < SMS_FORMAT_HP) return; - + if(!$self->allocated) + { + sms_error("file not yet alloceted"); + return; + } + if(i >= $self->header->nFrames) + { + sms_error("index is greater than number of frames in file"); + return; + } + int nTracks = $self->smsData[i].nTracks; + if(sizeFreq > nTracks) + { + sms_error("index is greater than number of frames in file"); return; + } + if(sizeFreq != sizeAmp) + { + sms_error("freq and amp arrays are different in size"); + return; + } + memcpy(pFreq, $self->smsData[i].pFSinFreq, sizeof(sfloat) * nTracks); + memcpy(pAmp, $self->smsData[i].pFSinAmp, sizeof(sfloat) * nTracks); } void getFrameDetP(int i, int sizeFreq, sfloat *pFreq, int sizeAmp, - sfloat *pAmp, int sizePhase, sfloat *pPhase) + sfloat *pAmp, int sizePhase, sfloat *pPhase) { - if(!$self->allocated) - { - sms_error("file not yet alloceted"); - return ; - } - if($self->header->iFormat < SMS_FORMAT_HP) - { - sms_error("file does not contain a phase component in Deterministic (iFormat < SMS_FORMAT_HP)"); - return; - } - if(i >= $self->header->nFrames) - { - sms_error("index is greater than number of frames in file"); - return; - } - int nTracks = $self->smsData[i].nTracks; - if(sizeFreq > nTracks) - { - sms_error("index is greater than number of frames in file"); - return; - } - if(sizeFreq != sizeAmp) - { - sms_error("freq and amp arrays are different in size"); - return; - } - memcpy(pFreq, $self->smsData[i].pFSinFreq, sizeof(sfloat) * nTracks); - memcpy(pAmp, $self->smsData[i].pFSinAmp, sizeof(sfloat) * nTracks); - - if(sizePhase != sizeFreq || sizePhase != sizeAmp) - { - sms_error("phase array and freq/amp arrays are different in size"); - return; - } - memcpy(pPhase, $self->smsData[i].pFSinPha, sizeof(sfloat) * nTracks); - + if(!$self->allocated) + { + sms_error("file not yet alloceted"); + return; + } + if($self->header->iFormat < SMS_FORMAT_HP) + { + sms_error("file does not contain a phase component in Deterministic (iFormat < SMS_FORMAT_HP)"); + return; + } + if(i >= $self->header->nFrames) + { + sms_error("index is greater than number of frames in file"); + return; + } + int nTracks = $self->smsData[i].nTracks; + if(sizeFreq > nTracks) + { + sms_error("index is greater than number of frames in file"); return; + } + if(sizeFreq != sizeAmp) + { + sms_error("freq and amp arrays are different in size"); + return; + } + memcpy(pFreq, $self->smsData[i].pFSinFreq, sizeof(sfloat) * nTracks); + memcpy(pAmp, $self->smsData[i].pFSinAmp, sizeof(sfloat) * nTracks); + + if(sizePhase != sizeFreq || sizePhase != sizeAmp) + { + sms_error("phase array and freq/amp arrays are different in size"); + return; + } + memcpy(pPhase, $self->smsData[i].pFSinPha, sizeof(sfloat) * nTracks); } void getFrameRes(int i, int sizeRes, sfloat *pRes) { - - if(!$self->allocated) - { - sms_error("file not yet alloceted"); - return ; - } - if($self->header->iStochasticType < 1) - { - sms_error("file does not contain a stochastic component"); - return ; - } - int nCoeff = sizeRes; - if($self->header->nStochasticCoeff > sizeRes) - nCoeff = $self->header->nStochasticCoeff; // return what you can - - memcpy(pRes, $self->smsData[i].pFStocCoeff, sizeof(sfloat) * nCoeff); + if(!$self->allocated) + { + sms_error("file not yet alloceted"); return; + } + if($self->header->iStochasticType < 1) + { + sms_error("file does not contain a stochastic component"); + return; + } + int nCoeff = sizeRes; + if($self->header->nStochasticCoeff > sizeRes) + nCoeff = $self->header->nStochasticCoeff; // return what you can + + memcpy(pRes, $self->smsData[i].pFStocCoeff, sizeof(sfloat) * nCoeff); } void getFrameEnv(int i, int sizeEnv, sfloat *pEnv) { - - if(!$self->allocated) - { - sms_error("file not yet alloceted"); - return ; - } - if($self->header->iEnvType < 1) - { - sms_error("file does not contain a spectral envelope"); - return ; - } - int nCoeff = sizeEnv; - if($self->header->nStochasticCoeff > sizeEnv) - nCoeff = $self->header->nEnvCoeff; // return what you can - - memcpy(pEnv, $self->smsData[i].pSpecEnv, sizeof(sfloat) * nCoeff); + if(!$self->allocated) + { + sms_error("file not yet alloceted"); return; + } + if($self->header->iEnvType < 1) + { + sms_error("file does not contain a spectral envelope"); + return; + } + int nCoeff = sizeEnv; + if($self->header->nStochasticCoeff > sizeEnv) + nCoeff = $self->header->nEnvCoeff; // return what you can + + memcpy(pEnv, $self->smsData[i].pSpecEnv, sizeof(sfloat) * nCoeff); } } %extend SMS_AnalParams { - SMS_AnalParams() - { - SMS_AnalParams *s = (SMS_AnalParams *)malloc(sizeof(SMS_AnalParams)); - sms_initAnalParams(s); - return s; - } + SMS_AnalParams() + { + SMS_AnalParams *s = (SMS_AnalParams *)malloc(sizeof(SMS_AnalParams)); + sms_initAnalParams(s); + return s; + } } %extend SMS_SynthParams { - SMS_SynthParams() - { - SMS_SynthParams *s = (SMS_SynthParams *)malloc(sizeof(SMS_SynthParams)); - sms_initSynthParams(s); - return s; - } + SMS_SynthParams() + { + SMS_SynthParams *s = (SMS_SynthParams *)malloc(sizeof(SMS_SynthParams)); + sms_initSynthParams(s); + return s; + } } %extend SMS_SpectralPeaks { - SMS_SpectralPeaks(int n) + SMS_SpectralPeaks(int n) + { + SMS_SpectralPeaks *s = (SMS_SpectralPeaks *)malloc(sizeof(SMS_SpectralPeaks)); + s->nPeaks = n; + if((s->pSpectralPeaks = (SMS_Peak *)calloc (s->nPeaks, sizeof(SMS_Peak))) == NULL) { - SMS_SpectralPeaks *s = (SMS_SpectralPeaks *)malloc(sizeof(SMS_SpectralPeaks)); - s->nPeaks = n; - if ((s->pSpectralPeaks = - (SMS_Peak *)calloc (s->nPeaks, sizeof(SMS_Peak))) == NULL) - { - sms_error("could not allocate memory for spectral peaks"); - return(NULL); - } - s->nPeaksFound = 0; - return s; + sms_error("could not allocate memory for spectral peaks"); + return NULL; } - void getFreq( int sizeArray, sfloat *pArray ) + s->nPeaksFound = 0; + return s; + } + void getFreq(int sizeArray, sfloat *pArray ) + { + if(sizeArray < $self->nPeaksFound) { - if(sizeArray < $self->nPeaksFound) - { - sms_error("numpy array not big enough"); - return; - } - int i; - for (i = 0; i < $self->nPeaksFound; i++) - pArray[i] = $self->pSpectralPeaks[i].fFreq; - + sms_error("numpy array not big enough"); + return; } - void getMag( int sizeArray, sfloat *pArray ) + int i; + for(i = 0; i < $self->nPeaksFound; i++) + pArray[i] = $self->pSpectralPeaks[i].fFreq; + } + void getMag( int sizeArray, sfloat *pArray ) + { + if(sizeArray < $self->nPeaksFound) { - if(sizeArray < $self->nPeaksFound) - { - sms_error("numpy array not big enough"); - return; - } - int i; - for (i = 0; i < $self->nPeaksFound; i++) - pArray[i] = $self->pSpectralPeaks[i].fMag; + sms_error("numpy array not big enough"); + return; } - void getPhase( int sizeArray, sfloat *pArray ) + int i; + for(i = 0; i < $self->nPeaksFound; i++) + pArray[i] = $self->pSpectralPeaks[i].fMag; + } + void getPhase( int sizeArray, sfloat *pArray ) + { + if(sizeArray < $self->nPeaksFound) { - if(sizeArray < $self->nPeaksFound) - { - sms_error("numpy array not big enough"); - return; - } - int i; - for (i = 0; i < $self->nPeaksFound; i++) - pArray[i] = $self->pSpectralPeaks[i].fPhase; - + sms_error("numpy array not big enough"); + return; } + int i; + for(i = 0; i < $self->nPeaksFound; i++) + pArray[i] = $self->pSpectralPeaks[i].fPhase; + } } %extend SMS_Data { - void getSinAmp(int sizeArray, sfloat *pArray) + void getSinAmp(int sizeArray, sfloat *pArray) + { + if(sizeArray < $self->nTracks) { - if(sizeArray < $self->nTracks) - { - sms_error("numpy array not big enough"); - return; - } - int i; - for (i = 0; i < $self->nTracks; i++) - pArray[i] = $self->pFSinAmp[i]; + sms_error("numpy array not big enough"); + return; } - void getSinFreq(int sizeArray, sfloat *pArray) + int i; + for(i = 0; i < $self->nTracks; i++) + pArray[i] = $self->pFSinAmp[i]; + } + void getSinFreq(int sizeArray, sfloat *pArray) + { + if(sizeArray < $self->nTracks) { - if(sizeArray < $self->nTracks) - { - sms_error("numpy array not big enough"); - return; - } - int i; - for (i = 0; i < $self->nTracks; i++) - pArray[i] = $self->pFSinFreq[i]; + sms_error("numpy array not big enough"); + return; } - void getSinPhase(int sizeArray, sfloat *pArray) + int i; + for(i = 0; i < $self->nTracks; i++) + pArray[i] = $self->pFSinFreq[i]; + } + void getSinPhase(int sizeArray, sfloat *pArray) + { + if(sizeArray < $self->nTracks) { - if(sizeArray < $self->nTracks) - { - sms_error("numpy array not big enough"); - return; - } - int i; - for (i = 0; i < $self->nTracks; i++) - pArray[i] = $self->pFSinPha[i]; + sms_error("numpy array not big enough"); + return; } - void getSinEnv(int sizeArray, sfloat *pArray) + int i; + for(i = 0; i < $self->nTracks; i++) + pArray[i] = $self->pFSinPha[i]; + } + void getSinEnv(int sizeArray, sfloat *pArray) + { + if(sizeArray < $self->nEnvCoeff) { - if(sizeArray < $self->nEnvCoeff) - { - sms_error("numpy array not big enough"); - return; - } - int i; - for (i = 0; i < $self->nEnvCoeff; i++) - pArray[i] = $self->pSpecEnv[i]; + sms_error("numpy array not big enough"); + return; } - void setSinAmp(int sizeArray, sfloat *pArray) + int i; + for(i = 0; i < $self->nEnvCoeff; i++) + pArray[i] = $self->pSpecEnv[i]; + } + void setSinAmp(int sizeArray, sfloat *pArray) + { + if(sizeArray < $self->nTracks) { - if(sizeArray < $self->nTracks) - { - sms_error("numpy array not big enough"); - return; - } - int i; - for (i = 0; i < $self->nTracks; i++) - $self->pFSinAmp[i] = pArray[i]; - + sms_error("numpy array not big enough"); + return; } - void setSinFreq(int sizeArray, sfloat *pArray) + int i; + for (i = 0; i < $self->nTracks; i++) + $self->pFSinAmp[i] = pArray[i]; + } + void setSinFreq(int sizeArray, sfloat *pArray) + { + if(sizeArray < $self->nTracks) { - if(sizeArray < $self->nTracks) - { - sms_error("numpy array not big enough"); - return; - } - int i; - for (i = 0; i < $self->nTracks; i++) - $self->pFSinFreq[i] = pArray[i]; + sms_error("numpy array not big enough"); + return; } - void setSinPha(int sizeArray, sfloat *pArray) + int i; + for(i = 0; i < $self->nTracks; i++) + $self->pFSinFreq[i] = pArray[i]; + } + void setSinPha(int sizeArray, sfloat *pArray) + { + if(sizeArray < $self->nTracks) { - if(sizeArray < $self->nTracks) - { - sms_error("numpy array not big enough"); - return; - } - int i; - for (i = 0; i < $self->nTracks; i++) - $self->pFSinPha[i] = pArray[i]; + sms_error("numpy array not big enough"); + return; } + int i; + for(i = 0; i < $self->nTracks; i++) + $self->pFSinPha[i] = pArray[i]; + } } %extend SMS_ModifyParams { - /* no need to return an error code, if sms_error is called, it will throw an exception in python */ - void setSinEnv(int sizeArray, sfloat *pArray) + /* no need to return an error code, if sms_error is called, it will throw an exception in python */ + void setSinEnv(int sizeArray, sfloat *pArray) + { + if(!$self->ready) { - if(!$self->ready) - { - sms_error("modify parameter structure has not been initialized"); - return; - } - if(sizeArray != $self->sizeSinEnv) - { - sms_error("numpy array is not equal to envelope size"); - return; - } - memcpy($self->sinEnv, pArray, sizeof(sfloat) * $self->sizeSinEnv); + sms_error("modify parameter structure has not been initialized"); + return; + } + if(sizeArray != $self->sizeSinEnv) + { + sms_error("numpy array is not equal to envelope size"); + return; } + memcpy($self->sinEnv, pArray, sizeof(sfloat) * $self->sizeSinEnv); + } } + diff --git a/sms/soundIO.c b/sms/soundIO.c index 1de75d6..1f68506 100644 --- a/sms/soundIO.c +++ b/sms/soundIO.c @@ -23,9 +23,6 @@ */ #include "sms.h" -const char *pChResidualFile = "residual.aiff"; -#define MAX_SAMPLES 10000 - /*! \brief fill the sound buffer * * \param sizeWaveform size of input data diff --git a/sms/spectralApprox.c b/sms/spectralApprox.c index 9e77f7a..c19afbe 100644 --- a/sms/spectralApprox.c +++ b/sms/spectralApprox.c @@ -35,121 +35,118 @@ * \param sizeSpec2 size of output envelope * \param nCoefficients number of coefficients to use in approximation * \return error code \see SMS_ERRORS (or -1 if the algorithm just messes up, - it will print an error of its own. + * it will print an error of its own. */ -int sms_spectralApprox (sfloat *pFSpec1, int sizeSpec1, int sizeSpec1Used, - sfloat *pFSpec2, int sizeSpec2, int nCoefficients) +int sms_spectralApprox(sfloat *pFSpec1, int sizeSpec1, int sizeSpec1Used, + sfloat *pFSpec2, int sizeSpec2, int nCoefficients, + sfloat *envelope) { - sfloat fHopSize, fCurrentLoc = 0, fLeft = 0, fRight = 0, fValue = 0, - fLastLocation, fSizeX, fSpec2Acum=0, fNextHop, fDeltaY, *pFEnvelope; - int iFirstGood = 0, iLastSample = 0, i, j; + sfloat fHopSize, fCurrentLoc = 0, fLeft = 0, fRight = 0, fValue = 0, + fLastLocation, fSizeX, fSpec2Acum=0, fNextHop, fDeltaY; + int iFirstGood = 0, iLastSample = 0, i, j; - /* when number of coefficients is smaller than 2 do not approximate */ - if (nCoefficients < 2) - { - for (i = 0; i < sizeSpec2; i++) - pFSpec2[i] = 1; - return(SMS_OK); - } - - if ((pFEnvelope = (sfloat *) calloc(nCoefficients, sizeof(sfloat))) == NULL) - return(SMS_MALLOC); - - /* calculate the hop size */ - if (sizeSpec1 != sizeSpec1Used) - fHopSize = (sfloat) sizeSpec1Used / nCoefficients; - else //why is this here, would be the same as sizeSpec1Used / nCoefficients - fHopSize = (sfloat) sizeSpec1 / nCoefficients; - if(nCoefficients > sizeSpec1) - nCoefficients = sizeSpec1; + /* when number of coefficients is smaller than 2 do not approximate */ + if(nCoefficients < 2) + { + for (i = 0; i < sizeSpec2; i++) + pFSpec2[i] = 1; + return SMS_OK; + } + /* calculate the hop size */ + if(sizeSpec1 != sizeSpec1Used) fHopSize = (sfloat) sizeSpec1Used / nCoefficients; - - /* approximate by linear interpolation */ - if (fHopSize > 1) - { - iFirstGood = 0; - for (i = 0; i < nCoefficients; i++) - { - iLastSample = fLastLocation = fCurrentLoc + fHopSize; - iLastSample = MIN (sizeSpec1-1, iLastSample); - if (iLastSample < sizeSpec1-1) - fRight = pFSpec1[iLastSample] + - (pFSpec1[iLastSample+1] - pFSpec1[iLastSample]) * - (fLastLocation - iLastSample); - else - fRight = pFSpec1[iLastSample]; - fValue = 0; - for (j = iFirstGood; j <= iLastSample; j++) - fValue = MAX (fValue, pFSpec1[j]); - fValue = MAX (fValue, MAX (fRight, fLeft)); - pFEnvelope[i] = fValue; - fLeft = fRight; - fCurrentLoc = fLastLocation; - iFirstGood = (int) (1+ fCurrentLoc); - } - } - else if (fHopSize == 1) - { - for (i = 0; i < nCoefficients; i++) - pFEnvelope[i] = pFSpec1[i]; - } - else - { - free (pFEnvelope); - //printf ("SpectralApprox: sizeSpec1 has too many nCoefficients\n"); /* \todo need to increase the frequency? */ - sms_error ("SpectralApprox: sizeSpec1 has too many nCoefficients\n"); /* \todo need to increase the frequency? */ - return -1; - } + else //why is this here, would be the same as sizeSpec1Used / nCoefficients + fHopSize = (sfloat) sizeSpec1 / nCoefficients; + + if(nCoefficients > sizeSpec1) + nCoefficients = sizeSpec1; + + fHopSize = (sfloat) sizeSpec1Used / nCoefficients; + + /* approximate by linear interpolation */ + if (fHopSize > 1) + { + iFirstGood = 0; + for(i = 0; i < nCoefficients; i++) + { + iLastSample = fLastLocation = fCurrentLoc + fHopSize; + iLastSample = MIN (sizeSpec1-1, iLastSample); + if(iLastSample < sizeSpec1-1) + fRight = pFSpec1[iLastSample] + + (pFSpec1[iLastSample+1] - pFSpec1[iLastSample]) * + (fLastLocation - iLastSample); + else + fRight = pFSpec1[iLastSample]; + fValue = 0; + for(j = iFirstGood; j <= iLastSample; j++) + fValue = MAX (fValue, pFSpec1[j]); + fValue = MAX (fValue, MAX (fRight, fLeft)); + envelope[i] = fValue; + fLeft = fRight; + fCurrentLoc = fLastLocation; + iFirstGood = (int) (1+ fCurrentLoc); + } + } + else if(fHopSize == 1) + { + for(i = 0; i < nCoefficients; i++) + envelope[i] = pFSpec1[i]; + } + else + { + sms_error("SpectralApprox: sizeSpec1 has too many nCoefficients\n"); /* \todo need to increase the frequency? */ + return -1; + } + + /* Creates Spec2 from Envelope */ + if(nCoefficients < sizeSpec2) + { + fSizeX = (sfloat) (sizeSpec2-1) / nCoefficients; - /* Creates Spec2 from Envelope */ - if (nCoefficients < sizeSpec2) - { - fSizeX = (sfloat) (sizeSpec2-1) / nCoefficients; + /* the first step */ + fNextHop = fSizeX / 2; + fDeltaY = envelope[0] / fNextHop; + fSpec2Acum=pFSpec2[j=0]=0; + while(++j < fNextHop) + pFSpec2[j] = (fSpec2Acum += fDeltaY); - /* the first step */ - fNextHop = fSizeX / 2; - fDeltaY = pFEnvelope[0] / fNextHop; - fSpec2Acum=pFSpec2[j=0]=0; - while (++j < fNextHop) - pFSpec2[j] = (fSpec2Acum += fDeltaY); - - /* middle values */ - for (i = 0; i <= nCoefficients-2; ++i) - { - fDeltaY = (pFEnvelope[i+1] - pFEnvelope[i]) / fSizeX; - /* first point of a segment */ - pFSpec2[j] = (fSpec2Acum = (pFEnvelope[i]+(fDeltaY*(j-fNextHop)))); - ++j; - /* remaining points */ - fNextHop += fSizeX; - while (j < fNextHop) - pFSpec2[j++] = (fSpec2Acum += fDeltaY); - } + /* middle values */ + for(i = 0; i <= nCoefficients-2; ++i) + { + fDeltaY = (envelope[i+1] - envelope[i]) / fSizeX; + /* first point of a segment */ + pFSpec2[j] = (fSpec2Acum = (envelope[i]+(fDeltaY*(j-fNextHop)))); + ++j; + /* remaining points */ + fNextHop += fSizeX; + while(j < fNextHop) + pFSpec2[j++] = (fSpec2Acum += fDeltaY); + } - /* last step */ - fDeltaY = -pFEnvelope[i] * 2 / fSizeX; - /* first point of the last segment */ - pFSpec2[j] = (fSpec2Acum = (pFEnvelope[i]+(fDeltaY*(j-fNextHop)))); - ++j; - fNextHop += fSizeX / 2; - while (j < sizeSpec2-1) - pFSpec2[j++]=(fSpec2Acum += fDeltaY); - /* last should be exactly zero */ - pFSpec2[sizeSpec2-1] = .0; + /* last step */ + fDeltaY = -envelope[i] * 2 / fSizeX; + /* first point of the last segment */ + pFSpec2[j] = (fSpec2Acum = (envelope[i]+(fDeltaY*(j-fNextHop)))); + ++j; + fNextHop += fSizeX / 2; + while(j < sizeSpec2-1) + pFSpec2[j++]=(fSpec2Acum += fDeltaY); + /* last should be exactly zero */ + pFSpec2[sizeSpec2-1] = .0; + } + else if(nCoefficients == sizeSpec2) + { + for(i = 0; i < nCoefficients; i++) + pFSpec2[i] = envelope[i]; + } + else + { + sms_error("SpectralApprox: sizeSpec2 has too many nCoefficients\n"); + return -1; } - else if (nCoefficients == sizeSpec2) - { - for (i = 0; i < nCoefficients; i++) - pFSpec2[i] = pFEnvelope[i]; - } - else - { - free (pFEnvelope); - //printf ("SpectralApprox: sizeSpec2 has too many nCoefficients\n"); - sms_error ("SpectralApprox: sizeSpec2 has too many nCoefficients\n"); - return -1; - } - free (pFEnvelope); /* \todo make this a static array */ - return (SMS_OK); + + return SMS_OK; } + + diff --git a/sms/spectrum.c b/sms/spectrum.c index c7d815a..356811f 100644 --- a/sms/spectrum.c +++ b/sms/spectrum.c @@ -25,58 +25,39 @@ /*! \brief compute a complex spectrum from a waveform * - * \param sizeWindow size of analysis window - * \param pWaveform pointer to input waveform - * \param pWindow pointer to input window - * \param sizeMag size of output magnitude and phase spectrums + * \param sizeWindow size of analysis window + * \param pWaveform pointer to input waveform + * \param pWindow pointer to input window + * \param sizeMag size of output magnitude and phase spectrums * \param pMag pointer to output magnitude spectrum * \param pPhase pointer to output phase spectrum * \return sizeFft, -1 on error \todo remove this return */ -int sms_spectrum (int sizeWindow, sfloat *pWaveform, sfloat *pWindow, int sizeMag, - sfloat *pMag, sfloat *pPhase) +int sms_spectrum(int sizeWindow, sfloat *pWaveform, sfloat *pWindow, int sizeMag, + sfloat *pMag, sfloat *pPhase, sfloat *pFftBuffer) { - int sizeFft = sizeMag << 1; - int i, it2; - int err = 0; - sfloat fReal, fImag; - - static sfloat *pFftBuffer; - static int sizeFftArray = 0; - /* if new size fft is larger than old, allocate more memory */ - if(sizeFftArray < sizeFft) - { - if(sizeFftArray != 0) free(pFftBuffer); - sizeFftArray = sms_power2(sizeFft); - if(sizeFftArray != sizeFft) - { - sms_error("bad fft size, incremented to power of 2"); - err = -1; - } - if ((pFftBuffer = (sfloat *) malloc(sizeFft * sizeof(sfloat))) == NULL) - { - sms_error("could not allocate memory for fft array"); - return(-1); - } - } - memset(pFftBuffer, 0, sizeFft * sizeof(sfloat)); - - /* apply window to waveform and center window around 0 (zero-phase windowing)*/ - sms_windowCentered(sizeWindow, pWaveform, pWindow, sizeFft, pFftBuffer); - - sms_fft(sizeFft, pFftBuffer); - - /* convert from rectangular to polar coordinates */ - for (i = 0; i < sizeMag; i++) - { - it2 = i << 1; //even numbers 0-N - fReal = pFftBuffer[it2]; /*odd numbers 1->N+1 */ - fImag = pFftBuffer[it2 + 1]; /*even numbers 2->N+2 */ - pMag[i] = sqrt (fReal * fReal + fImag * fImag); - pPhase[i] = atan2 (-fImag, fReal); /* \todo why is fImag negated? */ - } - - return (sizeFft); + int i, it2; + int err = 0; + sfloat fReal, fImag; + + int sizeFft = sizeMag << 1; + memset(pFftBuffer, 0, sizeFft * sizeof(sfloat)); + + /* apply window to waveform and center window around 0 (zero-phase windowing)*/ + sms_windowCentered(sizeWindow, pWaveform, pWindow, sizeFft, pFftBuffer); + sms_fft(sizeFft, pFftBuffer); + + /* convert from rectangular to polar coordinates */ + for (i = 0; i < sizeMag; i++) + { + it2 = i << 1; //even numbers 0-N + fReal = pFftBuffer[it2]; /*odd numbers 1->N+1 */ + fImag = pFftBuffer[it2 + 1]; /*even numbers 2->N+2 */ + pMag[i] = sqrt(fReal * fReal + fImag * fImag); + pPhase[i] = atan2(-fImag, fReal); /* \todo why is fImag negated? */ + } + + return sizeFft; } /*! \brief compute the spectrum Magnitude of a waveform @@ -85,63 +66,42 @@ int sms_spectrum (int sizeWindow, sfloat *pWaveform, sfloat *pWindow, int sizeMa * performs a zero-padded FFT (if sizeMag*2 > sizeWindow). * The spectra is then converted magnitude (RMS). * - * \param sizeWindow size of analysis window / input wavefrom - * \param pWaveform pointer to input waveform - * \param pWindow pointer to analysis window - * \param sizeMag size of output magnitude spectrum + * \param sizeWindow size of analysis window / input wavefrom + * \param pWaveform pointer to input waveform + * \param pWindow pointer to analysis window + * \param sizeMag size of output magnitude spectrum * \param pMag pointer to output magnitude spectrum * \return 0 on success, -1 on error */ -int sms_spectrumMag (int sizeWindow, sfloat *pWaveform, sfloat *pWindow, - int sizeMag, sfloat *pMag) +int sms_spectrumMag(int sizeWindow, sfloat *pWaveform, sfloat *pWindow, + int sizeMag, sfloat *pMag, sfloat *pFftBuffer) { - int i,it2; - int sizeFft = sizeMag << 1; - int err = 0; - sfloat fReal, fImag; - - static sfloat *pFftBuffer; - static int sizeFftArray = 0; - - if(sizeFftArray != sizeFft) - { - if(sizeFftArray != 0) free(pFftBuffer); - sizeFftArray = sms_power2(sizeFft); - if(sizeFftArray != sizeFft) - { - sms_error("bad fft size, incremented to power of 2"); - err = -1; - } - if ((pFftBuffer = (sfloat *) malloc(sizeFft * sizeof(sfloat))) == NULL) - { - sms_error("could not allocate memory for fft array"); - return(-1); - } - } - /* apply window to waveform, zero the rest of the array */ - //memset(pFftBuffer, 0, sizeFft * sizeof(sfloat)); - for (i = 0; i < sizeWindow; i++) - pFftBuffer[i] = pWindow[i] * pWaveform[i]; - for(i = sizeWindow; i < sizeFft; i++) - pFftBuffer[i] = 0.; - - /* compute real FFT */ - sms_fft(sizeFft, pFftBuffer); - - /* convert from rectangular to polar coordinates */ - for (i=0; i> 1, i, it2; - sfloat *pFBuffer, fPower; - - /* allocate buffer */ - if ((pFBuffer = (sfloat *) calloc(sizeFft, sizeof(sfloat))) == NULL) - return -1; - - /* convert from polar coordinates to rectangular */ - for (i = 0; i> 1, i, it2; + sfloat fPower; + + /* convert from polar coordinates to rectangular */ + for (i = 0; i> 1, i, it2; */ -/* sfloat *pFBuffer, fPower; */ - -/* /\* allocate buffer *\/ */ -/* if ((pFBuffer = (sfloat *) calloc(sizeFft+1, sizeof(sfloat))) == NULL) */ -/* return -1; */ - -/* /\* convert from polar coordinates to rectangular *\/ */ -/* for (i = 0; i < sizeMag; i++) */ -/* { */ -/* it2 = i << 1; */ -/* fPower = pFMagSpectrum[i]; */ -/* pFBuffer[it2] = fPower * cos (pFPhaseSpectrum[i]); */ -/* pFBuffer[it2+1] = fPower * sin (pFPhaseSpectrum[i]); */ -/* } */ -/* /\* compute IFFT *\/ */ -/* sms_ifft(sizeFft, pFBuffer); */ - -/* /\* assume the output array has been taken care off *\/ */ -/* for (i = 0; i < sizeWave; i++) */ -/* pFWaveform[i] += pFBuffer[i]; */ - -/* free(pFBuffer); */ - -/* return (sizeMag); */ -/* } */ diff --git a/sms/stocAnalysis.c b/sms/stocAnalysis.c index d50df48..d073ee7 100644 --- a/sms/stocAnalysis.c +++ b/sms/stocAnalysis.c @@ -26,53 +26,35 @@ #define ENV_THRESHOLD .01 /* \todo was this value for type shorts?? */ /*! \brief main function for the stochastic analysis - * \param sizeWindow size of buffer - * \param pResidual pointer to residual signal + * \param sizeWindow size of buffer + * \param pResidual pointer to residual signal * \param pWindow pointer to windowing array - * \param pSmsData pointer to output SMS data + * \param pSmsData pointer to output SMS data + * \param pAnalParams point to analysis parameters * \return 0 on success, -1 on error */ -int sms_stocAnalysis ( int sizeWindow, sfloat *pResidual, sfloat *pWindow, SMS_Data *pSmsData) +int sms_stocAnalysis(int sizeWindow, sfloat *pResidual, sfloat *pWindow, + SMS_Data *pSmsData, SMS_AnalParams* pAnalParams) { - int i; - sfloat fMag = 0.0; - sfloat fStocNorm; + int i; + sfloat fMag = 0.0; + sfloat fStocNorm; - static sfloat *pMagSpectrum; - static int sizeWindowStatic = 0; - static int sizeFft = 0; - static int sizeMag = 0; - /* update array sizes if sizeWindow is new */ - if (sizeWindowStatic != sizeWindow) - { - if(sizeWindowStatic != 0) free(pMagSpectrum); - sizeWindowStatic = sizeWindow; - sizeFft = sms_power2(sizeWindow); - sizeMag = sizeFft >> 1; - if((pMagSpectrum = (sfloat *) calloc(sizeMag, sizeof(sfloat))) == NULL) - { - sms_error("sms_stocAnalysis: error allocating memory for pMagSpectrum"); - return -1; - } - } - - sms_spectrumMag (sizeWindow, pResidual, pWindow, sizeMag, pMagSpectrum); - - sms_spectralApprox (pMagSpectrum, sizeMag, sizeMag, pSmsData->pFStocCoeff, - pSmsData->nCoeff, pSmsData->nCoeff); - - /* get energy of spectrum */ - for (i = 0; i < sizeMag; i++) - fMag += (pMagSpectrum[i] * pMagSpectrum[i]); - *pSmsData->pFStocGain = fMag / sizeMag; - fStocNorm = 1. / *pSmsData->pFStocGain; + sms_spectrumMag(sizeWindow, pResidual, pWindow, pAnalParams->sizeStocMagSpectrum, + pAnalParams->stocMagSpectrum, pAnalParams->fftBuffer); - /* normalize envelope */ - /* \todo what good is this scaling, it is only being undone in resynthesis */ -/* for (i = 0; i < pSmsData->nCoeff; i++) */ -/* pSmsData->pFStocCoeff[i] *= fStocNorm; */ - - // *pSmsData->pFStocGain = sms_magToDB(*pSmsData->pFStocGain); - return(0); + sms_spectralApprox(pAnalParams->stocMagSpectrum, pAnalParams->sizeStocMagSpectrum, + pAnalParams->sizeStocMagSpectrum, pSmsData->pFStocCoeff, + pSmsData->nCoeff, pSmsData->nCoeff, + pAnalParams->approxEnvelope); + + /* get energy of spectrum */ + for(i = 0; i < pAnalParams->sizeStocMagSpectrum; i++) + fMag += (pAnalParams->stocMagSpectrum[i] * pAnalParams->stocMagSpectrum[i]); + + *pSmsData->pFStocGain = fMag / pAnalParams->sizeStocMagSpectrum; + fStocNorm = 1. / *pSmsData->pFStocGain; + + return 0; } 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); } + diff --git a/sms/tables.c b/sms/tables.c index 1802952..85d21cb 100644 --- a/sms/tables.c +++ b/sms/tables.c @@ -40,57 +40,61 @@ static sfloat *sms_tab_sinc; * \param nTableSize size of table * \return error code \see SMS_MALLOC in SMS_ERRORS */ -int sms_prepSine (int nTableSize) +int sms_prepSine(int nTableSize) { - register int i; - sfloat fTheta; - - if((sms_tab_sine = (sfloat *)malloc(nTableSize*sizeof(sfloat))) == 0) - return (SMS_MALLOC); - fSineScale = (sfloat)(TWO_PI) / (sfloat)(nTableSize - 1); - fSineIncr = 1.0 / fSineScale; - fTheta = 0.0; - for(i = 0; i < nTableSize; i++) - { - fTheta = fSineScale * (sfloat)i; - sms_tab_sine[i] = sin(fTheta); - } - return (SMS_OK); + register int i; + sfloat fTheta; + + sms_tab_sine = (sfloat *)malloc(nTableSize * sizeof(sfloat)); + if(sms_tab_sine == NULL) + { + sms_error("Could not allocate memory for sine table"); + return SMS_MALLOC; + } + fSineScale = (sfloat)(TWO_PI) / (sfloat)(nTableSize - 1); + fSineIncr = 1.0 / fSineScale; + fTheta = 0.0; + for(i = 0; i < nTableSize; i++) + { + fTheta = fSineScale * (sfloat)i; + sms_tab_sine[i] = sin(fTheta); + } + return SMS_OK; } /*! \brief clear sine table */ void sms_clearSine() { - if(sms_tab_sine) - free(sms_tab_sine); - sms_tab_sine = 0; + if(sms_tab_sine) + free(sms_tab_sine); + sms_tab_sine = NULL; } /*! \brief table-lookup sine method * \param fTheta angle in radians * \return approximately sin(fTheta) */ -sfloat sms_sine (sfloat fTheta) +sfloat sms_sine(sfloat fTheta) { - int i; - fTheta = fTheta - floor(fTheta * INV_TWO_PI) * TWO_PI; - - if(fTheta < 0) - { - i = .5 - (fTheta * fSineIncr); - return(-(sms_tab_sine[i])); - } - else - { - i = fTheta * fSineIncr + .5; - return(sms_tab_sine[i]); - } + int i; + fTheta = fTheta - floor(fTheta * INV_TWO_PI) * TWO_PI; + + if(fTheta < 0) + { + i = .5 - (fTheta * fSineIncr); + return -(sms_tab_sine[i]); + } + else + { + i = fTheta * fSineIncr + .5; + return sms_tab_sine[i]; + } } /*! \brief Sinc method to generate the lookup table */ -static sfloat Sinc (sfloat x, sfloat N) +static sfloat Sinc(sfloat x, sfloat N) { - return (sinf ((N/2) * x) / sinf (x/2)); + return sinf((N/2) * x) / sinf(x/2); } /*! \brief prepare the Sinc table @@ -101,41 +105,45 @@ static sfloat Sinc (sfloat x, sfloat N) * \param nTableSize size of table * \return error code \see SMS_MALLOC in SMS_ERRORS */ -int sms_prepSinc (int nTableSize) +int sms_prepSinc(int nTableSize) { - int i, m; + int i, m; sfloat N = 512.0; sfloat fA[4] = {.35875, .48829, .14128, .01168}; - sfloat fMax = 0; - sfloat fTheta = -4.0 * TWO_PI / N; - sfloat fThetaIncr = (8.0 * TWO_PI / N) / (nTableSize); + sfloat fMax = 0; + sfloat fTheta = -4.0 * TWO_PI / N; + sfloat fThetaIncr = (8.0 * TWO_PI / N) / (nTableSize); + + sms_tab_sinc = (sfloat *)calloc(nTableSize, sizeof(sfloat)); + if(sms_tab_sinc == NULL) + { + sms_error("Could not allocate memory for sinc table"); + return (SMS_MALLOC); + } + + for(i = 0; i < nTableSize; i++) + { + for (m = 0; m < 4; m++) + sms_tab_sinc[i] += -1 * (fA[m]/2) * + (Sinc (fTheta - m * TWO_PI/N, N) + + Sinc (fTheta + m * TWO_PI/N, N)); + fTheta += fThetaIncr; + } - if((sms_tab_sinc = (sfloat *) calloc (nTableSize, sizeof(sfloat))) == 0) - return (SMS_MALLOC); - - for(i = 0; i < nTableSize; i++) - { - for (m = 0; m < 4; m++) - sms_tab_sinc[i] += -1 * (fA[m]/2) * - (Sinc (fTheta - m * TWO_PI/N, N) + - Sinc (fTheta + m * TWO_PI/N, N)); - fTheta += fThetaIncr; - } - fMax = sms_tab_sinc[(int) nTableSize / 2]; - for (i = 0; i < nTableSize; i++) - sms_tab_sinc[i] = sms_tab_sinc[i] / fMax; - - fSincScale = (sfloat) nTableSize / 8.0; - - return (SMS_OK); + fMax = sms_tab_sinc[(int) nTableSize / 2]; + for (i = 0; i < nTableSize; i++) + sms_tab_sinc[i] = sms_tab_sinc[i] / fMax; + + fSincScale = (sfloat) nTableSize / 8.0; + return SMS_OK; } /*! \brief clear sine table */ void sms_clearSinc() { - if(sms_tab_sinc) - free(sms_tab_sinc); - sms_tab_sinc = 0; + if(sms_tab_sinc) + free(sms_tab_sinc); + sms_tab_sinc = 0; } /*! \brief global sinc table-lookup method @@ -145,9 +153,10 @@ void sms_clearSinc() * \param fTheta angle in radians * \return approximately sinc(fTheta) */ -sfloat sms_sinc (sfloat fTheta) +sfloat sms_sinc(sfloat fTheta) { int index = (int) (.5 + fSincScale * fTheta); - - return (sms_tab_sinc[index]); + return sms_tab_sinc[index]; } + + -- cgit v1.2.3