home *** CD-ROM | disk | FTP | other *** search
/ modiromppu / modiromppu.iso / PROGRAMS / ORGPACKS / DIDO4.ZIP / SOURCE.ZIP / DIDOREC.C < prev   
C/C++ Source or Header  |  1995-01-17  |  8KB  |  266 lines

  1. struct RIFF {
  2.     char rID[4];
  3.     DWORD rLen;
  4.     } riff;
  5.  
  6. struct FORMAT {
  7.     char fID[4];
  8.     DWORD fLen;
  9.     WORD wTag;
  10.     WORD wChannel;
  11.     DWORD nSample;
  12.     DWORD nByte;
  13.     WORD align;
  14.     WORD sample;
  15.     };
  16.  
  17. struct DATA {
  18.     char dID[4];
  19.     DWORD dLen;
  20.     };
  21.  
  22. struct WAVE {
  23.     char wID[4];
  24.     struct FORMAT fmt;
  25.     struct DATA data;
  26.     } wave;
  27.  
  28. char error[80];                    // description of error, if any
  29.  
  30. int abortflag;
  31.  
  32. // Watch the cancel button
  33. #pragma argsused
  34. BOOL CALLBACK StatusDlgProc(HWND hdlg, UINT msg, WPARAM wp, LPARAM lp)
  35. {
  36.     if (msg==WM_INITDIALOG) {
  37.         SetDialogFont(hdlg,GetStockObject(ANSI_VAR_FONT));
  38.         CenterWindow(hdlg);
  39.         }
  40.     if (msg==WM_COMMAND && wp==IDCANCEL) abortflag=1;
  41.     return 0;
  42. }
  43.  
  44. // Write out a block of sound data, do some processing if necessary.
  45. // Return 0:failure, otherwise: bytes written.
  46. WORD wavwrite(signed int *sample,WORD len,FILE *f)
  47. {
  48.     if (hz44) {
  49.         if (stereo) { // 44khz stereo: no processing needed
  50.             if (fwrite(sample,len,1,f)==1) return len;
  51.             }
  52.         else { // 44khz mono: calculate left/right channel average, then write
  53.             WORD nsamples;
  54.             signed int *src=sample,*dst=sample;
  55.             nsamples=len>>2;
  56.             while (nsamples--) {
  57.                 *dst=(WORD)(((DWORD)*src+*(src+1))>>1);
  58.                 src+=2;
  59.                 dst++;
  60.                 }
  61.             if (fwrite(sample,len>>1,1,f)==1) return len>>1;
  62.             }
  63.         }
  64.     else { 
  65.         if (stereo) { // 22khz stereo: condense samples (write only samples 0, 2, 4 etc)
  66.             WORD nsamples;
  67.             DWORD *src=(DWORD *)sample,*dst=(DWORD *)sample;
  68.             nsamples=len>>3;
  69.             while (nsamples--) {
  70.                 *dst=*src; dst++; src+=2;
  71.                 }
  72.             if (fwrite(sample,len>>1,1,f)==1) return len>>1;
  73.             }
  74.         else {
  75.             if (bit16) {// 22khz mono 16bits
  76.                 WORD nsamples;
  77.                 signed int *src=sample,*dst=sample;
  78.                 nsamples=len>>3;
  79.                 while (nsamples--) {
  80.                     *dst=(WORD)(((DWORD)*src+*(src+1))>>1);
  81.                     src+=4;
  82.                     dst++;
  83.                     }
  84.                 if (fwrite(sample,len>>2,1,f)==1) return len>>2;
  85.                 }
  86.             else { // 22 khz mono 8 bits
  87.                 WORD nsamples;
  88.                 signed int *src=sample;
  89.                 signed char *dst=sample;
  90.                 nsamples=len>>3;
  91.                 while (nsamples--) {
  92.                     *dst=128+HIBYTE((WORD)(((DWORD)*src+*(src+1))>>1));
  93.                     src+=4;
  94.                     dst++;
  95.                     }
  96.                 if (fwrite(sample,len>>3,1,f)==1) return len>>3;
  97.                 }
  98.             }
  99.         }
  100.     return 0;
  101. }
  102.  
  103. int record(char *image,DWORD startloc,DWORD size) 
  104. {
  105.     int first_time,i,bps;
  106.     WORD offset,synch_size,written;
  107.     DWORD end_pos,loc=startloc;
  108.     FILE *f;
  109.     HWND status;
  110.     MSG msg;
  111.  
  112.     // Put up a modal dialog box (for status)
  113.     abortflag=0;
  114.     status=CreateDialog(hinst,"StatusDlg",0,StatusDlgProc);
  115.     if (!status) {
  116.         strcpy(error,"Cant create status window");
  117.         return 0;
  118.         }
  119.     strcpy(error,"");
  120.  
  121.     // Create WAV file
  122.     f=fopen(image,"wb");
  123.     if (!f) {
  124.         strcpy(error,"cant create file");
  125.         return 0;
  126.         }
  127.  
  128.     // Prepare RIFF+WAV header
  129.     bps=1;                                  // bytes per sample - for a 8 bit mono sample
  130.     if (bit16) bps<<=1;                     // two times as much for 16 bit samples
  131.     if (stereo) bps<<=1;                    // another 2x as much for stereo                     
  132.     strcpy(riff.rID, "RIFF");
  133.     riff.rLen = FRAME_SIZE * (DWORD)size + sizeof(struct WAVE);
  134.     strcpy(wave.wID, "WAVE");
  135.     strcpy(wave.fmt.fID, "fmt ");
  136.     wave.fmt.fLen = sizeof(struct FORMAT) - 8;
  137.     wave.fmt.wTag = 1;
  138.     wave.fmt.wChannel = stereo?2:1;                    // nr of channels
  139.     wave.fmt.nSample = hz44?44100L:22050L;            // sample rate
  140.     wave.fmt.nByte = (hz44?44100L:22050L) * bps;    // avg dataspeed bytes/sec
  141.     wave.fmt.align = bps;                            // size of one sample, in bytes
  142.     wave.fmt.sample = bit16?16:8;                    // bits per sample
  143.     strcpy(wave.data.dID, "data");
  144.     wave.data.dLen = FRAME_SIZE * (DWORD)size;
  145.  
  146.     if (fwrite(&riff,sizeof(struct RIFF),1,f)!=1) {
  147.         strcpy(error,"cant write to file (disk full?)");
  148.         goto Errorexit;
  149.         }
  150.     if (fwrite(&wave,sizeof(struct WAVE),1,f)!=1) {
  151.         strcpy(error,"cant write to file (disk full?)");
  152.         goto Errorexit;
  153.         }
  154.  
  155.     // Read the data in blocks, first in memory
  156.        // loc: start position (sierra sector)
  157.     // size: number of sectors to read
  158.     // end_loc: sector number at where to end 
  159.     wave.data.dLen = 0L;
  160.     first_time = 1;
  161.     end_pos = loc+size;
  162.     while (loc<end_pos) {
  163.         // Check abort
  164.         if (abortflag) {
  165.             strcpy(error,"   Recording cancelled   ");
  166.             goto Errorexit;
  167.             }
  168.         // Update reading status
  169.         sprintf(s,"sector %ld / %ld",loc-startloc,size);
  170.         SetDlgItemText(status,STATUS,s);
  171.         // Read data in buffers
  172.         for (i=0;i<nbuf;i++) {
  173.             //TODO: Fix bugs with the last sector(s)
  174.             /*res=*/ ReadLong(loc,NBLOCK,bufseg[i]);
  175.             loc+=NBLOCK;
  176.             }
  177.         /*
  178.         if (res!=0x0100) {
  179.             sprintf(error,"cant read raw sector, status %04x",res);
  180.             goto Errorexit;
  181.             }
  182.         */
  183.         // Except for first recording, synchronize data to previous data
  184.         if (first_time == 0) { 
  185.             offset = 0;
  186.             synch_size = SYNCH_SIZE;
  187.             while (offset == 0) {
  188.                 for (i=(NBLOCK/4)*FRAME_SIZE;i<(((WORD)NBLOCK*FRAME_SIZE)-synch_size);i+=4) {
  189.                     if (memcmp(pprev_end+(NBLOCK/2)*FRAME_SIZE,pbuf[0]+i,synch_size) == 0) {
  190.                         if (offset==0)
  191.                             offset=i;
  192.                         else {
  193.                             synch_size *= 2;
  194.                             if (synch_size>4096) {
  195.                                 strcpy(error,"Synchronisation failed. Retry the operation. Close some other programs, if possible.");
  196.                                 goto Errorexit;
  197.                                 }
  198.                             offset=0;
  199.                             break;
  200.                             }
  201.                         }
  202.                     }
  203.                 if (offset==0) {
  204.                     strcpy(error,"Synchronisation failed, no matching block. Retry the operation. Close some other programs, if possible.");
  205.                     goto Errorexit;
  206.                     }
  207.                 }
  208.             }
  209.         else
  210.             offset = 0;
  211.  
  212.         first_time=0;
  213.         memcpy(pprev_end,pbuf[nbuf-1],(WORD)((DWORD)FRAME_SIZE*NBLOCK));
  214.  
  215.         // Write all buffers to disk, except the last buffer
  216.         for (i=0;i<nbuf-1;i++) {
  217.             written=wavwrite((signed int *)(pbuf[i]+offset),((DWORD)FRAME_SIZE*NBLOCK)-offset,f);
  218.             if (!written) {
  219.                 strcpy(error,"cant write to file (disk full?)");
  220.                 goto Errorexit;
  221.                 }
  222.             wave.data.dLen+=written;
  223.             offset=0;
  224.             }
  225.         sprintf(s,"%s   %ld Kbytes",Sector2MSF(loc-startloc),wave.data.dLen/1024);
  226.         SetDlgItemText(status,STATUSDISK,s);
  227.  
  228.         // Write only half of last buffer, The next loop, after synchronisation the rest will be written
  229.         written=wavwrite((signed int *)pbuf[nbuf-1],(DWORD)FRAME_SIZE*(NBLOCK/2),f);
  230.         if (!written) {
  231.             strcpy(error,"cant write to file (disk full?)");
  232.             goto Errorexit;
  233.             }
  234.         wave.data.dLen+=written;
  235.  
  236.         loc-=NBLOCK;
  237.  
  238.         // Give some time slices
  239.         while (PeekMessage(&msg,0,0,0,PM_REMOVE)) {
  240.             TranslateMessage(&msg);
  241.             DispatchMessage(&msg);
  242.             }
  243.         }
  244.  
  245.     // Fix WAV header
  246.     fseek(f,0L,SEEK_SET);
  247.     riff.rLen = wave.data.dLen + sizeof(struct WAVE);
  248.     if (fwrite(&riff,sizeof(struct RIFF),1,f)!=1) {
  249.         strcpy(error,"cant write to file (disk full?)");
  250.         goto Errorexit;
  251.         }
  252.     if (fwrite(&wave,sizeof(struct WAVE),1,f)!=1) {
  253.         strcpy(error,"cant write to file (disk full?)");
  254.         goto Errorexit;
  255.         }
  256.  
  257.     fclose(f);
  258.     DestroyWindow(status);
  259.     return 1;
  260. Errorexit:
  261.     if (f) fclose(f);
  262.     unlink(image);
  263.     DestroyWindow(status);
  264.     return 0;
  265. }
  266.