⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 readcda.c

📁 直接读取CD内容的程序
💻 C
字号:
/*

  GOAL:
    This program is intended to read CD audio data into a disk file.

  Author:
    Yeng-Chee Su (yenchee@csie.nctu.edu.tw)
    Department of Computer Science and Information Engineering
    National Chiao Tung University
    &
    Klaas Hemstra (hst@mh.nl)
    Gouda, the Netherlands

  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.

*/

#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
#define NBUF   10
#define SYNCH_SIZE 128  /* Bytes synch pattern */

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, &reg, &reg, &seg);
}

int check_mscdex(void)
{
  union REGS reg;

  reg.x.ax=0x1500;
  reg.x.bx=0;
  int86(0x2f, &reg, &reg);
  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
read_location(char *question,DWORD *loc)
{
#define MAX_LOC 256
    char buf[MAX_LOC],*p;
    buf[0] = '\0';

    while (buf[0] == '\0') {
	printf("%s",question);
	fgets(buf,MAX_LOC,stdin);
    }
    for (p=buf;*p && (*p != ':'); p++)
      ;
    if (*p == ':') {
      *loc = atol(buf)*75L*60L+atol(p+1)*75L;
    } else {
      *loc = atol(buf);
    }
}


void main()
{
  WORD status;
  char *buf[NBUF],*previous_end;
  DWORD *track_loc, loc, end_pos, size;
  DWORD i, j, offset,synch_size;
  BYTE info;
  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;

  printf("CD-ROM digital audio data extractor, Ver 1.1\n");
  printf(" written by Yeng-Chee Su, CSIE, NCTU & Klaas Hemstra (hst@mh.nl)\n");
  printf("\n");

   /*
    * Allocate memory buffers
   */
  for (i=0; i< NBUF; i++)
    buf[i] = (char*)malloc((long)FRAME_SIZE * NBLOCK);
    if (buf[i] == NULL) {
      printf("Out of memory!\n");
      exit(1);
    }
  previous_end = (char*)malloc((long)FRAME_SIZE * NBLOCK);
  if (previous_end == (char *) NULL) {
    printf("Out of memory!\n");
    exit(1);
  }

   /*
    * Get Disc info
   */
  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);

   /*
    * User interface
   */
  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("(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 {
track_again:
    printf("Which track :");
    scanf("%d", &n);
    if (n < lowest || n > highest) {
      printf("illega track!\n");
      goto track_again;
    }
    loc = Red2Sierra(track_loc[n]);
    size = Red2Sierra(track_loc[n+1]) - Red2Sierra(track_loc[n]);
  }
  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");
    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);
    }
  }

   /*
    * Read the date in blocks, first in memory
   */
  wave.data.dLen = 0L;
  first_time = 1;
  end_pos = loc+size;
  while (loc < end_pos) {

    for (i=0;(i < NBUF);i++) {
      printf("\rReading frame %ld to %ld in memory                          \r",
                                                               loc, loc+NBLOCK-1);
      status = ReadLong(loc, NBLOCK, buf[i]);
      if (status != 0x0100) {
        printf("CDROM read with status %x\n", status);
	exit(1);
      }
      loc += NBLOCK;
    }

    if (first_time == 0) {
      /*
       * Synchronize data to previous block
      */
      offset = 0;
      synch_size = SYNCH_SIZE;
      while (offset == 0) {
        for (i=(NBLOCK/4)*FRAME_SIZE;
             i < (((unsigned int)NBLOCK*FRAME_SIZE)-synch_size);
	     i+=4) {
	  if (memcmp(previous_end+(NBLOCK/2)*FRAME_SIZE,buf[0]+i,synch_size) == 0) {
	    if (offset == 0)
	      offset = i;
	    else {
	      synch_size *= 2;
	      if (synch_size > 4096) {
		fprintf(stderr,"Synchronisation failed, synch size to big !!\n");
		exit(1);
	      }
	      break;
	    }
	  }
	}
	if (offset == 0) {
	  fprintf(stderr,"Synchronisation failed, no matching block found !!\n");
	  exit(1);
	}
      }
    }
    else
      offset = 0;

    first_time = 0;

    memcpy(previous_end,buf[NBUF-1],(long)FRAME_SIZE*NBLOCK);

    printf("\rSynchronized write frame %ld to %ld to disk, offset = %ld    ",
		loc-(NBUF*NBLOCK),loc-(NBLOCK/2),offset-(NBLOCK/2*FRAME_SIZE));

    for (i=0;(i < NBUF-1);i++) {
      if (write(fd, buf[i]+offset, ((long) FRAME_SIZE * NBLOCK)-offset) == -1) {
	perror("write");
	exit(1);
      }
      wave.data.dLen += (((long) FRAME_SIZE * NBLOCK)-offset);
      offset = 0;
    }

       /*
        * Write only half of last buffer,
        * The next loop, after synchronisation the rest will be written
       */

    if (write(fd, buf[NBUF-1], ((long) FRAME_SIZE * (NBLOCK/2))) == -1) {
      perror("write");
      exit(1);
    }
    wave.data.dLen += ((long) FRAME_SIZE * (NBLOCK/2));

    loc -= NBLOCK;
    /* sleep(1); */
  }

  if (waveform) {
    lseek(fd,0L,SEEK_SET);
    printf("\nCompleting 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");
      exit(1);
    }
    if (write(fd, &wave, sizeof(struct WAVE)) != sizeof(struct WAVE)) {
      perror("write");
      exit(1);
    }
  }

  close(fd);
  free(&track_loc[lowest]);
  free(buf);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -