~ubuntu-branches/debian/lenny/libofa/lenny

« back to all changes in this revision

Viewing changes to lib/frametracker_op.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Lukáš Lalinský
  • Date: 2006-08-21 23:06:01 UTC
  • Revision ID: james.westby@ubuntu.com-20060821230601-ik253yugpxbbo9xt
Tags: upstream-0.9.3
Import upstream version 0.9.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* ------------------------------------------------------------------
 
2
 
 
3
   libofa -- the Open Fingerprint Architecture library
 
4
 
 
5
   Copyright (C) 2006 MusicIP Corporation
 
6
   All rights reserved.
 
7
 
 
8
-------------------------------------------------------------------*/
 
9
// FILE: "frametracker_op.cpp"
 
10
// MODULE: Implementation for class FrameTracker
 
11
// AUTHOR: Stephen Pope, Frode Holm
 
12
// DATE CREATED: 01/12/06
 
13
 
 
14
#include <math.h>
 
15
#include "frametracker_op.h"
 
16
#include "trackdata_op.h"
 
17
 
 
18
// Constructor
 
19
 
 
20
FrameTracker_op::FrameTracker_op(float peakT, float fThresh, float lenT, int maxTrax)
 
21
{
 
22
        PeakThreshold = peakT;
 
23
        FreqThreshold = fThresh;
 
24
        LengthThreshold = lenT;
 
25
        MaxTracks = maxTrax;
 
26
        PeakWidth = 2;          // width of peak interval (on one side)
 
27
        BaseFr = 0;
 
28
}
 
29
 
 
30
// Destructor
 
31
 
 
32
FrameTracker_op::~FrameTracker_op() 
 
33
 
34
        BaseFr = 0;
 
35
}
 
36
 
 
37
 
 
38
void 
 
39
FrameTracker_op::Compute(FFT_op& spectra) 
 
40
{
 
41
        double sdur = spectra.GetStepDur();
 
42
 
 
43
        int numFrames = spectra.GetNumFrames();
 
44
 
 
45
        // Detect the peaks in each frame
 
46
        for (int i = 0; i < numFrames; i++) 
 
47
        {               
 
48
                float realTime = (float)(i * sdur);
 
49
                TrackFrame_op* thePeaks = new TrackFrame_op(realTime);
 
50
 
 
51
                FindPeaks(spectra, i, thePeaks);
 
52
                Tracks.Add(thePeaks);                           // add the frame to the track list
 
53
        }
 
54
                                        
 
55
        TrackPeaks();                                                   // Track the peaks between frames
 
56
        ContinuePeaks();                                                // Try to extend the tracks
 
57
}
 
58
 
 
59
// Find the peaks in a single frame;
 
60
// use local-max detection over the min threshold
 
61
void 
 
62
FrameTracker_op::FindPeaks(FFT_op& data, int frameNum, TrackFrame_op* thePeaks) 
 
63
{
 
64
 
 
65
        int numBins = data.GetNumBins();
 
66
        float* frame = data.GetFrame(frameNum);
 
67
        int npeak = 0;
 
68
        double realTime = frameNum * data.GetStepDur();
 
69
        TrackData_op* prevP = 0;
 
70
        float prevPV = * frame++;                       // previous previous sample
 
71
        float prevV = * frame++;                        // previous sample
 
72
        float thisV = * frame++;                        // this sample
 
73
        float nextV = * frame++;                        // next sample
 
74
        for (int i = 4; i < (numBins - 2); i++) 
 
75
        {
 
76
                float nextNV = * frame++;               // next next sample
 
77
 
 
78
                                                                        // check for peak relatively > PeakThreshold
 
79
                bool found = (thisV > PeakThreshold) && (thisV > prevV) && (thisV > nextV);
 
80
 
 
81
                if (found && (PeakWidth > 1))   // if using wide peaks, compare prevPV and nextNV
 
82
                        found = found && (thisV > prevPV) && (thisV > nextNV);
 
83
 
 
84
                if (found) 
 
85
                {
 
86
                                                                        // If peak detected, do cubic interpolation for index,                                                                  // freq, and magnitude -- first calculate "real" index
 
87
                        double realIndex = ((prevV - nextV) * 0.5) / (prevV - (2.0 * thisV) + nextV);
 
88
                                                                        // then interpolate the real magnitude and frequency
 
89
                        double realPeak = thisV - ((prevV - nextV) * 0.25 * realIndex);
 
90
                        double realFreq = data.GetFreqStep() * (float)(i-2);
 
91
                                                                        // Add the new peak to the list and link it in
 
92
                        TrackData_op* thisP = new TrackData_op((float)realTime, (float)realFreq, (float)realPeak, (float)data.GetStepDur());
 
93
                        if (prevP != 0)
 
94
                                prevP->linkHigher(thisP);
 
95
                        prevP = thisP;
 
96
                        thePeaks->Add(thisP);
 
97
                        npeak++;
 
98
                }
 
99
                prevPV = prevV;                         // step the values to the next freq. bin
 
100
                prevV = thisV;
 
101
                thisV = nextV;
 
102
                nextV = nextNV;
 
103
        }
 
104
}
 
105
 
 
106
// Answer the best match for the given frequency in the given frame
 
107
TrackData_op* 
 
108
FrameTracker_op::GetBestMatch(float pitch, TrackFrame_op* frame) 
 
109
{
 
110
        TrackData_op* match =  frame->getTrackNearestFreq(pitch);
 
111
        if (match != 0) {                               // If it's within the freq. range FreqThreshold
 
112
                double frqDiff = fabs(log(match->getPitch()) - log(pitch));
 
113
                if (frqDiff < FreqThreshold)
 
114
                        return match;
 
115
        }
 
116
        return 0;
 
117
}
 
118
 
 
119
// Track and group peaks in the given data set;
 
120
// do a running forward/backward comparison of all peaks in a track
 
121
 
 
122
void 
 
123
FrameTracker_op::TrackPeaks() 
 
124
{
 
125
 
 
126
        TrackFrame_op* prevFr = Tracks.getBaseFrame();
 
127
        TrackFrame_op* thisFr = prevFr->getNext();
 
128
        TrackFrame_op* nextFr = thisFr->getNext();
 
129
        TrackFrame_op* lastFr = nextFr->getNext();
 
130
        while (thisFr != 0) {                           // Iterate over the frames trying to track peaks
 
131
                TrackData_op* baseTr = prevFr->getBaseTrack();
 
132
                                                                                // Try to track the previous frame's peaks into this frame
 
133
                while (baseTr != 0) {                   // Find the best freq. match between track and current pks
 
134
                        float baseP = baseTr->getPitch();
 
135
                        TrackData_op* match =  GetBestMatch(baseP, thisFr);
 
136
                        if (match != 0) {
 
137
                                baseTr->linkTo(match);                                  // create double links
 
138
                        } 
 
139
                        baseTr = baseTr->getHigher();
 
140
                }                                                                // end of current frame
 
141
                prevFr = thisFr;
 
142
                thisFr = nextFr;
 
143
                nextFr = lastFr;
 
144
                if (lastFr != 0)
 
145
                        lastFr = lastFr->getNext();
 
146
        }                                                                       // end of all tracks
 
147
}
 
148
 
 
149
// Continue track groups, and gather track statistics
 
150
 
 
151
void 
 
152
FrameTracker_op::ContinuePeaks() 
 
153
{
 
154
 
 
155
        TrackFrame_op* base = Tracks.getBaseFrame();
 
156
        while (base != 0) {                     // Iterate over all frames
 
157
                TrackData_op* td = base->getBaseTrack();
 
158
                while (td != 0) {               // Iterate over peaks in a frame
 
159
                        if (td->isHead()) {
 
160
                                float am = td->getAmplitude();
 
161
                                float pc = td->getPitch();
 
162
                                float avgA = am;
 
163
                                float avgP = pc;
 
164
                                int i = 1;
 
165
                                TrackData_op* tl = td->getNext();
 
166
                                while (tl != 0) {               // Iterate forward over peaks in a track
 
167
                                        am = tl->getAmplitude();
 
168
                                        pc = tl->getPitch();
 
169
                                        avgA += am;
 
170
                                        avgP += pc;
 
171
                                        td->setEndPitch(pc);
 
172
                                        tl = tl->getNext();
 
173
                                        i++;
 
174
                                }               // end of links
 
175
                                td->setAvgAmplitude(avgA / (float) i);
 
176
                                td->setAvgPitch(avgP / (float) i);
 
177
                        }                       // end of track
 
178
                        td = td->getHigher();                   // go to next peak in frame
 
179
                }                               // end of frame
 
180
                base = base->getNext();                         // go to next frame
 
181
        }
 
182
}
 
183