Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members

Audio3D.cc

Go to the documentation of this file.
00001 /*
00002 
00003     3D audio engine
00004     Copyright (C) 2000-2003 Jussi Laako
00005 
00006     This program is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 */
00021 
00022 
00023 #define COMPILE
00024 #include "Audio3D.hh"
00025 
00026 
00027 void clAudio3D::CopyToLocal(GDT *fpDest, const float *fpSrc)
00028 {
00029     long lCopyCntr;
00030 
00031     for (lCopyCntr = 0l; lCopyCntr < HRTF_LENGTH; lCopyCntr++)
00032     {
00033         fpDest[lCopyCntr] = fpSrc[lCopyCntr];
00034     }
00035     for (lCopyCntr = HRTF_LENGTH; lCopyCntr < lFFTSize; lCopyCntr++)
00036     {
00037         fpDest[lCopyCntr] = (GDT) 0;
00038     }
00039 }
00040 
00041 
00042 void clAudio3D::HeadingElev0 (int iHeading)
00043 {
00044     int iAH = abs(iHeading);
00045 
00046     if (iAH >= 0 && iAH <= 2)
00047     {
00048         CopyToLocal(fpLeftFilt, fpH0e000aL);
00049         CopyToLocal(fpRightFilt, fpH0e000aR);
00050     }
00051     else if (iAH >= 3 && iAH <= 7)
00052     {
00053         CopyToLocal(fpLeftFilt, fpH0e005aL);
00054         CopyToLocal(fpRightFilt, fpH0e005aR);
00055     }
00056     else if (iAH >= 8 && iAH <= 12)
00057     {
00058         CopyToLocal(fpLeftFilt, fpH0e010aL);
00059         CopyToLocal(fpRightFilt, fpH0e010aR);
00060     }
00061     else if (iAH >= 13 && iAH <= 17)
00062     {
00063         CopyToLocal(fpLeftFilt, fpH0e015aL);
00064         CopyToLocal(fpRightFilt, fpH0e015aR);
00065     }
00066     else if (iAH >= 18 && iAH <= 22)
00067     {
00068         CopyToLocal(fpLeftFilt, fpH0e020aL);
00069         CopyToLocal(fpRightFilt, fpH0e020aR);
00070     }
00071     else if (iAH >= 23 && iAH <= 27)
00072     {
00073         CopyToLocal(fpLeftFilt, fpH0e025aL);
00074         CopyToLocal(fpRightFilt, fpH0e025aR);
00075     }
00076     else if (iAH >= 28 && iAH <= 32)
00077     {
00078         CopyToLocal(fpLeftFilt, fpH0e030aL);
00079         CopyToLocal(fpRightFilt, fpH0e030aR);
00080     }
00081     else if (iAH >= 33 && iAH <= 37)
00082     {
00083         CopyToLocal(fpLeftFilt, fpH0e035aL);
00084         CopyToLocal(fpRightFilt, fpH0e035aR);
00085     }
00086     else if (iAH >= 38 && iAH <= 42)
00087     {
00088         CopyToLocal(fpLeftFilt, fpH0e040aL);
00089         CopyToLocal(fpRightFilt, fpH0e040aR);
00090     }
00091     else if (iAH >= 43 && iAH <= 47)
00092     {
00093         CopyToLocal(fpLeftFilt, fpH0e045aL);
00094         CopyToLocal(fpRightFilt, fpH0e045aR);
00095     }
00096     else if (iAH >= 48 && iAH <= 52)
00097     {
00098         CopyToLocal(fpLeftFilt, fpH0e050aL);
00099         CopyToLocal(fpRightFilt, fpH0e050aR);
00100     }
00101     else if (iAH >= 53 && iAH <= 57)
00102     {
00103         CopyToLocal(fpLeftFilt, fpH0e055aL);
00104         CopyToLocal(fpRightFilt, fpH0e055aR);
00105     }
00106     else if (iAH >= 58 && iAH <= 62)
00107     {
00108         CopyToLocal(fpLeftFilt, fpH0e060aL);
00109         CopyToLocal(fpRightFilt, fpH0e060aR);
00110     }
00111     else if (iAH >= 63 && iAH <= 67)
00112     {
00113         CopyToLocal(fpLeftFilt, fpH0e065aL);
00114         CopyToLocal(fpRightFilt, fpH0e065aR);
00115     }
00116     else if (iAH >= 68 && iAH <= 72)
00117     {
00118         CopyToLocal(fpLeftFilt, fpH0e070aL);
00119         CopyToLocal(fpRightFilt, fpH0e070aR);
00120     }
00121     else if (iAH >= 73 && iAH <= 77)
00122     {
00123         CopyToLocal(fpLeftFilt, fpH0e075aL);
00124         CopyToLocal(fpRightFilt, fpH0e075aR);
00125     }
00126     else if (iAH >= 78 && iAH <= 82)
00127     {
00128         CopyToLocal(fpLeftFilt, fpH0e080aL);
00129         CopyToLocal(fpRightFilt, fpH0e080aR);
00130     }
00131     else if (iAH >= 83 && iAH <= 87)
00132     {
00133         CopyToLocal(fpLeftFilt, fpH0e085aL);
00134         CopyToLocal(fpRightFilt, fpH0e085aR);
00135     }
00136     else if (iAH >= 88 && iAH <= 92)
00137     {
00138         CopyToLocal(fpLeftFilt, fpH0e090aL);
00139         CopyToLocal(fpRightFilt, fpH0e090aR);
00140     }
00141     else if (iAH >= 93 && iAH <= 97)
00142     {
00143         CopyToLocal(fpLeftFilt, fpH0e095aL);
00144         CopyToLocal(fpRightFilt, fpH0e095aR);
00145     }
00146     else if (iAH >= 98 && iAH <= 102)
00147     {
00148         CopyToLocal(fpLeftFilt, fpH0e100aL);
00149         CopyToLocal(fpRightFilt, fpH0e100aR);
00150     }
00151     else if (iAH >= 103 && iAH <= 107)
00152     {
00153         CopyToLocal(fpLeftFilt, fpH0e105aL);
00154         CopyToLocal(fpRightFilt, fpH0e105aR);
00155     }
00156     else if (iAH >= 108 && iAH <= 112)
00157     {
00158         CopyToLocal(fpLeftFilt, fpH0e110aL);
00159         CopyToLocal(fpRightFilt, fpH0e110aR);
00160     }
00161     else if (iAH >= 113 && iAH <= 117)
00162     {
00163         CopyToLocal(fpLeftFilt, fpH0e115aL);
00164         CopyToLocal(fpRightFilt, fpH0e115aR);
00165     }
00166     else if (iAH >= 118 && iAH <= 122)
00167     {
00168         CopyToLocal(fpLeftFilt, fpH0e120aL);
00169         CopyToLocal(fpRightFilt, fpH0e120aR);
00170     }
00171     else if (iAH >= 123 && iAH <= 127)
00172     {
00173         CopyToLocal(fpLeftFilt, fpH0e125aL);
00174         CopyToLocal(fpRightFilt, fpH0e125aR);
00175     }
00176     else if (iAH >= 128 && iAH <= 132)
00177     {
00178         CopyToLocal(fpLeftFilt, fpH0e130aL);
00179         CopyToLocal(fpRightFilt, fpH0e130aR);
00180     }
00181     else if (iAH >= 133 && iAH <= 137)
00182     {
00183         CopyToLocal(fpLeftFilt, fpH0e135aL);
00184         CopyToLocal(fpRightFilt, fpH0e135aR);
00185     }
00186     else if (iAH >= 138 && iAH <= 142)
00187     {
00188         CopyToLocal(fpLeftFilt, fpH0e140aL);
00189         CopyToLocal(fpRightFilt, fpH0e140aR);
00190     }
00191     else if (iAH >= 143 && iAH <= 147)
00192     {
00193         CopyToLocal(fpLeftFilt, fpH0e145aL);
00194         CopyToLocal(fpRightFilt, fpH0e145aR);
00195     }
00196     else if (iAH >= 148 && iAH <= 152)
00197     {
00198         CopyToLocal(fpLeftFilt, fpH0e150aL);
00199         CopyToLocal(fpRightFilt, fpH0e150aR);
00200     }
00201     else if (iAH >= 153 && iAH <= 157)
00202     {
00203         CopyToLocal(fpLeftFilt, fpH0e155aL);
00204         CopyToLocal(fpRightFilt, fpH0e155aR);
00205     }
00206     else if (iAH >= 158 && iAH <= 162)
00207     {
00208         CopyToLocal(fpLeftFilt, fpH0e160aL);
00209         CopyToLocal(fpRightFilt, fpH0e160aR);
00210     }
00211     else if (iAH >= 163 && iAH <= 167)
00212     {
00213         CopyToLocal(fpLeftFilt, fpH0e165aL);
00214         CopyToLocal(fpRightFilt, fpH0e165aR);
00215     }
00216     else if (iAH >= 168 && iAH <= 172)
00217     {
00218         CopyToLocal(fpLeftFilt, fpH0e170aL);
00219         CopyToLocal(fpRightFilt, fpH0e170aR);
00220     }
00221     else if (iAH >= 173 && iAH <= 177)
00222     {
00223         CopyToLocal(fpLeftFilt, fpH0e175aL);
00224         CopyToLocal(fpRightFilt, fpH0e175aR);
00225     }
00226     else
00227     {
00228         CopyToLocal(fpLeftFilt, fpH0e180aL);
00229         CopyToLocal(fpRightFilt, fpH0e180aR);
00230     }
00231     if (iHeading >= 0)
00232         Prepare(false);
00233     else
00234         Prepare(true);
00235 }
00236 
00237 
00238 void clAudio3D::HeadingElev90 ()
00239 {
00240     CopyToLocal(fpLeftFilt, fpH90e000aL);
00241     CopyToLocal(fpRightFilt, fpH90e000aR);
00242     Prepare(false);
00243 }
00244 
00245 
00246 void clAudio3D::Prepare (bool bSwapped)
00247 {
00248     GDT fLeftMin;
00249     GDT fLeftMax;
00250     GDT fRightMin;
00251     GDT fRightMax;
00252     #ifdef __GNUG__
00253     GDT fpLeftMagn[lSpectSize];
00254     GDT fpRightMagn[lSpectSize];
00255     #else
00256     clDSPAlloc LeftMagn;
00257     clDSPAlloc RightMagn;
00258     GDT *fpLeftMagn = (GDT *) LeftMagn.Size(lSpectSize * sizeof(GDT));
00259     GDT *fpRightMagn = (GDT *) RightMagn.Size(lSpectSize * sizeof(GDT));
00260     #endif
00261 
00262     if (!bSwapped)
00263     {
00264         DSP.FFTi(spLeftFilt, fpLeftFilt);
00265         DSP.FFTi(spRightFilt, fpRightFilt);
00266     }
00267     else
00268     {
00269         DSP.FFTi(spRightFilt, fpLeftFilt);
00270         DSP.FFTi(spLeftFilt, fpRightFilt);
00271     }
00272     DSP.Magnitude(fpLeftMagn, spLeftFilt, lSpectSize);
00273     DSP.Magnitude(fpRightMagn, spRightFilt, lSpectSize);
00274     DSP.MinMax(&fLeftMin, &fLeftMax, fpLeftMagn, lSpectSize);
00275     DSP.MinMax(&fRightMin, &fRightMax, fpRightMagn, lSpectSize);
00276     if (fLeftMax >= fRightMax)
00277         fAmp = (GDT) 1 / fLeftMax;
00278     else
00279         fAmp = (GDT) 1 / fRightMax;
00280 }
00281 
00282 
00283 void clAudio3D::ProcessDistance (GDT *fpLeft, GDT *fpRight, long lDataCount)
00284 {
00285     long lDataCntr;
00286     GDT fWeight2 = (GDT) 1 - fDistance;
00287 
00288     for (lDataCntr = 0l; lDataCntr < lDataCount; lDataCntr++)
00289     {
00290         fpLeft[lDataCntr] = 
00291             fpLeft[lDataCntr] * fWeight2 + fpRight[lDataCntr] * fDistance;
00292         fpRight[lDataCntr] = 
00293             fpRight[lDataCntr] * fWeight2 + fpLeft[lDataCntr] * fDistance;
00294     }
00295 }
00296 
00297 
00298 clAudio3D::clAudio3D ()
00299 {
00300     bInitialized = false;
00301 }
00302 
00303 
00304 clAudio3D::~clAudio3D ()
00305 {
00306     if (bInitialized) Uninitialize();
00307 }
00308 
00309 
00310 void clAudio3D::Initialize (long lSize)
00311 {
00312     GDT *fpNullPtr = NULL;
00313 
00314     if (bInitialized) Uninitialize();
00315     lWindowSize = lSize;
00316     lFFTSize = lWindowSize;
00317     lSpectSize = lFFTSize / 2 + 1;
00318     DSP.FFTInitialize(lFFTSize, true);
00319     fpLeftFilt = (GDT *) LeftFilt.Size(lFFTSize * sizeof(GDT));
00320     fpRightFilt = (GDT *) RightFilt.Size(lFFTSize * sizeof(GDT));
00321     spLeftFilt = (GCDT *) CLeftFilt.Size(lSpectSize * sizeof(GCDT));
00322     spRightFilt = (GCDT *) CRightFilt.Size(lSpectSize * sizeof(GCDT));
00323     LeftData.Size(lWindowSize * sizeof(GDT));
00324     RightData.Size(lWindowSize * sizeof(GDT));
00325     CopyToLocal(fpLeftFilt, fpH0e000aL);
00326     CopyToLocal(fpRightFilt, fpH0e000aR);
00327     Prepare(false);
00328     FilterLeft.Initialize(lWindowSize, fpNullPtr);
00329     FilterRight.Initialize(lWindowSize, fpNullPtr);
00330     bInitialized = true;
00331 }
00332 
00333 
00334 void clAudio3D::Uninitialize ()
00335 {
00336     FilterLeft.Uninitialize();
00337     FilterRight.Uninitialize();
00338     DSP.FFTUninitialize();
00339     bInitialized = false;
00340 }
00341 
00342 
00343 void clAudio3D::SetAngles (int iHeading, int iPitch, GDT fDist)
00344 {
00345     if (iPitch <= -35) HeadingElevN40(iHeading);
00346     else if (iPitch > -35 && iPitch <= -25) HeadingElevN30(iHeading);
00347     else if (iPitch > -25 && iPitch <= -15) HeadingElevN20(iHeading);
00348     else if (iPitch > -15 && iPitch <= -5) HeadingElevN10(iHeading);
00349     else if (iPitch > -5 && iPitch < 5) HeadingElev0(iHeading);
00350     else if (iPitch >= 5 && iPitch < 15) HeadingElev10(iHeading);
00351     else if (iPitch >= 15 && iPitch < 25) HeadingElev20(iHeading);
00352     else if (iPitch >= 25 && iPitch < 35) HeadingElev30(iHeading);
00353     else if (iPitch >= 35 && iPitch < 45) HeadingElev40(iHeading);
00354     else if (iPitch >= 45 && iPitch < 55) HeadingElev50(iHeading);
00355     else if (iPitch >= 55 && iPitch < 65) HeadingElev60(iHeading);
00356     else if (iPitch >= 65 && iPitch < 75) HeadingElev70(iHeading);
00357     else if (iPitch >= 75 && iPitch < 85) HeadingElev80(iHeading);
00358     else HeadingElev90();
00359     fDistance = fDist;
00360 }
00361 
00362 
00363 void clAudio3D::Process (GDT *fpData)
00364 {
00365     long lDestCntr;
00366     long lSrcCntr;
00367     GDT *fpLeftData = LeftData;
00368     GDT *fpRightData = RightData;
00369 
00370     lSrcCntr = 0l;
00371     for (lDestCntr = 0l; lDestCntr < lWindowSize; lDestCntr++)
00372     {
00373         fpLeftData[lDestCntr] = fpData[lSrcCntr++];
00374         fpRightData[lDestCntr] = fpData[lSrcCntr++];
00375     }
00376     FilterLeft.SetCoeffs(spLeftFilt);
00377     FilterRight.SetCoeffs(spRightFilt);
00378     FilterLeft.Put(fpLeftData, lWindowSize);
00379     FilterRight.Put(fpRightData, lWindowSize);
00380     if (!FilterLeft.Get(fpLeftData, lWindowSize))
00381         DSP.Zero(fpLeftData, lWindowSize);
00382     if (!FilterRight.Get(fpRightData, lWindowSize))
00383         DSP.Zero(fpRightData, lWindowSize);
00384     ProcessDistance(fpLeftData, fpRightData, lWindowSize);
00385     DSP.Mul(fpLeftData, fAmp, lWindowSize);
00386     DSP.Mul(fpRightData, fAmp, lWindowSize);
00387     lDestCntr = 0l;
00388     for (lSrcCntr = 0l; lSrcCntr < lWindowSize; lSrcCntr++)
00389     {
00390         fpData[lDestCntr++] = fpLeftData[lSrcCntr];
00391         fpData[lDestCntr++] = fpRightData[lSrcCntr];
00392     }
00393 }
00394 
00395 
00396 void clAudio3D::Process (GDT *fpLeftData, GDT *fpRightData)
00397 {
00398     FilterLeft.SetCoeffs(spLeftFilt);
00399     FilterRight.SetCoeffs(spRightFilt);
00400     FilterLeft.Put(fpLeftData, lWindowSize);
00401     FilterRight.Put(fpRightData, lWindowSize);
00402     if (!FilterLeft.Get(fpLeftData, lWindowSize))
00403         DSP.Zero(fpLeftData, lWindowSize);
00404     if (!FilterRight.Get(fpRightData, lWindowSize))
00405         DSP.Zero(fpRightData, lWindowSize);
00406     ProcessDistance(fpLeftData, fpRightData, lWindowSize);
00407     DSP.Mul(fpLeftData, fAmp, lWindowSize);
00408     DSP.Mul(fpRightData, fAmp, lWindowSize);
00409 }
00410 

Generated on Sun Oct 26 19:11:18 2003 for HASAS by doxygen 1.3.3