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

📄 read_cdda.c

📁 读取音乐光盘磁道为磁盘文件的程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * $Id: read_cdda.c,v 1.13 1997/10/14 08:46:39 jim Exp $ * Read audio track from a CD using CDDA *  * Written by Jim Mintha (mintha@geog.ubc.ca) * Large portions are borrowed from the Workman  * sources written by Steven Grimm (koreth@hyperion.com) * * $Log: read_cdda.c,v $ * Revision 1.13  1997/10/14 08:46:39  jim * make sure we clean up on exit * * Revision 1.12  1997/10/14 07:32:31  jim * Added -D dev, fixed getopt struct, updated help * * Revision 1.11  1997/10/10 09:22:56  jim * type * * Revision 1.10  1997/10/10 09:09:44  jim * added patches from "Alexander V. Panasyuk" <panasyuk@cfauvcs5.harvard.edu> * * Revision 1.9  1997/10/02 16:57:01  jim * (int) stdout isn't correct, 1 is better * * Revision 1.8  1997/09/10 00:17:07  jim * lots of changes to add jitter control, clean things up * reset block size when done, better output, etc. * * Revision 1.7  1997/08/31 21:36:18  jim * added changes from Andreas Karrer for output to stdout, changed * options a bit. * * Revision 1.6  1996/06/04 23:00:45  jim * Patches from Hans Werner Strube (strube@physik3.gwdg.de) * to open volmgt device if normal open fails.  To allow * output to stdout (- filename) and don't call cdda_init if * just checking drive type. * * Revision 1.5  1996/01/18 14:05:49  jim * Added ability to query drive type * moved some stuff back from header file * * Revision 1.4  1996/01/10 10:05:33  jim * Fixed display on song sectors * * Revision 1.3  1996/01/10 09:53:22  jim * mistake in checking starting time * * Revision 1.2  1996/01/10 09:44:01  jim * Added -q to help * * Revision 1.1  1996/01/10 09:11:32  jim * Initial revision * *//* * Notes: (this is my understanding of things) *  * One CDDA block is 2368 bytes each block contains: * 588 frames and 16bytes for Q data. * Each frame is 4 bytes (presumably 2 16bit values) * 588 * 4 = 2352 + 16 = 2368 * Each frame is 1/44100 th. of a second (44100 Hz) * therefore each block is 1/75 th. of a second * * You can also read without the Q data in which case * each block is only 2352 bytes long. */#include "read_cdda.h"#include "version.h"/* disable X window stuff in my general utilities */NO_X_WIN/* Global variables - yuk *//* * This is the fastest way to convert from BCD to 8-bit. */unsigned char unbcd[256] = {  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  0,0,0,0,0,0, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,  0,0,0,0,0,0, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,  0,0,0,0,0,0, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,  0,0,0,0,0,0, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,  0,0,0,0,0,0, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,  0,0,0,0,0,0, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,  0,0,0,0,0,0, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,  0,0,0,0,0,0, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,  0,0,0,0,0,0, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,  0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};/* where we are and where we want to be */typedef struct {  int length;  int start_block;  int num_blocks;  int mins,secs,frames;} Track;Track tracks[60];boolean verbose = FALSE;unsigned char *ulawmap;int NUM_BLOCKS=150;intmain(int argc, char **argv){  unsigned char *cdda_buf, *cdda_buf2, *temp_buf, *prev_end;  long cddabuf_len, to_write, to_reread, jitter = 0, to_read, to_skip, num_read;  int cd_fd, out_fd, track, fmt = CDR, ch, ctr, want_percent;  int start_block, num_blocks, current_block, num_tracks;  int starting_sec = 0, ending_sec = 0, end_block;  boolean toc = FALSE, swap = FALSE, drv_type = FALSE;  char *device_name = NULL;  extern char *optarg;  extern int optind;  struct option const longopts[] =     {      /* name, has_arg, *flag, val */      { "help", 0, 0, 'h'},      { "start", 1, 0, 's'},      { "end", 1, 0, 'e'},      { "au16", 0, 0, 'a'},      { "au8", 0, 0, '8'},      { "swap", 0, 0, 'x'},      { "buffer", 1, 0, 'b'},      { "verbose", 0, 0, 'v'},      { "toc", 0, 0, 't'},      { "drvtype", 0, 0, 'd'},      { "device", 1, 0, 'D'},      { "version", 0, 0, 'V'},      { NULL, 0, NULL, 0}    };  while((ch = getopt_long(argc, argv, "hs:e:a8xb:vtdD:V",			  longopts, (int *) 0)) != -1)    {      switch(ch)	{	case 'h':   /* help */	  usage(argv[0]);	  break;	case 'v':   /* quiet */	  verbose = TRUE;	  break;	case 't':   /* toc */	  toc = TRUE;	  verbose = TRUE;	  break;	case 'd':   /* drive type */	  drv_type = TRUE;	  break;	case 'D':   /* device */	  device_name = optarg;	  break;	case 'x':   /* swap */	  swap = TRUE;	  break;	case '8':   /* Sun .au 8KHz */	  fmt = AU8;	  break;	case 'a':   /* Sun .au 44.1KHz */	  fmt = AU16;	  break;	case 'w':   /* WAV format */	  fmt = WAV;	  break;	case 'b':   /* Buffer size in blocks */	  sscanf(optarg, "%d", &NUM_BLOCKS);	  if(NUM_BLOCKS < 10 || NUM_BLOCKS > 400)	    pop_error(ERR_GEN, "Buffer size: %d invalid", NUM_BLOCKS);	  break;	case 's':   /* start time */	  sscanf(optarg, "%d", &starting_sec);	  if(starting_sec < 0)	    pop_error(ERR_GEN, "Starting time: %d invalid", starting_sec);	  break;	case 'e':   /* end time */	  sscanf(optarg, "%d", &ending_sec);	  if(ending_sec < 0)	    pop_error(ERR_GEN, "Ending time: %d invalid", ending_sec);	  break;	case 'V':	  fprintf(stderr, "%s\n", version_string);	  fprintf(stderr, "Written by Jim Mintha (mintha@geog.ubc.ca)\n");	  exit(0);	  break;	case '?':	  usage(argv[0]);	  break;	}    }    if(starting_sec > ending_sec && ending_sec != 0)    pop_error(ERR_GEN, "Starting time is after ending time");  if(!toc && !drv_type)    {      if(optind + 2 > argc)	pop_error(ERR_GEN, "Must specify a track and filename\n");            sscanf(argv[optind], "%d", &track);      if(track <= 0 || track > 99)	pop_error(ERR_GEN, "Invalid track specified: %d", track);      if(argv[optind + 1][0] == '-')	out_fd = 1;      else	out_fd = open(argv[optind + 1], O_WRONLY | O_CREAT, 0666);        if(out_fd < 0)	pop_error(ERR_FILE, "Error opening output file: %s", argv[optind + 1]);      if(fmt == AU8 || fmt == AU16)	write_sun_header(out_fd, fmt);    }    if(drv_type)    {      get_drv_type(cd_fd, device_name);      all_done(cd_fd);    }    cd_fd = cdda_init(&cdda_buf, &cdda_buf2, &cddabuf_len, device_name);  num_tracks = read_toc(cd_fd, toc);  if(toc)    all_done(cd_fd);  if(track > num_tracks)    pop_error(ERR_GEN, "Invalid track specified: %d", track);  if(verbose)    fprintf(stderr, "\nWriting track %d to %s\n", track, argv[optind + 1]);  if(starting_sec * 75 > tracks[track].num_blocks ||     ending_sec * 75 > tracks[track].num_blocks)    pop_error(ERR_GEN, "Start/End times too long\n");    start_block = tracks[track].start_block + starting_sec * 75;  num_blocks = tracks[track].num_blocks - starting_sec * 75;  end_block = start_block + num_blocks;  current_block = start_block;  want_percent = 10;  if(ending_sec != 0)    {      end_block = tracks[track].start_block + ending_sec * 75;      num_blocks = end_block - num_blocks;    }  else    ending_sec = tracks[track].length;  if(verbose)    {      fprintf(stderr, "Song is sectors: %d to %d\n", tracks[track].start_block, 	      tracks[track].start_block + tracks[track].num_blocks);            fprintf(stderr, "Recording sectors: %d to %d\n", start_block, end_block);      fprintf(stderr, "Song start time: %02d:%02d  end time: %02d:%02d\n",	     starting_sec / 60, starting_sec % 60,	     ending_sec / 60, ending_sec % 60);    }  /*   * Okay - now we do the actual reading.   *   */  while(current_block < end_block)    {      to_reread = REREAD_BLKS;      to_read = NUM_BLOCKS;            if((current_block - start_block) * 100 / num_blocks >= want_percent && verbose)	{	  fprintf(stderr, "%02d%% ", want_percent);	  while(want_percent <= (current_block - start_block) * 100 / num_blocks)	    want_percent += 10;	}      	      if(current_block == start_block)	to_reread = 0;            if(end_block - (current_block - to_reread) < to_read)	to_read = end_block - (current_block - to_reread);      /*      printf("Current block: %d\n",current_block);      printf("to_read %d\n",to_read);      */      num_read = cdda_read(cd_fd, cdda_buf, to_read, current_block - to_reread);      if(num_read != to_read)	pop_error(ERR_GEN, "Error reading CD");      if(current_block == start_block) 	{	  to_skip = 0;	  to_write = to_read;	}      else	{	  jitter = calc_jitter(cdda_buf, prev_end, to_read);	  /*	  printf("jitter %d\n", jitter - (CDDA_BLKSIZE * (REREAD_BLKS - COMPARE_BLKS)));*/	  to_skip = jitter + CDDA_BLKSIZE * COMPARE_BLKS;	  to_write = to_read - to_reread;	  	  /* don't write more than we read */	  while(to_skip + to_write * CDDA_BLKSIZE > to_read * CDDA_BLKSIZE)	    to_write--;	  	  /* don't write more than the length of track */	  if(to_write + current_block > end_block)	    to_write = end_block - current_block;	  	  /* if necessary add a padded block at end */	  if(to_write == 0)	    {	      current_block = end_block - 1;	      to_write = 1;	      for(ctr = CDDA_BLKSIZE - (to_skip % CDDA_BLKSIZE); ctr < CDDA_BLKSIZE; ctr++)		cdda_buf[to_skip + ctr] = 0;	    }	}            cdda_write(out_fd, cdda_buf + to_skip, CDDA_BLKSIZE * to_write, swap, fmt);      prev_end = cdda_buf + to_skip + to_write * CDDA_BLKSIZE;      temp_buf = cdda_buf;      cdda_buf = cdda_buf2;      cdda_buf2 = temp_buf;      current_block += to_write;   }  if(verbose)    fprintf(stderr, "100%%\nAll Done.\n");  all_done(cd_fd);}/* * calculate jitter (see explanation before cdda_read) * compare 128 frames or 512 bytes */longcalc_jitter(unsigned char *buf, unsigned char *last, int to_read){  int offset;    for(offset = CDDA_BLKSIZE * (REREAD_BLKS - COMPARE_BLKS);      offset >= 0; offset -= SAMPLE)    {      if(!memcmp(last - CDDA_BLKSIZE * COMPARE_BLKS,		 buf + offset, CDDA_BLKSIZE * COMPARE_BLKS))	return offset;    }    for(offset = CDDA_BLKSIZE * (REREAD_BLKS - COMPARE_BLKS);      offset < to_read * CDDA_BLKSIZE; offset += SAMPLE)    {      if(!memcmp(last - CDDA_BLKSIZE * COMPARE_BLKS,		 buf + offset, CDDA_BLKSIZE * COMPARE_BLKS))	return offset;    }    fprintf(stderr, "Jitter Control Failed!!\n");  return CDDA_BLKSIZE * (REREAD_BLKS - COMPARE_BLKS);}    /* * Initialize CDDA data buffer and open device. */

⌨️ 快捷键说明

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