/* Generated by XDS Modula-2 to ANSI C v4.20 translator */ #define X2C_int32 #define X2C_index32 #ifndef X2C_H_ #include "X2C.h" #endif #define audioundelay_C_ #ifndef osi_H_ #include "osi.h" #endif #include #ifndef mlib_H_ #include "mlib.h" #endif #ifndef Select_H_ #include "Select.h" #endif #ifndef aprsstr_H_ #include "aprsstr.h" #endif /* try repair audio stream delayed by internet */ /* gcc -Wall -Wno-unused-variable -Wno-parentheses -Wno-pointer-sign -Wno-format -Wno-return-type -Wno-char-subscripts -Wno-uninitialized -Werror=implicit-function-declaration -I. -c -O2 -fdata-sections-ffunction-sections -o audioundelay.o audioundelay.c cc -Wl,--gc-sections -o audioundelay aprsstr.o osic.o osi.o -lm audioundelay.o Select.o -g 0.001 -G 0.1 -d 10000 -i 10000 */ #define audioundelay_MAXBUFSIZE 10000000 #define audioundelay_DEFBUFSIZE 96000 /* maximum delay before throw away samples */ #define audioundelay_JUNKSIZE 128 /* read/write blocksize pitch */ #define audioundelay_WAVESIZE 1024 /* read/write blocksize delete/double wavez */ #define audioundelay_CR "\015" #define audioundelay_LF "\012" #define audioundelay_SAMPSIZE 2 typedef char FILENAME[4096]; union BUF; union BUF { char b0[10000000]; short w[5000000]; }; static union BUF * b; static union BUF * pb; static union BUF * workb; static FILENAME ifn; static FILENAME ofn; static uint32_t txp; static uint32_t rxp; static uint32_t rl; static uint32_t bfill; static uint32_t txw; static uint32_t looptxp; static uint32_t bfree; static uint32_t bufsize; static uint32_t delc; static uint32_t scnt; static int32_t res; static int32_t uo; static int32_t un; static int32_t sampc; static int32_t if0; static int32_t of; static uint32_t frac; static uint32_t sr; static uint32_t fr; static uint32_t cnt; static uint32_t optdelay; static uint32_t startdelay; static uint32_t initdelay; static uint32_t dropped; static uint32_t allbytes; static float fil; static float fili; static float integ; static float gain; static float intmul; static float maxpitchup; static float maxpitchdown; static float rel; static char verb; static char cut; static char usepitch; static char sign; static char lastsign; static char down; static uint32_t pipebytes(int32_t fd) { uint32_t b0; ioctl(fd, 21531L, (char *) &b0); /* FIONREAD */ return b0; } /* end pipebytes() */ static void Error(char text[], uint32_t text_len) { X2C_PCOPY((void **)&text,text_len); osi_Werr(text, text_len); osi_Werr(" error abort\012", 14ul); X2C_ABORT(); X2C_PFREE(text); } /* end Error() */ static void lim(float * x, float max0, float min0) { if (*x>max0) *x = max0; if (*x", 13ul); } bufsize = bufsize*2UL; if (bufsize<128UL) bufsize = 128UL; if (bufsize>10000000UL) bufsize = 10000000UL; } else if (h[1U]=='d') { osi_NextArg(h, 4096ul); if (!aprsstr_StrToCard(h, 4096ul, &optdelay)) { Error("-d ", 13ul); } optdelay = optdelay*2UL; if (optdelay==0UL) optdelay = 1UL; } else if (h[1U]=='i') { osi_NextArg(h, 4096ul); if (!aprsstr_StrToCard(h, 4096ul, &initdelay)) { Error("-i ", 13ul); } initdelay = initdelay*2UL; } else if (h[1U]=='p') { osi_NextArg(h, 4096ul); if (!aprsstr_StrToFix(&maxpitchup, h, 4096ul)) { Error("-p ", 35ul); } osi_NextArg(h, 4096ul); if (!aprsstr_StrToFix(&maxpitchdown, h, 4096ul)) { Error("-p ", 35ul); } lim(&maxpitchup, 0.5f, 0.0f); lim(&maxpitchdown, 0.0f, (-0.5f)); } else if (h[1U]=='L') { osi_NextArg(h, 4096ul); if (!aprsstr_StrToFix(&gain, h, 4096ul)) { Error("-L ", 48ul); } lim(&gain, 1.0f, 0.0f); osi_NextArg(h, 4096ul); if (!aprsstr_StrToFix(&integ, h, 4096ul)) { Error("-L ", 48ul); } osi_NextArg(h, 4096ul); if (!aprsstr_StrToFix(&intmul, h, 4096ul)) { Error("-L ", 48ul); } } else if (h[1U]=='v') verb = 1; else if (h[1U]=='G') { osi_NextArg(h, 4096ul); if (!aprsstr_StrToFix(&integ, h, 4096ul)) { Error("-G ", 19ul); } lim(&integ, 1.0f, 0.0f); } else if (h[1U]=='P') usepitch = 1; else { if (h[1U]=='h') { osi_WrStrLn(" try repair audio stream delayed by internet", 45ul); osi_WrStrLn(" -b maximum stored sound samples \ (96000)", 57ul); osi_WrStrLn(" -d desired delay sampels (2400)", 49ul); osi_WrStrLn(" -L pi\ -regulators config (0.1 <0.01) <30>", 85ul); osi_WrStrLn(" -g pi-regulators loop gain (0.1)\ ", 50ul); osi_WrStrLn(" -h this)", 26ul); osi_WrStrLn(" -i initial delay samples (before\ starts data output) (2400)", 77ul); osi_WrStrLn(" -p pitch to reach desired delay \ (0.05 -0.02)", 62ul); osi_WrStrLn(" -v show state on stderr", 41ul); osi_WrStrLn("", 1ul); X2C_ABORT(); } err = 1; } } else if (fc==0UL) { aprsstr_Assign(ifn, 4096ul, h, 4096ul); ++fc; } else if (fc==1UL) { aprsstr_Assign(ofn, 4096ul, h, 4096ul); ++fc; } else err = 1; if (err) break; } if (err) { osi_Werr(">", 2ul); osi_Werr(h, 4096ul); osi_Werr("< use -h\012", 10ul); X2C_ABORT(); } } /* end Parms() */ static void show(uint32_t bs, uint32_t dropped0, float sr0, uint32_t delc0) { char h[101]; osi_Werr("bufferd:", 9ul); aprsstr_IntToStr((int32_t)bs, 1UL, h, 101ul); osi_Werr(h, 101ul); osi_Werr(" io-rate:", 10ul); aprsstr_FixToStr(sr0, 4UL, h, 101ul); osi_Werr(h, 101ul); if (dropped0>0UL) { osi_Werr(" dropped:", 10ul); aprsstr_IntToStr((int32_t)dropped0, 1UL, h, 101ul); osi_Werr(h, 101ul); } if (delc0>0UL) { osi_Werr(" del:", 6ul); aprsstr_IntToStr((int32_t)delc0, 1UL, h, 101ul); osi_Werr(h, 101ul); } osi_Werr("\012", 2ul); } /* end show() */ static void show1(uint32_t delc0) { char h[101]; if (delc0>0UL) { osi_Werr(" del:", 6ul); aprsstr_IntToStr((int32_t)delc0, 1UL, h, 101ul); osi_Werr(h, 101ul); } osi_Werr("\012", 2ul); } /* end show1() */ static void show2(float f) { char h[101]; osi_Werr(" f:", 4ul); aprsstr_FixToStr(f, 4UL, h, 101ul); osi_Werr(h, 101ul); osi_Werr("\012", 2ul); } /* end show2() */ X2C_STACK_LIMIT(100000l) extern int main(int argc, char **argv) { X2C_BEGIN(&argc,argv,1,4000000l,8000000l); if (sizeof(FILENAME)!=4096) X2C_ASSERT(0); aprsstr_BEGIN(); osi_BEGIN(); ifn[0] = 0; ofn[0] = 0; bufsize = 96000UL; optdelay = 4800UL; fil = 0.0f; fili = 0.0f; integ = 0.01f; gain = 0.1f; intmul = 30.0f; verb = 0; initdelay = 4800UL; maxpitchup = 0.05f; maxpitchdown = (-0.02f); usepitch = 0; Parms(); if (initdelay<256UL) initdelay = 256UL; osic_alloc((char * *) &b, bufsize); if (b==0) Error("out of memory", 14ul); if (usepitch) osic_alloc((char * *) &workb, 512UL); else osic_alloc((char * *) &workb, 4096UL); if (workb==0) Error("out of memory", 14ul); if0 = osi_OpenRead(ifn, 4096ul); if (if0<0L) Error("input file not readable", 24ul); of = osi_OpenWrite(ofn, 4096ul); if (of<0L) Error("output file not writeable", 26ul); frac = 0UL; sr = 65536UL; rxp = 0UL; txp = 0UL; cnt = 0UL; dropped = 0UL; startdelay = initdelay; for (;;) { bfill = ((rxp+bufsize)-txp)%bufsize; /* bytes in fifo */ bfree = bufsize-bfill; /* free bytes in ring buffer */ fdclr(); fdsetr((uint32_t)if0); if (bfill>=startdelay) { /* not send before filled to desired */ fdsetw((uint32_t)of); startdelay = 256UL; } if (selectrw(1UL, 0UL)>=0L) { /* samples readable */ allbytes = bfill+pipebytes(of); /* internal + pipe bytes */ if (issetr((uint32_t)if0)) { rl = bufsize-rxp; if (rl>128UL) rl = 128UL; if (rl>bfree) rl = bfree; if (allbytes>bufsize || rl==0UL) { /* buffer full, read to /dev/null */ res = osi_RdBin(if0, (char *)workb->b0, 10000000u/1u, 128UL); dropped += (uint32_t)res; } else { pb = (union BUF *) &b->b0[rxp]; res = osi_RdBin(if0, (char *)pb, sizeof(union BUF)/1u, rl); if (res<=0L) { osi_Werr("input pipe broken\012", 19ul); break; } rxp = (rxp+(uint32_t)res)%bufsize; } } if (bfill>=256UL && issetw((uint32_t)of)) { /* samples writeable */ txw = 0UL; do { ++scnt; if (usepitch) { frac = (uint32_t)((uint32_t)frac&0xFFFFUL)+sr; fr = frac>>16; while (fr>0UL) { txp = (txp+2UL)%bufsize; uo = un; un = (int32_t)b->w[txp/2UL]; --fr; bfill -= 2UL; } fr = (uint32_t)(int32_t)((uint32_t)frac&0xFFFFUL); workb->w[txw] = (short)(uo*(int32_t)(65536UL-fr) +un*(int32_t)fr>>16); ++txw; } else { un = (int32_t)b->w[txp/2UL]; txp = (txp+2UL)%bufsize; bfill -= 2UL; /* rel:=FLOAT(allbytes)/FLOAT(optdelay) - 1.0; (* buffered samples to desired *) */ rel = (float)(int32_t)(allbytes-optdelay)*0.00005f; /* buffered samples to desired */ lim(&rel, maxpitchup*2.0f, maxpitchdown*2.0f); if (sampc<=0L) { sampc += (int32_t)X2C_TRUNCI((float)fabs(rel)*5.0f, X2C_min_longint,X2C_max_longint); } if ((scnt&32767UL)==0UL) { show2(rel); show1(allbytes); show1(optdelay); } if (sampc>0L) { sign = un<0L; if (!lastsign && sign) { /* rising zero crossing */ if (cut) { if (!down) { txp = looptxp; /* jump back a fullwave */ } /* DEC(sampc, VAL(INTEGER, 1.0/(maxpitchup+0.000001))); */ sampc -= 5000L; cut = 0; /*show1(delc); */ delc = 0UL; } else { down = rel>=0.0f; /* faster or slower */ looptxp = txp; if (down) osi_Werr("-", 2ul); else osi_Werr("+", 2ul); cut = 1; } } lastsign = sign; } if (!cut || !down) { /* else skip a fullwave */ workb->w[txw] = (short)un; ++txw; } else ++delc; } } while (!(bfill<4UL || txw>=128UL)); if (txw>0UL) { osi_WrBin(of, (char *)workb->b0, 10000000u/1u, txw*2UL); } } if ((cnt&15UL)==0UL) { /* cnt:=0; */ fil = X2C_DIVR((float)allbytes,(float)optdelay)-1.0f; /* buffered samples to desired */ fil = fil*gain; /* lim(fil, maxpitchup, maxpitchdown); */ fili = fili+(fil-fili)*integ; /* lim(fili, maxpitchup, maxpitchdown); */ fil = fil+fili*intmul; lim(&fil, maxpitchup, maxpitchdown); fil = fil+1.0f; sr = (uint32_t)(int32_t)X2C_TRUNCI(fil*65536.0f, X2C_min_longint,X2C_max_longint); /* new sampelrate conversion */ if (verb && (cnt&127UL)==0UL) { show(allbytes/2UL, dropped/2UL, fil, delc); dropped = 0UL; } } ++cnt; } } X2C_EXIT(); return 0; } X2C_MAIN_DEFINITION