From 362bcc9cc0d126c2983c21feb886d202442cdf80 Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Tue, 17 Oct 2006 16:52:58 +0000 Subject: [PATCH] Implemented some cdrecord pickiness for .wav extraction --- cdrskin/cdrskin.c | 86 ++++++++++++++++++++----------------- cdrskin/cdrskin_timestamp.h | 2 +- libburn/libdax_audioxtr.c | 24 +++++++++++ libburn/libdax_audioxtr.h | 23 +++++++++- test/dewav.c | 16 ++++--- 5 files changed, 104 insertions(+), 47 deletions(-) diff --git a/cdrskin/cdrskin.c b/cdrskin/cdrskin.c index 71de2aa..f2f8495 100644 --- a/cdrskin/cdrskin.c +++ b/cdrskin/cdrskin.c @@ -749,8 +749,9 @@ struct CdrfifO { /* --------------------------------------------------------------------- */ /** cdrecord pads up to 600 kB in any case. - libburn yields blank result on tracks <~ 600 kB */ -static double Cdrtrack_minimum_sizE= 600*1024; + libburn yields blank result on tracks <~ 600 kB + cdrecord demands 300 sectors = 705600 bytes for -audio */ +static double Cdrtrack_minimum_sizE= 300; /** This structure represents a track resp. a data source */ @@ -906,12 +907,14 @@ int Cdrtrack_get_fifo(struct CdrtracK *track, struct CdrfifO **fifo, int flag) /** Try wether automatic audio extraction is appropriate and eventually open a file descriptor to the raw data. - @return -2 could not open track source, no use in retrying + @return -3 identified as .wav but with cdrecord-inappropriate parameters + -2 could not open track source, no use in retrying -1 severe error 0 not appropriate to extract, burn plain file content 1 to be extracted, *fd is a filedescriptor delivering raw data */ -int Cdrtrack_extract_audio(struct CdrtracK *track, int *fd, int flag) +int Cdrtrack_extract_audio(struct CdrtracK *track, int *fd, off_t *xtr_size, + int flag) { int l,ret; #ifdef Cdrskin_libburn_has_audioxtR @@ -933,7 +936,7 @@ int Cdrtrack_extract_audio(struct CdrtracK *track, int *fd, int flag) if(track->track_type_by_default) { Cdrtrack_set_track_type(track,BURN_AUDIO,0); track->track_type_by_default= 2; - fprintf(stderr,"cdrskin: NOTE: Activated -audio for '%s'\n", + fprintf(stderr,"cdrskin: NOTE : Activated -audio for '%s'\n", track->source_path); } @@ -944,14 +947,19 @@ int Cdrtrack_extract_audio(struct CdrtracK *track, int *fd, int flag) return(ret); libdax_audioxtr_get_id(xtr,&fmt,&fmt_info, &num_channels,&sample_rate,&bits_per_sample,0); - if((num_channels!=2) || sample_rate!=44100 || bits_per_sample!=16) - {ret= 0; goto ex;} + if(strcmp(fmt,".wav")!=0 || + num_channels!=2 || sample_rate!=44100 || bits_per_sample!=16) { + fprintf(stderr,"cdrskin: ( %s )\n",fmt_info); + fprintf(stderr,"cdrskin: FATAL : Inappropriate audio coding in '%s'.\n", + track->source_path); + {ret= -3; goto ex;} + } + libdax_audioxtr_get_size(xtr,xtr_size,0); ret= libdax_audioxtr_detach_fd(xtr,fd,0); if(ret<=0) {ret= -1*!!ret; goto ex;} - - fprintf(stderr,"cdrskin: NOTE: Will extract plain audio from '%s'\n", - track->source_path); + fprintf(stderr,"cdrskin: NOTE : %.f audio bytes in '%s'\n", + (double) *xtr_size, track->source_path); ret= 1; ex: libdax_audioxtr_destroy(&xtr,0); @@ -971,6 +979,7 @@ ex: int Cdrtrack_open_source_path(struct CdrtracK *track, int *fd, int flag) { int is_wav= 0; + off_t xtr_size= 0; if(track->source_path[0]=='-' && track->source_path[1]==0) *fd= 0; @@ -979,49 +988,46 @@ int Cdrtrack_open_source_path(struct CdrtracK *track, int *fd, int flag) *fd= atoi(track->source_path+1); else { *fd= -1; - -#define Try_auto_extract 1 -#ifdef Try_auto_extract - - is_wav= Cdrtrack_extract_audio(track,fd,0); - if(is_wav<0 && is_wav!=-2) + is_wav= Cdrtrack_extract_audio(track,fd,&xtr_size,0); + if(is_wav==-1) return(-1); + if(is_wav==-3) + return(0); if(is_wav==0) *fd= open(track->source_path,O_RDONLY); - -#else /* Try_auto_extract */ - - if(*fd>=0) - close(*fd); - *fd= open(track->source_path,O_RDONLY); - - is_wav= 0; - - if(*fd>=0 && is_wav==1) { - char wav_head[44]; - read(*fd, wav_head, 44); - } - -#endif /* ! Try_auto_extract */ - if(*fd==-1) { fprintf(stderr,"cdrskin: failed to open source address '%s'\n", track->source_path); fprintf(stderr,"cdrskin: errno=%d , \"%s\"\n",errno, errno==0?"-no error code available-":strerror(errno)); - } else { - if(track->fixed_size<=0) { + return(0); + } + if(track->fixed_size<=0) { + if(xtr_size>0) + track->fixed_size= xtr_size; + else { struct stat stbuf; if(fstat(*fd,&stbuf)!=-1) - track->fixed_size= stbuf.st_size-(44*(is_wav==1)); + track->fixed_size= stbuf.st_size; } } } - if(track->fixed_size=0) { - fprintf(stderr, - "cdrskin: NOTE : Enforcing minimum track size of %.f bytes\n", - Cdrtrack_minimum_sizE); - track->fixed_size= Cdrtrack_minimum_sizE; + + if(track->fixed_size < Cdrtrack_minimum_sizE * track->sector_size) { + if(track->track_type == BURN_AUDIO) { + /* >>> cdrecord: We differ in automatic padding with audio: + Audio tracks must be at least 705600 bytes and a multiple of 2352. + */ + fprintf(stderr, + "cdrskin: FATAL : Audio tracks must be at least %.f bytes\n", + Cdrtrack_minimum_sizE*track->sector_size); + return(0); + } else { + fprintf(stderr, + "cdrskin: NOTE : Enforcing minimum track size of %.f bytes\n", + Cdrtrack_minimum_sizE*track->sector_size); + track->fixed_size= Cdrtrack_minimum_sizE*track->sector_size; + } } track->source_fd= *fd; return(*fd>=0); diff --git a/cdrskin/cdrskin_timestamp.h b/cdrskin/cdrskin_timestamp.h index c6f950a..c28f357 100644 --- a/cdrskin/cdrskin_timestamp.h +++ b/cdrskin/cdrskin_timestamp.h @@ -1 +1 @@ -#define Cdrskin_timestamP "2006.10.17.141053" +#define Cdrskin_timestamP "2006.10.17.164140" diff --git a/libburn/libdax_audioxtr.c b/libburn/libdax_audioxtr.c index 6b3d475..d6b1752 100644 --- a/libburn/libdax_audioxtr.c +++ b/libburn/libdax_audioxtr.c @@ -38,10 +38,13 @@ int libdax_audioxtr_new(struct libdax_audioxtr **xtr, char *path, int flag) o->fd= -1; strcpy(o->fmt,"unidentified"); o->fmt_info[0]= 0; + o->data_size= 0; + o->extract_count= 0; o->wav_num_channels= 0; o->wav_sample_rate= 0; o->wav_bits_per_sample= 0; + o->wav_subchunk2_size= 0; ret= libdax_audioxtr_open(o,0); if(ret<=0) @@ -136,6 +139,8 @@ static int libdax_audioxtr_identify(struct libdax_audioxtr *o, int flag) sprintf(o->fmt_info, ".wav , num_channels=%d , sample_rate=%d , bits_per_sample=%d", o->wav_num_channels,o->wav_sample_rate,o->wav_bits_per_sample); + o->wav_subchunk2_size= libdax_audioxtr_to_int(o,(unsigned char *)buf+40,4,0); + o->data_size= o->wav_subchunk2_size; return(1); } @@ -161,6 +166,7 @@ static int libdax_audioxtr_init_reading(struct libdax_audioxtr *o, int flag) if(o->fd==0) /* stdin: hope no read came after libdax_audioxtr_identify() */ return(1); + o->extract_count= 0; ret= lseek(o->fd,44,SEEK_SET); if(ret==-1) return(0); @@ -186,6 +192,17 @@ int libdax_audioxtr_get_id(struct libdax_audioxtr *o, } +int libdax_audioxtr_get_size(struct libdax_audioxtr *o, off_t *size, int flag) +{ + if(strcmp(o->fmt,".wav")==0) { + *size= o->wav_subchunk2_size; + return(1); + } + *size= 0; + return(0); +} + + int libdax_audioxtr_read(struct libdax_audioxtr *o, char buffer[], int buffer_size, int flag) { @@ -193,7 +210,14 @@ int libdax_audioxtr_read(struct libdax_audioxtr *o, if(buffer_size<=0 || o->fd<0) return(-2); + if(o->data_size>0 && !(flag&1)) + if(buffer_size > o->data_size - o->extract_count) + buffer_size= o->data_size - o->extract_count; + if(buffer_size<=0) + return(0); ret= read(o->fd,buffer,buffer_size); + if(ret>0) + o->extract_count+= ret; return(ret); } diff --git a/libburn/libdax_audioxtr.h b/libburn/libdax_audioxtr.h index d09e4a0..82ae06d 100644 --- a/libburn/libdax_audioxtr.h +++ b/libburn/libdax_audioxtr.h @@ -60,12 +60,23 @@ int libdax_audioxtr_get_id(struct libdax_audioxtr *xtr, int *bits_per_sample, int flag); +/** Obtain a prediction about the extracted size based on internal information + of the formatted file. + @param xtr Opaque handle to extractor + @param size Gets filled with the predicted size + @param flag Bitfield for control purposes (unused yet, submit 0) + @return 1 prediction was possible , 0 no prediction could be made +*/ +int libdax_audioxtr_get_size(struct libdax_audioxtr *o, off_t *size, int flag); + + /** Obtain next buffer full of extracted data in desired format (only raw audio for now). @param xtr Opaque handle to extractor @param buffer Gets filled with extracted data @param buffer_size Maximum number of bytes to be filled into buffer - @param flag Bitfield for control purposes (unused yet, submit 0) + @param flag Bitfield for control purposes + bit0= do not stop at predicted end of data @return >0 number of valid buffer bytes, 0 End of file -1 operating system reports error @@ -134,6 +145,12 @@ struct libdax_audioxtr { /* Format parameter info text */ char fmt_info[LIBDAX_AUDIOXTR_STRLEN]; + /* Number of bytes to extract (0= unknown/unlimited) */ + off_t data_size; + + /* Number of extracted data bytes */ + off_t extract_count; + /* Format dependent parameters */ @@ -149,6 +166,10 @@ struct libdax_audioxtr { /* 8 bits = 8, 16 bits = 16, etc. */ int wav_bits_per_sample; + /* == NumSamples * NumChannels * BitsPerSample/8 + This is the number of bytes in the data. */ + unsigned wav_subchunk2_size; + }; diff --git a/test/dewav.c b/test/dewav.c index ccdbe57..00d7aee 100644 --- a/test/dewav.c +++ b/test/dewav.c @@ -54,9 +54,10 @@ int main(int argc, char **argv) /* Inquired source parameters */ char *fmt, *fmt_info; int num_channels, sample_rate, bits_per_sample; + off_t data_size; /* Auxiliary variables */ - int ret, i, be_strict= 1, buf_count, detach_fd= 0; + int ret, i, be_strict= 1, buf_count, detach_fd= 0, extract_all= 0; char buf[2048]; if(argc < 2) @@ -75,8 +76,11 @@ int main(int argc, char **argv) } else if(strcmp(argv[i],"--strict")==0) { be_strict= 1; } else if(strcmp(argv[i],"--detach_fd")==0) { - /* Test the dirty detach method */ + /* Test the dirty detach method. Always --extract_all */ detach_fd= 1; + } else if(strcmp(argv[i],"--extract_all")==0) { + /* Dirty : read all available bytes regardless of data_size */ + extract_all= 1; } else if(strcmp(argv[i],"--help")==0) { help:; fprintf(stderr, @@ -140,7 +144,10 @@ help:; libdax_audioxtr_get_id(xtr, &fmt, &fmt_info, &num_channels, &sample_rate, &bits_per_sample, 0); fprintf(stderr, "Detected format: %s\n", fmt_info); - if(num_channels!=2 || sample_rate!=44100 || bits_per_sample!=16) { + libdax_audioxtr_get_size(xtr, &data_size, 0); + fprintf(stderr, "Data size : %.f bytes\n", (double) data_size); + if(strcmp(fmt,".wav")!=0 || + num_channels!=2 || sample_rate!=44100 || bits_per_sample!=16) { fprintf(stderr, "%sAudio source parameters do not comply to cdrskin/README specs\n", (be_strict ? "" : "WARNING: ")); @@ -162,14 +169,13 @@ help:; /* Extract and put out raw audio data */; while(1) { - if(detach_fd) { buf_count= read(xtr_fd, buf, sizeof(buf)); if(buf_count==-1) fprintf(stderr,"Error while reading from detached fd\n(%d) '%s'\n", errno, strerror(errno)); } else { - buf_count= libdax_audioxtr_read(xtr, buf, sizeof(buf), 0); + buf_count= libdax_audioxtr_read(xtr, buf, sizeof(buf), !!extract_all); } if(buf_count < 0) exit(7);