📄 cdda2wav.c
字号:
fprintf(stderr, "overlap:min/max/cur, jitter, percent_done:\n??/??/??/??????? 0%%"); \ else \ fputs("percent_done:\n 0%", stderr); \ }#if defined HAVE_FORK_AND_SHAREDMEMstatic void forked_read __PR((void));/* This function does all audio cdrom reads * until there is nothing more to do */static voidforked_read(){ unsigned total_unsuccessful_retries = 0;#if !defined(HAVE_SEMGET) || !defined(USE_SEMAPHORES) init_child();#endif minover = global.nsectors; PRINT_OVERLAP_INIT while (global.iloop) { do_read(get_next_buffer(), &total_unsuccessful_retries); define_buffer(); } /* while (global.iloop) */ flush_buffers(); if (total_unsuccessful_retries) { fprintf(stderr,"%u unsuccessful matches while reading\n",total_unsuccessful_retries); }}static void forked_write __PR((void));static voidforked_write(){ /* don't need these anymore. Good security policy says we get rid of them ASAP */ neverneedroot(); neverneedgroup();#if defined(HAVE_SEMGET) && defined(USE_SEMAPHORES)#else init_parent();#endif while (nSamplesDone < nSamplesToDo) { /* get oldest buffers */ nSamplesDone = do_write(get_oldest_buffer()); if (global.parent_died == 0) { drop_buffer(); } } /* end while */ if (global.verbose) { if (global.tracktitle[current_track -1] != NULL) { fprintf( stderr, " track %2u '%s' successfully recorded\n", current_track, global.tracktitle[current_track-1]); } else { fprintf( stderr, " track %2u successfully recorded\n", current_track); } }}#else/* This function implements the read and write calls in one loop (in case * there is no fork/thread_create system call). * This means reads and writes have to wait for each other to complete. */static void nonforked_loop __PR((void));static voidnonforked_loop(){ unsigned total_unsuccessful_retries = 0; minover = global.nsectors; PRINT_OVERLAP_INIT while (global.iloop) { do_read(get_next_buffer(), &total_unsuccessful_retries); do_write(get_oldest_buffer()); } if (total_unsuccessful_retries) { fprintf(stderr,"%u unsuccessful matches while reading\n",total_unsuccessful_retries); } if (global.verbose) { if (global.tracktitle[current_track -1] != NULL) { fprintf( stderr, " track %2u '%s' successfully recorded\n", current_track, global.tracktitle[current_track-1]); } else { fprintf( stderr, " track %2u successfully recorded\n", current_track); } }}#endif/* and finally: the MAIN program */int main( argc, argv ) int argc; char *argv [];{ long lSector_p1; long sector_offset = 0; unsigned long endtrack = 1; double rectime = DURATION; int cd_index = -1; double int_part; int littleendian = -1; int just_the_toc = 0; char int_name[100];#ifdef ECHO_TO_SOUNDCARD static char user_sound_device[200] = "";#endif /* ECHO_TO_SOUNDCARD */ int c;#ifdef USE_GETOPT_LONG int long_option_index=0;#endif /* USE_GETOPT_LONG */ int am_i_cdda2wav; char * env_p; int tracks_included; strcpy(int_name, DEF_INTERFACE); strcpy(audio_type, AUDIOTYPE); save_args(argc, argv); /* init global variables */ init_globals(); /* When being invoked as list_audio_tracks, just dump a list of audio tracks. */ am_i_cdda2wav = strcmp(argv[0],"list_audio_tracks"); if (!am_i_cdda2wav) global.verbose = SHOW_JUSTAUDIOTRACKS; /* Control those set-id privileges... */ initsecurity(); env_p = getenv("CDDA_DEVICE"); if (env_p != NULL) { strncpy( global.dev_name, env_p, sizeof(global.dev_name) ); global.dev_name[sizeof(global.dev_name)-1]=0; } /* command options parsing */#ifdef USE_GETOPT_LONG while ( (c = getopt_long (argc,argv,optstring,options,&long_option_index)) != EOF)#else while ( (c = getopt(argc, argv, optstring)) != EOF )#endif /* USE_GETOPT_LONG */ { switch (c) { case 'D': /* override device */ strncpy( global.dev_name, optarg, sizeof(global.dev_name) ); global.dev_name[sizeof(global.dev_name)-1]=0; break; case 'A': /* override device */ strncpy( global.aux_name, optarg, sizeof(global.aux_name) ); global.aux_name[sizeof(global.aux_name)-1]=0; break; case 'I': /* override interface */ strncpy( int_name, optarg, sizeof(int_name) ); int_name[sizeof(int_name)-1]=0; break;#ifdef ECHO_TO_SOUNDCARD case 'K': /* override sound device */ strncpy( user_sound_device, optarg, sizeof(user_sound_device) ); user_sound_device[sizeof(user_sound_device)-1]=0; break;#endif /* ECHO_TO_SOUNDCARD */ /* the following options are relevant to 'cdda2wav' only */#ifdef MD5_SIGNATURES case 'M': if (!am_i_cdda2wav) break; global.md5blocksize = strtoul( optarg, NULL, 10 ); break;#endif case 'O': /* override audio type */ if (!am_i_cdda2wav) break; strncpy( audio_type, optarg, 4); audio_type[sizeof(audio_type)-1]=0; break; case 'C': /* override input endianess */ if (!am_i_cdda2wav) break; if (strcasecmp(optarg, "little") == 0) { littleendian = 1; } else if (strcasecmp(optarg, "big") == 0) { littleendian = 0; } else if (strcasecmp(optarg, "guess") == 0) { littleendian = -2; } else { usage2("wrong parameter '%s' for option -C", optarg); } break; case 'E': /* override output endianess */ if (!am_i_cdda2wav) break; if (strcasecmp(optarg, "little") == 0) { global.outputendianess = LITTLE; } else if (strcasecmp(optarg, "big") == 0) { global.outputendianess = BIG; } else { usage2("wrong parameter '%s' for option -E", optarg); } break; case 'c': /* override channels */ if (!am_i_cdda2wav) break; if (optarg[0] == 's') { global.channels = 2; global.swapchannels = 1; } else { global.channels = strtol( optarg, NULL, 10); } break; case 'S': /* override drive speed */ if (!am_i_cdda2wav) break; global.userspeed = strtoul( optarg, NULL, 10); break; case 'l': /* install a ring buffer with 'buffers' elements */ if (!am_i_cdda2wav) break; global.buffers = strtoul( optarg, NULL, 10); break; case 'b': /* override bits */ if (!am_i_cdda2wav) break; bits = strtol( optarg, NULL, 10); break; case 'r': /* override rate */ if (!am_i_cdda2wav) break; rate = strtol( optarg, NULL, 10); break; case 'a': /* override rate */ if (!am_i_cdda2wav) break; if (strtod( optarg, NULL ) != 0.0) rate = 44100.0 / strtod( optarg, NULL ); else { fprintf(stderr, "-a requires a nonzero, positive divider.\n"); exit ( 1 ); } break; case 't': /* override start track */ if (!am_i_cdda2wav) break; { char * endptr; char * endptr2; track = strtoul( optarg, &endptr, 10 ); endtrack = strtoul( endptr, &endptr2, 10 ); if (endptr2 == endptr) endtrack = track; break; } case 'i': /* override start index */ if (!am_i_cdda2wav) break; cd_index = strtoul( optarg, NULL, 10); break; case 'd': /* override recording time */ if (!am_i_cdda2wav) break; /* we accept multiple formats now */ { char *end_ptr = NULL; rectime = strtod( optarg, &end_ptr ); if (*end_ptr == '\0') { } else if (*end_ptr == 'f') { rectime = rectime / 75.0; /* TODO: add an absolute end of recording. */#if 0 } else if (*end_ptr == 'F') { rectime = rectime / 75.0;#endif } else rectime = -1.0; } break; case 'o': /* override offset */ if (!am_i_cdda2wav) break; sector_offset = strtol( optarg, NULL, 10); break; case 'n': /* read sectors per request */ if (!am_i_cdda2wav) break; global.nsectors = strtoul( optarg, NULL, 10); break; /*-------------- RS 98 -------------*/ case 'p': /* specify playback pitch rate */ global.playback_rate = strtol( optarg, NULL, 10); RestrictPlaybackRate( global.playback_rate ); global.need_hostorder = 1; break; case 'P': /* set initial overlap sectors */ if (!am_i_cdda2wav) break; global.useroverlap = strtol( optarg, NULL, 10); break; case 's': /* stereo */ if (!am_i_cdda2wav) break; global.channels = 2; break; case 'm': /* mono */ if (!am_i_cdda2wav) break; global.channels = 1; global.need_hostorder = 1; break; case 'x': /* max */ if (!am_i_cdda2wav) break; global.channels = 2; bits = 16; rate = 44100; break; case 'w': /* wait for some audio intensity */ if (!am_i_cdda2wav) break; waitforsignal = 1; break; case 'F': /* find extreme amplitudes */ if (!am_i_cdda2wav) break; global.findminmax = 1; global.need_hostorder = 1; break; case 'G': /* find if mono */ if (!am_i_cdda2wav) break; global.findmono = 1; break; case 'e': /* echo to soundcard */ if (!am_i_cdda2wav) break;#ifdef ECHO_TO_SOUNDCARD global.echo = 1; global.need_hostorder = 1;#else fprintf(stderr, "There is no sound support compiled into %s.\n",argv[0]);#endif break; case 'v': /* tell us more */ if (!am_i_cdda2wav) break; global.verbose = strtol( optarg, NULL, 10); break; case 'q': /* be quiet */ if (!am_i_cdda2wav) break; global.quiet = 1; global.verbose = 0; break; case 'N': /* don't write to file */ if (!am_i_cdda2wav) break; global.no_file = 1; global.no_infofile = 1; global.no_cddbfile = 1; break; case 'J': /* information only */ if (!am_i_cdda2wav) break; global.verbose = SHOW_MAX; just_the_toc = 1; bulk = 1; break; case 'g': /* screen output formatted for guis */ if (!am_i_cdda2wav) break;#ifdef Thomas_will_es global.no_file = 1; global.no_infofile = 1; global.no_cddbfile = 1; global.verbose = SHOW_MAX;#endif global.gui = 1; break; case 'Q': /* silent scsi mode */ global.scsi_silent = 1; break; case 'H': /* don't write extra files */ if (!am_i_cdda2wav) break; global.no_infofile = 1; global.no_cddbfile = 1; break; case 'B': /* bulk transfer */ if (!am_i_cdda2wav) break; bulk = 1; break; case 'T': /* do deemphasis on the samples */ if (!am_i_cdda2wav) break; global.deemphasize = 1; global.need_hostorder = 1; break; case 'R': /* list available rates */ if (!am_i_cdda2wav) break; { int ii; fprintf(stderr, "Cdda2wav version %s: available rates are:\nRate Divider Rate Divider Rate Divider Rate Divider\n", VERSION ); for (ii = 1; ii <= 44100 / 880 / 2; ii++) { long i2 = ii; fprintf(stderr, "%-7g %2ld %-7g %2ld.5 ", 44100.0/i2,i2,44100/(i2+0.5),i2); i2 += 25; fprintf(stderr, "%-7g %2ld %-7g %2ld.5\n", 44100.0/i2,i2,44100/(i2+0.5),i2); i2 -= 25; } } exit(0); break; case 'V': if (!am_i_cdda2wav) break; global.scsi_verbose++; /* XXX nach open_scsi() scgp->verbose = .. !!!! */ break; case 'h': usage(); break; default:#ifdef USE_GETOPT_LONG fputs ("use cdda2wav --help to get more information.\n", stderr);#else fputs ("use cdda2wav -h to get more information.\n", stderr);#endif exit (1); } } /* check all parameters */ if (global.verbose < 0 || global.verbose > SHOW_MAX) { usage2("Incorrect verbose level setting: %d",global.verbose); } if (global.verbose == 0) global.quiet = 1; if ( rectime < 0.0 ) { usage2("Incorrect recording time setting: %d.%02d", (int)rectime, (int)(rectime*100+0.5) % 100); } if ( global.channels != 1 && global.channels != 2 ) { usage2("Incorrect channel setting: %d",global.channels); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -