/* external-routines for read and write win file from fortran program */ /* modified by Y.Ishihara */ #include #include #include #include #include #define LINELEN 128 void win_open_(); void wd_read_head_(); void win_close_(); void win_read_1sec_(); void win_read_1trace_(); void win_write_1sec_(); void win_write_all_(); typedef struct { char name[5], comp[4], unit[7]; int rec, delay; unsigned short sys_ch; float t0, h, d2u, alt, stcp, stcs; double phi, lamda; } CH_TBL; FILE *win_strm_ptr[256]; CH_TBL *chtbl; int win_written_sec[256], n_ch; /*-----------------------------------------------------------------------*/ void win_open_(lunit,filename,method,iflag) /* win形式のファイルをオープンするためのサブルーチン (注意:メイン側で、10以上のファイルを同時にオープンしないこと!!) 引数 long lunit: win形式ファイルの通し番号(1から256まで) char filename: win形式ファイルのファイル名(NULLをつける必要なし) long method: オープンするファイルのアクセス方法(0:read, 1:write, それ以外はエラー) long iflag: ステータス(0:正常、999:オープンできない) */ char *filename; int *lunit, *method, *iflag; { int i, ifile; if ((ifile =*lunit-1)<0||ifile>255) { /*ファイル番号は正しいか?*/ *iflag = 999; return; } *iflag = 0; for (i=0;filename[i]!=' '&&filename[i]!=NULL;i++) ; /*filename を C言語用に修正する (NULLを加える)*/ filename[i] = NULL; if (*method==0) { /*リードオンリーでオープンする*/ if ((win_strm_ptr[ifile]=fopen(filename, "r"))==NULL) { *iflag = 999; return; } } else if (*method==1) { /*更新モードでオープンする*/ if ((win_strm_ptr[ifile]=fopen(filename, "w+"))==NULL) { *iflag = 999; return; } win_written_sec[ifile] = 0; } else { *iflag = 999; return; } return; } /*---------------------------------------------------------------------------------------*/ void win_close_(lunit) /* win_openで開いたファイルをクローズする。 引数 long lunit: win形式ファイルの通し番号(1から10まで) */ int *lunit; { int ifile; ifile = *lunit-1; fclose(win_strm_ptr[ifile]); return; } /*---------------------------------------------------------------------------------------*/ void wd_read_head_(lunit,chead) /* read 128 bytes from the beggining of file (read header of LS8000WD Hakusan Data mark logger format) */ int *lunit; char chead[128]; { int ifile; int i; ifile = *lunit-1; for (i=0; i<128; i++) { chead[i] = fgetc(win_strm_ptr[ifile]); } /* fseek(win_strm_ptr[ifile],128,0); */ return; } /*---------------------------------------------------------------------------------------*/ void win_read_1sec_(lunit, isec, max_sample, max_ch, data, id_ch, date, nsample, iflag) /* win形式のファイルから1秒分の波形データを読み込むためのサブルーチン 引数(すべて4Byte integer) (入力として用いるもの) lunit: win形式ファイルの通し番号(1から10まで) isec: 取り込むデータの時間(先頭から秒単位で指定) 先頭の1秒間のデータを読み込む場合は isec=0 max_sample: メインルーチンでデータ用に確保した配列の上限(データ長=サンプル数) max_ch: メインルーチンでデータ用に確保した配列の上限(チャンネル数) (出力として用いるもの) data: データを入れるための配列 (data(max_sample,max_ch)) id_ch: dataの要素番号とチャンネル番号を対応付けるための配列(id_ch(max_ch)) date: 読み込んだデータの先頭の時刻(年月日時分秒)が返される配列(date(6)) nsample: サンプリング周波数(nsample(max_ch))=欠測のチャンネルに対しては0 iflag: 状態を返すフラグ 0: 正常 1: ファイルのデータ長がmax_sampleを越えている 2: ファイルのデータチャンネル数がmax_chを越えている 999: ファイルがオープンできなかった -999: そのほかのエラー by R. Hino 5/31/95 */ int *lunit, *isec, *max_sample, *max_ch, *data, *id_ch, *date, *nsample, *iflag; { int i, ich, ifile, mainsize, current, sec, ch_header, lsample, fs, sabun, *ptr_out, unpacked_bcd(), get_nbyte(); unsigned short sys_ch; unsigned char *mainbuf, *ptr_in, *ptr_lim, *read_data(); ifile = *lunit - 1; ptr_out = data; *iflag = 0; for (i=0;i<*max_ch;i++) nsample[i] = 0; fseek(win_strm_ptr[ifile],0,0); /*isecまで頭出し*/ /* fseek(win_strm_ptr[ifile],0,SEEK_SET); */ /* HP version */ for (current=0,sec=0;sec<*isec;sec++) { if ((mainbuf=read_data(win_strm_ptr[ifile],&mainsize))!=NULL) current += mainsize; else { *iflag = 999; return; } } fseek(win_strm_ptr[ifile],current,0); if ((mainbuf=read_data(win_strm_ptr[ifile],&mainsize))==0) { /*1秒分をバッファに読み込む*/ *iflag = 999; return; } for (i=0;i<6;i++) date[i]=unpacked_bcd(mainbuf[4+i]); /*BCDコード化された日付時刻をデコード*/ ptr_lim = mainbuf + mainsize; ptr_in = mainbuf+10; for (ich=0;ptr_in>12; id_ch[ich] = sys_ch = ch_header>>16; nsample[ich] = fs = ch_header&0xfff; if (fs>*max_sample) { *iflag = 1; /* サンプル数がmax_sampleを超えた */ nsample[ich] = 0; /* 欠測扱い(nsample[ich]=0) */ } else if (ich >= *max_ch) { *iflag = 2; /* 収録チャンネル数がmax_chを超えた */ } if (*iflag==0) { ptr_out = data + (*max_sample)*ich; *ptr_out = int_swap(get_nbyte(ptr_in,4)); /* 第1サンプルはいつも4Byte */ ptr_in+=4; if (lsample) { /* それ以降が1/2/3/4Byteのとき */ for (i=1;i>4); if (sabun>=8) sabun -= 16; *(ptr_out+1) = *ptr_out + sabun; ptr_out++; i++; /* 下位の4bit */ if (i=8) sabun -= 16; *(ptr_out+1) = *ptr_out + sabun; ptr_out++; i++; } ptr_in++; } } } else { if (lsample) ptr_in += 4 + lsample*(fs-1); else { if (fs%2) ptr_in += 5 + fs/2; else ptr_in += 4 + fs/2; } } } free(mainbuf); return; } /*---------------------------------------------------------------------------------------*/ void win_read_1trace_(lunit, id_ch, max_sample, data, date, nsample, length, iflag) /* win形式のファイルから1成分の波形データ(最初から最後まで)を読み込む 引数(すべて4Byte integer) (入力として用いるもの) lunit: win形式ファイルの通し番号(1から10まで) id_ch: 取り込むデータのチャンネル番号 max_sample: メインルーチンでデータ用に確保した配列の上限(データ長=サンプル数) (出力として用いるもの) data: データを入れるための配列 (data(max_sample)) date: 読み込んだデータの先頭の時刻(年月日時分秒)が返される配列(date(6)) nsample: サンプリング周波数=欠測の場合0 length: 読み込んだデータの長さ(秒) iflag: 状態を返すフラグ 0: 正常 -1: 指定されたチャンネルのデータはなかった -2: ファイルのデータ長がmax_sampleを越えている by R. Hino 5/31/95 int_swap is newly added at get_swap for little endian machines by T. Nishimura 99/10/31 */ int *lunit, *id_ch, *max_sample, *data, *date, *nsample, *length, *iflag; { int i, ifile, isec, isample, mainsize, ch_header, lsample, fs, sabun, *ptr_out, unpacked_bcd(), get_nbyte(); unsigned short sys_ch; unsigned char *mainbuf, *ptr_in, *ptr_lim, *read_data(); ifile = *lunit - 1; isec = 0; isample = 0; *nsample = 0; ptr_out = data; while (mainbuf=read_data(win_strm_ptr[ifile],&mainsize)) { /* 秒ごとのループ */ if (isec==0) for (i=0;i<6;i++) date[i]=unpacked_bcd(mainbuf[4+i]); ptr_lim = mainbuf + mainsize; ptr_in = mainbuf+10; do { /* チャンネルごとのループ */ ch_header = int_swap(get_nbyte(ptr_in,4)); ptr_in+=4; lsample = (ch_header&0xf000)>>12; sys_ch = ch_header>>16; fs = ch_header&0xfff; if (sys_ch==*id_ch) { if (++isample>*max_sample) goto end; *nsample = fs; *ptr_out = int_swap(get_nbyte(ptr_in,4)); /* 第1サンプルはいつも4Byte */ ptr_in += 4; if (lsample) { /* それ以降が1/2/3/4Byteの場合 */ for (i=1;i*max_sample) goto end; *(ptr_out+1) = *ptr_out + int_swap(get_nbyte(ptr_in,lsample)); ptr_out++; ptr_in+=lsample; } } else { for (i=1;i*max_sample) goto end; sabun = (int)(*ptr_in>>4); if (sabun>=8) sabun -= 16; *(ptr_out+1) = *ptr_out + sabun; ptr_out++; i++; /* 下位の4bit */ if (i*max_sample) goto end; sabun = (int)((*ptr_in)&0xf); if (sabun>=8) sabun -= 16; *(ptr_out+1) = *ptr_out + sabun; ptr_out++; i++; } ptr_in++; } } ptr_out++; } else { if (lsample) ptr_in += 4+lsample*(fs-1); else { if (fs%2) ptr_in += 5+fs/2; else ptr_in += 4+fs/2; } } } while (ptr_in*max_sample) *iflag = -2; *length = isec; return; } /*---------------------------------------------------------------------------------------*/ void win_write_1sec_(lunit, isec, max_sample, max_ch, data, id_ch, date, nsample, iflag) /* win形式のファイルに1秒分の波形データを書き込むためのサブルーチン (注意:1つにファイルには時間順に連続して書き込むこと!!) 引数(すべて4Byte integer) (入力として用いるもの) lunit: win形式ファイルの通し番号(1から10まで) isec: 書き込むデータの時間(先頭から秒単位で指定) 先頭の1秒間のデータを書き込む場合は isec=0 max_sample: メインルーチンでデータ用に確保した配列の上限(データ長=サンプル数) max_ch メインルーチンでデータ用に確保した配列の上限(チャンネル数) data: データが入っている配列 (data(max_sample,max_ch)) date: データの先頭の時刻(年月日時分秒)の配列(date(6)) id_ch: dataの要素番号とチャンネル番号を対応付けるための配列(id_ch(max_ch)) nsample: サンプリング周波数(nsample(max_ch))=欠測のチャンネルに対しては0 (出力として用いるもの) iflag: 状態を返すフラグ 0: 正常 999: ファイルに書き込めなかった -999: そのほかのエラー by R. Hino 5/31/95 */ int *lunit, *isec, *max_sample, *max_ch, *data, *id_ch, *date, *nsample, *iflag; { FILE *file_temp; int ifile, ich, fs, l, block_size, *ptr_in; unsigned char *outbuf, t_bcd[6], *wtp; unsigned short sys_ch; void set_bcd_time(); ifile = *lunit - 1; if (*isec!=win_written_sec[ifile]) { *iflag = 999; return; } win_written_sec[ifile]++; if ((file_temp=tmpfile())==NULL) { *iflag = -999; return; } for (ich=0,block_size=10;ich<*max_ch;ich++) { /* チャンネルごとのループ */ if ((fs=nsample[ich])==0) continue; if ((outbuf=(unsigned char *)malloc(l=sizeof(long)*fs))==NULL) { *iflag = -999; return; } ptr_in = data+(*max_sample)*ich; sys_ch = (unsigned short)(id_ch[ich]); block_size += l = winform(ptr_in,outbuf,fs,sys_ch); fwrite(outbuf,l,1,file_temp); /* データをテンポラリファイルにいったん保存*/ } fwrite(&block_size,4,1,win_strm_ptr[ifile]); /* ブロックサイズを4Bで書き込み(先頭)*/ set_bcd_time(t_bcd,date); fwrite(t_bcd,6,1,win_strm_ptr[ifile]); /* ブロックの時刻をBCDコード化して書き込み*/ if ((wtp=(unsigned char *)malloc(l=block_size-10))==NULL) { *iflag = -999; return; } rewind(file_temp); fread(wtp,l,1,file_temp); /* 一時保存したデータを読み込み*/ fwrite(wtp,l,1,win_strm_ptr[ifile]); /* ファイルへ書き込み*/ fclose(file_temp); free(outbuf); free(wtp); return; } /*---------------------------------------------------------------------------------------*/ void win_write_all_(lunit, max_sample, max_ch, data, id_ch, date, nsample, ldata, iflag) /* win形式のファイルに全成分のすべての波形データを書き込むためのサブルーチン 引数(すべて4Byte integer) (入力として用いるもの) lunit: win形式ファイルの通し番号(1から10まで) max_sample: メインルーチンでデータ用に確保した配列の上限(データ長=サンプル数) max_ch メインルーチンでデータ用に確保した配列の上限(チャンネル数) data: データが入っている配列 (data(max_sample,max_ch)) id_ch: dataの要素番号とチャンネル番号を対応付けるための配列(id_ch(max_ch)) date: データの先頭の時刻(年月日時分秒)の配列(date(6)) nsample: サンプリング周波数(nsample(max_ch))=欠測のチャンネルに対しては0 ldata: 配列に収録されているデータの長さ(秒) (出力として用いるもの) iflag: 状態を返すフラグ 0: 正常 999: ファイルに書き込めなかった -999: そのほかのエラー by R. Hino 5/31/95 */ int *lunit, *max_sample, *max_ch, *data, *id_ch, *date, *nsample, *ldata, *iflag; { FILE *file_temp; int i, ifile, isec, jdate[6], ich, fs, l, block_size, *ptr_in; unsigned char *outbuf, t_bcd[6], *wtp; unsigned short sys_ch; void set_bcd_time(); ifile = *lunit - 1; if (win_written_sec[ifile]!=0) { *iflag = 999; return; } if ((file_temp=tmpfile())==NULL) { *iflag = -999; return; } for (i=0;i<5;i++) jdate[i] = date[i]; for (isec=0;isec<*ldata;isec++) { for (ich=0,block_size=10;ich<*max_ch;ich++) { if ((fs=nsample[ich])==0) continue; if ((outbuf=(unsigned char *)malloc(sizeof(long)*fs))==NULL) { *iflag = -999; return; } ptr_in = data+(*max_sample)*ich + fs*isec; sys_ch = (unsigned short)(id_ch[ich]); block_size += l = winform(ptr_in,outbuf,fs,sys_ch); fwrite(outbuf,l,1,file_temp); /* データをテンポラリファイルにいったん保存*/ } fwrite(&block_size,4,1,win_strm_ptr[ifile]); /* ブロックサイズを4Bで書き込み(先頭)*/ jdate[5] = date[5] + isec; set_bcd_time(t_bcd,jdate); fwrite(t_bcd,6,1,win_strm_ptr[ifile]); /* ブロックの時刻をBCDコード化して書き込み*/ if ((wtp=(unsigned char *)malloc(l=block_size-10))==NULL) { *iflag = -999; return; } rewind(file_temp); fread(wtp,l,1,file_temp); /* 一時保存したデータを読み込み*/ fwrite(wtp,l,1,win_strm_ptr[ifile]); /* ファイルへ書き込み*/ rewind(file_temp); free(outbuf); free(wtp); } fclose(file_temp); return; } /*---------------------------------------------------------------------------------------*/ void win_write_all2_(lunit, max_sample, max_ch, data, id_ch, date, nsample, ldata, iflag) /* win形式のファイルに全成分のすべての波形データを書き込むためのサブルーチン (2バイトデータヴァージョン) 引数(data以外すべて4Byte integer, dataは2Byte integer) (入力として用いるもの) lunit: win形式ファイルの通し番号(1から10まで) max_sample: メインルーチンでデータ用に確保した配列の上限(データ長=サンプル数) max_ch メインルーチンでデータ用に確保した配列の上限(チャンネル数) data: データが入っている配列 (data(max_sample,max_ch)) id_ch: dataの要素番号とチャンネル番号を対応付けるための配列(id_ch(max_ch)) date: データの先頭の時刻(年月日時分秒)の配列(date(6)) nsample: サンプリング周波数(nsample(max_ch))=欠測のチャンネルに対しては0 ldata: 配列に収録されているデータの長さ(秒) (出力として用いるもの) iflag: 状態を返すフラグ 0: 正常 999: ファイルに書き込めなかった -999: そのほかのエラー by R. Hino 5/31/95 */ int *lunit, *max_sample, *max_ch, *id_ch, *date, *nsample, *ldata, *iflag; short *data; { FILE *file_temp; int i, ifile, isec, jdate[6], ich, fs, l, block_size, *inbuf, *ptr_in; short *ptr_data; unsigned char *outbuf, t_bcd[6], *wtp; unsigned short sys_ch; void set_bcd_time(); ifile = *lunit - 1; if (win_written_sec[ifile]!=0) { *iflag = 999; return; } if ((file_temp=tmpfile())==NULL) { *iflag = -999; return; } for (i=0;i<5;i++) jdate[i] = date[i]; for (isec=0;isec<*ldata;isec++) { for (ich=0,block_size=10;ich<*max_ch;ich++) { if ((fs=nsample[ich])==0) continue; if ((outbuf=(unsigned char *)malloc(sizeof(long)*fs))==NULL) { *iflag = -999; return; } if ((inbuf=(int *)malloc(sizeof(int)*fs))==NULL) { *iflag = -999; return; } for (i=0,ptr_in=inbuf,ptr_data=data+(*max_sample)*ich+fs*isec;i4) return (0); a = 0; if ((*ptr&0x80)==0x80) a = -1; ptr1 = (unsigned char *)&a; for (i=0;i<4;i++,ptr1++) { if (i>=4-nbyte) *(ptr1) = *ptr++; } return a; } /*---------------------------------------------------------------------------------------*/ void set_bcd_time(t,date) unsigned char t[6]; int date[6]; { unsigned char packed_bcd(); unsigned char w; int idate[6]; struct tm tm_date; tm_date.tm_year = date[0]; tm_date.tm_mon = date[1]-1; tm_date.tm_mday = date[2]; tm_date.tm_hour = date[3]; tm_date.tm_min = date[4]; tm_date.tm_sec = date[5]; mktime(&tm_date); idate[0]=tm_date.tm_year; t[0]= packed_bcd((w=idate[0])/10, w%10); idate[1]=tm_date.tm_mon+1; t[1]= packed_bcd((w=idate[1])/10, w%10); idate[2]=tm_date.tm_mday; t[2]= packed_bcd((w=idate[2])/10, w%10); idate[3]=tm_date.tm_hour; t[3]= packed_bcd((w=idate[3])/10, w%10); idate[4]=tm_date.tm_min; t[4]= packed_bcd((w=idate[4])/10, w%10); idate[5]=tm_date.tm_sec; t[5]= packed_bcd((w=idate[5])/10, w%10); } /*---------------------------------------------------------------------------------------*/ unsigned char packed_bcd(d10,d1) unsigned char d10,d1; { if ((d10>9)||(d1>9)) return (unsigned char)0x00; return (unsigned char)((d10<<4)|(d1&0x0f)); } /*---------------------------------------------------------------------------------------*/ int unpacked_bcd(bcd) unsigned char bcd; { int d10, d1, re; d10 = bcd>>4; d1 = bcd&0xf; re = 10*d10 + d1; return re; } /*---------------------------------------------------------------------------------------*/ /* winform.c 4/30/91 urabe */ /* winform converts fixed-sample-size-data into win's format */ /* winform returns the length in bytes of output data */ winform(inbuf,outbuf,sr,sys_ch) long *inbuf; /* input data array for one sec*/ unsigned char *outbuf; /* output data array for one sec */ int sr; /* n of data (i.e. sampling rate) */ unsigned short sys_ch; /* 16 bit long channel ID number */ { int dmin,dmax,aa,bb,br,i,byte_leng; long *ptr; unsigned char *buf,*bf; /* differentiate and obtain min and max */ ptr=inbuf; bb=(*ptr++); dmax=dmin=0; for(i=1;idmax) dmax=br; else if(br>8)&0xff; *buf++=sys_ch&0xff; *buf++=(byte_leng<<4)|(sr>>8); *buf++=sr&0xff; /* first sample is always 4 byte long */ bf=(unsigned char *)inbuf; *buf++=(*bf++); *buf++=(*bf++); *buf++=(*bf++); *buf++=(*bf++); /* second and after */ switch(byte_leng) { case 0: for(i=1;i