view Source/Decoder.cpp @ 13:989865d55c73 tip

Commit.
author martinm_home <martin.morrell@eecs.qmul.ac.uk>
date Thu, 27 Sep 2012 23:30:29 +0100
parents 87dc3d84c120
children
line wrap: on
line source
/*
 *  Decoder.cpp
 *  ClassicAmbiDec
 *
 *  Created by Martin Morrell on 14/06/2012.
 *  Copyright 2012 Queen Mary University of London. All rights reserved.
 *
 */


#include "Decoder.h"
#define _USE_MATH_DEFINES
#include <cmath>
#include <stdlib.h>
#define RearVerbWidth 55    //Rear Verb Microphone Width
#define RearVerbPattern 0.5 //Rear Verb Microphone Pattern
#define HiVerbWidth 30      //Hi Verb Microphone Width
#define HiVerbPattern 0.5   //Hi Verb Microphone Pattern


Decoder::Decoder()
{
 //  myDecoder parameters
 Rotate=0.0;
 Tilt=0.0;
 Tumble=0.0;
 Zoom=0.0;
 ZoomMethod=0.0;
 Width=45.0;
 Pattern=0.5;
 Mode=0;
 RearVerb=-100;
 HiVerb=-100;
 surMode=0;
 surPattern=0.5;
 surWidth=60.0;
 surGain = 0.0;
 Fc = 120;
 centrePattern=0.5;
 centreGain=0.0;
 subGain=0.0;
 Fs = 44100;
 filterCoefs();
 decoderMode=2; //Default mode is Stereo
 channelOrder=1;
 mode5x=0;
 
 // Zero up decoder outputs as a safety
 outputL=0.0;
 outputR=0.0;
 outputC=0.0;
 outputS=0.0;
 outputSL=0.0;
 outputSR=0.0;
};


//Conversion Functions
double Decoder::degRad(double angle)
{
	return (angle/180*M_PI);
};


double Decoder::radDeg(double angle)
{
	return (angle/M_PI*180);
};


//Overall Function
int Decoder::processDecoder(double &w, double &x, double &y, double &z)
{
    //Sound field rotations. Only called if the value is not 0
	if (Rotate!=0.0f)
		rotateField(x, y);
	
	if (Tilt!=0.0f)
		tiltField(y, z);
	
	if (Tumble!=0.0f)
		tumbleField(x, z);
	
	//Zoom function. Only called if the value is not 0
	if (Zoom!=0.0f) {
		switch (ZoomMethod) {
			case 0:
				dominanceZoom(w, x, y, z);
				break;
			case 1:
				pressZoom(w, x, y, z);
				break;
			case 2:
				pushZoom(w, x, y, z);
				break;
			case 3:
				focusZoom(w, x, y, z);
				break;
				
			default:
				break;
		}
	}
    
    
    switch (decoderMode) {
        case 1:
            monoDecoder(w, x, y, z);
            if (channelOrder==0) {
                output[0]=outputC;
                return 1;
            }
            else if (channelOrder==1) {
                output[0]=0;
                output[1]=0;
                output[2]=outputC;
                output[3]=0;
                output[4]=0;
                output[5]=0;
                return 6;
            }
            else {
                return 0;
            }
            break;
            
        case 2:
            stereoDecoder(w, x, y, z);
            if (channelOrder==0) {
                output[0]=outputL;
                output[1]=outputR;
                return 2;
            }
            else if (channelOrder==1) {
                output[0]=outputL;
                output[1]=outputR;
                output[2]=0;
                output[3]=0;
                output[4]=0;
                output[5]=0;
                return 6;
            }
            else {
                return 0;
            }
            break;
            
        case 3:
        {
            twoOneDecoder(w, x, y, z);
            if (channelOrder==0) {
                output[0]=outputL;
                output[1]=outputR;
                output[2]=outputS;
                return 3;
            }
            else if (channelOrder==1) {
                output[0]=outputL;
                output[1]=outputR;
                output[2]=0;
                output[3]=outputS;
                output[4]=0;
                output[5]=0;
                return 6;
            }
            else {
                return 0;
            }
            break;
        }
            
        case 4:
            quadDecoder(w, x, y, z);
            if (channelOrder==0) {
                output[0]=outputL;
                output[1]=outputR;
                output[2]=outputSR;
                output[3]=outputSR;
                return 4;
            }
            else if (channelOrder==1) {
                output[0]=outputL;
                output[1]=outputR;
                output[2]=0;
                output[3]=0;
                output[4]=outputSL;
                output[5]=outputSR;
                return 6;
            break;
            }
            else {
                return 0;
            }
            
        case 5:
            fiveDecoder(w, x, y, z);
            if (channelOrder==0) {
                output[0]=outputL;
                output[1]=outputR;
                output[2]=outputC;
                output[3]=outputSL;
                output[4]=outputSR;
                return 5;
            }
            else if (channelOrder==1) {
                output[0]=outputL;
                output[1]=outputR;
                output[2]=outputC;
                output[3]=0;
                output[4]=outputSL;
                output[5]=outputSR;
                return 6;
            break;
            }
            else {
                return 0;
            }
            
        case 6:
            fiveOneDecoder(w, x, y, z);
            if (channelOrder==0) {
                output[0]=outputL;
                output[1]=outputR;
                output[2]=outputC;
                output[3]=outputS;
                output[4]=outputSL;
                output[5]=outputSR;
                return 6;
            }
            else if (channelOrder==1) {
                output[0]=outputL;
                output[1]=outputR;
                output[2]=outputC;
                output[3]=outputS;
                output[4]=outputSL;
                output[5]=outputSR;
                return 6;
                break;
            }
            else {
                return 0;
            }
            
        default:
            return 0;
            break;
    }
};


//Decoder Mode Functions
void Decoder::monoDecoder(double &w, double &x, double &y, double &z)//NOT USED
{
	//Centre virtual mic
    centreMic(w, x);
};


void Decoder::stereoDecoder(double &w, double &x, double &y, double &z)
{
	switch (Mode) {
		case 0:
			xyDecode(w, x, y, z);
			break;
		case 1:
			msDecode(w, x, y, z);
			break;	
		default:
			break;
	}
	

	if (RearVerb > -40) {
		rearVerb(w, x, y, z);
	}
	
	if (HiVerb >-40) {
		hiVerb(w, x, y, z);
	}
};


void Decoder::twoOneDecoder(double &w, double &x, double &y, double &z)
{
    //Subwoofer signal and filtering
    filterLF(w);
    filterHF(w, x, y, z);
    
    
    //Front virtual mics
 	switch (Mode) {
		case 0:
			xyDecode(w, x, y, z);
			break;
		case 1:
			msDecode(w, x, y, z);
			break;	
		default:
			break;
	}   
    
    
    //Reverbs
    if (RearVerb > -40) {
		rearVerb(w, x, y, z);
	}
	
	if (HiVerb >-40) {
		hiVerb(w, x, y, z);
	}
	
};



void Decoder::quadDecoder(double &w, double &x, double &y, double &z)
{
    //Front virtual mics
 	switch (Mode) {
		case 0:
			xyDecode(w, x, y, z);
			break;
		case 1:
			msDecode(w, x, y, z);
			break;	
		default:
			break;
	}   
    
	//Rear virtual mics
	switch (surMode) {
		case 0:
			xySurDecode(w, x, y, z);
			break;
		case 1:
			msSurDecode(w, x, y, z);
			break;
            
		default:
			break;
	}
};



void Decoder::fiveDecoder(double &w, double &x, double &y, double &z)
{
    switch (mode5x) {
        case 0://Mic Pattern Decode
        {
        //Centre virtual mic
        centreMic(w, x);
        
        //Front virtual mics
        switch (Mode) {
            case 0:
            {
                xyDecode(w, x, y, z);
                break;
            }
            case 1:
            {
                msDecode(w, x, y, z);
                break;
            }
            default:
                break;
        }   
        
        //Rear virtual mics
        switch (surMode) {
            case 0:
            {
                xySurDecode(w, x, y, z);
                break;
            }
            case 1:
            {
                msSurDecode(w, x, y, z);
                break;
            }
            default:
                break;
        }
            break;
        }
        case 1://Heller 1 Decode - little centre
        {
            heller1(w, x, y, z);
            break;
        }
        case 2://Heller 2 Decode - More centre
        {
            heller2(w, x, y, z);
            break;
        }

            
        default:
            break;
    }
};



void Decoder::fiveOneDecoder(double &w, double &x, double &y, double &z)
{
    //Subwoofer signal and filtering
    filterLF(w);
    filterHF(w, x, y, z);

    switch (mode5x) {
        case 0://Mic Pattern Decode
        {
            //Centre virtual mic
            centreMic(w, x);
            
            //Front virtual mics
            switch (Mode) {
                case 0:
                {
                    xyDecode(w, x, y, z);
                    break;
                }
                case 1:
                {
                    msDecode(w, x, y, z);
                    break;
                }
                default:
                    break;
            }
            
            //Rear virtual mics
            switch (surMode) {
                case 0:
                {
                    xySurDecode(w, x, y, z);
                    break;
                }
                case 1:
                {
                    msSurDecode(w, x, y, z);
                    break;
                }
                default:
                    break;
            }
            break;
        }
        case 1://Heller 1 Decode - little centre
        {
            heller1(w, x, y, z);
            break;
        }
        case 2://Heller 2 Decode - More centre
        {
            heller2(w, x, y, z);
            break;
        }
            
            
        default:
            break;
    }
};



//Sound Field Rotations
void Decoder::rotateField(double &x, double &y)
{	
	double temp = x;
	x = cos(degRad(Rotate))*temp - sin(degRad(Rotate))*y;
	y = cos(degRad(Rotate))*y + sin(degRad(Rotate))*temp;
};


void Decoder::tiltField(double &y, double &z)
{
	double temp = y;
	y = cos(degRad(Tilt))*temp - sin(degRad(Tilt))*z;
	z = cos(degRad(Tilt))*z + sin(degRad(Tilt))*temp;	
};


void Decoder::tumbleField(double &x, double &z)
{
	double temp = x;
	x = cos(degRad(Tumble))*temp - sin(degRad(Tumble))*z;
	z = cos(degRad(Tumble))*z + sin(degRad(Tumble))*temp;
};




//Zoom Methods
void Decoder::dominanceZoom(double &w, double &x, double &y, double &z)
{
	double lambda = pow(10,(Zoom*0.24/20));
    double temp[4];
	temp[0]=w;
	temp[1]=x;
	temp[2]=y;
	temp[3]=z;
	
	w = 0.5*(lambda+pow(lambda,-1))*temp[0] + pow(8,-0.5)*(lambda-pow(lambda,-1))*temp[1];
	x = 0.5*(lambda+pow(lambda,-1))*temp[1] + pow(2,-0.5)*(lambda-pow(lambda,-1))*temp[0];
};


void Decoder::pressZoom(double &w, double &x, double &y, double &z)
{
    double temp[4];
	temp[0]=w;
	temp[1]=x;
	temp[2]=y;
	temp[3]=z;
	
	x = (sqrt(2.0)*std::abs(sin(degRad(Zoom*0.9)))*sin(degRad(Zoom*0.9))*temp[0]) + (pow(cos(degRad(Zoom*0.9)),2)*temp[1]);
	y = cos(degRad(Zoom*0.9))*temp[2];
	z = cos(degRad(Zoom*0.9))*temp[3];
};


void Decoder::pushZoom(double &w, double &x, double &y, double &z)
{
    double temp[4];
	temp[0]=w;
	temp[1]=x;
	temp[2]=y;
	temp[3]=z;
    
	x = (sqrt(2.0)*std::abs(sin(degRad(Zoom*0.9)))*sin(degRad(Zoom*0.9))*temp[0]) + (pow(cos(degRad(Zoom*0.9)),2)*temp[1]);
	y = pow(cos(degRad(Zoom*0.9)),2)*temp[2];
	z = pow(cos(degRad(Zoom*0.9)),2)*temp[3];
};


void Decoder::focusZoom(double &w, double &x, double &y, double &z)
{
    double temp[4];
	temp[0]=w;
	temp[1]=x;
	temp[2]=y;
	temp[3]=z;
	
	w = ((1/(1+std::abs(sin(degRad(Zoom*0.9)))))*temp[0]) + ((1/sqrt(2.0))*(sin(degRad(Zoom*0.9))/(1+std::abs(sin(degRad(Zoom*0.9))))))* temp[1];
	x = sqrt(2.0)*(sin(degRad(Zoom*0.9))/(1+std::abs(sin(degRad(Zoom*0.9)))))*temp[0] + (1/(1+std::abs(sin(degRad(Zoom*0.9)))))*temp[1];
	y = sqrt((1-std::abs(sin(degRad(Zoom*0.9))))/(1+std::abs(sin(degRad(Zoom*0.9)))))*temp[2];
	z = sqrt((1-std::abs(sin(degRad(Zoom*0.9))))/(1+std::abs(sin(degRad(Zoom*0.9)))))*temp[3];
};



//Stereo Microphone Pairs
void Decoder::xyDecode(double &w, double &x, double &y, double &z)
{	
    outputL = Pattern*sqrt(2.0)*w + (1-Pattern)*(cos(degRad(Width))*x + sin(degRad(Width))*y);
    outputR = Pattern*sqrt(2.0)*w + (1-Pattern)*(cos(degRad(Width))*x - sin(degRad(Width))*y);
};


void Decoder::msDecode(double &w, double &x, double &y, double &z)
{
	outputL = (cos(degRad(Width))*(Pattern*w*sqrt(2.0) + (1-Pattern)*x)) + (sin(degRad(Width))*y);
	outputR = (cos(degRad(Width))*(Pattern*w*sqrt(2.0) + (1-Pattern)*x)) - (sin(degRad(Width))*y);
};


//Stereo Reverbs
void Decoder::rearVerb(double &w, double &x, double &y, double &z)
{
	switch (Mode) {
		case 0:
			outputL += (RearVerbPattern*sqrt(2.0)*w + (1-RearVerbPattern)*(cos(degRad(RearVerbWidth))*-x + sin(degRad(RearVerbWidth))*y))*pow(10, RearVerb/20);
            outputR += (RearVerbPattern*sqrt(2.0)*w + (1-RearVerbPattern)*(cos(degRad(RearVerbWidth))*-x - sin(degRad(RearVerbWidth))*y))*pow(10, RearVerb/20);
			break;
		case 1:
            outputL += ((cos(degRad(RearVerbWidth))*(RearVerbPattern*w*sqrt(2.0) + (1-RearVerbPattern)*-x)) + (sin(degRad(RearVerbWidth))*y))*pow(10, RearVerb/20);
            outputR += ((cos(degRad(RearVerbWidth))*(RearVerbPattern*w*sqrt(2.0) + (1-RearVerbPattern)*-x)) - (sin(degRad(RearVerbWidth))*y))*pow(10, RearVerb/20);
			break;
	}
};

void Decoder::hiVerb(double &w, double &x, double &y, double &z)
{
	switch (Mode) {
		case 0:
			outputL += (HiVerbPattern*sqrt(2.0)*w + (1-HiVerbPattern)*(cos(degRad(HiVerbWidth))*z + sin(degRad(HiVerbWidth))*y))*pow(10, HiVerb/20);
            outputR += (HiVerbPattern*sqrt(2.0)*w + (1-HiVerbPattern)*(cos(degRad(HiVerbWidth))*z - sin(degRad(HiVerbWidth))*y))*pow(10, HiVerb/20);
			break;
		case 1:
            outputL += ((cos(degRad(HiVerbWidth))*(HiVerbPattern*w*sqrt(2.0) + (1-HiVerbPattern)*z)) + (sin(degRad(HiVerbWidth))*y))*pow(10, HiVerb/20);
            outputR += ((cos(degRad(HiVerbWidth))*(HiVerbPattern*w*sqrt(2.0) + (1-HiVerbPattern)*z)) - (sin(degRad(HiVerbWidth))*y))*pow(10, HiVerb/20);
			break;
	}
};


//Surround Microphone Pairs
void Decoder::xySurDecode(double &w, double &x, double &y, double &z)
{	
    outputSL = (surPattern*sqrt(2.0)*w + (1-surPattern)*(cos(degRad(surWidth))*-x + sin(degRad(surWidth))*y))*pow(10, surGain/20);
    outputSR = (surPattern*sqrt(2.0)*w + (1-surPattern)*(cos(degRad(surWidth))*-x - sin(degRad(surWidth))*y))*pow(10, surGain/20);
};


void Decoder::msSurDecode(double &w, double &x, double &y, double &z)
{
	outputSL = ((cos(degRad(surWidth))*(surPattern*w*sqrt(2.0) + (1-surPattern)*-x)) + (sin(degRad(surWidth))*y))*pow(10, surGain/20);
	outputSR = ((cos(degRad(surWidth))*(surPattern*w*sqrt(2.0) + (1-surPattern)*-x)) - (sin(degRad(surWidth))*y))*pow(10, surGain/20);
};


//Centre Microphone Pairs
void Decoder::centreMic(double &w, double &x)
{
    outputC = (centrePattern*sqrt(2.0)*w + (1-centrePattern)*x) * pow(10, centreGain/20);
};


//Heller 5.x Decoding
void Decoder::heller1(double &w, double &x, double &y, double &z)
{
    outputL = (0.28205165*w +0.24760232*x +0.18790454*y)*1.40171951577097;
    outputR = (0.28204229*w +0.24758662*x -0.18792311*y)*1.40171951577097;
    outputC = (-0.04881270*w -0.02756928*x +0.00001724*y)*1.40171951577097;
    outputSL = (0.44947336*w -0.23381746*x +0.31911519*y)*1.40171951577097;
    outputSR = (0.44945895*w -0.23380219*x -0.31911386*y)*1.40171951577097;
};


void Decoder::heller2(double &w, double &x, double &y, double &z)
{
    outputL = (0.21426224*w +0.19218459*x +0.20409261*y)*1.38921598327229;
    outputR = (0.21426400*w +0.19218379*x -0.20409362*y)*1.38921598327229;
    outputC = (0.09993309*w +0.15577050*x +0.00000000*y)*1.38921598327229;
    outputSL = (0.44287748*w -0.27006948*x +0.30405695*y)*1.38921598327229;
    outputSR = (0.44287676*w -0.27006941*x -0.30405595*y)*1.38921598327229;
};


//Second Order IIR Filter
void Decoder::filterCoefs(){
    double k = tan((M_PI*Fc)/Fs);
    double denominator = pow(k, 2.0) + 2.0*k + 1;
    
    clearFilter();
    
    //a values
    a[0] = 1;
    a[1] = (2.0*(pow(k, 2.0)-1))/denominator;
    a[2] = (pow(k, 2.0) - 2.0*k + 1)/denominator;
    
    //b LF value
    bLF[0] = pow(k, 2.0) / denominator;
    bLF[1] = 2.0 * bLF[0];
    bLF[2] = bLF[0];
    
    //b HF values
    bHF[0] = 1/denominator;
    bHF[1] = -2 * bHF[0];
    bHF[2] = bHF[0];
};


void Decoder::filterLF(double &w){
    double outLF;
    
    //LF Filtering
    outLF = w*sqrt(2.0)*bLF[0] + prevInS[0]*bLF[1] + prevInS[1]*bLF[2] - prevOutS[0]*a[1] - prevOutS[1]*a[2];
    
    //Previous Input and Output Samples
    prevOutS[1] = prevOutS[0];
    prevOutS[0] = outLF;
    prevInS[1] = prevInS[0];
    prevInS[0] = w*sqrt(2.0);
    
    //Final subwoofer Output
    outputS = outLF*pow(10, subGain/20);
};


void Decoder::filterHF(double &w, double &x, double &y, double &z){
    double outHFw, outHFx, outHFy, outHFz;
    
    //w Filtering
    outHFw = w*bHF[0] + prevInw[0]*bHF[1] + prevInw[1]*bHF[2] - prevOutw[0]*a[1] - prevOutw[1]*a[2];
    prevOutw[1] = prevOutw[0];
    prevOutw[0] = outHFw;
    prevInw[1] = prevInw[0];
    prevInw[0] = w;
    w = -outHFw;
    
    //x Filtering
    outHFx = x*bHF[0] + prevInx[0]*bHF[1] + prevInx[1]*bHF[2] - prevOutx[0]*a[1] - prevOutx[1]*a[2];
    prevOutx[1] = prevOutx[0];
    prevOutx[0] = outHFx;
    prevInx[1] = prevInx[0];
    prevInx[0] = x;
    x = -outHFx;
    
    //y Filtering
    outHFy = y*bHF[0] + prevIny[0]*bHF[1] + prevIny[1]*bHF[2] - prevOuty[0]*a[1] - prevOuty[1]*a[2];
    prevOuty[1] = prevOuty[0];
    prevOuty[0] = outHFy;
    prevIny[1] = prevIny[0];
    prevIny[0] = y;
    y = -outHFy;
    
    //z Filtering
    outHFz = z*bHF[0] + prevInz[0]*bHF[1] + prevInz[1]*bHF[2] - prevOutz[0]*a[1] - prevOutz[1]*a[2];
    prevOutz[1] = prevOutz[0];
    prevOutz[0] = outHFz;
    prevInz[1] = prevInz[0];
    prevInz[0] = z;
    z = -outHFz;
};


void Decoder::clearFilter(){
    for (int i=0; i<2; i++) {
        prevInS[i] = 0;
        prevOutS[i] = 0;
        prevInw[i] = 0;
        prevOutw[i] = 0;
        prevInx[i] = 0;
        prevOutx[i] = 0;
        prevIny[i] = 0;
        prevOuty[i] = 0;
        prevInz[i] = 0;
        prevOutz[i] = 0;
    }
};