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