libextractor

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

wav_extractor.c (4520B)


      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
     78 EXTRACTOR_wav_extract_method (struct EXTRACTOR_ExtractContext *ec)
     79 {
     80   void *data;
     81   const unsigned char *buf;
     82   uint16_t channels;
     83   uint16_t sample_size;
     84   uint32_t sample_rate;
     85   uint32_t data_len;
     86   uint32_t samples;
     87   char scratch[256];
     88 
     89   if (44 >
     90       ec->read (ec->cls,  &data, 44))
     91     return;
     92   buf = data;
     93   if (((buf[0] != 'R') || (buf[1] != 'I') ||
     94        (buf[2] != 'F') || (buf[3] != 'F') ||
     95        (buf[8] != 'W') || (buf[9] != 'A') ||
     96        (buf[10] != 'V') || (buf[11] != 'E') ||
     97        (buf[12] != 'f') || (buf[13] != 'm') || (buf[14] != 't') || (buf[15] !=
     98                                                                     ' ') ))
     99     return;                /* not a WAV file */
    100 
    101   channels = *((uint16_t *) &buf[22]);
    102   sample_rate = *((uint32_t *) &buf[24]);
    103   sample_size = *((uint16_t *) &buf[34]);
    104   data_len = *((uint32_t *) &buf[40]);
    105 
    106 #if BIG_ENDIAN_HOST
    107   channels = little_endian_to_host16 (channels);
    108   sample_size = little_endian_to_host16 (sample_size);
    109   sample_rate = little_endian_to_host32 (sample_rate);
    110   data_len = little_endian_to_host32 (data_len);
    111 #endif
    112 
    113   if ( (8 != sample_size) &&
    114        (16 != sample_size) )
    115     return;                /* invalid sample size found in wav file */
    116   if (0 == channels)
    117     return;                /* invalid channels value -- avoid division by 0! */
    118   if (0 == sample_rate)
    119     return;                /* invalid sample_rate */
    120   samples = data_len / (channels * (sample_size >> 3));
    121 
    122   snprintf (scratch,
    123             sizeof (scratch),
    124             "%u ms, %d Hz, %s",
    125             (samples < sample_rate)
    126             ? (samples * 1000 / sample_rate)
    127             : (samples / sample_rate) * 1000,
    128             sample_rate, (1 == channels) ? _ ("mono") : _ ("stereo"));
    129   if (0 != ec->proc (ec->cls,
    130                      "wav",
    131                      EXTRACTOR_METATYPE_RESOURCE_TYPE,
    132                      EXTRACTOR_METAFORMAT_UTF8,
    133                      "text/plain",
    134                      scratch,
    135                      strlen (scratch) + 1))
    136     return;
    137   if (0 != ec->proc (ec->cls,
    138                      "wav",
    139                      EXTRACTOR_METATYPE_MIMETYPE,
    140                      EXTRACTOR_METAFORMAT_UTF8,
    141                      "text/plain",
    142                      "audio/x-wav",
    143                      strlen ("audio/x-wav") + 1))
    144     return;
    145 }
    146 
    147 
    148 /* end of wav_extractor.c */