ese 519

Dependents:   PROJECT_3D_AUDIO

mit_hrtf_lib.c

Committer:
niv17
Date:
2015-04-07
Revision:
0:2076b4d80327

File content as of revision 0:2076b4d80327:

/*############################################################################*/
/*#                                                                          #*/
/*#  MIT HRTF C Library                                                      #*/
/*#  Copyright � 2007 Aristotel Digenis                                      #*/
/*#                                                                          #*/
/*#  Filename:  mit_hrtf_lib.c                                               #*/
/*#  Version:   0.1                                                          #*/
/*#  Date:      04/05/2007                                                   #*/
/*#  Author(s): Aristotel Digenis (adigenis@users.sourceforge.net)           #*/
/*#  Credit:    Bill Gardner and Keith Martin                                #*/
/*#  Licence:   GNU Library or Lesser General Public License (LGPL)          #*/
/*#                                                                          #*/
/*############################################################################*/


#include "../include/mit_hrtf_lib.h"
#include "../MIT_HRTF_Library/source/normal/mit_hrtf_normal_44100.h"
#include "../MIT_HRTF_Library/source/diffuse/mit_hrtf_diffuse_44100.h"
#include "../MIT_HRTF_Library/source/normal/mit_hrtf_normal_48000.h"
#include "../MIT_HRTF_Library/source/diffuse/mit_hrtf_diffuse_48000.h"
#include "../MIT_HRTF_Library/source/normal/mit_hrtf_normal_88200.h"
#include "../MIT_HRTF_Library/source/diffuse/mit_hrtf_diffuse_88200.h"
#include "../MIT_HRTF_Library/source/normal/mit_hrtf_normal_96000.h"
#include "../MIT_HRTF_Library/source/diffuse/mit_hrtf_diffuse_96000.h"


/*	Internal functions for handling the indexing of the -/+40 degree elevation 
	data which has irregular azimuth positions. */
int mit_hrtf_findAzimuthFor40Elev(int azimuth);
int mit_hrtf_findIndexFor40Elev(int azimuth);



unsigned int mit_hrtf_availability(int azimuth, int elevation, unsigned int samplerate, unsigned int diffused)
{
	if(elevation > 90 || elevation < -40)
		return 0;

	if(azimuth > 180 || azimuth < -180)
		return 0;
    
    if(diffused > 1)
        return 0;

	if(samplerate == 44100)
		return MIT_HRTF_44_TAPS;
	else if(samplerate == 48000)
		return MIT_HRTF_48_TAPS;
	else if(samplerate == 88200)
		return MIT_HRTF_88_TAPS;
	else if(samplerate == 96000)
		return MIT_HRTF_96_TAPS;

	return 0;
}



unsigned int mit_hrtf_get(int* pAzimuth, int* pElevation, unsigned int samplerate, unsigned int diffused, short* psLeft, short* psRight)
{
	int nInternalElevation = 0;
	float fAzimuthIncrement = 0;
	int nInternalAzimuth = 0;
	int nSwitchLeftRight = 0;
	int nAzimuthIndex = 0;
	const mit_hrtf_filter_set_44* pFilter44 = 0;
	const mit_hrtf_filter_set_48* pFilter48 = 0;
	const mit_hrtf_filter_set_88* pFilter88 = 0;
	const mit_hrtf_filter_set_96* pFilter96 = 0;
	const short* psLeftTaps = 0;
	const short* psRightTaps = 0;
	const short* psTempTaps = 0;
	unsigned int nTotalTaps = 0;
	unsigned int niTap = 0;

	//Check if the requested HRTF exists
	if(!mit_hrtf_availability(*pAzimuth, *pElevation, samplerate, diffused))
		return 0;

	//Snap elevation to the nearest available elevation in the filter set
	if(*pElevation < 0)
		nInternalElevation = ((*pElevation - 5) / 10) * 10;
	else
		nInternalElevation = ((*pElevation + 5) / 10) * 10;

	// Elevation of 50 has a maximum 176 in the azimuth plane so we need to handle that.
	if(nInternalElevation == 50)
	{
		if(*pAzimuth < 0)
			*pAzimuth = *pAzimuth < -176 ? -176 : *pAzimuth;
		else
			*pAzimuth = *pAzimuth > 176 ? 176 : *pAzimuth;
	}

	//Snap azimuth to the nearest available azimuth in the filter set.
	switch(nInternalElevation)
	{
	case 0:		fAzimuthIncrement = 180.f / (MIT_HRTF_AZI_POSITIONS_00 - 1);		break;	// 180 5
	case 10:	
	case -10:	fAzimuthIncrement = 180.f / (MIT_HRTF_AZI_POSITIONS_10 - 1);		break;	// 180 5
	case 20:	
	case -20:	fAzimuthIncrement = 180.f / (MIT_HRTF_AZI_POSITIONS_20 - 1);		break;	// 180 5
	case 30:	
	case -30:	fAzimuthIncrement = 180.f / (MIT_HRTF_AZI_POSITIONS_30 - 1);		break;	// 180 6
	case 40:	
	case -40:	fAzimuthIncrement = 180.f / (MIT_HRTF_AZI_POSITIONS_40 - 1);		break;	// 180 6.43
	case 50:	fAzimuthIncrement = 176.f / (MIT_HRTF_AZI_POSITIONS_50 - 1);		break;	// 176 8
	case 60:	fAzimuthIncrement = 180.f / (MIT_HRTF_AZI_POSITIONS_60 - 1);		break;	// 180 10
	case 70:	fAzimuthIncrement = 180.f / (MIT_HRTF_AZI_POSITIONS_70 - 1);		break;	// 180 15
	case 80:	fAzimuthIncrement = 180.f / (MIT_HRTF_AZI_POSITIONS_80 - 1);		break;	// 180 30
	case 90:	fAzimuthIncrement = 0;												break;	// 0   1
	};

	if(*pAzimuth < 0)
	{
		nInternalAzimuth = (int)((int)((-*pAzimuth + fAzimuthIncrement / 2.f) / fAzimuthIncrement) * fAzimuthIncrement + 0.5f);
		nSwitchLeftRight = 1;
	}
	else
	{
		nInternalAzimuth = (int)((int)((*pAzimuth + fAzimuthIncrement / 2.f) / fAzimuthIncrement) * fAzimuthIncrement + 0.5f);
	}

	//Determine array index for azimuth based on elevation
	switch(nInternalElevation)
	{
	case 0:		nAzimuthIndex = (int)((nInternalAzimuth / 180.f) * (MIT_HRTF_AZI_POSITIONS_00 - 1));	break;
	case 10: 
	case -10:	nAzimuthIndex = (int)((nInternalAzimuth / 180.f) * (MIT_HRTF_AZI_POSITIONS_10 - 1));	break;
	case 20:	
	case -20:	nAzimuthIndex = (int)((nInternalAzimuth / 180.f) * (MIT_HRTF_AZI_POSITIONS_20 - 1));	break;
	case 30:	
	case -30:	nAzimuthIndex = (int)((nInternalAzimuth / 180.f) * (MIT_HRTF_AZI_POSITIONS_30 - 1));	break;
	case 40:	
	case -40:	nAzimuthIndex = (int)((nInternalAzimuth / 180.f) * (MIT_HRTF_AZI_POSITIONS_40 - 1));	break;
	case 50:	nAzimuthIndex = (int)((nInternalAzimuth / 176.f) * (MIT_HRTF_AZI_POSITIONS_50 - 1));	break;
	case 60:	nAzimuthIndex = (int)((nInternalAzimuth / 180.f) * (MIT_HRTF_AZI_POSITIONS_60 - 1));	break;
	case 70:	nAzimuthIndex = (int)((nInternalAzimuth / 180.f) * (MIT_HRTF_AZI_POSITIONS_70 - 1));	break;
	case 80:	nAzimuthIndex = (int)((nInternalAzimuth / 180.f) * (MIT_HRTF_AZI_POSITIONS_80 - 1));	break;
	case 90:	nAzimuthIndex = (int)((nInternalAzimuth / 180.f) * (MIT_HRTF_AZI_POSITIONS_90 - 1));	break;
	};

	//The azimuths for +/- elevations need special handling
	if(nInternalElevation == 40 || nInternalElevation == -40)
	{
		nInternalAzimuth = mit_hrtf_findAzimuthFor40Elev(nInternalAzimuth);
		nAzimuthIndex = mit_hrtf_findIndexFor40Elev(nInternalAzimuth);
	}

	//Assign pointer to appropriate array depending on saple rate, normal or diffused filters, elevation, and azimuth index.
	switch(samplerate)
	{
	case 44100:
		if(diffused)
			pFilter44 = &diffuse_44;
		else
			pFilter44 = &normal_44;

		switch(nInternalElevation)
		{	
		case -10:	psLeftTaps = pFilter44->e_10[nAzimuthIndex].left;
					psRightTaps = pFilter44->e_10[nAzimuthIndex].right;		break;
		case -20:	psLeftTaps = pFilter44->e_20[nAzimuthIndex].left;
					psRightTaps = pFilter44->e_20[nAzimuthIndex].right;		break;
		case -30:	psLeftTaps = pFilter44->e_30[nAzimuthIndex].left;
					psRightTaps = pFilter44->e_30[nAzimuthIndex].right;		break;
		case -40:	psLeftTaps = pFilter44->e_40[nAzimuthIndex].left;
					psRightTaps = pFilter44->e_40[nAzimuthIndex].right;		break;
		case 0:		psLeftTaps = pFilter44->e00[nAzimuthIndex].left;
					psRightTaps = pFilter44->e00[nAzimuthIndex].right;		break;
		case 10:	psLeftTaps = pFilter44->e10[nAzimuthIndex].left;
					psRightTaps = pFilter44->e10[nAzimuthIndex].right;		break;
		case 20:	psLeftTaps = pFilter44->e20[nAzimuthIndex].left;
					psRightTaps = pFilter44->e20[nAzimuthIndex].right;		break;
		case 30:	psLeftTaps = pFilter44->e30[nAzimuthIndex].left;
					psRightTaps = pFilter44->e30[nAzimuthIndex].right;		break;
		case 40:	psLeftTaps = pFilter44->e40[nAzimuthIndex].left;
					psRightTaps = pFilter44->e40[nAzimuthIndex].right;		break;
		case 50:	psLeftTaps = pFilter44->e50[nAzimuthIndex].left;
					psRightTaps = pFilter44->e50[nAzimuthIndex].right;		break;
		case 60:	psLeftTaps = pFilter44->e60[nAzimuthIndex].left;
					psRightTaps = pFilter44->e60[nAzimuthIndex].right;		break;
		case 70:	psLeftTaps = pFilter44->e70[nAzimuthIndex].left;
					psRightTaps = pFilter44->e70[nAzimuthIndex].right;		break;
		case 80:	psLeftTaps = pFilter44->e80[nAzimuthIndex].left;
					psRightTaps = pFilter44->e80[nAzimuthIndex].right;		break;
		case 90:	psLeftTaps = pFilter44->e90[nAzimuthIndex].left;
					psRightTaps = pFilter44->e90[nAzimuthIndex].right;		break;
		};
		
		//How many taps to copy later to user's buffers
		nTotalTaps = MIT_HRTF_44_TAPS;
		break;
	case 48000:
		if(diffused)
			pFilter48 = &diffuse_48;
		else
			pFilter48 = &normal_48;

		switch(nInternalElevation)
		{	
		case -10:	psLeftTaps = pFilter48->e_10[nAzimuthIndex].left;
					psRightTaps = pFilter48->e_10[nAzimuthIndex].right;		break;
		case -20:	psLeftTaps = pFilter48->e_20[nAzimuthIndex].left;
					psRightTaps = pFilter48->e_20[nAzimuthIndex].right;		break;
		case -30:	psLeftTaps = pFilter48->e_30[nAzimuthIndex].left;
					psRightTaps = pFilter48->e_30[nAzimuthIndex].right;		break;
		case -40:	psLeftTaps = pFilter48->e_40[nAzimuthIndex].left;
					psRightTaps = pFilter48->e_40[nAzimuthIndex].right;		break;
		case 0:		psLeftTaps = pFilter48->e00[nAzimuthIndex].left;
					psRightTaps = pFilter48->e00[nAzimuthIndex].right;		break;
		case 10:	psLeftTaps = pFilter48->e10[nAzimuthIndex].left;
					psRightTaps = pFilter48->e10[nAzimuthIndex].right;		break;
		case 20:	psLeftTaps = pFilter48->e20[nAzimuthIndex].left;
					psRightTaps = pFilter48->e20[nAzimuthIndex].right;		break;
		case 30:	psLeftTaps = pFilter48->e30[nAzimuthIndex].left;
					psRightTaps = pFilter48->e30[nAzimuthIndex].right;		break;
		case 40:	psLeftTaps = pFilter48->e40[nAzimuthIndex].left;
					psRightTaps = pFilter48->e40[nAzimuthIndex].right;		break;
		case 50:	psLeftTaps = pFilter48->e50[nAzimuthIndex].left;
					psRightTaps = pFilter48->e50[nAzimuthIndex].right;		break;
		case 60:	psLeftTaps = pFilter48->e60[nAzimuthIndex].left;
					psRightTaps = pFilter48->e60[nAzimuthIndex].right;		break;
		case 70:	psLeftTaps = pFilter48->e70[nAzimuthIndex].left;
					psRightTaps = pFilter48->e70[nAzimuthIndex].right;		break;
		case 80:	psLeftTaps = pFilter48->e80[nAzimuthIndex].left;
					psRightTaps = pFilter48->e80[nAzimuthIndex].right;		break;
		case 90:	psLeftTaps = pFilter48->e90[nAzimuthIndex].left;
					psRightTaps = pFilter48->e90[nAzimuthIndex].right;		break;
		};
		
		//How many taps to copy later to user's buffers
		nTotalTaps = MIT_HRTF_48_TAPS;
		break;
	case 88200:
		if(diffused)
			pFilter88 = &diffuse_88;
		else
			pFilter88 = &normal_88;

		switch(nInternalElevation)
		{	
		case -10:	psLeftTaps = pFilter88->e_10[nAzimuthIndex].left;
					psRightTaps = pFilter88->e_10[nAzimuthIndex].right;		break;
		case -20:	psLeftTaps = pFilter88->e_20[nAzimuthIndex].left;
					psRightTaps = pFilter88->e_20[nAzimuthIndex].right;		break;
		case -30:	psLeftTaps = pFilter88->e_30[nAzimuthIndex].left;
					psRightTaps = pFilter88->e_30[nAzimuthIndex].right;		break;
		case -40:	psLeftTaps = pFilter88->e_40[nAzimuthIndex].left;
					psRightTaps = pFilter88->e_40[nAzimuthIndex].right;		break;
		case 0:		psLeftTaps = pFilter88->e00[nAzimuthIndex].left;
					psRightTaps = pFilter88->e00[nAzimuthIndex].right;		break;
		case 10:	psLeftTaps = pFilter88->e10[nAzimuthIndex].left;
					psRightTaps = pFilter88->e10[nAzimuthIndex].right;		break;
		case 20:	psLeftTaps = pFilter88->e20[nAzimuthIndex].left;
					psRightTaps = pFilter88->e20[nAzimuthIndex].right;		break;
		case 30:	psLeftTaps = pFilter88->e30[nAzimuthIndex].left;
					psRightTaps = pFilter88->e30[nAzimuthIndex].right;		break;
		case 40:	psLeftTaps = pFilter88->e40[nAzimuthIndex].left;
					psRightTaps = pFilter88->e40[nAzimuthIndex].right;		break;
		case 50:	psLeftTaps = pFilter88->e50[nAzimuthIndex].left;
					psRightTaps = pFilter88->e50[nAzimuthIndex].right;		break;
		case 60:	psLeftTaps = pFilter88->e60[nAzimuthIndex].left;
					psRightTaps = pFilter88->e60[nAzimuthIndex].right;		break;
		case 70:	psLeftTaps = pFilter88->e70[nAzimuthIndex].left;
					psRightTaps = pFilter88->e70[nAzimuthIndex].right;		break;
		case 80:	psLeftTaps = pFilter88->e80[nAzimuthIndex].left;
					psRightTaps = pFilter88->e80[nAzimuthIndex].right;		break;
		case 90:	psLeftTaps = pFilter88->e90[nAzimuthIndex].left;
					psRightTaps = pFilter88->e90[nAzimuthIndex].right;		break;
		};
		
		//How many taps to copy later to user's buffers
		nTotalTaps = MIT_HRTF_88_TAPS;
		break;
	case 96000:
		if(diffused)
			pFilter96 = &diffuse_96;
		else
			pFilter96 = &normal_96;

		switch(nInternalElevation)
		{	
		case -10:	psLeftTaps = pFilter96->e_10[nAzimuthIndex].left;
					psRightTaps = pFilter96->e_10[nAzimuthIndex].right;		break;
		case -20:	psLeftTaps = pFilter96->e_20[nAzimuthIndex].left;
					psRightTaps = pFilter96->e_20[nAzimuthIndex].right;		break;
		case -30:	psLeftTaps = pFilter96->e_30[nAzimuthIndex].left;
					psRightTaps = pFilter96->e_30[nAzimuthIndex].right;		break;
		case -40:	psLeftTaps = pFilter96->e_40[nAzimuthIndex].left;
					psRightTaps = pFilter96->e_40[nAzimuthIndex].right;		break;
		case 0:		psLeftTaps = pFilter96->e00[nAzimuthIndex].left;
					psRightTaps = pFilter96->e00[nAzimuthIndex].right;		break;
		case 10:	psLeftTaps = pFilter96->e10[nAzimuthIndex].left;
					psRightTaps = pFilter96->e10[nAzimuthIndex].right;		break;
		case 20:	psLeftTaps = pFilter96->e20[nAzimuthIndex].left;
					psRightTaps = pFilter96->e20[nAzimuthIndex].right;		break;
		case 30:	psLeftTaps = pFilter96->e30[nAzimuthIndex].left;
					psRightTaps = pFilter96->e30[nAzimuthIndex].right;		break;
		case 40:	psLeftTaps = pFilter96->e40[nAzimuthIndex].left;
					psRightTaps = pFilter96->e40[nAzimuthIndex].right;		break;
		case 50:	psLeftTaps = pFilter96->e50[nAzimuthIndex].left;
					psRightTaps = pFilter96->e50[nAzimuthIndex].right;		break;
		case 60:	psLeftTaps = pFilter96->e60[nAzimuthIndex].left;
					psRightTaps = pFilter96->e60[nAzimuthIndex].right;		break;
		case 70:	psLeftTaps = pFilter96->e70[nAzimuthIndex].left;
					psRightTaps = pFilter96->e70[nAzimuthIndex].right;		break;
		case 80:	psLeftTaps = pFilter96->e80[nAzimuthIndex].left;
					psRightTaps = pFilter96->e80[nAzimuthIndex].right;		break;
		case 90:	psLeftTaps = pFilter96->e90[nAzimuthIndex].left;
					psRightTaps = pFilter96->e90[nAzimuthIndex].right;		break;
		};
		
		//How many taps to copy later to user's buffers
		nTotalTaps = MIT_HRTF_96_TAPS;
		break;
	};

	//Switch left and right ear if the azimuth is to the left of front centre (azimuth < 0)
	if(nSwitchLeftRight)
	{
		psTempTaps = psRightTaps;
		psRightTaps = psLeftTaps;
		psLeftTaps = psTempTaps;
	}
	
	//Copy taps to user's arrays
	for(niTap = 0; niTap < nTotalTaps; niTap++)
	{
		psLeft[niTap] = psLeftTaps[niTap];
		psRight[niTap] = psRightTaps[niTap];
	}

	//Assign the real azimuth and elevation used
	*pAzimuth = nInternalAzimuth;
	*pElevation = nInternalElevation;

	return nTotalTaps;	
}



int mit_hrtf_findAzimuthFor40Elev(int azimuth)
{
	if(azimuth >= 0 && azimuth < 4)
		return 0;
	else if(azimuth >= 4 && azimuth < 10)
		return 6;
	else if(azimuth >= 10 && azimuth < 17)
		return 13;
	else if(azimuth >= 17 && azimuth < 23)
		return 19;
	else if(azimuth >= 23 && azimuth < 30)
		return 26;
	else if(azimuth >= 30 && azimuth < 36)
		return 32;
	else if(azimuth >= 36 && azimuth < 43)
		return 39;
	else if(azimuth >= 43 && azimuth < 49)
		return 45;
	else if(azimuth >= 49 && azimuth < 55)
		return 51;
	else if(azimuth >= 55 && azimuth < 62)
		return 58;
	else if(azimuth >= 62 && azimuth < 68)
		return 64;
	else if(azimuth >= 68 && azimuth < 75)
		return 71;
	else if(azimuth >= 75 && azimuth < 81)
		return 77;
	else if(azimuth >= 81 && azimuth < 88)
		return 84;
	else if(azimuth >= 88 && azimuth < 94)
		return 90;
	else if(azimuth >= 94 && azimuth < 100)
		return 96;
	else if(azimuth >= 100 && azimuth < 107)
		return 103;
	else if(azimuth >= 107 && azimuth < 113)
		return 109;
	else if(azimuth >= 113 && azimuth < 120)
		return 116;
	else if(azimuth >= 120 && azimuth < 126)
		return 122;
	else if(azimuth >= 126 && azimuth < 133)
		return 129;
	else if(azimuth >= 133 && azimuth < 139)
		return 135;
	else if(azimuth >= 139 && azimuth < 145)
		return 141;
	else if(azimuth >= 145 && azimuth < 152)
		return 148;
	else if(azimuth >= 152 && azimuth < 158)
		return 154;
	else if(azimuth >= 158 && azimuth < 165)
		return 161;
	else if(azimuth >= 165 && azimuth < 171)
		return 167;
	else if(azimuth >= 171 && azimuth < 178)
		return 174;
	else
		return 180;
};



int mit_hrtf_findIndexFor40Elev(int azimuth)
{
	if(azimuth >= 0 && azimuth < 4)
		return 0;
	else if(azimuth >= 4 && azimuth < 10)
		return 1;
	else if(azimuth >= 10 && azimuth < 17)
		return 2;
	else if(azimuth >= 17 && azimuth < 23)
		return 3;
	else if(azimuth >= 23 && azimuth < 30)
		return 4;
	else if(azimuth >= 30 && azimuth < 36)
		return 5;
	else if(azimuth >= 36 && azimuth < 43)
		return 6;
	else if(azimuth >= 43 && azimuth < 49)
		return 7;
	else if(azimuth >= 49 && azimuth < 55)
		return 8;
	else if(azimuth >= 55 && azimuth < 62)
		return 9;
	else if(azimuth >= 62 && azimuth < 68)
		return 10;
	else if(azimuth >= 68 && azimuth < 75)
		return 11;
	else if(azimuth >= 75 && azimuth < 81)
		return 12;
	else if(azimuth >= 81 && azimuth < 88)
		return 13;
	else if(azimuth >= 88 && azimuth < 94)
		return 14;
	else if(azimuth >= 94 && azimuth < 100)
		return 15;
	else if(azimuth >= 100 && azimuth < 107)
		return 16;
	else if(azimuth >= 107 && azimuth < 113)
		return 17;
	else if(azimuth >= 113 && azimuth < 120)
		return 18;
	else if(azimuth >= 120 && azimuth < 126)
		return 19;
	else if(azimuth >= 126 && azimuth < 133)
		return 20;
	else if(azimuth >= 133 && azimuth < 139)
		return 21;
	else if(azimuth >= 139 && azimuth < 145)
		return 22;
	else if(azimuth >= 145 && azimuth < 152)
		return 23;
	else if(azimuth >= 152 && azimuth < 158)
		return 24;
	else if(azimuth >= 158 && azimuth < 165)
		return 25;
	else if(azimuth >= 165 && azimuth < 171)
		return 26;
	else if(azimuth >= 171 && azimuth < 178)
		return 27;
	else
		return 28;
}