To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

The primary repository for this project is hosted at https://github.com/cannam/constant-q-cpp/ .
This repository is a read-only copy which is updated automatically every hour.

Statistics Download as Zip
| Branch: | Revision:

root / test / TestCQTime.cpp

History | View | Annotate | Download (3.95 KB)

1
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
2

    
3
#include "cq/CQSpectrogram.h"
4

    
5
#include "dsp/Window.h"
6

    
7
#include <cmath>
8
#include <vector>
9
#include <iostream>
10

    
11
using std::vector;
12
using std::cerr;
13
using std::endl;
14

    
15
#define BOOST_TEST_DYN_LINK
16
#define BOOST_TEST_MAIN
17

    
18
#include <boost/test/unit_test.hpp>
19

    
20
BOOST_AUTO_TEST_SUITE(TestCQTime)
21

    
22
// Principle: Run a Dirac impulse through the CQ transform and check
23
// that its output has all the peak bins aligned correctly in time.
24

    
25
// Set up fs/2 = 50, frequency range 10 -> 40 i.e. 2 octaves, fixed
26
// duration of 2 seconds
27
static const double sampleRate = 100;
28
static const double cqmin = 10;
29
static const double cqmax = 40;
30
static const double bpo = 4;
31
static const int duration = sampleRate * 2;
32

    
33
// Threshold below which to ignore a column completely
34
static const double threshold = 0.08;
35

    
36
void
37
testCQTime(double t)
38
{
39
    vector<CQSpectrogram::Interpolation> interpolationTypes;
40
    interpolationTypes.push_back(CQSpectrogram::InterpolateZeros);
41
    interpolationTypes.push_back(CQSpectrogram::InterpolateHold);
42
    interpolationTypes.push_back(CQSpectrogram::InterpolateLinear);
43

    
44
    for (int k = 0; k < int(interpolationTypes.size()); ++k) {
45

    
46
        CQSpectrogram::Interpolation interp = interpolationTypes[k];
47

    
48
        CQParameters params(sampleRate, cqmin, cqmax, bpo);
49
        CQSpectrogram cq(params, interp);
50

    
51
        BOOST_CHECK_EQUAL(cq.getBinsPerOctave(), bpo);
52
        BOOST_CHECK_EQUAL(cq.getOctaves(), 2);
53

    
54
        vector<double> input(duration, 0.0);
55
        int ix = int(floor(t * sampleRate));
56
        if (ix >= duration) ix = duration-1;
57
        input[ix] = 1.0;
58

    
59
        CQSpectrogram::RealBlock output = cq.process(input);
60
        CQSpectrogram::RealBlock rest = cq.getRemainingOutput();
61
        output.insert(output.end(), rest.begin(), rest.end());
62

    
63
        BOOST_CHECK_EQUAL(output[0].size(), 
64
                          cq.getBinsPerOctave() * cq.getOctaves());
65

    
66
        vector<int> peaks;
67
        double eps = 1e-8;
68

    
69
        for (int j = 0; j < int(output[0].size()); ++j) {
70

    
71
            int maxidx = -1;
72
            double max = 0.0;
73
            for (int i = 0; i < int(output.size()); ++i) {
74
                double value = output[i][j];
75
                if (i == 0 || value + eps > max) {
76
                    max = value;
77
                    maxidx = i;
78
                }
79
            }
80

    
81
            peaks.push_back(maxidx);
82
        }
83

    
84
        for (int j = 1; j < int(peaks.size()); ++j) {
85
            int oct = j / bpo;
86
            int spacing = (1 << oct);
87
            int actual = peaks[j]/spacing;
88
            int expected = int(round(double(peaks[0])/spacing));
89
            if (actual != expected) {
90
                cerr << "ERROR: In row " << j << " (bin freq "
91
                     << cq.getBinFrequency(j) << "), interpolation " << interp
92
                     << ", maximum value for time " << t 
93
                     << "\n       found at index " << peaks[j] 
94
                     << " of " << output.size() << " which does not align with"
95
                     << " highest frequency\n       bin peak at " << peaks[0]
96
                     << " given octave spacing of " << spacing
97
                     << "\n       [latency = " << cq.getLatency()
98
                     << ", hop = " << cq.getColumnHop() << ", duration = "
99
                     << duration << ", ix = " << ix << "]" << endl;
100
                cerr << "row contains: ";
101
                for (int i = 0; i < int(output.size()); ++i) {
102
                    if (i == expected * spacing) cerr << "*";
103
                    if (i == peaks[j]) cerr << "**";
104
                    cerr << output[i][j] << " ";
105
                }
106
                cerr << endl;
107

    
108
                BOOST_CHECK_EQUAL(actual, expected);
109
            }
110
        }
111
    }
112
}
113

    
114
BOOST_AUTO_TEST_CASE(time_zero) { testCQTime(0); }
115
BOOST_AUTO_TEST_CASE(time_half) { testCQTime(0.5); }
116
BOOST_AUTO_TEST_CASE(time_one) { testCQTime(1.0); }
117
BOOST_AUTO_TEST_CASE(time_two) { testCQTime(2.0); }
118

    
119
BOOST_AUTO_TEST_SUITE_END()
120