view Source/Decoder.cpp @ 12:87dc3d84c120

Addressed the load program defaults over user settings 'feature'. Removed isChild on objects that are added before the frame creation since a)they're always there and b) doesn't write to all displays present.
author martinm_home <martin.morrell@eecs.qmul.ac.uk>
date Thu, 27 Sep 2012 23:29:16 +0100
parents 76e2e62635b4
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;
    }
};