• Main Page
  • Data Structures
  • Files

data.c

Go to the documentation of this file.
00001 /*
00002  * This file is part of Titan2Reader
00003  *
00004  * Copyright (C) 2006, Sebastien Judenherc <sebastien.judenherc@agecodagis.com>
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
00019  * USA
00020  *
00021  */
00022 
00023 #include <stdlib.h>
00024 #include <stdio.h>
00025 #include <time.h>
00026 #include <ctype.h>
00027 #include <math.h>
00028 #include <errno.h>
00029 #include <unistd.h>
00030 #include <string.h>
00031 #include <sys/types.h>
00032 #include <sys/stat.h>
00033 #include <fcntl.h>
00034 
00035 #include "common.h"
00036 
00037 int32_t msf[9][3] = {
00038         { 0, 0, 0 },
00039         { 0xffffff, 1, 8 },
00040         { 0x000fff, 12, 20 },
00041         { 0x0000ff, 8, 24 },
00042         { 0x00003f, 6, 26 },
00043         { 0, 0, 0 },
00044         { 0x00000f, 4, 28 },
00045         { 0, 0, 0 },
00046         { 0x000007, 3, 29 }
00047 };
00048 
00049 int32_t lastData[MAX_CHANNEL]={
00050         0, 0, 0, 0, 0, 0, 0, 0,
00051         0, 0, 0, 0, 0, 0, 0, 0,
00052         0, 0, 0, 0, 0, 0, 0, 0,
00053         0, 0, 0, 0, 0, 0, 0, 0,
00054         0, 0, 0, 0, 0, 0, 0, 0
00055 };
00056 
00057 int nTitan1=0,nTitan2=0;
00058 int lastFormat=-1;
00059 
00060 struct Titan2TimeType lastFrameTime = {0, 0};
00061 
00062 int64_t lastSegment=0; 
00063 
00064 // set the value for aux channel in titan1 format
00065 // @param ch the channel number (>=MAX_OSIRIS_CHANNEL)
00066 // @val 32bits value
00067 void SetAuxChannel1(int ch, int32_t val)
00068 {
00069         HWConfig.data[ch][HWConfig.srObs[ch].npts]=val;
00070         HWConfig.srObs[ch].npts++;
00071         HWConfig.srExp[ch].npts++,
00072         HWConfig.srExp[ch].base=HWConfig.srExp[0].base;
00073         HWConfig.srExp[ch].div= HWConfig.srExp[0].div*128;
00074 }
00075 
00076 void ProcessAux1Frame(const unsigned char *frame)
00077 {
00078         int pair,ch;
00079         int32_t V0;
00080         int32_t V1;
00081         // process only if aux channels are requested
00082         if (auxiliaryMask==0LL)
00083         {
00084                 return;
00085         }
00086         // which pair ?
00087         pair=frame[9]&0x7;
00088         // read the values
00089         V0=frame2i24(frame,0);
00090         V1=frame2i24(frame,3);
00091         // store each value in the correct channel
00092         ch=MAX_OSIRIS_CHANNEL+pair*2+0;
00093         PrintDebug("AUX: pair=%d ch=%d V0=%d V1=%d\n",pair,ch,V0,V1);
00094         SetAuxChannel1(ch+0, V0);
00095         SetAuxChannel1(ch+1, V1);
00096 }
00097 
00098 // set the value for aux channel
00099 // @param ch the channel number (>=MAX_OSIRIS_CHANNEL)
00100 // @val 32bits value
00101 void SetAuxChannel2(int ch, int32_t val)
00102 {
00103         HWConfig.data[ch][0]=val;
00104         HWConfig.srObs[ch].npts=1;
00105         HWConfig.srExp[ch].npts=1;
00106         HWConfig.srExp[ch].base=1;
00107         HWConfig.srExp[ch].div=1;
00108 }
00109 
00111 void FlushDataFiles(void)
00112 {
00113         int i;
00114         for (i=0; i<MAX_CHANNEL; i++)
00115         {
00116                 CloseMSeedFile(i);
00117                 CloseSacFile(i);
00118                 CloseSegyFile(i);
00119                 CloseSeg2File(i);
00120                 CloseAscFile(i);
00121                 CloseBinFile(i);
00122                 CloseWavFile(i);
00123         }
00124         CloseFullSeg2File();
00125         CloseGifFile();
00126         CloseTitFile();
00127         CloseSisFile();
00128         // reset the last frame time
00129         lastFrameTime.usecond=0;
00130 }
00131 
00133 void FlushNonDataFiles(void)
00134 {
00135         CloseTimeFile(oldHWConfig.fieldIdent);
00136         CloseCacheFile(0);
00137 }
00138 
00147 int CheckContinuity(void)
00148 {
00149         int i,it=-1,ret;
00150         double eDeltaT;
00151         double oDeltaT;
00152         double threshold;
00153         struct Titan2TimeType diffTime = { 0, 0 };
00154         ret=0;
00155         if (ignoreDiscontinuity)
00156         {
00157                 threshold=120.; // two minutes gap are allowed
00158         }
00159         else
00160         {
00161                 threshold=1./900.;
00162         }
00163         // compare the sampling rates for each channel
00164         //for (i=0; i<MAX_OSIRIS_CHANNEL; i++)
00165         for (i=0; i<MAX_CHANNEL; i++)
00166         {
00167                 // ignore inactive channels
00168                 if (
00169                                 (HWConfig.srExp[i].base<1)||
00170                                 (HWConfig.srExp[i].div<1)||
00171                                 (HWConfig.srExp[i].npts<1)
00172                                 )
00173                 {
00174                         continue;
00175                 }
00176                 // test for the less than 1Hz frequencies
00177                 if (HWConfig.srExp[i].base/HWConfig.srExp[i].div<1)
00178                 {
00179                         continue;
00180                 }
00181                 // look for the first active channel
00182                 if (it==-1)
00183                 {
00184                         it=i;
00185                 }
00186                 // check the current channel
00187                 if (HWConfig.srObs[i].npts!=HWConfig.srExp[i].npts)
00188                 {
00189                         PrintError("ch%d, obs/exp=%d/%d (%s @ %d)%s\n",
00190                                         i,
00191                                         HWConfig.srObs[i].npts,
00192                                         HWConfig.srExp[i].npts,
00193                                         currentFile,SafeFtell(titan2File),
00194                                         (HWConfig.srObs[i].npts<HWConfig.srExp[i].npts)?"":
00195                                                 " killed");
00196                         if (HWConfig.srObs[i].npts>HWConfig.srExp[i].npts)
00197                         {
00198                                 PrintDebug("killing the frame: it is too long\n");
00199                                 // kill the frame and flush the buffers
00200                                 HWConfig.srObs[i].npts=0;
00201                                 HWConfig.srExp[i].npts=0;
00202                                 lastData[i]=0;
00203                         }
00204                         // stop extraction only if we are already extracting data
00205                         if (extractingData)
00206                         {
00207                                 ret=-2;
00208                         }
00209                         else // flush the buffers anyway
00210                         {
00211                                 HWConfig.srObs[i].npts=0;
00212                                 HWConfig.srExp[i].npts=0;
00213                                 lastData[i]=0;
00214                         }
00215                 }
00216         }
00217         if (it==-1)
00218         {
00219                 return(0);
00220         }
00221 
00222         // if no sample has been read, the next is meaningless
00223         if ((nTitan1+nTitan2)==0)
00224         {
00225                 return(ret);
00226         }
00227 
00228         // check that the current time is the old one shifted by 1 superframe
00229         if ((lastFrameTime.usecond>=(1LL<<32))&&(currentTime.usecond>(1LL<<32)))
00230         {
00231                 eDeltaT=DiffTimeT2T1(&lastFrameTime,&currentTime,&diffTime);
00232                 lastFrameTime.usecond=currentTime.usecond;
00233                 if ((it!=-1)&&(HWConfig.srExp[it].base>0))
00234                 {
00235                         oDeltaT=(double)(HWConfig.srObs[it].npts*HWConfig.srExp[it].div)/
00236                                 (double)HWConfig.srExp[it].base;
00237                 }
00238                 else
00239                 {
00240                         oDeltaT=0.;
00241                 }
00242                 // if extracting data and the format is titan1 and the overlap is exactly 1 primary sample
00243                 if ((HWConfig.formatVersion==1)&&(extractingData)&&(it<6))
00244                 {
00245                         if (fabs((oDeltaT-eDeltaT)-
00246                                 (float)HWConfig.srExp[it].div/(float)HWConfig.srExp[it].base)<0.001)
00247                         {
00248                                 PrintWarning("one sample corruption detected (fixed): %s @ %d\n\t%s\n",
00249                                                 currentFile, SafeFtell(titan2File), StrTime(&currentTime));
00250                                 for (i=0; i<MAX_OSIRIS_CHANNEL; i++)
00251                                 {
00252                                         int _i;
00253                                         int _imax=1,vtest=0,vmax=0;
00254                                         if (HWConfig.srExp[i].npts<1) continue;
00255                                         for (_i=1; _i<127; _i++)
00256                                         {
00257                                                 vtest=abs(HWConfig.data[i][_i]-HWConfig.data[i][_i-1])/(1+abs(abs(HWConfig.data[i][_i-1])-abs(HWConfig.data[i][_i+1])));
00258                                                 if (vtest>vmax)
00259                                                 {
00260                                                         vmax=vtest;
00261                                                         _imax=_i;
00262                                                 }
00263                                                 /*
00264                                                 printf("%d %#0x %d %d %d\n",_i,HWConfig.data[i][_i],
00265                                                                 HWConfig.data[i][_i],
00266                                                                 HWConfig.data[i][_i]-HWConfig.data[i][_i-1],
00267                                                                 vtest);
00268                                                 */
00269                                         }
00270                                         /*
00271                                         for (_i=_imax-1; _i<_imax+2; _i++)
00272                                         {
00273                                                 printf("%d %#0x %d %d\n",_i,HWConfig.data[i][_i],
00274                                                                 HWConfig.data[i][_i],
00275                                                                 HWConfig.data[i][_i]-HWConfig.data[i][_i-1]);
00276                                         }
00277                                         */
00278                                         // kill one sample
00279                                         HWConfig.data[i][_imax]=(HWConfig.data[i][_imax-1]+HWConfig.data[i][_imax+1])/2;
00280                                 }
00281                                 // recompute eDelta
00282                                 eDeltaT+=(float)HWConfig.srExp[it].div/(float)HWConfig.srExp[it].base;
00283                         }
00284                 // endif
00285                 }
00286                 // the difference must be less then 1 sample
00287                 if (fabs(eDeltaT-oDeltaT)>threshold) // préciser ça !!!! ICI
00288                 {
00289                         // we never know what could happen with config
00290                         ChangeStreamConfig();
00291                         if (seeking==0)
00292                         {
00293                                 PrintWarning("data %s: %s @ %d\n\t%s "
00294                                                 "%+.4fs (TimeFrame:%.3fs, Samples:%.3fs)\n",
00295                                                 (eDeltaT>oDeltaT)?"lag":"overlap",
00296                                                 currentFile,
00297                                                 SafeFtell(titan2File),
00298                                                 StrTime(&currentTime),
00299                                                 eDeltaT-oDeltaT,
00300                                                 eDeltaT,oDeltaT);
00301                                 LogPrint("DISCONTINUITY(s) %f\n",eDeltaT-oDeltaT);
00302                         }
00303                         if (ret>=0)
00304                         {
00305                                 ret=-1;
00306                         }
00307                         // the following test is ONLY for titan stations (titan1)
00308                         if (HWConfig.srExp[it].npts==128)
00309                         {
00310                                 int ed;
00311                                 double f;
00312                                 f=(double)HWConfig.srExp[it].base/(double)HWConfig.srExp[it].div;
00313                                 ed=(int)((100000000.1*(eDeltaT-oDeltaT)*f)/100000.0);
00314                                 PrintWarning("%f %d\n",  
00315                                                 100000000.1*(eDeltaT-oDeltaT)*f,  
00316                                                 ed);
00317                                 if (ed%(HWConfig.srExp[it].npts*1000)==0)
00318                                 {
00319                                         PrintWarning("POSSIBLE SUPERFRAME JUMP: %d frames\n",
00320                                                         ed/HWConfig.srExp[it].npts/1000);
00321                                         LogPrint("SuperFrameSkip %d\n",
00322                                                         ed/HWConfig.srExp[it].npts/1000);
00323                                 }
00324                         }
00325                         else
00326                         {
00327                                 PrintWarning("npts=%d\n",HWConfig.srExp[it].npts);
00328                         }
00329                 }
00330                 else
00331                 {
00332                         // the difference should be less than 1 sample at 1000Hz (2000Hz)
00333                         if (fabs(eDeltaT-oDeltaT)>1./500.)
00334                         {
00335                                 if (PrintMessages())
00336                                 {
00337                                         PrintWarning("time uncertainity: %s @ %d\n\t%s %+.4fs\n",
00338                                                         currentFile,
00339                                                         SafeFtell(titan2File),
00340                                                         StrTime(&currentTime),
00341                                                         eDeltaT-oDeltaT);
00342                                 }
00343                         }
00344                 }
00345         }
00346         lastFrameTime.usecond=currentTime.usecond;
00347         return(ret);
00348 }
00349 
00354 void EndSuperFrame(void)
00355 {
00356         int i,continuity=0;
00357         int exitNow=0;
00358         int score,format;
00359         // check for time continuity
00360         // if a time discontinuity is detected, the cache file must be
00361         // updated and all the data files must be flushed and closed
00362         continuity=CheckContinuity();
00363 
00364         // if a time segment extraction is running
00365         if (timeSegment>0)
00366         // then
00367         {
00368                 int64_t seg;
00369                 beginWindow=0;
00370                 // compute the segment number
00371                 seg=correctedTime.usecond/timeSegment;
00372                 seg>>=32;
00373                 if (seg!=lastSegment)
00374                 {
00375                         endWindow=1;
00376                         lastSegment=seg;
00377                 }
00378                 else
00379                 {
00380                         endWindow=0;
00381                 }
00382         // endif
00383         }
00384 
00385         exitNow=0;
00386         // exit now if we are out of the defined window
00387         //if ((scanAll==0)&&(endWindow>0)&&((correctedTime.usecond>>32)>endWindow)&&(dataExtracted))
00388         if (endWindow>0)
00389         {
00390                 if (scanAll==0)
00391                 {
00392                         if (dataExtracted)
00393                         {
00394                                 if ((correctedTime.usecond>>32)>endWindow)
00395                                 {
00396                                         exitNow=1;
00397                                 }
00398                         }
00399                 }
00400         }
00401         // also test the tag case
00402         if (onlyTag[0])
00403         {
00404                 if ((scanAll==0)&&(strcmp(currentTag,onlyTag)!=0))
00405                 {
00406                         exitNow=1;
00407                 }
00408         }
00409 
00410         // exit now if we missed the window
00411         if (
00412                         (endWindow>0)&&
00413                         (beginWindow>0)&&
00414                         ((correctedTime.usecond>>32)>endWindow)&&
00415                         ((correctedTime.usecond>>32)>beginWindow)
00416            )
00417         {
00418                 PrintDebug("endWindow=%d beginWindow=%d t=%d (%s)\n",
00419                                 endWindow,beginWindow,
00420                                 (int)((correctedTime.usecond>>32)),
00421                                 StrTime(&correctedTime));
00422                 if (scanAll==0)
00423                 {
00424                         exitNow=1;
00425                 }
00426         }
00427         // execute...
00428         if (exitNow)
00429         {
00430                 // close all the output files
00431                 if (extractingData)
00432                 {
00433                         PrintLog("end of window detected\n");
00434                 }
00435                 // lower the extraction flag
00436                 extractingData=0;
00437                 FlushDataFiles();
00438                 // if a time segment extraction is running
00439                 if (timeSegment>0)
00440                 // then
00441                 {
00442                         // compute the end of window
00443                         NextWindow();
00444                 // else
00445                 }
00446                 else
00447                 {
00448                         // if a timelist extraction is running
00449                         if ((timeList>0)||((beginWindow>0)&&(endWindow>0)))
00450                         // then
00451                         {
00452                                 // close before restarting extraction
00453                                 CloseInput();
00454                         // endif
00455                         }
00456                 // endif
00457                 }
00458         }
00459 /*
00460         // if we are in a segment window
00461         if (InWindow())
00462         {
00463                 // mark the extraction flag high
00464                 extractingData=Extracting(0);
00465                 // remember that we have seen this window
00466                 dataExtracted=1;
00467                 // then do something with the data
00468                 // process each channel
00469                 for (i=0; i<MAX_CHANNEL; i++)
00470                 {
00471                         // if there is something to do with this channel
00472                         if (((1LL<<i)&(auxiliaryMask|channelMask))&&(HWConfig.srObs[i].npts>=minSamplesPerFrame))
00473                         {
00474                                 // export to trigger
00475                                 if (extractTrig>0)
00476                                 {
00477                                         AddTriggerData(i);
00478                                 }
00479                                 // export to wav
00480                                 if (extractWav>0)
00481                                 {
00482                                         AddWavData(i);
00483                                 }
00484                                 // export to gif
00485                                 if (extractGif>0)
00486                                 {
00487                                         AddGifData(i);
00488                                 }
00489                                 // export to seg2
00490                                 if (extractSeg2>0)
00491                                 {
00492                                         AddSeg2Data(i);
00493                                 }
00494                                 // export to segy
00495                                 if (extractSegy>0)
00496                                 {
00497                                         AddSegyData(i);
00498                                 }
00499                                 // export to sis
00500                                 if (extractSis>0)
00501                                 {
00502                                         AddSisData(i);
00503                                 }
00504                                 // export to sac
00505                                 if (extractSac>0)
00506                                 {
00507                                         AddSacData(i);
00508                                 }
00509                                 // export to mseed
00510                                 if (extractMSeed>0)
00511                                 {
00512                                         AddMSeedData(i);
00513                                 }
00514                                 // export to asc
00515                                 if (extractAsc>0)
00516                                 {
00517                                         AddAscData(i);
00518                                 }
00519                         }
00520                         // save the uncorrected time (corrected later)
00521                         if (infoHeader[i].uncorrected.usecond<=0)
00522                         {
00523                                 memcpy(&(infoHeader[i].uncorrected),&currentTime,
00524                                                 sizeof(struct Titan2TimeType));
00525                         }
00526                 }
00527         }
00528         */
00529 
00530         // close now the files if a discontinuity was detected
00531         // should this block be placed before adding the data ?
00532         if ((continuity<0)&&(extractTit==0))
00533         {
00534                 PrintDebug("closing data files\n");
00535                 CachePrintCST();
00536                 FlushDataFiles();
00537                 ResetTimes();
00538                 strcpy(HWConfig.fieldIdent,DEFAULT_STATION);
00539                 if (manualStationName[0]!=0)  
00540                 {  
00541                         strcpy(HWConfig.fieldIdent,manualStationName);  
00542                         strcpy(oldHWConfig.fieldIdent,manualStationName);
00543                 }
00544                 strcpy(HWConfig.serialNumber,DEFAULT_SERIAL);
00545         }
00546 
00547         // identify the current file format and check it
00548         score=0;
00549         if (nTitan1+nTitan2)
00550         {
00551                 score+=(100*nTitan2)/(nTitan1+nTitan2);
00552         }
00553         // here, if score>50 we are reading titan2 data
00554         // identify the titan version
00555         format=lastFormat;
00556         if ((score==0)&&(nTitan1>0))
00557         {
00558                 format=1;
00559         }
00560         if (score>50)
00561         {
00562                 format=2;
00563         }
00564         // check the score
00565         if ((score<70)&&(score>5))
00566         {
00567                 PrintWarning("received mixed Titan1 and Titan2 data "
00568                                 "frames (s=%d t1=%d, t2=%d), format=%d\n",
00569                                 score,nTitan1,nTitan2,format);
00570         }
00571         // if the format changed
00572         if (format!=lastFormat)
00573         {
00574                 if (lastFormat!=-1)
00575                 {
00576                         PrintWarning("format change detected\n");
00577                         // flush all the tasks and close all the output files
00578                         CachePrintCST();
00579                         FlushDataFiles();
00580                         if (cutDtOnReset==0)
00581                         {
00582                                 FlushNonDataFiles();
00583                         }
00584                         ResetTimes();
00585                         strcpy(HWConfig.fieldIdent,DEFAULT_STATION);
00586                         if (manualStationName[0]!=0)  
00587                         {  
00588                                 strcpy(HWConfig.fieldIdent,manualStationName);  
00589                                 strcpy(oldHWConfig.fieldIdent,manualStationName);
00590                         }
00591                         strcpy(HWConfig.serialNumber,DEFAULT_SERIAL);
00592                 }
00593                 lastFormat=format;
00594                 if (HWConfig.formatVersion==-1)
00595                 {
00596                         PrintDebug("HWConfig.formatVersion=%d\n",format);
00597                         HWConfig.formatVersion=format;
00598                 }
00599         }
00600 
00601         // finally, we managed to get there with data, let's dump these data
00602         // if we are in a segment window
00603         if (InWindow())
00604         {
00605                 // mark the extraction flag high
00606                 extractingData=Extracting(0);
00607                 // remember that we have seen this window
00608                 dataExtracted=1;
00609                 // then do something with the data
00610                 // process each channel
00611                 for (i=0; i<MAX_CHANNEL; i++)
00612                 {
00613                         // if there is something to do with this channel
00614                         if (((1LL<<i)&(auxiliaryMask|channelMask))&&(HWConfig.srObs[i].npts>=minSamplesPerFrame))
00615                         {
00616                                 // export to trigger
00617                                 if (extractTrig>0)
00618                                 {
00619                                         AddTriggerData(i);
00620                                 }
00621                                 // export to wav
00622                                 if (extractWav>0)
00623                                 {
00624                                         AddWavData(i);
00625                                 }
00626                                 // export to gif
00627                                 if (extractGif>0)
00628                                 {
00629                                         AddGifData(i);
00630                                 }
00631                                 // export to seg2
00632                                 if (extractSeg2>0)
00633                                 {
00634                                         AddSeg2Data(i);
00635                                 }
00636                                 // export to segy
00637                                 if (extractSegy>0)
00638                                 {
00639                                         AddSegyData(i);
00640                                 }
00641                                 // export to sis
00642                                 if (extractSis>0)
00643                                 {
00644                                         AddSisData(i);
00645                                 }
00646                                 // export to sac
00647                                 if (extractSac>0)
00648                                 {
00649                                         AddSacData(i);
00650                                 }
00651                                 // export to mseed
00652                                 if (extractMSeed>0)
00653                                 {
00654                                         AddMSeedData(i);
00655                                 }
00656                                 // export to asc
00657                                 if (extractAsc>0)
00658                                 {
00659                                         AddAscData(i);
00660                                 }
00661                                 // export to bin
00662                                 if (extractBin>0)
00663                                 {
00664                                         AddBinData(i);
00665                                 }
00666                         }
00667                         // save the uncorrected time (corrected later)
00668                         if (infoHeader[i].uncorrected.usecond<=0)
00669                         {
00670                                 memcpy(&(infoHeader[i].uncorrected),&currentTime,
00671                                                 sizeof(struct Titan2TimeType));
00672                         }
00673                 }
00674         }
00675 
00676         // now that we have closed the files that should be closed...
00677         memcpy(&oldHWConfig,&HWConfig,
00678                         sizeof(struct HWConfigType)-sizeof(HWConfig.data));
00679 
00680         // finally, empty the working buffers (this must be after the memcpy)
00681         for (i=0; i<MAX_CHANNEL; i++)
00682         {
00683                 HWConfig.srObs[i].npts=0;
00684                 HWConfig.srExp[i].npts=0;
00685                 lastData[i]=0;
00686         }
00687         // reset the frame counters
00688         nTitan1=nTitan2=0;
00689 }
00690 
00694 int64_t ProcessDataFrame(const unsigned char *frame)
00695 {
00696         int ch,i2,i5,srq,rate,n;
00697         int32_t dummy=0;
00698         int32_t d;
00699         int triplet=0;
00700         int64_t ret=0;
00701         register int i;
00702         // test for extraction
00703         /*
00704         if (!extracting)
00705         {
00706                 return(0);
00707         }
00708         */
00709         // detect the type of data frame
00710         switch (frame[11]&0x7)
00711         {
00712                 // lire titan1 ici
00713                 case DAT1_FRAME: // titan1, post event
00714                         // HWConfig.trigger[ch]=1;
00715                 case DAT0_FRAME: // titan1, pre event
00716                         // decode the triplet number
00717                         triplet=(frame[9]&0xf0)>>4;
00718                         ret=7<<triplet;
00719                         // process auxilliary channels
00720                         if ((auxiliaryMask!=0)&&(triplet==12))
00721                         {
00722                                 ProcessAux1Frame(frame);
00723                                 break;
00724                         }
00725                         // skip non data triplets
00726                         if (triplet>3)
00727                         {
00728                                 break;
00729                         }
00730                         // increase the frame counter
00731                         nTitan1++;
00732                         if (3*triplet+2>=MAX_CHANNEL)
00733                         {
00734                                 PrintError("triplet number is %d\n",triplet);
00735                                 break;
00736                         }
00737                         /*
00738                         PrintLog("div=%d f=%.2f\n",
00739                                         HWConfig.srExp[3*triplet].div,
00740                                         (float)HWConfig.srExp[3*triplet].base/(float)HWConfig.srExp[3*triplet].div
00741                                         );
00742                                         */
00743                         // decode the compression rate
00744                         rate=frame[10]&0xf;
00745                         for (i=0; i<3; i++)
00746                         {
00747                                 int mch=0;
00748                                 ch=3*triplet+i;
00749                                 mch=ch-6;
00750                                 if (mch<0)
00751                                 {
00752                                         mch=ch;
00753                                 }
00754                         // decode the sampling rate
00755                                 switch (frame[9]&0x0f)
00756                                 {
00757                                         case 8:  case 9:  case 10: case 11:
00758                                         case 12: case 13: case 14: case 15:
00759                                                 HWConfig.srExp[ch].div=1<<(3-((frame[9]&0xf)-0x10));
00760                                                 break;
00761                                         case 0:
00762                                         case 1:
00763                                         case 2:
00764                                         case 3:
00765                                                 HWConfig.srExp[ch].div=1<<(3-(frame[9]&0x0f));
00766                                                 break;
00767                                         default:
00768                                                 PrintError("%d %#0x\n",
00769                                                                 frame[9]&0xf,
00770                                                                 frame[10]&0xff);
00771                                                 // abort
00772                                                 // nothing can be done since we are not
00773                                                 // able to determine the number of
00774                                                 // samples, the best thing to do is skip
00775                                                 // the frame and try the next
00776                                                 return(0);
00777                                 }
00778                                 if (HWConfig.srExp[ch].div<1)
00779                                 {
00780                                         HWConfig.srExp[ch].npts=0;
00781                                         PrintError("null divider for data frame "
00782                                                         "(%d,%d,%d)\n",
00783                                                         ch,mch,frame[9]&0x0f);
00784                                         return(0);
00785                                 }
00786 
00787                                 HWConfig.srObs[ch].base=HWConfig.srExp[ch].base=HWConfig.srExp[mch].base;
00788 
00789                                 HWConfig.srExp[ch].npts=128*HWConfig.srExp[mch].div/HWConfig.srExp[ch].div;
00790                                 // absolute samples
00791                                 if ((rate==1)&&(HWConfig.srObs[ch].npts==0))
00792                                 {
00793                                         d=frame2i24(frame,3*i);
00794                                         d<<=8;
00795                                         d>>=8;
00796 
00797                                         HWConfig.data[ch][HWConfig.srObs[ch].npts]=lastData[ch]+d;
00798                                         lastData[ch]=HWConfig.data[ch][HWConfig.srObs[ch].npts];
00799                                         // add the offset AFTER the copy to lastData
00800                                         HWConfig.data[ch][HWConfig.srObs[ch].npts]+=
00801                                                 HWConfig.absOffset[ch];
00802                                         if (HWConfig.srObs[ch].npts<MAX_SAMPLE-1)
00803                                         {
00804                                                 HWConfig.srObs[ch].npts++;
00805                                         }
00806                                         else
00807                                         {
00808                                                 PrintError("too many samples for channel"
00809                                                                 " %d, clearing buffer\n",
00810                                                                 ch);
00811                                                 HWConfig.srObs[ch].npts=0;
00812                                         }
00813                                 }
00814                                 // or relative samples
00815                                 else
00816                                 {
00817                                         // uncompress data only if needed
00818                                         if (extracting)
00819                                         {
00820                                                 dummy=frame2i24(frame,3*i);
00821                                                 for (n=0; n<rate; n++)
00822                                                 {
00823                                                         // keep the last bits of the word
00824                                                         d=dummy&msf[rate][0];
00825                                                         // suppress these bits
00826                                                         dummy>>=msf[rate][1];
00827                                                         // sign
00828                                                         d<<=msf[rate][2];
00829                                                         d>>=msf[rate][2];
00830                                                         HWConfig.data[ch][HWConfig.srObs[ch].npts]=lastData[ch]+d;
00831                                                         lastData[ch]=HWConfig.data[ch][HWConfig.srObs[ch].npts];
00832                                                         // add the offset AFTER the copy to lastData
00833                                                         HWConfig.data[ch][HWConfig.srObs[ch].npts]+=
00834                                                                 HWConfig.absOffset[ch];
00835                                                         HWConfig.srObs[ch].npts++;
00836                                                 }
00837                                         }
00838                                         // else just increase the number of samples
00839                                         else
00840                                         {
00841                                                 HWConfig.srObs[ch].npts+=rate;
00842                                         }
00843                                 }
00844                         }
00845                         break;
00846                 case DAT2_FRAME:
00847                         if (HWConfig.formatVersion==1)
00848                         {
00849                                 PrintDebug("DAT2 with formatVersion=1: %s\n\t%s @ %d\n",
00850                                                 StrFrame(frame),
00851                                                 currentFile,SafeFtell(