2000 /* DAGRABX grabs 16 bit 44.1 KHz CD Audio digitally to a file */ /* This version uses XMS as an intermediate buffer to avoid */ /* the "glitches" that otherwise occur */ #include #include #include #include #include #include #include #define FALSE 0 #define TRUE 1 int cdrom_loaded, cdrom_drive; struct EMMMoveStruct moverec; unsigned int xmshandle, xmsfree,xmstot; struct readlong_struc readlong_block; struct ioctl_struc ioctl_block; struct diskinfo_struc diskinfo_block; struct trackinfo_struc trackinfo_block[100]; unsigned long red2hsg(unsigned long redval); int *buffer; struct wavhdr_str { unsigned char riff[4]; unsigned long riff_len; unsigned char wave[4]; unsigned char fmt[4]; unsigned long fmt_len; unsigned int fmt_tag; unsigned int channels; unsigned long smp_sec; unsigned long avg_smp_sec; unsigned int blk_align; unsigned int bits_per_sample; unsigned char data[4]; unsigned long smpdata_len; } wavhdr; main(int argc, char *argv[]) { struct dfree diskfree; long avail; int drive; unsigned long start_sect, end_sect, start_sect2; unsigned int num_sect, num_sect2, sects_to_grab, sects_to_write,i,j,k,offs; unsigned char filename[80]; FILE *outfp; int track, start_min, start_sec, start_frame, end_min, end_sec, end_frame; char local_buffer[132]; char c = ':'; if(argc > 3) { if (! check_cd2f()){ printf("MSCDEX NOT LOADED\n"); exit(1); } if(!XMS_Setup()) { printf("No XMS handler installed!\n"); exit(1); } while(get_diskinfo() != STAT_DONE); for(i = diskinfo_block.low_track; i <= diskinfo_block.high_track; i++) get_trackinfo(i); track = atoi(argv[1]); if( (track < 1) || (track > diskinfo_block.high_track)) { printf("Error: Track must be between %d and %d\n", diskinfo_block.low_track, diskinfo_block.high_track); errexit(); } start_min = 0; start_sec = 0; start_frame = 0; end_min = 0; end_sec = 0; end_frame = 0; strcpy(local_buffer, argv[2]); start_min = atoi(strtok(local_buffer, ":")); start_sec = atoi(strtok(NULL, ":")); start_frame = atoi(&local_buffer[strrchr(argv[2],c)+1-local_buffer]); strcpy(local_buffer, argv[3]); end_min = atoi(strtok(local_buffer, ":")); end_sec = atoi(strtok(NULL, ":")); end_frame = atoi(&local_buffer[strrchr(argv[3],c)+1-local_buffer]); start_sect = red2hsg(trackinfo_block[track].start_point)+(start_min*60L+((long)start_sec))*75L+((long)start_frame) -150L; end_sect = red2hsg(trackinfo_block[track].start_point)+(end_min*60L+((long)end_sec))*75L+((long)end_frame) -150L; num_sect = (unsigned int)(end_sect-start_sect); num_sect2 = num_sect; start_sect2 = start_sect; printf("Start sector : %ld\n", start_sect); printf("End sector : %ld\n", end_sect); printf("Number of sectors: %d\n", num_sect); printf("CDDA data size : %ld bytes\n", ((unsigned long)num_sect)*2352L); if(argc > 4) { if((buffer = malloc(59000)) == NULL){ printf("Malloc error!\n"); errexit(); } XMS_FreeMem(&xmsfree,&xmstot); XMS_AllocEMB(xmsfree,&xmshandle); if(xmsfree < ((unsigned long)num_sect)*2352L/1024L) { printf("Not enough XMS memory!\n"); errexit(); } drive = getdisk(); getdfree(drive+1,&diskfree); avail = (long) diskfree.df_avail * (long) diskfree.df_bsec * (long) diskfree.df_sclus; if(avail < ((unsigned long)num_sect)*2352L) { printf("Not enough disk space!\n"); errexit(); } strcpy(filename,argv[4]); outfp = fopen(filename,"wb"); if(strstr(strupr(filename), ".WAV")) { strncpy(wavhdr.riff, "RIFF", 4); strncpy(wavhdr.wave, "WAVE", 4); strncpy(wavhdr.fmt, "fmt ", 4); wavhdr.fmt_len = 0x10L; wavhdr.fmt_tag = 0x01; wavhdr.channels = 0x02; wavhdr.smp_sec = 44100L; wavhdr.avg_smp_sec = 44100L; wavhdr.blk_align = 0x02; wavhdr.bits_per_sample = 16; strncpy(wavhdr.data, "data", 4); wavhdr.smpdata_len = ((unsigned long)num_sect)*2352L; wavhdr.riff_len = wavhdr.smpdata_len + 36L; fwrite(&wavhdr, sizeof(wavhdr), 1,outfp); } moverec.TLen = 58800L; /* 2352 bytes * 25 sectors */ moverec.SHand = 0; moverec.SOff = (unsigned long)buffer; moverec.DHand = xmshandle; moverec.DOff = 0L; do{ sects_to_grab = 25; if(num_sect2 < 25) { sects_to_grab = num_sect2; moverec.TLen = (unsigned long)(sects_to_grab*2352); } read_long(start_sect2, sects_to_grab); while(readlong_block.req_hdr.status & STAT_HAS_AN_ERROR) read_long(start_sect2, sects_to_grab); XMS_MoveEMB(&moverec); start_sect2 += 25; num_sect2 -= 25; moverec.DOff += 58800L; } while ((int)num_sect2 > 0); moverec.TLen = 58800; moverec.SHand = xmshandle; moverec.SOff = 0L; moverec.DHand = 0; moverec.DOff = (unsigned long)buffer; do { sects_to_write = 25; if(num_sect < 25) { sects_to_write = num_sect; moverec.TLen = (unsigned long)(sects_to_write*2352); } XMS_MoveEMB(&moverec); fwrite(buffer,2,1176*sects_to_write,outfp); moverec.SOff += 58800L; num_sect -= 25; } while ((int)num_sect > 0); fclose(outfp); free(buffer); XMS_FreeEMB(xmshandle); } else { printf("\nPlaying only...\n"); play(start_sect, (unsigned long)num_sect); } } else { printf("DAGRAB CD-DA Audio grabber v0.1\n"); printf("usage: dagrab []\n"); } } check_cd2f() { union REGS regs; regs.x.ax = INIT_MP_INT; int86(MULTIPLEX_INT,®s,®s); cdrom_loaded = regs.x.bx; cdrom_drive = regs.x.cx; } get_diskinfo() { union REGS regs; struct SREGS sregs; diskinfo_block.cntrl_code = GET_AUDIO_DISKINFO; ioctl_block.req_hdr.param_length = 13; ioctl_block.req_hdr.sub_unit = 0; ioctl_block.req_hdr.command_code = READ_IOCTL_COMMAND; ioctl_block.req_hdr.status = 0; ioctl_block.med_descr = 0; ioctl_block.transf_addr = (unsigned long)&diskinfo_block; ioctl_block.num_bytes = 7; ioctl_block.start_sect = 0; ioctl_block.vol_id = 0; regs.x.ax = CDREQ_MP_INT; regs.x.bx = FP_OFF(&ioctl_block); regs.x.cx = cdrom_drive; sregs.es = FP_SEG(&ioctl_block); int86x(MULTIPLEX_INT,®s,®s,&sregs); return(ioctl_block.req_hdr.status); } get_trackinfo(unsigned char trk) { union REGS regs; struct SREGS sregs; trackinfo_block[trk].cntrl_code = GET_AUDIO_TRACKINFO; trackinfo_block[trk].track_num = trk; ioctl_block.req_hdr.param_length = 13; ioctl_block.req_hdr.sub_unit = 0; ioctl_block.req_hdr.command_code = READ_IOCTL_COMMAND; ioctl_block.req_hdr.status = 0; ioctl_block.med_descr = 0; ioctl_block.transf_addr = (unsigned long)&(trackinfo_block[trk]); ioctl_block.num_bytes = 7; ioctl_block.start_sect = 0; ioctl_block.vol_id = 0; regs.x.ax = CDREQ_MP_INT; regs.x.bx = FP_OFF(&ioctl_block); regs.x.cx = cdrom_drive; sregs.es = FP_SEG(&ioctl_block); int86x(MULTIPLEX_INT,®s,®s,&sregs); return(ioctl_block.req_hdr.status); } play(unsigned long ssec,unsigned long numsecs) { union REGS regs; struct SREGS sregs; struct play_struc play_block; struct qinfo_struc qinfo_block; play_block.req_hdr.param_length = 13; play_block.req_hdr.sub_unit = 0; play_block.req_hdr.command_code = CD_PLAY_AUDIO; play_block.req_hdr.status = 0; play_block.address_mode = ADDR_HSG; play_block.start_sect = ssec; play_block.num_sect = numsecs; regs.x.ax = CDREQ_MP_INT; regs.x.bx = FP_OFF(&play_block); regs.x.cx = cdrom_drive; sregs.es = FP_SEG(&play_block); int86x(MULTIPLEX_INT,®s,®s,&sregs); do { qinfo_block.cntrl_code = GET_QCHAN_INFO; ioctl_block.req_hdr.param_length = 13; ioctl_block.req_hdr.sub_unit = 0; ioctl_block.req_hdr.command_code = READ_IOCTL_COMMAND 821 ; ioctl_block.req_hdr.status = 0; ioctl_block.med_descr = 0; ioctl_block.transf_addr = (unsigned long)&qinfo_block; ioctl_block.num_bytes = 11; ioctl_block.start_sect = 0; ioctl_block.vol_id = 0; regs.x.ax = CDREQ_MP_INT; regs.x.bx = FP_OFF(&ioctl_block); regs.x.cx = cdrom_drive; sregs.es = FP_SEG(&ioctl_block); int86x(MULTIPLEX_INT,®s,®s,&sregs); if(kbhit()){ getch(); stop(); break; } } while (ioctl_block.req_hdr.status & STAT_BUSY); } stop() { union REGS regs; struct SREGS sregs; struct reqhdr_struc stop_block; stop_block.param_length = 13; stop_block.sub_unit = 0; stop_block.command_code = CD_STOP_AUDIO; stop_block.status = 0; regs.x.ax = CDREQ_MP_INT; regs.x.bx = FP_OFF(&stop_block); regs.x.cx = cdrom_drive; sregs.es = FP_SEG(&stop_block); int86x(MULTIPLEX_INT,®s,®s,&sregs); return(stop_block.status); } read_long(unsigned long ssec,unsigned int numsecs) { union REGS regs; struct SREGS sregs; readlong_block.req_hdr.param_length = 13; readlong_block.req_hdr.sub_unit = 0; readlong_block.req_hdr.command_code = CD_READ_LONG; readlong_block.req_hdr.status = 0; readlong_block.address_mode = ADDR_HSG; readlong_block.transf_addr = (int far*)buffer; readlong_block.num_sect = numsecs; readlong_block.start_sect = ssec; readlong_block.read_mode = RAW; readlong_block.interl_size = 0; readlong_block.interl_skip = 0; regs.x.ax = CDREQ_MP_INT; regs.x.bx = FP_OFF(&readlong_block); regs.x.cx = cdrom_drive; sregs.es = FP_SEG(&readlong_block); int86x(MULTIPLEX_INT,®s,®s,&sregs); return(readlong_block.req_hdr.status); } unsigned long red2hsg(unsigned long redval) { unsigned long mins; unsigned long secs; unsigned long plus_frames; plus_frames = redval & 0x000000ffL; secs = ((redval & 0x0000ff00L) >> 8); mins = ((redval & 0x00ff0000L) >> 16); return((mins*60+secs)*75+plus_frames); } errexit() { XMS_FreeEMB(xmshandle); exit(1); } . 0