Mercurial > hg > ambi-plugin
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; } };