@@ -49,8 +49,12 @@ struct AudioFFTConfig : public AudioInfo {
4949 uint8_t channel_used = 0 ;
5050 int length = 8192 ;
5151 int stride = 0 ;
52- // / Optional window function
52+ // / Optional window function for both fft and ifft
5353 WindowFunction *window_function = nullptr ;
54+ // / Optional window function for fft only
55+ WindowFunction *window_function_fft = nullptr ;
56+ // / Optional window function for ifft only
57+ WindowFunction *window_function_ifft = nullptr ;
5458 // / TX_MODE = FFT, RX_MODE = IFFT
5559 RxTxMode rxtx_mode = TX_MODE;
5660};
@@ -96,18 +100,19 @@ class FFTInverseOverlapAdder {
96100 // adds the values to the array (by applying the window function)
97101 void add (float value, int pos, WindowFunction *window_function) {
98102 float add_value = value;
99- if (window_function != nullptr )
103+ if (window_function != nullptr ) {
100104 add_value = value * window_function->factor (pos);
105+ }
101106 data[pos] += add_value;
102107 }
103108
104109 // gets the scaled audio data as result
105- void getStepData (float *result, int step_size , float maxResult) {
106- for (int j = 0 ; j < step_size ; j++) {
110+ void getStepData (float *result, int stride , float maxResult) {
111+ for (int j = 0 ; j < stride ; j++) {
107112 // determine max value to scale
108- if (rfft_max < data[j]) rfft_max = data[j];
113+ if (data[j] > rfft_max ) rfft_max = data[j];
109114 }
110- for (int j = 0 ; j < step_size ; j++) {
115+ for (int j = 0 ; j < stride ; j++) {
111116 result[j] = data[j] / rfft_max * maxResult;
112117 // clip
113118 if (result[j] > maxResult) {
@@ -118,17 +123,21 @@ class FFTInverseOverlapAdder {
118123 }
119124 }
120125 // copy data to head
121- for (int j = 0 ; j < len - step_size ; j++) {
122- data[j] = data[j + step_size ];
126+ for (int j = 0 ; j < len - stride ; j++) {
127+ data[j] = data[j + stride ];
123128 }
124129 // clear tail
125- for (int j = len - step_size ; j < len; j++) {
130+ for (int j = len - stride ; j < len; j++) {
126131 data[j] = 0.0 ;
127132 }
128133 }
129134
130135 int size () { return data.size (); }
131136
137+ void begin (){
138+ rfft_max = 0 ;
139+ }
140+
132141 protected:
133142 Vector<float > data{0 };
134143 int len = 0 ;
@@ -200,24 +209,32 @@ class AudioFFTBase : public AudioStream {
200209 // / starts the processing
201210 bool begin () override {
202211 bins = cfg.length / 2 ;
212+ // define window functions
213+ if (cfg.window_function_fft ==nullptr ) cfg.window_function_fft = cfg.window_function ;
214+ if (cfg.window_function_ifft ==nullptr ) cfg.window_function_ifft = cfg.window_function ;
215+ // define default stride value if not defined
216+ if (cfg.stride == 0 ) cfg.stride = cfg.length ;
217+
203218 if (!isPowerOfTwo (cfg.length )) {
204219 LOGE (" Len must be of the power of 2: %d" , cfg.length );
205220 return false ;
206221 }
207222 if (!p_driver->begin (cfg.length )) {
208223 LOGE (" Not enough memory" );
209224 }
210- int step_size = cfg.stride > 0 ? cfg.stride : cfg.length ;
211- if (cfg.window_function != nullptr ) {
212- cfg.window_function ->begin (step_size);
225+
226+ if (cfg.window_function_fft != nullptr ) {
227+ cfg.window_function_fft ->begin (cfg.length );
228+ }
229+ if (cfg.window_function_ifft != nullptr ) {
230+ cfg.window_function_ifft ->begin (cfg.length );
213231 }
214232
233+ int step_size = cfg.stride > 0 ? cfg.stride : cfg.length ;
215234 bool is_valid_rxtx = false ;
216235 if (cfg.rxtx_mode == TX_MODE || cfg.rxtx_mode == RXTX_MODE) {
217- if (cfg.stride > 0 && cfg.stride < cfg.length ) {
218- // holds last N bytes that need to be reprocessed
219- stride_buffer.resize ((cfg.length - cfg.stride ) * bytesPerSample ());
220- }
236+ // holds last N bytes that need to be reprocessed
237+ stride_buffer.resize ((cfg.length ) * bytesPerSample ());
221238 is_valid_rxtx = true ;
222239 }
223240 if (cfg.rxtx_mode == RX_MODE || cfg.rxtx_mode == RXTX_MODE) {
@@ -238,8 +255,11 @@ class AudioFFTBase : public AudioStream {
238255 // / Just resets the current_pos e.g. to start a new cycle
239256 void reset () {
240257 current_pos = 0 ;
241- if (cfg.window_function != nullptr ) {
242- cfg.window_function ->begin (length ());
258+ if (cfg.window_function_fft != nullptr ) {
259+ cfg.window_function_fft ->begin (cfg.length );
260+ }
261+ if (cfg.window_function_ifft != nullptr ) {
262+ cfg.window_function_ifft ->begin (cfg.length );
243263 }
244264 }
245265
@@ -290,7 +310,7 @@ class AudioFFTBase : public AudioStream {
290310
291311 // / Provides the result of a reverse FFT
292312 size_t readBytes (uint8_t *data, size_t len) override {
293- LOGD ( " setup ifft data " );
313+ TRACED ( );
294314 if (rfft_data.size () == 0 ) return 0 ;
295315 // execute rfft when we consumed all data
296316 if (has_rfft_data && rfft_data.available () == 0 ) {
@@ -432,7 +452,7 @@ class AudioFFTBase : public AudioStream {
432452 AudioFFTConfig cfg;
433453 unsigned long timestamp_begin = 0l ;
434454 unsigned long timestamp = 0l ;
435- RingBuffer <uint8_t > stride_buffer{0 };
455+ SingleBuffer <uint8_t > stride_buffer{0 };
436456 Vector<float > l_magnitudes{0 };
437457 Vector<float > step_data{0 };
438458 int bins = 0 ;
@@ -445,35 +465,35 @@ class AudioFFTBase : public AudioStream {
445465 void processSamples (const void *data, size_t samples) {
446466 T *dataT = (T *)data;
447467 T sample;
448- float sample_windowed;
449468 for (int j = 0 ; j < samples; j += cfg.channels ) {
450469 sample = dataT[j + cfg.channel_used ];
451- p_driver->setValue (current_pos, windowedSample (sample, current_pos));
452- writeStrideBuffer ((uint8_t *)&sample, sizeof (T));
453- if (++current_pos >= cfg.length ) {
454- fft<T>();
455- current_pos = 0 ;
456-
457- // reprocess data in stride buffer
458- if (stride_buffer.size () > 0 ) {
459- // reload data from stride buffer
460- while (stride_buffer.available ()) {
461- T sample;
462- stride_buffer.readArray ((uint8_t *)&sample, sizeof (T));
463- p_driver->setValue (current_pos,
464- windowedSample (sample, current_pos));
465- current_pos++;
466- }
470+ if (writeStrideBuffer ((uint8_t *)&sample, sizeof (T))){
471+ // process data if buffer is full
472+ T* samples = (T*) stride_buffer.data ();
473+ int sample_count = stride_buffer.size () / sizeof (T);
474+ assert (sample_count == cfg.length );
475+ for (int j=0 ; j< sample_count; j++){
476+ T out_sample = samples[j];
477+ p_driver->setValue (j, windowedSample (out_sample, j));
467478 }
479+
480+ fft<T>();
481+
482+ // remove stride samples
483+ stride_buffer.clearArray (cfg.stride * sizeof (T));
484+
485+ // validate available data in stride buffer
486+ if (cfg.stride == cfg.length ) assert (stride_buffer.available ()==0 );
487+
468488 }
469489 }
470490 }
471491
472492 template <typename T>
473493 T windowedSample (T sample, int pos) {
474494 T result = sample;
475- if (cfg.window_function != nullptr ) {
476- result = cfg.window_function ->factor (pos) * sample;
495+ if (cfg.window_function_fft != nullptr ) {
496+ result = cfg.window_function_fft ->factor (pos) * sample;
477497 }
478498 return result;
479499 }
@@ -498,35 +518,34 @@ class AudioFFTBase : public AudioStream {
498518 // add data to sum buffer
499519 for (int j = 0 ; j < cfg.length ; j++) {
500520 float value = p_driver->getValue (j);
501- rfft_add.add (value, j, cfg.window_function );
521+ rfft_add.add (value, j, cfg.window_function_ifft );
502522 }
503523 // get result data from sum buffer
504524 rfftWriteData (rfft_data);
505525 }
506526
507527 // / write reverse fft result to buffer to make it available for readBytes
508528 void rfftWriteData (BaseBuffer<uint8_t > &data) {
509- int step_size = cfg.stride > 0 ? cfg.stride : cfg.length ;
510529 // get data to result buffer
511- step_data.resize (step_size );
512- for (int j = 0 ; j < step_size ; j++) {
530+ step_data.resize (cfg. stride );
531+ for (int j = 0 ; j < cfg. stride ; j++) {
513532 step_data[j] = 0.0 ;
514533 }
515- rfft_add.getStepData (step_data.data (), step_size ,
534+ rfft_add.getStepData (step_data.data (), cfg. stride ,
516535 NumberConverter::maxValue (cfg.bits_per_sample ));
517536
518537 switch (cfg.bits_per_sample ) {
519538 case 8 :
520- writeIFFT<int8_t >(step_data.data (), step_size );
539+ writeIFFT<int8_t >(step_data.data (), cfg. stride );
521540 break ;
522541 case 16 :
523- writeIFFT<int16_t >(step_data.data (), step_size );
542+ writeIFFT<int16_t >(step_data.data (), cfg. stride );
524543 break ;
525544 case 24 :
526- writeIFFT<int24_t >(step_data.data (), step_size );
545+ writeIFFT<int24_t >(step_data.data (), cfg. stride );
527546 break ;
528547 case 32 :
529- writeIFFT<int32_t >(step_data.data (), step_size );
548+ writeIFFT<int32_t >(step_data.data (), cfg. stride );
530549 break ;
531550 default :
532551 LOGE (" Unsupported bits: %d" , cfg.bits_per_sample );
@@ -567,18 +586,10 @@ class AudioFFTBase : public AudioStream {
567586 }
568587 }
569588
570- void writeStrideBuffer (uint8_t *buffer, size_t len) {
571- if (stride_buffer.size () > 0 ) {
572- int available = stride_buffer.availableForWrite ();
573- if (len > available) {
574- // clear oldest values to make space
575- int diff = len - available;
576- for (int j = 0 ; j < diff; j++) {
577- stride_buffer.read ();
578- }
579- }
580- stride_buffer.writeArray (buffer, len);
581- }
589+ // adds samples to stride buffer, returns true if the buffer is full
590+ bool writeStrideBuffer (uint8_t *buffer, size_t len) {
591+ stride_buffer.writeArray (buffer, len);
592+ return stride_buffer.isFull ();
582593 }
583594
584595 bool isPowerOfTwo (uint16_t x) { return (x & (x - 1 )) == 0 ; }
0 commit comments