libextractor

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

wav_extractor.c (4446B)


      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   return ((ptr[3] & 0xFF) << 24) | ((ptr[2] & 0xFF) << 16)
     53          | ((ptr[1] & 0xFF) << 8) | (ptr[0] & 0xFF);
     54 }
     55 
     56 
     57 #endif
     58 
     59 
     60 /**
     61  * Extract information from WAV files.
     62  *
     63  * @param ec extraction context
     64  *
     65  * @detail
     66  * A WAV header looks as follows:
     67  *
     68  * Offset  Value    meaning
     69  * 16      4 bytes  0x00000010     // Length of the fmt data (16 bytes)
     70  * 20      2 bytes  0x0001         // Format tag: 1 = PCM
     71  * 22      2 bytes  <channels>     // Channels: 1 = mono, 2 = stereo
     72  * 24      4 bytes  <sample rate>  // Samples per second: e.g., 44100
     73  */
     74 void
     75 EXTRACTOR_wav_extract_method (struct EXTRACTOR_ExtractContext *ec)
     76 {
     77   void *data;
     78   const unsigned char *buf;
     79   uint16_t channels;
     80   uint16_t sample_size;
     81   uint32_t sample_rate;
     82   uint32_t data_len;
     83   uint32_t samples;
     84   char scratch[256];
     85 
     86   if (44 >
     87       ec->read (ec->cls,  &data, 44))
     88     return;
     89   buf = data;
     90   if (((buf[0] != 'R') || (buf[1] != 'I') ||
     91        (buf[2] != 'F') || (buf[3] != 'F') ||
     92        (buf[8] != 'W') || (buf[9] != 'A') ||
     93        (buf[10] != 'V') || (buf[11] != 'E') ||
     94        (buf[12] != 'f') || (buf[13] != 'm') || (buf[14] != 't') || (buf[15] !=
     95                                                                     ' ') ))
     96     return;                /* not a WAV file */
     97 
     98   channels = *((uint16_t *) &buf[22]);
     99   sample_rate = *((uint32_t *) &buf[24]);
    100   sample_size = *((uint16_t *) &buf[34]);
    101   data_len = *((uint32_t *) &buf[40]);
    102 
    103 #if BIG_ENDIAN_HOST
    104   channels = little_endian_to_host16 (channels);
    105   sample_size = little_endian_to_host16 (sample_size);
    106   sample_rate = little_endian_to_host32 (sample_rate);
    107   data_len = little_endian_to_host32 (data_len);
    108 #endif
    109 
    110   if ( (8 != sample_size) &&
    111        (16 != sample_size) )
    112     return;                /* invalid sample size found in wav file */
    113   if (0 == channels)
    114     return;                /* invalid channels value -- avoid division by 0! */
    115   if (0 == sample_rate)
    116     return;                /* invalid sample_rate */
    117   samples = data_len / (channels * (sample_size >> 3));
    118 
    119   snprintf (scratch,
    120             sizeof (scratch),
    121             "%u ms, %d Hz, %s",
    122             (samples < sample_rate)
    123             ? (samples * 1000 / sample_rate)
    124             : (samples / sample_rate) * 1000,
    125             sample_rate, (1 == channels) ? _ ("mono") : _ ("stereo"));
    126   if (0 != ec->proc (ec->cls,
    127                      "wav",
    128                      EXTRACTOR_METATYPE_RESOURCE_TYPE,
    129                      EXTRACTOR_METAFORMAT_UTF8,
    130                      "text/plain",
    131                      scratch,
    132                      strlen (scratch) + 1))
    133     return;
    134   if (0 != ec->proc (ec->cls,
    135                      "wav",
    136                      EXTRACTOR_METATYPE_MIMETYPE,
    137                      EXTRACTOR_METAFORMAT_UTF8,
    138                      "text/plain",
    139                      "audio/x-wav",
    140                      strlen ("audio/x-wav") + 1))
    141     return;
    142 }
    143 
    144 
    145 /* end of wav_extractor.c */