initial

Dependencies:   mbed BSP_DISCO_F746NG mbed-dsp

Revision:
5:a658cda1d619
Parent:
4:99de9b4005d2
Child:
6:291e341f0d71
--- a/signal_processing.cpp	Wed Mar 04 00:55:43 2020 +0000
+++ b/signal_processing.cpp	Fri Mar 06 01:41:05 2020 +0000
@@ -29,11 +29,16 @@
 ** ------------------------------------------------------------------- */ 
 
 #define AUDIO_BLOCK_SAMPLES             ((uint32_t)128)         // Number of samples (L and R) in audio block (each samples is 16 bits)
-#define BUFFER_LENGTH                   (WIN_NUM_TAPS + AUDIO_BLOCK_SAMPLES - 1)
-#define FFT_BUFFER_LENGTH                2048
+#define CONV_LENGTH                     (WIN_NUM_TAPS + AUDIO_BLOCK_SAMPLES - 1)
+#define BUFFER_LENGTH                   (WIN_NUM_TAPS - 1)
+#define FFT_BUFFER_LENGTH               2048
+#define FFT_LENGTH                      1024
+#define PADDED_FILTER_LENGTH            (WIN_NUM_TAPS + 2*(AUDIO_BLOCK_SAMPLES - 1))
 
 /* For Lab Exercise */
-#define Lab_Execution_Type              3
+#define Lab_Execution_Type              6
+
+float32_t padded_filter[PADDED_FILTER_LENGTH];
 
 float32_t lState[NUM_TAPS + AUDIO_BLOCK_SAMPLES - 1];
 float32_t rState[NUM_TAPS + AUDIO_BLOCK_SAMPLES - 1];
@@ -41,17 +46,18 @@
 float32_t l_buf[BUFFER_LENGTH];
 float32_t r_buf[BUFFER_LENGTH];
 
+float32_t l_buf2[FFT_LENGTH];
+float32_t r_buf2[FFT_LENGTH];
+
 arm_fir_instance_f32 filter_left;
 arm_fir_instance_f32 filter_right;
 
 float32_t fft_buf[FFT_BUFFER_LENGTH];
+float32_t ifft_buf[FFT_BUFFER_LENGTH];
 
 float32_t fft_of_filter[FFT_BUFFER_LENGTH];
 
 
-
-
-
 /* FUNCTION DEFINITIONS BELOW */
 
 /**
@@ -76,7 +82,7 @@
   arm_fir_init_f32(&filter_right, OUR_NUM_TAPS, (float32_t *)&our_Filter_coeffs, (float32_t *)&rState, AUDIO_BLOCK_SAMPLES);
     break;
   
-  case 3: // FFT Overlap-add 
+  case 3: // conv Overlap-add 
   filter_conv_init();
     break;
     
@@ -131,21 +137,21 @@
     break;
   
   case 3: // OA CONV
-  filter_OA_CONV(l_buf, L_channel_in, L_channel_out, Signal_Length, BUFFER_LENGTH);
-  filter_OA_CONV(r_buf, R_channel_in, R_channel_out, Signal_Length, BUFFER_LENGTH);
+  filter_OA_CONV(l_buf, L_channel_in, L_channel_out, Signal_Length);
+  filter_OA_CONV(r_buf, R_channel_in, R_channel_out, Signal_Length);
     break;
     
   case 4: // OA FFT Overlap-add
- 
+  filter_OA_FFT(l_buf, fft_buf, ifft_buf, L_channel_in, L_channel_out, Signal_Length);
+  filter_OA_FFT(r_buf, fft_buf, ifft_buf, R_channel_in, R_channel_out, Signal_Length);
     break;
 
   case 5: // FFT Overlap-add with real-imag efficiency
- 
+  filter_OA_FFT_RI(l_buf, r_buf, fft_buf, ifft_buf, L_channel_in, R_channel_in, L_channel_out, R_channel_out, Signal_Length);
     break;
     
   case 6: // OS FFT RI
- 
- 
+  filter_OS_FFT_RI(l_buf2, r_buf2, fft_buf, ifft_buf, L_channel_in, R_channel_in, L_channel_out, R_channel_out, Signal_Length);
     break;
 
     
@@ -156,65 +162,35 @@
 
 //buffer: pointer to the storage buffer for the filter output
 //buf_length: the length of the storage buffer (len_filter + len_batch - 1)
-void filter_OA_CONV(float32_t* overlap_buffer, float32_t* d_in, float32_t* d_out, uint16_t sig_length, uint16_t buf_length)
+
+void filter_OA_CONV(float32_t* overlap_buffer, float32_t* d_in, float32_t* d_out, uint16_t sig_length)
 {
-    float32_t* data_sample = d_in;
-    float32_t* filter_sample = win_filter_coeffs;
     float32_t result = 0;
-    uint16_t conv_length = 0;
     
-    //convolve and save to buffer
-    /*
-    for(uint16_t shift = 0; shift < buf_length; shift++)
+    //shift the data sample and convolve
+    for(uint16_t shift = 0; shift < CONV_LENGTH; shift++)
     {
-        //shift
+        result = 0;
+        //multiply-add the shifted, reversed data sample to the padded filter
+        for(int i=0; i<sig_length; i++)
+        {
+            result += padded_filter[i + shift] * d_in[i];
+        }
+        
+        // overlap-add to the buffer
+        //overlap_buffer[shift] += result;
+        
         if(shift < sig_length)
         {
-            conv_length = shift + 1;
-        }
-        else if(shift >= sig_length && shift < WIN_NUM_TAPS)
-        {
-            conv_length = sig_length;
-        }
-        else if(shift >= WIN_NUM_TAPS)
-        {
-            conv_length = sig_length - (shift - WIN_NUM_TAPS + 1);
+            d_out[shift] = overlap_buffer[shift] + result;
         }
-        
-        result = 0;
-        //multiply-add
-        for(int i=0; i<conv_length; i++)
+        else if(shift < BUFFER_LENGTH)
         {
-            result += (filter_sample[i]) * (data_sample[shift - i]);
-        }
-        
-        // save to the buffer
-        overlap_buffer[shift] += result;
-    }
-    */
-    for(int i=0; i < buf_length; i++)
-    {
-        if(i < sig_length)
-        {
-            overlap_buffer[i] = data_sample[i];
+            overlap_buffer[shift - sig_length] = overlap_buffer[shift] + result;
         }
         else
         {
-            overlap_buffer[i] = 0;
-        }
-    }
-    
-    //copy from buffer to d_out, shift buffer, zero pad
-    for(int i=0; i < buf_length; i++)
-    {
-        if(i < sig_length)
-        {
-            d_out[i] = overlap_buffer[i];
-            overlap_buffer[i] = overlap_buffer[i+sig_length];
-        }
-        else
-        {
-            overlap_buffer[i] = 0;
+            overlap_buffer[shift - sig_length] = result;
         }
     }
     return;
@@ -222,75 +198,180 @@
 
 
 
-void filter_OA_FFT(float32_t* buffer_begin, float32_t* buffer_head, uint16_t buffer_head_idx, float32_t* d_in, float32_t* d_out, uint16_t sig_length, uint16_t buf_length)
+void filter_OA_FFT(
+float32_t* overlap_buffer, 
+float32_t* fft_buffer, 
+float32_t* ifft_buffer, 
+float32_t* d_in, 
+float32_t* d_out, 
+uint16_t sig_length)
 {
-    /*float32_t* data_sample = d_in+sig_length-1;
-    float32_t* filter_sample = win_filter_coeffs;
-    float32_t result = 0;
-    float32_t* buffer_data_location = buffer_head;
-    
-    for(uint16_t i = 0; i < FFT_BUFFER_LENGTH; i++)
-    {
-        fft_buf[i] = d_in[i];
-    }
-    
-    arm_cfft_f32(&arm_cfft_sR_f32_len1024, fft_buf, 0, 1);
-    
-    for(uint16_t i = 0; i < FFT_BUFFER_LENGTH; i++)
+    //fill the FFT buffer
+    for(int i=0; i < FFT_LENGTH; i++)
     {
-        fft_buf[i] = fft_buf[i]*fft_of_filter[i];
-    }
-    
-    arm_cfft_f32(&arm_cfft_sR_f32_len1024, fft_buf, 1, 1);
-    
-    
-    // save to buffer
-    for(uint16_t i = 0; i < buf_length; i++)
-    {        
-        
-        // save to the buffer
-        *buffer_data_location += fft_buf[i];
-        //increment, looping back to beginning of buffer
-        if(buffer_data_location == (buffer_begin + buf_length - 1))
+        if(i < sig_length)
         {
-            buffer_data_location = buffer_begin;
+        fft_buffer[2*i] = d_in[i];
+        fft_buffer[2*i+1] = 0;
         }
         else
         {
-            buffer_data_location++;
+        fft_buffer[2*i] = 0;
+        fft_buffer[2*i+1] = 0;
         }
     }
     
-    //copy from buffer to d_out
-    buffer_data_location = buffer_head;
-    for(int i=0; i < sig_length; i++)
+    //perform FFT in place
+    arm_cfft_f32(&arm_cfft_sR_f32_len1024, fft_buffer, 0, 1);
+    
+    
+    //multiply with filter FFT
+    arm_cmplx_mult_cmplx_f32(fft_buffer, fft_of_filter, ifft_buffer, FFT_LENGTH);
+
+    //perform inverse FFT in place
+    arm_cfft_f32(&arm_cfft_sR_f32_len1024, ifft_buffer, 1, 1);
+    
+    // overlap-add to the buffer
+    for(uint16_t i = 0; i < CONV_LENGTH; i++)
     {
-        d_out[i] = *buffer_data_location;
-        *buffer_data_location = 0;
-        //increment, looping back to beginning of buffer
-        if(buffer_data_location + i == (buffer_begin + buf_length - 1))
+        if(i < sig_length)
         {
-            buffer_data_location = buffer_begin;
+            d_out[i] = ifft_buffer[2*i] + overlap_buffer[i];
+        }
+        else if(i < BUFFER_LENGTH)
+        {
+            overlap_buffer[i - sig_length] = overlap_buffer[i] + ifft_buffer[2*i];
         }
         else
         {
-            buffer_data_location++;
+            overlap_buffer[i - sig_length] = ifft_buffer[2*i];
         }
-    }*/
+    }    
     return;
 }
 
 
+//The overlap-add method uses previous outputs to adjust the filtered
+//output to be more representative of the continuous version of the signal
+void filter_OA_FFT_RI(
+    float32_t* overlap_buffer1,
+    float32_t* overlap_buffer2,
+    float32_t* fft_buffer,
+    float32_t* ifft_buffer,
+    float32_t* d_in1,
+    float32_t* d_in2,
+    float32_t* d_out1,
+    float32_t* d_out2,
+    uint16_t sig_length)
+{
+    //fill the FFT buffer
+    for(int i=0; i < FFT_LENGTH; i++)
+    {
+        if(i < sig_length)
+        {
+        fft_buffer[2*i] = d_in1[i];
+        fft_buffer[2*i+1] = d_in2[i];
+        }
+        else
+        {
+        fft_buffer[2*i] = 0;
+        fft_buffer[2*i+1] = 0;
+        }
+    }
     
-void filter_OA_FFT_RI(float32_t* buffer_begin, float32_t* buffer_head, uint16_t buffer_head_idx, float32_t* d_in, float32_t* d_out, uint16_t sig_length, uint16_t buf_length)
-{
+    //perform FFT in place
+    arm_cfft_f32(&arm_cfft_sR_f32_len1024, fft_buffer, 0, 1);
+    
+    
+    //multiply with filter FFT
+    arm_cmplx_mult_cmplx_f32(fft_buffer, fft_of_filter, ifft_buffer, FFT_LENGTH);
+    
+    
+    //perform inverse FFT in place
+    arm_cfft_f32(&arm_cfft_sR_f32_len1024, ifft_buffer, 1, 1);
+    
+    // overlap-add to the buffer
+    for(uint16_t i = 0; i < CONV_LENGTH; i++)
+    {
+        if(i < sig_length)
+        {
+            d_out1[i] = ifft_buffer[2*i] + overlap_buffer1[i];
+            d_out2[i] = ifft_buffer[2*i+1] + overlap_buffer2[i];
+        }
+        else if(i < BUFFER_LENGTH)
+        {
+            overlap_buffer1[i - sig_length] = overlap_buffer1[i] + ifft_buffer[2*i];
+            overlap_buffer2[i - sig_length] = overlap_buffer2[i] + ifft_buffer[2*i+1];
+        }
+        else
+        {
+            overlap_buffer1[i - sig_length] = ifft_buffer[2*i];
+            overlap_buffer2[i - sig_length] = ifft_buffer[2*i+1];
+        }
+    }    
     return;
 }
 
 
-
-void filter_OS_FFT_RI(float32_t* buffer_begin, float32_t* buffer_head, uint16_t buffer_head_idx, float32_t* d_in, float32_t* d_out, uint16_t sig_length, uint16_t buf_length)
+//The overlap-save method uses previous inputs to perform a 
+//more representative filtering operation
+void filter_OS_FFT_RI(
+    float32_t* save_buffer1,
+    float32_t* save_buffer2,
+    float32_t* fft_buffer, 
+    float32_t* ifft_buffer,
+    float32_t* d_in1, 
+    float32_t* d_in2, 
+    float32_t* d_out1, 
+    float32_t* d_out2, 
+    uint16_t sig_length)
 {
+    //shift the save buffers by the input data size
+    for(int i=0; i < FFT_LENGTH; i++)
+    {
+        if(i < FFT_LENGTH - sig_length)
+        {
+            save_buffer1[i] = save_buffer1[i+sig_length];
+            save_buffer2[i] = save_buffer2[i+sig_length];
+        }
+        else
+        {
+            save_buffer1[i] = 0;   
+            save_buffer2[i] = 0; 
+        }
+    }
+    
+    //insert new data into save buffer
+    for(int i=0; i < sig_length; i++)
+    {
+        save_buffer1[(FFT_LENGTH - sig_length) + i] = d_in1[i];
+        save_buffer2[(FFT_LENGTH - sig_length) + i] = d_in2[i];
+    }
+    
+    //fill the FFT buffer
+    for(int i=0; i < FFT_LENGTH; i++)
+    {
+        fft_buffer[2*i] = save_buffer1[i];
+        fft_buffer[2*i+1] = save_buffer2[i];
+    }
+    
+    //perform FFT in place
+    arm_cfft_f32(&arm_cfft_sR_f32_len1024, fft_buffer, 0, 1);
+    
+    
+    //multiply with filter FFT
+    arm_cmplx_mult_cmplx_f32(fft_buffer, fft_of_filter, ifft_buffer, FFT_LENGTH);
+    
+    
+    //perform inverse FFT in place
+    arm_cfft_f32(&arm_cfft_sR_f32_len1024, ifft_buffer, 1, 1);
+    
+    // copy to output buffer
+    for(uint16_t i = CONV_LENGTH - sig_length; i < CONV_LENGTH; i++)
+    {
+        d_out1[i] = ifft_buffer[2*i];
+        d_out2[i] = ifft_buffer[2*i+1];
+    }    
     return;
 }
 
@@ -306,6 +387,18 @@
         l_buf[i] = 0;
         r_buf[i] = 0;
     }
+    for(int i=0; i < PADDED_FILTER_LENGTH; i++)
+    {
+        if((i < AUDIO_BLOCK_SAMPLES - 1) || (i >= WIN_NUM_TAPS + AUDIO_BLOCK_SAMPLES - 1))
+        {
+         padded_filter[i] = 0;
+        }
+        else
+        {
+         padded_filter[i] = win_filter_coeffs[WIN_NUM_TAPS - 1 - (i - AUDIO_BLOCK_SAMPLES - 1)];   
+        }
+    }
+    
     return;
 }
 
@@ -313,15 +406,17 @@
 
 void filter_fft_init()
 {
-    for(int i=0; i < FFT_BUFFER_LENGTH; i++)
+    for(int i=0; i < FFT_LENGTH; i++)
     {
         if(i < WIN_NUM_TAPS)
         {
-         fft_of_filter[i] = win_filter_coeffs[i];
+         fft_of_filter[2*i] = win_filter_coeffs[i];
+         fft_of_filter[2*i+1] = 0;
         }
         else
         {
-         fft_of_filter[i] = 0;   
+         fft_of_filter[2*i] = 0;   
+         fft_of_filter[2*i+1] = 0;
         }
     }
     
@@ -329,3 +424,4 @@
     
     return;
 }
+