OpenShot Library | libopenshot  0.3.3
STFT.cpp
Go to the documentation of this file.
1 // © OpenShot Studios, LLC
2 //
3 // SPDX-License-Identifier: LGPL-3.0-or-later
4 
5 #include "STFT.h"
6 
7 using namespace openshot;
8 
9 void STFT::setup(const int num_input_channels)
10 {
11  num_channels = (num_input_channels > 0) ? num_input_channels : 1;
12 }
13 
14 void STFT::updateParameters(const int new_fft_size, const int new_overlap, const int new_window_type)
15 {
16  updateFftSize(new_fft_size);
17  updateHopSize(new_overlap);
18  updateWindow(new_window_type);
19 }
20 
22 {
23  num_samples = block.getNumSamples();
24 
25  for (int channel = 0; channel < num_channels; ++channel) {
26  float *channel_data = block.getWritePointer(channel);
27 
32 
33  for (int sample = 0; sample < num_samples; ++sample) {
34  const float input_sample = channel_data[sample];
35 
36  input_buffer.setSample(channel, current_input_buffer_write_position, input_sample);
39  // diff
40  channel_data[sample] = output_buffer.getSample(channel, current_output_buffer_read_position);
41 
42  output_buffer.setSample(channel, current_output_buffer_read_position, 0.0f);
45 
48  analysis(channel);
49  modification(channel);
50  synthesis(channel);
51  }
52  }
53  }
54 
59 }
60 
61 
62 void STFT::updateFftSize(const int new_fft_size)
63 {
64  if (new_fft_size != fft_size)
65  {
66  fft_size = new_fft_size;
67  fft = std::make_unique<juce::dsp::FFT>(log2(fft_size));
68 
70  input_buffer.clear();
72 
74  output_buffer.clear();
76 
77  fft_window.realloc(fft_size);
78  fft_window.clear(fft_size);
79 
82 
85 
90  }
91 }
92 
93 void STFT::updateHopSize(const int new_overlap)
94 {
95  if (new_overlap != overlap)
96  {
97  overlap = new_overlap;
98 
99  if (overlap != 0) {
102  }
103  }
104 }
105 
106 
107 void STFT::updateWindow(const int new_window_type)
108 {
109  window_type = new_window_type;
110 
111  switch (window_type) {
112  case RECTANGULAR: {
113  for (int sample = 0; sample < fft_size; ++sample)
114  fft_window[sample] = 1.0f;
115  break;
116  }
117  case BART_LETT: {
118  for (int sample = 0; sample < fft_size; ++sample)
119  fft_window[sample] = 1.0f - fabs (2.0f * (float)sample / (float)(fft_size - 1) - 1.0f);
120  break;
121  }
122  case HANN: {
123  for (int sample = 0; sample < fft_size; ++sample)
124  fft_window[sample] = 0.5f - 0.5f * cosf (2.0f * M_PI * (float)sample / (float)(fft_size - 1));
125  break;
126  }
127  case HAMMING: {
128  for (int sample = 0; sample < fft_size; ++sample)
129  fft_window[sample] = 0.54f - 0.46f * cosf (2.0f * M_PI * (float)sample / (float)(fft_size - 1));
130  break;
131  }
132  }
133 
134  float window_sum = 0.0f;
135  for (int sample = 0; sample < fft_size; ++sample)
136  window_sum += fft_window[sample];
137 
138  window_scale_factor = 0.0f;
139  if (overlap != 0 && window_sum != 0.0f)
140  window_scale_factor = 1.0f / (float)overlap / window_sum * (float)fft_size;
141 }
142 
143 
144 
145 void STFT::analysis(const int channel)
146 {
147  int input_buffer_index = current_input_buffer_write_position;
148  for (int index = 0; index < fft_size; ++index) {
149  time_domain_buffer[index].real(fft_window[index] * input_buffer.getSample(channel, input_buffer_index));
150  time_domain_buffer[index].imag(0.0f);
151 
152  if (++input_buffer_index >= input_buffer_length)
153  input_buffer_index = 0;
154  }
155 }
156 
157 void STFT::modification(const int channel)
158 {
160 
161  for (int index = 0; index < fft_size / 2 + 1; ++index) {
162  float magnitude = abs(frequency_domain_buffer[index]);
163  float phase = arg(frequency_domain_buffer[index]);
164 
165  frequency_domain_buffer[index].real(magnitude * cosf (phase));
166  frequency_domain_buffer[index].imag(magnitude * sinf (phase));
167 
168  if (index > 0 && index < fft_size / 2) {
169  frequency_domain_buffer[fft_size - index].real(magnitude * cosf (phase));
170  frequency_domain_buffer[fft_size - index].imag(magnitude * sinf (-phase));
171  }
172  }
173 
175 }
176 
177 void STFT::synthesis(const int channel)
178 {
179  int output_buffer_index = current_output_buffer_write_position;
180  for (int index = 0; index < fft_size; ++index) {
181  float output_sample = output_buffer.getSample(channel, output_buffer_index);
182  output_sample += time_domain_buffer[index].real() * window_scale_factor;
183  output_buffer.setSample(channel, output_buffer_index, output_sample);
184 
185  if (++output_buffer_index >= output_buffer_length)
186  output_buffer_index = 0;
187  }
188 
192 }
openshot
This namespace is the default namespace for all code in the openshot library.
Definition: Compressor.h:28
openshot::STFT::input_buffer_length
int input_buffer_length
Definition: STFT.h:55
juce::AudioBuffer< float >
openshot::STFT::current_output_buffer_write_position
int current_output_buffer_write_position
Definition: STFT.h:76
openshot::RECTANGULAR
@ RECTANGULAR
Definition: Enums.h:113
openshot::STFT::window_type
int window_type
Definition: STFT.h:67
openshot::STFT::fft
std::unique_ptr< juce::dsp::FFT > fft
Definition: STFT.h:53
openshot::STFT::current_input_buffer_write_position
int current_input_buffer_write_position
Definition: STFT.h:75
openshot::STFT::num_samples
int num_samples
Definition: STFT.h:50
openshot::STFT::updateFftSize
virtual void updateFftSize(const int new_fft_size)
Definition: STFT.cpp:62
openshot::BART_LETT
@ BART_LETT
Definition: Enums.h:114
openshot::STFT::updateHopSize
virtual void updateHopSize(const int new_overlap)
Definition: STFT.cpp:93
openshot::STFT::frequency_domain_buffer
juce::HeapBlock< juce::dsp::Complex< float > > frequency_domain_buffer
Definition: STFT.h:63
openshot::STFT::output_buffer_length
int output_buffer_length
Definition: STFT.h:58
openshot::STFT::current_output_buffer_read_position
int current_output_buffer_read_position
Definition: STFT.h:77
openshot::STFT::samples_since_last_FFT
int samples_since_last_FFT
Definition: STFT.h:73
openshot::STFT::num_channels
int num_channels
Definition: STFT.h:49
openshot::STFT::process
void process(juce::AudioBuffer< float > &block)
Definition: STFT.cpp:21
openshot::STFT::window_scale_factor
float window_scale_factor
Definition: STFT.h:68
openshot::HAMMING
@ HAMMING
Definition: Enums.h:116
openshot::STFT::fft_size
int fft_size
Definition: STFT.h:52
openshot::STFT::input_buffer
juce::AudioBuffer< float > input_buffer
Definition: STFT.h:56
openshot::STFT::updateWindow
virtual void updateWindow(const int new_window_type)
Definition: STFT.cpp:107
openshot::STFT::hop_size
int hop_size
Definition: STFT.h:66
openshot::STFT::output_buffer_read_position
int output_buffer_read_position
Definition: STFT.h:72
openshot::STFT::updateParameters
void updateParameters(const int new_fft_size, const int new_overlap, const int new_window_type)
Definition: STFT.cpp:14
openshot::STFT::time_domain_buffer
juce::HeapBlock< juce::dsp::Complex< float > > time_domain_buffer
Definition: STFT.h:62
openshot::STFT::output_buffer
juce::AudioBuffer< float > output_buffer
Definition: STFT.h:59
openshot::STFT::input_buffer_write_position
int input_buffer_write_position
Definition: STFT.h:70
openshot::HANN
@ HANN
Definition: Enums.h:115
openshot::STFT::output_buffer_write_position
int output_buffer_write_position
Definition: STFT.h:71
STFT.h
openshot::STFT::overlap
int overlap
Definition: STFT.h:65
openshot::STFT::setup
void setup(const int num_input_channels)
Definition: STFT.cpp:9
openshot::STFT::fft_window
juce::HeapBlock< float > fft_window
Definition: STFT.h:61
openshot::STFT::current_samples_since_last_FFT
int current_samples_since_last_FFT
Definition: STFT.h:78