From 9d3f1292d6be2443909089115c7d205712bc2fee Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Sun, 15 Oct 2006 13:51:41 +0000 Subject: [PATCH] Implemented a first attempt of a .wav decapitator (ticket 38) --- Makefile.am | 6 ++ libburn/libdax_audioxtr.c | 196 ++++++++++++++++++++++++++++++++++++++ libburn/libdax_audioxtr.h | 168 ++++++++++++++++++++++++++++++++ libburn/libdax_msgs.h | 5 + 4 files changed, 375 insertions(+) create mode 100644 libburn/libdax_audioxtr.c create mode 100644 libburn/libdax_audioxtr.h diff --git a/Makefile.am b/Makefile.am index fc5dc36..458be98 100644 --- a/Makefile.am +++ b/Makefile.am @@ -29,6 +29,8 @@ libburn_libburn_la_SOURCES = \ libburn/lec.c \ libburn/lec.h \ libburn/libburn.h \ + libburn/libdax_audioxtr.h \ + libburn/libdax_audioxtr.c \ libburn/libdax_msgs.h \ libburn/libdax_msgs.c \ libburn/mmc.c \ @@ -95,6 +97,7 @@ libinclude_HEADERS = \ ## Build test applications noinst_PROGRAMS = \ test/libburner \ + test/dewav \ test/iso \ test/poll \ test/toc \ @@ -106,6 +109,9 @@ bin_PROGRAMS = \ test_libburner_CPPFLAGS = -Ilibburn test_libburner_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS) test_libburner_SOURCES = test/libburner.c +test_dewav_CPPFLAGS = -Ilibburn +test_dewav_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS) +test_dewav_SOURCES = test/dewav.c test_poll_CPPFLAGS = -Ilibburn test_poll_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS) test_poll_SOURCES = test/poll.c diff --git a/libburn/libdax_audioxtr.c b/libburn/libdax_audioxtr.c new file mode 100644 index 0000000..c3b8000 --- /dev/null +++ b/libburn/libdax_audioxtr.c @@ -0,0 +1,196 @@ + +/* libdax_audioxtr + Audio track data extraction facility of libdax and libburn. + Copyright (C) 2006 Thomas Schmitt , provided under GPL +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "libdax_msgs.h" +extern struct libdax_msgs *libdax_messenger; + + +/* Only this single source module is entitled to do this */ +#define LIBDAX_AUDIOXTR_H_INTERNAL 1 + +/* All clients of the extraction facility must do this */ +#include "libdax_audioxtr.h" + + +int libdax_audioxtr_new(struct libdax_audioxtr **xtr, char *path, int flag) +{ + int ret; + struct libdax_audioxtr *o; + + o= *xtr= (struct libdax_audioxtr *)malloc(sizeof(struct libdax_audioxtr *)); + if(o==NULL) + return(-1); + strncpy(o->path,path,LIBDAX_AUDIOXTR_STRLEN-1); + o->path[LIBDAX_AUDIOXTR_STRLEN]= 0; + o->fd= -1; + strcpy(o->fmt,"unidentified"); + o->fmt_info[0]= 0; + + o->wav_num_channels= 0; + o->wav_sample_rate= 0; + o->wav_bits_per_sample= 0; + + ret= libdax_audioxtr_open(o,0); + if(ret<=0) + goto failure; + + return(1); +failure: + libdax_audioxtr_destroy(xtr,0); + return(-1); +} + + +int libdax_audioxtr_destroy(struct libdax_audioxtr **xtr, int flag) +{ + struct libdax_audioxtr *o; + + o= *xtr; + if(o==NULL) + return(0); + if(o->fd>=0 && strcmp(o->path,"-")!=0) + close(o->fd); + free((char *) o); + *xtr= NULL; + return(1); +} + + +static int libdax_audioxtr_open(struct libdax_audioxtr *o, int flag) +{ + int ret; + char msg[LIBDAX_AUDIOXTR_STRLEN+80]; + + if(strcmp(o->path,"-")==0) + o->fd= 0; + else + o->fd= open(o->path, O_RDONLY); + if(o->fd<0) { + sprintf(msg,"Cannot open audio source file : %s",o->path); + libdax_msgs_submit(libdax_messenger,-1,0x00020200, + LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, + msg, errno, 0); + return(-1); + } + ret= libdax_audioxtr_identify(o,0); + if(ret<=0) { + sprintf(msg,"Audio source file has unsuitable format : %s",o->path); + libdax_msgs_submit(libdax_messenger,-1,0x00020201, + LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, + msg, 0, 0); + return(0); + } + ret= libdax_audioxtr_init_reading(o,0); + if(ret<=0) { + sprintf(msg,"Failed to prepare reading of audio data : %s",o->path); + libdax_msgs_submit(libdax_messenger,-1,0x00020202, + LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, + msg, 0, 0); + return(0); + } + return(1); +} + + +static int libdax_audioxtr_identify(struct libdax_audioxtr *o, int flag) +{ + int ret; + char buf[45]; + + /* currently this only works for MS WAVE files .wav */ + /* info used: http://ccrma.stanford.edu/courses/422/projects/WaveFormat/ */ + + ret= read(o->fd, buf, 44); + if(ret<44) + return(0); + buf[44]= 0; /* as stopper for any string operations */ + + if(strncmp(buf,"RIFF",4)!=0) /* ChunkID */ + return(0); + if(strncmp(buf+8,"WAVE",4)!=0) /* Format */ + return(0); + if(strncmp(buf+12,"fmt ",4)!=0) /* Subchunk1ID */ + return(0); + if(buf[16]!=16 || buf[17]!=0 || buf[18]!=0 || buf[19]!=0) /* Subchunk1Size */ + return(0); + if(buf[20]!=1 || buf[21]!=0) /* AudioFormat must be 1 (Linear quantization) */ + return(0); + + strcpy(o->fmt,".wav"); + o->wav_num_channels= libdax_audioxtr_to_int(o,(unsigned char *) buf+22,2,0); + o->wav_sample_rate= libdax_audioxtr_to_int(o,(unsigned char *) buf+24,4,0); + o->wav_bits_per_sample= libdax_audioxtr_to_int(o,(unsigned char *)buf+34,2,0); + 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); + + return(1); +} + + +static unsigned libdax_audioxtr_to_int(struct libdax_audioxtr *o, + unsigned char *bytes, int len, int flag) +{ + unsigned int ret= 0; + int i; + + for(i= len-1; i>=0; i--) + ret= ret*256+bytes[i]; + return(ret); +} + + +static int libdax_audioxtr_init_reading(struct libdax_audioxtr *o, int flag) +{ + int ret; + + /* currently this only works for MS WAVE files .wav */; + ret= lseek(o->fd,44,SEEK_SET); + if(ret==-1) + return(0); + + return(1); +} + + +int libdax_audioxtr_get_id(struct libdax_audioxtr *o, + char **fmt, char **fmt_info, + int *num_channels, int *sample_rate, int *bits_per_sample, + int flag) +{ + *fmt= o->fmt; + *fmt_info= o->fmt_info; + if(strcmp(o->fmt,".wav")==0) { + *num_channels= o->wav_num_channels; + *sample_rate= o->wav_sample_rate; + *bits_per_sample= o->wav_bits_per_sample; + } else + *num_channels= *sample_rate= *bits_per_sample= 0; + return(1); +} + + +int libdax_audioxtr_read(struct libdax_audioxtr *o, + char buffer[], int buffer_size, int flag) +{ + int ret; + + if(buffer_size<=0 || o->fd<0) + return(-2); + ret= read(o->fd,buffer,buffer_size); + return(ret); +} + diff --git a/libburn/libdax_audioxtr.h b/libburn/libdax_audioxtr.h new file mode 100644 index 0000000..d2779be --- /dev/null +++ b/libburn/libdax_audioxtr.h @@ -0,0 +1,168 @@ + +/* libdax_audioxtr + Audio track data extraction facility of libdax and libburn. + Copyright (C) 2006 Thomas Schmitt , provided under GPL +*/ + +#ifndef LIBDAX_AUDIOXTR_H_INCLUDED +#define LIBDAX_AUDIOXTR_H_INCLUDED 1 + + /* Public Macros */ + +#define LIBDAX_AUDIOXTR_STRLEN 4096 + + + /* Public Opaque Handles */ + +/** Extractor object encapsulating intermediate states of extraction. + The clients of libdax_audioxtr shall only allocate pointers to this + struct and get a storage object via libdax_audioxtr_new(). + Appropriate initial value for the pointer is NULL. +*/ +struct libdax_audioxtr; + + + /* Public Functions */ + + /* Calls initiated from inside libdax/libburn */ + + + /* Calls from applications (to be forwarded by libdax/libburn) */ + + +/** Open an audio file, check wether suitable, create extractor object. + @param xtr Opaque handle to extractor. Gets attached extractor object. + @param path Address of the audio file to extract. "-" is stdin (but might + be not suitable for all futurely supported formats). + @param flag Bitfield for control purposes (unused yet, submit 0) + @return >0 success, <=0 failure +*/ +int libdax_audioxtr_new(struct libdax_audioxtr **xtr, char *path, int flag); + + +/** Obtain identification parameters of opened audio source. + @param xtr Opaque handle to extractor + @param fmt Gets pointed to the audio file format id text: ".wav" + @param fmt_info Gets pointed to a format info text telling parameters + @param num_channels e.g. 1=mono, 2=stereo, etc + @param sample_rate e.g. 11025, 44100 + @param bits_per_sample e.g. 8= 8 bits per sample, 16= 16 bits ... + @param flag Bitfield for control purposes (unused yet, submit 0) + @return >0 success, <=0 failure +*/ +int libdax_audioxtr_get_id(struct libdax_audioxtr *xtr, + char **fmt, char **fmt_info, + int *num_channels, int *sample_rate, + int *bits_per_sample, 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) + @return >0 number of valid buffer bytes, + 0 End of file + -1 operating system reports error + -2 usage error by application +*/ +int libdax_audioxtr_read(struct libdax_audioxtr *xtr, + char buffer[], int buffer_size, int flag); + + +/** Clean up after extraction and destroy extractor object. + @param xtr Opaque handle to extractor, *xtr is allowed to be NULL, + *xtr is set to NULL by this function + @param flag Bitfield for control purposes (unused yet, submit 0) + @return 1 = destroyed object, 0 = was already destroyed +*/ +int libdax_audioxtr_destroy(struct libdax_audioxtr **xtr, int flag); + + + +#ifdef LIDBAX_AUDIOXTR________________ + + +-- place documentation text here --- + + +#endif /* LIDBAX_AUDIOXTR_________________ */ + + + +/* + *Never* set this macro outside libdax_audioxtr.c ! + The entrails of this facility are not to be seen by + the other library components or the applications. +*/ +#ifdef LIBDAX_AUDIOXTR_H_INTERNAL + + /* Internal Structures */ + +/** Extractor object encapsulating intermediate states of extraction */ +struct libdax_audioxtr { + + /* Source of the encoded audio data */ + char path[LIBDAX_AUDIOXTR_STRLEN]; + + /* File descriptor to path */ + int fd; + + /* Format identifier. E.g. ".wav" */ + char fmt[80]; + + /* Format parameter info text */ + char fmt_info[LIBDAX_AUDIOXTR_STRLEN]; + + + /* Format dependent parameters */ + + /* MS WAVE Format */ + /* info used: http://ccrma.stanford.edu/courses/422/projects/WaveFormat/ */ + + /* 1= mono, 2= stereo, etc. */ + int wav_num_channels; + + /* 8000, 44100, etc. */ + int wav_sample_rate; + + /* 8 bits = 8, 16 bits = 16, etc. */ + int wav_bits_per_sample; + +}; + + + /* Internal Functions */ + +/** Open the audio source pointed to by .path and evaluate suitability. + @return -1 failure to open, 0 unsuitable format, 1 success +*/ +static int libdax_audioxtr_open(struct libdax_audioxtr *o, int flag); + + +/** Identify format and evaluate suitability. + @return 0 unsuitable format, 1 format is suitable +*/ +static int libdax_audioxtr_identify(struct libdax_audioxtr *o, int flag); + + +/** Convert a byte string into a number (currently only little endian) + @return The resulting number +*/ +static unsigned libdax_audioxtr_to_int(struct libdax_audioxtr *o, + unsigned char *bytes, int len, int flag); + + +/** Prepare for reading of first buffer. + @return 0 error, 1 success +*/ +static int libdax_audioxtr_init_reading(struct libdax_audioxtr *o, int flag); + + + +#endif /* LIBDAX_AUDIOXTR_H_INTERNAL */ + + +#endif /* ! LIBDAX_AUDIOXTR_H_INCLUDED */ + diff --git a/libburn/libdax_msgs.h b/libburn/libdax_msgs.h index 36e2416..6052848 100644 --- a/libburn/libdax_msgs.h +++ b/libburn/libdax_msgs.h @@ -330,6 +330,11 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff 0x00020116 (FATAL,HIGH) = Track mode has unusable value 0x00020117 (FATAL,HIGH) = toc_entry of drive is already in use + libdax_audioxtr: + 0x00020200 (SORRY,HIGH) = Cannot open audio source file + 0x00020201 (SORRY,HIGH) = Audio source file has unsuitable format + 0x00020202 (SORRY,HIGH) = Failed to prepare reading of audio data + ------------------------------------------------------------------------------