Sound:
[blender-staging.git] / intern / audaspace / fftw / AUD_BandPassReader.cpp
1 /*
2  * $Id$
3  *
4  * ***** BEGIN LGPL LICENSE BLOCK *****
5  *
6  * Copyright 2009 Jörg Hermann Müller
7  *
8  * This file is part of AudaSpace.
9  *
10  * AudaSpace is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU Lesser General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * AudaSpace is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * along with AudaSpace.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  * ***** END LGPL LICENSE BLOCK *****
24  */
25
26 #include "AUD_BandPassReader.h"
27 #include "AUD_Buffer.h"
28
29 #include <cstring>
30 #include <stdio.h>
31
32 AUD_BandPassReader::AUD_BandPassReader(AUD_IReader* reader, float low,
33                                                                            float high) :
34                 AUD_EffectReader(reader), m_low(low), m_high(high)
35 {
36         m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
37         m_in = new AUD_Buffer(); AUD_NEW("buffer")
38         m_out = new AUD_Buffer(); AUD_NEW("buffer")
39         m_length = 0;
40 }
41
42 AUD_BandPassReader::~AUD_BandPassReader()
43 {
44         if(m_length != 0)
45         {
46                 fftw_destroy_plan(m_forward);
47                 fftw_destroy_plan(m_backward);
48         }
49
50         delete m_buffer; AUD_DELETE("buffer")
51         delete m_in; AUD_DELETE("buffer")
52         delete m_out; AUD_DELETE("buffer")
53 }
54
55 AUD_ReaderType AUD_BandPassReader::getType()
56 {
57         return m_reader->getType();
58 }
59
60 void AUD_BandPassReader::read(int & length, sample_t* & buffer)
61 {
62         AUD_Specs specs = m_reader->getSpecs();
63
64         m_reader->read(length, buffer);
65
66         if(length > 0)
67         {
68                 if(length * AUD_SAMPLE_SIZE(specs) > m_buffer->getSize())
69                         m_buffer->resize(length * AUD_SAMPLE_SIZE(specs));
70
71                 if(length != m_length)
72                 {
73                         if(m_length != 0)
74                         {
75                                 fftw_destroy_plan(m_forward);
76                                 fftw_destroy_plan(m_backward);
77                         }
78
79                         m_length = length;
80                         printf("WINDOW: %d\n", m_length);
81
82                         if(m_length * sizeof(double) > m_in->getSize())
83                         {
84                                 m_in->resize(m_length * sizeof(double));
85                                 m_out->resize((m_length / 2 + 1) * sizeof(fftw_complex));
86                         }
87
88                         m_forward = fftw_plan_dft_r2c_1d(m_length,
89                                                                                          (double*)m_in->getBuffer(),
90                                                                                          (fftw_complex*)m_out->getBuffer(),
91                                                                                          FFTW_ESTIMATE);
92                         m_backward = fftw_plan_dft_c2r_1d(m_length,
93                                                                                           (fftw_complex*)m_out->getBuffer(),
94                                                                                           (double*)m_in->getBuffer(),
95                                                                                           FFTW_ESTIMATE);
96                 }
97
98                 float* source = (float*) buffer;
99                 double* target = (double*) m_in->getBuffer();
100                 float* target2 = (float*) m_buffer->getBuffer();
101                 fftw_complex* complex = (fftw_complex*) m_out->getBuffer();
102                 float frequency;
103
104                 for(int channel = 0; channel < specs.channels; channel++)
105                 {
106                         for(int i = 0; i < m_length; i++)
107                                 target[i] = source[i * specs.channels + channel];
108
109                         fftw_execute(m_forward);
110
111                         for(int i = 0; i < m_length / 2 + 1; i++)
112                         {
113                                 frequency = i * specs.rate / (m_length / 2.0 + 1.0);
114                                 if((frequency < m_low) || (frequency > m_high))
115                                         complex[i][0] = complex[i][1] = 0.0;
116                         }
117
118                         fftw_execute(m_backward);
119
120                         for(int i = 0; i < m_length; i++)
121                                 target2[i * specs.channels + channel] = target[i] / m_length;
122                 }
123         }
124
125         buffer = m_buffer->getBuffer();
126 }