home *** CD-ROM | disk | FTP | other *** search
- /*
-
- GOAL:
- This program is intended to read CD audio data into a disk file.
-
- Author:
- First version:
- Yeng-Chee Su (yenchee@csie.nctu.edu.tw)
- Department of Computer Science and Information Engineering
- National Chiao Tung University
- Later adapted and extended by:
- Klaas Hemstra (hst@mh.nl) Gouda, the Netherlands
- Stewart Addison (tardis.ed.ac.uk) Edinburgh, Scotland
-
- Notice:
- Most CD-ROM drive doesn't have the capability to read raw
- data on compact disk, but some drives can work. These includes
- Panasonic CR-562B/563B and Toshiba XM-3401B. This program
- is designed on CR-562B and should work well on it. If it
- can't work for you, find a better driver around.
- Yeng-Chee Su wrote the first attempt, but the program depended on
- the speed of the file-system for clean 'recordings'.
-
- The buffered read + synchronisation is added later by me.
-
- Klaas Hemstra
-
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdarg.h>
- #include <conio.h>
- #include <dos.h>
- #include <string.h>
- #include <ctype.h>
- #include <fcntl.h>
- #include <sys/stat.h>
- #include <io.h>
-
- #include <sys/timeb.h> /* Allows accurate timing - psyche */
-
- #define MAXPATH 80 /* Compensates for the lack of dir.h <g> */
-
- #define RAW_MODE 1
- #define COOKED_MODE 0
- #define READ_MODE RAW_MODE
- #if READ_MODE == COOKED_MODE
- #define FRAME_SIZE 2048
- #else
- #define FRAME_SIZE 2352
- #endif
-
- /********** Some constants for the allocation of buffers etc. *********/
-
- #define NBLOCK 8 /* Each buffer is 8x2352 = about 18K of data */
- #define BUFSIZE (NBLOCK*FRAME_SIZE) /* One buffer = 18K */
- #define SYNCH_SIZE 128 /* Bytes synch pattern (to start with) */
-
- typedef unsigned char BYTE;
- typedef unsigned int WORD;
- typedef unsigned long int DWORD;
-
- /************* Structures for calling the CD-ROM device driver *******/
-
- struct ReqHdr {
- BYTE len;
- BYTE unit;
- BYTE command;
- WORD status;
- BYTE reserved[8];
- };
-
- struct IOCTLI {
- struct ReqHdr req;
- BYTE descriptor;
- void far *address;
- WORD len;
- WORD secnum;
- void far *ptr;
- };
-
- struct DeviceStatus {
- BYTE control;
- DWORD param;
- };
-
- struct DiskInfo {
- BYTE control;
- BYTE lowest;
- BYTE highest;
- DWORD total;
- };
-
- struct TrackInfo {
- BYTE control;
- BYTE track;
- DWORD loc;
- BYTE info;
- };
-
- struct SEEK {
- struct ReqHdr req;
- BYTE mode;
- DWORD address;
- WORD secnum;
- DWORD loc;
- };
-
- struct PlayReq {
- struct ReqHdr req;
- BYTE mode;
- DWORD loc;
- DWORD secnum;
- };
-
- int CDROM;
- int lowest, highest;
- DWORD total_time;
- char image[MAXPATH];
-
- void CallDevice(void *ptr)
- {
- static union REGS reg;
- static struct SREGS seg;
-
- segread(&seg);
- seg.es=FP_SEG(ptr);
- reg.x.ax=0x1510;
- reg.x.bx=FP_OFF(ptr);
- reg.x.cx=CDROM;
- int86x(0x2f, ®, ®, &seg);
- }
-
- int check_mscdex(void)
- {
- union REGS reg;
-
- reg.x.ax=0x1500;
- reg.x.bx=0;
- int86(0x2f, ®, ®);
- if (!reg.x.bx)
- return 0;
- else {
- CDROM=reg.x.cx;
- return 1;
- }
- }
-
- int GetDeviceStatus(void)
- {
- struct IOCTLI cmd;
- struct DeviceStatus buf;
-
- cmd.req.len=26;
- cmd.req.unit=0;
- cmd.req.command=3;
- cmd.descriptor=0;
- cmd.address=&buf;
- cmd.len=5;
- cmd.secnum=0;
- cmd.ptr=NULL;
- buf.control=6;
- CallDevice(&cmd);
- return cmd.req.status;
- }
-
- int GetDiskInfo(void)
- {
- struct IOCTLI cmd;
- struct DiskInfo buf;
-
- cmd.req.len=26;
- cmd.req.unit=0;
- cmd.req.command=3;
- cmd.descriptor=0;
- cmd.address=&buf;
- cmd.len=7;
- cmd.secnum=0;
- cmd.ptr=NULL;
- buf.control=10;
- CallDevice(&cmd);
- lowest=buf.lowest;
- highest=buf.highest;
- total_time=buf.total;
- return cmd.req.status;
- }
-
- int GetTrackInfo(int track, DWORD *loc, BYTE *info)
- {
- struct IOCTLI cmd;
- struct TrackInfo buf;
-
- cmd.req.len=26;
- cmd.req.unit=0;
- cmd.req.command=3;
- cmd.descriptor=0;
- cmd.address=&buf;
- cmd.len=7;
- cmd.secnum=0;
- cmd.ptr=NULL;
- buf.control=11;
- buf.track=track;
- CallDevice(&cmd);
- *loc=buf.loc;
- *info=buf.info;
- return cmd.req.status;
- }
-
- int SeekTrack(DWORD loc)
- {
- struct SEEK cmd;
-
- cmd.req.len=24;
- cmd.req.unit=0;
- cmd.req.command=131;
- cmd.mode=1;
- cmd.address=NULL;
- cmd.secnum=0;
- cmd.loc=loc;
- CallDevice(&cmd);
- return cmd.req.status;
- }
-
- int PlayAudio(DWORD loc, DWORD num)
- {
- struct PlayReq cmd;
-
- cmd.req.len=22;
- cmd.req.unit=0;
- cmd.req.command=132;
- cmd.mode=1;
- cmd.loc=loc;
- cmd.secnum=num;
- CallDevice(&cmd);
- return cmd.req.status;
- }
-
- int StopAudio(void)
- {
- struct ReqHdr cmd;
-
- cmd.len=13;
- cmd.unit=0;
- cmd.command=133;
- CallDevice(&cmd);
- return cmd.status;
- }
-
- DWORD Red2Sierra(DWORD loc)
- {
- BYTE min, sec, frame;
-
- min = (loc >> 16) & 0xff;
- sec = (loc >> 8) & 0xff;
- frame = loc & 0xff;
- return (DWORD)min * 75 * 60 + (DWORD)sec * 75 + (DWORD)frame - 150;
- }
-
- int ReadLong(DWORD loc, WORD secnum, char far *buf)
- {
- struct ReadL {
- struct ReqHdr req;
- BYTE mode;
- void far *address;
- WORD secnum;
- DWORD loc;
- BYTE readmode;
- BYTE skip[2];
- } cmd;
-
- cmd.req.len=sizeof(cmd);
- cmd.req.unit=0;
- cmd.req.command=128;
- cmd.mode=0;
- cmd.address=buf;
- cmd.secnum=secnum;
- cmd.loc=loc;
- cmd.readmode=READ_MODE;
- cmd.skip[0]=cmd.skip[1]=0;
- CallDevice(&cmd);
- return cmd.req.status;
- }
-
- int GetVolSize(DWORD *size)
- {
- struct IOCTLI cmd;
- struct {
- BYTE control;
- DWORD size;
- } buf;
-
- cmd.req.len=sizeof(cmd);
- cmd.req.unit=0;
- cmd.req.command=3;
- cmd.descriptor=0;
- cmd.address=&buf;
- cmd.len=sizeof(buf);
- cmd.secnum=0;
- cmd.ptr=NULL;
- buf.control=8;
- CallDevice(&cmd);
- *size=buf.size;
- return cmd.req.status;
- }
-
- char *
- location_str(DWORD loc)
- {
- static char ret_buf[256];
- long min,sec,frames;
-
- frames = loc % 75;
- sec = (loc+150) / 75;
- min = sec / 60;
- sec = sec % 60;
-
- sprintf(ret_buf,"High sierra %ld ; %02ld:%02ld.%02ld",loc,min,sec,frames);
- return ret_buf;
- }
-
- void
- translate_location(char *strbuf,DWORD *loc)
- {
- char *p;
-
- for (p=strbuf;*p && (*p != ':'); p++)
- ;
- if (*p == ':') {
- *loc = atol(strbuf)*75L*60L+atol(p+1)*75L;
- } else {
- *loc = atol(strbuf);
- }
- }
-
- void
- read_location(char *question,DWORD *loc)
- {
- #define MAX_LOC 256
- char buf[MAX_LOC];
- buf[0] = '\0';
-
- while (buf[0] == '\0') {
- printf("%s",question);
- fgets(buf,MAX_LOC,stdin);
- }
- translate_location(buf,loc);
- }
-
-
- void
- usage()
- {
- fprintf(stderr,"Usage: readcda [options]\n");
- fprintf(stderr," If no options are specified the user is asked for the required data\n");
- fprintf(stderr,"Options: -file <output-filename> [needed]\n");
- fprintf(stderr," -track <tracknumber> which track to read\n");
- fprintf(stderr," -from <location> from where to read\n");
- fprintf(stderr," -length <length> how long to read\n");
- fprintf(stderr,"Note: -track or -from are needed, and -from must be combined with -length\n");
- fprintf(stderr," where -track CAN be combined with -length\n");
- fprintf(stderr," both -length and -from can be 'min:sec' or sector number\n");
- fprintf(stderr,"Extra options:\n");
- fprintf(stderr," -debug <level> Display more output with higher level\n");
- fprintf(stderr," -wav Write an WAV file (=default)\n");
- fprintf(stderr," -cdda Write the RAW CDDA output\n");
- fprintf(stderr," -nbuf <#buf> Use #buf buffers (>8,when automatic failes\n");
- fprintf(stderr," -swapbytes Swap all bytes (MSB/LSB) in output\n");
- fprintf(stderr," -swapwords Swap all words (channels) in output\n");
- fprintf(stderr," -nosynch Skip the synchronization algorithm\n");
- fprintf(stderr," -synch Keep using the synchronization algorithm\n");
- exit(1);
- }
-
-
- /**** Commandline parameter fields ***************************/
-
- int p_track=-1; /* track-no 1... */
- char p_filename[255]; /* file name */
- char p_from[255]; /* From location */
- char p_length[255]; /* Length of recording */
- int p_nbuf = -1; /* Default number of audio buffers */
- int p_debug=0; /* debug-info-lebel (0=no,1,2,..) */
- int p_waveform=1; /* Default = WAV file */
- int p_swapbytes; /* Default = No swapping of bytes (MSB/LSB) */
- int p_swapwords; /* Default = No swapping of words (audio channels) */
- int ask_param=1; /* Flag for asking of parameters */
- int p_nosynch=0; /* Default= use synchronization algorithm,if 1 don't */
- #ifdef TIMING
- struct timeb ts, te; /* For overall timing */
- struct timeb tms, tme; /* For exact-ish timing */
- #endif
-
- void
- writelog(char *format, ... )
- {
- FILE *f_log;
- va_list(arglist);
-
- if ( p_debug ) {
- va_start(arglist,format);
- f_log=fopen("readcda2.log","a");
- vfprintf(f_log,format,arglist);
- fclose(f_log);
- va_end(arglist);
- }
- }
-
- void
- get_command_line_param(int argc, char *argv[])
- {
- int i;
- i = 1;
-
- while (i < argc) {
- if (strcmp(argv[i],"-track") == 0) {
- i++;
- p_track = atoi(argv[i]);
- } else if(strcmp(argv[i],"-file")== 0) {
- i++;
- strcpy(p_filename,argv[i]);
- } else if(strcmp(argv[i],"-from")== 0) {
- i++;
- strcpy(p_from,argv[i]);
- } else if(strcmp(argv[i],"-length")== 0) {
- i++;
- strcpy(p_length,argv[i]);
- } else if(strcmp(argv[i],"-debug")== 0) {
- i++;
- p_debug = atoi(argv[i]);
- } else if(strcmp(argv[i],"-nbuf")== 0) {
- i++;
- p_nbuf = atoi(argv[i]);
- } else if(strcmp(argv[i],"-wav")== 0) {
- p_waveform = 1;
- } else if(strcmp(argv[i],"-cdda")== 0) {
- p_waveform = 0;
- } else if(strcmp(argv[i],"-swapbytes")== 0) {
- p_swapbytes = 1;
- } else if(strcmp(argv[i],"-swapwords")== 0) {
- p_swapwords = 1;
- } else if(strcmp(argv[i],"-synch")== 0) {
- p_nosynch = 0;
- } else if(strcmp(argv[i],"-nosynch")== 0) {
- p_nosynch = 1;
- } else {
- usage();
- }
- i++;
- }
-
- if (argc > 1) {
- ask_param = 0; /* Ok, there are command line parameters */
-
- if (((p_track == -1) && (*p_from == '\0')) || (*p_filename == '\0')) {
- printf("Not all parameters supplied !!\n\n");
- usage(); /* Not all necessary param specified */
- }
-
- writelog("-----------------------------------------------\n");
- writelog("Reading file %s\n",p_filename);
- if (p_track != -1) {
- if (! *p_length)
- writelog("Reading track %d\n",p_track);
- else
- writelog("Reading track %d, length %s\n",p_track,p_length);
- }
- else
- writelog("Reading from pos %s, length %s\n",p_from,p_length);
- }
-
- return;
- }
-
- /*
- * Ok, here is the main program.
- * Most of the programming is below :-)
- *
- */
-
- void main(int argc, char *argv[])
- {
- WORD status,w;
- char *buf[50],*previous_end;
- DWORD *track_loc, loc, start_pos, end_pos, buf_start,size;
- DWORD i, j, offset=0, synch_size;
- long work_offset, min_offset=32768, max_offset=0, avg_offset=0;
- int no_offset=0, num_reads;
- long readtime_min=0, readtime_max=0; /* Max & min. timings - psyche */
- long maxtime,mintime;
- BYTE info,b;
- int fd, key, n,first_time;
- int retry, waveform;
-
- struct RIFF {
- char rID[4];
- DWORD rLen;
- } riff;
- struct FORMAT {
- char fID[4];
- DWORD fLen;
- WORD wTag;
- WORD wChannel;
- DWORD nSample;
- DWORD nByte;
- WORD align;
- WORD sample;
- };
- struct DATA {
- char dID[4];
- DWORD dLen;
- };
- struct WAVE {
- char wID[4];
- struct FORMAT fmt;
- struct DATA data;
- } wave;
-
- struct timeb ts, te; /* For overall timing (maximum) */
- struct timeb tms, tme; /* For exact-ish timing (minimum) */
-
- printf("READ CD digital Audio 2.0\n");
- printf("Written by Klaas Hemstra (hst@mh.nl).\n");
- printf("Based on code by Yeng-Chee Su (yenchee@csie.nctu.edu.tw)\n");
- printf("Timing by Stewart Addison (psyche@tardis.ed.ac.uk)\n\n");
-
- /*
- * See if user added commandline param
- */
- get_command_line_param(argc,argv);
-
- /*
- * Allocate memory buffers
- *
- * First the one for the block to synchronize against.
- */
- previous_end = (char*)malloc(BUFSIZE/2);
- if (previous_end == (char *) NULL) {
- fprintf(stderr,"Out of memory allocating synch buffer, real low on memory !!\n");
- writelog("Out of memory while allocating synch buffer\n");
- exit(1);
- }
- /*
- * Then the for the real thing, the buffers that are filled each sweep
- */
- i=0;
- do
- {
- buf[i] = (char*)malloc(BUFSIZE);
- if (buf[i] == (char *) NULL)
- break;
- else
- i++;
- }
- while (((p_nbuf > 0) && (i < p_nbuf)) /* nbuf parameter given ? */
- || /* Or all memory allocated ? */
- ((p_nbuf <= 0) && (buf[i-1] != (char *) NULL)));
-
- if ((p_nbuf > 0) && (i < p_nbuf)) {
- fprintf(stderr,"Only %d buffers allocated (lower the nbuf parameter)\n",i);
- writelog("Out of memory while allocating buffers\n");
- exit(1);
- }
- if (i < 8) {
- printf("Warning: only %d memory buffers, try freeing up DOS memory !\n",i);
- }
- p_nbuf = i;
-
- printf("Memory used for %d buffers = %dK\n",p_nbuf,
- (int)(((long)BUFSIZE * p_nbuf) / 1024L));
-
- /*
- * Get Disc info
- */
- if (!check_mscdex()) {
- fprintf(stderr,"No CD-ROM extension available!\n");
- writelog("No CD-ROM extension available !\n");
- exit(1);
- }
- retry=0;
- status=GetDiskInfo();
- while (status != 0x0100) {
- printf("Can't get CD-ROM information, status=%x\n", status);
- delay(1000);
- retry++;
- if (retry == 3) {
- fprintf(stderr,"Get CD-ROM information failed\n");
- writelog("Get CD-ROM information failed !\n");
- exit(1);
- }
- status=GetDiskInfo();
- }
- /*
- * Ok, there is a CD-ROM, Get Track information
- */
- track_loc=(DWORD*)malloc(sizeof(DWORD)*(highest-lowest+2));
- if (track_loc==NULL) {
- fprintf(stderr,"Out of memory!\n");
- writelog("Out of memory, while allocating track info buffers\n");
- exit(1);
- }
- track_loc = &track_loc[-lowest];
- track_loc[highest+1]=total_time;
- for (i=lowest; i<=highest; i++) {
- status=GetTrackInfo(i, &loc, &info);
- track_loc[i]=loc;
- }
- /*
- * If it is an interactive session or lots of debug wanted Then
- * Display track info
- */
- for (i=lowest; i<=highest; i++) {
- if (p_debug >= 3 || argc==1) {
- printf("Track %2ld : %02ld:%02ld.%02ld %6ld Len = %ld\n",
- i, (track_loc[i] >> 16) & 0xff,
- (track_loc[i] >> 8) & 0xff,
- track_loc[i] & 0xff, Red2Sierra(track_loc[i]),
- Red2Sierra(track_loc[i+1]) - Red2Sierra(track_loc[i]));
- writelog("Track %2ld : %02ld:%02ld.%02ld %6ld Len = %ld\n",
- i, (track_loc[i] >> 16) & 0xff,
- (track_loc[i] >> 8) & 0xff,
- track_loc[i] & 0xff, Red2Sierra(track_loc[i]),
- Red2Sierra(track_loc[i+1]) - Red2Sierra(track_loc[i]));
- }
- }
- if (p_debug >= 3) {
- printf("Total time : %02ld:%02ld.%02ld\n", (total_time >> 16) & 0xff,
- (total_time >> 8) & 0xff, total_time & 0xff);
- writelog("Total time : %02ld:%02ld.%02ld\n", (total_time >> 16) & 0xff,
- (total_time >> 8) & 0xff, total_time & 0xff);
- }
-
- /*
- * Interactive User interface (it's real simple...)
- */
- if (ask_param) {
- printf("Image filename: ");
- gets(image);
- } else {
- strcpy(image,p_filename);
- }
-
- if (ask_param) {
- printf("(0) CDDA format, (1) WAV format : ");
- key = getch();
- while (key != '0' && key != '1')
- key = getch();
- printf("%c\n", key);
- if (key == '1')
- waveform = 1;
- else
- waveform = 0;
- } else {
- waveform = p_waveform;
- }
-
- if (ask_param) {
- printf("(0) Read Track, (1) Read A to B : ");
- key = getch();
- while (key != '0' && key != '1')
- key = getch();
- printf("%c\n", key);
-
- if (key == '1') {
- read_location("Start location (High sierra or min:sec) : ",&loc);
- read_location("Frame length (Sectors or min:sec) : ",&size);
- } else {
- n = -1;
- while (n == -1) {
- printf("Which track :");
- scanf("%d", &n);
-
- if (n < lowest || n > highest) {
- printf("Illegal track! ->%i<-\n",n);
- n = -1;
- } else {
- loc = Red2Sierra(track_loc[n]);
- size = Red2Sierra(track_loc[n+1]) - Red2Sierra(track_loc[n]);
- }
- }
- }
- } else {
- if (p_track != -1) {
- n = p_track;
- if (n < lowest || n > highest) {
- fprintf(stderr,"Illegal track! ->%i<-\n",n);
- writelog("Illegal track, should be between %d and %d\n",highest,lowest);
- exit(1);
- }
- loc = Red2Sierra(track_loc[n]);
- size = Red2Sierra(track_loc[n+1]) - Red2Sierra(track_loc[n]);
- if (*p_length)
- translate_location(p_length,&size);
- } else {
- translate_location(p_from,&loc);
- translate_location(p_length,&size);
- }
- }
-
- if (size < NBLOCK * p_nbuf)
- size = NBLOCK * 4;
-
- printf("Start location %s\n", location_str(loc));
- printf("Stop location %s\n", location_str(loc+size));
-
-
- /*
- * Create the file
- */
- _fmode = O_BINARY;
- fd = creat(image, S_IREAD|S_IWRITE);
- if (fd == -1) {
- perror("open");
- writelog("Can not open output file %s\n",p_filename);
- exit(1);
- }
-
- /*
- * If a WAV file should be created, write the WAV header
- */
- if (waveform) {
- strcpy(riff.rID, "RIFF");
- riff.rLen = FRAME_SIZE * (DWORD)size + sizeof(struct WAVE);
- strcpy(wave.wID, "WAVE");
- strcpy(wave.fmt.fID, "fmt ");
- wave.fmt.fLen = sizeof(struct FORMAT) - 8;
- wave.fmt.wTag = 1;
- wave.fmt.wChannel = 2;
- wave.fmt.nSample = 44100L;
- wave.fmt.nByte = 44100L * 4;
- wave.fmt.align = 4;
- wave.fmt.sample = 16;
- strcpy(wave.data.dID, "data");
- wave.data.dLen = FRAME_SIZE * (DWORD)size;
- if (write(fd, &riff, sizeof(struct RIFF)) != sizeof(struct RIFF)) {
- perror("write");
- writelog("Can not write wav-header (RIFF) to file %s\n",p_filename);
- exit(1);
- }
- if (write(fd, &wave, sizeof(struct WAVE)) != sizeof(struct WAVE)) {
- perror("write");
- writelog("Can not write wav-header (WAVE) to file %s\n",p_filename);
- exit(1);
- }
- }
-
- /*
- * Here the Reading of the data is done.
- * Read the date in blocks, as much as possible in memory
- * After p_nbuf (default 8) blocks of FRAME_SIZE*NBLOCK are read
- * the data is written to the output file, after synchronizing the
- * position to write it to.
- */
-
- wave.data.dLen = 0L;
- first_time = 1;
- start_pos = loc;
- end_pos = loc+size;
-
- ftime(&ts); /* Starts micro-timer - psyche */
- num_reads=0;
-
- while (loc < end_pos) {
-
- /*
- * Read thos p_nbuf blocks of data in memory first
- */
- for (i=0; (i < p_nbuf); i++) {
-
- printf("\rReading frame %ld to %ld in mem (%ld) buf[%2i] \r",
- loc, loc+NBLOCK-1, end_pos, i);
- if (p_debug >= 3) {
- writelog("Reading frame %ld to %ld in mem (%ld) buf[%2i]\n",
- loc, loc+NBLOCK-1,end_pos,i);
- }
-
- ftime(&tms);
- status = ReadLong(loc, NBLOCK, buf[i]);
- ftime(&tme);
- readtime_min += (1000L*tme.time+tme.millitm)-(1000L*tms.time+tms.millitm);
-
- if (status != 0x0100) {
- fprintf(stderr,"CDROM read status %x\n", status);
- fprintf(stderr,"Your CD-ROM does not support the READ LONG call properly !!\n");
- writelog("CDROM read status %x)\n",status);
- writelog("Your CD-ROM does not support the READ LONG call properly !!\n");
- exit(1);
- }
-
- if (p_swapbytes) { /* Swap bytes option, swap each word's MSB/LSB */
- for (j=0; j < BUFSIZE; j += 2) {
- b = buf[i][j];
- buf[i][j] = buf[i][j+1];
- buf[i][j+1] = b;
- }
- }
-
- if (p_swapwords) { /* Swap words option, swap each two words */
- for (j=0; j < BUFSIZE; j += 4) {
- w = *((WORD *) (&(buf[i][j])));
- *((WORD *) (&(buf[i][j]))) = *((WORD *) (&(buf[i][j+2])));
- *((WORD *) (&(buf[i][j+2]))) = w;
- }
- }
-
- loc += NBLOCK;
- }
-
- offset = 0;
- if (!first_time && !p_nosynch) {
- /*
- * Synchronize data to previous block
- * This is really important !!
- * Some CD-ROM drive do it themselves, but others don't
- * The problem is that if you tell it to read at sector 2034,
- * and after writing the data to the file tell it to read
- * sector 2035, the data is not exactly 'positioned' right.
- * Most of the time there is an offset of something like a 1000
- * bytes. This offset is determined by searching for the matching
- * block of data in the datablock that is read twice.
- */
- synch_size = SYNCH_SIZE; /* Start with the default synch size */
-
- i=BUFSIZE/4;
- while (i < (BUFSIZE-synch_size)) {
- if (memcmp(previous_end,buf[0]+i,synch_size) == 0) {
- if (offset == 0) {
- offset = i; /* Ok, found a matching block */
- /* Continue searching, */
- /* if you find another match it is not right */
- } else {
- /*
- * Shit, found another match
- * Maybe the data coincedently matches another piece of data
- * So, Try a bigger block to compare
- */
- synch_size *= 2;
- if (synch_size > 4096) {
- /*
- * Well, two matches were found,
- * there is however a possibility that this matches are
- * located in dead silence on the CD (like in a gap between tracks)
- * In that case, it is OK, synchronization has NOT failed
- */
- j = offset;
- for (j=offset; j < synch_size; j++) {
- if (*(buf[0]+j) != '\000') {
- fprintf(stderr,"Synchronisation failed,TWO matches found !\n");
- writelog("Sync failed,sync size to big !!\n");
- exit(1);
- }
- }
- offset = BUFSIZE/2; /* Synch=middle of block */
- break;
- }
- i = 0;
- continue;
- }
- }
- i+=4;
- }
-
- if (offset == 0) {
- fprintf(stderr,"Synchronisation failed, no matching block found !!\n");
- writelog("Sync failed,no matching block found !!\n");
- exit(1);
- }
- work_offset = abs(offset - BUFSIZE/2);
-
- if ( work_offset!=0 )
- no_offset++;
-
- if (work_offset < min_offset)
- min_offset = work_offset;
- else
- if (work_offset > max_offset)
- max_offset = work_offset;
-
- avg_offset+=work_offset;
-
- }
-
- first_time = 0;
-
- /*
- * Copy last block, for next read
- */
- memcpy(previous_end,buf[p_nbuf-1]+BUFSIZE/2,BUFSIZE/2);
-
- /*
- * Now write that read blocks to the output file.
- * The first one is written from possition 'offset' in the block
- * The rest of them is written as read from the CD
- * Except the last buffer, of which only half of it is written
- * Stop when the required number of frames are written to the file
- * The way it is programmed now, this could be NBLOCK-1 frames
- * too much, but that is only milliseconds of audio...
- */
- printf("\rSynchronized write frame %ld to %ld to disk, offset = %ld ",
- loc-(p_nbuf*NBLOCK),loc-(NBLOCK/2),
- p_nosynch ? 0 : offset-(BUFSIZE/2));
- fflush(stdout);
- if ( p_debug >=2 )
- writelog("Synchronized write frame %ld to %ld to disk, offset = %ld\n",
- loc-(p_nbuf*NBLOCK),loc-(NBLOCK/2),
- p_nosynch ? 0 : offset-(BUFSIZE/2));
-
-
- for (i=0;(i < ((p_nbuf-1)+ (p_nosynch ? 1 : 0)));i++) {
- if ( write(fd, buf[i]+offset, BUFSIZE-offset) != (BUFSIZE-offset)) {
- perror("write");
- writelog("Error writing data to file %s!!\n",p_filename);
- exit(1);
- }
- wave.data.dLen += (BUFSIZE-offset);
- if (wave.data.dLen > (size * FRAME_SIZE))
- i = p_nbuf; /* Skip the rest */
- offset = 0;
- }
-
- if (wave.data.dLen <= (size * FRAME_SIZE)) {
- /*
- * Write only half of last buffer,
- * The next loop, after synchronisation the rest will be written
- */
-
- if (write(fd, buf[p_nbuf-1], BUFSIZE/2) != (BUFSIZE/2)) {
- perror("write");
- writelog("Error writing data to file %s\n",p_filename);
- exit(1);
- }
- wave.data.dLen += (BUFSIZE/2);
- }
-
- if (!p_nosynch)
- loc -= NBLOCK;
- /* sleep(1); */
- num_reads++;
- }
-
- /*
- * Display timing data
- */
- if ( !p_nosynch )
- loc+=NBLOCK; /* Adjusts for final block count - psyche */
-
- ftime(&te); /**** save end-time ***/
-
- readtime_max=(1000L*te.time+te.millitm)-(1000L*ts.time+ts.millitm);
-
- /*
- * Do all calculations without floats, that saves executable size
- */
- maxtime = ((1000L*(loc-start_pos))/75L+5L)/(readtime_max/100L);
- mintime = ((1000L*(loc-start_pos))/75L+5L)/(readtime_min/100L);
-
- printf("\n\nReading speed was somewhere between %d.%02dx and %d.%02dx.\n",
- (int)(maxtime / 100L),(int)(maxtime % 100L),
- (int)(mintime / 100L),(int)(mintime % 100L));
- writelog("\n\nReading speed was somewhere between %d.%02dx and %d.%02dx.\n",
- (int)(maxtime / 100L),(int)(maxtime % 100L),
- (int)(mintime / 100L),(int)(mintime % 100L));
-
- if (p_nosynch == 2)
- printf("Synchronization not needed.\n");
- else if (!p_nosynch ) {
- if ( min_offset==0 && max_offset==0 ) {
- printf("No synchronization was needed !!!\n");
- printf("Consider using -nosynch for extra performance\n");
- writelog("No synchronization was needed\n");
- } else {
- printf("Synchronization offsets : minimum = %ld%%, maximum = %ld%%, average=%ld%%.\n",
- (100L*min_offset)/FRAME_SIZE,
- (100L*max_offset)/FRAME_SIZE,
- ((100L*avg_offset)/FRAME_SIZE)/num_reads);
- printf("Correction was required on %d%% of all reads (%d of %d)\n",
- 100*(no_offset+1)/num_reads, (no_offset+1), num_reads);
-
- writelog("Synchronization offsets : minimum = %d%%, maximum = %d%%, average=%d%%.\n\
- Correction was required on %d%% of all reads (%d of %d)\n",
- (100L*min_offset)/FRAME_SIZE,
- (100L*max_offset)/FRAME_SIZE,
- ((100L*avg_offset)/FRAME_SIZE)/((end_pos-start_pos)/NBLOCK),
- 100*no_offset/num_reads,
- no_offset, num_reads);
- }
- }
-
- /*
- * Complete the WAV file header in the file
- */
- if (waveform) {
- lseek(fd,0L,SEEK_SET);
- printf("\nCompleting header information of WAV file");
- writelog("Completing header information of WAV file\n");
- riff.rLen = wave.data.dLen + sizeof(struct WAVE);
-
- if (write(fd, &riff, sizeof(struct RIFF)) != sizeof(struct RIFF)) {
- perror("write");
- writelog("Error completing wav-header in file %s\n",p_filename);
- exit(1);
- }
-
- if (write(fd, &wave, sizeof(struct WAVE)) != sizeof(struct WAVE)) {
- perror("write");
- writelog("Error completing wav-header in file %s\n",p_filename);
- exit(1);
- }
- printf(" ... Done.\n");
- }
-
- close(fd);
- writelog("Output file %s complete !\n",p_filename);
-
- /*
- * Not really necessary of course, but it's a good style of programming !
- * Free all those malloc-ed memory blocks
- */
- free(&track_loc[lowest]);
- free(previous_end);
- for (i=0; i< p_nbuf ;i++)
- free(buf[i]);
- }
-