diff options
author | John Glover <glover.john@gmail.com> | 2011-06-24 18:17:23 +0100 |
---|---|---|
committer | John Glover <glover.john@gmail.com> | 2011-06-24 18:17:23 +0100 |
commit | 416bd737074a287ea47106c73ea6bcfde40a75a8 (patch) | |
tree | 74562303d4f4f2f2e010f7e13cba41dc4852b50c /sms/peakContinuation.c | |
parent | d26519464dcbf8c3682348167c29454961facefe (diff) | |
download | simpl-416bd737074a287ea47106c73ea6bcfde40a75a8.tar.gz simpl-416bd737074a287ea47106c73ea6bcfde40a75a8.tar.bz2 simpl-416bd737074a287ea47106c73ea6bcfde40a75a8.zip |
Change to using distutils.
Currently only builds the simplsndobj module
Diffstat (limited to 'sms/peakContinuation.c')
-rw-r--r-- | sms/peakContinuation.c | 481 |
1 files changed, 0 insertions, 481 deletions
diff --git a/sms/peakContinuation.c b/sms/peakContinuation.c deleted file mode 100644 index b61d14e..0000000 --- a/sms/peakContinuation.c +++ /dev/null @@ -1,481 +0,0 @@ -/* - * Copyright (c) 2008 MUSIC TECHNOLOGY GROUP (MTG) - * UNIVERSITAT POMPEU FABRA - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -/*! \file peakContinuation.c - * \brief peak continuation algorithm and functions - */ - -#include "sms.h" - -/*! guide states */ -#define GUIDE_BEG -2 -#define GUIDE_DEAD -1 -#define GUIDE_ACTIVE 0 - -/*!< maximum number of peak continuation candidates */ -#define MAX_CONT_CANDIDATES 5 - -/*! \brief function to get the next closest peak from a guide - * - * \param fGuideFreq guide's frequency - * \param pFFreqDistance distance of last best peak from guide - * \param pSpectralPeaks array of peaks - * \param pAnalParams analysis parameters - * \param fFreqDev maximum deviation from guide - * \return peak number or -1 if nothing is good - */ -static int GetNextClosestPeak(sfloat fGuideFreq, sfloat *pFFreqDistance, - SMS_Peak *pSpectralPeaks, SMS_AnalParams *pAnalParams, - sfloat fFreqDev) -{ - int iInitialPeak = SMS_MAX_NPEAKS * fGuideFreq / (pAnalParams->iSamplingRate * .5); - int iLowPeak, iHighPeak, iChosenPeak = -1; - sfloat fLowDistance, fHighDistance, fFreq; - - if(iInitialPeak >= pAnalParams->maxPeaks) - iInitialPeak = 0; - else if(pSpectralPeaks[iInitialPeak].fFreq <= 0) - iInitialPeak = 0; - - /* find a low peak to start */ - fLowDistance = fGuideFreq - pSpectralPeaks[iInitialPeak].fFreq; - if(floor(fLowDistance) < floor(*pFFreqDistance)) - { - while(floor(fLowDistance) <= floor(*pFFreqDistance) && - iInitialPeak > 0) - { - iInitialPeak--; - fLowDistance = fGuideFreq - pSpectralPeaks[iInitialPeak].fFreq; - } - } - else - { - while(floor(fLowDistance) >= floor(*pFFreqDistance) && - iInitialPeak < (pAnalParams->maxPeaks-1)) - { - iInitialPeak++; - if((fFreq = pSpectralPeaks[iInitialPeak].fFreq) == 0) - return -1; - fLowDistance = fGuideFreq - fFreq; - } - if(iInitialPeak > 0) - iInitialPeak--; - fLowDistance = fGuideFreq - pSpectralPeaks[iInitialPeak].fFreq; - } - - if(floor(fLowDistance) <= floor(*pFFreqDistance) || - fLowDistance > fFreqDev) - iLowPeak = -1; - else - iLowPeak = iInitialPeak; - - /* find a high peak to finish */ - iHighPeak = iInitialPeak; - fHighDistance = fGuideFreq - pSpectralPeaks[iHighPeak].fFreq; - while(floor(fHighDistance) >= floor(-*pFFreqDistance) && - iHighPeak < (pAnalParams->maxPeaks - 1)) - { - iHighPeak++; - if((fFreq = pSpectralPeaks[iHighPeak].fFreq) == 0) - { - iHighPeak = -1; - break; - } - fHighDistance = fGuideFreq - fFreq; - } - if(fHighDistance > 0 || fabs(fHighDistance) > fFreqDev || - floor(fabs(fHighDistance)) <= floor(*pFFreqDistance)) - iHighPeak = -1; - - /* chose between the two extrema */ - if(iHighPeak >= 0 && iLowPeak >= 0) - { - if(fabs(fHighDistance) > fLowDistance) - iChosenPeak = iLowPeak; - else - iChosenPeak = iHighPeak; - } - else if(iHighPeak < 0 && iLowPeak >= 0) - iChosenPeak = iLowPeak; - else if(iHighPeak >= 0 && iLowPeak < 0) - iChosenPeak = iHighPeak; - else - return -1; - - *pFFreqDistance = fabs(fGuideFreq - pSpectralPeaks[iChosenPeak].fFreq); - return iChosenPeak; -} - -/*! \brief choose the best candidate out of all - * - * \param pCandidate pointer to all the continuation candidates - * \param nCandidates number of candidates - * \param fFreqDev maximum frequency deviation allowed - * \return the peak number of the best candidate - */ -static int ChooseBestCand(SMS_ContCandidate *pCandidate, int nCandidates, sfloat fFreqDev) -{ - int i, iHighestCand, iClosestCand, iBestCand = 0; - sfloat fMaxMag, fClosestFreq; - - /* intial guess */ - iClosestCand = 0; - fClosestFreq = pCandidate[iClosestCand].fFreqDev; - iHighestCand = 0; - fMaxMag = pCandidate[iHighestCand].fMagDev; - - /* get the best candidate */ - for (i = 1; i < nCandidates; i++) - { - /* look for the one with highest magnitude */ - if (pCandidate[i].fMagDev > fMaxMag) - { - fMaxMag = pCandidate[i].fMagDev; - iHighestCand = i; - } - /* look for the closest one to the guide */ - if (pCandidate[i].fFreqDev < fClosestFreq) - { - fClosestFreq = pCandidate[i].fFreqDev; - iClosestCand = i; - } - } - iBestCand = iHighestCand; - - /* reconcile the two results */ - if(iBestCand != iClosestCand && - fabs(pCandidate[iHighestCand].fFreqDev - fClosestFreq) > fFreqDev / 2) - iBestCand = iClosestCand; - - return pCandidate[iBestCand].iPeak; -} - -/*! \brief check for one guide that has choosen iBestPeak - * - * \param iBestPeak choosen peak for a guide - * \param pGuides array of guides - * \param nGuides total number of guides - * \return number of guide that chose the peak, or -1 if none - */ -static int CheckForConflict(int iBestPeak, SMS_Guide *pGuides, int nGuides) -{ - int iGuide; - - for (iGuide = 0; iGuide < nGuides; iGuide++) - if (pGuides[iGuide].iPeakChosen == iBestPeak) - return iGuide; - - return -1; -} - -/*! \brief chose the best of the two guides for the conflicting peak - * - * \param iConflictingGuide conflicting guide number - * \param iGuide guide number - * \param pGuides array of guides - * \param pSpectralPeaks array of peaks - * \return number of guide - */ -static int BestGuide(int iConflictingGuide, int iGuide, SMS_Guide *pGuides, - SMS_Peak *pSpectralPeaks) -{ - int iConflictingPeak = pGuides[iConflictingGuide].iPeakChosen; - sfloat fGuideDistance = fabs(pSpectralPeaks[iConflictingPeak].fFreq - - pGuides[iGuide].fFreq); - sfloat fConfGuideDistance = fabs(pSpectralPeaks[iConflictingPeak].fFreq - - pGuides[iConflictingGuide].fFreq); - - if(fGuideDistance > fConfGuideDistance) - return iConflictingGuide; - else - return iGuide; -} - -/*! \brief function to find the best continuation peak for a given guide - * \param pGuides guide attributes - * \param iGuide number of guide - * \param pSpectralPeaks peak values at the current frame - * \param pAnalParams analysis parameters - * \param fFreqDev frequency deviation allowed - * \return the peak number - */ -int GetBestPeak(SMS_Guide *pGuides, int iGuide, SMS_Peak *pSpectralPeaks, - SMS_AnalParams *pAnalParams, sfloat fFreqDev) -{ - int iCand = 0, iPeak, iBestPeak, iConflictingGuide, iWinnerGuide; - sfloat fGuideFreq = pGuides[iGuide].fFreq, - fGuideMag = pGuides[iGuide].fMag, - fMagDistance = 0; - sfloat fFreqDistance = -1; - SMS_ContCandidate pCandidate[MAX_CONT_CANDIDATES]; - - /* find all possible candidates */ - while (iCand < MAX_CONT_CANDIDATES) - { - /* find the next best peak */ - if((iPeak = GetNextClosestPeak(fGuideFreq, &fFreqDistance, - pSpectralPeaks, pAnalParams, fFreqDev)) < 0) - break; - - /* if the peak's magnitude is not too small accept it as */ - /* possible candidate */ - if ((fMagDistance = pSpectralPeaks[iPeak].fMag - fGuideMag) > -20.0) - { - pCandidate[iCand].fFreqDev = fabs(fFreqDistance); - pCandidate[iCand].fMagDev = fMagDistance; - pCandidate[iCand].iPeak = iPeak; - - if(pAnalParams->iDebugMode == SMS_DBG_PEAK_CONT || - pAnalParams->iDebugMode == SMS_DBG_ALL) - fprintf(stdout, "candidate %d: freq %f mag %f\n", - iCand, pSpectralPeaks[iPeak].fFreq, - pSpectralPeaks[iPeak].fMag); - iCand++; - } - } - /* get best candidate */ - if(iCand < 1) - return 0; - else if (iCand == 1) - iBestPeak = pCandidate[0].iPeak; - else - iBestPeak = ChooseBestCand (pCandidate, iCand, - pAnalParams->fFreqDeviation); - - if(pAnalParams->iDebugMode == SMS_DBG_PEAK_CONT || - pAnalParams->iDebugMode == SMS_DBG_ALL) - fprintf (stdout, "BestCandidate: freq %f\n", - pSpectralPeaks[iBestPeak].fFreq); - - /* if peak taken by another guide resolve conflict */ - if ((iConflictingGuide = CheckForConflict (iBestPeak, pGuides, - pAnalParams->nGuides)) >= 0) - { - iWinnerGuide = BestGuide (iConflictingGuide, iGuide, pGuides, - pSpectralPeaks); - if(pAnalParams->iDebugMode == SMS_DBG_PEAK_CONT || - pAnalParams->iDebugMode == SMS_DBG_ALL) - fprintf (stdout, - "Conflict: guide: %d (%f), and guide: %d (%f). best: %d\n", - iGuide, pGuides[iGuide].fFreq, - iConflictingGuide, pGuides[iConflictingGuide].fFreq, - iWinnerGuide); - - if (iGuide == iWinnerGuide) - { - pGuides[iGuide].iPeakChosen = iBestPeak; - pGuides[iConflictingGuide].iPeakChosen = -1; - } - } - else - pGuides[iGuide].iPeakChosen = iBestPeak; - - return iBestPeak; -} - -/*! \brief function to get the next maximum (magnitude) peak - * \param pSpectralPeaks array of peaks - * \param pFCurrentMax last peak maximum - * \return the number of the maximum peak - */ -static int GetNextMax(SMS_Peak *pSpectralPeaks, SMS_AnalParams *pAnalParams, - sfloat *pFCurrentMax) -{ - sfloat fPeakMag; - sfloat fMaxMag = 0.; - int iPeak, iMaxPeak = -1; - - for (iPeak = 0; iPeak < pAnalParams->maxPeaks; iPeak++) - { - fPeakMag = pSpectralPeaks[iPeak].fMag; - - if (fPeakMag == 0) - break; - - if (fPeakMag > fMaxMag && fPeakMag < *pFCurrentMax) - { - iMaxPeak = iPeak; - fMaxMag = fPeakMag; - } - } - *pFCurrentMax = fMaxMag; - return (iMaxPeak); -} - -/*! \brief function to get a good starting peak for a track - * - * \param iGuide current guide - * \param pGuides array of guides - * \param nGuides total number of guides - * \param pSpectralPeaks array of peaks - * \param pFCurrentMax current peak maximum - * \return \todo should this return something? - */ -static int GetStartingPeak(int iGuide, SMS_Guide *pGuides, int nGuides, - SMS_Peak *pSpectralPeaks, SMS_AnalParams *pAnalParams, - sfloat *pFCurrentMax) -{ - int iPeak = -1; - short peakNotFound = 1; - - while (peakNotFound == 1 && *pFCurrentMax > 0) - { - /* \todo I don't think this ever returns -1, but check */ - if ((iPeak = GetNextMax(pSpectralPeaks, pAnalParams, pFCurrentMax)) < 0) - return (-1); - - if (CheckForConflict (iPeak, pGuides, nGuides) < 0) - { - pGuides[iGuide].iPeakChosen = iPeak; - pGuides[iGuide].iStatus = GUIDE_BEG; - pGuides[iGuide].fFreq = pSpectralPeaks[iPeak].fFreq; - peakNotFound = 0; - } - } - return (1); -} - -/*! \brief function to advance the guides through the next frame - * - * the output is the frequency, magnitude, and phase tracks - * - * \param iFrame current frame number - * \param pAnalParams analysis parameters - * \return error code \see SMS_ERRORS - */ -int sms_peakContinuation(int iFrame, SMS_AnalParams *pAnalParams) -{ - 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, - pAnalParams, &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; -} - |