summaryrefslogtreecommitdiff
path: root/src/sms/analysis.c
diff options
context:
space:
mode:
authorJohn Glover <j@johnglover.net>2013-01-21 22:08:31 +0100
committerJohn Glover <j@johnglover.net>2013-01-21 22:08:31 +0100
commit4d00d10a308c4a0337f56d4c95b5f62596bbb69e (patch)
tree84316e64a8f42359bc9992002cdb5cddbc793b8a /src/sms/analysis.c
parent0e39f53d8e2092018ae54f1e6679ab837511da77 (diff)
downloadsimpl-4d00d10a308c4a0337f56d4c95b5f62596bbb69e.tar.gz
simpl-4d00d10a308c4a0337f56d4c95b5f62596bbb69e.tar.bz2
simpl-4d00d10a308c4a0337f56d4c95b5f62596bbb69e.zip
[partial_tracking,sms] Fix bug in SMS partial tracking.
GetNextClosestPeak was missing peaks in some situations. Some general tidy up of SMS partial tracking code.
Diffstat (limited to 'src/sms/analysis.c')
-rw-r--r--src/sms/analysis.c65
1 files changed, 41 insertions, 24 deletions
diff --git a/src/sms/analysis.c b/src/sms/analysis.c
index b904449..2355a8f 100644
--- a/src/sms/analysis.c
+++ b/src/sms/analysis.c
@@ -254,15 +254,25 @@ int sms_findPeaks(int sizeWaveform, sfloat *pWaveform, SMS_AnalParams *pAnalPara
void sms_setPeaks(SMS_AnalParams *pAnalParams, int numamps, sfloat* amps,
int numfreqs, sfloat* freqs, int numphases, sfloat* phases)
{
+ if(pAnalParams->iMaxDelayFrames < 2)
+ {
+ printf("Error: iMaxDelayFrames analysis parameter must be at least 2"
+ " (currently set to %d)\n", pAnalParams->iMaxDelayFrames);
+ return;
+ }
+
int i;
SMS_AnalFrame *tempFrame;
- int currentFrame = pAnalParams->iMaxDelayFrames - 1; /* frame # of current frame */
+
+ int currentFrame = pAnalParams->iMaxDelayFrames > 2 ? pAnalParams->iMaxDelayFrames - 1 : 1;
/* 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;
+ {
+ pAnalParams->ppFrames[i - 1] = pAnalParams->ppFrames[i];
+ }
+ pAnalParams->ppFrames[currentFrame] = tempFrame;
/* initialize the current frame */
SMS_AnalFrame *frame = pAnalParams->ppFrames[currentFrame];
@@ -289,14 +299,20 @@ void sms_setPeaks(SMS_AnalParams *pAnalParams, int numamps, sfloat* amps,
{
/* get a reference fundamental */
sfloat refFundamental = 0;
- sfloat avgDeviation = sms_fundDeviation(pAnalParams, currentFrame-1);
+ sfloat avgDeviation = sms_fundDeviation(pAnalParams, currentFrame - 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[currentFrame-1]->fFundamental;
+ }
else
+ {
refFundamental = 0;
+ }
frame->fFundamental = sms_harmDetection(frame->nPeaks, frame->pSpectralPeaks,
refFundamental, pAnalParams->iRefHarmonic,
@@ -308,52 +324,53 @@ void sms_setPeaks(SMS_AnalParams *pAnalParams, int numamps, sfloat* amps,
int sms_findPartials(SMS_Data *pSmsData, SMS_AnalParams *pAnalParams)
{
- int currentFrame = pAnalParams->iMaxDelayFrames - 1;
+ if(pAnalParams->iMaxDelayFrames < 2)
+ {
+ printf("Error: iMaxDelayFrames analysis parameter must be at least 2"
+ " (currently set to %d)\n", pAnalParams->iMaxDelayFrames);
+ return 1;
+ }
+
+ int currentFrame = pAnalParams->iMaxDelayFrames > 2 ? pAnalParams->iMaxDelayFrames - 1 : 1;
- /* 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.
- */
int delayFrames = pAnalParams->minGoodFrames + pAnalParams->analDelay;
- if(delayFrames > (pAnalParams->iMaxDelayFrames - 1))
- delayFrames = pAnalParams->iMaxDelayFrames - 1;
+ if(delayFrames >= currentFrame)
+ {
+ printf("Error: analysis delay is too large (%d, max is %d)\n",
+ delayFrames, currentFrame - 1);
+ return 1;
+ }
- /* clear SMS output */
sms_clearFrame(pSmsData);
- /* incorporate the peaks into the corresponding tracks */
- if(pAnalParams->ppFrames[currentFrame-delayFrames]->fFundamental > 0 ||
+ if(pAnalParams->ppFrames[currentFrame - delayFrames]->fFundamental > 0 ||
((pAnalParams->iFormat == SMS_FORMAT_IH || pAnalParams->iFormat == SMS_FORMAT_IHP) &&
- pAnalParams->ppFrames[currentFrame-delayFrames]->nPeaks > 0))
+ pAnalParams->ppFrames[currentFrame - delayFrames]->nPeaks > 0))
{
- sms_peakContinuation(currentFrame-delayFrames, pAnalParams);
+ sms_peakContinuation(currentFrame - delayFrames, pAnalParams);
}
- /* fill gaps and delete short tracks */
if(pAnalParams->iCleanTracks > 0)
{
- sms_cleanTracks(currentFrame-delayFrames, pAnalParams);
+ sms_cleanTracks(currentFrame - delayFrames, pAnalParams);
}
- /* output data */
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);
+ }
- return 1;
+ return 0;
}
int sms_findResidual(int sizeSynthesis, sfloat* pSynthesis,