Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

diff.h

00001 #ifndef _DIFF_H_
00002 #define _DIFF_H_
00003 
00004 #include <cassert>
00005 #include <iostream>
00006 #include <vector>
00007 #include "debug.h"
00008 
00009 
00010 typedef std::pair <float,float> Maximum; // Point stores position and value at maxima
00011 
00012 // Calculate difference of elements in vector (aproximate derivative).
00013 // Vector must not be empty and output-vector has one less element.
00014 template <typename T>
00015 std::vector<T> diff(std::vector<T> const& input) {
00016   assert(input.size());
00017 
00018   std::vector<T> output(input.size() - 1);
00019   for(unsigned i = 0; i < output.size(); ++i) {
00020     output[i] = input[i + 1] - input[i];
00021   }
00022 
00023   return output;
00024 }
00025 
00026 template <typename T>
00027 T greatest(std::vector<T> const& xx) {
00028   assert(xx.size() >= 1);
00029 
00030   T m = xx[0];
00031 
00032   for(unsigned i = 1; i < xx.size(); ++i) {
00033     if(xx[i] > m) m = xx[i];
00034   }
00035 
00036   return m;
00037 }
00038 template <typename T>
00039 
00040 T smallest(std::vector<T> const& xx) {
00041   assert(xx.size() >= 1);
00042 
00043   T m = xx[0];
00044 
00045   for(unsigned i = 1; i < xx.size(); ++i) {
00046     if(xx[i] < m) m = xx[i];
00047   }
00048 
00049   return m;
00050 }
00051 
00052 template <typename T>
00053 double linear_interpolation(double subpos, T const& a, T const& b) {
00054   return a + subpos * (b - a);
00055 }
00056 
00057 inline double interpolate_phase(double freq, std::vector<double> const& phase) {
00058   unsigned floor = unsigned(freq);
00059   unsigned ceiling = unsigned(freq + 0.999999);
00060   double subpos = freq - (double)floor;
00061   //cout << "freq = " << freq << ", subpos = " << subpos << endl;
00062   //cout << "floor = " << floor << ", ceiling = " << ceiling << endl;
00063   //cout << "[floor] = " << phase[floor] << ", [ceiling] = " << phase[ceiling] << endl;
00064 
00065   double y = linear_interpolation(subpos, phase[floor], phase[ceiling]);
00066   //cout << "estimate = " << y << endl;
00067   return y;
00068 }
00069 
00070 // Find local maxima in xx-vector. The return-vector has sub-index
00071 // precision estimating from by polynomial approximation of
00072 // derivative. The interval [-delta;+delta] is considered zero.  Only
00073 // extrema that are greater than global_maxima * relative_threshold
00074 // are returned.
00075 
00076 template <typename T>
00077 std::vector<Maximum> local_maxima(std::vector<T> const& xx, double delta, double relative_threshold = 0.0) {
00078   std::vector<Maximum> maxima;
00079 
00080   // Perhaps threshold in frequency range should be allowed
00081   // Perhaps the magnitude frequency should be independent of data
00082 
00083   T threshold = relative_threshold * greatest(xx);
00084 
00085   for(unsigned i = 1; i < xx.size() - 1; ++i) {
00086     // Look for cross-overs where xx[i-1] <= xx[i] >= xx[i+1]
00087     if(xx[i] >= threshold && xx[i-1] + delta <= xx[i] && xx[i] - delta >= xx[i+1]) {
00088       // We approximate the signal using a polynomial defined by
00089       // points xx[i-1], xx[i] & xx[i+1]. 
00090       // xx[i-1] = A*(-1)^2 + B*(-1) + C = A - B + C
00091       // xx[i]   = A*(0)^2 + B*(0) + C = C
00092       // xx[i+1] = A*(1)^2 + B*(1) + C = A + B + C
00093       // 
00094       // This requires that: xx[i+1]=A+B+C  =>  xx[i+1]-B=A+C
00095       //                and: xx[i-1]=A-B+C  =>  xx[i-1]+B=A+C
00096       // The lines combine to make:
00097       //  xx[i+1]-B = xx[i-1]+B  =>  xx[i+1]-xx[i-1] = 2B
00098       //                         =>  B = 0.5*(xx[i+1]-xx[i-1])
00099       // 
00100       // xx[i+1] = A + B + C  =>  A = xx[i+1] - B - C
00101 
00102       //dbg2("i = %d\n", i);
00103       //dbg4("left=%f, center=%f, right=%f\n", xx[i-1], xx[i], xx[i+1]);
00104 
00105       double C = xx[i];
00106       double B = 0.5 * (xx[i+1] - xx[i-1]);
00107       double A = xx[i+1] - B - C;
00108       //dbg4("A=%f, B=%f, C=%f\n", A, B, C);
00109 
00110       // To find exact maximum the polynomial is differentiated
00111       // to get Y = 2AX + B which is zero in X = -B/2A
00112       double sub_idx = -0.5 * B / A;      
00113       //dbg2("sub-idx = %f\n", sub_idx);
00114       double value = A*sub_idx*sub_idx + B*sub_idx + C;
00115       //dbg2("value = %f\n", value);
00116       maxima.push_back(Maximum(sub_idx + i, value));
00117     }
00118   }
00119   return maxima;
00120 }
00121 
00122 #endif//_DIFF_H_

Generated on Tue Feb 14 16:05:52 2006 for estfunc by doxygen 1.3.6