"Fossies" - the Fresh Open Source Software Archive

Member "xorriso-1.5.4/libburn/libdax_audioxtr.c" (30 Jan 2021, 10081 Bytes) of package /linux/misc/xorriso-1.5.4.pl02.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "libdax_audioxtr.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.5.2_vs_1.5.4.

    1 
    2 /* libdax_audioxtr 
    3    Audio track data extraction facility of libdax and libburn.
    4    Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPLv2+
    5 */
    6 
    7 #ifdef HAVE_CONFIG_H
    8 #include "../config.h"
    9 #endif
   10 
   11 #include <stdio.h>
   12 #include <sys/types.h>
   13 #include <sys/stat.h>
   14 #include <fcntl.h>
   15 #include <unistd.h>
   16 #include <string.h>
   17 #include <stdlib.h>
   18 #include <errno.h>
   19 
   20 /* ts B41126 : O_BINARY is needed for Cygwin but undefined elsewhere */
   21 #ifndef O_BINARY
   22 #define O_BINARY 0
   23 #endif
   24 
   25 #include "libdax_msgs.h"
   26 extern struct libdax_msgs *libdax_messenger;
   27 
   28 
   29 /* Only this single source module is entitled to do this */
   30 #define LIBDAX_AUDIOXTR_H_INTERNAL 1
   31 
   32 /* All clients of the extraction facility must do this or include libburn.h */
   33 #define LIBDAX_AUDIOXTR_H_PUBLIC 1
   34 #include "libdax_audioxtr.h"
   35 
   36 
   37 int libdax_audioxtr_new(struct libdax_audioxtr **xtr, char *path, int flag)
   38 {
   39  int ret= -1;
   40  struct libdax_audioxtr *o;
   41 
   42  o= *xtr= (struct libdax_audioxtr *) calloc(1, sizeof(struct libdax_audioxtr));
   43  if(o==NULL)
   44    return(-1);
   45  strncpy(o->path,path,LIBDAX_AUDIOXTR_STRLEN-1);
   46  o->path[LIBDAX_AUDIOXTR_STRLEN-1]= 0;
   47  o->fd= -1;
   48  strcpy(o->fmt,"unidentified");
   49  o->fmt_info[0]= 0;
   50  o->data_size= 0;
   51  o->extract_count= 0;
   52 
   53  o->num_channels= 0;
   54  o->sample_rate= 0;
   55  o->bits_per_sample= 0;
   56  o->msb_first= 0;
   57 
   58  o->wav_data_location= 44;
   59  o->wav_subchunk2_size= 0;
   60 
   61  o->au_data_location= 0;
   62  o->au_data_size= 0xffffffff;
   63 
   64  ret= libdax_audioxtr_open(o,0);
   65  if(ret<=0)
   66    {ret= -2*(ret<0); goto failure;}
   67 
   68  return(1);
   69 failure:
   70  libdax_audioxtr_destroy(xtr,0);
   71  return(ret);
   72 }
   73 
   74 
   75 int libdax_audioxtr_destroy(struct libdax_audioxtr **xtr, int flag)
   76 {
   77  struct libdax_audioxtr *o;
   78 
   79  o= *xtr;
   80  if(o==NULL)
   81    return(0);
   82  if(o->fd>=0 && strcmp(o->path,"-")!=0)
   83    close(o->fd);
   84  free((char *) o);
   85  *xtr= NULL;
   86  return(1);
   87 }
   88 
   89 
   90 static int libdax_audioxtr_open(struct libdax_audioxtr *o, int flag)
   91 {
   92  int ret;
   93  char msg[LIBDAX_AUDIOXTR_STRLEN+80];
   94  
   95  if(strcmp(o->path,"-")==0)
   96    o->fd= 0;
   97  else
   98    o->fd= open(o->path, O_RDONLY | O_BINARY);
   99  if(o->fd<0) {
  100    sprintf(msg,"Cannot open audio source file : %s",o->path);
  101    libdax_msgs_submit(libdax_messenger,-1,0x00020200,
  102                       LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
  103                       msg, errno, 0);
  104    return(-1);
  105  }
  106  ret= libdax_audioxtr_identify(o,0);
  107  if(ret<=0) {
  108    sprintf(msg,"Audio source file has unsuitable format : %s",o->path);
  109    libdax_msgs_submit(libdax_messenger,-1,0x00020201,
  110                       LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
  111                       msg, 0, 0);
  112    return(0);
  113  }
  114  ret= libdax_audioxtr_init_reading(o,0);
  115  if(ret<=0) {
  116    sprintf(msg,"Failed to prepare reading of audio data : %s",o->path);
  117    libdax_msgs_submit(libdax_messenger,-1,0x00020202,
  118                       LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
  119                       msg, 0, 0);
  120    return(0);
  121  }
  122  return(1);
  123 }
  124 
  125 /* @param flag: bit0= sequential file, skip by reading data
  126 */
  127 static int libdax_audioxtr_skip(struct libdax_audioxtr *o,
  128                                 off_t *old_pos,
  129                                 off_t pos, int flag)
  130 {
  131  int ret;
  132  size_t to_read;
  133  static char buf[256]; /* Thread safe because the content does not matter */
  134 
  135  if((flag & 1) || o->fd == 0) { /* stdin */
  136    while(pos - *old_pos > 0) {
  137      to_read= pos - *old_pos;
  138      if(to_read > sizeof(buf))
  139        to_read= sizeof(buf);
  140      ret= read(o->fd, buf, to_read);
  141      if(ret < (int) to_read)
  142        return(0);
  143      *old_pos+= to_read;
  144    }
  145  } else {
  146    ret= lseek(o->fd, pos, SEEK_SET);
  147    if(ret == -1)
  148      return(0);
  149    *old_pos= pos;
  150  }
  151  return(1);
  152 }
  153 
  154 static int libdax_audioxtr_identify_wav(struct libdax_audioxtr *o, int flag)
  155 {
  156  int ret, fmt_seen= 0, data_seen= 0;
  157  off_t pos= 0, old_pos= 0, riff_end= 0;
  158  char buf[16];
  159  unsigned char *ubuf;
  160 
  161  /* check whether this is a MS WAVE file .wav */
  162  /* info used: http://ccrma.stanford.edu/courses/422/projects/WaveFormat/
  163                https://en.wikipedia.org/wiki/WAV
  164     see summary in: doc/waveformat.txt
  165  */
  166  ubuf= (unsigned char *) buf;
  167 
  168  /* Look for ChunkID "RIFF" , tolerate other known chunks */
  169  while(1) {
  170    ret= libdax_audioxtr_skip(o, &old_pos, pos, 0);
  171    if(ret <= 0)
  172      return(0);
  173    ret= read(o->fd, buf, 8);
  174    if(ret < 8)
  175      return(0);
  176    old_pos+= 8;
  177    pos= old_pos + libdax_audioxtr_to_int(o, ubuf + 4, 4, 0);
  178    if(pos > 0xffffffff || pos - old_pos < 4) /* Too large or no Format word */
  179      return(0);
  180    if(strncmp(buf, "RIFF", 4) == 0)
  181  break;
  182    /* Wikipedia mentions these known ChunkId values */
  183    if(strncmp(buf, "INFO", 4) == 0 ||
  184       strncmp(buf, "CSET", 4) == 0 ||
  185       strncmp(buf, "JUNK", 4) == 0 ||
  186       strncmp(buf, "PAD ", 4) == 0)
  187  continue;
  188    return(0);
  189  }
  190 
  191  /* Read RIFF Format header */
  192  ret= read(o->fd, buf, 4);
  193  if(ret < 4)
  194    return(0);
  195  old_pos+= 4;
  196  if(strncmp(buf, "WAVE", 4) != 0) /* Format */
  197    return(0);
  198  riff_end= pos;
  199 
  200  /* Look for SubchunkID "fmt " and "data" */
  201  pos= old_pos;
  202  while(old_pos < riff_end) {
  203    ret= libdax_audioxtr_skip(o, &old_pos, pos, 0);
  204    if(ret <= 0)
  205      return(0);
  206    ret= read(o->fd, buf, 8);
  207    if(ret < 8)
  208      return(0);
  209    old_pos= pos + 8;
  210    pos= old_pos + libdax_audioxtr_to_int(o, ubuf + 4, 4, 0); /* SubchunkSize */
  211 
  212    if(strncmp(buf,"fmt ", 4) == 0) {
  213      if(pos - old_pos < 16)
  214        return(0);
  215      ret= read(o->fd, buf, 16);
  216      if(ret < 16)
  217        return(0);
  218      old_pos+= 16;
  219      if(buf[0]!=1 || buf[1]!=0) /* AudioFormat (1 = Linear quantization) */
  220        return(0);
  221      o->msb_first= 0;
  222      o->num_channels= libdax_audioxtr_to_int(o, ubuf + 2 , 2, 0);
  223      o->sample_rate= libdax_audioxtr_to_int(o, ubuf + 4, 4, 0);
  224      o->bits_per_sample= libdax_audioxtr_to_int(o, ubuf + 14, 2, 0);
  225      sprintf(o->fmt_info,
  226              ".wav , num_channels=%d , sample_rate=%d , bits_per_sample=%d",
  227              o->num_channels, o->sample_rate, o->bits_per_sample);
  228      fmt_seen= 1;
  229 
  230    } else if(strncmp(buf,"data", 4) == 0) {
  231      o->wav_data_location= old_pos;
  232      o->wav_subchunk2_size= pos - old_pos;
  233      o->data_size= o->wav_subchunk2_size;
  234      data_seen= 1;
  235    }
  236    if(fmt_seen && data_seen) {
  237      strcpy(o->fmt,".wav");
  238      return(1);
  239    }
  240  }
  241  return(0);
  242 }
  243 
  244 
  245 static int libdax_audioxtr_identify_au(struct libdax_audioxtr *o, int flag)
  246 {
  247  int ret,encoding;
  248  char buf[24];
  249 
  250  /* Check whether this is a Sun Audio, .au file */
  251  /* info used: http://ccrma.stanford.edu/courses/422/projects/WaveFormat/ */
  252 
  253  if(o->fd!=0) {
  254    ret= lseek(o->fd,0,SEEK_SET);
  255    if(ret==-1)
  256      return(0);
  257  }
  258  ret= read(o->fd, buf, 24);
  259  if(ret<24)
  260    return(0);
  261 
  262  if(strncmp(buf,".snd",4)!=0)
  263    return(0);
  264  strcpy(o->fmt,".au");
  265  o->msb_first= 1;
  266  o->au_data_location= libdax_audioxtr_to_int(o,(unsigned char *)buf+4,4,1);
  267  o->au_data_size= libdax_audioxtr_to_int(o,(unsigned char *)buf+8,4,1);
  268  encoding= libdax_audioxtr_to_int(o,(unsigned char *)buf+12,4,1);
  269  if(encoding==2)
  270    o->bits_per_sample= 8;
  271  else if(encoding==3)
  272    o->bits_per_sample= 16;
  273  else if(encoding==4)
  274    o->bits_per_sample= 24;
  275  else if(encoding==5)
  276    o->bits_per_sample= 32;
  277  else
  278    o->bits_per_sample= -encoding;
  279  o->sample_rate= libdax_audioxtr_to_int(o,(unsigned char *)buf+16,4,1);
  280  o->num_channels= libdax_audioxtr_to_int(o,(unsigned char *)buf+20,4,1);
  281  if(o->au_data_size!=0xffffffff)
  282    o->data_size= o->au_data_size;
  283  else
  284    o->data_size= 0;
  285  sprintf(o->fmt_info,
  286          ".au , num_channels=%d , sample_rate=%d , bits_per_sample=%d",
  287          o->num_channels,o->sample_rate,o->bits_per_sample);
  288  return(o->bits_per_sample>0); /* Audio format must be linear PCM */
  289 }
  290 
  291 
  292 static int libdax_audioxtr_identify(struct libdax_audioxtr *o, int flag)
  293 {
  294  int ret;
  295 
  296  ret= libdax_audioxtr_identify_wav(o, 0);
  297  if(ret!=0)
  298    return(ret);
  299  if(o->fd==0) /* cannot rewind stdin */
  300    return(0);
  301  ret= libdax_audioxtr_identify_au(o, 0);
  302  if(ret!=0)
  303    return(ret);
  304  return(0);
  305 }
  306 
  307 
  308 /* @param flag bit0=msb_first */
  309 static unsigned libdax_audioxtr_to_int(struct libdax_audioxtr *o,
  310                                       unsigned char *bytes, int len, int flag)
  311 {
  312  unsigned int ret= 0;
  313  int i;
  314 
  315  if(flag&1)
  316    for(i= 0; i<len; i++)
  317      ret= ret*256+bytes[i];
  318  else
  319    for(i= len-1; i>=0; i--)
  320      ret= ret*256+bytes[i];
  321  return(ret);
  322 }
  323 
  324 
  325 static int libdax_audioxtr_init_reading(struct libdax_audioxtr *o, int flag)
  326 {
  327  int ret;
  328 
  329 
  330  /* currently this only works for MS WAVE files .wav and Sun .au*/;
  331  if(o->fd==0) /* stdin: hope no read came after libdax_audioxtr_identify() */
  332    return(1);
  333 
  334  o->extract_count= 0;
  335  if(strcmp(o->fmt,".wav")==0)
  336    ret= lseek(o->fd, o->wav_data_location, SEEK_SET);
  337  else if(strcmp(o->fmt,".au")==0)
  338    ret= lseek(o->fd,o->au_data_location,SEEK_SET);
  339  else
  340    ret= -1;
  341  if(ret==-1)
  342    return(0);
  343 
  344  return(1);
  345 }
  346 
  347 
  348 int libdax_audioxtr_get_id(struct libdax_audioxtr *o,
  349                      char **fmt, char **fmt_info,
  350                      int *num_channels, int *sample_rate, int *bits_per_sample,
  351                      int *msb_first, int flag)
  352 {
  353  *fmt= o->fmt;
  354  *fmt_info= o->fmt_info;
  355  *num_channels= o->num_channels;
  356  *sample_rate= o->sample_rate;
  357  *bits_per_sample= o->bits_per_sample;
  358  *msb_first= o->msb_first;
  359  return(1);
  360 }
  361 
  362 
  363 int libdax_audioxtr_get_size(struct libdax_audioxtr *o, off_t *size, int flag)
  364 {
  365  *size= o->data_size;
  366  return(1);
  367 }
  368 
  369 
  370 int libdax_audioxtr_read(struct libdax_audioxtr *o,
  371                          char buffer[], int buffer_size, int flag)
  372 {
  373  int ret;
  374 
  375  if(buffer_size<=0 || o->fd<0)
  376    return(-2);
  377  if(o->data_size>0 && !(flag&1))
  378    if(buffer_size > o->data_size - o->extract_count)
  379      buffer_size= o->data_size - o->extract_count;
  380  if(buffer_size<=0)
  381    return(0);
  382  ret= read(o->fd,buffer,buffer_size);
  383  if(ret>0)
  384    o->extract_count+= ret;
  385  return(ret);
  386 }
  387 
  388 
  389 int libdax_audioxtr_detach_fd(struct libdax_audioxtr *o, int *fd, int flag)
  390 {
  391  if(o->fd<0)
  392    return(-1);
  393  if(strcmp(o->fmt,".wav")!=0 && strcmp(o->fmt,".au")!=0)
  394    return(0);
  395  if(flag&1) {
  396    *fd= o->fd;
  397  } else {
  398    *fd= dup(o->fd);
  399    if(*fd>=0 && strcmp(o->path,"-")!=0)
  400      close(o->fd);
  401  }
  402  if(*fd>=0) {
  403    o->fd= -1;
  404    return(1);
  405  }
  406  return(-1);
  407 }
  408