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

BeamAudio.cc

Go to the documentation of this file.
00001 /*
00002 
00003     Server for beamformed audio
00004     Copyright (C) 2000-2001 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 #include <stdio.h>
00024 #include <string.h>
00025 #include <signal.h>
00026 #include <math.h>
00027 #include <float.h>
00028 #include <unistd.h>
00029 #include <sched.h>
00030 #include <sys/time.h>
00031 #include <sys/types.h>
00032 
00033 #include "BeamAudio.hh"
00034 
00035 
00036 static bool bDebug;
00037 static bool bDaemon;
00038 clBeamAudio *BeamAudio;
00039 
00040 
00041 void SigHandler (int iSigNum)
00042 {
00043     switch (iSigNum)
00044     {
00045         case SIGSEGV:
00046             if (bDebug)
00047             {
00048                 printf("Oops, received SIGSEGV, crash...\n");
00049                 abort();
00050             }
00051             else exit(-1);
00052             break;
00053     }
00054 }
00055 
00056 
00057 int main (int argc, char *argv[])
00058 {
00059     int iRetVal;
00060     #ifndef BSDSYS
00061     uid_t uidCurrent;
00062     struct sched_param sSchedParam;
00063     #endif
00064 
00065     signal(SIGPIPE, SIG_IGN);
00066     signal(SIGFPE, SIG_IGN);
00067     signal(SIGSEGV, SigHandler);
00068     #ifndef BSDSYS
00069     uidCurrent = getuid();
00070     setuid(0);
00071     sSchedParam.sched_priority = BA_SCHED_PRIORITY;
00072     sched_setscheduler(0, SCHED_FIFO, &sSchedParam);
00073     setuid(uidCurrent);
00074     #endif
00075     bDebug = false;
00076     bDaemon = false;
00077     if (argc >= 2)
00078     {
00079         if (strcmp(argv[1], "--debug") == 0)
00080         {
00081             bDebug = true;
00082         }
00083         if (strcmp(argv[1], "-D") == 0)
00084         {
00085             bDaemon = true;
00086         }
00087     }
00088     if (bDebug) printf("beamaudio: Started\n");
00089     BeamAudio = new clBeamAudio(3, 4);
00090     iRetVal = BeamAudio->Main();
00091     delete BeamAudio;
00092     if (bDebug) printf("beamaudio: Exit = %i\n", iRetVal);
00093     return iRetVal;
00094 }
00095 
00096 
00097 bool clBeamAudio::GetCfg ()
00098 {
00099     CfgFile.SetFileName(SD_CFGFILE);
00100     if (!CfgFile.GetStr("LocalSocket", cpStreamSocket)) return false;
00101     CfgFile.SetFileName(BA_CFGFILE);
00102     if (!CfgFile.GetInt("StartCh", &lStartCh)) return false;
00103     if (!CfgFile.GetInt("ArrayType", &iArrayType)) return false;
00104     if (!CfgFile.GetInt("WindowSize", &lWindowSize))
00105         lWindowSize = BA_DEF_FRAGMENT_SIZE;
00106     if (!CfgFile.GetInt("SensorCount", &lSensorCount)) return false;
00107     if (!CfgFile.GetFlt("SensorSpacing", &fSensorSpacing)) return false;
00108     if (!CfgFile.GetInt("Shading", &iShadingType)) iShadingType = 0;
00109     return true;
00110 }
00111 
00112 
00113 bool clBeamAudio::GetRq ()
00114 {
00115     char cpReqMsg[GLOBAL_HEADER_LEN];
00116 
00117     if (!SOpRequest.ReadSelect(BA_1STREQ_TIMEOUT)) return false;
00118     if (SOpRequest.ReadN(cpReqMsg, GLOBAL_HEADER_LEN) < GLOBAL_HEADER_LEN)
00119         return false;
00120     Msg.GetRequest(cpReqMsg, &sRequest);
00121     return true;
00122 }
00123 
00124 
00125 bool clBeamAudio::ConnectStream ()
00126 {
00127     int iSockH;
00128     stRawDataReq sDataReq;
00129     
00130     iSockH = SClient.Connect(cpStreamSocket);
00131     if (iSockH < 0) return false;
00132     SOpRaw.SetHandle(iSockH);
00133     if (!SOpRaw.ReadSelect(BA_RAW1ST_TIMEOUT)) return false;
00134     if (SOpRaw.ReadN(&sRawHdr, sizeof(sRawHdr)) < (int) sizeof(sRawHdr))
00135         return false;
00136     sDataReq.iChannel = -1;
00137     if (SOpRaw.WriteN(&sDataReq, sizeof(sDataReq)) < (int) sizeof(sDataReq))
00138         return false;
00139     return true;
00140 }
00141 
00142 
00143 bool clBeamAudio::InitBeam ()
00144 {
00145     switch (iArrayType)
00146     {
00147         case BA_ARRAY_TYPE_DIPOLE:
00148             if (bDebug)
00149                 printf("beamaudio: Dipole array\n");
00150             FBeamDipole.SetDebug(bDebug);
00151             if (!FBeamDipole.Initialize(fSensorSpacing, lWindowSize, 
00152                 (GDT) sRawHdr.dSampleRate)) return false;
00153             FBeamDipole.SetSoundSpeed(sRequest.fSoundSpeed);
00154             FBeamDipole.SetDirection(sRequest.fDirection, !sRequest.bHighFreq);
00155             break;
00156         case BA_ARRAY_TYPE_TRIANGLE:
00157             if (bDebug) 
00158                 printf("beamaudio: Triangle array not supported yet\n");
00159             return false;
00160             break;
00161         case BA_ARRAY_TYPE_LINE:
00162             if (bDebug)
00163                 printf("beamaudio: Line array\n");
00164             FBeamLine.SetDebug(bDebug);
00165             if (!FBeamLine.Initialize(lSensorCount, fSensorSpacing, 
00166                 lWindowSize, (GDT) sRawHdr.dSampleRate)) return false;
00167             FBeamLine.SetSoundSpeed(sRequest.fSoundSpeed);
00168             FBeamLine.SetDirection(sRequest.fDirection, !sRequest.bHighFreq);
00169             break;
00170         case BA_ARRAY_TYPE_PLANE:
00171             if (bDebug) 
00172                 printf("beamaudio: Plane array not supported yet\n");
00173             return false;
00174             break;
00175         case BA_ARRAY_TYPE_CYLINDER:
00176             if (bDebug)
00177                 printf("beamaudio: Cylinder array not supported yet\n");
00178             return false;
00179             break;
00180         case BA_ARRAY_TYPE_SPHERE:
00181             if (bDebug)
00182                 printf("beamaudio: Spherical array not supported yet\n");
00183             return false;
00184             break;
00185     }
00186     return true;
00187 }
00188 
00189 
00190 bool clBeamAudio::SendFirst ()
00191 {
00192     char cpMsgBuf[GLOBAL_HEADER_LEN];
00193     stBeamAudioFirst sFirstMsg;
00194 
00195     sFirstMsg.lBufLength = lWindowSize / 2;
00196     sFirstMsg.iSampleRate = (int) (sRawHdr.dSampleRate + 0.5);
00197     Msg.SetFirst(cpMsgBuf, &sFirstMsg);
00198     if (SOpResult.WriteN(cpMsgBuf, GLOBAL_HEADER_LEN) < GLOBAL_HEADER_LEN)
00199         return false;
00200     return true;
00201 }
00202 
00203 
00204 void clBeamAudio::SetDirection ()
00205 {
00206     switch (iArrayType)
00207     {
00208         case BA_ARRAY_TYPE_DIPOLE:
00209             FBeamDipole.SetDirection(sRequest.fDirection, !sRequest.bHighFreq);
00210             break;
00211         case BA_ARRAY_TYPE_TRIANGLE:
00212             break;
00213         case BA_ARRAY_TYPE_LINE:
00214             FBeamLine.SetDirection(sRequest.fDirection, !sRequest.bHighFreq);
00215             break;
00216         case BA_ARRAY_TYPE_PLANE:
00217             break;
00218         case BA_ARRAY_TYPE_CYLINDER:
00219             break;
00220         case BA_ARRAY_TYPE_SPHERE:
00221             break;
00222     }
00223 }
00224 
00225 
00226 void clBeamAudio::ProcessLoop ()
00227 {
00228     long lInDataCount = lWindowSize / 2 * sRawHdr.iChannels;
00229     long lInDataSize = lInDataCount * sizeof(GDT);
00230     long lOutDataCount = lWindowSize / 2;
00231     #ifdef __GNUG__
00232     GDT fpInData[lInDataCount];
00233     GDT fpResData[lOutDataCount];
00234     #else
00235     clDSPAlloc InData;
00236     clDSPAlloc ResData;
00237     GDT *fpInData = (GDT *) InData.Size(lInDataCount * sizeof(GDT));
00238     GDT *fpResData = (GDT *) ResData.Size(lOutDataCount * sizeof(GDT));
00239     #endif
00240 
00241     while (bRun)
00242     {
00243         if (SOpRequest.ReadSelect(0))
00244         {
00245             GetRq();
00246             SetDirection();
00247         }
00248         if (SOpRaw.ReadN(fpInData, lInDataSize) < lInDataSize) return;
00249         DSP.Zero(fpResData, lOutDataCount);
00250         switch (iArrayType)
00251         {
00252             case BA_ARRAY_TYPE_DIPOLE:
00253                 FBeamDipole.Put(fpInData, lInDataCount, lStartCh, 
00254                     sRawHdr.iChannels);
00255                 while (FBeamDipole.Get(fpResData, lOutDataCount))
00256                 {
00257                     if (!SendResult(fpResData, lOutDataCount)) return;
00258                 }
00259                 break;
00260             case BA_ARRAY_TYPE_TRIANGLE:
00261                 break;
00262             case BA_ARRAY_TYPE_LINE:
00263                 FBeamLine.Put(fpInData, lInDataCount, lStartCh,
00264                     sRawHdr.iChannels);
00265                 while (FBeamLine.Get(fpResData, lOutDataCount))
00266                 {
00267                     if (!SendResult(fpResData, lOutDataCount)) return;
00268                 }
00269                 break;
00270             case BA_ARRAY_TYPE_PLANE:
00271                 break;
00272             case BA_ARRAY_TYPE_CYLINDER:
00273                 break;
00274             case BA_ARRAY_TYPE_SPHERE:
00275                 break;
00276         }
00277     }
00278 }
00279 
00280 
00281 bool clBeamAudio::SendResult (GDT *fpResData, long lResCount)
00282 {
00283     long lResultSize = GLOBAL_HEADER_LEN + lResCount * sizeof(GDT);
00284     #ifdef __GNUG__
00285     char cpMsgBuf[lResultSize];
00286     #else
00287     clAlloc MsgBuf;
00288     char *cpMsgBuf = (char *) MsgBuf.Size(lResultSize);
00289     #endif
00290 
00291     DSP.Mul(fpResData, fAttenuation, lResCount);
00292     gettimeofday(&sResHdr.sTimeStamp, NULL);
00293     sResHdr.lBufLength = lResCount;
00294     sResHdr.fPeakLevel = DSP.PeakLevel(fpResData, lResCount);
00295     sResHdr.fDirection = sRequest.fDirection;
00296     Msg.SetResult(cpMsgBuf, &sResHdr, fpResData);
00297     if (SOpResult.WriteN(cpMsgBuf, lResultSize) < lResultSize) return false;
00298     return true;
00299 }
00300 
00301 
00302 clBeamAudio::clBeamAudio (int iInHandle, int iOutHandle)
00303 {
00304     bRun = true;
00305     fAttenuation = (GDT) pow(10.0, -1.0 / 20.0);
00306     SOpRequest.SetHandle(iInHandle);
00307     SOpResult.SetHandle(iOutHandle);
00308     SOpResult.DisableNagle();
00309 }
00310 
00311 
00312 clBeamAudio::~clBeamAudio ()
00313 {
00314 }
00315 
00316 
00317 int clBeamAudio::Main ()
00318 {
00319     if (!GetCfg())
00320     {
00321         if (bDebug) printf("beamaudio: Error reading configuration\n");
00322         return 1;
00323     }
00324     if (!GetRq())
00325     {
00326         if (bDebug) printf("beamaudio: Unable to receive request message\n");
00327         return 1;
00328     }
00329     if (!ConnectStream())
00330     {
00331         if (bDebug) printf("beamaudio: Unable to connect to streamdist\n");
00332         return 1;
00333     }
00334     if (!InitBeam())
00335     {
00336         if (bDebug) printf("beamaudio: Beamformer initialization failed\n");
00337         return 1;
00338     }
00339     if (!SendFirst())
00340     {
00341         if (bDebug) printf("beamaudio: Failed to send first message\n");
00342         return 1;
00343     }
00344     ProcessLoop();
00345     return 0;
00346 }
00347 

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