📄 cdda2wav.c
字号:
if ( bits != 8 && bits != 12 && bits != 16 ) { usage2("Incorrect bits_per_sample setting: %d",bits); } if ( rate < 827.0 || rate > 44100.0 ) { usage2("Incorrect sample rate setting: %d.%02d", (int)rate, ((int)rate*100) % 100); } int_part = (double)(long) (2*44100.0 / rate); if (2*44100.0 / rate - int_part >= 0.5 ) { int_part += 1.0; fprintf( stderr, "Nearest available sample rate is %d.%02d Hertz\n", 2*44100 / (int)int_part, (2*4410000 / (int)int_part) % 100); } Halved = ((int) int_part) & 1; rate = 2*44100.0 / int_part; undersampling = (int) int_part / 2.0; samples_to_do = undersampling; if (!strcmp((char *)int_name,"generic_scsi")) interface = GENERIC_SCSI; else if (!strcmp((char *)int_name,"cooked_ioctl")) interface = COOKED_IOCTL; else { usage2("Incorrect interface setting: %s",int_name); } /* If we need to calculate with samples or write them to a soundcard, * we need a conversion to host byte order. */ if (global.channels != 2 || bits != 16 || rate != 44100) global.need_hostorder = 1; /* check * init audio file */ if (!strncmp(audio_type,"wav",3)) { global.audio_out = &wavsound; } else if (!strncmp(audio_type, "sun", 3) || !strncmp(audio_type, "au", 2)) { /* Enhanced compatibility */ strcpy(audio_type, "au"); global.audio_out = &sunsound; } else if (!strncmp(audio_type, "cdr", 3) || !strncmp(audio_type, "raw", 3)) { global.audio_out = &rawsound; } else if (!strncmp(audio_type, "aiff", 4)) { global.audio_out = &aiffsound; } else if (!strncmp(audio_type, "aifc", 4)) { global.audio_out = &aifcsound; } else { usage2("Incorrect audio type setting: %3s", audio_type); } global.need_big_endian = global.audio_out->need_big_endian; if (global.outputendianess != NONE) global.need_big_endian = global.outputendianess == BIG; if (global.no_file) global.fname_base[0] = '\0'; if (!bulk) { strcat(global.fname_base, "."); strcat(global.fname_base, audio_type); } /* * all options processed. * Now a file name per track may follow */ argc2 = argc3 = argc - optind; argv2 = argv + optind; if ( optind < argc ) { if (!strcmp(argv[optind],"-")) { /* * pipe mode */ if (bulk == 1) { fprintf(stderr, "bulk mode disabled while outputting to a pipe\n"); bulk = 0; }#if defined(__CYGWIN32__) || defined(__EMX__) setmode(fileno(stdout), O_BINARY);#endif global.audio = dup (fileno(stdout)); strncpy( global.fname_base, "standard output", sizeof(global.fname_base) ); global.fname_base[sizeof(global.fname_base)-1]=0; global.no_infofile = 1; global.no_cddbfile = 1; } else if (optind + 1 < argc) { /* do we have more than one argument? */ global.multiname = 1; } }#define SETSIGHAND(PROC, SIG, SIGNAME) if (signal(SIG, PROC) == SIG_ERR) \ { fprintf(stderr, "cannot set signal %s handler\n", SIGNAME); exit(1); } SETSIGHAND(exit, SIGINT, "SIGINT") SETSIGHAND(exit, SIGQUIT, "SIGQUIT") SETSIGHAND(exit, SIGTERM, "SIGTERM") SETSIGHAND(exit, SIGHUP, "SIGHUP") SETSIGHAND(set_nonforked, SIGPIPE, "SIGPIPE") /* setup interface and open cdrom device */ /* request sychronization facilities and shared memory */ SetupInterface( );#if defined(HAVE_SEMGET) && defined(USE_SEMAPHORES) atexit ( free_sem );#endif /* * set input endian default */ if (littleendian != -1) *in_lendian = littleendian; /* get table of contents */ cdtracks = ReadToc( get_scsi_p(), g_toc ); if (cdtracks == 0) { fprintf(stderr, "No track in table of contents! Aborting...\n"); exit(10); } if (ReadTocText != NULL) ReadTocText(get_scsi_p()); handle_cdtext(); calc_cddb_id(); calc_cdindex_id(); if ( global.verbose == SHOW_JUSTAUDIOTRACKS ) { unsigned int z; for (z = 0; z < cdtracks; z++) if ((g_toc[z].bFlags & CDROM_DATA_TRACK) == 0) printf("%02d\t%06u\n", g_toc[z].bTrack, g_toc[z].dwStartSector); exit(0); } if ( global.verbose != 0 ) { fputs( "#Cdda2wav version ", stderr ); fputs( VERSION, stderr );#if defined _POSIX_PRIORITY_SCHEDULING || defined HAVE_SYS_PRIOCNTL_H fputs( " real time sched.", stderr );#endif#if defined ECHO_TO_SOUNDCARD fputs( " soundcard support", stderr );#endif fputs( "\n", stderr ); } have_CD_extra = FixupTOC(cdtracks + 1); if ( global.verbose & (SHOW_TOC | SHOW_STARTPOSITIONS) ) DisplayToc (); /* use global.useroverlap to set our overlap */ if (global.useroverlap != -1) global.overlap = global.useroverlap; if (global.nsectors < 1+global.overlap) { usage2("Overlap (%d) is greater or equal than nsectors (%d)\nUse -P to set the overlap sectors and -n to set the nsectors",global.overlap, global.nsectors); } /* try to get some extra kicks */ needroot(0);#if defined(HAVE_NICE) && (HAVE_NICE == 1) nice(-20);#endif dontneedroot(); /* switch cdrom to audio mode */ EnableCdda (get_scsi_p(), 1); atexit ( CloseAll ); if ( !FirstAudioTrack () ) FatalError ( "This disk has no audio tracks\n" ); if ( global.verbose & (SHOW_MCN | SHOW_ISRC) ) Read_MCN_ISRC(); /* check if start track is in range */ if ( track < 1 || track > cdtracks ) { usage2("Incorrect start track setting: %d",track); } /* check if end track is in range */ if ( endtrack < track || endtrack > cdtracks ) { usage2("Incorrect end track setting: %ld",endtrack); } do { lSector = GetStartSector ( track ); lSector_p1 = GetEndSector ( track ) + 1; if ( lSector < 0 ) { if ( bulk == 0 ) { FatalError ( "track %d not found\n", track ); } else { fprintf(stderr, "Skipping data track %d...\n", track); if (endtrack == track) endtrack++; track++; } } } while (bulk != 0 && track <= cdtracks && lSector < 0); if (cd_index != -1) { if (global.verbose && !global.quiet) { global.verbose |= SHOW_INDICES; } sector_offset += ScanIndices( track, cd_index, bulk ); } else { cd_index = 1; if (global.verbose & SHOW_INDICES) { ScanIndices( track, cd_index, bulk ); } } lSector += sector_offset; /* check against end sector of track */ if ( lSector >= lSector_p1 ) { fputs( "sector offset exceeds track size (ignored)\n", stderr ); lSector -= sector_offset; } if ( lSector < 0L ) { fputs( "negative start sector! Set to zero.\n", stderr ); lSector = 0L; } lSector_p2 = GetLastSectorOnCd( track ); if (bulk == 1 && track == endtrack && rectime == 0.0) rectime = 99999.0; if ( rectime == 0.0 ) { /* set time to track time */ nSamplesToDo = (lSector_p1 - lSector) * CD_FRAMESAMPLES; rectime = (lSector_p1 - lSector) / 75.0; if (CheckTrackrange( track, endtrack) == 1) { lSector_p2 = GetEndSector ( endtrack ) + 1; if (lSector_p2 >= 0) { rectime = (lSector_p2 - lSector) / 75.0; nSamplesToDo = (long)(rectime*44100.0 + 0.5); } else { fputs( "end track is no valid audio track (ignored)\n", stderr ); } } else { fputs( "track range does not consist of audio tracks only (ignored)\n", stderr ); } } else { /* Prepare the maximum recording duration. * It is defined as the biggest amount of * adjacent audio sectors beginning with the * specified track/index/offset. */ if ( rectime > (lSector_p2 - lSector) / 75.0 ) { rectime = (lSector_p2 - lSector) / 75.0; lSector_p1 = lSector_p2; } /* calculate # of samples to read */ nSamplesToDo = (long)(rectime*44100.0 + 0.5); } global.OutSampleSize = (1+bits/12); if (nSamplesToDo/undersampling == 0L) { usage2("Time interval is too short. Choose a duration greater than %d.%02d secs!", undersampling/44100, (int)(undersampling/44100) % 100); } SamplesToWrite = nSamplesToDo*2/(int)int_part; tracks_included = GetTrack( (unsigned) (lSector + nSamplesToDo/CD_FRAMESAMPLES -1)) - track + 1; if ( !waitforsignal ) { if (global.multiname != 0 && optind + tracks_included > argc) { global.multiname = 0; }#ifdef INFOFILES if (!global.no_infofile) { int i; for (i = track; i < track + tracks_included; i++) { unsigned minsec, maxsec; char *tmp_fname; /* build next filename */ tmp_fname = get_next_name(); if (tmp_fname != NULL) strncpy( global.fname_base, tmp_fname, sizeof(global.fname_base)-8 ); global.fname_base[sizeof(global.fname_base)-1]=0; minsec = max(lSector, GetStartSector(i)); maxsec = min(lSector_p2, 1+GetEndSector(i)); write_info_file(global.fname_base,i,(maxsec-minsec)*CD_FRAMESAMPLES, bulk && global.multiname == 0); if (!bulk) break; } reset_name_iterator(); }#endif } if (just_the_toc) exit(0);#ifdef ECHO_TO_SOUNDCARD if (user_sound_device[0] != '\0') { set_snd_device(user_sound_device); } init_soundcard(rate, bits);#endif /* ECHO_TO_SOUNDCARD */ if (global.userspeed > -1) global.speed = global.userspeed; if (global.speed != 0 && SelectSpeed != NULL) { SelectSpeed(get_scsi_p(), global.speed); } current_track = track; if ( !global.no_file ) { { char *myfname; myfname = get_next_name(); if (myfname != NULL) { strncpy( global.fname_base, myfname, sizeof(global.fname_base)-8 ); global.fname_base[sizeof(global.fname_base)-1]=0; } } /* strip audio_type extension */ { char *cp = global.fname_base; cp = strrchr(cp, '.'); if (cp == NULL) { cp = global.fname_base + strlen(global.fname_base); } *cp = '\0'; } if (bulk && global.multiname == 0) { sprintf(fname, "%s_%02u.%s",global.fname_base,current_track,audio_type); } else { sprintf(fname, "%s.%s",global.fname_base,audio_type); } OpenAudio( fname, rate, bits, global.channels, (unsigned)(SamplesToWrite*global.OutSampleSize*global.channels), global.audio_out); } global.Remainder = (75 % global.nsectors)+1; global.sh_bits = 16 - bits; /* shift counter */ global.iloop = nSamplesToDo; if (Halved && (global.iloop&1)) global.iloop += 2; BeginAtSample = lSector * CD_FRAMESAMPLES; if ( 1 ) { if ( (global.verbose & SHOW_SUMMARY) && !just_the_toc ) { fprintf(stderr, "samplefile size will be %lu bytes.\n", global.audio_out->GetHdrSize() + SamplesToWrite*global.OutSampleSize*global.channels ); fprintf (stderr, "recording %d.%05d seconds %s with %d bits @ %5d.%01d Hz" ,(int)rectime , (int)(rectime * 10000) % 10000, global.channels == 1 ? "mono":"stereo", bits, (int)rate, (int)(rate*10)%10); if (!global.no_file && *global.fname_base) fprintf(stderr, " ->'%s'...", global.fname_base ); fputs("\n", stderr); } }#if defined(HAVE_SEMGET) && defined(USE_SEMAPHORES)#else init_pipes();#endif#if defined(HAVE_FORK_AND_SHAREDMEM) /* Everything is set up. Now fork and let one process read cdda sectors and let the other one store them in a wav file */ /* forking */ child_pid = fork(); if (child_pid > 0 && global.gui > 0 && global.verbose > 0) fprintf( stderr, "child pid is %d\n", child_pid); /*********************** fork **************************************/ if (child_pid == 0) { /* child WRITER section */#ifdef __EMX__ if (DosGetSharedMem(fill_buffer, 3)) { comerr("DosGetSharedMem() failed.\n"); }#endif global.have_forked = 1; forked_write();#ifdef __EMX__ DosFreeMem(fill_buffer); _exit(0);#endif exit(0); } else if (child_pid > 0) { /* parent READER section */ global.have_forked = 1; switch_to_realtime_priority(); forked_read();#ifdef __EMX__ DosFreeMem(fill_buffer);#endif exit(0); } else#else /* version without fork */ { global.have_forked = 0; switch_to_realtime_priority(); fprintf(stderr, "a nonforking version is running...\n"); nonforked_loop(); exit(0); }#endif return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -