analysistransform.cpp 3.32 KB
Newer Older
1
2
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#include "analysistransform.h"



// Create a constructor for analysis transform
analysistransform::analysistransform()
{
    this->signallength = 20480;
    this->windowsize = 2048;
    this->overlap = 1024;
    this->nofmics = 32;

    int lngth = (windowsize / 2 + 1) * (signallength / (overlap));

    outputsignal = (std::complex <float> *) malloc(sizeof(std::complex <float>) * lngth);

}

// Create a constructor for analysis transform
analysistransform::analysistransform(int windowsize=2048, int signallength=20480, int hopsize=1024,int nofmics=32)
{
    this->signallength = signallength;
    this->windowsize = windowsize;
    this->overlap = hopsize;
    this->nofmics = nofmics;

    int lngth = (windowsize / 2 + 1) * (signallength / (hopsize));

    outputsignal = (std::complex <float> *) malloc(sizeof(std::complex <float>) * lngth);


}

// Create a hamming window of windowLength samples in buffer
void analysistransform::hamming(int windowLength, float* buffer) {

    for (int i = 0; i < windowLength; i++) {

        buffer[i] = 0.54 - (0.46 * cos(2 * PI * (i / ((windowLength - 1) * 1.0))));
    }
}

/*
Signal in : x[0] to x[signalLength - 1]
realpart : fft_real[0] to fft_real[N/2 -1]
imagpart : imagpart[0] to imagpart[N/2 -1]
*/
void* analysistransform::STFT(float* signal, float* realpart, float* imagpart) {


    double* data;
    fftw_complex* fft_result;
    fftw_plan       plan_forward, plan_backward;
    int             i;



    data = (double*)fftw_malloc(sizeof(double) * this->windowsize);
    fft_result = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * this->windowsize);

    int outputcounter = 0;


    plan_forward = fftw_plan_dft_r2c_1d(this->windowsize, data, fft_result, FFTW_ESTIMATE);

    // Create a hamming window of appropriate length
    float* window = (float*)malloc(sizeof(float) * this->windowsize);

    hamming(this->windowsize, window);

    int chunkPosition = 0;

    int readIndex;

    // Should we stop reading in chunks?
    int bStop = 0;

    // Process each chunk of the signal



    while (chunkPosition < this->signallength && !bStop) {

        // Copy the chunk into our buffer
        for (i = 0; i < this->windowsize; i++) {


            readIndex = chunkPosition + i;

            if (readIndex < this->signallength) {

                // Note the windowing!
                data[i] = signal[readIndex] * window[i];

            }
            else {

                // we have read beyond the signal, so zero-pad it!

                data[i] = 0.0;

                bStop = 1;

            }
        }

        // Perform the FFT on our chunk
        fftw_execute(plan_forward);


        // Copy the first (windowSize/2 + 1) data points into your spectrogram.
        // We do this because the FFT output is mirrored about the nyquist
        // frequency, so the second half of the data is redundant. This is how
        // Matlab's spectrogram routine works.


        for (i = 0; i < this->windowsize / 2; i++) {

            *(realpart + outputcounter) = fft_result[i][0];
            *(imagpart + outputcounter) = fft_result[i][1];

            outputcounter += this->nofmics;
        }


        chunkPosition += this->overlap;

    } // Excuse the formatting, the while ends here.

    fftw_destroy_plan(plan_forward);

    fftw_free(data);
    fftw_free(fft_result);
    free(window);

    return 0;

}