10000 tap headers, slow implementations and distortion

Here’s a little MATLAB routine which can be used to convert CIPIC’s .mat files to C headers:

function hrir_az2c(file, arrName, hrir, el)
%// arrName: name for the C array that will be created, could use a string corresponding to the MATLAB array:
%// hrir: the hrir 25x50x200 array
%// el: current plan is to output one header per elevation per L/R channel
%// Adapted from Aj's post here: 
%// http://www.mathworks.com/matlabcentral/newsreader/view_thread/48182

scale = 1e3; %// weights are very small -> round to 0s
[max_el, max_az, max_tap] = size(hrir);
if (el>max_el)
    el = max_el;
end
toWrite = ['Int16 ', arrName, '[', num2str(max_az*max_tap), '] = {'];
for az = 1:max_az
    for tap = 1:max_tap
        if az ~= max_az && tap ~= max_tap
            toWrite = [ toWrite, sprintf('%i, ', int16(scale.*hrir(el, az, tap)))];
        end
    end
end
toWrite = [toWrite, sprintf('%i};', int16(scale.*hrir(el, max_az, max_tap)))];

fid = fopen([file, '.h'], 'w');
fprintf(fid, toWrite);
fclose(fid);
end

For some reason, Code Composer Studio doesn’t appear to like 2-D arrays. So, I resorted to using one long array, and indexing different filters out of it.

Also, I used the switches to switch between different modes:

[1] No filtering done. Codec input is directly outputted
[2] Filtering done (left channel through left HRIR, likewise for right channel), but codec input still directly outputted. This is to observe some distortion that creeps in in comparison to [1]. Reason being slow code.
[3] Filtering done, and outputted
[4] Filtering done in the mono sense: the same channel is run through left and right HRIRs and outputted in stereo

Mode [4] is not working as expected. It might be that my HRIR switching is not working. The LCD display can be used to verify the azimuth indexing being used.

Also, it should be noted that this code has a crude timer to make sure that HRIRs don’t start switching rapidly the moment the switch is pressed. This is crude, it would be better to detect changes in the switch’s state.

Here’s the latest version of the program. I hope to add sound samples soon (codec board needs to be resolved for doing the recording 🙂 )

/*
 * fir_filter.c
 * A crude implementation for using HRIRs. A 100 tap HRIR was loaded for each channel.
 *      Author: GSI + Abhinav
 */

#include <usbstk5515.h>
#include <usbstk5515_i2c.h>
#include <AIC_func.h>
#include <sar.h>
#include <stdio.h>
#include "hrir_l_subject3_el10_azAll.h"
#include "hrir_r_subject3_el10_azAll.h"

#define ASIZE 		200

#define TCR0 		*((ioport volatile Uint16 *)0x1810)
#define TIMCNT1_0 	*((ioport volatile Uint16 *)0x1814)
#define TIME_START  0x8001
#define TIME_STOP   0x8000

Int16 in_left[ASIZE], in_right[ASIZE];
Uint16 delta_time;

Int16 FIR_left(Uint16 i, Uint16 az)
{
	Int32 sum;
	Uint16 j;
	Uint32 index;
	sum=0;
	//The actual filter work
	for(j=0; j<ASIZE; j++)
	{
		if(i>=j)
 			index = i - j;
		else
 			index = ASIZE + i - j;
		sum += (Int32)in_left[index] * (Int32)hrir_l[az*ASIZE + j];
	}
	sum = sum + 0x00004000;			// So we round rather than truncate.
	return (Int16) (sum >> 15);  	// Conversion from 32 Q30 to 16 Q15.
}

Int16 FIR_right(Uint16 i, Uint16 az)
{
	Int32 sum;
	Uint16 j;
	Uint32 index;
	sum=0;
	//The actual filter work
	for(j=0; j<ASIZE; j++)
	{
		if(i>=j)
 			index = i - j;
		else
 			index = ASIZE + i - j;
		sum += (Int32)in_right[index] * (Int32)hrir_r[az*ASIZE + j];
	}
	sum = sum + 0x00004000;			// So we round rather than truncate.
	return (Int16) (sum >> 15);  	// Conversion from 32 Q30 to 16 Q15.
}

Int16 FIR(Int16* in, Int16* hrir,  Uint16 i, Uint16 az)
{
	Int32 sum;
	Uint16 j;
	Uint32 index;
	sum=0;
	//The actual filter work
	for(j=0; j<ASIZE; j++)
	{
		if(i>=j)
 			index = i - j;
		else
 			index = ASIZE + i - j;
		sum += (Int32)in[index] * (Int32)hrir[az*ASIZE + j];
	}
	sum = sum + 0x00004000;			// So we round rather than truncate.
	return (Int16) (sum >> 15);  	// Conversion from 32 Q30 to 16 Q15.
}



void main(void)
{
	Uint16 i, az = 0, j = 0, WTIME = 100;
//	Uint16 start_time;
//	Uint16 end_time;
	Int16 right, left; //AIC inputs
	Int16 out_left, out_right;
	Uint16 key;
	Uint16 filter = 0;

	USBSTK5515_init(); 	//Initializing the Processor
	AIC_init(); 		//Initializing the Audio Codec
	Init_SAR(); 		//Initializing the SAR ADC for key presses
	//Priming the PUMP
	for(i = 0; i < (ASIZE); i++)
	{
		AIC_read2(&right, &left);
		in_right[i] = right;
		in_left[i] = left;
	}
	while(1)
	{
		if(i>=ASIZE) i=0;
		if(j>=WTIME){
			if(key == SW2) az += 1;
			j = 0;
		}

		AIC_read2(&right, &left);
		in_left[i] = left;
		in_right[i] = right;

		if (filter == 0){ //bypass
			out_left = left;
			out_right = right;
		}
		else if (filter == 1){ //redundant calculation (slow down)
			16*FIR_left(i, az);
			16*FIR_right(i, az);
			out_left = left;
			out_right = right;
		}
		else if (filter == 2){ //using the HRIR output
			out_left = 16*FIR_left(i, az);
			out_right = 16*FIR_right(i, az);
		}
		else if (filter == 3){ //mono summed (using right channel)
			out_left = 16*FIR(in_right, hrir_l, i, az);
			out_right = 16*FIR(in_right, hrir_r, i, az);
		}
		else{
			out_left = 0;
			out_right= 0;
		}
		//POSTFILTER:
		AIC_write2(out_right, out_left);

		key = Get_Key_Human();
		if (key == SW1) filter += 1;
		if (filter>4) filter = 0;
		if (az > 50) az = 0;
		//filter = 1;
		//if (filter)
		//	AIC_write2(16*out_right, 16*out_left);
		//else
		//	AIC_write2(right, left);
		i++, j++;
	}
}
Advertisements

One thought on “10000 tap headers, slow implementations and distortion

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s