📄 cdda2wav.c
字号:
int amichild; /* terminate child process first */ amichild = child_pid == 0;#if defined HAVE_FORK_AND_SHAREDMEM if (amichild == 0) {# ifdef DEBUG_CLEANUPfprintf(stderr, "Parent (READER) terminating, \n");# endif if (global.iloop > 0) { /* set to zero */ global.iloop = 0; kill(child_pid, SIGINT); }#else if (1) {#endif /* switch to original mode and close device */ EnableCdda (get_scsi_p(), 0);#if defined HAVE_FORK_AND_SHAREDMEM } else {#ifdef DEBUG_CLEANUPfprintf(stderr, "Child (WRITER) terminating, \n");#endif#else# ifdef DEBUG_CLEANUPfprintf(stderr, "Cdda2wav single process terminating, \n");# endif#endif /* do general clean up */ if (global.audio>=0) { if (bulk) { /* finish sample file for this track */ CloseAudio(global.fname_base, current_track, bulk, global.channels, global.nSamplesDoneInTrack, global.audio_out); } else { /* finish sample file for this track */ CloseAudio(global.fname_base, track, bulk, global.channels, (unsigned int) nSamplesToDo, global.audio_out); } } /* tell minimum and maximum amplitudes, if required */ if (global.findminmax) { fprintf(stderr, "right channel: minimum amplitude :%d/-32768, maximum amplitude :%d/32767\n", global.minamp[0], global.maxamp[0]); fprintf(stderr, "left channel: minimum amplitude :%d/-32768, maximum amplitude :%d/32767\n", global.minamp[1], global.maxamp[1]); } /* tell mono or stereo recording, if required */ if (global.findmono) { fprintf(stderr, "Audio samples are originally %s.\n", global.ismono ? "mono" : "stereo"); }#ifdef DEBUG_CLEANUPfprintf(stderr, "Child (WRITER) terminating, \n");#endif return; } if (global.have_forked == 1) {#ifdef DEBUG_CLEANUPfprintf(stderr, "Parent wait for child death, \n");#endif#if defined(HAVE_SYS_WAIT_H) && (HAVE_SYS_WAIT_H == 1) /* wait for child to terminate */ if (0 > wait(&chld_return_status)) { perror(""); } else { if (WIFEXITED(chld_return_status)) { if (WEXITSTATUS(chld_return_status)) { fprintf(stderr, "Child exited with %d\n", WEXITSTATUS(chld_return_status)); } } if (WIFSIGNALED(chld_return_status)) { fprintf(stderr, "Child exited due to signal %d\n", WTERMSIG(chld_return_status)); } if (WIFSTOPPED(chld_return_status)) { fprintf(stderr, "Child is stopped due to signal %d\n", WSTOPSIG(chld_return_status)); } }#endif#ifdef DEBUG_CLEANUPfprintf(stderr, "Parent child death, state:%d\n", chld_return_status);#endif }#ifdef GPROF rename("gmon.out", "gmon.child");#endif}/* report a usage error and exit */#ifdef PROTOTYPESstatic void usage2 (const char *szMessage, ...)#elsestatic void usage2 (szMessage, va_alist) const char *szMessage; va_dcl#endif{ va_list marker;#ifdef PROTOTYPES va_start(marker, szMessage);#else va_start(marker);#endif error("%r", szMessage, marker); va_end(marker); fprintf(stderr, "\nPlease use -h or consult the man page for help.\n"); exit (1);}/* report a fatal error, clean up and exit */#ifdef PROTOTYPESvoid FatalError (const char *szMessage, ...)#elsevoid FatalError (szMessage, va_alist) const char *szMessage; va_dcl#endif{ va_list marker;#ifdef PROTOTYPES va_start(marker, szMessage);#else va_start(marker);#endif error("%r", szMessage, marker); va_end(marker); if (child_pid == -2) exit (1); if (child_pid == 0) { /* kill the parent too */ kill(getppid(), SIGINT); } else { kill(child_pid, SIGINT); } exit (1);}/* open the audio output file and prepare the header. * the header will be defined on terminating (when the size * is known). So hitting the interrupt key leaves an intact * file. */static void OpenAudio (fname, rate, nBitsPerSample, channels_val, expected_bytes, audio_out) char *fname; double rate; long nBitsPerSample; long channels_val; unsigned long expected_bytes; struct soundfile * audio_out;{ if (global.audio == -1) { global.audio = open (fname, O_CREAT | O_WRONLY | O_TRUNC | O_BINARY#ifdef O_NONBLOCK | O_NONBLOCK#endif#ifdef SYNCHRONOUS_WRITE | O_SYNC#endif , 0666); if (global.audio == -1) { perror("open audio sample file"); FatalError ("Could not open file %s\n", fname); } } audio_out->InitSound( global.audio, channels_val, (unsigned long)rate, nBitsPerSample, expected_bytes );#ifdef MD5_SIGNATURES if (global.md5blocksize) MD5Init (&global.context); global.md5count = global.md5blocksize;#endif}static void set_offset(p, offset) myringbuff *p; int offset;{#ifdef DEBUG_SHM fprintf(stderr, "Write offset %d at %p\n", offset, &p->offset);#endif p->offset = offset;}static int get_offset(p)myringbuff *p;{#ifdef DEBUG_SHM fprintf(stderr, "Read offset %d from %p\n", p->offset, &p->offset);#endif return p->offset;}static void usage( ){ fprintf( stderr,"cdda2wav [-c chans] [-s] [-m] [-b bits] [-r rate] [-a divider] [-S speed] [-x]\n"); fprintf( stderr," [-t track[+endtrack]] [-i index] [-o offset] [-d duration] [-F] [-G]\n"); fprintf( stderr," [-q] [-w] [-v] [-R] [-P overlap] [-B] [-T] [-C input-endianess]\n"); fprintf( stderr," [-e] [-n sectors] [-N] [-J] [-H] [-g] [-l buffers] [-D cd-device]\n"); fprintf( stderr," [-I interface] [-K sound-device] [-O audiotype] [-E output-endianess]\n"); fprintf( stderr," [-A auxdevice] [audiofiles ...]\n"); fprintf( stderr,"Version %s\n", VERSION); fprintf( stderr,"cdda2wav copies parts from audio cd's directly to wav or au files.\n"); fprintf( stderr,"It requires a supported cdrom drive to work.\n"); fprintf( stderr,"options: -D cd-device: set the cdrom or scsi device (as Bus,Id,Lun).\n"); fprintf( stderr," -A auxdevice: set the aux device (typically /dev/cdrom).\n"); fprintf( stderr," -K sound-device: set the sound device to use for -e (typically /dev/dsp).\n"); fprintf( stderr," -I interface: specify the interface for cdrom access.\n"); fprintf( stderr," : (generic_scsi or cooked_ioctl).\n"); fprintf( stderr," -c channels : set 1 for mono, 2 or s for stereo (s: channels swapped).\n"); fprintf( stderr," -s : set to stereo recording.\n"); fprintf( stderr," -m : set to mono recording.\n"); fprintf( stderr," -x : set to maximum quality (stereo/16-bit/44.1 KHz).\n"); fprintf( stderr," -b bits : set bits per sample per channel (8, 12 or 16 bits).\n"); fprintf( stderr," -r rate : set rate in samples per second. -R gives all rates\n"); fprintf( stderr," -a divider : set rate to 44100Hz / divider. -R gives all rates\n"); fprintf( stderr," -R : dump a table with all available sample rates\n"); fprintf( stderr," -S speed : set the cdrom drive to a given speed during reading\n"); fprintf( stderr," -P sectors : set amount of overlap sampling (default is 0)\n");#ifdef NOTYET fprintf( stderr," -X : switch off extra alignment paranoia; implies -Y -Z\n"); fprintf( stderr," -Y : switch off scratch detection; implies -Z\n"); fprintf( stderr," -Z : switch off scratch reconstruction\n"); fprintf( stderr," -y threshold: tune scratch detection filter; low values catch\n"); fprintf( stderr," : more scratches but may also catch legitimate values\n"); fprintf( stderr," -z : disable 'smart' scratch auto-detect and force \n"); fprintf( stderr," : paranoia to treat all data as possibly scratched\n\n");#endif fprintf( stderr," -n sectors : read 'sectors' sectors per request.\n"); fprintf( stderr," -l buffers : use a ring buffer with 'buffers' elements.\n"); fprintf( stderr," -t track[+end track]\n"); fprintf( stderr," : select start track (and optionally end track).\n"); fprintf( stderr," -i index : select start index.\n"); fprintf( stderr," -o offset : start at 'offset' sectors behind start track/index.\n"); fprintf( stderr," one sector equivalents 1/75 second.\n"); fprintf( stderr," -O audiotype: set wav or au (aka sun) or cdr (aka raw) or aiff or aifc audio format. Default is %s.\n", AUDIOTYPE); fprintf( stderr," -C endianess: set little or big input sample endianess.\n"); fprintf( stderr," -E endianess: set little or big output sample endianess.\n"); fprintf( stderr," -d duration : set recording time in seconds or 0 for whole track.\n"); fprintf( stderr," -w : wait for audio signal, then start recording.\n"); fprintf( stderr," -F : find extrem amplitudes in samples.\n"); fprintf( stderr," -G : find if input samples are mono.\n"); fprintf( stderr," -T : undo pre-emphasis in input samples.\n");#ifdef ECHO_TO_SOUNDCARD fprintf( stderr," -e : echo audio data to sound device SOUND_DEV.\n");#endif fprintf( stderr," -v level : print informations on current cd (level: 0-63).\n"); fprintf( stderr," -N : no file operation.\n"); fprintf( stderr," -J : give disc information only.\n"); fprintf( stderr," -H : no info file generation.\n"); fprintf( stderr," -g : generate special output suitable for gui frontends.\n"); fprintf( stderr," -Q : do not print status of erreneous scsi-commands.\n");#ifdef MD5_SIGNATURES fprintf( stderr," -M count : calculate MD-5 checksum for 'count' bytes.\n");#endif fprintf( stderr," -q : quiet operation, no screen output.\n"); fprintf( stderr," -p percent : play (echo) audio at a new pitch rate.\n"); fprintf( stderr," -V : increase verbosity for SCSI commands.\n"); fprintf( stderr," -h : this help screen.\n" ); fprintf( stderr," -B : record each track into a seperate file.\n"); fprintf( stderr,"defaults: %s, %d bit, %d.%02d Hz, track 1, no offset, one track,\n", CHANNELS-1?"stereo":"mono", BITS_P_S, 44100 / UNDERSAMPLING, (4410000 / UNDERSAMPLING) % 100); fprintf( stderr," type %s '%s', don't wait for signal, not quiet, not verbose,\n", AUDIOTYPE, FILENAME); fprintf( stderr," use %s, device %s, aux %s", DEF_INTERFACE, CD_DEVICE, AUX_DEVICE);#ifdef ECHO_TO_SOUNDCARD fprintf( stderr,", sound device %s\n", SOUND_DEV);#else fprintf( stderr, "\n");#endif fprintf( stderr,"parameters: (optional) a file name or - for standard output.\n"); exit( 1 );}static void init_globals(){ strncpy(global.dev_name, CD_DEVICE, sizeof(global.dev_name)); /* device name */ strncpy(global.aux_name, AUX_DEVICE, sizeof(global.aux_name));/* auxiliary cdrom device */ strncpy(global.fname_base, FILENAME, sizeof(global.fname_base));/* auxiliary cdrom device */ global.have_forked = 0; /* state variable for clean up */ global.parent_died = 0; /* state variable for clean up */ global.audio = -1; /* audio file desc */ global.cooked_fd = -1; /* cdrom file desc */ global.no_file = 0; /* flag no_file */ global.no_infofile = 0; /* flag no_infofile */ global.no_cddbfile = 0; /* flag no_cddbfile */ global.quiet = 0; /* flag quiet */ global.verbose = 3 + 32 + 64; /* verbose level */ global.scsi_silent = 0; global.scsi_verbose = 0; /* SCSI verbose level */ global.multiname = 0; /* multiple file names given */ global.sh_bits = 0; /* sh_bits: sample bit shift */ global.Remainder= 0; /* remainder */ global.iloop = 0; /* todo counter */ global.SkippedSamples = 0; /* skipped samples */ global.OutSampleSize = 0; /* output sample size */ global.channels = CHANNELS; /* output sound channels */ global.nSamplesDoneInTrack = 0; /* written samples in current track */ global.buffers = 4; /* buffers to use */ global.nsectors = NSECTORS; /* sectors to read in one request */ global.overlap = 1; /* amount of overlapping sectors */ global.useroverlap = -1; /* amount of overlapping sectors user override */ global.need_hostorder = 0; /* processing needs samples in host endianess */ global.outputendianess = NONE; /* user specified output endianess */ global.findminmax = 0; /* flag find extrem amplitudes */#ifdef HAVE_LIMITS_H global.maxamp[0] = INT_MIN; /* maximum amplitude */ global.maxamp[1] = INT_MIN; /* maximum amplitude */ global.minamp[0] = INT_MAX; /* minimum amplitude */ global.minamp[1] = INT_MAX; /* minimum amplitude */#else global.maxamp[0] = -32768; /* maximum amplitude */ global.maxamp[1] = -32768; /* maximum amplitude */ global.minamp[0] = 32767; /* minimum amplitude */ global.minamp[1] = 32767; /* minimum amplitude */#endif global.speed = DEFAULT_SPEED; /* use default */ global.userspeed = -1; /* speed user override */ global.findmono = 0; /* flag find if samples are mono */ global.ismono = 1; /* flag if samples are mono */ global.swapchannels = 0; /* flag if channels shall be swapped */ global.deemphasize = 0; /* flag undo pre-emphasis in samples */ global.playback_rate = 100; /* new fancy selectable sound output rate */ global.gui = 0; /* flag plain formatting for guis */ global.cddb_id = 0; /* disc identifying id for CDDB database */ global.disctitle = NULL; global.creator = NULL; global.copyright_message = NULL; memset(global.tracktitle, 0, sizeof(global.tracktitle)); memset(global.trackindexlist, 0, sizeof(global.trackindexlist));}#if !defined (HAVE_STRCASECMP) || (HAVE_STRCASECMP != 1)#include <ctype.h>static int strcasecmp __PR(( const char *s1, const char *s2 ));static int strcasecmp(s1, s2) const char *s1; const char *s2;{ if (s1 && s2) { while (*s1 && *s2 && (tolower(*s1) - tolower(*s2) == 0)) { s1++; s2++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -