diff options
author | John Glover <glover.john@gmail.com> | 2010-11-24 23:26:43 +0000 |
---|---|---|
committer | John Glover <glover.john@gmail.com> | 2010-11-24 23:26:43 +0000 |
commit | 5e25edb1b78f28bee09bd7513a80fb500bbd59c4 (patch) | |
tree | 9290c3757abdecf2525c68cd5e5082fa9604ca61 /sms/analysis.c | |
parent | 580dd2e019e9666dc5f4771dedeb0720aa8d1d07 (diff) | |
download | simpl-5e25edb1b78f28bee09bd7513a80fb500bbd59c4.tar.gz simpl-5e25edb1b78f28bee09bd7513a80fb500bbd59c4.tar.bz2 simpl-5e25edb1b78f28bee09bd7513a80fb500bbd59c4.zip |
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
Diffstat (limited to 'sms/analysis.c')
-rw-r--r-- | sms/analysis.c | 1081 |
1 files changed, 536 insertions, 545 deletions
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; } |