libextractor

GNU libextractor
Log | Files | Refs | Submodules | README | LICENSE

wav_extractor.c (4666B)


      1 /*
      2      This file is part of libextractor.
      3      Copyright (C) 2004, 2009, 2012 Vidyut Samanta and Christian Grothoff
      4 
      5      libextractor is free software; you can redistribute it and/or modify
      6      it under the terms of the GNU General Public License as published
      7      by the Free Software Foundation; either version 3, or (at your
      8      option) any later version.
      9 
     10      libextractor is distributed in the hope that it will be useful, but
     11      WITHOUT ANY WARRANTY; without even the implied warranty of
     12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13      General Public License for more details.
     14 
     15      You should have received a copy of the GNU General Public License
     16      along with libextractor; see the file COPYING.  If not, write to the
     17      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     18      Boston, MA 02110-1301, USA.
     19 
     20      This code was based on bitcollider 0.6.0
     21      (PD) 2004 The Bitzi Corporation
     22      http://bitzi.com/
     23      (PD) 2001 The Bitzi Corporation
     24      Please see file COPYING or http://bitzi.com/publicdomain
     25      for more info.
     26 */
     27 /**
     28  * @file plugins/wav_extractor.c
     29  * @brief plugin to support WAV files
     30  * @author Christian Grothoff
     31  */
     32 
     33 #include "platform.h"
     34 #include "extractor.h"
     35 
     36 
     37 #if BIG_ENDIAN_HOST
     38 static uint16_t
     39 little_endian_to_host16 (uint16_t in)
     40 {
     41   unsigned char *ptr = (unsigned char *) ∈
     42 
     43   return ((ptr[1] & 0xFF) << 8) | (ptr[0] & 0xFF);
     44 }
     45 
     46 
     47 static uint32_t
     48 little_endian_to_host32 (uint32_t in)
     49 {
     50   unsigned char *ptr = (unsigned char *) &in;
     51 
     52   /* Widen before shifting: `unsigned char' promotes to `int', and
     53      0x80 << 24 overflows a 32 bit int. */
     54   return (((uint32_t) ptr[3]) << 24) | (((uint32_t) ptr[2]) << 16)
     55          | (((uint32_t) ptr[1]) << 8) | ((uint32_t) ptr[0]);
     56 }
     57 
     58 
     59 #endif
     60 
     61 
     62 /**
     63  * Extract information from WAV files.
     64  *
     65  * @param ec extraction context
     66  *
     67  * @detail
     68  * A WAV header looks as follows:
     69  *
     70  * Offset  Value    meaning
     71  * 16      4 bytes  0x00000010     // Length of the fmt data (16 bytes)
     72  * 20      2 bytes  0x0001         // Format tag: 1 = PCM
     73  * 22      2 bytes  <channels>     // Channels: 1 = mono, 2 = stereo
     74  * 24      4 bytes  <sample rate>  // Samples per second: e.g., 44100
     75  */
     76 void
     77 EXTRACTOR_wav_extract_method (struct EXTRACTOR_ExtractContext *ec);
     78 
     79 void
     80 EXTRACTOR_wav_extract_method (struct EXTRACTOR_ExtractContext *ec)
     81 {
     82   void *data;
     83   const unsigned char *buf;
     84   uint16_t channels;
     85   uint16_t sample_size;
     86   uint32_t sample_rate;
     87   uint32_t data_len;
     88   uint32_t samples;
     89   char scratch[256];
     90 
     91   if (44 >
     92       ec->read (ec->cls,  &data, 44))
     93     return;
     94   buf = data;
     95   if (((buf[0] != 'R') || (buf[1] != 'I') ||
     96        (buf[2] != 'F') || (buf[3] != 'F') ||
     97        (buf[8] != 'W') || (buf[9] != 'A') ||
     98        (buf[10] != 'V') || (buf[11] != 'E') ||
     99        (buf[12] != 'f') || (buf[13] != 'm') || (buf[14] != 't') || (buf[15] !=
    100                                                                     ' ') ))
    101     return;                /* not a WAV file */
    102 
    103   channels = *((uint16_t *) &buf[22]);
    104   sample_rate = *((uint32_t *) &buf[24]);
    105   sample_size = *((uint16_t *) &buf[34]);
    106   data_len = *((uint32_t *) &buf[40]);
    107 
    108 #if BIG_ENDIAN_HOST
    109   channels = little_endian_to_host16 (channels);
    110   sample_size = little_endian_to_host16 (sample_size);
    111   sample_rate = little_endian_to_host32 (sample_rate);
    112   data_len = little_endian_to_host32 (data_len);
    113 #endif
    114 
    115   if ( (8 != sample_size) &&
    116        (16 != sample_size) )
    117     return;                /* invalid sample size found in wav file */
    118   if (0 == channels)
    119     return;                /* invalid channels value -- avoid division by 0! */
    120   if (0 == sample_rate)
    121     return;                /* invalid sample_rate */
    122   samples = data_len / (channels * (sample_size >> 3));
    123 
    124   snprintf (scratch,
    125             sizeof (scratch),
    126             "%llu ms, %d Hz, %s",
    127             (samples < sample_rate)
    128             ? (samples * 1000LLU / sample_rate)
    129             : (samples / sample_rate) * 1000LLU,
    130             sample_rate,
    131             (1 == channels) ? _ ("mono") : _ ("stereo"));
    132   if (0 != ec->proc (ec->cls,
    133                      "wav",
    134                      EXTRACTOR_METATYPE_RESOURCE_TYPE,
    135                      EXTRACTOR_METAFORMAT_UTF8,
    136                      "text/plain",
    137                      scratch,
    138                      strlen (scratch) + 1))
    139     return;
    140   if (0 != ec->proc (ec->cls,
    141                      "wav",
    142                      EXTRACTOR_METATYPE_MIMETYPE,
    143                      EXTRACTOR_METAFORMAT_UTF8,
    144                      "text/plain",
    145                      "audio/x-wav",
    146                      strlen ("audio/x-wav") + 1))
    147     return;
    148 }
    149 
    150 
    151 /* end of wav_extractor.c */