Please consider a donation to the Higher Intellect project. See https://preterhuman.net/donate.php or the Donate to Higher Intellect page for more info. |
CDDA.C
Revision as of 11:48, 23 July 2020 by Netfreak (talk | contribs) (Created page with "<pre> /* From [email protected] (Yeng-Chee Su) I've written a program which can read CDDA data from audio CD and make them as Microsoft Windows WAV format o...")
/* From [email protected] (Yeng-Chee Su) I've written a program which can read CDDA data from audio CD and make them as Microsoft Windows WAV format on disk. This works on Panasonic CR-562B/563B. Any commect/suggest/flame welcomed. It should be compiled on Turbo C/Borland C on any memory model. GOAL: This program is intended to read CD raw data into disk file. Author: Yeng-Chee Su Department of Computer Science and Information Engineering National Chiao Tung University 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. Since the current driver doesn't have callback facility, the speed of file system is very important for timing constrain. If your system doesn't be fast enough, you will hear a glitch periodically. To increase the cache size of smartdrv delayed write buffer will release the timing a little but not totally solved. I'm still looking for a callback driver. */ #include <stdio.h> #include <stdlib.h> #include <conio.h> #include <dos.h> #include <dir.h> #include <string.h> #include <ctype.h> #include <fcntl.h> #include <sys/stat.h> #include <io.h> #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 #define NBLOCK 16 typedef unsigned char BYTE; typedef unsigned int WORD; typedef unsigned long int DWORD; 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; } void main() { WORD status; char *buf; DWORD *track_loc, loc, size; DWORD i, j; BYTE info; int fd, key, n; 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; printf("CD-ROM digital audio data extractor, Ver 1.0\n"); printf(" written by Yeng-Chee Su, CSIE, NCTU\n"); printf("\n"); buf = (char*)malloc((long)FRAME_SIZE * NBLOCK); if (buf == NULL) { printf("Out of memory!\n"); exit(1); } if (!check_mscdex()) { printf("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) { printf("Get CD-ROM information failed\n"); exit(1); } status=GetDiskInfo(); } track_loc=(DWORD*)malloc(sizeof(DWORD)*(highest-lowest+2)); if (track_loc==NULL) { printf("Out of memory!\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; } for (i=lowest; i<=highest; i++) 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])); printf("Total time : %02ld:%02ld.%02ld\n", (total_time >> 16) & 0xff, (total_time >> 8) & 0xff, total_time & 0xff); printf("Image filename:"); gets(image); 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; /* printf("Start location (High Sierra format) :"); scanf("%ld", &loc); printf("Frame length :"); scanf("%ld", &size); printf("Stop location (High Sierra format): %ld\n", loc+size); */ again: printf("Which track :"); scanf("%d", &n); if (n < lowest || n > highest) { printf("illega track!\n"); goto again; } loc = Red2Sierra(track_loc[n]); size = Red2Sierra(track_loc[n+1]) - Red2Sierra(track_loc[n]); printf("Start location (High Sierra format) : %ld\n", loc); printf("Stop location (High Sierra format) : %ld\n", loc+size); _fmode = O_BINARY; fd = creat(image, S_IREAD|S_IWRITE); if (fd == -1) { perror("open"); exit(1); } 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"); exit(1); } if (write(fd, &wave, sizeof(struct WAVE)) != sizeof(struct WAVE)) { perror("write"); exit(1); } } if (size > NBLOCK) i = NBLOCK; else i = size; printf("Reading frame %ld to %ld\r", loc, loc+i-1); status = ReadLong(loc, i, buf); if (status != 0x0100) { printf("CDROM read with status %x\n", status); exit(1); } loc += i; size -= i; while (size > 0) { if (size > NBLOCK) j = NBLOCK; else j = size; if (write(fd, buf, FRAME_SIZE * i) == -1) { perror("write"); exit(1); } i = j; printf("Reading frame %ld to %ld\r", loc, loc+i-1); status = ReadLong(loc, i, buf); if (status != 0x0100) { printf("CDROM read failed with status %x\n", status); exit(1); } loc += i; size -= i; } if (write(fd, buf, FRAME_SIZE * i) == -1) { perror("write"); exit(1); } close(fd); free(&track_loc[lowest]); free(buf); } -- ________________________________________________________________________ / National Chiao Tung University in Taiwan / \ | Name: Yeng-Chee Su Dept: Computer Engineering |__/ | Phone: +886-35-783513 E-mail: [email protected] | | Address: 22, Alley 2, Lane 173, Gao Tsui Road, HsinChu, Taiwan 300 |___ \______________________________________________________________________\__/ +++ Dep. Computer Sci. & Information Eng., Chiao Tung Univ., Taiwan, R.O.C -!- uugate 0.31 (OS/2 2.10) ! Origin: Internet gateway (cindy) (2:200/427.3)