00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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