delaydetectiontest.cpp 6.65 KB
Newer Older
1
/*
2
 *  Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010 Savoir-Faire Linux Inc.
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
 *  Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *  Additional permission under GNU GPL version 3 section 7:
 *
 *  If you modify this program, or any covered work, by linking or
 *  combining it with the OpenSSL project's OpenSSL library (or a
 *  modified version of that library), containing parts covered by the
 *  terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
 *  grants you additional permission to convey the resulting work.
 *  Corresponding Source for a non-source form of such a combination
 *  shall include the source code for the parts of OpenSSL used as well
 *  as that of the covered work.
 */


#include "delaydetectiontest.h"
Tristan Matthews's avatar
Tristan Matthews committed
33
#include <cstring>
34
#include "array_size.h"
35

Emmanuel Milou's avatar
[#2402]  
Emmanuel Milou committed
36 37
void DelayDetectionTest::testCrossCorrelation()
{
38 39
    float signal[10] = {0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0,  7.0, 8.0, 9.0};
    float ref[3] = {0.0, 1.0, 2.0};
40

41 42
    float result[10];
    float expected[10] = {0.0, 0.89442719, 1.0, 0.95618289, 0.91350028, 0.88543774, 0.86640023, 0.85280287, 0.8426548, 0.83480969};
43

44 45
    CPPUNIT_ASSERT(delaydetect_.correlate(ref, ref, 3) == 5.0);
    CPPUNIT_ASSERT(delaydetect_.correlate(signal, signal, 10) == 285.0);
46

47
    delaydetect_.crossCorrelate(ref, signal, result, 3, 10);
48

49
    float tmp;
50

Tristan Matthews's avatar
Tristan Matthews committed
51
    for (int i = 0; i < ARRAYSIZE(result); i++) {
52
        tmp = result[i] - expected[i];
53 54

        if (tmp < 0.0)
55
            CPPUNIT_ASSERT(tmp > -0.001);
56
        else
57
            CPPUNIT_ASSERT(tmp < 0.001);
58
    }
59 60
}

Emmanuel Milou's avatar
[#2402]  
Emmanuel Milou committed
61 62
void DelayDetectionTest::testCrossCorrelationDelay()
{
63 64 65 66
    float signal[10] = {0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0,  0.0, 0.0, 0.0};
    float ref[3] = {0.0, 1.0, 0.0};

    float result[10];
67

68
    delaydetect_.crossCorrelate(ref, signal, result, 3, 10);
69

70
//    float expected[10] = {0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0};
71 72
}

Emmanuel Milou's avatar
[#2402]  
Emmanuel Milou committed
73 74
void DelayDetectionTest::testFirFilter()
{
Tristan Matthews's avatar
Tristan Matthews committed
75 76 77 78 79 80 81 82 83
    const float decimationCoefs[] = {-0.09870257, 0.07473655, 0.05616626, 0.04448337, 0.03630817, 0.02944626,
        0.02244098, 0.01463477, 0.00610982, -0.00266367, -0.01120109, -0.01873722,
        -0.02373243, -0.02602213, -0.02437806, -0.01869834, -0.00875287, 0.00500204,
        0.02183252, 0.04065763, 0.06015944, 0.0788299, 0.09518543, 0.10799179,
        0.1160644,  0.12889288, 0.1160644, 0.10799179, 0.09518543, 0.0788299,
        0.06015944, 0.04065763, 0.02183252, 0.00500204, -0.00875287, -0.01869834,
        -0.02437806, -0.02602213, -0.02373243, -0.01873722, -0.01120109, -0.00266367,
        0.00610982, 0.01463477, 0.02244098, 0.02944626, 0.03630817, 0.04448337,
        0.05616626,  0.07473655, -0.09870257};
Tristan Matthews's avatar
Tristan Matthews committed
84
    const std::vector<double> ird(decimationCoefs, decimationCoefs + ARRAYSIZE(decimationCoefs));
Tristan Matthews's avatar
Tristan Matthews committed
85 86 87 88 89 90 91

    const float bandpassCoefs[] = {0.06278034, -0.0758545, -0.02274943, -0.0084497, 0.0702427, 0.05986113,
        0.06436469, -0.02412049, -0.03433526, -0.07568665, -0.03214543, -0.07236507,
        -0.06979052, -0.12446371, -0.05530828, 0.00947243, 0.15294699, 0.17735563,
        0.15294699, 0.00947243, -0.05530828, -0.12446371, -0.06979052, -0.07236507,
        -0.03214543, -0.07568665, -0.03433526, -0.02412049,  0.06436469, 0.05986113,
        0.0702427, -0.0084497, -0.02274943, -0.0758545, 0.06278034};
Tristan Matthews's avatar
Tristan Matthews committed
92
    const std::vector<double> irb(bandpassCoefs, bandpassCoefs + ARRAYSIZE(bandpassCoefs));
93 94

    float impulse[100];
Tristan Matthews's avatar
Tristan Matthews committed
95
    memset(impulse, 0, sizeof(impulse))
96 97
    impulse[0] = 1.0;

98 99
    FirFilter decimationFilter_(ird);
    FirFilter bandpassFilter_(irb);
100 101

    float impulseresponse[100];
Tristan Matthews's avatar
Tristan Matthews committed
102
    memset(impulseresponse, 0, sizeof impulseresponse);
103 104

    // compute impulse response
Tristan Matthews's avatar
Tristan Matthews committed
105
    for (int i = 0; i < ARRAYSIZE(impulse); i++)
106
        impulseresponse[i] = decimationFilter_.getOutputSample(impulse[i]);
107

Tristan Matthews's avatar
Tristan Matthews committed
108 109
    for (int i = 0; i < ARRAYSIZE(decimationCoefs); ++i) {
        float tmp = decimationCoefs[i] - impulseresponse[i];
110 111

        if (tmp < 0.0)
112
            CPPUNIT_ASSERT(tmp > -0.000001);
113
        else
114
            CPPUNIT_ASSERT(tmp < 0.000001);
115 116 117
    }


Tristan Matthews's avatar
Tristan Matthews committed
118
    for (size_t i = 0; i < ARRAYSIZE(impulseresponse); ++i)
119
        impulseresponse[i] = bandpassFilter_.getOutputSample(impulse[i]);
120

Tristan Matthews's avatar
Tristan Matthews committed
121
    for (size_t i = 0; i < ARRAYSIZE(bandpassCoefs); ++i) {
122 123 124
        tmp = bandpassCoefs[i] - impulseresponse[i];

        if (tmp < 0.0)
125
            CPPUNIT_ASSERT(tmp > -0.000001);
126
        else
127
            CPPUNIT_ASSERT(tmp < 0.000001);
128 129 130
    }
}

Emmanuel Milou's avatar
[#2402]  
Emmanuel Milou committed
131 132
void DelayDetectionTest::testIntToFloatConversion()
{
Tristan Matthews's avatar
Tristan Matthews committed
133 134
    SFLDataFormat data[32768 * 2];
    float converted[ARRAYSIZE(data)];
135

136
    for (int i = -32768; i < 32768; i++)
Tristan Matthews's avatar
Tristan Matthews committed
137
        data[i + 32768] = i;
138

Tristan Matthews's avatar
Tristan Matthews committed
139
    delaydetect_.convertInt16ToFloat32(data, converted, ARRAYSIZE(data));
140 141

    for (int i = -32768; i < 0; i++) {
Tristan Matthews's avatar
Tristan Matthews committed
142 143
        CPPUNIT_ASSERT(converted[i + 32768] >= -1.0);
        CPPUNIT_ASSERT(converted[i + 32768] <= 0.0);
144
    }
145

146
    for (int i = 0; i < 32768; i++) {
Tristan Matthews's avatar
Tristan Matthews committed
147 148
        CPPUNIT_ASSERT(converted[i + 32768] >= 0.0);
        CPPUNIT_ASSERT(converted[i + 32768] <= 1.0);
149
    }
150 151
}

Emmanuel Milou's avatar
[#2402]  
Emmanuel Milou committed
152 153
void DelayDetectionTest::testDownSamplingData()
{
Tristan Matthews's avatar
Tristan Matthews committed
154 155 156
    SFLDataFormat data[32768 * 2];
    float converted[ARRAYSIZE(data)];
    float resampled[ARRAYSIZE(data)];
157 158

    for (int i = -32768; i < 32768; i++)
Tristan Matthews's avatar
Tristan Matthews committed
159
        data[i + 32768] = i;
160

Tristan Matthews's avatar
Tristan Matthews committed
161
    delaydetect_.convertInt16ToFloat32(data, converted, 32768 * 2);
162

Tristan Matthews's avatar
Tristan Matthews committed
163
    delaydetect_.downsampleData(converted, resampled, 32768 * 2, 8);
164

Tristan Matthews's avatar
Tristan Matthews committed
165
    for (size_t i = 0; i < 32768 / 8; ++i) {
166 167
        CPPUNIT_ASSERT(resampled[i] >= -1.0);
        CPPUNIT_ASSERT(resampled[i] <= 0.0);
168
    }
169

Tristan Matthews's avatar
Tristan Matthews committed
170
    for (size_t i = 32768 / 8 + 1; i < 32768 / 4; i++) {
171 172
        CPPUNIT_ASSERT(resampled[i] >= 0.0);
        CPPUNIT_ASSERT(resampled[i] <= 1.0);
173
    }
174 175 176


}
177 178


Emmanuel Milou's avatar
[#2402]  
Emmanuel Milou committed
179 180
void DelayDetectionTest::testDelayDetection()
{
181
    SFLDataFormat spkr[WINDOW_SIZE];
Tristan Matthews's avatar
Tristan Matthews committed
182 183 184
    memset(spkr, 0, sizeof spkr);
    for (size_t i = 0; i < 5; ++i)
        spkr[i] = 32000;
185 186

    SFLDataFormat mic[DELAY_BUFF_SIZE];
Tristan Matthews's avatar
Tristan Matthews committed
187 188 189 190 191 192
    memset(mic, 0, sizeof mic);
    for (size_t delay = 100; delay < 105; ++delay)
        mic[delay] = 32000;

    delaydetect_.putData(spkr, ARRAYSIZE(spkr));
    delaydetect_.process(mic, ARRAYSIZE(mic));
193
}