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 *) ∈ 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 */