home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / sound / nh10src / nohiss.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-15  |  36.6 KB  |  1,118 lines

  1. //┌───────────────────────────────────────────────────────────────────────┐
  2. //│ NOHISS: Digital Noise Reduction v1.0    (C) Copyright 1991 Andy Hakim │
  3. //├───────────────────────────────────────────────────────────────────────┤
  4. //│                                                                       │
  5. //│    Internet E-Mail: andyh@menudo.uh.edu (starting May 1992)           │
  6. //│                     st144@menudo.uh.edu                               │
  7. //│                     st144@simpsons.cc.uh.edu (NeXT voice mail)        │
  8. //│                     cosc12r2@jetson.uh.edu                            │
  9. //│                                                                       │
  10. //│               Mail: NOHISS Development                                │
  11. //│                     P.O. Box 70392                                    │
  12. //│                     Houston, TX 77270-0392                            │
  13. //│                                                                       │
  14. //│              Phone: (713) 880-3059                                    │
  15. //│                                                                       │
  16. //│                BBS: Sands PC Board (713)-961-1604                     │
  17. //│                                                                       │
  18. //│  Compilation Specs:  Borland C++ v2.0 (small model)                   │
  19. //│                      BCC -ms sbcs.lib nohiss.c                        │
  20. //├───────────────────────────────────────────────────────────────────────┤
  21. //│I am making the Nohiss source code available to the public to          │
  22. //│facilitate non-commercial programming for Soundblaster compatible      │
  23. //│cards.  Please observe the following conditions:                       │
  24. //│                                                                       │
  25. //│*  If you borrow extensively from it, "do the right thing" and give    │
  26. //│   credit where it is due.                                             │
  27. //│                                                                       │
  28. //│*  If you want to use it for commercial purposes, contact me.          │
  29. //└───────────────────────────────────────────────────────────────────────┘
  30.  
  31. #if !defined(__MSDOS__)
  32. #error OS is not MS-DOS
  33. #endif
  34.  
  35. //┌───────────────────────────────────────────────────────────────────────┐//
  36. //│ INCLUDES                                                              │//
  37. //└───────────────────────────────────────────────────────────────────────┘//
  38. #include <dir.h>
  39. #include <stdio.h>
  40. #include <stdlib.h>
  41. #include <time.h>
  42. #include <conio.h>
  43. #include <dos.h>
  44. #include <bios.h>
  45. #include <fcntl.h>
  46. #include <io.h>
  47. #include <sbc.h>
  48. #include <sbcvoice.h>
  49. #include "nohiss.fnt"           // New fonts
  50. #include "vga.fnt"              // old fonts
  51.  
  52. //┌───────────────────────────────────────────────────────────────────────┐//
  53. //│ DEFINES/ENUMS                                                         │//
  54. //└───────────────────────────────────────────────────────────────────────┘//
  55. #define DEFAULT_OFFSET 0xAA8A
  56.  
  57. enum { OFF, ON };
  58. enum { NO, YES };
  59. enum { SOU, VOC, S32, SND };
  60. enum { FALSE, TRUE };
  61. enum { BIOS, MDA, CGA, EGA, VGA };
  62.  
  63. //┌───────────────────────────────────────────────────────────────────────┐//
  64. //│ GLOBAL VARIABLES                                                      │//
  65. //└───────────────────────────────────────────────────────────────────────┘//
  66. typedef struct
  67. {
  68.    char nr_factor;
  69.    unsigned minimum;
  70.    unsigned maximum;
  71.    unsigned duration;
  72.    long length;
  73.    char fancy;
  74.    char process;
  75.    char playfile;
  76.    char overwrite;
  77.    unsigned sbport;
  78.    char endpause;
  79. } DEFAULTS;
  80. //.........................................................................
  81. DEFAULTS D =       {100, 118, 138, 3600, 200, YES, YES, 3, NO, 0x220, YES};
  82. DEFAULTS FACTORY = {100, 118, 138, 3600, 200, YES, YES, 3, NO, 0x220, YES};
  83. //.........................................................................
  84. long filesize;
  85. long changes;
  86. char input_file[64]="",
  87.      output_file[64]="",
  88.      ftype;
  89. unsigned char chunk[0x8000];
  90. unsigned char savescreen[7*80*2]={255};
  91. char buffer[81];
  92. //.........................................................................
  93. unsigned
  94.    VIDBASE=0xB800;
  95.  
  96. char bclr = 7,
  97.      hbclr = 15,
  98.      sbclr = 7,
  99.      ybclr = 14,
  100.      bbclr = 128,
  101.      VCARD = NO,
  102.      SPINYPOS = 3,
  103.      ABORT = NO;
  104.  
  105.  
  106. //┌───────────────────────────────────────────────────────────────────────┐//
  107. //│ PROTOTYPES                                                            │//
  108. //└───────────────────────────────────────────────────────────────────────┘//
  109. long fsize(char *filename);
  110. long voc_frequency(char *filename);
  111.  
  112.  
  113. //┌───────────────────────────────────────────────────────────────────────┐
  114. //│ QTOOLS.H: detects video card (similar to BC detect_graph)             │
  115. //└───────────────────────────────────────────────────────────────────────┘
  116. detect_gr_card()
  117. {
  118.   char card;
  119.   card = CGA;                             // default card type
  120.   _AX = 0x0F00;
  121.   asm int 0x10;
  122.   if (_AL == 7) return MDA;               // checks mono mode
  123.   _AX = 0x1200;
  124.   _BX = 0xFF10;
  125.   asm int 0x10;
  126.   if (_BH != 0xFF) card = EGA;            // check for a function that
  127.   _AX = 0x1A00;                           // only EGA+ can do
  128.   asm int 0x10;
  129.   if (_AL == 0x1A) card = VGA;            // check for a function that
  130.   return card;                            // only VGA+ can do
  131. }
  132.  
  133.  
  134.  
  135.  
  136. //┌───────────────────────────────────────────────────────────────────────┐//
  137. //│ QTOOLS.H: EGA/VGA blinking attribute changer                          │
  138. //└───────────────────────────────────────────────────────────────────────┘//
  139. qblink (char on_off)
  140. {
  141.   if (VCARD < EGA) return;
  142.   asm mov ax, 0x1003;
  143.   asm mov bl, on_off;
  144.   asm int 0x10;
  145.   return;
  146. }
  147.  
  148.  
  149.  
  150. //┌───────────────────────────────────────────────────────────────────────┐
  151. //│ QTOOLS.H: Initializes Qvideo system                                   │
  152. //└───────────────────────────────────────────────────────────────────────┘
  153. init_video()
  154. {
  155.   VCARD = detect_gr_card();
  156.   if (VCARD == MDA) VIDBASE=0xB000;
  157.   else VIDBASE=0xB800;
  158.   if (VCARD == MDA || VCARD == CGA)
  159.   {
  160.     bclr = 7;
  161.     hbclr = 15;
  162.     sbclr = 7;
  163.     ybclr = 14;
  164.     bbclr = 128;
  165.    }
  166.   else
  167.   {
  168.    bclr = 128+7;
  169.    hbclr = 128+15;
  170.    sbclr = 128;
  171.    ybclr = 128+14;
  172.    bbclr = 128+1;
  173.   }
  174.   return;
  175. }
  176.  
  177.  
  178.  
  179. //┌───────────────────────────────────────────────────────────────────────┐
  180. //│ QTOOLS.H: Set screen font                                             │
  181. //└───────────────────────────────────────────────────────────────────────┘
  182. setfont(char *font, unsigned size)
  183. {
  184.    if (VCARD < EGA) return;
  185.    _CX=size/16;
  186.    _ES = FP_SEG(font);
  187.    _BP = FP_OFF(font);
  188.    _BH=16;
  189.    _BL=0;
  190.    _DX=128;
  191.    _AX=0x1100;
  192.    asm int 0x10;
  193.    return;
  194. }
  195.  
  196. //┌───────────────────────────────────────────────────────────────────────┐//
  197. //│                                                                       │//
  198. //└───────────────────────────────────────────────────────────────────────┘//
  199. close_video()
  200. {
  201.    if (VCARD < EGA) return;
  202.    if (*savescreen != 255)
  203.       movedata (_DS, FP_OFF(savescreen), (unsigned)VIDBASE, 0, (7*80*2));
  204.    setfont(vgafont, sizeof(vgafont));
  205.    _setcursortype (_NORMALCURSOR);
  206.    qblink(1);
  207.    return;
  208. }
  209.  
  210.  
  211.  
  212. //┌───────────────────────────────────────────────────────────────────────┐//
  213. //│ QTOOLS.H: Quickprint direct screen writing routine                    │//
  214. //└───────────────────────────────────────────────────────────────────────┘//
  215. qprintf (char *txt, char x, char y, unsigned int color)
  216. {
  217.   unsigned int far *screen;
  218. //.........................................................................
  219.   x--; y--;
  220.   if (strlen(txt)>80) *(txt+79) = 0;
  221.   color <<= 8;
  222.   screen = MK_FP(VIDBASE, y*160+x*2);
  223.   while (*txt)
  224.   {
  225.    *screen = color + (unsigned char)*txt;
  226.    screen++;
  227.    txt++;
  228.   }
  229.   return;
  230. }
  231.  
  232.  
  233.  
  234. //┌───────────────────────────────────────────────────────────────────────┐//
  235. //│ SPINNER: 1 = square   2 = circle  3 = bios star  4 = erase            │//
  236. //└───────────────────────────────────────────────────────────────────────┘//
  237. spinner(char type, char x, char y, char color)
  238. {
  239.   static char index;
  240.   static clock_t start;
  241. //.........................................................................
  242.   if (VCARD < EGA) return;
  243.   if ((clock()-start) / CLK_TCK > 0.03)
  244.   {
  245.   start = clock();
  246.   index++;
  247.   }
  248. else return;
  249.   if (VCARD == MDA || VCARD == CGA) type = 3;
  250.   if (type==1)
  251.   {
  252.      if (index == 1) qprintf ("äÇ", x, y, color); else
  253.      if (index == 2) qprintf ("àü", x, y, color); else
  254.      if (index == 3) qprintf ("åé", x, y, color); else
  255.      if (index == 4) qprintf ("çâ", x, y, color);
  256.      if (index >= 4) index=0;
  257.   }
  258. else
  259.   if (type==2)
  260.   {
  261.      if (index == 5) qprintf ("£¥", x, y, color); else
  262.      if (index == 10) qprintf ("₧ƒ", x, y, color);
  263.      if (index >= 10) index=0;
  264.   }
  265. else
  266.   if (type==3)
  267.   {
  268.      if (index == 1) qprintf ("-", x, y, color); else
  269.      if (index == 2) qprintf ("\\", x, y, color); else
  270.      if (index == 3) qprintf ("|", x, y, color); else
  271.      if (index == 4) qprintf ("/", x, y, color);
  272.      if (index >= 4) index=0;
  273.    }
  274.   if (type==4)
  275.    {
  276.      qprintf ("  ", x, y, color);
  277.      index = 0;
  278.    }
  279.    return;
  280. }
  281.  
  282.  
  283. //┌───────────────────────────────────────────────────────────────────────┐//
  284. //│ Displays the background stuff on the screen                           │//
  285. //└───────────────────────────────────────────────────────────────────────┘//
  286. screen_prep()
  287. {
  288.   char drive[MAXDRIVE];
  289.   char dir[MAXDIR];
  290.   char file[MAXFILE];
  291.   char ext[MAXEXT];
  292.   char i;
  293. //.........................................................................
  294.   textcolor (7);
  295.   textbackground (0);
  296.   if (VCARD < EGA) return;
  297.  
  298.   qblink (0);
  299.   _setcursortype (_NOCURSOR);
  300.  
  301.   movedata ((unsigned)VIDBASE, 0, _DS, FP_OFF(savescreen), (7*80*2));
  302.  
  303.   setfont(newfont, sizeof(newfont));
  304.  
  305.   qprintf (" áí Digital Noise Reduction v1.0                  ", 1, 1, 112);
  306.   qprintf ("êìë ìùÿ¢ÖôæÆÜ èïïè îûÉ¢ ÄÅöôò ", 51, 1, 120);
  307.  
  308.   memset (buffer, 32, 80);
  309.   *(buffer+80)=0;
  310.   for (i=2; i<=6; i++) qprintf (buffer, 1, i, 128);
  311.  
  312.   memset (buffer, 223, 80);
  313.   qprintf (buffer, 1, 7, 7);
  314.   show_keys();
  315.  
  316.   qprintf ("Input file:", 5, 3, 135);
  317.   qprintf ("Output file:", 5, 4, 135);
  318.   qprintf ("Processing:", 39, 3, 135);
  319.   qprintf ("▐", 50, 3, 142);
  320.   qprintf ("                            ", 51, 3, 224);
  321.  
  322.   strlwr (input_file);
  323.   fnsplit(input_file, drive, dir, file, ext);
  324.   strcpy (buffer, file);
  325.   strcat (buffer, ext);
  326.   qprintf (buffer, 17, 3, 135);
  327.  
  328.   strlwr (output_file);
  329.   fnsplit(output_file, drive, dir, file, ext);
  330.   strcpy (buffer, file);
  331.   strcat (buffer, ext);
  332.   qprintf (buffer, 18, 4, 135);
  333.  
  334.   return;
  335. }
  336.  
  337.  
  338. show_header()
  339. {
  340.   printf ("\nDigital Noise Reduction v1.0                     (C) Copyright 1991 Andy Hakim\n");
  341.   printf ("──────────────────────────────────────────────────────────────────────────────\n");
  342.   return;
  343. }
  344. //┌───────────────────────────────────────────────────────────────────────┐
  345. //│ Displays error messege                                                │
  346. //└───────────────────────────────────────────────────────────────────────┘
  347. show_error(char errnum, char *info)
  348. {
  349.    char errmsg[][60] =
  350.    {
  351.        "1: Invalid command line option",
  352.        "2: Input file not found",
  353.        "3: VOC file compressed",
  354.        "4: VOC file corrupt/unsupported format",
  355.        "5: File read error",
  356.        "6: File write error/Disk full?",
  357.        "7: Output file same as input file",
  358.        "8: Option value out of bounds",
  359.        "9: Cannot access program file",
  360.       "10: Soundblaster playback error",
  361.       "11: Soundblaster interrupt error",
  362.       "12: Soundblaster not installed or wrong IO port",
  363.       "13: (User abort)",
  364.       "14: Unauthorized modification of program file"
  365.    };
  366. //.........................................................................
  367.    fcloseall();
  368.    if (VCARD < EGA) printf ("\n");
  369.    remove (output_file);
  370.    close_video();
  371.    if (errnum == 13) exit(13);
  372.    printf ("Error #");
  373.    if (*info) printf ("%s: %s\n\n", errmsg[--errnum], info);
  374. else
  375.    printf ("%s\n\n", errmsg[--errnum]);
  376.    printf ("Type NOHISS /? or see NOHISS.DOC for more information\n");
  377.    exit(++errnum);
  378.    return;
  379. }
  380.  
  381.  
  382.  
  383. //┌───────────────────────────────────────────────────────────────────────┐
  384. //│ Converts integer to time                                              │
  385. //└───────────────────────────────────────────────────────────────────────┘
  386. int2time(unsigned x, char *txt)
  387. {
  388.    char tmp[5];
  389.    sprintf (tmp, "%02d:", x / 3600);
  390.    strcpy (txt, tmp);
  391.    sprintf (tmp, "%02d:", (x % 3600) / 60);
  392.    strcat (txt, tmp);
  393.    sprintf (tmp, "%02d", (x % 3600) % 60);
  394.    strcat (txt, tmp);
  395.    return;
  396. }
  397.  
  398.  
  399.  
  400.  
  401. //┌───────────────────────────────────────────────────────────────────────┐//
  402. //│ SB Disk Play                                                          │//
  403. //└───────────────────────────────────────────────────────────────────────┘//
  404. sb_disk_play (char *filename)
  405. {
  406.    ct_io_addx = D.sbport;
  407.    if (sbc_check_card() & 4)
  408.    {
  409.     if (sbc_scan_int())
  410.     {
  411.       if (!ctvd_init(16))
  412.       {
  413.          play_file (filename);
  414.          ctvd_terminate () ;
  415.       }
  416.  else show_error (10, "");             // sb driver
  417.     }
  418. else show_error (11, "");              // interrupt
  419.   }
  420. else show_error (12, "");              // no sb present
  421.     if (ABORT) show_error (13, "");    // user pressed ESC
  422.     return;
  423. }
  424.  
  425.  
  426. //┌───────────────────────────────────────────────────────────────────────┐//
  427. //│                                                                       │//
  428. //└───────────────────────────────────────────────────────────────────────┘//
  429. play_file (char *filename)
  430. {
  431.    int handle ;
  432.    if (VCARD >= EGA)
  433.    {
  434.       sprintf (buffer, "%ld Hertz      ", voc_frequency(filename));
  435.       qprintf ("Frequency: ", 5, 5, 135);
  436.       qprintf (buffer, 16, 5, 135);
  437.    }
  438.    handle = open(filename, O_RDONLY);
  439.    ctvd_speaker (1);
  440.    if (ctvd_output(handle) == NO_ERROR)
  441.    {
  442.       play_voice_in_bkgnd(handle);
  443.       if (ctvd_drv_error()) show_error (10, "");
  444.    }
  445.    close (handle);
  446.    return;
  447. }
  448.  
  449.  
  450.  
  451. //┌───────────────────────────────────────────────────────────────────────┐//
  452. //│                                                                       │//
  453. //└───────────────────────────────────────────────────────────────────────┘//
  454. show_keys()
  455. {
  456.   qprintf ("  ESC ", 0+20, 7, 113);
  457.   qprintf ("exit ", 6+20, 7, 112);
  458.   qprintf (" ENTER ", 11+20, 7, 113);
  459.   qprintf ("skip ", 18+20, 7, 112);
  460.   qprintf (" SPACE ", 23+20, 7, 113);
  461.   qprintf ("pause  ", 30+20, 7, 112);
  462.   return;
  463. }
  464.  
  465.  
  466. //┌───────────────────────────────────────────────────────────────────────┐//
  467. //│                                                                       │//
  468. //└───────────────────────────────────────────────────────────────────────┘//
  469. play_voice_in_bkgnd (int handle)
  470. {
  471.    char x,y, pct, ch;
  472.    char time[10];
  473.    clock_t temp, start, end, elapsed = 0;
  474.  
  475.    start = end = clock();
  476.    if (VCARD >= EGA)
  477.    {
  478.       show_bar (0);
  479.       qprintf ("Elapsed:", 42, 5, 135);
  480.    }
  481.    filesize = filelength(handle);
  482.    while (ct_voice_status && (end-start)/CLK_TCK <= D.duration+1)
  483.    {
  484.        spinner (2-(SPINYPOS-3), 2, SPINYPOS, 140);
  485.        end = clock();
  486.        if (((end-start)/CLK_TCK) - ((elapsed)/CLK_TCK) > 1)
  487.        {
  488.          elapsed=end-start;
  489.          pct = (tell(handle) * 100) / filesize;
  490.          int2time ((unsigned)(elapsed/CLK_TCK), time);
  491.          if (VCARD < EGA)
  492.          {
  493.             _setcursortype(_NOCURSOR);
  494.             x = wherex();
  495.             y = wherey();
  496.             printf ("[%d%%]", pct);
  497.             printf (" %s", time);
  498.             gotoxy (x,y);
  499.             _setcursortype(_NORMALCURSOR);
  500.          }
  501.     else {
  502.             show_bar (pct);
  503.             qprintf (time, 51, 5, 135);
  504.             sprintf (time, "[%d%%]  ", pct);
  505.             qprintf (time, 61, 5, 135);
  506.          }
  507.        }
  508.        if (kbhit())
  509.        {
  510.          ch = getch();
  511.          if (ch == 13 || ch == 27) break;
  512.          if (ch == 32)
  513.          {
  514.             temp = clock();
  515.             pause();
  516.             start += clock()-temp;
  517.          }
  518.        }
  519.    }
  520.    ctvd_stop();
  521.    if (ch == 27) ABORT = YES;
  522.    if (VCARD < EGA)
  523.    {
  524.       printf ("[%d%%]", (tell(handle) * 100) / filesize);
  525.       int2time ((unsigned)(elapsed/CLK_TCK), time);
  526.       printf (" %s", time);
  527.       printf ("\n");
  528.    }
  529.    return;
  530. }
  531.  
  532.  
  533.  
  534. //┌───────────────────────────────────────────────────────────────────────┐//
  535. //│                                                                       │//
  536. //└───────────────────────────────────────────────────────────────────────┘//
  537. pause ()
  538. {
  539.    ctvd_pause();
  540.    if (VCARD >= EGA)
  541.    {
  542.       qprintf ("            SPACE continue          ", 20, 7, 112);
  543.       qprintf ("SPACE", 32, 7, 113);
  544.    }
  545.    getch();
  546.    if (VCARD >= EGA) show_keys();
  547.    ctvd_continue();
  548.    return;
  549. }
  550.  
  551.  
  552.  
  553. //┌───────────────────────────────────────────────────────────────────────┐//
  554. //│                                                                       │//
  555. //└───────────────────────────────────────────────────────────────────────┘//
  556. show_bar (char percent)
  557. {
  558.    char graph[30];
  559.    char VGAdetail[]=" óúñ";
  560.    char EGAdetail[]=" ªº¿";
  561.    char solids;
  562.    char *ptr;
  563.  
  564.    if (VCARD==EGA) ptr=EGAdetail; else ptr=VGAdetail;
  565.    percent = percent * 0.84;
  566.    memset (graph, 0, sizeof(graph));
  567.    memset (graph, 32, 28);
  568.    memset (graph, *(ptr+3), percent / 3);
  569.    if ((percent % 3) > 0) memset (graph+(percent/3), *(ptr+percent%3), 1);
  570.    qprintf (graph, 51, 3, 224);
  571.    return;
  572. }
  573.  
  574.  
  575. //┌───────────────────────────────────────────────────────────────────────┐//
  576. //│                                                                       │//
  577. //└───────────────────────────────────────────────────────────────────────┘//
  578. fprint_pct(FILE *handle)
  579. {
  580.    char x,y;
  581.    char pct;
  582.  
  583.    pct = (ftell(handle) * 100) / filesize;
  584.    if (VCARD >= EGA) { show_bar (pct); return; }
  585.    x = wherex();
  586.    y = wherey();
  587.    printf ("[%d%%]", pct);
  588.    gotoxy (x,y);
  589.    return;
  590. }
  591.  
  592.  
  593. //┌───────────────────────────────────────────────────────────────────────┐//
  594. //│                                                                       │//
  595. //└───────────────────────────────────────────────────────────────────────┘//
  596. long voc_frequency(char *filename)
  597. {
  598.    FILE *fin;
  599.    VOCHDR VH;
  600.    long type_size, size;
  601.    char type, frequency;
  602.    long freq;
  603. //.........................................................................
  604.    freq = 0;
  605.    if ((fin = fopen (filename, "rb")) == NULL) show_error(2, input_file);
  606.    if (fread (&VH, sizeof(VH), 1, fin) == 0) show_error(5, input_file);
  607.    if (fseek (fin, VH.voice_offset, SEEK_SET) != 0) show_error(5, input_file);
  608.    while (!feof(fin))
  609.    {
  610.       if (fread (&type_size, 4, 1, fin) == 0 && !feof(fin)) show_error(5, input_file);
  611.       type = type_size & 0x000000FF;
  612.       size = type_size >> 8;
  613.       if (type == 0) break;
  614.       if (feof(fin)) break;
  615.       if (type == 1)
  616.       {
  617.          fread (&frequency, 1, 1, fin);
  618.          freq = 1000000/(256-(unsigned char)frequency);
  619.          break;
  620.       }
  621.       if (fseek (fin, size, SEEK_CUR) != 0) show_error (5, input_file);
  622.    }
  623.    fclose(fin);
  624.    return freq;
  625. }
  626.  
  627.  
  628. //┌───────────────────────────────────────────────────────────────────────┐//
  629. //│                                                                       │//
  630. //└───────────────────────────────────────────────────────────────────────┘//
  631. process_VOC()
  632. {
  633.    FILE *fin, *fout;
  634.    VOCHDR VH;
  635.    long amount, type_size, size;
  636.    char type, compression, frequency;
  637. //.........................................................................
  638.    if ((fin = fopen (input_file, "rb")) == NULL) show_error(2, input_file);
  639.    if ((fout = fopen (output_file, "wb")) == NULL) show_error (6, output_file);
  640.    if (fread (&VH, sizeof(VH), 1, fin) == 0) show_error(5, input_file);
  641.    if (fwrite (&VH, sizeof(VH), 1, fout) == 0) show_error(6, output_file);
  642.    if (fseek (fin, VH.voice_offset, SEEK_SET) != 0) show_error(5, input_file);
  643.    if (fseek (fout, VH.voice_offset, SEEK_SET) != 0) show_error(6, output_file);
  644.    while (!feof(fin))
  645.    {
  646.       if (kbhit())
  647.       if (getch() == 27) show_error(13, "");
  648.       if (fread (&type_size, 4, 1, fin) == 0 && !feof(fin)) show_error(5, input_file);
  649.       type = type_size & 0x000000FF;
  650.       size = type_size >> 8;
  651.       if (type == 0) break;
  652.       if (fwrite (&type_size, 4, 1, fout) == 0) show_error(6, input_file);
  653.       if (feof(fin)) break;
  654.       if (type == 1)
  655.       {
  656.          fread (&frequency, 1, 1, fin);
  657.          fwrite (&frequency, 1, 1, fout);
  658.          size--;
  659.          fread (&compression, 1, 1, fin);
  660.          fwrite (&compression, 1, 1, fout);
  661.          size--;
  662.       }
  663.       if (type <= 2 && compression != 0) show_error (3, input_file);
  664.       while (size > 0)
  665.       {
  666.          fprint_pct(fin);
  667.          amount = min (size, sizeof(chunk));
  668.          if (fread (chunk, amount, 1, fin) == 0) show_error(4, input_file);
  669.          if (type <= 2) hiss (chunk, amount);
  670.          if (fwrite (chunk, amount, 1, fout) == 0) show_error(6, input_file);
  671.          size -= amount;
  672.       }
  673.    }
  674.    fputc (0, fout);
  675.    fprint_pct(fin);
  676.    fcloseall();
  677.    if (VCARD < EGA) printf ("      \n");
  678.    return;
  679. }
  680.  
  681.  
  682. //┌───────────────────────────────────────────────────────────────────────┐//
  683. //│                                                                       │//
  684. //└───────────────────────────────────────────────────────────────────────┘//
  685. process_8()
  686. {
  687.    FILE *fin, *fout;
  688.    long amount, size, position;
  689. //.........................................................................
  690.    size = fsize (input_file);
  691.    if ((fin = fopen (input_file, "rb")) == NULL) show_error(5, input_file);
  692.    if ((fout = fopen (output_file, "wb")) == NULL) show_error (6, output_file);
  693.    if (ftype != SOU)
  694.    {
  695.       if (ftype == S32) amount = 32;
  696.       if (ftype == SND) amount = 126;
  697.       fread (&chunk, amount, 1, fin);
  698.       fwrite (&chunk, amount, 1, fout);
  699.    }
  700.    size -= amount;
  701.    while (feof(fin)==0 && size > 0)
  702.    {
  703.       if (kbhit())
  704.       {
  705.         if (getch() == 27) show_error(13, "");
  706.       }
  707.       while (size > 0)
  708.       {
  709.          fprint_pct(fin);
  710.          amount = min (size, sizeof(chunk));
  711.          if (fread (chunk, amount, 1, fin) == 0) show_error(4, input_file);
  712.          hiss (chunk, amount);
  713.          if (fwrite (chunk, amount, 1, fout) == 0) show_error(6, input_file);
  714.          size -= amount;
  715.       }
  716.    }
  717.    fprint_pct(fin);
  718.    fcloseall();
  719.    if (VCARD < EGA) printf ("      \n");
  720.    return;
  721. }
  722.  
  723.  
  724. //┌───────────────────────────────────────────────────────────────────────┐//
  725. //│ HISS REMOVAL                                                          │//
  726. //└───────────────────────────────────────────────────────────────────────┘//
  727. hiss(unsigned char *chunk, unsigned size)
  728. {
  729.    unsigned x, t, ok;
  730.    for (x = 0; x <= size;)
  731.    {
  732.       ok = YES;
  733.       for (t = 0; t <= D.length; t++)
  734.          if ((x+t < size) &&
  735.              ((*(chunk+x+t) < D.minimum) || (*(chunk+x+t) > D.maximum))) ok = NO;
  736.       if (ok)
  737.       {
  738.          for (t = 0; t <= D.length; t++)
  739.             if (x+t < size) *(chunk+x+t) = (((*(chunk+x+t)-0x80) * D.nr_factor) / 100)+0x80;
  740.          changes += t;
  741.       }
  742.       x += t;
  743.       sprintf (buffer, "Changes: %ld samples  [%d%%]", changes, changes * 100 / filesize);
  744.       if (VCARD >= EGA) qprintf (buffer, 42, 4, 135);
  745.    }
  746.    return;
  747. }
  748.  
  749.  
  750. //┌───────────────────────────────────────────────────────────────────────┐
  751. //│                                                                       │
  752. //└───────────────────────────────────────────────────────────────────────┘
  753. fsavedefaults(char *filename)
  754. {
  755.      FILE *test;
  756.      char status;
  757.  
  758.      if ((test = fopen (filename, "rb+")) != NULL)
  759.      {
  760.          printf ("Saving new defaults to %s\n", filename);
  761.          fseek (test, DEFAULT_OFFSET, SEEK_SET);
  762.          fwrite (&D, sizeof(D), 1, test);
  763.      }
  764. else show_error (9, filename);
  765.      fclose (test);
  766.      return status;
  767. }
  768.  
  769.  
  770. //┌───────────────────────────────────────────────────────────────────────┐
  771. //│                                                                       │
  772. //└───────────────────────────────────────────────────────────────────────┘
  773. fcheckdefaults(char *filename)
  774. {
  775.      FILE *test;
  776.      DEFAULTS check;
  777.      char status;
  778.      if ((test = fopen (filename, "rb")) != NULL)
  779.      {
  780.          fseek (test, DEFAULT_OFFSET, SEEK_SET);
  781.          fread (&check, sizeof(check), 1, test);
  782.      }
  783. else show_error (7, filename);
  784.      if (memcmp (&D, &check, sizeof(D)) != 0) show_error(14, "");
  785.      fclose (test);
  786.      return status;
  787. }
  788.  
  789.  
  790. //┌───────────────────────────────────────────────────────────────────────┐
  791. //│ QTOOLS.H: File exists?                                                │
  792. //└───────────────────────────────────────────────────────────────────────┘
  793. fexist(char *filename)
  794. {
  795.      FILE *test;
  796.      char status;
  797.      status = 0;
  798.      if ((test = fopen (filename, "rb")) == NULL) status = 1;
  799.      fclose (test);
  800.      return status;
  801. }
  802.  
  803.  
  804. //┌───────────────────────────────────────────────────────────────────────┐
  805. //│                                                                       │
  806. //└───────────────────────────────────────────────────────────────────────┘
  807. long fsize(char *filename)
  808. {
  809.      FILE *test;
  810.      long size = 0;
  811.      if ((test = fopen (filename, "rb")) != NULL)
  812.      {
  813.         fseek (test, 0, SEEK_END);
  814.         size = ftell(test);
  815.      }
  816.      fclose (test);
  817.      return size;
  818. }
  819.  
  820.  
  821. //┌───────────────────────────────────────────────────────────────────────┐
  822. //│ Returns 1 for 32byte SND, 2 for 126byte SND, and 0 otherwise          │
  823. //└───────────────────────────────────────────────────────────────────────┘
  824. is_SND(char *filename)
  825. {
  826.      char drive[MAXDRIVE];
  827.      char dir[MAXDIR];
  828.      char file[MAXFILE];
  829.      char ext[MAXEXT];
  830.      FILE *test;
  831.      char buffer[6];
  832.      char status;
  833.  
  834.      status = 0;
  835.      fnsplit(filename, drive, dir, file, ext);
  836.      if (strcmp (strlwr(ext), "snd")) status = S32;
  837.      if ((test = fopen (filename, "rb")) != NULL)
  838.      {
  839.         fread (&buffer, sizeof(buffer), 1, test);
  840.         if (memcmp (buffer, "SOUND", 5) == 0) status = SND;
  841.      }
  842.      fclose (test);
  843.      return status;
  844. }
  845.  
  846.  
  847. //┌───────────────────────────────────────────────────────────────────────┐
  848. //│                                                                       │
  849. //└───────────────────────────────────────────────────────────────────────┘
  850. is_VOC(char *filename)
  851. {
  852.      VOCHDR VH;
  853.      FILE *test;
  854.      char status;
  855.      status = 0;
  856.      if ((test = fopen (filename, "rb")) != NULL)
  857.      {
  858.         fread (&VH, sizeof(VH), 1, test);
  859.         if (memcmp (VH.id, "Creative Voice File", 19) == 0) status = 1;
  860.      }
  861.      fclose (test);
  862.      return status;
  863. }
  864.  
  865.  
  866. //┌───────────────────────────────────────────────────────────────────────┐
  867. //│                                                                       │
  868. //└───────────────────────────────────────────────────────────────────────┘
  869. fname_inprep (char *filename)
  870. {
  871.      char status;
  872.      char name[64];
  873.      strupr(filename);
  874.      strcpy (name, filename);
  875.      status = fexist (name);
  876.      if (status)
  877.      {
  878.          strcat (name, ".VOC");
  879.          status = fexist (name);
  880.      }
  881.      if (status)
  882.      {
  883.          strcpy (name, filename);
  884.          strcat (name, ".SOU");
  885.          status = fexist (name);
  886.      };
  887.      if (status)
  888.      {
  889.          strcpy (name, filename);
  890.          strcat (name, ".SND");
  891.          status = fexist (name);
  892.      };
  893.      if (!status)
  894.      {
  895.          strcpy (filename, name);
  896.          filesize = fsize(filename);
  897.      }
  898.      return status;
  899. }
  900.  
  901.  
  902. //┌───────────────────────────────────────────────────────────────────────┐
  903. //│                                                                       │
  904. //└───────────────────────────────────────────────────────────────────────┘
  905. fname_outprep (char *filename)
  906. {
  907.    char t;
  908.    strupr(filename);
  909.    if (*filename == 0) strcat (filename, "(NONE)");
  910. else
  911.    if ((strstr(filename, ".") == NULL) &&
  912.        (strstr(filename, ".VOC") == NULL) &&
  913.        (strstr(filename, ".SND") == NULL) &&
  914.        (strstr(filename, ".SOU") == NULL))
  915.    {
  916.       if (ftype == VOC) strcat (filename, ".VOC");
  917.       if (ftype == SOU) strcat (filename, ".SOU");
  918.       if (ftype == S32) strcat (filename, ".SND");
  919.       if (ftype == SND) strcat (filename, ".SND");
  920.    }
  921.    if (strcmp(filename, input_file)==0) show_error (7, input_file);
  922.    if (fexist (filename)==0 && D.overwrite==NO && D.process==YES)
  923.    {
  924.       printf ("Overwrite %s? (Y or [N]) ", filename);
  925.       t = getche(); printf("\n");
  926.       if (t != 'Y' && t != 'y') exit(4);
  927.    }
  928.    return;
  929. }
  930.  
  931.  
  932.  
  933.  
  934. //┌───────────────────────────────────────────────────────────────────────┐//
  935. //│ Shows help screen                                                     │//
  936. //└───────────────────────────────────────────────────────────────────────┘//
  937. show_help()
  938. {
  939.   char help_text[][81]=
  940. {
  941.   "Usage:\n         NOHISS <inputfile[.ext]> [outputfile[.ext]] [options]\n\n",
  942.   "Options:                                                      Defaults\n",
  943.   "         /NR=#            Noise reduction level               %d percent\n",
  944.   "         /SIZE=#          Minimum duration of hiss            %d samples\n",
  945.   "         /RANGE=#         Hiss spectrum (0 to 254)            %d units\n",
  946.   "         /MIN=#           Hiss lower limit (-127 to +127)    %d units\n",
  947.   "         /MAX=#           Hiss upper limit (-127 to +127)     %d units\n",
  948.   "         /[NO]FANCY       Screen display type                 %s\n",
  949.   "         /[NO]OVER        Overwrite output file               %s\n",
  950.   "         /[NO]PROCESS     Noise processor mode                %s\n",
  951.   "         /[NO]PAUSE       Pause after playback                %s\n",
  952.   "         /[NO]PLAY[I][O]  Playback mode (none, in, out)       %s\n",
  953.   "         /TIME=#          Playback timer                      %d seconds\n",
  954.   "         /PORT=#          Soundblaster IO port number         %x hex\n",
  955.   "         /SAVE            Save new defaults to NOHISS.EXE\n",
  956.   "         /RESET           Reset factory defaults in NOHISS.EXE\n\n",
  957.   "         Samples may be VOC, SND, SOU or any 8-bit raw data\n"
  958. };
  959.    show_header();
  960.    printf (help_text[0]);
  961.    printf (help_text[1]);
  962.    printf (help_text[2], D.nr_factor);
  963.    printf (help_text[3], D.length);
  964.    printf (help_text[4], D.maximum-D.minimum);
  965.    printf (help_text[5], D.minimum-128);
  966.    printf (help_text[6], D.maximum-128);
  967.    printf (help_text[7], (D.fancy ? "FANCY" : "NOFANCY"));
  968.    printf (help_text[8], (D.overwrite ? "OVER" : "NOOVER"));
  969.    printf (help_text[9], (D.process ? "PROCESS" : "NOPROCESS"));
  970.    printf (help_text[10], (D.endpause ? "PAUSE" : "NOPAUSE"));
  971.    if (D.playfile == 1) printf (help_text[11], "PLAYI");
  972. else if (D.playfile == 2) printf (help_text[11], "PLAYO");
  973. else if (D.playfile == 3) printf (help_text[11], "PLAYIO");
  974. else printf (help_text[11], "NOPLAY");
  975.    printf (help_text[12], D.duration);
  976.    printf (help_text[13], D.sbport);
  977.    printf (help_text[14]);
  978.    printf (help_text[15]);
  979.    printf (help_text[16]);
  980.    exit(0);
  981.    return;
  982. }
  983.  
  984.  
  985. //┌────────────────────────────────────────────────────────────────────────┐
  986. //│ Parses command line arguements                                         │
  987. //│ Note: the **argv != NULL method is not stable under COMPACT & > models │
  988. //│       it is better to have a loop of n=argc                            │
  989. //└────────────────────────────────────────────────────────────────────────┘
  990. parse_args(char argc, char *argv[])
  991. {
  992.    int value;
  993.    char save = NO;
  994.    char help = NO;
  995.    char *prgname=argv[0];
  996.    fcheckdefaults(prgname);
  997.    if (argc == 1) show_help();
  998.    for (argv++; argc > 1; argc--, argv++)
  999.    {
  1000.      strlwr (*argv);
  1001.      if (**argv == '-') **argv = '/';
  1002.      if (!memcmp("/range=", *argv, 7))
  1003.         {
  1004.             D.minimum = 128 - (atoi((*argv)+7)/2);
  1005.             D.maximum = 128 + (atoi((*argv)+7)/2);
  1006.         }
  1007. else if (!memcmp("/nr=",    *argv, 4)) D.nr_factor = atol((*argv)+4);
  1008. else if (!memcmp("/size=",  *argv, 6)) D.length = atol((*argv)+6);
  1009. else if (!memcmp("/s=",     *argv, 3)) D.length = atol((*argv)+3);
  1010. else if (!memcmp("/time=",  *argv, 6)) D.duration = atol((*argv)+6);
  1011. else if (!memcmp("/t=",     *argv, 3)) D.duration = atol((*argv)+3);
  1012. else if (!memcmp("/port=",  *argv, 6)) sscanf((*argv)+6, "%x", &D.sbport);
  1013. else if (!memcmp("/p=",     *argv, 3)) sscanf((*argv)+3, "%x", &D.sbport);
  1014. else if (!memcmp("/s",      *argv, 2)) save = YES;
  1015. else if (!memcmp("/nopr",   *argv, 5)) D.process = 0;
  1016. else if (!memcmp("/pause",  *argv, 6)) D.endpause = YES;
  1017. else if (!memcmp("/nopause",*argv, 8)) D.endpause = NO;
  1018. else if (!memcmp("/nofancy",*argv, 8)) D.fancy = NO;
  1019. else if (!memcmp("/fancy",  *argv, 6)) D.fancy = YES;
  1020. else if (!memcmp("/noplay", *argv, 7)) D.playfile = 0;
  1021. else if (!memcmp("/playio", *argv, 7)) D.playfile = 3;
  1022. else if (!memcmp("/playoi", *argv, 7)) D.playfile = 3;
  1023. else if (!memcmp("/playi",  *argv, 6)) D.playfile = 1;
  1024. else if (!memcmp("/playo",  *argv, 6)) D.playfile = 2;
  1025. else if (!memcmp("/min=",   *argv, 5)) D.minimum = 128+atoi((*argv)+5);
  1026. else if (!memcmp("/max=",   *argv, 5)) D.maximum = 128+atoi((*argv)+5);
  1027. else if (!memcmp("/r",      *argv, 2)) {D = FACTORY; save=YES;}
  1028. else if (!memcmp("/noover", *argv, 7)) D.overwrite = NO;
  1029. else if (!memcmp("/o",      *argv, 2)) D.overwrite = YES;
  1030. else if (!memcmp("?",       *argv, 1)) help = YES;
  1031. else if (!memcmp("/?",      *argv, 2)) help = YES;
  1032. else if (!memcmp("/h",      *argv, 2)) help = YES;
  1033. else if (**argv != '/')
  1034.      {
  1035.          if (!*input_file) strcpy (input_file, *argv);
  1036.     else if (!*output_file) strcpy (output_file, *argv);
  1037.      }
  1038. else show_error(1, *argv);
  1039.    }
  1040.  
  1041.    if ((D.minimum < 1) || (D.minimum > 255) ||
  1042.        (D.maximum < 1) || (D.maximum > 255)) show_error (8, "/RANGE from 2 to 254");
  1043.    if (D.minimum >= D.maximum) show_error (8, "Minimum must be smaller than maximum");
  1044.    if (D.length < 1 || D.length > 32000) show_error (8, "/SIZE from 1 to 32000");
  1045.    if (D.nr_factor < 0 || D.nr_factor > 100) show_error (8, "/NR from 0 to 100");
  1046.    if (save) fsavedefaults(prgname);
  1047.    if (help) show_help();
  1048.    if (*input_file==0 && save) exit(2);
  1049.    D.nr_factor = 100-D.nr_factor;
  1050.    return;
  1051. }
  1052.  
  1053.  
  1054. //┌───────────────────────────────────────────────────────────────────────┐//
  1055. //│                                                                       │//
  1056. //└───────────────────────────────────────────────────────────────────────┘//
  1057. process()
  1058. {
  1059.   if (fname_inprep(input_file)) show_error(2, input_file);
  1060.   ftype = is_VOC(input_file);
  1061.   if (ftype != VOC) ftype = is_SND(input_file);
  1062.   fname_outprep(output_file);
  1063.   screen_prep();
  1064.   if (D.process)
  1065.   {
  1066.       if (VCARD < EGA)
  1067.       {
  1068.          printf ("Processing output file: %s ", output_file);
  1069.       }
  1070. else  {
  1071.          qprintf ("Sample count: ", 5, 5, 135);
  1072.          sprintf (buffer, "%ld", fsize (input_file));
  1073.          qprintf (buffer, 19, 5, 135);
  1074.       }
  1075.       if (ftype==VOC) process_VOC(); else process_8();
  1076.       sprintf (buffer, "Changes: %ld samples  [%d%%]", changes, changes * 100 / filesize);
  1077.       if (VCARD < EGA)
  1078.          printf ("Reduction changes: %ld samples, affecting %d%% of file\n", changes, changes * 100 / filesize);
  1079.     else qprintf (buffer, 42, 4, 135);
  1080.   }
  1081.   if (ftype == VOC)
  1082.   {
  1083.      if (D.playfile == 3 || D.playfile == 1)
  1084.      {
  1085.         if (VCARD < EGA) printf ("Playing input file: %s ", input_file);
  1086.       else qprintf ("   Playing:", 39, 3, 135);
  1087.         sb_disk_play (input_file);
  1088.         if (VCARD >= EGA) spinner (4, 2, SPINYPOS, 135);
  1089.      }
  1090.      if ((D.playfile == 3 || D.playfile == 2) && (!fexist (output_file)))
  1091.      {
  1092.        SPINYPOS++;
  1093.        if (VCARD < EGA) printf ("Playing output file: %s ", output_file);
  1094.        sb_disk_play (output_file);
  1095.        if (VCARD >= EGA) spinner (4, 2, SPINYPOS, 135);
  1096.      }
  1097.   }
  1098.   if (D.endpause && VCARD >= EGA) pause();
  1099.   return;
  1100. }
  1101.  
  1102.  
  1103. //┌───────────────────────────────────────────────────────────────────────┐//
  1104. //│ MAIN ROUTINE                                                          │//
  1105. //└───────────────────────────────────────────────────────────────────────┘//
  1106. main(char argc, char *argv[])
  1107. {
  1108.   init_video();
  1109.   parse_args (argc, argv);
  1110.   if (D.fancy == NO) VCARD = BIOS;
  1111.   if (VCARD < EGA) show_header();
  1112.   process();
  1113.   remove ("(NONE)");
  1114.   close_video();
  1115.   return 0;
  1116. }
  1117.  
  1118.