00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifndef SIGNALTEMPLATE_H
00030 #define SIGNALTEMPLATE_H
00031
00032 #include <QGpCoreTools.h>
00033
00034 #include "GeopsyCoreEngine.h"
00035 #include "GeopsyCoreDLLExport.h"
00036
00037 namespace GeopsyCore {
00038
00039 template <class sampleType> class GEOPSYCORE_EXPORT SignalTemplate : public CacheItem
00040 {
00041 public:
00042 SignalTemplate( );
00043 SignalTemplate(int n);
00044 SignalTemplate(const SignalTemplate<sampleType>& o);
00045 virtual ~SignalTemplate();
00046
00047 sampleType * lockSamples(char * file, int line);
00048 const sampleType * constLockSamples(char * file, int line) const;
00049 void unlockSamples(char * file, int line) const;
00050
00051 virtual sampleType * lockSamples();
00052 virtual const sampleType * constLockSamples() const;
00053 virtual inline void unlockSamples() const;
00054 void freeSamples();
00055
00056 int nSamples() const {return _nSamples;}
00057 virtual void setNSamples(int n) {ASSERT(!_samples); _nSamples=n;}
00058
00059 void multiply(const SignalTemplate<sampleType> * sig);
00060 void multiply(sampleType value);
00061 void subtractSignal(const SignalTemplate<sampleType> * sig);
00062 void range(sampleType& min, sampleType& max) const;
00063 sampleType maximum() const;
00064 sampleType average(int startAt, int nSamples) const;
00065 sampleType average2(int startAt, int nSamples) const;
00066 sampleType variance(int startAt, int nSamples) const;
00067 void copySamplesFrom(const SignalTemplate<sampleType> * sig);
00068 bool copySamplesFrom(const SignalTemplate<sampleType> * sig,
00069 int sigStart, int thisStart, int nToCopy);
00070 int add(const SignalTemplate<sampleType> * sig,
00071 int sigStart=0, int thisStart=0, int nToCopy=-1,
00072 bool checkInvalid=false, sampleType invalidValue=0);
00073 void initValues(sampleType value, int startAt, int nSamples);
00074 int findValue(sampleType value, int from, bool whileNotFound=false) const;
00075
00076 double dataSizeMb() const {return (double) dataSize()/(1024.0 * 1024.0);}
00077 protected:
00078 int _nSamples;
00079
00080
00081 sampleType * samples() const {return _samples;}
00082 void setSamples(sampleType * s) const {_samples=s;}
00083
00084 void adjustLimits(const SignalTemplate<sampleType> * sig,
00085 int& sigStart, int& thisStart, int& nToCopy) const;
00086 virtual bool isAllocated() const {return _samples;}
00087 virtual int dataSize() const {return _nSamples * sizeof(sampleType);}
00088 private:
00089 mutable sampleType *_samples;
00090
00091 virtual bool allocate() const;
00092 virtual void free() const;
00093 virtual void save(QDir& d) const;
00094 virtual void load(QDir& d) const;
00095 };
00096
00100 template <class sampleType>
00101 sampleType * SignalTemplate<sampleType>::lockSamples()
00102 {
00103 lockData();
00104 if(isAllocated() || geopsyCore->cache()->makeAvailable(this)) {
00105 return _samples;
00106 } else {
00107 unlockData();
00108 return 0;
00109 }
00110 }
00111
00112
00116 template <class sampleType>
00117 const sampleType * SignalTemplate<sampleType>::constLockSamples() const
00118 {
00119 lockData();
00120 if(isAllocated() || geopsyCore->cache()->makeAvailable(this)) {
00121 return _samples;
00122 } else {
00123 unlockData();
00124 return 0;
00125 }
00126 }
00127
00131 template <class sampleType>
00132 inline void SignalTemplate<sampleType>::unlockSamples() const
00133 {
00134 unlockData();
00135 }
00136
00137 #if 0
00138
00139 template <class sampleType>
00140 sampleType * SignalTemplate<sampleType>::lockSamples(char * file, int line)
00141 {
00142 printf( "Lock samples of signal %p at %s:%i\n", this, file, line);
00143 return lockSamples();
00144 }
00145
00146 template <class sampleType>
00147 const sampleType * SignalTemplate<sampleType>::constLockSamples(char * file, int line) const
00148 {
00149 printf( "Const lock samples of signal %p at %s:%i\n", this, file, line);
00150 return constLockSamples();
00151 }
00152
00153 template <class sampleType>
00154 void SignalTemplate<sampleType>::unlockSamples(char * file, int line) const
00155 {
00156 unlockSamples();
00157 printf( "Unlock samples of signal %p at %s:%i\n", this, file, line);
00158 }
00159
00160 #define LOCK_SAMPLES(type,samp,sig) \
00161 type * samp=sig->lockSamples(__FILE__, __LINE__); \
00162 if(samp) {
00163 #define CONST_LOCK_SAMPLES(type,samp,sig) \
00164 const type * samp=sig->constLockSamples(__FILE__, __LINE__); \
00165 if(samp) {
00166 #define UNLOCK_SAMPLES(sig) \
00167 sig->unlockSamples(__FILE__, __LINE__); \
00168 }
00169 #endif
00170
00171 #define LOCK_SAMPLES(type,samp,sig) \
00172 type * samp=sig->lockSamples(); \
00173 if(samp) {
00174 #define CONST_LOCK_SAMPLES(type,samp,sig) \
00175 const type * samp=sig->constLockSamples(); \
00176 if(samp) {
00177 #define UNLOCK_SAMPLES(sig) \
00178 sig->unlockSamples(); \
00179 }
00180
00181 template <class sampleType>
00182 SignalTemplate<sampleType>::SignalTemplate( )
00183 {
00184 _samples=0;
00185 _nSamples=0;
00186 }
00187
00188 template <class sampleType>
00189 SignalTemplate<sampleType>::SignalTemplate(int n)
00190 {
00191 _samples=0;
00192 _nSamples=n;
00193 }
00194
00195 template <class sampleType>
00196 SignalTemplate<sampleType>::SignalTemplate(const SignalTemplate<sampleType>& o) :
00197 CacheItem(o)
00198 {
00199 _nSamples=o._nSamples;
00200 _samples=0;
00201 }
00202
00203 template <class sampleType>
00204 SignalTemplate<sampleType>::~SignalTemplate()
00205 {
00206 geopsyCore->cache()->free(this, false);
00207 }
00208
00209 template <class sampleType>
00210 void SignalTemplate<sampleType>::freeSamples()
00211 {
00212 lockData();
00213 if(isAllocated()) {
00214 geopsyCore->cache()->free(this, false);
00215 }
00216 unlockData();
00217 }
00218
00219 template <class sampleType>
00220 bool SignalTemplate<sampleType>::allocate() const
00221 {
00222 TRACE;
00223 if( !_samples) {
00224 if(_nSamples<=0) {
00225
00226 _samples=new sampleType [ 1 ];
00227 ASSERT(_samples);
00228 } else {
00229 _samples=new sampleType [ _nSamples ];
00230 ASSERT(_samples);
00231 }
00232 }
00233 return true;
00234 }
00235
00236 template <class sampleType>
00237 void SignalTemplate<sampleType>::free() const
00238 {
00239 TRACE;
00240 if(_samples) {
00241 delete [] _samples;
00242 _samples=0;
00243 }
00244 }
00245
00249 template <class sampleType>
00250 void SignalTemplate<sampleType>::save(QDir& d) const
00251 {
00252 TRACE;
00253 QFile f(d.absoluteFilePath(swapFileName()) );
00254 if(f.open(QIODevice::WriteOnly) ) {
00255 f.write(( const char * ) _samples, dataSize());
00256 } else App::stream() << QObject::tr( "Cannot save temporary file, check disk space!" ) << endl;
00257 }
00258
00262 template <class sampleType>
00263 void SignalTemplate<sampleType>::load(QDir& d) const
00264 {
00265 TRACE;
00266 QFile f(d.absoluteFilePath(swapFileName()) );
00267 if(f.open(QIODevice::ReadOnly) ) {
00268 f.read((char *)_samples, dataSize());
00269 } else App::stream() << QObject::tr( "Cannot load temporary file" ) << endl;
00270 }
00271
00272 template <class sampleType>
00273 void SignalTemplate<sampleType>::multiply(sampleType value)
00274 {
00275 TRACE;
00276 LOCK_SAMPLES(sampleType, thisSamples, this)
00277 for(int i=0; i < _nSamples; i++ ) thisSamples[ i ] *= value;
00278 UNLOCK_SAMPLES(this)
00279 }
00280
00281 template <class sampleType>
00282 void SignalTemplate<sampleType>::multiply(const SignalTemplate<sampleType> * sig)
00283 {
00284 TRACE;
00285 if(nSamples()!=sig->nSamples()) return;
00286 CacheProcess cp;
00287 cp << this << sig;
00288 LOCK_SAMPLES(sampleType, thisSamples, this)
00289 CONST_LOCK_SAMPLES(sampleType, sigSamples, sig)
00290 for(int i=0; i < _nSamples; i++ ) thisSamples[ i ] *= sigSamples[ i ];
00291 UNLOCK_SAMPLES(sig)
00292 UNLOCK_SAMPLES(this)
00293 }
00294
00295 template <class sampleType>
00296 void SignalTemplate<sampleType>::subtractSignal(const SignalTemplate<sampleType> * sig)
00297 {
00298 TRACE;
00299 CacheProcess cp;
00300 cp << this << sig;
00301 LOCK_SAMPLES(sampleType, thisSamples, this)
00302 CONST_LOCK_SAMPLES(sampleType, sigSamples, sig)
00303 int nSamples=_nSamples;
00304 if(sig->nSamples() < _nSamples) nSamples=sig->nSamples();
00305 for(int i=0; i < nSamples; i++ ) thisSamples[ i ] -= sigSamples[ i ];
00306 UNLOCK_SAMPLES(sig)
00307 UNLOCK_SAMPLES(this)
00308 }
00309
00310 template <class sampleType>
00311 void SignalTemplate<sampleType>::range(sampleType& min, sampleType& max) const
00312 {
00313 TRACE;
00314 CONST_LOCK_SAMPLES(sampleType, thisSamples, this)
00315 min=thisSamples[ 0 ];
00316 max=thisSamples[ 0 ];
00317 for(int i=0; i < _nSamples; i++ ) {
00318 if(thisSamples[ i ] < min) min=thisSamples[ i ];
00319 if(thisSamples[ i ] > max) max=thisSamples[ i ];
00320 }
00321 UNLOCK_SAMPLES(this)
00322 }
00323
00324 template <class sampleType>
00325 void SignalTemplate<sampleType>::copySamplesFrom(const SignalTemplate<sampleType> * sig)
00326 {
00327 TRACE;
00328 if(sig->_nSamples!=_nSamples) return ;
00329 CacheProcess cp;
00330 cp << this << sig;
00331 LOCK_SAMPLES(sampleType, thisSamples, this)
00332 CONST_LOCK_SAMPLES(sampleType, sigSamples, sig)
00333 memcpy(thisSamples, sigSamples, _nSamples * sizeof(sampleType) );
00334 UNLOCK_SAMPLES(sig)
00335 UNLOCK_SAMPLES(this)
00336 }
00337
00338 template <class sampleType>
00339 void SignalTemplate<sampleType>::adjustLimits(const SignalTemplate<sampleType> * sig,
00340 int& sigStart, int& thisStart, int& nToCopy) const
00341 {
00342 TRACE;
00343
00344 if(sigStart >= sig->_nSamples ||
00345 thisStart >= _nSamples ||
00346 sigStart + nToCopy < 0 ||
00347 thisStart + nToCopy < 0) {
00348 nToCopy=0;
00349 return;
00350 }
00351 if(sigStart < 0) {
00352 nToCopy += sigStart;
00353 thisStart -= sigStart;
00354 sigStart=0;
00355 }
00356 if(thisStart < 0) {
00357 nToCopy += thisStart;
00358 sigStart -= thisStart;
00359 thisStart=0;
00360 }
00361 if(thisStart + nToCopy >= _nSamples) nToCopy=_nSamples - thisStart;
00362 if(sigStart + nToCopy >= sig->_nSamples) nToCopy=sig->_nSamples - sigStart;
00363 }
00364
00365 template <class sampleType>
00366 bool SignalTemplate<sampleType>::copySamplesFrom(const SignalTemplate<sampleType> * sig,
00367 int sigStart, int thisStart, int nToCopy)
00368 {
00369 TRACE;
00370 adjustLimits(sig, sigStart, thisStart, nToCopy);
00371 if(nToCopy<=0) return false;
00372 CacheProcess cp;
00373 cp << this << sig;
00374 LOCK_SAMPLES(sampleType, thisSamples, this)
00375 CONST_LOCK_SAMPLES(sampleType, sigSamples, sig)
00376 memcpy(thisSamples + thisStart, sigSamples + sigStart, nToCopy * sizeof(sampleType) );
00377 UNLOCK_SAMPLES(sig)
00378 UNLOCK_SAMPLES(this)
00379 return true;
00380 }
00381
00382 template <class sampleType>
00383 int SignalTemplate<sampleType>::add(const SignalTemplate<sampleType> * sig,
00384 int sigStart, int thisStart, int nToCopy,
00385 bool checkInvalid, sampleType invalidValue)
00386 {
00387 TRACE;
00388 if(nToCopy==-1) nToCopy=nSamples();
00389 adjustLimits(sig, sigStart, thisStart, nToCopy);
00390 if(nToCopy<=0) return 0;
00391 int nCommon=0;
00392 CacheProcess cp;
00393 cp << this << sig;
00394 LOCK_SAMPLES(sampleType, thisSamples, this)
00395 CONST_LOCK_SAMPLES(sampleType, sigSamples, sig)
00396 sampleType * thisPtr=thisSamples + thisStart;
00397 const sampleType * sigPtr=sigSamples + sigStart;
00398 sampleType * endPtr=thisPtr + nToCopy;
00399 if(checkInvalid) {
00400 for( ;thisPtr < endPtr;thisPtr++, sigPtr++ ) {
00401 if(( *thisPtr)==invalidValue) ( *thisPtr)=( *sigPtr);
00402 else {
00403 nCommon++;
00404 ( *thisPtr) += ( *sigPtr);
00405 }
00406 }
00407 } else {
00408 for( ;thisPtr < endPtr;thisPtr++, sigPtr++ )
00409 ( *thisPtr) += ( *sigPtr);
00410 }
00411 UNLOCK_SAMPLES(sig)
00412 UNLOCK_SAMPLES(this)
00413 return nCommon;
00414 }
00415
00416 template <class sampleType>
00417 sampleType SignalTemplate<sampleType>::maximum() const
00418 {
00419 TRACE;
00420 sampleType max=0;
00421 CONST_LOCK_SAMPLES(sampleType, thisSamples, this)
00422 for(int i=0;i < _nSamples;i++ ) {
00423 if(thisSamples[ i ] > 0) {
00424 if(thisSamples[ i ] > max) max=thisSamples[ i ];
00425 } else {
00426 if(thisSamples[ i ] < -max) max=-thisSamples[ i ];
00427 }
00428 }
00429 UNLOCK_SAMPLES(this)
00430 return max;
00431 }
00432
00433 template <class sampleType>
00434 sampleType SignalTemplate<sampleType>::average(int startAt, int nSamples) const
00435 {
00436 TRACE;
00437 if(startAt >= _nSamples) return 0;
00438 int endAt=startAt + nSamples;
00439 if(endAt > _nSamples) endAt=_nSamples;
00440 if(startAt < 0) startAt=0;
00441 sampleType average=0;
00442 CONST_LOCK_SAMPLES(sampleType, thisSamples, this)
00443 for(int i=startAt;i < endAt;i++ ) average += thisSamples[ i ];
00444 UNLOCK_SAMPLES(this)
00445 return average/nSamples;
00446 }
00447
00448 template <class sampleType>
00449 sampleType SignalTemplate<sampleType>::average2(int startAt, int nSamples) const
00450 {
00451 TRACE;
00452 if(startAt >= _nSamples) return 0;
00453 int endAt=startAt + nSamples;
00454 if(endAt > _nSamples) endAt=_nSamples;
00455 if(startAt < 0) startAt=0;
00456 sampleType average2=0;
00457 CONST_LOCK_SAMPLES(sampleType, thisSamples, this)
00458 for(int i=startAt;i < endAt;i++ ) {
00459 average2 += thisSamples[ i ] * thisSamples[ i ];
00460 }
00461 UNLOCK_SAMPLES(this)
00462 return average2/(nSamples-1);
00463 }
00464
00465 template <class sampleType>
00466 sampleType SignalTemplate<sampleType>::variance(int startAt, int nSamples) const
00467 {
00468 double aver=average(startAt, nSamples);
00469 return average2(startAt, nSamples) - nSamples*aver*aver/(nSamples-1);
00470 }
00471
00472 template <class sampleType>
00473 void SignalTemplate<sampleType>::initValues(sampleType value, int startAt, int nSamples)
00474 {
00475 TRACE;
00476 if(startAt >= _nSamples) return ;
00477 int endAt=startAt + nSamples;
00478 if(endAt > _nSamples) endAt=_nSamples;
00479 if(startAt < 0) startAt=0;
00480 LOCK_SAMPLES(sampleType, thisSamples, this)
00481 for(int i=startAt;i < endAt;i++ ) thisSamples[ i ]=value;
00482 UNLOCK_SAMPLES(this)
00483 }
00484
00485 template <class sampleType>
00486 int SignalTemplate<sampleType>::findValue(sampleType value, int from, bool whileNotFound) const
00487 {
00488 TRACE;
00489 int i=-1;
00490 CONST_LOCK_SAMPLES(sampleType, thisSamples, this)
00491 if(whileNotFound) {
00492 for(i=from;i < _nSamples;i++ ) {
00493 if(thisSamples[ i ]!=value) {
00494 break;
00495 }
00496 }
00497 } else {
00498 for(i=from;i < _nSamples;i++ ) {
00499 if(thisSamples[ i ]==value) {
00500 break;
00501 }
00502 }
00503 }
00504 UNLOCK_SAMPLES(this)
00505 return i;
00506 }
00507
00508 }
00509
00510 #endif // SIGNALTEMPLATE_H