00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <stdio.h>
00023 #include <ctype.h>
00024 #include <stdlib.h>
00025 #include <unistd.h>
00026 #include <time.h>
00027 #include <string.h>
00028 #include <assert.h>
00029 #include <sys/types.h>
00030
00031 #include "common.h"
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 struct SegyHead {
00062 int32_t lineSeq;
00063 int32_t reelSeq;
00064 int32_t event_number;
00065 int32_t channel_number;
00066 int32_t energySourcePt;
00067 int32_t cdpEns;
00068 int32_t traceInEnsemble;
00069 int16_t traceID;
00070 int16_t vertSum;
00071 int16_t horSum;
00072 int16_t dataUse;
00073 int32_t sourceToRecDist;
00074 int32_t recElevation;
00075 int32_t sourceSurfaceElevation;
00076 int32_t sourceDepth;
00077 int32_t datumElevRec;
00078 int32_t datumElevSource;
00079 int32_t sourceWaterDepth;
00080 int32_t recWaterDepth;
00081 int16_t elevationScale;
00082 int16_t coordScale;
00083 int32_t sourceLongOrX;
00084 int32_t sourceLatOrY;
00085 int32_t recLongOrX;
00086 int32_t recLatOrY;
00087 int16_t coordUnits;
00088 int16_t weatheringVelocity;
00089 int16_t subWeatheringVelocity;
00090 int16_t sourceUpholeTime;
00091 int16_t recUpholeTime;
00092 int16_t sourceStaticCor;
00093 int16_t recStaticCor;
00094 int16_t totalStatic;
00095 int16_t lagTimeA;
00096 int16_t lagTimeB;
00097 int16_t delay;
00098 int16_t muteStart;
00099 int16_t muteEnd;
00100 int16_t sampleLength;
00101 int16_t deltaSample;
00102 int16_t gainType;
00103 int16_t gainConst;
00104 int16_t initialGain;
00105 int16_t correlated;
00106 int16_t sweepStart;
00107 int16_t sweepEnd;
00108 int16_t sweepLength;
00109 int16_t sweepType;
00110 int16_t sweepTaperAtStart;
00111 int16_t sweepTaperAtEnd;
00112 int16_t taperType;
00113 int16_t aliasFreq;
00114 int16_t aliasSlope;
00115 int16_t notchFreq;
00116 int16_t notchSlope;
00117 int16_t lowCutFreq;
00118 int16_t hiCutFreq;
00119 int16_t lowCutSlope;
00120 int16_t hiCutSlope;
00121 int16_t year;
00122 int16_t day;
00123 int16_t hour;
00124 int16_t minute;
00125 int16_t second;
00126 int16_t timeBasisCode;
00127 int16_t traceWeightingFactor;
00128 int16_t phoneRollPos1;
00129 int16_t phoneFirstTrace;
00130 int16_t phoneLastTrace;
00131 int16_t gapSize;
00132 int16_t taperOvertravel;
00133 char station_name[6];
00134 char sensor_serial[8];
00135 char channel_name[4];
00136 int16_t totalStaticHi;
00137 int32_t samp_rate;
00138 int16_t data_form;
00139 int16_t m_secs;
00140 int16_t trigyear;
00141 int16_t trigday;
00142 int16_t trighour;
00143 int16_t trigminute;
00144 int16_t trigsecond;
00145 int16_t trigmills;
00146 float scale_fac;
00147 int16_t inst_no;
00148 int16_t not_to_be_used;
00149 int32_t num_samps;
00150
00151 int32_t max;
00152 int32_t min;
00153 };
00154
00155 struct SegyHead segyHeader[MAX_CHANNEL];
00156 FILE *segyChannelFile[MAX_CHANNEL] = {
00157 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
00158 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
00159 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
00160 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
00161 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
00162 };
00163 char segyChannelFileName[MAX_CHANNEL][128];
00164
00165
00166 void UpdateSegyHeader(int ch)
00167 {
00168 time_t T0;
00169 struct tm tm0;
00170 UpdateInfoHeader(ch);
00171 T0=(time_t)infoHeader[ch].correctedTime;
00172 memcpy(&tm0,gmtime(&T0),sizeof(struct tm));
00173
00174
00175 segyHeader[ch].year= tm0.tm_year+1900;
00176 segyHeader[ch].day= tm0.tm_yday+1;
00177 segyHeader[ch].hour= tm0.tm_hour;
00178 segyHeader[ch].minute= tm0.tm_min;
00179 segyHeader[ch].second= tm0.tm_sec;
00180 segyHeader[ch].m_secs= (int32_t)(1000.*(infoHeader[ch].correctedTime-(double)T0));
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191 if (infoHeader[ch].npts<32767)
00192 {
00193 segyHeader[ch].sampleLength=infoHeader[ch].npts;
00194 segyHeader[ch].num_samps=infoHeader[ch].npts;
00195 } else
00196 {
00197 segyHeader[ch].sampleLength=32767;
00198 segyHeader[ch].num_samps=infoHeader[ch].npts;
00199 }
00200 }
00201
00202 void InitSegyHeader(int ch)
00203 {
00204 memset(&(segyHeader[ch]),0,sizeof(struct SegyHead));
00205 segyHeader[ch].traceID=1;
00206 segyHeader[ch].elevationScale=1;
00207 segyHeader[ch].coordScale=1;
00208 segyHeader[ch].coordUnits=2;
00209 segyHeader[ch].gainType=1;
00210 segyHeader[ch].gainConst=1;
00211 segyHeader[ch].timeBasisCode=2;
00212 snprintf(segyHeader[ch].station_name,5,"%-5s",infoHeader[ch].station);
00213 segyHeader[ch].station_name[5]=0;
00214 segyHeader[ch].sensor_serial[0]=0;
00215 snprintf(segyHeader[ch].channel_name,3,"%-3s",infoHeader[ch].channel);
00216 segyHeader[ch].channel_name[3]=0;
00217 segyHeader[ch].samp_rate=
00218 ((1000000*infoHeader[ch].sr.div)/infoHeader[ch].sr.base);
00219
00220 if (segyHeader[ch].samp_rate>32768)
00221 {
00222 segyHeader[ch].deltaSample=1;
00223 }
00224 else
00225 {
00226 segyHeader[ch].deltaSample=segyHeader[ch].samp_rate;
00227 }
00228 segyHeader[ch].data_form=1;
00229 segyHeader[ch].scale_fac=1.;
00230 }
00231
00235 FILE* OpenSegyChannel(int channel)
00236 {
00237 if (segyChannelFile[channel]==NULL)
00238 {
00239 int fd;
00240 strcpy(segyChannelFileName[channel],"titanfileXXXXXX");
00241 fd=OpenTempFile(segyChannelFileName[channel]);
00242 assert((segyChannelFile[channel]=fdopen(fd,"wb"))!=NULL);
00243 setvbuf(segyChannelFile[channel],NULL,_IOFBF,FILE_BUFFER_SIZE);
00244
00245 if (segyChannelFile[channel])
00246 {
00247
00248 InitInfoHeader(channel);
00249
00250 InitSegyHeader(channel);
00251
00252 fwrite(&segyHeader[channel],sizeof(struct SegyHead),1,segyChannelFile[channel]);
00253 }
00254 else
00255 {
00256 PrintError("unable to open %s: %m\n",segyChannelFileName[channel]);
00257 }
00258 }
00259 return(segyChannelFile[channel]);
00260 }
00261
00265 void CloseSegyFile(int channel)
00266 {
00267 char line[128];
00268 if (segyChannelFile[channel]==NULL)
00269 {
00270 return;
00271 }
00272
00273 UpdateSegyHeader(channel);
00274
00275
00276
00277 fseek(segyChannelFile[channel],0,SEEK_SET);
00278 fwrite(&segyHeader[channel],sizeof(struct SegyHead),1,segyChannelFile[channel]);
00279 fclose(segyChannelFile[channel]);
00280 segyChannelFile[channel]=NULL;
00281 strcpy(line,FileName("", ".SEGY", channel, fileNameOptions));
00282 if (noWrite==0)
00283 {
00284 Rename(segyChannelFileName[channel],line);
00285 }
00286 PrintLog("OUTPUT: %s %d samples (%.2fs)\n",line,
00287 infoHeader[channel].npts,
00288 (float)infoHeader[channel].npts/(double)infoHeader[channel].sr.npts);
00289 unlink(segyChannelFileName[channel]);
00290 }
00291
00294 void AbortSegyFile(int channel)
00295 {
00296 PrintDebug("abort for %s\n",segyChannelFileName[channel]);
00297 if (segyChannelFile[channel])
00298 {
00299 fclose(segyChannelFile[channel]);
00300 segyChannelFile[channel]=NULL;
00301 unlink(segyChannelFileName[channel]);
00302 }
00303 }
00304
00306 void AddSegyData(int channel)
00307 {
00308 if ((HWConfig.srObs[channel].npts==0)||(HWConfig.srExp[channel].npts==0))
00309 {
00310 return;
00311 }
00312 if (OpenSegyChannel(channel))
00313 {
00314 if (fwrite(HWConfig.data[channel],4,
00315 HWConfig.srObs[channel].npts,segyChannelFile[channel])
00316 !=HWConfig.srObs[channel].npts)
00317 {
00318 PrintError("unable to write to %s: %m\n",segyChannelFileName[channel]);
00319 AbortSegyFile(channel);
00320 }
00321 infoHeader[channel].npts+=HWConfig.srObs[channel].npts;
00322 }
00323 }