summaryrefslogtreecommitdiff
path: root/src/sms/fixTracks.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sms/fixTracks.c')
-rw-r--r--src/sms/fixTracks.c259
1 files changed, 259 insertions, 0 deletions
diff --git a/src/sms/fixTracks.c b/src/sms/fixTracks.c
new file mode 100644
index 0000000..109d854
--- /dev/null
+++ b/src/sms/fixTracks.c
@@ -0,0 +1,259 @@
+/*
+ * 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 fixTracks.c
+ * \brief functions for making smoothly evolving tracks (partial frequencies)
+ *
+ * Tries to fix gaps and short tracks
+ */
+
+#include "sms.h"
+
+/*! \brief fill a gap in a given track
+ *
+ * \param iCurrentFrame currrent frame number
+ * \param iTrack track to be filled
+ * \param pIState pointer to the state of tracks
+ * \param pAnalParams pointer to analysis parameters
+ */
+static void FillGap(int iCurrentFrame, int iTrack, int *pIState,
+ SMS_AnalParams *pAnalParams)
+{
+ int iFrame, iLastFrame = - (pIState[iTrack] - 1);
+ sfloat fConstant = TWO_PI / pAnalParams->iSamplingRate;
+ sfloat fFirstMag, fFirstFreq, fLastMag, fLastFreq, fIncrMag, fIncrFreq,
+ fMag, fTmpPha, fFreq;
+
+ if(iCurrentFrame - iLastFrame < 0)
+ return;
+
+ /* if firstMag is 0 it means that there is no Gap, just the begining of a track */
+ if(pAnalParams->ppFrames[iCurrentFrame -
+ iLastFrame]->deterministic.pFSinAmp[iTrack] == 0)
+ {
+ pIState[iTrack] = 1;
+ return;
+ }
+
+ fFirstMag =
+ pAnalParams->ppFrames[iCurrentFrame - iLastFrame]->deterministic.pFSinAmp[iTrack];
+ fFirstFreq =
+ pAnalParams->ppFrames[iCurrentFrame - iLastFrame]->deterministic.pFSinFreq[iTrack];
+ fLastMag = pAnalParams->ppFrames[iCurrentFrame]->deterministic.pFSinAmp[iTrack];
+ fLastFreq = pAnalParams->ppFrames[iCurrentFrame]->deterministic.pFSinFreq[iTrack];
+ fIncrMag = (fLastMag - fFirstMag) / iLastFrame;
+ fIncrFreq = (fLastFreq - fFirstFreq) / iLastFrame;
+
+ /* if inharmonic format and the two extremes are very different */
+ /* do not interpolate, it means that they are different tracks */
+ if((pAnalParams->iFormat == SMS_FORMAT_IH ||
+ pAnalParams->iFormat == SMS_FORMAT_IHP) &&
+ (MIN (fFirstFreq, fLastFreq) * .5 * pAnalParams->fFreqDeviation <
+ fabs(fLastFreq - fFirstFreq)))
+ {
+ pIState[iTrack] = 1;
+ return;
+ }
+
+ fMag = fFirstMag;
+ fFreq = fFirstFreq;
+ /* fill the gap by interpolating values */
+ /* if the gap is too long it should consider the lower partials */
+ for(iFrame = iCurrentFrame - iLastFrame + 1; iFrame < iCurrentFrame; iFrame++)
+ {
+ /* interpolate magnitude */
+ fMag += fIncrMag;
+ pAnalParams->ppFrames[iFrame]->deterministic.pFSinAmp[iTrack] = fMag;
+ /* interpolate frequency */
+ fFreq += fIncrFreq;
+ pAnalParams->ppFrames[iFrame]->deterministic.pFSinFreq[iTrack] = fFreq;
+ /*interpolate phase (this may not be the right way) */
+ fTmpPha =
+ pAnalParams->ppFrames[iFrame-1]->deterministic.pFSinPha[iTrack] -
+ (pAnalParams->ppFrames[iFrame-1]->deterministic.pFSinFreq[iTrack] *
+ fConstant) * pAnalParams->sizeHop;
+ pAnalParams->ppFrames[iFrame]->deterministic.pFSinPha[iTrack] =
+ fTmpPha - floor(fTmpPha/ TWO_PI) * TWO_PI;
+ }
+
+ if(pAnalParams->iDebugMode == SMS_DBG_CLEAN_TRAJ ||
+ pAnalParams->iDebugMode == SMS_DBG_ALL)
+ {
+ fprintf (stdout, "fillGap: track %d, frames %d to %d filled\n",
+ iTrack, pAnalParams->ppFrames[iCurrentFrame-iLastFrame + 1]->iFrameNum,
+ pAnalParams->ppFrames[iCurrentFrame-1]->iFrameNum);
+ fprintf (stdout, "firstFreq %f lastFreq %f, firstMag %f lastMag %f\n",
+ fFirstFreq, fLastFreq, fFirstMag, fLastMag);
+
+ }
+
+ /* reset status */
+ pIState[iTrack] = pAnalParams->iMinTrackLength;
+}
+
+
+/*! \brief delete a short track
+ *
+ * this function is not exported to sms.h
+ *
+ * \param iCurrentFrame current frame
+ * \param iTrack track to be deleted
+ * \param pIState pointer to the state of tracks
+ * \param pAnalParams pointer to analysis parameters
+ */
+static void DeleteShortTrack(int iCurrentFrame, int iTrack, int *pIState,
+ SMS_AnalParams *pAnalParams)
+{
+ int iFrame, frame;
+
+ for(iFrame = 1; iFrame <= pIState[iTrack]; iFrame++)
+ {
+ frame = iCurrentFrame - iFrame;
+
+ if(frame <= 0)
+ return;
+
+ pAnalParams->ppFrames[frame]->deterministic.pFSinAmp[iTrack] = 0;
+ pAnalParams->ppFrames[frame]->deterministic.pFSinFreq[iTrack] = 0;
+ pAnalParams->ppFrames[frame]->deterministic.pFSinPha[iTrack] = 0;
+ }
+
+ if(pAnalParams->iDebugMode == SMS_DBG_CLEAN_TRAJ ||
+ pAnalParams->iDebugMode == SMS_DBG_ALL)
+ fprintf(stdout, "deleteShortTrack: track %d, frames %d to %d deleted\n",
+ iTrack, pAnalParams->ppFrames[iCurrentFrame - pIState[iTrack]]->iFrameNum,
+ pAnalParams->ppFrames[iCurrentFrame-1]->iFrameNum);
+
+ /* reset state */
+ pIState[iTrack] = -pAnalParams->iMaxSleepingTime;
+}
+
+/*! \brief fill gaps and delete short tracks
+ *
+ * \param iCurrentFrame current frame number
+ * \param pAnalParams pointer to analysis parameters
+ */
+void sms_cleanTracks(int iCurrentFrame, SMS_AnalParams *pAnalParams)
+{
+ int iTrack, iLength, iFrame;
+
+ /* 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)
+ {
+ 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(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
+ *
+ * \param pFSynthBuffer synthesis buffer
+ * \param pFOriginalBuffer original sound
+ * \param pFSinAmp magnitudes to be scaled
+ * \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)
+{
+ sfloat fOriginalMag = 0, fSynthesisMag = 0;
+ sfloat fCosScaleFactor;
+ int iTrack, i;
+
+ /* get sound energy */
+ for(i = 0; i < pAnalParams->sizeHop; i++)
+ {
+ fOriginalMag += fabs(pFOriginalBuffer[i]);
+ fSynthesisMag += fabs(pFSynthBuffer[i]);
+ }
+
+ /* if total energy of deterministic sound is larger than original,
+ scale deterministic representation */
+ 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);
+
+ for(iTrack = 0; iTrack < nTrack; iTrack++)
+ if(pFSinAmp[iTrack] > 0)
+ pFSinAmp[iTrack] = sms_magToDB(sms_dBToMag(pFSinAmp[iTrack]) * fCosScaleFactor);
+ }
+}
+