Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] FIR Implementation on Audio using C

Status
Not open for further replies.

subway

Newbie level 1
Newbie level 1
Joined
Mar 23, 2012
Messages
1
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,287
Hi, I'm new to this forum. I'm currently working on implementing a FIR filter on audio wav file. Somehow the output wav file doesn't seem right. If you use Hex Editor to view the data in the output wav, there are weird characters of 'Ì' in it. Does anyone has an idea on how to solve this?

p/s: same issue occurs when i tested with other wav file.

Here is my coding.

Code:
#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>

// define path and destination
#define PATH "C:\\YouTube\\bc1.wav"
#define DEST "C:\\YouTube\\test.wav"

// number of samples to read per loop
#define SAMPLES   12000

//////////////////////////////////////////////////////////////
//  Filter Code Definitions
//////////////////////////////////////////////////////////////

// maximum number of inputs that can be handled
// in one function call
#define MAX_INPUT_LEN   12000 //80
// maximum length of filter than can be handled
#define MAX_FLT_LEN     56
// buffer to hold all of the input samples
#define BUFFER_LEN      (MAX_FLT_LEN - 1 + MAX_INPUT_LEN)

// array to hold input samples
double insamp[ BUFFER_LEN ];

// FIR init
void firFloatInit( void )
{
    memset( insamp, 0, sizeof( insamp ) );
}

// the FIR filter function
void firFloat( double *coeffs, double *input, double *output,
       int length, int filterLength )
{
    double acc;     // accumulator for MACs
    double *coeffp; // pointer to coefficients
    double *inputp; // pointer to input samples
    int n;
    int k;

    // put the new samples at the high end of the buffer
    memcpy( &insamp[filterLength - 1], input,
            length * sizeof(double) );

    // apply the filter to each input sample
    for ( n = 0; n < length; n++ ) {
        // calculate output n
        coeffp = coeffs;
        inputp = &insamp[filterLength - 1 + n];
        acc = 0;
        for ( k = 0; k < filterLength; k++ ) {
            acc += (*coeffp++) * (*inputp--);
        }
        output[n] = acc;
    }
    // shift input samples back in time for next time
    memmove( &insamp[0], &insamp[length],
            (filterLength - 1) * sizeof(double) );

}



#define FILTER_LEN  56
double coeffs[ FILTER_LEN ] =
{
       
  
// bandpass filter centred around 1000 Hz
// sampling frequency = 11025 Hz
// Hamming window method  
   
   -0.0036525,	-0.0032294,	-0.0017329,	
   0.00093613,	 0.0044845, 0.0079234,
   0.00961818,	0.00785081,	0.0017546,
   -0.0078068,	-0.0179545,	-0.024464,
   -0.0233340,	-0.0127056,	0.0057155,	
   0.02653121,	0.04214803,	0.0455294,	
   0.03320032,	0.0072329,	-0.024781,
   -0.0520149,	-0.064244,	-0.055822,
   -0.0281917,	0.0101904,	0.0466194,	
   0.06865154,	0.0686515,	0.0466194,	
   0.01019042,	-0.028192,	-0.055822,
   -0.0642436,	-0.052015	-0.024781,
   0.00723290,	0.0332003,	0.0455294,	
   0.04214803,	0.0265312,	0.0057155,	
   -0.0127056,	-0.023334,	-0.024464,
   -0.0179545,	-0.007807,	0.0017546,	
   0.00785081,	0.0096182,	0.0079234,	
   0.00448454,	0.0009361,	-0.001733,	
   -0.0032293,	-0.003652

    
};

void intToFloat( int16_t *input, double *output, int length )
{
    int i;

    for ( i = 0; i < length; i++ ) {
        output[i] = (double)input[i];
    }
}

void floatToInt( double *input, int16_t *output, int length )
{
int i;
    for ( i = 0; i < length; i++ ) {
// add rounding constant
   input[i] += 0.5;
// bound the values to be 16 bits
   if ( input[i] > 32767.0 ) {
        input[i] = 32767.0;
      } 
   else if ( input[i] < -32768.0 ) {
        input[i] = -32768.0;
      }
// convert
   output[i] = (int16_t)input[i];
   }
}


int _tmain(int argc, _TCHAR* argv[])
{
// Buffers etc..
	char ChunkID[4], Format[4], Subchunk1ID[4],Subchunk2ID[4];
	int ChunkSize,Subchunk1Size, SampleRate, ByteRate,Subchunk2Size;
	short AudioFormat, NumChannels, BlockAlign, BitsPerSample;
	short *Data;

	int size;
    int16_t input[SAMPLES];
    int16_t output[SAMPLES];
    double floatInput[SAMPLES];
    double floatOutput[SAMPLES];
	
	// Read the wave file
	FILE *fhandle_in=fopen(PATH,"rb");
	fread(ChunkID,1,4,fhandle_in);
	fread(&ChunkSize,4,1,fhandle_in);
	fread(Format,1,4,fhandle_in);
	fread(Subchunk1ID,1,4,fhandle_in);
	fread(&Subchunk1Size,4,1,fhandle_in);
	fread(&AudioFormat,2,1,fhandle_in);
	fread(&NumChannels,2,1,fhandle_in);
	fread(&SampleRate,4,1,fhandle_in);
	fread(&ByteRate,4,1,fhandle_in);
	fread(&BlockAlign,2,1,fhandle_in);
	fread(&BitsPerSample,2,1,fhandle_in);
	fread(&Subchunk2ID,1,4,fhandle_in);
	fread(&Subchunk2Size,4,1,fhandle_in);
	Data=new short [Subchunk2Size/(BitsPerSample/8)];	// Create an element for every sample
	fread(Data,BitsPerSample/8,Subchunk2Size/(BitsPerSample/8),fhandle_in); // Reading raw audio data


	if(fhandle_in == NULL)
    {
        printf("Unable to open wave file.\n");
        getchar();
    }

	// Write the same wave header file
	FILE *fhandle;
	fhandle=fopen(DEST,"wb");
	fwrite(ChunkID,1,4,fhandle);
	fwrite(&ChunkSize,4,1,fhandle);
	fwrite(Format,1,4,fhandle);
	fwrite(Subchunk1ID,1,4,fhandle);
	fwrite(&Subchunk1Size,4,1,fhandle);
	fwrite(&AudioFormat,2,1,fhandle);
	fwrite(&NumChannels,2,1,fhandle);
	fwrite(&SampleRate,4,1,fhandle);
	fwrite(&ByteRate,4,1,fhandle);
	fwrite(&BlockAlign,2,1,fhandle);
	fwrite(&BitsPerSample,2,1,fhandle);
	fwrite(&Subchunk2ID,1,4,fhandle);
	fwrite(&Subchunk2Size,4,1,fhandle);
	// To copy whole input to output
	// fwrite(Data,BitsPerSample/8,Subchunk2Size/(BitsPerSample/8),fhandle);	
	
	 if ( fhandle == NULL ) {
        printf("couldn't open output file");
        getchar();
    }


    // initialize the filter
    firFloatInit();
 
    // process all of the samples
     do {
        // read samples from file
        size = fread( Data, BitsPerSample/8,Subchunk2Size/(BitsPerSample/8), fhandle_in );
        
        // convert to doubles
        intToFloat( Data, floatInput, size );
        
        // perform the filtering
         firFloat( coeffs, floatInput, floatOutput, size, FILTER_LEN );
         
        // convert to ints
        floatToInt( floatInput, output, size );
        
        // write samples to file
        fwrite( output, BitsPerSample/8,Subchunk2Size/(BitsPerSample/8), fhandle );

    } while ( size != 0 );
    

    printf("Done");
	fclose(fhandle_in);
	fclose(fhandle);

	return 0;
}

Thanks in advance.
 

Hi mate,

Is this code functional?
I'm trying to do something similar .. but got stuck when dealing with "removing" header from filtering and swapping the endians.

Can you kindly show me where these are implemented in your code so that I can follow, or maybe you can give a link or something which might be usefull for this.

thanks :)
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top