1
$\begingroup$

I'm trying to design a: $$H(z)=1 - 0.95z$$

FIR filter, for speech signal. I am using this arm_fir_example_f32.c code shown below. And I need to change the filter coefficients, firCoeffs32. I know very little about filter design, so I don't even know if the code is understandable, but I will answer what I can.

EDIT: To give a little bit more detail on why I need this filter. I am making a speech recognizer and on page 18, of this work, there is a small passage about using the pre-emphasis filter to spectrally flatten the speech signal. I figured the details are in the higher frequencies, so that's why the filter is used.

CODE:

/* ----------------------------------------------------------------------
 * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
 *
* $Date:         17. January 2013
* $Revision:     V1.4.0
*
* Project:       CMSIS DSP Library
 * Title:        arm_fir_example_f32.c
 *
 * Description:  Example code demonstrating how an FIR filter can be used
 *               as a low pass filter.
 *
 * Target Processor: Cortex-M4/Cortex-M3
 *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*   - Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*   - Redistributions in binary form must reproduce the above copyright
*     notice, this list of conditions and the following disclaimer in
*     the documentation and/or other materials provided with the
*     distribution.
*   - Neither the name of ARM LIMITED nor the names of its contributors
*     may be used to endorse or promote products derived from this
*     software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
 * -------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
** Include Files
** ------------------------------------------------------------------- */
#include "arm_math.h"
#include "math_helper.h"
/* ----------------------------------------------------------------------
** Macro Defines
** ------------------------------------------------------------------- */
#define TEST_LENGTH_SAMPLES  320
#define SNR_THRESHOLD_F32    140.0f
#define BLOCK_SIZE            32
#define NUM_TAPS              29
/* -------------------------------------------------------------------
 * The input signal and reference output (computed with MATLAB)
 * are defined externally in arm_fir_lpf_data.c.
 * ------------------------------------------------------------------- */
extern float32_t testInput_f32_1kHz_15kHz[TEST_LENGTH_SAMPLES];
extern float32_t refOutput[TEST_LENGTH_SAMPLES];
/* -------------------------------------------------------------------
 * Declare Test output buffer
 * ------------------------------------------------------------------- */
static float32_t testOutput[TEST_LENGTH_SAMPLES];
/* -------------------------------------------------------------------
 * Declare State buffer of size (numTaps + blockSize - 1)
 * ------------------------------------------------------------------- */
static float32_t firStateF32[BLOCK_SIZE + NUM_TAPS - 1];
/* ----------------------------------------------------------------------
** FIR Coefficients buffer generated using fir1() MATLAB function.
** fir1(28, 6/24)
** ------------------------------------------------------------------- */
const float32_t firCoeffs32[NUM_TAPS] = {
  -0.0018225230f, -0.0015879294f, +0.0000000000f, +0.0036977508f, +0.0080754303f, +0.0085302217f, -0.0000000000f, -0.0173976984f,
  -0.0341458607f, -0.0333591565f, +0.0000000000f, +0.0676308395f, +0.1522061835f, +0.2229246956f, +0.2504960933f, +0.2229246956f,
  +0.1522061835f, +0.0676308395f, +0.0000000000f, -0.0333591565f, -0.0341458607f, -0.0173976984f, -0.0000000000f, +0.0085302217f,
  +0.0080754303f, +0.0036977508f, +0.0000000000f, -0.0015879294f, -0.0018225230f
};
/* ------------------------------------------------------------------
 * Global variables for FIR LPF Example
 * ------------------------------------------------------------------- */
uint32_t blockSize = BLOCK_SIZE;
uint32_t numBlocks = TEST_LENGTH_SAMPLES/BLOCK_SIZE;
float32_t  snr;
/* ----------------------------------------------------------------------
 * FIR LPF Example
 * ------------------------------------------------------------------- */
int32_t main(void)
{
  uint32_t i;
  arm_fir_instance_f32 S;
  arm_status status;
  float32_t  *inputF32, *outputF32;
  /* Initialize input and output buffer pointers */
  inputF32 = &testInput_f32_1kHz_15kHz[0];
  outputF32 = &testOutput[0];
  /* Call FIR init function to initialize the instance structure. */
  arm_fir_init_f32(&S, NUM_TAPS, (float32_t *)&firCoeffs32[0], &firStateF32[0], blockSize);
  /* ----------------------------------------------------------------------
  ** Call the FIR process function for every blockSize samples
  ** ------------------------------------------------------------------- */
  for(i=0; i < numBlocks; i++)
  {
    arm_fir_f32(&S, inputF32 + (i * blockSize), outputF32 + (i * blockSize), blockSize);
  }
  /* ----------------------------------------------------------------------
  ** Compare the generated output against the reference output computed
  ** in MATLAB.
  ** ------------------------------------------------------------------- */
  snr = arm_snr_f32(&refOutput[0], &testOutput[0], TEST_LENGTH_SAMPLES);
  if (snr < SNR_THRESHOLD_F32)
  {
    status = ARM_MATH_TEST_FAILURE;
  }
  else
  {
    status = ARM_MATH_SUCCESS;
  }
  /* ----------------------------------------------------------------------
  ** Loop here if the signal does not match the reference output.
  ** ------------------------------------------------------------------- */
  if ( status != ARM_MATH_SUCCESS)
  {
    while (1);
  }
  while (1);                             /* main function does not return */
}
$\endgroup$
  • 1
    $\begingroup$ Um, read the wikipedia article on FIRs, especially the moving average example. What you plan to do is convolve with the sequence $[1, -0.95]$, and that would be done with a simple out[i] = -0.95*in[i] + in[i-1] in C or whatever language. You don't need a library to do so. Also, what does that filter even remotely have to do with the bandpass or bandstop (unclear!) that you're specifying with your "300 Hz – 8000 Hz"? Your two taps are pretty clearly a high-pass filter, and under no circumstances would be a bandstop or -pass filter. $\endgroup$ – Marcus Müller Dec 13 '17 at 21:08
  • $\begingroup$ Yeah, sorry. Could have made that more clear. I wasn't thinking about any bandpasses. The library is optimized for DSP, so it's preferable. You have given me an idea on how to proceed. Thanks! $\endgroup$ – Desperado Dec 13 '17 at 21:58
  • $\begingroup$ no, it's not inherently preferable to use a FIR library function if you actually only have a two-tap fir, of which one tap is 1.0. Please note that your statement "filter for frequencies 300 Hz to 8000 Hz" does imply bandpass (or bandstop) behaviour. It's absolutely unclear what you want to build, how you came to your transfer function (your $H(z)$), and why you think you need this to start with. You'll get a lot more out of your question if you gave us a lot more background, like why you need this, where you've got that transfer function from and so on. $\endgroup$ – Marcus Müller Dec 13 '17 at 22:30
  • $\begingroup$ i have an example for pre-emphasis filter and idont know how to solve it can u give your email or any contact so i can send it to you because it is in Microsoft word file $\endgroup$ – Mody_19 Dec 24 '17 at 1:09
3
$\begingroup$

For your filter, the number of taps is 2 and the coefficients are simply [-0.95, 1].

Although this is a very simple case, it is instructive if you are less familiar with FIR filtering. To go from your transfer function to a filter implementation it is easier to put the transfer function in terms of inverse powers of z, since $z^{-1}$ is the z transform of a unit delay (a delay of one sample, at whatever sampling rate you are running the filter at- for more detail on that see How/why are the $\mathcal Z$-transform and unit delays related?).

So in your case:

$$H(z) = 1 - 0.95z$$ should actually be as follows in order to be causal (the trivial pole at the origin was left out):

$$H(z) = \frac{1 - 0.95z}{z}$$

Which is equivalent to:

$$H(z) = z^{-1} - 0.95 $$

Noting that $z^{-1}$ is simply the same signal delayed by one sample, the implementation is given as:

2 tap FIR

Which shows the generic FIR structure for a 2 tap FIR, which in this case can be even more simply shown as:

2 tap FIR with unity gain coeff

The frequency response of such a filter is easily determined (for example in Octave/Matlab using freqz([-0.95 1]) with the result shown below (the normalized frequency of 1 is scaled to half your sampling frequency of the filter; so if your sampling rate for example was 20 KHz, the frequency axis in the plot shown below goes from DC to 10 KHz).

plot of filter transfer function

Also note that for the order of the tap coefficients as given, the implementation would be "maximum phase". Reversing the taps results in the identical magnitude response but would be "minimum phase" as the dominant tap occurs first. Here is the resulting frequency response for [1 -.95] instead of [-.95 1]. Notice how the magnitude is identical but the overall phase shift vs frequency is minimized:

min phase transfer function

Cascading a minimum phase filter with a maximum phase filter results in a magnitude response exactly twice of each with a linear phase response. The cascade of [1 -.95] with [-.95 1] is [-.95 1.9025 -.95] (found by convolving the two), and the response of this 3 tap filter is:

linear phase filter

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.