signalanalyzer.cpp


1
#include "signalanalyzer.h"
2
3
#include <QDebug>
4
#include <qfile.h>
5
#include <QTime>
6
#include <qtimer.h>
7
#include <omp.h>
8
9
#include "configuration.h"
10
11
SignalAnalyzer::SignalAnalyzer()
12
    : QObject()
13
{
14
    fftw_init_threads();
15
    updatePlan();
16
}
17
18
void SignalAnalyzer::updatePlan()
19
{
20
    auto c = Configuration::instance();
21
    omp_set_num_threads(1); // TODO: ?
22
    fftw_plan_with_nthreads(1);
23
    auto tmp = fftw_alloc_real((c->channels+2)*c->average);
24
    m_plan = fftw_plan_dft_r2c_2d(c->average, c->channels,
25
                                  tmp, reinterpret_cast<fftw_complex*>(tmp),
26
                                  FFTW_ESTIMATE); // FFTW_MEASURE
27
    fftw_free(tmp);
28
}
29
30
SignalAnalyzer::~SignalAnalyzer()
31
{
32
33
}
34
35
void SignalAnalyzer::processQueued()
36
{
37
    if ( m_chunks.isEmpty() ) {
38
        return;
39
    }
40
    static uint32_t processed = 0;
41
42
    QTime t;
43
    t.start();
44
    auto chunk = m_chunks.takeFirst();
45
    auto s = processChunk(chunk);
46
    Q_EMIT processingFinished(s, chunk.identification);
47
    qDebug() << "processed chunk" << processed << "in" << t.elapsed() << "ms";
48
    processed++;
49
    QTimer::singleShot(3, this, &SignalAnalyzer::processQueued);
50
}
51
52
SignalAnalyzer::Spectrum SignalAnalyzer::processChunk(DataStream::DataBlock chunk)
53
{
54
    auto c = Configuration::instance();
55
    static QVector<double> value_for_bits;
56
    if ( value_for_bits.isEmpty() ) {
57
        for ( int j = 0; j <= 256; j++ ) {
58
//             value_for_bits.append(bitswap_lut[j]);
59
            value_for_bits.append(j*0.004/sqrt(50));
60
        }
61
    }
62
63
    static QVector<double> window;
64
    if ( window.isEmpty() ) {
65
        for ( int j = 0; j < c->channels; j++ ) {
66
            window.append((0.54-0.46*cos(2*3.1415*j/(c->channels-1))));
67
        }
68
    }
69
70
    Q_ASSERT(chunk.data.size() == c->average * c->channels);
71
    static auto d = fftw_alloc_real((c->channels+2)*c->average);
72
    static auto dzero = d;
73
    d = dzero;
74
75
    auto src = chunk.data.data();
76
    for ( unsigned int i = 0; i < c->average; i++ ) {
77
        for ( unsigned int j = 0; j < c->channels; j++ ) {
78
            *d++ = value_for_bits.at(*reinterpret_cast<unsigned char*>(src++)) * window.at(j);
79
        }
80
        d += 2;
81
    }
82
83
    d = dzero;
84
    fftw_execute_dft_r2c(m_plan, d, reinterpret_cast<fftw_complex*>(d));
85
86
    d = dzero;
87
    Spectrum ret(c->channels/2);
88
    for ( unsigned int j = 0; j < c->average; j += 1 ) {
89
        for ( int i = 0; i < c->channels/2; i += 1 ) {
90
            const auto re = *d++;
91
            const auto im = *d++;
92
            ret[i] += re*re + im*im;
93
        }
94
        d += 2;
95
    }
96
97
    for ( int j = 0; j < ret.size(); j++ ) {
98
        // fftw normalization
99
        ret[j] /= c->average * c->channels;
100
        // averaging
101
        ret[j] /= c->average;
102
//         ret[j] = 10*log10(ret[j]);
103
    }
104
    return ret;
105
}
106
107
void SignalAnalyzer::addData(DataStream::DataBlock chunk)
108
{
109
//     cpu_set_t cpuset;
110
//     CPU_ZERO(&cpuset);
111
//     CPU_SET(0, &cpuset);
112
//     pthread_setaffinity_np((pthread_t) pthread_self(), sizeof(cpu_set_t), &cpuset);
113
114
//     qDebug() << "adding chunk of size" << chunk.size() << "( queued:" << m_chunks.size() << ")";
115
    m_chunks.append(chunk);
116
    processQueued();
117
//     qDebug() << "processing finished";
118
}