subway
Newbie level 1
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.
Thanks in advance.
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.