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