1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
|
/*
This file is part of libextractor.
Copyright (C) 2004, 2009, 2012 Vidyut Samanta and Christian Grothoff
libextractor is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
by the Free Software Foundation; either version 3, or (at your
option) any later version.
libextractor is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with libextractor; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
This code was based on bitcollider 0.6.0
(PD) 2004 The Bitzi Corporation
http://bitzi.com/
(PD) 2001 The Bitzi Corporation
Please see file COPYING or http://bitzi.com/publicdomain
for more info.
*/
/**
* @file plugins/wav_extractor.c
* @brief plugin to support WAV files
* @author Christian Grothoff
*/
#include "platform.h"
#include "extractor.h"
#if BIG_ENDIAN_HOST
static uint16_t
little_endian_to_host16 (uint16_t in)
{
unsigned char *ptr = (unsigned char *) ∈
return ((ptr[1] & 0xFF) << 8) | (ptr[0] & 0xFF);
}
static uint32_t
little_endian_to_host32 (uint32_t in)
{
unsigned char *ptr = (unsigned char *) ∈
return ((ptr[3] & 0xFF) << 24) | ((ptr[2] & 0xFF) << 16)
| ((ptr[1] & 0xFF) << 8) | (ptr[0] & 0xFF);
}
#endif
/**
* Extract information from WAV files.
*
* @param ec extraction context
*
* @detail
* A WAV header looks as follows:
*
* Offset Value meaning
* 16 4 bytes 0x00000010 // Length of the fmt data (16 bytes)
* 20 2 bytes 0x0001 // Format tag: 1 = PCM
* 22 2 bytes <channels> // Channels: 1 = mono, 2 = stereo
* 24 4 bytes <sample rate> // Samples per second: e.g., 44100
*/
void
EXTRACTOR_wav_extract_method (struct EXTRACTOR_ExtractContext *ec)
{
void *data;
const unsigned char *buf;
uint16_t channels;
uint16_t sample_size;
uint32_t sample_rate;
uint32_t data_len;
uint32_t samples;
char scratch[256];
if (44 >
ec->read (ec->cls, &data, 44))
return;
buf = data;
if (((buf[0] != 'R') || (buf[1] != 'I') ||
(buf[2] != 'F') || (buf[3] != 'F') ||
(buf[8] != 'W') || (buf[9] != 'A') ||
(buf[10] != 'V') || (buf[11] != 'E') ||
(buf[12] != 'f') || (buf[13] != 'm') || (buf[14] != 't') || (buf[15] !=
' ') ))
return; /* not a WAV file */
channels = *((uint16_t *) &buf[22]);
sample_rate = *((uint32_t *) &buf[24]);
sample_size = *((uint16_t *) &buf[34]);
data_len = *((uint32_t *) &buf[40]);
#if BIG_ENDIAN_HOST
channels = little_endian_to_host16 (channels);
sample_size = little_endian_to_host16 (sample_size);
sample_rate = little_endian_to_host32 (sample_rate);
data_len = little_endian_to_host32 (data_len);
#endif
if ( (8 != sample_size) &&
(16 != sample_size) )
return; /* invalid sample size found in wav file */
if (0 == channels)
return; /* invalid channels value -- avoid division by 0! */
if (0 == sample_rate)
return; /* invalid sample_rate */
samples = data_len / (channels * (sample_size >> 3));
snprintf (scratch,
sizeof (scratch),
"%u ms, %d Hz, %s",
(samples < sample_rate)
? (samples * 1000 / sample_rate)
: (samples / sample_rate) * 1000,
sample_rate, (1 == channels) ? _ ("mono") : _ ("stereo"));
if (0 != ec->proc (ec->cls,
"wav",
EXTRACTOR_METATYPE_RESOURCE_TYPE,
EXTRACTOR_METAFORMAT_UTF8,
"text/plain",
scratch,
strlen (scratch) + 1))
return;
if (0 != ec->proc (ec->cls,
"wav",
EXTRACTOR_METATYPE_MIMETYPE,
EXTRACTOR_METAFORMAT_UTF8,
"text/plain",
"audio/x-wav",
strlen ("audio/x-wav") + 1))
return;
}
/* end of wav_extractor.c */
|