This is peakContinuation.c in view mode; [Download] [Up]
#include "../sms.h" /* function to get the next closest peak from a guide * float fGuideFreq; guide's frequency * float *pFFreqDistance; distance of last best peak from guide * PEAK *pSpectralPeaks; array of peaks * ANAL_PARAMS analParams; analysis parameters * float fFreqDev; maximum deviation from guide */ static int GetNextClosestPeak (float fGuideFreq, float *pFFreqDistance, PEAK *pSpectralPeaks, ANAL_PARAMS analParams, float fFreqDev) { int iInitialPeak = MAX_NUM_PEAKS * fGuideFreq / (analParams.fSamplingRate * .5), iLowPeak, iHighPeak, iChosenPeak = -1; float fLowDistance, fHighDistance, fFreq; 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 < MAX_NUM_PEAKS) { iInitialPeak++; if ((fFreq = pSpectralPeaks[iInitialPeak].fFreq) == 0) return -1; fLowDistance = fGuideFreq - fFreq; } 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 < MAX_NUM_PEAKS) { 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); } /* choose the best candidate out of all, returns the peak number of * the best candidate * * CONT_CANDIDATE *pCandidate; pointer to all the continuation candidates * int nCandidates; number of candidates * float fFreqDev; maximum frequency deviation allowed */ static int ChooseBestCand (CONT_CANDIDATE *pCandidate, int nCandidates, float fFreqDev) { int i, iHighestCand, iClosestCand, iBestCand = 0; float 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); } /* check for one guide that has choosen iBestPeak * int iBestPeak; choosen peak for a guide * GUIDE *pGuides; array of guides * int nGuides; total number of guides */ static int CheckForConflict (int iBestPeak, GUIDE *pGuides, int nGuides) { int iGuide; for (iGuide = 0; iGuide < nGuides; iGuide++) if (pGuides[iGuide].iPeakChosen == iBestPeak) return iGuide; return -1; } /* chose the best of the two guides for the conflicting peak * int iConflictingGuide; conflicting guide number * int iGuide; guide number * GUIDE *pGuides; array of guides * PEAK *pSpectralPeaks; array of peaks */ static int BestGuide (int iConflictingGuide, int iGuide, GUIDE *pGuides, PEAK *pSpectralPeaks) { int iConflictingPeak = pGuides[iConflictingGuide].iPeakChosen; float fGuideDistance = fabs (pSpectralPeaks[iConflictingPeak].fFreq - pGuides[iGuide].fFreq); float fConfGuideDistance = fabs (pSpectralPeaks[iConflictingPeak].fFreq - pGuides[iConflictingGuide].fFreq); if (fGuideDistance > fConfGuideDistance) return (iConflictingGuide); else return (iGuide); } /* function to find the best continuation peak for a given guide * returns the peak number * GUIDE *pGuideVal; guide attributes * PEAK *pSpectralPeaks; peak values at the current frame * ANAL_PARAMS analParams; analysis parameters * float fFreqDev; frequency deviation allowed */ static int GetBestPeak (GUIDE *pGuides, int iGuide, PEAK *pSpectralPeaks, ANAL_PARAMS analParams, float fFreqDev) { int iCand = 0, iPeak, iBestPeak, iConflictingGuide, iWinnerGuide; float fGuideFreq = pGuides[iGuide].fFreq, fGuideMag = pGuides[iGuide].fMag, fFreqDistance = -1, fMagDistance = 0; CONT_CANDIDATE pCandidate[MAX_CONT_CANDIDATES]; /* find all possible candidates */ while (iCand < MAX_CONT_CANDIDATES) { /* find the next best peak */ if ((iPeak = GetNextClosestPeak (fGuideFreq, &fFreqDistance, pSpectralPeaks, analParams, 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(analParams.iDebugMode == DEBUG_PEAK_CONT || analParams.iDebugMode == DEBUG_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, analParams.fFreqDeviation); if(analParams.iDebugMode == DEBUG_PEAK_CONT || analParams.iDebugMode == DEBUG_ALL) fprintf (stdout, "BestCandidate: freq %f\n", pSpectralPeaks[iBestPeak].fFreq); /* if peak taken by another guide resolve conflict */ if ((iConflictingGuide = CheckForConflict (iBestPeak, pGuides, analParams.nGuides)) >= 0) { iWinnerGuide = BestGuide (iConflictingGuide, iGuide, pGuides, pSpectralPeaks); if(analParams.iDebugMode == DEBUG_PEAK_CONT || analParams.iDebugMode == DEBUG_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); } /* function to get the next maximum peak * PEAK *pSpectralPeaks; array of peaks * float *pFCurrentMax; last peak maximum */ static int GetNextMax (PEAK *pSpectralPeaks, float *pFCurrentMax) { float fPeakMag, fMaxMag = MAG_THRESHOLD; int iPeak, iMaxPeak = -1; for (iPeak = 0; iPeak < MAX_NUM_PEAKS; iPeak++) { fPeakMag = pSpectralPeaks[iPeak].fMag; if (fPeakMag == 0) break; if (fPeakMag > fMaxMag && fPeakMag < *pFCurrentMax) { iMaxPeak = iPeak; fMaxMag = fPeakMag; } } *pFCurrentMax = fMaxMag; return (iMaxPeak); } /* function to get a good starting peak for a trajectory * int iGuide; current guide * GUIDE *pGuides; array of guides * int nGuides; total number of guides * PEAK *pSpectralPeaks; array of peaks * float *pFCurrentMax; current peak maximum */ static int GetStartingPeak (int iGuide, GUIDE *pGuides, int nGuides, PEAK *pSpectralPeaks, float *pFCurrentMax) { int iPeak = -1; short peakNotFound = 1; while (peakNotFound == 1 && *pFCurrentMax > 0) { if ((iPeak = GetNextMax (pSpectralPeaks, pFCurrentMax)) < 0) return (-1); if (CheckForConflict (iPeak, pGuides, nGuides) < 0) { pGuides[iGuide].iPeakChosen = iPeak; pGuides[iGuide].iStatus = BEGINNING; pGuides[iGuide].fFreq = pSpectralPeaks[iPeak].fFreq; peakNotFound = 0; } } return (1); } /* function to advance the guides through the next frame * the output is the freq., mag., and phase trajectories * * int iFrame; current frame number * ANAL_PARAMS analParams; analysis parameters */ int PeakContinuation (int iFrame, ANAL_PARAMS analParams) { int iGuide, iCurrentPeak = -1, iGoodPeak = -1; float fFund = ppFrames[iFrame]->fFundamental, fFreqDev = fFund * analParams.fFreqDeviation, fCurrentMax = 1000; static GUIDE *pGuides = NULL; if (pGuides == NULL) { if ((pGuides = (GUIDE *) calloc(analParams.nGuides, sizeof(GUIDE))) == NULL) return -1; if (analParams.iFormat == FORMAT_HARMONIC || analParams.iFormat == FORMAT_HARMONIC_WITH_PHASE) for (iGuide = 0; iGuide < analParams.nGuides; iGuide++) pGuides[iGuide].fFreq = analParams.fDefaultFundamental * (iGuide + 1); } /* update guides with fundamental contribution */ if (fFund > 0 && (analParams.iFormat == FORMAT_HARMONIC || analParams.iFormat == FORMAT_HARMONIC_WITH_PHASE)) for(iGuide = 0; iGuide < analParams.nGuides; iGuide++) pGuides[iGuide].fFreq = (1 - analParams.fFundContToGuide) * pGuides[iGuide].fFreq + analParams.fFundContToGuide * fFund * (iGuide + 1); if (analParams.iDebugMode == DEBUG_PEAK_CONT || analParams.iDebugMode == DEBUG_ALL) fprintf (stdout, "Frame %d Peak Continuation: \n", ppFrames[iFrame]->iFrameNum); /* continue all guides */ for (iGuide = 0; iGuide < analParams.nGuides; iGuide++) { float fPreviousFreq = ppFrames[iFrame-1]->deterministic.pFFreqTraj[iGuide]; /* get the guide value by upgrading the previous guide */ if (fPreviousFreq > 0) pGuides[iGuide].fFreq = (1 - analParams.fPeakContToGuide) * pGuides[iGuide].fFreq + analParams.fPeakContToGuide * fPreviousFreq; if (analParams.iDebugMode == DEBUG_PEAK_CONT || analParams.iDebugMode == DEBUG_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 > analParams.fHighestFreq) { pGuides[iGuide].iStatus = DEAD; pGuides[iGuide].fFreq = 0; continue; } pGuides[iGuide].iPeakChosen = -1; if (analParams.iFormat == FORMAT_INHARMONIC || analParams.iFormat == FORMAT_INHARMONIC_WITH_PHASE) fFreqDev = pGuides[iGuide].fFreq * analParams.fFreqDeviation; /* get the best peak for the guide */ iGoodPeak = GetBestPeak(pGuides, iGuide, ppFrames[iFrame]->pSpectralPeaks, analParams, fFreqDev); } /* try to find good peaks for the DEAD guides */ if (analParams.iFormat == FORMAT_INHARMONIC || analParams.iFormat == FORMAT_INHARMONIC_WITH_PHASE) for(iGuide = 0; iGuide < analParams.nGuides; iGuide++) { if (pGuides[iGuide].iStatus != DEAD) continue; if (GetStartingPeak (iGuide, pGuides, analParams.nGuides, ppFrames[iFrame]->pSpectralPeaks, &fCurrentMax) == -1) break; } /* save all the continuation values, * assume output trajectories are already clear */ for (iGuide = 0; iGuide < analParams.nGuides; iGuide++) { if (pGuides[iGuide].iStatus == DEAD) continue; if (analParams.iFormat == FORMAT_INHARMONIC || analParams.iFormat == FORMAT_INHARMONIC_WITH_PHASE) { if (pGuides[iGuide].iStatus > 0 && pGuides[iGuide].iPeakChosen == -1) { if(pGuides[iGuide].iStatus++ > analParams.iMaxSleepingTime) { pGuides[iGuide].iStatus = DEAD; pGuides[iGuide].fFreq = 0; pGuides[iGuide].fMag = 0; pGuides[iGuide].iPeakChosen = -1; } else pGuides[iGuide].iStatus++; continue; } if (pGuides[iGuide].iStatus == ACTIVE && pGuides[iGuide].iPeakChosen == -1) { pGuides[iGuide].iStatus = 1; continue; } } /* if good continuation peak found, save it */ if ((iCurrentPeak = pGuides[iGuide].iPeakChosen) >= 0) { ppFrames[iFrame]->deterministic.pFFreqTraj[iGuide] = ppFrames[iFrame]->pSpectralPeaks[iCurrentPeak].fFreq; ppFrames[iFrame]->deterministic.pFMagTraj[iGuide] = ppFrames[iFrame]->pSpectralPeaks[iCurrentPeak].fMag; ppFrames[iFrame]->deterministic.pFPhaTraj[iGuide] = ppFrames[iFrame]->pSpectralPeaks[iCurrentPeak].fPhase; pGuides[iGuide].iStatus = ACTIVE; pGuides[iGuide].iPeakChosen = -1; } } return 1; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.