void sigFunc( short num, void *msg ); /* * IMPLEMENTATION NOTES * * Converting is achieved by interpolating the input samples in * order to evaluate the represented continuous input slope at * sample instances of the new rate (resampling). It is implemented * as a polyphase FIR-filtering process (see reference). The rate * conversion factor is determined by a rational factor. Its * nominator and denominator are integers of almost arbitrary * value, limited only by coefficient memory size. * * General rate conversion formula: * * out(n*Tout) = SUM in(m*Tin) * g((n*d/u-m)*Tin) * Tin * over all m * * FIR-based rate conversion formula for polyphase processing: * * L-1 * out(n*Tout) = SUM in(A(i,n)*Tin) * g(B(i,n)*Tin) * Tin * i=0 * * A(i,n) = i - (L-1)/2 + [n*d/u] * = i - (L-1)/2 + [(n%u)*d/u] + [n/u]*d * B(i,n) = n*d/u - [n*d/u] + (L-1)/2 - i * = ((n%u)*d/u)%1 + (L-1)/2 - i * Tout = Tin * d/u * * where: * n,i running integers * out(t) output signal sampled at t=n*Tout * in(t) input signal sampled in intervalls Tin * u,d up- and downsampling factor, integers * g(t) interpolating function * L FIR-length of realized g(t), integer * / float-division-operator * % float-modulo-operator * [] integer-operator * * note: * (L-1)/2 in A(i,n) can be omitted as pure time shift yielding * a causal design with a delay of ((L-1)/2)*Tin. * n%u is a cyclic modulo-u counter clocked by out-rate * [n/u]*d is a d-increment counter, advanced when n%u resets * B(i,n)*Tin can take on L*u differnt values, at which g(t) * has to be sampled as a coefficient array * * Interpolation function design: * * The interpolation function design is based on a sinc-function * windowed by a gaussian function. The former determines the * cutoff frequency, the latter limits the necessary FIR-length by * pushing the outer skirts of the resulting impulse response below * a certain threshold fast enough. The drawback is a smoothed * cutoff inducing some aliasing. Due to the symmetry of g(t) the * group delay of the filtering process is contant (linear phase). * * g(t) = 2*fgK*sinc(pi*2*fgK*t) * exp(-pi*(2*fgG*t)**2) * * where: * fgK cutoff frequency of sinc function in f-domain * fgG key frequency of gaussian window in f-domain * reflecting the 6.82dB-down point * * note: * Taking fsin=1/Tin as the input sampling frequncy, it turns out * that in conjunction with L, u and d only the ratios fgK/(fsin/2) * and fgG/(fsin/2) specify the whole proces. Requiring fsin, fgK * and fgG as input purposely keeps the notion of absolute * frequencies. * * Numerical design: * * Samples are expected to be 16bit-signed integers, alternating * left and right channel in case of stereo mode- The byte order * per sample is selectable. FIR-filtering is implemented using * 32bit-signed integer arithmetic. Coefficients are scaled to * find the output sample in the high word of accumulated FIR-sum. * * Interpolation can lead to sample magnitudes exceeding the * input maximum. Worst case is a full scale step function on the * input. In this case the sinc-function exhibits an overshoot of * 2*9=18percent (Gibb's phaenomenon). In any case sample overflow * can be avoided by a gain of 0.8. * * If u=d=1 and if the input stream contains only a single sample, * the whole length of the FIR-filter will be written to the output. * In general the resulting output signal will be (L-1)*fsout/fsin * samples longer than the input signal. The effect is that a * finite input sequence is viewed as padded with zeros before the * `beginning' and after the `end'. * * The output lags ((L-1)/2)*Tin behind to implement g(t) as a * causal system corresponding to a causal relationship of the * discrete-time sequences in(m/fsin) and out(n/fsout) with * resepect to a sequence time origin at t=n*Tin=m*Tout=0. * * * REFERENCES * * Crochiere, R. E., Rabiner, L. R.: "Multirate Digital Signal * Processing", Prentice-Hall, Englewood Cliffs, New Jersey, 1983 * * Zwicker, E., Fastl, H.: "Psychoacoustics - Facts and Models", * Springer-Verlag, Berlin, Heidelberg, New-York, Tokyo, 1990 */ #define INCL_DOSPROCESS #define INCL_DOS #include #include #include #include #include #include #include #include #include #include "mmioos2.h" #include "..\..\..\units\common.src\bastypes.h" #include "..\..\..\units\common.src\util.h" #include "..\..\..\units\common.src\cfg_file.h" #include "..\..\..\units\common.src\num2nam.h" #include "..\..\common\source\global.h" #include "..\..\common\source\texte.h" #include "..\..\..\units\common.src\os.h" /* * adaptable defines and globals */ #define M_PI 3.14159265358979323846 #ifndef MAXUP #define MAXUP 0x400 /* MAXUP*MAXLENGTH worst case malloc */ #endif #ifndef MAXLENGTH #define MAXLENGTH 0x400 /* max FIR length */ #endif #define OUTBUFFSIZE MAXLENGTH /* fit >=MAXLENGHT samples */ #define INBUFFSIZE (2*MAXLENGTH) /* fit >=2*MAXLENGTH samples */ #define sqr(a) ((a)*(a)) /* * other globals */ double g_ampli = 0.8; /* default gain, don't change */ int g_outfilehandle = 0, /* */ g_firlen = 0, /* FIR-length */ g_up = 0, /* upsampling factor */ g_down = 0 /* downsampling factor */ ; LONG g_sin[INBUFFSIZE], /* input buffer */ g_sout[OUTBUFFSIZE], /* output buffer */ *g_coep /* coefficient array pointer */ ; double g_fsi =0.0, /* input sampling frequency */ g_fgk =0.0, /* sinc-filter cutoff frequency */ g_fgg =0.0 /* gaussian window key frequency */ ; /* (6.8dB down freq. in f-domain) */ MMAUDIOHEADER mmAudHdr; UCHAR reverse_byte[256]={ 0x00,0x80,0x40,0xC0,0x20,0xA0,0x60,0xE0,0x10,0x90,0x50,0xD0,0x30,0xB0,0x70,0xF0, 0x08,0x88,0x48,0xC8,0x28,0xA8,0x68,0xE8,0x18,0x98,0x58,0xD8,0x38,0xB8,0x78,0xF8, 0x04,0x84,0x44,0xC4,0x24,0xA4,0x64,0xE4,0x14,0x94,0x54,0xD4,0x34,0xB4,0x74,0xF4, 0x0C,0x8C,0x4C,0xCC,0x2C,0xAC,0x6C,0xEC,0x1C,0x9C,0x5C,0xDC,0x3C,0xBC,0x7C,0xFC, 0x02,0x82,0x42,0xC2,0x22,0xA2,0x62,0xE2,0x12,0x92,0x52,0xD2,0x32,0xB2,0x72,0xF2, 0x0A,0x8A,0x4A,0xCA,0x2A,0xAA,0x6A,0xEA,0x1A,0x9A,0x5A,0xDA,0x3A,0xBA,0x7A,0xFA, 0x06,0x86,0x46,0xC6,0x26,0xA6,0x66,0xE6,0x16,0x96,0x56,0xD6,0x36,0xB6,0x76,0xF6, 0x0E,0x8E,0x4E,0xCE,0x2E,0xAE,0x6E,0xEE,0x1E,0x9E,0x5E,0xDE,0x3E,0xBE,0x7E,0xFE, 0x01,0x81,0x41,0xC1,0x21,0xA1,0x61,0xE1,0x11,0x91,0x51,0xD1,0x31,0xB1,0x71,0xF1, 0x09,0x89,0x49,0xC9,0x29,0xA9,0x69,0xE9,0x19,0x99,0x59,0xD9,0x39,0xB9,0x79,0xF9, 0x05,0x85,0x45,0xC5,0x25,0xA5,0x65,0xE5,0x15,0x95,0x55,0xD5,0x35,0xB5,0x75,0xF5, 0x0D,0x8D,0x4D,0xCD,0x2D,0xAD,0x6D,0xED,0x1D,0x9D,0x5D,0xDD,0x3D,0xBD,0x7D,0xFD, 0x03,0x83,0x43,0xC3,0x23,0xA3,0x63,0xE3,0x13,0x93,0x53,0xD3,0x33,0xB3,0x73,0xF3, 0x0B,0x8B,0x4B,0xCB,0x2B,0xAB,0x6B,0xEB,0x1B,0x9B,0x5B,0xDB,0x3B,0xBB,0x7B,0xFB, 0x07,0x87,0x47,0xC7,0x27,0xA7,0x67,0xE7,0x17,0x97,0x57,0xD7,0x37,0xB7,0x77,0xF7, 0x0F,0x8F,0x4F,0xCF,0x2F,0xAF,0x6F,0xEF,0x1F,0x9F,0x5F,0xDF,0x3F,0xBF,0x7F,0xFF }; /* * linear2alaw() - Convert a 16-bit linear alw value to 8-bit A-law * * linear2alaw() accepts an 16-bit integer and encodes it as A-law data. * * Linear Input Code Compressed Code * ------------------------ --------------- * 0000000wxyza 000wxyz * 0000001wxyza 001wxyz * 000001wxyzab 010wxyz * 00001wxyzabc 011wxyz * 0001wxyzabcd 100wxyz * 001wxyzabcde 101wxyz * 01wxyzabcdef 110wxyz * 1wxyzabcdefg 111wxyz * */ UCHAR linear2alaw(long alw_val) /* 2's complement (16-bit range) */ { long mask = 0; long seg = 0; unsigned char aval = 0; static short seg_end[8] = {0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF}; if (alw_val >= 0) { mask = 0xD5; /* sign (7th) bit = 1 */ } else { mask = 0x55; /* sign bit = 0 */ alw_val = -alw_val; } if(alw_val<0x7ff8) alw_val+=8; if(alw_val<0x10) mask = 0xD5; /* Convert the scaled magnitude to segment number. */ for (seg = 0; seg < 8; seg++) { if (alw_val <= seg_end[seg]) break; } /* Combine the sign, segment, and quantization bits. */ if (seg >= 8) /* out of range, return maximum value. */ return (0x7F ^ mask); else { aval = seg << 4; if (seg < 2) aval |= (alw_val >> 4) & 0xf; else aval |= (alw_val >> (seg + 3)) & 0xf; return (aval ^ mask); } } /* * evaluate sinc(x) = sin(x)/x safely */ double sinc(double x) { return(fabs(x) < 1E-50 ? 1. : sin(fmod(x,2*M_PI))/x); } /* * evaluate interpolation function g(t) at t * integral of g(t) over all times is expected to be one */ double interpol_func(double t, double fgk, double fgg) { return (2*fgk*sinc(M_PI*2*fgk*t)*exp(-M_PI*sqr(2*fgg*t))); } /* * evaluate coefficient from i, q=n%u by sampling interpolation function * and scale it for integer multiplication used by FIR-filtering */ LONG coefficient(long i, long q, long firlen, double fgk, double fgg, double fsi, long up, long down, double amp) { return( (int)(0x10000 * amp * interpol_func( (fmod(q*down/(double)up,1.) + (firlen-1)/2 - i) / fsi, fgk, fgg ) / fsi ) ); } /* * transfer n LONGs from s to d */ void transfer_int(LONG *s, LONG *d, long n) { LONG *e; if (n < 1) return; e = d + n; while (d != e) *d++ = *s++; } /* * zerofill n LONGs from s */ void zerofill(LONG *s, long n) { LONG *e; if (n < 1) return; e = s + n; while (s != e) *s++ = 0; } /* * convert buffer of n samples to LONGs */ void bsample_to_int(void *buff, long n) { UCHAR *s; LONG *d; if (n < 1) return; s = (UCHAR*)buff + n; d = (LONG*)buff + n; while (s != buff) { *--d = ((LONG)(*--s)-128L)<<8; } } /* * convert buffer of n samples to LONGs */ void bsample2_to_int(void *buff, long n) { UCHAR *s; LONG *d; if (n < 1) return; s = (UCHAR*)buff + n*2; d = (LONG*)buff + n; while (s != buff) { *--d = (((LONG)(*--s)-128L)<<7)+(((LONG)(*--s)-128L)<<7); } } /* * convert buffer of n samples to LONGs */ void sample_to_int(void *buff, long n) { short *s; LONG *d; if (n < 1) return; s = (short*)buff + n; d = (LONG*)buff + n; while (s != buff) { *--d = (LONG)(*--s); } } /* * convert buffer of n samples to LONGs */ void sample2_to_int(void *buff, long n) { short *s; LONG *d; if (n < 1) return; s = (short*)buff + n*2; d = (LONG*)buff + n; while (s != buff) { *--d = ((LONG)(*--s)+(LONG)(*--s))>>1; } } /* * convert buffer of n LONGs to samples */ void int_to_sample(short *buff, long n) { short *s, *e; UCHAR *d; if (n < 1) return; s = buff; d = (UCHAR*)buff; e = buff + n*2; while (s != e) { s++; *d++ = reverse_byte[linear2alaw(*s++)]; } } /* * convert buffer of n LONGs to samples */ void intlo_to_sample(short *buff, long n) { short *s, *e; UCHAR *d; if (n < 1) return; s = buff; d = (UCHAR*)buff; e = buff + n*2; while (s != e) { *d++ = reverse_byte[linear2alaw(*s++)]; s++; } } /* * FIR-routines, * this is where we need all the MIPS */ void fir(register LONG *inp, register LONG *coep, long firlen, LONG *outp) { register LONG akku = 0, *endp; long n1 = (firlen / 8) * 8, n0 = firlen % 8; endp = coep + n1; while (coep != endp) { akku += *inp++ * *coep++; akku += *inp++ * *coep++; akku += *inp++ * *coep++; akku += *inp++ * *coep++; akku += *inp++ * *coep++; akku += *inp++ * *coep++; akku += *inp++ * *coep++; akku += *inp++ * *coep++; } endp = coep + n0; while (coep != endp) { akku += *inp++ * *coep++; } *outp = akku; } /* * filtering from input buffer to output buffer; * returns number of processed samples in output buffer: * if it is not equal to output buffer size, * the input buffer is expected to be refilled upon entry, so that * the last firlen numbers of the old input buffer are * the first firlen numbers of the new input buffer; * if it is equal to output buffer size, the output buffer * is full and is expected to be stowed away; * */ long filtering_on_buffers(LONG *inp, long insize, LONG *outp, long outsize, LONG *coep, long firlen, long up, long down) { static long inbaseidx = 0, inoffset = 0, cycctr = 0, outidx = 0; for (;;) { inoffset = (cycctr * down)/up; if ((inbaseidx + inoffset + firlen) > insize) { inbaseidx -= insize - firlen + 1; return(outidx); } fir(inp + inoffset + inbaseidx, coep + cycctr * firlen, firlen, outp + outidx++); cycctr++; if (!(cycctr %= up)) inbaseidx += down; if (!(outidx %= outsize)) return(outsize); } } /* * read and convert input sample format to integer */ long intread(HMMIO hmmioSrc, void *buff, long n, long Bits, long Channels) { long rd = 0; if(Channels==2) { if(Bits==8) { if ((rd = mmioRead (hmmioSrc, buff, n*2)) <= 0) return(rd); bsample2_to_int(buff,n); return(rd/2); } else { if ((rd = mmioRead (hmmioSrc, buff, n*sizeof(short)*2)) <= 0) return(rd); sample2_to_int(buff,n); return(rd/sizeof(short)/2); } } else { if(Bits==8) { if ((rd = mmioRead (hmmioSrc, buff, n)) <= 0) return(rd); bsample_to_int(buff,n); return(rd); } else { if ((rd = mmioRead (hmmioSrc, buff, n*sizeof(short))) <= 0) return(rd); sample_to_int(buff,n); return(rd/sizeof(short)); } } } /* * do some conversion jobs and write */ long intwrite(long hd, LONG *buff, long n) { long written = 0; int_to_sample((short*)buff, n); if ((written = write(g_outfilehandle, buff, n)) <= 0) return(written); return(written); } /* * do some conversion jobs and write */ long intlowrite(long hd, LONG *buff, long n) { long written = 0; intlo_to_sample((short*)buff, n); if ((written = write(g_outfilehandle, buff, n)) <= 0) return(written); return(written); } /* * set up coefficient array */ void make_coe(void) { long i = 0, q =0; for (i = 0; i < g_firlen; i++) { for (q = 0; q < g_up; q++) { g_coep[q * g_firlen + i] = coefficient(i, q, g_firlen, g_fgk, g_fgg, g_fsi, g_up, g_down, g_ampli); } } } void comp_para(void) { long u = 0,d=0; double fin1=0.0,fdiff=0.0; fdiff=HUGE_VAL; for(u=1;u<=1024;u++) { d=(g_fsi*u)/8000.; fin1=(8000.*d)/u; if(fdiff>fabs(g_fsi-fin1)) { fdiff=fabs(g_fsi-fin1); g_up=u; g_down=d; } d++; fin1=(8000.*d)/u; if(fdiff>fabs(g_fsi-fin1)) { fdiff=fabs(g_fsi-fin1); g_up=u; g_down=d; } if(fdiff==0.) break; } if (g_up >= g_down) { /* upsampling */ g_fgg = g_fsi * 0.0116; g_fgk = g_fsi * 0.461; g_firlen = 162; } else { /* downsampling */ g_fgg = (g_up * g_fsi * 0.0116)/g_down; g_fgk = (g_up * g_fsi * 0.461)/g_down; g_firlen = (162 * g_down)/g_up; } } /* * main */ short wav2alw(char *InName) { long insize = 0, outsize = 0, skirtlen=0; MMIOINFO mmioinfoSource; unsigned long ulAudioHeaderLength=0; HMMIO hmmioSource; unsigned long ulBytesRead=0; LONG rc=0; char OutName[300]; char *help; char helpstr[300]; memset (g_sin ,0,sizeof(LONG)*INBUFFSIZE); memset (g_sout,0,sizeof(LONG)*OUTBUFFSIZE); if (InName[0] == '*') return (-200); if (!util_file_exist(InName)) { sprintf (helpstr,STR_NOT_FOUND,InName); sigFunc (1,helpstr); return (-100); } if (!strstr(InName,".wav")) return (-101); strcpy (OutName,InName); help = strstr(OutName,".wav"); *(++help) = 'a'; *(++help) = 'l'; *(++help) = 'w'; strcpy (OutName,util_strip_path(OutName)); if (util_file_exist(OutName)) { if (util_file_age(InName) <= util_file_age(OutName)) return (-102); } /*******************************/ /* Set up/open the SOURCE file */ /*******************************/ memset (&mmioinfoSource, 0L, sizeof (MMIOINFO)); mmioinfoSource.ulTranslate = MMIO_TRANSLATEHEADER | MMIO_TRANSLATEDATA; hmmioSource = mmioOpen (InName, &mmioinfoSource, MMIO_READ | MMIO_DENYWRITE); if (!hmmioSource) { // perror(InName); return (2); } /****************************/ /* Obtain the SOURCE HEADER */ /****************************/ mmioQueryHeaderLength (hmmioSource, (PLONG)&ulAudioHeaderLength, 0L, 0L); if (ulAudioHeaderLength != sizeof (MMAUDIOHEADER)) { /* We have a problem.....possibly incompatible versions */ mmioClose (hmmioSource, 0L); // perror(InName); return (4); } rc = (LONG)mmioGetHeader (hmmioSource, &mmAudHdr, (LONG)sizeof (MMAUDIOHEADER), (PLONG)&ulBytesRead, 0L, 0L); if (rc != MMIO_SUCCESS) { /* Header unavailable */ mmioClose (hmmioSource, 0L); // perror(InName); return (4); } // printf("\nType of wave format: %d",mmAudHdr.mmXWAVHeader.WAVEHeader.usFormatTag); // printf("\nNumber of channels: %d",mmAudHdr.mmXWAVHeader.WAVEHeader.usChannels); // printf("\nSampling rate: %ld",mmAudHdr.mmXWAVHeader.WAVEHeader.ulSamplesPerSec); // printf("\nAvg bytes per sec: %ld",mmAudHdr.mmXWAVHeader.WAVEHeader.ulAvgBytesPerSec); // printf("\nBlock Alignment in bytes: %d",mmAudHdr.mmXWAVHeader.WAVEHeader.usBlockAlign); // printf("\nBits per sample: %d",mmAudHdr.mmXWAVHeader.WAVEHeader.usBitsPerSample); g_outfilehandle=open(OutName,O_CREAT|O_BINARY|O_TRUNC|O_RDWR,S_IWRITE|S_IREAD); if (g_outfilehandle==-1) { // perror(OutName); mmioClose (hmmioSource, 0L); return(-1); } if(mmAudHdr.mmXWAVHeader.WAVEHeader.ulSamplesPerSec < 7984 || mmAudHdr.mmXWAVHeader.WAVEHeader.ulSamplesPerSec > 8016) { g_fsi=mmAudHdr.mmXWAVHeader.WAVEHeader.ulSamplesPerSec; comp_para(); if ((g_coep = (LONG*)malloc(g_firlen * g_up * sizeof(int))) == NULL) { // fprintf(stderr, "cannot allocate coefficient memory\n"); return (-2); } make_coe(); skirtlen = g_firlen - 1; zerofill(g_sin, skirtlen); do { insize = intread(hmmioSource, g_sin + skirtlen, INBUFFSIZE - skirtlen, mmAudHdr.mmXWAVHeader.WAVEHeader.usBitsPerSample, mmAudHdr.mmXWAVHeader.WAVEHeader.usChannels); if (insize < 0 || insize > INBUFFSIZE - skirtlen) { // perror(InName); close(g_outfilehandle); free(g_coep); return (-3); } for (;;) { outsize = filtering_on_buffers(g_sin, skirtlen + insize, g_sout, OUTBUFFSIZE, g_coep, g_firlen, g_up, g_down); if (outsize != OUTBUFFSIZE) { transfer_int(g_sin + insize, g_sin, skirtlen); break; } if (intwrite(g_outfilehandle, g_sout, outsize) != outsize) { // perror(OutName); free(g_coep); return (-4); } }; } while (insize > 0); zerofill(g_sin + skirtlen, skirtlen); do { outsize = filtering_on_buffers(g_sin, skirtlen + skirtlen, g_sout, OUTBUFFSIZE, g_coep, g_firlen, g_up, g_down); if (intwrite(g_outfilehandle, g_sout, outsize) != outsize) { // perror(OutName); free(g_coep); return (-5); } } while (outsize == OUTBUFFSIZE); free(g_coep); } else { /* Input is 8000Sample/s no rate conversion */ do { insize = intread(hmmioSource, g_sin, INBUFFSIZE, mmAudHdr.mmXWAVHeader.WAVEHeader.usBitsPerSample, mmAudHdr.mmXWAVHeader.WAVEHeader.usChannels); if (insize < 0 || insize > INBUFFSIZE) { // perror(InName); close(g_outfilehandle); return (-6); } if (intlowrite(g_outfilehandle, g_sin, insize) != insize) { // perror(OutName); return (-7); } } while (insize > 0); } if (close(g_outfilehandle)) { // perror(OutName); return (-8); } mmioClose (hmmioSource, 0L); return 0; } /*******************************************************************/ short runflag = 0; void convert_all_lookup (char *filename) { FILE *namedat; char str [300]; char help[300]; char *strptr; namedat = fopen (filename,"r"); if (namedat) { while (fgets(str,200,namedat)) { if((str[0] != '#') && (strchr(str,'|'))) { strptr = &str[0]; strptr = strchr(strptr,'|'); strptr++; strptr = strchr(strptr,'|'); strptr++; *strchr(strptr,'|') = 0; strcpy (help,check_time(strptr)); wav2alw (help); } } fclose (namedat); } } void wav2alw_all (void) { char help[200]; convert_all_lookup (NAMFILE); convert_all_lookup (PRTFILE); config_file_read_string(STD_CFG_FILE,WELCOME_WAVE ,help,WELCOME_WAVE_DEF); strcpy (help,check_time(help)); wav2alw (help); config_file_read_string(STD_CFG_FILE,RINGRING_WAVE,help,RINGRING_WAVE_DEF); strcpy (help,check_time(help)); wav2alw (help); } void _Optlink convert_all (void *arglist) { while (runflag) OsSleep (250); runflag++; sigFunc( 7, &runflag); wav2alw_all(); runflag--; sigFunc( 7, &runflag); }; void _Optlink convert (void *filename) { while (runflag) OsSleep (250); runflag++; sigFunc( 7, &runflag); wav2alw (filename); runflag--; sigFunc( 7, &runflag); }; void wav2alw_convert_all (void) { _beginthread (convert_all, NULL, os2_stack_of_thread, NULL); //convert_all(NULL); }; void wav2alw_convert (char * filename) { _beginthread (convert, NULL, os2_stack_of_thread, (void *)filename); //convert(filename); }; short wav2alw_convert_runs (void) { return (runflag); };