initial

Dependencies:   mbed BSP_DISCO_F746NG mbed-dsp

signal_processing.cpp

Committer:
justenmg
Date:
2020-02-20
Revision:
2:89234085faae
Parent:
1:103e3e426b55
Child:
3:51e15bd15778

File content as of revision 2:89234085faae:

/**
  ******************************************************************************
  * @file    signal_processing.c
  * @author  Brian Mazzeo
  * @date    2020
  * @brief   This file provides a set of code for signal processing in 487.
  *          Parts are taken from example code from STMIcroelectronics
  ******************************************************************************
  * @attention
  *          This code was specifically developed for BYU ECEn 487 course 
  *          Introduction to Digital Signal Processing.
  *
  *
  ******************************************************************************
  */ 

#include "mbed.h"
#include "stm32746g_discovery_lcd.h"
#include "arm_math.h"
#include "arm_const_structs.h"
#include "filter_coefficients.h"
#include "our_filter.h"


/* ---------------------------------------------------------------------- 
** Defines for signal processing
** ------------------------------------------------------------------- */ 

#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)

/* For Lab Exercise */
#define Lab_Execution_Type              2

float32_t lState[NUM_TAPS + AUDIO_BLOCK_SAMPLES - 1];
float32_t rState[NUM_TAPS + AUDIO_BLOCK_SAMPLES - 1];

float32_t l_buf[BUFFER_LENGTH];
float32_t r_buf[BUFFER_LENGTH];

float32_t* l_buf_head = &l_buf;
uint16_t l_buf_head_idx = 0;
float32_t* r_buf_head = &r_buf;
uint16_t r_buf_head_idx = 0;

arm_fir_instance_f32 filter_left;
arm_fir_instance_f32 filter_right;

/* FUNCTION DEFINITIONS BELOW */

/**
  * @brief  Initialize filter structures to be used in loops later
  * @retval None
  */
void initalize_signal_processing(void) {

  switch (Lab_Execution_Type)
  {
  case 0: // Passthrough case
    break;
  
  case 1: // FIR case (ARM)
  arm_fir_init_f32(&filter_left, NUM_TAPS, (float32_t *)&Filter_coeffs, (float32_t *)&lState, AUDIO_BLOCK_SAMPLES);
  arm_fir_init_f32(&filter_right, NUM_TAPS, (float32_t *)&Filter_coeffs, (float32_t *)&rState, AUDIO_BLOCK_SAMPLES);
    break;
  
  case 2: // FIR case (student)
  arm_fir_init_f32(&filter_left, OUR_NUM_TAPS, (float32_t *)&our_Filter_coeffs, (float32_t *)&lState, AUDIO_BLOCK_SAMPLES);
  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 
  filter_init();
    break;
    
  case 4: // FFT Overlap-add with real-imag efficiency
    break;


  }
}

/**
  * @brief  Process audio channel signals
  * @param  L_channel_in: Pointer to Left channel data input (float32_t)
  * @param  R_channel_in: Pointer to Right channel data input (float32_t)
  * @param  L_channel_out: Pointer to Left channel data output (float32_t)
  * @param  R_channel_out: Pointer to Right channel data output (float32_t)
  * @param  Signal_Length: length of data to process
  * @retval None
  */
void process_audio_channel_signals(float32_t* L_channel_in, float32_t* R_channel_in, float32_t* L_channel_out, float32_t* R_channel_out, uint16_t Signal_Length)
{
    char buf[70];    
    BSP_LCD_SetFont(&Font8);
    BSP_LCD_SetTextColor(LCD_COLOR_CYAN);
    sprintf(buf, "Processing Signals" );
    BSP_LCD_DisplayStringAt(0, 200, (uint8_t *) buf, LEFT_MODE);

  switch(Lab_Execution_Type)
  {
  case 0: // Passthrough case
    arm_copy_f32(L_channel_in, L_channel_out, Signal_Length);
    arm_copy_f32(R_channel_in, R_channel_out, Signal_Length);
    break;
  
  case 1: // FIR case (ARM)
  arm_fir_f32(&filter_left, L_channel_in, L_channel_out, Signal_Length);
  arm_fir_f32(&filter_right, R_channel_in, R_channel_out, Signal_Length);
    break;
  
  case 2: // FIR case (student)
  arm_fir_f32(&filter_left, L_channel_in, L_channel_out, Signal_Length);
  arm_fir_f32(&filter_right, R_channel_in, R_channel_out, Signal_Length);
    break;
  
  case 3: // FFT Overlap-add 
  filter(l_buf, l_buf_head, l_buf_head_idx, L_channel_in, L_channel_out, Signal_Length, BUFFER_LENGTH);
  filter(r_buf, r_buf_head, r_buf_head_idx, R_channel_in, R_channel_out, Signal_Length, BUFFER_LENGTH);
    break;
    
  case 4: // FFT Overlap-add with real-imag efficiency
    break;

    
  }
    /* Change font back */  
    BSP_LCD_SetFont(&Font16);
}

//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(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)
{
    float32_t* data_sample = d_in+sig_length-1;
    float32_t* filter_sample = filter;
    float32_t result = 0;
    uint16_t conv_length = 0;
    float32_t* buffer_data_location = buffer_head;
    
    //convolve and save to buffer
    for(uint16_t shift = 0; shift < buf_length; shift++)
    {
        //shift
        if(shift < sig_lenth)
        {
            conv_length = shift + 1;
        }
        else if(shift >= sig_lenth && shift < filt_length)
        {
            conv_length = sig_lenth;
        }
        else if(shift >= filt_length)
        {
            conv_length = sig_lenth - (shift - filt_length + 1)
        }
        
        result = 0;
        //multiply-add
        for(i=0; i<conv_length; i++)
        {
            result += (*filter_sample) * (*data_sample);
            filter_sample++;
            data_sample--;
        }
        
        // save to the buffer
        *buffer_data_location += result;
        //increment, looping back to beginning of buffer
        if(buffer_data_location == (buffer_begin + buf_length - 1))
        {
            buffer_data_location = buffer_begin;
        }
        else
        {
            buffer_data_location++;
        }
    }
    
    //copy from buffer to d_out
    buffer_data_location = buffer_head;
    for(int i=0; i < sig_lenth; 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))
        {
            buffer_data_location = buffer_begin;
        }
        else
        {
            buffer_data_location++;
        }
    }
    return;
}

void filter_init()
{
    for(int i=0; i < BUFFER_LENGTH; i++)
    {
        l_buf[i] = 0;
        r_buf[i] = 0;
    }
}